fix a bug in dead code elimination (#168)
* fix a bug in dead code elimination * add some tests
This commit is contained in:
parent
2f86800724
commit
9b6c5e670a
2 changed files with 39 additions and 6 deletions
|
@ -6,7 +6,6 @@ import (
|
|||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/d5/tengo"
|
||||
|
@ -722,16 +721,15 @@ func (c *Compiler) optimizeFunc(node ast.Node) {
|
|||
// are considered as unreachable.
|
||||
|
||||
// pass 1. identify all jump destinations
|
||||
var dsts []int
|
||||
dsts := make(map[int]bool)
|
||||
iterateInstructions(c.scopes[c.scopeIndex].instructions, func(pos int, opcode Opcode, operands []int) bool {
|
||||
switch opcode {
|
||||
case OpJump, OpJumpFalsy, OpAndJump, OpOrJump:
|
||||
dsts = append(dsts, operands[0])
|
||||
dsts[operands[0]] = true
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
sort.Ints(dsts) // sort jump positions
|
||||
|
||||
var newInsts []byte
|
||||
|
||||
|
@ -746,7 +744,7 @@ func (c *Compiler) optimizeFunc(node ast.Node) {
|
|||
return true
|
||||
}
|
||||
deadCode = true
|
||||
case dstIdx < len(dsts) && pos == dsts[dstIdx]:
|
||||
case dsts[pos]:
|
||||
dstIdx++
|
||||
deadCode = false
|
||||
case deadCode:
|
||||
|
@ -761,7 +759,7 @@ func (c *Compiler) optimizeFunc(node ast.Node) {
|
|||
// pass 3. update jump positions
|
||||
var lastOp Opcode
|
||||
var appendReturn bool
|
||||
endPos := len(newInsts)
|
||||
endPos := len(c.scopes[c.scopeIndex].instructions)
|
||||
iterateInstructions(newInsts, func(pos int, opcode Opcode, operands []int) bool {
|
||||
switch opcode {
|
||||
case OpJump, OpJumpFalsy, OpAndJump, OpOrJump:
|
||||
|
|
|
@ -65,4 +65,39 @@ func() {
|
|||
// expression statement in init (should not leave objects on stack)
|
||||
expect(t, `a := 1; if a; a { out = a }`, nil, 1)
|
||||
expect(t, `a := 1; if a + 4; a { out = a }`, nil, 1)
|
||||
|
||||
// dead code elimination
|
||||
expect(t, `
|
||||
out = func() {
|
||||
if false { return 1 }
|
||||
|
||||
a := undefined
|
||||
|
||||
a = 2
|
||||
if !a {
|
||||
b := func() {
|
||||
return is_callable(a) ? a(8) : a
|
||||
}()
|
||||
if is_error(b) {
|
||||
return b
|
||||
} else if !is_undefined(b) {
|
||||
return immutable(b)
|
||||
}
|
||||
}
|
||||
|
||||
a = 3
|
||||
if a {
|
||||
b := func() {
|
||||
return is_callable(a) ? a(9) : a
|
||||
}()
|
||||
if is_error(b) {
|
||||
return b
|
||||
} else if !is_undefined(b) {
|
||||
return immutable(b)
|
||||
}
|
||||
}
|
||||
|
||||
return a
|
||||
}()
|
||||
`, nil, 3)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue