14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/builtins/linked_hashtable_stub_builder.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/compiler/builtins/builtins_stubs.h" 194514f5e3Sopenharmony_ci#include "ecmascript/compiler/call_stub_builder.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/hash_stub_builder.h" 214514f5e3Sopenharmony_ci#include "ecmascript/compiler/new_object_stub_builder.h" 224514f5e3Sopenharmony_ci#include "ecmascript/linked_hash_table.h" 234514f5e3Sopenharmony_ci#include "ecmascript/js_set.h" 244514f5e3Sopenharmony_ci#include "ecmascript/js_map.h" 254514f5e3Sopenharmony_ci 264514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 274514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 284514f5e3Sopenharmony_civoid LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Rehash( 294514f5e3Sopenharmony_ci GateRef linkedTable, GateRef newTable) 304514f5e3Sopenharmony_ci{ 314514f5e3Sopenharmony_ci auto env = GetEnvironment(); 324514f5e3Sopenharmony_ci Label entryLabel(env); 334514f5e3Sopenharmony_ci env->SubCfgEntry(&entryLabel); 344514f5e3Sopenharmony_ci 354514f5e3Sopenharmony_ci GateRef numberOfAllElements = Int32Add(GetNumberOfElements(linkedTable), 364514f5e3Sopenharmony_ci GetNumberOfDeletedElements(linkedTable)); 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_ci DEFVARIABLE(desEntry, VariableType::INT32(), Int32(0)); 394514f5e3Sopenharmony_ci DEFVARIABLE(currentDeletedElements, VariableType::INT32(), Int32(0)); 404514f5e3Sopenharmony_ci SetNextTable(linkedTable, newTable); 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ci Label loopHead(env); 434514f5e3Sopenharmony_ci Label loopEnd(env); 444514f5e3Sopenharmony_ci Label next(env); 454514f5e3Sopenharmony_ci Label loopExit(env); 464514f5e3Sopenharmony_ci 474514f5e3Sopenharmony_ci DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 484514f5e3Sopenharmony_ci Jump(&loopHead); 494514f5e3Sopenharmony_ci LoopBegin(&loopHead); 504514f5e3Sopenharmony_ci { 514514f5e3Sopenharmony_ci BRANCH(Int32LessThan(*i, numberOfAllElements), &next, &loopExit); 524514f5e3Sopenharmony_ci Bind(&next); 534514f5e3Sopenharmony_ci 544514f5e3Sopenharmony_ci GateRef fromIndex = EntryToIndex(linkedTable, *i); 554514f5e3Sopenharmony_ci DEFVARIABLE(key, VariableType::JS_ANY(), GetElement(linkedTable, fromIndex)); 564514f5e3Sopenharmony_ci Label hole(env); 574514f5e3Sopenharmony_ci Label notHole(env); 584514f5e3Sopenharmony_ci BRANCH(TaggedIsHole(*key), &hole, ¬Hole); 594514f5e3Sopenharmony_ci Bind(&hole); 604514f5e3Sopenharmony_ci { 614514f5e3Sopenharmony_ci currentDeletedElements = Int32Add(*currentDeletedElements, Int32(1)); 624514f5e3Sopenharmony_ci SetDeletedNum(linkedTable, *i, *currentDeletedElements); 634514f5e3Sopenharmony_ci Jump(&loopEnd); 644514f5e3Sopenharmony_ci } 654514f5e3Sopenharmony_ci Bind(¬Hole); 664514f5e3Sopenharmony_ci { 674514f5e3Sopenharmony_ci Label weak(env); 684514f5e3Sopenharmony_ci Label notWeak(env); 694514f5e3Sopenharmony_ci BRANCH(TaggedIsWeak(*key), &weak, ¬Weak); 704514f5e3Sopenharmony_ci Bind(&weak); 714514f5e3Sopenharmony_ci { 724514f5e3Sopenharmony_ci key = RemoveTaggedWeakTag(*key); 734514f5e3Sopenharmony_ci Jump(¬Weak); 744514f5e3Sopenharmony_ci } 754514f5e3Sopenharmony_ci Bind(¬Weak); 764514f5e3Sopenharmony_ci 774514f5e3Sopenharmony_ci HashStubBuilder hashBuilder(this, glue_); 784514f5e3Sopenharmony_ci GateRef hash = hashBuilder.GetHash(*key); 794514f5e3Sopenharmony_ci GateRef bucket = HashToBucket(newTable, hash); 804514f5e3Sopenharmony_ci InsertNewEntry(newTable, bucket, *desEntry); 814514f5e3Sopenharmony_ci GateRef desIndex = EntryToIndex(newTable, *desEntry); 824514f5e3Sopenharmony_ci 834514f5e3Sopenharmony_ci Label loopHead1(env); 844514f5e3Sopenharmony_ci Label loopEnd1(env); 854514f5e3Sopenharmony_ci Label next1(env); 864514f5e3Sopenharmony_ci Label loopExit1(env); 874514f5e3Sopenharmony_ci DEFVARIABLE(j, VariableType::INT32(), Int32(0)); 884514f5e3Sopenharmony_ci Jump(&loopHead1); 894514f5e3Sopenharmony_ci LoopBegin(&loopHead1); 904514f5e3Sopenharmony_ci { 914514f5e3Sopenharmony_ci BRANCH(Int32LessThan(*j, Int32(LinkedHashTableObject::ENTRY_SIZE)), &next1, &loopExit1); 924514f5e3Sopenharmony_ci Bind(&next1); 934514f5e3Sopenharmony_ci GateRef ele = GetElement(linkedTable, Int32Add(fromIndex, *j)); 944514f5e3Sopenharmony_ci SetElement(newTable, Int32Add(desIndex, *j), ele); 954514f5e3Sopenharmony_ci Jump(&loopEnd1); 964514f5e3Sopenharmony_ci } 974514f5e3Sopenharmony_ci Bind(&loopEnd1); 984514f5e3Sopenharmony_ci j = Int32Add(*j, Int32(1)); 994514f5e3Sopenharmony_ci LoopEnd(&loopHead1); 1004514f5e3Sopenharmony_ci Bind(&loopExit1); 1014514f5e3Sopenharmony_ci desEntry = Int32Add(*desEntry, Int32(1)); 1024514f5e3Sopenharmony_ci Jump(&loopEnd); 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci } 1054514f5e3Sopenharmony_ci Bind(&loopEnd); 1064514f5e3Sopenharmony_ci i = Int32Add(*i, Int32(1)); 1074514f5e3Sopenharmony_ci LoopEnd(&loopHead, env, glue_); 1084514f5e3Sopenharmony_ci Bind(&loopExit); 1094514f5e3Sopenharmony_ci 1104514f5e3Sopenharmony_ci SetNumberOfElements(newTable, GetNumberOfElements(linkedTable)); 1114514f5e3Sopenharmony_ci SetNumberOfDeletedElements(newTable, Int32(0)); 1124514f5e3Sopenharmony_ci env->SubCfgExit(); 1134514f5e3Sopenharmony_ci} 1144514f5e3Sopenharmony_ci 1154514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 1164514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GrowCapacity( 1174514f5e3Sopenharmony_ci GateRef linkedTable, GateRef numberOfAddedElements) 1184514f5e3Sopenharmony_ci{ 1194514f5e3Sopenharmony_ci auto env = GetEnvironment(); 1204514f5e3Sopenharmony_ci Label entryLabel(env); 1214514f5e3Sopenharmony_ci env->SubCfgEntry(&entryLabel); 1224514f5e3Sopenharmony_ci Label exit(env); 1234514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::JS_ANY(), linkedTable); 1244514f5e3Sopenharmony_ci 1254514f5e3Sopenharmony_ci GateRef hasSufficient = HasSufficientCapacity(linkedTable, numberOfAddedElements); 1264514f5e3Sopenharmony_ci Label grow(env); 1274514f5e3Sopenharmony_ci BRANCH(hasSufficient, &exit, &grow); 1284514f5e3Sopenharmony_ci Bind(&grow); 1294514f5e3Sopenharmony_ci { 1304514f5e3Sopenharmony_ci GateRef newCapacity = ComputeCapacity(Int32Add(GetNumberOfElements(linkedTable), numberOfAddedElements)); 1314514f5e3Sopenharmony_ci GateRef newTable = Create(newCapacity); 1324514f5e3Sopenharmony_ci Rehash(linkedTable, newTable); 1334514f5e3Sopenharmony_ci res = newTable; 1344514f5e3Sopenharmony_ci Jump(&exit); 1354514f5e3Sopenharmony_ci } 1364514f5e3Sopenharmony_ci Bind(&exit); 1374514f5e3Sopenharmony_ci auto ret = *res; 1384514f5e3Sopenharmony_ci env->SubCfgExit(); 1394514f5e3Sopenharmony_ci return ret; 1404514f5e3Sopenharmony_ci} 1414514f5e3Sopenharmony_ci 1424514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 1434514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::ComputeCapacity( 1444514f5e3Sopenharmony_ci GateRef atLeastSpaceFor) 1454514f5e3Sopenharmony_ci{ 1464514f5e3Sopenharmony_ci if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashMap>) { 1474514f5e3Sopenharmony_ci return TaggedGetInt(CallRuntime(glue_, RTSTUB_ID(LinkedHashMapComputeCapacity), { 1484514f5e3Sopenharmony_ci IntToTaggedInt(atLeastSpaceFor) })); 1494514f5e3Sopenharmony_ci } else { 1504514f5e3Sopenharmony_ci return TaggedGetInt(CallRuntime(glue_, RTSTUB_ID(LinkedHashSetComputeCapacity), { 1514514f5e3Sopenharmony_ci IntToTaggedInt(atLeastSpaceFor) })); 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci} 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 1564514f5e3Sopenharmony_civoid LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::RemoveEntry( 1574514f5e3Sopenharmony_ci GateRef linkedTable, GateRef entry) 1584514f5e3Sopenharmony_ci{ 1594514f5e3Sopenharmony_ci auto env = GetEnvironment(); 1604514f5e3Sopenharmony_ci Label entryLabel(env); 1614514f5e3Sopenharmony_ci Label exit(env); 1624514f5e3Sopenharmony_ci env->SubCfgEntry(&entryLabel); 1634514f5e3Sopenharmony_ci DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 1644514f5e3Sopenharmony_ci 1654514f5e3Sopenharmony_ci Label loopHead(env); 1664514f5e3Sopenharmony_ci Label loopEnd(env); 1674514f5e3Sopenharmony_ci Label next(env); 1684514f5e3Sopenharmony_ci Label loopExit(env); 1694514f5e3Sopenharmony_ci GateRef index = EntryToIndex(linkedTable, entry); 1704514f5e3Sopenharmony_ci Jump(&loopHead); 1714514f5e3Sopenharmony_ci LoopBegin(&loopHead); 1724514f5e3Sopenharmony_ci { 1734514f5e3Sopenharmony_ci BRANCH(Int32LessThan(*i, Int32(LinkedHashTableObject::ENTRY_SIZE)), &next, &loopExit); 1744514f5e3Sopenharmony_ci Bind(&next); 1754514f5e3Sopenharmony_ci 1764514f5e3Sopenharmony_ci GateRef idx = Int32Add(index, *i); 1774514f5e3Sopenharmony_ci SetElement(linkedTable, idx, Hole()); 1784514f5e3Sopenharmony_ci Jump(&loopEnd); 1794514f5e3Sopenharmony_ci } 1804514f5e3Sopenharmony_ci Bind(&loopEnd); 1814514f5e3Sopenharmony_ci i = Int32Add(*i, Int32(1)); 1824514f5e3Sopenharmony_ci LoopEnd(&loopHead, env, glue_); 1834514f5e3Sopenharmony_ci Bind(&loopExit); 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_ci GateRef newNofe = Int32Sub(GetNumberOfElements(linkedTable), Int32(1)); 1864514f5e3Sopenharmony_ci SetNumberOfElements(linkedTable, newNofe); 1874514f5e3Sopenharmony_ci GateRef newNofd = Int32Add(GetNumberOfDeletedElements(linkedTable), Int32(1)); 1884514f5e3Sopenharmony_ci SetNumberOfDeletedElements(linkedTable, newNofd); 1894514f5e3Sopenharmony_ci env->SubCfgExit(); 1904514f5e3Sopenharmony_ci} 1914514f5e3Sopenharmony_ci 1924514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 1934514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::HasSufficientCapacity( 1944514f5e3Sopenharmony_ci GateRef linkedTable, GateRef numOfAddElements) 1954514f5e3Sopenharmony_ci{ 1964514f5e3Sopenharmony_ci auto env = GetEnvironment(); 1974514f5e3Sopenharmony_ci Label entryLabel(env); 1984514f5e3Sopenharmony_ci Label exit(env); 1994514f5e3Sopenharmony_ci env->SubCfgEntry(&entryLabel); 2004514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::BOOL(), False()); 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci GateRef numberOfElements = GetNumberOfElements(linkedTable); 2034514f5e3Sopenharmony_ci GateRef numOfDelElements = GetNumberOfDeletedElements(linkedTable); 2044514f5e3Sopenharmony_ci GateRef nof = Int32Add(numberOfElements, numOfAddElements); 2054514f5e3Sopenharmony_ci GateRef capacity = GetCapacity(linkedTable); 2064514f5e3Sopenharmony_ci GateRef isLess = LogicAndBuilder(env) 2074514f5e3Sopenharmony_ci .And(Int32LessThan(nof, capacity)) 2084514f5e3Sopenharmony_ci .And(Int32LessThanOrEqual(numOfDelElements, Int32Div(Int32Sub(capacity, nof), Int32(2)))) 2094514f5e3Sopenharmony_ci .Done(); 2104514f5e3Sopenharmony_ci Label lessLable(env); 2114514f5e3Sopenharmony_ci BRANCH(isLess, &lessLable, &exit); 2124514f5e3Sopenharmony_ci Bind(&lessLable); 2134514f5e3Sopenharmony_ci { 2144514f5e3Sopenharmony_ci Label need(env); 2154514f5e3Sopenharmony_ci BRANCH(Int32LessThanOrEqual(Int32Add(nof, Int32Div(nof, Int32(2))), capacity), &need, &exit); // 2: half 2164514f5e3Sopenharmony_ci Bind(&need); 2174514f5e3Sopenharmony_ci { 2184514f5e3Sopenharmony_ci res = True(); 2194514f5e3Sopenharmony_ci Jump(&exit); 2204514f5e3Sopenharmony_ci } 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci Bind(&exit); 2234514f5e3Sopenharmony_ci auto ret = *res; 2244514f5e3Sopenharmony_ci env->SubCfgExit(); 2254514f5e3Sopenharmony_ci return ret; 2264514f5e3Sopenharmony_ci} 2274514f5e3Sopenharmony_ci 2284514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 2294514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::HashObjectIsMatch( 2304514f5e3Sopenharmony_ci GateRef key, GateRef other) 2314514f5e3Sopenharmony_ci{ 2324514f5e3Sopenharmony_ci return SameValueZero(glue_, key, other); 2334514f5e3Sopenharmony_ci} 2344514f5e3Sopenharmony_ci 2354514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 2364514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::FindElement( 2374514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key, GateRef hash) 2384514f5e3Sopenharmony_ci{ 2394514f5e3Sopenharmony_ci auto env = GetEnvironment(); 2404514f5e3Sopenharmony_ci Label entryLabel(env); 2414514f5e3Sopenharmony_ci env->SubCfgEntry(&entryLabel); 2424514f5e3Sopenharmony_ci 2434514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::INT32(), Int32(-1)); 2444514f5e3Sopenharmony_ci Label exit(env); 2454514f5e3Sopenharmony_ci Label isKey(env); 2464514f5e3Sopenharmony_ci BRANCH(IsKey(key), &isKey, &exit); 2474514f5e3Sopenharmony_ci Bind(&isKey); 2484514f5e3Sopenharmony_ci { 2494514f5e3Sopenharmony_ci GateRef bucket = HashToBucket(linkedTable, hash); 2504514f5e3Sopenharmony_ci GateRef index = BucketToIndex(bucket); 2514514f5e3Sopenharmony_ci DEFVARIABLE(entry, VariableType::JS_ANY(), GetElement(linkedTable, index)); 2524514f5e3Sopenharmony_ci Label loopHead(env); 2534514f5e3Sopenharmony_ci Label loopEnd(env); 2544514f5e3Sopenharmony_ci Label next(env); 2554514f5e3Sopenharmony_ci Label loopExit(env); 2564514f5e3Sopenharmony_ci 2574514f5e3Sopenharmony_ci Jump(&loopHead); 2584514f5e3Sopenharmony_ci LoopBegin(&loopHead); 2594514f5e3Sopenharmony_ci { 2604514f5e3Sopenharmony_ci BRANCH(TaggedIsHole(*entry), &loopExit, &next); 2614514f5e3Sopenharmony_ci Bind(&next); 2624514f5e3Sopenharmony_ci 2634514f5e3Sopenharmony_ci DEFVARIABLE(element, VariableType::JS_ANY(), GetKey(linkedTable, TaggedGetInt(*entry))); 2644514f5e3Sopenharmony_ci Label notHole(env); 2654514f5e3Sopenharmony_ci BRANCH(TaggedIsHole(*element), &loopEnd, ¬Hole); 2664514f5e3Sopenharmony_ci Bind(¬Hole); 2674514f5e3Sopenharmony_ci { 2684514f5e3Sopenharmony_ci Label weak(env); 2694514f5e3Sopenharmony_ci Label notWeak(env); 2704514f5e3Sopenharmony_ci BRANCH(TaggedIsWeak(*element), &weak, ¬Weak); 2714514f5e3Sopenharmony_ci Bind(&weak); 2724514f5e3Sopenharmony_ci { 2734514f5e3Sopenharmony_ci element = RemoveTaggedWeakTag(*element); 2744514f5e3Sopenharmony_ci Jump(¬Weak); 2754514f5e3Sopenharmony_ci } 2764514f5e3Sopenharmony_ci Bind(¬Weak); 2774514f5e3Sopenharmony_ci Label match(env); 2784514f5e3Sopenharmony_ci BRANCH(HashObjectIsMatch(key, *element), &match, &loopEnd); 2794514f5e3Sopenharmony_ci Bind(&match); 2804514f5e3Sopenharmony_ci { 2814514f5e3Sopenharmony_ci res = TaggedGetInt(*entry); 2824514f5e3Sopenharmony_ci Jump(&loopExit); 2834514f5e3Sopenharmony_ci } 2844514f5e3Sopenharmony_ci } 2854514f5e3Sopenharmony_ci } 2864514f5e3Sopenharmony_ci Bind(&loopEnd); 2874514f5e3Sopenharmony_ci entry = GetNextEntry(linkedTable, TaggedGetInt(*entry)); 2884514f5e3Sopenharmony_ci LoopEnd(&loopHead, env, glue_); 2894514f5e3Sopenharmony_ci Bind(&loopExit); 2904514f5e3Sopenharmony_ci Jump(&exit); 2914514f5e3Sopenharmony_ci } 2924514f5e3Sopenharmony_ci Bind(&exit); 2934514f5e3Sopenharmony_ci auto ret = *res; 2944514f5e3Sopenharmony_ci env->SubCfgExit(); 2954514f5e3Sopenharmony_ci return ret; 2964514f5e3Sopenharmony_ci} 2974514f5e3Sopenharmony_ci 2984514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 2994514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GetDeletedElementsAt( 3004514f5e3Sopenharmony_ci GateRef linkedTable, GateRef entry) 3014514f5e3Sopenharmony_ci{ 3024514f5e3Sopenharmony_ci auto env = GetEnvironment(); 3034514f5e3Sopenharmony_ci Label entryLabel(env); 3044514f5e3Sopenharmony_ci env->SubCfgEntry(&entryLabel); 3054514f5e3Sopenharmony_ci Label exit(env); 3064514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::INT32(), Int32(0)); 3074514f5e3Sopenharmony_ci DEFVARIABLE(currentEntry, VariableType::INT32(), Int32Sub(entry, Int32(1))); 3084514f5e3Sopenharmony_ci Label loopHead(env); 3094514f5e3Sopenharmony_ci Label loopEnd(env); 3104514f5e3Sopenharmony_ci Label next(env); 3114514f5e3Sopenharmony_ci Label loopExit(env); 3124514f5e3Sopenharmony_ci 3134514f5e3Sopenharmony_ci Jump(&loopHead); 3144514f5e3Sopenharmony_ci LoopBegin(&loopHead); 3154514f5e3Sopenharmony_ci { 3164514f5e3Sopenharmony_ci BRANCH(Int32GreaterThanOrEqual(*currentEntry, Int32(0)), &next, &loopExit); 3174514f5e3Sopenharmony_ci Bind(&next); 3184514f5e3Sopenharmony_ci GateRef key = GetKey(linkedTable, *currentEntry); 3194514f5e3Sopenharmony_ci Label hole(env); 3204514f5e3Sopenharmony_ci BRANCH(TaggedIsHole(key), &hole, &loopEnd); 3214514f5e3Sopenharmony_ci Bind(&hole); 3224514f5e3Sopenharmony_ci { 3234514f5e3Sopenharmony_ci GateRef deletedNum = GetDeletedNum(linkedTable, *currentEntry); 3244514f5e3Sopenharmony_ci res = deletedNum; 3254514f5e3Sopenharmony_ci Jump(&exit); 3264514f5e3Sopenharmony_ci } 3274514f5e3Sopenharmony_ci } 3284514f5e3Sopenharmony_ci Bind(&loopEnd); 3294514f5e3Sopenharmony_ci currentEntry = Int32Sub(*currentEntry, Int32(1)); 3304514f5e3Sopenharmony_ci LoopEnd(&loopHead, env, glue_); 3314514f5e3Sopenharmony_ci Bind(&loopExit); 3324514f5e3Sopenharmony_ci Jump(&exit); 3334514f5e3Sopenharmony_ci Bind(&exit); 3344514f5e3Sopenharmony_ci auto ret = *res; 3354514f5e3Sopenharmony_ci env->SubCfgExit(); 3364514f5e3Sopenharmony_ci return ret; 3374514f5e3Sopenharmony_ci} 3384514f5e3Sopenharmony_ci 3394514f5e3Sopenharmony_citemplate<typename LinkedHashTableType, typename LinkedHashTableObject> 3404514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Create(GateRef numberOfElements) 3414514f5e3Sopenharmony_ci{ 3424514f5e3Sopenharmony_ci auto env = GetEnvironment(); 3434514f5e3Sopenharmony_ci Label entry(env); 3444514f5e3Sopenharmony_ci env->SubCfgEntry(&entry); 3454514f5e3Sopenharmony_ci Label exit(env); 3464514f5e3Sopenharmony_ci 3474514f5e3Sopenharmony_ci // new LinkedHashTable 3484514f5e3Sopenharmony_ci GateRef length = CalNewTaggedArrayLength(numberOfElements); 3494514f5e3Sopenharmony_ci NewObjectStubBuilder newBuilder(this); 3504514f5e3Sopenharmony_ci GateRef array = newBuilder.NewTaggedArray(glue_, length); 3514514f5e3Sopenharmony_ci 3524514f5e3Sopenharmony_ci Label noException(env); 3534514f5e3Sopenharmony_ci BRANCH(TaggedIsException(array), &exit, &noException); 3544514f5e3Sopenharmony_ci Bind(&noException); 3554514f5e3Sopenharmony_ci { 3564514f5e3Sopenharmony_ci // SetNumberOfElements 3574514f5e3Sopenharmony_ci SetNumberOfElements(array, Int32(0)); 3584514f5e3Sopenharmony_ci // SetNumberOfDeletedElements 3594514f5e3Sopenharmony_ci SetNumberOfDeletedElements(array, Int32(0)); 3604514f5e3Sopenharmony_ci // SetCapacity 3614514f5e3Sopenharmony_ci SetCapacity(array, numberOfElements); 3624514f5e3Sopenharmony_ci Jump(&exit); 3634514f5e3Sopenharmony_ci } 3644514f5e3Sopenharmony_ci Bind(&exit); 3654514f5e3Sopenharmony_ci env->SubCfgExit(); 3664514f5e3Sopenharmony_ci return array; 3674514f5e3Sopenharmony_ci} 3684514f5e3Sopenharmony_ci 3694514f5e3Sopenharmony_citemplate<typename LinkedHashTableType, typename LinkedHashTableObject> 3704514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Clear(GateRef linkedTable) 3714514f5e3Sopenharmony_ci{ 3724514f5e3Sopenharmony_ci auto env = GetEnvironment(); 3734514f5e3Sopenharmony_ci Label entry(env); 3744514f5e3Sopenharmony_ci env->SubCfgEntry(&entry); 3754514f5e3Sopenharmony_ci Label exit(env); 3764514f5e3Sopenharmony_ci Label setLinked(env); 3774514f5e3Sopenharmony_ci DEFVARIABLE(result, VariableType::JS_ANY(), linkedTable); 3784514f5e3Sopenharmony_ci 3794514f5e3Sopenharmony_ci Label reuseExistingTable(env); 3804514f5e3Sopenharmony_ci Label createNewTable(env); 3814514f5e3Sopenharmony_ci GateRef cap = GetCapacity(linkedTable); 3824514f5e3Sopenharmony_ci GateRef minCapacity = Int32(LinkedHashTableType::MIN_CAPACITY); 3834514f5e3Sopenharmony_ci BRANCH(Equal(cap, minCapacity), &reuseExistingTable, &createNewTable); 3844514f5e3Sopenharmony_ci 3854514f5e3Sopenharmony_ci Bind(&reuseExistingTable); 3864514f5e3Sopenharmony_ci size_t length = static_cast<size_t>(LinkedHashTableType::GetLengthOfTable(LinkedHashTableType::MIN_CAPACITY)); 3874514f5e3Sopenharmony_ci for (size_t i = LinkedHashTableType::ELEMENTS_START_INDEX; i < length; ++i) { 3884514f5e3Sopenharmony_ci SetValueToTaggedArray(VariableType::JS_NOT_POINTER(), glue_, linkedTable, Int32(i), Hole()); 3894514f5e3Sopenharmony_ci } 3904514f5e3Sopenharmony_ci GateRef numberOfElements = GetNumberOfElements(linkedTable); 3914514f5e3Sopenharmony_ci GateRef numberOfDeletedElements = GetNumberOfDeletedElements(linkedTable); 3924514f5e3Sopenharmony_ci SetNumberOfElements(linkedTable, Int32(0)); 3934514f5e3Sopenharmony_ci SetNumberOfDeletedElements(linkedTable, Int32Add(numberOfElements, numberOfDeletedElements)); 3944514f5e3Sopenharmony_ci Jump(&exit); 3954514f5e3Sopenharmony_ci 3964514f5e3Sopenharmony_ci Bind(&createNewTable); 3974514f5e3Sopenharmony_ci GateRef newTable = Create(minCapacity); 3984514f5e3Sopenharmony_ci result = newTable; 3994514f5e3Sopenharmony_ci Label noException(env); 4004514f5e3Sopenharmony_ci BRANCH(TaggedIsException(newTable), &exit, &noException); 4014514f5e3Sopenharmony_ci Bind(&noException); 4024514f5e3Sopenharmony_ci 4034514f5e3Sopenharmony_ci Label capGreaterZero(env); 4044514f5e3Sopenharmony_ci BRANCH(Int32GreaterThan(cap, Int32(0)), &capGreaterZero, &exit); 4054514f5e3Sopenharmony_ci Bind(&capGreaterZero); 4064514f5e3Sopenharmony_ci { 4074514f5e3Sopenharmony_ci // NextTable 4084514f5e3Sopenharmony_ci SetNextTable(linkedTable, newTable); 4094514f5e3Sopenharmony_ci // SetNumberOfDeletedElements 4104514f5e3Sopenharmony_ci SetNumberOfDeletedElements(linkedTable, Int32(-1)); 4114514f5e3Sopenharmony_ci Jump(&exit); 4124514f5e3Sopenharmony_ci } 4134514f5e3Sopenharmony_ci 4144514f5e3Sopenharmony_ci Bind(&exit); 4154514f5e3Sopenharmony_ci GateRef res = *result; 4164514f5e3Sopenharmony_ci env->SubCfgExit(); 4174514f5e3Sopenharmony_ci return res; 4184514f5e3Sopenharmony_ci} 4194514f5e3Sopenharmony_ci 4204514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Clear(GateRef); 4214514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Clear(GateRef); 4224514f5e3Sopenharmony_ci 4234514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 4244514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::ForEach(GateRef thisValue, 4254514f5e3Sopenharmony_ci GateRef srcLinkedTable, GateRef callbackFnHandle, GateRef thisArg) 4264514f5e3Sopenharmony_ci{ 4274514f5e3Sopenharmony_ci auto env = GetEnvironment(); 4284514f5e3Sopenharmony_ci Label entry(env); 4294514f5e3Sopenharmony_ci env->SubCfgEntry(&entry); 4304514f5e3Sopenharmony_ci Label exit(env); 4314514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::JS_ANY(), Undefined()); 4324514f5e3Sopenharmony_ci DEFVARIABLE(linkedTable, VariableType::JS_ANY(), srcLinkedTable); 4334514f5e3Sopenharmony_ci 4344514f5e3Sopenharmony_ci GateRef numberOfElements = GetNumberOfElements(*linkedTable); 4354514f5e3Sopenharmony_ci GateRef numberOfDeletedElements = GetNumberOfDeletedElements(*linkedTable); 4364514f5e3Sopenharmony_ci GateRef tmpTotalElements = Int32Add(numberOfElements, numberOfDeletedElements); 4374514f5e3Sopenharmony_ci DEFVARIABLE(totalElements, VariableType::INT32(), tmpTotalElements); 4384514f5e3Sopenharmony_ci DEFVARIABLE(index, VariableType::INT32(), Int32(0)); 4394514f5e3Sopenharmony_ci 4404514f5e3Sopenharmony_ci Label loopHead(env); 4414514f5e3Sopenharmony_ci Label loopEnd(env); 4424514f5e3Sopenharmony_ci Label next(env); 4434514f5e3Sopenharmony_ci Label loopExit(env); 4444514f5e3Sopenharmony_ci Jump(&loopHead); 4454514f5e3Sopenharmony_ci LoopBegin(&loopHead); 4464514f5e3Sopenharmony_ci { 4474514f5e3Sopenharmony_ci BRANCH(Int32LessThan(*index, *totalElements), &next, &loopExit); 4484514f5e3Sopenharmony_ci Bind(&next); 4494514f5e3Sopenharmony_ci GateRef valueIndex = *index; 4504514f5e3Sopenharmony_ci 4514514f5e3Sopenharmony_ci GateRef key = GetKey(*linkedTable, *index); 4524514f5e3Sopenharmony_ci index = Int32Add(*index, Int32(1)); 4534514f5e3Sopenharmony_ci Label keyNotHole(env); 4544514f5e3Sopenharmony_ci BRANCH(TaggedIsHole(key), &loopEnd, &keyNotHole); 4554514f5e3Sopenharmony_ci Bind(&keyNotHole); 4564514f5e3Sopenharmony_ci 4574514f5e3Sopenharmony_ci GateRef value = key; 4584514f5e3Sopenharmony_ci if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashMap>) { 4594514f5e3Sopenharmony_ci value = GetValue(*linkedTable, valueIndex); 4604514f5e3Sopenharmony_ci } 4614514f5e3Sopenharmony_ci Label hasException(env); 4624514f5e3Sopenharmony_ci Label notHasException(env); 4634514f5e3Sopenharmony_ci JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 4644514f5e3Sopenharmony_ci callArgs.callThisArg3WithReturnArgs = { thisArg, value, key, thisValue }; 4654514f5e3Sopenharmony_ci CallStubBuilder callBuilder(this, glue_, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 4664514f5e3Sopenharmony_ci Circuit::NullGate(), callArgs, ProfileOperation(), false); 4674514f5e3Sopenharmony_ci GateRef retValue = callBuilder.JSCallDispatch(); 4684514f5e3Sopenharmony_ci BRANCH(HasPendingException(glue_), &hasException, ¬HasException); 4694514f5e3Sopenharmony_ci Bind(&hasException); 4704514f5e3Sopenharmony_ci { 4714514f5e3Sopenharmony_ci res = retValue; 4724514f5e3Sopenharmony_ci Jump(&exit); 4734514f5e3Sopenharmony_ci } 4744514f5e3Sopenharmony_ci Bind(¬HasException); 4754514f5e3Sopenharmony_ci { 4764514f5e3Sopenharmony_ci // Maybe add or delete, get next table 4774514f5e3Sopenharmony_ci GateRef tmpNextTable = GetNextTable(*linkedTable); 4784514f5e3Sopenharmony_ci DEFVARIABLE(nextTable, VariableType::JS_ANY(), tmpNextTable); 4794514f5e3Sopenharmony_ci Label loopHead1(env); 4804514f5e3Sopenharmony_ci Label loopEnd1(env); 4814514f5e3Sopenharmony_ci Label next1(env); 4824514f5e3Sopenharmony_ci Label loopExit1(env); 4834514f5e3Sopenharmony_ci Jump(&loopHead1); 4844514f5e3Sopenharmony_ci LoopBegin(&loopHead1); 4854514f5e3Sopenharmony_ci { 4864514f5e3Sopenharmony_ci BRANCH(TaggedIsHole(*nextTable), &loopExit1, &next1); 4874514f5e3Sopenharmony_ci Bind(&next1); 4884514f5e3Sopenharmony_ci GateRef deleted = GetDeletedElementsAt(*linkedTable, *index); 4894514f5e3Sopenharmony_ci index = Int32Sub(*index, deleted); 4904514f5e3Sopenharmony_ci linkedTable = *nextTable; 4914514f5e3Sopenharmony_ci nextTable = GetNextTable(*linkedTable); 4924514f5e3Sopenharmony_ci Jump(&loopEnd1); 4934514f5e3Sopenharmony_ci } 4944514f5e3Sopenharmony_ci Bind(&loopEnd1); 4954514f5e3Sopenharmony_ci LoopEnd(&loopHead1); 4964514f5e3Sopenharmony_ci Bind(&loopExit1); 4974514f5e3Sopenharmony_ci // update totalElements 4984514f5e3Sopenharmony_ci GateRef numberOfEle = GetNumberOfElements(*linkedTable); 4994514f5e3Sopenharmony_ci GateRef numberOfDeletedEle = GetNumberOfDeletedElements(*linkedTable); 5004514f5e3Sopenharmony_ci totalElements = Int32Add(numberOfEle, numberOfDeletedEle); 5014514f5e3Sopenharmony_ci Jump(&loopEnd); 5024514f5e3Sopenharmony_ci } 5034514f5e3Sopenharmony_ci } 5044514f5e3Sopenharmony_ci Bind(&loopEnd); 5054514f5e3Sopenharmony_ci LoopEnd(&loopHead); 5064514f5e3Sopenharmony_ci Bind(&loopExit); 5074514f5e3Sopenharmony_ci Jump(&exit); 5084514f5e3Sopenharmony_ci 5094514f5e3Sopenharmony_ci Bind(&exit); 5104514f5e3Sopenharmony_ci env->SubCfgExit(); 5114514f5e3Sopenharmony_ci return *res; 5124514f5e3Sopenharmony_ci} 5134514f5e3Sopenharmony_ci 5144514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::ForEach(GateRef thisValue, 5154514f5e3Sopenharmony_ci GateRef linkedTable, GateRef callbackFnHandle, GateRef thisArg); 5164514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::ForEach(GateRef thisValue, 5174514f5e3Sopenharmony_ci GateRef linkedTable, GateRef callbackFnHandle, GateRef thisArg); 5184514f5e3Sopenharmony_ci 5194514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 5204514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Insert( 5214514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key, GateRef value) 5224514f5e3Sopenharmony_ci{ 5234514f5e3Sopenharmony_ci auto env = GetEnvironment(); 5244514f5e3Sopenharmony_ci Label cfgEntry(env); 5254514f5e3Sopenharmony_ci env->SubCfgEntry(&cfgEntry); 5264514f5e3Sopenharmony_ci Label exit(env); 5274514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::JS_ANY(), linkedTable); 5284514f5e3Sopenharmony_ci HashStubBuilder hashBuilder(this, glue_); 5294514f5e3Sopenharmony_ci GateRef hash = hashBuilder.GetHash(key); 5304514f5e3Sopenharmony_ci GateRef entry = FindElement(linkedTable, key, hash); 5314514f5e3Sopenharmony_ci Label findEntry(env); 5324514f5e3Sopenharmony_ci Label notFind(env); 5334514f5e3Sopenharmony_ci BRANCH(Int32Equal(entry, Int32(-1)), ¬Find, &findEntry); 5344514f5e3Sopenharmony_ci Bind(&findEntry); 5354514f5e3Sopenharmony_ci { 5364514f5e3Sopenharmony_ci SetValue(linkedTable, entry, value); 5374514f5e3Sopenharmony_ci Jump(&exit); 5384514f5e3Sopenharmony_ci } 5394514f5e3Sopenharmony_ci Bind(¬Find); 5404514f5e3Sopenharmony_ci { 5414514f5e3Sopenharmony_ci GateRef newTable = GrowCapacity(linkedTable, Int32(1)); 5424514f5e3Sopenharmony_ci res = newTable; 5434514f5e3Sopenharmony_ci GateRef bucket = HashToBucket(newTable, hash); 5444514f5e3Sopenharmony_ci GateRef numberOfElements = GetNumberOfElements(newTable); 5454514f5e3Sopenharmony_ci 5464514f5e3Sopenharmony_ci GateRef newEntry = Int32Add(numberOfElements, GetNumberOfDeletedElements(newTable)); 5474514f5e3Sopenharmony_ci InsertNewEntry(newTable, bucket, newEntry); 5484514f5e3Sopenharmony_ci SetKey(newTable, newEntry, key); 5494514f5e3Sopenharmony_ci SetValue(newTable, newEntry, value); 5504514f5e3Sopenharmony_ci GateRef newNumberOfElements = Int32Add(numberOfElements, Int32(1)); 5514514f5e3Sopenharmony_ci SetNumberOfElements(newTable, newNumberOfElements); 5524514f5e3Sopenharmony_ci Jump(&exit); 5534514f5e3Sopenharmony_ci } 5544514f5e3Sopenharmony_ci 5554514f5e3Sopenharmony_ci Bind(&exit); 5564514f5e3Sopenharmony_ci auto ret = *res; 5574514f5e3Sopenharmony_ci env->SubCfgExit(); 5584514f5e3Sopenharmony_ci return ret; 5594514f5e3Sopenharmony_ci} 5604514f5e3Sopenharmony_ci 5614514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Insert( 5624514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key, GateRef value); 5634514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Insert( 5644514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key, GateRef value); 5654514f5e3Sopenharmony_ci 5664514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 5674514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Delete( 5684514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key) 5694514f5e3Sopenharmony_ci{ 5704514f5e3Sopenharmony_ci auto env = GetEnvironment(); 5714514f5e3Sopenharmony_ci Label cfgEntry(env); 5724514f5e3Sopenharmony_ci env->SubCfgEntry(&cfgEntry); 5734514f5e3Sopenharmony_ci Label exit(env); 5744514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::BOOL(), False()); 5754514f5e3Sopenharmony_ci HashStubBuilder hashBuilder(this, glue_); 5764514f5e3Sopenharmony_ci GateRef hash = hashBuilder.GetHash(key); 5774514f5e3Sopenharmony_ci GateRef entry = FindElement(linkedTable, key, hash); 5784514f5e3Sopenharmony_ci Label findEntry(env); 5794514f5e3Sopenharmony_ci BRANCH(Int32Equal(entry, Int32(-1)), &exit, &findEntry); 5804514f5e3Sopenharmony_ci Bind(&findEntry); 5814514f5e3Sopenharmony_ci { 5824514f5e3Sopenharmony_ci RemoveEntry(linkedTable, entry); 5834514f5e3Sopenharmony_ci res = True(); 5844514f5e3Sopenharmony_ci Jump(&exit); 5854514f5e3Sopenharmony_ci } 5864514f5e3Sopenharmony_ci 5874514f5e3Sopenharmony_ci Bind(&exit); 5884514f5e3Sopenharmony_ci auto ret = *res; 5894514f5e3Sopenharmony_ci env->SubCfgExit(); 5904514f5e3Sopenharmony_ci return ret; 5914514f5e3Sopenharmony_ci} 5924514f5e3Sopenharmony_ci 5934514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Delete( 5944514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key); 5954514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Delete( 5964514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key); 5974514f5e3Sopenharmony_ci 5984514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 5994514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Has( 6004514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key) 6014514f5e3Sopenharmony_ci{ 6024514f5e3Sopenharmony_ci auto env = GetEnvironment(); 6034514f5e3Sopenharmony_ci Label cfgEntry(env); 6044514f5e3Sopenharmony_ci env->SubCfgEntry(&cfgEntry); 6054514f5e3Sopenharmony_ci HashStubBuilder hashBuilder(this, glue_); 6064514f5e3Sopenharmony_ci GateRef hash = hashBuilder.GetHash(key); 6074514f5e3Sopenharmony_ci GateRef entry = FindElement(linkedTable, key, hash); 6084514f5e3Sopenharmony_ci GateRef ret = Int32NotEqual(entry, Int32(-1)); 6094514f5e3Sopenharmony_ci env->SubCfgExit(); 6104514f5e3Sopenharmony_ci return ret; 6114514f5e3Sopenharmony_ci} 6124514f5e3Sopenharmony_ci 6134514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Has( 6144514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key); 6154514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Has( 6164514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key); 6174514f5e3Sopenharmony_ci 6184514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 6194514f5e3Sopenharmony_civoid LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::StoreHashTableToNewObject( 6204514f5e3Sopenharmony_ci GateRef newTargetHClass, Variable& returnValue) 6214514f5e3Sopenharmony_ci{ 6224514f5e3Sopenharmony_ci NewObjectStubBuilder newBuilder(this); 6234514f5e3Sopenharmony_ci GateRef res = newBuilder.NewJSObject(glue_, newTargetHClass); 6244514f5e3Sopenharmony_ci returnValue.WriteVariable(res); 6254514f5e3Sopenharmony_ci GateRef table; 6264514f5e3Sopenharmony_ci if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashMap>) { 6274514f5e3Sopenharmony_ci table = Create(Int32(LinkedHashMap::MIN_CAPACITY)); 6284514f5e3Sopenharmony_ci Store(VariableType::JS_ANY(), glue_, *returnValue, IntPtr(JSMap::LINKED_MAP_OFFSET), table); 6294514f5e3Sopenharmony_ci } else if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashSet>) { 6304514f5e3Sopenharmony_ci table = Create(Int32(LinkedHashSet::MIN_CAPACITY)); 6314514f5e3Sopenharmony_ci Store(VariableType::JS_ANY(), glue_, *returnValue, IntPtr(JSSet::LINKED_SET_OFFSET), table); 6324514f5e3Sopenharmony_ci } 6334514f5e3Sopenharmony_ci} 6344514f5e3Sopenharmony_ci 6354514f5e3Sopenharmony_citemplate void LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::StoreHashTableToNewObject( 6364514f5e3Sopenharmony_ci GateRef newTargetHClass, Variable& returnValue); 6374514f5e3Sopenharmony_citemplate void LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::StoreHashTableToNewObject( 6384514f5e3Sopenharmony_ci GateRef newTargetHClass, Variable& returnValue); 6394514f5e3Sopenharmony_ci 6404514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 6414514f5e3Sopenharmony_civoid LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GenMapSetConstructor( 6424514f5e3Sopenharmony_ci GateRef nativeCode, GateRef func, GateRef newTarget, GateRef thisValue, GateRef numArgs, GateRef arg0, GateRef argv) 6434514f5e3Sopenharmony_ci{ 6444514f5e3Sopenharmony_ci auto env = GetEnvironment(); 6454514f5e3Sopenharmony_ci DEFVARIABLE(returnValue, VariableType::JS_ANY(), Undefined()); 6464514f5e3Sopenharmony_ci 6474514f5e3Sopenharmony_ci Label newTargetObject(env); 6484514f5e3Sopenharmony_ci Label newTargetNotObject(env); 6494514f5e3Sopenharmony_ci Label newTargetFunction(env); 6504514f5e3Sopenharmony_ci Label slowPath(env); 6514514f5e3Sopenharmony_ci Label exit(env); 6524514f5e3Sopenharmony_ci 6534514f5e3Sopenharmony_ci // 1.If NewTarget is undefined, throw a TypeError exception 6544514f5e3Sopenharmony_ci BRANCH(TaggedIsHeapObject(newTarget), &newTargetObject, &newTargetNotObject); 6554514f5e3Sopenharmony_ci 6564514f5e3Sopenharmony_ci Bind(&newTargetObject); 6574514f5e3Sopenharmony_ci BRANCH(IsJSFunction(newTarget), &newTargetFunction, &slowPath); 6584514f5e3Sopenharmony_ci 6594514f5e3Sopenharmony_ci Bind(&newTargetFunction); 6604514f5e3Sopenharmony_ci Label fastGetHClass(env); 6614514f5e3Sopenharmony_ci Label intialHClassIsHClass(env); 6624514f5e3Sopenharmony_ci GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 6634514f5e3Sopenharmony_ci GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset); 6644514f5e3Sopenharmony_ci GateRef mapOrSetFunc; 6654514f5e3Sopenharmony_ci if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashMap>) { 6664514f5e3Sopenharmony_ci mapOrSetFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 6674514f5e3Sopenharmony_ci GlobalEnv::BUILTINS_MAP_FUNCTION_INDEX); 6684514f5e3Sopenharmony_ci } else if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashSet>) { 6694514f5e3Sopenharmony_ci mapOrSetFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 6704514f5e3Sopenharmony_ci GlobalEnv::BUILTINS_SET_FUNCTION_INDEX); 6714514f5e3Sopenharmony_ci } 6724514f5e3Sopenharmony_ci GateRef newTargetHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 6734514f5e3Sopenharmony_ci BRANCH(LogicAndBuilder(env).And(Equal(mapOrSetFunc, newTarget)).And(IsJSHClass(newTargetHClass)).Done(), 6744514f5e3Sopenharmony_ci &fastGetHClass, &slowPath); 6754514f5e3Sopenharmony_ci 6764514f5e3Sopenharmony_ci Bind(&fastGetHClass); 6774514f5e3Sopenharmony_ci Label isUndefinedOrNull(env); 6784514f5e3Sopenharmony_ci BRANCH(TaggedIsUndefinedOrNull(arg0), &isUndefinedOrNull, &slowPath); 6794514f5e3Sopenharmony_ci 6804514f5e3Sopenharmony_ci Bind(&isUndefinedOrNull); 6814514f5e3Sopenharmony_ci StoreHashTableToNewObject(newTargetHClass, returnValue); 6824514f5e3Sopenharmony_ci Jump(&exit); 6834514f5e3Sopenharmony_ci 6844514f5e3Sopenharmony_ci Bind(&newTargetNotObject); 6854514f5e3Sopenharmony_ci GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InvalidNewTarget)); 6864514f5e3Sopenharmony_ci CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); 6874514f5e3Sopenharmony_ci returnValue = Exception(); 6884514f5e3Sopenharmony_ci Jump(&exit); 6894514f5e3Sopenharmony_ci 6904514f5e3Sopenharmony_ci Bind(&slowPath); 6914514f5e3Sopenharmony_ci returnValue = CallBuiltinRuntimeWithNewTarget(glue_, {glue_, nativeCode, func, thisValue, 6924514f5e3Sopenharmony_ci numArgs, argv, newTarget}); 6934514f5e3Sopenharmony_ci Jump(&exit); 6944514f5e3Sopenharmony_ci 6954514f5e3Sopenharmony_ci Bind(&exit); 6964514f5e3Sopenharmony_ci Return(*returnValue); 6974514f5e3Sopenharmony_ci} 6984514f5e3Sopenharmony_ci 6994514f5e3Sopenharmony_citemplate void LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::GenMapSetConstructor( 7004514f5e3Sopenharmony_ci GateRef nativeCode, GateRef func, GateRef newTarget, GateRef thisValue, GateRef numArgs, 7014514f5e3Sopenharmony_ci GateRef arg0, GateRef argv); 7024514f5e3Sopenharmony_citemplate void LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::GenMapSetConstructor( 7034514f5e3Sopenharmony_ci GateRef nativeCode, GateRef func, GateRef newTarget, GateRef thisValue, GateRef numArgs, 7044514f5e3Sopenharmony_ci GateRef arg0, GateRef argv); 7054514f5e3Sopenharmony_ci 7064514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 7074514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GetLinked(GateRef jsThis) 7084514f5e3Sopenharmony_ci{ 7094514f5e3Sopenharmony_ci GateRef linkedTableOffset = GetLinkedOffset(); 7104514f5e3Sopenharmony_ci return Load(VariableType::JS_ANY(), jsThis, linkedTableOffset); 7114514f5e3Sopenharmony_ci} 7124514f5e3Sopenharmony_ci 7134514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::GetLinked( 7144514f5e3Sopenharmony_ci GateRef jsThis); 7154514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::GetLinked( 7164514f5e3Sopenharmony_ci GateRef jsThis); 7174514f5e3Sopenharmony_ci 7184514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 7194514f5e3Sopenharmony_civoid LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::SetLinked(GateRef jsThis, GateRef newTable) 7204514f5e3Sopenharmony_ci{ 7214514f5e3Sopenharmony_ci GateRef linkedTableOffset = GetLinkedOffset(); 7224514f5e3Sopenharmony_ci Store(VariableType::JS_ANY(), glue_, jsThis, linkedTableOffset, newTable); 7234514f5e3Sopenharmony_ci} 7244514f5e3Sopenharmony_ci 7254514f5e3Sopenharmony_citemplate void LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::SetLinked( 7264514f5e3Sopenharmony_ci GateRef jsThis, GateRef newTable); 7274514f5e3Sopenharmony_citemplate void LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::SetLinked( 7284514f5e3Sopenharmony_ci GateRef jsThis, GateRef newTable); 7294514f5e3Sopenharmony_ci 7304514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 7314514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Get( 7324514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key) 7334514f5e3Sopenharmony_ci{ 7344514f5e3Sopenharmony_ci auto env = GetEnvironment(); 7354514f5e3Sopenharmony_ci Label cfgEntry(env); 7364514f5e3Sopenharmony_ci env->SubCfgEntry(&cfgEntry); 7374514f5e3Sopenharmony_ci Label exit(env); 7384514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::JS_ANY(), Undefined()); 7394514f5e3Sopenharmony_ci HashStubBuilder hashBuilder(this, glue_); 7404514f5e3Sopenharmony_ci GateRef hash = hashBuilder.GetHash(key); 7414514f5e3Sopenharmony_ci GateRef entry = FindElement(linkedTable, key, hash); 7424514f5e3Sopenharmony_ci Label findEntry(env); 7434514f5e3Sopenharmony_ci Branch(Int32Equal(entry, Int32(-1)), &exit, &findEntry); 7444514f5e3Sopenharmony_ci Bind(&findEntry); 7454514f5e3Sopenharmony_ci { 7464514f5e3Sopenharmony_ci res = GetValue(linkedTable, entry); 7474514f5e3Sopenharmony_ci Jump(&exit); 7484514f5e3Sopenharmony_ci } 7494514f5e3Sopenharmony_ci 7504514f5e3Sopenharmony_ci Bind(&exit); 7514514f5e3Sopenharmony_ci auto ret = *res; 7524514f5e3Sopenharmony_ci env->SubCfgExit(); 7534514f5e3Sopenharmony_ci return ret; 7544514f5e3Sopenharmony_ci} 7554514f5e3Sopenharmony_ci 7564514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Get( 7574514f5e3Sopenharmony_ci GateRef linkedTable, GateRef key); 7584514f5e3Sopenharmony_ci 7594514f5e3Sopenharmony_citemplate <typename LinkedHashTableType, typename LinkedHashTableObject> 7604514f5e3Sopenharmony_ciGateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GetLinkedOffset() 7614514f5e3Sopenharmony_ci{ 7624514f5e3Sopenharmony_ci int32_t linkedTableOffset = 0; 7634514f5e3Sopenharmony_ci if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashMap>) { 7644514f5e3Sopenharmony_ci linkedTableOffset = JSMap::LINKED_MAP_OFFSET; 7654514f5e3Sopenharmony_ci } else { 7664514f5e3Sopenharmony_ci static_assert(std::is_same_v<LinkedHashTableType, LinkedHashSet>); 7674514f5e3Sopenharmony_ci linkedTableOffset = JSSet::LINKED_SET_OFFSET; 7684514f5e3Sopenharmony_ci } 7694514f5e3Sopenharmony_ci return IntPtr(linkedTableOffset); 7704514f5e3Sopenharmony_ci} 7714514f5e3Sopenharmony_ci 7724514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::GetLinkedOffset(); 7734514f5e3Sopenharmony_citemplate GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::GetLinkedOffset(); 7744514f5e3Sopenharmony_ci 7754514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 776