• 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