• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/compiler/builtins/linked_hashtable_stub_builder.h"
17 
18 #include "ecmascript/compiler/builtins/builtins_stubs.h"
19 #include "ecmascript/compiler/new_object_stub_builder.h"
20 #include "ecmascript/linked_hash_table.h"
21 #include "ecmascript/js_set.h"
22 #include "ecmascript/js_map.h"
23 
24 namespace panda::ecmascript::kungfu {
25 template <typename LinkedHashTableType, typename LinkedHashTableObject>
Rehash(GateRef linkedTable,GateRef newTable)26 void LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Rehash(
27     GateRef linkedTable, GateRef newTable)
28 {
29     auto env = GetEnvironment();
30     Label entryLabel(env);
31     env->SubCfgEntry(&entryLabel);
32 
33     GateRef numberOfAllElements = Int32Add(GetNumberOfElements(linkedTable),
34         GetNumberOfDeletedElements(linkedTable));
35 
36     DEFVARIABLE(desEntry, VariableType::INT32(), Int32(0));
37     DEFVARIABLE(currentDeletedElements, VariableType::INT32(), Int32(0));
38     SetNextTable(linkedTable, newTable);
39 
40     Label loopHead(env);
41     Label loopEnd(env);
42     Label next(env);
43     Label loopExit(env);
44 
45     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
46     Jump(&loopHead);
47     LoopBegin(&loopHead);
48     {
49         Branch(Int32LessThan(*i, numberOfAllElements), &next, &loopExit);
50         Bind(&next);
51 
52         GateRef fromIndex = EntryToIndex(linkedTable, *i);
53         DEFVARIABLE(key, VariableType::JS_ANY(), GetElement(linkedTable, fromIndex));
54         Label hole(env);
55         Label notHole(env);
56         Branch(TaggedIsHole(*key), &hole, &notHole);
57         Bind(&hole);
58         {
59             currentDeletedElements = Int32Add(*currentDeletedElements, Int32(1));
60             SetDeletedNum(linkedTable, *i, *currentDeletedElements);
61             Jump(&loopEnd);
62         }
63         Bind(&notHole);
64         {
65             Label weak(env);
66             Label notWeak(env);
67             Branch(TaggedIsWeak(*key), &weak, &notWeak);
68             Bind(&weak);
69             {
70                 key = RemoveTaggedWeakTag(*key);
71                 Jump(&notWeak);
72             }
73             Bind(&notWeak);
74 
75             GateRef hash = GetHash(*key);
76             GateRef bucket = HashToBucket(newTable, hash);
77             InsertNewEntry(newTable, bucket, *desEntry);
78             GateRef desIndex = EntryToIndex(newTable, *desEntry);
79 
80             Label loopHead1(env);
81             Label loopEnd1(env);
82             Label next1(env);
83             Label loopExit1(env);
84             DEFVARIABLE(j, VariableType::INT32(), Int32(0));
85             Jump(&loopHead1);
86             LoopBegin(&loopHead1);
87             {
88                 Branch(Int32LessThan(*j, Int32(LinkedHashTableObject::ENTRY_SIZE)), &next1, &loopExit1);
89                 Bind(&next1);
90                 GateRef ele = GetElement(linkedTable, Int32Add(fromIndex, *j));
91                 SetElement(newTable, Int32Add(desIndex, *j), ele);
92                 Jump(&loopEnd1);
93             }
94             Bind(&loopEnd1);
95             j = Int32Add(*j, Int32(1));
96             LoopEnd(&loopHead1);
97             Bind(&loopExit1);
98             desEntry = Int32Add(*desEntry, Int32(1));
99             Jump(&loopEnd);
100         }
101     }
102     Bind(&loopEnd);
103     i = Int32Add(*i, Int32(1));
104     LoopEnd(&loopHead);
105     Bind(&loopExit);
106 
107     SetNumberOfElements(newTable, GetNumberOfElements(linkedTable));
108     SetNumberOfDeletedElements(newTable, Int32(0));
109     env->SubCfgExit();
110 }
111 
112 template <typename LinkedHashTableType, typename LinkedHashTableObject>
GrowCapacity(GateRef linkedTable,GateRef numberOfAddedElements)113 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GrowCapacity(
114     GateRef linkedTable, GateRef numberOfAddedElements)
115 {
116     auto env = GetEnvironment();
117     Label entryLabel(env);
118     env->SubCfgEntry(&entryLabel);
119     Label exit(env);
120     DEFVARIABLE(res, VariableType::JS_ANY(), linkedTable);
121 
122     GateRef hasSufficient = HasSufficientCapacity(linkedTable, numberOfAddedElements);
123     Label grow(env);
124     Branch(hasSufficient, &exit, &grow);
125     Bind(&grow);
126     {
127         GateRef newCapacity = ComputeCapacity(Int32Add(GetNumberOfElements(linkedTable), numberOfAddedElements));
128         GateRef newTable = Create(newCapacity);
129         Rehash(linkedTable, newTable);
130         res = newTable;
131         Jump(&exit);
132     }
133     Bind(&exit);
134     auto ret = *res;
135     env->SubCfgExit();
136     return ret;
137 }
138 
139 template <typename LinkedHashTableType, typename LinkedHashTableObject>
ComputeCapacity(GateRef atLeastSpaceFor)140 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::ComputeCapacity(
141     GateRef atLeastSpaceFor)
142 {
143     if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashMap>) {
144         return TaggedGetInt(CallRuntime(glue_, RTSTUB_ID(LinkedHashMapComputeCapacity), {
145         IntToTaggedInt(atLeastSpaceFor) }));
146     } else {
147         return TaggedGetInt(CallRuntime(glue_, RTSTUB_ID(LinkedHashSetComputeCapacity), {
148         IntToTaggedInt(atLeastSpaceFor) }));
149     }
150 }
151 
152 template <typename LinkedHashTableType, typename LinkedHashTableObject>
RemoveEntry(GateRef linkedTable,GateRef entry)153 void LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::RemoveEntry(
154     GateRef linkedTable, GateRef entry)
155 {
156     auto env = GetEnvironment();
157     Label entryLabel(env);
158     Label exit(env);
159     env->SubCfgEntry(&entryLabel);
160     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
161 
162     Label loopHead(env);
163     Label loopEnd(env);
164     Label next(env);
165     Label loopExit(env);
166     GateRef index = EntryToIndex(linkedTable, entry);
167     Jump(&loopHead);
168     LoopBegin(&loopHead);
169     {
170         Branch(Int32LessThan(*i, Int32(LinkedHashTableObject::ENTRY_SIZE)), &next, &loopExit);
171         Bind(&next);
172 
173         GateRef idx = Int32Add(index, *i);
174         SetElement(linkedTable, idx, Hole());
175         Jump(&loopEnd);
176     }
177     Bind(&loopEnd);
178     i = Int32Add(*i, Int32(1));
179     LoopEnd(&loopHead);
180     Bind(&loopExit);
181 
182     GateRef newNofe = Int32Sub(GetNumberOfElements(linkedTable), Int32(1));
183     SetNumberOfElements(linkedTable, newNofe);
184     GateRef newNofd = Int32Add(GetNumberOfDeletedElements(linkedTable), Int32(1));
185     SetNumberOfDeletedElements(linkedTable, newNofd);
186     env->SubCfgExit();
187 }
188 
189 template <typename LinkedHashTableType, typename LinkedHashTableObject>
HasSufficientCapacity(GateRef linkedTable,GateRef numOfAddElements)190 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::HasSufficientCapacity(
191     GateRef linkedTable, GateRef numOfAddElements)
192 {
193     auto env = GetEnvironment();
194     Label entryLabel(env);
195     Label exit(env);
196     env->SubCfgEntry(&entryLabel);
197     DEFVARIABLE(res, VariableType::BOOL(), False());
198 
199     GateRef numberOfElements = GetNumberOfElements(linkedTable);
200     GateRef numOfDelElements = GetNumberOfDeletedElements(linkedTable);
201     GateRef nof = Int32Add(numberOfElements, numOfAddElements);
202     GateRef capacity = GetCapacity(linkedTable);
203     GateRef less = Int32LessThan(nof, capacity);
204     GateRef half = Int32Div(Int32Sub(capacity, nof), Int32(2));
205     GateRef lessHalf = Int32LessThanOrEqual(numOfDelElements, half);
206 
207     Label lessLable(env);
208     Branch(BoolAnd(less, lessHalf), &lessLable, &exit);
209     Bind(&lessLable);
210     {
211         Label need(env);
212         Branch(Int32LessThanOrEqual(Int32Add(nof, Int32Div(nof, Int32(2))), capacity), &need, &exit);
213         Bind(&need);
214         {
215             res = True();
216             Jump(&exit);
217         }
218     }
219     Bind(&exit);
220     auto ret = *res;
221     env->SubCfgExit();
222     return ret;
223 }
224 
225 template <typename LinkedHashTableType, typename LinkedHashTableObject>
GetHash(GateRef key)226 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GetHash(GateRef key)
227 {
228     auto env = GetEnvironment();
229     Label entryLabel(env);
230     Label exit(env);
231     env->SubCfgEntry(&entryLabel);
232     DEFVARIABLE(res, VariableType::INT32(), Int32(0));
233 
234     Label symbolKey(env);
235     Label stringCheck(env);
236     Branch(TaggedIsSymbol(key), &symbolKey, &stringCheck);
237     Bind(&symbolKey);
238     {
239         res = Load(VariableType::INT32(), key, IntPtr(JSSymbol::HASHFIELD_OFFSET));
240         Jump(&exit);
241     }
242     Bind(&stringCheck);
243     Label stringKey(env);
244     Label slowGetHash(env);
245     Branch(TaggedIsString(key), &stringKey, &slowGetHash);
246     Bind(&stringKey);
247     {
248         res = GetHashcodeFromString(glue_, key);
249         Jump(&exit);
250     }
251     Bind(&slowGetHash);
252     {
253         // GetHash();
254         GateRef hash = CallRuntime(glue_, RTSTUB_ID(GetLinkedHash), { key });
255         res = GetInt32OfTInt(hash);
256         Jump(&exit);
257     }
258     Bind(&exit);
259     auto ret = *res;
260     env->SubCfgExit();
261     return ret;
262 }
263 
264 template <typename LinkedHashTableType, typename LinkedHashTableObject>
HashObjectIsMatch(GateRef key,GateRef other)265 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::HashObjectIsMatch(
266     GateRef key, GateRef other)
267 {
268     return SameValueZero(glue_, key, other);
269 }
270 
271 template <typename LinkedHashTableType, typename LinkedHashTableObject>
FindElement(GateRef linkedTable,GateRef key)272 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::FindElement(
273     GateRef linkedTable, GateRef key)
274 {
275     auto env = GetEnvironment();
276     Label entryLabel(env);
277     env->SubCfgEntry(&entryLabel);
278 
279     DEFVARIABLE(res, VariableType::INT32(), Int32(-1));
280     Label exit(env);
281     Label isKey(env);
282     Branch(IsKey(key), &isKey, &exit);
283     Bind(&isKey);
284     {
285         GateRef hash = GetHash(key);
286         GateRef bucket = HashToBucket(linkedTable, hash);
287         GateRef index = BucketToIndex(bucket);
288         DEFVARIABLE(entry, VariableType::JS_ANY(), GetElement(linkedTable, index));
289         Label loopHead(env);
290         Label loopEnd(env);
291         Label next(env);
292         Label loopExit(env);
293 
294         Jump(&loopHead);
295         LoopBegin(&loopHead);
296         {
297             Branch(TaggedIsHole(*entry), &loopExit, &next);
298             Bind(&next);
299 
300             DEFVARIABLE(element, VariableType::JS_ANY(), GetKey(linkedTable, TaggedGetInt(*entry)));
301             Label notHole(env);
302             Branch(TaggedIsHole(*element), &loopEnd, &notHole);
303             Bind(&notHole);
304             {
305                 Label weak(env);
306                 Label notWeak(env);
307                 Branch(TaggedIsWeak(*element), &weak, &notWeak);
308                 Bind(&weak);
309                 {
310                     element = RemoveTaggedWeakTag(*element);
311                     Jump(&notWeak);
312                 }
313                 Bind(&notWeak);
314                 Label match(env);
315                 Branch(HashObjectIsMatch(key, *element), &match, &loopEnd);
316                 Bind(&match);
317                 {
318                     res = TaggedGetInt(*entry);
319                     Jump(&loopExit);
320                 }
321             }
322         }
323         Bind(&loopEnd);
324         entry = GetNextEntry(linkedTable, TaggedGetInt(*entry));
325         LoopEnd(&loopHead);
326         Bind(&loopExit);
327         Jump(&exit);
328     }
329     Bind(&exit);
330     auto ret = *res;
331     env->SubCfgExit();
332     return ret;
333 }
334 
335 template <typename LinkedHashTableType, typename LinkedHashTableObject>
GetDeletedElementsAt(GateRef linkedTable,GateRef entry)336 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GetDeletedElementsAt(
337     GateRef linkedTable, GateRef entry)
338 {
339     auto env = GetEnvironment();
340     Label entryLabel(env);
341     env->SubCfgEntry(&entryLabel);
342     Label exit(env);
343     DEFVARIABLE(res, VariableType::INT32(), Int32(0));
344     DEFVARIABLE(currentEntry, VariableType::INT32(), Int32Sub(entry, Int32(1)));
345     Label loopHead(env);
346     Label loopEnd(env);
347     Label next(env);
348     Label loopExit(env);
349 
350     Jump(&loopHead);
351     LoopBegin(&loopHead);
352     {
353         Branch(Int32GreaterThanOrEqual(*currentEntry, Int32(0)), &next, &loopExit);
354         Bind(&next);
355         GateRef key = GetKey(linkedTable, *currentEntry);
356         Label hole(env);
357         Branch(TaggedIsHole(key), &hole, &loopEnd);
358         Bind(&hole);
359         {
360             GateRef deletedNum = GetDeletedNum(linkedTable, *currentEntry);
361             res = deletedNum;
362             Jump(&exit);
363         }
364     }
365     Bind(&loopEnd);
366     currentEntry = Int32Sub(*currentEntry, Int32(1));
367     LoopEnd(&loopHead);
368     Bind(&loopExit);
369     Jump(&exit);
370     Bind(&exit);
371     auto ret = *res;
372     env->SubCfgExit();
373     return ret;
374 }
375 
376 template<typename LinkedHashTableType, typename LinkedHashTableObject>
Create(GateRef numberOfElements)377 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Create(GateRef numberOfElements)
378 {
379     auto env = GetEnvironment();
380     Label entry(env);
381     env->SubCfgEntry(&entry);
382     Label exit(env);
383 
384     // new LinkedHashTable
385     GateRef length = CalNewTaggedArrayLength(numberOfElements);
386     NewObjectStubBuilder newBuilder(this);
387     GateRef array = newBuilder.NewTaggedArray(glue_, length);
388 
389     Label noException(env);
390     Branch(TaggedIsException(array), &exit, &noException);
391     Bind(&noException);
392     {
393         // SetNumberOfElements
394         SetNumberOfElements(array, Int32(0));
395         // SetNumberOfDeletedElements
396         SetNumberOfDeletedElements(array, Int32(0));
397         // SetCapacity
398         SetCapacity(array, numberOfElements);
399         Jump(&exit);
400     }
401     Bind(&exit);
402     env->SubCfgExit();
403     return array;
404 }
405 
406 template<typename LinkedHashTableType, typename LinkedHashTableObject>
Clear(GateRef linkedTable)407 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Clear(GateRef linkedTable)
408 {
409     auto env = GetEnvironment();
410     Label entry(env);
411     env->SubCfgEntry(&entry);
412     Label exit(env);
413     Label setLinked(env);
414 
415     GateRef newTable = Create(Int32(LinkedHashTableType::MIN_CAPACITY));
416     Label noException(env);
417     Branch(TaggedIsException(newTable), &exit, &noException);
418     Bind(&noException);
419 
420     GateRef cap = GetCapacity(linkedTable);
421     Label capGreaterZero(env);
422     Branch(Int32GreaterThan(cap, Int32(0)), &capGreaterZero, &exit);
423     Bind(&capGreaterZero);
424     {
425         // NextTable
426         SetNextTable(linkedTable, newTable);
427         // SetNumberOfDeletedElements
428         SetNumberOfDeletedElements(linkedTable, Int32(-1));
429         Jump(&exit);
430     }
431 
432     Bind(&exit);
433     env->SubCfgExit();
434     return newTable;
435 }
436 
437 template GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Clear(GateRef);
438 template GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Clear(GateRef);
439 
440 template <typename LinkedHashTableType, typename LinkedHashTableObject>
ForEach(GateRef thisValue,GateRef srcLinkedTable,GateRef numArgs)441 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::ForEach(GateRef thisValue,
442     GateRef srcLinkedTable, GateRef numArgs)
443 {
444     auto env = GetEnvironment();
445     Label entry(env);
446     env->SubCfgEntry(&entry);
447     Label exit(env);
448     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
449 
450     // caller checked callbackFnHandle callable
451     GateRef callbackFnHandle = GetCallArg0(numArgs);
452     GateRef thisArg = GetCallArg1(numArgs);
453     DEFVARIABLE(linkedTable, VariableType::JS_ANY(), srcLinkedTable);
454 
455     GateRef numberOfElements = GetNumberOfElements(*linkedTable);
456     GateRef numberOfDeletedElements = GetNumberOfDeletedElements(*linkedTable);
457     GateRef tmpTotalElements = Int32Add(numberOfElements, numberOfDeletedElements);
458     DEFVARIABLE(totalElements, VariableType::INT32(), tmpTotalElements);
459     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
460 
461     Label loopHead(env);
462     Label loopEnd(env);
463     Label next(env);
464     Label loopExit(env);
465     Jump(&loopHead);
466     LoopBegin(&loopHead);
467     {
468         Branch(Int32LessThan(*index, *totalElements), &next, &loopExit);
469         Bind(&next);
470         GateRef valueIndex = *index;
471 
472         GateRef key = GetKey(*linkedTable, *index);
473         index = Int32Add(*index, Int32(1));
474         Label keyNotHole(env);
475         Branch(TaggedIsHole(key), &loopEnd, &keyNotHole);
476         Bind(&keyNotHole);
477 
478         GateRef value = key;
479         if constexpr (std::is_same_v<LinkedHashTableType, LinkedHashMap>) {
480             value = GetValue(*linkedTable, valueIndex);
481         }
482         Label hasException(env);
483         Label notHasException(env);
484         GateRef retValue = JSCallDispatch(glue_, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
485             Circuit::NullGate(), JSCallMode::CALL_THIS_ARG3_WITH_RETURN, { thisArg, value, key, thisValue });
486         Branch(HasPendingException(glue_), &hasException, &notHasException);
487         Bind(&hasException);
488         {
489             res = retValue;
490             Jump(&exit);
491         }
492         Bind(&notHasException);
493         {
494             // Maybe add or delete, get next table
495             GateRef tmpNextTable = GetNextTable(*linkedTable);
496             DEFVARIABLE(nextTable, VariableType::JS_ANY(), tmpNextTable);
497             Label loopHead1(env);
498             Label loopEnd1(env);
499             Label next1(env);
500             Label loopExit1(env);
501             Jump(&loopHead1);
502             LoopBegin(&loopHead1);
503             {
504                 Branch(TaggedIsHole(*nextTable), &loopExit1, &next1);
505                 Bind(&next1);
506                 GateRef deleted = GetDeletedElementsAt(*linkedTable, *index);
507                 index = Int32Sub(*index, deleted);
508                 linkedTable = *nextTable;
509                 nextTable = GetNextTable(*linkedTable);
510                 Jump(&loopEnd1);
511             }
512             Bind(&loopEnd1);
513             LoopEnd(&loopHead1);
514             Bind(&loopExit1);
515             // update totalElements
516             GateRef numberOfEle = GetNumberOfElements(*linkedTable);
517             GateRef numberOfDeletedEle = GetNumberOfDeletedElements(*linkedTable);
518             totalElements = Int32Add(numberOfEle, numberOfDeletedEle);
519             Jump(&loopEnd);
520         }
521     }
522     Bind(&loopEnd);
523     LoopEnd(&loopHead);
524     Bind(&loopExit);
525     Jump(&exit);
526 
527     Bind(&exit);
528     env->SubCfgExit();
529     return *res;
530 }
531 
532 template GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::ForEach(GateRef thisValue,
533     GateRef linkedTable, GateRef numArgs);
534 template GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::ForEach(GateRef thisValue,
535     GateRef linkedTable, GateRef numArgs);
536 
537 template <typename LinkedHashTableType, typename LinkedHashTableObject>
Insert(GateRef linkedTable,GateRef key,GateRef value)538 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Insert(
539     GateRef linkedTable, GateRef key, GateRef value)
540 {
541     auto env = GetEnvironment();
542     Label cfgEntry(env);
543     env->SubCfgEntry(&cfgEntry);
544     Label exit(env);
545     DEFVARIABLE(res, VariableType::JS_ANY(), linkedTable);
546     GateRef entry = FindElement(linkedTable, key);
547     Label findEntry(env);
548     Label notFind(env);
549     Branch(Int32Equal(entry, Int32(-1)), &notFind, &findEntry);
550     Bind(&findEntry);
551     {
552         SetValue(linkedTable, entry, value);
553         Jump(&exit);
554     }
555     Bind(&notFind);
556     {
557         GateRef newTable = GrowCapacity(linkedTable, Int32(1));
558         res = newTable;
559         GateRef hash = GetHash(key);
560         GateRef bucket = HashToBucket(newTable, hash);
561         GateRef numberOfElements = GetNumberOfElements(newTable);
562 
563         GateRef newEntry = Int32Add(numberOfElements, GetNumberOfDeletedElements(newTable));
564         InsertNewEntry(newTable, bucket, newEntry);
565         SetKey(newTable, newEntry, key);
566         SetValue(newTable, newEntry, value);
567         GateRef newNumberOfElements = Int32Add(numberOfElements, Int32(1));
568         SetNumberOfElements(newTable, newNumberOfElements);
569         Jump(&exit);
570     }
571 
572     Bind(&exit);
573     auto ret = *res;
574     env->SubCfgExit();
575     return ret;
576 }
577 
578 template GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Insert(
579     GateRef linkedTable, GateRef key, GateRef value);
580 template GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Insert(
581     GateRef linkedTable, GateRef key, GateRef value);
582 
583 template <typename LinkedHashTableType, typename LinkedHashTableObject>
Delete(GateRef linkedTable,GateRef key)584 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Delete(
585     GateRef linkedTable, GateRef key)
586 {
587     auto env = GetEnvironment();
588     Label cfgEntry(env);
589     env->SubCfgEntry(&cfgEntry);
590     Label exit(env);
591     DEFVARIABLE(res, VariableType::JS_ANY(), TaggedFalse());
592     GateRef entry = FindElement(linkedTable, key);
593     Label findEntry(env);
594     Branch(Int32Equal(entry, Int32(-1)), &exit, &findEntry);
595     Bind(&findEntry);
596     {
597         RemoveEntry(linkedTable, entry);
598         res = TaggedTrue();
599         Jump(&exit);
600     }
601 
602     Bind(&exit);
603     auto ret = *res;
604     env->SubCfgExit();
605     return ret;
606 }
607 
608 template GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Delete(
609     GateRef linkedTable, GateRef key);
610 template GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Delete(
611     GateRef linkedTable, GateRef key);
612 
613 template <typename LinkedHashTableType, typename LinkedHashTableObject>
Has(GateRef linkedTable,GateRef key)614 GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Has(
615     GateRef linkedTable, GateRef key)
616 {
617     auto env = GetEnvironment();
618     Label cfgEntry(env);
619     env->SubCfgEntry(&cfgEntry);
620     Label exit(env);
621     DEFVARIABLE(res, VariableType::JS_ANY(), TaggedFalse());
622     GateRef entry = FindElement(linkedTable, key);
623     Label findEntry(env);
624     Branch(Int32Equal(entry, Int32(-1)), &exit, &findEntry);
625     Bind(&findEntry);
626     {
627         res = TaggedTrue();
628         Jump(&exit);
629     }
630 
631     Bind(&exit);
632     auto ret = *res;
633     env->SubCfgExit();
634     return ret;
635 }
636 
637 template GateRef LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject>::Has(
638     GateRef linkedTable, GateRef key);
639 template GateRef LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject>::Has(
640     GateRef linkedTable, GateRef key);
641 }  // namespace panda::ecmascript::kungfu
642