1 /* 2 * Copyright (c) 2021 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_IC_IC_HANDLER_H 17 #define ECMASCRIPT_IC_IC_HANDLER_H 18 19 #include "ecmascript/ecma_macros.h" 20 #include "ecmascript/js_tagged_value-inl.h" 21 #include "ecmascript/mem/tagged_object.h" 22 23 namespace panda::ecmascript { 24 class HandlerBase { 25 public: 26 static constexpr uint32_t KIND_BIT_LENGTH = 3; 27 enum HandlerKind { 28 NONE = 0, 29 FIELD, 30 ELEMENT, 31 DICTIONARY, 32 NON_EXIST, 33 }; 34 35 using KindBit = BitField<HandlerKind, 0, KIND_BIT_LENGTH>; 36 using InlinedPropsBit = KindBit::NextFlag; 37 using AccessorBit = InlinedPropsBit::NextFlag; 38 using InternalAccessorBit = AccessorBit::NextFlag; 39 using IsJSArrayBit = InternalAccessorBit::NextFlag; 40 using OffsetBit = IsJSArrayBit::NextField<uint32_t, PropertyAttributes::OFFSET_BITFIELD_NUM>; 41 42 HandlerBase() = default; 43 virtual ~HandlerBase() = default; 44 IsAccessor(uint32_t handler)45 static inline bool IsAccessor(uint32_t handler) 46 { 47 return AccessorBit::Get(handler); 48 } 49 IsInternalAccessor(uint32_t handler)50 static inline bool IsInternalAccessor(uint32_t handler) 51 { 52 return InternalAccessorBit::Get(handler); 53 } 54 IsNonExist(uint32_t handler)55 static inline bool IsNonExist(uint32_t handler) 56 { 57 return GetKind(handler) == HandlerKind::NON_EXIST; 58 } 59 IsField(uint32_t handler)60 static inline bool IsField(uint32_t handler) 61 { 62 return GetKind(handler) == HandlerKind::FIELD; 63 } 64 IsElement(uint32_t handler)65 static inline bool IsElement(uint32_t handler) 66 { 67 return GetKind(handler) == HandlerKind::ELEMENT; 68 } 69 IsDictionary(uint32_t handler)70 static inline bool IsDictionary(uint32_t handler) 71 { 72 return GetKind(handler) == HandlerKind::DICTIONARY; 73 } 74 IsInlinedProps(uint32_t handler)75 static inline bool IsInlinedProps(uint32_t handler) 76 { 77 return InlinedPropsBit::Get(handler); 78 } 79 GetKind(uint32_t handler)80 static inline HandlerKind GetKind(uint32_t handler) 81 { 82 return KindBit::Get(handler); 83 } 84 IsJSArray(uint32_t handler)85 static inline bool IsJSArray(uint32_t handler) 86 { 87 return IsJSArrayBit::Get(handler); 88 } 89 GetOffset(uint32_t handler)90 static inline int GetOffset(uint32_t handler) 91 { 92 return OffsetBit::Get(handler); 93 } 94 }; 95 96 class LoadHandler final : public HandlerBase { 97 public: 98 static inline JSHandle<JSTaggedValue> LoadProperty(const JSThread *thread, const ObjectOperator &op); 99 static inline JSHandle<JSTaggedValue> LoadElement(const JSThread *thread); 100 }; 101 102 class StoreHandler final : public HandlerBase { 103 public: 104 static inline JSHandle<JSTaggedValue> StoreProperty(const JSThread *thread, const ObjectOperator &op); 105 static inline JSHandle<JSTaggedValue> StoreElement(const JSThread *thread, 106 JSHandle<JSTaggedValue> receiver); 107 }; 108 109 class TransitionHandler : public TaggedObject { 110 public: Cast(TaggedObject * object)111 static TransitionHandler *Cast(TaggedObject *object) 112 { 113 ASSERT(JSTaggedValue(object).IsTransitionHandler()); 114 return static_cast<TransitionHandler *>(object); 115 } 116 117 static inline JSHandle<JSTaggedValue> StoreTransition(const JSThread *thread, const ObjectOperator &op); 118 119 static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize(); 120 ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, TRANSITION_HCLASS_OFFSET) 121 122 ACCESSORS(TransitionHClass, TRANSITION_HCLASS_OFFSET, SIZE) 123 124 DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE) 125 DECL_DUMP() 126 }; 127 128 class PrototypeHandler : public TaggedObject { 129 public: Cast(TaggedObject * object)130 static PrototypeHandler *Cast(TaggedObject *object) 131 { 132 ASSERT(JSTaggedValue(object).IsPrototypeHandler()); 133 return static_cast<PrototypeHandler *>(object); 134 } 135 136 static inline JSHandle<JSTaggedValue> LoadPrototype(const JSThread *thread, const ObjectOperator &op, 137 const JSHandle<JSHClass> &hclass); 138 static inline JSHandle<JSTaggedValue> StorePrototype(const JSThread *thread, const ObjectOperator &op, 139 const JSHandle<JSHClass> &hclass); 140 141 static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize(); 142 143 ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, PROTO_CELL_OFFSET) 144 145 ACCESSORS(ProtoCell, PROTO_CELL_OFFSET, HOLDER_OFFSET) 146 147 ACCESSORS(Holder, HOLDER_OFFSET, SIZE) 148 149 DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE) 150 DECL_DUMP() 151 }; 152 } // namespace panda::ecmascript 153 #endif // ECMASCRIPT_IC_IC_HANDLER_H 154