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