• 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     static bool IsBytecodeNoThrow(EcmaOpcode &opcode);
243 
244 private:
245     BytecodeMetaData() = default;
246     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BytecodeMetaData);
247     DEFAULT_COPY_SEMANTIC(BytecodeMetaData);
BytecodeMetaData(uint64_t value)248     explicit BytecodeMetaData(uint64_t value) : value_(value) {}
249 
250     static BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc);
251     static void InitBytecodeFlags(EcmaOpcode &opcode, uint32_t &flags);
252     static void InitBytecodeKind(EcmaOpcode &opcode, BytecodeKind &kind);
253 
254     static void InitNoSideEffectFlag(EcmaOpcode &opcode, uint32_t &flags);
255     static void InitNoGCFlag(EcmaOpcode &opcode, uint32_t &flags);
256     static void InitNoThrowFlag(EcmaOpcode &opcode, uint32_t &flags);
257     static void InitReadThisObjectFlag(EcmaOpcode &opcode, uint32_t &flags);
258     static void InitSupportDeoptFlag(EcmaOpcode &opcode, uint32_t &flags);
259     static void InitReadACCFlag(EcmaOpcode &opcode, uint32_t &flags);
260     static void InitDebuggerFlag(EcmaOpcode &opcode, uint32_t &flags);
261     static void InitReadFuncFlag(EcmaOpcode &opcode, uint32_t &flags);
262     static void InitWriteEnvFlag(EcmaOpcode &opcode, uint32_t &flags);
263     static void InitReadEnvFlag(EcmaOpcode &opcode, uint32_t &flags);
264     static void InitReadNewTargetFlag(EcmaOpcode &opcode, uint32_t &flags);
265     static void InitReadArgcFlag(EcmaOpcode &opcode, uint32_t &flags);
266 
267     static bool InitMovKind(EcmaOpcode &opcode, BytecodeKind &kind);
268     static bool InitSetConstantKind(EcmaOpcode &opcode, BytecodeKind &kind);
269     static bool InitCallBCKind(EcmaOpcode &opcode, BytecodeKind &kind);
270     static bool InitRetrunKind(EcmaOpcode &opcode, BytecodeKind &kind);
271     static bool InitSuspendKind(EcmaOpcode &opcode, BytecodeKind &kind);
272     static bool InitResumeKind(EcmaOpcode &opcode, BytecodeKind &kind);
273     static bool InitDiscardedKind(EcmaOpcode &opcode, BytecodeKind &kind);
274     static bool InitThrowKind(EcmaOpcode &opcode, BytecodeKind &kind);
275     static bool InitConditionJumpKind(EcmaOpcode &opcode, BytecodeKind &kind);
276     static bool InitJumpIMMKind(EcmaOpcode &opcode, BytecodeKind &kind);
277     static bool InitGeneratorResolveKind(EcmaOpcode &opcode, BytecodeKind &kind);
278     static bool InitAccessorKind(EcmaOpcode &opcode, BytecodeKind &kind);
279 
280     static size_t GetVRegCount(const BytecodeInstruction &inst);
281 
HasFlag(BytecodeFlags flag)282     inline bool HasFlag(BytecodeFlags flag) const
283     {
284         return (GetFlags() & flag) == flag;
285     }
286 
GetFlags()287     inline BytecodeFlags GetFlags() const
288     {
289         return FlagsField::Get(value_);
290     }
291 
GetKind()292     inline BytecodeKind GetKind() const
293     {
294         return KindField::Get(value_);
295     }
296 
297     uint64_t value_ {0};
298     friend class Bytecodes;
299     friend class BytecodeInfo;
300     friend class BytecodeCircuitBuilder;
301 };
302 
303 class Bytecodes {
304 public:
305     static constexpr uint32_t NUM_BYTECODES = 0xFF;
306     static constexpr uint32_t OPCODE_MASK = 0xFF00;
307     static constexpr uint32_t BYTE_SIZE = 8;
308     static constexpr uint32_t CALLRUNTIME_PREFIX_OPCODE_INDEX = 251;
309     static constexpr uint32_t DEPRECATED_PREFIX_OPCODE_INDEX = 252;
310     static constexpr uint32_t WIDE_PREFIX_OPCODE_INDEX = 253;
311     static constexpr uint32_t THROW_PREFIX_OPCODE_INDEX = 254;
312     static constexpr uint32_t MIN_PREFIX_OPCODE_INDEX = CALLRUNTIME_PREFIX_OPCODE_INDEX;
313 
314     static constexpr uint32_t LAST_OPCODE =
315         static_cast<uint32_t>(EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8);
316     static constexpr uint32_t LAST_DEPRECATED_OPCODE =
317         static_cast<uint32_t>(EcmaOpcode::DEPRECATED_DYNAMICIMPORT_PREF_V8);
318     static constexpr uint32_t LAST_WIDE_OPCODE =
319         static_cast<uint32_t>(EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16);
320     static constexpr uint32_t LAST_THROW_OPCODE =
321         static_cast<uint32_t>(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16);
322     static constexpr uint32_t LAST_CALLRUNTIME_OPCODE =
323         static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_WIDELDSENDABLELOCALMODULEVAR_PREF_IMM16);
324 
325     static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX ==
326         static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE));
327     static_assert(DEPRECATED_PREFIX_OPCODE_INDEX ==
328         static_cast<uint32_t>(EcmaOpcode::DEPRECATED_LDLEXENV_PREF_NONE));
329     static_assert(WIDE_PREFIX_OPCODE_INDEX ==
330         static_cast<uint32_t>(EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8));
331     static_assert(THROW_PREFIX_OPCODE_INDEX ==
332         static_cast<uint32_t>(EcmaOpcode::THROW_PREF_NONE));
333 
334     Bytecodes();
335     Bytecodes(const Bytecodes&) = delete;
336     void operator=(const Bytecodes&) = delete;
337 
GetOpcode(const uint8_t * pc)338     static EcmaOpcode GetOpcode(const uint8_t *pc)
339     {
340         uint8_t primary = ReadByte(pc);
341         if (primary >= MIN_PREFIX_OPCODE_INDEX) {
342             uint8_t secondary = ReadByte1(pc);
343             return static_cast<EcmaOpcode>((secondary << 8U) | primary); // 8: byte size
344         }
345         return static_cast<EcmaOpcode>(primary);
346     }
347 
GetBytecodeMetaData(const uint8_t * pc)348     BytecodeMetaData GetBytecodeMetaData(const uint8_t *pc) const
349     {
350         uint8_t primary = ReadByte(pc);
351         if (primary >= MIN_PREFIX_OPCODE_INDEX) {
352             uint8_t secondary = ReadByte1(pc);
353             if (primary == CALLRUNTIME_PREFIX_OPCODE_INDEX) {
354                 return callRuntimeBytecodes_[secondary];
355             } else if (primary == DEPRECATED_PREFIX_OPCODE_INDEX) {
356                 return deprecatedBytecodes_[secondary];
357             } else if (primary == WIDE_PREFIX_OPCODE_INDEX) {
358                 return wideBytecodes_[secondary];
359             } else {
360                 ASSERT(primary == THROW_PREFIX_OPCODE_INDEX);
361                 return throwBytecodes_[secondary];
362             }
363         }
364         return bytecodes_[primary];
365     }
366 
IsCallOp(EcmaOpcode opcode)367     static bool IsCallOp(EcmaOpcode opcode)
368     {
369         switch (opcode) {
370             case EcmaOpcode::CALLARG0_IMM8:
371             case EcmaOpcode::CALLARG1_IMM8_V8:
372             case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
373             case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
374             case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
375             case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
376             case EcmaOpcode::CALLTHIS0_IMM8_V8:
377             case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
378             case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
379             case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
380             case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
381             case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
382             case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8:
383                 return true;
384             default:
385                 return false;
386         }
387     }
388 
IsCreateObjectWithBufferOp(EcmaOpcode opcode)389     static bool IsCreateObjectWithBufferOp(EcmaOpcode opcode)
390     {
391         switch (opcode) {
392             case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
393             case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
394                 return true;
395             default:
396                 return false;
397         }
398     }
399 
IsCreateEmptyArrayOp(EcmaOpcode opcode)400     static bool IsCreateEmptyArrayOp(EcmaOpcode opcode)
401     {
402         switch (opcode) {
403             case EcmaOpcode::CREATEEMPTYARRAY_IMM8:
404             case EcmaOpcode::CREATEEMPTYARRAY_IMM16:
405                 return true;
406             default:
407                 return false;
408         }
409     }
410 
IsCreateArrayWithBufferOp(EcmaOpcode opcode)411     static bool IsCreateArrayWithBufferOp(EcmaOpcode opcode)
412     {
413         switch (opcode) {
414             case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
415             case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
416                 return true;
417             default:
418                 return false;
419         }
420     }
421 
IsDefineClassWithBufferOp(EcmaOpcode opcode)422     static bool IsDefineClassWithBufferOp(EcmaOpcode opcode)
423     {
424         switch (opcode) {
425             case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
426             case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
427                 return true;
428             default:
429                 return false;
430         }
431     }
432 
IsLdLexVarOp(EcmaOpcode opcode)433     static bool IsLdLexVarOp(EcmaOpcode opcode)
434     {
435         switch (opcode) {
436             case EcmaOpcode::LDLEXVAR_IMM4_IMM4:
437             case EcmaOpcode::LDLEXVAR_IMM8_IMM8:
438             case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16:
439                 return true;
440             default:
441                 return false;
442         }
443     }
444 
IsStLexVarOp(EcmaOpcode opcode)445     static bool IsStLexVarOp(EcmaOpcode opcode)
446     {
447         switch (opcode) {
448             case EcmaOpcode::STLEXVAR_IMM4_IMM4:
449             case EcmaOpcode::STLEXVAR_IMM8_IMM8:
450             case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16:
451                 return true;
452             default:
453                 return false;
454         }
455     }
456 
IsCallOrAccessorOp(EcmaOpcode opcode)457     static bool IsCallOrAccessorOp(EcmaOpcode opcode)
458     {
459         switch (opcode) {
460             case EcmaOpcode::CALLARG0_IMM8:
461             case EcmaOpcode::CALLARG1_IMM8_V8:
462             case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
463             case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
464             case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
465             case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
466             case EcmaOpcode::CALLTHIS0_IMM8_V8:
467             case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
468             case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
469             case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
470             case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
471             case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
472             case EcmaOpcode::LDOBJBYNAME_IMM8_ID16:
473             case EcmaOpcode::LDOBJBYNAME_IMM16_ID16:
474             case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
475             case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
476             case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
477             case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
478             case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
479             case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
480             case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
481             case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
482             case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8:
483                 return true;
484             default:
485                 return false;
486         }
487     }
488 
IsDefineFunc(EcmaOpcode opcode)489     static bool IsDefineFunc(EcmaOpcode opcode)
490     {
491         switch (opcode) {
492             case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8:
493             case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8:
494                 return true;
495             default:
496                 return false;
497         }
498     }
499 
500 private:
ReadByte(const uint8_t * pc)501     static uint8_t ReadByte(const uint8_t *pc)
502     {
503         return *pc;
504     }
ReadByte1(const uint8_t * pc)505     static uint8_t ReadByte1(const uint8_t *pc)
506     {
507         return *(pc + 1); // 1: byte1
508     }
509     BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc);
510 
511     std::array<BytecodeMetaData, NUM_BYTECODES> bytecodes_{};
512     std::array<BytecodeMetaData, NUM_BYTECODES> callRuntimeBytecodes_{};
513     std::array<BytecodeMetaData, NUM_BYTECODES> deprecatedBytecodes_{};
514     std::array<BytecodeMetaData, NUM_BYTECODES> wideBytecodes_{};
515     std::array<BytecodeMetaData, NUM_BYTECODES> throwBytecodes_{};
516 };
517 
518 enum class ConstDataIDType : uint8_t {
519     StringIDType,
520     MethodIDType,
521     ArrayLiteralIDType,
522     ObjectLiteralIDType,
523     ClassLiteralIDType,
524 };
525 
526 class VirtualRegister {
527 public:
VirtualRegister(VRegIDType id)528     explicit VirtualRegister(VRegIDType id) : id_(id)
529     {
530     }
531     ~VirtualRegister() = default;
532 
SetId(VRegIDType id)533     void SetId(VRegIDType id)
534     {
535         id_ = id;
536     }
537 
GetId()538     VRegIDType GetId() const
539     {
540         return id_;
541     }
542 
543 private:
544     VRegIDType id_;
545 };
546 
547 class Immediate {
548 public:
Immediate(ImmValueType value)549     explicit Immediate(ImmValueType value) : value_(value)
550     {
551     }
552     ~Immediate() = default;
553 
SetValue(ImmValueType value)554     void SetValue(ImmValueType value)
555     {
556         value_ = value;
557     }
558 
ToJSTaggedValueInt()559     ImmValueType ToJSTaggedValueInt() const
560     {
561         return value_ | JSTaggedValue::TAG_INT;
562     }
563 
ToJSTaggedValueDouble()564     ImmValueType ToJSTaggedValueDouble() const
565     {
566         return JSTaggedValue(base::bit_cast<double>(value_)).GetRawData();
567     }
568 
GetValue()569     ImmValueType GetValue() const
570     {
571         return value_;
572     }
573 
574 private:
575     ImmValueType value_;
576 };
577 
578 
579 class ICSlotId {
580 public:
ICSlotId(ICSlotIdType id)581     explicit ICSlotId(ICSlotIdType id) : id_(id)
582     {
583     }
584     ~ICSlotId() = default;
585 
SetId(ICSlotIdType id)586     void SetId(ICSlotIdType id)
587     {
588         id_ = id;
589     }
590 
GetId()591     ICSlotIdType GetId() const
592     {
593         return id_;
594     }
595 
596 private:
597     ICSlotIdType id_;
598 };
599 
600 class ConstDataId {
601 public:
ConstDataId(ConstDataIDType type,uint16_t id)602     ConstDataId(ConstDataIDType type, uint16_t id)
603         :type_(type), id_(id)
604     {
605     }
606 
ConstDataId(uint64_t bitfield)607     explicit ConstDataId(uint64_t bitfield)
608     {
609         type_ = ConstDataIDType(bitfield >> TYPE_SHIFT);
610         id_ = bitfield & ((1 << TYPE_SHIFT) - 1);
611     }
612 
613     ~ConstDataId() = default;
614 
SetId(uint16_t id)615     void SetId(uint16_t id)
616     {
617         id_ = id;
618     }
619 
GetId()620     uint16_t GetId() const
621     {
622         return id_;
623     }
624 
SetType(ConstDataIDType type)625     void SetType(ConstDataIDType type)
626     {
627         type_ = type;
628     }
629 
GetType()630     ConstDataIDType GetType() const
631     {
632         return type_;
633     }
634 
IsStringId()635     bool IsStringId() const
636     {
637         return type_ == ConstDataIDType::StringIDType;
638     }
639 
IsMethodId()640     bool IsMethodId() const
641     {
642         return type_ == ConstDataIDType::MethodIDType;
643     }
644 
IsClassLiteraId()645     bool IsClassLiteraId() const
646     {
647         return type_ == ConstDataIDType::ClassLiteralIDType;
648     }
649 
IsObjectLiteralID()650     bool IsObjectLiteralID() const
651     {
652         return type_ == ConstDataIDType::ObjectLiteralIDType;
653     }
654 
IsArrayLiteralID()655     bool IsArrayLiteralID() const
656     {
657         return type_ == ConstDataIDType::ArrayLiteralIDType;
658     }
659 
CaculateBitField()660     uint64_t CaculateBitField() const
661     {
662         return (static_cast<uint8_t>(type_) << TYPE_SHIFT) | id_;
663     }
664 
665 private:
666     static constexpr int TYPE_SHIFT = 16;
667     ConstDataIDType type_;
668     uint16_t id_;
669 };
670 
671 class BytecodeInfo {
672 public:
673     // set of id, immediate and read register
674     std::vector<std::variant<ConstDataId, ICSlotId, Immediate, VirtualRegister>> inputs {};
675     std::vector<VRegIDType> vregOut {}; // write register
676 
Deopt()677     bool Deopt() const
678     {
679         return metaData_.SupportDeopt();
680     }
681 
AccOut()682     bool AccOut() const
683     {
684         return metaData_.HasAccOut();
685     }
686 
AccIn()687     bool AccIn() const
688     {
689         return metaData_.HasAccIn();
690     }
691 
EnvIn()692     bool EnvIn() const
693     {
694         return metaData_.HasEnvIn();
695     }
696 
EnvOut()697     bool EnvOut() const
698     {
699         return metaData_.HasEnvOut();
700     }
701 
NoSideEffects()702     bool NoSideEffects() const
703     {
704         return metaData_.IsNoSideEffects();
705     }
706 
NoThrow()707     bool NoThrow() const
708     {
709         return metaData_.IsNoThrow();
710     }
711 
ThisObjectIn()712     bool ThisObjectIn() const
713     {
714         return metaData_.HasThisIn();
715     }
716 
GetSize()717     size_t GetSize() const
718     {
719         return metaData_.GetSize();
720     }
721 
IsDef()722     bool IsDef() const
723     {
724         return (!vregOut.empty()) || AccOut();
725     }
726 
IsOut(VRegIDType reg,uint32_t index)727     bool IsOut(VRegIDType reg, uint32_t index) const
728     {
729         bool isDefined = (!vregOut.empty() && (reg == vregOut.at(index)));
730         return isDefined;
731     }
732 
IsMov()733     bool IsMov() const
734     {
735         return metaData_.IsMov();
736     }
737 
IsJump()738     bool IsJump() const
739     {
740         return metaData_.IsJump();
741     }
742 
IsCondJump()743     bool IsCondJump() const
744     {
745         return metaData_.IsCondJump();
746     }
747 
IsReturn()748     bool IsReturn() const
749     {
750         return metaData_.IsReturn();
751     }
752 
IsThrow()753     bool IsThrow() const
754     {
755         return metaData_.IsThrow();
756     }
757 
IsSuspend()758     bool IsSuspend() const
759     {
760         return metaData_.IsSuspend();
761     }
762 
IsGeneratorResolve()763     bool IsGeneratorResolve() const
764     {
765         return metaData_.IsGeneratorResolve();
766     }
767 
IsDiscarded()768     bool IsDiscarded() const
769     {
770         return metaData_.IsDiscarded();
771     }
772 
IsSetConstant()773     bool IsSetConstant() const
774     {
775         return metaData_.IsSetConstant();
776     }
777 
IsGeneral()778     bool IsGeneral() const
779     {
780         return metaData_.IsGeneral();
781     }
782 
needFallThrough()783     bool needFallThrough() const
784     {
785         return !IsJump() && !IsReturn() && !IsThrow() && !IsInsufficientProfile();
786     }
787 
IsGeneratorRelative()788     bool IsGeneratorRelative() const
789     {
790         return metaData_.IsGeneratorRelative();
791     }
792 
ComputeValueInputCount()793     size_t ComputeValueInputCount() const
794     {
795         return (AccIn() ? 1 : 0) + inputs.size();
796     }
797 
ComputeOutCount()798     size_t ComputeOutCount() const
799     {
800         return (AccOut() ? 1 : 0) + vregOut.size();
801     }
802 
IsBc(EcmaOpcode ecmaOpcode)803     bool IsBc(EcmaOpcode ecmaOpcode) const
804     {
805         return metaData_.GetOpcode() == ecmaOpcode;
806     }
807 
HasFuncIn()808     bool HasFuncIn() const
809     {
810         return metaData_.HasFuncIn();
811     }
812 
HasNewTargetIn()813     bool HasNewTargetIn() const
814     {
815         return metaData_.HasNewTargetIn();
816     }
817 
HasArgcIn()818     bool HasArgcIn() const
819     {
820         return metaData_.HasArgcIn();
821     }
822 
HasFrameArgs()823     bool HasFrameArgs() const
824     {
825         return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn();
826     }
827 
HasFrameState()828     bool HasFrameState() const
829     {
830         return HasFrameArgs() || !NoThrow();
831     }
832 
NeedFrameStateInPlace()833     bool NeedFrameStateInPlace() const
834     {
835         return IsCall() || IsAccessorBC() || !NoThrow();
836     }
837 
IsCall()838     bool IsCall() const
839     {
840         return metaData_.IsCall();
841     }
842 
IsAccessorBC()843     bool IsAccessorBC() const
844     {
845         return metaData_.IsAccessorBC();
846     }
847 
HasDebuggerStmt()848     bool HasDebuggerStmt() const
849     {
850         return metaData_.HasDebuggerStmt();
851     }
852 
GetOpcode()853     inline EcmaOpcode GetOpcode() const
854     {
855         return metaData_.GetOpcode();
856     }
857 
IsInsufficientProfile()858     inline bool IsInsufficientProfile() const
859     {
860         return isInsufficientProfile_;
861     }
862 
863     static void InitBytecodeInfo(BytecodeCircuitBuilder *builder,
864         BytecodeInfo &info, const uint8_t* pc);
865 
866 private:
867     void SetInsufficientProfile(BytecodeCircuitBuilder *builder, const uint8_t *pc);
868 
869     BytecodeMetaData metaData_ { 0 };
870     bool isInsufficientProfile_ {false};
871     friend class BytecodeCircuitBuilder;
872 };
873 
874 class BytecodeIterator {
875 public:
876     static constexpr int INVALID_INDEX = -1;
877     BytecodeIterator() = default;
BytecodeIterator(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)878     BytecodeIterator(BytecodeCircuitBuilder *builder,
879         uint32_t start, uint32_t end)
880         : builder_(builder), start_(start), end_(end) {}
Reset(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)881     void Reset(BytecodeCircuitBuilder *builder,
882         uint32_t start, uint32_t end)
883     {
884         builder_ = builder;
885         start_ = static_cast<int32_t>(start);
886         end_ = static_cast<int32_t>(end);
887     }
888 
889     BytecodeIterator& operator++()
890     {
891         if (InRange()) {
892             index_++;
893         }
894         return *this;
895     }
896     BytecodeIterator& operator--()
897     {
898         if (InRange()) {
899             index_--;
900         }
901         return *this;
902     }
903 
Goto(uint32_t i)904     void Goto(uint32_t i)
905     {
906         index_ = static_cast<int32_t>(i);
907     }
908 
GotoStart()909     void GotoStart()
910     {
911         index_ = start_;
912     }
913 
GotoEnd()914     void GotoEnd()
915     {
916         index_ = end_;
917         ASSERT(InRange());
918     }
919 
IsInRange(int idx)920     bool IsInRange(int idx) const
921     {
922         return (idx <= end_) && (idx >= start_);
923     }
924 
InRange()925     bool InRange() const
926     {
927         return (index_ <= end_) && (index_ >= start_);
928     }
929 
Done()930     bool Done() const
931     {
932         return !InRange();
933     }
934 
Index()935     uint32_t Index() const
936     {
937         return static_cast<uint32_t>(index_);
938     }
939 
940     const BytecodeInfo &GetBytecodeInfo() const;
941     const uint8_t *PeekNextPc(size_t i) const;
942     const uint8_t *PeekPrevPc(size_t i) const;
943 
944 private:
945     BytecodeCircuitBuilder *builder_ {nullptr};
946     int32_t start_ {0};
947     int32_t end_ {0};
948     int32_t index_{ INVALID_INDEX };
949 };
950 
951 class BytecodeCallArgc {
952 public:
ComputeCallArgc(int gateNumIn,EcmaOpcode op)953     static int ComputeCallArgc(int gateNumIn, EcmaOpcode op)
954     {
955         switch (op) {
956             case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
957             case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
958             case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
959             case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
960             case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
961             case EcmaOpcode::CALLTHIS0_IMM8_V8:
962             case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: {
963                 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 2; // 2: calltarget, this
964             }
965             default: {
966                 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 1; // 1: calltarget
967             }
968         }
969     }
970 };
971 }  // panda::ecmascript::kungfu
972 #endif  // ECMASCRIPT_COMPILER_BYTECODES_H
973