Skip to content

Commit 18b953c

Browse files
wlxwlxwlx王录祥
and
王录祥
authored
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>
1 parent da09c30 commit 18b953c

File tree

4 files changed

+46
-38
lines changed

4 files changed

+46
-38
lines changed

compiler_test.go

+27-27
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,11 @@ func TestCompiler_Compile(t *testing.T) {
204204
expectCompile(t, `if true { 10 }; 3333`,
205205
bytecode(
206206
concatInsts(
207-
tengo.MakeInstruction(parser.OpTrue), // 0000
208-
tengo.MakeInstruction(parser.OpJumpFalsy, 8), // 0001
209-
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
210-
tengo.MakeInstruction(parser.OpPop), // 0007
211-
tengo.MakeInstruction(parser.OpConstant, 1), // 0008
207+
tengo.MakeInstruction(parser.OpTrue), // 0000
208+
tengo.MakeInstruction(parser.OpJumpFalsy, 10), // 0001
209+
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
210+
tengo.MakeInstruction(parser.OpPop), // 0007
211+
tengo.MakeInstruction(parser.OpConstant, 1), // 0008
212212
tengo.MakeInstruction(parser.OpPop),
213213
tengo.MakeInstruction(parser.OpSuspend)), // 0011
214214
objectsArray(
@@ -219,10 +219,10 @@ func TestCompiler_Compile(t *testing.T) {
219219
bytecode(
220220
concatInsts(
221221
tengo.MakeInstruction(parser.OpTrue), // 0000
222-
tengo.MakeInstruction(parser.OpJumpFalsy, 11), // 0001
222+
tengo.MakeInstruction(parser.OpJumpFalsy, 15), // 0001
223223
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
224224
tengo.MakeInstruction(parser.OpPop), // 0007
225-
tengo.MakeInstruction(parser.OpJump, 15), // 0008
225+
tengo.MakeInstruction(parser.OpJump, 19), // 0008
226226
tengo.MakeInstruction(parser.OpConstant, 1), // 0011
227227
tengo.MakeInstruction(parser.OpPop), // 0014
228228
tengo.MakeInstruction(parser.OpConstant, 2), // 0015
@@ -577,12 +577,12 @@ func TestCompiler_Compile(t *testing.T) {
577577
intObject(1),
578578
intObject(2),
579579
compiledFunction(0, 0,
580-
tengo.MakeInstruction(parser.OpTrue), // 0000
581-
tengo.MakeInstruction(parser.OpJumpFalsy, 9), // 0001
582-
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
583-
tengo.MakeInstruction(parser.OpReturn, 1), // 0007
584-
tengo.MakeInstruction(parser.OpConstant, 1), // 0009
585-
tengo.MakeInstruction(parser.OpReturn, 1))))) // 0012
580+
tengo.MakeInstruction(parser.OpTrue), // 0000
581+
tengo.MakeInstruction(parser.OpJumpFalsy, 11), // 0001
582+
tengo.MakeInstruction(parser.OpConstant, 0), // 0004
583+
tengo.MakeInstruction(parser.OpReturn, 1), // 0007
584+
tengo.MakeInstruction(parser.OpConstant, 1), // 0009
585+
tengo.MakeInstruction(parser.OpReturn, 1))))) // 0012
586586

587587
expectCompile(t, `func() { 1; if(true) { 2 } else { 3 }; 4 }`,
588588
bytecode(
@@ -599,10 +599,10 @@ func TestCompiler_Compile(t *testing.T) {
599599
tengo.MakeInstruction(parser.OpConstant, 0), // 0000
600600
tengo.MakeInstruction(parser.OpPop), // 0003
601601
tengo.MakeInstruction(parser.OpTrue), // 0004
602-
tengo.MakeInstruction(parser.OpJumpFalsy, 15), // 0005
602+
tengo.MakeInstruction(parser.OpJumpFalsy, 19), // 0005
603603
tengo.MakeInstruction(parser.OpConstant, 1), // 0008
604604
tengo.MakeInstruction(parser.OpPop), // 0011
605-
tengo.MakeInstruction(parser.OpJump, 19), // 0012
605+
tengo.MakeInstruction(parser.OpJump, 23), // 0012
606606
tengo.MakeInstruction(parser.OpConstant, 2), // 0015
607607
tengo.MakeInstruction(parser.OpPop), // 0018
608608
tengo.MakeInstruction(parser.OpConstant, 3), // 0019
@@ -932,7 +932,7 @@ func() {
932932
tengo.MakeInstruction(parser.OpGetGlobal, 0),
933933
tengo.MakeInstruction(parser.OpConstant, 1),
934934
tengo.MakeInstruction(parser.OpBinaryOp, 38),
935-
tengo.MakeInstruction(parser.OpJumpFalsy, 31),
935+
tengo.MakeInstruction(parser.OpJumpFalsy, 35),
936936
tengo.MakeInstruction(parser.OpGetGlobal, 0),
937937
tengo.MakeInstruction(parser.OpConstant, 2),
938938
tengo.MakeInstruction(parser.OpBinaryOp, 11),
@@ -954,7 +954,7 @@ func() {
954954
tengo.MakeInstruction(parser.OpSetGlobal, 1),
955955
tengo.MakeInstruction(parser.OpGetGlobal, 1),
956956
tengo.MakeInstruction(parser.OpIteratorNext),
957-
tengo.MakeInstruction(parser.OpJumpFalsy, 37),
957+
tengo.MakeInstruction(parser.OpJumpFalsy, 41),
958958
tengo.MakeInstruction(parser.OpGetGlobal, 1),
959959
tengo.MakeInstruction(parser.OpIteratorKey),
960960
tengo.MakeInstruction(parser.OpSetGlobal, 2),
@@ -973,11 +973,11 @@ func() {
973973
tengo.MakeInstruction(parser.OpGetGlobal, 0),
974974
tengo.MakeInstruction(parser.OpConstant, 0),
975975
tengo.MakeInstruction(parser.OpEqual),
976-
tengo.MakeInstruction(parser.OpAndJump, 23),
976+
tengo.MakeInstruction(parser.OpAndJump, 25),
977977
tengo.MakeInstruction(parser.OpGetGlobal, 0),
978978
tengo.MakeInstruction(parser.OpConstant, 1),
979979
tengo.MakeInstruction(parser.OpNotEqual),
980-
tengo.MakeInstruction(parser.OpOrJump, 34),
980+
tengo.MakeInstruction(parser.OpOrJump, 38),
981981
tengo.MakeInstruction(parser.OpGetGlobal, 0),
982982
tengo.MakeInstruction(parser.OpConstant, 1),
983983
tengo.MakeInstruction(parser.OpBinaryOp, 38),
@@ -1089,7 +1089,7 @@ func() {
10891089
intObject(4),
10901090
compiledFunction(0, 0,
10911091
tengo.MakeInstruction(parser.OpTrue),
1092-
tengo.MakeInstruction(parser.OpJumpFalsy, 9),
1092+
tengo.MakeInstruction(parser.OpJumpFalsy, 11),
10931093
tengo.MakeInstruction(parser.OpConstant, 0),
10941094
tengo.MakeInstruction(parser.OpReturn, 1),
10951095
tengo.MakeInstruction(parser.OpConstant, 1),
@@ -1123,7 +1123,7 @@ func() {
11231123
tengo.MakeInstruction(parser.OpGetLocal, 0),
11241124
tengo.MakeInstruction(parser.OpConstant, 1),
11251125
tengo.MakeInstruction(parser.OpEqual),
1126-
tengo.MakeInstruction(parser.OpJumpFalsy, 19),
1126+
tengo.MakeInstruction(parser.OpJumpFalsy, 21),
11271127
tengo.MakeInstruction(parser.OpConstant, 2),
11281128
tengo.MakeInstruction(parser.OpReturn, 1),
11291129
tengo.MakeInstruction(parser.OpConstant, 1),
@@ -1156,7 +1156,7 @@ func() {
11561156
intObject(4),
11571157
compiledFunction(0, 0,
11581158
tengo.MakeInstruction(parser.OpTrue),
1159-
tengo.MakeInstruction(parser.OpJumpFalsy, 9),
1159+
tengo.MakeInstruction(parser.OpJumpFalsy, 11),
11601160
tengo.MakeInstruction(parser.OpConstant, 0),
11611161
tengo.MakeInstruction(parser.OpReturn, 1),
11621162
tengo.MakeInstruction(parser.OpConstant, 1),
@@ -1180,7 +1180,7 @@ func() {
11801180
intObject(123),
11811181
compiledFunction(0, 0,
11821182
tengo.MakeInstruction(parser.OpTrue),
1183-
tengo.MakeInstruction(parser.OpJumpFalsy, 6),
1183+
tengo.MakeInstruction(parser.OpJumpFalsy, 8),
11841184
tengo.MakeInstruction(parser.OpReturn, 0),
11851185
tengo.MakeInstruction(parser.OpReturn, 0),
11861186
tengo.MakeInstruction(parser.OpConstant, 0),
@@ -1200,12 +1200,12 @@ if a := 1; a {
12001200
tengo.MakeInstruction(parser.OpConstant, 0),
12011201
tengo.MakeInstruction(parser.OpSetGlobal, 0),
12021202
tengo.MakeInstruction(parser.OpGetGlobal, 0),
1203-
tengo.MakeInstruction(parser.OpJumpFalsy, 27),
1203+
tengo.MakeInstruction(parser.OpJumpFalsy, 31),
12041204
tengo.MakeInstruction(parser.OpConstant, 1),
12051205
tengo.MakeInstruction(parser.OpSetGlobal, 0),
12061206
tengo.MakeInstruction(parser.OpGetGlobal, 0),
12071207
tengo.MakeInstruction(parser.OpSetGlobal, 1),
1208-
tengo.MakeInstruction(parser.OpJump, 39),
1208+
tengo.MakeInstruction(parser.OpJump, 43),
12091209
tengo.MakeInstruction(parser.OpConstant, 2),
12101210
tengo.MakeInstruction(parser.OpSetGlobal, 0),
12111211
tengo.MakeInstruction(parser.OpGetGlobal, 0),
@@ -1238,12 +1238,12 @@ func() {
12381238
tengo.MakeInstruction(parser.OpConstant, 0),
12391239
tengo.MakeInstruction(parser.OpDefineLocal, 0),
12401240
tengo.MakeInstruction(parser.OpGetLocal, 0),
1241-
tengo.MakeInstruction(parser.OpJumpFalsy, 22),
1241+
tengo.MakeInstruction(parser.OpJumpFalsy, 26),
12421242
tengo.MakeInstruction(parser.OpConstant, 1),
12431243
tengo.MakeInstruction(parser.OpSetLocal, 0),
12441244
tengo.MakeInstruction(parser.OpGetLocal, 0),
12451245
tengo.MakeInstruction(parser.OpDefineLocal, 1),
1246-
tengo.MakeInstruction(parser.OpJump, 31),
1246+
tengo.MakeInstruction(parser.OpJump, 35),
12471247
tengo.MakeInstruction(parser.OpConstant, 2),
12481248
tengo.MakeInstruction(parser.OpSetLocal, 0),
12491249
tengo.MakeInstruction(parser.OpGetLocal, 0),

instructions.go

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ func MakeInstruction(opcode parser.Opcode, operands ...int) []byte {
2828
n := uint16(o)
2929
instruction[offset] = byte(n >> 8)
3030
instruction[offset+1] = byte(n)
31+
case 4:
32+
n := uint32(o)
33+
instruction[offset] = byte(n >> 24)
34+
instruction[offset+1] = byte(n >> 16)
35+
instruction[offset+2] = byte(n >> 8)
36+
instruction[offset+3] = byte(n)
3137
}
3238
offset += width
3339
}

parser/opcodes.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,10 @@ var OpcodeOperands = [...][]int{
106106
OpNotEqual: {},
107107
OpMinus: {},
108108
OpLNot: {},
109-
OpJumpFalsy: {2},
110-
OpAndJump: {2},
111-
OpOrJump: {2},
112-
OpJump: {2},
109+
OpJumpFalsy: {4},
110+
OpAndJump: {4},
111+
OpOrJump: {4},
112+
OpJump: {4},
113113
OpNull: {},
114114
OpGetGlobal: {2},
115115
OpSetGlobal: {2},
@@ -149,6 +149,8 @@ func ReadOperands(numOperands []int, ins []byte) (operands []int, offset int) {
149149
operands = append(operands, int(ins[offset]))
150150
case 2:
151151
operands = append(operands, int(ins[offset+1])|int(ins[offset])<<8)
152+
case 4:
153+
operands = append(operands, int(ins[offset+3])|int(ins[offset+2])<<8|int(ins[offset+1])<<16|int(ins[offset])<<24)
152154
}
153155
offset += width
154156
}

vm.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -218,30 +218,30 @@ func (v *VM) run() {
218218
return
219219
}
220220
case parser.OpJumpFalsy:
221-
v.ip += 2
221+
v.ip += 4
222222
v.sp--
223223
if v.stack[v.sp].IsFalsy() {
224-
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
224+
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
225225
v.ip = pos - 1
226226
}
227227
case parser.OpAndJump:
228-
v.ip += 2
228+
v.ip += 4
229229
if v.stack[v.sp-1].IsFalsy() {
230-
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
230+
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
231231
v.ip = pos - 1
232232
} else {
233233
v.sp--
234234
}
235235
case parser.OpOrJump:
236-
v.ip += 2
236+
v.ip += 4
237237
if v.stack[v.sp-1].IsFalsy() {
238238
v.sp--
239239
} else {
240-
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
240+
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
241241
v.ip = pos - 1
242242
}
243243
case parser.OpJump:
244-
pos := int(v.curInsts[v.ip+2]) | int(v.curInsts[v.ip+1])<<8
244+
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
245245
v.ip = pos - 1
246246
case parser.OpSetGlobal:
247247
v.ip += 2

0 commit comments

Comments
 (0)