From 18424deb5a3a15277bc115fa173b9d27ac691583 Mon Sep 17 00:00:00 2001 From: wlxwlxwlx <49864724+wlxwlxwlx@users.noreply.github.com> Date: Wed, 6 Dec 2023 03:30:50 +0800 Subject: [PATCH 1/2] [OpJumpFalse, OpAndJump, OpOrJump, OpJump], these four instructions have been changed to use 4 bytes to avoid precision loss and panic when the number of instructions exceeds the maximum of 16 bits (65535) (#433) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 王录祥 --- instructions.go | 6 ++++++ parser/opcodes.go | 10 ++++++---- vm.go | 14 +++++++------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/instructions.go b/instructions.go index eb1fbf27..27f7af39 100644 --- a/instructions.go +++ b/instructions.go @@ -28,6 +28,12 @@ func MakeInstruction(opcode parser.Opcode, operands ...int) []byte { n := uint16(o) instruction[offset] = byte(n >> 8) instruction[offset+1] = byte(n) + case 4: + n := uint32(o) + instruction[offset] = byte(n >> 24) + instruction[offset+1] = byte(n >> 16) + instruction[offset+2] = byte(n >> 8) + instruction[offset+3] = byte(n) } offset += width } diff --git a/parser/opcodes.go b/parser/opcodes.go index d97f4896..c1e94c1f 100644 --- a/parser/opcodes.go +++ b/parser/opcodes.go @@ -106,10 +106,10 @@ var OpcodeOperands = [...][]int{ OpNotEqual: {}, OpMinus: {}, OpLNot: {}, - OpJumpFalsy: {2}, - OpAndJump: {2}, - OpOrJump: {2}, - OpJump: {2}, + OpJumpFalsy: {4}, + OpAndJump: {4}, + OpOrJump: {4}, + OpJump: {4}, OpNull: {}, OpGetGlobal: {2}, OpSetGlobal: {2}, @@ -149,6 +149,8 @@ func ReadOperands(numOperands []int, ins []byte) (operands []int, offset int) { operands = append(operands, int(ins[offset])) case 2: operands = append(operands, int(ins[offset+1])|int(ins[offset])<<8) + case 4: + operands = append(operands, int(ins[offset+3])|int(ins[offset+2])<<8|int(ins[offset+1])<<16|int(ins[offset])<<24) } offset += width } diff --git a/vm.go b/vm.go index 64bd23bc..2f8f6fc5 100644 --- a/vm.go +++ b/vm.go @@ -218,30 +218,30 @@ func (v *VM) run() { return } case parser.OpJumpFalsy: - v.ip += 2 + v.ip += 4 v.sp-- if v.stack[v.sp].IsFalsy() { - pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 + pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 | int(v.curInsts[v.ip-2])<<16 | int(v.curInsts[v.ip-3])<<24 v.ip = pos - 1 } case parser.OpAndJump: - v.ip += 2 + v.ip += 4 if v.stack[v.sp-1].IsFalsy() { - pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 + pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 | int(v.curInsts[v.ip-2])<<16 | int(v.curInsts[v.ip-3])<<24 v.ip = pos - 1 } else { v.sp-- } case parser.OpOrJump: - v.ip += 2 + v.ip += 4 if v.stack[v.sp-1].IsFalsy() { v.sp-- } else { - pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 + pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 | int(v.curInsts[v.ip-2])<<16 | int(v.curInsts[v.ip-3])<<24 v.ip = pos - 1 } case parser.OpJump: - pos := int(v.curInsts[v.ip+2]) | int(v.curInsts[v.ip+1])<<8 + pos := int(v.curInsts[v.ip+4]) | int(v.curInsts[v.ip+3])<<8 | int(v.curInsts[v.ip+2])<<16 | int(v.curInsts[v.ip+1])<<24 v.ip = pos - 1 case parser.OpSetGlobal: v.ip += 2 From da09c300a5e2fa918e0c867031bc2a8e89071934 Mon Sep 17 00:00:00 2001 From: E Sequeira <5458743+geseq@users.noreply.github.com> Date: Tue, 5 Dec 2023 20:52:53 +0000 Subject: [PATCH 2/2] Revert "[OpJumpFalse, OpAndJump, OpOrJump, OpJump], these four instructions have been changed to use 4 bytes to avoid precision loss and panic when the number of instructions exceeds the maximum of 16 bits (65535) (#433)" (#436) This reverts commit 18424deb5a3a15277bc115fa173b9d27ac691583. --- instructions.go | 6 ------ parser/opcodes.go | 10 ++++------ vm.go | 14 +++++++------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/instructions.go b/instructions.go index 27f7af39..eb1fbf27 100644 --- a/instructions.go +++ b/instructions.go @@ -28,12 +28,6 @@ func MakeInstruction(opcode parser.Opcode, operands ...int) []byte { n := uint16(o) instruction[offset] = byte(n >> 8) instruction[offset+1] = byte(n) - case 4: - n := uint32(o) - instruction[offset] = byte(n >> 24) - instruction[offset+1] = byte(n >> 16) - instruction[offset+2] = byte(n >> 8) - instruction[offset+3] = byte(n) } offset += width } diff --git a/parser/opcodes.go b/parser/opcodes.go index c1e94c1f..d97f4896 100644 --- a/parser/opcodes.go +++ b/parser/opcodes.go @@ -106,10 +106,10 @@ var OpcodeOperands = [...][]int{ OpNotEqual: {}, OpMinus: {}, OpLNot: {}, - OpJumpFalsy: {4}, - OpAndJump: {4}, - OpOrJump: {4}, - OpJump: {4}, + OpJumpFalsy: {2}, + OpAndJump: {2}, + OpOrJump: {2}, + OpJump: {2}, OpNull: {}, OpGetGlobal: {2}, OpSetGlobal: {2}, @@ -149,8 +149,6 @@ func ReadOperands(numOperands []int, ins []byte) (operands []int, offset int) { operands = append(operands, int(ins[offset])) case 2: operands = append(operands, int(ins[offset+1])|int(ins[offset])<<8) - case 4: - operands = append(operands, int(ins[offset+3])|int(ins[offset+2])<<8|int(ins[offset+1])<<16|int(ins[offset])<<24) } offset += width } diff --git a/vm.go b/vm.go index 2f8f6fc5..64bd23bc 100644 --- a/vm.go +++ b/vm.go @@ -218,30 +218,30 @@ func (v *VM) run() { return } case parser.OpJumpFalsy: - v.ip += 4 + v.ip += 2 v.sp-- if v.stack[v.sp].IsFalsy() { - pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 | int(v.curInsts[v.ip-2])<<16 | int(v.curInsts[v.ip-3])<<24 + pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 v.ip = pos - 1 } case parser.OpAndJump: - v.ip += 4 + v.ip += 2 if v.stack[v.sp-1].IsFalsy() { - pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 | int(v.curInsts[v.ip-2])<<16 | int(v.curInsts[v.ip-3])<<24 + pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 v.ip = pos - 1 } else { v.sp-- } case parser.OpOrJump: - v.ip += 4 + v.ip += 2 if v.stack[v.sp-1].IsFalsy() { v.sp-- } else { - pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 | int(v.curInsts[v.ip-2])<<16 | int(v.curInsts[v.ip-3])<<24 + pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8 v.ip = pos - 1 } case parser.OpJump: - pos := int(v.curInsts[v.ip+4]) | int(v.curInsts[v.ip+3])<<8 | int(v.curInsts[v.ip+2])<<16 | int(v.curInsts[v.ip+1])<<24 + pos := int(v.curInsts[v.ip+2]) | int(v.curInsts[v.ip+1])<<8 v.ip = pos - 1 case parser.OpSetGlobal: v.ip += 2