1 /* 2 * Copyright (c) 2022 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_COMPILER_BUILTINS_LINKED_HASHTABLE_STUB_BUILDER_H 17 #define ECMASCRIPT_COMPILER_BUILTINS_LINKED_HASHTABLE_STUB_BUILDER_H 18 #include "ecmascript/compiler/stub_builder-inl.h" 19 20 namespace panda::ecmascript::kungfu { 21 22 template<typename LinkedHashTableType, typename LinkedHashTableObject> 23 class LinkedHashTableStubBuilder : public StubBuilder { 24 public: LinkedHashTableStubBuilder(StubBuilder * parent,GateRef glue)25 explicit LinkedHashTableStubBuilder(StubBuilder *parent, GateRef glue) 26 : StubBuilder(parent), glue_(glue) {} 27 ~LinkedHashTableStubBuilder() override = default; 28 NO_MOVE_SEMANTIC(LinkedHashTableStubBuilder); 29 NO_COPY_SEMANTIC(LinkedHashTableStubBuilder); GenerateCircuit()30 void GenerateCircuit() override {} 31 32 GateRef Create(GateRef numberOfElements); 33 GateRef Clear(GateRef linkedTable); 34 GateRef ForEach(GateRef thisValue, GateRef linkedTable, GateRef callbackFnHandle, GateRef thisArg); 35 GateRef Insert(GateRef linkedTable, GateRef key, GateRef value); 36 GateRef Delete(GateRef linkedTable, GateRef key); 37 GateRef Has(GateRef linkedTable, GateRef key); 38 GateRef Get(GateRef linkedTable, GateRef key); 39 40 void GenMapSetConstructor(GateRef nativeCode, GateRef func, GateRef newTarget, GateRef thisValue, GateRef numArgs, 41 GateRef arg0, GateRef argv); 42 43 GateRef GetLinked(GateRef jsThis); 44 45 void SetLinked(GateRef jsThis, GateRef newTable); 46 47 private: 48 template <typename IteratorType> 49 friend class BuiltinsCollectionIteratorStubBuilder; 50 IsKey(GateRef key)51 GateRef IsKey(GateRef key) 52 { 53 return TaggedIsNotHole(key); 54 } 55 HashToBucket(GateRef linkedTable,GateRef hash)56 GateRef HashToBucket(GateRef linkedTable, GateRef hash) 57 { 58 GateRef cap = GetCapacity(linkedTable); 59 return Int32And(hash, Int32Sub(cap, Int32(1))); 60 } 61 BucketToIndex(GateRef bucket)62 GateRef BucketToIndex(GateRef bucket) 63 { 64 return Int32Add(bucket, Int32(LinkedHashTableType::ELEMENTS_START_INDEX)); 65 } 66 67 GateRef HashObjectIsMatch(GateRef key, GateRef other); 68 GateRef FindElement(GateRef linkedTable, GateRef key, GateRef hash); GetKey(GateRef linkedTable,GateRef entry)69 GateRef GetKey(GateRef linkedTable, GateRef entry) 70 { 71 GateRef index = EntryToIndex(linkedTable, entry); 72 return GetElement(linkedTable, index); 73 } 74 SetKey(GateRef linkedTable,GateRef entry,GateRef key)75 void SetKey(GateRef linkedTable, GateRef entry, GateRef key) 76 { 77 GateRef index = EntryToIndex(linkedTable, entry); 78 SetElement(linkedTable, index, key); 79 } 80 GetValue(GateRef linkedTable,GateRef entry)81 GateRef GetValue(GateRef linkedTable, GateRef entry) 82 { 83 GateRef index = EntryToIndex(linkedTable, entry); 84 GateRef valueIndex = Int32(LinkedHashTableObject::ENTRY_VALUE_INDEX); 85 return GetElement(linkedTable, Int32Add(index, valueIndex)); 86 } 87 SetValue(GateRef linkedTable,GateRef entry,GateRef value)88 void SetValue(GateRef linkedTable, GateRef entry, GateRef value) 89 { 90 GateRef index = EntryToIndex(linkedTable, entry); 91 GateRef valueIndex = Int32(LinkedHashTableObject::ENTRY_VALUE_INDEX); 92 SetElement(linkedTable, Int32Add(index, valueIndex), value); 93 } 94 EntryToIndex(GateRef linkedTable,GateRef entry)95 GateRef EntryToIndex(GateRef linkedTable, GateRef entry) 96 { 97 int32_t startIndex = LinkedHashTableType::ELEMENTS_START_INDEX; 98 int32_t entrySize = LinkedHashTableObject::ENTRY_SIZE; 99 GateRef sumEntrySize = Int32Mul(entry, Int32Add(Int32(entrySize), Int32(1))); 100 return Int32Add(Int32(startIndex), Int32Add(GetCapacity(linkedTable), sumEntrySize)); 101 } 102 GetElement(GateRef linkedTable,GateRef index)103 GateRef GetElement(GateRef linkedTable, GateRef index) 104 { 105 return GetValueFromTaggedArray(linkedTable, index); 106 } 107 SetElement(GateRef linkedTable,GateRef index,GateRef value)108 void SetElement(GateRef linkedTable, GateRef index, GateRef value) 109 { 110 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, linkedTable, index, value); 111 } 112 GetDeletedNum(GateRef linkedTable,GateRef entry)113 GateRef GetDeletedNum(GateRef linkedTable, GateRef entry) 114 { 115 return TaggedGetInt(GetNextEntry(linkedTable, entry)); 116 } 117 SetDeletedNum(GateRef linkedTable,GateRef entry,GateRef num)118 void SetDeletedNum(GateRef linkedTable, GateRef entry, GateRef num) 119 { 120 SetNextEntry(linkedTable, entry, IntToTaggedInt(num)); 121 } 122 GetNextEntry(GateRef linkedTable,GateRef entry)123 GateRef GetNextEntry(GateRef linkedTable, GateRef entry) 124 { 125 GateRef entryIndex = EntryToIndex(linkedTable, entry); 126 return GetElement(linkedTable, Int32Add(entryIndex, Int32(LinkedHashTableObject::ENTRY_SIZE))); 127 } 128 SetNextEntry(GateRef linkedTable,GateRef entry,GateRef nextEntry)129 void SetNextEntry(GateRef linkedTable, GateRef entry, GateRef nextEntry) 130 { 131 GateRef entryIndex = EntryToIndex(linkedTable, entry); 132 SetElement(linkedTable, Int32Add(entryIndex, Int32(LinkedHashTableObject::ENTRY_SIZE)), nextEntry); 133 } 134 GetCapacity(GateRef linkedTable)135 GateRef GetCapacity(GateRef linkedTable) 136 { 137 GateRef capacityIndex = Int32(LinkedHashTableType::CAPACITY_INDEX); 138 GateRef capacity = GetValueFromTaggedArray(linkedTable, capacityIndex); 139 return TaggedGetInt(capacity); 140 } 141 SetCapacity(GateRef linkedTable,GateRef numberOfElements)142 void SetCapacity(GateRef linkedTable, GateRef numberOfElements) 143 { 144 GateRef capacityIndex = Int32(LinkedHashTableType::CAPACITY_INDEX); 145 SetValueToTaggedArray(VariableType::JS_NOT_POINTER(), glue_, linkedTable, capacityIndex, 146 IntToTaggedInt(numberOfElements)); 147 } 148 GetNumberOfElements(GateRef linkedTable)149 GateRef GetNumberOfElements(GateRef linkedTable) 150 { 151 int32_t elementsIndex = LinkedHashTableType::NUMBER_OF_ELEMENTS_INDEX; 152 GateRef tmpNumberOfElements = GetValueFromTaggedArray(linkedTable, Int32(elementsIndex)); 153 return TaggedGetInt(tmpNumberOfElements); 154 } 155 SetNumberOfElements(GateRef linkedTable,GateRef num)156 void SetNumberOfElements(GateRef linkedTable, GateRef num) 157 { 158 int32_t elementsIndex = LinkedHashTableType::NUMBER_OF_ELEMENTS_INDEX; 159 SetValueToTaggedArray(VariableType::JS_NOT_POINTER(), glue_, linkedTable, Int32(elementsIndex), 160 IntToTaggedInt(num)); 161 } 162 GetNumberOfDeletedElements(GateRef linkedTable)163 GateRef GetNumberOfDeletedElements(GateRef linkedTable) 164 { 165 GateRef deletedIndex = Int32(LinkedHashTableType::NUMBER_OF_DELETED_ELEMENTS_INDEX); 166 GateRef tmpNumberOfDeletedElements = GetValueFromTaggedArray(linkedTable, deletedIndex); 167 return TaggedGetInt(tmpNumberOfDeletedElements); 168 } 169 SetNumberOfDeletedElements(GateRef linkedTable,GateRef num)170 void SetNumberOfDeletedElements(GateRef linkedTable, GateRef num) 171 { 172 GateRef deletedIndex = Int32(LinkedHashTableType::NUMBER_OF_DELETED_ELEMENTS_INDEX); 173 SetValueToTaggedArray(VariableType::JS_NOT_POINTER(), glue_, linkedTable, deletedIndex, IntToTaggedInt(num)); 174 } 175 GetNextTable(GateRef linkedTable)176 GateRef GetNextTable(GateRef linkedTable) 177 { 178 GateRef nextTableIndex = Int32(LinkedHashTableType::NEXT_TABLE_INDEX); 179 return GetValueFromTaggedArray(linkedTable, nextTableIndex); 180 } 181 SetNextTable(GateRef linkedTable,GateRef nexTable)182 void SetNextTable(GateRef linkedTable, GateRef nexTable) 183 { 184 GateRef nextTableIndex = Int32(LinkedHashTableType::NEXT_TABLE_INDEX); 185 SetValueToTaggedArray(VariableType::JS_POINTER(), glue_, linkedTable, nextTableIndex, nexTable); 186 } 187 CalNewTaggedArrayLength(GateRef numberOfElements)188 GateRef CalNewTaggedArrayLength(GateRef numberOfElements) 189 { 190 GateRef startIndex = Int32(LinkedHashTableType::ELEMENTS_START_INDEX); 191 GateRef entrySize = Int32(LinkedHashTableObject::ENTRY_SIZE); 192 GateRef nEntrySize = Int32Mul(numberOfElements, Int32Add(entrySize, Int32(1))); 193 GateRef length = Int32Add(startIndex, Int32Add(numberOfElements, nEntrySize)); 194 return length; 195 } 196 InsertNewEntry(GateRef linkedTable,GateRef bucket,GateRef entry)197 void InsertNewEntry(GateRef linkedTable, GateRef bucket, GateRef entry) 198 { 199 GateRef bucketIndex = BucketToIndex(bucket); 200 GateRef previousEntry = GetElement(linkedTable, bucketIndex); 201 SetNextEntry(linkedTable, entry, previousEntry); 202 SetElement(linkedTable, bucketIndex, IntToTaggedInt(entry)); 203 } 204 205 GateRef GetDeletedElementsAt(GateRef linkedTable, GateRef entry); 206 GateRef GrowCapacity(GateRef linkedTable, GateRef numberOfAddedElements); 207 GateRef HasSufficientCapacity(GateRef linkedTable, GateRef numOfAddElements); 208 void Rehash(GateRef linkedTable, GateRef newTable); 209 GateRef ComputeCapacity(GateRef atLeastSpaceFor); 210 void RemoveEntry(GateRef linkedTable, GateRef entry); 211 void StoreHashTableToNewObject(GateRef newTargetHClass, Variable& returnValue); 212 GateRef GetLinkedOffset(); 213 214 GateRef glue_; 215 }; 216 } // namespace panda::ecmascript::kungfu 217 #endif // ECMASCRIPT_COMPILER_BUILTINS_LINKED_HASHTABLE_STUB_BUILDER_H 218