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 void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; Dump()88 void Dump() const DUMP_API_ATTR 89 { 90 Dump(std::cout); 91 } 92 void DumpForSnapshot(std::vector<Reference> &vec) const; 93 94 static constexpr int ENTRY_KEY_INDEX = 0; 95 static constexpr int ENTRY_VALUE_INDEX = 1; 96 static constexpr int ENTRY_DETAILS_INDEX = 2; 97 static constexpr int ENTRY_SIZE = 3; 98 }; 99 100 class NumberDictionary : public OrderTaggedHashTable<NumberDictionary> { 101 public: 102 using OrderHashTableT = OrderTaggedHashTable<NumberDictionary>; GetKeyIndex(int entry)103 inline static int GetKeyIndex(int entry) 104 { 105 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX; 106 } GetValueIndex(int entry)107 inline static int GetValueIndex(int entry) 108 { 109 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX; 110 } GetEntryIndex(int entry)111 inline static int GetEntryIndex(int entry) 112 { 113 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize(); 114 } GetEntrySize()115 inline static int GetEntrySize() 116 { 117 return ENTRY_SIZE; 118 } 119 static int PUBLIC_API Hash(const JSTaggedValue &key); 120 static bool PUBLIC_API IsMatch(const JSTaggedValue &key, const JSTaggedValue &other); 121 static JSHandle<NumberDictionary> Create(const JSThread *thread, 122 int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 123 static JSHandle<NumberDictionary> CreateInSharedHeap( 124 const JSThread *thread, int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 125 // Returns the property metaData for the property at entry. 126 PropertyAttributes PUBLIC_API GetAttributes(int entry) const; 127 void SetAttributes(const JSThread *thread, int entry, const PropertyAttributes &metaData); 128 void SetEntry([[maybe_unused]] const JSThread *thread, int entry, const JSTaggedValue &key, 129 const JSTaggedValue &value, const PropertyAttributes &metaData); 130 void UpdateValueAndAttributes(const JSThread *thread, int entry, const JSTaggedValue &value, 131 const PropertyAttributes &metaData); 132 void PUBLIC_API UpdateValue(const JSThread *thread, int entry, const JSTaggedValue &value); 133 void UpdateAttributes(int entry, const PropertyAttributes &metaData); 134 void ClearEntry(const JSThread *thread, int entry); 135 136 static void GetAllKeys(const JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset, 137 const JSHandle<TaggedArray> &keyArray); 138 static void GetAllKeysByFilter(const JSThread *thread, const JSHandle<NumberDictionary> &obj, 139 uint32_t &keyArrayEffectivelength, const JSHandle<TaggedArray> &keyArray, uint32_t filter); 140 static void GetAllEnumKeys(JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset, 141 const JSHandle<TaggedArray> &keyArray, uint32_t *keys, int32_t lastLength = -1); CompKey(const JSTaggedValue & a,const JSTaggedValue & b)142 static inline bool CompKey(const JSTaggedValue &a, const JSTaggedValue &b) 143 { 144 ASSERT(a.IsNumber() && b.IsNumber()); 145 return a.GetNumber() < b.GetNumber(); 146 } 147 void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; Dump()148 void Dump() const DUMP_API_ATTR 149 { 150 Dump(std::cout); 151 } 152 void DumpForSnapshot(std::vector<Reference> &vec) const; 153 154 static constexpr int ENTRY_KEY_INDEX = 0; 155 static constexpr int ENTRY_VALUE_INDEX = 1; 156 static constexpr int ENTRY_DETAILS_INDEX = 2; 157 static constexpr int ENTRY_SIZE = 3; 158 }; 159 160 class PointerToIndexDictionary : public OrderTaggedHashTable<PointerToIndexDictionary> { 161 public: 162 using OrderHashTableT = OrderTaggedHashTable<PointerToIndexDictionary>; GetKeyIndex(int entry)163 inline static int GetKeyIndex(int entry) 164 { 165 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX; 166 } 167 GetValueIndex(int entry)168 inline static int GetValueIndex(int entry) 169 { 170 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX; 171 } 172 GetEntryIndex(int entry)173 inline static int GetEntryIndex(int entry) 174 { 175 return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize(); 176 } 177 GetEntrySize()178 inline static int GetEntrySize() 179 { 180 return ENTRY_SIZE; 181 } 182 SetEntry(const JSThread * thread,int entry,const JSTaggedValue & key,const JSTaggedValue & value)183 inline void SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value) 184 { 185 SetKey(thread, entry, key); 186 SetValue(thread, entry, value); 187 } 188 Hash(const JSTaggedValue & key)189 static int32_t Hash(const JSTaggedValue &key) 190 { 191 return static_cast<int32_t>(key.GetRawData()); 192 } 193 IsMatch(const JSTaggedValue & key,const JSTaggedValue & other)194 static bool IsMatch(const JSTaggedValue &key, const JSTaggedValue &other) 195 { 196 return key == other; 197 } 198 static JSHandle<PointerToIndexDictionary> Create(const JSThread *thread, 199 int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER); 200 static JSHandle<PointerToIndexDictionary> PutIfAbsent( 201 const JSThread *thread, const JSHandle<PointerToIndexDictionary> &dictionary, 202 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 203 204 // DECL_DUMP() 205 206 static constexpr int ENTRY_KEY_INDEX = 0; 207 static constexpr int ENTRY_VALUE_INDEX = 1; 208 static constexpr int ENTRY_SIZE = 2; 209 }; 210 211 class FunctionProtoTransitionTable { 212 public: 213 explicit FunctionProtoTransitionTable(const JSThread *thread); 214 virtual ~FunctionProtoTransitionTable(); 215 216 void Iterate(RootVisitor &v); 217 218 void InsertTransitionItem(const JSThread *thread, 219 JSHandle<JSTaggedValue> ihc, 220 JSHandle<JSTaggedValue> baseIhc, 221 JSHandle<JSTaggedValue> transIhc, 222 JSHandle<JSTaggedValue> transPhc); 223 224 std::pair<JSTaggedValue, JSTaggedValue> FindTransitionByHClass(const JSThread *thread, 225 JSHandle<JSTaggedValue> ihc, 226 JSHandle<JSTaggedValue> baseIhc) const; 227 228 bool TryInsertFakeParentItem(JSTaggedType child, JSTaggedType parent); 229 JSTaggedType GetFakeParent(JSTaggedType child); 230 GetProtoTransitionTable()231 JSTaggedValue GetProtoTransitionTable() const 232 { 233 return protoTransitionTable_; 234 } 235 236 void UpdateProtoTransitionTable(const JSThread *thread, JSHandle<PointerToIndexDictionary> map); 237 238 class ProtoArray : public TaggedArray { 239 public: 240 CAST_CHECK(ProtoArray, IsTaggedArray); 241 242 static JSHandle<ProtoArray> Create(const JSThread *thread); 243 void SetEntry(const JSThread *thread, uint32_t index, JSTaggedValue key, JSTaggedValue transIhc, 244 JSTaggedValue transPhc); 245 JSTaggedValue GetKey(uint32_t index) const; 246 std::pair<JSTaggedValue, JSTaggedValue> GetTransition(uint32_t index) const; 247 int32_t FindEntry(JSTaggedValue key) const; 248 std::pair<JSTaggedValue, JSTaggedValue> FindTransition(JSTaggedValue key) const; 249 static bool GetEntry(JSHandle<JSHClass> hclass); 250 251 private: 252 static constexpr uint32_t ENTRY_NUMBER = 2; 253 static constexpr uint32_t INIT_ENTRY_INDEX = 0; 254 static constexpr uint32_t CLONED_ENTRY_INDEX = 1; 255 256 static constexpr uint32_t ENTRY_SIZE = 3; 257 static constexpr uint32_t KEY_INDEX = 0; 258 static constexpr uint32_t TRANS_IHC_INDEX = 1; 259 static constexpr uint32_t TRANS_PHC_INDEX = 2; 260 }; 261 262 private: 263 static constexpr uint32_t DEFAULT_FIRST_LEVEL_SIZE = 2; 264 // second level table: 265 // <PointerToIndexDictionary(n): 266 // [ihc, 267 // <ProtoArray(2): 268 // [base.ihc, 269 // (trans_ihc, trans_phc) 270 // ] 271 // [base.ihc(cloned), 272 // (trans_ihc, trans_phc) 273 // ] 274 // > 275 // ] 276 // ... 277 // > 278 JSTaggedValue protoTransitionTable_ {JSTaggedValue::Hole()}; 279 // hclasses after set prototype maps to hclasses before set prototype 280 CUnorderedMap<JSTaggedType, JSTaggedType> fakeParentMap_ {}; 281 // reverse fakeParentMap_ 282 CUnorderedMap<JSTaggedType, JSTaggedType> fakeChildMap_ {}; 283 Mutex fakeParentMutex_; 284 }; 285 } // namespace panda::ecmascript 286 #endif // ECMASCRIPT_NEW_DICTIONARY_H 287