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, ¬Hole);
57 Bind(&hole);
58 {
59 currentDeletedElements = Int32Add(*currentDeletedElements, Int32(1));
60 SetDeletedNum(linkedTable, *i, *currentDeletedElements);
61 Jump(&loopEnd);
62 }
63 Bind(¬Hole);
64 {
65 Label weak(env);
66 Label notWeak(env);
67 Branch(TaggedIsWeak(*key), &weak, ¬Weak);
68 Bind(&weak);
69 {
70 key = RemoveTaggedWeakTag(*key);
71 Jump(¬Weak);
72 }
73 Bind(¬Weak);
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, ¬Hole);
303 Bind(¬Hole);
304 {
305 Label weak(env);
306 Label notWeak(env);
307 Branch(TaggedIsWeak(*element), &weak, ¬Weak);
308 Bind(&weak);
309 {
310 element = RemoveTaggedWeakTag(*element);
311 Jump(¬Weak);
312 }
313 Bind(¬Weak);
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, ¬HasException);
487 Bind(&hasException);
488 {
489 res = retValue;
490 Jump(&exit);
491 }
492 Bind(¬HasException);
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)), ¬Find, &findEntry);
550 Bind(&findEntry);
551 {
552 SetValue(linkedTable, entry, value);
553 Jump(&exit);
554 }
555 Bind(¬Find);
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