opcode.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. package encoder
  2. import (
  3. "fmt"
  4. "strings"
  5. "unsafe"
  6. "github.com/goccy/go-json/internal/runtime"
  7. )
  8. const uintptrSize = 4 << (^uintptr(0) >> 63)
  9. type OpFlags uint16
  10. const (
  11. AnonymousHeadFlags OpFlags = 1 << 0
  12. AnonymousKeyFlags OpFlags = 1 << 1
  13. IndirectFlags OpFlags = 1 << 2
  14. IsTaggedKeyFlags OpFlags = 1 << 3
  15. NilCheckFlags OpFlags = 1 << 4
  16. AddrForMarshalerFlags OpFlags = 1 << 5
  17. IsNextOpPtrTypeFlags OpFlags = 1 << 6
  18. IsNilableTypeFlags OpFlags = 1 << 7
  19. MarshalerContextFlags OpFlags = 1 << 8
  20. NonEmptyInterfaceFlags OpFlags = 1 << 9
  21. )
  22. type Opcode struct {
  23. Op OpType // operation type
  24. Idx uint32 // offset to access ptr
  25. Next *Opcode // next opcode
  26. End *Opcode // array/slice/struct/map end
  27. NextField *Opcode // next struct field
  28. Key string // struct field key
  29. Offset uint32 // offset size from struct header
  30. PtrNum uint8 // pointer number: e.g. double pointer is 2.
  31. NumBitSize uint8
  32. Flags OpFlags
  33. Type *runtime.Type // go type
  34. Jmp *CompiledCode // for recursive call
  35. FieldQuery *FieldQuery // field query for Interface / MarshalJSON / MarshalText
  36. ElemIdx uint32 // offset to access array/slice elem
  37. Length uint32 // offset to access slice length or array length
  38. Indent uint32 // indent number
  39. Size uint32 // array/slice elem size
  40. DisplayIdx uint32 // opcode index
  41. DisplayKey string // key text to display
  42. }
  43. func (c *Opcode) Validate() error {
  44. var prevIdx uint32
  45. for code := c; !code.IsEnd(); {
  46. if prevIdx != 0 {
  47. if code.DisplayIdx != prevIdx+1 {
  48. return fmt.Errorf(
  49. "invalid index. previous display index is %d but next is %d. dump = %s",
  50. prevIdx, code.DisplayIdx, c.Dump(),
  51. )
  52. }
  53. }
  54. prevIdx = code.DisplayIdx
  55. code = code.IterNext()
  56. }
  57. return nil
  58. }
  59. func (c *Opcode) IterNext() *Opcode {
  60. if c == nil {
  61. return nil
  62. }
  63. switch c.Op.CodeType() {
  64. case CodeArrayElem, CodeSliceElem, CodeMapKey:
  65. return c.End
  66. default:
  67. return c.Next
  68. }
  69. }
  70. func (c *Opcode) IsEnd() bool {
  71. if c == nil {
  72. return true
  73. }
  74. return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd
  75. }
  76. func (c *Opcode) MaxIdx() uint32 {
  77. max := uint32(0)
  78. for _, value := range []uint32{
  79. c.Idx,
  80. c.ElemIdx,
  81. c.Length,
  82. c.Size,
  83. } {
  84. if max < value {
  85. max = value
  86. }
  87. }
  88. return max
  89. }
  90. func (c *Opcode) ToHeaderType(isString bool) OpType {
  91. switch c.Op {
  92. case OpInt:
  93. if isString {
  94. return OpStructHeadIntString
  95. }
  96. return OpStructHeadInt
  97. case OpIntPtr:
  98. if isString {
  99. return OpStructHeadIntPtrString
  100. }
  101. return OpStructHeadIntPtr
  102. case OpUint:
  103. if isString {
  104. return OpStructHeadUintString
  105. }
  106. return OpStructHeadUint
  107. case OpUintPtr:
  108. if isString {
  109. return OpStructHeadUintPtrString
  110. }
  111. return OpStructHeadUintPtr
  112. case OpFloat32:
  113. if isString {
  114. return OpStructHeadFloat32String
  115. }
  116. return OpStructHeadFloat32
  117. case OpFloat32Ptr:
  118. if isString {
  119. return OpStructHeadFloat32PtrString
  120. }
  121. return OpStructHeadFloat32Ptr
  122. case OpFloat64:
  123. if isString {
  124. return OpStructHeadFloat64String
  125. }
  126. return OpStructHeadFloat64
  127. case OpFloat64Ptr:
  128. if isString {
  129. return OpStructHeadFloat64PtrString
  130. }
  131. return OpStructHeadFloat64Ptr
  132. case OpString:
  133. if isString {
  134. return OpStructHeadStringString
  135. }
  136. return OpStructHeadString
  137. case OpStringPtr:
  138. if isString {
  139. return OpStructHeadStringPtrString
  140. }
  141. return OpStructHeadStringPtr
  142. case OpNumber:
  143. if isString {
  144. return OpStructHeadNumberString
  145. }
  146. return OpStructHeadNumber
  147. case OpNumberPtr:
  148. if isString {
  149. return OpStructHeadNumberPtrString
  150. }
  151. return OpStructHeadNumberPtr
  152. case OpBool:
  153. if isString {
  154. return OpStructHeadBoolString
  155. }
  156. return OpStructHeadBool
  157. case OpBoolPtr:
  158. if isString {
  159. return OpStructHeadBoolPtrString
  160. }
  161. return OpStructHeadBoolPtr
  162. case OpBytes:
  163. return OpStructHeadBytes
  164. case OpBytesPtr:
  165. return OpStructHeadBytesPtr
  166. case OpMap:
  167. return OpStructHeadMap
  168. case OpMapPtr:
  169. c.Op = OpMap
  170. return OpStructHeadMapPtr
  171. case OpArray:
  172. return OpStructHeadArray
  173. case OpArrayPtr:
  174. c.Op = OpArray
  175. return OpStructHeadArrayPtr
  176. case OpSlice:
  177. return OpStructHeadSlice
  178. case OpSlicePtr:
  179. c.Op = OpSlice
  180. return OpStructHeadSlicePtr
  181. case OpMarshalJSON:
  182. return OpStructHeadMarshalJSON
  183. case OpMarshalJSONPtr:
  184. return OpStructHeadMarshalJSONPtr
  185. case OpMarshalText:
  186. return OpStructHeadMarshalText
  187. case OpMarshalTextPtr:
  188. return OpStructHeadMarshalTextPtr
  189. }
  190. return OpStructHead
  191. }
  192. func (c *Opcode) ToFieldType(isString bool) OpType {
  193. switch c.Op {
  194. case OpInt:
  195. if isString {
  196. return OpStructFieldIntString
  197. }
  198. return OpStructFieldInt
  199. case OpIntPtr:
  200. if isString {
  201. return OpStructFieldIntPtrString
  202. }
  203. return OpStructFieldIntPtr
  204. case OpUint:
  205. if isString {
  206. return OpStructFieldUintString
  207. }
  208. return OpStructFieldUint
  209. case OpUintPtr:
  210. if isString {
  211. return OpStructFieldUintPtrString
  212. }
  213. return OpStructFieldUintPtr
  214. case OpFloat32:
  215. if isString {
  216. return OpStructFieldFloat32String
  217. }
  218. return OpStructFieldFloat32
  219. case OpFloat32Ptr:
  220. if isString {
  221. return OpStructFieldFloat32PtrString
  222. }
  223. return OpStructFieldFloat32Ptr
  224. case OpFloat64:
  225. if isString {
  226. return OpStructFieldFloat64String
  227. }
  228. return OpStructFieldFloat64
  229. case OpFloat64Ptr:
  230. if isString {
  231. return OpStructFieldFloat64PtrString
  232. }
  233. return OpStructFieldFloat64Ptr
  234. case OpString:
  235. if isString {
  236. return OpStructFieldStringString
  237. }
  238. return OpStructFieldString
  239. case OpStringPtr:
  240. if isString {
  241. return OpStructFieldStringPtrString
  242. }
  243. return OpStructFieldStringPtr
  244. case OpNumber:
  245. if isString {
  246. return OpStructFieldNumberString
  247. }
  248. return OpStructFieldNumber
  249. case OpNumberPtr:
  250. if isString {
  251. return OpStructFieldNumberPtrString
  252. }
  253. return OpStructFieldNumberPtr
  254. case OpBool:
  255. if isString {
  256. return OpStructFieldBoolString
  257. }
  258. return OpStructFieldBool
  259. case OpBoolPtr:
  260. if isString {
  261. return OpStructFieldBoolPtrString
  262. }
  263. return OpStructFieldBoolPtr
  264. case OpBytes:
  265. return OpStructFieldBytes
  266. case OpBytesPtr:
  267. return OpStructFieldBytesPtr
  268. case OpMap:
  269. return OpStructFieldMap
  270. case OpMapPtr:
  271. c.Op = OpMap
  272. return OpStructFieldMapPtr
  273. case OpArray:
  274. return OpStructFieldArray
  275. case OpArrayPtr:
  276. c.Op = OpArray
  277. return OpStructFieldArrayPtr
  278. case OpSlice:
  279. return OpStructFieldSlice
  280. case OpSlicePtr:
  281. c.Op = OpSlice
  282. return OpStructFieldSlicePtr
  283. case OpMarshalJSON:
  284. return OpStructFieldMarshalJSON
  285. case OpMarshalJSONPtr:
  286. return OpStructFieldMarshalJSONPtr
  287. case OpMarshalText:
  288. return OpStructFieldMarshalText
  289. case OpMarshalTextPtr:
  290. return OpStructFieldMarshalTextPtr
  291. }
  292. return OpStructField
  293. }
  294. func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode {
  295. return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ))
  296. }
  297. func opcodeOffset(idx int) uint32 {
  298. return uint32(idx) * uintptrSize
  299. }
  300. func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode {
  301. addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{})
  302. return *(**Opcode)(unsafe.Pointer(&addr))
  303. }
  304. func copyOpcode(code *Opcode) *Opcode {
  305. codeNum := ToEndCode(code).DisplayIdx + 1
  306. codeSlice := make([]Opcode, codeNum)
  307. head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data)
  308. ptr := head
  309. c := code
  310. for {
  311. *ptr = Opcode{
  312. Op: c.Op,
  313. Key: c.Key,
  314. PtrNum: c.PtrNum,
  315. NumBitSize: c.NumBitSize,
  316. Flags: c.Flags,
  317. Idx: c.Idx,
  318. Offset: c.Offset,
  319. Type: c.Type,
  320. FieldQuery: c.FieldQuery,
  321. DisplayIdx: c.DisplayIdx,
  322. DisplayKey: c.DisplayKey,
  323. ElemIdx: c.ElemIdx,
  324. Length: c.Length,
  325. Size: c.Size,
  326. Indent: c.Indent,
  327. Jmp: c.Jmp,
  328. }
  329. if c.End != nil {
  330. ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx)
  331. }
  332. if c.NextField != nil {
  333. ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx)
  334. }
  335. if c.Next != nil {
  336. ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx)
  337. }
  338. if c.IsEnd() {
  339. break
  340. }
  341. ptr = getCodeAddrByIdx(head, c.DisplayIdx+1)
  342. c = c.IterNext()
  343. }
  344. return head
  345. }
  346. func setTotalLengthToInterfaceOp(code *Opcode) {
  347. for c := code; !c.IsEnd(); {
  348. if c.Op == OpInterface || c.Op == OpInterfacePtr {
  349. c.Length = uint32(code.TotalLength())
  350. }
  351. c = c.IterNext()
  352. }
  353. }
  354. func ToEndCode(code *Opcode) *Opcode {
  355. c := code
  356. for !c.IsEnd() {
  357. c = c.IterNext()
  358. }
  359. return c
  360. }
  361. func copyToInterfaceOpcode(code *Opcode) *Opcode {
  362. copied := copyOpcode(code)
  363. c := copied
  364. c = ToEndCode(c)
  365. c.Idx += uintptrSize
  366. c.ElemIdx = c.Idx + uintptrSize
  367. c.Length = c.Idx + 2*uintptrSize
  368. c.Op = OpInterfaceEnd
  369. return copied
  370. }
  371. func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode {
  372. return &Opcode{
  373. Op: op,
  374. Idx: opcodeOffset(ctx.ptrIndex),
  375. Next: next,
  376. Type: typ,
  377. DisplayIdx: ctx.opcodeIndex,
  378. Indent: ctx.indent,
  379. }
  380. }
  381. func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode {
  382. return newOpCodeWithNext(ctx, typ, OpEnd, nil)
  383. }
  384. func (c *Opcode) TotalLength() int {
  385. var idx int
  386. code := c
  387. for !code.IsEnd() {
  388. maxIdx := int(code.MaxIdx() / uintptrSize)
  389. if idx < maxIdx {
  390. idx = maxIdx
  391. }
  392. if code.Op == OpRecursiveEnd {
  393. break
  394. }
  395. code = code.IterNext()
  396. }
  397. maxIdx := int(code.MaxIdx() / uintptrSize)
  398. if idx < maxIdx {
  399. idx = maxIdx
  400. }
  401. return idx + 1
  402. }
  403. func (c *Opcode) dumpHead(code *Opcode) string {
  404. var length uint32
  405. if code.Op.CodeType() == CodeArrayHead {
  406. length = code.Length
  407. } else {
  408. length = code.Length / uintptrSize
  409. }
  410. return fmt.Sprintf(
  411. `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
  412. code.DisplayIdx,
  413. strings.Repeat("-", int(code.Indent)),
  414. code.Op,
  415. code.Idx/uintptrSize,
  416. code.ElemIdx/uintptrSize,
  417. length,
  418. )
  419. }
  420. func (c *Opcode) dumpMapHead(code *Opcode) string {
  421. return fmt.Sprintf(
  422. `[%03d]%s%s ([idx:%d])`,
  423. code.DisplayIdx,
  424. strings.Repeat("-", int(code.Indent)),
  425. code.Op,
  426. code.Idx/uintptrSize,
  427. )
  428. }
  429. func (c *Opcode) dumpMapEnd(code *Opcode) string {
  430. return fmt.Sprintf(
  431. `[%03d]%s%s ([idx:%d])`,
  432. code.DisplayIdx,
  433. strings.Repeat("-", int(code.Indent)),
  434. code.Op,
  435. code.Idx/uintptrSize,
  436. )
  437. }
  438. func (c *Opcode) dumpElem(code *Opcode) string {
  439. var length uint32
  440. if code.Op.CodeType() == CodeArrayElem {
  441. length = code.Length
  442. } else {
  443. length = code.Length / uintptrSize
  444. }
  445. return fmt.Sprintf(
  446. `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
  447. code.DisplayIdx,
  448. strings.Repeat("-", int(code.Indent)),
  449. code.Op,
  450. code.Idx/uintptrSize,
  451. code.ElemIdx/uintptrSize,
  452. length,
  453. code.Size,
  454. )
  455. }
  456. func (c *Opcode) dumpField(code *Opcode) string {
  457. return fmt.Sprintf(
  458. `[%03d]%s%s ([idx:%d][key:%s][offset:%d])`,
  459. code.DisplayIdx,
  460. strings.Repeat("-", int(code.Indent)),
  461. code.Op,
  462. code.Idx/uintptrSize,
  463. code.DisplayKey,
  464. code.Offset,
  465. )
  466. }
  467. func (c *Opcode) dumpKey(code *Opcode) string {
  468. return fmt.Sprintf(
  469. `[%03d]%s%s ([idx:%d])`,
  470. code.DisplayIdx,
  471. strings.Repeat("-", int(code.Indent)),
  472. code.Op,
  473. code.Idx/uintptrSize,
  474. )
  475. }
  476. func (c *Opcode) dumpValue(code *Opcode) string {
  477. return fmt.Sprintf(
  478. `[%03d]%s%s ([idx:%d])`,
  479. code.DisplayIdx,
  480. strings.Repeat("-", int(code.Indent)),
  481. code.Op,
  482. code.Idx/uintptrSize,
  483. )
  484. }
  485. func (c *Opcode) Dump() string {
  486. codes := []string{}
  487. for code := c; !code.IsEnd(); {
  488. switch code.Op.CodeType() {
  489. case CodeSliceHead:
  490. codes = append(codes, c.dumpHead(code))
  491. code = code.Next
  492. case CodeMapHead:
  493. codes = append(codes, c.dumpMapHead(code))
  494. code = code.Next
  495. case CodeArrayElem, CodeSliceElem:
  496. codes = append(codes, c.dumpElem(code))
  497. code = code.End
  498. case CodeMapKey:
  499. codes = append(codes, c.dumpKey(code))
  500. code = code.End
  501. case CodeMapValue:
  502. codes = append(codes, c.dumpValue(code))
  503. code = code.Next
  504. case CodeMapEnd:
  505. codes = append(codes, c.dumpMapEnd(code))
  506. code = code.Next
  507. case CodeStructField:
  508. codes = append(codes, c.dumpField(code))
  509. code = code.Next
  510. case CodeStructEnd:
  511. codes = append(codes, c.dumpField(code))
  512. code = code.Next
  513. default:
  514. codes = append(codes, fmt.Sprintf(
  515. "[%03d]%s%s ([idx:%d])",
  516. code.DisplayIdx,
  517. strings.Repeat("-", int(code.Indent)),
  518. code.Op,
  519. code.Idx/uintptrSize,
  520. ))
  521. code = code.Next
  522. }
  523. }
  524. return strings.Join(codes, "\n")
  525. }
  526. func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
  527. idx := opcodeOffset(ctx.ptrIndex)
  528. ctx.incPtrIndex()
  529. elemIdx := opcodeOffset(ctx.ptrIndex)
  530. ctx.incPtrIndex()
  531. length := opcodeOffset(ctx.ptrIndex)
  532. return &Opcode{
  533. Op: OpSlice,
  534. Type: typ,
  535. Idx: idx,
  536. DisplayIdx: ctx.opcodeIndex,
  537. ElemIdx: elemIdx,
  538. Length: length,
  539. Indent: ctx.indent,
  540. }
  541. }
  542. func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode {
  543. return &Opcode{
  544. Op: OpSliceElem,
  545. Type: typ,
  546. Idx: head.Idx,
  547. DisplayIdx: ctx.opcodeIndex,
  548. ElemIdx: head.ElemIdx,
  549. Length: head.Length,
  550. Indent: ctx.indent,
  551. Size: uint32(size),
  552. }
  553. }
  554. func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode {
  555. idx := opcodeOffset(ctx.ptrIndex)
  556. ctx.incPtrIndex()
  557. elemIdx := opcodeOffset(ctx.ptrIndex)
  558. return &Opcode{
  559. Op: OpArray,
  560. Type: typ,
  561. Idx: idx,
  562. DisplayIdx: ctx.opcodeIndex,
  563. ElemIdx: elemIdx,
  564. Indent: ctx.indent,
  565. Length: uint32(alen),
  566. }
  567. }
  568. func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode {
  569. return &Opcode{
  570. Op: OpArrayElem,
  571. Type: typ,
  572. Idx: head.Idx,
  573. DisplayIdx: ctx.opcodeIndex,
  574. ElemIdx: head.ElemIdx,
  575. Length: uint32(length),
  576. Indent: ctx.indent,
  577. Size: uint32(size),
  578. }
  579. }
  580. func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
  581. idx := opcodeOffset(ctx.ptrIndex)
  582. ctx.incPtrIndex()
  583. return &Opcode{
  584. Op: OpMap,
  585. Type: typ,
  586. Idx: idx,
  587. DisplayIdx: ctx.opcodeIndex,
  588. Indent: ctx.indent,
  589. }
  590. }
  591. func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
  592. return &Opcode{
  593. Op: OpMapKey,
  594. Type: typ,
  595. Idx: head.Idx,
  596. DisplayIdx: ctx.opcodeIndex,
  597. Indent: ctx.indent,
  598. }
  599. }
  600. func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
  601. return &Opcode{
  602. Op: OpMapValue,
  603. Type: typ,
  604. Idx: head.Idx,
  605. DisplayIdx: ctx.opcodeIndex,
  606. Indent: ctx.indent,
  607. }
  608. }
  609. func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
  610. return &Opcode{
  611. Op: OpMapEnd,
  612. Type: typ,
  613. Idx: head.Idx,
  614. DisplayIdx: ctx.opcodeIndex,
  615. Indent: ctx.indent,
  616. Next: newEndOp(ctx, typ),
  617. }
  618. }
  619. func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode {
  620. return &Opcode{
  621. Op: OpRecursive,
  622. Type: typ,
  623. Idx: opcodeOffset(ctx.ptrIndex),
  624. Next: newEndOp(ctx, typ),
  625. DisplayIdx: ctx.opcodeIndex,
  626. Indent: ctx.indent,
  627. Jmp: jmp,
  628. }
  629. }