bytecode.go 7.1 KB

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