• 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     DEBUGGER_STMT = 1 << 13,
54 };
55 
56 enum BytecodeKind : uint32_t {
57     GENERAL = 0,
58     THROW_BC,
59     RETURN_BC,
60     JUMP_IMM,
61     CONDITIONAL_JUMP,
62     MOV,
63     SET_CONSTANT,
64     SUSPEND,
65     RESUME,
66     GENERATOR_RESOLVE,
67     DISCARDED,
68     CALL_BC,
69     ACCESSOR_BC,
70 };
71 
72 class BytecodeMetaData {
73 public:
74     static constexpr uint32_t MAX_OPCODE_SIZE = 16;
75     static constexpr uint32_t MAX_SIZE_BITS = 4;
76     static constexpr uint32_t BYTECODE_KIND_SIZE = 4;
77     static constexpr uint32_t BYTECODE_FLAGS_SIZE = 14;
78     static constexpr uint32_t VREG_COUNT_SIZE = 16;
79 
80     using OpcodeField = panda::BitField<EcmaOpcode, 0, MAX_OPCODE_SIZE>;
81     using SizeField = OpcodeField::NextField<size_t, MAX_SIZE_BITS>;
82     using KindField = SizeField::NextField<BytecodeKind, BYTECODE_KIND_SIZE>;
83     using FlagsField = KindField::NextField<BytecodeFlags, BYTECODE_FLAGS_SIZE>;
84     using VRegCountField = FlagsField::NextField<size_t, VREG_COUNT_SIZE>;
85 
HasAccIn()86     bool HasAccIn() const
87     {
88         return HasFlag(BytecodeFlags::READ_ACC);
89     }
90 
IsNoSideEffects()91     bool IsNoSideEffects() const
92     {
93         return HasFlag(BytecodeFlags::NO_SIDE_EFFECTS);
94     }
95 
IsNoThrow()96     bool IsNoThrow() const
97     {
98         return HasFlag(BytecodeFlags::NO_THROW);
99     }
100 
HasThisIn()101     bool HasThisIn() const
102     {
103         return HasFlag(BytecodeFlags::READ_THIS_OBJECT);
104     }
105 
HasAccOut()106     bool HasAccOut() const
107     {
108         return HasFlag(BytecodeFlags::WRITE_ACC);
109     }
110 
HasEnvIn()111     bool HasEnvIn() const
112     {
113         return HasFlag(BytecodeFlags::READ_ENV);
114     }
115 
HasEnvOut()116     bool HasEnvOut() const
117     {
118         return HasFlag(BytecodeFlags::WRITE_ENV);
119     }
120 
IsNoGC()121     bool IsNoGC() const
122     {
123         return HasFlag(BytecodeFlags::NO_GC);
124     }
125 
IsMov()126     bool IsMov() const
127     {
128         return GetKind() == BytecodeKind::MOV;
129     }
130 
IsReturn()131     bool IsReturn() const
132     {
133         return GetKind() == BytecodeKind::RETURN_BC;
134     }
135 
IsThrow()136     bool IsThrow() const
137     {
138         return GetKind() == BytecodeKind::THROW_BC;
139     }
140 
IsJump()141     bool IsJump() const
142     {
143         return IsJumpImm() || IsCondJump();
144     }
145 
IsCondJump()146     bool IsCondJump() const
147     {
148         return GetKind() == BytecodeKind::CONDITIONAL_JUMP;
149     }
150 
IsJumpImm()151     bool IsJumpImm() const
152     {
153         return GetKind() == BytecodeKind::JUMP_IMM;
154     }
155 
IsSuspend()156     bool IsSuspend() const
157     {
158         return GetKind() == BytecodeKind::SUSPEND;
159     }
160 
IsSetConstant()161     bool IsSetConstant() const
162     {
163         return GetKind() == BytecodeKind::SET_CONSTANT;
164     }
165 
SupportDeopt()166     bool SupportDeopt() const
167     {
168         return HasFlag(BytecodeFlags::SUPPORT_DEOPT);
169     }
170 
GetSize()171     size_t GetSize() const
172     {
173         return SizeField::Get(value_);
174     }
175 
IsGeneral()176     bool IsGeneral() const
177     {
178         return HasFlag(BytecodeFlags::GENERAL_BC);
179     }
180 
IsGeneratorResolve()181     bool IsGeneratorResolve() const
182     {
183         return GetKind() == BytecodeKind::GENERATOR_RESOLVE;
184     }
185 
IsGeneratorRelative()186     bool IsGeneratorRelative() const
187     {
188         BytecodeKind kind = GetKind();
189         return (kind == BytecodeKind::RESUME) || (kind == BytecodeKind::SUSPEND) ||
190                (kind == BytecodeKind::GENERATOR_RESOLVE);
191     }
192 
IsDiscarded()193     bool IsDiscarded() const
194     {
195         return GetKind() == BytecodeKind::DISCARDED;
196     }
197 
HasFuncIn()198     bool HasFuncIn() const
199     {
200         return HasFlag(BytecodeFlags::READ_FUNC);
201     }
202 
HasNewTargetIn()203     bool HasNewTargetIn() const
204     {
205         return HasFlag(BytecodeFlags::READ_NEWTARGET);
206     }
207 
HasArgcIn()208     bool HasArgcIn() const
209     {
210         return HasFlag(BytecodeFlags::READ_ARGC);
211     }
212 
GetOpcode()213     inline EcmaOpcode GetOpcode() const
214     {
215         return OpcodeField::Get(value_);
216     }
217 
IsInvalid()218     bool IsInvalid() const
219     {
220         return value_ == 0;
221     }
222 
IsCall()223     bool IsCall() const
224     {
225         return GetKind() == BytecodeKind::CALL_BC;
226     }
227 
IsAccessorBC()228     bool IsAccessorBC() const
229     {
230         return GetKind() == BytecodeKind::ACCESSOR_BC;
231     }
232 
HasDebuggerStmt()233     bool HasDebuggerStmt() const
234     {
235         return HasFlag(BytecodeFlags::DEBUGGER_STMT);
236     }
237 
GetVRegCount()238     uint32_t GetVRegCount() const
239     {
240         return VRegCountField::Get(value_);
241     }
242 
243 private:
244     BytecodeMetaData() = default;
245     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BytecodeMetaData);
246     DEFAULT_COPY_SEMANTIC(BytecodeMetaData);
BytecodeMetaData(uint64_t value)247     explicit BytecodeMetaData(uint64_t value) : value_(value) {}
248 
249     static BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc);
250 
251     static size_t GetVRegCount(const BytecodeInstruction &inst);
252 
HasFlag(BytecodeFlags flag)253     inline bool HasFlag(BytecodeFlags flag) const
254     {
255         return (GetFlags() & flag) == flag;
256     }
257 
GetFlags()258     inline BytecodeFlags GetFlags() const
259     {
260         return FlagsField::Get(value_);
261     }
262 
GetKind()263     inline BytecodeKind GetKind() const
264     {
265         return KindField::Get(value_);
266     }
267 
268     uint64_t value_ {0};
269     friend class Bytecodes;
270     friend class BytecodeInfo;
271     friend class BytecodeCircuitBuilder;
272 };
273 
274 class Bytecodes {
275 public:
276     static constexpr uint32_t NUM_BYTECODES = 0xFF;
277     static constexpr uint32_t OPCODE_MASK = 0xFF00;
278     static constexpr uint32_t BYTE_SIZE = 8;
279     static constexpr uint32_t CALLRUNTIME_PREFIX_OPCODE_INDEX = 251;
280     static constexpr uint32_t DEPRECATED_PREFIX_OPCODE_INDEX = 252;
281     static constexpr uint32_t WIDE_PREFIX_OPCODE_INDEX = 253;
282     static constexpr uint32_t THROW_PREFIX_OPCODE_INDEX = 254;
283     static constexpr uint32_t MIN_PREFIX_OPCODE_INDEX = CALLRUNTIME_PREFIX_OPCODE_INDEX;
284 
285     static constexpr uint32_t LAST_OPCODE =
286         static_cast<uint32_t>(EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8);
287     static constexpr uint32_t LAST_DEPRECATED_OPCODE =
288         static_cast<uint32_t>(EcmaOpcode::DEPRECATED_DYNAMICIMPORT_PREF_V8);
289     static constexpr uint32_t LAST_WIDE_OPCODE =
290         static_cast<uint32_t>(EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16);
291     static constexpr uint32_t LAST_THROW_OPCODE =
292         static_cast<uint32_t>(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16);
293     static constexpr uint32_t LAST_CALLRUNTIME_OPCODE =
294         static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16);
295 
296     static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX ==
297         static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE));
298     static_assert(DEPRECATED_PREFIX_OPCODE_INDEX ==
299         static_cast<uint32_t>(EcmaOpcode::DEPRECATED_LDLEXENV_PREF_NONE));
300     static_assert(WIDE_PREFIX_OPCODE_INDEX ==
301         static_cast<uint32_t>(EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8));
302     static_assert(THROW_PREFIX_OPCODE_INDEX ==
303         static_cast<uint32_t>(EcmaOpcode::THROW_PREF_NONE));
304 
305     Bytecodes();
306     Bytecodes(const Bytecodes&) = delete;
307     void operator=(const Bytecodes&) = delete;
308 
GetOpcode(const uint8_t * pc)309     static EcmaOpcode GetOpcode(const uint8_t *pc)
310     {
311         uint8_t primary = ReadByte(pc);
312         if (primary >= MIN_PREFIX_OPCODE_INDEX) {
313             uint8_t secondary = ReadByte1(pc);
314             return static_cast<EcmaOpcode>((secondary << 8U) | primary); // 8: byte size
315         }
316         return static_cast<EcmaOpcode>(primary);
317     }
318 
GetBytecodeMetaData(const uint8_t * pc)319     BytecodeMetaData GetBytecodeMetaData(const uint8_t *pc) const
320     {
321         uint8_t primary = ReadByte(pc);
322         if (primary >= MIN_PREFIX_OPCODE_INDEX) {
323             uint8_t secondary = ReadByte1(pc);
324             if (primary == CALLRUNTIME_PREFIX_OPCODE_INDEX) {
325                 return callRuntimeBytecodes_[secondary];
326             } else if (primary == DEPRECATED_PREFIX_OPCODE_INDEX) {
327                 return deprecatedBytecodes_[secondary];
328             } else if (primary == WIDE_PREFIX_OPCODE_INDEX) {
329                 return wideBytecodes_[secondary];
330             } else {
331                 ASSERT(primary == THROW_PREFIX_OPCODE_INDEX);
332                 return throwBytecodes_[secondary];
333             }
334         }
335         return bytecodes_[primary];
336     }
337 
IsCallOp(EcmaOpcode opcode)338     static bool IsCallOp(EcmaOpcode opcode)
339     {
340         switch (opcode) {
341             case EcmaOpcode::CALLARG0_IMM8:
342             case EcmaOpcode::CALLARG1_IMM8_V8:
343             case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
344             case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
345             case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
346             case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
347             case EcmaOpcode::CALLTHIS0_IMM8_V8:
348             case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
349             case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
350             case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
351             case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
352             case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
353             case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8:
354                 return true;
355             default:
356                 return false;
357         }
358     }
359 
IsCreateObjectWithBufferOp(EcmaOpcode opcode)360     static bool IsCreateObjectWithBufferOp(EcmaOpcode opcode)
361     {
362         switch (opcode) {
363             case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
364             case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
365                 return true;
366             default:
367                 return false;
368         }
369     }
370 
IsCreateEmptyArrayOp(EcmaOpcode opcode)371     static bool IsCreateEmptyArrayOp(EcmaOpcode opcode)
372     {
373         switch (opcode) {
374             case EcmaOpcode::CREATEEMPTYARRAY_IMM8:
375             case EcmaOpcode::CREATEEMPTYARRAY_IMM16:
376                 return true;
377             default:
378                 return false;
379         }
380     }
381 
IsCreateArrayWithBufferOp(EcmaOpcode opcode)382     static bool IsCreateArrayWithBufferOp(EcmaOpcode opcode)
383     {
384         switch (opcode) {
385             case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
386             case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
387                 return true;
388             default:
389                 return false;
390         }
391     }
392 
IsDefineClassWithBufferOp(EcmaOpcode opcode)393     static bool IsDefineClassWithBufferOp(EcmaOpcode opcode)
394     {
395         switch (opcode) {
396             case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
397             case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
398                 return true;
399             default:
400                 return false;
401         }
402     }
403 
IsLdLexVarOp(EcmaOpcode opcode)404     static bool IsLdLexVarOp(EcmaOpcode opcode)
405     {
406         switch (opcode) {
407             case EcmaOpcode::LDLEXVAR_IMM4_IMM4:
408             case EcmaOpcode::LDLEXVAR_IMM8_IMM8:
409             case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16:
410                 return true;
411             default:
412                 return false;
413         }
414     }
415 
IsStLexVarOp(EcmaOpcode opcode)416     static bool IsStLexVarOp(EcmaOpcode opcode)
417     {
418         switch (opcode) {
419             case EcmaOpcode::STLEXVAR_IMM4_IMM4:
420             case EcmaOpcode::STLEXVAR_IMM8_IMM8:
421             case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16:
422                 return true;
423             default:
424                 return false;
425         }
426     }
427 
IsCallOrAccessorOp(EcmaOpcode opcode)428     static bool IsCallOrAccessorOp(EcmaOpcode opcode)
429     {
430         switch (opcode) {
431             case EcmaOpcode::CALLARG0_IMM8:
432             case EcmaOpcode::CALLARG1_IMM8_V8:
433             case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
434             case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
435             case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
436             case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
437             case EcmaOpcode::CALLTHIS0_IMM8_V8:
438             case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
439             case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
440             case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
441             case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
442             case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
443             case EcmaOpcode::LDOBJBYNAME_IMM8_ID16:
444             case EcmaOpcode::LDOBJBYNAME_IMM16_ID16:
445             case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
446             case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
447             case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
448             case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
449             case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
450             case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
451             case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
452             case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
453             case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8:
454                 return true;
455             default:
456                 return false;
457         }
458     }
459 
IsDefineFunc(EcmaOpcode opcode)460     static bool IsDefineFunc(EcmaOpcode opcode)
461     {
462         switch (opcode) {
463             case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8:
464             case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8:
465                 return true;
466             default:
467                 return false;
468         }
469     }
470 
471 private:
ReadByte(const uint8_t * pc)472     static uint8_t ReadByte(const uint8_t *pc)
473     {
474         return *pc;
475     }
ReadByte1(const uint8_t * pc)476     static uint8_t ReadByte1(const uint8_t *pc)
477     {
478         return *(pc + 1); // 1: byte1
479     }
480     BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc);
481 
482     std::array<BytecodeMetaData, NUM_BYTECODES> bytecodes_{};
483     std::array<BytecodeMetaData, NUM_BYTECODES> callRuntimeBytecodes_{};
484     std::array<BytecodeMetaData, NUM_BYTECODES> deprecatedBytecodes_{};
485     std::array<BytecodeMetaData, NUM_BYTECODES> wideBytecodes_{};
486     std::array<BytecodeMetaData, NUM_BYTECODES> throwBytecodes_{};
487 };
488 
489 enum class ConstDataIDType : uint8_t {
490     StringIDType,
491     MethodIDType,
492     ArrayLiteralIDType,
493     ObjectLiteralIDType,
494     ClassLiteralIDType,
495 };
496 
497 class VirtualRegister {
498 public:
VirtualRegister(VRegIDType id)499     explicit VirtualRegister(VRegIDType id) : id_(id)
500     {
501     }
502     ~VirtualRegister() = default;
503 
SetId(VRegIDType id)504     void SetId(VRegIDType id)
505     {
506         id_ = id;
507     }
508 
GetId()509     VRegIDType GetId() const
510     {
511         return id_;
512     }
513 
514 private:
515     VRegIDType id_;
516 };
517 
518 class Immediate {
519 public:
Immediate(ImmValueType value)520     explicit Immediate(ImmValueType value) : value_(value)
521     {
522     }
523     ~Immediate() = default;
524 
SetValue(ImmValueType value)525     void SetValue(ImmValueType value)
526     {
527         value_ = value;
528     }
529 
ToJSTaggedValueInt()530     ImmValueType ToJSTaggedValueInt() const
531     {
532         return value_ | JSTaggedValue::TAG_INT;
533     }
534 
ToJSTaggedValueDouble()535     ImmValueType ToJSTaggedValueDouble() const
536     {
537         return JSTaggedValue(base::bit_cast<double>(value_)).GetRawData();
538     }
539 
GetValue()540     ImmValueType GetValue() const
541     {
542         return value_;
543     }
544 
545 private:
546     ImmValueType value_;
547 };
548 
549 
550 class ICSlotId {
551 public:
ICSlotId(ICSlotIdType id)552     explicit ICSlotId(ICSlotIdType id) : id_(id)
553     {
554     }
555     ~ICSlotId() = default;
556 
SetId(ICSlotIdType id)557     void SetId(ICSlotIdType id)
558     {
559         id_ = id;
560     }
561 
GetId()562     ICSlotIdType GetId() const
563     {
564         return id_;
565     }
566 
567 private:
568     ICSlotIdType id_;
569 };
570 
571 class ConstDataId {
572 public:
ConstDataId(ConstDataIDType type,uint16_t id)573     ConstDataId(ConstDataIDType type, uint16_t id)
574         :type_(type), id_(id)
575     {
576     }
577 
ConstDataId(uint64_t bitfield)578     explicit ConstDataId(uint64_t bitfield)
579     {
580         type_ = ConstDataIDType(bitfield >> TYPE_SHIFT);
581         id_ = bitfield & ((1 << TYPE_SHIFT) - 1);
582     }
583 
584     ~ConstDataId() = default;
585 
SetId(uint16_t id)586     void SetId(uint16_t id)
587     {
588         id_ = id;
589     }
590 
GetId()591     uint16_t GetId() const
592     {
593         return id_;
594     }
595 
SetType(ConstDataIDType type)596     void SetType(ConstDataIDType type)
597     {
598         type_ = type;
599     }
600 
GetType()601     ConstDataIDType GetType() const
602     {
603         return type_;
604     }
605 
IsStringId()606     bool IsStringId() const
607     {
608         return type_ == ConstDataIDType::StringIDType;
609     }
610 
IsMethodId()611     bool IsMethodId() const
612     {
613         return type_ == ConstDataIDType::MethodIDType;
614     }
615 
IsClassLiteraId()616     bool IsClassLiteraId() const
617     {
618         return type_ == ConstDataIDType::ClassLiteralIDType;
619     }
620 
IsObjectLiteralID()621     bool IsObjectLiteralID() const
622     {
623         return type_ == ConstDataIDType::ObjectLiteralIDType;
624     }
625 
IsArrayLiteralID()626     bool IsArrayLiteralID() const
627     {
628         return type_ == ConstDataIDType::ArrayLiteralIDType;
629     }
630 
CaculateBitField()631     uint64_t CaculateBitField() const
632     {
633         return (static_cast<uint8_t>(type_) << TYPE_SHIFT) | id_;
634     }
635 
636 private:
637     static constexpr int TYPE_SHIFT = 16;
638     ConstDataIDType type_;
639     uint16_t id_;
640 };
641 
642 class BytecodeInfo {
643 public:
644     // set of id, immediate and read register
645     std::vector<std::variant<ConstDataId, ICSlotId, Immediate, VirtualRegister>> inputs {};
646     std::vector<VRegIDType> vregOut {}; // write register
647 
Deopt()648     bool Deopt() const
649     {
650         return metaData_.SupportDeopt();
651     }
652 
AccOut()653     bool AccOut() const
654     {
655         return metaData_.HasAccOut();
656     }
657 
AccIn()658     bool AccIn() const
659     {
660         return metaData_.HasAccIn();
661     }
662 
EnvIn()663     bool EnvIn() const
664     {
665         return metaData_.HasEnvIn();
666     }
667 
EnvOut()668     bool EnvOut() const
669     {
670         return metaData_.HasEnvOut();
671     }
672 
NoSideEffects()673     bool NoSideEffects() const
674     {
675         return metaData_.IsNoSideEffects();
676     }
677 
NoThrow()678     bool NoThrow() const
679     {
680         return metaData_.IsNoThrow();
681     }
682 
ThisObjectIn()683     bool ThisObjectIn() const
684     {
685         return metaData_.HasThisIn();
686     }
687 
GetSize()688     size_t GetSize() const
689     {
690         return metaData_.GetSize();
691     }
692 
IsDef()693     bool IsDef() const
694     {
695         return (!vregOut.empty()) || AccOut();
696     }
697 
IsOut(VRegIDType reg,uint32_t index)698     bool IsOut(VRegIDType reg, uint32_t index) const
699     {
700         bool isDefined = (!vregOut.empty() && (reg == vregOut.at(index)));
701         return isDefined;
702     }
703 
IsMov()704     bool IsMov() const
705     {
706         return metaData_.IsMov();
707     }
708 
IsJump()709     bool IsJump() const
710     {
711         return metaData_.IsJump();
712     }
713 
IsCondJump()714     bool IsCondJump() const
715     {
716         return metaData_.IsCondJump();
717     }
718 
IsReturn()719     bool IsReturn() const
720     {
721         return metaData_.IsReturn();
722     }
723 
IsThrow()724     bool IsThrow() const
725     {
726         return metaData_.IsThrow();
727     }
728 
IsSuspend()729     bool IsSuspend() const
730     {
731         return metaData_.IsSuspend();
732     }
733 
IsGeneratorResolve()734     bool IsGeneratorResolve() const
735     {
736         return metaData_.IsGeneratorResolve();
737     }
738 
IsDiscarded()739     bool IsDiscarded() const
740     {
741         return metaData_.IsDiscarded();
742     }
743 
IsSetConstant()744     bool IsSetConstant() const
745     {
746         return metaData_.IsSetConstant();
747     }
748 
IsGeneral()749     bool IsGeneral() const
750     {
751         return metaData_.IsGeneral();
752     }
753 
needFallThrough()754     bool needFallThrough() const
755     {
756         return !IsJump() && !IsReturn() && !IsThrow();
757     }
758 
IsGeneratorRelative()759     bool IsGeneratorRelative() const
760     {
761         return metaData_.IsGeneratorRelative();
762     }
763 
ComputeValueInputCount()764     size_t ComputeValueInputCount() const
765     {
766         return (AccIn() ? 1 : 0) + inputs.size();
767     }
768 
ComputeOutCount()769     size_t ComputeOutCount() const
770     {
771         return (AccOut() ? 1 : 0) + vregOut.size();
772     }
773 
IsBc(EcmaOpcode ecmaOpcode)774     bool IsBc(EcmaOpcode ecmaOpcode) const
775     {
776         return metaData_.GetOpcode() == ecmaOpcode;
777     }
778 
HasFuncIn()779     bool HasFuncIn() const
780     {
781         return metaData_.HasFuncIn();
782     }
783 
HasNewTargetIn()784     bool HasNewTargetIn() const
785     {
786         return metaData_.HasNewTargetIn();
787     }
788 
HasArgcIn()789     bool HasArgcIn() const
790     {
791         return metaData_.HasArgcIn();
792     }
793 
HasFrameArgs()794     bool HasFrameArgs() const
795     {
796         return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn();
797     }
798 
HasFrameState()799     bool HasFrameState() const
800     {
801         return HasFrameArgs() || !NoThrow();
802     }
803 
IsCall()804     bool IsCall() const
805     {
806         return metaData_.IsCall();
807     }
808 
IsAccessorBC()809     bool IsAccessorBC() const
810     {
811         return metaData_.IsAccessorBC();
812     }
813 
HasDebuggerStmt()814     bool HasDebuggerStmt() const
815     {
816         return metaData_.HasDebuggerStmt();
817     }
818 
GetOpcode()819     inline EcmaOpcode GetOpcode() const
820     {
821         return metaData_.GetOpcode();
822     }
823 
824     static void InitBytecodeInfo(BytecodeCircuitBuilder *builder,
825         BytecodeInfo &info, const uint8_t* pc);
826 
827 private:
828     BytecodeMetaData metaData_ { 0 };
829     friend class BytecodeCircuitBuilder;
830 };
831 
832 class BytecodeIterator {
833 public:
834     static constexpr int INVALID_INDEX = -1;
835     BytecodeIterator() = default;
BytecodeIterator(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)836     BytecodeIterator(BytecodeCircuitBuilder *builder,
837         uint32_t start, uint32_t end)
838         : builder_(builder), start_(start), end_(end) {}
Reset(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)839     void Reset(BytecodeCircuitBuilder *builder,
840         uint32_t start, uint32_t end)
841     {
842         builder_ = builder;
843         start_ = static_cast<int32_t>(start);
844         end_ = static_cast<int32_t>(end);
845     }
846 
847     BytecodeIterator& operator++()
848     {
849         if (InRange()) {
850             index_++;
851         }
852         return *this;
853     }
854     BytecodeIterator& operator--()
855     {
856         if (InRange()) {
857             index_--;
858         }
859         return *this;
860     }
861 
Goto(uint32_t i)862     void Goto(uint32_t i)
863     {
864         index_ = static_cast<int32_t>(i);
865     }
866 
GotoStart()867     void GotoStart()
868     {
869         index_ = start_;
870     }
871 
GotoEnd()872     void GotoEnd()
873     {
874         index_ = end_;
875         ASSERT(InRange());
876     }
877 
IsInRange(int idx)878     bool IsInRange(int idx) const
879     {
880         return (idx <= end_) && (idx >= start_);
881     }
882 
InRange()883     bool InRange() const
884     {
885         return (index_ <= end_) && (index_ >= start_);
886     }
887 
Done()888     bool Done() const
889     {
890         return !InRange();
891     }
892 
Index()893     uint32_t Index() const
894     {
895         return static_cast<uint32_t>(index_);
896     }
897 
898     const BytecodeInfo &GetBytecodeInfo() const;
899     const uint8_t *PeekNextPc(size_t i) const;
900     const uint8_t *PeekPrevPc(size_t i) const;
901 
902 private:
903     BytecodeCircuitBuilder *builder_ {nullptr};
904     int32_t start_ {0};
905     int32_t end_ {0};
906     int32_t index_{ INVALID_INDEX };
907 };
908 
909 class BytecodeCallArgc {
910 public:
ComputeCallArgc(int gateNumIn,EcmaOpcode op)911     static int ComputeCallArgc(int gateNumIn, EcmaOpcode op)
912     {
913         switch (op) {
914             case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
915             case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
916             case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
917             case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
918             case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
919             case EcmaOpcode::CALLTHIS0_IMM8_V8:
920             case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: {
921                 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 2; // 2: calltarget, this
922             }
923             default: {
924                 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 1; // 1: calltarget
925             }
926         }
927     }
928 };
929 }  // panda::ecmascript::kungfu
930 #endif  // ECMASCRIPT_COMPILER_BYTECODES_H
931