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