• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/compiler/operations_stub_builder.h"
17 #include "ecmascript/compiler/stub_builder-inl.h"
18 
19 namespace panda::ecmascript::kungfu {
Equal(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)20 GateRef OperationsStubBuilder::Equal(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
21 {
22     auto env = GetEnvironment();
23     Label entry(env);
24     env->SubCfgEntry(&entry);
25     Label exit(env);
26     Label isHole(env);
27     Label notHole(env);
28     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
29     result = FastEqual(glue, left, right, callback);
30     BRANCH(TaggedIsHole(*result), &isHole, &notHole);
31     Bind(&isHole);
32     {
33         // slow path
34         result = CallRuntime(glue, RTSTUB_ID(Eq), { left, right });
35         Jump(&exit);
36     }
37     Bind(&notHole);
38     {
39         Label resultIsTrue(env);
40         Label resultNotTrue(env);
41         BRANCH(TaggedIsTrue(*result), &resultIsTrue, &resultNotTrue);
42         Bind(&resultIsTrue);
43         {
44             callback.ProfileBranch(true);
45             Jump(&exit);
46         }
47         Bind(&resultNotTrue);
48         {
49             callback.ProfileBranch(false);
50             Jump(&exit);
51         }
52     }
53     Bind(&exit);
54     auto ret = *result;
55     env->SubCfgExit();
56     return ret;
57 }
58 
NotEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)59 GateRef OperationsStubBuilder::NotEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
60 {
61     auto env = GetEnvironment();
62     Label entry(env);
63     env->SubCfgEntry(&entry);
64     Label exit(env);
65 
66     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
67     result = FastEqual(glue, left, right, callback);
68     Label isHole(env);
69     Label notHole(env);
70     BRANCH(TaggedIsHole(*result), &isHole, &notHole);
71     Bind(&isHole);
72     {
73         // slow path
74         result = CallRuntime(glue, RTSTUB_ID(NotEq), { left, right });
75         Jump(&exit);
76     }
77     Bind(&notHole);
78     {
79         Label resultIsTrue(env);
80         Label resultNotTrue(env);
81         BRANCH(TaggedIsTrue(*result), &resultIsTrue, &resultNotTrue);
82         Bind(&resultIsTrue);
83         {
84             result = TaggedFalse();
85             callback.ProfileBranch(false);
86             Jump(&exit);
87         }
88         Bind(&resultNotTrue);
89         {
90             callback.ProfileBranch(true);
91             result = TaggedTrue();
92             Jump(&exit);
93         }
94     }
95     Bind(&exit);
96     auto ret = *result;
97     env->SubCfgExit();
98     return ret;
99 }
100 
StrictEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)101 GateRef OperationsStubBuilder::StrictEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
102 {
103     auto env = GetEnvironment();
104     Label entry(env);
105     env->SubCfgEntry(&entry);
106     Label exit(env);
107     Label strictEqual(env);
108     Label notStrictEqual(env);
109     DEFVARIABLE(result, VariableType::JS_ANY(), TaggedTrue());
110     BRANCH(FastStrictEqual(glue, left, right, callback), &strictEqual, &notStrictEqual);
111     Bind(&strictEqual);
112     {
113         callback.ProfileBranch(true);
114         Jump(&exit);
115     }
116     Bind(&notStrictEqual);
117     {
118         result = TaggedFalse();
119         callback.ProfileBranch(false);
120         Jump(&exit);
121     }
122     Bind(&exit);
123     auto ret = *result;
124     env->SubCfgExit();
125     return ret;
126 }
127 
StrictNotEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)128 GateRef OperationsStubBuilder::StrictNotEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
129 {
130     auto env = GetEnvironment();
131     Label entry(env);
132     env->SubCfgEntry(&entry);
133     Label exit(env);
134     Label strictEqual(env);
135     Label notStrictEqual(env);
136     DEFVARIABLE(result, VariableType::JS_ANY(), TaggedTrue());
137     BRANCH(FastStrictEqual(glue, left, right, callback), &strictEqual, &notStrictEqual);
138     Bind(&strictEqual);
139     {
140         result = TaggedFalse();
141         callback.ProfileBranch(false);
142         Jump(&exit);
143     }
144     Bind(&notStrictEqual);
145     {
146         callback.ProfileBranch(true);
147         Jump(&exit);
148     }
149     Bind(&exit);
150     auto ret = *result;
151     env->SubCfgExit();
152     return ret;
153 }
154 
Less(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)155 GateRef OperationsStubBuilder::Less(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
156 {
157     auto env = GetEnvironment();
158     Label entry(env);
159     env->SubCfgEntry(&entry);
160     Label exit(env);
161     Label leftIsInt(env);
162     Label leftOrRightNotInt(env);
163     Label leftLessRight(env);
164     Label leftNotLessRight(env);
165     Label slowPath(env);
166 
167     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
168     BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
169     Bind(&leftIsInt);
170     {
171         Label rightIsInt(env);
172         BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
173         Bind(&rightIsInt);
174         {
175             callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
176             GateRef intLeft = TaggedGetInt(left);
177             GateRef intRight = TaggedGetInt(right);
178             BRANCH(Int32LessThan(intLeft, intRight), &leftLessRight, &leftNotLessRight);
179         }
180     }
181     Bind(&leftOrRightNotInt);
182     {
183         Label leftIsNumber(env);
184         BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath);
185         Bind(&leftIsNumber);
186         {
187             Label rightIsNumber(env);
188             BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath);
189             Bind(&rightIsNumber);
190             {
191                 // fast path
192                 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
193                 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
194                 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType()));
195                 Label leftIsInt1(env);
196                 Label leftNotInt1(env);
197                 Label exit1(env);
198                 Label exit2(env);
199                 Label rightIsInt1(env);
200                 Label rightNotInt1(env);
201                 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
202                 Bind(&leftIsInt1);
203                 {
204                     doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
205                     Jump(&exit1);
206                 }
207                 Bind(&leftNotInt1);
208                 {
209                     curType = TaggedInt(PGOSampleType::DoubleType());
210                     doubleLeft = GetDoubleOfTDouble(left);
211                     Jump(&exit1);
212                 }
213                 Bind(&exit1);
214                 {
215                     BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
216                 }
217                 Bind(&rightIsInt1);
218                 {
219                     GateRef type = TaggedInt(PGOSampleType::IntType());
220                     COMBINE_TYPE_CALL_BACK(curType, type);
221                     doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
222                     Jump(&exit2);
223                 }
224                 Bind(&rightNotInt1);
225                 {
226                     GateRef type = TaggedInt(PGOSampleType::DoubleType());
227                     COMBINE_TYPE_CALL_BACK(curType, type);
228                     doubleRight = GetDoubleOfTDouble(right);
229                     Jump(&exit2);
230                 }
231                 Bind(&exit2);
232                 {
233                     BRANCH(DoubleLessThan(*doubleLeft, *doubleRight), &leftLessRight, &leftNotLessRight);
234                 }
235             }
236         }
237     }
238     Bind(&leftLessRight);
239     {
240         callback.ProfileBranch(true);
241         result = TaggedTrue();
242         Jump(&exit);
243     }
244     Bind(&leftNotLessRight);
245     {
246         callback.ProfileBranch(false);
247         result = TaggedFalse();
248         Jump(&exit);
249     }
250     Bind(&slowPath);
251     {
252         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
253         result = CallRuntime(glue, RTSTUB_ID(Less), { left, right });
254         Jump(&exit);
255     }
256     Bind(&exit);
257     auto ret = *result;
258     env->SubCfgExit();
259     return ret;
260 }
261 
LessEq(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)262 GateRef OperationsStubBuilder::LessEq(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
263 {
264     auto env = GetEnvironment();
265     Label entry(env);
266     env->SubCfgEntry(&entry);
267     Label exit(env);
268     Label leftIsInt(env);
269     Label leftOrRightNotInt(env);
270     Label leftLessEqRight(env);
271     Label leftNotLessEqRight(env);
272     Label slowPath(env);
273 
274     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
275     BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
276     Bind(&leftIsInt);
277     {
278         Label rightIsInt(env);
279         BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
280         Bind(&rightIsInt);
281         {
282             callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
283             GateRef intLeft = TaggedGetInt(left);
284             GateRef intRight = TaggedGetInt(right);
285             BRANCH(Int32LessThanOrEqual(intLeft, intRight), &leftLessEqRight, &leftNotLessEqRight);
286         }
287     }
288     Bind(&leftOrRightNotInt);
289     {
290         Label leftIsNumber(env);
291         BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath);
292         Bind(&leftIsNumber);
293         {
294             Label rightIsNumber(env);
295             BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath);
296             Bind(&rightIsNumber);
297             {
298                 // fast path
299                 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
300                 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
301                 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType()));
302                 Label leftIsInt1(env);
303                 Label leftNotInt1(env);
304                 Label exit1(env);
305                 Label exit2(env);
306                 Label rightIsInt1(env);
307                 Label rightNotInt1(env);
308                 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
309                 Bind(&leftIsInt1);
310                 {
311                     doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
312                     Jump(&exit1);
313                 }
314                 Bind(&leftNotInt1);
315                 {
316                     curType = TaggedInt(PGOSampleType::DoubleType());
317                     doubleLeft = GetDoubleOfTDouble(left);
318                     Jump(&exit1);
319                 }
320                 Bind(&exit1);
321                 {
322                     BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
323                 }
324                 Bind(&rightIsInt1);
325                 {
326                     GateRef type = TaggedInt(PGOSampleType::IntType());
327                     COMBINE_TYPE_CALL_BACK(curType, type);
328                     doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
329                     Jump(&exit2);
330                 }
331                 Bind(&rightNotInt1);
332                 {
333                     GateRef type = TaggedInt(PGOSampleType::DoubleType());
334                     COMBINE_TYPE_CALL_BACK(curType, type);
335                     doubleRight = GetDoubleOfTDouble(right);
336                     Jump(&exit2);
337                 }
338                 Bind(&exit2);
339                 {
340                     BRANCH(DoubleLessThanOrEqual(*doubleLeft, *doubleRight), &leftLessEqRight, &leftNotLessEqRight);
341                 }
342             }
343         }
344     }
345     Bind(&leftLessEqRight);
346     {
347         callback.ProfileBranch(true);
348         result = TaggedTrue();
349         Jump(&exit);
350     }
351     Bind(&leftNotLessEqRight);
352     {
353         callback.ProfileBranch(false);
354         result = TaggedFalse();
355         Jump(&exit);
356     }
357     Bind(&slowPath);
358     {
359         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
360         result = CallRuntime(glue, RTSTUB_ID(LessEq), { left, right });
361         Jump(&exit);
362     }
363     Bind(&exit);
364     auto ret = *result;
365     env->SubCfgExit();
366     return ret;
367 }
368 
Greater(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)369 GateRef OperationsStubBuilder::Greater(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
370 {
371     auto env = GetEnvironment();
372     Label entry(env);
373     env->SubCfgEntry(&entry);
374     Label exit(env);
375     Label leftIsInt(env);
376     Label leftOrRightNotInt(env);
377     Label leftGreaterRight(env);
378     Label leftNotGreaterRight(env);
379     Label slowPath(env);
380     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
381     BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
382     Bind(&leftIsInt);
383     {
384         Label rightIsInt(env);
385         BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
386         Bind(&rightIsInt);
387         {
388             callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
389             GateRef intLeft = TaggedGetInt(left);
390             GateRef intRight = TaggedGetInt(right);
391             BRANCH(Int32GreaterThan(intLeft, intRight), &leftGreaterRight, &leftNotGreaterRight);
392         }
393     }
394     Bind(&leftOrRightNotInt);
395     {
396         Label leftIsNumber(env);
397         BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath);
398         Bind(&leftIsNumber);
399         {
400             Label rightIsNumber(env);
401             BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath);
402             Bind(&rightIsNumber);
403             {
404                 // fast path
405                 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
406                 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
407                 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType()));
408                 Label leftIsInt1(env);
409                 Label leftNotInt1(env);
410                 Label exit1(env);
411                 Label exit2(env);
412                 Label rightIsInt1(env);
413                 Label rightNotInt1(env);
414                 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
415                 Bind(&leftIsInt1);
416                 {
417                     doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
418                     Jump(&exit1);
419                 }
420                 Bind(&leftNotInt1);
421                 {
422                     curType = TaggedInt(PGOSampleType::DoubleType());
423                     doubleLeft = GetDoubleOfTDouble(left);
424                     Jump(&exit1);
425                 }
426                 Bind(&exit1);
427                 {
428                     BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
429                 }
430                 Bind(&rightIsInt1);
431                 {
432                     GateRef type = TaggedInt(PGOSampleType::IntType());
433                     COMBINE_TYPE_CALL_BACK(curType, type);
434                     doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
435                     Jump(&exit2);
436                 }
437                 Bind(&rightNotInt1);
438                 {
439                     GateRef type = TaggedInt(PGOSampleType::DoubleType());
440                     COMBINE_TYPE_CALL_BACK(curType, type);
441                     doubleRight = GetDoubleOfTDouble(right);
442                     Jump(&exit2);
443                 }
444                 Bind(&exit2);
445                 {
446                     BRANCH(DoubleGreaterThan(*doubleLeft, *doubleRight), &leftGreaterRight, &leftNotGreaterRight);
447                 }
448             }
449         }
450     }
451     Bind(&leftGreaterRight);
452     {
453         callback.ProfileBranch(true);
454         result = TaggedTrue();
455         Jump(&exit);
456     }
457     Bind(&leftNotGreaterRight);
458     {
459         callback.ProfileBranch(false);
460         result = TaggedFalse();
461         Jump(&exit);
462     }
463     Bind(&slowPath);
464     {
465         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
466         result = CallRuntime(glue, RTSTUB_ID(Greater), { left, right });
467         Jump(&exit);
468     }
469     Bind(&exit);
470     auto ret = *result;
471     env->SubCfgExit();
472     return ret;
473 }
474 
GreaterEq(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)475 GateRef OperationsStubBuilder::GreaterEq(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
476 {
477     auto env = GetEnvironment();
478     Label entry(env);
479     env->SubCfgEntry(&entry);
480     Label exit(env);
481     Label leftIsInt(env);
482     Label leftOrRightNotInt(env);
483     Label leftGreaterEqRight(env);
484     Label leftNotGreaterEQRight(env);
485     Label slowPath(env);
486     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
487     BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
488     Bind(&leftIsInt);
489     {
490         Label rightIsInt(env);
491         BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
492         Bind(&rightIsInt);
493         {
494             callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
495             GateRef intLeft = TaggedGetInt(left);
496             GateRef intRight = TaggedGetInt(right);
497             BRANCH(Int32GreaterThanOrEqual(intLeft, intRight), &leftGreaterEqRight, &leftNotGreaterEQRight);
498         }
499     }
500     Bind(&leftOrRightNotInt);
501     {
502         Label leftIsNumber(env);
503         BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath);
504         Bind(&leftIsNumber);
505         {
506             Label rightIsNumber(env);
507             BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath);
508             Bind(&rightIsNumber);
509             {
510                 // fast path
511                 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
512                 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
513                 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType()));
514                 Label leftIsInt1(env);
515                 Label leftNotInt1(env);
516                 Label exit1(env);
517                 Label exit2(env);
518                 Label rightIsInt1(env);
519                 Label rightNotInt1(env);
520                 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
521                 Bind(&leftIsInt1);
522                 {
523                     doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
524                     Jump(&exit1);
525                 }
526                 Bind(&leftNotInt1);
527                 {
528                     curType = TaggedInt(PGOSampleType::DoubleType());
529                     doubleLeft = GetDoubleOfTDouble(left);
530                     Jump(&exit1);
531                 }
532                 Bind(&exit1);
533                 {
534                     BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
535                 }
536                 Bind(&rightIsInt1);
537                 {
538                     GateRef type = TaggedInt(PGOSampleType::IntType());
539                     COMBINE_TYPE_CALL_BACK(curType, type);
540                     doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
541                     Jump(&exit2);
542                 }
543                 Bind(&rightNotInt1);
544                 {
545                     GateRef type = TaggedInt(PGOSampleType::DoubleType());
546                     COMBINE_TYPE_CALL_BACK(curType, type);
547                     doubleRight = GetDoubleOfTDouble(right);
548                     Jump(&exit2);
549                 }
550                 Bind(&exit2);
551                 {
552                     BRANCH(DoubleGreaterThanOrEqual(*doubleLeft, *doubleRight),
553                         &leftGreaterEqRight, &leftNotGreaterEQRight);
554                 }
555             }
556         }
557     }
558     Bind(&leftGreaterEqRight);
559     {
560         callback.ProfileBranch(true);
561         result = TaggedTrue();
562         Jump(&exit);
563     }
564     Bind(&leftNotGreaterEQRight);
565     {
566         callback.ProfileBranch(false);
567         result = TaggedFalse();
568         Jump(&exit);
569     }
570     Bind(&slowPath);
571     {
572         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
573         result = CallRuntime(glue, RTSTUB_ID(GreaterEq), { left, right });
574         Jump(&exit);
575     }
576     Bind(&exit);
577     auto ret = *result;
578     env->SubCfgExit();
579     return ret;
580 }
581 
Add(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)582 GateRef OperationsStubBuilder::Add(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
583 {
584     auto env = GetEnvironment();
585     Label entry(env);
586     env->SubCfgEntry(&entry);
587     Label exit(env);
588     Label slowPath(env);
589     DEFVARIABLE(result, VariableType::JS_ANY(), FastAdd(glue, left, right, callback));
590     BRANCH(TaggedIsHole(*result), &slowPath, &exit);
591     Bind(&slowPath);
592     {
593         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
594         result = CallRuntime(glue, RTSTUB_ID(Add2), { left, right });
595         Jump(&exit);
596     }
597     Bind(&exit);
598     auto ret = *result;
599     env->SubCfgExit();
600     return ret;
601 }
602 
Sub(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)603 GateRef OperationsStubBuilder::Sub(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
604 {
605     auto env = GetEnvironment();
606     Label entry(env);
607     env->SubCfgEntry(&entry);
608     Label exit(env);
609     Label slowPath(env);
610     DEFVARIABLE(result, VariableType::JS_ANY(), FastSub(glue, left, right, callback));
611     BRANCH(TaggedIsHole(*result), &slowPath, &exit);
612     Bind(&slowPath);
613     {
614         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
615         result = CallRuntime(glue, RTSTUB_ID(Sub2), { left, right });
616         Jump(&exit);
617     }
618     Bind(&exit);
619     auto ret = *result;
620     env->SubCfgExit();
621     return ret;
622 }
623 
Mul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)624 GateRef OperationsStubBuilder::Mul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
625 {
626     auto env = GetEnvironment();
627     Label entry(env);
628     env->SubCfgEntry(&entry);
629     Label exit(env);
630     Label slowPath(env);
631     DEFVARIABLE(result, VariableType::JS_ANY(), FastMul(glue, left, right, callback));
632     BRANCH(TaggedIsHole(*result), &slowPath, &exit);
633     Bind(&slowPath);
634     {
635         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
636         result = CallRuntime(glue, RTSTUB_ID(Mul2), { left, right });
637         Jump(&exit);
638     }
639     Bind(&exit);
640     auto ret = *result;
641     env->SubCfgExit();
642     return ret;
643 }
644 
Div(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)645 GateRef OperationsStubBuilder::Div(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
646 {
647     auto env = GetEnvironment();
648     Label entry(env);
649     env->SubCfgEntry(&entry);
650     Label exit(env);
651     Label slowPath(env);
652     DEFVARIABLE(result, VariableType::JS_ANY(), FastDiv(left, right, callback));
653     BRANCH(TaggedIsHole(*result), &slowPath, &exit);
654     Bind(&slowPath);
655     {
656         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
657         result = CallRuntime(glue, RTSTUB_ID(Div2), { left, right });
658         Jump(&exit);
659     }
660     Bind(&exit);
661     auto ret = *result;
662     env->SubCfgExit();
663     return ret;
664 }
665 
Mod(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)666 GateRef OperationsStubBuilder::Mod(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
667 {
668     auto env = GetEnvironment();
669     Label entry(env);
670     env->SubCfgEntry(&entry);
671     Label exit(env);
672     Label slowPath(env);
673     DEFVARIABLE(result, VariableType::JS_ANY(), FastMod(glue, left, right, callback));
674     BRANCH(TaggedIsHole(*result), &slowPath, &exit);
675     Bind(&slowPath);
676     {
677         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
678         result = CallRuntime(glue, RTSTUB_ID(Mod2), { left, right });
679         Jump(&exit);
680     }
681     Bind(&exit);
682     auto ret = *result;
683     env->SubCfgExit();
684     return ret;
685 }
686 
Shl(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)687 GateRef OperationsStubBuilder::Shl(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
688 {
689     auto env = GetEnvironment();
690     Label entry(env);
691     env->SubCfgEntry(&entry);
692     Label exit(env);
693 
694     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
695     DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
696     DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
697 
698     Label calculate(env);
699     Label leftIsNumber(env);
700     Label leftNotNumberOrRightNotNumber(env);
701     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
702     Bind(&leftIsNumber);
703     {
704         Label rightIsNumber(env);
705         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
706         Bind(&rightIsNumber);
707         {
708             Label leftIsInt(env);
709             Label leftIsDouble(env);
710             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
711             Bind(&leftIsInt);
712             {
713                 Label rightIsInt(env);
714                 Label rightIsDouble(env);
715                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
716                 Bind(&rightIsInt);
717                 {
718                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
719                     opNumber0 = GetInt32OfTInt(left);
720                     opNumber1 = GetInt32OfTInt(right);
721                     Jump(&calculate);
722                 }
723                 Bind(&rightIsDouble);
724                 {
725                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
726                     GateRef rightDouble = GetDoubleOfTDouble(right);
727                     opNumber0 = GetInt32OfTInt(left);
728                     opNumber1 = DoubleToInt(glue, rightDouble);
729                     Jump(&calculate);
730                 }
731             }
732             Bind(&leftIsDouble);
733             {
734                 Label rightIsInt(env);
735                 Label rightIsDouble(env);
736                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
737                 Bind(&rightIsInt);
738                 {
739                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
740                     GateRef leftDouble = GetDoubleOfTDouble(left);
741                     opNumber0 = DoubleToInt(glue, leftDouble);
742                     opNumber1 = GetInt32OfTInt(right);
743                     Jump(&calculate);
744                 }
745                 Bind(&rightIsDouble);
746                 {
747                     callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
748                     GateRef rightDouble = GetDoubleOfTDouble(right);
749                     GateRef leftDouble = GetDoubleOfTDouble(left);
750                     opNumber0 = DoubleToInt(glue, leftDouble);
751                     opNumber1 = DoubleToInt(glue, rightDouble);
752                     Jump(&calculate);
753                 }
754             }
755         }
756     }
757     // slow path
758     Bind(&leftNotNumberOrRightNotNumber);
759     {
760         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
761         result = CallRuntime(glue, RTSTUB_ID(Shl2), { left, right });
762         Jump(&exit);
763     }
764     Bind(&calculate);
765     {
766         GateRef shift = Int32And(*opNumber1, Int32(0x1f));
767         GateRef val = Int32LSL(*opNumber0, shift);
768         result = IntToTaggedPtr(val);
769         Jump(&exit);
770     }
771     Bind(&exit);
772     auto ret = *result;
773     env->SubCfgExit();
774     return ret;
775 }
776 
Shr(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)777 GateRef OperationsStubBuilder::Shr(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
778 {
779     auto env = GetEnvironment();
780     Label entry(env);
781     env->SubCfgEntry(&entry);
782     Label exit(env);
783 
784     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
785     DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
786     DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
787     DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None()));
788 
789     Label doShr(env);
790     Label overflow(env);
791     Label notOverflow(env);
792     Label leftIsNumber(env);
793     Label leftNotNumberOrRightNotNumber(env);
794     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
795     Bind(&leftIsNumber);
796     {
797         Label rightIsNumber(env);
798         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
799         Bind(&rightIsNumber);
800         {
801             Label leftIsInt(env);
802             Label leftIsDouble(env);
803             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
804             Bind(&leftIsInt);
805             {
806                 Label rightIsInt(env);
807                 Label rightIsDouble(env);
808                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
809                 Bind(&rightIsInt);
810                 {
811                     curType = TaggedInt(PGOSampleType::IntType());
812                     opNumber0 = GetInt32OfTInt(left);
813                     opNumber1 = GetInt32OfTInt(right);
814                     Jump(&doShr);
815                 }
816                 Bind(&rightIsDouble);
817                 {
818                     curType = TaggedInt(PGOSampleType::NumberType());
819                     GateRef rightDouble = GetDoubleOfTDouble(right);
820                     opNumber0 = GetInt32OfTInt(left);
821                     opNumber1 = DoubleToInt(glue, rightDouble);
822                     Jump(&doShr);
823                 }
824             }
825             Bind(&leftIsDouble);
826             {
827                 Label rightIsInt(env);
828                 Label rightIsDouble(env);
829                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
830                 Bind(&rightIsInt);
831                 {
832                     curType = TaggedInt(PGOSampleType::NumberType());
833                     GateRef leftDouble = GetDoubleOfTDouble(left);
834                     opNumber0 = DoubleToInt(glue, leftDouble);
835                     opNumber1 = GetInt32OfTInt(right);
836                     Jump(&doShr);
837                 }
838                 Bind(&rightIsDouble);
839                 {
840                     curType = TaggedInt(PGOSampleType::DoubleType());
841                     GateRef rightDouble = GetDoubleOfTDouble(right);
842                     GateRef leftDouble = GetDoubleOfTDouble(left);
843                     opNumber0 = DoubleToInt(glue, leftDouble);
844                     opNumber1 = DoubleToInt(glue, rightDouble);
845                     Jump(&doShr);
846                 }
847             }
848         }
849     }
850     // slow path
851     Bind(&leftNotNumberOrRightNotNumber);
852     {
853         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
854         result = CallRuntime(glue, RTSTUB_ID(Shr2), { left, right });
855         Jump(&exit);
856     }
857     Bind(&doShr);
858     {
859         GateRef shift = Int32And(*opNumber1, Int32(0x1f));
860         GateRef val = Int32LSR(*opNumber0, shift);
861         auto condition = Int32UnsignedGreaterThan(val, Int32(INT32_MAX));
862         BRANCH(condition, &overflow, &notOverflow);
863         Bind(&overflow);
864         {
865             callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType()));
866             result = DoubleToTaggedDoublePtr(ChangeUInt32ToFloat64(val));
867             Jump(&exit);
868         }
869         Bind(&notOverflow);
870         {
871             callback.ProfileOpType(*curType);
872             result = IntToTaggedPtr(val);
873             Jump(&exit);
874         }
875     }
876     Bind(&exit);
877     auto ret = *result;
878     env->SubCfgExit();
879     return ret;
880 }
881 
Ashr(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)882 GateRef OperationsStubBuilder::Ashr(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
883 {
884     auto env = GetEnvironment();
885     Label entry(env);
886     env->SubCfgEntry(&entry);
887     Label exit(env);
888 
889     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
890     DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
891     DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
892 
893     Label calculate(env);
894     Label leftIsNumber(env);
895     Label leftNotNumberOrRightNotNumber(env);
896     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
897     Bind(&leftIsNumber);
898     {
899         Label rightIsNumber(env);
900         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
901         Bind(&rightIsNumber);
902         {
903             Label leftIsInt(env);
904             Label leftIsDouble(env);
905             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
906             Bind(&leftIsInt);
907             {
908                 Label rightIsInt(env);
909                 Label rightIsDouble(env);
910                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
911                 Bind(&rightIsInt);
912                 {
913                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
914                     opNumber0 = GetInt32OfTInt(left);
915                     opNumber1 = GetInt32OfTInt(right);
916                     Jump(&calculate);
917                 }
918                 Bind(&rightIsDouble);
919                 {
920                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
921                     GateRef rightDouble = GetDoubleOfTDouble(right);
922                     opNumber0 = GetInt32OfTInt(left);
923                     opNumber1 = DoubleToInt(glue, rightDouble);
924                     Jump(&calculate);
925                 }
926             }
927             Bind(&leftIsDouble);
928             {
929                 Label rightIsInt(env);
930                 Label rightIsDouble(env);
931                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
932                 Bind(&rightIsInt);
933                 {
934                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
935                     GateRef leftDouble = GetDoubleOfTDouble(left);
936                     opNumber0 = DoubleToInt(glue, leftDouble);
937                     opNumber1 = GetInt32OfTInt(right);
938                     Jump(&calculate);
939                 }
940                 Bind(&rightIsDouble);
941                 {
942                     callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
943                     GateRef rightDouble = GetDoubleOfTDouble(right);
944                     GateRef leftDouble = GetDoubleOfTDouble(left);
945                     opNumber0 = DoubleToInt(glue, leftDouble);
946                     opNumber1 = DoubleToInt(glue, rightDouble);
947                     Jump(&calculate);
948                 }
949             }
950         }
951     }
952     // slow path
953     Bind(&leftNotNumberOrRightNotNumber);
954     {
955         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
956         result = CallRuntime(glue, RTSTUB_ID(Ashr2), { left, right });
957         Jump(&exit);
958     }
959     Bind(&calculate);
960     {
961         GateRef shift = Int32And(*opNumber1, Int32(0x1f));
962         GateRef val = Int32ASR(*opNumber0, shift);
963         result = IntToTaggedPtr(val);
964         Jump(&exit);
965     }
966     Bind(&exit);
967     auto ret = *result;
968     env->SubCfgExit();
969     return ret;
970 }
971 
And(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)972 GateRef OperationsStubBuilder::And(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
973 {
974     auto env = GetEnvironment();
975     Label entry(env);
976     env->SubCfgEntry(&entry);
977     Label exit(env);
978 
979     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
980     DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
981     DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
982 
983     Label calculate(env);
984     Label leftIsNumber(env);
985     Label leftNotNumberOrRightNotNumber(env);
986     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
987     Bind(&leftIsNumber);
988     {
989         Label rightIsNumber(env);
990         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
991         Bind(&rightIsNumber);
992         {
993             Label leftIsInt(env);
994             Label leftIsDouble(env);
995             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
996             Bind(&leftIsInt);
997             {
998                 Label rightIsInt(env);
999                 Label rightIsDouble(env);
1000                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1001                 Bind(&rightIsInt);
1002                 {
1003                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
1004                     opNumber0 = GetInt32OfTInt(left);
1005                     opNumber1 = GetInt32OfTInt(right);
1006                     Jump(&calculate);
1007                 }
1008                 Bind(&rightIsDouble);
1009                 {
1010                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
1011                     opNumber0 = GetInt32OfTInt(left);
1012                     GateRef rightDouble = GetDoubleOfTDouble(right);
1013                     opNumber1 = DoubleToInt(glue, rightDouble);
1014                     Jump(&calculate);
1015                 }
1016             }
1017             Bind(&leftIsDouble);
1018             {
1019                 Label rightIsInt(env);
1020                 Label rightIsDouble(env);
1021                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1022                 Bind(&rightIsInt);
1023                 {
1024                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
1025                     GateRef leftDouble = GetDoubleOfTDouble(left);
1026                     opNumber0 = DoubleToInt(glue, leftDouble);
1027                     opNumber1 = GetInt32OfTInt(right);
1028                     Jump(&calculate);
1029                 }
1030                 Bind(&rightIsDouble);
1031                 {
1032                     callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
1033                     GateRef rightDouble = GetDoubleOfTDouble(right);
1034                     GateRef leftDouble = GetDoubleOfTDouble(left);
1035                     opNumber0 = DoubleToInt(glue, leftDouble);
1036                     opNumber1 = DoubleToInt(glue, rightDouble);
1037                     Jump(&calculate);
1038                 }
1039             }
1040         }
1041     }
1042     // slow path
1043     Bind(&leftNotNumberOrRightNotNumber);
1044     {
1045         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
1046         result = CallRuntime(glue, RTSTUB_ID(And2), { left, right });
1047         Jump(&exit);
1048     }
1049     Bind(&calculate);
1050     {
1051         GateRef val = Int32And(*opNumber0, *opNumber1);
1052         result = IntToTaggedPtr(val);
1053         Jump(&exit);
1054     }
1055     Bind(&exit);
1056     auto ret = *result;
1057     env->SubCfgExit();
1058     return ret;
1059 }
1060 
Or(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)1061 GateRef OperationsStubBuilder::Or(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
1062 {
1063     auto env = GetEnvironment();
1064     Label entry(env);
1065     env->SubCfgEntry(&entry);
1066     Label exit(env);
1067 
1068     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1069     DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
1070     DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
1071 
1072     Label calculate(env);
1073     Label leftIsNumber(env);
1074     Label leftNotNumberOrRightNotNumber(env);
1075     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
1076     Bind(&leftIsNumber);
1077     {
1078         Label rightIsNumber(env);
1079         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
1080         Bind(&rightIsNumber);
1081         {
1082             Label leftIsInt(env);
1083             Label leftIsDouble(env);
1084             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
1085             Bind(&leftIsInt);
1086             {
1087                 Label rightIsInt(env);
1088                 Label rightIsDouble(env);
1089                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1090                 Bind(&rightIsInt);
1091                 {
1092                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
1093                     opNumber0 = GetInt32OfTInt(left);
1094                     opNumber1 = GetInt32OfTInt(right);
1095                     Jump(&calculate);
1096                 }
1097                 Bind(&rightIsDouble);
1098                 {
1099                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
1100                     GateRef rightDouble = GetDoubleOfTDouble(right);
1101                     opNumber0 = GetInt32OfTInt(left);
1102                     opNumber1 = DoubleToInt(glue, rightDouble);
1103                     Jump(&calculate);
1104                 }
1105             }
1106             Bind(&leftIsDouble);
1107             {
1108                 Label rightIsInt(env);
1109                 Label rightIsDouble(env);
1110                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1111                 Bind(&rightIsInt);
1112                 {
1113                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
1114                     GateRef leftDouble = GetDoubleOfTDouble(left);
1115                     opNumber0 = DoubleToInt(glue, leftDouble);
1116                     opNumber1 = GetInt32OfTInt(right);
1117                     Jump(&calculate);
1118                 }
1119                 Bind(&rightIsDouble);
1120                 {
1121                     callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
1122                     GateRef rightDouble = GetDoubleOfTDouble(right);
1123                     GateRef leftDouble = GetDoubleOfTDouble(left);
1124                     opNumber0 = DoubleToInt(glue, leftDouble);
1125                     opNumber1 = DoubleToInt(glue, rightDouble);
1126                     Jump(&calculate);
1127                 }
1128             }
1129         }
1130     }
1131     // slow path
1132     Bind(&leftNotNumberOrRightNotNumber);
1133     {
1134         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
1135         result = CallRuntime(glue, RTSTUB_ID(Or2), { left, right });
1136         Jump(&exit);
1137     }
1138     Bind(&calculate);
1139     {
1140         GateRef val = Int32Or(*opNumber0, *opNumber1);
1141         result = IntToTaggedPtr(val);
1142         Jump(&exit);
1143     }
1144     Bind(&exit);
1145     auto ret = *result;
1146     env->SubCfgExit();
1147     return ret;
1148 }
1149 
Xor(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)1150 GateRef OperationsStubBuilder::Xor(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
1151 {
1152     auto env = GetEnvironment();
1153     Label entry(env);
1154     env->SubCfgEntry(&entry);
1155     Label exit(env);
1156 
1157     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1158     DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
1159     DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
1160 
1161     Label calculate(env);
1162     Label leftIsNumber(env);
1163     Label leftNotNumberOrRightNotNumber(env);
1164     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
1165     Bind(&leftIsNumber);
1166     {
1167         Label rightIsNumber(env);
1168         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
1169         Bind(&rightIsNumber);
1170         {
1171             Label leftIsInt(env);
1172             Label leftIsDouble(env);
1173             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
1174             Bind(&leftIsInt);
1175             {
1176                 Label rightIsInt(env);
1177                 Label rightIsDouble(env);
1178                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1179                 Bind(&rightIsInt);
1180                 {
1181                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
1182                     opNumber0 = GetInt32OfTInt(left);
1183                     opNumber1 = GetInt32OfTInt(right);
1184                     Jump(&calculate);
1185                 }
1186                 Bind(&rightIsDouble);
1187                 {
1188                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
1189                     GateRef rightDouble = GetDoubleOfTDouble(right);
1190                     opNumber0 = GetInt32OfTInt(left);
1191                     opNumber1 = DoubleToInt(glue, rightDouble);
1192                     Jump(&calculate);
1193                 }
1194             }
1195             Bind(&leftIsDouble);
1196             {
1197                 Label rightIsInt(env);
1198                 Label rightIsDouble(env);
1199                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1200                 Bind(&rightIsInt);
1201                 {
1202                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
1203                     GateRef leftDouble = GetDoubleOfTDouble(left);
1204                     opNumber0 = DoubleToInt(glue, leftDouble);
1205                     opNumber1 = GetInt32OfTInt(right);
1206                     Jump(&calculate);
1207                 }
1208                 Bind(&rightIsDouble);
1209                 {
1210                     callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
1211                     GateRef rightDouble = GetDoubleOfTDouble(right);
1212                     GateRef leftDouble = GetDoubleOfTDouble(left);
1213                     opNumber0 = DoubleToInt(glue, leftDouble);
1214                     opNumber1 = DoubleToInt(glue, rightDouble);
1215                     Jump(&calculate);
1216                 }
1217             }
1218         }
1219     }
1220     // slow path
1221     Bind(&leftNotNumberOrRightNotNumber);
1222     {
1223         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
1224         result = CallRuntime(glue, RTSTUB_ID(Xor2), { left, right });
1225         Jump(&exit);
1226     }
1227     Bind(&calculate);
1228     {
1229         GateRef val = Int32Xor(*opNumber0, *opNumber1);
1230         result = IntToTaggedPtr(val);
1231         Jump(&exit);
1232     }
1233     Bind(&exit);
1234     auto ret = *result;
1235     env->SubCfgExit();
1236     return ret;
1237 }
1238 
Inc(GateRef glue,GateRef value,ProfileOperation callback)1239 GateRef OperationsStubBuilder::Inc(GateRef glue, GateRef value, ProfileOperation callback)
1240 {
1241     auto env = GetEnvironment();
1242     Label entry(env);
1243     env->SubCfgEntry(&entry);
1244     Label exit(env);
1245 
1246     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1247     Label valueIsInt(env);
1248     Label valueNotInt(env);
1249     Label slowPath(env);
1250     BRANCH(TaggedIsInt(value), &valueIsInt, &valueNotInt);
1251     Bind(&valueIsInt);
1252     {
1253         GateRef valueInt = GetInt32OfTInt(value);
1254         Label valueNoOverflow(env);
1255         BRANCH(Int32Equal(valueInt, Int32(INT32_MAX)), &valueNotInt, &valueNoOverflow);
1256         Bind(&valueNoOverflow);
1257         {
1258             callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
1259             result = IntToTaggedPtr(Int32Add(valueInt, Int32(1)));
1260             Jump(&exit);
1261         }
1262     }
1263     Bind(&valueNotInt);
1264     {
1265         Label valueIsDouble(env);
1266         Label valueIsNanOrInf(env);
1267         Label valueIsNotNanOrInf(env);
1268         BRANCH(TaggedIsDouble(value), &valueIsDouble, &slowPath);
1269         Bind(&valueIsDouble);
1270         {
1271             GateRef valueDouble = GetDoubleOfTDouble(value);
1272             callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
1273             BRANCH_UNLIKELY(DoubleIsNanOrInf(valueDouble), &valueIsNanOrInf, &valueIsNotNanOrInf);
1274             Bind(&valueIsNanOrInf);
1275             {
1276                 result = value;
1277                 Jump(&exit);
1278             }
1279             Bind(&valueIsNotNanOrInf);
1280             {
1281                 result = DoubleToTaggedDoublePtr(DoubleAdd(valueDouble, Double(1.0)));
1282                 Jump(&exit);
1283             }
1284         }
1285     }
1286     Bind(&slowPath);
1287     {
1288         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
1289         result = CallRuntime(glue, RTSTUB_ID(Inc), { value });
1290         Jump(&exit);
1291     }
1292     Bind(&exit);
1293     auto ret = *result;
1294     env->SubCfgExit();
1295     return ret;
1296 }
1297 
Dec(GateRef glue,GateRef value,ProfileOperation callback)1298 GateRef OperationsStubBuilder::Dec(GateRef glue, GateRef value, ProfileOperation callback)
1299 {
1300     auto env = GetEnvironment();
1301     Label entry(env);
1302     env->SubCfgEntry(&entry);
1303     Label exit(env);
1304 
1305     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1306     Label valueIsInt(env);
1307     Label valueNotInt(env);
1308     Label slowPath(env);
1309     BRANCH(TaggedIsInt(value), &valueIsInt, &valueNotInt);
1310     Bind(&valueIsInt);
1311     {
1312         GateRef valueInt = GetInt32OfTInt(value);
1313         Label valueNoOverflow(env);
1314         BRANCH(Int32Equal(valueInt, Int32(INT32_MIN)), &valueNotInt, &valueNoOverflow);
1315         Bind(&valueNoOverflow);
1316         {
1317             callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
1318             result = IntToTaggedPtr(Int32Sub(valueInt, Int32(1)));
1319             Jump(&exit);
1320         }
1321     }
1322     Bind(&valueNotInt);
1323     {
1324         Label valueIsDouble(env);
1325         Label valueIsNanOrInf(env);
1326         Label valueIsNotNanOrInf(env);
1327         BRANCH(TaggedIsDouble(value), &valueIsDouble, &slowPath);
1328         Bind(&valueIsDouble);
1329         {
1330             GateRef valueDouble = GetDoubleOfTDouble(value);
1331             callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
1332             BRANCH_UNLIKELY(DoubleIsNanOrInf(valueDouble), &valueIsNanOrInf, &valueIsNotNanOrInf);
1333             Bind(&valueIsNanOrInf);
1334             {
1335                 result = value;
1336                 Jump(&exit);
1337             }
1338             Bind(&valueIsNotNanOrInf);
1339             {
1340                 result = DoubleToTaggedDoublePtr(DoubleSub(valueDouble, Double(1.0)));
1341                 Jump(&exit);
1342             }
1343         }
1344     }
1345     Bind(&slowPath);
1346     {
1347         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
1348         result = CallRuntime(glue, RTSTUB_ID(Dec), { value });
1349         Jump(&exit);
1350     }
1351 
1352     Bind(&exit);
1353     auto ret = *result;
1354     env->SubCfgExit();
1355     return ret;
1356 }
1357 
Neg(GateRef glue,GateRef value,ProfileOperation callback)1358 GateRef OperationsStubBuilder::Neg(GateRef glue, GateRef value, ProfileOperation callback)
1359 {
1360     auto env = GetEnvironment();
1361     Label entry(env);
1362     env->SubCfgEntry(&entry);
1363     Label exit(env);
1364 
1365     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1366     Label valueIsInt(env);
1367     Label valueNotInt(env);
1368     BRANCH(TaggedIsInt(value), &valueIsInt, &valueNotInt);
1369     Bind(&valueIsInt);
1370     {
1371         GateRef valueInt = GetInt32OfTInt(value);
1372         Label valueIsZero(env);
1373         Label valueNotZero(env);
1374         BRANCH(Int32Equal(valueInt, Int32(0)), &valueIsZero, &valueNotZero);
1375         Bind(&valueIsZero);
1376         {
1377             callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType()));
1378             result = DoubleToTaggedDoublePtr(Double(-0.0));
1379             Jump(&exit);
1380         }
1381         Bind(&valueNotZero);
1382         {
1383             Label valueIsInt32Min(env);
1384             Label valueNotInt32Min(env);
1385             BRANCH(Int32Equal(valueInt, Int32(INT32_MIN)), &valueIsInt32Min, &valueNotInt32Min);
1386             Bind(&valueIsInt32Min);
1387             {
1388                 callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType()));
1389                 result = DoubleToTaggedDoublePtr(Double(-static_cast<double>(INT32_MIN)));
1390                 Jump(&exit);
1391             }
1392             Bind(&valueNotInt32Min);
1393             {
1394                 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
1395                 result = IntToTaggedPtr(Int32Sub(Int32(0), valueInt));
1396                 Jump(&exit);
1397             }
1398         }
1399     }
1400     Bind(&valueNotInt);
1401     {
1402         Label valueIsDouble(env);
1403         Label valueNotDouble(env);
1404         BRANCH(TaggedIsDouble(value), &valueIsDouble, &valueNotDouble);
1405         Bind(&valueIsDouble);
1406         {
1407             callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
1408             GateRef valueDouble = GetDoubleOfTDouble(value);
1409             result = DoubleToTaggedDoublePtr(DoubleMul(Double(-1), valueDouble));
1410             Jump(&exit);
1411         }
1412         Bind(&valueNotDouble);
1413         {
1414             // slow path
1415             callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
1416             result = CallRuntime(glue, RTSTUB_ID(Neg), { value });
1417             Jump(&exit);
1418         }
1419     }
1420     Bind(&exit);
1421     auto ret = *result;
1422     env->SubCfgExit();
1423     return ret;
1424 }
1425 
Not(GateRef glue,GateRef value,ProfileOperation callback)1426 GateRef OperationsStubBuilder::Not(GateRef glue, GateRef value, ProfileOperation callback)
1427 {
1428     auto env = GetEnvironment();
1429     Label entry(env);
1430     env->SubCfgEntry(&entry);
1431     Label exit(env);
1432 
1433     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1434     Label numberIsInt(env);
1435     Label numberNotInt(env);
1436     BRANCH(TaggedIsInt(value), &numberIsInt, &numberNotInt);
1437     Bind(&numberIsInt);
1438     {
1439         callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
1440         GateRef valueInt = GetInt32OfTInt(value);
1441         result = IntToTaggedPtr(Int32Not(valueInt));
1442         Jump(&exit);
1443     }
1444     Bind(&numberNotInt);
1445     {
1446         Label numberIsDouble(env);
1447         Label numberNotDouble(env);
1448         BRANCH(TaggedIsDouble(value), &numberIsDouble, &numberNotDouble);
1449         Bind(&numberIsDouble);
1450         {
1451             callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
1452             GateRef valueDouble = GetDoubleOfTDouble(value);
1453             result = IntToTaggedPtr(Int32Not(DoubleToInt(glue, valueDouble)));
1454             Jump(&exit);
1455         }
1456         Bind(&numberNotDouble);
1457         {
1458             // slow path
1459             callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
1460             result = CallRuntime(glue, RTSTUB_ID(Not), { value });
1461             Jump(&exit);
1462         }
1463     }
1464     Bind(&exit);
1465     auto ret = *result;
1466     env->SubCfgExit();
1467     return ret;
1468 }
1469 }  // namespace panda::ecmascript::kungfu
1470