increase size of jump operands (#438)
* [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) * update test cases * update test cases --------- Co-authored-by: 王录祥 <wanglx@smartsteps.com>
This commit is contained in:
parent
da09c300a5
commit
18b953c7be
4 changed files with 46 additions and 38 deletions
|
@ -204,11 +204,11 @@ func TestCompiler_Compile(t *testing.T) {
|
|||
expectCompile(t, `if true { 10 }; 3333`,
|
||||
bytecode(
|
||||
concatInsts(
|
||||
tengo.MakeInstruction(parser.OpTrue), // 0000
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 8), // 0001
|
||||
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
|
||||
tengo.MakeInstruction(parser.OpPop), // 0007
|
||||
tengo.MakeInstruction(parser.OpConstant, 1), // 0008
|
||||
tengo.MakeInstruction(parser.OpTrue), // 0000
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 10), // 0001
|
||||
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
|
||||
tengo.MakeInstruction(parser.OpPop), // 0007
|
||||
tengo.MakeInstruction(parser.OpConstant, 1), // 0008
|
||||
tengo.MakeInstruction(parser.OpPop),
|
||||
tengo.MakeInstruction(parser.OpSuspend)), // 0011
|
||||
objectsArray(
|
||||
|
@ -219,10 +219,10 @@ func TestCompiler_Compile(t *testing.T) {
|
|||
bytecode(
|
||||
concatInsts(
|
||||
tengo.MakeInstruction(parser.OpTrue), // 0000
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 11), // 0001
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 15), // 0001
|
||||
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
|
||||
tengo.MakeInstruction(parser.OpPop), // 0007
|
||||
tengo.MakeInstruction(parser.OpJump, 15), // 0008
|
||||
tengo.MakeInstruction(parser.OpJump, 19), // 0008
|
||||
tengo.MakeInstruction(parser.OpConstant, 1), // 0011
|
||||
tengo.MakeInstruction(parser.OpPop), // 0014
|
||||
tengo.MakeInstruction(parser.OpConstant, 2), // 0015
|
||||
|
@ -577,12 +577,12 @@ func TestCompiler_Compile(t *testing.T) {
|
|||
intObject(1),
|
||||
intObject(2),
|
||||
compiledFunction(0, 0,
|
||||
tengo.MakeInstruction(parser.OpTrue), // 0000
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 9), // 0001
|
||||
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
|
||||
tengo.MakeInstruction(parser.OpReturn, 1), // 0007
|
||||
tengo.MakeInstruction(parser.OpConstant, 1), // 0009
|
||||
tengo.MakeInstruction(parser.OpReturn, 1))))) // 0012
|
||||
tengo.MakeInstruction(parser.OpTrue), // 0000
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 11), // 0001
|
||||
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
|
||||
tengo.MakeInstruction(parser.OpReturn, 1), // 0007
|
||||
tengo.MakeInstruction(parser.OpConstant, 1), // 0009
|
||||
tengo.MakeInstruction(parser.OpReturn, 1))))) // 0012
|
||||
|
||||
expectCompile(t, `func() { 1; if(true) { 2 } else { 3 }; 4 }`,
|
||||
bytecode(
|
||||
|
@ -599,10 +599,10 @@ func TestCompiler_Compile(t *testing.T) {
|
|||
tengo.MakeInstruction(parser.OpConstant, 0), // 0000
|
||||
tengo.MakeInstruction(parser.OpPop), // 0003
|
||||
tengo.MakeInstruction(parser.OpTrue), // 0004
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 15), // 0005
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 19), // 0005
|
||||
tengo.MakeInstruction(parser.OpConstant, 1), // 0008
|
||||
tengo.MakeInstruction(parser.OpPop), // 0011
|
||||
tengo.MakeInstruction(parser.OpJump, 19), // 0012
|
||||
tengo.MakeInstruction(parser.OpJump, 23), // 0012
|
||||
tengo.MakeInstruction(parser.OpConstant, 2), // 0015
|
||||
tengo.MakeInstruction(parser.OpPop), // 0018
|
||||
tengo.MakeInstruction(parser.OpConstant, 3), // 0019
|
||||
|
@ -932,7 +932,7 @@ func() {
|
|||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
tengo.MakeInstruction(parser.OpBinaryOp, 38),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 31),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 35),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||
tengo.MakeInstruction(parser.OpBinaryOp, 11),
|
||||
|
@ -954,7 +954,7 @@ func() {
|
|||
tengo.MakeInstruction(parser.OpSetGlobal, 1),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 1),
|
||||
tengo.MakeInstruction(parser.OpIteratorNext),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 37),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 41),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 1),
|
||||
tengo.MakeInstruction(parser.OpIteratorKey),
|
||||
tengo.MakeInstruction(parser.OpSetGlobal, 2),
|
||||
|
@ -973,11 +973,11 @@ func() {
|
|||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||
tengo.MakeInstruction(parser.OpEqual),
|
||||
tengo.MakeInstruction(parser.OpAndJump, 23),
|
||||
tengo.MakeInstruction(parser.OpAndJump, 25),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
tengo.MakeInstruction(parser.OpNotEqual),
|
||||
tengo.MakeInstruction(parser.OpOrJump, 34),
|
||||
tengo.MakeInstruction(parser.OpOrJump, 38),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
tengo.MakeInstruction(parser.OpBinaryOp, 38),
|
||||
|
@ -1089,7 +1089,7 @@ func() {
|
|||
intObject(4),
|
||||
compiledFunction(0, 0,
|
||||
tengo.MakeInstruction(parser.OpTrue),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 9),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 11),
|
||||
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||
tengo.MakeInstruction(parser.OpReturn, 1),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
|
@ -1123,7 +1123,7 @@ func() {
|
|||
tengo.MakeInstruction(parser.OpGetLocal, 0),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
tengo.MakeInstruction(parser.OpEqual),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 19),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 21),
|
||||
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||
tengo.MakeInstruction(parser.OpReturn, 1),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
|
@ -1156,7 +1156,7 @@ func() {
|
|||
intObject(4),
|
||||
compiledFunction(0, 0,
|
||||
tengo.MakeInstruction(parser.OpTrue),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 9),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 11),
|
||||
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||
tengo.MakeInstruction(parser.OpReturn, 1),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
|
@ -1180,7 +1180,7 @@ func() {
|
|||
intObject(123),
|
||||
compiledFunction(0, 0,
|
||||
tengo.MakeInstruction(parser.OpTrue),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 6),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 8),
|
||||
tengo.MakeInstruction(parser.OpReturn, 0),
|
||||
tengo.MakeInstruction(parser.OpReturn, 0),
|
||||
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||
|
@ -1200,12 +1200,12 @@ if a := 1; a {
|
|||
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||
tengo.MakeInstruction(parser.OpSetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 27),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 31),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
tengo.MakeInstruction(parser.OpSetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpSetGlobal, 1),
|
||||
tengo.MakeInstruction(parser.OpJump, 39),
|
||||
tengo.MakeInstruction(parser.OpJump, 43),
|
||||
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||
tengo.MakeInstruction(parser.OpSetGlobal, 0),
|
||||
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||
|
@ -1238,12 +1238,12 @@ func() {
|
|||
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||
tengo.MakeInstruction(parser.OpDefineLocal, 0),
|
||||
tengo.MakeInstruction(parser.OpGetLocal, 0),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 22),
|
||||
tengo.MakeInstruction(parser.OpJumpFalsy, 26),
|
||||
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||
tengo.MakeInstruction(parser.OpGetLocal, 0),
|
||||
tengo.MakeInstruction(parser.OpDefineLocal, 1),
|
||||
tengo.MakeInstruction(parser.OpJump, 31),
|
||||
tengo.MakeInstruction(parser.OpJump, 35),
|
||||
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||
tengo.MakeInstruction(parser.OpGetLocal, 0),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
14
vm.go
14
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
|
||||
|
|
Loading…
Reference in a new issue