fix a bug in bytecode optimization code (#292)
* fix a bug in bytecode optimization code * add a test
This commit is contained in:
parent
d08a636e7c
commit
d1dd01499f
2 changed files with 28 additions and 3 deletions
12
bytecode.go
12
bytecode.go
|
@ -97,6 +97,7 @@ func (b *Bytecode) RemoveDuplicates() {
|
|||
var deduped []Object
|
||||
|
||||
indexMap := make(map[int]int) // mapping from old constant index to new index
|
||||
fns := make(map[*CompiledFunction]int)
|
||||
ints := make(map[int64]int)
|
||||
strings := make(map[string]int)
|
||||
floats := make(map[float64]int)
|
||||
|
@ -106,9 +107,14 @@ func (b *Bytecode) RemoveDuplicates() {
|
|||
for curIdx, c := range b.Constants {
|
||||
switch c := c.(type) {
|
||||
case *CompiledFunction:
|
||||
// add to deduped list
|
||||
indexMap[curIdx] = len(deduped)
|
||||
deduped = append(deduped, c)
|
||||
if newIdx, ok := fns[c]; ok {
|
||||
indexMap[curIdx] = newIdx
|
||||
} else {
|
||||
newIdx = len(deduped)
|
||||
fns[c] = newIdx
|
||||
indexMap[curIdx] = newIdx
|
||||
deduped = append(deduped, c)
|
||||
}
|
||||
case *ImmutableMap:
|
||||
modName := inferModuleName(c)
|
||||
newIdx, ok := immutableMaps[modName]
|
||||
|
|
19
vm_test.go
19
vm_test.go
|
@ -2654,6 +2654,25 @@ export func(a) {
|
|||
expectRun(t, `out = import("mod0")`,
|
||||
Opts().Module("mod0", `for v:=0;;v++ { if v == 3 { break } } }`),
|
||||
tengo.UndefinedValue)
|
||||
|
||||
// duplicate compiled functions
|
||||
// NOTE: module "mod" has a function with some local variable, and it's
|
||||
// imported twice by the main script. That causes the same CompiledFunction
|
||||
// put in constants twice and the Bytecode optimization (removing duplicate
|
||||
// constants) should still work correctly.
|
||||
expectRun(t, `
|
||||
m1 := import("mod")
|
||||
m2 := import("mod")
|
||||
out = m1.x
|
||||
`,
|
||||
Opts().Module("mod", `
|
||||
f1 := func(a, b) {
|
||||
c := a + b + 1
|
||||
return a + b + 1
|
||||
}
|
||||
export { x: 1 }
|
||||
`),
|
||||
1)
|
||||
}
|
||||
|
||||
func TestModuleBlockScopes(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue