fix a bug in dead code elimination (#168)

* fix a bug in dead code elimination

* add some tests
This commit is contained in:
Daniel 2019-03-31 12:20:10 -07:00 committed by GitHub
parent 2f86800724
commit 9b6c5e670a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 6 deletions

View file

@ -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:

View file

@ -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)
}