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