• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (c) 2022 Huawei Device Co., Ltd.
3   * Licensed under the Apache License, Version 2.0 (the "License");
4   * you may not use this file except in compliance with the License.
5   * You may obtain a copy of the License at
6   *
7   *     http://www.apache.org/licenses/LICENSE-2.0
8   *
9   * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  #ifndef ECMASCRIPT_COMPILER_BYTECODES_H
17  #define ECMASCRIPT_COMPILER_BYTECODES_H
18  
19  #include <cstddef>
20  #include <array>
21  
22  #include "libpandabase/macros.h"
23  #include "libpandabase/utils/bit_field.h"
24  #include "libpandafile/bytecode_instruction-inl.h"
25  #include "ecmascript/common.h"
26  #include "ecmascript/js_tagged_value.h"
27  
28  namespace panda::ecmascript::kungfu {
29  using VRegIDType = uint32_t;
30  using ICSlotIdType = uint16_t;
31  using ImmValueType = uint64_t;
32  using EcmaOpcode = BytecodeInstruction::Opcode;
33  
34  class BytecodeCircuitBuilder;
35  class Bytecodes;
36  class BytecodeInfo;
37  class BytecodeIterator;
38  
39  enum BytecodeFlags : uint32_t {
40      READ_ACC = 1 << 0, // 1: flag bit
41      WRITE_ACC = 1 << 1, // 1: flag 1
42      SUPPORT_DEOPT = 1 << 2, // 2: flag 2
43      GENERAL_BC = 1 << 3,
44      READ_THIS_OBJECT = 1 << 4,
45      NO_SIDE_EFFECTS = 1 << 5,
46      NO_THROW = 1 << 6,
47      READ_ENV = 1 << 7,
48      WRITE_ENV = 1 << 8,
49      READ_FUNC = 1 << 9,
50      READ_NEWTARGET = 1 << 10,
51      READ_ARGC = 1 << 11,
52      NO_GC = 1 << 12,
53  };
54  
55  enum BytecodeKind : uint32_t {
56      GENERAL = 0,
57      THROW_BC,
58      RETURN_BC,
59      JUMP_IMM,
60      CONDITIONAL_JUMP,
61      MOV,
62      SET_CONSTANT,
63      SUSPEND,
64      RESUME,
65      GENERATOR_RESOLVE,
66      DISCARDED,
67      CALL_BC,
68  };
69  
70  class BytecodeMetaData {
71  public:
72      static constexpr uint32_t MAX_OPCODE_SIZE = 16;
73      static constexpr uint32_t MAX_SIZE_BITS = 4;
74      static constexpr uint32_t BYTECODE_FLAGS_SIZE = 13;
75      static constexpr uint32_t BYTECODE_KIND_SIZE = 4;
76  
77      using OpcodeField = panda::BitField<EcmaOpcode, 0, MAX_OPCODE_SIZE>;
78      using SizeField = OpcodeField::NextField<size_t, MAX_SIZE_BITS>;
79      using KindField = SizeField::NextField<BytecodeKind, BYTECODE_KIND_SIZE>;
80      using FlagsField = KindField::NextField<BytecodeFlags, BYTECODE_FLAGS_SIZE>;
81  
HasAccIn()82      bool HasAccIn() const
83      {
84          return HasFlag(BytecodeFlags::READ_ACC);
85      }
86  
IsNoSideEffects()87      bool IsNoSideEffects() const
88      {
89          return HasFlag(BytecodeFlags::NO_SIDE_EFFECTS);
90      }
91  
IsNoThrow()92      bool IsNoThrow() const
93      {
94          return HasFlag(BytecodeFlags::NO_THROW);
95      }
96  
HasThisIn()97      bool HasThisIn() const
98      {
99          return HasFlag(BytecodeFlags::READ_THIS_OBJECT);
100      }
101  
HasAccOut()102      bool HasAccOut() const
103      {
104          return HasFlag(BytecodeFlags::WRITE_ACC);
105      }
106  
HasEnvIn()107      bool HasEnvIn() const
108      {
109          return HasFlag(BytecodeFlags::READ_ENV);
110      }
111  
HasEnvOut()112      bool HasEnvOut() const
113      {
114          return HasFlag(BytecodeFlags::WRITE_ENV);
115      }
116  
IsNoGC()117      bool IsNoGC() const
118      {
119          return HasFlag(BytecodeFlags::NO_GC);
120      }
121  
IsMov()122      bool IsMov() const
123      {
124          return GetKind() == BytecodeKind::MOV;
125      }
126  
IsReturn()127      bool IsReturn() const
128      {
129          return GetKind() == BytecodeKind::RETURN_BC;
130      }
131  
IsThrow()132      bool IsThrow() const
133      {
134          return GetKind() == BytecodeKind::THROW_BC;
135      }
136  
IsJump()137      bool IsJump() const
138      {
139          return IsJumpImm() || IsCondJump();
140      }
141  
IsCondJump()142      bool IsCondJump() const
143      {
144          return GetKind() == BytecodeKind::CONDITIONAL_JUMP;
145      }
146  
IsJumpImm()147      bool IsJumpImm() const
148      {
149          return GetKind() == BytecodeKind::JUMP_IMM;
150      }
151  
IsSuspend()152      bool IsSuspend() const
153      {
154          return GetKind() == BytecodeKind::SUSPEND;
155      }
156  
IsSetConstant()157      bool IsSetConstant() const
158      {
159          return GetKind() == BytecodeKind::SET_CONSTANT;
160      }
161  
SupportDeopt()162      bool SupportDeopt() const
163      {
164          return HasFlag(BytecodeFlags::SUPPORT_DEOPT);
165      }
166  
GetSize()167      size_t GetSize() const
168      {
169          return SizeField::Get(value_);
170      }
171  
IsGeneral()172      bool IsGeneral() const
173      {
174          return HasFlag(BytecodeFlags::GENERAL_BC);
175      }
176  
IsGeneratorResolve()177      bool IsGeneratorResolve() const
178      {
179          return GetKind() == BytecodeKind::GENERATOR_RESOLVE;
180      }
181  
IsGeneratorRelative()182      bool IsGeneratorRelative() const
183      {
184          BytecodeKind kind = GetKind();
185          return (kind == BytecodeKind::RESUME) || (kind == BytecodeKind::SUSPEND) ||
186                 (kind == BytecodeKind::GENERATOR_RESOLVE);
187      }
188  
IsDiscarded()189      bool IsDiscarded() const
190      {
191          return GetKind() == BytecodeKind::DISCARDED;
192      }
193  
HasFuncIn()194      bool HasFuncIn() const
195      {
196          return HasFlag(BytecodeFlags::READ_FUNC);
197      }
198  
HasNewTargetIn()199      bool HasNewTargetIn() const
200      {
201          return HasFlag(BytecodeFlags::READ_NEWTARGET);
202      }
203  
HasArgcIn()204      bool HasArgcIn() const
205      {
206          return HasFlag(BytecodeFlags::READ_ARGC);
207      }
208  
GetOpcode()209      inline EcmaOpcode GetOpcode() const
210      {
211          return OpcodeField::Get(value_);
212      }
213  
IsInvalid()214      bool IsInvalid() const
215      {
216          return value_ == 0;
217      }
218  
IsCall()219      bool IsCall() const
220      {
221          return GetKind() == BytecodeKind::CALL_BC;
222      }
223  
224  private:
225      BytecodeMetaData() = default;
226      DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BytecodeMetaData);
227      DEFAULT_COPY_SEMANTIC(BytecodeMetaData);
BytecodeMetaData(uint64_t value)228      explicit BytecodeMetaData(uint64_t value) : value_(value) {}
229  
230      static BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc);
231  
HasFlag(BytecodeFlags flag)232      inline bool HasFlag(BytecodeFlags flag) const
233      {
234          return (GetFlags() & flag) == flag;
235      }
236  
GetFlags()237      inline BytecodeFlags GetFlags() const
238      {
239          return FlagsField::Get(value_);
240      }
241  
GetKind()242      inline BytecodeKind GetKind() const
243      {
244          return KindField::Get(value_);
245      }
246  
247      uint64_t value_ {0};
248      friend class Bytecodes;
249      friend class BytecodeInfo;
250      friend class BytecodeCircuitBuilder;
251  };
252  
253  class Bytecodes {
254  public:
255      static constexpr uint32_t NUM_BYTECODES = 0xFF;
256      static constexpr uint32_t OPCODE_MASK = 0xFF00;
257      static constexpr uint32_t BYTE_SIZE = 8;
258      static constexpr uint32_t CALLRUNTIME_PREFIX_OPCODE_INDEX = 251;
259      static constexpr uint32_t DEPRECATED_PREFIX_OPCODE_INDEX = 252;
260      static constexpr uint32_t WIDE_PREFIX_OPCODE_INDEX = 253;
261      static constexpr uint32_t THROW_PREFIX_OPCODE_INDEX = 254;
262      static constexpr uint32_t MIN_PREFIX_OPCODE_INDEX = CALLRUNTIME_PREFIX_OPCODE_INDEX;
263  
264      static constexpr uint32_t LAST_OPCODE =
265          static_cast<uint32_t>(EcmaOpcode::GETASYNCITERATOR_IMM8);
266      static constexpr uint32_t LAST_DEPRECATED_OPCODE =
267          static_cast<uint32_t>(EcmaOpcode::DEPRECATED_DYNAMICIMPORT_PREF_V8);
268      static constexpr uint32_t LAST_WIDE_OPCODE =
269          static_cast<uint32_t>(EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16);
270      static constexpr uint32_t LAST_THROW_OPCODE =
271          static_cast<uint32_t>(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16);
272      static constexpr uint32_t LAST_CALLRUNTIME_OPCODE =
273          static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE);
274  
275      static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX ==
276          static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE));
277      static_assert(DEPRECATED_PREFIX_OPCODE_INDEX ==
278          static_cast<uint32_t>(EcmaOpcode::DEPRECATED_LDLEXENV_PREF_NONE));
279      static_assert(WIDE_PREFIX_OPCODE_INDEX ==
280          static_cast<uint32_t>(EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8));
281      static_assert(THROW_PREFIX_OPCODE_INDEX ==
282          static_cast<uint32_t>(EcmaOpcode::THROW_PREF_NONE));
283  
284      Bytecodes();
285      Bytecodes(const Bytecodes&) = delete;
286      void operator=(const Bytecodes&) = delete;
287  
GetOpcode(const uint8_t * pc)288      static EcmaOpcode GetOpcode(const uint8_t *pc)
289      {
290          uint8_t primary = ReadByte(pc);
291          if (primary >= MIN_PREFIX_OPCODE_INDEX) {
292              uint8_t secondary = ReadByte1(pc);
293              return static_cast<EcmaOpcode>((secondary << 8U) | primary); // 8: byte size
294          }
295          return static_cast<EcmaOpcode>(primary);
296      }
297  
GetBytecodeMetaData(const uint8_t * pc)298      BytecodeMetaData GetBytecodeMetaData(const uint8_t *pc) const
299      {
300          uint8_t primary = ReadByte(pc);
301          if (primary >= MIN_PREFIX_OPCODE_INDEX) {
302              uint8_t secondary = ReadByte1(pc);
303              if (primary == CALLRUNTIME_PREFIX_OPCODE_INDEX) {
304                  return callRuntimeBytecodes_[secondary];
305              } else if (primary == DEPRECATED_PREFIX_OPCODE_INDEX) {
306                  return deprecatedBytecodes_[secondary];
307              } else if (primary == WIDE_PREFIX_OPCODE_INDEX) {
308                  return wideBytecodes_[secondary];
309              } else {
310                  ASSERT(primary == THROW_PREFIX_OPCODE_INDEX);
311                  return throwBytecodes_[secondary];
312              }
313          }
314          return bytecodes_[primary];
315      }
316  
IsCallOp(EcmaOpcode opcode)317      static bool IsCallOp(EcmaOpcode opcode)
318      {
319          switch (opcode) {
320              case EcmaOpcode::CALLARG0_IMM8:
321              case EcmaOpcode::CALLARG1_IMM8_V8:
322              case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
323              case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
324              case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
325              case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
326              case EcmaOpcode::CALLTHIS0_IMM8_V8:
327              case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
328              case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
329              case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
330              case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
331              case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
332                  return true;
333              default:
334                  return false;
335          }
336      }
337  
IsCreateObjectWithBufferOp(EcmaOpcode opcode)338      static bool IsCreateObjectWithBufferOp(EcmaOpcode opcode)
339      {
340          switch (opcode) {
341              case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
342              case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
343                  return true;
344              default:
345                  return false;
346          }
347      }
348  
IsCreateArrayWithBufferOp(EcmaOpcode opcode)349      static bool IsCreateArrayWithBufferOp(EcmaOpcode opcode)
350      {
351          switch (opcode) {
352              case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
353              case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
354                  return true;
355              default:
356                  return false;
357          }
358      }
359  
360  private:
ReadByte(const uint8_t * pc)361      static uint8_t ReadByte(const uint8_t *pc)
362      {
363          return *pc;
364      }
ReadByte1(const uint8_t * pc)365      static uint8_t ReadByte1(const uint8_t *pc)
366      {
367          return *(pc + 1); // 1: byte1
368      }
369      BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc);
370  
371      std::array<BytecodeMetaData, NUM_BYTECODES> bytecodes_{};
372      std::array<BytecodeMetaData, NUM_BYTECODES> callRuntimeBytecodes_{};
373      std::array<BytecodeMetaData, NUM_BYTECODES> deprecatedBytecodes_{};
374      std::array<BytecodeMetaData, NUM_BYTECODES> wideBytecodes_{};
375      std::array<BytecodeMetaData, NUM_BYTECODES> throwBytecodes_{};
376  };
377  
378  enum class ConstDataIDType : uint8_t {
379      StringIDType,
380      MethodIDType,
381      ArrayLiteralIDType,
382      ObjectLiteralIDType,
383      ClassLiteralIDType,
384  };
385  
386  class VirtualRegister {
387  public:
VirtualRegister(VRegIDType id)388      explicit VirtualRegister(VRegIDType id) : id_(id)
389      {
390      }
391      ~VirtualRegister() = default;
392  
SetId(VRegIDType id)393      void SetId(VRegIDType id)
394      {
395          id_ = id;
396      }
397  
GetId()398      VRegIDType GetId() const
399      {
400          return id_;
401      }
402  
403  private:
404      VRegIDType id_;
405  };
406  
407  class Immediate {
408  public:
Immediate(ImmValueType value)409      explicit Immediate(ImmValueType value) : value_(value)
410      {
411      }
412      ~Immediate() = default;
413  
SetValue(ImmValueType value)414      void SetValue(ImmValueType value)
415      {
416          value_ = value;
417      }
418  
ToJSTaggedValueInt()419      ImmValueType ToJSTaggedValueInt() const
420      {
421          return value_ | JSTaggedValue::TAG_INT;
422      }
423  
ToJSTaggedValueDouble()424      ImmValueType ToJSTaggedValueDouble() const
425      {
426          return JSTaggedValue(base::bit_cast<double>(value_)).GetRawData();
427      }
428  
GetValue()429      ImmValueType GetValue() const
430      {
431          return value_;
432      }
433  
434  private:
435      ImmValueType value_;
436  };
437  
438  
439  class ICSlotId {
440  public:
ICSlotId(ICSlotIdType id)441      explicit ICSlotId(ICSlotIdType id) : id_(id)
442      {
443      }
444      ~ICSlotId() = default;
445  
SetId(ICSlotIdType id)446      void SetId(ICSlotIdType id)
447      {
448          id_ = id;
449      }
450  
GetId()451      ICSlotIdType GetId() const
452      {
453          return id_;
454      }
455  
456  private:
457      ICSlotIdType id_;
458  };
459  
460  class ConstDataId {
461  public:
ConstDataId(ConstDataIDType type,uint16_t id)462      ConstDataId(ConstDataIDType type, uint16_t id)
463          :type_(type), id_(id)
464      {
465      }
466  
ConstDataId(uint64_t bitfield)467      explicit ConstDataId(uint64_t bitfield)
468      {
469          type_ = ConstDataIDType(bitfield >> TYPE_SHIFT);
470          id_ = bitfield & ((1 << TYPE_SHIFT) - 1);
471      }
472  
473      ~ConstDataId() = default;
474  
SetId(uint16_t id)475      void SetId(uint16_t id)
476      {
477          id_ = id;
478      }
479  
GetId()480      uint16_t GetId() const
481      {
482          return id_;
483      }
484  
SetType(ConstDataIDType type)485      void SetType(ConstDataIDType type)
486      {
487          type_ = type;
488      }
489  
GetType()490      ConstDataIDType GetType() const
491      {
492          return type_;
493      }
494  
IsStringId()495      bool IsStringId() const
496      {
497          return type_ == ConstDataIDType::StringIDType;
498      }
499  
IsMethodId()500      bool IsMethodId() const
501      {
502          return type_ == ConstDataIDType::MethodIDType;
503      }
504  
IsClassLiteraId()505      bool IsClassLiteraId() const
506      {
507          return type_ == ConstDataIDType::ClassLiteralIDType;
508      }
509  
IsObjectLiteralID()510      bool IsObjectLiteralID() const
511      {
512          return type_ == ConstDataIDType::ObjectLiteralIDType;
513      }
514  
IsArrayLiteralID()515      bool IsArrayLiteralID() const
516      {
517          return type_ == ConstDataIDType::ArrayLiteralIDType;
518      }
519  
CaculateBitField()520      uint64_t CaculateBitField() const
521      {
522          return (static_cast<uint8_t>(type_) << TYPE_SHIFT) | id_;
523      }
524  
525  private:
526      static constexpr int TYPE_SHIFT = 16;
527      ConstDataIDType type_;
528      uint16_t id_;
529  };
530  
531  class BytecodeInfo {
532  public:
533      // set of id, immediate and read register
534      std::vector<std::variant<ConstDataId, ICSlotId, Immediate, VirtualRegister>> inputs {};
535      std::vector<VRegIDType> vregOut {}; // write register
536  
Deopt()537      bool Deopt() const
538      {
539          return metaData_.SupportDeopt();
540      }
541  
AccOut()542      bool AccOut() const
543      {
544          return metaData_.HasAccOut();
545      }
546  
AccIn()547      bool AccIn() const
548      {
549          return metaData_.HasAccIn();
550      }
551  
EnvIn()552      bool EnvIn() const
553      {
554          return metaData_.HasEnvIn();
555      }
556  
EnvOut()557      bool EnvOut() const
558      {
559          return metaData_.HasEnvOut();
560      }
561  
NoSideEffects()562      bool NoSideEffects() const
563      {
564          return metaData_.IsNoSideEffects();
565      }
566  
NoThrow()567      bool NoThrow() const
568      {
569          return metaData_.IsNoThrow();
570      }
571  
ThisObjectIn()572      bool ThisObjectIn() const
573      {
574          return metaData_.HasThisIn();
575      }
576  
GetSize()577      size_t GetSize() const
578      {
579          return metaData_.GetSize();
580      }
581  
IsDef()582      bool IsDef() const
583      {
584          return (!vregOut.empty()) || AccOut();
585      }
586  
IsOut(VRegIDType reg,uint32_t index)587      bool IsOut(VRegIDType reg, uint32_t index) const
588      {
589          bool isDefined = (!vregOut.empty() && (reg == vregOut.at(index)));
590          return isDefined;
591      }
592  
IsMov()593      bool IsMov() const
594      {
595          return metaData_.IsMov();
596      }
597  
IsJump()598      bool IsJump() const
599      {
600          return metaData_.IsJump();
601      }
602  
IsCondJump()603      bool IsCondJump() const
604      {
605          return metaData_.IsCondJump();
606      }
607  
IsReturn()608      bool IsReturn() const
609      {
610          return metaData_.IsReturn();
611      }
612  
IsThrow()613      bool IsThrow() const
614      {
615          return metaData_.IsThrow();
616      }
617  
IsSuspend()618      bool IsSuspend() const
619      {
620          return metaData_.IsSuspend();
621      }
622  
IsGeneratorResolve()623      bool IsGeneratorResolve() const
624      {
625          return metaData_.IsGeneratorResolve();
626      }
627  
IsDiscarded()628      bool IsDiscarded() const
629      {
630          return metaData_.IsDiscarded();
631      }
632  
IsSetConstant()633      bool IsSetConstant() const
634      {
635          return metaData_.IsSetConstant();
636      }
637  
IsGeneral()638      bool IsGeneral() const
639      {
640          return metaData_.IsGeneral();
641      }
642  
needFallThrough()643      bool needFallThrough() const
644      {
645          return !IsJump() && !IsReturn() && !IsThrow();
646      }
647  
IsGeneratorRelative()648      bool IsGeneratorRelative() const
649      {
650          return metaData_.IsGeneratorRelative();
651      }
652  
ComputeValueInputCount()653      size_t ComputeValueInputCount() const
654      {
655          return (AccIn() ? 1 : 0) + inputs.size();
656      }
657  
ComputeOutCount()658      size_t ComputeOutCount() const
659      {
660          return (AccOut() ? 1 : 0) + vregOut.size();
661      }
662  
IsBc(EcmaOpcode ecmaOpcode)663      bool IsBc(EcmaOpcode ecmaOpcode) const
664      {
665          return metaData_.GetOpcode() == ecmaOpcode;
666      }
667  
HasFuncIn()668      bool HasFuncIn() const
669      {
670          return metaData_.HasFuncIn();
671      }
672  
HasNewTargetIn()673      bool HasNewTargetIn() const
674      {
675          return metaData_.HasNewTargetIn();
676      }
677  
HasArgcIn()678      bool HasArgcIn() const
679      {
680          return metaData_.HasArgcIn();
681      }
682  
HasFrameArgs()683      bool HasFrameArgs() const
684      {
685          return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn();
686      }
687  
IsCall()688      bool IsCall() const
689      {
690          return metaData_.IsCall();
691      }
692  
GetOpcode()693      inline EcmaOpcode GetOpcode() const
694      {
695          return metaData_.GetOpcode();
696      }
697  
698      static void InitBytecodeInfo(BytecodeCircuitBuilder *builder,
699          BytecodeInfo &info, const uint8_t* pc);
700  
701  private:
702      BytecodeMetaData metaData_ { 0 };
703      friend class BytecodeCircuitBuilder;
704  };
705  
706  class BytecodeIterator {
707  public:
708      BytecodeIterator() = default;
BytecodeIterator(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)709      BytecodeIterator(BytecodeCircuitBuilder *builder,
710          uint32_t start, uint32_t end)
711          : builder_(builder), start_(start), end_(end) {}
Reset(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)712      void Reset(BytecodeCircuitBuilder *builder,
713          uint32_t start, uint32_t end)
714      {
715          builder_ = builder;
716          start_ = start;
717          end_ = end;
718      }
719  
720      BytecodeIterator& operator++()
721      {
722          if (InRange()) {
723              index_++;
724          }
725          return *this;
726      }
727      BytecodeIterator& operator--()
728      {
729          if (InRange()) {
730              index_--;
731          }
732          return *this;
733      }
734  
Goto(uint32_t i)735      void Goto(uint32_t i)
736      {
737          index_ = i;
738      }
739  
GotoStart()740      void GotoStart()
741      {
742          index_ = start_;
743          ASSERT(InRange());
744      }
745  
GotoEnd()746      void GotoEnd()
747      {
748          index_ = end_;
749          ASSERT(InRange());
750      }
751  
InRange()752      bool InRange() const
753      {
754          return (index_ <= end_) && (index_ >= start_);
755      }
756  
Done()757      bool Done() const
758      {
759          return !InRange();
760      }
761  
Index()762      uint32_t Index() const
763      {
764          return index_;
765      }
766  
767      const BytecodeInfo &GetBytecodeInfo() const;
768      const uint8_t *PeekNextPc(size_t i) const;
769      const uint8_t *PeekPrevPc(size_t i) const;
770  
771  private:
772      BytecodeCircuitBuilder *builder_ {nullptr};
773      uint32_t start_ {0};
774      uint32_t end_ {0};
775      uint32_t index_{ INVALID_INDEX };
776  };
777  
778  class BytecodeCallArgc {
779  public:
ComputeCallArgc(int gateNumIn,EcmaOpcode op)780      static int ComputeCallArgc(int gateNumIn, EcmaOpcode op)
781      {
782          switch (op) {
783              case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
784              case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
785              case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
786              case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
787              case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
788              case EcmaOpcode::CALLTHIS0_IMM8_V8: {
789                  return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 2; // 2: calltarget, this
790              }
791              default: {
792                  return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 1; // 1: calltarget
793              }
794          }
795      }
796  };
797  }  // panda::ecmascript::kungfu
798  #endif  // ECMASCRIPT_COMPILER_BYTECODES_H
799