bytecode.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. package tengo
  2. import (
  3. "encoding/gob"
  4. "fmt"
  5. "io"
  6. "github.com/d5/tengo/v2/parser"
  7. )
  8. // Bytecode is a compiled instructions and constants.
  9. type Bytecode struct {
  10. FileSet *parser.SourceFileSet
  11. MainFunction *CompiledFunction
  12. Constants []Object
  13. }
  14. // Encode writes Bytecode data to the writer.
  15. func (b *Bytecode) Encode(w io.Writer) error {
  16. enc := gob.NewEncoder(w)
  17. if err := enc.Encode(b.FileSet); err != nil {
  18. return err
  19. }
  20. if err := enc.Encode(b.MainFunction); err != nil {
  21. return err
  22. }
  23. return enc.Encode(b.Constants)
  24. }
  25. // CountObjects returns the number of objects found in Constants.
  26. func (b *Bytecode) CountObjects() int {
  27. n := 0
  28. for _, c := range b.Constants {
  29. n += CountObjects(c)
  30. }
  31. return n
  32. }
  33. // FormatInstructions returns human readable string representations of
  34. // compiled instructions.
  35. func (b *Bytecode) FormatInstructions() []string {
  36. return FormatInstructions(b.MainFunction.Instructions, 0)
  37. }
  38. // FormatConstants returns human readable string representations of
  39. // compiled constants.
  40. func (b *Bytecode) FormatConstants() (output []string) {
  41. for cidx, cn := range b.Constants {
  42. switch cn := cn.(type) {
  43. case *CompiledFunction:
  44. output = append(output, fmt.Sprintf(
  45. "[% 3d] (Compiled Function|%p)", cidx, &cn))
  46. for _, l := range FormatInstructions(cn.Instructions, 0) {
  47. output = append(output, fmt.Sprintf(" %s", l))
  48. }
  49. default:
  50. output = append(output, fmt.Sprintf("[% 3d] %s (%s|%p)",
  51. cidx, cn, cn.TypeName(), &cn))
  52. }
  53. }
  54. return
  55. }
  56. // Decode reads Bytecode data from the reader.
  57. func (b *Bytecode) Decode(r io.Reader, modules *ModuleMap) error {
  58. if modules == nil {
  59. modules = NewModuleMap()
  60. }
  61. dec := gob.NewDecoder(r)
  62. if err := dec.Decode(&b.FileSet); err != nil {
  63. return err
  64. }
  65. // TODO: files in b.FileSet.File does not have their 'set' field properly
  66. // set to b.FileSet as it's private field and not serialized by gob
  67. // encoder/decoder.
  68. if err := dec.Decode(&b.MainFunction); err != nil {
  69. return err
  70. }
  71. if err := dec.Decode(&b.Constants); err != nil {
  72. return err
  73. }
  74. for i, v := range b.Constants {
  75. fv, err := fixDecodedObject(v, modules)
  76. if err != nil {
  77. return err
  78. }
  79. b.Constants[i] = fv
  80. }
  81. return nil
  82. }
  83. // RemoveDuplicates finds and remove the duplicate values in Constants.
  84. // Note this function mutates Bytecode.
  85. func (b *Bytecode) RemoveDuplicates() {
  86. var deduped []Object
  87. indexMap := make(map[int]int) // mapping from old constant index to new index
  88. fns := make(map[*CompiledFunction]int)
  89. ints := make(map[int64]int)
  90. strings := make(map[string]int)
  91. floats := make(map[float64]int)
  92. chars := make(map[rune]int)
  93. immutableMaps := make(map[string]int) // for modules
  94. for curIdx, c := range b.Constants {
  95. switch c := c.(type) {
  96. case *CompiledFunction:
  97. if newIdx, ok := fns[c]; ok {
  98. indexMap[curIdx] = newIdx
  99. } else {
  100. newIdx = len(deduped)
  101. fns[c] = newIdx
  102. indexMap[curIdx] = newIdx
  103. deduped = append(deduped, c)
  104. }
  105. case *ImmutableMap:
  106. modName := inferModuleName(c)
  107. newIdx, ok := immutableMaps[modName]
  108. if modName != "" && ok {
  109. indexMap[curIdx] = newIdx
  110. } else {
  111. newIdx = len(deduped)
  112. immutableMaps[modName] = newIdx
  113. indexMap[curIdx] = newIdx
  114. deduped = append(deduped, c)
  115. }
  116. case Int:
  117. if newIdx, ok := ints[c.Value]; ok {
  118. indexMap[curIdx] = newIdx
  119. } else {
  120. newIdx = len(deduped)
  121. ints[c.Value] = newIdx
  122. indexMap[curIdx] = newIdx
  123. deduped = append(deduped, c)
  124. }
  125. case *String:
  126. if newIdx, ok := strings[c.Value]; ok {
  127. indexMap[curIdx] = newIdx
  128. } else {
  129. newIdx = len(deduped)
  130. strings[c.Value] = newIdx
  131. indexMap[curIdx] = newIdx
  132. deduped = append(deduped, c)
  133. }
  134. case Float:
  135. if newIdx, ok := floats[c.Value]; ok {
  136. indexMap[curIdx] = newIdx
  137. } else {
  138. newIdx = len(deduped)
  139. floats[c.Value] = newIdx
  140. indexMap[curIdx] = newIdx
  141. deduped = append(deduped, c)
  142. }
  143. case Char:
  144. if newIdx, ok := chars[c.Value]; ok {
  145. indexMap[curIdx] = newIdx
  146. } else {
  147. newIdx = len(deduped)
  148. chars[c.Value] = newIdx
  149. indexMap[curIdx] = newIdx
  150. deduped = append(deduped, c)
  151. }
  152. default:
  153. panic(fmt.Errorf("unsupported top-level constant type: %s",
  154. c.TypeName()))
  155. }
  156. }
  157. // replace with de-duplicated constants
  158. b.Constants = deduped
  159. // update CONST instructions with new indexes
  160. // main function
  161. updateConstIndexes(b.MainFunction.Instructions, indexMap)
  162. // other compiled functions in constants
  163. for _, c := range b.Constants {
  164. switch c := c.(type) {
  165. case *CompiledFunction:
  166. updateConstIndexes(c.Instructions, indexMap)
  167. }
  168. }
  169. }
  170. func fixDecodedObject(
  171. o Object,
  172. modules *ModuleMap,
  173. ) (Object, error) {
  174. switch o := o.(type) {
  175. case Bool:
  176. if o.IsFalsy() {
  177. return FalseValue, nil
  178. }
  179. return TrueValue, nil
  180. case *Undefined:
  181. return UndefinedValue, nil
  182. case *Array:
  183. for i, v := range o.Value {
  184. fv, err := fixDecodedObject(v, modules)
  185. if err != nil {
  186. return nil, err
  187. }
  188. o.Value[i] = fv
  189. }
  190. case *ImmutableArray:
  191. for i, v := range o.Value {
  192. fv, err := fixDecodedObject(v, modules)
  193. if err != nil {
  194. return nil, err
  195. }
  196. o.Value[i] = fv
  197. }
  198. case *Map:
  199. for k, v := range o.Value {
  200. fv, err := fixDecodedObject(v, modules)
  201. if err != nil {
  202. return nil, err
  203. }
  204. o.Value[k] = fv
  205. }
  206. case *ImmutableMap:
  207. modName := inferModuleName(o)
  208. if mod := modules.GetBuiltinModule(modName); mod != nil {
  209. return mod.AsImmutableMap(modName), nil
  210. }
  211. for k, v := range o.Value {
  212. // encoding of user function not supported
  213. if _, isUserFunction := v.(*UserFunction); isUserFunction {
  214. return nil, fmt.Errorf("user function not decodable")
  215. }
  216. fv, err := fixDecodedObject(v, modules)
  217. if err != nil {
  218. return nil, err
  219. }
  220. o.Value[k] = fv
  221. }
  222. }
  223. return o, nil
  224. }
  225. func updateConstIndexes(insts []byte, indexMap map[int]int) {
  226. i := 0
  227. for i < len(insts) {
  228. op := insts[i]
  229. numOperands := parser.OpcodeOperands[op]
  230. _, read := parser.ReadOperands(numOperands, insts[i+1:])
  231. switch op {
  232. case parser.OpConstant:
  233. curIdx := int(insts[i+2]) | int(insts[i+1])<<8
  234. newIdx, ok := indexMap[curIdx]
  235. if !ok {
  236. panic(fmt.Errorf("constant index not found: %d", curIdx))
  237. }
  238. copy(insts[i:], MakeInstruction(op, newIdx))
  239. case parser.OpClosure:
  240. curIdx := int(insts[i+2]) | int(insts[i+1])<<8
  241. numFree := int(insts[i+3])
  242. newIdx, ok := indexMap[curIdx]
  243. if !ok {
  244. panic(fmt.Errorf("constant index not found: %d", curIdx))
  245. }
  246. copy(insts[i:], MakeInstruction(op, newIdx, numFree))
  247. }
  248. i += 1 + read
  249. }
  250. }
  251. func inferModuleName(mod *ImmutableMap) string {
  252. if modName, ok := mod.Value["__module_name__"].(*String); ok {
  253. return modName.Value
  254. }
  255. return ""
  256. }
  257. func init() {
  258. gob.Register(&parser.SourceFileSet{})
  259. gob.Register(&parser.SourceFile{})
  260. gob.Register(&Array{})
  261. gob.Register(Bool{})
  262. gob.Register(&Bytes{})
  263. gob.Register(Char{})
  264. gob.Register(&CompiledFunction{})
  265. gob.Register(&Error{})
  266. gob.Register(Float{})
  267. gob.Register(&ImmutableArray{})
  268. gob.Register(&ImmutableMap{})
  269. gob.Register(Int{})
  270. gob.Register(&Map{})
  271. gob.Register(&String{})
  272. gob.Register(&Time{})
  273. gob.Register(&Undefined{})
  274. gob.Register(&UserFunction{})
  275. }