Skip to content

Commit 83fdcc8

Browse files
authored
Merge pull request #3412 from NeoGoBros/fix-seq-points-after-shorten-jump
2 parents 1786136 + 9b688a9 commit 83fdcc8

File tree

2 files changed

+88
-9
lines changed

2 files changed

+88
-9
lines changed

pkg/compiler/codegen.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,7 +2413,7 @@ func (c *codegen) writeJumps(b []byte) ([]byte, error) {
24132413
for _, f := range c.funcs {
24142414
f.rng.Start, f.rng.End = correctRange(f.rng.Start, f.rng.End, nopOffsets)
24152415
}
2416-
return removeNOPs(b, nopOffsets), nil
2416+
return removeNOPs(b, nopOffsets, c.sequencePoints), nil
24172417
}
24182418

24192419
func correctRange(start, end uint16, offsets []int) (uint16, uint16) {
@@ -2455,9 +2455,10 @@ func (c *codegen) replaceLabelWithOffset(ip int, arg []byte) (int, error) {
24552455
// This is done in 2 passes:
24562456
// 1. Alter jump offsets taking into account parts to be removed.
24572457
// 2. Perform actual removal of jump targets.
2458+
// 3. Reevaluate debug sequence points offsets.
24582459
// Note: after jump offsets altering, there can appear new candidates for conversion.
24592460
// These are ignored for now.
2460-
func removeNOPs(b []byte, nopOffsets []int) []byte {
2461+
func removeNOPs(b []byte, nopOffsets []int, sequencePoints map[string][]DebugSeqPoint) []byte {
24612462
if len(nopOffsets) == 0 {
24622463
return b
24632464
}
@@ -2519,6 +2520,20 @@ func removeNOPs(b []byte, nopOffsets []int) []byte {
25192520
copy(b[start-copyOffset:], b[start+1:end])
25202521
copyOffset++
25212522
}
2523+
2524+
// 3. Reevaluate debug sequence points.
2525+
for _, seqPoints := range sequencePoints {
2526+
for i := range seqPoints {
2527+
diff := 0
2528+
for _, offset := range nopOffsets {
2529+
if offset < seqPoints[i].Opcode {
2530+
diff++
2531+
}
2532+
}
2533+
seqPoints[i].Opcode -= diff
2534+
}
2535+
}
2536+
25222537
return b[:len(b)-copyOffset]
25232538
}
25242539

pkg/compiler/jumps_test.go

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@ import (
77
"github.com/stretchr/testify/require"
88
)
99

10-
func testShortenJumps(t *testing.T, before, after []opcode.Opcode, indices []int) {
10+
func testShortenJumps(t *testing.T, before, after []opcode.Opcode, indices []int, spBefore, spAfter map[string][]DebugSeqPoint) {
1111
prog := make([]byte, len(before))
1212
for i := range before {
1313
prog[i] = byte(before[i])
1414
}
15-
raw := removeNOPs(prog, indices)
15+
raw := removeNOPs(prog, indices, spBefore)
1616
actual := make([]opcode.Opcode, len(raw))
1717
for i := range raw {
1818
actual[i] = opcode.Opcode(raw[i])
1919
}
20+
require.Equal(t, spAfter, spBefore)
2021
require.Equal(t, after, actual)
2122
}
2223

@@ -45,18 +46,32 @@ func TestShortenJumps(t *testing.T) {
4546
op, 3, 12, 0, 0, opcode.PUSH1, opcode.NOP,
4647
sop, 249, sop, 0xFF - 2,
4748
}
48-
testShortenJumps(t, before, after, []int{2, 3, 4, 16, 17, 18, 21, 22, 23})
49+
spBefore := map[string][]DebugSeqPoint{
50+
"test": {
51+
DebugSeqPoint{Opcode: 0}, DebugSeqPoint{Opcode: 5},
52+
DebugSeqPoint{Opcode: 7}, DebugSeqPoint{Opcode: 12},
53+
DebugSeqPoint{Opcode: 14}, DebugSeqPoint{Opcode: 19},
54+
},
55+
}
56+
spAfter := map[string][]DebugSeqPoint{
57+
"test": {
58+
DebugSeqPoint{Opcode: 0}, DebugSeqPoint{Opcode: 2},
59+
DebugSeqPoint{Opcode: 4}, DebugSeqPoint{Opcode: 9},
60+
DebugSeqPoint{Opcode: 11}, DebugSeqPoint{Opcode: 13},
61+
},
62+
}
63+
testShortenJumps(t, before, after, []int{2, 3, 4, 16, 17, 18, 21, 22, 23}, spBefore, spAfter)
4964
})
5065
}
5166
t.Run("NoReplace", func(t *testing.T) {
5267
b := []byte{0, 1, 2, 3, 4, 5}
5368
expected := []byte{0, 1, 2, 3, 4, 5}
54-
require.Equal(t, expected, removeNOPs(b, nil))
69+
require.Equal(t, expected, removeNOPs(b, nil, map[string][]DebugSeqPoint{}))
5570
})
5671
t.Run("InvalidIndex", func(t *testing.T) {
5772
before := []byte{byte(opcode.PUSH1), 0, 0, 0, 0}
5873
require.Panics(t, func() {
59-
removeNOPs(before, []int{0})
74+
removeNOPs(before, []int{0}, map[string][]DebugSeqPoint{})
6075
})
6176
})
6277
t.Run("SideConditions", func(t *testing.T) {
@@ -69,7 +84,19 @@ func TestShortenJumps(t *testing.T) {
6984
opcode.JMP, 2,
7085
opcode.JMP, 2,
7186
}
72-
testShortenJumps(t, before, after, []int{2, 3, 4, 7, 8, 9})
87+
spBefore := map[string][]DebugSeqPoint{
88+
"test": {
89+
DebugSeqPoint{Opcode: 0},
90+
DebugSeqPoint{Opcode: 5},
91+
},
92+
}
93+
spAfter := map[string][]DebugSeqPoint{
94+
"test": {
95+
DebugSeqPoint{Opcode: 0},
96+
DebugSeqPoint{Opcode: 2},
97+
},
98+
}
99+
testShortenJumps(t, before, after, []int{2, 3, 4, 7, 8, 9}, spBefore, spAfter)
73100
})
74101
t.Run("Backwards", func(t *testing.T) {
75102
before := []opcode.Opcode{
@@ -82,7 +109,21 @@ func TestShortenJumps(t *testing.T) {
82109
opcode.JMP, 0xFF - 1,
83110
opcode.JMP, 0xFF - 1,
84111
}
85-
testShortenJumps(t, before, after, []int{2, 3, 4, 7, 8, 9, 12, 13, 14})
112+
spBefore := map[string][]DebugSeqPoint{
113+
"test": {
114+
DebugSeqPoint{Opcode: 0},
115+
DebugSeqPoint{Opcode: 5},
116+
DebugSeqPoint{Opcode: 10},
117+
},
118+
}
119+
spAfter := map[string][]DebugSeqPoint{
120+
"test": {
121+
DebugSeqPoint{Opcode: 0},
122+
DebugSeqPoint{Opcode: 2},
123+
DebugSeqPoint{Opcode: 4},
124+
},
125+
}
126+
testShortenJumps(t, before, after, []int{2, 3, 4, 7, 8, 9, 12, 13, 14}, spBefore, spAfter)
86127
})
87128
})
88129
}
@@ -100,6 +141,17 @@ func TestWriteJumps(t *testing.T) {
100141
"main": {rng: DebugRange{Start: 4, End: 9}},
101142
"method": {rng: DebugRange{Start: 10, End: 11}},
102143
}
144+
c.sequencePoints = map[string][]DebugSeqPoint{
145+
"init": {
146+
DebugSeqPoint{Opcode: 1}, DebugSeqPoint{Opcode: 3},
147+
},
148+
"main": {
149+
DebugSeqPoint{Opcode: 4}, DebugSeqPoint{Opcode: 9},
150+
},
151+
"method": {
152+
DebugSeqPoint{Opcode: 10}, DebugSeqPoint{Opcode: 11},
153+
},
154+
}
103155

104156
expProg := []byte{
105157
byte(opcode.NOP), byte(opcode.JMP), 2, byte(opcode.RET),
@@ -111,11 +163,23 @@ func TestWriteJumps(t *testing.T) {
111163
"main": {rng: DebugRange{Start: 4, End: 6}},
112164
"method": {rng: DebugRange{Start: 7, End: 8}},
113165
}
166+
expSeqPoints := map[string][]DebugSeqPoint{
167+
"init": {
168+
DebugSeqPoint{Opcode: 1}, DebugSeqPoint{Opcode: 3},
169+
},
170+
"main": {
171+
DebugSeqPoint{Opcode: 4}, DebugSeqPoint{Opcode: 6},
172+
},
173+
"method": {
174+
DebugSeqPoint{Opcode: 7}, DebugSeqPoint{Opcode: 8},
175+
},
176+
}
114177

115178
buf, err := c.writeJumps(before)
116179
require.NoError(t, err)
117180
require.Equal(t, expProg, buf)
118181
require.Equal(t, expFuncs, c.funcs)
182+
require.Equal(t, expSeqPoints, c.sequencePoints)
119183
}
120184

121185
func TestWriteJumpsLastJump(t *testing.T) {

0 commit comments

Comments
 (0)