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_MEGA_IC_CACHE_H 17 #define ECMASCRIPT_IC_MEGA_IC_CACHE_H 18 19 #include <array> 20 21 #include "ecmascript/js_hclass.h" 22 #include "ecmascript/js_tagged_value.h" 23 #include "ecmascript/ecma_macros.h" 24 #include "ecmascript/log.h" 25 #include "ecmascript/log_wrapper.h" 26 #include "jsnapi_expo.h" 27 28 namespace panda::ecmascript { 29 class EcmaVM; 30 class MegaICCache { 31 public: 32 enum MegaICKind { 33 None, 34 Load, 35 Store, 36 }; Get(JSHClass * jsHclass,JSTaggedValue key)37 inline JSTaggedValue Get(JSHClass *jsHclass, JSTaggedValue key) 38 { 39 int hash = Hash(jsHclass, key); 40 PropertyKey &prop = keys_[hash]; 41 if ((prop.hclass_ == jsHclass) && (prop.key_ == key)) { 42 return keys_[hash].results_; 43 } 44 return NOT_FOUND; 45 } 46 void Set(JSHClass *jsHclass, JSTaggedValue key, JSTaggedValue handler, JSThread* thread); Clear()47 inline void Clear() 48 { 49 for (auto &key : keys_) { 50 key.hclass_ = nullptr; 51 key.key_ = JSTaggedValue::Hole(); 52 } 53 } IsCleared()54 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 Iterate(RootVisitor & v)64 void Iterate(RootVisitor &v) 65 { 66 for (auto &key : keys_) { 67 if (key.hclass_ != nullptr) { 68 auto value = JSTaggedValue::Cast(key.hclass_); 69 v.VisitRoot(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&(value)))); 70 } 71 v.VisitRoot(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&(key.key_)))); 72 v.VisitRoot(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&(key.results_)))); 73 } 74 } 75 constexpr static const JSTaggedValue NOT_FOUND = JSTaggedValue::Hole(); 76 static const uint32_t CACHE_LENGTH_BIT = 10; 77 static const uint32_t CACHE_LENGTH = (1U << CACHE_LENGTH_BIT); 78 static const uint32_t CACHE_LENGTH_MASK = CACHE_LENGTH - 1; 79 static const uint32_t HCLASS_SHIFT = 3; 80 struct PropertyKey : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 81 base::AlignedPointer, 82 JSTaggedValue, 83 JSTaggedValue> { 84 enum class Index : size_t { 85 HclassIndex = 0, 86 KeyIndex, 87 ResultsIndex, 88 NumOfMembers 89 }; 90 static size_t GetHclassOffset(bool isArch32 = false) 91 { 92 return GetOffset<static_cast<size_t>(Index::HclassIndex)>(isArch32); 93 } 94 95 static size_t GetKeyOffset(bool isArch32 = false) 96 { 97 return GetOffset<static_cast<size_t>(Index::KeyIndex)>(isArch32); 98 } 99 100 static size_t GetResultsOffset(bool isArch32 = false) 101 { 102 return GetOffset<static_cast<size_t>(Index::ResultsIndex)>(isArch32); 103 } 104 GetPropertyKeySizePropertyKey105 static size_t GetPropertyKeySize() 106 { 107 return static_cast<size_t>(Index::NumOfMembers) * static_cast<size_t>(JSTaggedValue::TaggedTypeSize()); 108 } 109 110 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 111 alignas(EAS) JSHClass *hclass_ {nullptr}; 112 alignas(EAS) JSTaggedValue key_ {JSTaggedValue::Hole()}; 113 alignas(EAS) JSTaggedValue results_ {JSTaggedValue::Hole()}; 114 }; 115 116 private: MegaICCache()117 MegaICCache() 118 { 119 for (uint32_t i = 0; i < CACHE_LENGTH; ++i) { 120 keys_[i].hclass_ = nullptr; 121 keys_[i].key_ = JSTaggedValue::Hole(); 122 keys_[i].results_ = NOT_FOUND; 123 } 124 } 125 ~MegaICCache() = default; 126 127 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) Hash(JSHClass * cls,JSTaggedValue key)128 static inline int Hash(JSHClass *cls, JSTaggedValue key) 129 { 130 uint32_t clsHash = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(cls)) >> HCLASS_SHIFT; // skip 8bytes 131 uint32_t keyHash = key.GetStringKeyHashCode(); 132 uint32_t hash = (clsHash * 31) ^ ((keyHash * 0x9e3779b9) ^ (keyHash >> 16)); 133 return static_cast<int>((hash) & CACHE_LENGTH_MASK); 134 } 135 PropertyKey keys_[CACHE_LENGTH]; 136 137 friend class EcmaContext; 138 }; 139 } // namespace panda::ecmascript 140 #endif // ECMASCRIPT_IC_MEGA_IC_CACHE_H 141