• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/interpreter_stub.h"
21 #include "ecmascript/compiler/llvm_ir_builder.h"
22 #include "ecmascript/compiler/new_object_stub_builder.h"
23 #include "ecmascript/compiler/operations_stub_builder.h"
24 #include "ecmascript/compiler/stub_builder-inl.h"
25 #include "ecmascript/compiler/variable_type.h"
26 #include "ecmascript/js_array.h"
27 #include "ecmascript/message_string.h"
28 #include "ecmascript/tagged_hash_table.h"
29 
30 namespace panda::ecmascript::kungfu {
31 using namespace panda::ecmascript;
32 
GenerateCircuit()33 void AddStubBuilder::GenerateCircuit()
34 {
35     GateRef glue = PtrArgument(0);
36     GateRef x = TaggedArgument(1);
37     GateRef y = TaggedArgument(2);
38     OperationsStubBuilder operationBuilder(this);
39     Return(operationBuilder.Add(glue, x, y));
40 }
41 
GenerateCircuit()42 void SubStubBuilder::GenerateCircuit()
43 {
44     GateRef glue = PtrArgument(0);
45     GateRef x = TaggedArgument(1);
46     GateRef y = TaggedArgument(2);
47     OperationsStubBuilder operationBuilder(this);
48     Return(operationBuilder.Sub(glue, x, y));
49 }
50 
GenerateCircuit()51 void MulStubBuilder::GenerateCircuit()
52 {
53     GateRef glue = PtrArgument(0);
54     GateRef x = TaggedArgument(1);
55     GateRef y = TaggedArgument(2);
56     OperationsStubBuilder operationBuilder(this);
57     Return(operationBuilder.Mul(glue, x, y));
58 }
59 
GenerateCircuit()60 void DivStubBuilder::GenerateCircuit()
61 {
62     GateRef glue = PtrArgument(0);
63     GateRef x = TaggedArgument(1);
64     GateRef y = TaggedArgument(2);
65     OperationsStubBuilder operationBuilder(this);
66     Return(operationBuilder.Div(glue, x, y));
67 }
68 
GenerateCircuit()69 void ModStubBuilder::GenerateCircuit()
70 {
71     GateRef glue = PtrArgument(0);
72     GateRef x = TaggedArgument(1);
73     GateRef y = TaggedArgument(2); // 2: 3rd argument
74     OperationsStubBuilder operationBuilder(this);
75     Return(operationBuilder.Mod(glue, x, y));
76 }
77 
GenerateCircuit()78 void TypeOfStubBuilder::GenerateCircuit()
79 {
80     GateRef glue = PtrArgument(0);
81     GateRef obj = TaggedArgument(1);
82     Return(FastTypeOf(glue, obj));
83 }
84 
GenerateCircuit()85 void EqualStubBuilder::GenerateCircuit()
86 {
87     GateRef glue = PtrArgument(0);
88     GateRef x = TaggedArgument(1);
89     GateRef y = TaggedArgument(2); // 2: 3rd argument
90     OperationsStubBuilder operationBuilder(this);
91     Return(operationBuilder.Equal(glue, x, y));
92 }
93 
GenerateCircuit()94 void NotEqualStubBuilder::GenerateCircuit()
95 {
96     GateRef glue = PtrArgument(0);
97     GateRef x = TaggedArgument(1);
98     GateRef y = TaggedArgument(2); // 2: 3rd argument
99     OperationsStubBuilder operationBuilder(this);
100     Return(operationBuilder.NotEqual(glue, x, y));
101 }
102 
GenerateCircuit()103 void StrictEqualStubBuilder::GenerateCircuit()
104 {
105     GateRef glue = PtrArgument(0);
106     GateRef x = TaggedArgument(1);
107     GateRef y = TaggedArgument(2); // 2: 3rd argument
108     OperationsStubBuilder operationBuilder(this);
109     Return(operationBuilder.StrictEqual(glue, x, y));
110 }
111 
GenerateCircuit()112 void StrictNotEqualStubBuilder::GenerateCircuit()
113 {
114     GateRef glue = PtrArgument(0);
115     GateRef x = TaggedArgument(1);
116     GateRef y = TaggedArgument(2); // 2: 3rd argument
117     OperationsStubBuilder operationBuilder(this);
118     Return(operationBuilder.StrictNotEqual(glue, x, y));
119 }
120 
GenerateCircuit()121 void LessStubBuilder::GenerateCircuit()
122 {
123     GateRef glue = PtrArgument(0);
124     GateRef x = TaggedArgument(1);
125     GateRef y = TaggedArgument(2); // 2: 3rd argument
126     OperationsStubBuilder operationBuilder(this);
127     Return(operationBuilder.Less(glue, x, y));
128 }
129 
GenerateCircuit()130 void LessEqStubBuilder::GenerateCircuit()
131 {
132     GateRef glue = PtrArgument(0);
133     GateRef x = TaggedArgument(1);
134     GateRef y = TaggedArgument(2); // 2: 3rd argument
135     OperationsStubBuilder operationBuilder(this);
136     Return(operationBuilder.LessEq(glue, x, y));
137 }
138 
GenerateCircuit()139 void GreaterStubBuilder::GenerateCircuit()
140 {
141     GateRef glue = PtrArgument(0);
142     GateRef x = TaggedArgument(1);
143     GateRef y = TaggedArgument(2); // 2: 3rd argument
144     OperationsStubBuilder operationBuilder(this);
145     Return(operationBuilder.Greater(glue, x, y));
146 }
147 
GenerateCircuit()148 void GreaterEqStubBuilder::GenerateCircuit()
149 {
150     GateRef glue = PtrArgument(0);
151     GateRef x = TaggedArgument(1);
152     GateRef y = TaggedArgument(2); // 2: 3rd argument
153     OperationsStubBuilder operationBuilder(this);
154     Return(operationBuilder.GreaterEq(glue, x, y));
155 }
156 
GenerateCircuit()157 void ShlStubBuilder::GenerateCircuit()
158 {
159     GateRef glue = PtrArgument(0);
160     GateRef x = TaggedArgument(1);
161     GateRef y = TaggedArgument(2); // 2: 3rd argument
162     OperationsStubBuilder operationBuilder(this);
163     Return(operationBuilder.Shl(glue, x, y));
164 }
165 
GenerateCircuit()166 void ShrStubBuilder::GenerateCircuit()
167 {
168     GateRef glue = PtrArgument(0);
169     GateRef x = TaggedArgument(1);
170     GateRef y = TaggedArgument(2); // 2: 3rd argument
171     OperationsStubBuilder operationBuilder(this);
172     Return(operationBuilder.Shr(glue, x, y));
173 }
174 
GenerateCircuit()175 void AshrStubBuilder::GenerateCircuit()
176 {
177     GateRef glue = PtrArgument(0);
178     GateRef x = TaggedArgument(1);
179     GateRef y = TaggedArgument(2); // 2: 3rd argument
180     OperationsStubBuilder operationBuilder(this);
181     Return(operationBuilder.Ashr(glue, x, y));
182 }
183 
GenerateCircuit()184 void AndStubBuilder::GenerateCircuit()
185 {
186     GateRef glue = PtrArgument(0);
187     GateRef x = TaggedArgument(1);
188     GateRef y = TaggedArgument(2); // 2: 3rd argument
189     OperationsStubBuilder operationBuilder(this);
190     Return(operationBuilder.And(glue, x, y));
191 }
192 
GenerateCircuit()193 void OrStubBuilder::GenerateCircuit()
194 {
195     GateRef glue = PtrArgument(0);
196     GateRef x = TaggedArgument(1);
197     GateRef y = TaggedArgument(2); // 2: 3rd argument
198     OperationsStubBuilder operationBuilder(this);
199     Return(operationBuilder.Or(glue, x, y));
200 }
201 
GenerateCircuit()202 void XorStubBuilder::GenerateCircuit()
203 {
204     GateRef glue = PtrArgument(0);
205     GateRef x = TaggedArgument(1);
206     GateRef y = TaggedArgument(2); // 2: 3rd argument
207     OperationsStubBuilder operationBuilder(this);
208     Return(operationBuilder.Xor(glue, x, y));
209 }
210 
GenerateCircuit()211 void InstanceofStubBuilder::GenerateCircuit()
212 {
213     GateRef glue = PtrArgument(0);
214     GateRef object = TaggedArgument(1);
215     GateRef target = TaggedArgument(2); // 2: 3rd argument
216     GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
217     GateRef slotId = Int32Argument(4); // 4 : 5th pars
218     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
219     Return(InstanceOf(glue, object, target, profileTypeInfo, slotId, ProfileOperation()));
220 }
221 
GenerateCircuit()222 void IncStubBuilder::GenerateCircuit()
223 {
224     GateRef glue = PtrArgument(0);
225     GateRef x = TaggedArgument(1);
226     OperationsStubBuilder operationBuilder(this);
227     Return(operationBuilder.Inc(glue, x));
228 }
229 
GenerateCircuit()230 void DecStubBuilder::GenerateCircuit()
231 {
232     GateRef glue = PtrArgument(0);
233     GateRef x = TaggedArgument(1);
234     OperationsStubBuilder operationBuilder(this);
235     Return(operationBuilder.Dec(glue, x));
236 }
237 
GenerateCircuit()238 void NegStubBuilder::GenerateCircuit()
239 {
240     GateRef glue = PtrArgument(0);
241     GateRef x = TaggedArgument(1);
242     OperationsStubBuilder operationBuilder(this);
243     Return(operationBuilder.Neg(glue, x));
244 }
245 
GenerateCircuit()246 void NotStubBuilder::GenerateCircuit()
247 {
248     GateRef glue = PtrArgument(0);
249     GateRef x = TaggedArgument(1);
250     OperationsStubBuilder operationBuilder(this);
251     Return(operationBuilder.Not(glue, x));
252 }
253 
GenerateCircuit()254 void ToBooleanStubBuilder::GenerateCircuit()
255 {
256     GateRef glue = PtrArgument(0);
257     (void)glue;
258     GateRef x = TaggedArgument(1);
259     Return(FastToBoolean(x));
260 }
261 
GenerateCircuit()262 void NewLexicalEnvStubBuilder::GenerateCircuit()
263 {
264     auto env = GetEnvironment();
265     GateRef glue = PtrArgument(0);
266     GateRef parent = TaggedArgument(1);
267     GateRef numVars = Int32Argument(2); /* 2 : 3rd parameter is index */
268 
269     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
270     NewObjectStubBuilder newBuilder(this);
271     newBuilder.SetParameters(glue, 0);
272     Label afterNew(env);
273     newBuilder.NewLexicalEnv(&result, &afterNew, numVars, parent);
274     Bind(&afterNew);
275     Return(*result);
276 }
277 
GenerateCircuit()278 void GetUnmapedArgsStubBuilder::GenerateCircuit()
279 {
280     auto env = GetEnvironment();
281     GateRef glue = PtrArgument(0);
282     GateRef numArgs = Int32Argument(1);
283 
284     DEFVARIABLE(argumentsList, VariableType::JS_ANY(), Hole());
285     DEFVARIABLE(argumentsObj, VariableType::JS_ANY(), Hole());
286     Label afterArgumentsList(env);
287     Label newArgumentsObj(env);
288     Label exit(env);
289 
290     GateRef argv = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
291     GateRef args = PtrAdd(argv, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
292     GateRef actualArgc = Int32Sub(numArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
293     GateRef startIdx = Int32(0);
294     NewObjectStubBuilder newBuilder(this);
295     newBuilder.SetParameters(glue, 0);
296     newBuilder.NewArgumentsList(&argumentsList, &afterArgumentsList, args, startIdx, actualArgc);
297     Bind(&afterArgumentsList);
298     Branch(TaggedIsException(*argumentsList), &exit, &newArgumentsObj);
299     Bind(&newArgumentsObj);
300     newBuilder.NewArgumentsObj(&argumentsObj, &exit, *argumentsList, actualArgc);
301     Bind(&exit);
302     Return(*argumentsObj);
303 }
304 
GenerateCircuit()305 void GetPropertyByIndexStubBuilder::GenerateCircuit()
306 {
307     GateRef glue = PtrArgument(0);
308     GateRef receiver = TaggedArgument(1);
309     GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
310     Return(GetPropertyByIndex(glue, receiver, index, ProfileOperation()));
311 }
312 
GenerateCircuit()313 void SetPropertyByIndexStubBuilder::GenerateCircuit()
314 {
315     GateRef glue = PtrArgument(0);
316     GateRef receiver = TaggedArgument(1);
317     GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
318     GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
319     Return(SetPropertyByIndex(glue, receiver, index, value, false, ProfileOperation()));
320 }
321 
GenerateCircuit()322 void SetPropertyByIndexWithOwnStubBuilder::GenerateCircuit()
323 {
324     GateRef glue = PtrArgument(0);
325     GateRef receiver = TaggedArgument(1);
326     GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
327     GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
328     Return(SetPropertyByIndex(glue, receiver, index, value, true, ProfileOperation()));
329 }
330 
GenerateCircuit()331 void GetPropertyByNameStubBuilder::GenerateCircuit()
332 {
333     GateRef glue = PtrArgument(0);
334     GateRef receiver = TaggedArgument(1);
335     GateRef id = Int64Argument(2); // 2 : 3rd para
336     GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
337     GateRef slotId = Int32Argument(4); // 4 : 5th para
338     AccessObjectStubBuilder builder(this, jsFunc);
339     StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
340     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
341     Return(builder.LoadObjByName(glue, receiver, id, info, profileTypeInfo, slotId, ProfileOperation()));
342 }
343 
GenerateCircuit()344 void DeprecatedGetPropertyByNameStubBuilder::GenerateCircuit()
345 {
346     GateRef glue = PtrArgument(0);
347     GateRef receiver = TaggedArgument(1);
348     GateRef key = TaggedPointerArgument(2); // 2 : 3rd para
349     AccessObjectStubBuilder builder(this);
350     Return(builder.DeprecatedLoadObjByName(glue, receiver, key));
351 }
352 
GenerateCircuit()353 void SetPropertyByNameStubBuilder::GenerateCircuit()
354 {
355     GateRef glue = PtrArgument(0);
356     GateRef receiver = TaggedArgument(1);
357     GateRef id = Int64Argument(2); // 2 : 3rd para
358     GateRef value = TaggedPointerArgument(3); // 3 : 4th para
359     GateRef jsFunc = TaggedArgument(4); // 4 : 5th para
360     GateRef slotId = Int32Argument(5); // 5 : 6th para
361     AccessObjectStubBuilder builder(this, jsFunc);
362     StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
363     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
364     Return(builder.StoreObjByName(glue, receiver, id, info, value, profileTypeInfo, slotId, ProfileOperation()));
365 }
366 
GenerateCircuit()367 void DeprecatedSetPropertyByNameStubBuilder::GenerateCircuit()
368 {
369     GateRef glue = PtrArgument(0);
370     GateRef receiver = TaggedArgument(1);
371     GateRef key = TaggedArgument(2); // 2 : 3rd para
372     GateRef value = TaggedArgument(3); // 3 : 4th para
373     Return(SetPropertyByName(glue, receiver, key, value, false));
374 }
375 
GenerateCircuit()376 void SetPropertyByNameWithOwnStubBuilder::GenerateCircuit()
377 {
378     GateRef glue = PtrArgument(0);
379     GateRef receiver = TaggedArgument(1);
380     GateRef key = TaggedArgument(2); // 2 : 3rd para
381     GateRef value = TaggedArgument(3); // 3 : 4th para
382     Return(SetPropertyByName(glue, receiver, key, value, true));
383 }
384 
GenerateCircuit()385 void GetPropertyByValueStubBuilder::GenerateCircuit()
386 {
387     GateRef glue = PtrArgument(0);
388     GateRef receiver = TaggedArgument(1);
389     GateRef key = TaggedArgument(2); // 2 : 3rd para
390     GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
391     GateRef slotId = Int32Argument(4); // 4 : 5th para
392     AccessObjectStubBuilder builder(this);
393     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
394     Return(builder.LoadObjByValue(glue, receiver, key, profileTypeInfo, slotId));
395 }
396 
GenerateCircuit()397 void DeprecatedGetPropertyByValueStubBuilder::GenerateCircuit()
398 {
399     GateRef glue = PtrArgument(0);
400     GateRef receiver = TaggedArgument(1);
401     GateRef key = TaggedArgument(2); // 2 : 3rd para
402     Return(GetPropertyByValue(glue, receiver, key, ProfileOperation()));
403 }
404 
GenerateCircuit()405 void SetPropertyByValueStubBuilder::GenerateCircuit()
406 {
407     GateRef glue = PtrArgument(0);
408     GateRef receiver = TaggedArgument(1);
409     GateRef key = TaggedArgument(2);        // 2 : 3rd para
410     GateRef value = TaggedArgument(3);      // 3 : 4th para
411     GateRef jsFunc = TaggedArgument(4);     // 4 : 5th para
412     GateRef slotId = Int32Argument(5);      // 5 : 6th para
413     AccessObjectStubBuilder builder(this);
414     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
415     Return(builder.StoreObjByValue(glue, receiver, key, value, profileTypeInfo, slotId));
416 }
417 
GenerateCircuit()418 void DeprecatedSetPropertyByValueStubBuilder::GenerateCircuit()
419 {
420     GateRef glue = PtrArgument(0);
421     GateRef receiver = TaggedArgument(1);
422     GateRef key = TaggedArgument(2);              /* 2 : 3rd parameter is key */
423     GateRef value = TaggedArgument(3);            /* 3 : 4th parameter is value */
424     Return(SetPropertyByValue(glue, receiver, key, value, false));
425 }
426 
GenerateCircuit()427 void SetPropertyByValueWithOwnStubBuilder::GenerateCircuit()
428 {
429     GateRef glue = PtrArgument(0);
430     GateRef receiver = TaggedArgument(1);
431     GateRef key = TaggedArgument(2);              /* 2 : 3rd parameter is key */
432     GateRef value = TaggedArgument(3);            /* 3 : 4th parameter is value */
433     Return(SetPropertyByValue(glue, receiver, key, value, true));
434 }
435 
GenerateCircuit()436 void TryLdGlobalByNameStubBuilder::GenerateCircuit()
437 {
438     GateRef glue = PtrArgument(0);
439     GateRef id = Int64Argument(1);
440     GateRef jsFunc = TaggedArgument(2); // 2 : 3th para
441     GateRef slotId = Int32Argument(3); // 3 : 4th para
442     AccessObjectStubBuilder builder(this, jsFunc);
443     StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
444     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
445     Return(builder.TryLoadGlobalByName(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
446 }
447 
GenerateCircuit()448 void TryStGlobalByNameStubBuilder::GenerateCircuit()
449 {
450     GateRef glue = PtrArgument(0);
451     GateRef id = Int64Argument(1);
452     GateRef value = TaggedArgument(2); // 2 : 3rd para
453     GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
454     GateRef slotId = Int32Argument(4);  // 4: 5th para
455     AccessObjectStubBuilder builder(this, jsFunc);
456     StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
457     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
458     Return(builder.TryStoreGlobalByName(glue, id, info, value, profileTypeInfo, slotId, ProfileOperation()));
459 }
460 
GenerateCircuit()461 void LdGlobalVarStubBuilder::GenerateCircuit()
462 {
463     GateRef glue = PtrArgument(0);
464     GateRef id = Int64Argument(1);
465     GateRef jsFunc = TaggedArgument(2); // 2 : 3th para
466     GateRef slotId = Int32Argument(3); // 3 : 4th para
467     AccessObjectStubBuilder builder(this, jsFunc);
468     StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
469     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
470     Return(builder.LoadGlobalVar(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
471 }
472 
GenerateCircuit()473 void StGlobalVarStubBuilder::GenerateCircuit()
474 {
475     GateRef glue = PtrArgument(0);
476     GateRef id = Int64Argument(1);
477     GateRef value = TaggedArgument(2); // 2 : 3rd para
478     GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
479     GateRef slotId = Int32Argument(4);  // 4: 5th para
480     AccessObjectStubBuilder builder(this, jsFunc);
481     StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
482     GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
483     Return(builder.StoreGlobalVar(glue, id, info, value, profileTypeInfo, slotId));
484 }
485 
GenerateCircuit()486 void TryLoadICByNameStubBuilder::GenerateCircuit()
487 {
488     auto env = GetEnvironment();
489     GateRef glue = PtrArgument(0);
490     GateRef receiver = TaggedArgument(1);
491     GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
492     GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
493 
494     Label receiverIsHeapObject(env);
495     Label receiverNotHeapObject(env);
496     Label hclassEqualFirstValue(env);
497     Label hclassNotEqualFirstValue(env);
498     Label cachedHandlerNotHole(env);
499     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
500     Bind(&receiverIsHeapObject);
501     {
502         GateRef hclass = LoadHClass(receiver);
503         Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
504                &hclassEqualFirstValue,
505                &hclassNotEqualFirstValue);
506         Bind(&hclassEqualFirstValue);
507         {
508             Return(LoadICWithHandler(glue, receiver, receiver, secondValue, ProfileOperation()));
509         }
510         Bind(&hclassNotEqualFirstValue);
511         {
512             GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
513             Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
514             Bind(&cachedHandlerNotHole);
515             {
516                 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
517             }
518         }
519     }
520     Bind(&receiverNotHeapObject);
521     {
522         Return(Hole());
523     }
524 }
525 
GenerateCircuit()526 void TryLoadICByValueStubBuilder::GenerateCircuit()
527 {
528     auto env = GetEnvironment();
529     GateRef glue = PtrArgument(0);
530     GateRef receiver = TaggedArgument(1);
531     GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
532     GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
533     GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
534 
535     Label receiverIsHeapObject(env);
536     Label receiverNotHeapObject(env);
537     Label hclassEqualFirstValue(env);
538     Label hclassNotEqualFirstValue(env);
539     Label firstValueEqualKey(env);
540     Label cachedHandlerNotHole(env);
541     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
542     Bind(&receiverIsHeapObject);
543     {
544         GateRef hclass = LoadHClass(receiver);
545         Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
546                &hclassEqualFirstValue,
547                &hclassNotEqualFirstValue);
548         Bind(&hclassEqualFirstValue);
549         Return(LoadElement(glue, receiver, key, ProfileOperation()));
550         Bind(&hclassNotEqualFirstValue);
551         {
552             Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
553             Bind(&firstValueEqualKey);
554             {
555                 auto cachedHandler = CheckPolyHClass(secondValue, hclass);
556                 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
557                 Bind(&cachedHandlerNotHole);
558                 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
559             }
560         }
561     }
562     Bind(&receiverNotHeapObject);
563     Return(Hole());
564 }
565 
GenerateCircuit()566 void TryStoreICByNameStubBuilder::GenerateCircuit()
567 {
568     auto env = GetEnvironment();
569     GateRef glue = PtrArgument(0);
570     GateRef receiver = TaggedArgument(1);
571     GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
572     GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
573     GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */
574     Label receiverIsHeapObject(env);
575     Label receiverNotHeapObject(env);
576     Label hclassEqualFirstValue(env);
577     Label hclassNotEqualFirstValue(env);
578     Label cachedHandlerNotHole(env);
579     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
580     Bind(&receiverIsHeapObject);
581     {
582         GateRef hclass = LoadHClass(receiver);
583         Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
584                &hclassEqualFirstValue,
585                &hclassNotEqualFirstValue);
586         Bind(&hclassEqualFirstValue);
587         {
588             Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue));
589         }
590         Bind(&hclassNotEqualFirstValue);
591         {
592             GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
593             Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
594             Bind(&cachedHandlerNotHole);
595             {
596                 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
597             }
598         }
599     }
600     Bind(&receiverNotHeapObject);
601     Return(Hole());
602 }
603 
GenerateCircuit()604 void TryStoreICByValueStubBuilder::GenerateCircuit()
605 {
606     auto env = GetEnvironment();
607     GateRef glue = PtrArgument(0);
608     GateRef receiver = TaggedArgument(1);
609     GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
610     GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
611     GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
612     GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */
613     Label receiverIsHeapObject(env);
614     Label receiverNotHeapObject(env);
615     Label hclassEqualFirstValue(env);
616     Label hclassNotEqualFirstValue(env);
617     Label firstValueEqualKey(env);
618     Label cachedHandlerNotHole(env);
619     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
620     Bind(&receiverIsHeapObject);
621     {
622         GateRef hclass = LoadHClass(receiver);
623         Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
624                &hclassEqualFirstValue,
625                &hclassNotEqualFirstValue);
626         Bind(&hclassEqualFirstValue);
627         Return(ICStoreElement(glue, receiver, key, value, secondValue, ProfileOperation()));
628         Bind(&hclassNotEqualFirstValue);
629         {
630             Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
631             Bind(&firstValueEqualKey);
632             {
633                 GateRef cachedHandler = CheckPolyHClass(secondValue, hclass);
634                 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
635                 Bind(&cachedHandlerNotHole);
636                 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
637             }
638         }
639     }
640     Bind(&receiverNotHeapObject);
641     Return(Hole());
642 }
643 
GenerateCircuit()644 void SetValueWithBarrierStubBuilder::GenerateCircuit()
645 {
646     GateRef glue = PtrArgument(0);
647     GateRef obj = TaggedArgument(1);
648     GateRef offset = PtrArgument(2); // 2 : 3rd para
649     GateRef value = TaggedArgument(3); // 3 : 4th para
650     SetValueWithBarrier(glue, obj, offset, value);
651     Return();
652 }
653 
GenerateCircuit()654 void NewThisObjectCheckedStubBuilder::GenerateCircuit()
655 {
656     GateRef glue = PtrArgument(0);
657     GateRef ctor = TaggedArgument(1);
658     NewObjectStubBuilder newBuilder(this);
659     Return(newBuilder.NewThisObjectChecked(glue, ctor));
660 }
661 
GenerateCircuit()662 void ConstructorCheckStubBuilder::GenerateCircuit()
663 {
664     GateRef glue = PtrArgument(0);
665     GateRef ctor = TaggedArgument(1);
666     GateRef value = TaggedArgument(2); // 2 : 3rd para
667     GateRef thisObj = TaggedArgument(3); // 3 : 4th para
668     Return(ConstructorCheck(glue, ctor, value, thisObj));
669 }
670 
GenerateCircuit()671 void CreateEmptyArrayStubBuilder::GenerateCircuit()
672 {
673     GateRef glue = PtrArgument(0);
674     NewObjectStubBuilder newBuilder(this);
675     Return(newBuilder.CreateEmptyArray(glue, ProfileOperation()));
676 }
677 
GenerateCircuit()678 void CreateArrayWithBufferStubBuilder::GenerateCircuit()
679 {
680     GateRef glue = PtrArgument(0);
681     GateRef index = Int32Argument(1);
682     GateRef jsFunc = TaggedArgument(2); // 2 : 3rd para
683     NewObjectStubBuilder newBuilder(this);
684     Return(newBuilder.CreateArrayWithBuffer(glue, index, jsFunc, ProfileOperation()));
685 }
686 
GenerateCircuit()687 void NewJSObjectStubBuilder::GenerateCircuit()
688 {
689     GateRef glue = PtrArgument(0);
690     GateRef hclass = TaggedArgument(1);
691     NewObjectStubBuilder newBuilder(this);
692     Return(newBuilder.NewJSObject(glue, hclass));
693 }
694 
GenerateCircuit()695 void JsBoundCallInternalStubBuilder::GenerateCircuit()
696 {
697     auto env = GetEnvironment();
698     Label exit(env);
699     Label fastCall(env);
700     Label notFastCall(env);
701     Label methodIsFastCall(env);
702     Label fastCallBridge(env);
703     Label slowCall(env);
704     Label slowCallBridge(env);
705 
706     GateRef glue = PtrArgument(0);
707     GateRef argc = Int64Argument(1);
708     GateRef func = TaggedPointerArgument(2); // callTarget
709     GateRef argv = PtrArgument(3);
710     GateRef thisValue = TaggedPointerArgument(4); // this
711     GateRef newTarget = TaggedPointerArgument(5); // new target
712     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
713     GateRef method = GetMethodFromFunction(func);
714     GateRef callfield = Load(VariableType::INT64(), method, IntPtr(Method::CALL_FIELD_OFFSET));
715     GateRef expectedNum = Int64And(Int64LSR(callfield, Int64(MethodLiteral::NumArgsBits::START_BIT)),
716         Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
717     GateRef expectedArgc = Int64Add(expectedNum, Int64(NUM_MANDATORY_JSFUNC_ARGS));
718     GateRef actualArgc = Int64Sub(argc, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
719     GateRef hClass = LoadHClass(func);
720     GateRef bitfield = Load(VariableType::INT32(), hClass, Int32(JSHClass::BIT_FIELD_OFFSET));
721     Branch(CanFastCallWithBitField(bitfield), &methodIsFastCall, &notFastCall);
722     Bind(&methodIsFastCall);
723     {
724         Branch(Int64LessThanOrEqual(expectedArgc, argc), &fastCall, &fastCallBridge);
725         Bind(&fastCall);
726         {
727             result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgV),
728                 { glue, func, thisValue, actualArgc, argv });
729             Jump(&exit);
730         }
731         Bind(&fastCallBridge);
732         {
733             result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgVAndPushUndefined),
734                 { glue, func, thisValue, actualArgc, argv, expectedNum });
735             Jump(&exit);
736         }
737     }
738     Bind(&notFastCall);
739     {
740         Branch(Int64LessThanOrEqual(expectedArgc, argc), &slowCall, &slowCallBridge);
741         Bind(&slowCall);
742         {
743             result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgV),
744                 { glue, actualArgc, func, newTarget, thisValue, argv });
745             Jump(&exit);
746         }
747         Bind(&slowCallBridge);
748         {
749             result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgVAndPushUndefined),
750                 { glue, actualArgc, func, newTarget, thisValue, argv });
751             Jump(&exit);
752         }
753     }
754     Bind(&exit);
755     Return(*result);
756 }
757 
GenerateCircuit()758 void JsProxyCallInternalStubBuilder::GenerateCircuit()
759 {
760     auto env = GetEnvironment();
761     Label exit(env);
762     Label isNull(env);
763     Label notNull(env);
764     Label isUndefined(env);
765     Label isNotUndefined(env);
766 
767     GateRef glue = PtrArgument(0);
768     GateRef argc = Int64Argument(1);
769     GateRef proxy = TaggedPointerArgument(2); // callTarget
770     GateRef argv = PtrArgument(3);
771     GateRef newTarget = Load(VariableType::JS_POINTER(), argv, IntPtr(sizeof(JSTaggedValue)));
772     GateRef thisTarget = Load(VariableType::JS_POINTER(), argv, IntPtr(2 * sizeof(JSTaggedValue)));
773 
774     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
775 
776     GateRef handler = GetHandlerFromJSProxy(proxy);
777     Branch(TaggedIsNull(handler), &isNull, &notNull);
778     Bind(&isNull);
779     {
780         ThrowTypeAndReturn(glue, GET_MESSAGE_STRING_ID(NonCallable), Exception());
781     }
782     Bind(&notNull);
783     {
784         GateRef target = GetTargetFromJSProxy(proxy);
785         GateRef gConstPointer = Load(VariableType::JS_ANY(), glue,
786             IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit())));
787 
788         GateRef keyOffset = PtrAdd(gConstPointer,
789             PtrMul(IntPtr(static_cast<int64_t>(ConstantIndex::APPLY_STRING_INDEX)),
790             IntPtr(sizeof(JSTaggedValue))));
791         GateRef key = Load(VariableType::JS_ANY(), keyOffset);
792         GateRef method = CallRuntime(glue, RTSTUB_ID(JSObjectGetMethod), {handler, key});
793         ReturnExceptionIfAbruptCompletion(glue);
794 
795         Branch(TaggedIsUndefined(method), &isUndefined, &isNotUndefined);
796         Bind(&isUndefined);
797         {
798             Label isHeapObject(env);
799             Label slowPath(env);
800             Label isJsFcuntion(env);
801             Label notCallConstructor(env);
802             Label fastCall(env);
803             Label notFastCall(env);
804             Label slowCall(env);
805             Branch(TaggedIsHeapObject(target), &isHeapObject, &slowPath);
806             Bind(&isHeapObject);
807             {
808                 GateRef hClass = LoadHClass(target);
809                 GateRef bitfield = Load(VariableType::INT32(), hClass, Int32(JSHClass::BIT_FIELD_OFFSET));
810                 Branch(IsClassConstructorFromBitField(bitfield), &slowPath, &notCallConstructor);
811                 Bind(&notCallConstructor);
812                 GateRef actualArgc = Int64Sub(argc, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
813                 GateRef actualArgv = PtrAdd(argv, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * sizeof(JSTaggedValue)));
814                 Branch(CanFastCallWithBitField(bitfield), &fastCall, &notFastCall);
815                 Bind(&fastCall);
816                 {
817                     result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgV),
818                         { glue, target, thisTarget, actualArgc, actualArgv });
819                     Jump(&exit);
820                 }
821                 Bind(&notFastCall);
822                 {
823                     Branch(IsOptimizedWithBitField(bitfield), &slowCall, &slowPath);
824                     Bind(&slowCall);
825                     {
826                         result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgV),
827                             { glue, actualArgc, target, newTarget, thisTarget, actualArgv });
828                         Jump(&exit);
829                     }
830                 }
831             }
832             Bind(&slowPath);
833             {
834                 result = CallNGCRuntime(glue, RTSTUB_ID(JSProxyCallInternalWithArgV), {glue, target});
835                 Jump(&exit);
836             }
837         }
838         Bind(&isNotUndefined);
839         {
840             Label isHeapObject1(env);
841             Label slowPath1(env);
842             Label isJsFcuntion1(env);
843             Label notCallConstructor1(env);
844             Label fastCall1(env);
845             Label notFastCall1(env);
846             Label slowCall1(env);
847             const int JSPROXY_NUM_ARGS = 3;
848             GateRef arrHandle = CallRuntime(glue, RTSTUB_ID(CreateArrayFromList), argc, argv);
849             // 2: this offset
850             GateRef numArgs = Int64(JSPROXY_NUM_ARGS + NUM_MANDATORY_JSFUNC_ARGS);
851 
852             Branch(TaggedIsHeapObject(method), &isHeapObject1, &slowPath1);
853             Bind(&isHeapObject1);
854             {
855                 GateRef hClass = LoadHClass(method);
856                 GateRef bitfield = Load(VariableType::INT32(), hClass, Int32(JSHClass::BIT_FIELD_OFFSET));
857                 Branch(IsClassConstructor(method), &slowPath1, &notCallConstructor1);
858                 Bind(&notCallConstructor1);
859                 GateRef meth = GetMethodFromFunction(method);
860                 GateRef code = GetAotCodeAddr(meth);
861                 Branch(CanFastCallWithBitField(bitfield), &fastCall1, &notFastCall1);
862                 Bind(&fastCall1);
863                 {
864                     result = FastCallOptimized(glue, code,
865                         { glue, method, handler, target, thisTarget, arrHandle });
866                     Jump(&exit);
867                 }
868                 Bind(&notFastCall1);
869                 {
870                     Branch(IsOptimizedWithBitField(bitfield), &slowCall1, &slowPath1);
871                     Bind(&slowCall1);
872                     {
873                         result = CallOptimized(glue, code,
874                             { glue, numArgs, method, Undefined(), handler, target, thisTarget, arrHandle });
875                         Jump(&exit);
876                     }
877                 }
878             }
879             Bind(&slowPath1);
880             {
881                 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
882                     { glue, numArgs, method, Undefined(), handler, target, thisTarget, arrHandle });
883                 Jump(&exit);
884             }
885         }
886     }
887     Bind(&exit);
888     Return(*result);
889 }
890 
891 CallSignature CommonStubCSigns::callSigns_[CommonStubCSigns::NUM_OF_STUBS];
892 
Initialize()893 void CommonStubCSigns::Initialize()
894 {
895 #define INIT_SIGNATURES(name)                                                              \
896     name##CallSignature::Initialize(&callSigns_[name]);                                    \
897     callSigns_[name].SetID(name);                                                          \
898     callSigns_[name].SetName(std::string("COStub_") + #name);                              \
899     callSigns_[name].SetConstructor(                                                       \
900         [](void* env) {                                                                    \
901             return static_cast<void*>(                                                     \
902                 new name##StubBuilder(&callSigns_[name], static_cast<Environment*>(env))); \
903         });
904 
905     COMMON_STUB_ID_LIST(INIT_SIGNATURES)
906 #undef INIT_SIGNATURES
907 }
908 
GetCSigns(std::vector<const CallSignature * > & outCSigns)909 void CommonStubCSigns::GetCSigns(std::vector<const CallSignature*>& outCSigns)
910 {
911     for (size_t i = 0; i < NUM_OF_STUBS; i++) {
912         outCSigns.push_back(&callSigns_[i]);
913     }
914 }
915 }  // namespace panda::ecmascript::kungfu
916