mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-02 00:06:19 +00:00
129
vendor/github.com/d5/tengo/compiler/bytecode_optimize.go
generated
vendored
Normal file
129
vendor/github.com/d5/tengo/compiler/bytecode_optimize.go
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/d5/tengo/objects"
|
||||
)
|
||||
|
||||
// RemoveDuplicates finds and remove the duplicate values in Constants.
|
||||
// Note this function mutates Bytecode.
|
||||
func (b *Bytecode) RemoveDuplicates() {
|
||||
var deduped []objects.Object
|
||||
|
||||
indexMap := make(map[int]int) // mapping from old constant index to new index
|
||||
ints := make(map[int64]int)
|
||||
strings := make(map[string]int)
|
||||
floats := make(map[float64]int)
|
||||
chars := make(map[rune]int)
|
||||
immutableMaps := make(map[string]int) // for modules
|
||||
|
||||
for curIdx, c := range b.Constants {
|
||||
switch c := c.(type) {
|
||||
case *objects.CompiledFunction:
|
||||
// add to deduped list
|
||||
indexMap[curIdx] = len(deduped)
|
||||
deduped = append(deduped, c)
|
||||
case *objects.ImmutableMap:
|
||||
modName := moduleName(c)
|
||||
newIdx, ok := immutableMaps[modName]
|
||||
if modName != "" && ok {
|
||||
indexMap[curIdx] = newIdx
|
||||
} else {
|
||||
newIdx = len(deduped)
|
||||
immutableMaps[modName] = newIdx
|
||||
indexMap[curIdx] = newIdx
|
||||
deduped = append(deduped, c)
|
||||
}
|
||||
case *objects.Int:
|
||||
if newIdx, ok := ints[c.Value]; ok {
|
||||
indexMap[curIdx] = newIdx
|
||||
} else {
|
||||
newIdx = len(deduped)
|
||||
ints[c.Value] = newIdx
|
||||
indexMap[curIdx] = newIdx
|
||||
deduped = append(deduped, c)
|
||||
}
|
||||
case *objects.String:
|
||||
if newIdx, ok := strings[c.Value]; ok {
|
||||
indexMap[curIdx] = newIdx
|
||||
} else {
|
||||
newIdx = len(deduped)
|
||||
strings[c.Value] = newIdx
|
||||
indexMap[curIdx] = newIdx
|
||||
deduped = append(deduped, c)
|
||||
}
|
||||
case *objects.Float:
|
||||
if newIdx, ok := floats[c.Value]; ok {
|
||||
indexMap[curIdx] = newIdx
|
||||
} else {
|
||||
newIdx = len(deduped)
|
||||
floats[c.Value] = newIdx
|
||||
indexMap[curIdx] = newIdx
|
||||
deduped = append(deduped, c)
|
||||
}
|
||||
case *objects.Char:
|
||||
if newIdx, ok := chars[c.Value]; ok {
|
||||
indexMap[curIdx] = newIdx
|
||||
} else {
|
||||
newIdx = len(deduped)
|
||||
chars[c.Value] = newIdx
|
||||
indexMap[curIdx] = newIdx
|
||||
deduped = append(deduped, c)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported top-level constant type: %s", c.TypeName()))
|
||||
}
|
||||
}
|
||||
|
||||
// replace with de-duplicated constants
|
||||
b.Constants = deduped
|
||||
|
||||
// update CONST instructions with new indexes
|
||||
// main function
|
||||
updateConstIndexes(b.MainFunction.Instructions, indexMap)
|
||||
// other compiled functions in constants
|
||||
for _, c := range b.Constants {
|
||||
switch c := c.(type) {
|
||||
case *objects.CompiledFunction:
|
||||
updateConstIndexes(c.Instructions, indexMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateConstIndexes(insts []byte, indexMap map[int]int) {
|
||||
i := 0
|
||||
for i < len(insts) {
|
||||
op := insts[i]
|
||||
numOperands := OpcodeOperands[op]
|
||||
_, read := ReadOperands(numOperands, insts[i+1:])
|
||||
|
||||
switch op {
|
||||
case OpConstant:
|
||||
curIdx := int(insts[i+2]) | int(insts[i+1])<<8
|
||||
newIdx, ok := indexMap[curIdx]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("constant index not found: %d", curIdx))
|
||||
}
|
||||
copy(insts[i:], MakeInstruction(op, newIdx))
|
||||
case OpClosure:
|
||||
curIdx := int(insts[i+2]) | int(insts[i+1])<<8
|
||||
numFree := int(insts[i+3])
|
||||
newIdx, ok := indexMap[curIdx]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("constant index not found: %d", curIdx))
|
||||
}
|
||||
copy(insts[i:], MakeInstruction(op, newIdx, numFree))
|
||||
}
|
||||
|
||||
i += 1 + read
|
||||
}
|
||||
}
|
||||
|
||||
func moduleName(mod *objects.ImmutableMap) string {
|
||||
if modName, ok := mod.Value["__module_name__"].(*objects.String); ok {
|
||||
return modName.Value
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
Reference in New Issue
Block a user