• 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 "fast_stub.h"
17 
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/compiler/llvm_ir_builder.h"
20 #include "ecmascript/compiler/machine_type.h"
21 #include "ecmascript/js_array.h"
22 #include "ecmascript/message_string.h"
23 #include "ecmascript/tagged_hash_table-inl.h"
24 
25 namespace panda::ecmascript::kungfu {
26 using namespace panda::ecmascript;
27 
28 #ifndef NDEBUG
GenerateCircuit(const CompilationConfig * cfg)29 void PhiGateTestStub::GenerateCircuit(const CompilationConfig *cfg)
30 {
31     Stub::GenerateCircuit(cfg);
32     auto env = GetEnvironment();
33     DEFVARIABLE(z, StubMachineType::INT32, GetInt32Constant(0));
34     DEFVARIABLE(x, StubMachineType::INT32, Int32Argument(0));
35     Label ifTrue(env);
36     Label ifFalse(env);
37     Label next(env);
38 
39     Branch(Int32Equal(*x, GetInt32Constant(10)), &ifTrue, &ifFalse);  // 10 : size of entry
40     Bind(&ifTrue);
41     z = Int32Add(*x, GetInt32Constant(10));  // 10 : size of entry
42     Jump(&next);
43     Bind(&ifFalse);
44     z = Int32Add(*x, GetInt32Constant(100));  // 100 : size of entry
45     Jump(&next);
46     Bind(&next);
47     Return(*z);
48 }
49 
GenerateCircuit(const CompilationConfig * cfg)50 void LoopTestStub::GenerateCircuit(const CompilationConfig *cfg)
51 {
52     Stub::GenerateCircuit(cfg);
53     auto env = GetEnvironment();
54     DEFVARIABLE(z, StubMachineType::INT32, GetInt32Constant(0));
55     DEFVARIABLE(y, StubMachineType::INT32, Int32Argument(0));
56     Label loopHead(env);
57     Label loopEnd(env);
58     Label afterLoop(env);
59     Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop);  // 10 : size of entry
60     LoopBegin(&loopHead);
61     Label ifTrue(env);
62     Label ifFalse(env);
63     Label next(env);
64     Branch(Int32Equal(Int32Argument(0), GetInt32Constant(9)), &ifTrue, &ifFalse);  // 9 : size of entry
65     Bind(&ifTrue);
66     z = Int32Add(*y, GetInt32Constant(10));  // 10 : size of entry
67     y = Int32Add(*z, GetInt32Constant(1));
68     Jump(&next);
69     Bind(&ifFalse);
70     z = Int32Add(*y, GetInt32Constant(100));  // 100 : size of entry
71     Jump(&next);
72     Bind(&next);
73     y = Int32Add(*y, GetInt32Constant(1));
74     Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop);  // 10 : size of entry
75     Bind(&loopEnd);
76     LoopEnd(&loopHead);
77     Bind(&afterLoop);
78     Return(*z);
79 }
80 
GenerateCircuit(const CompilationConfig * cfg)81 void LoopTest1Stub::GenerateCircuit(const CompilationConfig *cfg)
82 {
83     Stub::GenerateCircuit(cfg);
84     auto env = GetEnvironment();
85     DEFVARIABLE(y, StubMachineType::INT32, Int32Argument(0));
86     DEFVARIABLE(x, StubMachineType::INT32, Int32Argument(0));
87     DEFVARIABLE(z, StubMachineType::INT32, Int32Argument(0));
88     Label loopHead(env);
89     Label loopEnd(env);
90     Label afterLoop(env);
91     Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop);  // 10 : size of entry
92     LoopBegin(&loopHead);
93     x = Int32Add(*z, GetInt32Constant(3));  // 3 : size of entry
94     Label ifTrue(env);
95     Label next(env);
96     Branch(Int32Equal(*x, GetInt32Constant(9)), &ifTrue, &next);  // 9 : size of entry
97     Bind(&ifTrue);
98     y = Int32Add(*z, *x);
99     Jump(&next);
100     Bind(&next);
101     y = Int32Add(*y, GetInt32Constant(1));
102     Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop);  // 10 : size of entry
103     Bind(&loopEnd);
104     LoopEnd(&loopHead);
105     Bind(&afterLoop);
106     z = *y;
107     Return(*z);
108 }
109 
GenerateCircuit(const CompilationConfig * cfg)110 void FastMulGCTestStub::GenerateCircuit(const CompilationConfig *cfg)
111 {
112     Stub::GenerateCircuit(cfg);
113     auto env = GetEnvironment();
114     GateRef glue = PtrArgument(0);
115     GateRef x = Int64Argument(1);
116     GateRef y = Int64Argument(2); // 2: 3rd argument
117 
118     DEFVARIABLE(intX, StubMachineType::INT64, GetInt64Constant(0));
119     DEFVARIABLE(intY, StubMachineType::INT64, GetInt64Constant(0));
120     DEFVARIABLE(valuePtr, StubMachineType::INT64, GetInt64Constant(0));
121     DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
122     DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
123     Label xIsNumber(env);
124     Label xNotNumberOryNotNumber(env);
125     Label xIsNumberAndyIsNumber(env);
126     Label xIsDoubleAndyIsDouble(env);
127     Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
128     Bind(&xIsNumber);
129     {
130         Label yIsNumber(env);
131         // if right.IsNumber()
132         Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
133         Bind(&yIsNumber);
134         {
135             Label xIsInt(env);
136             Label xNotInt(env);
137             Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
138             Bind(&xIsInt);
139             {
140                 intX = TaggedCastToInt64(x);
141                 doubleX = CastInt64ToFloat64(*intX);
142                 Jump(&xIsNumberAndyIsNumber);
143             }
144             Bind(&xNotInt);
145             {
146                 doubleX = TaggedCastToDouble(x);
147                 Jump(&xIsNumberAndyIsNumber);
148             }
149         }
150     }
151     Bind(&xNotNumberOryNotNumber);
152     Return(GetHoleConstant(StubMachineType::TAGGED));
153     Label yIsInt(env);
154     Label yNotInt(env);
155     Bind(&xIsNumberAndyIsNumber);
156     {
157         Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
158         Bind(&yIsInt);
159         {
160             intY = TaggedCastToInt64(y);
161             doubleY = CastInt64ToFloat64(*intY);
162             Jump(&xIsDoubleAndyIsDouble);
163         }
164         Bind(&yNotInt);
165         {
166             doubleY = TaggedCastToDouble(y);
167             Jump(&xIsDoubleAndyIsDouble);
168         }
169     }
170     Bind(&xIsDoubleAndyIsDouble);
171     doubleX = DoubleMul(*doubleX, *doubleY);
172     GateRef ptr1 = CallRuntimeTrampoline(glue, GetInt64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), {});
173     GateRef ptr2 = CallRuntimeTrampoline(glue, GetInt64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), {});
174     auto value1 = GetValueFromTaggedArray(StubMachineType::UINT64, ptr1, GetInt64Constant(0));
175     GateRef tmp = CastInt64ToFloat64(value1);
176     doubleX = DoubleMul(*doubleX, tmp);
177     auto value2 = GetValueFromTaggedArray(StubMachineType::UINT64, ptr2, GetInt64Constant(1));
178     tmp = CastInt64ToFloat64(value2);
179     doubleX = DoubleMul(*doubleX, tmp);
180     Return(DoubleBuildTaggedWithNoGC(*doubleX));
181 }
182 #endif
183 
GenerateCircuit(const CompilationConfig * cfg)184 void FastAddStub::GenerateCircuit(const CompilationConfig *cfg)
185 {
186     Stub::GenerateCircuit(cfg);
187     auto env = GetEnvironment();
188     GateRef x = TaggedArgument(0);
189     GateRef y = TaggedArgument(1);
190     DEFVARIABLE(intX, StubMachineType::INT32, 0);
191     DEFVARIABLE(intY, StubMachineType::INT32, 0);
192     DEFVARIABLE(doubleX, StubMachineType::FLOAT64, 0);
193     DEFVARIABLE(doubleY, StubMachineType::FLOAT64, 0);
194     Label xIsNumber(env);
195     Label xNotNumberOryNotNumber(env);
196     Label xIsNumberAndyIsNumber(env);
197     Label xIsDoubleAndyIsDouble(env);
198     Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
199     Bind(&xIsNumber);
200     {
201         Label yIsNumber(env);
202         // if right.IsNumber()
203         Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
204         Bind(&yIsNumber);
205         {
206             Label xIsInt(env);
207             Label xNotInt(env);
208             Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
209             Bind(&xIsInt);
210             {
211                 intX = TaggedCastToInt32(x);
212                 doubleX = ChangeInt32ToFloat64(*intX);
213                 Jump(&xIsNumberAndyIsNumber);
214             }
215             Bind(&xNotInt);
216             {
217                 doubleX = TaggedCastToDouble(x);
218                 Jump(&xIsNumberAndyIsNumber);
219             }
220         }
221     }
222     Bind(&xNotNumberOryNotNumber);
223     Return(GetHoleConstant(StubMachineType::TAGGED));
224     Label yIsInt(env);
225     Label yNotInt(env);
226     Bind(&xIsNumberAndyIsNumber);
227     {
228         Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
229         Bind(&yIsInt);
230         {
231             intY = TaggedCastToInt32(y);
232             doubleY = ChangeInt32ToFloat64(*intY);
233             Jump(&xIsDoubleAndyIsDouble);
234         }
235         Bind(&yNotInt);
236         {
237             doubleY = TaggedCastToDouble(y);
238             Jump(&xIsDoubleAndyIsDouble);
239         }
240     }
241     Bind(&xIsDoubleAndyIsDouble);
242     doubleX = DoubleAdd(*doubleX, *doubleY);
243     Return(DoubleBuildTaggedWithNoGC(*doubleX));
244 }
245 
GenerateCircuit(const CompilationConfig * cfg)246 void FastSubStub::GenerateCircuit(const CompilationConfig *cfg)
247 {
248     Stub::GenerateCircuit(cfg);
249     auto env = GetEnvironment();
250     GateRef x = TaggedArgument(0);
251     GateRef y = TaggedArgument(1);
252     DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
253     DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
254     DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
255     DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
256     Label xIsNumber(env);
257     Label xNotNumberOryNotNumber(env);
258     Label xNotIntOryNotInt(env);
259     Label xIsIntAndyIsInt(env);
260     // if x is number
261     Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
262     Bind(&xIsNumber);
263     {
264         Label yIsNumber(env);
265         // if y is number
266         Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
267         {
268             Bind(&yIsNumber);
269             {
270                 Label xIsInt(env);
271                 Label xNotInt(env);
272                 Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
273                 Bind(&xIsInt);
274                 {
275                     intX = TaggedCastToInt32(x);
276                     Label yIsInt(env);
277                     Label yNotInt(env);
278                     Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
279                     Bind(&yIsInt);
280                     {
281                         intY = TaggedCastToInt32(y);
282                         intX = Int32Sub(*intX, *intY);
283                         Jump(&xIsIntAndyIsInt);
284                     }
285                     Bind(&yNotInt);
286                     {
287                         doubleY = TaggedCastToDouble(y);
288                         doubleX = ChangeInt32ToFloat64(*intX);
289                         Jump(&xNotIntOryNotInt);
290                     }
291                 }
292                 Bind(&xNotInt);
293                 {
294                     Label yIsInt(env);
295                     Label yNotInt(env);
296                     doubleX = TaggedCastToDouble(x);
297                     Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
298                     Bind(&yIsInt);
299                     {
300                         intY = TaggedCastToInt32(y);
301                         doubleY = ChangeInt32ToFloat64(*intY);
302                         Jump(&xNotIntOryNotInt);
303                     }
304                     Bind(&yNotInt);
305                     {
306                         doubleY = TaggedCastToDouble(y);
307                         Jump(&xNotIntOryNotInt);
308                     }
309                 }
310             }
311         }
312     }
313     Bind(&xNotNumberOryNotNumber);
314     Return(GetHoleConstant(StubMachineType::TAGGED));
315     Bind(&xNotIntOryNotInt);
316     doubleX = DoubleSub(*doubleX, *doubleY);
317     Return(DoubleBuildTaggedWithNoGC(*doubleX));
318     Bind(&xIsIntAndyIsInt);
319     Return(IntBuildTaggedWithNoGC(*intX));
320 }
321 
GenerateCircuit(const CompilationConfig * cfg)322 void FastMulStub::GenerateCircuit(const CompilationConfig *cfg)
323 {
324     Stub::GenerateCircuit(cfg);
325     auto env = GetEnvironment();
326     GateRef x = TaggedArgument(0);
327     GateRef y = TaggedArgument(1);
328     DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
329     DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
330     DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
331     DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
332     Label xIsNumber(env);
333     Label xNotNumberOryNotNumber(env);
334     Label xIsNumberAndyIsNumber(env);
335     Label xIsDoubleAndyIsDouble(env);
336     Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
337     Bind(&xIsNumber);
338     {
339         Label yIsNumber(env);
340         // if right.IsNumber()
341         Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
342         Bind(&yIsNumber);
343         {
344             Label xIsInt(env);
345             Label xNotInt(env);
346             Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
347             Bind(&xIsInt);
348             {
349                 intX = TaggedCastToInt32(x);
350                 doubleX = ChangeInt32ToFloat64(*intX);
351                 Jump(&xIsNumberAndyIsNumber);
352             }
353             Bind(&xNotInt);
354             {
355                 doubleX = TaggedCastToDouble(x);
356                 Jump(&xIsNumberAndyIsNumber);
357             }
358         }
359     }
360     Bind(&xNotNumberOryNotNumber);
361     Return(GetHoleConstant(StubMachineType::TAGGED));
362     Label yIsInt(env);
363     Label yNotInt(env);
364     Bind(&xIsNumberAndyIsNumber);
365     {
366         Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
367         Bind(&yIsInt);
368         {
369             intY = TaggedCastToInt32(y);
370             doubleY = ChangeInt32ToFloat64(*intY);
371             Jump(&xIsDoubleAndyIsDouble);
372         }
373         Bind(&yNotInt);
374         {
375             doubleY = TaggedCastToDouble(y);
376             Jump(&xIsDoubleAndyIsDouble);
377         }
378     }
379     Bind(&xIsDoubleAndyIsDouble);
380     doubleX = DoubleMul(*doubleX, *doubleY);
381     Return(DoubleBuildTaggedWithNoGC(*doubleX));
382 }
383 
GenerateCircuit(const CompilationConfig * cfg)384 void FastDivStub::GenerateCircuit(const CompilationConfig *cfg)
385 {
386     Stub::GenerateCircuit(cfg);
387     auto env = GetEnvironment();
388     GateRef x = TaggedArgument(0);
389     GateRef y = TaggedArgument(1);
390     DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
391     DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
392     DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
393     DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
394     Label xIsNumber(env);
395     Label xNotNumberOryNotNumber(env);
396     Label xIsNumberAndyIsNumber(env);
397     Label xIsDoubleAndyIsDouble(env);
398     Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
399     Bind(&xIsNumber);
400     {
401         Label yIsNumber(env);
402         // if right.IsNumber()
403         Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
404         Bind(&yIsNumber);
405         {
406             Label xIsInt(env);
407             Label xNotInt(env);
408             Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
409             Bind(&xIsInt);
410             {
411                 intX = TaggedCastToInt32(x);
412                 doubleX = ChangeInt32ToFloat64(*intX);
413                 Jump(&xIsNumberAndyIsNumber);
414             }
415             Bind(&xNotInt);
416             {
417                 doubleX = TaggedCastToDouble(x);
418                 Jump(&xIsNumberAndyIsNumber);
419             }
420         }
421     }
422     Bind(&xNotNumberOryNotNumber);
423     Return(GetHoleConstant(StubMachineType::TAGGED));
424     Label yIsInt(env);
425     Label yNotInt(env);
426     Bind(&xIsNumberAndyIsNumber);
427     Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
428     Bind(&yIsInt);
429     {
430         intY = TaggedCastToInt32(y);
431         doubleY = ChangeInt32ToFloat64(*intY);
432         Jump(&xIsDoubleAndyIsDouble);
433     }
434     Bind(&yNotInt);
435     {
436         doubleY = TaggedCastToDouble(y);
437         Jump(&xIsDoubleAndyIsDouble);
438     }
439     Bind(&xIsDoubleAndyIsDouble);
440     {
441         Label divisorIsZero(env);
442         Label divisorNotZero(env);
443         Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &divisorIsZero, &divisorNotZero);
444         Bind(&divisorIsZero);
445         {
446             Label xIsZeroOrNan(env);
447             Label xNeiZeroOrNan(env);
448             Label xIsZero(env);
449             Label xNotZero(env);
450             // dLeft == 0.0 || std::isnan(dLeft)
451             Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsZero, &xNotZero);
452             Bind(&xIsZero);
453             Jump(&xIsZeroOrNan);
454             Bind(&xNotZero);
455             {
456                 Label xIsNan(env);
457                 Label xNotNan(env);
458                 Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan);
459                 Bind(&xIsNan);
460                 Jump(&xIsZeroOrNan);
461                 Bind(&xNotNan);
462                 Jump(&xNeiZeroOrNan);
463             }
464             Bind(&xIsZeroOrNan);
465             Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE)));
466             Bind(&xNeiZeroOrNan);
467             {
468                 GateRef intXTmp = CastDoubleToInt64(*doubleX);
469                 GateRef intYtmp = CastDoubleToInt64(*doubleY);
470                 intXTmp = Int64And(Int64Xor(intXTmp, intYtmp), GetInt64Constant(base::DOUBLE_SIGN_MASK));
471                 intXTmp = Int64Xor(intXTmp, CastDoubleToInt64(GetDoubleConstant(base::POSITIVE_INFINITY)));
472                 doubleX = CastInt64ToFloat64(intXTmp);
473                 Return(DoubleBuildTaggedWithNoGC(*doubleX));
474             }
475         }
476         Bind(&divisorNotZero);
477         {
478             doubleX = DoubleDiv(*doubleX, *doubleY);
479             Return(DoubleBuildTaggedWithNoGC(*doubleX));
480         }
481     }
482 }
483 
GenerateCircuit(const CompilationConfig * cfg)484 void FastModStub::GenerateCircuit(const CompilationConfig *cfg)
485 {
486     Stub::GenerateCircuit(cfg);
487     auto env = GetEnvironment();
488     GateRef glue = PtrArgument(0);
489     GateRef x = TaggedArgument(1);
490     GateRef y = TaggedArgument(2); // 2: 3rd argument
491     DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
492     DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
493     DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
494     DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
495     Label xIsInt(env);
496     Label xNotIntOryNotInt(env);
497     Branch(TaggedIsInt(x), &xIsInt, &xNotIntOryNotInt);
498     Bind(&xIsInt);
499     {
500         Label yIsInt(env);
501         Label xIsIntAndyIsInt(env);
502         // if right.IsInt()
503         Branch(TaggedIsInt(y), &yIsInt, &xNotIntOryNotInt);
504         Bind(&yIsInt);
505         {
506             intX = TaggedCastToInt32(x);
507             intY = TaggedCastToInt32(y);
508             Jump(&xIsIntAndyIsInt);
509         }
510         Bind(&xIsIntAndyIsInt);
511         {
512             Label xGtZero(env);
513             Label xGtZeroAndyGtZero(env);
514             Branch(Int32GreaterThan(*intX, GetInt32Constant(0)), &xGtZero, &xNotIntOryNotInt);
515             Bind(&xGtZero);
516             {
517                 Branch(Int32GreaterThan(*intY, GetInt32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt);
518                 Bind(&xGtZeroAndyGtZero);
519                 {
520                     intX = Int32Mod(*intX, *intY);
521                     Return(IntBuildTaggedWithNoGC(*intX));
522                 }
523             }
524         }
525     }
526     Bind(&xNotIntOryNotInt);
527     {
528         Label xIsNumber(env);
529         Label xNotNumberOryNotNumber(env);
530         Label xIsNumberAndyIsNumber(env);
531         Label xIsDoubleAndyIsDouble(env);
532         Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
533         Bind(&xIsNumber);
534         {
535             Label yIsNumber(env);
536             // if right.IsNumber()
537             Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
538             Bind(&yIsNumber);
539             {
540                 Label xIfInt(env);
541                 Label xIfNotInt(env);
542                 Branch(TaggedIsInt(x), &xIfInt, &xIfNotInt);
543                 Bind(&xIfInt);
544                 {
545                     intX = TaggedCastToInt32(x);
546                     doubleX = ChangeInt32ToFloat64(*intX);
547                     Jump(&xIsNumberAndyIsNumber);
548                 }
549                 Bind(&xIfNotInt);
550                 {
551                     doubleX = TaggedCastToDouble(x);
552                     Jump(&xIsNumberAndyIsNumber);
553                 }
554             }
555         }
556         Bind(&xNotNumberOryNotNumber);
557         Return(GetHoleConstant(StubMachineType::TAGGED));
558         Label yIfInt(env);
559         Label yIfNotInt(env);
560         Bind(&xIsNumberAndyIsNumber);
561         Branch(TaggedIsInt(y), &yIfInt, &yIfNotInt);
562         Bind(&yIfInt);
563         {
564             intY = TaggedCastToInt32(y);
565             doubleY = ChangeInt32ToFloat64(*intY);
566             Jump(&xIsDoubleAndyIsDouble);
567         }
568         Bind(&yIfNotInt);
569         {
570             doubleY = TaggedCastToDouble(y);
571             Jump(&xIsDoubleAndyIsDouble);
572         }
573         Bind(&xIsDoubleAndyIsDouble);
574         {
575             Label yIsZero(env);
576             Label yNotZero(env);
577             Label yIsZeroOrNanOrxIsNanOrInf(env);
578             Label yNeiZeroOrNanAndxNeiNanOrInf(env);
579             // dRight == 0.0 or std::isnan(dRight) or std::isnan(dLeft) or std::isinf(dLeft)
580             Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &yIsZero, &yNotZero);
581             Bind(&yIsZero);
582             Jump(&yIsZeroOrNanOrxIsNanOrInf);
583             Bind(&yNotZero);
584             {
585                 Label yIsNan(env);
586                 Label yNotNan(env);
587                 Branch(DoubleIsNAN(*doubleY), &yIsNan, &yNotNan);
588                 Bind(&yIsNan);
589                 Jump(&yIsZeroOrNanOrxIsNanOrInf);
590                 Bind(&yNotNan);
591                 {
592                     Label xIsNan(env);
593                     Label xNotNan(env);
594                     Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan);
595                     Bind(&xIsNan);
596                     Jump(&yIsZeroOrNanOrxIsNanOrInf);
597                     Bind(&xNotNan);
598                     {
599                         Label xIsInf(env);
600                         Label xNotInf(env);
601                         Branch(DoubleIsINF(*doubleX), &xIsInf, &xNotInf);
602                         Bind(&xIsInf);
603                         Jump(&yIsZeroOrNanOrxIsNanOrInf);
604                         Bind(&xNotInf);
605                         Jump(&yNeiZeroOrNanAndxNeiNanOrInf);
606                     }
607                 }
608             }
609             Bind(&yIsZeroOrNanOrxIsNanOrInf);
610             Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE)));
611             Bind(&yNeiZeroOrNanAndxNeiNanOrInf);
612             {
613                 Label xIsFloatZero(env);
614                 Label xIsZeroOryIsInf(env);
615                 Label xNotZeroAndyNotInf(env);
616                 Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsFloatZero, &xNotZeroAndyNotInf);
617                 Bind(&xIsFloatZero);
618                 Jump(&xIsZeroOryIsInf);
619                 Label yIsInf(env);
620                 Label yNotInf(env);
621                 Bind(&xNotZeroAndyNotInf);
622                 Branch(DoubleIsINF(*doubleY), &yIsInf, &yNotInf);
623                 Bind(&yIsInf);
624                 Jump(&xIsZeroOryIsInf);
625                 Bind(&yNotInf);
626                 {
627                     doubleX = TaggedCastToDouble(CallRuntimeTrampoline(glue, GetInt64Constant(FAST_STUB_ID(FloatMod)), {
628                             DoubleBuildTaggedTypeWithNoGC(*doubleX), DoubleBuildTaggedTypeWithNoGC(*doubleY)
629                         }));
630                     Return(DoubleBuildTaggedWithNoGC(*doubleX));
631                 }
632                 Bind(&xIsZeroOryIsInf);
633                 Return(DoubleBuildTaggedWithNoGC(*doubleX));
634             }
635         }
636     }
637 }
638 
GenerateCircuit(const CompilationConfig * cfg)639 void FastTypeOfStub::GenerateCircuit(const CompilationConfig *cfg)
640 {
641     Stub::GenerateCircuit(cfg);
642     auto env = GetEnvironment();
643     GateRef glue = PtrArgument(0);
644     GateRef obj = TaggedArgument(1);
645     DEFVARIABLE(holder, StubMachineType::TAGGED, obj);
646     GateRef gConstOffset = IntPtrAdd(glue, GetIntPtrConstant(env->GetGlueOffset(JSThread::GlueID::GLOBAL_CONST)));
647     GateRef booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX);
648     GateRef gConstUndefindStr = Load(StubMachineType::TAGGED_POINTER, gConstOffset, booleanIndex);
649     DEFVARIABLE(resultRep, StubMachineType::TAGGED_POINTER, gConstUndefindStr);
650     Label objIsTrue(env);
651     Label objNotTrue(env);
652     Label exit(env);
653     Label defaultLabel(env);
654     GateRef gConstBooleanStr = Load(
655         StubMachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX));
656     Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_TRUE)), &objIsTrue, &objNotTrue);
657     Bind(&objIsTrue);
658     {
659         resultRep = gConstBooleanStr;
660         Jump(&exit);
661     }
662     Bind(&objNotTrue);
663     {
664         Label objIsFalse(env);
665         Label objNotFalse(env);
666         Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_FALSE)), &objIsFalse, &objNotFalse);
667         Bind(&objIsFalse);
668         {
669             resultRep = gConstBooleanStr;
670             Jump(&exit);
671         }
672         Bind(&objNotFalse);
673         {
674             Label objIsNull(env);
675             Label objNotNull(env);
676             Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_NULL)), &objIsNull, &objNotNull);
677             Bind(&objIsNull);
678             {
679                 resultRep = Load(
680                     StubMachineType::TAGGED_POINTER, gConstOffset,
681                     GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
682                 Jump(&exit);
683             }
684             Bind(&objNotNull);
685             {
686                 Label objIsUndefined(env);
687                 Label objNotUndefined(env);
688                 Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)), &objIsUndefined,
689                     &objNotUndefined);
690                 Bind(&objIsUndefined);
691                 {
692                     resultRep = Load(StubMachineType::TAGGED_POINTER, gConstOffset,
693                         GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX));
694                     Jump(&exit);
695                 }
696                 Bind(&objNotUndefined);
697                 Jump(&defaultLabel);
698             }
699         }
700     }
701     Bind(&defaultLabel);
702     {
703         Label objIsHeapObject(env);
704         Label objNotHeapObject(env);
705         Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
706         Bind(&objIsHeapObject);
707         {
708             Label objIsString(env);
709             Label objNotString(env);
710             Branch(IsString(obj), &objIsString, &objNotString);
711             Bind(&objIsString);
712             {
713                 resultRep = Load(
714                     StubMachineType::TAGGED_POINTER, gConstOffset,
715                     GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX));
716                 Jump(&exit);
717             }
718             Bind(&objNotString);
719             {
720                 Label objIsSymbol(env);
721                 Label objNotSymbol(env);
722                 Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol);
723                 Bind(&objIsSymbol);
724                 {
725                     resultRep = Load(StubMachineType::TAGGED_POINTER, gConstOffset,
726                         GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX));
727                     Jump(&exit);
728                 }
729                 Bind(&objNotSymbol);
730                 {
731                     Label objIsCallable(env);
732                     Label objNotCallable(env);
733                     Branch(IsCallable(obj), &objIsCallable, &objNotCallable);
734                     Bind(&objIsCallable);
735                     {
736                         resultRep = Load(
737                             StubMachineType::TAGGED_POINTER, gConstOffset,
738                             GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX));
739                         Jump(&exit);
740                     }
741                     Bind(&objNotCallable);
742                     {
743                         resultRep = Load(
744                             StubMachineType::TAGGED_POINTER, gConstOffset,
745                             GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
746                         Jump(&exit);
747                     }
748                 }
749             }
750         }
751         Bind(&objNotHeapObject);
752         {
753             Label objIsNum(env);
754             Label objNotNum(env);
755             Branch(TaggedIsNumber(obj), &objIsNum, &objNotNum);
756             Bind(&objIsNum);
757             {
758                 resultRep = Load(
759                     StubMachineType::TAGGED_POINTER, gConstOffset,
760                     GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX));
761                 Jump(&exit);
762             }
763             Bind(&objNotNum);
764             Jump(&exit);
765         }
766     }
767     Bind(&exit);
768     Return(*resultRep);
769 }
770 
GenerateCircuit(const CompilationConfig * cfg)771 void FastEqualStub::GenerateCircuit(const CompilationConfig *cfg)
772 {
773     Stub::GenerateCircuit(cfg);
774     auto env = GetEnvironment();
775     GateRef x = TaggedArgument(0);
776     GateRef y = TaggedArgument(1);
777     Label xIsEqualy(env);
778     Label xIsNotEqualy(env);
779     Branch(Int64Equal(x, y), &xIsEqualy, &xIsNotEqualy);
780     Bind(&xIsEqualy);
781     {
782         Label xIsDouble(env);
783         Label xNotDoubleOrxNotNan(env);
784         Branch(TaggedIsDouble(x), &xIsDouble, &xNotDoubleOrxNotNan);
785         Bind(&xIsDouble);
786         {
787             GateRef doubleX = TaggedCastToDouble(x);
788             Label xIsNan(env);
789             Branch(DoubleIsNAN(doubleX), &xIsNan, &xNotDoubleOrxNotNan);
790             Bind(&xIsNan);
791             Return(TaggedFalse());
792         }
793         Bind(&xNotDoubleOrxNotNan);
794         Return(TaggedTrue());
795     }
796     Bind(&xIsNotEqualy);
797     {
798         Label xIsNumber(env);
799         Label xNotNumberAndxNotIntAndyNotInt(env);
800         Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberAndxNotIntAndyNotInt);
801         Bind(&xIsNumber);
802         {
803             Label xIsInt(env);
804             Branch(TaggedIsInt(x), &xIsInt, &xNotNumberAndxNotIntAndyNotInt);
805             Bind(&xIsInt);
806             {
807                 Label yIsInt(env);
808                 Branch(TaggedIsInt(y), &yIsInt, &xNotNumberAndxNotIntAndyNotInt);
809                 Bind(&yIsInt);
810                 Return(TaggedFalse());
811             }
812         }
813         Bind(&xNotNumberAndxNotIntAndyNotInt);
814         {
815             Label yIsUndefinedOrNull(env);
816             Label xyNotUndefinedAndNull(env);
817             Branch(TaggedIsUndefinedOrNull(y), &yIsUndefinedOrNull, &xyNotUndefinedAndNull);
818             Bind(&yIsUndefinedOrNull);
819             {
820                 Label xIsHeapObject(env);
821                 Label xNotHeapObject(env);
822                 Branch(TaggedIsHeapObject(x), &xIsHeapObject, &xNotHeapObject);
823                 Bind(&xIsHeapObject);
824                 Return(TaggedFalse());
825                 Bind(&xNotHeapObject);
826                 {
827                     Label xIsUndefinedOrNull(env);
828                     Branch(TaggedIsUndefinedOrNull(x), &xIsUndefinedOrNull, &xyNotUndefinedAndNull);
829                     Bind(&xIsUndefinedOrNull);
830                     Return(TaggedTrue());
831                 }
832             }
833             Bind(&xyNotUndefinedAndNull);
834             {
835                 Label xIsBoolean(env);
836                 Label xNotBooleanAndyNotSpecial(env);
837                 Branch(TaggedIsBoolean(x), &xIsBoolean, &xNotBooleanAndyNotSpecial);
838                 Bind(&xIsBoolean);
839                 {
840                     Label yIsSpecial(env);
841                     Branch(TaggedIsSpecial(y), &yIsSpecial, &xNotBooleanAndyNotSpecial);
842                     Bind(&yIsSpecial);
843                     Return(TaggedFalse());
844                 }
845                 Bind(&xNotBooleanAndyNotSpecial);
846                 {
847                     Return(GetHoleConstant(StubMachineType::UINT64));
848                 }
849             }
850         }
851     }
852 }
853 
GenerateCircuit(const CompilationConfig * cfg)854 void GetPropertyByIndexStub::GenerateCircuit(const CompilationConfig *cfg)
855 {
856     Stub::GenerateCircuit(cfg);
857     GateRef glue = PtrArgument(0);
858     GateRef receiver = TaggedArgument(1);
859     GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
860     Return(GetPropertyByIndex(glue, receiver, index));
861 }
862 
GenerateCircuit(const CompilationConfig * cfg)863 void SetPropertyByIndexStub::GenerateCircuit(const CompilationConfig *cfg)
864 {
865     Stub::GenerateCircuit(cfg);
866     GateRef glue = PtrArgument(0);
867     GateRef receiver = TaggedArgument(1);
868     GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
869     GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
870     Return(SetPropertyByIndex(glue, receiver, index, value));
871 }
872 
GenerateCircuit(const CompilationConfig * cfg)873 void GetPropertyByNameStub::GenerateCircuit(const CompilationConfig *cfg)
874 {
875     Stub::GenerateCircuit(cfg);
876     GateRef glue = PtrArgument(0);
877     GateRef receiver = TaggedArgument(1);
878     GateRef key = TaggedArgument(2); // 2 : 3rd para
879     Return(GetPropertyByName(glue, receiver, key));
880 }
881 
GenerateCircuit(const CompilationConfig * cfg)882 void SetPropertyByNameStub::GenerateCircuit(const CompilationConfig *cfg)
883 {
884     Stub::GenerateCircuit(cfg);
885     GateRef glue = PtrArgument(0);
886     GateRef receiver = TaggedArgument(1);
887     GateRef key = TaggedArgument(2); // 2 : 3rd para
888     GateRef value = TaggedArgument(3); // 3 : 4th para
889     Return(SetPropertyByName(glue, receiver, key, value));
890 }
891 
GenerateCircuit(const CompilationConfig * cfg)892 void SetPropertyByNameWithOwnStub::GenerateCircuit(const CompilationConfig *cfg)
893 {
894     Stub::GenerateCircuit(cfg);
895     GateRef glue = PtrArgument(0);
896     GateRef receiver = TaggedArgument(1);
897     GateRef key = TaggedArgument(2); // 2 : 3rd para
898     GateRef value = TaggedArgument(3); // 3 : 4th para
899     Return(SetPropertyByNameWithOwn(glue, receiver, key, value));
900 }
901 
GenerateCircuit(const CompilationConfig * cfg)902 void GetPropertyByValueStub::GenerateCircuit(const CompilationConfig *cfg)
903 {
904     Stub::GenerateCircuit(cfg);
905     auto env = GetEnvironment();
906     GateRef glue = PtrArgument(0);
907     GateRef receiver = TaggedArgument(1);
908     DEFVARIABLE(key, StubMachineType::TAGGED, TaggedArgument(2)); /* 2 : 3rd parameter is key */
909 
910     Label isNumberOrStringSymbol(env);
911     Label notNumber(env);
912     Label isStringOrSymbol(env);
913     Label notStringOrSymbol(env);
914     Label exit(env);
915 
916     Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, &notNumber);
917     Bind(&notNumber);
918     {
919         Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, &notStringOrSymbol);
920         Bind(&notStringOrSymbol);
921         {
922             Return(GetHoleConstant());
923         }
924     }
925     Bind(&isNumberOrStringSymbol);
926     {
927         GateRef index = TryToElementsIndex(*key);
928         Label validIndex(env);
929         Label notValidIndex(env);
930         Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, &notValidIndex);
931         Bind(&validIndex);
932         {
933             Return(GetPropertyByIndex(glue, receiver, index));
934         }
935         Bind(&notValidIndex);
936         {
937             Label notNumber(env);
938             Label getByName(env);
939             Branch(TaggedIsNumber(*key), &exit, &notNumber);
940             Bind(&notNumber);
941             {
942                 Label isString(env);
943                 Label notString(env);
944                 Label isInternalString(env);
945                 Label notIntenalString(env);
946                 Branch(TaggedIsString(*key), &isString, &notString);
947                 Bind(&isString);
948                 {
949                     Branch(IsInternalString(*key), &isInternalString, &notIntenalString);
950                     Bind(&isInternalString);
951                     Jump(&getByName);
952                     Bind(&notIntenalString);
953                     {
954                         key = CallRuntimeTrampoline(glue,
955                             GetInt64Constant(FAST_STUB_ID(NewInternalString)), { *key });
956                         Jump(&getByName);
957                     }
958                 }
959                 Bind(&notString);
960                 {
961                     Jump(&getByName);
962                 }
963             }
964             Bind(&getByName);
965             {
966                 Return(GetPropertyByName(glue, receiver, *key));
967             }
968         }
969     }
970     Bind(&exit);
971     Return(GetHoleConstant());
972 }
973 
GenerateCircuit(const CompilationConfig * cfg)974 void SetPropertyByValueStub::GenerateCircuit(const CompilationConfig *cfg)
975 {
976     Stub::GenerateCircuit(cfg);
977     auto env = GetEnvironment();
978     GateRef glue = PtrArgument(0);
979     GateRef receiver = TaggedArgument(1);
980     DEFVARIABLE(key, StubMachineType::TAGGED, TaggedArgument(2)); /* 2 : 3rd parameter is key */
981     GateRef value = TaggedArgument(3);            /* 3 : 4th parameter is value */
982 
983     Label isNumberOrStringSymbol(env);
984     Label notNumber(env);
985     Label isStringOrSymbol(env);
986     Label notStringOrSymbol(env);
987     Label exit(env);
988 
989     Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, &notNumber);
990     Bind(&notNumber);
991     {
992         Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, &notStringOrSymbol);
993         Bind(&notStringOrSymbol);
994         {
995             Return(GetHoleConstant(StubMachineType::UINT64));
996         }
997     }
998     Bind(&isNumberOrStringSymbol);
999     {
1000         GateRef index = TryToElementsIndex(*key);
1001         Label validIndex(env);
1002         Label notValidIndex(env);
1003         Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, &notValidIndex);
1004         Bind(&validIndex);
1005         {
1006             Return(SetPropertyByIndex(glue, receiver, index, value));
1007         }
1008         Bind(&notValidIndex);
1009         {
1010             Label notNumber(env);
1011             Label getByName(env);
1012             Branch(TaggedIsNumber(*key), &exit, &notNumber);
1013             Bind(&notNumber);
1014             {
1015                 Label isString(env);
1016                 Label notString(env);
1017                 Label isInternalString(env);
1018                 Label notIntenalString(env);
1019                 Branch(TaggedIsString(*key), &isString, &notString);
1020                 Bind(&isString);
1021                 {
1022                     Branch(IsInternalString(*key), &isInternalString, &notIntenalString);
1023                     Bind(&isInternalString);
1024                     Jump(&getByName);
1025                     Bind(&notIntenalString);
1026                     {
1027                         key = CallRuntimeTrampoline(glue,
1028                             GetInt64Constant(FAST_STUB_ID(NewInternalString)), { *key });
1029                         Jump(&getByName);
1030                     }
1031                 }
1032                 Bind(&notString);
1033                 {
1034                     Jump(&getByName);
1035                 }
1036             }
1037             Bind(&getByName);
1038             {
1039                 Return(SetPropertyByName(glue, receiver, *key, value));
1040             }
1041         }
1042     }
1043     Bind(&exit);
1044     Return(GetHoleConstant(StubMachineType::UINT64));
1045 }
1046 
GenerateCircuit(const CompilationConfig * cfg)1047 void TryLoadICByNameStub::GenerateCircuit(const CompilationConfig *cfg)
1048 {
1049     Stub::GenerateCircuit(cfg);
1050     auto env = GetEnvironment();
1051     GateRef glue = PtrArgument(0);
1052     GateRef receiver = TaggedArgument(1);
1053     GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
1054     GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1055 
1056     Label receiverIsHeapObject(env);
1057     Label receiverNotHeapObject(env);
1058     Label hclassEqualFirstValue(env);
1059     Label hclassNotEqualFirstValue(env);
1060     Label cachedHandlerNotHole(env);
1061     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1062     Bind(&receiverIsHeapObject);
1063     {
1064         GateRef hclass = LoadHClass(receiver);
1065         Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1066                &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1067         Bind(&hclassEqualFirstValue);
1068         {
1069             Return(LoadICWithHandler(glue, receiver, receiver, secondValue));
1070         }
1071         Bind(&hclassNotEqualFirstValue);
1072         {
1073             GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
1074             Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1075             Bind(&cachedHandlerNotHole);
1076             {
1077                 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
1078             }
1079         }
1080     }
1081     Bind(&receiverNotHeapObject);
1082     {
1083         Return(GetHoleConstant());
1084     }
1085 }
1086 
GenerateCircuit(const CompilationConfig * cfg)1087 void TryLoadICByValueStub::GenerateCircuit(const CompilationConfig *cfg)
1088 {
1089     Stub::GenerateCircuit(cfg);
1090     auto env = GetEnvironment();
1091     GateRef glue = PtrArgument(0);
1092     GateRef receiver = TaggedArgument(1);
1093     GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
1094     GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1095     GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
1096 
1097     Label receiverIsHeapObject(env);
1098     Label receiverNotHeapObject(env);
1099     Label hclassEqualFirstValue(env);
1100     Label hclassNotEqualFirstValue(env);
1101     Label firstValueEqualKey(env);
1102     Label cachedHandlerNotHole(env);
1103     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1104     Bind(&receiverIsHeapObject);
1105     {
1106         GateRef hclass = LoadHClass(receiver);
1107         Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1108             &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1109         Bind(&hclassEqualFirstValue);
1110         Return(LoadElement(receiver, key));
1111         Bind(&hclassNotEqualFirstValue);
1112         {
1113             Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
1114             Bind(&firstValueEqualKey);
1115             {
1116                 auto cachedHandler = CheckPolyHClass(secondValue, hclass);
1117                 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1118                 Bind(&cachedHandlerNotHole);
1119                 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
1120             }
1121         }
1122     }
1123     Bind(&receiverNotHeapObject);
1124     Return(GetHoleConstant());
1125 }
1126 
GenerateCircuit(const CompilationConfig * cfg)1127 void TryStoreICByNameStub::GenerateCircuit(const CompilationConfig *cfg)
1128 {
1129     Stub::GenerateCircuit(cfg);
1130     auto env = GetEnvironment();
1131     GateRef glue = PtrArgument(0);
1132     GateRef receiver = TaggedArgument(1);
1133     GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
1134     GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1135     GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */
1136     Label receiverIsHeapObject(env);
1137     Label receiverNotHeapObject(env);
1138     Label hclassEqualFirstValue(env);
1139     Label hclassNotEqualFirstValue(env);
1140     Label cachedHandlerNotHole(env);
1141     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1142     Bind(&receiverIsHeapObject);
1143     {
1144         GateRef hclass = LoadHClass(receiver);
1145         Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1146                &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1147         Bind(&hclassEqualFirstValue);
1148         {
1149             Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue));
1150         }
1151         Bind(&hclassNotEqualFirstValue);
1152         {
1153             GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
1154             Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1155             Bind(&cachedHandlerNotHole);
1156             {
1157                 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
1158             }
1159         }
1160     }
1161     Bind(&receiverNotHeapObject);
1162     Return(GetHoleConstant(StubMachineType::UINT64));
1163 }
1164 
GenerateCircuit(const CompilationConfig * cfg)1165 void TryStoreICByValueStub::GenerateCircuit(const CompilationConfig *cfg)
1166 {
1167     Stub::GenerateCircuit(cfg);
1168     auto env = GetEnvironment();
1169     GateRef glue = PtrArgument(0);
1170     GateRef receiver = TaggedArgument(1);
1171     GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
1172     GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1173     GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
1174     GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */
1175     Label receiverIsHeapObject(env);
1176     Label receiverNotHeapObject(env);
1177     Label hclassEqualFirstValue(env);
1178     Label hclassNotEqualFirstValue(env);
1179     Label firstValueEqualKey(env);
1180     Label cachedHandlerNotHole(env);
1181     Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1182     Bind(&receiverIsHeapObject);
1183     {
1184         GateRef hclass = LoadHClass(receiver);
1185         Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1186             &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1187         Bind(&hclassEqualFirstValue);
1188         Return(ICStoreElement(glue, receiver, key, value, secondValue));
1189         Bind(&hclassNotEqualFirstValue);
1190         {
1191             Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
1192             Bind(&firstValueEqualKey);
1193             {
1194                 GateRef cachedHandler = CheckPolyHClass(secondValue, hclass);
1195                 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1196                 Bind(&cachedHandlerNotHole);
1197                 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
1198             }
1199         }
1200     }
1201     Bind(&receiverNotHeapObject);
1202     Return(GetHoleConstant(StubMachineType::UINT64));
1203 }
1204 
GenerateCircuit(const CompilationConfig * cfg)1205 void TestAbsoluteAddressRelocationStub::GenerateCircuit(const CompilationConfig *cfg)
1206 {
1207     Stub::GenerateCircuit(cfg);
1208     auto env = GetEnvironment();
1209     GateRef a = Int64Argument(0);
1210     GateRef b = Int64Argument(1);
1211     Label start(env);
1212     Jump(&start);
1213     Bind(&start);
1214     GateRef globalValueC = GetRelocatableData(0xabc);
1215     GateRef globalValueD = GetRelocatableData(0xbcd);
1216     GateRef dummyValueC = Load(StubMachineType::INT64, globalValueC);
1217     GateRef dummyValueD = Load(StubMachineType::INT64, globalValueD);
1218     // Load from same relocatable data twice to see if it breaks constant fold opt. Result shows it doesn't.
1219     GateRef dummyValueC1 = Load(StubMachineType::INT64, globalValueC);
1220     GateRef result = Int64Add(a, Int64Add(b, Int64Add(dummyValueC, Int64Add(dummyValueD, dummyValueC1))));
1221     Return(result);
1222 }
1223 }  // namespace panda::ecmascript::kungfu
1224