1/*
2 * Copyright (c) 2021 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/common_stubs.h"
17
18#include "ecmascript/base/number_helper.h"
19#include "ecmascript/compiler/access_object_stub_builder.h"
20#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
21#include "ecmascript/compiler/builtins/linked_hashtable_stub_builder.h"
22#include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h"
23#include "ecmascript/compiler/interpreter_stub.h"
24#include "ecmascript/compiler/new_object_stub_builder.h"
25#include "ecmascript/compiler/operations_stub_builder.h"
26#include "ecmascript/compiler/stub_builder-inl.h"
27#include "ecmascript/compiler/variable_type.h"
28#include "ecmascript/js_array.h"
29#include "ecmascript/js_map.h"
30#include "ecmascript/js_map_iterator.h"
31#include "ecmascript/js_set.h"
32#include "ecmascript/js_set_iterator.h"
33#include "ecmascript/linked_hash_table.h"
34#include "ecmascript/message_string.h"
35#include "ecmascript/tagged_hash_table.h"
36
37namespace panda::ecmascript::kungfu {
38using namespace panda::ecmascript;
39
40void AddStubBuilder::GenerateCircuit()
41{
42    GateRef glue = PtrArgument(0);
43    GateRef x = TaggedArgument(1);
44    GateRef y = TaggedArgument(2);
45    OperationsStubBuilder operationBuilder(this);
46    Return(operationBuilder.Add(glue, x, y));
47}
48
49void SubStubBuilder::GenerateCircuit()
50{
51    GateRef glue = PtrArgument(0);
52    GateRef x = TaggedArgument(1);
53    GateRef y = TaggedArgument(2);
54    OperationsStubBuilder operationBuilder(this);
55    Return(operationBuilder.Sub(glue, x, y));
56}
57
58void DefineFieldStubBuilder::GenerateCircuit()
59{
60    GateRef glue = PtrArgument(0);
61    GateRef receiver = TaggedArgument(1);
62    GateRef propKey = TaggedArgument(2);    // 2: 3rd argument
63    GateRef acc = TaggedArgument(3);        // 3: 4th argument
64    Return(DefineField(glue, receiver, propKey, acc));
65}
66
67void DefinefuncStubBuilder::GenerateCircuit()
68{
69    auto env = GetEnvironment();
70    GateRef glue = PtrArgument(0);
71    GateRef jsFunc = TaggedArgument(1);
72    GateRef methodId = Int32Argument(2); // 2: 3rd argument
73    GateRef length = Int32Argument(3);   // 3: 4th argument
74    GateRef lexEnv = TaggedArgument(4);  // 4: 5th argument
75    GateRef slotId = Int32Argument(5);   // 5: 6th argument
76
77    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
78    Label exit(env);
79    Label failed(env);
80    NewObjectStubBuilder newBuilder(this);
81    newBuilder.NewJSFunction(glue, jsFunc, methodId, length, lexEnv, &result, &exit, &failed, slotId);
82    Bind(&failed);
83    {
84        result = Exception();
85        Jump(&exit);
86    }
87    Bind(&exit);
88    Return(*result);
89}
90
91void ConvertCharToInt32StubBuilder::GenerateCircuit()
92{
93    GateRef glue = PtrArgument(0);
94    GateRef charCode = Int32Argument(1);
95    BuiltinsStringStubBuilder builder(this);
96    // char to string
97    GateRef result = builder.CreateStringBySingleCharCode(glue, charCode);
98    // string to number
99    result = CallNGCRuntime(glue, RTSTUB_ID(StringToNumber), {result, Int32(0)}, charCode);
100    // get int from number
101    result = NumberGetInt(glue, result);
102    Return(result);
103}
104
105void ConvertCharToDoubleStubBuilder::GenerateCircuit()
106{
107    GateRef glue = PtrArgument(0);
108    GateRef charCode = Int32Argument(1);
109    BuiltinsStringStubBuilder builder(this);
110    // char to string
111    GateRef result = builder.CreateStringBySingleCharCode(glue, charCode);
112    // string to number
113    result = CallNGCRuntime(glue, RTSTUB_ID(StringToNumber), {result, Int32(0)}, charCode);
114    // get double from number
115    result = GetDoubleOfTNumber(result);
116    Return(result);
117}
118
119void MulStubBuilder::GenerateCircuit()
120{
121    GateRef glue = PtrArgument(0);
122    GateRef x = TaggedArgument(1);
123    GateRef y = TaggedArgument(2);
124    OperationsStubBuilder operationBuilder(this);
125    Return(operationBuilder.Mul(glue, x, y));
126}
127
128void DivStubBuilder::GenerateCircuit()
129{
130    GateRef glue = PtrArgument(0);
131    GateRef x = TaggedArgument(1);
132    GateRef y = TaggedArgument(2);
133    OperationsStubBuilder operationBuilder(this);
134    Return(operationBuilder.Div(glue, x, y));
135}
136
137void ModStubBuilder::GenerateCircuit()
138{
139    GateRef glue = PtrArgument(0);
140    GateRef x = TaggedArgument(1);
141    GateRef y = TaggedArgument(2); // 2: 3rd argument
142    OperationsStubBuilder operationBuilder(this);
143    Return(operationBuilder.Mod(glue, x, y));
144}
145
146void TypeOfStubBuilder::GenerateCircuit()
147{
148    GateRef glue = PtrArgument(0);
149    GateRef obj = TaggedArgument(1);
150    Return(FastTypeOf(glue, obj));
151}
152
153void EqualStubBuilder::GenerateCircuit()
154{
155    GateRef glue = PtrArgument(0);
156    GateRef x = TaggedArgument(1);
157    GateRef y = TaggedArgument(2); // 2: 3rd argument
158    OperationsStubBuilder operationBuilder(this);
159    Return(operationBuilder.Equal(glue, x, y));
160}
161
162void NotEqualStubBuilder::GenerateCircuit()
163{
164    GateRef glue = PtrArgument(0);
165    GateRef x = TaggedArgument(1);
166    GateRef y = TaggedArgument(2); // 2: 3rd argument
167    OperationsStubBuilder operationBuilder(this);
168    Return(operationBuilder.NotEqual(glue, x, y));
169}
170
171void StrictEqualStubBuilder::GenerateCircuit()
172{
173    GateRef glue = PtrArgument(0);
174    GateRef x = TaggedArgument(1);
175    GateRef y = TaggedArgument(2); // 2: 3rd argument
176    OperationsStubBuilder operationBuilder(this);
177    Return(operationBuilder.StrictEqual(glue, x, y));
178}
179
180void StrictNotEqualStubBuilder::GenerateCircuit()
181{
182    GateRef glue = PtrArgument(0);
183    GateRef x = TaggedArgument(1);
184    GateRef y = TaggedArgument(2); // 2: 3rd argument
185    OperationsStubBuilder operationBuilder(this);
186    Return(operationBuilder.StrictNotEqual(glue, x, y));
187}
188
189void LessStubBuilder::GenerateCircuit()
190{
191    GateRef glue = PtrArgument(0);
192    GateRef x = TaggedArgument(1);
193    GateRef y = TaggedArgument(2); // 2: 3rd argument
194    OperationsStubBuilder operationBuilder(this);
195    Return(operationBuilder.Less(glue, x, y));
196}
197
198void LessEqStubBuilder::GenerateCircuit()
199{
200    GateRef glue = PtrArgument(0);
201    GateRef x = TaggedArgument(1);
202    GateRef y = TaggedArgument(2); // 2: 3rd argument
203    OperationsStubBuilder operationBuilder(this);
204    Return(operationBuilder.LessEq(glue, x, y));
205}
206
207void GreaterStubBuilder::GenerateCircuit()
208{
209    GateRef glue = PtrArgument(0);
210    GateRef x = TaggedArgument(1);
211    GateRef y = TaggedArgument(2); // 2: 3rd argument
212    OperationsStubBuilder operationBuilder(this);
213    Return(operationBuilder.Greater(glue, x, y));
214}
215
216void GreaterEqStubBuilder::GenerateCircuit()
217{
218    GateRef glue = PtrArgument(0);
219    GateRef x = TaggedArgument(1);
220    GateRef y = TaggedArgument(2); // 2: 3rd argument
221    OperationsStubBuilder operationBuilder(this);
222    Return(operationBuilder.GreaterEq(glue, x, y));
223}
224
225void ShlStubBuilder::GenerateCircuit()
226{
227    GateRef glue = PtrArgument(0);
228    GateRef x = TaggedArgument(1);
229    GateRef y = TaggedArgument(2); // 2: 3rd argument
230    OperationsStubBuilder operationBuilder(this);
231    Return(operationBuilder.Shl(glue, x, y));
232}
233
234void ShrStubBuilder::GenerateCircuit()
235{
236    GateRef glue = PtrArgument(0);
237    GateRef x = TaggedArgument(1);
238    GateRef y = TaggedArgument(2); // 2: 3rd argument
239    OperationsStubBuilder operationBuilder(this);
240    Return(operationBuilder.Shr(glue, x, y));
241}
242
243void AshrStubBuilder::GenerateCircuit()
244{
245    GateRef glue = PtrArgument(0);
246    GateRef x = TaggedArgument(1);
247    GateRef y = TaggedArgument(2); // 2: 3rd argument
248    OperationsStubBuilder operationBuilder(this);
249    Return(operationBuilder.Ashr(glue, x, y));
250}
251
252void AndStubBuilder::GenerateCircuit()
253{
254    GateRef glue = PtrArgument(0);
255    GateRef x = TaggedArgument(1);
256    GateRef y = TaggedArgument(2); // 2: 3rd argument
257    OperationsStubBuilder operationBuilder(this);
258    Return(operationBuilder.And(glue, x, y));
259}
260
261void OrStubBuilder::GenerateCircuit()
262{
263    GateRef glue = PtrArgument(0);
264    GateRef x = TaggedArgument(1);
265    GateRef y = TaggedArgument(2); // 2: 3rd argument
266    OperationsStubBuilder operationBuilder(this);
267    Return(operationBuilder.Or(glue, x, y));
268}
269
270void XorStubBuilder::GenerateCircuit()
271{
272    GateRef glue = PtrArgument(0);
273    GateRef x = TaggedArgument(1);
274    GateRef y = TaggedArgument(2); // 2: 3rd argument
275    OperationsStubBuilder operationBuilder(this);
276    Return(operationBuilder.Xor(glue, x, y));
277}
278
279void InstanceofStubBuilder::GenerateCircuit()
280{
281    GateRef glue = PtrArgument(0);
282    GateRef object = TaggedArgument(1);
283    GateRef target = TaggedArgument(2); // 2: 3rd argument
284    GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
285    GateRef slotId = Int32Argument(4); // 4 : 5th pars
286    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
287    Return(InstanceOf(glue, object, target, profileTypeInfo, slotId, ProfileOperation()));
288}
289
290void IncStubBuilder::GenerateCircuit()
291{
292    GateRef glue = PtrArgument(0);
293    GateRef x = TaggedArgument(1);
294    OperationsStubBuilder operationBuilder(this);
295    Return(operationBuilder.Inc(glue, x));
296}
297
298void DecStubBuilder::GenerateCircuit()
299{
300    GateRef glue = PtrArgument(0);
301    GateRef x = TaggedArgument(1);
302    OperationsStubBuilder operationBuilder(this);
303    Return(operationBuilder.Dec(glue, x));
304}
305
306void NegStubBuilder::GenerateCircuit()
307{
308    GateRef glue = PtrArgument(0);
309    GateRef x = TaggedArgument(1);
310    OperationsStubBuilder operationBuilder(this);
311    Return(operationBuilder.Neg(glue, x));
312}
313
314void NotStubBuilder::GenerateCircuit()
315{
316    GateRef glue = PtrArgument(0);
317    GateRef x = TaggedArgument(1);
318    OperationsStubBuilder operationBuilder(this);
319    Return(operationBuilder.Not(glue, x));
320}
321
322void ToBooleanTrueStubBuilder::GenerateCircuit()
323{
324    GateRef glue = PtrArgument(0);
325    (void)glue;
326    GateRef x = TaggedArgument(1);
327    Return(FastToBoolean(x, true));
328}
329
330void ToBooleanFalseStubBuilder::GenerateCircuit()
331{
332    GateRef glue = PtrArgument(0);
333    (void)glue;
334    GateRef x = TaggedArgument(1);
335    Return(FastToBoolean(x, false));
336}
337
338void NewLexicalEnvStubBuilder::GenerateCircuit()
339{
340    auto env = GetEnvironment();
341    GateRef glue = PtrArgument(0);
342    GateRef parent = TaggedArgument(1);
343    GateRef numVars = Int32Argument(2); /* 2 : 3rd parameter is index */
344
345    DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
346    NewObjectStubBuilder newBuilder(this);
347    newBuilder.SetParameters(glue, 0);
348    Label afterNew(env);
349    newBuilder.NewLexicalEnv(&result, &afterNew, numVars, parent);
350    Bind(&afterNew);
351    Return(*result);
352}
353
354void CopyRestArgsStubBuilder::GenerateCircuit()
355{
356    DEFVARIABLE(arrayObj, VariableType::JS_ANY(), Undefined());
357    DEFVARIABLE(argv, VariableType::NATIVE_POINTER(), PtrArgument(1));
358    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
359    DEFVARIABLE(actualRestNum, VariableType::INT32(), Int32(0));
360    auto env = GetEnvironment();
361    GateRef glue = PtrArgument(0);
362    GateRef startIdx = Int32Argument(2); /* 2 : 3rd parameter is startIdx */
363    GateRef numArgs = Int32Argument(3); /* 3 : 4th parameter is numArgs */
364    GateRef argvTaggedArray = TaggedArgument(4); /* 4 : 5th parameter is argvTaggedArray */
365
366    Label numArgsGreater(env);
367    Label numArgsNotGreater(env);
368    Label afterCreateArrayObj(env);
369
370    GateRef actualArgc = Int32Sub(numArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
371    // 1. Calculate actual rest num.
372    BRANCH(Int32UnsignedGreaterThan(actualArgc, startIdx), &numArgsGreater, &numArgsNotGreater);
373    Bind(&numArgsGreater);
374    {
375        actualRestNum = Int32Sub(actualArgc, startIdx);
376        Jump(&numArgsNotGreater);
377    }
378    Bind(&numArgsNotGreater);
379    // 2. Construct RestArguments object.
380    NewObjectStubBuilder newBuilder(this);
381    newBuilder.SetParameters(glue, 0);
382    GateRef intialHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
383                                                  ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX);
384    arrayObj = newBuilder.NewJSArrayWithSize(intialHClass, *actualRestNum);
385
386    GateRef args = GetArgumentsElements(glue, argvTaggedArray, *argv);
387    newBuilder.AssignRestArg(&arrayObj, &afterCreateArrayObj, args, startIdx, *actualRestNum, intialHClass);
388    Bind(&afterCreateArrayObj);
389    Return(*arrayObj);
390}
391
392void GetUnmappedArgsStubBuilder::GenerateCircuit()
393{
394    auto env = GetEnvironment();
395    GateRef glue = PtrArgument(0);
396    GateRef numArgs = Int32Argument(2); /* 2 : 3rd parameter is numArgs */
397    GateRef argvTaggedArray = TaggedArgument(3); /* 3 : 4th parameter is argvTaggedArray */
398
399    DEFVARIABLE(argumentsList, VariableType::JS_ANY(), Hole());
400    DEFVARIABLE(argumentsObj, VariableType::JS_ANY(), Hole());
401    DEFVARIABLE(argv, VariableType::NATIVE_POINTER(), PtrArgument(1));
402    Label afterArgumentsList(env);
403    Label newArgumentsObj(env);
404    Label exit(env);
405
406    GateRef actualArgc = Int32Sub(numArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
407    GateRef startIdx = Int32(0);
408    NewObjectStubBuilder newBuilder(this);
409    newBuilder.SetParameters(glue, 0);
410
411    Label fillArguments(env);
412    Label argumentsException(env);
413    GateRef argumentsListObj = newBuilder.NewArgumentsListObj(actualArgc);
414    argumentsList.WriteVariable(argumentsListObj);
415    Branch(TaggedIsException(*argumentsList), &argumentsException, &fillArguments);
416    Bind(&argumentsException);
417    argumentsObj.WriteVariable(*argumentsList);
418    Jump(&exit);
419    Bind(&fillArguments);
420
421    GateRef args = GetArgumentsElements(glue, argvTaggedArray, *argv);
422    newBuilder.FillArgumentsList(*argumentsList, args, startIdx, actualArgc);
423    newBuilder.NewArgumentsObj(&argumentsObj, &exit, *argumentsList, actualArgc);
424    Bind(&exit);
425    Return(*argumentsObj);
426}
427
428void GetCallSpreadArgsStubBuilder::GenerateCircuit()
429{
430    GateRef glue = PtrArgument(0);
431    GateRef array = TaggedArgument(1);
432    Return(GetCallSpreadArgs(glue, array, ProfileOperation()));
433}
434
435void GetPropertyByIndexStubBuilder::GenerateCircuit()
436{
437    GateRef glue = PtrArgument(0);
438    GateRef receiver = TaggedArgument(1);
439    GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
440    Return(GetPropertyByIndex(glue, receiver, index, ProfileOperation()));
441}
442
443void SetPropertyByIndexStubBuilder::GenerateCircuit()
444{
445    GateRef glue = PtrArgument(0);
446    GateRef receiver = TaggedArgument(1);
447    GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
448    GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
449    Return(SetPropertyByIndex(glue, receiver, index, value, false));
450}
451
452void SetPropertyByIndexWithOwnStubBuilder::GenerateCircuit()
453{
454    GateRef glue = PtrArgument(0);
455    GateRef receiver = TaggedArgument(1);
456    GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
457    GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
458    Return(SetPropertyByIndex(glue, receiver, index, value, true));
459}
460
461void GetPropertyByNameStubBuilder::GenerateCircuit()
462{
463    GateRef glue = PtrArgument(0);
464    GateRef receiver = TaggedArgument(1);
465    GateRef id = Int64Argument(2); // 2 : 3rd para
466    GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
467    GateRef slotId = Int32Argument(4); // 4 : 5th para
468    AccessObjectStubBuilder builder(this, jsFunc);
469    StringIdInfo info(0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID);
470    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
471    Return(builder.LoadObjByName(glue, receiver, id, info, profileTypeInfo, slotId, ProfileOperation()));
472}
473
474void DeprecatedGetPropertyByNameStubBuilder::GenerateCircuit()
475{
476    GateRef glue = PtrArgument(0);
477    GateRef receiver = TaggedArgument(1);
478    GateRef key = TaggedPointerArgument(2); // 2 : 3rd para
479    AccessObjectStubBuilder builder(this);
480    Return(builder.DeprecatedLoadObjByName(glue, receiver, key));
481}
482
483void SetPropertyByNameStubBuilder::GenerateCircuit()
484{
485    GateRef glue = PtrArgument(0);
486    GateRef receiver = TaggedArgument(1);
487    GateRef id = Int64Argument(2); // 2 : 3rd para
488    GateRef value = TaggedPointerArgument(3); // 3 : 4th para
489    GateRef jsFunc = TaggedArgument(4); // 4 : 5th para
490    GateRef slotId = Int32Argument(5); // 5 : 6th para
491    AccessObjectStubBuilder builder(this, jsFunc);
492    StringIdInfo info(0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID);
493    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
494    Return(builder.StoreObjByName(glue, receiver, id, info, value, profileTypeInfo, slotId, ProfileOperation()));
495}
496
497void DeprecatedSetPropertyByNameStubBuilder::GenerateCircuit()
498{
499    GateRef glue = PtrArgument(0);
500    GateRef receiver = TaggedArgument(1);
501    GateRef key = TaggedArgument(2); // 2 : 3rd para
502    GateRef value = TaggedArgument(3); // 3 : 4th para
503    Return(SetPropertyByName(glue, receiver, key, value, false, True()));
504}
505
506void SetPropertyByNameWithOwnStubBuilder::GenerateCircuit()
507{
508    GateRef glue = PtrArgument(0);
509    GateRef receiver = TaggedArgument(1);
510    GateRef key = TaggedArgument(2); // 2 : 3rd para
511    GateRef value = TaggedArgument(3); // 3 : 4th para
512    Return(SetPropertyByName(glue, receiver, key, value, true, True()));
513}
514
515void GetPropertyByValueStubBuilder::GenerateCircuit()
516{
517    GateRef glue = PtrArgument(0);
518    GateRef receiver = TaggedArgument(1);
519    GateRef key = TaggedArgument(2); // 2 : 3rd para
520    GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
521    GateRef slotId = Int32Argument(4); // 4 : 5th para
522    AccessObjectStubBuilder builder(this);
523    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
524    Return(builder.LoadObjByValue(glue, receiver, key, profileTypeInfo, slotId));
525}
526
527void DeprecatedGetPropertyByValueStubBuilder::GenerateCircuit()
528{
529    GateRef glue = PtrArgument(0);
530    GateRef receiver = TaggedArgument(1);
531    GateRef key = TaggedArgument(2); // 2 : 3rd para
532    Return(GetPropertyByValue(glue, receiver, key, ProfileOperation()));
533}
534
535void SetPropertyByValueStubBuilder::GenerateCircuit()
536{
537    GateRef glue = PtrArgument(0);
538    GateRef receiver = TaggedArgument(1);
539    GateRef key = TaggedArgument(2);        // 2 : 3rd para
540    GateRef value = TaggedArgument(3);      // 3 : 4th para
541    GateRef jsFunc = TaggedArgument(4);     // 4 : 5th para
542    GateRef slotId = Int32Argument(5);      // 5 : 6th para
543    AccessObjectStubBuilder builder(this);
544    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
545    Return(builder.StoreObjByValue(glue, receiver, key, value, profileTypeInfo, slotId));
546}
547
548void DeprecatedSetPropertyByValueStubBuilder::GenerateCircuit()
549{
550    GateRef glue = PtrArgument(0);
551    GateRef receiver = TaggedArgument(1);
552    GateRef key = TaggedArgument(2);              /* 2 : 3rd parameter is key */
553    GateRef value = TaggedArgument(3);            /* 3 : 4th parameter is value */
554    Return(SetPropertyByValue(glue, receiver, key, value, false));
555}
556
557void SetPropertyByValueWithOwnStubBuilder::GenerateCircuit()
558{
559    GateRef glue = PtrArgument(0);
560    GateRef receiver = TaggedArgument(1);
561    GateRef key = TaggedArgument(2);              /* 2 : 3rd parameter is key */
562    GateRef value = TaggedArgument(3);            /* 3 : 4th parameter is value */
563    Return(SetPropertyByValue(glue, receiver, key, value, true));
564}
565
566void StOwnByIndexStubBuilder::GenerateCircuit()
567{
568    GateRef glue = PtrArgument(0);
569    GateRef receiver = TaggedArgument(1);
570    GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
571    GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
572    AccessObjectStubBuilder builder(this);
573    Return(builder.StOwnByIndex(glue, receiver, index, value));
574}
575
576void StOwnByValueStubBuilder::GenerateCircuit()
577{
578    GateRef glue = PtrArgument(0);
579    GateRef receiver = TaggedArgument(1);
580    GateRef key = TaggedArgument(2);              /* 2 : 3rd parameter is key */
581    GateRef value = TaggedArgument(3);            /* 3 : 4th parameter is value */
582    AccessObjectStubBuilder builder(this);
583    Return(builder.StOwnByValue(glue, receiver, key, value));
584}
585
586void StOwnByNameStubBuilder::GenerateCircuit()
587{
588    GateRef glue = PtrArgument(0);
589    GateRef receiver = TaggedArgument(1);
590    GateRef key = TaggedArgument(2); // 2 : 3rd para
591    GateRef value = TaggedArgument(3); // 3 : 4th para
592    AccessObjectStubBuilder builder(this);
593    Return(builder.StOwnByName(glue, receiver, key, value));
594}
595
596void StOwnByValueWithNameSetStubBuilder::GenerateCircuit()
597{
598    GateRef glue = PtrArgument(0);
599    GateRef receiver = TaggedArgument(1);
600    GateRef key = TaggedArgument(2);              /* 2 : 3rd parameter is key */
601    GateRef value = TaggedArgument(3);            /* 3 : 4th parameter is value */
602    AccessObjectStubBuilder builder(this);
603    Return(builder.StOwnByValueWithNameSet(glue, receiver, key, value));
604}
605
606void StOwnByNameWithNameSetStubBuilder::GenerateCircuit()
607{
608    GateRef glue = PtrArgument(0);
609    GateRef receiver = TaggedArgument(1);
610    GateRef key = TaggedArgument(2); // 2 : 3rd para
611    GateRef value = TaggedArgument(3); // 3 : 4th para
612    AccessObjectStubBuilder builder(this);
613    Return(builder.StOwnByNameWithNameSet(glue, receiver, key, value));
614}
615
616void LdObjByIndexStubBuilder::GenerateCircuit()
617{
618    GateRef glue = PtrArgument(0);
619    GateRef receiver = TaggedArgument(1);
620    GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
621    AccessObjectStubBuilder builder(this);
622    Return(builder.LdObjByIndex(glue, receiver, index));
623}
624
625void StObjByIndexStubBuilder::GenerateCircuit()
626{
627    GateRef glue = PtrArgument(0);
628    GateRef receiver = TaggedArgument(1);
629    GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
630    GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
631    AccessObjectStubBuilder builder(this);
632    Return(builder.StObjByIndex(glue, receiver, index, value));
633}
634
635void TryLdGlobalByNameStubBuilder::GenerateCircuit()
636{
637    GateRef glue = PtrArgument(0);
638    GateRef id = Int64Argument(1);
639    GateRef jsFunc = TaggedArgument(2); // 2 : 3th para
640    GateRef slotId = Int32Argument(3); // 3 : 4th para
641    AccessObjectStubBuilder builder(this, jsFunc);
642    StringIdInfo info(0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID);
643    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
644    Return(builder.TryLoadGlobalByName(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
645}
646
647void TryStGlobalByNameStubBuilder::GenerateCircuit()
648{
649    GateRef glue = PtrArgument(0);
650    GateRef id = Int64Argument(1);
651    GateRef value = TaggedArgument(2); // 2 : 3rd para
652    GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
653    GateRef slotId = Int32Argument(4);  // 4: 5th para
654    AccessObjectStubBuilder builder(this, jsFunc);
655    StringIdInfo info(0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID);
656    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
657    Return(builder.TryStoreGlobalByName(glue, id, info, value, profileTypeInfo, slotId, ProfileOperation()));
658}
659
660void LdGlobalVarStubBuilder::GenerateCircuit()
661{
662    GateRef glue = PtrArgument(0);
663    GateRef id = Int64Argument(1);
664    GateRef jsFunc = TaggedArgument(2); // 2 : 3th para
665    GateRef slotId = Int32Argument(3); // 3 : 4th para
666    AccessObjectStubBuilder builder(this, jsFunc);
667    StringIdInfo info(0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID);
668    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
669    Return(builder.LoadGlobalVar(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
670}
671
672void StGlobalVarStubBuilder::GenerateCircuit()
673{
674    GateRef glue = PtrArgument(0);
675    GateRef id = Int64Argument(1);
676    GateRef value = TaggedArgument(2); // 2 : 3rd para
677    GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
678    GateRef slotId = Int32Argument(4);  // 4: 5th para
679    AccessObjectStubBuilder builder(this, jsFunc);
680    StringIdInfo info(0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID);
681    GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
682    Return(builder.StoreGlobalVar(glue, id, info, value, profileTypeInfo, slotId));
683}
684
685void TryLoadICByNameStubBuilder::GenerateCircuit()
686{
687    auto env = GetEnvironment();
688    GateRef glue = PtrArgument(0);
689    GateRef receiver = TaggedArgument(1);
690    GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
691    GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
692
693    Label receiverIsHeapObject(env);
694    Label receiverNotHeapObject(env);
695    Label hclassEqualFirstValue(env);
696    Label hclassNotEqualFirstValue(env);
697    Label cachedHandlerNotHole(env);
698    BRANCH(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
699    Bind(&receiverIsHeapObject);
700    {
701        GateRef hclass = LoadHClass(receiver);
702        BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass),
703               &hclassEqualFirstValue,
704               &hclassNotEqualFirstValue);
705        Bind(&hclassEqualFirstValue);
706        {
707            Return(LoadICWithHandler(glue, receiver, receiver, secondValue, ProfileOperation()));
708        }
709        Bind(&hclassNotEqualFirstValue);
710        {
711            GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
712            BRANCH(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
713            Bind(&cachedHandlerNotHole);
714            {
715                Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
716            }
717        }
718    }
719    Bind(&receiverNotHeapObject);
720    {
721        Return(Hole());
722    }
723}
724
725void TryLoadICByValueStubBuilder::GenerateCircuit()
726{
727    auto env = GetEnvironment();
728    GateRef glue = PtrArgument(0);
729    GateRef receiver = TaggedArgument(1);
730    GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
731    GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
732    GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
733
734    Label receiverIsHeapObject(env);
735    Label receiverNotHeapObject(env);
736    Label hclassEqualFirstValue(env);
737    Label hclassNotEqualFirstValue(env);
738    Label firstValueEqualKey(env);
739    Label cachedHandlerNotHole(env);
740    BRANCH(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
741    Bind(&receiverIsHeapObject);
742    {
743        GateRef hclass = LoadHClass(receiver);
744        BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass),
745               &hclassEqualFirstValue,
746               &hclassNotEqualFirstValue);
747        Bind(&hclassEqualFirstValue);
748        Return(LoadElement(glue, receiver, key));
749        Bind(&hclassNotEqualFirstValue);
750        {
751            BRANCH(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
752            Bind(&firstValueEqualKey);
753            {
754                auto cachedHandler = CheckPolyHClass(secondValue, hclass);
755                BRANCH(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
756                Bind(&cachedHandlerNotHole);
757                Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
758            }
759        }
760    }
761    Bind(&receiverNotHeapObject);
762    Return(Hole());
763}
764
765void TryStoreICByNameStubBuilder::GenerateCircuit()
766{
767    auto env = GetEnvironment();
768    GateRef glue = PtrArgument(0);
769    GateRef receiver = TaggedArgument(1);
770    GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
771    GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
772    GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */
773    Label receiverIsHeapObject(env);
774    Label receiverNotHeapObject(env);
775    Label hclassEqualFirstValue(env);
776    Label hclassNotEqualFirstValue(env);
777    Label cachedHandlerNotHole(env);
778    BRANCH(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
779    Bind(&receiverIsHeapObject);
780    {
781        GateRef hclass = LoadHClass(receiver);
782        BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass),
783               &hclassEqualFirstValue,
784               &hclassNotEqualFirstValue);
785        Bind(&hclassEqualFirstValue);
786        {
787            Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue));
788        }
789        Bind(&hclassNotEqualFirstValue);
790        {
791            GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
792            BRANCH(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
793            Bind(&cachedHandlerNotHole);
794            {
795                Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
796            }
797        }
798    }
799    Bind(&receiverNotHeapObject);
800    Return(Hole());
801}
802
803void TryStoreICByValueStubBuilder::GenerateCircuit()
804{
805    auto env = GetEnvironment();
806    GateRef glue = PtrArgument(0);
807    GateRef receiver = TaggedArgument(1);
808    GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
809    GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
810    GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
811    GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */
812    Label receiverIsHeapObject(env);
813    Label receiverNotHeapObject(env);
814    Label hclassEqualFirstValue(env);
815    Label hclassNotEqualFirstValue(env);
816    Label firstValueEqualKey(env);
817    Label cachedHandlerNotHole(env);
818    BRANCH(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
819    Bind(&receiverIsHeapObject);
820    {
821        GateRef hclass = LoadHClass(receiver);
822        BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass),
823               &hclassEqualFirstValue,
824               &hclassNotEqualFirstValue);
825        Bind(&hclassEqualFirstValue);
826        Return(ICStoreElement(glue, receiver, key, value, secondValue));
827        Bind(&hclassNotEqualFirstValue);
828        {
829            BRANCH(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
830            Bind(&firstValueEqualKey);
831            {
832                GateRef cachedHandler = CheckPolyHClass(secondValue, hclass);
833                BRANCH(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
834                Bind(&cachedHandlerNotHole);
835                Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
836            }
837        }
838    }
839    Bind(&receiverNotHeapObject);
840    Return(Hole());
841}
842
843void SetValueWithBarrierStubBuilder::GenerateCircuit()
844{
845    GateRef glue = PtrArgument(0);
846    GateRef obj = TaggedArgument(1);
847    GateRef offset = PtrArgument(2); // 2 : 3rd para
848    GateRef value = TaggedArgument(3); // 3 : 4th para
849    SetValueWithBarrier(glue, obj, offset, value);
850    Return();
851}
852
853void SetNonSValueWithBarrierStubBuilder::GenerateCircuit()
854{
855    GateRef glue = PtrArgument(0);
856    GateRef obj = TaggedArgument(1);
857    GateRef offset = PtrArgument(2); // 2 : 3rd para
858    GateRef value = TaggedArgument(3); // 3 : 4th para
859    SetValueWithBarrier(glue, obj, offset, value, false, MemoryAttribute::NON_SHARE);
860    Return();
861}
862
863void SetValueWithEdenBarrierStubBuilder::GenerateCircuit()
864{
865    GateRef glue = PtrArgument(0);
866    GateRef obj = TaggedArgument(1);
867    GateRef offset = PtrArgument(2); // 2 : 3rd para
868    GateRef value = TaggedArgument(3); // 3 : 4th para
869    SetValueWithBarrier(glue, obj, offset, value, true);
870    Return();
871}
872
873void SetNonSValueWithEdenBarrierStubBuilder::GenerateCircuit()
874{
875    GateRef glue = PtrArgument(0);
876    GateRef obj = TaggedArgument(1);
877    GateRef offset = PtrArgument(2); // 2 : 3rd para
878    GateRef value = TaggedArgument(3); // 3 : 4th para
879    SetValueWithBarrier(glue, obj, offset, value, true, MemoryAttribute::NON_SHARE);
880    Return();
881}
882
883void SetSValueWithBarrierStubBuilder::GenerateCircuit()
884{
885    GateRef glue = PtrArgument(0);
886    GateRef obj = TaggedArgument(1);
887    GateRef offset = PtrArgument(2); // 2 : 3rd para
888    GateRef value = TaggedArgument(3); // 3 : 4th para
889    SetValueWithBarrier(glue, obj, offset, value, false, MemoryAttribute::SHARED);
890    Return();
891}
892
893void VerifyBarrierStubBuilder::GenerateCircuit()
894{
895    GateRef glue = PtrArgument(0);
896    GateRef obj = TaggedArgument(1);
897    GateRef offset = PtrArgument(2); // 2 : 3rd para
898    GateRef value = TaggedArgument(3); // 3 : 4th para
899    VerifyBarrier(glue, obj, offset, value);
900    Return();
901}
902
903void NewThisObjectCheckedStubBuilder::GenerateCircuit()
904{
905    GateRef glue = PtrArgument(0);
906    GateRef ctor = TaggedArgument(1);
907    NewObjectStubBuilder newBuilder(this);
908    Return(newBuilder.NewThisObjectChecked(glue, ctor));
909}
910
911void ConstructorCheckStubBuilder::GenerateCircuit()
912{
913    GateRef glue = PtrArgument(0);
914    GateRef ctor = TaggedArgument(1);
915    GateRef value = TaggedArgument(2); // 2 : 3rd para
916    GateRef thisObj = TaggedArgument(3); // 3 : 4th para
917    Return(ConstructorCheck(glue, ctor, value, thisObj));
918}
919
920void CreateEmptyArrayStubBuilder::GenerateCircuit()
921{
922    GateRef glue = PtrArgument(0);
923    NewObjectStubBuilder newBuilder(this);
924    Return(newBuilder.CreateEmptyArray(glue));
925}
926
927void CreateArrayWithBufferStubBuilder::GenerateCircuit()
928{
929    GateRef glue = PtrArgument(0);
930    GateRef index = Int32Argument(1);
931    GateRef jsFunc = TaggedArgument(2); // 2 : 3rd para
932    GateRef slotId = Int32Argument(5); // 5 : 6th para
933    NewObjectStubBuilder newBuilder(this);
934    Return(newBuilder.CreateArrayWithBuffer(
935        glue, index, jsFunc, { IntPtr(0), 0, true }, Undefined(), slotId, ProfileOperation()));
936}
937
938void NewJSObjectStubBuilder::GenerateCircuit()
939{
940    GateRef glue = PtrArgument(0);
941    GateRef ctor = TaggedArgument(1);
942    NewObjectStubBuilder newBuilder(this);
943    Return(newBuilder.FastNewThisObject(glue, ctor));
944}
945
946void JsBoundCallInternalStubBuilder::GenerateCircuit()
947{
948    auto env = GetEnvironment();
949    Label exit(env);
950    Label fastCall(env);
951    Label notFastCall(env);
952    Label methodIsFastCall(env);
953    Label fastCallBridge(env);
954    Label slowCall(env);
955    Label slowCallBridge(env);
956
957    GateRef glue = PtrArgument(0);
958    GateRef argc = Int64Argument(1);
959    GateRef func = TaggedPointerArgument(2); // callTarget
960    GateRef argv = PtrArgument(3);
961    GateRef thisValue = TaggedPointerArgument(4); // this
962    GateRef newTarget = TaggedPointerArgument(5); // new target
963    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
964    GateRef method = GetMethodFromFunction(func);
965    GateRef callfield = Load(VariableType::INT64(), method, IntPtr(Method::CALL_FIELD_OFFSET));
966    GateRef expectedNum = Int64And(Int64LSR(callfield, Int64(MethodLiteral::NumArgsBits::START_BIT)),
967        Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
968    GateRef expectedArgc = Int64Add(expectedNum, Int64(NUM_MANDATORY_JSFUNC_ARGS));
969    GateRef actualArgc = Int64Sub(argc, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
970    BRANCH(JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT_FASTCALL),
971        &methodIsFastCall, &notFastCall);
972    Bind(&methodIsFastCall);
973    {
974        BRANCH(Int64Equal(expectedArgc, argc), &fastCall, &fastCallBridge);
975        Bind(&fastCall);
976        {
977            result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgV),
978                { glue, func, thisValue, actualArgc, argv });
979            Jump(&exit);
980        }
981        Bind(&fastCallBridge);
982        {
983            result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgVAndPushArgv),
984                { glue, func, thisValue, actualArgc, argv, expectedNum });
985            Jump(&exit);
986        }
987    }
988    Bind(&notFastCall);
989    {
990        BRANCH(Int64Equal(expectedArgc, argc), &slowCall, &slowCallBridge);
991        Bind(&slowCall);
992        {
993            result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgV),
994                { glue, actualArgc, func, newTarget, thisValue, argv });
995            Jump(&exit);
996        }
997        Bind(&slowCallBridge);
998        {
999            result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgVAndPushArgv),
1000                { glue, actualArgc, func, newTarget, thisValue, argv });
1001            Jump(&exit);
1002        }
1003    }
1004    Bind(&exit);
1005    Return(*result);
1006}
1007
1008void GetSingleCharCodeByIndexStubBuilder::GenerateCircuit()
1009{
1010    GateRef str = TaggedArgument(1);
1011    GateRef index = Int32Argument(2);
1012    BuiltinsStringStubBuilder builder(this);
1013    GateRef result = builder.GetSingleCharCodeByIndex(str, index);
1014    Return(result);
1015}
1016
1017void CreateStringBySingleCharCodeStubBuilder::GenerateCircuit()
1018{
1019    GateRef glue = PtrArgument(0);
1020    GateRef charCode = Int32Argument(1);
1021    BuiltinsStringStubBuilder builder(this);
1022    GateRef result = builder.CreateStringBySingleCharCode(glue, charCode);
1023    Return(result);
1024}
1025
1026void FastStringEqualStubBuilder::GenerateCircuit()
1027{
1028    auto env = GetEnvironment();
1029    GateRef glue = PtrArgument(0);
1030    GateRef str1 = TaggedArgument(1);
1031    GateRef str2 = Int32Argument(2);
1032
1033    Label leftEqualRight(env);
1034    Label leftNotEqualRight(env);
1035    Label exit(env);
1036    DEFVARIABLE(result, VariableType::BOOL(), False());
1037    BRANCH(Equal(str1, str2), &leftEqualRight, &leftNotEqualRight);
1038    Bind(&leftEqualRight);
1039    {
1040        result = True();
1041        Jump(&exit);
1042    }
1043    Bind(&leftNotEqualRight);
1044    {
1045        result = FastStringEqual(glue, str1, str2);
1046        Jump(&exit);
1047    }
1048    Bind(&exit);
1049    Return(*result);
1050}
1051
1052void FastStringAddStubBuilder::GenerateCircuit()
1053{
1054    GateRef glue = PtrArgument(0);
1055    GateRef str1 = TaggedArgument(1);
1056    GateRef str2 = Int32Argument(2);
1057
1058    BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
1059    GateRef result = builtinsStringStubBuilder.StringConcat(glue, str1, str2);
1060    Return(result);
1061}
1062
1063void DeleteObjectPropertyStubBuilder::GenerateCircuit()
1064{
1065    GateRef glue = PtrArgument(0);
1066    GateRef object = TaggedArgument(1);
1067    GateRef prop = TaggedArgument(2);
1068    GateRef result = DeletePropertyOrThrow(glue, object, prop);
1069    Return(result);
1070}
1071
1072void GetpropiteratorStubBuilder::GenerateCircuit()
1073{
1074    GateRef glue = PtrArgument(0);
1075    GateRef object = TaggedArgument(1);
1076    NewObjectStubBuilder newBuilder(this);
1077    GateRef result = newBuilder.EnumerateObjectProperties(glue, object);
1078    Return(result);
1079}
1080
1081void GetnextpropnameStubBuilder::GenerateCircuit()
1082{
1083    GateRef glue = PtrArgument(0);
1084    GateRef iter = TaggedArgument(1);
1085    GateRef result = NextInternal(glue, iter);
1086    Return(result);
1087}
1088
1089#define CREATE_ITERATOR_STUB_BUILDER(name, collection, iterationKind)                                            \
1090void name##StubBuilder::GenerateCircuit()                                                                        \
1091{                                                                                                                \
1092    auto env = GetEnvironment();                                                                                 \
1093    Label exit(env);                                                                                             \
1094                                                                                                                 \
1095    GateRef glue = PtrArgument(0);                                                                               \
1096    GateRef obj = TaggedArgument(1);                                                                             \
1097    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());                                                    \
1098                                                                                                                 \
1099    NewObjectStubBuilder newBuilder(this);                                                                       \
1100    newBuilder.SetGlue(glue);                                                                                    \
1101    GateRef kind = Int32(static_cast<int32_t>(IterationKind::iterationKind));                                    \
1102    newBuilder.CreateJSCollectionIterator<JS##collection##Iterator, JS##collection>(&result, &exit, obj, kind);  \
1103    Bind(&exit);                                                                                                 \
1104    Return(*result);                                                                                             \
1105}
1106
1107CREATE_ITERATOR_STUB_BUILDER(CreateJSSetIterator, Set, VALUE)
1108CREATE_ITERATOR_STUB_BUILDER(JSSetEntries, Set, KEY_AND_VALUE)
1109CREATE_ITERATOR_STUB_BUILDER(JSMapKeys, Map, KEY)
1110CREATE_ITERATOR_STUB_BUILDER(JSMapValues, Map, VALUE)
1111CREATE_ITERATOR_STUB_BUILDER(CreateJSMapIterator, Map, KEY_AND_VALUE)
1112
1113void StringIteratorNextStubBuilder::GenerateCircuit()
1114{
1115    auto env = GetEnvironment();                                                                                 \
1116    Label exit(env);
1117    Label slowpath(env);
1118
1119    GateRef glue = PtrArgument(0);
1120    GateRef obj = TaggedArgument(1);
1121
1122    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1123
1124    BuiltinsStringStubBuilder builder(this);
1125    builder.StringIteratorNext(glue, obj, Gate::InvalidGateRef, &result, &exit, &slowpath);
1126    Bind(&slowpath);
1127    {
1128        result = CallRuntime(glue, RTSTUB_ID(StringIteratorNext), { obj });
1129        Jump(&exit);
1130    }
1131    Bind(&exit);
1132    Return(*result);
1133}
1134
1135void JSMapGetStubBuilder::GenerateCircuit()
1136{
1137    GateRef glue = PtrArgument(0);
1138    GateRef obj = TaggedArgument(1);
1139    GateRef key = TaggedArgument(2U);
1140
1141    LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> builder(this, glue);
1142    GateRef linkedTable = builder.GetLinked(obj);
1143    Return(builder.Get(linkedTable, key));
1144}
1145
1146void JSMapHasStubBuilder::GenerateCircuit()
1147{
1148    GateRef glue = PtrArgument(0);
1149    GateRef obj = TaggedArgument(1);
1150    GateRef key = TaggedArgument(2U);
1151
1152    LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> builder(this, glue);
1153    GateRef linkedTable = builder.GetLinked(obj);
1154    Return(builder.Has(linkedTable, key));
1155}
1156
1157void JSSetHasStubBuilder::GenerateCircuit()
1158{
1159    GateRef glue = PtrArgument(0);
1160    GateRef obj = TaggedArgument(1);
1161    GateRef key = TaggedArgument(2U);
1162
1163    LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> builder(this, glue);
1164    GateRef linkedTable = builder.GetLinked(obj);
1165    Return(builder.Has(linkedTable, key));
1166}
1167
1168void CreateJSTypedArrayEntriesStubBuilder::GenerateCircuit()
1169{
1170    auto env = GetEnvironment();
1171    Label exit(env);
1172
1173    GateRef glue = PtrArgument(0);
1174    GateRef obj = TaggedArgument(1);
1175    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1176
1177    NewObjectStubBuilder newBuilder(this);
1178    newBuilder.SetGlue(glue);
1179    GateRef kind = Int32(static_cast<int32_t>(IterationKind::KEY_AND_VALUE));
1180    newBuilder.CreateJSTypedArrayIterator(&result, &exit, obj, kind);
1181    Bind(&exit);
1182    Return(*result);
1183}
1184
1185void CreateJSTypedArrayKeysStubBuilder::GenerateCircuit()
1186{
1187    auto env = GetEnvironment();
1188    Label exit(env);
1189
1190    GateRef glue = PtrArgument(0);
1191    GateRef obj = TaggedArgument(1);
1192    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1193
1194    NewObjectStubBuilder newBuilder(this);
1195    newBuilder.SetGlue(glue);
1196    GateRef kind = Int32(static_cast<int32_t>(IterationKind::KEY));
1197    newBuilder.CreateJSTypedArrayIterator(&result, &exit, obj, kind);
1198    Bind(&exit);
1199    Return(*result);
1200}
1201
1202void CreateJSTypedArrayValuesStubBuilder::GenerateCircuit()
1203{
1204    auto env = GetEnvironment();
1205    Label exit(env);
1206
1207    GateRef glue = PtrArgument(0);
1208    GateRef obj = TaggedArgument(1);
1209    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1210
1211    NewObjectStubBuilder newBuilder(this);
1212    newBuilder.SetGlue(glue);
1213    GateRef kind = Int32(static_cast<int32_t>(IterationKind::VALUE));
1214    newBuilder.CreateJSTypedArrayIterator(&result, &exit, obj, kind);
1215    Bind(&exit);
1216    Return(*result);
1217}
1218
1219void JSMapDeleteStubBuilder::GenerateCircuit()
1220{
1221    GateRef glue = PtrArgument(0);
1222    GateRef obj = TaggedArgument(1);
1223    GateRef key = TaggedArgument(2U);
1224
1225    LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> builder(this, glue);
1226    GateRef linkedTable = builder.GetLinked(obj);
1227    Return(builder.Delete(linkedTable, key));
1228}
1229
1230void JSSetDeleteStubBuilder::GenerateCircuit()
1231{
1232    GateRef glue = PtrArgument(0);
1233    GateRef obj = TaggedArgument(1);
1234    GateRef key = TaggedArgument(2U);
1235
1236    LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> builder(this, glue);
1237    GateRef linkedTable = builder.GetLinked(obj);
1238    Return(builder.Delete(linkedTable, key));
1239}
1240
1241void JSSetAddStubBuilder::GenerateCircuit()
1242{
1243    GateRef glue = PtrArgument(0);
1244    GateRef obj = TaggedArgument(1);
1245    GateRef key = TaggedArgument(2U);
1246
1247    LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> builder(this, glue);
1248    GateRef linkedTable = builder.GetLinked(obj);
1249    GateRef newTable = builder.Insert(linkedTable, key, key);
1250    builder.Store(VariableType::JS_ANY(), glue, obj, IntPtr(JSSet::LINKED_SET_OFFSET), newTable);
1251    Return(obj);
1252}
1253
1254void SameValueStubBuilder::GenerateCircuit()
1255{
1256    GateRef glue = PtrArgument(0);
1257    GateRef left = TaggedArgument(1);
1258    GateRef right = TaggedArgument(2U);
1259    GateRef result = SameValue(glue, left, right);
1260    Return(result);
1261}
1262
1263CallSignature CommonStubCSigns::callSigns_[CommonStubCSigns::NUM_OF_STUBS];
1264
1265void CommonStubCSigns::Initialize()
1266{
1267#define INIT_SIGNATURES(name)                                                              \
1268    name##CallSignature::Initialize(&callSigns_[name]);                                    \
1269    callSigns_[name].SetID(name);                                                          \
1270    callSigns_[name].SetName(std::string("COStub_") + #name);                              \
1271    callSigns_[name].SetConstructor(                                                       \
1272        [](void* env) {                                                                    \
1273            return static_cast<void*>(                                                     \
1274                new name##StubBuilder(&callSigns_[name], static_cast<Environment*>(env))); \
1275        });
1276
1277    COMMON_STUB_ID_LIST(INIT_SIGNATURES)
1278#undef INIT_SIGNATURES
1279}
1280
1281void CommonStubCSigns::GetCSigns(std::vector<const CallSignature*>& outCSigns)
1282{
1283    for (size_t i = 0; i < NUM_OF_STUBS; i++) {
1284        outCSigns.push_back(&callSigns_[i]);
1285    }
1286}
1287}  // namespace panda::ecmascript::kungfu
1288