1 /*
2  * Copyright (c) 2022-2024 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_SHARE_GATE_META_DATA_H
17 #define ECMASCRIPT_COMPILER_SHARE_GATE_META_DATA_H
18 
19 #include <string>
20 
21 #include "ecmascript/compiler/bytecodes.h"
22 #include "ecmascript/compiler/share_opcodes.h"
23 #include "ecmascript/compiler/type.h"
24 #include "ecmascript/elements.h"
25 #include "ecmascript/js_thread_hclass_entries.h"
26 #include "ecmascript/mem/chunk.h"
27 #include "ecmascript/mem/chunk_containers.h"
28 #include "ecmascript/mem/region.h"
29 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
30 #include "libpandabase/macros.h"
31 
32 namespace panda::ecmascript::kungfu {
33 using ProfileType = pgo::ProfileType;
34 using GateRef = int32_t;
35 using PGOTypeRef = pgo::PGOTypeRef;
36 using PGODefineOpType = pgo::PGODefineOpType;
37 using PGOSampleType = pgo::PGOSampleType;
38 using PGORWOpType = pgo::PGORWOpType;
39 enum class TypedBinOp : uint8_t;
40 enum class TypedUnOp : uint8_t;
41 enum class TypedJumpOp : uint8_t;
42 enum class TypedLoadOp : uint8_t;
43 enum class TypedStoreOp : uint8_t;
44 enum class TypedCallTargetCheckOp : uint8_t;
45 
46 enum GateFlags : uint8_t {
47     NONE_FLAG = 0,
48     NO_WRITE = 1 << 0,
49     HAS_ROOT = 1 << 1,
50     HAS_FRAME_STATE = 1 << 2,
51     CONTROL = NO_WRITE,
52     CONTROL_ROOT = NO_WRITE | HAS_ROOT,
53     CHECKABLE = NO_WRITE | HAS_FRAME_STATE,
54     ROOT = NO_WRITE | HAS_ROOT,
55     FIXED = NO_WRITE,
56 };
57 
58 class GateMetaData : public ChunkObject {
59 public:
60     enum class Kind : uint8_t {
61         IMMUTABLE = 0,
62         MUTABLE_WITH_SIZE,
63         IMMUTABLE_ONE_PARAMETER,
64         MUTABLE_ONE_PARAMETER,
65         IMMUTABLE_BOOL,
66         MUTABLE_STRING,
67         JSBYTECODE,
68         TYPED_BINARY_OP,
69         TYPED_CALLTARGETCHECK_OP,
70         TYPED_CALL,
71         CALL_NEW,
72     };
73     GateMetaData() = default;
GateMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn)74     GateMetaData(OpCode opcode, GateFlags flags,
75         uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn)
76         : opcode_(opcode), flags_(flags),
77         statesIn_(statesIn), dependsIn_(dependsIn), valuesIn_(valuesIn) {}
78 
equal(const GateMetaData &other) const79     virtual bool equal(const GateMetaData &other) const
80     {
81         if (opcode_ == other.opcode_ && kind_ == other.kind_ && flags_ == other.flags_ &&
82             statesIn_ == other.statesIn_ && dependsIn_ == other.dependsIn_ && valuesIn_ == other.valuesIn_) {
83             return true;
84         }
85         return false;
86     }
87 
GetStateCount() const88     size_t GetStateCount() const
89     {
90         return statesIn_;
91     }
92 
GetDependCount() const93     size_t GetDependCount() const
94     {
95         return dependsIn_;
96     }
97 
GetInValueCount() const98     size_t GetInValueCount() const
99     {
100         return valuesIn_;
101     }
102 
GetRootCount() const103     size_t GetRootCount() const
104     {
105         return HasRoot() ? 1 : 0;
106     }
107 
GetInFrameStateCount() const108     size_t GetInFrameStateCount() const
109     {
110         return HasFrameState() ? 1 : 0;
111     }
112 
GetNumIns() const113     size_t GetNumIns() const
114     {
115         return GetStateCount() + GetDependCount() + GetInValueCount()
116             + GetInFrameStateCount() + GetRootCount();
117     }
118 
GetInValueStarts() const119     size_t GetInValueStarts() const
120     {
121         return GetStateCount() + GetDependCount();
122     }
123 
GetInFrameStateStarts() const124     size_t GetInFrameStateStarts() const
125     {
126         return GetInValueStarts() + GetInValueCount();
127     }
128 
GetOpCode() const129     OpCode GetOpCode() const
130     {
131         return opcode_;
132     }
133 
GetKind() const134     Kind GetKind() const
135     {
136         return kind_;
137     }
138 
AssertKind([[maybe_unused]] Kind kind) const139     void AssertKind([[maybe_unused]] Kind kind) const
140     {
141         ASSERT(GetKind() == kind);
142     }
143 
IsOneParameterKind() const144     bool IsOneParameterKind() const
145     {
146         return GetKind() == Kind::IMMUTABLE_ONE_PARAMETER || GetKind() == Kind::MUTABLE_ONE_PARAMETER ||
147             GetKind() == Kind::TYPED_BINARY_OP || GetKind() == Kind::TYPED_CALLTARGETCHECK_OP ||
148             GetKind() == Kind::CALL_NEW;
149     }
150 
IsStringType() const151     bool IsStringType() const
152     {
153         return GetKind() == Kind::MUTABLE_STRING;
154     }
155 
156     bool IsRoot() const;
157     bool IsProlog() const;
158     bool IsFixed() const;
159     bool IsSchedulable() const;
160     bool IsState() const;  // note: IsState(STATE_ENTRY) == false
161     bool IsGeneralState() const;
162     bool IsTerminalState() const;
163     bool IsVirtualState() const;
164     bool IsCFGMerge() const;
165     bool IsControlCase() const;
166     bool IsIfOrSwitchRelated() const;
167     bool IsLoopHead() const;
168     bool IsNop() const;
169     bool IsDead() const;
170     bool IsConstant() const;
171     bool IsDependSelector() const;
172     bool IsTypedOperator() const;
173     bool IsCheckWithOneIn() const;
174     bool IsCheckWithTwoIns() const;
HasFrameState() const175     bool HasFrameState() const
176     {
177         return HasFlag(GateFlags::HAS_FRAME_STATE);
178     }
179 
IsNotWrite() const180     bool IsNotWrite() const
181     {
182         return HasFlag(GateFlags::NO_WRITE);
183     }
184 
185     ~GateMetaData() = default;
186 
187     static std::string Str(OpCode opcode);
188     static std::string Str(TypedBinOp op);
189     static std::string Str(TypedUnOp op);
190     static std::string Str(TypedJumpOp op);
191     static std::string Str(TypedLoadOp op);
192     static std::string Str(TypedStoreOp op);
193     static std::string Str(TypedCallTargetCheckOp op);
194     static std::string Str(ValueType type);
Str() const195     std::string Str() const
196     {
197         return Str(opcode_);
198     }
199 protected:
SetKind(Kind kind)200     void SetKind(Kind kind)
201     {
202         kind_ = kind;
203     }
204 
SetFlags(GateFlags flags)205     void SetFlags(GateFlags flags)
206     {
207         flags_ = flags;
208     }
209 
DecreaseIn(size_t idx)210     void DecreaseIn(size_t idx)
211     {
212         ASSERT(GetKind() == Kind::MUTABLE_WITH_SIZE);
213         if (idx < statesIn_) {
214             statesIn_--;
215         } else if (idx < statesIn_ + dependsIn_) {
216             dependsIn_--;
217         } else {
218             valuesIn_--;
219         }
220     }
221 
HasRoot() const222     bool HasRoot() const
223     {
224         return HasFlag(GateFlags::HAS_ROOT);
225     }
226 
HasFlag(GateFlags flag) const227     bool HasFlag(GateFlags flag) const
228     {
229         return (GetFlags() & flag) == flag;
230     }
231 
GetFlags() const232     GateFlags GetFlags() const
233     {
234         return flags_;
235     }
236 
237 private:
238     friend class Gate;
239     friend class Circuit;
240     friend class GateMetaBuilder;
241 
242     OpCode opcode_ { OpCode::NOP };
243     Kind kind_ { Kind::IMMUTABLE };
244     GateFlags flags_ { GateFlags::NONE_FLAG };
245     uint32_t statesIn_ { 0 };
246     uint32_t dependsIn_ { 0 };
247     uint32_t valuesIn_ { 0 };
248 };
249 
operator <<(std::ostream& os, OpCode opcode)250 inline std::ostream& operator<<(std::ostream& os, OpCode opcode)
251 {
252     return os << GateMetaData::Str(opcode);
253 }
254 
255 class BoolMetaData : public GateMetaData {
256 public:
BoolMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn, bool value)257     BoolMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
258         uint16_t dependsIn, uint32_t valuesIn, bool value)
259         : GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value)
260     {
261         SetKind(GateMetaData::Kind::IMMUTABLE_BOOL);
262     }
263 
264     bool equal(const GateMetaData &other) const override
265     {
266         if (!GateMetaData::equal(other)) {
267             return false;
268         }
269         auto cast_other = static_cast<const BoolMetaData *>(&other);
270         if (value_ == cast_other->value_) {
271             return true;
272         }
273         return false;
274     }
275 
Cast(const GateMetaData* meta)276     static const BoolMetaData* Cast(const GateMetaData* meta)
277     {
278         meta->AssertKind(GateMetaData::Kind::IMMUTABLE_BOOL);
279         return static_cast<const BoolMetaData*>(meta);
280     }
281 
GetBool() const282     bool GetBool() const
283     {
284         return value_;
285     }
286 
SetBool(bool value)287     void SetBool(bool value)
288     {
289         value_ = value;
290     }
291 
292 private:
293     bool value_ { false };
294 };
295 
296 class OneParameterMetaData : public GateMetaData {
297 public:
OneParameterMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn, uint64_t value)298     OneParameterMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
299         uint16_t dependsIn, uint32_t valuesIn, uint64_t value)
300         : GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value)
301     {
302         SetKind(GateMetaData::Kind::IMMUTABLE_ONE_PARAMETER);
303     }
304 
305     bool equal(const GateMetaData &other) const override
306     {
307         if (!GateMetaData::equal(other)) {
308             return false;
309         }
310         auto cast_other = static_cast<const OneParameterMetaData *>(&other);
311         if (value_ == cast_other->value_) {
312             return true;
313         }
314         return false;
315     }
316 
Cast(const GateMetaData* meta)317     static const OneParameterMetaData* Cast(const GateMetaData* meta)
318     {
319         ASSERT(meta->IsOneParameterKind());
320         return static_cast<const OneParameterMetaData*>(meta);
321     }
322 
GetValue() const323     uint64_t GetValue() const
324     {
325         return value_;
326     }
327 
SetValue(uint64_t value)328     void SetValue(uint64_t value)
329     {
330         value_ = value;
331     }
332 
333 private:
334     uint64_t value_ { 0 };
335 };
336 
337 class StringMetaData : public GateMetaData {
338 public:
StringMetaData(Chunk* chunk, std::string_view str)339     StringMetaData(Chunk* chunk, std::string_view str)
340         : GateMetaData(OpCode::CONSTSTRING, GateFlags::NONE_FLAG, 0, 0, 0),
341         stringData_(str.size() + 1, chunk)
342     {
343         auto srcLength = str.size();
344         auto destlength = stringData_.size();
345         auto dest = stringData_.data();
346         auto src = str.data();
347         if (destlength <= static_cast<size_t>(srcLength) || strcpy_s(dest, destlength, src) != EOK) {
348             LOG_COMPILER(FATAL) << "StringMetaData strcpy_s failed";
349         }
350         SetKind(GateMetaData::Kind::MUTABLE_STRING);
351     }
352     bool equal(const GateMetaData &other) const override
353     {
354         if (!GateMetaData::equal(other)) {
355             return false;
356         }
357         auto cast_other = static_cast<const StringMetaData *>(&other);
358         if (stringData_.size() != cast_other->GetString().size()) {
359             return false;
360         }
361 
362         if (strncmp(stringData_.data(), cast_other->GetString().data(), stringData_.size()) != 0) {
363             return false;
364         }
365 
366         return true;
367     }
368 
GetString() const369     const ChunkVector<char> &GetString() const
370     {
371         return stringData_;
372     }
373 
374 private:
375     ChunkVector<char> stringData_;
376 };
377 
378 class GateTypeAccessor {
379 public:
GateTypeAccessor(uint64_t value)380     explicit GateTypeAccessor(uint64_t value)
381         : type_(static_cast<uint32_t>(value)) {}
382 
GetGateType() const383     GateType GetGateType() const
384     {
385         return GateType(type_);
386     }
387 
GetParamType() const388     ParamType GetParamType() const
389     {
390         return ParamType(type_);
391     }
392 private:
393     uint32_t type_;
394 };
395 
396 class ValuePairTypeAccessor {
397 public:
398     // type bits shift
399     static constexpr int OPRAND_TYPE_BITS = 8;
ValuePairTypeAccessor(uint64_t value)400     explicit ValuePairTypeAccessor(uint64_t value) : bitField_(value) {}
401 
GetSrcType() const402     ValueType GetSrcType() const
403     {
404         return static_cast<ValueType>(LeftBits::Get(bitField_));
405     }
406 
GetDstType() const407     ValueType GetDstType() const
408     {
409         return static_cast<ValueType>(RightBits::Get(bitField_));
410     }
411 
IsConvertSupport() const412     bool IsConvertSupport() const
413     {
414         return ConvertSupportBits::Get(bitField_) == ConvertSupport::ENABLE;
415     }
416 
ToValue(ValueType srcType, ValueType dstType, ConvertSupport support = ConvertSupport::ENABLE)417     static uint64_t ToValue(ValueType srcType, ValueType dstType, ConvertSupport support = ConvertSupport::ENABLE)
418     {
419         uint8_t srcVlaue = static_cast<uint8_t>(srcType);
420         uint8_t dstVlaue = static_cast<uint8_t>(dstType);
421         return LeftBits::Encode(srcVlaue) | RightBits::Encode(dstVlaue) | ConvertSupportBits::Encode(support);
422     }
423 
424 private:
425     using LeftBits = panda::BitField<uint8_t, 0, OPRAND_TYPE_BITS>;
426     using RightBits = LeftBits::NextField<uint8_t, OPRAND_TYPE_BITS>;
427     using ConvertSupportBits = RightBits::NextField<ConvertSupport, OPRAND_TYPE_BITS>;
428 
429     uint64_t bitField_;
430 };
431 
432 class TypeConvertAccessor {
433 public:
434     // type bits shift
435     static constexpr int OPRAND_TYPE_BITS = 32;
TypeConvertAccessor(uint64_t value)436     explicit TypeConvertAccessor(uint64_t value) : bitField_(value) {}
437 
GetLeftType() const438     ParamType GetLeftType() const
439     {
440         return ParamType(LeftBits::Get(bitField_));
441     }
442 
GetRightType() const443     GateType GetRightType() const
444     {
445         return GateType(RightBits::Get(bitField_));
446     }
447 
ToValue(ParamType leftType, GateType rightType)448     static uint64_t ToValue(ParamType leftType, GateType rightType)
449     {
450         return LeftBits::Encode(leftType.Value()) | RightBits::Encode(rightType.Value());
451     }
452 
453 private:
454     using LeftBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
455     using RightBits = LeftBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
456 
457     uint64_t bitField_;
458 };
459 
460 class UInt32PairAccessor {
461 public:
462     // type bits shift
463     static constexpr int OPRAND_TYPE_BITS = 32;
UInt32PairAccessor(uint64_t value)464     explicit UInt32PairAccessor(uint64_t value) : bitField_(value) {}
UInt32PairAccessor(uint32_t first, uint32_t second)465     explicit UInt32PairAccessor(uint32_t first, uint32_t second)
466     {
467         bitField_ = FirstBits::Encode(first) | SecondBits::Encode(second);
468     }
469 
GetFirstValue() const470     uint32_t GetFirstValue() const
471     {
472         return FirstBits::Get(bitField_);
473     }
474 
GetSecondValue() const475     uint32_t GetSecondValue() const
476     {
477         return SecondBits::Get(bitField_);
478     }
479 
ToValue() const480     uint64_t ToValue() const
481     {
482         return bitField_;
483     }
484 
485 private:
486     using FirstBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
487     using SecondBits = FirstBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
488 
489     uint64_t bitField_;
490 };
491 
492 class ArrayMetaDataAccessor {
493 public:
494     enum Mode : uint8_t {
495         CREATE = 0,
496         LOAD_ELEMENT,
497         STORE_ELEMENT,
498         LOAD_LENGTH,
499         CALL_BUILTIN_METHOD
500     };
501 
502     static constexpr int BITS_SIZE = 8;
503     static constexpr int ARRAY_LENGTH_BITS_SIZE = 32;
ArrayMetaDataAccessor(uint64_t value)504     explicit ArrayMetaDataAccessor(uint64_t value) : bitField_(value) {}
ArrayMetaDataAccessor(ElementsKind kind, Mode mode, uint32_t length = 0, RegionSpaceFlag flag = RegionSpaceFlag::IN_YOUNG_SPACE)505     explicit ArrayMetaDataAccessor(ElementsKind kind, Mode mode,
506                                    uint32_t length = 0, RegionSpaceFlag flag = RegionSpaceFlag::IN_YOUNG_SPACE)
507     {
508         bitField_ = ElementsKindBits::Encode(kind) | ModeBits::Encode(mode) |
509                     ArrayLengthBits::Encode(length) | RegionSpaceFlagBits::Encode(flag);
510     }
511 
GetRegionSpaceFlag() const512     RegionSpaceFlag GetRegionSpaceFlag() const
513     {
514         return RegionSpaceFlagBits::Get(bitField_);
515     }
516 
GetElementsKind() const517     ElementsKind GetElementsKind() const
518     {
519         return ElementsKindBits::Get(bitField_);
520     }
521 
GetMode() const522     Mode GetMode() const
523     {
524         return ModeBits::Get(bitField_);
525     }
526 
SetElementsKind(ElementsKind kind)527     void SetElementsKind(ElementsKind kind)
528     {
529         bitField_ = ElementsKindBits::Update(bitField_, kind);
530     }
531 
SetArrayLength(uint32_t length)532     void SetArrayLength(uint32_t length)
533     {
534         bitField_ = ArrayLengthBits::Update(bitField_, length);
535     }
536 
SetRegionSpaceFlag(RegionSpaceFlag flag)537     void SetRegionSpaceFlag(RegionSpaceFlag flag)
538     {
539         bitField_ = RegionSpaceFlagBits::Update(bitField_, flag);
540     }
541 
GetArrayLength() const542     uint32_t GetArrayLength() const
543     {
544         return ArrayLengthBits::Get(bitField_);
545     }
546 
IsLoadElement() const547     bool IsLoadElement() const
548     {
549         return GetMode() == Mode::LOAD_ELEMENT;
550     }
551 
IsStoreElement() const552     bool IsStoreElement() const
553     {
554         return GetMode() == Mode::STORE_ELEMENT;
555     }
556 
ToValue() const557     uint64_t ToValue() const
558     {
559         return bitField_;
560     }
561 
562 private:
563     using ElementsKindBits = panda::BitField<ElementsKind, 0, BITS_SIZE>;
564     using ModeBits = ElementsKindBits::NextField<Mode, BITS_SIZE>;
565     using ArrayLengthBits = ModeBits::NextField<uint32_t, ARRAY_LENGTH_BITS_SIZE>;
566     using RegionSpaceFlagBits = ArrayLengthBits::NextField<RegionSpaceFlag, BITS_SIZE>;
567 
568     uint64_t bitField_;
569 };
570 
571 class CreateArgumentsAccessor {
572 public:
573     enum Mode : uint8_t {
574         REST_ARGUMENTS,
575         UNMAPPED_ARGUMENTS,
576         INVALID,
577     };
578 
579     static constexpr int BITS_SIZE = 8;
CreateArgumentsAccessor(uint64_t value)580     explicit CreateArgumentsAccessor(uint64_t value) : bitField_(value) {}
CreateArgumentsAccessor(ElementsKind kind, Mode mode)581     explicit CreateArgumentsAccessor(ElementsKind kind, Mode mode)
582     {
583         bitField_ = ElementsKindBits::Encode(kind) | ModeBits::Encode(mode);
584     }
GetMode() const585     Mode GetMode() const
586     {
587         return ModeBits::Get(bitField_);
588     }
ToValue() const589     uint64_t ToValue() const
590     {
591         return bitField_;
592     }
593 private:
594     using ElementsKindBits = panda::BitField<ElementsKind, 0, BITS_SIZE>;
595     using ModeBits = ElementsKindBits::NextField<Mode, BITS_SIZE>;
596 
597     uint64_t bitField_;
598 };
599 
600 class ObjectTypeAccessor {
601 public:
602     static constexpr int IS_HEAP_OBJECT_BIT_SIZE = 1;
603 
ObjectTypeAccessor(uint64_t value)604     explicit ObjectTypeAccessor(uint64_t value) : bitField_(value) {}
ObjectTypeAccessor(bool isHeapObject = false)605     explicit ObjectTypeAccessor(bool isHeapObject = false)
606     {
607         bitField_ = IsHeapObjectBit::Encode(isHeapObject);
608     }
609 
IsHeapObject() const610     bool IsHeapObject() const
611     {
612         return IsHeapObjectBit::Get(bitField_);
613     }
614 
ToValue() const615     uint64_t ToValue() const
616     {
617         return bitField_;
618     }
619 
620 private:
621     using IsHeapObjectBit = panda::BitField<bool, 0, IS_HEAP_OBJECT_BIT_SIZE>;
622 
623     uint64_t bitField_;
624 };
625 
626 class BuiltinPrototypeHClassAccessor {
627 public:
628     static constexpr int WORD_BITS_SIZE = 8;
629     static constexpr int IS_PROTOTYPE_OF_PROTOTYPE_BITS_SIZE = 1;
630 
BuiltinPrototypeHClassAccessor(uint64_t value)631     explicit BuiltinPrototypeHClassAccessor(uint64_t value): type_(value) {}
632     // Only valid indices accepted
BuiltinPrototypeHClassAccessor(BuiltinTypeId type, ElementsKind kind, bool isPrototypeOfPrototype)633     explicit BuiltinPrototypeHClassAccessor(BuiltinTypeId type, ElementsKind kind,
634                                             bool isPrototypeOfPrototype): type_(0)
635     {
636         type_ = BuiltinTypeIdBits::Encode(type) | ElementsKindBits::Encode(kind) |
637                 IsPrototypeOfPrototypeBits::Encode(isPrototypeOfPrototype);
638         type_ = BuiltinTypeIdBits::Encode(type) | ElementsKindBits::Encode(kind);
639         ASSERT(BuiltinHClassEntries::GetEntryIndex(type) < BuiltinHClassEntries::N_ENTRIES);
640     }
641 
GetElementsKind() const642     ElementsKind GetElementsKind() const
643     {
644         return ElementsKindBits::Get(type_);
645     }
646 
GetBuiltinTypeId() const647     BuiltinTypeId GetBuiltinTypeId() const
648     {
649         return BuiltinTypeIdBits::Get(type_);
650     }
651 
IsPrototypeOfPrototype() const652     bool IsPrototypeOfPrototype() const
653     {
654         return IsPrototypeOfPrototypeBits::Get(type_);
655     }
656 
ToValue() const657     uint64_t ToValue() const
658     {
659         return type_;
660     }
661 
662 private:
663     using BuiltinTypeIdBits = panda::BitField<BuiltinTypeId, 0, WORD_BITS_SIZE>;
664     using ElementsKindBits = BuiltinTypeIdBits::NextField<ElementsKind, WORD_BITS_SIZE>;
665     using IsPrototypeOfPrototypeBits = ElementsKindBits::NextField<bool, IS_PROTOTYPE_OF_PROTOTYPE_BITS_SIZE>;
666 
667     uint64_t type_;
668 };
669 
670 class TypedArrayMetaDataAccessor {
671 public:
672     enum Mode : uint8_t {
673         ACCESS_ELEMENT = 0,
674         LOAD_LENGTH,
675     };
676 
677     static constexpr int TYPE_BITS_SIZE = 32;
678     static constexpr int MODE_BITS_SIZE = 2;
679     static constexpr int ON_HEAP_MODE_BITS_SIZE = 2;
680 
TypedArrayMetaDataAccessor(uint64_t value)681     explicit TypedArrayMetaDataAccessor(uint64_t value) : bitField_(value) {}
682 
GetParamType() const683     ParamType GetParamType() const
684     {
685         return ParamType(TypeBits::Get(bitField_));
686     }
687 
GetOnHeapMode() const688     OnHeapMode GetOnHeapMode() const
689     {
690         return OnHeapModeBits::Get(bitField_);
691     }
692 
IsAccessElement() const693     bool IsAccessElement() const
694     {
695         return ModeBits::Get(bitField_) == Mode::ACCESS_ELEMENT;
696     }
697 
ToValue()698     uint64_t ToValue()
699     {
700         return bitField_;
701     }
702 
ToValue(ParamType paramType, Mode mode, OnHeapMode onHeap)703     static uint64_t ToValue(ParamType paramType, Mode mode, OnHeapMode onHeap)
704     {
705         return TypeBits::Encode(paramType.Value()) | ModeBits::Encode(mode) | OnHeapModeBits::Encode(onHeap);
706     }
707 
708 private:
709     using TypeBits = panda::BitField<uint32_t, 0, TYPE_BITS_SIZE>;
710     using ModeBits = TypeBits::NextField<Mode, MODE_BITS_SIZE>;
711     using OnHeapModeBits = ModeBits::NextField<OnHeapMode, ON_HEAP_MODE_BITS_SIZE>;
712 
713     uint64_t bitField_;
714 };
715 
716 class LoadElementAccessor {
717 public:
718     static constexpr int TYPED_LOAD_OP_BITS_SIZE = 8;
719     static constexpr int ON_HEAP_MODE_BITS_SIZE = 8;
720 
LoadElementAccessor(uint64_t value)721     explicit LoadElementAccessor(uint64_t value): bitField_(value) {}
LoadElementAccessor(TypedLoadOp op, OnHeapMode onHeap)722     explicit LoadElementAccessor(TypedLoadOp op, OnHeapMode onHeap)
723     {
724         bitField_ = TypedLoadOpBits::Encode(op) | OnHeapModeBits::Encode(onHeap);
725     }
726 
GetTypedLoadOp() const727     TypedLoadOp GetTypedLoadOp() const
728     {
729         return TypedLoadOpBits::Get(bitField_);
730     }
731 
GetOnHeapMode() const732     OnHeapMode GetOnHeapMode() const
733     {
734         return OnHeapModeBits::Get(bitField_);
735     }
736 
ToValue() const737     uint64_t ToValue() const
738     {
739         return bitField_;
740     }
741 
742 private:
743     using TypedLoadOpBits = panda::BitField<TypedLoadOp, 0, TYPED_LOAD_OP_BITS_SIZE>;
744     using OnHeapModeBits = TypedLoadOpBits::NextField<OnHeapMode, ON_HEAP_MODE_BITS_SIZE>;
745 
746     uint64_t bitField_;
747 };
748 
749 class StoreElementAccessor {
750 public:
751     static constexpr int TYPED_STORE_OP_BITS_SIZE = 8;
752     static constexpr int ON_HEAP_MODE_BITS_SIZE = 8;
753 
StoreElementAccessor(uint64_t value)754     explicit StoreElementAccessor(uint64_t value): bitField_(value) {}
StoreElementAccessor(TypedStoreOp op, OnHeapMode onHeap)755     explicit StoreElementAccessor(TypedStoreOp op, OnHeapMode onHeap)
756     {
757         bitField_ = TypedStoreOpBits::Encode(op) | OnHeapModeBits::Encode(onHeap);
758     }
759 
GetTypedStoreOp() const760     TypedStoreOp GetTypedStoreOp() const
761     {
762         return TypedStoreOpBits::Get(bitField_);
763     }
764 
GetOnHeapMode() const765     OnHeapMode GetOnHeapMode() const
766     {
767         return OnHeapModeBits::Get(bitField_);
768     }
769 
ToValue() const770     uint64_t ToValue() const
771     {
772         return bitField_;
773     }
774 
775 private:
776     using TypedStoreOpBits = panda::BitField<TypedStoreOp, 0, TYPED_STORE_OP_BITS_SIZE>;
777     using OnHeapModeBits = TypedStoreOpBits::NextField<OnHeapMode, ON_HEAP_MODE_BITS_SIZE>;
778 
779     uint64_t bitField_;
780 };
781 
782 class StringStatusAccessor {
783 public:
StringStatusAccessor(uint64_t value = 0)784     explicit StringStatusAccessor(uint64_t value = 0) : type_(value) {}
785 
GetStringStatus() const786     uint32_t GetStringStatus() const
787     {
788         return static_cast<uint32_t>(type_);
789     }
790 
ToValue() const791     uint64_t ToValue() const
792     {
793         return type_;
794     }
795 
796 private:
797     uint64_t type_ {0};
798 };
799 } // namespace panda::ecmascript::kungfu
800 
801 #endif  // ECMASCRIPT_COMPILER_SHARE_GATE_META_DATA_H
802