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: IsKey(GateRef key)48 GateRef IsKey(GateRef key) 49 { 50 return TaggedIsNotHole(key); 51 } 52 HashToBucket(GateRef linkedTable,GateRef hash)53 GateRef HashToBucket(GateRef linkedTable, GateRef hash) 54 { 55 GateRef cap = GetCapacity(linkedTable); 56 return Int32And(hash, Int32Sub(cap, Int32(1))); 57 } 58 BucketToIndex(GateRef bucket)59 GateRef BucketToIndex(GateRef bucket) 60 { 61 return Int32Add(bucket, Int32(LinkedHashTableType::ELEMENTS_START_INDEX)); 62 } 63 64 GateRef HashObjectIsMatch(GateRef key, GateRef other); 65 GateRef FindElement(GateRef linkedTable, GateRef key, GateRef hash); GetKey(GateRef linkedTable,GateRef entry)66 GateRef GetKey(GateRef linkedTable, GateRef entry) 67 { 68 GateRef index = EntryToIndex(linkedTable, entry); 69 return GetElement(linkedTable, index); 70 } 71 SetKey(GateRef linkedTable,GateRef entry,GateRef key)72 void SetKey(GateRef linkedTable, GateRef entry, GateRef key) 73 { 74 GateRef index = EntryToIndex(linkedTable, entry); 75 SetElement(linkedTable, index, key); 76 } 77 GetValue(GateRef linkedTable,GateRef entry)78 GateRef GetValue(GateRef linkedTable, GateRef entry) 79 { 80 GateRef index = EntryToIndex(linkedTable, entry); 81 GateRef valueIndex = Int32(LinkedHashTableObject::ENTRY_VALUE_INDEX); 82 return GetElement(linkedTable, Int32Add(index, valueIndex)); 83 } 84 SetValue(GateRef linkedTable,GateRef entry,GateRef value)85 void SetValue(GateRef linkedTable, GateRef entry, GateRef value) 86 { 87 GateRef index = EntryToIndex(linkedTable, entry); 88 GateRef valueIndex = Int32(LinkedHashTableObject::ENTRY_VALUE_INDEX); 89 SetElement(linkedTable, Int32Add(index, valueIndex), value); 90 } 91 EntryToIndex(GateRef linkedTable,GateRef entry)92 GateRef EntryToIndex(GateRef linkedTable, GateRef entry) 93 { 94 int32_t startIndex = LinkedHashTableType::ELEMENTS_START_INDEX; 95 int32_t entrySize = LinkedHashTableObject::ENTRY_SIZE; 96 GateRef sumEntrySize = Int32Mul(entry, Int32Add(Int32(entrySize), Int32(1))); 97 return Int32Add(Int32(startIndex), Int32Add(GetCapacity(linkedTable), sumEntrySize)); 98 } 99 GetElement(GateRef linkedTable,GateRef index)100 GateRef GetElement(GateRef linkedTable, GateRef index) 101 { 102 return GetValueFromTaggedArray(linkedTable, index); 103 } 104 SetElement(GateRef linkedTable,GateRef index,GateRef value)105 void SetElement(GateRef linkedTable, GateRef index, GateRef value) 106 { 107 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, linkedTable, index, value); 108 } 109 GetDeletedNum(GateRef linkedTable,GateRef entry)110 GateRef GetDeletedNum(GateRef linkedTable, GateRef entry) 111 { 112 return TaggedGetInt(GetNextEntry(linkedTable, entry)); 113 } 114 SetDeletedNum(GateRef linkedTable,GateRef entry,GateRef num)115 void SetDeletedNum(GateRef linkedTable, GateRef entry, GateRef num) 116 { 117 SetNextEntry(linkedTable, entry, IntToTaggedInt(num)); 118 } 119 GetNextEntry(GateRef linkedTable,GateRef entry)120 GateRef GetNextEntry(GateRef linkedTable, GateRef entry) 121 { 122 GateRef entryIndex = EntryToIndex(linkedTable, entry); 123 return GetElement(linkedTable, Int32Add(entryIndex, Int32(LinkedHashTableObject::ENTRY_SIZE))); 124 } 125 SetNextEntry(GateRef linkedTable,GateRef entry,GateRef nextEntry)126 void SetNextEntry(GateRef linkedTable, GateRef entry, GateRef nextEntry) 127 { 128 GateRef entryIndex = EntryToIndex(linkedTable, entry); 129 SetElement(linkedTable, Int32Add(entryIndex, Int32(LinkedHashTableObject::ENTRY_SIZE)), nextEntry); 130 } 131 GetCapacity(GateRef linkedTable)132 GateRef GetCapacity(GateRef linkedTable) 133 { 134 GateRef capacityIndex = Int32(LinkedHashTableType::CAPACITY_INDEX); 135 GateRef capacity = GetValueFromTaggedArray(linkedTable, capacityIndex); 136 return TaggedGetInt(capacity); 137 } 138 SetCapacity(GateRef linkedTable,GateRef numberOfElements)139 void SetCapacity(GateRef linkedTable, GateRef numberOfElements) 140 { 141 GateRef capacityIndex = Int32(LinkedHashTableType::CAPACITY_INDEX); 142 SetValueToTaggedArray(VariableType::JS_NOT_POINTER(), glue_, linkedTable, capacityIndex, 143 IntToTaggedInt(numberOfElements)); 144 } 145 GetNumberOfElements(GateRef linkedTable)146 GateRef GetNumberOfElements(GateRef linkedTable) 147 { 148 int32_t elementsIndex = LinkedHashTableType::NUMBER_OF_ELEMENTS_INDEX; 149 GateRef tmpNumberOfElements = GetValueFromTaggedArray(linkedTable, Int32(elementsIndex)); 150 return TaggedGetInt(tmpNumberOfElements); 151 } 152 SetNumberOfElements(GateRef linkedTable,GateRef num)153 void SetNumberOfElements(GateRef linkedTable, GateRef num) 154 { 155 int32_t elementsIndex = LinkedHashTableType::NUMBER_OF_ELEMENTS_INDEX; 156 SetValueToTaggedArray(VariableType::JS_NOT_POINTER(), glue_, linkedTable, Int32(elementsIndex), 157 IntToTaggedInt(num)); 158 } 159 GetNumberOfDeletedElements(GateRef linkedTable)160 GateRef GetNumberOfDeletedElements(GateRef linkedTable) 161 { 162 GateRef deletedIndex = Int32(LinkedHashTableType::NUMBER_OF_DELETED_ELEMENTS_INDEX); 163 GateRef tmpNumberOfDeletedElements = GetValueFromTaggedArray(linkedTable, deletedIndex); 164 return TaggedGetInt(tmpNumberOfDeletedElements); 165 } 166 SetNumberOfDeletedElements(GateRef linkedTable,GateRef num)167 void SetNumberOfDeletedElements(GateRef linkedTable, GateRef num) 168 { 169 GateRef deletedIndex = Int32(LinkedHashTableType::NUMBER_OF_DELETED_ELEMENTS_INDEX); 170 SetValueToTaggedArray(VariableType::JS_NOT_POINTER(), glue_, linkedTable, deletedIndex, IntToTaggedInt(num)); 171 } 172 GetNextTable(GateRef linkedTable)173 GateRef GetNextTable(GateRef linkedTable) 174 { 175 GateRef nextTableIndex = Int32(LinkedHashTableType::NEXT_TABLE_INDEX); 176 return GetValueFromTaggedArray(linkedTable, nextTableIndex); 177 } 178 SetNextTable(GateRef linkedTable,GateRef nexTable)179 void SetNextTable(GateRef linkedTable, GateRef nexTable) 180 { 181 GateRef nextTableIndex = Int32(LinkedHashTableType::NEXT_TABLE_INDEX); 182 SetValueToTaggedArray(VariableType::JS_POINTER(), glue_, linkedTable, nextTableIndex, nexTable); 183 } 184 CalNewTaggedArrayLength(GateRef numberOfElements)185 GateRef CalNewTaggedArrayLength(GateRef numberOfElements) 186 { 187 GateRef startIndex = Int32(LinkedHashTableType::ELEMENTS_START_INDEX); 188 GateRef entrySize = Int32(LinkedHashTableObject::ENTRY_SIZE); 189 GateRef nEntrySize = Int32Mul(numberOfElements, Int32Add(entrySize, Int32(1))); 190 GateRef length = Int32Add(startIndex, Int32Add(numberOfElements, nEntrySize)); 191 return length; 192 } 193 InsertNewEntry(GateRef linkedTable,GateRef bucket,GateRef entry)194 void InsertNewEntry(GateRef linkedTable, GateRef bucket, GateRef entry) 195 { 196 GateRef bucketIndex = BucketToIndex(bucket); 197 GateRef previousEntry = GetElement(linkedTable, bucketIndex); 198 SetNextEntry(linkedTable, entry, previousEntry); 199 SetElement(linkedTable, bucketIndex, IntToTaggedInt(entry)); 200 } 201 202 GateRef GetDeletedElementsAt(GateRef linkedTable, GateRef entry); 203 GateRef GrowCapacity(GateRef linkedTable, GateRef numberOfAddedElements); 204 GateRef HasSufficientCapacity(GateRef linkedTable, GateRef numOfAddElements); 205 void Rehash(GateRef linkedTable, GateRef newTable); 206 GateRef ComputeCapacity(GateRef atLeastSpaceFor); 207 void RemoveEntry(GateRef linkedTable, GateRef entry); 208 void StoreHashTableToNewObject(GateRef newTargetHClass, Variable& returnValue); 209 GateRef GetLinkedOffset(); 210 211 GateRef glue_; 212 }; 213 } // namespace panda::ecmascript::kungfu 214 #endif // ECMASCRIPT_COMPILER_BUILTINS_LINKED_HASHTABLE_STUB_BUILDER_H 215