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_TAGGED_DICTIONARY_H 17 #define ECMASCRIPT_TAGGED_DICTIONARY_H 18 19 #include "ecmascript/js_tagged_value-inl.h" 20 #include "ecmascript/platform/mutex.h" 21 #include "ecmascript/tagged_array-inl.h" 22 #include "ecmascript/tagged_hash_table.h" 23 24 namespace panda::ecmascript { 25 class NameDictionary : public OrderTaggedHashTable<NameDictionary> { 26 public: 27 using OrderHashTableT = OrderTaggedHashTable<NameDictionary>; GetKeyIndex(int entry)28 inline static int GetKeyIndex(int entry) 29 { 30 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX; 31 } GetValueIndex(int entry)32 inline static int GetValueIndex(int entry) 33 { 34 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX; 35 } GetEntryIndex(int entry)36 inline static int GetEntryIndex(int entry) 37 { 38 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize(); 39 } GetEntrySize()40 inline static int GetEntrySize() 41 { 42 return ENTRY_SIZE; 43 } 44 static int PUBLIC_API Hash(const JSTaggedValue &key); 45 static int Hash(const uint8_t* str, int strSize); 46 47 static bool PUBLIC_API IsMatch(const JSTaggedValue &key, const JSTaggedValue &other); 48 static bool IsMatch(const uint8_t* str, int size, const JSTaggedValue &other); 49 50 static JSHandle<NameDictionary> Create(const JSThread *thread, 51 int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 52 static JSHandle<NameDictionary> PUBLIC_API CreateInSharedHeap(const JSThread *thread, 53 int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 54 // Returns the property metaData for the property at entry. 55 PropertyAttributes PUBLIC_API GetAttributes(int entry) const; 56 void PUBLIC_API SetAttributes(const JSThread *thread, int entry, const PropertyAttributes &metaData); 57 void PUBLIC_API SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value, 58 const PropertyAttributes &metaData); 59 void UpdateValueAndAttributes(const JSThread *thread, int entry, const JSTaggedValue &value, 60 const PropertyAttributes &metaData); 61 void PUBLIC_API UpdateValue(const JSThread *thread, int entry, const JSTaggedValue &value); 62 void UpdateAttributes(int entry, const PropertyAttributes &metaData); 63 void UpdateAllAttributesToNoWitable(const JSThread *thread); 64 void ClearEntry(const JSThread *thread, int entry); 65 void GetAllKeys(const JSThread *thread, int offset, TaggedArray *keyArray) const; 66 void GetAllKeysByFilter(const JSThread *thread, uint32_t &keyArrayEffectivelength, 67 TaggedArray *keyArray, uint32_t filter) const; 68 std::pair<uint32_t, uint32_t> GetNumOfEnumKeys() const; 69 void GetAllEnumKeys(JSThread *thread, int offset, JSHandle<TaggedArray> keyArray, uint32_t *keys, 70 JSHandle<TaggedQueue> shadowQueue, int32_t lastLength) const; 71 void GetAllEnumKeys(JSThread *thread, int offset, JSHandle<TaggedArray> keyArray, uint32_t *keys) const; CompHandleKey(const std::pair<JSHandle<JSTaggedValue>,PropertyAttributes> & a,const std::pair<JSHandle<JSTaggedValue>,PropertyAttributes> & b)72 static inline bool CompHandleKey(const std::pair<JSHandle<JSTaggedValue>, PropertyAttributes> &a, 73 const std::pair<JSHandle<JSTaggedValue>, PropertyAttributes> &b) 74 { 75 return a.second.GetDictionaryOrder() < b.second.GetDictionaryOrder(); 76 } CompKey(const std::pair<JSTaggedValue,PropertyAttributes> & a,const std::pair<JSTaggedValue,PropertyAttributes> & b)77 static inline bool CompKey(const std::pair<JSTaggedValue, PropertyAttributes> &a, 78 const std::pair<JSTaggedValue, PropertyAttributes> &b) 79 { 80 return a.second.GetDictionaryOrder() < b.second.GetDictionaryOrder(); 81 } CompIndex(const PropertyAttributes & a,const PropertyAttributes & b)82 static inline bool CompIndex(const PropertyAttributes &a, 83 const PropertyAttributes &b) 84 { 85 return a.GetDictionaryOrder() < b.GetDictionaryOrder(); 86 } 87 DECL_DUMP() 88 89 static constexpr int ENTRY_KEY_INDEX = 0; 90 static constexpr int ENTRY_VALUE_INDEX = 1; 91 static constexpr int ENTRY_DETAILS_INDEX = 2; 92 static constexpr int ENTRY_SIZE = 3; 93 }; 94 95 class NumberDictionary : public OrderTaggedHashTable<NumberDictionary> { 96 public: 97 using OrderHashTableT = OrderTaggedHashTable<NumberDictionary>; GetKeyIndex(int entry)98 inline static int GetKeyIndex(int entry) 99 { 100 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX; 101 } GetValueIndex(int entry)102 inline static int GetValueIndex(int entry) 103 { 104 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX; 105 } GetEntryIndex(int entry)106 inline static int GetEntryIndex(int entry) 107 { 108 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize(); 109 } GetEntrySize()110 inline static int GetEntrySize() 111 { 112 return ENTRY_SIZE; 113 } 114 static int PUBLIC_API Hash(const JSTaggedValue &key); 115 static bool PUBLIC_API IsMatch(const JSTaggedValue &key, const JSTaggedValue &other); 116 static JSHandle<NumberDictionary> Create(const JSThread *thread, 117 int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 118 static JSHandle<NumberDictionary> CreateInSharedHeap( 119 const JSThread *thread, int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 120 // Returns the property metaData for the property at entry. 121 PropertyAttributes PUBLIC_API GetAttributes(int entry) const; 122 void SetAttributes(const JSThread *thread, int entry, const PropertyAttributes &metaData); 123 void SetEntry([[maybe_unused]] const JSThread *thread, int entry, const JSTaggedValue &key, 124 const JSTaggedValue &value, const PropertyAttributes &metaData); 125 void UpdateValueAndAttributes(const JSThread *thread, int entry, const JSTaggedValue &value, 126 const PropertyAttributes &metaData); 127 void PUBLIC_API UpdateValue(const JSThread *thread, int entry, const JSTaggedValue &value); 128 void UpdateAttributes(int entry, const PropertyAttributes &metaData); 129 void ClearEntry(const JSThread *thread, int entry); 130 131 static void GetAllKeys(const JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset, 132 const JSHandle<TaggedArray> &keyArray); 133 static void GetAllKeysByFilter(const JSThread *thread, const JSHandle<NumberDictionary> &obj, 134 uint32_t &keyArrayEffectivelength, const JSHandle<TaggedArray> &keyArray, uint32_t filter); 135 static void GetAllEnumKeys(JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset, 136 const JSHandle<TaggedArray> &keyArray, uint32_t *keys, int32_t lastLength = -1); CompKey(const JSTaggedValue & a,const JSTaggedValue & b)137 static inline bool CompKey(const JSTaggedValue &a, const JSTaggedValue &b) 138 { 139 ASSERT(a.IsNumber() && b.IsNumber()); 140 return a.GetNumber() < b.GetNumber(); 141 } 142 DECL_DUMP() 143 144 static constexpr int ENTRY_KEY_INDEX = 0; 145 static constexpr int ENTRY_VALUE_INDEX = 1; 146 static constexpr int ENTRY_DETAILS_INDEX = 2; 147 static constexpr int ENTRY_SIZE = 3; 148 }; 149 150 class PointerToIndexDictionary : public OrderTaggedHashTable<PointerToIndexDictionary> { 151 public: 152 using OrderHashTableT = OrderTaggedHashTable<PointerToIndexDictionary>; GetKeyIndex(int entry)153 inline static int GetKeyIndex(int entry) 154 { 155 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX; 156 } 157 GetValueIndex(int entry)158 inline static int GetValueIndex(int entry) 159 { 160 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX; 161 } 162 GetEntryIndex(int entry)163 inline static int GetEntryIndex(int entry) 164 { 165 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize(); 166 } 167 GetEntrySize()168 inline static int GetEntrySize() 169 { 170 return ENTRY_SIZE; 171 } 172 SetEntry(const JSThread * thread,int entry,const JSTaggedValue & key,const JSTaggedValue & value)173 inline void SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value) 174 { 175 SetKey(thread, entry, key); 176 SetValue(thread, entry, value); 177 } 178 Hash(const JSTaggedValue & key)179 static int32_t Hash(const JSTaggedValue &key) 180 { 181 return static_cast<int32_t>(key.GetRawData()); 182 } 183 IsMatch(const JSTaggedValue & key,const JSTaggedValue & other)184 static bool IsMatch(const JSTaggedValue &key, const JSTaggedValue &other) 185 { 186 return key == other; 187 } 188 static JSHandle<PointerToIndexDictionary> Create(const JSThread *thread, 189 int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 190 static JSHandle<PointerToIndexDictionary> PutIfAbsent( 191 const JSThread *thread, const JSHandle<PointerToIndexDictionary> &dictionary, 192 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 193 194 // DECL_DUMP() 195 196 static constexpr int ENTRY_KEY_INDEX = 0; 197 static constexpr int ENTRY_VALUE_INDEX = 1; 198 static constexpr int ENTRY_SIZE = 2; 199 }; 200 201 class FunctionProtoTransitionTable { 202 public: 203 explicit FunctionProtoTransitionTable(const JSThread *thread); 204 virtual ~FunctionProtoTransitionTable(); 205 206 void Iterate(const RootVisitor &v); 207 208 void InsertTransitionItem(const JSThread *thread, 209 JSHandle<JSTaggedValue> ihc, 210 JSHandle<JSTaggedValue> baseIhc, 211 JSHandle<JSTaggedValue> transIhc, 212 JSHandle<JSTaggedValue> transPhc); 213 214 std::pair<JSTaggedValue, JSTaggedValue> FindTransitionByHClass(const JSThread *thread, 215 JSHandle<JSTaggedValue> ihc, 216 JSHandle<JSTaggedValue> baseIhc) const; 217 218 bool TryInsertFakeParentItem(JSTaggedType child, JSTaggedType parent); 219 JSTaggedType GetFakeParent(JSTaggedType child); 220 GetProtoTransitionTable()221 JSTaggedValue GetProtoTransitionTable() const 222 { 223 return protoTransitionTable_; 224 } 225 226 void UpdateProtoTransitionTable(const JSThread *thread, JSHandle<PointerToIndexDictionary> map); 227 228 class ProtoArray : public TaggedArray { 229 public: 230 CAST_CHECK(ProtoArray, IsTaggedArray); 231 232 static JSHandle<ProtoArray> Create(const JSThread *thread); 233 void SetEntry(const JSThread *thread, uint32_t index, JSTaggedValue key, JSTaggedValue transIhc, 234 JSTaggedValue transPhc); 235 JSTaggedValue GetKey(uint32_t index) const; 236 std::pair<JSTaggedValue, JSTaggedValue> GetTransition(uint32_t index) const; 237 int32_t FindEntry(JSTaggedValue key) const; 238 std::pair<JSTaggedValue, JSTaggedValue> FindTransition(JSTaggedValue key) const; 239 static bool GetEntry(JSHandle<JSHClass> hclass); 240 241 private: 242 static constexpr uint32_t ENTRY_NUMBER = 2; 243 static constexpr uint32_t INIT_ENTRY_INDEX = 0; 244 static constexpr uint32_t CLONED_ENTRY_INDEX = 1; 245 246 static constexpr uint32_t ENTRY_SIZE = 3; 247 static constexpr uint32_t KEY_INDEX = 0; 248 static constexpr uint32_t TRANS_IHC_INDEX = 1; 249 static constexpr uint32_t TRANS_PHC_INDEX = 2; 250 }; 251 252 private: 253 static constexpr uint32_t DEFAULT_FIRST_LEVEL_SIZE = 2; 254 // second level table: 255 // <PointerToIndexDictionary(n): 256 // [ihc, 257 // <ProtoArray(2): 258 // [base.ihc, 259 // (trans_ihc, trans_phc) 260 // ] 261 // [base.ihc(cloned), 262 // (trans_ihc, trans_phc) 263 // ] 264 // > 265 // ] 266 // ... 267 // > 268 JSTaggedValue protoTransitionTable_ {JSTaggedValue::Hole()}; 269 // hclasses after set prototype maps to hclasses before set prototype 270 CUnorderedMap<JSTaggedType, JSTaggedType> fakeParentMap_ {}; 271 // reverse fakeParentMap_ 272 CUnorderedMap<JSTaggedType, JSTaggedType> fakeChildMap_ {}; 273 Mutex fakeParentMutex_; 274 }; 275 } // namespace panda::ecmascript 276 #endif // ECMASCRIPT_NEW_DICTIONARY_H 277