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, &notHole);
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(&notHole);
664514f5e3Sopenharmony_ci        {
674514f5e3Sopenharmony_ci            Label weak(env);
684514f5e3Sopenharmony_ci            Label notWeak(env);
694514f5e3Sopenharmony_ci            BRANCH(TaggedIsWeak(*key), &weak, &notWeak);
704514f5e3Sopenharmony_ci            Bind(&weak);
714514f5e3Sopenharmony_ci            {
724514f5e3Sopenharmony_ci                key = RemoveTaggedWeakTag(*key);
734514f5e3Sopenharmony_ci                Jump(&notWeak);
744514f5e3Sopenharmony_ci            }
754514f5e3Sopenharmony_ci            Bind(&notWeak);
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, &notHole);
2664514f5e3Sopenharmony_ci            Bind(&notHole);
2674514f5e3Sopenharmony_ci            {
2684514f5e3Sopenharmony_ci                Label weak(env);
2694514f5e3Sopenharmony_ci                Label notWeak(env);
2704514f5e3Sopenharmony_ci                BRANCH(TaggedIsWeak(*element), &weak, &notWeak);
2714514f5e3Sopenharmony_ci                Bind(&weak);
2724514f5e3Sopenharmony_ci                {
2734514f5e3Sopenharmony_ci                    element = RemoveTaggedWeakTag(*element);
2744514f5e3Sopenharmony_ci                    Jump(&notWeak);
2754514f5e3Sopenharmony_ci                }
2764514f5e3Sopenharmony_ci                Bind(&notWeak);
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, &notHasException);
4694514f5e3Sopenharmony_ci        Bind(&hasException);
4704514f5e3Sopenharmony_ci        {
4714514f5e3Sopenharmony_ci            res = retValue;
4724514f5e3Sopenharmony_ci            Jump(&exit);
4734514f5e3Sopenharmony_ci        }
4744514f5e3Sopenharmony_ci        Bind(&notHasException);
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)), &notFind, &findEntry);
5344514f5e3Sopenharmony_ci    Bind(&findEntry);
5354514f5e3Sopenharmony_ci    {
5364514f5e3Sopenharmony_ci        SetValue(linkedTable, entry, value);
5374514f5e3Sopenharmony_ci        Jump(&exit);
5384514f5e3Sopenharmony_ci    }
5394514f5e3Sopenharmony_ci    Bind(&notFind);
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