1 /* 2 * Copyright (c) 2021-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_IC_PROPERTIES_CACHE_H 17 #define ECMASCRIPT_IC_PROPERTIES_CACHE_H 18 19 #include <array> 20 21 #include "ecmascript/js_hclass.h" 22 #include "ecmascript/js_tagged_value.h" 23 #include "ecmascript/js_tagged_value-inl.h" 24 #include "ecmascript/ecma_macros.h" 25 26 namespace panda::ecmascript { 27 class EcmaVM; 28 class PropertiesCache { 29 public: Get(JSHClass *jsHclass, JSTaggedValue key)30 inline int Get(JSHClass *jsHclass, JSTaggedValue key) 31 { 32 int hash = Hash(jsHclass, key); 33 PropertyKey &prop = keys_[hash]; 34 if ((prop.hclass_ == jsHclass) && (prop.key_ == key)) { 35 return keys_[hash].results_; 36 } 37 return NOT_FOUND; 38 } Set(JSHClass *jsHclass, JSTaggedValue key, int index)39 inline void Set(JSHClass *jsHclass, JSTaggedValue key, int index) 40 { 41 int hash = Hash(jsHclass, key); 42 PropertyKey &prop = keys_[hash]; 43 prop.hclass_ = jsHclass; 44 prop.key_ = key; 45 keys_[hash].results_ = index; 46 } Clear()47 inline void Clear() 48 { 49 for (auto &key : keys_) { 50 key.hclass_ = nullptr; 51 key.key_ = JSTaggedValue::Hole(); 52 } 53 } IsCleared() const54 inline bool IsCleared() const 55 { 56 for (auto &key : keys_) { 57 if (key.hclass_ != nullptr) { 58 return false; 59 } 60 } 61 return true; 62 } 63 static const int NOT_FOUND = -1; 64 static const uint32_t CACHE_LENGTH_BIT = 10; 65 static const uint32_t CACHE_LENGTH = (1U << CACHE_LENGTH_BIT); 66 static const uint32_t CACHE_LENGTH_MASK = CACHE_LENGTH - 1; 67 68 struct PropertyKey : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 69 base::AlignedPointer, 70 JSTaggedValue, 71 base::AlignedUint32> { 72 enum class Index : size_t { 73 HclassIndex = 0, 74 KeyIndex, 75 ResultsIndex, 76 NumOfMembers 77 }; GetHclassOffsetpanda::ecmascript::PropertiesCache::PropertyKey78 static size_t GetHclassOffset(bool isArch32 = false) 79 { 80 return GetOffset<static_cast<size_t>(Index::HclassIndex)>(isArch32); 81 } 82 GetKeyOffsetpanda::ecmascript::PropertiesCache::PropertyKey83 static size_t GetKeyOffset(bool isArch32 = false) 84 { 85 return GetOffset<static_cast<size_t>(Index::KeyIndex)>(isArch32); 86 } 87 GetResultsOffsetpanda::ecmascript::PropertiesCache::PropertyKey88 static size_t GetResultsOffset(bool isArch32 = false) 89 { 90 return GetOffset<static_cast<size_t>(Index::ResultsIndex)>(isArch32); 91 } 92 GetPropertyKeySizepanda::ecmascript::PropertiesCache::PropertyKey93 static size_t GetPropertyKeySize() 94 { 95 return static_cast<size_t>(Index::NumOfMembers) * static_cast<size_t>(JSTaggedValue::TaggedTypeSize()); 96 } 97 98 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 99 alignas(EAS) JSHClass *hclass_ {nullptr}; 100 alignas(EAS) JSTaggedValue key_ {JSTaggedValue::Hole()}; 101 alignas(EAS) int results_ {NOT_FOUND}; 102 }; 103 104 private: PropertiesCache()105 PropertiesCache() 106 { 107 for (uint32_t i = 0; i < CACHE_LENGTH; ++i) { 108 keys_[i].hclass_ = nullptr; 109 keys_[i].key_ = JSTaggedValue::Hole(); 110 keys_[i].results_ = NOT_FOUND; 111 } 112 } 113 ~PropertiesCache() = default; 114 115 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 116 Hash(JSHClass *cls, JSTaggedValue key)117 static inline int Hash(JSHClass *cls, JSTaggedValue key) 118 { 119 uint32_t clsHash = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(cls)) >> 3U; // skip 8bytes 120 uint32_t keyHash = key.GetKeyHashCode(); 121 return static_cast<int>((clsHash ^ keyHash) & CACHE_LENGTH_MASK); 122 } 123 124 std::array<PropertyKey, CACHE_LENGTH> keys_{}; 125 126 friend class EcmaContext; 127 }; 128 } // namespace panda::ecmascript 129 #endif // ECMASCRIPT_IC_PROPERTIES_CACHE_H 130