• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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/assembler/assembler.h"
17 #include "ecmascript/compiler/call_stub_builder.h"
18 #include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h"
19 #include "ecmascript/compiler/circuit_builder_helper.h"
20 #include "ecmascript/compiler/share_gate_meta_data.h"
21 #include "ecmascript/compiler/stub_builder-inl.h"
22 #include "ecmascript/compiler/assembler_module.h"
23 #include "ecmascript/compiler/access_object_stub_builder.h"
24 #include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
25 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
26 #include "ecmascript/compiler/interpreter_stub.h"
27 #include "ecmascript/compiler/new_object_stub_builder.h"
28 #include "ecmascript/compiler/profiler_stub_builder.h"
29 #include "ecmascript/compiler/rt_call_signature.h"
30 #include "ecmascript/global_env_constants.h"
31 #include "ecmascript/ic/properties_cache.h"
32 #include "ecmascript/js_api/js_api_arraylist.h"
33 #include "ecmascript/js_api/js_api_vector.h"
34 #include "ecmascript/js_object.h"
35 #include "ecmascript/js_primitive_ref.h"
36 #include "ecmascript/js_arguments.h"
37 #include "ecmascript/js_thread.h"
38 #include "ecmascript/lexical_env.h"
39 #include "ecmascript/mem/remembered_set.h"
40 #include "ecmascript/message_string.h"
41 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
42 #include "ecmascript/property_attributes.h"
43 #include "ecmascript/tagged_dictionary.h"
44 #include "ecmascript/tagged_hash_table.h"
45 #include "ecmascript/transitions_dictionary.h"
46 
47 namespace panda::ecmascript::kungfu {
Jump(Label * label)48 void StubBuilder::Jump(Label *label)
49 {
50     ASSERT(label);
51     auto currentLabel = env_->GetCurrentLabel();
52     auto currentControl = currentLabel->GetControl();
53     auto jump = env_->GetBuilder()->Goto(currentControl);
54     currentLabel->SetControl(jump);
55     label->AppendPredecessor(currentLabel);
56     label->MergeControl(currentLabel->GetControl());
57     env_->SetCurrentLabel(nullptr);
58 }
59 
Branch(GateRef condition,Label * trueLabel,Label * falseLabel,const char * comment)60 void StubBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel, const char* comment)
61 {
62     return BranchPredict(condition, trueLabel, falseLabel, BranchWeight::ONE_WEIGHT, BranchWeight::ONE_WEIGHT, comment);
63 }
64 
BranchPredict(GateRef condition,Label * trueLabel,Label * falseLabel,uint32_t trueWeight,uint32_t falseWeight,const char * comment)65 void StubBuilder::BranchPredict(GateRef condition, Label *trueLabel, Label *falseLabel, uint32_t trueWeight,
66                                 uint32_t falseWeight, const char *comment)
67 {
68     auto currentLabel = env_->GetCurrentLabel();
69     auto currentControl = currentLabel->GetControl();
70     GateRef ifBranch = env_->GetBuilder()->Branch(currentControl, condition, trueWeight, falseWeight, comment);
71     currentLabel->SetControl(ifBranch);
72     GateRef ifTrue = env_->GetBuilder()->IfTrue(ifBranch);
73     trueLabel->AppendPredecessor(env_->GetCurrentLabel());
74     trueLabel->MergeControl(ifTrue);
75     GateRef ifFalse = env_->GetBuilder()->IfFalse(ifBranch);
76     falseLabel->AppendPredecessor(env_->GetCurrentLabel());
77     falseLabel->MergeControl(ifFalse);
78     env_->SetCurrentLabel(nullptr);
79 }
80 
Switch(GateRef index,Label * defaultLabel,int64_t * keysValue,Label * keysLabel,int numberOfKeys)81 void StubBuilder::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
82 {
83     auto currentLabel = env_->GetCurrentLabel();
84     auto currentControl = currentLabel->GetControl();
85     GateRef switchBranch = env_->GetBuilder()->SwitchBranch(currentControl, index, numberOfKeys);
86     currentLabel->SetControl(switchBranch);
87     for (int i = 0; i < numberOfKeys; i++) {
88         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
89         GateRef switchCase = env_->GetBuilder()->SwitchCase(switchBranch, keysValue[i]);
90         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
91         keysLabel[i].AppendPredecessor(currentLabel);
92         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
93         keysLabel[i].MergeControl(switchCase);
94     }
95 
96     GateRef defaultCase = env_->GetBuilder()->DefaultCase(switchBranch);
97     defaultLabel->AppendPredecessor(currentLabel);
98     defaultLabel->MergeControl(defaultCase);
99     env_->SetCurrentLabel(nullptr);
100 }
101 
LoopBegin(Label * loopHead)102 void StubBuilder::LoopBegin(Label *loopHead)
103 {
104     ASSERT(loopHead);
105     auto loopControl = env_->GetBuilder()->LoopBegin(loopHead->GetControl());
106     loopHead->SetControl(loopControl);
107     loopHead->SetPreControl(loopControl);
108     loopHead->Bind();
109     env_->SetCurrentLabel(loopHead);
110 }
111 
CheckSuspend(GateRef glue)112 GateRef StubBuilder::CheckSuspend(GateRef glue)
113 {
114     GateRef stateAndFlagsOffset = IntPtr(JSThread::GlueData::GetStateAndFlagsOffset(env_->IsArch32Bit()));
115     GateRef stateAndFlags = Load(VariableType::INT16(), glue, stateAndFlagsOffset);
116     return Int32And(ZExtInt16ToInt32(stateAndFlags), Int32(SUSPEND_REQUEST));
117 }
118 
LoopEnd(Label * loopHead,Environment * env,GateRef glue)119 void StubBuilder::LoopEnd(Label *loopHead, Environment *env, GateRef glue)
120 {
121     Label loopEnd(env);
122     Label needSuspend(env);
123     BRANCH_UNLIKELY(Int32Equal(Int32(ThreadFlag::SUSPEND_REQUEST), CheckSuspend(glue)), &needSuspend, &loopEnd);
124     Bind(&needSuspend);
125     {
126         CallRuntime(glue, RTSTUB_ID(CheckSafePoint), {});
127         Jump(&loopEnd);
128     }
129     Bind(&loopEnd);
130     LoopEnd(loopHead);
131 }
132 
LoopEnd(Label * loopHead)133 void StubBuilder::LoopEnd(Label *loopHead)
134 {
135     ASSERT(loopHead);
136     auto currentLabel = env_->GetCurrentLabel();
137     auto currentControl = currentLabel->GetControl();
138     auto loopend = env_->GetBuilder()->LoopEnd(currentControl);
139     currentLabel->SetControl(loopend);
140     loopHead->AppendPredecessor(currentLabel);
141     loopHead->MergeControl(loopend);
142     loopHead->Seal();
143     loopHead->MergeAllControl();
144     loopHead->MergeAllDepend();
145     env_->SetCurrentLabel(nullptr);
146 }
147 
MatchFieldType(GateRef fieldType,GateRef value,Label * executeSetProp,Label * typeMismatch)148 void StubBuilder::MatchFieldType(GateRef fieldType, GateRef value, Label *executeSetProp, Label *typeMismatch)
149 {
150     auto *env = GetEnvironment();
151     Label valueIsUndefined(env);
152     Label checkNumber(env);
153     Label isNumber(env);
154     Label checkBoolean(env);
155     Label isBoolean(env);
156     Label checkString(env);
157     Label isString(env);
158     Label checkJSShared(env);
159     Label isJSShared(env);
160     Label checkBigInt(env);
161     Label isBigInt(env);
162     Label checkNoneOrGeneric(env);
163     Label isNoneOrGeneric(env);
164     Label checkNull(env);
165     Label isNull(env);
166     Label checkUndefined(env);
167     Label isUndefined(env);
168     Label exit(env);
169     DEFVARIABLE(result, VariableType::BOOL(), False());
170     GateRef checkType = TaggedIsUndefined(value);
171     BRANCH(checkType, &valueIsUndefined, &checkNumber);
172     Bind(&valueIsUndefined);
173     {
174         result = True();
175         Jump(&exit);
176     }
177     Bind(&checkNumber);
178     {
179         checkType = LogicAndBuilder(env)
180             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NUMBER))), Int32(0)))
181             .And(TaggedIsNumber(value))
182             .Done();
183         BRANCH(checkType, &isNumber, &checkBoolean);
184         Bind(&isNumber);
185         {
186             result = True();
187             Jump(&exit);
188         }
189     }
190     Bind(&checkBoolean);
191     {
192         checkType = LogicAndBuilder(env)
193             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::BOOLEAN))), Int32(0)))
194             .And(TaggedIsBoolean(value))
195             .Done();
196         BRANCH(checkType, &isBoolean, &checkString);
197         Bind(&isBoolean);
198         {
199             result = True();
200             Jump(&exit);
201         }
202     }
203     Bind(&checkString);
204     {
205         checkType = LogicAndBuilder(env)
206             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::STRING))), Int32(0)))
207             .And(LogicOrBuilder(env).Or(TaggedIsString(value)).Or(TaggedIsNull(value)).Done())
208             .Done();
209         BRANCH(checkType, &isString, &checkJSShared);
210         Bind(&isString);
211         {
212             result = True();
213             Jump(&exit);
214         }
215     }
216     Bind(&checkJSShared);
217     {
218         checkType = LogicAndBuilder(env)
219             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::SENDABLE))), Int32(0)))
220             .And(LogicOrBuilder(env).Or(TaggedIsSharedObj(value)).Or(TaggedIsNull(value)).Done())
221             .Done();
222         BRANCH(checkType, &isJSShared, &checkBigInt);
223         Bind(&isJSShared);
224         {
225             result = True();
226             Jump(&exit);
227         }
228     }
229     Bind(&checkBigInt);
230     {
231         checkType = LogicAndBuilder(env)
232             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::BIG_INT))), Int32(0)))
233             .And(TaggedIsBigInt(value))
234             .Done();
235         BRANCH(checkType, &isBigInt, &checkNoneOrGeneric);
236         Bind(&isBigInt);
237         {
238             result = True();
239             Jump(&exit);
240         }
241     }
242     Bind(&checkNoneOrGeneric);
243     {
244         GateRef fieldTypeCheck = LogicOrBuilder(env)
245             .Or(Equal(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NONE))))
246             .Or(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::GENERIC))), Int32(0)))
247             .Done();
248         checkType = LogicAndBuilder(env)
249             .And(fieldTypeCheck)
250             .And(LogicOrBuilder(env).Or(BoolNot(TaggedIsHeapObject(value))).Or(TaggedIsSharedObj(value)).Done())
251             .Done();
252         BRANCH(checkType, &isNoneOrGeneric, &checkNull);
253         Bind(&isNoneOrGeneric);
254         {
255             // (none || generic) && (jsShared || !heapObject)
256             result = True();
257             Jump(&exit);
258         }
259     }
260     Bind(&checkNull);
261     {
262         checkType = LogicAndBuilder(env)
263             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NULL_TYPE))), Int32(0)))
264             .And(TaggedIsNull(value))
265             .Done();
266         BRANCH(checkType, &isNull, &checkUndefined);
267         Bind(&isNull);
268         {
269             result = True();
270             Jump(&exit);
271         }
272     }
273     Bind(&checkUndefined);
274     {
275         checkType = LogicAndBuilder(env)
276             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::UNDEFINED))), Int32(0)))
277             .And(TaggedIsUndefined(value))
278             .Done();
279         BRANCH(checkType, &isUndefined, &exit);
280         Bind(&isUndefined);
281         {
282             result = True();
283             Jump(&exit);
284         }
285     }
286     Bind(&exit);
287     BRANCH(*result, executeSetProp, typeMismatch);
288 }
289 
290 // FindElementWithCache in ecmascript/layout_info-inl.h
FindElementWithCache(GateRef glue,GateRef layoutInfo,GateRef hclass,GateRef key,GateRef propsNum,GateRef hir)291 GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, GateRef hclass,
292     GateRef key, GateRef propsNum, GateRef hir)
293 {
294     auto env = GetEnvironment();
295     Label subEntry(env);
296     env->SubCfgEntry(&subEntry);
297     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
298     Label exit(env);
299     Label notExceedUpper(env);
300     Label exceedUpper(env);
301     // 9 : Builtins Object properties number is nine
302     constexpr int32_t maxPropsNum = 9;
303     BRANCH(Int32LessThanOrEqual(propsNum, Int32(maxPropsNum)), &notExceedUpper, &exceedUpper);
304     Bind(&notExceedUpper);
305     {
306         Label labels[maxPropsNum] = {Label(env), Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
307                                      Label(env), Label(env)};
308         Label notFount(env);
309         GateRef elementAddr = GetPropertiesAddrFromLayoutInfo(layoutInfo);
310         Jump(&labels[0]);
311         for (int32_t idx = 0; idx < maxPropsNum; idx++) {
312             bool isLast = (idx == maxPropsNum - 1);
313             Label check(env);
314             Bind(&labels[idx]);
315             {
316                 BRANCH_LIKELY(Int32LessThan(Int32(idx), propsNum), &check, &notFount);
317                 // Not real "likely", just to make the code layout of labels and check block tightly.
318             }
319             Bind(&check);
320             {
321                 result = Int32(idx);
322                 GateRef keyInProperty = Load(VariableType::JS_ANY(), elementAddr,
323                                              PtrMul(ZExtInt32ToPtr(Int32(idx)),
324                                                     IntPtr(sizeof(panda::ecmascript::Properties))));
325                 if (!isLast) {
326                     BRANCH_UNLIKELY(Equal(keyInProperty, key), &exit, &labels[idx + 1]);
327                     // Not real "unlikely", just to make the code layout of labels and check block tightly.
328                 } else {
329                     BRANCH(Equal(keyInProperty, key), &exit, &notFount);
330                 }
331             }
332         }
333         Bind(&notFount);
334         result = Int32(-1);
335         Jump(&exit);
336     }
337     Bind(&exceedUpper);
338     Label find(env);
339     Label notFind(env);
340     Label setCache(env);
341     GateRef cache = GetPropertiesCache(glue);
342     GateRef index = GetIndexFromPropertiesCache(glue, cache, hclass, key, hir);
343     BRANCH(Int32Equal(index, Int32(PropertiesCache::NOT_FOUND)), &notFind, &find);
344     Bind(&notFind);
345     {
346         result = BinarySearch(glue, layoutInfo, key, propsNum, hir);
347         BRANCH(Int32Equal(*result, Int32(PropertiesCache::NOT_FOUND)), &exit, &setCache);
348         Bind(&setCache);
349         SetToPropertiesCache(glue, cache, hclass, key, *result, hir);
350         Jump(&exit);
351     }
352     Bind(&find);
353     {
354         result = index;
355         Jump(&exit);
356     }
357     Bind(&exit);
358     auto ret = *result;
359     env->SubCfgExit();
360     return ret;
361 }
362 
GetIndexFromPropertiesCache(GateRef glue,GateRef cache,GateRef cls,GateRef key,GateRef hir)363 GateRef StubBuilder::GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef hir)
364 {
365     auto env = GetEnvironment();
366     Label subentry(env);
367     env->SubCfgEntry(&subentry);
368     DEFVARIABLE(result, VariableType::INT32(), Int32(PropertiesCache::NOT_FOUND));
369 
370     Label exit(env);
371     Label find(env);
372     GateRef hash = HashFromHclassAndKey(glue, cls, key, hir);
373     GateRef prop =
374             PtrAdd(cache, PtrMul(ZExtInt32ToPtr(hash), IntPtr(PropertiesCache::PropertyKey::GetPropertyKeySize())));
375     size_t propHclassOffset = PropertiesCache::PropertyKey::GetHclassOffset();
376     size_t propKeyOffset = PropertiesCache::PropertyKey::GetKeyOffset();
377     BRANCH(LogicAndBuilder(env)
378         .And(IntPtrEqual(cls, Load(VariableType::JS_POINTER(), prop, IntPtr(propHclassOffset))))
379         .And(IntPtrEqual(key, Load(VariableType::JS_ANY(), prop, IntPtr(propKeyOffset))))
380         .Done(), &find, &exit);
381     Bind(&find);
382     {
383         result = Load(VariableType::INT32(), prop, IntPtr(PropertiesCache::PropertyKey::GetResultsOffset()));
384         Jump(&exit);
385     }
386     Bind(&exit);
387     auto ret = *result;
388     env->SubCfgExit();
389     return ret;
390 }
391 
BinarySearch(GateRef glue,GateRef layoutInfo,GateRef key,GateRef propsNum,GateRef hir)392 GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum, GateRef hir)
393 {
394     auto env = GetEnvironment();
395     Label subentry(env);
396     env->SubCfgEntry(&subentry);
397     DEFVARIABLE(low, VariableType::INT32(), Int32(0));
398     Label exit(env);
399     GateRef elements = GetExtraLengthOfTaggedArray(layoutInfo);
400     DEFVARIABLE(high, VariableType::INT32(), Int32Sub(elements, Int32(1)));
401     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
402     DEFVARIABLE(mid, VariableType::INT32(), Int32(-1));
403 
404     GateRef keyHash = GetKeyHashCode(glue, key, hir);
405     Label loopHead(env);
406     Label loopEnd(env);
407     Label afterLoop(env);
408     Label midGreaterKey(env);
409     Label midnotGreaterKey(env);
410     Label midLessKey(env);
411     Label midEqualKey(env);
412     Label next(env);
413     Jump(&loopHead);
414     LoopBegin(&loopHead);
415     {
416         BRANCH(Int32LessThanOrEqual(*low, *high), &next, &exit);
417         Bind(&next);
418         mid = Int32Add(*low, Int32Div(Int32Sub(*high, *low), Int32(2)));  // 2: half
419         GateRef midKey = GetSortedKey(layoutInfo, *mid);
420         GateRef midHash = GetKeyHashCode(glue, midKey, hir);
421         BRANCH(Int32UnsignedGreaterThan(midHash, keyHash), &midGreaterKey, &midnotGreaterKey);
422         Bind(&midGreaterKey);
423         {
424             high = Int32Sub(*mid, Int32(1));
425             Jump(&loopEnd);
426         }
427         Bind(&midnotGreaterKey);
428         {
429             BRANCH(Int32UnsignedLessThan(midHash, keyHash), &midLessKey, &midEqualKey);
430             Bind(&midLessKey);
431             {
432                 low = Int32Add(*mid, Int32(1));
433                 Jump(&loopEnd);
434             }
435             Bind(&midEqualKey);
436             {
437                 Label retIndex(env);
438                 Label nextLoop(env);
439                 DEFVARIABLE(sortIndex, VariableType::INT32(), GetSortedIndex(layoutInfo, *mid));
440                 DEFVARIABLE(currentKey, VariableType::JS_ANY(), midKey);
441                 BRANCH(IntPtrEqual(midKey, key), &retIndex, &nextLoop);
442                 Bind(&retIndex);
443                 {
444                     Label retSortIndex(env);
445                     BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
446                     Bind(&retSortIndex);
447                     {
448                         result = *sortIndex;
449                         Jump(&exit);
450                     }
451                 }
452                 Bind(&nextLoop);
453                 {
454                     DEFVARIABLE(midLeft, VariableType::INT32(), *mid);
455                     DEFVARIABLE(midRight, VariableType::INT32(), *mid);
456                     Label loopHead1(env);
457                     Label loopEnd1(env);
458                     Label afterLoop1(env);
459                     Label nextCount(env);
460                     Jump(&loopHead1);
461                     LoopBegin(&loopHead1);
462                     {
463                         BRANCH(Int32GreaterThanOrEqual(Int32Sub(*midLeft, Int32(1)), Int32(0)),
464                             &nextCount, &afterLoop1);
465                         Bind(&nextCount);
466                         {
467                             Label hashEqual(env);
468                             midLeft = Int32Sub(*midLeft, Int32(1));
469                             sortIndex = GetSortedIndex(layoutInfo, *midLeft);
470                             currentKey = GetKey(layoutInfo, *sortIndex);
471                             BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual,
472                                    &afterLoop1);
473                             Bind(&hashEqual);
474                             {
475                                 Label retIndex1(env);
476                                 BRANCH(IntPtrEqual(*currentKey, key), &retIndex1, &loopEnd1);
477                                 Bind(&retIndex1);
478                                 {
479                                     Label retSortIndex(env);
480                                     BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
481                                     Bind(&retSortIndex);
482                                     {
483                                         result = *sortIndex;
484                                         Jump(&exit);
485                                     }
486                                 }
487                             }
488                         }
489                         Bind(&loopEnd1);
490                         {
491                             LoopEnd(&loopHead1);
492                         }
493                     }
494                     Bind(&afterLoop1);
495                     {
496                         Label loopHead2(env);
497                         Label loopEnd2(env);
498                         Label nextCount1(env);
499                         Jump(&loopHead2);
500                         LoopBegin(&loopHead2);
501                         {
502                             BRANCH(Int32LessThan(Int32Add(*midRight, Int32(1)), elements), &nextCount1, &exit);
503                             Bind(&nextCount1);
504                             {
505                                 Label hashEqual(env);
506                                 midRight = Int32Add(*midRight, Int32(1));
507                                 sortIndex = GetSortedIndex(layoutInfo, *midRight);
508                                 currentKey = GetKey(layoutInfo, *sortIndex);
509                                 BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual, &exit);
510                                 Bind(&hashEqual);
511                                 {
512                                     Label retIndex2(env);
513                                     BRANCH(IntPtrEqual(*currentKey, key), &retIndex2, &loopEnd2);
514                                     Bind(&retIndex2);
515                                     {
516                                         Label retSortIndex(env);
517                                         BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
518                                         Bind(&retSortIndex);
519                                         {
520                                             result = *sortIndex;
521                                             Jump(&exit);
522                                         }
523                                     }
524                                 }
525                             }
526                             Bind(&loopEnd2);
527                             {
528                                 LoopEnd(&loopHead2);
529                             }
530                         }
531                     }
532                 }
533             }
534         }
535     }
536 
537     Bind(&loopEnd);
538     {
539         LoopEnd(&loopHead);
540     }
541 
542     Bind(&exit);
543     auto ret = *result;
544     env->SubCfgExit();
545     return ret;
546 }
547 
GetKeyHashCode(GateRef glue,GateRef key,GateRef hir)548 GateRef StubBuilder::GetKeyHashCode(GateRef glue, GateRef key, GateRef hir)
549 {
550     auto env = GetEnvironment();
551     Label subentry(env);
552     env->SubCfgEntry(&subentry);
553     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
554 
555     Label exit(env);
556     Label isString(env);
557     Label isSymblo(env);
558     BRANCH(TaggedIsString(key), &isString, &isSymblo);
559     Bind(&isString);
560     {
561         result = GetHashcodeFromString(glue, key, hir);
562         Jump(&exit);
563     }
564     Bind(&isSymblo);
565     {
566         result = GetInt32OfTInt(Load(VariableType::INT64(), key,
567             IntPtr(JSSymbol::HASHFIELD_OFFSET)));
568         Jump(&exit);
569     }
570     Bind(&exit);
571     auto ret = *result;
572     env->SubCfgExit();
573     return ret;
574 }
575 
CreateDataProperty(GateRef glue,GateRef obj,GateRef propKey,GateRef value)576 GateRef StubBuilder::CreateDataProperty(GateRef glue, GateRef obj, GateRef propKey, GateRef value)
577 {
578     auto env = GetEnvironment();
579     Label subentry(env);
580     env->SubCfgEntry(&subentry);
581     Label exit(env);
582     Label next(env);
583     Label objIsShared(env);
584     Label objIsNotShared(env);
585     Label isHole(env);
586     Label notHole(env);
587     Label hasPendingException(env);
588 
589     DEFVARIABLE(result, VariableType::BOOL(), True());
590     GateRef SCheckModelIsCHECK = Boolean(true);
591     auto flag = DefinePropertyByValue(glue, obj, propKey, value, SCheckModelIsCHECK, ProfileOperation());
592     BRANCH(HasPendingException(glue), &hasPendingException, &next);
593     Bind(&hasPendingException);
594     {
595         result = False();
596         Jump(&exit);
597     }
598     Bind(&next);
599     {
600         BRANCH(TaggedIsHole(flag), &isHole, &notHole);
601         Bind(&isHole);
602         {
603             GateRef temp = CallRuntime(glue, RTSTUB_ID(DefineOwnProperty), {obj, propKey, value});
604             result = TaggedIsTrue(temp);
605             Jump(&exit);
606         }
607         Bind(&notHole);
608         {
609             result = BoolNot(TaggedIsException(flag));
610             Jump(&exit);
611         }
612     }
613     Bind(&exit);
614     auto ret = *result;
615     env->SubCfgExit();
616     return ret;
617 }
618 
CreateDataPropertyOrThrow(GateRef glue,GateRef obj,GateRef key,GateRef value)619 GateRef StubBuilder::CreateDataPropertyOrThrow(GateRef glue, GateRef obj, GateRef key, GateRef value)
620 {
621     auto env = GetEnvironment();
622     Label subentry(env);
623     env->SubCfgEntry(&subentry);
624     Label exit(env);
625     Label isPropertyKey(env);
626     Label isNotStringOrSymbol(env);
627     Label isNotNumber(env);
628     Label newThrow(env);
629     Label isThrow(env);
630 
631     DEFVARIABLE(result, VariableType::BOOL(), True());
632     DEFVARIABLE(isPropertyKeyFlag, VariableType::BOOL(), True());
633 
634     CanNotConvertNotValidObject(obj);
635     BRANCH(TaggedIsStringOrSymbol(key), &isPropertyKey, &isNotStringOrSymbol);
636     Bind(&isNotStringOrSymbol);
637     {
638         BRANCH(TaggedIsNumber(key), &isPropertyKey, &isNotNumber);
639         Bind(&isNotNumber);
640         {
641             isPropertyKeyFlag = False();
642             Jump(&isPropertyKey);
643         }
644     }
645     Bind(&isPropertyKey);
646     {
647         IsNotPropertyKey(*isPropertyKeyFlag);
648         result = CreateDataProperty(glue, obj, key, value);
649         BRANCH(*result, &exit, &isThrow);
650         Bind(&isThrow);
651         {
652             BRANCH(HasPendingException(glue), &exit, &newThrow);
653             Bind(&newThrow);
654             {
655                 GateRef msgIntId = Int32(GET_MESSAGE_STRING_ID(CreateDataPropertyFailed));
656                 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId)});
657                 Jump(&exit);
658             }
659         }
660     }
661 
662     Bind(&exit);
663     auto ret = *result;
664     env->SubCfgExit();
665     return ret;
666 }
667 
DefineField(GateRef glue,GateRef obj,GateRef propKey,GateRef value)668 GateRef StubBuilder::DefineField(GateRef glue, GateRef obj, GateRef propKey, GateRef value)
669 {
670     auto env = GetEnvironment();
671     Label entry(env);
672     env->SubCfgEntry(&entry);
673     Label exit(env);
674     Label next(env);
675     Label newThrow(env);
676     Label isObj(env);
677     Label notObj(env);
678     Label hasPendingException(env);
679     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
680     DEFVARIABLE(key, VariableType::JS_ANY(), Undefined());
681     BRANCH(IsEcmaObject(obj), &isObj, &notObj);
682     Bind(&isObj);
683     {
684         key = CallRuntime(glue, RTSTUB_ID(ToPropertyKey), {propKey});
685         BRANCH(HasPendingException(glue), &hasPendingException, &next);
686     }
687     Bind(&next);
688     {
689         CreateDataPropertyOrThrow(glue, obj, *key, value);
690         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
691     }
692     Bind(&notObj);
693     {
694         BRANCH(HasPendingException(glue), &hasPendingException, &newThrow);
695     }
696     Bind(&hasPendingException);
697     {
698         result = Exception();
699         Jump(&exit);
700     }
701     Bind(&newThrow);
702     {
703         GateRef msgIntId = Int32(GET_MESSAGE_STRING_ID(DefineFieldField));
704         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId)});
705         result = Exception();
706         Jump(&exit);
707     }
708 
709     Bind(&exit);
710     auto ret = *result;
711     env->SubCfgExit();
712     return ret;
713 }
714 
FindElementFromNumberDictionary(GateRef glue,GateRef elements,GateRef index)715 GateRef StubBuilder::FindElementFromNumberDictionary(GateRef glue, GateRef elements, GateRef index)
716 {
717     auto env = GetEnvironment();
718     Label subentry(env);
719     env->SubCfgEntry(&subentry);
720     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
721     Label exit(env);
722     GateRef capcityoffset =
723         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
724                IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
725     GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
726     GateRef capacity = GetInt32OfTInt(Load(VariableType::INT64(), elements,
727                                            PtrAdd(dataoffset, capcityoffset)));
728     DEFVARIABLE(count, VariableType::INT32(), Int32(1));
729     GateRef len = Int32(sizeof(int) / sizeof(uint8_t));
730     GateRef hash = CallRuntime(glue, RTSTUB_ID(GetHash32),
731         { IntToTaggedInt(index), IntToTaggedInt(len) });
732     DEFVARIABLE(entry, VariableType::INT32(),
733         Int32And(TruncInt64ToInt32(ChangeTaggedPointerToInt64(hash)), Int32Sub(capacity, Int32(1))));
734     Label loopHead(env);
735     Label loopEnd(env);
736     Label afterLoop(env);
737     Jump(&loopHead);
738     LoopBegin(&loopHead);
739     GateRef element = GetKeyFromDictionary<NumberDictionary>(elements, *entry);
740     Label isHole(env);
741     Label notHole(env);
742     BRANCH(TaggedIsHole(element), &isHole, &notHole);
743     Bind(&isHole);
744     Jump(&loopEnd);
745     Bind(&notHole);
746     Label isUndefined(env);
747     Label notUndefined(env);
748     BRANCH(TaggedIsUndefined(element), &isUndefined, &notUndefined);
749     Bind(&isUndefined);
750     result = Int32(-1);
751     Jump(&exit);
752     Bind(&notUndefined);
753     Label isMatch(env);
754     Label notMatch(env);
755     BRANCH(Int32Equal(index, GetInt32OfTInt(element)), &isMatch, &notMatch);
756     Bind(&isMatch);
757     result = *entry;
758     Jump(&exit);
759     Bind(&notMatch);
760     Jump(&loopEnd);
761     Bind(&loopEnd);
762     entry = GetNextPositionForHash(*entry, *count, capacity);
763     count = Int32Add(*count, Int32(1));
764     LoopEnd(&loopHead, env, glue);
765     Bind(&exit);
766     auto ret = *result;
767     env->SubCfgExit();
768     return ret;
769 }
770 
771 // int TaggedHashTable<Derived>::FindEntry(const JSTaggedValue &key) in tagged_hash_table.h
FindEntryFromNameDictionary(GateRef glue,GateRef elements,GateRef key,GateRef hir)772 GateRef StubBuilder::FindEntryFromNameDictionary(GateRef glue, GateRef elements, GateRef key, GateRef hir)
773 {
774     auto env = GetEnvironment();
775     Label funcEntry(env);
776     env->SubCfgEntry(&funcEntry);
777     Label exit(env);
778     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
779     GateRef capcityoffset =
780         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
781                IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
782     GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
783     GateRef capacity = GetInt32OfTInt(Load(VariableType::INT64(), elements,
784                                            PtrAdd(dataoffset, capcityoffset)));
785     DEFVARIABLE(count, VariableType::INT32(), Int32(1));
786     DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
787     // NameDictionary::hash
788     Label isSymbol(env);
789     Label notSymbol(env);
790     Label loopHead(env);
791     Label loopEnd(env);
792     Label afterLoop(env);
793     Label beforeDefineHash(env);
794     BRANCH(IsSymbol(key), &isSymbol, &notSymbol);
795     Bind(&isSymbol);
796     {
797         hash = GetInt32OfTInt(Load(VariableType::INT64(), key,
798             IntPtr(JSSymbol::HASHFIELD_OFFSET)));
799         Jump(&beforeDefineHash);
800     }
801     Bind(&notSymbol);
802     {
803         Label isString(env);
804         Label notString(env);
805         BRANCH(IsString(key), &isString, &notString);
806         Bind(&isString);
807         {
808             hash = GetHashcodeFromString(glue, key, hir);
809             Jump(&beforeDefineHash);
810         }
811         Bind(&notString);
812         {
813             Jump(&beforeDefineHash);
814         }
815     }
816     Bind(&beforeDefineHash);
817     // GetFirstPosition(hash, size)
818     DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
819     Jump(&loopHead);
820     LoopBegin(&loopHead);
821     {
822         GateRef element = GetKeyFromDictionary<NameDictionary>(elements, *entry);
823         Label isHole(env);
824         Label notHole(env);
825         BRANCH(TaggedIsHole(element), &isHole, &notHole);
826         {
827             Bind(&isHole);
828             {
829                 Jump(&loopEnd);
830             }
831             Bind(&notHole);
832             {
833                 Label isUndefined(env);
834                 Label notUndefined(env);
835                 BRANCH(TaggedIsUndefined(element), &isUndefined, &notUndefined);
836                 {
837                     Bind(&isUndefined);
838                     {
839                         result = Int32(-1);
840                         Jump(&exit);
841                     }
842                     Bind(&notUndefined);
843                     {
844                         Label isMatch(env);
845                         Label notMatch(env);
846                         BRANCH(Equal(key, element), &isMatch, &notMatch);
847                         {
848                             Bind(&isMatch);
849                             {
850                                 result = *entry;
851                                 Jump(&exit);
852                             }
853                             Bind(&notMatch);
854                             {
855                                 Jump(&loopEnd);
856                             }
857                         }
858                     }
859                 }
860             }
861         }
862         Bind(&loopEnd);
863         {
864             entry = GetNextPositionForHash(*entry, *count, capacity);
865             count = Int32Add(*count, Int32(1));
866             LoopEnd(&loopHead, env, glue);
867         }
868     }
869     Bind(&exit);
870     auto ret = *result;
871     env->SubCfgExit();
872     return ret;
873 }
874 
IsMatchInTransitionDictionary(GateRef element,GateRef key,GateRef metaData,GateRef attr)875 GateRef StubBuilder::IsMatchInTransitionDictionary(GateRef element, GateRef key, GateRef metaData, GateRef attr)
876 {
877     return BitAnd(Equal(element, key), Int32Equal(metaData, attr));
878 }
879 
FindEntryFromTransitionDictionary(GateRef glue,GateRef elements,GateRef key,GateRef metaData)880 GateRef StubBuilder::FindEntryFromTransitionDictionary(GateRef glue, GateRef elements, GateRef key, GateRef metaData)
881 {
882     auto env = GetEnvironment();
883     Label funcEntry(env);
884     env->SubCfgEntry(&funcEntry);
885     Label exit(env);
886     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
887     GateRef capcityoffset =
888         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
889                IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
890     GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
891     GateRef capacity = GetInt32OfTInt(Load(VariableType::INT64(), elements,
892                                            PtrAdd(dataoffset, capcityoffset)));
893     DEFVARIABLE(count, VariableType::INT32(), Int32(1));
894     DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
895     // TransitionDictionary::hash
896     Label isSymbol(env);
897     Label notSymbol(env);
898     Label loopHead(env);
899     Label loopEnd(env);
900     Label afterLoop(env);
901     Label beforeDefineHash(env);
902     BRANCH(IsSymbol(key), &isSymbol, &notSymbol);
903     Bind(&isSymbol);
904     {
905         hash = GetInt32OfTInt(Load(VariableType::INT64(), key,
906             IntPtr(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET)));
907         Jump(&beforeDefineHash);
908     }
909     Bind(&notSymbol);
910     {
911         Label isString(env);
912         Label notString(env);
913         BRANCH(IsString(key), &isString, &notString);
914         Bind(&isString);
915         {
916             hash = GetHashcodeFromString(glue, key);
917             Jump(&beforeDefineHash);
918         }
919         Bind(&notString);
920         {
921             Jump(&beforeDefineHash);
922         }
923     }
924     Bind(&beforeDefineHash);
925     hash = Int32Add(*hash, metaData);
926     // GetFirstPosition(hash, size)
927     DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
928     Jump(&loopHead);
929     LoopBegin(&loopHead);
930     {
931         GateRef element = GetKeyFromDictionary<TransitionsDictionary>(elements, *entry);
932         Label isHole(env);
933         Label notHole(env);
934         BRANCH(TaggedIsHole(element), &isHole, &notHole);
935         {
936             Bind(&isHole);
937             {
938                 Jump(&loopEnd);
939             }
940             Bind(&notHole);
941             {
942                 Label isUndefined(env);
943                 Label notUndefined(env);
944                 BRANCH(TaggedIsUndefined(element), &isUndefined, &notUndefined);
945                 {
946                     Bind(&isUndefined);
947                     {
948                         result = Int32(-1);
949                         Jump(&exit);
950                     }
951                     Bind(&notUndefined);
952                     {
953                         Label isMatch(env);
954                         Label notMatch(env);
955                         BRANCH(
956                             IsMatchInTransitionDictionary(element, key, metaData,
957                             // metaData is int32 type
958                             TruncInt64ToInt32(GetAttributesFromDictionary<TransitionsDictionary>(elements, *entry))),
959                             &isMatch, &notMatch);
960                         {
961                             Bind(&isMatch);
962                             {
963                                 result = *entry;
964                                 Jump(&exit);
965                             }
966                             Bind(&notMatch);
967                             {
968                                 Jump(&loopEnd);
969                             }
970                         }
971                     }
972                 }
973             }
974         }
975         Bind(&loopEnd);
976         {
977             entry = GetNextPositionForHash(*entry, *count, capacity);
978             count = Int32Add(*count, Int32(1));
979             LoopEnd(&loopHead, env, glue);
980         }
981     }
982     Bind(&exit);
983     auto ret = *result;
984     env->SubCfgExit();
985     return ret;
986 }
987 
JSObjectGetProperty(GateRef obj,GateRef hclass,GateRef attr)988 GateRef StubBuilder::JSObjectGetProperty(GateRef obj, GateRef hclass, GateRef attr)
989 {
990     auto env = GetEnvironment();
991     Label entry(env);
992     env->SubCfgEntry(&entry);
993     Label exit(env);
994     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
995     Label inlinedProp(env);
996     Label notInlinedProp(env);
997     Label post(env);
998     GateRef attrOffset = GetOffsetFieldInPropAttr(attr);
999     GateRef rep = GetRepInPropAttr(attr);
1000     BRANCH(IsInlinedProperty(attr), &inlinedProp, &notInlinedProp);
1001     {
1002         Bind(&inlinedProp);
1003         {
1004             result = GetPropertyInlinedProps(obj, hclass, attrOffset);
1005             Jump(&post);
1006         }
1007         Bind(&notInlinedProp);
1008         {
1009             // compute outOfLineProp offset, get it and return
1010             GateRef array =
1011                 Load(VariableType::INT64(), obj, IntPtr(JSObject::PROPERTIES_OFFSET));
1012             result = GetValueFromTaggedArray(array, Int32Sub(attrOffset,
1013                 GetInlinedPropertiesFromHClass(hclass)));
1014             Jump(&post);
1015         }
1016     }
1017     Bind(&post);
1018     {
1019         Label nonDoubleToTagged(env);
1020         Label doubleToTagged(env);
1021         BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
1022         Bind(&doubleToTagged);
1023         {
1024             result = TaggedPtrToTaggedDoublePtr(*result);
1025             Jump(&exit);
1026         }
1027         Bind(&nonDoubleToTagged);
1028         {
1029             Label intToTagged(env);
1030             BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit);
1031             Bind(&intToTagged);
1032             {
1033                 result = TaggedPtrToTaggedIntPtr(*result);
1034                 Jump(&exit);
1035             }
1036         }
1037     }
1038     Bind(&exit);
1039     auto ret = *result;
1040     env->SubCfgExit();
1041     return ret;
1042 }
1043 
JSObjectSetProperty(GateRef glue,GateRef obj,GateRef hclass,GateRef attr,GateRef key,GateRef value)1044 void StubBuilder::JSObjectSetProperty(
1045     GateRef glue, GateRef obj, GateRef hclass, GateRef attr, GateRef key, GateRef value)
1046 {
1047     auto env = GetEnvironment();
1048     Label subEntry(env);
1049     env->SubCfgEntry(&subEntry);
1050     Label exit(env);
1051     Label inlinedProp(env);
1052     Label notInlinedProp(env);
1053     GateRef attrIndex = GetOffsetFieldInPropAttr(attr);
1054     BRANCH(IsInlinedProperty(attr), &inlinedProp, &notInlinedProp);
1055     {
1056         Bind(&inlinedProp);
1057         {
1058             GateRef offset = GetInlinedPropOffsetFromHClass(hclass, attrIndex);
1059             SetValueWithAttr(glue, obj, offset, key, value, attr);
1060             Jump(&exit);
1061         }
1062         Bind(&notInlinedProp);
1063         {
1064             // compute outOfLineProp offset, get it and return
1065             GateRef array = Load(VariableType::JS_POINTER(), obj,
1066                                  IntPtr(JSObject::PROPERTIES_OFFSET));
1067             GateRef offset = Int32Sub(attrIndex, GetInlinedPropertiesFromHClass(hclass));
1068             SetValueToTaggedArrayWithAttr(glue, array, offset, key, value, attr);
1069             Jump(&exit);
1070         }
1071     }
1072     Bind(&exit);
1073     env->SubCfgExit();
1074     return;
1075 }
1076 
ComputeNonInlinedFastPropsCapacity(GateRef glue,GateRef oldLength,GateRef maxNonInlinedFastPropsCapacity)1077 GateRef StubBuilder::ComputeNonInlinedFastPropsCapacity(GateRef glue, GateRef oldLength,
1078                                                         GateRef maxNonInlinedFastPropsCapacity)
1079 {
1080     auto env = GetEnvironment();
1081     Label subEntry(env);
1082     env->SubCfgEntry(&subEntry);
1083     Label exit(env);
1084     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1085     GateRef propertiesStep = Load(VariableType::INT32(), glue,
1086         IntPtr(JSThread::GlueData::GetPropertiesGrowStepOffset(env->Is32Bit())));
1087     GateRef newL = Int32Add(oldLength, propertiesStep);
1088     Label reachMax(env);
1089     Label notReachMax(env);
1090     BRANCH(Int32GreaterThan(newL, maxNonInlinedFastPropsCapacity), &reachMax, &notReachMax);
1091     {
1092         Bind(&reachMax);
1093         result = maxNonInlinedFastPropsCapacity;
1094         Jump(&exit);
1095         Bind(&notReachMax);
1096         result = newL;
1097         Jump(&exit);
1098     }
1099     Bind(&exit);
1100     auto ret = *result;
1101     env->SubCfgExit();
1102     return ret;
1103 }
1104 
ComputeElementCapacity(GateRef oldLength)1105 GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength)
1106 {
1107     auto env = GetEnvironment();
1108     Label subEntry(env);
1109     env->SubCfgEntry(&subEntry);
1110     Label exit(env);
1111     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1112     GateRef newL = Int32Add(oldLength, Int32LSR(oldLength, Int32(1)));
1113     Label reachMin(env);
1114     Label notReachMin(env);
1115     BRANCH(Int32GreaterThan(newL, Int32(JSObject::MIN_ELEMENTS_LENGTH)), &reachMin, &notReachMin);
1116     {
1117         Bind(&reachMin);
1118         result = newL;
1119         Jump(&exit);
1120         Bind(&notReachMin);
1121         result = Int32(JSObject::MIN_ELEMENTS_LENGTH);
1122         Jump(&exit);
1123     }
1124     Bind(&exit);
1125     auto ret = *result;
1126     env->SubCfgExit();
1127     return ret;
1128 }
1129 
CallGetterHelper(GateRef glue,GateRef receiver,GateRef holder,GateRef accessor,ProfileOperation callback,GateRef hir)1130 GateRef StubBuilder::CallGetterHelper(
1131     GateRef glue, GateRef receiver, GateRef holder, GateRef accessor, ProfileOperation callback, GateRef hir)
1132 {
1133     auto env = GetEnvironment();
1134     Label subEntry(env);
1135     env->SubCfgEntry(&subEntry);
1136     Label exit(env);
1137     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
1138 
1139     Label isInternal(env);
1140     Label notInternal(env);
1141     BRANCH(IsAccessorInternal(accessor), &isInternal, &notInternal);
1142     Bind(&isInternal);
1143     {
1144         Label arrayLength(env);
1145         Label tryContinue(env);
1146         auto lengthAccessor = GetGlobalConstantValue(
1147             VariableType::JS_POINTER(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1148         BRANCH(Equal(accessor, lengthAccessor), &arrayLength, &tryContinue);
1149         Bind(&arrayLength);
1150         {
1151             auto length = Load(VariableType::INT32(), holder, IntPtr(JSArray::LENGTH_OFFSET));
1152             // TaggedInt supports up to INT32_MAX.
1153             // If length is greater than Int32_MAX, needs to be converted to TaggedDouble.
1154             auto condition = Int32UnsignedGreaterThan(length, Int32(INT32_MAX));
1155             Label overflow(env);
1156             Label notOverflow(env);
1157             BRANCH(condition, &overflow, &notOverflow);
1158             Bind(&overflow);
1159             {
1160                 result = DoubleToTaggedDoublePtr(ChangeUInt32ToFloat64(length));
1161                 Jump(&exit);
1162             }
1163             Bind(&notOverflow);
1164             {
1165                 result = IntToTaggedPtr(length);
1166                 Jump(&exit);
1167             }
1168         }
1169         Bind(&tryContinue);
1170         result = CallRuntime(glue, RTSTUB_ID(CallInternalGetter), { accessor, holder });
1171         Jump(&exit);
1172     }
1173     Bind(&notInternal);
1174     {
1175         auto getter = Load(VariableType::JS_ANY(), accessor,
1176                            IntPtr(AccessorData::GETTER_OFFSET));
1177         Label objIsUndefined(env);
1178         Label objNotUndefined(env);
1179         Label callExit(env);
1180         BRANCH(TaggedIsUndefined(getter), &objIsUndefined, &objNotUndefined);
1181         // if getter is undefined, return undefiend
1182         Bind(&objIsUndefined);
1183         {
1184             result = Undefined();
1185             Jump(&exit);
1186         }
1187         Bind(&objNotUndefined);
1188         {
1189             DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Exception());
1190             JSCallArgs callArgs(JSCallMode::CALL_GETTER);
1191             callArgs.callGetterArgs = { receiver };
1192             CallStubBuilder callBuilder(this, glue, getter, Int32(0), 0, &tmpResult, Circuit::NullGate(), callArgs,
1193                 callback, true, hir);
1194             if (env->IsBaselineBuiltin()) {
1195                 callBuilder.JSCallDispatchForBaseline(&callExit);
1196                 Bind(&callExit);
1197             } else {
1198                 tmpResult = callBuilder.JSCallDispatch();
1199             }
1200             Label noPendingException(env);
1201             BRANCH(HasPendingException(glue), &exit, &noPendingException);
1202             Bind(&noPendingException);
1203             {
1204                 result = *tmpResult;
1205                 Jump(&exit);
1206             }
1207         }
1208     }
1209     Bind(&exit);
1210     auto ret = *result;
1211     env->SubCfgExit();
1212     return ret;
1213 }
1214 
CallSetterHelper(GateRef glue,GateRef receiver,GateRef accessor,GateRef value,ProfileOperation callback)1215 GateRef StubBuilder::CallSetterHelper(
1216     GateRef glue, GateRef receiver, GateRef accessor, GateRef value, ProfileOperation callback)
1217 {
1218     auto env = GetEnvironment();
1219     Label subEntry(env);
1220     env->SubCfgEntry(&subEntry);
1221     Label exit(env);
1222     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
1223 
1224     Label isInternal(env);
1225     Label notInternal(env);
1226     BRANCH(IsAccessorInternal(accessor), &isInternal, &notInternal);
1227     Bind(&isInternal);
1228     {
1229         result = CallRuntime(glue, RTSTUB_ID(CallInternalSetter), { receiver, accessor, value });
1230         Jump(&exit);
1231     }
1232     Bind(&notInternal);
1233     {
1234         auto setter = Load(VariableType::JS_ANY(), accessor, IntPtr(AccessorData::SETTER_OFFSET));
1235         Label objIsUndefined(env);
1236         Label objNotUndefined(env);
1237         Label callExit(env);
1238         BRANCH(TaggedIsUndefined(setter), &objIsUndefined, &objNotUndefined);
1239         Bind(&objIsUndefined);
1240         {
1241             CallRuntime(glue, RTSTUB_ID(ThrowSetterIsUndefinedException), {});
1242             result = Exception();
1243             Jump(&exit);
1244         }
1245         Bind(&objNotUndefined);
1246         {
1247             DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Exception());
1248             JSCallArgs callArgs(JSCallMode::CALL_SETTER);
1249             callArgs.callSetterArgs = { receiver, value };
1250             CallStubBuilder callBuilder(this, glue, setter, Int32(1), 0, &tmpResult, Circuit::NullGate(), callArgs,
1251                 callback);
1252             if (env->IsBaselineBuiltin()) {
1253                 callBuilder.JSCallDispatchForBaseline(&callExit);
1254                 Bind(&callExit);
1255             } else {
1256                 tmpResult = callBuilder.JSCallDispatch();
1257             }
1258             Label noPendingException(env);
1259             BRANCH(HasPendingException(glue), &exit, &noPendingException);
1260             Bind(&noPendingException);
1261             {
1262                 result = *tmpResult;
1263                 Jump(&exit);
1264             }
1265         }
1266     }
1267     Bind(&exit);
1268     auto ret = *result;
1269     env->SubCfgExit();
1270     return ret;
1271 }
1272 
ShouldCallSetter(GateRef receiver,GateRef holder,GateRef accessor,GateRef attr)1273 GateRef StubBuilder::ShouldCallSetter(GateRef receiver, GateRef holder, GateRef accessor, GateRef attr)
1274 {
1275     auto env = GetEnvironment();
1276     Label subEntry(env);
1277     env->SubCfgEntry(&subEntry);
1278     Label exit(env);
1279     DEFVARIABLE(result, VariableType::BOOL(), True());
1280     Label isInternal(env);
1281     Label notInternal(env);
1282     BRANCH(IsAccessorInternal(accessor), &isInternal, &notInternal);
1283     Bind(&isInternal);
1284     {
1285         Label receiverEqualsHolder(env);
1286         Label receiverNotEqualsHolder(env);
1287         BRANCH(Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder);
1288         Bind(&receiverEqualsHolder);
1289         {
1290             result = IsWritable(attr);
1291             Jump(&exit);
1292         }
1293         Bind(&receiverNotEqualsHolder);
1294         {
1295             result = False();
1296             Jump(&exit);
1297         }
1298     }
1299     Bind(&notInternal);
1300     {
1301         result = True();
1302         Jump(&exit);
1303     }
1304     Bind(&exit);
1305     auto ret = *result;
1306     env->SubCfgExit();
1307     return ret;
1308 }
1309 
JSHClassAddProperty(GateRef glue,GateRef receiver,GateRef key,GateRef attr,GateRef value)1310 void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef key, GateRef attr, GateRef value)
1311 {
1312     auto env = GetEnvironment();
1313     Label subEntry(env);
1314     env->SubCfgEntry(&subEntry);
1315     Label exit(env);
1316     GateRef hclass = LoadHClass(receiver);
1317     GateRef metaData = GetPropertyMetaDataFromAttr(attr);
1318     GateRef newClass = FindTransitions(glue, hclass, key, metaData, value);
1319     Label findHClass(env);
1320     Label notFindHClass(env);
1321     BRANCH(Equal(newClass, Undefined()), &notFindHClass, &findHClass);
1322     Bind(&findHClass);
1323     {
1324         GateRef isTSHClass = IsTSHClass(newClass);
1325         Label setPrototype(env);
1326         Label endSetPrototypeCheck(env);
1327         Branch(isTSHClass, &setPrototype, &endSetPrototypeCheck);
1328         Bind(&setPrototype);
1329         {
1330             GateRef prototype = GetPrototypeFromHClass(hclass);
1331             StorePrototype(glue, newClass, prototype);
1332             Jump(&endSetPrototypeCheck);
1333         }
1334         Bind(&endSetPrototypeCheck);
1335         GateRef oldKind = GetElementsKindFromHClass(LoadHClass(receiver));
1336         RestoreElementsKindToGeneric(glue, newClass);
1337         StoreHClass(glue, receiver, newClass);
1338 #if ECMASCRIPT_ENABLE_IC
1339         Label needUpdateAOTHClass(env);
1340         Label normalNotify(env);
1341         Label endUpdate(env);
1342         GateRef updateCondition = LogicAndBuilder(env).And(isTSHClass).And(IsProtoTypeHClass(newClass)).Done();
1343         Branch(updateCondition, &needUpdateAOTHClass, &normalNotify);
1344         Bind(&needUpdateAOTHClass);
1345         {
1346             TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1347             CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass),
1348                         { hclass, newClass, key });
1349             Jump(&endUpdate);
1350         }
1351         Bind(&normalNotify);
1352         {
1353             // Because we currently only supports Fast ElementsKind
1354             TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1355             NotifyHClassChanged(glue, hclass, newClass);
1356             Jump(&endUpdate);
1357         }
1358         Bind(&endUpdate);
1359 #else
1360         // Because we currently only supports Fast ElementsKind
1361         CallRuntime(glue, RTSTUB_ID(TryRestoreElementsKind), { receiver, newClass });
1362 #endif
1363         Jump(&exit);
1364     }
1365     Bind(&notFindHClass);
1366     {
1367         GateRef type = GetObjectType(hclass);
1368         GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
1369                                 Int32(JSTaggedValue::TaggedTypeSize()));
1370         GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
1371         GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
1372             { IntToTaggedInt(size), IntToTaggedInt(type),
1373               IntToTaggedInt(inlineProps) });
1374         CopyAllHClass(glue, newJshclass, hclass);
1375         CallRuntime(glue, RTSTUB_ID(UpdateLayOutAndAddTransition),
1376                     { hclass, newJshclass, key, Int64ToTaggedInt(attr) });
1377 #if ECMASCRIPT_ENABLE_IC
1378         NotifyHClassChanged(glue, hclass, newJshclass);
1379 #endif
1380         // Because we currently only supports Fast ElementsKind
1381         RestoreElementsKindToGeneric(glue, newJshclass);
1382         StoreHClass(glue, receiver, newJshclass);
1383         Jump(&exit);
1384     }
1385     Bind(&exit);
1386     env->SubCfgExit();
1387     return;
1388 }
1389 
1390 // if condition:(objHandle->IsJSArray() || objHandle->IsTypedArray()) &&
1391 //      keyHandle.GetTaggedValue() == thread->GlobalConstants()->GetConstructorString()
SetHasConstructorCondition(GateRef glue,GateRef receiver,GateRef key)1392 GateRef StubBuilder::SetHasConstructorCondition(GateRef glue, GateRef receiver, GateRef key)
1393 {
1394     Label subentry(env_);
1395     env_->SubCfgEntry(&subentry);
1396     Label isArray(env_);
1397     Label exit(env_);
1398     DEFVALUE(result, env_, VariableType::BOOL(), False());
1399     Branch(LogicOrBuilder(env_).Or(IsJsArray(receiver)).Or(IsTypedArray(receiver)).Done(), &isArray, &exit);
1400     Bind(&isArray);
1401     {
1402         GateRef gConstOffset = Load(VariableType::JS_ANY(), glue,
1403                                     IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
1404         GateRef gCtorStr = Load(VariableType::JS_ANY(),
1405                                 gConstOffset,
1406                                 Int64Mul(Int64(sizeof(JSTaggedValue)),
1407                                          Int64(static_cast<uint64_t>(ConstantIndex::CONSTRUCTOR_STRING_INDEX))));
1408         result = Equal(key, gCtorStr);
1409         Jump(&exit);
1410     }
1411     Bind(&exit);
1412     auto ret = *result;
1413     env_->SubCfgExit();
1414     return ret;
1415 }
1416 
1417 // Note: set return exit node
AddPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef propertyAttributes,ProfileOperation callback)1418 GateRef StubBuilder::AddPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
1419                                        GateRef propertyAttributes, ProfileOperation callback)
1420 {
1421     auto env = GetEnvironment();
1422     Label subentry(env);
1423     env->SubCfgEntry(&subentry);
1424     Label exit(env);
1425     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1426     Label setHasCtor(env);
1427     Label notSetHasCtor(env);
1428     Label afterCtorCon(env);
1429     GateRef hclass = LoadHClass(receiver);
1430     BRANCH(SetHasConstructorCondition(glue, receiver, key), &setHasCtor, &notSetHasCtor);
1431     {
1432         Bind(&setHasCtor);
1433         SetHClassBit<JSHClass::HasConstructorBits>(glue, hclass, Int32(1));
1434         Jump(&afterCtorCon);
1435         Bind(&notSetHasCtor);
1436         Jump(&afterCtorCon);
1437     }
1438     Bind(&afterCtorCon);
1439     // 0x111 : default attribute for property: writable, enumerable, configurable
1440     DEFVARIABLE(attr, VariableType::INT64(), propertyAttributes);
1441     GateRef numberOfProps = GetNumberOfPropsFromHClass(hclass);
1442     GateRef inlinedProperties = GetInlinedPropertiesFromHClass(hclass);
1443     Label hasUnusedInProps(env);
1444     Label noUnusedInProps(env);
1445     Label afterInPropsCon(env);
1446     BRANCH(Int32UnsignedLessThan(numberOfProps, inlinedProperties), &hasUnusedInProps, &noUnusedInProps);
1447     {
1448         Bind(&noUnusedInProps);
1449         Jump(&afterInPropsCon);
1450         Bind(&hasUnusedInProps);
1451         {
1452             attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
1453             attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(1)); // 1: set inInlineProps true
1454             attr = SetTaggedRepInPropAttr(*attr);
1455             attr = ProfilerStubBuilder(env).UpdateTrackTypeInPropAttr(*attr, value, callback);
1456             GateRef oldKind = GetElementsKindFromHClass(LoadHClass(receiver));
1457             JSHClassAddProperty(glue, receiver, key, *attr, value);
1458             TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1459             GateRef newHclass = LoadHClass(receiver);
1460             GateRef newLayoutInfo = GetLayoutFromHClass(newHclass);
1461             GateRef offset = GetInlinedPropOffsetFromHClass(hclass, numberOfProps);
1462             attr = GetPropAttrFromLayoutInfo(newLayoutInfo, numberOfProps);
1463             SetValueWithAttr(glue, receiver, offset, key, value, *attr);
1464             result = Undefined();
1465             Jump(&exit);
1466         }
1467     }
1468     Bind(&afterInPropsCon);
1469     DEFVARIABLE(array, VariableType::JS_POINTER(), GetPropertiesArray(receiver));
1470     DEFVARIABLE(length, VariableType::INT32(), GetLengthOfTaggedArray(*array));
1471     Label lenIsZero(env);
1472     Label lenNotZero(env);
1473     Label afterLenCon(env);
1474     BRANCH(Int32Equal(*length, Int32(0)), &lenIsZero, &lenNotZero);
1475     {
1476         Bind(&lenIsZero);
1477         {
1478             length = Int32(JSObject::MIN_PROPERTIES_LENGTH);
1479             array = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(*length) });
1480             SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
1481             Jump(&afterLenCon);
1482         }
1483         Bind(&lenNotZero);
1484         Jump(&afterLenCon);
1485     }
1486     Bind(&afterLenCon);
1487     Label isDictMode(env);
1488     Label notDictMode(env);
1489     BRANCH(IsDictionaryMode(*array), &isDictMode, &notDictMode);
1490     {
1491         Bind(&isDictMode);
1492         {
1493             GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
1494                                       {receiver, *array, key, value, Int64ToTaggedInt(*attr), TaggedFalse()});
1495             SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
1496             Jump(&exit);
1497         }
1498         Bind(&notDictMode);
1499         {
1500             attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(0));
1501             GateRef outProps = Int32Sub(numberOfProps, inlinedProperties);
1502             Label ChangeToDict(env);
1503             Label notChangeToDict(env);
1504             Label afterDictChangeCon(env);
1505             BRANCH(Int32GreaterThanOrEqual(numberOfProps, Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY)),
1506                 &ChangeToDict, &notChangeToDict);
1507             {
1508                 Bind(&ChangeToDict);
1509                 {
1510                     attr = SetDictionaryOrderFieldInPropAttr(*attr,
1511                         Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY));
1512                     GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
1513                         { receiver, *array, key, value, Int64ToTaggedInt(*attr), TaggedTrue() });
1514                     Label isPendingException(env);
1515                     Label noPendingException(env);
1516                     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
1517                     Bind(&isPendingException);
1518                     {
1519                         result = Exception();
1520                         Jump(&exit);
1521                     }
1522                     Bind(&noPendingException);
1523                     SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
1524                     result = Undefined();
1525                     Jump(&exit);
1526                 }
1527                 Bind(&notChangeToDict);
1528                 Jump(&afterDictChangeCon);
1529             }
1530             Bind(&afterDictChangeCon);
1531             Label isArrayFull(env);
1532             Label arrayNotFull(env);
1533             Label afterArrLenCon(env);
1534             BRANCH(Int32Equal(*length, outProps), &isArrayFull, &arrayNotFull);
1535             {
1536                 Bind(&isArrayFull);
1537                 {
1538                     GateRef maxNonInlinedFastPropsCapacity =
1539                         Int32Sub(Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY), inlinedProperties);
1540                     GateRef capacity = ComputeNonInlinedFastPropsCapacity(glue, *length,
1541                         maxNonInlinedFastPropsCapacity);
1542                     array = CallRuntime(glue, RTSTUB_ID(CopyArray),
1543                         { *array, IntToTaggedInt(*length), IntToTaggedInt(capacity) });
1544                     SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
1545                     Jump(&afterArrLenCon);
1546                 }
1547                 Bind(&arrayNotFull);
1548                 Jump(&afterArrLenCon);
1549             }
1550             Bind(&afterArrLenCon);
1551             {
1552                 attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
1553                 attr = SetTaggedRepInPropAttr(*attr);
1554                 attr = ProfilerStubBuilder(env).UpdateTrackTypeInPropAttr(*attr, value, callback);
1555                 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(receiver));
1556                 JSHClassAddProperty(glue, receiver, key, *attr, value);
1557                 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1558                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, outProps, value);
1559                 Jump(&exit);
1560             }
1561         }
1562     }
1563     Bind(&exit);
1564     auto ret = *result;
1565     env->SubCfgExit();
1566     return ret;
1567 }
1568 
ThrowTypeAndReturn(GateRef glue,int messageId,GateRef val)1569 void StubBuilder::ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val)
1570 {
1571     GateRef msgIntId = Int32(messageId);
1572     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId) });
1573     Return(val);
1574 }
1575 
TaggedToRepresentation(GateRef value)1576 GateRef StubBuilder::TaggedToRepresentation(GateRef value)
1577 {
1578     auto env = GetEnvironment();
1579     Label entry(env);
1580     env->SubCfgEntry(&entry);
1581     Label exit(env);
1582     DEFVARIABLE(resultRep, VariableType::INT64(),
1583                 Int64(static_cast<int32_t>(Representation::TAGGED)));
1584     Label isInt(env);
1585     Label notInt(env);
1586 
1587     BRANCH(TaggedIsInt(value), &isInt, &notInt);
1588     Bind(&isInt);
1589     {
1590         resultRep = Int64(static_cast<int32_t>(Representation::INT));
1591         Jump(&exit);
1592     }
1593     Bind(&notInt);
1594     {
1595         Label isDouble(env);
1596         Label notDouble(env);
1597         BRANCH(TaggedIsDouble(value), &isDouble, &notDouble);
1598         Bind(&isDouble);
1599         {
1600             resultRep = Int64(static_cast<int32_t>(Representation::DOUBLE));
1601             Jump(&exit);
1602         }
1603         Bind(&notDouble);
1604         {
1605             resultRep = Int64(static_cast<int32_t>(Representation::TAGGED));
1606             Jump(&exit);
1607         }
1608     }
1609     Bind(&exit);
1610     auto ret = *resultRep;
1611     env->SubCfgExit();
1612     return ret;
1613 }
1614 
TaggedToElementKind(GateRef value)1615 GateRef StubBuilder::TaggedToElementKind(GateRef value)
1616 {
1617     auto env = GetEnvironment();
1618     Label entry(env);
1619     env->SubCfgEntry(&entry);
1620     Label exit(env);
1621 
1622     DEFVARIABLE(result, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::TAGGED)));
1623     Label isHole(env);
1624     Label isNotHole(env);
1625     BRANCH(TaggedIsHole(value), &isHole, &isNotHole);
1626     Bind(&isHole);
1627     {
1628         result = Int32(static_cast<int32_t>(ElementsKind::HOLE));
1629         Jump(&exit);
1630     }
1631     Bind(&isNotHole);
1632     {
1633         Label isInt(env);
1634         Label isNotInt(env);
1635         BRANCH(TaggedIsInt(value), &isInt, &isNotInt);
1636         Bind(&isInt);
1637         {
1638             result = Int32(static_cast<int32_t>(ElementsKind::INT));
1639             Jump(&exit);
1640         }
1641         Bind(&isNotInt);
1642         {
1643             Label isObject(env);
1644             Label isDouble(env);
1645             BRANCH(TaggedIsObject(value), &isObject, &isDouble);
1646             Bind(&isDouble);
1647             {
1648                 result = Int32(static_cast<int32_t>(ElementsKind::NUMBER));
1649                 Jump(&exit);
1650             }
1651             Bind(&isObject);
1652             {
1653                 Label isHeapObject(env);
1654                 BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit);
1655                 Bind(&isHeapObject);
1656                 {
1657                     Label isString(env);
1658                     Label isNonString(env);
1659                     BRANCH(TaggedIsString(value), &isString, &isNonString);
1660                     Bind(&isString);
1661                     {
1662                         result = Int32(static_cast<int32_t>(ElementsKind::STRING));
1663                         Jump(&exit);
1664                     }
1665                     Bind(&isNonString);
1666                     {
1667                         result = Int32(static_cast<int32_t>(ElementsKind::OBJECT));
1668                         Jump(&exit);
1669                     }
1670                 }
1671             }
1672         }
1673     }
1674     Bind(&exit);
1675     auto ret = *result;
1676     env->SubCfgExit();
1677     return ret;
1678 }
1679 
Store(VariableType type,GateRef glue,GateRef base,GateRef offset,GateRef value,MemoryAttribute mAttr)1680 void StubBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value,
1681                         MemoryAttribute mAttr)
1682 {
1683     if (!env_->IsAsmInterp()) {
1684         env_->GetBuilder()->Store(type, glue, base, offset, value, mAttr);
1685     } else {
1686         auto depend = env_->GetCurrentLabel()->GetDepend();
1687         auto bit = LoadStoreAccessor::ToValue(mAttr);
1688         GateRef result = env_->GetCircuit()->NewGate(
1689             env_->GetCircuit()->Store(bit), MachineType::NOVALUE,
1690             { depend, glue, base, offset, value }, type.GetGateType());
1691         env_->GetCurrentLabel()->SetDepend(result);
1692     }
1693 }
1694 
SetValueWithAttr(GateRef glue,GateRef obj,GateRef offset,GateRef key,GateRef value,GateRef attr)1695 void StubBuilder::SetValueWithAttr(GateRef glue, GateRef obj, GateRef offset, GateRef key, GateRef value, GateRef attr)
1696 {
1697     auto env = GetEnvironment();
1698     Label entry(env);
1699     env->SubCfgEntry(&entry);
1700 
1701     Label exit(env);
1702     Label repChange(env);
1703     GateRef rep = GetRepInPropAttr(attr);
1704     SetValueWithRep(glue, obj, offset, value, rep, &repChange);
1705     Jump(&exit);
1706     Bind(&repChange);
1707     {
1708         attr = SetTaggedRepInPropAttr(attr);
1709         TransitionForRepChange(glue, obj, key, attr);
1710         Store(VariableType::JS_ANY(), glue, obj, offset, value);
1711         Jump(&exit);
1712     }
1713     Bind(&exit);
1714     env->SubCfgExit();
1715 }
1716 
SetValueWithRep(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef rep,Label * repChange)1717 void StubBuilder::SetValueWithRep(
1718     GateRef glue, GateRef obj, GateRef offset, GateRef value, GateRef rep, Label *repChange)
1719 {
1720     auto env = GetEnvironment();
1721     Label entry(env);
1722     env->SubCfgEntry(&entry);
1723 
1724     Label exit(env);
1725     Label repIsDouble(env);
1726     Label repIsNonDouble(env);
1727     BRANCH(IsDoubleRepInPropAttr(rep), &repIsDouble, &repIsNonDouble);
1728     Bind(&repIsDouble);
1729     {
1730         Label valueIsInt(env);
1731         Label valueIsNotInt(env);
1732         BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsNotInt);
1733         Bind(&valueIsInt);
1734         {
1735             GateRef result = GetDoubleOfTInt(value);
1736             Store(VariableType::FLOAT64(), glue, obj, offset, result);
1737             Jump(&exit);
1738         }
1739         Bind(&valueIsNotInt);
1740         {
1741             Label valueIsObject(env);
1742             Label valueIsDouble(env);
1743             BRANCH(TaggedIsObject(value), &valueIsObject, &valueIsDouble);
1744             Bind(&valueIsDouble);
1745             {
1746                 // TaggedDouble to double
1747                 GateRef result = GetDoubleOfTDouble(value);
1748                 Store(VariableType::FLOAT64(), glue, obj, offset, result);
1749                 Jump(&exit);
1750             }
1751             Bind(&valueIsObject);
1752             {
1753                 Jump(repChange);
1754             }
1755         }
1756     }
1757     Bind(&repIsNonDouble);
1758     {
1759         Label repIsInt(env);
1760         Label repIsTagged(env);
1761         BRANCH(IsIntRepInPropAttr(rep), &repIsInt, &repIsTagged);
1762         Bind(&repIsInt);
1763         {
1764             Label valueIsInt(env);
1765             Label valueIsNotInt(env);
1766             BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsNotInt);
1767             Bind(&valueIsInt);
1768             {
1769                 GateRef result = GetInt32OfTInt(value);
1770                 Store(VariableType::INT32(), glue, obj, offset, result);
1771                 Jump(&exit);
1772             }
1773             Bind(&valueIsNotInt);
1774             {
1775                 Jump(repChange);
1776             }
1777         }
1778         Bind(&repIsTagged);
1779         {
1780             Store(VariableType::JS_ANY(), glue, obj, offset, value);
1781             Jump(&exit);
1782         }
1783     }
1784 
1785     Bind(&exit);
1786     env->SubCfgExit();
1787     return;
1788 }
1789 
SetValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,bool withEden,MemoryAttribute::ShareFlag share)1790 void StubBuilder::SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, bool withEden,
1791                                       MemoryAttribute::ShareFlag share)
1792 {
1793     auto env = GetEnvironment();
1794     Label entry(env);
1795     env->SubCfgEntry(&entry);
1796     Label exit(env);
1797     // ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj.
1798     GateRef objectRegion = ObjectAddressToRange(obj);
1799     GateRef valueRegion = ObjectAddressToRange(value);
1800 #ifndef NDEBUG
1801     Label fatal(env);
1802     Label noFatal(env);
1803     int msgId = GET_MESSAGE_STRING_ID(SharedObjectRefersLocalObject);
1804     if (share == MemoryAttribute::SHARED) {
1805         BRANCH(BoolNot(InSharedHeap(valueRegion)), &fatal, &noFatal);
1806         msgId = GET_MESSAGE_STRING_ID(ValueIsNonSObject);
1807     }
1808     if (share == MemoryAttribute::NON_SHARE) {
1809         BRANCH(InSharedHeap(objectRegion), &fatal, &noFatal);
1810     }
1811     if (share == MemoryAttribute::UNKNOWN) {
1812         BRANCH(BitAnd(InSharedHeap(objectRegion), BoolNot(InSharedHeap(valueRegion))), &fatal, &noFatal);
1813     }
1814     Bind(&fatal);
1815     {
1816         FatalPrint(glue, {Int32(msgId)});
1817         Jump(&exit);
1818     }
1819     Bind(&noFatal);
1820 #endif
1821     switch (share) {
1822         case MemoryAttribute::SHARED: {
1823             SetSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
1824             Jump(&exit);
1825             break;
1826         }
1827         case MemoryAttribute::NON_SHARE: {
1828             SetNonSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion, withEden);
1829             Jump(&exit);
1830             break;
1831         }
1832         case MemoryAttribute::UNKNOWN: {
1833             Label valueIsShared(env);
1834             Label valueIsNotShared(env);
1835             BRANCH_UNLIKELY(InSharedHeap(valueRegion), &valueIsShared, &valueIsNotShared);
1836             Bind(&valueIsShared);
1837             {
1838                 SetSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
1839                 Jump(&exit);
1840             }
1841             Bind(&valueIsNotShared);
1842             {
1843                 SetNonSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion, withEden);
1844                 Jump(&exit);
1845             }
1846             break;
1847         }
1848         default:
1849             UNREACHABLE();
1850     }
1851     Bind(&exit);
1852     env->SubCfgExit();
1853 }
1854 
SetSValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef objectRegion,GateRef valueRegion)1855 void StubBuilder::SetSValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, GateRef objectRegion,
1856                                        GateRef valueRegion)
1857 {
1858     auto env = GetEnvironment();
1859     Label entry(env);
1860     env->SubCfgEntry(&entry);
1861     Label exit(env);
1862 
1863     Label needBarrier(env);
1864     GateRef valueRegionInSweepableShare = InSharedSweepableSpace(valueRegion);
1865     BRANCH(valueRegionInSweepableShare, &needBarrier, &exit);
1866     Bind(&needBarrier);
1867     {
1868         Label updateLocalToShareRSet(env);
1869         Label checkBarrierForSharedValue(env);
1870         GateRef objectNotInShare = BoolNot(InSharedHeap(objectRegion));
1871         BRANCH(objectNotInShare, &updateLocalToShareRSet, &checkBarrierForSharedValue);
1872         Bind(&updateLocalToShareRSet);
1873         {
1874             Label callSharedBarrier(env);
1875             Label storeToSharedRSet(env);
1876             GateRef loadOffset = IntPtr(Region::PackedData::GetLocalToShareSetOffset(env_->Is32Bit()));
1877             auto localToShareSet = Load(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
1878             BRANCH(IntPtrEqual(localToShareSet, IntPtr(0)), &callSharedBarrier, &storeToSharedRSet);
1879             Bind(&storeToSharedRSet);
1880             {
1881                 GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
1882                 // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
1883                 GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
1884                 GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
1885                 GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
1886                 GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
1887                 // bitOffset >> BIT_PER_WORD_LOG2
1888                 GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
1889                 GateRef byteIndex = Int32Mul(index, bytePerWord);
1890                 // bitset_[index] |= mask;
1891                 GateRef bitsetData = PtrAdd(localToShareSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
1892                 GateRef oldsetValue = Load(VariableType::INT32(), bitsetData, byteIndex);
1893                 GateRef mask = GetBitMask(bitOffset);
1894                 GateRef flag = Int32And(oldsetValue, mask);
1895                 // Load the bit using relaxed memory order.
1896                 // If the bit is set, do nothing (local->shared barrier is done).
1897                 Label needSet(env);
1898                 BRANCH(Int32NotEqual(flag, Int32(0)), &checkBarrierForSharedValue, &needSet);
1899                 Bind(&needSet);
1900                 {
1901                     GateRef newMapValue = Int32Or(oldsetValue, mask);
1902                     Store(VariableType::INT32(), glue, bitsetData, byteIndex, newMapValue);
1903                     Jump(&checkBarrierForSharedValue);
1904                 }
1905             }
1906             Bind(&callSharedBarrier);
1907             {
1908                 CallNGCRuntime(glue, RTSTUB_ID(InsertLocalToShareRSet), { glue, obj, offset });
1909                 Jump(&checkBarrierForSharedValue);
1910             }
1911         }
1912         Bind(&checkBarrierForSharedValue);
1913         {
1914             Label sharedMarking(env);
1915             bool isArch32 = GetEnvironment()->Is32Bit();
1916             GateRef stateBitField = Load(VariableType::INT64(), glue,
1917                                          Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(isArch32)));
1918             GateRef state = Int64And(stateBitField, Int64(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK));
1919             BRANCH(Int64Equal(state, Int64(static_cast<int64_t>(SharedMarkStatus::READY_TO_CONCURRENT_MARK))),
1920                 &exit, &sharedMarking);
1921 
1922             Bind(&sharedMarking);
1923             CallNGCRuntime(glue, RTSTUB_ID(SharedGCMarkingBarrier), {glue, value});
1924             Jump(&exit);
1925         }
1926     }
1927     Bind(&exit);
1928     env->SubCfgExit();
1929 }
1930 
SetNonSValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef objectRegion,GateRef valueRegion,bool withEden)1931 void StubBuilder::SetNonSValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value,
1932                                           GateRef objectRegion, GateRef valueRegion, bool withEden)
1933 {
1934     auto env = GetEnvironment();
1935     Label entry(env);
1936     env->SubCfgEntry(&entry);
1937     Label exit(env);
1938 
1939     Label checkMarkStatus(env);
1940     Label isOldToYoung(env);
1941     Label checkEden(env);
1942     if (withEden) {
1943         GateRef objectRegionInOld = InGeneralOldGeneration(objectRegion);
1944         GateRef valueRegionInYoung = InGeneralYoungGeneration(valueRegion);
1945         BRANCH(BitAnd(objectRegionInOld, valueRegionInYoung), &isOldToYoung, &checkEden);
1946     } else {
1947         GateRef objectNotInYoung = BoolNot(InYoungGeneration(objectRegion));
1948         GateRef valueRegionInYoung = InYoungGeneration(valueRegion);
1949         BRANCH_UNLIKELY(BitAnd(objectNotInYoung, valueRegionInYoung), &isOldToYoung, &checkMarkStatus);
1950     }
1951 
1952     Bind(&isOldToYoung);
1953     {
1954         GateRef loadOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env_->Is32Bit()));
1955         auto oldToNewSet = Load(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
1956         Label isNullPtr(env);
1957         Label notNullPtr(env);
1958         BRANCH(IntPtrEuqal(oldToNewSet, IntPtr(0)), &isNullPtr, &notNullPtr);
1959         Bind(&notNullPtr);
1960         {
1961             GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
1962             // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
1963             GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
1964             GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
1965             GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
1966             GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
1967             // bitOffset >> BIT_PER_WORD_LOG2
1968             GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
1969             GateRef byteIndex = Int32Mul(index, bytePerWord);
1970             // bitset_[index] |= mask;
1971             GateRef bitsetData = PtrAdd(oldToNewSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
1972             GateRef oldsetValue = Load(VariableType::INT32(), bitsetData, byteIndex);
1973             GateRef newmapValue = Int32Or(oldsetValue, GetBitMask(bitOffset));
1974 
1975             Store(VariableType::INT32(), glue, bitsetData, byteIndex, newmapValue);
1976             Jump(&checkMarkStatus);
1977         }
1978         Bind(&isNullPtr);
1979         {
1980             CallNGCRuntime(glue, RTSTUB_ID(InsertOldToNewRSet), { glue, obj, offset });
1981             Jump(&checkMarkStatus);
1982         }
1983     }
1984     if (withEden) {
1985         Bind(&checkEden);
1986         GateRef objectRegionInYoung = InYoungGeneration(objectRegion);
1987         GateRef valueRegionInEden = InEdenGeneration(valueRegion);
1988         Label newToEden(env);
1989         Branch(BitAnd(objectRegionInYoung, valueRegionInEden), &newToEden, &checkMarkStatus);
1990         Bind(&newToEden);
1991         {
1992             GateRef loadOffset = IntPtr(Region::PackedData::GetNewToEdenSetOffset(env_->Is32Bit()));
1993             auto newToEdenSet = Load(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
1994             Label isNullPtr(env);
1995             Label notNullPtr(env);
1996             Branch(IntPtrEuqal(newToEdenSet, IntPtr(0)), &isNullPtr, &notNullPtr);
1997             Bind(&notNullPtr);
1998             {
1999                 GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
2000                 // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
2001                 GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
2002                 GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
2003                 GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
2004                 GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
2005                 // bitOffset >> BIT_PER_WORD_LOG2
2006                 GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
2007                 GateRef byteIndex = Int32Mul(index, bytePerWord);
2008                 // bitset_[index] |= mask;
2009                 GateRef bitsetData = PtrAdd(newToEdenSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
2010                 GateRef oldsetValue = Load(VariableType::INT32(), bitsetData, byteIndex);
2011                 GateRef newmapValue = Int32Or(oldsetValue, GetBitMask(bitOffset));
2012 
2013                 Store(VariableType::INT32(), glue, bitsetData, byteIndex, newmapValue);
2014                 Jump(&checkMarkStatus);
2015             }
2016             Bind(&isNullPtr);
2017             {
2018                 CallNGCRuntime(glue, RTSTUB_ID(InsertNewToEdenRSet), { glue, obj, offset });
2019                 Jump(&checkMarkStatus);
2020             }
2021         }
2022     }
2023     Bind(&checkMarkStatus);
2024     {
2025         Label marking(env);
2026         bool isArch32 = GetEnvironment()->Is32Bit();
2027         GateRef stateBitField = Load(VariableType::INT64(), glue,
2028                                      Int64(JSThread::GlueData::GetGCStateBitFieldOffset(isArch32)));
2029         GateRef state = Int64And(stateBitField, Int64(JSThread::CONCURRENT_MARKING_BITFIELD_MASK));
2030         BRANCH_LIKELY(Int64Equal(state, Int64(static_cast<int64_t>(MarkStatus::READY_TO_MARK))), &exit, &marking);
2031 
2032         Bind(&marking);
2033         {
2034             // Check fresh region, and directly mark value instead of call runtime.
2035             CallNGCRuntime(glue, RTSTUB_ID(MarkingBarrier), {glue, obj, offset, value});
2036             Jump(&exit);
2037         }
2038     }
2039     Bind(&exit);
2040     env->SubCfgExit();
2041 }
2042 
TaggedIsBigInt(GateRef obj)2043 GateRef StubBuilder::TaggedIsBigInt(GateRef obj)
2044 {
2045     auto env = GetEnvironment();
2046     Label entry(env);
2047     env->SubCfgEntry(&entry);
2048     Label exit(env);
2049     Label isHeapObject(env);
2050     DEFVARIABLE(result, VariableType::BOOL(), False());
2051     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
2052     Bind(&isHeapObject);
2053     {
2054         result = Int32Equal(GetObjectType(LoadHClass(obj)),
2055                             Int32(static_cast<int32_t>(JSType::BIGINT)));
2056         Jump(&exit);
2057     }
2058     Bind(&exit);
2059     auto ret = *result;
2060     env->SubCfgExit();
2061     return ret;
2062 }
2063 
TaggedIsPropertyBox(GateRef obj)2064 GateRef StubBuilder::TaggedIsPropertyBox(GateRef obj)
2065 {
2066     auto env = GetEnvironment();
2067     Label entry(env);
2068     env->SubCfgEntry(&entry);
2069     Label exit(env);
2070     Label isHeapObject(env);
2071     DEFVARIABLE(result, VariableType::BOOL(), False());
2072     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
2073     Bind(&isHeapObject);
2074     {
2075         GateRef type = GetObjectType(LoadHClass(obj));
2076         result = Int32Equal(type, Int32(static_cast<int32_t>(JSType::PROPERTY_BOX)));
2077         Jump(&exit);
2078     }
2079     Bind(&exit);
2080     auto ret = *result;
2081     env->SubCfgExit();
2082     return ret;
2083 }
2084 
TaggedIsAccessor(GateRef x)2085 GateRef StubBuilder::TaggedIsAccessor(GateRef x)
2086 {
2087     auto env = GetEnvironment();
2088     Label entry(env);
2089     env->SubCfgEntry(&entry);
2090     Label exit(env);
2091     Label isHeapObject(env);
2092     DEFVARIABLE(result, VariableType::BOOL(), False());
2093     BRANCH(TaggedIsHeapObject(x), &isHeapObject, &exit);
2094     Bind(&isHeapObject);
2095     {
2096         GateRef type = GetObjectType(LoadHClass(x));
2097         result = BitOr(Int32Equal(type, Int32(static_cast<int32_t>(JSType::ACCESSOR_DATA))),
2098                        Int32Equal(type, Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR))));
2099         Jump(&exit);
2100     }
2101     Bind(&exit);
2102     auto ret = *result;
2103     env->SubCfgExit();
2104     return ret;
2105 }
2106 
IsUtf16String(GateRef string)2107 GateRef StubBuilder::IsUtf16String(GateRef string)
2108 {
2109     // compressedStringsEnabled fixed to true constant
2110     GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
2111     return Int32Equal(
2112         Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
2113         Int32(EcmaString::STRING_UNCOMPRESSED));
2114 }
2115 
IsUtf8String(GateRef string)2116 GateRef StubBuilder::IsUtf8String(GateRef string)
2117 {
2118     // compressedStringsEnabled fixed to true constant
2119     GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
2120     return Int32Equal(
2121         Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
2122         Int32(EcmaString::STRING_COMPRESSED));
2123 }
2124 
IsInternalString(GateRef string)2125 GateRef StubBuilder::IsInternalString(GateRef string)
2126 {
2127     // compressedStringsEnabled fixed to true constant
2128     GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
2129     return Int32NotEqual(
2130         Int32And(len, Int32(EcmaString::STRING_INTERN_BIT)),
2131         Int32(0));
2132 }
2133 
IsDigit(GateRef ch)2134 GateRef StubBuilder::IsDigit(GateRef ch)
2135 {
2136     return BitAnd(Int32LessThanOrEqual(ch, Int32('9')),
2137         Int32GreaterThanOrEqual(ch, Int32('0')));
2138 }
2139 
TryToGetInteger(GateRef string,Variable * num,Label * success,Label * failed)2140 void StubBuilder::TryToGetInteger(GateRef string, Variable *num, Label *success, Label *failed)
2141 {
2142     auto env = GetEnvironment();
2143     Label exit(env);
2144     Label inRange(env);
2145     Label isInteger(env);
2146 
2147     GateRef len = GetLengthFromString(string);
2148     BRANCH(Int32LessThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &inRange, failed);
2149     Bind(&inRange);
2150     {
2151         BRANCH(IsIntegerString(string), &isInteger, failed);
2152         Bind(&isInteger);
2153         {
2154             GateRef integerNum = ZExtInt32ToInt64(GetRawHashFromString(string));
2155             num->WriteVariable(integerNum);
2156             Jump(success);
2157         }
2158     }
2159 }
2160 
StringToElementIndex(GateRef glue,GateRef string)2161 GateRef StubBuilder::StringToElementIndex(GateRef glue, GateRef string)
2162 {
2163     auto env = GetEnvironment();
2164     Label entry(env);
2165     env->SubCfgEntry(&entry);
2166     Label exit(env);
2167     DEFVARIABLE(result, VariableType::INT64(), Int64(-1));
2168     Label greatThanZero(env);
2169     Label inRange(env);
2170     Label flattenFastPath(env);
2171     auto len = GetLengthFromString(string);
2172     BRANCH(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
2173     Bind(&greatThanZero);
2174     BRANCH(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
2175     Bind(&inRange);
2176     {
2177         Label isUtf8(env);
2178         GateRef isUtf16String = IsUtf16String(string);
2179         BRANCH(isUtf16String, &exit, &isUtf8);
2180         Bind(&isUtf8);
2181         {
2182             Label getFailed(env);
2183             TryToGetInteger(string, &result, &exit, &getFailed);
2184             Bind(&getFailed);
2185             DEFVARIABLE(c, VariableType::INT32(), Int32(0));
2186             FlatStringStubBuilder thisFlat(this);
2187             thisFlat.FlattenString(glue, string, &flattenFastPath);
2188             Bind(&flattenFastPath);
2189             StringInfoGateRef stringInfoGate(&thisFlat);
2190             GateRef dataUtf8 = GetNormalStringData(stringInfoGate);
2191             c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8));
2192             Label isDigitZero(env);
2193             Label notDigitZero(env);
2194             BRANCH(Int32Equal(*c, Int32('0')), &isDigitZero, &notDigitZero);
2195             Bind(&isDigitZero);
2196             {
2197                 Label lengthIsOne(env);
2198                 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
2199                 Bind(&lengthIsOne);
2200                 {
2201                     result = Int64(0);
2202                     Jump(&exit);
2203                 }
2204             }
2205             Bind(&notDigitZero);
2206             {
2207                 Label isDigit(env);
2208                 DEFVARIABLE(i, VariableType::INT32(), Int32(1));
2209                 DEFVARIABLE(n, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(*c), Int64('0')));
2210                 BRANCH(IsDigit(*c), &isDigit, &exit);
2211                 Label loopHead(env);
2212                 Label loopEnd(env);
2213                 Label afterLoop(env);
2214                 Bind(&isDigit);
2215                 BRANCH(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
2216                 LoopBegin(&loopHead);
2217                 {
2218                     c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8, ZExtInt32ToPtr(*i)));
2219                     Label isDigit2(env);
2220                     Label notDigit2(env);
2221                     BRANCH(IsDigit(*c), &isDigit2, &notDigit2);
2222                     Bind(&isDigit2);
2223                     {
2224                         // 10 means the base of digit is 10.
2225                         n = Int64Add(Int64Mul(*n, Int64(10)), Int64Sub(ZExtInt32ToInt64(*c), Int64('0')));
2226                         i = Int32Add(*i, Int32(1));
2227                         BRANCH(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
2228                     }
2229                     Bind(&notDigit2);
2230                     Jump(&exit);
2231                 }
2232                 Bind(&loopEnd);
2233                 LoopEnd(&loopHead, env, glue);
2234                 Bind(&afterLoop);
2235                 {
2236                     Label lessThanMaxIndex(env);
2237                     BRANCH(Int64LessThan(*n, Int64(JSObject::MAX_ELEMENT_INDEX)),
2238                            &lessThanMaxIndex, &exit);
2239                     Bind(&lessThanMaxIndex);
2240                     {
2241                         result = *n;
2242                         Jump(&exit);
2243                     }
2244                 }
2245             }
2246         }
2247     }
2248     Bind(&exit);
2249     auto ret = *result;
2250     env->SubCfgExit();
2251     return ret;
2252 }
2253 
TryToElementsIndex(GateRef glue,GateRef key)2254 GateRef StubBuilder::TryToElementsIndex(GateRef glue, GateRef key)
2255 {
2256     auto env = GetEnvironment();
2257     Label entry(env);
2258     env->SubCfgEntry(&entry);
2259     Label exit(env);
2260     Label isKeyInt(env);
2261     Label notKeyInt(env);
2262 
2263     DEFVARIABLE(resultKey, VariableType::INT64(), Int64(-1));
2264     BRANCH(TaggedIsInt(key), &isKeyInt, &notKeyInt);
2265     Bind(&isKeyInt);
2266     {
2267         resultKey = GetInt64OfTInt(key);
2268         Jump(&exit);
2269     }
2270     Bind(&notKeyInt);
2271     {
2272         Label isString(env);
2273         Label notString(env);
2274         BRANCH(TaggedIsString(key), &isString, &notString);
2275         Bind(&isString);
2276         {
2277             resultKey = StringToElementIndex(glue, key);
2278             Jump(&exit);
2279         }
2280         Bind(&notString);
2281         {
2282             Label isDouble(env);
2283             BRANCH(TaggedIsDouble(key), &isDouble, &exit);
2284             Bind(&isDouble);
2285             {
2286                 GateRef number = GetDoubleOfTDouble(key);
2287                 GateRef integer = ChangeFloat64ToInt32(number);
2288                 Label isEqual(env);
2289                 BRANCH(DoubleEqual(number, ChangeInt32ToFloat64(integer)), &isEqual, &exit);
2290                 Bind(&isEqual);
2291                 {
2292                     resultKey = SExtInt32ToInt64(integer);
2293                     Jump(&exit);
2294                 }
2295             }
2296         }
2297     }
2298     Bind(&exit);
2299     auto ret = *resultKey;
2300     env->SubCfgExit();
2301     return ret;
2302 }
2303 
LdGlobalRecord(GateRef glue,GateRef key)2304 GateRef StubBuilder::LdGlobalRecord(GateRef glue, GateRef key)
2305 {
2306     auto env = GetEnvironment();
2307     Label entry(env);
2308     env->SubCfgEntry(&entry);
2309     Label exit(env);
2310 
2311     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2312     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2313     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2314     GateRef globalRecord = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::GLOBAL_RECORD);
2315     GateRef recordEntry = FindEntryFromNameDictionary(glue, globalRecord, key);
2316     Label foundInGlobalRecord(env);
2317     BRANCH(Int32NotEqual(recordEntry, Int32(-1)), &foundInGlobalRecord, &exit);
2318     Bind(&foundInGlobalRecord);
2319     {
2320         result = GetBoxFromGlobalDictionary(globalRecord, recordEntry);
2321         Jump(&exit);
2322     }
2323     Bind(&exit);
2324     auto ret = *result;
2325     env->SubCfgExit();
2326     return ret;
2327 }
2328 
LoadFromField(GateRef receiver,GateRef handlerInfo)2329 GateRef StubBuilder::LoadFromField(GateRef receiver, GateRef handlerInfo)
2330 {
2331     auto env = GetEnvironment();
2332     Label entry(env);
2333     env->SubCfgEntry(&entry);
2334     Label exit(env);
2335     Label handlerInfoIsInlinedProps(env);
2336     Label handlerInfoNotInlinedProps(env);
2337     Label handlerPost(env);
2338     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2339     GateRef index = HandlerBaseGetOffset(handlerInfo);
2340     BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
2341     Bind(&handlerInfoIsInlinedProps);
2342     {
2343         result = Load(VariableType::JS_ANY(), receiver, PtrMul(ZExtInt32ToPtr(index),
2344             IntPtr(JSTaggedValue::TaggedTypeSize())));
2345         Jump(&handlerPost);
2346     }
2347     Bind(&handlerInfoNotInlinedProps);
2348     {
2349         result = GetValueFromTaggedArray(GetPropertiesArray(receiver), index);
2350         Jump(&handlerPost);
2351     }
2352     Bind(&handlerPost);
2353     {
2354         Label nonDoubleToTagged(env);
2355         Label doubleToTagged(env);
2356         GateRef rep = HandlerBaseGetRep(handlerInfo);
2357         BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
2358         Bind(&doubleToTagged);
2359         {
2360             result = TaggedPtrToTaggedDoublePtr(*result);
2361             Jump(&exit);
2362         }
2363         Bind(&nonDoubleToTagged);
2364         {
2365             Label intToTagged(env);
2366             BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit);
2367             Bind(&intToTagged);
2368             {
2369                 result = TaggedPtrToTaggedIntPtr(*result);
2370                 Jump(&exit);
2371             }
2372         }
2373     }
2374     Bind(&exit);
2375     auto ret = *result;
2376     env->SubCfgExit();
2377     return ret;
2378 }
2379 
LoadGlobal(GateRef cell)2380 GateRef StubBuilder::LoadGlobal(GateRef cell)
2381 {
2382     auto env = GetEnvironment();
2383     Label entry(env);
2384     env->SubCfgEntry(&entry);
2385     Label exit(env);
2386     Label cellNotInvalid(env);
2387     Label cellNotAccessor(env);
2388     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2389     BRANCH(IsInvalidPropertyBox(cell), &exit, &cellNotInvalid);
2390     Bind(&cellNotInvalid);
2391     {
2392         BRANCH(IsAccessorPropertyBox(cell), &exit, &cellNotAccessor);
2393         Bind(&cellNotAccessor);
2394         {
2395             result = GetValueFromPropertyBox(cell);
2396             Jump(&exit);
2397         }
2398     }
2399     Bind(&exit);
2400     auto ret = *result;
2401     env->SubCfgExit();
2402     return ret;
2403 }
2404 
CheckPolyHClass(GateRef cachedValue,GateRef hclass)2405 GateRef StubBuilder::CheckPolyHClass(GateRef cachedValue, GateRef hclass)
2406 {
2407     auto env = GetEnvironment();
2408     Label entry(env);
2409     env->SubCfgEntry(&entry);
2410     Label exit(env);
2411     Label loopHead(env);
2412     Label loopEnd(env);
2413     Label iLessLength(env);
2414     Label hasHclass(env);
2415     Label cachedValueNotWeak(env);
2416     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2417     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2418     BRANCH(TaggedIsWeak(cachedValue), &exit, &cachedValueNotWeak);
2419     Bind(&cachedValueNotWeak);
2420     {
2421         Label isTaggedArray(env);
2422         Branch(IsTaggedArray(cachedValue), &isTaggedArray, &exit);
2423         Bind(&isTaggedArray);
2424         {
2425             GateRef length = GetLengthOfTaggedArray(cachedValue);
2426             Jump(&loopHead);
2427             LoopBegin(&loopHead);
2428             {
2429                 BRANCH(Int32UnsignedLessThan(*i, length), &iLessLength, &exit);
2430                 Bind(&iLessLength);
2431                 {
2432                     GateRef element = GetValueFromTaggedArray(cachedValue, *i);
2433                     BRANCH(Equal(LoadObjectFromWeakRef(element), hclass), &hasHclass, &loopEnd);
2434                     Bind(&hasHclass);
2435                     result = GetValueFromTaggedArray(cachedValue, Int32Add(*i, Int32(1)));
2436                     Jump(&exit);
2437                 }
2438                 Bind(&loopEnd);
2439                 i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot
2440                 LoopEnd(&loopHead);
2441             }
2442         }
2443     }
2444     Bind(&exit);
2445     auto ret = *result;
2446     env->SubCfgExit();
2447     return ret;
2448 }
2449 
LoadICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef argHandler,ProfileOperation callback)2450 GateRef StubBuilder::LoadICWithHandler(
2451     GateRef glue, GateRef receiver, GateRef argHolder, GateRef argHandler, ProfileOperation callback)
2452 {
2453     auto env = GetEnvironment();
2454     Label entry(env);
2455     env->SubCfgEntry(&entry);
2456     Label exit(env);
2457     Label handlerIsInt(env);
2458     Label handlerNotInt(env);
2459     Label handlerInfoIsField(env);
2460     Label handlerInfoNotField(env);
2461     Label handlerInfoIsNonExist(env);
2462     Label handlerInfoNotNonExist(env);
2463     Label handlerInfoIsPrimitive(env);
2464     Label handlerInfoNotPrimitive(env);
2465     Label handlerInfoIsStringLength(env);
2466     Label handlerInfoNotStringLength(env);
2467     Label handlerIsPrototypeHandler(env);
2468     Label handlerNotPrototypeHandler(env);
2469     Label cellHasChanged(env);
2470     Label cellNotUndefined(env);
2471     Label loopHead(env);
2472     Label loopEnd(env);
2473     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2474     DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
2475     DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
2476 
2477     Jump(&loopHead);
2478     LoopBegin(&loopHead);
2479     {
2480         BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
2481         Bind(&handlerIsInt);
2482         {
2483             GateRef handlerInfo = GetInt64OfTInt(*handler);
2484             BRANCH(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2485             Bind(&handlerInfoIsField);
2486             {
2487                 result = LoadFromField(*holder, handlerInfo);
2488                 Jump(&exit);
2489             }
2490             Bind(&handlerInfoNotField);
2491             {
2492                 BRANCH(BitOr(IsStringElement(handlerInfo), IsNumber(handlerInfo)),
2493                     &handlerInfoIsPrimitive, &handlerInfoNotPrimitive);
2494                 Bind(&handlerInfoIsPrimitive);
2495                 {
2496                     result = LoadFromField(*holder, handlerInfo);
2497                     Jump(&exit);
2498                 }
2499                 Bind(&handlerInfoNotPrimitive);
2500                 {
2501                     BRANCH(IsNonExist(handlerInfo), &handlerInfoIsNonExist, &handlerInfoNotNonExist);
2502                     Bind(&handlerInfoIsNonExist);
2503                     Jump(&exit);
2504                     Bind(&handlerInfoNotNonExist);
2505                     {
2506                         BRANCH(IsStringLength(handlerInfo), &handlerInfoIsStringLength, &handlerInfoNotStringLength);
2507                         Bind(&handlerInfoNotStringLength);
2508                         {
2509                             GateRef accessor = LoadFromField(*holder, handlerInfo);
2510                             result = CallGetterHelper(glue, receiver, *holder, accessor, callback);
2511                             Jump(&exit);
2512                         }
2513                         Bind(&handlerInfoIsStringLength);
2514                         {
2515                             result = IntToTaggedPtr(GetLengthFromString(receiver));
2516                             Jump(&exit);
2517                         }
2518                     }
2519                 }
2520             }
2521         }
2522         Bind(&handlerNotInt);
2523         BRANCH(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
2524         Bind(&handlerIsPrototypeHandler);
2525         {
2526             GateRef cellValue = GetProtoCell(*handler);
2527             BRANCH(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
2528             Bind(&cellNotUndefined);
2529             BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2530             Bind(&cellHasChanged);
2531             {
2532                 result = Hole();
2533                 Jump(&exit);
2534             }
2535             Bind(&loopEnd);
2536             holder = GetPrototypeHandlerHolder(*handler);
2537             handler = GetPrototypeHandlerHandlerInfo(*handler);
2538             LoopEnd(&loopHead, env, glue);
2539         }
2540     }
2541     Bind(&handlerNotPrototypeHandler);
2542     result = LoadGlobal(*handler);
2543     Jump(&exit);
2544 
2545     Bind(&exit);
2546     auto ret = *result;
2547     env->SubCfgExit();
2548     return ret;
2549 }
2550 
LoadElement(GateRef glue,GateRef receiver,GateRef key)2551 GateRef StubBuilder::LoadElement(GateRef glue, GateRef receiver, GateRef key)
2552 {
2553     auto env = GetEnvironment();
2554     Label entry(env);
2555     env->SubCfgEntry(&entry);
2556     Label exit(env);
2557     Label indexLessZero(env);
2558     Label indexNotLessZero(env);
2559     Label lengthLessIndex(env);
2560     Label lengthNotLessIndex(env);
2561     Label greaterThanInt32Max(env);
2562     Label notGreaterThanInt32Max(env);
2563     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2564     GateRef index64 = TryToElementsIndex(glue, key);
2565     BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
2566     Bind(&greaterThanInt32Max);
2567     {
2568         Jump(&exit);
2569     }
2570     Bind(&notGreaterThanInt32Max);
2571     GateRef index = TruncInt64ToInt32(index64);
2572     BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2573     Bind(&indexLessZero);
2574     {
2575         Jump(&exit);
2576     }
2577     Bind(&indexNotLessZero);
2578     {
2579         GateRef elements = GetElementsArray(receiver);
2580         BRANCH(Int32LessThanOrEqual(GetLengthOfTaggedArray(elements), index), &lengthLessIndex, &lengthNotLessIndex);
2581         Bind(&lengthLessIndex);
2582         Jump(&exit);
2583         Bind(&lengthNotLessIndex);
2584         result = GetTaggedValueWithElementsKind(receiver, index);
2585         Jump(&exit);
2586     }
2587     Bind(&exit);
2588     auto ret = *result;
2589     env->SubCfgExit();
2590     return ret;
2591 }
2592 
LoadStringElement(GateRef glue,GateRef receiver,GateRef key)2593 GateRef StubBuilder::LoadStringElement(GateRef glue, GateRef receiver, GateRef key)
2594 {
2595     auto env = GetEnvironment();
2596     Label entry(env);
2597     env->SubCfgEntry(&entry);
2598     Label exit(env);
2599     Label indexLessZero(env);
2600     Label indexNotLessZero(env);
2601     Label lengthLessIndex(env);
2602     Label lengthNotLessIndex(env);
2603     Label greaterThanInt32Max(env);
2604     Label notGreaterThanInt32Max(env);
2605     Label flattenFastPath(env);
2606 
2607     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2608     GateRef index64 = TryToElementsIndex(glue, key);
2609     BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
2610     Bind(&greaterThanInt32Max);
2611     {
2612         Jump(&exit);
2613     }
2614     Bind(&notGreaterThanInt32Max);
2615     GateRef index = TruncInt64ToInt32(index64);
2616     BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2617     Bind(&indexLessZero);
2618     {
2619         Jump(&exit);
2620     }
2621     Bind(&indexNotLessZero);
2622     {
2623         FlatStringStubBuilder thisFlat(this);
2624         thisFlat.FlattenString(glue, receiver, &flattenFastPath);
2625         Bind(&flattenFastPath);
2626         BRANCH(Int32LessThanOrEqual(GetLengthFromString(receiver), index), &lengthLessIndex, &lengthNotLessIndex);
2627         Bind(&lengthLessIndex);
2628         Jump(&exit);
2629         Bind(&lengthNotLessIndex);
2630         BuiltinsStringStubBuilder stringBuilder(this);
2631         StringInfoGateRef stringInfoGate(&thisFlat);
2632         result = stringBuilder.CreateFromEcmaString(glue, index, stringInfoGate);
2633         Jump(&exit);
2634     }
2635     Bind(&exit);
2636     auto ret = *result;
2637     env->SubCfgExit();
2638     return ret;
2639 }
2640 
ICStoreElement(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef handler,bool updateHandler,GateRef profileTypeInfo,GateRef slotId)2641 GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef handler,
2642                                     bool updateHandler, GateRef profileTypeInfo, GateRef slotId)
2643 {
2644     auto env = GetEnvironment();
2645     Label entry(env);
2646     env->SubCfgEntry(&entry);
2647     Label exit(env);
2648     Label indexLessZero(env);
2649     Label indexNotLessZero(env);
2650     Label handlerInfoIsTypedArray(env);
2651     Label handerInfoNotTypedArray(env);
2652     Label handerInfoIsJSArray(env);
2653     Label handerInfoNotJSArray(env);
2654     Label isJsCOWArray(env);
2655     Label isNotJsCOWArray(env);
2656     Label setElementsLength(env);
2657     Label indexGreaterLength(env);
2658     Label indexGreaterCapacity(env);
2659     Label callRuntime(env);
2660     Label storeElement(env);
2661     Label handlerIsInt(env);
2662     Label handlerNotInt(env);
2663     Label cellHasChanged(env);
2664     Label cellHasNotChanged(env);
2665     Label loopHead(env);
2666     Label loopEnd(env);
2667     Label greaterThanInt32Max(env);
2668     Label notGreaterThanInt32Max(env);
2669     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2670     DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler);
2671     GateRef index64 = TryToElementsIndex(glue, key);
2672     BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
2673     Bind(&greaterThanInt32Max);
2674     {
2675         Jump(&exit);
2676     }
2677     Bind(&notGreaterThanInt32Max);
2678     GateRef index = TruncInt64ToInt32(index64);
2679     BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2680     Bind(&indexLessZero);
2681     {
2682         Jump(&exit);
2683     }
2684     Bind(&indexNotLessZero);
2685     {
2686         Jump(&loopHead);
2687         LoopBegin(&loopHead);
2688         BRANCH(TaggedIsInt(*varHandler), &handlerIsInt, &handlerNotInt);
2689         Bind(&handlerIsInt);
2690         {
2691             GateRef handlerInfo = GetInt64OfTInt(*varHandler);
2692             BRANCH(IsTypedArrayElement(handlerInfo), &handlerInfoIsTypedArray, &handerInfoNotTypedArray);
2693             Bind(&handlerInfoIsTypedArray);
2694             {
2695                 GateRef hclass = LoadHClass(receiver);
2696                 GateRef jsType = GetObjectType(hclass);
2697                 BuiltinsTypedArrayStubBuilder typedArrayBuilder(this);
2698                 result = typedArrayBuilder.StoreTypedArrayElement(glue, receiver, index64, value, jsType);
2699                 Jump(&exit);
2700             }
2701             Bind(&handerInfoNotTypedArray);
2702             BRANCH(HandlerBaseIsJSArray(handlerInfo), &handerInfoIsJSArray, &handerInfoNotJSArray);
2703             Bind(&handerInfoIsJSArray);
2704             {
2705                 BRANCH(IsJsCOWArray(receiver), &isJsCOWArray, &isNotJsCOWArray);
2706                 Bind(&isJsCOWArray);
2707                 {
2708                     CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {receiver});
2709                     Jump(&setElementsLength);
2710                 }
2711                 Bind(&isNotJsCOWArray);
2712                 {
2713                     Jump(&setElementsLength);
2714                 }
2715                 Bind(&setElementsLength);
2716                 {
2717                     GateRef oldLength = GetArrayLength(receiver);
2718                     BRANCH(Int32GreaterThanOrEqual(index, oldLength), &indexGreaterLength, &handerInfoNotJSArray);
2719                     Bind(&indexGreaterLength);
2720                     Store(VariableType::INT32(), glue, receiver,
2721                         IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET),
2722                         Int32Add(index, Int32(1)));
2723                     if (updateHandler) {
2724                         Label update(env);
2725                         GateRef oldHandler = GetValueFromTaggedArray(profileTypeInfo, slotId);
2726                         BRANCH(Equal(oldHandler, Hole()), &handerInfoNotJSArray, &update);
2727                         Bind(&update);
2728                         handler = Int64ToTaggedInt(UpdateSOutOfBoundsForHandler(handlerInfo));
2729                         SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, handler);
2730                     }
2731                 }
2732                 Jump(&handerInfoNotJSArray);
2733             }
2734             Bind(&handerInfoNotJSArray);
2735             {
2736                 GateRef elements = GetElementsArray(receiver);
2737                 GateRef capacity = GetLengthOfTaggedArray(elements);
2738                 BRANCH(Int32GreaterThanOrEqual(index, capacity), &callRuntime, &storeElement);
2739                 Bind(&callRuntime);
2740                 {
2741                     result = CallRuntime(glue,
2742                         RTSTUB_ID(TaggedArraySetValue),
2743                         { receiver, value, elements, IntToTaggedInt(index),
2744                           IntToTaggedInt(capacity) });
2745                     Label transition(env);
2746                     BRANCH(TaggedIsHole(*result), &exit, &transition);
2747                     Bind(&transition);
2748                     {
2749                         Label hole(env);
2750                         Label notHole(env);
2751                         DEFVARIABLE(kind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::NONE)));
2752                         BRANCH(Int32GreaterThan(index, capacity), &hole, &notHole);
2753                         Bind(&hole);
2754                         {
2755                             kind = Int32(static_cast<int32_t>(ElementsKind::HOLE));
2756                             Jump(&notHole);
2757                         }
2758                         Bind(&notHole);
2759                         {
2760                             SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
2761                             Jump(&exit);
2762                         }
2763                     }
2764                 }
2765                 Bind(&storeElement);
2766                 {
2767                     SetValueWithElementsKind(glue, receiver, value, index, Boolean(true),
2768                                              Int32(static_cast<int32_t>(ElementsKind::NONE)));
2769                     result = Undefined();
2770                     Jump(&exit);
2771                 }
2772             }
2773         }
2774         Bind(&handlerNotInt);
2775         {
2776             GateRef cellValue = GetProtoCell(*varHandler);
2777             BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2778             Bind(&cellHasChanged);
2779             {
2780                 Jump(&exit);
2781             }
2782             Bind(&loopEnd);
2783             {
2784                 varHandler = GetPrototypeHandlerHandlerInfo(*varHandler);
2785                 LoopEnd(&loopHead, env, glue);
2786             }
2787         }
2788     }
2789     Bind(&exit);
2790     auto ret = *result;
2791     env->SubCfgExit();
2792     return ret;
2793 }
2794 
GetArrayLength(GateRef object)2795 GateRef StubBuilder::GetArrayLength(GateRef object)
2796 {
2797     GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
2798     GateRef result = Load(VariableType::INT32(), object, lengthOffset);
2799     return result;
2800 }
2801 
SetArrayLength(GateRef glue,GateRef object,GateRef len)2802 void StubBuilder::SetArrayLength(GateRef glue, GateRef object, GateRef len)
2803 {
2804     GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
2805     Store(VariableType::INT32(), glue, object, lengthOffset, len);
2806 }
2807 
StoreICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef value,GateRef argHandler,ProfileOperation callback)2808 GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder,
2809                                         GateRef value, GateRef argHandler, ProfileOperation callback)
2810 {
2811     auto env = GetEnvironment();
2812     Label entry(env);
2813     env->SubCfgEntry(&entry);
2814     Label exit(env);
2815     Label handlerIsInt(env);
2816     Label handlerNotInt(env);
2817     Label handlerInfoIsField(env);
2818     Label handlerInfoNotField(env);
2819     Label isShared(env);
2820     Label notShared(env);
2821     Label matchType(env);
2822     Label prepareIntHandlerLoop(env);
2823     Label handlerIsTransitionHandler(env);
2824     Label handlerNotTransitionHandler(env);
2825     Label handlerIsTransWithProtoHandler(env);
2826     Label handlerNotTransWithProtoHandler(env);
2827     Label handlerIsPrototypeHandler(env);
2828     Label handlerNotPrototypeHandler(env);
2829     Label handlerIsPropertyBox(env);
2830     Label handlerNotPropertyBox(env);
2831     Label handlerIsStoreTSHandler(env);
2832     Label handlerNotStoreTSHandler(env);
2833     Label aotHandlerInfoIsField(env);
2834     Label aotHandlerInfoNotField(env);
2835     Label cellHasChanged(env);
2836     Label cellNotChanged(env);
2837     Label cellNotUndefined(env);
2838     Label aotCellNotChanged(env);
2839     Label loopHead(env);
2840     Label loopEnd(env);
2841     Label JumpLoopHead(env);
2842     Label cellNotNull(env);
2843     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2844     DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
2845     DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
2846     Jump(&loopHead);
2847     LoopBegin(&loopHead);
2848     {
2849         BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
2850         Bind(&handlerIsInt);
2851         {
2852             GateRef handlerInfo = GetInt64OfTInt(*handler);
2853             BRANCH(IsNonSharedStoreField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2854             Bind(&handlerInfoIsField);
2855             {
2856                 result = StoreField(glue, receiver, value, handlerInfo, callback);
2857                 Jump(&exit);
2858             }
2859             Bind(&handlerInfoNotField);
2860             {
2861                 BRANCH(IsStoreShared(handlerInfo), &isShared, &notShared);
2862                 Bind(&isShared);
2863                 {
2864                     BRANCH(HandlerBaseIsAccessor(handlerInfo), &prepareIntHandlerLoop, &matchType);
2865                     Bind(&matchType);
2866                     {
2867                         GateRef field = GetFieldTypeFromHandler(handlerInfo);
2868                         MatchFieldType(&result, glue, field, value, &prepareIntHandlerLoop, &exit);
2869                     }
2870                     Bind(&prepareIntHandlerLoop);
2871                     {
2872                         handler = IntToTaggedPtr(ClearSharedStoreKind(handlerInfo));
2873                         Jump(&JumpLoopHead);
2874                     }
2875                 }
2876                 Bind(&notShared);
2877                 GateRef accessor = LoadFromField(*holder, handlerInfo);
2878                 result = CallSetterHelper(glue, receiver, accessor, value, callback);
2879                 Jump(&exit);
2880             }
2881         }
2882         Bind(&handlerNotInt);
2883         {
2884             BRANCH(TaggedIsTransitionHandler(*handler), &handlerIsTransitionHandler, &handlerNotTransitionHandler);
2885             Bind(&handlerIsTransitionHandler);
2886             {
2887                 result = StoreWithTransition(glue, receiver, value, *handler, callback);
2888                 Jump(&exit);
2889             }
2890             Bind(&handlerNotTransitionHandler);
2891             {
2892                 BRANCH(TaggedIsTransWithProtoHandler(*handler), &handlerIsTransWithProtoHandler,
2893                     &handlerNotTransWithProtoHandler);
2894                 Bind(&handlerIsTransWithProtoHandler);
2895                 {
2896                     GateRef cellValue = GetProtoCell(*handler);
2897                     BRANCH(GetHasChanged(cellValue), &cellHasChanged, &cellNotChanged);
2898                     Bind(&cellNotChanged);
2899                     {
2900                         result = StoreWithTransition(glue, receiver, value, *handler, callback, true);
2901                         Jump(&exit);
2902                     }
2903                 }
2904                 Bind(&handlerNotTransWithProtoHandler);
2905                 {
2906                     BRANCH(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
2907                     Bind(&handlerNotPrototypeHandler);
2908                     {
2909                         BRANCH(TaggedIsPropertyBox(*handler), &handlerIsPropertyBox, &handlerNotPropertyBox);
2910                         Bind(&handlerIsPropertyBox);
2911                         StoreGlobal(glue, value, *handler);
2912                         Jump(&exit);
2913                     }
2914                 }
2915             }
2916         }
2917         Bind(&handlerIsPrototypeHandler);
2918         {
2919             GateRef cellValue = GetProtoCell(*handler);
2920             BRANCH(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
2921             Bind(&cellNotUndefined);
2922             BRANCH(TaggedIsNull(cellValue), &cellHasChanged, &cellNotNull);
2923             Bind(&cellNotNull);
2924             {
2925                 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2926             }
2927             Bind(&loopEnd);
2928             {
2929                 holder = GetPrototypeHandlerHolder(*handler);
2930                 handler = GetPrototypeHandlerHandlerInfo(*handler);
2931                 Jump(&JumpLoopHead);
2932             }
2933         }
2934         Bind(&handlerNotPropertyBox);
2935         {
2936             BRANCH(TaggedIsStoreTSHandler(*handler), &handlerIsStoreTSHandler, &handlerNotStoreTSHandler);
2937             Bind(&handlerIsStoreTSHandler);
2938             {
2939                 GateRef cellValue = GetProtoCell(*handler);
2940                 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &aotCellNotChanged);
2941                 Bind(&aotCellNotChanged);
2942                 {
2943                     holder = GetStoreTSHandlerHolder(*handler);
2944                     handler = GetStoreTSHandlerHandlerInfo(*handler);
2945                     GateRef handlerInfo = GetInt64OfTInt(*handler);
2946                     BRANCH(IsField(handlerInfo), &aotHandlerInfoIsField, &aotHandlerInfoNotField);
2947                     Bind(&aotHandlerInfoIsField);
2948                     {
2949                         result = StoreField(glue, receiver, value, handlerInfo, callback);
2950                         Jump(&exit);
2951                     }
2952                     Bind(&aotHandlerInfoNotField);
2953                     {
2954                         GateRef accessor = LoadFromField(*holder, handlerInfo);
2955                         result = CallSetterHelper(glue, receiver, accessor, value, callback);
2956                         Jump(&exit);
2957                     }
2958                 }
2959             }
2960             Bind(&handlerNotStoreTSHandler);
2961             Jump(&exit);
2962         }
2963         Bind(&cellHasChanged);
2964         {
2965             result = Hole();
2966             Jump(&exit);
2967         }
2968         Bind(&JumpLoopHead);
2969         {
2970             LoopEnd(&loopHead, env, glue);
2971         }
2972     }
2973     Bind(&exit);
2974     auto ret = *result;
2975     env->SubCfgExit();
2976     return ret;
2977 }
2978 
StoreField(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback)2979 GateRef StubBuilder::StoreField(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
2980     ProfileOperation callback)
2981 {
2982     auto env = GetEnvironment();
2983     Label entry(env);
2984     env->SubCfgEntry(&entry);
2985     ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handler, callback);
2986     Label exit(env);
2987     Label handlerIsInlinedProperty(env);
2988     Label handlerNotInlinedProperty(env);
2989     GateRef index = HandlerBaseGetOffset(handler);
2990     GateRef rep = HandlerBaseGetRep(handler);
2991     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2992     Label repChange(env);
2993     BRANCH(HandlerBaseIsInlinedProperty(handler), &handlerIsInlinedProperty, &handlerNotInlinedProperty);
2994     Bind(&handlerIsInlinedProperty);
2995     {
2996         GateRef toOffset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
2997         SetValueWithRep(glue, receiver, toOffset, value, rep, &repChange);
2998         Jump(&exit);
2999     }
3000     Bind(&handlerNotInlinedProperty);
3001     {
3002         GateRef array = GetPropertiesArray(receiver);
3003         SetValueToTaggedArrayWithRep(glue, array, index, value, rep, &repChange);
3004         Jump(&exit);
3005     }
3006     Bind(&repChange);
3007     {
3008         result = Hole();
3009         Jump(&exit);
3010     }
3011 
3012     Bind(&exit);
3013     auto ret = *result;
3014     env->SubCfgExit();
3015     return ret;
3016 }
3017 
StoreWithTransition(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback,bool withPrototype)3018 GateRef StubBuilder::StoreWithTransition(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
3019                                          ProfileOperation callback, bool withPrototype)
3020 {
3021     auto env = GetEnvironment();
3022     Label entry(env);
3023     env->SubCfgEntry(&entry);
3024     Label exit(env);
3025 
3026     Label handlerInfoIsInlinedProps(env);
3027     Label handlerInfoNotInlinedProps(env);
3028     Label indexMoreCapacity(env);
3029     Label indexLessCapacity(env);
3030     Label capacityIsZero(env);
3031     Label capacityNotZero(env);
3032     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3033     GateRef newHClass;
3034     GateRef handlerInfo;
3035     if (withPrototype) {
3036         newHClass = GetTransWithProtoHClass(handler);
3037         handlerInfo = GetInt64OfTInt(GetTransWithProtoHandlerInfo(handler));
3038     } else {
3039         newHClass = GetTransitionHClass(handler);
3040         handlerInfo = GetInt64OfTInt(GetTransitionHandlerInfo(handler));
3041     }
3042 
3043     GateRef oldHClass = LoadHClass(receiver);
3044     GateRef prototype = GetPrototypeFromHClass(oldHClass);
3045     StorePrototype(glue, newHClass, prototype);
3046     // Because we currently only supports Fast ElementsKind
3047     GateRef oldKind = GetElementsKindFromHClass(LoadHClass(receiver));
3048     RestoreElementsKindToGeneric(glue, newHClass);
3049     StoreHClass(glue, receiver, newHClass);
3050     TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
3051     BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
3052     Bind(&handlerInfoNotInlinedProps);
3053     {
3054         ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handlerInfo, callback);
3055         Label repChange(env);
3056         GateRef array = GetPropertiesArray(receiver);
3057         GateRef capacity = GetLengthOfTaggedArray(array);
3058         GateRef index = HandlerBaseGetOffset(handlerInfo);
3059         BRANCH(Int32GreaterThanOrEqual(index, capacity), &indexMoreCapacity, &indexLessCapacity);
3060         Bind(&indexMoreCapacity);
3061         {
3062             NewObjectStubBuilder newBuilder(this);
3063             BRANCH(Int32Equal(capacity, Int32(0)), &capacityIsZero, &capacityNotZero);
3064             Bind(&capacityIsZero);
3065             {
3066                 GateRef properties = newBuilder.NewTaggedArray(glue, Int32(JSObject::MIN_PROPERTIES_LENGTH));
3067                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3068                 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3069                 Jump(&exit);
3070             }
3071             Bind(&capacityNotZero);
3072             {
3073                 GateRef inlinedProperties = GetInlinedPropertiesFromHClass(newHClass);
3074                 GateRef maxNonInlinedFastPropsCapacity =
3075                                 Int32Sub(Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY), inlinedProperties);
3076                 GateRef newLen = ComputeNonInlinedFastPropsCapacity(glue, capacity, maxNonInlinedFastPropsCapacity);
3077                 GateRef properties = newBuilder.CopyArray(glue, array, capacity, newLen);
3078                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3079                 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3080                 Jump(&exit);
3081             }
3082         }
3083         Bind(&indexLessCapacity);
3084         {
3085             GateRef rep = HandlerBaseGetRep(handlerInfo);
3086             GateRef base = PtrAdd(array, IntPtr(TaggedArray::DATA_OFFSET));
3087             GateRef toIndex = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
3088             SetValueWithRep(glue, base, toIndex, value, rep, &repChange);
3089             Jump(&exit);
3090         }
3091         Bind(&repChange);
3092         {
3093             result = Hole();
3094             Jump(&exit);
3095         }
3096     }
3097     Bind(&handlerInfoIsInlinedProps);
3098     {
3099         result = StoreField(glue, receiver, value, handlerInfo, callback);
3100         Jump(&exit);
3101     }
3102     Bind(&exit);
3103     auto ret = *result;
3104     env->SubCfgExit();
3105     return ret;
3106 }
3107 
StoreGlobal(GateRef glue,GateRef value,GateRef cell)3108 GateRef StubBuilder::StoreGlobal(GateRef glue, GateRef value, GateRef cell)
3109 {
3110     auto env = GetEnvironment();
3111     Label entry(env);
3112     env->SubCfgEntry(&entry);
3113     Label exit(env);
3114     Label cellNotInvalid(env);
3115     Label cellIsNotAccessorData(env);
3116     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3117     BRANCH(IsInvalidPropertyBox(cell), &exit, &cellNotInvalid);
3118     Bind(&cellNotInvalid);
3119     {
3120         BRANCH(IsAccessorPropertyBox(cell), &exit, &cellIsNotAccessorData);
3121         Bind(&cellIsNotAccessorData);
3122         {
3123             Store(VariableType::JS_ANY(), glue, cell, IntPtr(PropertyBox::VALUE_OFFSET), value);
3124             result = Undefined();
3125             Jump(&exit);
3126         }
3127     }
3128     Bind(&exit);
3129     auto ret = *result;
3130     env->SubCfgExit();
3131     return ret;
3132 }
3133 
3134 template<typename DictionaryT>
GetAttributesFromDictionary(GateRef elements,GateRef entry)3135 GateRef StubBuilder::GetAttributesFromDictionary(GateRef elements, GateRef entry)
3136 {
3137     GateRef arrayIndex =
3138     Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3139              Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3140     GateRef attributesIndex =
3141         Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_DETAILS_INDEX));
3142     auto attrValue = GetValueFromTaggedArray(elements, attributesIndex);
3143     return GetInt64OfTInt(attrValue);
3144 }
3145 
3146 template<typename DictionaryT>
GetValueFromDictionary(GateRef elements,GateRef entry)3147 GateRef StubBuilder::GetValueFromDictionary(GateRef elements, GateRef entry)
3148 {
3149     GateRef arrayIndex =
3150         Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3151                  Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3152     GateRef valueIndex =
3153         Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3154     return GetValueFromTaggedArray(elements, valueIndex);
3155 }
3156 
3157 template<typename DictionaryT>
GetKeyFromDictionary(GateRef elements,GateRef entry)3158 GateRef StubBuilder::GetKeyFromDictionary(GateRef elements, GateRef entry)
3159 {
3160     auto env = GetEnvironment();
3161     Label subentry(env);
3162     env->SubCfgEntry(&subentry);
3163     Label exit(env);
3164     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3165     Label ltZero(env);
3166     Label notLtZero(env);
3167     Label gtLength(env);
3168     Label notGtLength(env);
3169     GateRef dictionaryLength =
3170         Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
3171     GateRef arrayIndex =
3172         Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3173                  Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3174     BRANCH(Int32LessThan(arrayIndex, Int32(0)), &ltZero, &notLtZero);
3175     Bind(&ltZero);
3176     Jump(&exit);
3177     Bind(&notLtZero);
3178     BRANCH(Int32GreaterThan(arrayIndex, dictionaryLength), &gtLength, &notGtLength);
3179     Bind(&gtLength);
3180     Jump(&exit);
3181     Bind(&notGtLength);
3182     result = GetValueFromTaggedArray(elements, arrayIndex);
3183     Jump(&exit);
3184     Bind(&exit);
3185     auto ret = *result;
3186     env->SubCfgExit();
3187     return ret;
3188 }
3189 
UpdateValueAndAttributes(GateRef glue,GateRef elements,GateRef index,GateRef value,GateRef attr)3190 inline void StubBuilder::UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index,
3191                                                   GateRef value, GateRef attr)
3192 {
3193     GateRef arrayIndex =
3194         Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
3195                  Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
3196     GateRef valueIndex =
3197         Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
3198     GateRef attributesIndex =
3199         Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_DETAILS_INDEX));
3200     SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3201     GateRef attroffset =
3202         PtrMul(ZExtInt32ToPtr(attributesIndex), IntPtr(JSTaggedValue::TaggedTypeSize()));
3203     GateRef dataOffset = PtrAdd(attroffset, IntPtr(TaggedArray::DATA_OFFSET));
3204     Store(VariableType::INT64(), glue, elements, dataOffset, Int64ToTaggedInt(attr));
3205 }
3206 
3207 template<typename DictionaryT>
UpdateValueInDict(GateRef glue,GateRef elements,GateRef index,GateRef value)3208 inline void StubBuilder::UpdateValueInDict(GateRef glue, GateRef elements, GateRef index, GateRef value)
3209 {
3210     GateRef arrayIndex = Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3211         Int32Mul(index, Int32(DictionaryT::ENTRY_SIZE)));
3212     GateRef valueIndex = Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3213     SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3214 }
3215 
GetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,ProfileOperation callback,GateRef hir)3216 GateRef StubBuilder::GetPropertyByIndex(GateRef glue, GateRef receiver,
3217                                         GateRef index, ProfileOperation callback, GateRef hir)
3218 {
3219     auto env = GetEnvironment();
3220     Label entry(env);
3221     env->SubCfgEntry(&entry);
3222     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3223     DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
3224     Label exit(env);
3225     Label loopHead(env);
3226     Label loopEnd(env);
3227     Label loopExit(env);
3228     Label afterLoop(env);
3229     Jump(&loopHead);
3230     LoopBegin(&loopHead);
3231     {
3232         GateRef hclass = LoadHClass(*holder);
3233         GateRef jsType = GetObjectType(hclass);
3234         Label isSpecialIndexed(env);
3235         Label notSpecialIndexed(env);
3236         BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndexed, &notSpecialIndexed);
3237         Bind(&isSpecialIndexed);
3238         {
3239             // TypeArray
3240             Label isFastTypeArray(env);
3241             Label notFastTypeArray(env);
3242             Label notTypedArrayProto(env);
3243             BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, &notTypedArrayProto);
3244             Bind(&notTypedArrayProto);
3245             BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
3246             Bind(&isFastTypeArray);
3247             {
3248                 BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this);
3249                 result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, *holder, index, jsType);
3250                 Jump(&exit);
3251             }
3252             Bind(&notFastTypeArray);
3253 
3254             Label isSpecialContainer(env);
3255             Label notSpecialContainer(env);
3256             // Add SpecialContainer
3257             BRANCH(IsSpecialContainer(jsType), &isSpecialContainer, &notSpecialContainer);
3258             Bind(&isSpecialContainer);
3259             {
3260                 result = GetContainerProperty(glue, *holder, index, jsType);
3261                 Jump(&exit);
3262             }
3263             Bind(&notSpecialContainer);
3264 
3265             Label isString(env);
3266             Label notString(env);
3267             Label getSubString(env);
3268             BRANCH(TaggedIsString(*holder), &isString, &notString);
3269             Bind(&isString);
3270             {
3271                 GateRef length = GetLengthFromString(*holder);
3272                 BRANCH(Int32LessThan(index, length), &getSubString, &notString);
3273                 Bind(&getSubString);
3274                 Label flattenFastPath(env);
3275                 BuiltinsStringStubBuilder stringBuilder(this);
3276                 FlatStringStubBuilder thisFlat(this);
3277                 thisFlat.FlattenString(glue, *holder, &flattenFastPath);
3278                 Bind(&flattenFastPath);
3279                 StringInfoGateRef stringInfoGate(&thisFlat);
3280                 result = stringBuilder.FastSubString(glue, *holder, index, Int32(1), stringInfoGate);
3281                 Jump(&exit);
3282             }
3283             Bind(&notString);
3284             {
3285                 result = Hole();
3286                 Jump(&exit);
3287             }
3288         }
3289         Bind(&notSpecialIndexed);
3290         {
3291             GateRef elements = GetElementsArray(*holder);
3292             Label isDictionaryElement(env);
3293             Label notDictionaryElement(env);
3294             BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, &notDictionaryElement);
3295             Bind(&notDictionaryElement);
3296             {
3297                 Label lessThanLength(env);
3298                 Label notLessThanLength(env);
3299                 BRANCH(Int32UnsignedLessThan(index, GetLengthOfTaggedArray(elements)),
3300                        &lessThanLength, &notLessThanLength);
3301                 Bind(&lessThanLength);
3302                 {
3303                     DEFVARIABLE(value, VariableType::JS_ANY(), Hole());
3304                     Label notHole(env);
3305                     Label isHole(env);
3306                     value = GetTaggedValueWithElementsKind(*holder, index);
3307                     BRANCH(TaggedIsNotHole(*value), &notHole, &isHole);
3308                     Bind(&notHole);
3309                     {
3310                         result = *value;
3311                         Jump(&exit);
3312                     }
3313                     Bind(&isHole);
3314                     {
3315                         Jump(&loopExit);
3316                     }
3317                 }
3318                 Bind(&notLessThanLength);
3319                 {
3320                     Jump(&loopExit);
3321                 }
3322             }
3323             Bind(&isDictionaryElement);
3324             {
3325                 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
3326                 Label notNegtiveOne(env);
3327                 Label negtiveOne(env);
3328                 BRANCH(Int32NotEqual(entryA, Int32(-1)), &notNegtiveOne, &negtiveOne);
3329                 Bind(&notNegtiveOne);
3330                 {
3331                     GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
3332                     GateRef value = GetValueFromDictionary<NumberDictionary>(elements, entryA);
3333                     Label isAccessor(env);
3334                     Label notAccessor(env);
3335                     BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
3336                     Bind(&isAccessor);
3337                     {
3338                         result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
3339                         Jump(&exit);
3340                     }
3341                     Bind(&notAccessor);
3342                     {
3343                         result = value;
3344                         Jump(&exit);
3345                     }
3346                 }
3347                 Bind(&negtiveOne);
3348                 Jump(&loopExit);
3349             }
3350             Bind(&loopExit);
3351             {
3352                 holder = GetPrototypeFromHClass(LoadHClass(*holder));
3353                 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3354             }
3355         }
3356         Bind(&loopEnd);
3357         LoopEnd(&loopHead, env, glue);
3358         Bind(&afterLoop);
3359         {
3360             result = Undefined();
3361             Jump(&exit);
3362         }
3363     }
3364     Bind(&exit);
3365     auto ret = *result;
3366     env->SubCfgExit();
3367     return ret;
3368 }
3369 
GetPropertyByValue(GateRef glue,GateRef receiver,GateRef keyValue,ProfileOperation callback)3370 GateRef StubBuilder::GetPropertyByValue(GateRef glue, GateRef receiver, GateRef keyValue, ProfileOperation callback)
3371 {
3372     auto env = GetEnvironment();
3373     Label entry(env);
3374     env->SubCfgEntry(&entry);
3375     DEFVARIABLE(key, VariableType::JS_ANY(), keyValue);
3376     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3377     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
3378     Label isNumberOrStringSymbol(env);
3379     Label notNumber(env);
3380     Label isStringOrSymbol(env);
3381     Label notStringOrSymbol(env);
3382     Label exit(env);
3383 
3384     BRANCH(TaggedIsNumber(*key), &isNumberOrStringSymbol, &notNumber);
3385     Bind(&notNumber);
3386     {
3387         BRANCH(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, &notStringOrSymbol);
3388         Bind(&notStringOrSymbol);
3389         {
3390             result = Hole();
3391             Jump(&exit);
3392         }
3393     }
3394     Bind(&isNumberOrStringSymbol);
3395     {
3396         GateRef index64 = TryToElementsIndex(glue, *key);
3397         Label validIndex(env);
3398         Label notValidIndex(env);
3399         Label greaterThanInt32Max(env);
3400         Label notGreaterThanInt32Max(env);
3401         BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
3402         Bind(&greaterThanInt32Max);
3403         {
3404             Jump(&exit);
3405         }
3406         Bind(&notGreaterThanInt32Max);
3407         GateRef index = TruncInt64ToInt32(index64);
3408         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
3409         Bind(&validIndex);
3410         {
3411             result = GetPropertyByIndex(glue, receiver, index, callback);
3412             Jump(&exit);
3413         }
3414         Bind(&notValidIndex);
3415         {
3416             Label notNumber1(env);
3417             Label getByName(env);
3418             BRANCH(TaggedIsNumber(*key), &exit, &notNumber1);
3419             Bind(&notNumber1);
3420             {
3421                 Label isString(env);
3422                 Label notString(env);
3423                 Label isInternalString(env);
3424                 Label notIntenalString(env);
3425                 BRANCH(TaggedIsString(*key), &isString, &notString);
3426                 Bind(&isString);
3427                 {
3428                     BRANCH(IsInternalString(*key), &isInternalString, &notIntenalString);
3429                     Bind(&isInternalString);
3430                     Jump(&getByName);
3431                     Bind(&notIntenalString);
3432                     {
3433                         Label notFind(env);
3434                         Label find(env);
3435                         // if key can't find in stringtabele, key is not propertyname for a object
3436                         GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *key });
3437                         BRANCH(TaggedIsHole(res), &notFind, &find);
3438                         Bind(&notFind);
3439                         {
3440                             isInternal = False();
3441                             Jump(&getByName);
3442                         }
3443                         Bind(&find);
3444                         {
3445                             key = res;
3446                             Jump(&getByName);
3447                         }
3448                     }
3449                 }
3450                 Bind(&notString);
3451                 {
3452                     Jump(&getByName);
3453                 }
3454             }
3455             Bind(&getByName);
3456             {
3457                 result = GetPropertyByName(glue, receiver, *key, callback, *isInternal, true);
3458                 Jump(&exit);
3459             }
3460         }
3461     }
3462     Bind(&exit);
3463     auto ret = *result;
3464     env->SubCfgExit();
3465     return ret;
3466 }
3467 
GetPropertyByName(GateRef glue,GateRef receiver,GateRef key,ProfileOperation callback,GateRef isInternal,bool canUseIsInternal)3468 GateRef StubBuilder::GetPropertyByName(GateRef glue, GateRef receiver, GateRef key,
3469                                        ProfileOperation callback, GateRef isInternal, bool canUseIsInternal)
3470 {
3471     auto env = GetEnvironment();
3472     Label entry(env);
3473     env->SubCfgEntry(&entry);
3474     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3475     DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
3476     Label exit(env);
3477     Label loopHead(env);
3478     Label loopEnd(env);
3479     Label loopExit(env);
3480     Label afterLoop(env);
3481     Label findProperty(env);
3482     Jump(&loopHead);
3483     LoopBegin(&loopHead);
3484     {
3485         GateRef hclass = LoadHClass(*holder);
3486         GateRef jsType = GetObjectType(hclass);
3487         Label isSIndexObj(env);
3488         Label notSIndexObj(env);
3489         BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, &notSIndexObj);
3490         Bind(&isSIndexObj);
3491         {
3492             // TypeArray
3493             Label isFastTypeArray(env);
3494             Label notFastTypeArray(env);
3495             BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
3496             Bind(&isFastTypeArray);
3497             {
3498                 result = GetTypeArrayPropertyByName(glue, receiver, *holder, key, jsType);
3499                 Label isNull(env);
3500                 Label notNull(env);
3501                 BRANCH(TaggedIsNull(*result), &isNull, &notNull);
3502                 Bind(&isNull);
3503                 {
3504                     result = Hole();
3505                     Jump(&exit);
3506                 }
3507                 Bind(&notNull);
3508                 BRANCH(TaggedIsHole(*result), &notSIndexObj, &exit);
3509             }
3510             Bind(&notFastTypeArray);
3511 
3512             Label isString(env);
3513             Label notString(env);
3514             Label notJsPrimitiveRef(env);
3515             auto holderValue = *holder;
3516             BRANCH(LogicAndBuilder(env).And(TaggedIsString(holderValue)).And(TaggedIsString(key)).Done(),
3517                 &isString, &notString);
3518             Bind(&isString);
3519             {
3520                 Label getStringLength(env);
3521                 Label getStringPrototype(env);
3522                 GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
3523                                                               ConstantIndex::LENGTH_STRING_INDEX);
3524                 BRANCH(FastStringEqual(glue, key, lengthString), &getStringLength, &getStringPrototype);
3525                 Bind(&getStringLength);
3526                 {
3527                     result = IntToTaggedPtr(GetLengthFromString(*holder));
3528                     Jump(&exit);
3529                 }
3530                 Bind(&getStringPrototype);
3531                 {
3532                     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
3533                     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
3534                     GateRef stringPrototype = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
3535                                                                 GlobalEnv::STRING_PROTOTYPE_INDEX);
3536                     holder = stringPrototype;
3537                     BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3538                 }
3539             }
3540             Bind(&notString);
3541             BRANCH(IsJSPrimitiveRef(*holder), &notSIndexObj, &notJsPrimitiveRef);
3542             Bind(&notJsPrimitiveRef);  // not string prototype etc.
3543             {
3544                 result = Hole();
3545                 Jump(&exit);
3546             }
3547         }
3548         Bind(&notSIndexObj);
3549         {
3550             if (canUseIsInternal) {
3551                 BRANCH(isInternal, &findProperty, &loopExit);
3552             } else {
3553                 Jump(&findProperty);
3554             }
3555             Label isDicMode(env);
3556             Label notDicMode(env);
3557             Bind(&findProperty);
3558             BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
3559             Bind(&notDicMode);
3560             {
3561                 GateRef layOutInfo = GetLayoutFromHClass(hclass);
3562                 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
3563                 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
3564                 GateRef entryA = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
3565                 Label hasEntry(env);
3566                 Label noEntry(env);
3567                 // if branch condition : entry != -1
3568                 BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, &noEntry);
3569                 Bind(&hasEntry);
3570                 {
3571                     // PropertyAttributes attr(layoutInfo->GetAttr(entry))
3572                     GateRef attr = GetPropAttrFromLayoutInfo(layOutInfo, entryA);
3573                     GateRef value = JSObjectGetProperty(*holder, hclass, attr);
3574                     Label isAccessor(env);
3575                     Label notAccessor(env);
3576                     BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
3577                     Bind(&isAccessor);
3578                     {
3579                         result = CallGetterHelper(glue, receiver, *holder, value, callback);
3580                         Jump(&exit);
3581                     }
3582                     Bind(&notAccessor);
3583                     {
3584                         Label notHole(env);
3585                         BRANCH(TaggedIsHole(value), &noEntry, &notHole);
3586                         Bind(&notHole);
3587                         {
3588                             result = value;
3589                             Jump(&exit);
3590                         }
3591                     }
3592                 }
3593                 Bind(&noEntry);
3594                 {
3595                     Jump(&loopExit);
3596                 }
3597             }
3598             Bind(&isDicMode);
3599             {
3600                 GateRef array = GetPropertiesArray(*holder);
3601                 // int entry = dict->FindEntry(key)
3602                 GateRef entryB = FindEntryFromNameDictionary(glue, array, key);
3603                 Label notNegtiveOne(env);
3604                 Label negtiveOne(env);
3605                 // if branch condition : entry != -1
3606                 BRANCH(Int32NotEqual(entryB, Int32(-1)), &notNegtiveOne, &negtiveOne);
3607                 Bind(&notNegtiveOne);
3608                 {
3609                     // auto value = dict->GetValue(entry)
3610                     GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, entryB);
3611                     // auto attr = dict->GetAttributes(entry)
3612                     GateRef value = GetValueFromDictionary<NameDictionary>(array, entryB);
3613                     Label isAccessor1(env);
3614                     Label notAccessor1(env);
3615                     BRANCH(IsAccessor(attr), &isAccessor1, &notAccessor1);
3616                     Bind(&isAccessor1);
3617                     {
3618                         result = CallGetterHelper(glue, receiver, *holder, value, callback);
3619                         Jump(&exit);
3620                     }
3621                     Bind(&notAccessor1);
3622                     {
3623                         result = value;
3624                         Jump(&exit);
3625                     }
3626                 }
3627                 Bind(&negtiveOne);
3628                 Jump(&loopExit);
3629             }
3630             Bind(&loopExit);
3631             {
3632                 holder = GetPrototypeFromHClass(LoadHClass(*holder));
3633                 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3634             }
3635         }
3636         Bind(&loopEnd);
3637         LoopEnd(&loopHead, env, glue);
3638         Bind(&afterLoop);
3639         {
3640             result = Undefined();
3641             Jump(&exit);
3642         }
3643     }
3644     Bind(&exit);
3645     auto ret = *result;
3646     env->SubCfgExit();
3647     return ret;
3648 }
3649 
CopyAllHClass(GateRef glue,GateRef dstHClass,GateRef srcHClass)3650 void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHClass)
3651 {
3652     auto env = GetEnvironment();
3653     Label entry(env);
3654     Label isTS(env);
3655     Label isNotTS(env);
3656     env->SubCfgEntry(&entry);
3657     auto proto = GetPrototypeFromHClass(srcHClass);
3658     SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto);
3659     SetBitFieldToHClass(glue, dstHClass, GetBitFieldFromHClass(srcHClass));
3660     SetIsAllTaggedProp(glue, dstHClass, GetIsAllTaggedPropFromHClass(srcHClass));
3661     SetNumberOfPropsToHClass(glue, dstHClass, GetNumberOfPropsFromHClass(srcHClass));
3662     SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
3663     SetParentToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
3664     SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, dstHClass, Null());
3665     SetEnumCacheToHClass(VariableType::INT64(), glue, dstHClass, Null());
3666     SetLayoutToHClass(VariableType::JS_POINTER(),
3667                       glue,
3668                       dstHClass,
3669                       GetLayoutFromHClass(srcHClass),
3670                       MemoryAttribute::NeedBarrierAndAtomic());
3671     BRANCH(IsTSHClass(srcHClass), &isTS, &isNotTS);
3672     Bind(&isTS);
3673     {
3674         SetIsTS(glue, dstHClass, False());
3675         Jump(&isNotTS);
3676     }
3677     Bind(&isNotTS);
3678     env->SubCfgExit();
3679     return;
3680 }
3681 
TransitionForRepChange(GateRef glue,GateRef receiver,GateRef key,GateRef attr)3682 void StubBuilder::TransitionForRepChange(GateRef glue, GateRef receiver, GateRef key, GateRef attr)
3683 {
3684     auto env = GetEnvironment();
3685     Label subEntry(env);
3686     env->SubCfgEntry(&subEntry);
3687     GateRef hclass = LoadHClass(receiver);
3688     GateRef type = GetObjectType(hclass);
3689     GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
3690                             Int32(JSTaggedValue::TaggedTypeSize()));
3691     GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
3692     GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
3693         { IntToTaggedInt(size), IntToTaggedInt(type),
3694           IntToTaggedInt(inlineProps) });
3695     CopyAllHClass(glue, newJshclass, hclass);
3696     CallRuntime(glue, RTSTUB_ID(CopyAndUpdateObjLayout),
3697                 { hclass, newJshclass, key, Int64ToTaggedInt(attr) });
3698 #if ECMASCRIPT_ENABLE_IC
3699     NotifyHClassChanged(glue, hclass, newJshclass);
3700 #endif
3701     // Because we currently only supports Fast ElementsKind
3702     GateRef oldKind = GetElementsKindFromHClass(LoadHClass(receiver));
3703     RestoreElementsKindToGeneric(glue, newJshclass);
3704     StoreHClass(glue, receiver, newJshclass);
3705     TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
3706     env->SubCfgExit();
3707 }
3708 
TransitToElementsKind(GateRef glue,GateRef receiver,GateRef value,GateRef kind)3709 void StubBuilder::TransitToElementsKind(GateRef glue, GateRef receiver, GateRef value, GateRef kind)
3710 {
3711     auto env = GetEnvironment();
3712     Label subEntry(env);
3713     env->SubCfgEntry(&subEntry);
3714     Label exit(env);
3715 
3716     GateRef hclass = LoadHClass(receiver);
3717     GateRef elementsKind = GetElementsKindFromHClass(hclass);
3718 
3719     Label isNoneDefault(env);
3720     BRANCH(Int32Equal(elementsKind, Int32(static_cast<int32_t>(ElementsKind::GENERIC))), &exit, &isNoneDefault);
3721     Bind(&isNoneDefault);
3722     {
3723         GateRef newKind = TaggedToElementKind(value);
3724         newKind = Int32Or(newKind, kind);
3725         newKind = Int32Or(newKind, elementsKind);
3726         Label change(env);
3727         BRANCH(Int32Equal(elementsKind, newKind), &exit, &change);
3728         Bind(&change);
3729         {
3730             CallRuntime(glue, RTSTUB_ID(UpdateHClassForElementsKind), { receiver, newKind });
3731             MigrateArrayWithKind(glue, receiver, elementsKind, newKind);
3732             Jump(&exit);
3733         }
3734     }
3735 
3736     Bind(&exit);
3737     env->SubCfgExit();
3738 }
3739 
TryMigrateToGenericKindForJSObject(GateRef glue,GateRef receiver,GateRef oldKind)3740 void StubBuilder::TryMigrateToGenericKindForJSObject(GateRef glue, GateRef receiver, GateRef oldKind)
3741 {
3742     auto env = GetEnvironment();
3743     Label subEntry(env);
3744     env->SubCfgEntry(&subEntry);
3745     Label exit(env);
3746 
3747     Label isJSArray(env);
3748     BRANCH(TaggedIsJSArray(receiver), &isJSArray, &exit);
3749     Bind(&isJSArray);
3750     {
3751         Label elementsIsMutantTaggedArray(env);
3752         GateRef elements = GetElementsArray(receiver);
3753         BRANCH(IsMutantTaggedArray(elements), &elementsIsMutantTaggedArray, &exit);
3754         Bind(&elementsIsMutantTaggedArray);
3755         {
3756             MigrateArrayWithKind(glue, receiver, oldKind, Int32(static_cast<int32_t>(ElementsKind::GENERIC)));
3757             Jump(&exit);
3758         }
3759     }
3760 
3761     Bind(&exit);
3762     env->SubCfgExit();
3763 }
3764 
AddElementInternal(GateRef glue,GateRef receiver,GateRef index,GateRef value,GateRef attr)3765 GateRef StubBuilder::AddElementInternal(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef attr)
3766 {
3767     auto env = GetEnvironment();
3768     Label subEntry(env);
3769     env->SubCfgEntry(&subEntry);
3770     Label exit(env);
3771     DEFVARIABLE(kind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::NONE)));
3772     DEFVARIABLE(result, VariableType::BOOL(), False());
3773     Label isArray(env);
3774     Label notArray(env);
3775     BRANCH(IsJsArray(receiver), &isArray, &notArray);
3776     Bind(&isArray);
3777     {
3778         GateRef oldLen = GetArrayLength(receiver);
3779         Label indexGreaterOrEq(env);
3780         BRANCH(Int32GreaterThanOrEqual(index, oldLen), &indexGreaterOrEq, &notArray);
3781         Bind(&indexGreaterOrEq);
3782         {
3783             Label isArrLenWritable(env);
3784             Label notArrLenWritable(env);
3785             BRANCH(IsArrayLengthWritable(glue, receiver), &isArrLenWritable, &notArrLenWritable);
3786             Bind(&isArrLenWritable);
3787             {
3788                 SetArrayLength(glue, receiver, Int32Add(index, Int32(1)));
3789                 Label indexGreater(env);
3790                 BRANCH(Int32GreaterThan(index, oldLen), &indexGreater, &notArray);
3791                 Bind(&indexGreater);
3792                 kind = Int32(static_cast<int32_t>(ElementsKind::HOLE));
3793                 Jump(&notArray);
3794             }
3795             Bind(&notArrLenWritable);
3796             result = False();
3797             Jump(&exit);
3798         }
3799     }
3800     Bind(&notArray);
3801     {
3802         NotifyStableArrayElementsGuardians(glue, receiver);
3803         GateRef hclass = LoadHClass(receiver);
3804         GateRef elements = GetElementsArray(receiver);
3805         Label isDicMode(env);
3806         Label notDicMode(env);
3807         BRANCH(IsDictionaryElement(hclass), &isDicMode, &notDicMode);
3808         Bind(&isDicMode);
3809         {
3810             GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
3811                 { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedFalse() });
3812             SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
3813             result = True();
3814             Jump(&exit);
3815         }
3816         Bind(&notDicMode);
3817         {
3818             GateRef capacity = GetLengthOfTaggedArray(elements);
3819             GateRef notDefault = BoolNot(IsDefaultAttribute(attr));
3820             Label indexGreaterLen(env);
3821             Label notGreaterLen(env);
3822             BRANCH(BitOr(notDefault, Int32GreaterThanOrEqual(index, capacity)), &indexGreaterLen, &notGreaterLen);
3823             Bind(&indexGreaterLen);
3824             {
3825                 Label isTransToDict(env);
3826                 Label notTransToDict(env);
3827                 BRANCH(LogicOrBuilder(env).Or(notDefault).Or(ShouldTransToDict(capacity, index)).Done(),
3828                     &isTransToDict, &notTransToDict);
3829                 Bind(&isTransToDict);
3830                 {
3831                     GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
3832                         { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedTrue() });
3833                     Label isPendingException(env);
3834                     Label noPendingException(env);
3835                     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
3836                     Bind(&isPendingException);
3837                     {
3838                         result = False();
3839                         Jump(&exit);
3840                     }
3841                     Bind(&noPendingException);
3842                     SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
3843                     result = True();
3844                     Jump(&exit);
3845                 }
3846                 Bind(&notTransToDict);
3847                 {
3848                     GrowElementsCapacity(glue, receiver, Int32Add(index, Int32(1)));
3849                     SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
3850                     result = True();
3851                     Jump(&exit);
3852                 }
3853             }
3854             Bind(&notGreaterLen);
3855             {
3856                 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
3857                 result = True();
3858                 Jump(&exit);
3859             }
3860         }
3861     }
3862     Bind(&exit);
3863     auto ret = *result;
3864     env->SubCfgExit();
3865     return ret;
3866 }
3867 
GrowElementsCapacity(GateRef glue,GateRef receiver,GateRef capacity)3868 GateRef StubBuilder::GrowElementsCapacity(GateRef glue, GateRef receiver, GateRef capacity)
3869 {
3870     auto env = GetEnvironment();
3871     Label subEntry(env);
3872     env->SubCfgEntry(&subEntry);
3873     DEFVARIABLE(newElements, VariableType::JS_ANY(), Hole());
3874     NewObjectStubBuilder newBuilder(this);
3875     GateRef newCapacity = ComputeElementCapacity(capacity);
3876     GateRef elements = GetElementsArray(receiver);
3877     newElements = newBuilder.CopyArray(glue, elements, capacity, newCapacity);
3878     SetElementsArray(VariableType::JS_POINTER(), glue, receiver, *newElements);
3879     auto ret = *newElements;
3880     env->SubCfgExit();
3881     return ret;
3882 }
3883 
ShouldTransToDict(GateRef capacity,GateRef index)3884 GateRef StubBuilder::ShouldTransToDict(GateRef capacity, GateRef index)
3885 {
3886     auto env = GetEnvironment();
3887     Label subEntry(env);
3888     env->SubCfgEntry(&subEntry);
3889     Label exit(env);
3890     DEFVARIABLE(result, VariableType::BOOL(), True());
3891     Label isGreaterThanCapcity(env);
3892     Label notGreaterThanCapcity(env);
3893     BRANCH(Int32GreaterThanOrEqual(index, capacity), &isGreaterThanCapcity, &notGreaterThanCapcity);
3894     Bind(&isGreaterThanCapcity);
3895     {
3896         Label isLessThanMax(env);
3897         Label notLessThanMax(env);
3898         BRANCH(Int32LessThanOrEqual(Int32Sub(index, capacity),
3899             Int32(JSObject::MAX_GAP)), &isLessThanMax, &notLessThanMax);
3900         Bind(&isLessThanMax);
3901         {
3902             Label isLessThanInt32Max(env);
3903             Label notLessThanInt32Max(env);
3904             BRANCH(Int32LessThan(index, Int32(INT32_MAX)), &isLessThanInt32Max, &notLessThanInt32Max);
3905             Bind(&isLessThanInt32Max);
3906             {
3907                 Label isLessThanMin(env);
3908                 Label notLessThanMin(env);
3909                 BRANCH(Int32LessThan(capacity, Int32(JSObject::MIN_GAP)), &isLessThanMin, &notLessThanMin);
3910                 Bind(&isLessThanMin);
3911                 {
3912                     result = False();
3913                     Jump(&exit);
3914                 }
3915                 Bind(&notLessThanMin);
3916                 {
3917                     result = Int32GreaterThan(index, Int32Mul(capacity, Int32(JSObject::FAST_ELEMENTS_FACTOR)));
3918                     Jump(&exit);
3919                 }
3920             }
3921             Bind(&notLessThanInt32Max);
3922             {
3923                 result = True();
3924                 Jump(&exit);
3925             }
3926         }
3927         Bind(&notLessThanMax);
3928         {
3929             result = True();
3930             Jump(&exit);
3931         }
3932     }
3933     Bind(&notGreaterThanCapcity);
3934     {
3935         result = False();
3936         Jump(&exit);
3937     }
3938     Bind(&exit);
3939     auto ret = *result;
3940     env->SubCfgExit();
3941     return ret;
3942 }
3943 
NotifyStableArrayElementsGuardians(GateRef glue,GateRef receiver)3944 void StubBuilder::NotifyStableArrayElementsGuardians(GateRef glue, GateRef receiver)
3945 {
3946     auto env = GetEnvironment();
3947     Label subEntry(env);
3948     env->SubCfgEntry(&subEntry);
3949     Label exit(env);
3950     GateRef guardiansOffset =
3951                 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
3952     GateRef guardians = Load(VariableType::BOOL(), glue, guardiansOffset);
3953     Label isGuardians(env);
3954     BRANCH(Equal(guardians, True()), &isGuardians, &exit);
3955     Bind(&isGuardians);
3956     {
3957         GateRef hclass = LoadHClass(receiver);
3958         Label isProtoType(env);
3959         BRANCH(BitOr(IsProtoTypeHClass(hclass), IsJsArray(receiver)), &isProtoType, &exit);
3960         Bind(&isProtoType);
3961         {
3962             Label isEnvProtoType(env);
3963             GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
3964             GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
3965             GateRef isEnvProtoTypeCheck = LogicOrBuilder(env)
3966                 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
3967                     GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX), receiver))
3968                 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
3969                     GlobalEnv::ARRAY_PROTOTYPE_INDEX), receiver))
3970                 .Done();
3971             BRANCH(isEnvProtoTypeCheck, &isEnvProtoType, &exit);
3972             Bind(&isEnvProtoType);
3973             Store(VariableType::BOOL(), glue, glue, guardiansOffset, False());
3974             Jump(&exit);
3975         }
3976     }
3977     Bind(&exit);
3978     env->SubCfgExit();
3979     return;
3980 }
3981 
IsArrayLengthWritable(GateRef glue,GateRef receiver)3982 GateRef StubBuilder::IsArrayLengthWritable(GateRef glue, GateRef receiver)
3983 {
3984     auto env = GetEnvironment();
3985     Label subEntry(env);
3986     env->SubCfgEntry(&subEntry);
3987     Label exit(env);
3988     GateRef hclass = LoadHClass(receiver);
3989     Label isDicMode(env);
3990     Label notDicMode(env);
3991     DEFVARIABLE(result, VariableType::BOOL(), False());
3992     BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
3993     Bind(&isDicMode);
3994     {
3995         GateRef array = GetPropertiesArray(receiver);
3996         GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
3997                                                       ConstantIndex::LENGTH_STRING_INDEX);
3998         GateRef entry = FindEntryFromNameDictionary(glue, array, lengthString);
3999         Label notNegtiveOne(env);
4000         Label isNegtiveOne(env);
4001         BRANCH(Int32NotEqual(entry, Int32(-1)), &notNegtiveOne, &isNegtiveOne);
4002         Bind(&notNegtiveOne);
4003         {
4004             GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, entry);
4005             result = IsWritable(attr);
4006             Jump(&exit);
4007         }
4008         Bind(&isNegtiveOne);
4009         {
4010             GateRef attr1 = Int64(PropertyAttributes::GetDefaultAttributes());
4011             result = IsWritable(attr1);
4012             Jump(&exit);
4013         }
4014     }
4015     Bind(&notDicMode);
4016     {
4017         GateRef layoutInfo = GetLayoutFromHClass(hclass);
4018         GateRef attr = GetPropAttrFromLayoutInfo(layoutInfo, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4019         result = IsWritable(attr);
4020         Jump(&exit);
4021     }
4022     Bind(&exit);
4023     auto ret = *result;
4024     env->SubCfgExit();
4025     return ret;
4026 }
4027 
CheckHClassForRep(GateRef hclass,GateRef value)4028 GateRef StubBuilder::CheckHClassForRep(GateRef hclass, GateRef value)
4029 {
4030     auto env = GetEnvironment();
4031     Label subEntry(env);
4032     env->SubCfgEntry(&subEntry);
4033     Label exit(env);
4034     Label isTSHClass(env);
4035     DEFVARIABLE(result, VariableType::BOOL(), Boolean(true));
4036     Branch(IsTSHClass(hclass), &isTSHClass, &exit);
4037     Bind(&isTSHClass);
4038     {
4039         GateRef propNums = GetNumberOfPropsFromHClass(hclass);
4040         GateRef last = Int32Sub(propNums, Int32(1));
4041         GateRef layoutInfo = GetLayoutFromHClass(hclass);
4042         GateRef cachedAttr = GetPropAttrFromLayoutInfo(layoutInfo, last);
4043         GateRef lastRep = GetRepInPropAttr(cachedAttr);
4044         Label repIsInt(env);
4045         Label repIsNotInt(env);
4046         Label repIsDouble(env);
4047         Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::INT))), &repIsInt, &repIsNotInt);
4048         Bind(&repIsInt);
4049         {
4050             GateRef valueRep = TranslateToRep(value);
4051             Label valueRepIsNotInt(env);
4052             Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4053             Bind(&valueRepIsNotInt);
4054             {
4055                 result = Boolean(false);
4056                 Jump(&exit);
4057             }
4058         }
4059         Bind(&repIsNotInt);
4060         {
4061             Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &repIsDouble, &exit);
4062             Bind(&repIsDouble);
4063             GateRef valueRep = TranslateToRep(value);
4064             Label valueRepIsNotInt(env);
4065             Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4066             Bind(&valueRepIsNotInt);
4067             {
4068                 Label valueRepIsNotDouble(env);
4069                 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &exit,
4070                     &valueRepIsNotDouble);
4071                 Bind(&valueRepIsNotDouble);
4072                 {
4073                     result = Boolean(false);
4074                     Jump(&exit);
4075                 }
4076             }
4077         }
4078     }
4079     Bind(&exit);
4080     auto ret = *result;
4081     env->SubCfgExit();
4082     return ret;
4083 }
4084 
FindTransitions(GateRef glue,GateRef hclass,GateRef key,GateRef metaData,GateRef value)4085 GateRef StubBuilder::FindTransitions(GateRef glue, GateRef hclass, GateRef key, GateRef metaData, GateRef value)
4086 {
4087     auto env = GetEnvironment();
4088     Label entry(env);
4089     env->SubCfgEntry(&entry);
4090     Label exit(env);
4091     GateRef transitionOffset = IntPtr(JSHClass::TRANSTIONS_OFFSET);
4092     GateRef transition = Load(VariableType::JS_POINTER(), hclass, transitionOffset);
4093     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
4094 
4095     Label notUndefined(env);
4096     BRANCH(Equal(transition, Undefined()), &exit, &notUndefined);
4097     Bind(&notUndefined);
4098     {
4099         Label isWeak(env);
4100         Label notWeak(env);
4101         BRANCH(TaggedIsWeak(transition), &isWeak, &notWeak);
4102         Bind(&isWeak);
4103         {
4104             GateRef transitionHClass = LoadObjectFromWeakRef(transition);
4105             GateRef propNums = GetNumberOfPropsFromHClass(transitionHClass);
4106             GateRef last = Int32Sub(propNums, Int32(1));
4107             GateRef layoutInfo = GetLayoutFromHClass(transitionHClass);
4108             GateRef cachedKey = GetKeyFromLayoutInfo(layoutInfo, last);
4109             GateRef cachedAttr = GetPropAttrFromLayoutInfo(layoutInfo, last);
4110             GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
4111             Label keyMatch(env);
4112             Label isMatch(env);
4113             Label repMatch(env);
4114             BRANCH(Equal(cachedKey, key), &keyMatch, &exit);
4115             Bind(&keyMatch);
4116             {
4117                 BRANCH(Int32Equal(metaData, cachedMetaData), &isMatch, &exit);
4118                 Bind(&isMatch);
4119                 {
4120                     BRANCH(CheckHClassForRep(transitionHClass, value), &repMatch, &exit);
4121                     Bind(&repMatch);
4122                     result = transitionHClass;
4123                     Jump(&exit);
4124                 }
4125             }
4126         }
4127         Bind(&notWeak);
4128         {
4129             // need to find from dictionary
4130             GateRef entryA = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
4131             Label isFound(env);
4132             BRANCH(Int32NotEqual(entryA, Int32(-1)), &isFound, &exit);
4133             Bind(&isFound);
4134             auto cachedValue = GetValueFromDictionary<TransitionsDictionary>(transition, entryA);
4135             Label valueNotUndefined(env);
4136             Label repMatch(env);
4137             BRANCH(Int64NotEqual(cachedValue, Undefined()), &valueNotUndefined, &exit);
4138             Bind(&valueNotUndefined);
4139             {
4140                 GateRef newHClass = LoadObjectFromWeakRef(cachedValue);
4141                 BRANCH(CheckHClassForRep(newHClass, value), &repMatch, &exit);
4142                 Bind(&repMatch);
4143                 result = newHClass;
4144                 Jump(&exit);
4145             }
4146         }
4147     }
4148     Bind(&exit);
4149     auto ret = *result;
4150     env->SubCfgExit();
4151     return ret;
4152 }
4153 
SetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics)4154 GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn,
4155     ProfileOperation callback, bool defineSemantics)
4156 {
4157     auto env = GetEnvironment();
4158     Label entry(env);
4159     env->SubCfgEntry(&entry);
4160     DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
4161     DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
4162     Label exit(env);
4163     Label ifEnd(env);
4164     Label loopHead(env);
4165     Label loopEnd(env);
4166     Label loopExit(env);
4167     Label afterLoop(env);
4168     Label isJsCOWArray(env);
4169     Label isNotJsCOWArray(env);
4170     Label setElementsArray(env);
4171     if (!useOwn && !defineSemantics) {
4172         Jump(&loopHead);
4173         LoopBegin(&loopHead);
4174     }
4175     GateRef hclass = LoadHClass(*holder);
4176     GateRef jsType = GetObjectType(hclass);
4177     Label isSpecialIndex(env);
4178     Label notSpecialIndex(env);
4179     BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, &notSpecialIndex);
4180     Bind(&isSpecialIndex);
4181     {
4182         // TypeArray
4183         Label isFastTypeArray(env);
4184         Label notFastTypeArray(env);
4185         Label checkIsOnPrototypeChain(env);
4186         Label notTypedArrayProto(env);
4187         BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, &notTypedArrayProto);
4188         Bind(&notTypedArrayProto);
4189         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
4190         Bind(&isFastTypeArray);
4191         {
4192             BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
4193             Bind(&checkIsOnPrototypeChain);
4194             {
4195                 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
4196                     { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
4197                 Jump(&exit);
4198             }
4199         }
4200         Bind(&notFastTypeArray);
4201         returnValue = Hole();
4202         Jump(&exit);
4203     }
4204     Bind(&notSpecialIndex);
4205     {
4206         GateRef elements = GetElementsArray(*holder);
4207         Label isDictionaryElement(env);
4208         Label notDictionaryElement(env);
4209         BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, &notDictionaryElement);
4210         Bind(&notDictionaryElement);
4211         {
4212             Label isReceiver(env);
4213             if (useOwn) {
4214                 BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
4215             } else {
4216                 BRANCH(Equal(*holder, receiver), &isReceiver, &afterLoop);
4217             }
4218             Bind(&isReceiver);
4219             {
4220                 GateRef length = GetLengthOfTaggedArray(elements);
4221                 Label inRange(env);
4222                 if (useOwn) {
4223                     BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
4224                 } else {
4225                     BRANCH(Int64LessThan(index, length), &inRange, &loopExit);
4226                 }
4227                 Bind(&inRange);
4228                 {
4229                     GateRef value1 = GetTaggedValueWithElementsKind(*holder, index);
4230                     Label notHole(env);
4231                     if (useOwn) {
4232                         BRANCH(Int64NotEqual(value1, Hole()), &notHole, &ifEnd);
4233                     } else {
4234                         BRANCH(Int64NotEqual(value1, Hole()), &notHole, &loopExit);
4235                     }
4236                     Bind(&notHole);
4237                     {
4238                         BRANCH(IsJsCOWArray(*holder), &isJsCOWArray, &isNotJsCOWArray);
4239                         Bind(&isJsCOWArray);
4240                         {
4241                             CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
4242                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4243                                                      Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4244                             returnValue = Undefined();
4245                             Jump(&exit);
4246                         }
4247                         Bind(&isNotJsCOWArray);
4248                         {
4249                             Jump(&setElementsArray);
4250                         }
4251                         Bind(&setElementsArray);
4252                         {
4253                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4254                                                      Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4255                             returnValue = Undefined();
4256                             Jump(&exit);
4257                         }
4258                     }
4259                 }
4260             }
4261         }
4262         Bind(&isDictionaryElement);
4263         {
4264             GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
4265             Label negtiveOne(env);
4266             Label notNegtiveOne(env);
4267             BRANCH(Int32NotEqual(entryA, Int32(-1)), &notNegtiveOne, &negtiveOne);
4268             Bind(&notNegtiveOne);
4269             {
4270                 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
4271                 Label isWritandConfig(env);
4272                 Label notWritandConfig(env);
4273                 BRANCH(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
4274                     &isWritandConfig, &notWritandConfig);
4275                 Bind(&isWritandConfig);
4276                 {
4277                     Label isAccessor(env);
4278                     Label notAccessor(env);
4279                     BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
4280                     Bind(&isAccessor);
4281                     if (defineSemantics) {
4282                         Jump(&exit);
4283                     } else {
4284                         GateRef accessor = GetValueFromDictionary<NumberDictionary>(elements, entryA);
4285                         Label shouldCall(env);
4286                         BRANCH(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, &notAccessor);
4287                         Bind(&shouldCall);
4288                         {
4289                             returnValue = CallSetterHelper(glue, receiver, accessor, value, callback);
4290                             Jump(&exit);
4291                         }
4292                     }
4293                     Bind(&notAccessor);
4294                     {
4295                         Label holdEqualsRecv(env);
4296                         if (useOwn) {
4297                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4298                         } else {
4299                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
4300                         }
4301                         Bind(&holdEqualsRecv);
4302                         {
4303                             UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
4304                             returnValue = Undefined();
4305                             Jump(&exit);
4306                         }
4307                     }
4308                 }
4309                 Bind(&notWritandConfig);
4310                 {
4311                     returnValue = Hole();
4312                     Jump(&exit);
4313                 }
4314             }
4315             Bind(&negtiveOne);
4316             returnValue = Hole();
4317             Jump(&exit);
4318         }
4319     }
4320     if (useOwn) {
4321         Bind(&ifEnd);
4322     } else {
4323         Bind(&loopExit);
4324         {
4325             holder = GetPrototypeFromHClass(LoadHClass(*holder));
4326             BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4327         }
4328         Bind(&loopEnd);
4329         LoopEnd(&loopHead, env, glue);
4330         Bind(&afterLoop);
4331     }
4332     Label isExtensible(env);
4333     Label notExtensible(env);
4334     Label throwNotExtensible(env);
4335     BRANCH(IsExtensible(receiver), &isExtensible, &notExtensible);
4336     Bind(&notExtensible);
4337     {
4338         // fixme(hzzhouzebin) this makes SharedArray's frozen no sense.
4339         BRANCH(IsJsSArray(receiver), &isExtensible, &throwNotExtensible);
4340     }
4341     Bind(&isExtensible);
4342     {
4343         Label success(env);
4344         Label failed(env);
4345         BRANCH(AddElementInternal(glue, receiver, index, value,
4346             Int64(PropertyAttributes::GetDefaultAttributes())), &success, &failed);
4347         Bind(&success);
4348         {
4349             returnValue = Undefined();
4350             Jump(&exit);
4351         }
4352         Bind(&failed);
4353         {
4354             returnValue = Exception();
4355             Jump(&exit);
4356         }
4357     }
4358     Bind(&throwNotExtensible);
4359     {
4360         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
4361         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4362         returnValue = Exception();
4363         Jump(&exit);
4364     }
4365     Bind(&exit);
4366     auto ret = *returnValue;
4367     env->SubCfgExit();
4368     return ret;
4369 }
4370 
DefinePropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)4371 GateRef StubBuilder::DefinePropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
4372 {
4373     auto env = GetEnvironment();
4374     Label entry(env);
4375     env->SubCfgEntry(&entry);
4376     DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
4377     DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
4378     Label exit(env);
4379     Label ifEnd(env);
4380     Label loopHead(env);
4381     Label loopEnd(env);
4382     Label loopExit(env);
4383     Label afterLoop(env);
4384     Label isJsCOWArray(env);
4385     Label isNotJsCOWArray(env);
4386     Label setElementsArray(env);
4387     GateRef hclass = LoadHClass(*holder);
4388     GateRef jsType = GetObjectType(hclass);
4389     Label isSpecialIndex(env);
4390     Label notSpecialIndex(env);
4391     BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, &notSpecialIndex);
4392     Bind(&isSpecialIndex);
4393     {
4394         Label isFastTypeArray(env);
4395         Label notFastTypeArray(env);
4396         Label checkIsOnPrototypeChain(env);
4397         Label notTypedArrayProto(env);
4398         BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, &notTypedArrayProto);
4399         Bind(&notTypedArrayProto);
4400         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
4401         Bind(&isFastTypeArray);
4402         {
4403             BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
4404             Bind(&checkIsOnPrototypeChain);
4405             {
4406                 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
4407                     { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
4408                 Jump(&exit);
4409             }
4410         }
4411         Bind(&notFastTypeArray);
4412         returnValue = Hole();
4413         Jump(&exit);
4414     }
4415     Bind(&notSpecialIndex);
4416     {
4417         GateRef elements = GetElementsArray(*holder);
4418         Label isDictionaryElement(env);
4419         Label notDictionaryElement(env);
4420         BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, &notDictionaryElement);
4421         Bind(&notDictionaryElement);
4422         {
4423             Label isReceiver(env);
4424             BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
4425             Bind(&isReceiver);
4426             {
4427                 GateRef length = GetLengthOfTaggedArray(elements);
4428                 Label inRange(env);
4429                 BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
4430                 Bind(&inRange);
4431                 {
4432                     GateRef value1 = GetTaggedValueWithElementsKind(*holder, index);
4433                     Label notHole(env);
4434                     BRANCH(Int64NotEqual(value1, Hole()), &notHole, &ifEnd);
4435                     Bind(&notHole);
4436                     {
4437                         BRANCH(IsJsCOWArray(*holder), &isJsCOWArray, &isNotJsCOWArray);
4438                         Bind(&isJsCOWArray);
4439                         {
4440                             CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
4441                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4442                                                      Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4443                             returnValue = Undefined();
4444                             Jump(&exit);
4445                         }
4446                         Bind(&isNotJsCOWArray);
4447                         {
4448                             Jump(&setElementsArray);
4449                         }
4450                         Bind(&setElementsArray);
4451                         {
4452                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4453                                                      Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4454                             returnValue = Undefined();
4455                             Jump(&exit);
4456                         }
4457                     }
4458                 }
4459             }
4460         }
4461         Bind(&isDictionaryElement);
4462         {
4463             GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
4464             Label negtiveOne(env);
4465             Label notNegtiveOne(env);
4466             BRANCH(Int32NotEqual(entryA, Int32(-1)), &notNegtiveOne, &negtiveOne);
4467             Bind(&notNegtiveOne);
4468             {
4469                 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
4470                 Label isWritandConfig(env);
4471                 Label notWritandConfig(env);
4472                 BRANCH(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
4473                     &isWritandConfig, &notWritandConfig);
4474                 Bind(&isWritandConfig);
4475                 {
4476                     Label notAccessor(env);
4477                     BRANCH(IsAccessor(attr), &exit, &notAccessor);
4478                     Bind(&notAccessor);
4479                     {
4480                         Label holdEqualsRecv(env);
4481                         BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4482                         Bind(&holdEqualsRecv);
4483                         {
4484                             UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
4485                             returnValue = Undefined();
4486                             Jump(&exit);
4487                         }
4488                     }
4489                 }
4490                 Bind(&notWritandConfig);
4491                 {
4492                     returnValue = Hole();
4493                     Jump(&exit);
4494                 }
4495             }
4496             Bind(&negtiveOne);
4497             returnValue = Hole();
4498             Jump(&exit);
4499         }
4500     }
4501     Bind(&ifEnd);
4502     Label isExtensible(env);
4503     Label notExtensible(env);
4504     Label throwNotExtensible(env);
4505     BRANCH(IsExtensible(receiver), &isExtensible, &notExtensible);
4506     Bind(&notExtensible);
4507     {
4508         BRANCH(IsJsSArray(receiver), &isExtensible, &throwNotExtensible);
4509     }
4510     Bind(&isExtensible);
4511     {
4512         Label success(env);
4513         Label failed(env);
4514         BRANCH(AddElementInternal(glue, receiver, index, value, Int64(PropertyAttributes::GetDefaultAttributes())),
4515                &success, &failed);
4516         Bind(&success);
4517         {
4518             returnValue = Undefined();
4519             Jump(&exit);
4520         }
4521         Bind(&failed);
4522         {
4523             returnValue = Exception();
4524             Jump(&exit);
4525         }
4526     }
4527     Bind(&throwNotExtensible);
4528     {
4529         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
4530         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4531         returnValue = Exception();
4532         Jump(&exit);
4533     }
4534     Bind(&exit);
4535     auto ret = *returnValue;
4536     env->SubCfgExit();
4537     return ret;
4538 }
4539 
SetPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,GateRef isInternal,ProfileOperation callback,bool canUseIsInternal,bool defineSemantics)4540 GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
4541     bool useOwn, GateRef isInternal, ProfileOperation callback, bool canUseIsInternal, bool defineSemantics)
4542 {
4543     auto env = GetEnvironment();
4544     Label entryPass(env);
4545     env->SubCfgEntry(&entryPass);
4546     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4547     DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
4548     DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
4549     Label exit(env);
4550     Label ifEnd(env);
4551     Label loopHead(env);
4552     Label loopEnd(env);
4553     Label loopExit(env);
4554     Label afterLoop(env);
4555     Label findProperty(env);
4556     if (!useOwn) {
4557         Jump(&loopHead);
4558         LoopBegin(&loopHead);
4559     }
4560     GateRef hclass = LoadHClass(*holder);
4561     GateRef jsType = GetObjectType(hclass);
4562     Label isSIndexObj(env);
4563     Label notSIndexObj(env);
4564     BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, &notSIndexObj);
4565     Bind(&isSIndexObj);
4566     {
4567         Label isFastTypeArray(env);
4568         Label notFastTypeArray(env);
4569         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
4570         Bind(&isFastTypeArray);
4571         {
4572             result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
4573             Label isNull(env);
4574             Label notNull(env);
4575             BRANCH(TaggedIsNull(*result), &isNull, &notNull);
4576             Bind(&isNull);
4577             {
4578                 result = Hole();
4579                 Jump(&exit);
4580             }
4581             Bind(&notNull);
4582             BRANCH(TaggedIsHole(*result), &notSIndexObj, &exit);
4583         }
4584         Bind(&notFastTypeArray);
4585 
4586         Label isSpecialContainer(env);
4587         Label notSpecialContainer(env);
4588         BRANCH(IsSpecialContainer(jsType), &isSpecialContainer, &notSpecialContainer);
4589         Bind(&isSpecialContainer);
4590         {
4591             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
4592             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4593             result = Exception();
4594             Jump(&exit);
4595         }
4596         Bind(&notSpecialContainer);
4597         {
4598             result = Hole();
4599             Jump(&exit);
4600         }
4601     }
4602     Bind(&notSIndexObj);
4603     {
4604         if (canUseIsInternal) {
4605             if (useOwn) {
4606                 BRANCH(isInternal, &findProperty, &ifEnd);
4607             } else {
4608                 BRANCH(isInternal, &findProperty, &loopExit);
4609             }
4610         } else {
4611             Jump(&findProperty);
4612         }
4613         Label isDicMode(env);
4614         Label notDicMode(env);
4615         Bind(&findProperty);
4616         BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
4617         Bind(&notDicMode);
4618         {
4619             GateRef layOutInfo = GetLayoutFromHClass(hclass);
4620             GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4621             GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
4622             Label hasEntry(env);
4623             if (useOwn || defineSemantics) {
4624                 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
4625             } else {
4626                 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &loopExit);
4627             }
4628             Bind(&hasEntry);
4629             {
4630                 GateRef attr = GetPropAttrFromLayoutInfo(layOutInfo, entry);
4631                 Label isAccessor(env);
4632                 Label notAccessor(env);
4633                 BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
4634                 Bind(&isAccessor);
4635                 if (defineSemantics) {
4636                     Jump(&exit);
4637                 } else {
4638                     GateRef accessor = JSObjectGetProperty(*holder, hclass, attr);
4639                     Label shouldCall(env);
4640                     BRANCH(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, &notAccessor);
4641                     Bind(&shouldCall);
4642                     {
4643                         result = CallSetterHelper(glue, receiver, accessor, value, callback);
4644                         Jump(&exit);
4645                     }
4646                 }
4647                 Bind(&notAccessor);
4648                 {
4649                     Label writable(env);
4650                     Label notWritable(env);
4651                     BRANCH(IsWritable(attr), &writable, &notWritable);
4652                     Bind(&notWritable);
4653                     if (defineSemantics) {
4654                         Jump(&exit);
4655                     } else {
4656                         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
4657                         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4658                         result = Exception();
4659                         Jump(&exit);
4660                     }
4661                     Bind(&writable);
4662                     {
4663                         Label isTS(env);
4664                         Label notTS(env);
4665                         BRANCH(IsTSHClass(hclass), &isTS, &notTS);
4666                         Bind(&isTS);
4667                         {
4668                             GateRef attrVal = JSObjectGetProperty(*holder, hclass, attr);
4669                             Label attrValIsHole(env);
4670                             BRANCH(TaggedIsHole(attrVal), &attrValIsHole, &notTS);
4671                             Bind(&attrValIsHole);
4672                             {
4673                                 Label storeReceiverHoleEntry(env);
4674                                 Label noNeedStore(env);
4675                                 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
4676                                 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
4677                                 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
4678                                     &storeReceiverHoleEntry, &noNeedStore);
4679                                 Bind(&storeReceiverHoleEntry);
4680                                 {
4681                                     receiverHoleEntry = entry;
4682                                     Jump(&noNeedStore);
4683                                 }
4684                                 Bind(&noNeedStore);
4685                                 if (useOwn || defineSemantics) {
4686                                     Jump(&ifEnd);
4687                                 } else {
4688                                     Jump(&loopExit);
4689                                 }
4690                             }
4691                         }
4692                         Bind(&notTS);
4693                         Label holdEqualsRecv(env);
4694                         if (useOwn || defineSemantics) {
4695                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4696                         } else {
4697                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
4698                         }
4699                         Bind(&holdEqualsRecv);
4700                         {
4701                             Label executeSetProp(env);
4702                             CheckUpdateSharedType(false, &result, glue, receiver, attr, value, &executeSetProp, &exit);
4703                             Bind(&executeSetProp);
4704                             JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
4705                             ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value, callback);
4706                             result = Undefined();
4707                             Jump(&exit);
4708                         }
4709                     }
4710                 }
4711             }
4712         }
4713         Bind(&isDicMode);
4714         {
4715             GateRef array = GetPropertiesArray(*holder);
4716             GateRef entry1 = FindEntryFromNameDictionary(glue, array, key);
4717             Label notNegtiveOne(env);
4718             if (useOwn || defineSemantics) {
4719                 BRANCH(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &ifEnd);
4720             } else {
4721                 BRANCH(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &loopExit);
4722             }
4723             Bind(&notNegtiveOne);
4724             {
4725                 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(array, entry1);
4726                 Label isAccessor1(env);
4727                 Label notAccessor1(env);
4728                 BRANCH(IsAccessor(attr1), &isAccessor1, &notAccessor1);
4729                 Bind(&isAccessor1);
4730                 if (defineSemantics) {
4731                     Jump(&exit);
4732                 } else {
4733                     GateRef accessor1 = GetValueFromDictionary<NameDictionary>(array, entry1);
4734                     Label shouldCall1(env);
4735                     BRANCH(ShouldCallSetter(receiver, *holder, accessor1, attr1), &shouldCall1, &notAccessor1);
4736                     Bind(&shouldCall1);
4737                     {
4738                         result = CallSetterHelper(glue, receiver, accessor1, value, callback);
4739                         Jump(&exit);
4740                     }
4741                 }
4742                 Bind(&notAccessor1);
4743                 {
4744                     Label writable1(env);
4745                     Label notWritable1(env);
4746                     BRANCH(IsWritable(attr1), &writable1, &notWritable1);
4747                     Bind(&notWritable1);
4748                     if (defineSemantics) {
4749                         Jump(&exit);
4750                     } else {
4751                         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
4752                         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4753                         result = Exception();
4754                         Jump(&exit);
4755                     }
4756                     Bind(&writable1);
4757                     {
4758                         Label holdEqualsRecv1(env);
4759                         if (useOwn) {
4760                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
4761                         } else {
4762                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &afterLoop);
4763                         }
4764                         Bind(&holdEqualsRecv1);
4765                         {
4766                             Label executeSetProp(env);
4767                             CheckUpdateSharedType(true, &result, glue, receiver, attr1, value, &executeSetProp, &exit);
4768                             Bind(&executeSetProp);
4769                             UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
4770                             result = Undefined();
4771                             Jump(&exit);
4772                         }
4773                     }
4774                 }
4775             }
4776         }
4777     }
4778     if (useOwn || defineSemantics) {
4779         Bind(&ifEnd);
4780     } else {
4781         Bind(&loopExit);
4782         {
4783             holder = GetPrototypeFromHClass(LoadHClass(*holder));
4784             BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4785         }
4786         Bind(&loopEnd);
4787         LoopEnd(&loopHead, env, glue);
4788         Bind(&afterLoop);
4789     }
4790     Label holeEntryNotNegtiveOne(env);
4791     Label holeEntryIfEnd(env);
4792     BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
4793     Bind(&holeEntryNotNegtiveOne);
4794     {
4795         GateRef receiverHClass = LoadHClass(receiver);
4796         GateRef receiverLayoutInfo = GetLayoutFromHClass(receiverHClass);
4797         GateRef holeAttr = GetPropAttrFromLayoutInfo(receiverLayoutInfo, *receiverHoleEntry);
4798         JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
4799         ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
4800         result = Undefined();
4801         Jump(&exit);
4802     }
4803     Bind(&holeEntryIfEnd);
4804 
4805     Label extensible(env);
4806     Label inextensible(env);
4807     BRANCH(IsExtensible(receiver), &extensible, &inextensible);
4808     Bind(&inextensible);
4809     {
4810         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
4811         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4812         result = Exception();
4813         Jump(&exit);
4814     }
4815     Bind(&extensible);
4816     {
4817         result = AddPropertyByName(glue, receiver, key, value,
4818             Int64(PropertyAttributes::GetDefaultAttributes()), callback);
4819         Jump(&exit);
4820     }
4821     Bind(&exit);
4822     auto ret = *result;
4823     env->SubCfgExit();
4824     return ret;
4825 }
4826 
DefinePropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef isInternal,GateRef SCheckModelIsCHECK,ProfileOperation callback)4827 GateRef StubBuilder::DefinePropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
4828     GateRef isInternal, GateRef SCheckModelIsCHECK, ProfileOperation callback)
4829 {
4830     auto env = GetEnvironment();
4831     Label entryPass(env);
4832     env->SubCfgEntry(&entryPass);
4833     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4834     DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
4835     DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
4836     Label exit(env);
4837     Label ifEnd(env);
4838     Label loopHead(env);
4839     Label loopEnd(env);
4840     Label loopExit(env);
4841     Label afterLoop(env);
4842     Label findProperty(env);
4843 
4844     GateRef hclass = LoadHClass(*holder);
4845     GateRef jsType = GetObjectType(hclass);
4846     Label isSIndexObj(env);
4847     Label notSIndexObj(env);
4848     BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, &notSIndexObj);
4849     Bind(&isSIndexObj);
4850     {
4851         Label isFastTypeArray(env);
4852         Label notFastTypeArray(env);
4853         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
4854         Bind(&isFastTypeArray);
4855         {
4856             result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
4857             Label isNull(env);
4858             Label notNull(env);
4859             BRANCH(TaggedIsNull(*result), &isNull, &notNull);
4860             Bind(&isNull);
4861             {
4862                 result = Hole();
4863                 Jump(&exit);
4864             }
4865             Bind(&notNull);
4866             BRANCH(TaggedIsHole(*result), &notSIndexObj, &exit);
4867         }
4868         Bind(&notFastTypeArray);
4869 
4870         Label isSpecialContainer(env);
4871         Label notSpecialContainer(env);
4872         BRANCH(IsSpecialContainer(jsType), &isSpecialContainer, &notSpecialContainer);
4873         Bind(&isSpecialContainer);
4874         {
4875             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
4876             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4877             result = Exception();
4878             Jump(&exit);
4879         }
4880         Bind(&notSpecialContainer);
4881         {
4882             result = Hole();
4883             Jump(&exit);
4884         }
4885     }
4886     Bind(&notSIndexObj);
4887     {
4888         BRANCH(isInternal, &findProperty, &ifEnd);
4889         Label isDicMode(env);
4890         Label notDicMode(env);
4891         Bind(&findProperty);
4892         BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
4893         Bind(&notDicMode);
4894         {
4895             GateRef layOutInfo = GetLayoutFromHClass(hclass);
4896             GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4897             GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
4898             Label hasEntry(env);
4899             BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
4900             Bind(&hasEntry);
4901             {
4902                 GateRef attr = GetPropAttrFromLayoutInfo(layOutInfo, entry);
4903                 Label isAccessor(env);
4904                 Label notAccessor(env);
4905                 Label isSCheckModelIsCHECK1(env);
4906                 Label isNotSCheckModelIsCHECK1(env);
4907                 BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
4908                 Bind(&isAccessor);
4909                 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK1, &isNotSCheckModelIsCHECK1);
4910                 Bind(&isSCheckModelIsCHECK1);
4911                 {
4912                     Jump(&exit);
4913                 }
4914                 Bind(&isNotSCheckModelIsCHECK1);
4915                 GateRef accessor = JSObjectGetProperty(*holder, hclass, attr);
4916                 Label shouldCall(env);
4917                 BRANCH(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, &notAccessor);
4918                 Bind(&shouldCall);
4919                 {
4920                     result = CallSetterHelper(glue, receiver, accessor, value, callback);
4921                     Jump(&exit);
4922                 }
4923                 Bind(&notAccessor);
4924                 {
4925                     Label writable(env);
4926                     Label notWritable(env);
4927                     Label isSCheckModelIsCHECK2(env);
4928                     Label isNotSCheckModelIsCHECK2(env);
4929                     BRANCH(IsWritable(attr), &writable, &notWritable);
4930                     Bind(&notWritable);
4931                     BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK2, &isNotSCheckModelIsCHECK2);
4932                     Bind(&isSCheckModelIsCHECK2);
4933                     {
4934                         Jump(&exit);
4935                     }
4936                     Bind(&isNotSCheckModelIsCHECK2);
4937                     GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
4938                     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4939                     result = Exception();
4940                     Jump(&exit);
4941                     Bind(&writable);
4942                     {
4943                         Label isTS(env);
4944                         Label notTS(env);
4945                         BRANCH(IsTSHClass(hclass), &isTS, &notTS);
4946                         Bind(&isTS);
4947                         {
4948                             GateRef attrVal = JSObjectGetProperty(*holder, hclass, attr);
4949                             Label attrValIsHole(env);
4950                             BRANCH(TaggedIsHole(attrVal), &attrValIsHole, &notTS);
4951                             Bind(&attrValIsHole);
4952                             {
4953                                 Label storeReceiverHoleEntry(env);
4954                                 Label noNeedStore(env);
4955                                 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
4956                                 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
4957                                 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
4958                                     &storeReceiverHoleEntry, &ifEnd);
4959                                 Bind(&storeReceiverHoleEntry);
4960                                 {
4961                                     receiverHoleEntry = entry;
4962                                     Jump(&ifEnd);
4963                                 }
4964                             }
4965                         }
4966                         Bind(&notTS);
4967                         Label holdEqualsRecv(env);
4968                         BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4969                         Bind(&holdEqualsRecv);
4970                         {
4971                             Label executeSetProp(env);
4972                             CheckUpdateSharedType(false, &result, glue, receiver, attr, value,
4973                                 &executeSetProp, &exit, SCheckModelIsCHECK);
4974                             Bind(&executeSetProp);
4975                             JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
4976                             ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value, callback);
4977                             result = Undefined();
4978                             Jump(&exit);
4979                         }
4980                     }
4981                 }
4982             }
4983         }
4984         Bind(&isDicMode);
4985         {
4986             GateRef array = GetPropertiesArray(*holder);
4987             GateRef entry1 = FindEntryFromNameDictionary(glue, array, key);
4988             Label notNegtiveOne(env);
4989             BRANCH(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &ifEnd);
4990             Bind(&notNegtiveOne);
4991             {
4992                 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(array, entry1);
4993                 Label isAccessor1(env);
4994                 Label notAccessor1(env);
4995                 Label isSCheckModelIsCHECK3(env);
4996                 Label isNotSCheckModelIsCHECK3(env);
4997                 BRANCH(IsAccessor(attr1), &isAccessor1, &notAccessor1);
4998                 Bind(&isAccessor1);
4999                 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK3, &isNotSCheckModelIsCHECK3);
5000                 Bind(&isSCheckModelIsCHECK3);
5001                 {
5002                     Jump(&exit);
5003                 }
5004                 Bind(&isNotSCheckModelIsCHECK3);
5005                 GateRef accessor1 = GetValueFromDictionary<NameDictionary>(array, entry1);
5006                 Label shouldCall1(env);
5007                 BRANCH(ShouldCallSetter(receiver, *holder, accessor1, attr1), &shouldCall1, &notAccessor1);
5008                 Bind(&shouldCall1);
5009                 {
5010                     result = CallSetterHelper(glue, receiver, accessor1, value, callback);
5011                     Jump(&exit);
5012                 }
5013                 Bind(&notAccessor1);
5014                 {
5015                     Label writable1(env);
5016                     Label notWritable1(env);
5017                     Label isSCheckModelIsCHECK4(env);
5018                     Label isNotSCheckModelIsCHECK4(env);
5019                     BRANCH(IsWritable(attr1), &writable1, &notWritable1);
5020                     Bind(&notWritable1);
5021                     BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK4, &isNotSCheckModelIsCHECK4);
5022                     Bind(&isSCheckModelIsCHECK4);
5023                     {
5024                         Jump(&exit);
5025                     }
5026                     Bind(&isNotSCheckModelIsCHECK4);
5027                     GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5028                     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5029                     result = Exception();
5030                     Jump(&exit);
5031                     Bind(&writable1);
5032                     {
5033                         Label holdEqualsRecv1(env);
5034                         BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
5035                         Bind(&holdEqualsRecv1);
5036                         {
5037                             Label executeSetProp(env);
5038                             CheckUpdateSharedType(true, &result, glue, receiver, attr1,
5039                                 value, &executeSetProp, &exit, SCheckModelIsCHECK);
5040                             Bind(&executeSetProp);
5041                             UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
5042                             result = Undefined();
5043                             Jump(&exit);
5044                         }
5045                     }
5046                 }
5047             }
5048         }
5049     }
5050     Bind(&ifEnd);
5051     Label holeEntryNotNegtiveOne(env);
5052     Label holeEntryIfEnd(env);
5053     BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
5054     Bind(&holeEntryNotNegtiveOne);
5055     {
5056         GateRef receiverHClass = LoadHClass(receiver);
5057         GateRef receiverLayoutInfo = GetLayoutFromHClass(receiverHClass);
5058         GateRef holeAttr = GetPropAttrFromLayoutInfo(receiverLayoutInfo, *receiverHoleEntry);
5059         JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
5060         ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
5061         result = Undefined();
5062         Jump(&exit);
5063     }
5064     Bind(&holeEntryIfEnd);
5065 
5066     Label extensible(env);
5067     Label inextensible(env);
5068     BRANCH(IsExtensible(receiver), &extensible, &inextensible);
5069     Bind(&inextensible);
5070     {
5071         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5072         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5073         result = Exception();
5074         Jump(&exit);
5075     }
5076     Bind(&extensible);
5077     {
5078         result = AddPropertyByName(glue, receiver, key, value,
5079             Int64(PropertyAttributes::GetDefaultAttributes()), callback);
5080         Jump(&exit);
5081     }
5082     Bind(&exit);
5083     auto ret = *result;
5084     env->SubCfgExit();
5085     return ret;
5086 }
5087 
SetPropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics)5088 GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn,
5089     ProfileOperation callback, bool defineSemantics)
5090 {
5091     auto env = GetEnvironment();
5092     Label subEntry1(env);
5093     env->SubCfgEntry(&subEntry1);
5094     DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5095     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5096     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5097     Label isNumberOrStringSymbol(env);
5098     Label notNumber(env);
5099     Label isStringOrSymbol(env);
5100     Label notStringOrSymbol(env);
5101     Label exit(env);
5102     BRANCH(TaggedIsNumber(*varKey), &isNumberOrStringSymbol, &notNumber);
5103     Bind(&notNumber);
5104     {
5105         BRANCH(TaggedIsStringOrSymbol(*varKey), &isNumberOrStringSymbol, &notStringOrSymbol);
5106         Bind(&notStringOrSymbol);
5107         {
5108             result = Hole();
5109             Jump(&exit);
5110         }
5111     }
5112     Bind(&isNumberOrStringSymbol);
5113     {
5114         GateRef index64 = TryToElementsIndex(glue, *varKey);
5115         Label validIndex(env);
5116         Label notValidIndex(env);
5117         Label greaterThanInt32Max(env);
5118         Label notGreaterThanInt32Max(env);
5119         BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
5120         Bind(&greaterThanInt32Max);
5121         {
5122             Jump(&exit);
5123         }
5124         Bind(&notGreaterThanInt32Max);
5125         GateRef index = TruncInt64ToInt32(index64);
5126         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
5127         Bind(&validIndex);
5128         {
5129             result = SetPropertyByIndex(glue, receiver, index, value, useOwn, callback, defineSemantics);
5130             Jump(&exit);
5131         }
5132         Bind(&notValidIndex);
5133         {
5134             Label isNumber1(env);
5135             Label notNumber1(env);
5136             Label setByName(env);
5137             BRANCH(TaggedIsNumber(*varKey), &isNumber1, &notNumber1);
5138             Bind(&isNumber1);
5139             {
5140                 result = Hole();
5141                 Jump(&exit);
5142             }
5143             Label isString(env);
5144             Label checkDetector(env);
5145             Bind(&notNumber1);
5146             {
5147                 Label notIntenalString(env);
5148                 BRANCH(TaggedIsString(*varKey), &isString, &checkDetector);
5149                 Bind(&isString);
5150                 {
5151                     BRANCH(IsInternalString(*varKey), &setByName, &notIntenalString);
5152                     Bind(&notIntenalString);
5153                     {
5154                         Label notFind(env);
5155                         Label find(env);
5156                         GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
5157                         BRANCH(TaggedIsHole(res), &notFind, &find);
5158                         Bind(&notFind);
5159                         {
5160                             varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
5161                             isInternal = False();
5162                             Jump(&checkDetector);
5163                         }
5164                         Bind(&find);
5165                         {
5166                             varKey = res;
5167                             Jump(&checkDetector);
5168                         }
5169                     }
5170                 }
5171             }
5172             Bind(&checkDetector);
5173             CheckDetectorName(glue, *varKey, &setByName, &exit);
5174             Bind(&setByName);
5175             {
5176                 result = SetPropertyByName(glue, receiver, *varKey, value, useOwn, *isInternal,
5177                     callback, true, defineSemantics);
5178                 Jump(&exit);
5179             }
5180         }
5181     }
5182     Bind(&exit);
5183     auto ret = *result;
5184     env->SubCfgExit();
5185     return ret;
5186 }
5187 
DefinePropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef SCheckModelIsCHECK,ProfileOperation callback)5188 GateRef StubBuilder::DefinePropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value,
5189     GateRef SCheckModelIsCHECK, ProfileOperation callback)
5190 {
5191     auto env = GetEnvironment();
5192     Label subEntry1(env);
5193     env->SubCfgEntry(&subEntry1);
5194     DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5195     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5196     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5197     Label isNumberOrStringSymbol(env);
5198     Label notNumber(env);
5199     Label isStringOrSymbol(env);
5200     Label notStringOrSymbol(env);
5201     Label exit(env);
5202     BRANCH(TaggedIsNumber(*varKey), &isNumberOrStringSymbol, &notNumber);
5203     Bind(&notNumber);
5204     {
5205         BRANCH(TaggedIsStringOrSymbol(*varKey), &isNumberOrStringSymbol, &notStringOrSymbol);
5206         Bind(&notStringOrSymbol);
5207         {
5208             result = Hole();
5209             Jump(&exit);
5210         }
5211     }
5212     Bind(&isNumberOrStringSymbol);
5213     {
5214         GateRef index64 = TryToElementsIndex(glue, *varKey);
5215         Label validIndex(env);
5216         Label notValidIndex(env);
5217         Label greaterThanInt32Max(env);
5218         Label notGreaterThanInt32Max(env);
5219         BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
5220         Bind(&greaterThanInt32Max);
5221         {
5222             Jump(&exit);
5223         }
5224         Bind(&notGreaterThanInt32Max);
5225         GateRef index = TruncInt64ToInt32(index64);
5226         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
5227         Bind(&validIndex);
5228         {
5229             result = DefinePropertyByIndex(glue, receiver, index, value);
5230             Jump(&exit);
5231         }
5232         Bind(&notValidIndex);
5233         {
5234             Label isNumber1(env);
5235             Label notNumber1(env);
5236             Label setByName(env);
5237             BRANCH(TaggedIsNumber(*varKey), &isNumber1, &notNumber1);
5238             Bind(&isNumber1);
5239             {
5240                 result = Hole();
5241                 Jump(&exit);
5242             }
5243             Label isString(env);
5244             Label checkDetector(env);
5245             Bind(&notNumber1);
5246             {
5247                 Label notIntenalString(env);
5248                 BRANCH(TaggedIsString(*varKey), &isString, &checkDetector);
5249                 Bind(&isString);
5250                 {
5251                     BRANCH(IsInternalString(*varKey), &setByName, &notIntenalString);
5252                     Bind(&notIntenalString);
5253                     {
5254                         Label notFind(env);
5255                         Label find(env);
5256                         GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
5257                         BRANCH(TaggedIsHole(res), &notFind, &find);
5258                         Bind(&notFind);
5259                         {
5260                             varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
5261                             isInternal = False();
5262                             Jump(&checkDetector);
5263                         }
5264                         Bind(&find);
5265                         {
5266                             varKey = res;
5267                             Jump(&checkDetector);
5268                         }
5269                     }
5270                 }
5271             }
5272             Bind(&checkDetector);
5273             CheckDetectorName(glue, *varKey, &setByName, &exit);
5274             Bind(&setByName);
5275             {
5276                 result = DefinePropertyByName(glue, receiver, *varKey, value, *isInternal,
5277                     SCheckModelIsCHECK, callback);
5278                 Jump(&exit);
5279             }
5280         }
5281     }
5282     Bind(&exit);
5283     auto ret = *result;
5284     env->SubCfgExit();
5285     return ret;
5286 }
5287 
SetPropertiesToLexicalEnv(GateRef glue,GateRef object,GateRef index,GateRef value)5288 void StubBuilder::SetPropertiesToLexicalEnv(GateRef glue, GateRef object, GateRef index, GateRef value)
5289 {
5290     GateRef valueIndex = Int32Add(index, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
5291     SetValueToTaggedArray(VariableType::JS_ANY(), glue, object, valueIndex, value);
5292 }
5293 
NotifyHClassChanged(GateRef glue,GateRef oldHClass,GateRef newHClass)5294 void StubBuilder::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef newHClass)
5295 {
5296     auto env = GetEnvironment();
5297     Label entry(env);
5298     env->SubCfgEntry(&entry);
5299     Label exit(env);
5300     Label isProtoType(env);
5301     BRANCH(IsProtoTypeHClass(oldHClass), &isProtoType, &exit);
5302     Bind(&isProtoType);
5303     {
5304         Label notEqualHClass(env);
5305         BRANCH(Equal(oldHClass, newHClass), &exit, &notEqualHClass);
5306         Bind(&notEqualHClass);
5307         {
5308             SetIsProtoTypeToHClass(glue, newHClass, True());
5309             CallRuntime(glue, RTSTUB_ID(NoticeThroughChainAndRefreshUser), { oldHClass, newHClass });
5310             Jump(&exit);
5311         }
5312     }
5313     Bind(&exit);
5314     env->SubCfgExit();
5315     return;
5316 }
5317 
GetContainerProperty(GateRef glue,GateRef receiver,GateRef index,GateRef jsType)5318 GateRef StubBuilder::GetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef jsType)
5319 {
5320     auto env = GetEnvironment();
5321     Label entry(env);
5322     env->SubCfgEntry(&entry);
5323     Label exit(env);
5324     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5325 
5326     Label isDefaultLabel(env);
5327     Label noDefaultLabel(env);
5328     BRANCH(IsSpecialContainer(jsType), &noDefaultLabel, &isDefaultLabel);
5329     Bind(&noDefaultLabel);
5330     {
5331         result = JSAPIContainerGet(glue, receiver, index);
5332         Jump(&exit);
5333     }
5334     Bind(&isDefaultLabel);
5335     {
5336         Jump(&exit);
5337     }
5338     Bind(&exit);
5339 
5340     auto ret = *result;
5341     env->SubCfgExit();
5342     return ret;
5343 }
5344 
FastTypeOf(GateRef glue,GateRef obj)5345 GateRef StubBuilder::FastTypeOf(GateRef glue, GateRef obj)
5346 {
5347     auto env = GetEnvironment();
5348     Label entry(env);
5349     env->SubCfgEntry(&entry);
5350     Label exit(env);
5351 
5352     GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
5353         IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
5354     GateRef undefinedIndex = GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX);
5355     GateRef gConstUndefinedStr = Load(VariableType::JS_POINTER(), gConstAddr, undefinedIndex);
5356     DEFVARIABLE(result, VariableType::JS_POINTER(), gConstUndefinedStr);
5357     Label objIsTrue(env);
5358     Label objNotTrue(env);
5359     Label defaultLabel(env);
5360     GateRef gConstBooleanStr = Load(VariableType::JS_POINTER(), gConstAddr,
5361         GetGlobalConstantOffset(ConstantIndex::BOOLEAN_STRING_INDEX));
5362     BRANCH(TaggedIsTrue(obj), &objIsTrue, &objNotTrue);
5363     Bind(&objIsTrue);
5364     {
5365         result = gConstBooleanStr;
5366         Jump(&exit);
5367     }
5368     Bind(&objNotTrue);
5369     {
5370         Label objIsFalse(env);
5371         Label objNotFalse(env);
5372         BRANCH(TaggedIsFalse(obj), &objIsFalse, &objNotFalse);
5373         Bind(&objIsFalse);
5374         {
5375             result = gConstBooleanStr;
5376             Jump(&exit);
5377         }
5378         Bind(&objNotFalse);
5379         {
5380             Label objIsNull(env);
5381             Label objNotNull(env);
5382             BRANCH(TaggedIsNull(obj), &objIsNull, &objNotNull);
5383             Bind(&objIsNull);
5384             {
5385                 result = Load(VariableType::JS_POINTER(), gConstAddr,
5386                     GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
5387                 Jump(&exit);
5388             }
5389             Bind(&objNotNull);
5390             {
5391                 Label objIsUndefined(env);
5392                 Label objNotUndefined(env);
5393                 BRANCH(TaggedIsUndefined(obj), &objIsUndefined, &objNotUndefined);
5394                 Bind(&objIsUndefined);
5395                 {
5396                     result = Load(VariableType::JS_POINTER(), gConstAddr,
5397                         GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX));
5398                     Jump(&exit);
5399                 }
5400                 Bind(&objNotUndefined);
5401                 Jump(&defaultLabel);
5402             }
5403         }
5404     }
5405     Bind(&defaultLabel);
5406     {
5407         Label objIsHeapObject(env);
5408         Label objNotHeapObject(env);
5409         BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
5410         Bind(&objIsHeapObject);
5411         {
5412             Label objIsString(env);
5413             Label objNotString(env);
5414             BRANCH(IsString(obj), &objIsString, &objNotString);
5415             Bind(&objIsString);
5416             {
5417                 result = Load(VariableType::JS_POINTER(), gConstAddr,
5418                     GetGlobalConstantOffset(ConstantIndex::STRING_STRING_INDEX));
5419                 Jump(&exit);
5420             }
5421             Bind(&objNotString);
5422             {
5423                 Label objIsSymbol(env);
5424                 Label objNotSymbol(env);
5425                 BRANCH(IsSymbol(obj), &objIsSymbol, &objNotSymbol);
5426                 Bind(&objIsSymbol);
5427                 {
5428                     result = Load(VariableType::JS_POINTER(), gConstAddr,
5429                         GetGlobalConstantOffset(ConstantIndex::SYMBOL_STRING_INDEX));
5430                     Jump(&exit);
5431                 }
5432                 Bind(&objNotSymbol);
5433                 {
5434                     Label objIsCallable(env);
5435                     Label objNotCallable(env);
5436                     BRANCH(IsCallable(obj), &objIsCallable, &objNotCallable);
5437                     Bind(&objIsCallable);
5438                     {
5439                         result = Load(VariableType::JS_POINTER(), gConstAddr,
5440                             GetGlobalConstantOffset(ConstantIndex::FUNCTION_STRING_INDEX));
5441                         Jump(&exit);
5442                     }
5443                     Bind(&objNotCallable);
5444                     {
5445                         Label objIsBigInt(env);
5446                         Label objNotBigInt(env);
5447                         BRANCH(TaggedObjectIsBigInt(obj), &objIsBigInt, &objNotBigInt);
5448                         Bind(&objIsBigInt);
5449                         {
5450                             result = Load(VariableType::JS_POINTER(), gConstAddr,
5451                                 GetGlobalConstantOffset(ConstantIndex::BIGINT_STRING_INDEX));
5452                             Jump(&exit);
5453                         }
5454                         Bind(&objNotBigInt);
5455                         {
5456                             Label objIsNativeModuleFailureInfo(env);
5457                             Label objNotNativeModuleFailureInfo(env);
5458                             BRANCH(IsNativeModuleFailureInfo(obj), &objIsNativeModuleFailureInfo,
5459                                 &objNotNativeModuleFailureInfo);
5460                             Bind(&objIsNativeModuleFailureInfo);
5461                             {
5462                                 result = Load(VariableType::JS_POINTER(), gConstAddr,
5463                                     GetGlobalConstantOffset(ConstantIndex::NATIVE_MODULE_FAILURE_INFO_STRING_INDEX));
5464                                 Jump(&exit);
5465                             }
5466                             Bind(&objNotNativeModuleFailureInfo);
5467                             {
5468                                 result = Load(VariableType::JS_POINTER(), gConstAddr,
5469                                     GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
5470                                 Jump(&exit);
5471                             }
5472                         }
5473                     }
5474                 }
5475             }
5476         }
5477         Bind(&objNotHeapObject);
5478         {
5479             Label objIsNum(env);
5480             Label objNotNum(env);
5481             BRANCH(TaggedIsNumber(obj), &objIsNum, &objNotNum);
5482             Bind(&objIsNum);
5483             {
5484                 result = Load(VariableType::JS_POINTER(), gConstAddr,
5485                     GetGlobalConstantOffset(ConstantIndex::NUMBER_STRING_INDEX));
5486                 Jump(&exit);
5487             }
5488             Bind(&objNotNum);
5489             Jump(&exit);
5490         }
5491     }
5492     Bind(&exit);
5493     auto ret = *result;
5494     env->SubCfgExit();
5495     return ret;
5496 }
5497 
InstanceOf(GateRef glue,GateRef object,GateRef target,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)5498 GateRef StubBuilder::InstanceOf(
5499     GateRef glue, GateRef object, GateRef target, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
5500 {
5501     auto env = GetEnvironment();
5502     Label entry(env);
5503     env->SubCfgEntry(&entry);
5504     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5505     Label exit(env);
5506 
5507     // 1.If Type(target) is not Object, throw a TypeError exception.
5508     Label targetIsHeapObject(env);
5509     Label targetIsEcmaObject(env);
5510     Label targetNotEcmaObject(env);
5511     BRANCH(TaggedIsHeapObject(target), &targetIsHeapObject, &targetNotEcmaObject);
5512     Bind(&targetIsHeapObject);
5513     BRANCH(TaggedObjectIsEcmaObject(target), &targetIsEcmaObject, &targetNotEcmaObject);
5514     Bind(&targetNotEcmaObject);
5515     {
5516         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
5517         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5518         result = Exception();
5519         Jump(&exit);
5520     }
5521     Bind(&targetIsEcmaObject);
5522     {
5523         // 2.Let instOfHandler be GetMethod(target, @@hasInstance).
5524         GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
5525         GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
5526         GateRef hasInstanceSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
5527                                                       GlobalEnv::HASINSTANCE_SYMBOL_INDEX);
5528         GateRef instof = GetMethod(glue, target, hasInstanceSymbol, profileTypeInfo, slotId);
5529 
5530         // 3.ReturnIfAbrupt(instOfHandler).
5531         Label isPendingException(env);
5532         Label noPendingException(env);
5533         BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
5534         Bind(&isPendingException);
5535         {
5536             result = Exception();
5537             Jump(&exit);
5538         }
5539         Bind(&noPendingException);
5540 
5541         // 4.If instOfHandler is not undefined, then
5542         Label instOfNotUndefined(env);
5543         Label instOfIsUndefined(env);
5544         Label fastPath(env);
5545         Label targetNotCallable(env);
5546         BRANCH(TaggedIsUndefined(instof), &instOfIsUndefined, &instOfNotUndefined);
5547         Bind(&instOfNotUndefined);
5548         {
5549             TryFastHasInstance(glue, instof, target, object, &fastPath, &exit, &result, callback);
5550         }
5551         Bind(&instOfIsUndefined);
5552         {
5553             // 5.If IsCallable(target) is false, throw a TypeError exception.
5554             BRANCH(IsCallable(target), &fastPath, &targetNotCallable);
5555             Bind(&targetNotCallable);
5556             {
5557                 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
5558                 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5559                 result = Exception();
5560                 Jump(&exit);
5561             }
5562         }
5563         Bind(&fastPath);
5564         {
5565             // 6.Return ? OrdinaryHasInstance(target, object).
5566             result = OrdinaryHasInstance(glue, target, object);
5567             Jump(&exit);
5568         }
5569     }
5570     Bind(&exit);
5571     auto ret = *result;
5572     env->SubCfgExit();
5573     return ret;
5574 }
5575 
TryFastHasInstance(GateRef glue,GateRef instof,GateRef target,GateRef object,Label * fastPath,Label * exit,Variable * result,ProfileOperation callback)5576 void StubBuilder::TryFastHasInstance(GateRef glue, GateRef instof, GateRef target, GateRef object, Label *fastPath,
5577                                      Label *exit, Variable *result, ProfileOperation callback)
5578 {
5579     auto env = GetEnvironment();
5580 
5581     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
5582     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
5583     GateRef function = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::HASINSTANCE_FUNCTION_INDEX);
5584 
5585     Label slowPath(env);
5586     Label tryFastPath(env);
5587     Label callExit(env);
5588     GateRef isEqual = IntPtrEqual(instof, function);
5589     BRANCH(isEqual, &tryFastPath, &slowPath);
5590     Bind(&tryFastPath);
5591     Jump(fastPath);
5592     Bind(&slowPath);
5593     {
5594         JSCallArgs callArgs(JSCallMode::CALL_SETTER);
5595         callArgs.callSetterArgs = { target, object };
5596         if (env->IsBaselineBuiltin()) {
5597             DEFVARIABLE(callRes, VariableType::JS_ANY(), Undefined());
5598             CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, &callRes, Circuit::NullGate(), callArgs,
5599                 callback);
5600             callBuilder.JSCallDispatchForBaseline(&callExit);
5601             Bind(&callExit);
5602             result->WriteVariable(FastToBoolean(*callRes));
5603         } else {
5604             CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, nullptr, Circuit::NullGate(), callArgs,
5605                 callback);
5606             GateRef retValue = callBuilder.JSCallDispatch();
5607             result->WriteVariable(FastToBoolean(retValue));
5608         }
5609         Jump(exit);
5610     }
5611 }
5612 
GetMethod(GateRef glue,GateRef obj,GateRef key,GateRef profileTypeInfo,GateRef slotId)5613 GateRef StubBuilder::GetMethod(GateRef glue, GateRef obj, GateRef key, GateRef profileTypeInfo, GateRef slotId)
5614 {
5615     auto env = GetEnvironment();
5616     Label entry(env);
5617     env->SubCfgEntry(&entry);
5618     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5619     Label exit(env);
5620 
5621     StringIdInfo info;
5622     AccessObjectStubBuilder builder(this);
5623     GateRef value = builder.LoadObjByName(glue, obj, key, info, profileTypeInfo, slotId, ProfileOperation());
5624 
5625     Label isPendingException(env);
5626     Label noPendingException(env);
5627     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
5628     Bind(&isPendingException);
5629     {
5630         result = Exception();
5631         Jump(&exit);
5632     }
5633     Bind(&noPendingException);
5634     Label valueIsUndefinedOrNull(env);
5635     Label valueNotUndefinedOrNull(env);
5636     BRANCH(TaggedIsUndefinedOrNull(value), &valueIsUndefinedOrNull, &valueNotUndefinedOrNull);
5637     Bind(&valueIsUndefinedOrNull);
5638     {
5639         result = Undefined();
5640         Jump(&exit);
5641     }
5642     Bind(&valueNotUndefinedOrNull);
5643     {
5644         Label valueIsCallable(env);
5645         Label valueNotCallable(env);
5646         Label valueIsHeapObject(env);
5647         BRANCH(TaggedIsHeapObject(value), &valueIsHeapObject, &valueNotCallable);
5648         Bind(&valueIsHeapObject);
5649         BRANCH(IsCallable(value), &valueIsCallable, &valueNotCallable);
5650         Bind(&valueNotCallable);
5651         {
5652             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(NonCallable));
5653             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5654             result = Exception();
5655             Jump(&exit);
5656         }
5657         Bind(&valueIsCallable);
5658         {
5659             result = value;
5660             Jump(&exit);
5661         }
5662     }
5663     Bind(&exit);
5664     auto ret = *result;
5665     env->SubCfgExit();
5666     return ret;
5667 }
5668 
FastGetPropertyByName(GateRef glue,GateRef obj,GateRef key,ProfileOperation callback)5669 GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key, ProfileOperation callback)
5670 {
5671     auto env = GetEnvironment();
5672     Label entry(env);
5673     env->SubCfgEntry(&entry);
5674     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5675     Label exit(env);
5676     Label checkResult(env);
5677     Label fastpath(env);
5678     Label slowpath(env);
5679 
5680     BRANCH(TaggedIsHeapObject(obj), &fastpath, &slowpath);
5681     Bind(&fastpath);
5682     {
5683         result = GetPropertyByName(glue, obj, key, callback, True());
5684         BRANCH(TaggedIsHole(*result), &slowpath, &exit);
5685     }
5686     Bind(&slowpath);
5687     {
5688         result = CallRuntime(glue, RTSTUB_ID(LoadICByName), { Undefined(), obj, key, IntToTaggedInt(Int32(0)) });
5689         Jump(&exit);
5690     }
5691     Bind(&exit);
5692     auto ret = *result;
5693     env->SubCfgExit();
5694     return ret;
5695 }
5696 
FastGetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,ProfileOperation callback,GateRef hir)5697 GateRef StubBuilder::FastGetPropertyByIndex(GateRef glue, GateRef obj,
5698                                             GateRef index, ProfileOperation callback, GateRef hir)
5699 {
5700     auto env = GetEnvironment();
5701     Label entry(env);
5702     env->SubCfgEntry(&entry);
5703     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5704     Label exit(env);
5705     Label fastPath(env);
5706     Label slowPath(env);
5707 
5708     BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
5709     Bind(&fastPath);
5710     {
5711         result = GetPropertyByIndex(glue, obj, index, callback, hir);
5712         Label notHole(env);
5713         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
5714     }
5715     Bind(&slowPath);
5716     {
5717         result = CallRuntime(glue, RTSTUB_ID(LdObjByIndex),
5718             { obj, IntToTaggedInt(index), TaggedFalse(), Undefined() });
5719         Jump(&exit);
5720     }
5721     Bind(&exit);
5722     auto ret = *result;
5723     env->SubCfgExit();
5724     return ret;
5725 }
5726 
FastSetPropertyByName(GateRef glue,GateRef obj,GateRef key,GateRef value,ProfileOperation callback)5727 void StubBuilder::FastSetPropertyByName(GateRef glue, GateRef obj, GateRef key, GateRef value,
5728     ProfileOperation callback)
5729 {
5730     auto env = GetEnvironment();
5731     Label entry(env);
5732     env->SubCfgEntry(&entry);
5733     DEFVARIABLE(keyVar, VariableType::JS_ANY(), key);
5734     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5735     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5736     Label exit(env);
5737     Label fastPath(env);
5738     Label slowPath(env);
5739     BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
5740     Bind(&fastPath);
5741     {
5742         Label isString(env);
5743         Label getByName(env);
5744         Label isInternalString(env);
5745         Label notIntenalString(env);
5746         BRANCH(TaggedIsString(*keyVar), &isString, &getByName);
5747         Bind(&isString);
5748         {
5749             BRANCH(IsInternalString(*keyVar), &isInternalString, &notIntenalString);
5750             Bind(&isInternalString);
5751             Jump(&getByName);
5752             Bind(&notIntenalString);
5753             {
5754                 Label notFind(env);
5755                 Label find(env);
5756                 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *keyVar });
5757                 BRANCH(TaggedIsHole(res), &notFind, &find);
5758                 Bind(&notFind);
5759                 {
5760                     keyVar = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { key });
5761                     isInternal = False();
5762                     Jump(&getByName);
5763                 }
5764                 Bind(&find);
5765                 {
5766                     keyVar = res;
5767                     Jump(&getByName);
5768                 }
5769             }
5770         }
5771         Bind(&getByName);
5772 
5773         result = SetPropertyByName(glue, obj, *keyVar, value, false, *isInternal, callback, true);
5774         Label notHole(env);
5775         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
5776     }
5777     Bind(&slowPath);
5778     {
5779         result = CallRuntime(glue, RTSTUB_ID(StoreICByValue), { obj, *keyVar, value, IntToTaggedInt(Int32(0)) });
5780         Jump(&exit);
5781     }
5782     Bind(&exit);
5783     env->SubCfgExit();
5784 }
5785 
FastSetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,GateRef value)5786 void StubBuilder::FastSetPropertyByIndex(GateRef glue, GateRef obj, GateRef index, GateRef value)
5787 {
5788     auto env = GetEnvironment();
5789     Label entry(env);
5790     env->SubCfgEntry(&entry);
5791     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5792     Label exit(env);
5793     Label fastPath(env);
5794     Label slowPath(env);
5795 
5796     BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
5797     Bind(&fastPath);
5798     {
5799         result = SetPropertyByIndex(glue, obj, index, value, false);
5800         Label notHole(env);
5801         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
5802     }
5803     Bind(&slowPath);
5804     {
5805         result = CallRuntime(glue, RTSTUB_ID(StObjByIndex),
5806             { obj, IntToTaggedInt(index), value });
5807         Jump(&exit);
5808     }
5809     Bind(&exit);
5810     env->SubCfgExit();
5811 }
5812 
GetCtorPrototype(GateRef ctor)5813 GateRef StubBuilder::GetCtorPrototype(GateRef ctor)
5814 {
5815     auto env = GetEnvironment();
5816     Label entry(env);
5817     env->SubCfgEntry(&entry);
5818     DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
5819     Label exit(env);
5820     Label isHClass(env);
5821     Label isPrototype(env);
5822     Label isHeapObject(env);
5823     Label notHeapObject(env);
5824 
5825     GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), ctor, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
5826     BRANCH(TaggedIsHeapObject(ctorProtoOrHC), &isHeapObject, &notHeapObject);
5827     Bind(&notHeapObject);
5828     {
5829         // If go slow path, return hole.
5830         constructorPrototype = Hole();
5831         Jump(&exit);
5832     }
5833     Bind(&isHeapObject);
5834     BRANCH(IsJSHClass(ctorProtoOrHC), &isHClass, &isPrototype);
5835     Bind(&isHClass);
5836     {
5837         constructorPrototype = Load(VariableType::JS_POINTER(), ctorProtoOrHC, IntPtr(JSHClass::PROTOTYPE_OFFSET));
5838         Jump(&exit);
5839     }
5840     Bind(&isPrototype);
5841     {
5842         constructorPrototype = ctorProtoOrHC;
5843         Jump(&exit);
5844     }
5845 
5846     Bind(&exit);
5847     auto ret = *constructorPrototype;
5848     env->SubCfgExit();
5849     return ret;
5850 }
5851 
OrdinaryHasInstance(GateRef glue,GateRef target,GateRef obj)5852 GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj)
5853 {
5854     auto env = GetEnvironment();
5855     Label entry(env);
5856     env->SubCfgEntry(&entry);
5857     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5858     Label exit(env);
5859     DEFVARIABLE(object, VariableType::JS_ANY(), obj);
5860 
5861     // 1. If IsCallable(C) is false, return false.
5862     Label targetIsCallable(env);
5863     Label targetNotCallable(env);
5864     BRANCH(IsCallable(target), &targetIsCallable, &targetNotCallable);
5865     Bind(&targetNotCallable);
5866     {
5867         result = TaggedFalse();
5868         Jump(&exit);
5869     }
5870     Bind(&targetIsCallable);
5871     {
5872         // 2. If C has a [[BoundTargetFunction]] internal slot, then
5873         //    a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
5874         //    b. Return InstanceofOperator(O,BC)  (see 12.9.4).
5875         Label targetIsBoundFunction(env);
5876         Label targetNotBoundFunction(env);
5877         BRANCH(IsBoundFunction(target), &targetIsBoundFunction, &targetNotBoundFunction);
5878         Bind(&targetIsBoundFunction);
5879         {
5880             GateRef boundTarget = Load(VariableType::JS_ANY(), target, IntPtr(JSBoundFunction::BOUND_TARGET_OFFSET));
5881             result = CallRuntime(glue, RTSTUB_ID(InstanceOf), { obj, boundTarget });
5882             Jump(&exit);
5883         }
5884         Bind(&targetNotBoundFunction);
5885         {
5886             // 3. If Type(O) is not Object, return false
5887             Label objIsHeapObject(env);
5888             Label objIsEcmaObject(env);
5889             Label objNotEcmaObject(env);
5890             BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotEcmaObject);
5891             Bind(&objIsHeapObject);
5892             BRANCH(TaggedObjectIsEcmaObject(obj), &objIsEcmaObject, &objNotEcmaObject);
5893             Bind(&objNotEcmaObject);
5894             {
5895                 result = TaggedFalse();
5896                 Jump(&exit);
5897             }
5898             Bind(&objIsEcmaObject);
5899             {
5900                 // 4. Let P be Get(C, "prototype").
5901                 Label getCtorProtoSlowPath(env);
5902                 Label ctorIsJSFunction(env);
5903                 Label gotCtorPrototype(env);
5904                 DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
5905                 BRANCH(IsJSFunction(target), &ctorIsJSFunction, &getCtorProtoSlowPath);
5906                 Bind(&ctorIsJSFunction);
5907                 {
5908                     Label getCtorProtoFastPath(env);
5909                     GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), target,
5910                                                  IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
5911 
5912                     BRANCH(TaggedIsHole(ctorProtoOrHC), &getCtorProtoSlowPath, &getCtorProtoFastPath);
5913                     Bind(&getCtorProtoFastPath);
5914                     {
5915                         constructorPrototype = GetCtorPrototype(target);
5916                         BRANCH(TaggedIsHole(*constructorPrototype), &getCtorProtoSlowPath, &gotCtorPrototype);
5917                     }
5918                 }
5919                 Bind(&getCtorProtoSlowPath);
5920                 {
5921                     auto prototypeString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
5922                                                                   ConstantIndex::PROTOTYPE_STRING_INDEX);
5923                     constructorPrototype = FastGetPropertyByName(glue, target, prototypeString, ProfileOperation());
5924                     Jump(&gotCtorPrototype);
5925                 }
5926                 Bind(&gotCtorPrototype);
5927 
5928                 // 5. ReturnIfAbrupt(P).
5929                 // no throw exception, so needn't return
5930                 Label isPendingException(env);
5931                 Label noPendingException(env);
5932                 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
5933                 Bind(&isPendingException);
5934                 {
5935                     result = Exception();
5936                     Jump(&exit);
5937                 }
5938                 Bind(&noPendingException);
5939 
5940                 // 6. If Type(P) is not Object, throw a TypeError exception.
5941                 Label constructorPrototypeIsHeapObject(env);
5942                 Label constructorPrototypeIsEcmaObject(env);
5943                 Label constructorPrototypeNotEcmaObject(env);
5944                 BRANCH(TaggedIsHeapObject(*constructorPrototype), &constructorPrototypeIsHeapObject,
5945                     &constructorPrototypeNotEcmaObject);
5946                 Bind(&constructorPrototypeIsHeapObject);
5947                 BRANCH(TaggedObjectIsEcmaObject(*constructorPrototype), &constructorPrototypeIsEcmaObject,
5948                     &constructorPrototypeNotEcmaObject);
5949                 Bind(&constructorPrototypeNotEcmaObject);
5950                 {
5951                     GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
5952                     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5953                     result = Exception();
5954                     Jump(&exit);
5955                 }
5956                 Bind(&constructorPrototypeIsEcmaObject);
5957                 {
5958                     // 7. Repeat
5959                     //    a.Let O be O.[[GetPrototypeOf]]().
5960                     //    b.ReturnIfAbrupt(O).
5961                     //    c.If O is null, return false.
5962                     //    d.If SameValue(P, O) is true, return true.
5963                     Label loopHead(env);
5964                     Label loopEnd(env);
5965                     Label afterLoop(env);
5966                     Label strictEqual1(env);
5967                     Label notStrictEqual1(env);
5968                     Label shouldReturn(env);
5969                     Label shouldContinue(env);
5970 
5971                     BRANCH(TaggedIsNull(*object), &afterLoop, &loopHead);
5972                     LoopBegin(&loopHead);
5973                     {
5974                         object = GetPrototype(glue, *object);
5975                         Branch(HasPendingException(glue), &shouldReturn, &shouldContinue);
5976                         Bind(&shouldReturn);
5977                         {
5978                             result = Exception();
5979                             Jump(&exit);
5980                         }
5981                         Bind(&shouldContinue);
5982                         {
5983                             GateRef isEqual = SameValue(glue, *object, *constructorPrototype);
5984                             Branch(isEqual, &strictEqual1, &notStrictEqual1);
5985                             Bind(&strictEqual1);
5986                             {
5987                                 result = TaggedTrue();
5988                                 Jump(&exit);
5989                             }
5990                             Bind(&notStrictEqual1);
5991                             Branch(TaggedIsNull(*object), &afterLoop, &loopEnd);
5992                         }
5993                     }
5994                     Bind(&loopEnd);
5995                     LoopEnd(&loopHead, env, glue);
5996                     Bind(&afterLoop);
5997                     {
5998                         result = TaggedFalse();
5999                         Jump(&exit);
6000                     }
6001                 }
6002             }
6003         }
6004     }
6005     Bind(&exit);
6006     auto ret = *result;
6007     env->SubCfgExit();
6008     return ret;
6009 }
6010 
SameValue(GateRef glue,GateRef left,GateRef right)6011 GateRef StubBuilder::SameValue(GateRef glue, GateRef left, GateRef right)
6012 {
6013     auto env = GetEnvironment();
6014     Label entry(env);
6015     env->SubCfgEntry(&entry);
6016     DEFVARIABLE(result, VariableType::BOOL(), False());
6017     Label exit(env);
6018     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6019     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6020     Label strictEqual(env);
6021     Label stringEqualCheck(env);
6022     Label stringCompare(env);
6023     Label bigIntEqualCheck(env);
6024     Label numberEqualCheck1(env);
6025 
6026     BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6027     Bind(&strictEqual);
6028     {
6029         result = True();
6030         Jump(&exit);
6031     }
6032     Bind(&numberEqualCheck1);
6033     {
6034         Label leftIsNumber(env);
6035         Label leftIsNotNumber(env);
6036         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6037         Bind(&leftIsNumber);
6038         {
6039             Label rightIsNumber(env);
6040             BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6041             Bind(&rightIsNumber);
6042             {
6043                 Label numberEqualCheck2(env);
6044                 Label leftIsInt(env);
6045                 Label leftNotInt(env);
6046                 Label getRight(env);
6047 
6048                 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6049                 Bind(&leftIsInt);
6050                 {
6051                     Label fastPath(env);
6052                     Label slowPath(env);
6053                     BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6054                     Bind(&fastPath);
6055                     {
6056                         result = False();
6057                         Jump(&exit);
6058                     }
6059                     Bind(&slowPath);
6060                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6061                     doubleRight = GetDoubleOfTDouble(right);
6062                     Jump(&numberEqualCheck2);
6063                 }
6064                 Bind(&leftNotInt);
6065                 {
6066                     doubleLeft = GetDoubleOfTDouble(left);
6067                     Jump(&getRight);
6068                 }
6069                 Bind(&getRight);
6070                 {
6071                     Label rightIsInt(env);
6072                     Label rightNotInt(env);
6073                     BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6074                     Bind(&rightIsInt);
6075                     {
6076                         doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6077                         Jump(&numberEqualCheck2);
6078                     }
6079                     Bind(&rightNotInt);
6080                     {
6081                         doubleRight = GetDoubleOfTDouble(right);
6082                         Jump(&numberEqualCheck2);
6083                     }
6084                 }
6085                 Bind(&numberEqualCheck2);
6086                 {
6087                     Label boolAndCheck(env);
6088                     Label signbitCheck(env);
6089                     BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &signbitCheck, &boolAndCheck);
6090                     Bind(&signbitCheck);
6091                     {
6092                         GateRef leftEncoding = CastDoubleToInt64(*doubleLeft);
6093                         GateRef RightEncoding = CastDoubleToInt64(*doubleRight);
6094                         Label leftIsMinusZero(env);
6095                         Label leftNotMinusZero(env);
6096                         BRANCH(Int64Equal(leftEncoding, Int64(base::MINUS_ZERO_BITS)),
6097                             &leftIsMinusZero, &leftNotMinusZero);
6098                         Bind(&leftIsMinusZero);
6099                         {
6100                             Label rightIsMinusZero(env);
6101                             BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &rightIsMinusZero, &exit);
6102                             Bind(&rightIsMinusZero);
6103                             {
6104                                 result = True();
6105                                 Jump(&exit);
6106                             }
6107                         }
6108                         Bind(&leftNotMinusZero);
6109                         {
6110                             Label rightNotMinusZero(env);
6111                             BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &exit, &rightNotMinusZero);
6112                             Bind(&rightNotMinusZero);
6113                             {
6114                                 result = True();
6115                                 Jump(&exit);
6116                             }
6117                         }
6118                     }
6119                     Bind(&boolAndCheck);
6120                     {
6121                         GateRef doubleLeftVal = *doubleLeft;
6122                         GateRef doubleRightVal = *doubleRight;
6123                         result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
6124                             .And(DoubleIsNAN(doubleRightVal)).Done();
6125                         Jump(&exit);
6126                     }
6127                 }
6128             }
6129         }
6130         Bind(&leftIsNotNumber);
6131         BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
6132         Bind(&stringEqualCheck);
6133         BRANCH(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
6134         Bind(&stringCompare);
6135         {
6136             result = FastStringEqual(glue, left, right);
6137             Jump(&exit);
6138         }
6139         Bind(&bigIntEqualCheck);
6140         {
6141             Label leftIsBigInt(env);
6142             Label leftIsNotBigInt(env);
6143             BRANCH(TaggedIsBigInt(left), &leftIsBigInt, &exit);
6144             Bind(&leftIsBigInt);
6145             {
6146                 Label rightIsBigInt(env);
6147                 BRANCH(TaggedIsBigInt(right), &rightIsBigInt, &exit);
6148                 Bind(&rightIsBigInt);
6149                 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
6150                 Jump(&exit);
6151             }
6152         }
6153     }
6154     Bind(&exit);
6155     auto ret = *result;
6156     env->SubCfgExit();
6157     return ret;
6158 }
6159 
SameValueZero(GateRef glue,GateRef left,GateRef right)6160 GateRef StubBuilder::SameValueZero(GateRef glue, GateRef left, GateRef right)
6161 {
6162     auto env = GetEnvironment();
6163     Label entry(env);
6164     env->SubCfgEntry(&entry);
6165     DEFVARIABLE(result, VariableType::BOOL(), False());
6166     Label exit(env);
6167     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6168     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6169     Label strictEqual(env);
6170     Label stringEqualCheck(env);
6171     Label stringCompare(env);
6172     Label bigIntEqualCheck(env);
6173     Label numberEqualCheck1(env);
6174 
6175     BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6176     Bind(&strictEqual);
6177     {
6178         result = True();
6179         Jump(&exit);
6180     }
6181     Bind(&numberEqualCheck1);
6182     {
6183         Label leftIsNumber(env);
6184         Label leftIsNotNumber(env);
6185         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6186         Bind(&leftIsNumber);
6187         {
6188             Label rightIsNumber(env);
6189             BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6190             Bind(&rightIsNumber);
6191             {
6192                 Label numberEqualCheck2(env);
6193                 Label leftIsInt(env);
6194                 Label leftNotInt(env);
6195                 Label getRight(env);
6196                 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6197                 Bind(&leftIsInt);
6198                 {
6199                     Label fastPath(env);
6200                     Label slowPath(env);
6201                     BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6202                     Bind(&fastPath);
6203                     {
6204                         result = False();
6205                         Jump(&exit);
6206                     }
6207                     Bind(&slowPath);
6208                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6209                     doubleRight = GetDoubleOfTDouble(right);
6210                     Jump(&numberEqualCheck2);
6211                 }
6212                 Bind(&leftNotInt);
6213                 {
6214                     doubleLeft = GetDoubleOfTDouble(left);
6215                     Jump(&getRight);
6216                 }
6217                 Bind(&getRight);
6218                 {
6219                     Label rightIsInt(env);
6220                     Label rightNotInt(env);
6221                     BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6222                     Bind(&rightIsInt);
6223                     {
6224                         doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6225                         Jump(&numberEqualCheck2);
6226                     }
6227                     Bind(&rightNotInt);
6228                     {
6229                         doubleRight = GetDoubleOfTDouble(right);
6230                         Jump(&numberEqualCheck2);
6231                     }
6232                 }
6233                 Bind(&numberEqualCheck2);
6234                 {
6235                     Label nanCheck(env);
6236                     Label doubleEqual(env);
6237                     BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &doubleEqual, &nanCheck);
6238                     Bind(&doubleEqual);
6239                     {
6240                         result = True();
6241                         Jump(&exit);
6242                     }
6243                     Bind(&nanCheck);
6244                     {
6245                         GateRef doubleLeftVal = *doubleLeft;
6246                         GateRef doubleRightVal = *doubleRight;
6247                         result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
6248                             .And(DoubleIsNAN(doubleRightVal)).Done();
6249                         Jump(&exit);
6250                     }
6251                 }
6252             }
6253         }
6254         Bind(&leftIsNotNumber);
6255         BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
6256         Bind(&stringEqualCheck);
6257         BRANCH(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
6258         Bind(&stringCompare);
6259         {
6260             result = FastStringEqual(glue, left, right);
6261             Jump(&exit);
6262         }
6263         Bind(&bigIntEqualCheck);
6264         {
6265             Label leftIsBigInt(env);
6266             Label leftIsNotBigInt(env);
6267             BRANCH(TaggedIsBigInt(left), &leftIsBigInt, &exit);
6268             Bind(&leftIsBigInt);
6269             {
6270                 Label rightIsBigInt(env);
6271                 BRANCH(TaggedIsBigInt(right), &rightIsBigInt, &exit);
6272                 Bind(&rightIsBigInt);
6273                 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntSameValueZero), { left, right });
6274                 Jump(&exit);
6275             }
6276         }
6277     }
6278     Bind(&exit);
6279     auto ret = *result;
6280     env->SubCfgExit();
6281     return ret;
6282 }
6283 
FastStringEqual(GateRef glue,GateRef left,GateRef right)6284 GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right)
6285 {
6286     auto env = GetEnvironment();
6287     Label entry(env);
6288     env->SubCfgEntry(&entry);
6289     DEFVARIABLE(result, VariableType::BOOL(), False());
6290     Label exit(env);
6291     Label hashcodeCompare(env);
6292     Label contentsCompare(env);
6293     Label lenEqualOneCheck(env);
6294     Label lenIsOne(env);
6295     BRANCH(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &lenEqualOneCheck, &exit);
6296     Bind(&lenEqualOneCheck);
6297     BRANCH(Int32Equal(GetLengthFromString(left), Int32(1)), &lenIsOne, &hashcodeCompare);
6298     Bind(&lenIsOne);
6299     {
6300         Label leftFlattenFastPath(env);
6301         FlatStringStubBuilder leftFlat(this);
6302         leftFlat.FlattenString(glue, left, &leftFlattenFastPath);
6303         Bind(&leftFlattenFastPath);
6304         {
6305             Label rightFlattenFastPath(env);
6306             FlatStringStubBuilder rightFlat(this);
6307             rightFlat.FlattenString(glue, right, &rightFlattenFastPath);
6308             Bind(&rightFlattenFastPath);
6309             {
6310                 BuiltinsStringStubBuilder stringBuilder(this);
6311                 StringInfoGateRef leftStrInfoGate(&leftFlat);
6312                 StringInfoGateRef rightStrInfoGate(&rightFlat);
6313                 GateRef leftStrToInt = stringBuilder.StringAt(leftStrInfoGate, Int32(0));
6314                 GateRef rightStrToInt = stringBuilder.StringAt(rightStrInfoGate, Int32(0));
6315                 result = Equal(leftStrToInt, rightStrToInt);
6316                 Jump(&exit);
6317             }
6318         }
6319     }
6320 
6321     Bind(&hashcodeCompare);
6322     Label leftNotNeg(env);
6323     GateRef leftHash = TryGetHashcodeFromString(left);
6324     GateRef rightHash = TryGetHashcodeFromString(right);
6325     BRANCH(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg);
6326     Bind(&leftNotNeg);
6327     {
6328         Label rightNotNeg(env);
6329         BRANCH(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg);
6330         Bind(&rightNotNeg);
6331         BRANCH(Int64Equal(leftHash, rightHash), &contentsCompare, &exit);
6332     }
6333 
6334     Bind(&contentsCompare);
6335     {
6336         GateRef stringEqual = CallRuntime(glue, RTSTUB_ID(StringEqual), { left, right });
6337         result = Equal(stringEqual, TaggedTrue());
6338         Jump(&exit);
6339     }
6340 
6341     Bind(&exit);
6342     auto ret = *result;
6343     env->SubCfgExit();
6344     return ret;
6345 }
6346 
FastStrictEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)6347 GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
6348 {
6349     auto env = GetEnvironment();
6350     Label entry(env);
6351     env->SubCfgEntry(&entry);
6352     DEFVARIABLE(result, VariableType::BOOL(), False());
6353     Label strictEqual(env);
6354     Label leftIsNumber(env);
6355     Label leftIsNotNumber(env);
6356     Label sameVariableCheck(env);
6357     Label stringEqualCheck(env);
6358     Label stringCompare(env);
6359     Label bigIntEqualCheck(env);
6360     Label exit(env);
6361     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6362     Bind(&leftIsNumber);
6363     {
6364         Label rightIsNumber(env);
6365         BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6366         Bind(&rightIsNumber);
6367         {
6368             DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6369             DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6370             DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::IntType()));
6371             Label leftIsInt(env);
6372             Label leftNotInt(env);
6373             Label getRight(env);
6374             Label numberEqualCheck(env);
6375 
6376             BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6377             Bind(&leftIsInt);
6378             {
6379                 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6380                 Jump(&getRight);
6381             }
6382             Bind(&leftNotInt);
6383             {
6384                 curType = Int32(PGOSampleType::DoubleType());
6385                 doubleLeft = GetDoubleOfTDouble(left);
6386                 Jump(&getRight);
6387             }
6388             Bind(&getRight);
6389             {
6390                 Label rightIsInt(env);
6391                 Label rightNotInt(env);
6392                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6393                 Bind(&rightIsInt);
6394                 {
6395                     GateRef type = Int32(PGOSampleType::IntType());
6396                     COMBINE_TYPE_CALL_BACK(curType, type);
6397                     doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6398                     Jump(&numberEqualCheck);
6399                 }
6400                 Bind(&rightNotInt);
6401                 {
6402                     GateRef type = Int32(PGOSampleType::DoubleType());
6403                     COMBINE_TYPE_CALL_BACK(curType, type);
6404                     doubleRight = GetDoubleOfTDouble(right);
6405                     Jump(&numberEqualCheck);
6406                 }
6407             }
6408             Bind(&numberEqualCheck);
6409             {
6410                 Label doubleEqualCheck(env);
6411                 BRANCH(BitOr(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight)), &exit, &doubleEqualCheck);
6412                 Bind(&doubleEqualCheck);
6413                 {
6414                     result = DoubleEqual(*doubleLeft, *doubleRight);
6415                     Jump(&exit);
6416                 }
6417             }
6418         }
6419     }
6420     Bind(&leftIsNotNumber);
6421     BRANCH(TaggedIsNumber(right), &exit, &sameVariableCheck);
6422     Bind(&sameVariableCheck);
6423     BRANCH(Equal(left, right), &strictEqual, &stringEqualCheck);
6424     Bind(&stringEqualCheck);
6425     BRANCH(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
6426     Bind(&stringCompare);
6427     {
6428         callback.ProfileOpType(Int32(PGOSampleType::StringType()));
6429         result = FastStringEqual(glue, left, right);
6430         Jump(&exit);
6431     }
6432     Bind(&bigIntEqualCheck);
6433     {
6434         Label leftIsBigInt(env);
6435         Label leftIsNotBigInt(env);
6436         BRANCH(TaggedIsBigInt(left), &leftIsBigInt, &exit);
6437         Bind(&leftIsBigInt);
6438         {
6439             Label rightIsBigInt(env);
6440             BRANCH(TaggedIsBigInt(right), &rightIsBigInt, &exit);
6441             Bind(&rightIsBigInt);
6442             callback.ProfileOpType(Int32(PGOSampleType::BigIntType()));
6443             result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
6444             Jump(&exit);
6445         }
6446     }
6447     Bind(&strictEqual);
6448     {
6449         callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6450         result = True();
6451         Jump(&exit);
6452     }
6453     Bind(&exit);
6454     auto ret = *result;
6455     env->SubCfgExit();
6456     return ret;
6457 }
6458 
FastEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)6459 GateRef StubBuilder::FastEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
6460 {
6461     auto env = GetEnvironment();
6462     Label entry(env);
6463     env->SubCfgEntry(&entry);
6464     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6465     Label leftEqualRight(env);
6466     Label leftNotEqualRight(env);
6467     Label exit(env);
6468     BRANCH(Equal(left, right), &leftEqualRight, &leftNotEqualRight);
6469     Bind(&leftEqualRight);
6470     {
6471         Label leftIsDouble(env);
6472         Label leftNotDoubleOrLeftNotNan(env);
6473         BRANCH(TaggedIsDouble(left), &leftIsDouble, &leftNotDoubleOrLeftNotNan);
6474         Bind(&leftIsDouble);
6475         {
6476             callback.ProfileOpType(Int32(PGOSampleType::DoubleType()));
6477             GateRef doubleLeft = GetDoubleOfTDouble(left);
6478             Label leftIsNan(env);
6479             Label leftIsNotNan(env);
6480             BRANCH(DoubleIsNAN(doubleLeft), &leftIsNan, &leftIsNotNan);
6481             Bind(&leftIsNan);
6482             {
6483                 result = TaggedFalse();
6484                 Jump(&exit);
6485             }
6486             Bind(&leftIsNotNan);
6487             {
6488                 result = TaggedTrue();
6489                 Jump(&exit);
6490             }
6491         }
6492         Bind(&leftNotDoubleOrLeftNotNan);
6493         {
6494             // Collect the type of left value
6495             result = TaggedTrue();
6496             if (callback.IsEmpty()) {
6497                 Jump(&exit);
6498             } else {
6499                 Label leftIsInt(env);
6500                 Label leftIsNotInt(env);
6501                 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsNotInt);
6502                 Bind(&leftIsInt);
6503                 {
6504                     callback.ProfileOpType(Int32(PGOSampleType::IntType()));
6505                     Jump(&exit);
6506                 }
6507                 Bind(&leftIsNotInt);
6508                 {
6509                     Label leftIsString(env);
6510                     Label leftIsNotString(env);
6511                     BRANCH(TaggedIsString(left), &leftIsString, &leftIsNotString);
6512                     Bind(&leftIsString);
6513                     {
6514                         callback.ProfileOpType(Int32(PGOSampleType::StringType()));
6515                         Jump(&exit);
6516                     }
6517                     Bind(&leftIsNotString);
6518                     {
6519                         callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6520                         Jump(&exit);
6521                     }
6522                 }
6523             }
6524         }
6525     }
6526     Bind(&leftNotEqualRight);
6527     {
6528         Label leftIsNumber(env);
6529         Label leftNotNumberOrLeftNotIntOrRightNotInt(env);
6530         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrLeftNotIntOrRightNotInt);
6531         Bind(&leftIsNumber);
6532         {
6533             Label leftIsInt(env);
6534             BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
6535             Bind(&leftIsInt);
6536             {
6537                 Label rightIsInt(env);
6538                 BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
6539                 Bind(&rightIsInt);
6540                 {
6541                     callback.ProfileOpType(Int32(PGOSampleType::IntType()));
6542                     result = TaggedFalse();
6543                     Jump(&exit);
6544                 }
6545             }
6546         }
6547         Bind(&leftNotNumberOrLeftNotIntOrRightNotInt);
6548         {
6549             DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::None()));
6550             Label rightIsUndefinedOrNull(env);
6551             Label rightIsNotUndefinedOrNull(env);
6552             BRANCH(TaggedIsUndefinedOrNull(right), &rightIsUndefinedOrNull, &rightIsNotUndefinedOrNull);
6553             Bind(&rightIsUndefinedOrNull);
6554             {
6555                 curType = Int32(PGOSampleType::UndefineOrNullType());
6556                 Label leftIsHeapObject(env);
6557                 Label leftNotHeapObject(env);
6558                 BRANCH(TaggedIsHeapObject(left), &leftIsHeapObject, &leftNotHeapObject);
6559                 Bind(&leftIsHeapObject);
6560                 {
6561                     GateRef type = Int32(PGOSampleType::HeapObjectType());
6562                     COMBINE_TYPE_CALL_BACK(curType, type);
6563                     result = TaggedFalse();
6564                     Jump(&exit);
6565                 }
6566                 Bind(&leftNotHeapObject);
6567                 {
6568                     Label leftIsUndefinedOrNull(env);
6569                     Label leftIsNotUndefinedOrNull(env);
6570                     // if left is undefined or null, then result is true, otherwise result is false
6571                     BRANCH(TaggedIsUndefinedOrNull(left), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
6572                     Bind(&leftIsUndefinedOrNull);
6573                     {
6574                         callback.ProfileOpType(*curType);
6575                         result = TaggedTrue();
6576                         Jump(&exit);
6577                     }
6578                     Bind(&leftIsNotUndefinedOrNull);
6579                     {
6580                         callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6581                         result = TaggedFalse();
6582                         Jump(&exit);
6583                     }
6584                 }
6585             }
6586             Bind(&rightIsNotUndefinedOrNull);
6587             {
6588                 Label leftIsUndefinedOrNull(env);
6589                 Label leftIsNotUndefinedOrNull(env);
6590                 BRANCH(TaggedIsUndefinedOrNull(right), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
6591                 // If left is undefined or null, result will always be false
6592                 // because we can ensure that right is not null here.
6593                 Bind(&leftIsUndefinedOrNull);
6594                 {
6595                     callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6596                     result = TaggedFalse();
6597                     Jump(&exit);
6598                 }
6599                 Bind(&leftIsNotUndefinedOrNull);
6600                 {
6601                     Label leftIsBool(env);
6602                     Label leftNotBoolOrRightNotSpecial(env);
6603                     BRANCH(TaggedIsBoolean(left), &leftIsBool, &leftNotBoolOrRightNotSpecial);
6604                     Bind(&leftIsBool);
6605                     {
6606                         curType = Int32(PGOSampleType::BooleanType());
6607                         Label rightIsSpecial(env);
6608                         BRANCH(TaggedIsSpecial(right), &rightIsSpecial, &leftNotBoolOrRightNotSpecial);
6609                         Bind(&rightIsSpecial);
6610                         {
6611                             GateRef type = Int32(PGOSampleType::SpecialType());
6612                             COMBINE_TYPE_CALL_BACK(curType, type);
6613                             result = TaggedFalse();
6614                             Jump(&exit);
6615                         }
6616                     }
6617                     Bind(&leftNotBoolOrRightNotSpecial);
6618                     {
6619                         Label bothString(env);
6620                         Label eitherNotString(env);
6621                         BRANCH(BothAreString(left, right), &bothString, &eitherNotString);
6622                         Bind(&bothString);
6623                         {
6624                             callback.ProfileOpType(Int32(PGOSampleType::StringType()));
6625                             Label stringEqual(env);
6626                             Label stringNotEqual(env);
6627                             BRANCH(FastStringEqual(glue, left, right), &stringEqual, &stringNotEqual);
6628                             Bind(&stringEqual);
6629                             result = TaggedTrue();
6630                             Jump(&exit);
6631                             Bind(&stringNotEqual);
6632                             result = TaggedFalse();
6633                             Jump(&exit);
6634                         }
6635                         Bind(&eitherNotString);
6636                         callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6637                         Jump(&exit);
6638                     }
6639                 }
6640             }
6641         }
6642     }
6643     Bind(&exit);
6644     auto ret = *result;
6645     env->SubCfgExit();
6646     return ret;
6647 }
6648 
FastToBoolean(GateRef value,bool flag)6649 GateRef StubBuilder::FastToBoolean(GateRef value, bool flag)
6650 {
6651     auto env = GetEnvironment();
6652     Label entry(env);
6653     env->SubCfgEntry(&entry);
6654     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6655     Label exit(env);
6656 
6657     Label isSpecial(env);
6658     Label notSpecial(env);
6659     Label isNumber(env);
6660     Label isInt(env);
6661     Label isDouble(env);
6662     Label notNumber(env);
6663     Label notNan(env);
6664     Label isString(env);
6665     Label notString(env);
6666     Label isBigint(env);
6667     Label lengthIsOne(env);
6668     Label returnTrue(env);
6669     Label returnFalse(env);
6670 
6671     BRANCH(TaggedIsSpecial(value), &isSpecial, &notSpecial);
6672     Bind(&isSpecial);
6673     {
6674         BRANCH(TaggedIsTrue(value), &returnTrue, &returnFalse);
6675     }
6676     Bind(&notSpecial);
6677     {
6678         BRANCH(TaggedIsNumber(value), &isNumber, &notNumber);
6679         Bind(&notNumber);
6680         {
6681             BRANCH(IsString(value), &isString, &notString);
6682             Bind(&isString);
6683             {
6684                 auto len = GetLengthFromString(value);
6685                 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
6686             }
6687             Bind(&notString);
6688             BRANCH(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
6689             Bind(&isBigint);
6690             {
6691                 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
6692                 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
6693                 Bind(&lengthIsOne);
6694                 {
6695                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
6696                     auto data0 = Load(VariableType::INT32(), data, Int32(0));
6697                     BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
6698                 }
6699             }
6700         }
6701         Bind(&isNumber);
6702         {
6703             BRANCH(TaggedIsInt(value), &isInt, &isDouble);
6704             Bind(&isInt);
6705             {
6706                 auto intValue = GetInt32OfTInt(value);
6707                 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
6708             }
6709             Bind(&isDouble);
6710             {
6711                 auto doubleValue = GetDoubleOfTDouble(value);
6712                 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
6713                 Bind(&notNan);
6714                 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
6715             }
6716         }
6717     }
6718     if (flag == 1) {
6719         Bind(&returnTrue);
6720         {
6721             result = TaggedTrue();
6722             Jump(&exit);
6723         }
6724         Bind(&returnFalse);
6725         {
6726             result = TaggedFalse();
6727             Jump(&exit);
6728         }
6729     } else {
6730         Bind(&returnFalse);
6731         {
6732             result = TaggedTrue();
6733             Jump(&exit);
6734         }
6735         Bind(&returnTrue);
6736         {
6737             result = TaggedFalse();
6738             Jump(&exit);
6739         }
6740     }
6741 
6742     Bind(&exit);
6743     auto ret = *result;
6744     env->SubCfgExit();
6745     return ret;
6746 }
6747 
FastToBooleanBaseline(GateRef value,bool flag)6748 GateRef StubBuilder::FastToBooleanBaseline(GateRef value, bool flag)
6749 {
6750     auto env = GetEnvironment();
6751     Label entry(env);
6752     env->SubCfgEntry(&entry);
6753     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6754     Label exit(env);
6755 
6756     Label isSpecial(env);
6757     Label notSpecial(env);
6758     Label isNumber(env);
6759     Label isInt(env);
6760     Label isDouble(env);
6761     Label notNumber(env);
6762     Label notNan(env);
6763     Label isString(env);
6764     Label notString(env);
6765     Label isBigint(env);
6766     Label lengthIsOne(env);
6767     Label returnTrue(env);
6768     Label returnFalse(env);
6769 
6770     Branch(TaggedIsSpecial(value), &isSpecial, &notSpecial);
6771     Bind(&isSpecial);
6772     {
6773         Branch(TaggedIsTrue(value), &returnTrue, &returnFalse);
6774     }
6775     Bind(&notSpecial);
6776     {
6777         Branch(TaggedIsNumber(value), &isNumber, &notNumber);
6778         Bind(&notNumber);
6779         {
6780             Branch(IsString(value), &isString, &notString);
6781             Bind(&isString);
6782             {
6783                 auto len = GetLengthFromString(value);
6784                 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
6785             }
6786             Bind(&notString);
6787             Branch(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
6788             Bind(&isBigint);
6789             {
6790                 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
6791                 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
6792                 Bind(&lengthIsOne);
6793                 {
6794                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
6795                     auto data0 = Load(VariableType::INT32(), data, Int32(0));
6796                     Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
6797                 }
6798             }
6799         }
6800         Bind(&isNumber);
6801         {
6802             Branch(TaggedIsInt(value), &isInt, &isDouble);
6803             Bind(&isInt);
6804             {
6805                 auto intValue = GetInt32OfTInt(value);
6806                 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
6807             }
6808             Bind(&isDouble);
6809             {
6810                 auto doubleValue = GetDoubleOfTDouble(value);
6811                 Branch(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
6812                 Bind(&notNan);
6813                 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
6814             }
6815         }
6816     }
6817     if (flag == 1) {
6818         Bind(&returnTrue);
6819         {
6820             result = TaggedTrue();
6821             Jump(&exit);
6822         }
6823         Bind(&returnFalse);
6824         {
6825             result = TaggedFalse();
6826             Jump(&exit);
6827         }
6828     } else {
6829         Bind(&returnFalse);
6830         {
6831             result = TaggedTrue();
6832             Jump(&exit);
6833         }
6834         Bind(&returnTrue);
6835         {
6836             result = TaggedFalse();
6837             Jump(&exit);
6838         }
6839     }
6840 
6841     Bind(&exit);
6842     auto ret = *result;
6843     env->SubCfgExit();
6844     return ret;
6845 }
6846 
FastToBooleanWithProfile(GateRef value,ProfileOperation callback,bool flag)6847 GateRef StubBuilder::FastToBooleanWithProfile(GateRef value, ProfileOperation callback, bool flag)
6848 {
6849     auto env = GetEnvironment();
6850     Label entry(env);
6851     env->SubCfgEntry(&entry);
6852     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6853     Label exit(env);
6854 
6855     Label isSpecial(env);
6856     Label notSpecial(env);
6857     Label isNumber(env);
6858     Label isInt(env);
6859     Label isDouble(env);
6860     Label notNumber(env);
6861     Label notNan(env);
6862     Label isString(env);
6863     Label notString(env);
6864     Label isBigint(env);
6865     Label lengthIsOne(env);
6866     Label returnTrue(env);
6867     Label returnFalse(env);
6868     Label isTrue(env);
6869     Label isNotTrue(env);
6870     Label isFalse(env);
6871     Label isNotFalse(env);
6872 
6873     BRANCH(TaggedIsSpecial(value), &isSpecial, &notSpecial);
6874     Bind(&isSpecial);
6875     {
6876         BRANCH(TaggedIsTrue(value), &isTrue, &isNotTrue);
6877         Bind(&isTrue);
6878         {
6879             callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
6880             Jump(&returnTrue);
6881         }
6882         Bind(&isNotTrue);
6883         {
6884             BRANCH(TaggedIsFalse(value), &isFalse, &isNotFalse);
6885             Bind(&isFalse);
6886             {
6887                 callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
6888                 Jump(&returnFalse);
6889             }
6890         }
6891         Bind(&isNotFalse);
6892         Jump(&returnFalse);
6893     }
6894     Bind(&notSpecial);
6895     {
6896         BRANCH(TaggedIsNumber(value), &isNumber, &notNumber);
6897         Bind(&notNumber);
6898         {
6899             BRANCH(IsString(value), &isString, &notString);
6900             Bind(&isString);
6901             {
6902                 auto len = GetLengthFromString(value);
6903                 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
6904             }
6905             Bind(&notString);
6906             BRANCH(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
6907             Bind(&isBigint);
6908             {
6909                 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
6910                 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
6911                 Bind(&lengthIsOne);
6912                 {
6913                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
6914                     auto data0 = Load(VariableType::INT32(), data, Int32(0));
6915                     BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
6916                 }
6917             }
6918         }
6919         Bind(&isNumber);
6920         {
6921             callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
6922             BRANCH(TaggedIsInt(value), &isInt, &isDouble);
6923             Bind(&isInt);
6924             {
6925                 auto intValue = GetInt32OfTInt(value);
6926                 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
6927             }
6928             Bind(&isDouble);
6929             {
6930                 auto doubleValue = GetDoubleOfTDouble(value);
6931                 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
6932                 Bind(&notNan);
6933                 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
6934             }
6935         }
6936     }
6937     if (flag == 1) {
6938         Bind(&returnTrue);
6939         {
6940             result = TaggedTrue();
6941             Jump(&exit);
6942         }
6943         Bind(&returnFalse);
6944         {
6945             result = TaggedFalse();
6946             Jump(&exit);
6947         }
6948     } else {
6949         Bind(&returnFalse);
6950         {
6951             result = TaggedTrue();
6952             Jump(&exit);
6953         }
6954         Bind(&returnTrue);
6955         {
6956             result = TaggedFalse();
6957             Jump(&exit);
6958         }
6959     }
6960 
6961     Bind(&exit);
6962     auto ret = *result;
6963     env->SubCfgExit();
6964     return ret;
6965 }
6966 
FastToBooleanWithProfileBaseline(GateRef value,ProfileOperation callback,bool flag)6967 GateRef StubBuilder::FastToBooleanWithProfileBaseline(GateRef value, ProfileOperation callback, bool flag)
6968 {
6969     auto env = GetEnvironment();
6970     Label entry(env);
6971     env->SubCfgEntry(&entry);
6972     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6973     Label exit(env);
6974 
6975     Label isSpecial(env);
6976     Label notSpecial(env);
6977     Label isNumber(env);
6978     Label isInt(env);
6979     Label isDouble(env);
6980     Label notNumber(env);
6981     Label notNan(env);
6982     Label isString(env);
6983     Label notString(env);
6984     Label isBigint(env);
6985     Label lengthIsOne(env);
6986     Label returnTrue(env);
6987     Label returnFalse(env);
6988     Label isTrue(env);
6989     Label isNotTrue(env);
6990     Label isFalse(env);
6991     Label isNotFalse(env);
6992 
6993     Branch(TaggedIsSpecial(value), &isSpecial, &notSpecial);
6994     Bind(&isSpecial);
6995     {
6996         Branch(TaggedIsTrue(value), &isTrue, &isNotTrue);
6997         Bind(&isTrue);
6998         {
6999             callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
7000             Jump(&returnTrue);
7001         }
7002         Bind(&isNotTrue);
7003         {
7004             Branch(TaggedIsFalse(value), &isFalse, &isNotFalse);
7005             Bind(&isFalse);
7006             {
7007                 callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
7008                 Jump(&returnFalse);
7009             }
7010         }
7011         Bind(&isNotFalse);
7012         Jump(&returnFalse);
7013     }
7014     Bind(&notSpecial);
7015     {
7016         Branch(TaggedIsNumber(value), &isNumber, &notNumber);
7017         Bind(&notNumber);
7018         {
7019             Branch(IsString(value), &isString, &notString);
7020             Bind(&isString);
7021             {
7022                 auto len = GetLengthFromString(value);
7023                 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7024             }
7025             Bind(&notString);
7026             Branch(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
7027             Bind(&isBigint);
7028             {
7029                 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7030                 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7031                 Bind(&lengthIsOne);
7032                 {
7033                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7034                     auto data0 = Load(VariableType::INT32(), data, Int32(0));
7035                     Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7036                 }
7037             }
7038         }
7039         Bind(&isNumber);
7040         {
7041             callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
7042             Branch(TaggedIsInt(value), &isInt, &isDouble);
7043             Bind(&isInt);
7044             {
7045                 auto intValue = GetInt32OfTInt(value);
7046                 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7047             }
7048             Bind(&isDouble);
7049             {
7050                 auto doubleValue = GetDoubleOfTDouble(value);
7051                 Branch(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
7052                 Bind(&notNan);
7053                 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
7054             }
7055         }
7056     }
7057     if (flag == 1) {
7058         Bind(&returnTrue);
7059         {
7060             result = TaggedTrue();
7061             Jump(&exit);
7062         }
7063         Bind(&returnFalse);
7064         {
7065             result = TaggedFalse();
7066             Jump(&exit);
7067         }
7068     } else {
7069         Bind(&returnFalse);
7070         {
7071             result = TaggedTrue();
7072             Jump(&exit);
7073         }
7074         Bind(&returnTrue);
7075         {
7076             result = TaggedFalse();
7077             Jump(&exit);
7078         }
7079     }
7080 
7081     Bind(&exit);
7082     auto ret = *result;
7083     env->SubCfgExit();
7084     return ret;
7085 }
7086 
FastDiv(GateRef left,GateRef right,ProfileOperation callback)7087 GateRef StubBuilder::FastDiv(GateRef left, GateRef right, ProfileOperation callback)
7088 {
7089     auto env = GetEnvironment();
7090     Label entry(env);
7091     env->SubCfgEntry(&entry);
7092     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7093     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7094     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7095     DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::None()));
7096     Label leftIsNumber(env);
7097     Label leftNotNumberOrRightNotNumber(env);
7098     Label leftIsNumberAndRightIsNumber(env);
7099     Label leftIsDoubleAndRightIsDouble(env);
7100     Label exit(env);
7101     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
7102     Bind(&leftIsNumber);
7103     {
7104         Label rightIsNumber(env);
7105         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
7106         Bind(&rightIsNumber);
7107         {
7108             Label leftIsInt(env);
7109             Label leftNotInt(env);
7110             BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
7111             Bind(&leftIsInt);
7112             {
7113                 Label rightIsInt(env);
7114                 Label bailout(env);
7115                 BRANCH(TaggedIsInt(right), &rightIsInt, &bailout);
7116                 Bind(&rightIsInt);
7117                 {
7118                     result = FastIntDiv(left, right, &bailout, callback);
7119                     Jump(&exit);
7120                 }
7121                 Bind(&bailout);
7122                 {
7123                     curType = Int32(PGOSampleType::IntOverFlowType());
7124                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7125                     Jump(&leftIsNumberAndRightIsNumber);
7126                 }
7127             }
7128             Bind(&leftNotInt);
7129             {
7130                 curType = Int32(PGOSampleType::DoubleType());
7131                 doubleLeft = GetDoubleOfTDouble(left);
7132                 Jump(&leftIsNumberAndRightIsNumber);
7133             }
7134         }
7135     }
7136     Bind(&leftNotNumberOrRightNotNumber);
7137     {
7138         Jump(&exit);
7139     }
7140     Bind(&leftIsNumberAndRightIsNumber);
7141     {
7142         Label rightIsInt(env);
7143         Label rightNotInt(env);
7144         BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
7145         Bind(&rightIsInt);
7146         {
7147             GateRef type = Int32(PGOSampleType::IntType());
7148             COMBINE_TYPE_CALL_BACK(curType, type);
7149             doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7150             Jump(&leftIsDoubleAndRightIsDouble);
7151         }
7152         Bind(&rightNotInt);
7153         {
7154             GateRef type = Int32(PGOSampleType::DoubleType());
7155             COMBINE_TYPE_CALL_BACK(curType, type);
7156             doubleRight = GetDoubleOfTDouble(right);
7157             Jump(&leftIsDoubleAndRightIsDouble);
7158         }
7159     }
7160     Bind(&leftIsDoubleAndRightIsDouble);
7161     {
7162         Label rightIsZero(env);
7163         Label rightNotZero(env);
7164         BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZero, &rightNotZero);
7165         Bind(&rightIsZero);
7166         {
7167             Label leftIsZero(env);
7168             Label leftNotZero(env);
7169             Label leftIsZeroOrNan(env);
7170             Label leftNotZeroAndNotNan(env);
7171             BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZero, &leftNotZero);
7172             Bind(&leftIsZero);
7173             {
7174                 Jump(&leftIsZeroOrNan);
7175             }
7176             Bind(&leftNotZero);
7177             {
7178                 Label leftIsNan(env);
7179                 BRANCH(DoubleIsNAN(*doubleLeft), &leftIsNan, &leftNotZeroAndNotNan);
7180                 Bind(&leftIsNan);
7181                 {
7182                     Jump(&leftIsZeroOrNan);
7183                 }
7184             }
7185             Bind(&leftIsZeroOrNan);
7186             {
7187                 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
7188                 Jump(&exit);
7189             }
7190             Bind(&leftNotZeroAndNotNan);
7191             {
7192                 GateRef intLeftTmp = CastDoubleToInt64(*doubleLeft);
7193                 GateRef intRightTmp = CastDoubleToInt64(*doubleRight);
7194                 GateRef flagBit = Int64And(Int64Xor(intLeftTmp, intRightTmp), Int64(base::DOUBLE_SIGN_MASK));
7195                 GateRef tmpResult = Int64Xor(flagBit, CastDoubleToInt64(Double(base::POSITIVE_INFINITY)));
7196                 result = DoubleToTaggedDoublePtr(CastInt64ToFloat64(tmpResult));
7197                 Jump(&exit);
7198             }
7199         }
7200         Bind(&rightNotZero);
7201         {
7202             result = DoubleToTaggedDoublePtr(DoubleDiv(*doubleLeft, *doubleRight));
7203             Jump(&exit);
7204         }
7205     }
7206     Bind(&exit);
7207     auto ret = *result;
7208     env->SubCfgExit();
7209     return ret;
7210 }
7211 
NumberOperation(Environment * env,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)7212 GateRef StubBuilder::NumberOperation(Environment *env, GateRef left, GateRef right,
7213                                      const BinaryOperation& intOp,
7214                                      const BinaryOperation& floatOp,
7215                                      ProfileOperation callback)
7216 {
7217     Label entry(env);
7218     env->SubCfgEntry(&entry);
7219     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7220     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7221     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7222     Label exit(env);
7223     Label doFloatOp(env);
7224     Label doIntOp(env);
7225     Label leftIsNumber(env);
7226     Label leftIsIntRightIsDouble(env);
7227     Label rightIsDouble(env);
7228     Label rightIsInt(env);
7229     Label rightIsNumber(env);
7230     BRANCH(TaggedIsNumber(left), &leftIsNumber, &exit);
7231     Bind(&leftIsNumber);
7232     {
7233         BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
7234         Bind(&rightIsNumber);
7235         {
7236             Label leftIsInt(env);
7237             Label leftIsDouble(env);
7238             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
7239             Bind(&leftIsInt);
7240             {
7241                 BRANCH(TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
7242                 Bind(&leftIsIntRightIsDouble);
7243                 {
7244                     callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
7245                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7246                     doubleRight = GetDoubleOfTDouble(right);
7247                     Jump(&doFloatOp);
7248                 }
7249             }
7250             Bind(&leftIsDouble);
7251             {
7252                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
7253                 Bind(&rightIsInt);
7254                 {
7255                     callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
7256                     doubleLeft = GetDoubleOfTDouble(left);
7257                     doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7258                     Jump(&doFloatOp);
7259                 }
7260                 Bind(&rightIsDouble);
7261                 {
7262                     callback.ProfileOpType(Int32(PGOSampleType::DoubleType()));
7263                     doubleLeft = GetDoubleOfTDouble(left);
7264                     doubleRight = GetDoubleOfTDouble(right);
7265                     Jump(&doFloatOp);
7266                 }
7267             }
7268         }
7269     }
7270     Bind(&doIntOp);
7271     {
7272         result = intOp(env, left, right);
7273         Jump(&exit);
7274     }
7275     Bind(&doFloatOp);
7276     {
7277         result = floatOp(env, *doubleLeft, *doubleRight);
7278         Jump(&exit);
7279     }
7280     Bind(&exit);
7281     auto ret = *result;
7282     env->SubCfgExit();
7283     return ret;
7284 }
7285 
TryStringAdd(Environment * env,GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)7286 GateRef StubBuilder::TryStringAdd(Environment *env, GateRef glue, GateRef left, GateRef right,
7287                                   const BinaryOperation& intOp,
7288                                   const BinaryOperation& floatOp,
7289                                   ProfileOperation callback)
7290 {
7291     Label entry(env);
7292     env->SubCfgEntry(&entry);
7293     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7294     Label exit(env);
7295     Label leftIsNotSpecial(env);
7296     Label leftIsNotString(env);
7297     Label leftIsString(env);
7298     Label rightIsNotSpecial(env);
7299     Label rightIsNotString(env);
7300     Label rightIsString(env);
7301     Label stringLeftAddNumberRight(env);
7302     Label numberLeftAddStringRight(env);
7303     Label stringLeftAddStringRight(env);
7304     Label notStringAdd(env);
7305     BRANCH(TaggedIsString(left), &leftIsString, &leftIsNotString);
7306     Bind(&leftIsString);
7307     {
7308         BRANCH(TaggedIsString(right), &stringLeftAddStringRight, &rightIsNotString);
7309         Bind(&rightIsNotString);
7310         {
7311             BRANCH(TaggedIsSpecial(right), &notStringAdd, &rightIsNotSpecial);
7312             Bind(&rightIsNotSpecial);
7313             {
7314                 BRANCH(TaggedIsNumber(right), &stringLeftAddNumberRight, &notStringAdd);
7315             }
7316         }
7317     }
7318     Bind(&leftIsNotString);
7319     {
7320         BRANCH(TaggedIsString(right), &rightIsString, &notStringAdd);
7321         Bind(&rightIsString);
7322         {
7323             BRANCH(TaggedIsSpecial(left), &notStringAdd, &leftIsNotSpecial);
7324             Bind(&leftIsNotSpecial);
7325             {
7326                 BRANCH(TaggedIsNumber(left), &numberLeftAddStringRight, &notStringAdd);
7327             }
7328         }
7329     }
7330     Bind(&stringLeftAddNumberRight);
7331     {
7332         Label hasPendingException(env);
7333         // NOTICE-PGO: support string and number
7334         callback.ProfileOpType(Int32(PGOSampleType::NumberOrStringType()));
7335         BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
7336         result = builtinsStringStubBuilder.StringConcat(glue, left, NumberToString(glue, right));
7337         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
7338         Bind(&hasPendingException);
7339         result = Exception();
7340         Jump(&exit);
7341     }
7342     Bind(&numberLeftAddStringRight);
7343     {
7344         Label hasPendingException(env);
7345         // NOTICE-PGO: support string and number
7346         callback.ProfileOpType(Int32(PGOSampleType::NumberOrStringType()));
7347         BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
7348         result = builtinsStringStubBuilder.StringConcat(glue, NumberToString(glue, left), right);
7349         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
7350         Bind(&hasPendingException);
7351         result = Exception();
7352         Jump(&exit);
7353     }
7354     Bind(&stringLeftAddStringRight);
7355     {
7356         Label hasPendingException(env);
7357         callback.ProfileOpType(Int32(PGOSampleType::StringType()));
7358         BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
7359         result = builtinsStringStubBuilder.StringConcat(glue, left, right);
7360         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
7361         Bind(&hasPendingException);
7362         result = Exception();
7363         Jump(&exit);
7364     }
7365     Bind(&notStringAdd);
7366     {
7367         result = NumberOperation(env, left, right, intOp, floatOp, callback);
7368         Jump(&exit);
7369     }
7370     Bind(&exit);
7371     auto ret = *result;
7372     env->SubCfgExit();
7373     return ret;
7374 }
7375 
7376 template<OpCode Op>
FastBinaryOp(GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)7377 GateRef StubBuilder::FastBinaryOp(GateRef glue, GateRef left, GateRef right,
7378                                   const BinaryOperation& intOp,
7379                                   const BinaryOperation& floatOp,
7380                                   ProfileOperation callback)
7381 {
7382     auto env = GetEnvironment();
7383     Label entry(env);
7384     env->SubCfgEntry(&entry);
7385     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7386     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7387     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7388 
7389     if (Op == OpCode::ADD) { // Try string Add
7390         result = TryStringAdd(env, glue, left, right, intOp, floatOp, callback);
7391     } else {
7392         result = NumberOperation(env, left, right, intOp, floatOp, callback);
7393     }
7394     auto ret = *result;
7395     env->SubCfgExit();
7396     return ret;
7397 }
7398 
7399 template<OpCode Op>
FastAddSubAndMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7400 GateRef StubBuilder::FastAddSubAndMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7401 {
7402     auto intOperation = [=](Environment *env, GateRef left, GateRef right) {
7403         Label entry(env);
7404         env->SubCfgEntry(&entry);
7405         DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7406         Label exit(env);
7407         Label overflow(env);
7408         Label notOverflow(env);
7409         auto res = BinaryOpWithOverflow<Op, MachineType::I32>(GetInt32OfTInt(left), GetInt32OfTInt(right));
7410         GateRef condition = env->GetBuilder()->ExtractValue(MachineType::I1, res, Int32(1));
7411         BRANCH(condition, &overflow, &notOverflow);
7412         Bind(&overflow);
7413         {
7414             auto doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7415             auto doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7416             auto ret = BinaryOp<Op, MachineType::F64>(doubleLeft, doubleRight);
7417             result = DoubleToTaggedDoublePtr(ret);
7418             callback.ProfileOpType(Int32(PGOSampleType::IntOverFlowType()));
7419             Jump(&exit);
7420         }
7421         Bind(&notOverflow);
7422         {
7423             res = env->GetBuilder()->ExtractValue(MachineType::I32, res, Int32(0));
7424             if (Op == OpCode::MUL) {
7425                 Label resultIsZero(env);
7426                 Label returnNegativeZero(env);
7427                 Label returnResult(env);
7428                 BRANCH(Int32Equal(res, Int32(0)), &resultIsZero, &returnResult);
7429                 Bind(&resultIsZero);
7430                 BRANCH(LogicOrBuilder(env).Or(Int32LessThan(GetInt32OfTInt(left), Int32(0)))
7431                     .Or(Int32LessThan(GetInt32OfTInt(right), Int32(0))).Done(),
7432                     &returnNegativeZero, &returnResult);
7433                 Bind(&returnNegativeZero);
7434                 result = DoubleToTaggedDoublePtr(Double(-0.0));
7435                 callback.ProfileOpType(Int32(PGOSampleType::DoubleType()));
7436                 Jump(&exit);
7437                 Bind(&returnResult);
7438                 result = IntToTaggedPtr(res);
7439                 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7440                 Jump(&exit);
7441             } else {
7442                 result = IntToTaggedPtr(res);
7443                 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7444                 Jump(&exit);
7445             }
7446         }
7447         Bind(&exit);
7448         auto ret = *result;
7449         env->SubCfgExit();
7450         return ret;
7451     };
7452     auto floatOperation = [=]([[maybe_unused]] Environment *env, GateRef left, GateRef right) {
7453         auto res = BinaryOp<Op, MachineType::F64>(left, right);
7454         return DoubleToTaggedDoublePtr(res);
7455     };
7456     return FastBinaryOp<Op>(glue, left, right, intOperation, floatOperation, callback);
7457 }
7458 
FastIntDiv(GateRef left,GateRef right,Label * bailout,ProfileOperation callback)7459 GateRef StubBuilder::FastIntDiv(GateRef left, GateRef right, Label *bailout, ProfileOperation callback)
7460 {
7461     auto env = GetEnvironment();
7462     Label entry(env);
7463     env->SubCfgEntry(&entry);
7464     DEFVARIABLE(intResult, VariableType::INT32(), Int32(0));
7465 
7466     GateRef intLeft = GetInt32OfTInt(left);
7467     GateRef intRight = GetInt32OfTInt(right);
7468     Label exit(env);
7469     Label rightIsNotZero(env);
7470     Label leftIsIntMin(env);
7471     Label leftAndRightIsNotBoundary(env);
7472     BRANCH(Int32Equal(intRight, Int32(0)), bailout, &rightIsNotZero);
7473     Bind(&rightIsNotZero);
7474     BRANCH(Int32Equal(intLeft, Int32(INT_MIN)), &leftIsIntMin, &leftAndRightIsNotBoundary);
7475     Bind(&leftIsIntMin);
7476     BRANCH(Int32Equal(intRight, Int32(-1)), bailout, &leftAndRightIsNotBoundary);
7477     Bind(&leftAndRightIsNotBoundary);
7478     {
7479         Label leftIsZero(env);
7480         Label leftIsNotZero(env);
7481         BRANCH(Int32Equal(intLeft, Int32(0)), &leftIsZero, &leftIsNotZero);
7482         Bind(&leftIsZero);
7483         {
7484             BRANCH(Int32LessThan(intRight, Int32(0)), bailout, &leftIsNotZero);
7485         }
7486         Bind(&leftIsNotZero);
7487         {
7488             intResult = Int32Div(intLeft, intRight);
7489             GateRef truncated = Int32Mul(*intResult, intRight);
7490             BRANCH(Equal(intLeft, truncated), &exit, bailout);
7491         }
7492     }
7493     Bind(&exit);
7494     callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7495     auto ret = IntToTaggedPtr(*intResult);
7496     env->SubCfgExit();
7497     return ret;
7498 }
7499 
FastAdd(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7500 GateRef StubBuilder::FastAdd(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7501 {
7502     return FastAddSubAndMul<OpCode::ADD>(glue, left, right, callback);
7503 }
7504 
FastSub(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7505 GateRef StubBuilder::FastSub(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7506 {
7507     return FastAddSubAndMul<OpCode::SUB>(glue, left, right, callback);
7508 }
7509 
FastMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7510 GateRef StubBuilder::FastMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7511 {
7512     return FastAddSubAndMul<OpCode::MUL>(glue, left, right, callback);
7513 }
7514 
FastMod(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7515 GateRef StubBuilder::FastMod(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7516 {
7517     auto env = GetEnvironment();
7518     Label entry(env);
7519     env->SubCfgEntry(&entry);
7520     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7521     DEFVARIABLE(intLeft, VariableType::INT32(), Int32(0));
7522     DEFVARIABLE(intRight, VariableType::INT32(), Int32(0));
7523     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7524     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7525     Label leftIsInt(env);
7526     Label leftNotIntOrRightNotInt(env);
7527     Label exit(env);
7528     BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotIntOrRightNotInt);
7529     Bind(&leftIsInt);
7530     {
7531         Label rightIsInt(env);
7532         BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotIntOrRightNotInt);
7533         Bind(&rightIsInt);
7534         {
7535             intLeft = GetInt32OfTInt(left);
7536             intRight = GetInt32OfTInt(right);
7537             Label leftGreaterZero(env);
7538             BRANCH(Int32GreaterThanOrEqual(*intLeft, Int32(0)), &leftGreaterZero, &leftNotIntOrRightNotInt);
7539             Bind(&leftGreaterZero);
7540             {
7541                 Label rightGreaterZero(env);
7542                 BRANCH(Int32GreaterThan(*intRight, Int32(0)), &rightGreaterZero, &leftNotIntOrRightNotInt);
7543                 Bind(&rightGreaterZero);
7544                 {
7545                     callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7546                     result = IntToTaggedPtr(Int32Mod(*intLeft, *intRight));
7547                     Jump(&exit);
7548                 }
7549             }
7550         }
7551     }
7552     Bind(&leftNotIntOrRightNotInt);
7553     {
7554         Label leftIsNumber(env);
7555         Label leftNotNumberOrRightNotNumber(env);
7556         Label leftIsNumberAndRightIsNumber(env);
7557         Label leftIsDoubleAndRightIsDouble(env);
7558         DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::None()));
7559         // less than 0 result should be double
7560         curType = Int32(PGOSampleType::DoubleType());
7561         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
7562         Bind(&leftIsNumber);
7563         {
7564             Label rightIsNumber(env);
7565             BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
7566             Bind(&rightIsNumber);
7567             {
7568                 Label leftIsInt1(env);
7569                 Label leftNotInt1(env);
7570                 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
7571                 Bind(&leftIsInt1);
7572                 {
7573                     GateRef type = Int32(PGOSampleType::IntType());
7574                     COMBINE_TYPE_CALL_BACK(curType, type);
7575                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7576                     Jump(&leftIsNumberAndRightIsNumber);
7577                 }
7578                 Bind(&leftNotInt1);
7579                 {
7580                     GateRef type = Int32(PGOSampleType::DoubleType());
7581                     COMBINE_TYPE_CALL_BACK(curType, type);
7582                     doubleLeft = GetDoubleOfTDouble(left);
7583                     Jump(&leftIsNumberAndRightIsNumber);
7584                 }
7585             }
7586         }
7587         Bind(&leftNotNumberOrRightNotNumber);
7588         {
7589             Jump(&exit);
7590         }
7591         Bind(&leftIsNumberAndRightIsNumber);
7592         {
7593             Label rightIsInt1(env);
7594             Label rightNotInt1(env);
7595             BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
7596             Bind(&rightIsInt1);
7597             {
7598                 GateRef type = Int32(PGOSampleType::IntType());
7599                 COMBINE_TYPE_CALL_BACK(curType, type);
7600                 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7601                 Jump(&leftIsDoubleAndRightIsDouble);
7602             }
7603             Bind(&rightNotInt1);
7604             {
7605                 GateRef type = Int32(PGOSampleType::DoubleType());
7606                 COMBINE_TYPE_CALL_BACK(curType, type);
7607                 doubleRight = GetDoubleOfTDouble(right);
7608                 Jump(&leftIsDoubleAndRightIsDouble);
7609             }
7610         }
7611         Bind(&leftIsDoubleAndRightIsDouble);
7612         {
7613             Label rightNotZero(env);
7614             Label rightIsZeroOrNanOrLeftIsNanOrInf(env);
7615             Label rightNotZeroAndNanAndLeftNotNanAndInf(env);
7616             BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotZero);
7617             Bind(&rightNotZero);
7618             {
7619                 Label rightNotNan(env);
7620                 BRANCH(DoubleIsNAN(*doubleRight), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotNan);
7621                 Bind(&rightNotNan);
7622                 {
7623                     Label leftNotNan(env);
7624                     BRANCH(DoubleIsNAN(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf, &leftNotNan);
7625                     Bind(&leftNotNan);
7626                     {
7627                         BRANCH(DoubleIsINF(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf,
7628                             &rightNotZeroAndNanAndLeftNotNanAndInf);
7629                     }
7630                 }
7631             }
7632             Bind(&rightIsZeroOrNanOrLeftIsNanOrInf);
7633             {
7634                 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
7635                 Jump(&exit);
7636             }
7637             Bind(&rightNotZeroAndNanAndLeftNotNanAndInf);
7638             {
7639                 Label leftNotZero(env);
7640                 Label leftIsZeroOrRightIsInf(env);
7641                 BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZeroOrRightIsInf, &leftNotZero);
7642                 Bind(&leftNotZero);
7643                 {
7644                     Label rightNotInf(env);
7645                     BRANCH(DoubleIsINF(*doubleRight), &leftIsZeroOrRightIsInf, &rightNotInf);
7646                     Bind(&rightNotInf);
7647                     {
7648                         result = DoubleToTaggedDoublePtr(CallNGCRuntime(glue, RTSTUB_ID(FloatMod),
7649                             { *doubleLeft, *doubleRight }));
7650                         Jump(&exit);
7651                     }
7652                 }
7653                 Bind(&leftIsZeroOrRightIsInf);
7654                 {
7655                     result = DoubleToTaggedDoublePtr(*doubleLeft);
7656                     Jump(&exit);
7657                 }
7658             }
7659         }
7660     }
7661     Bind(&exit);
7662     auto ret = *result;
7663     env->SubCfgExit();
7664     return ret;
7665 }
7666 
GetGlobalOwnProperty(GateRef glue,GateRef receiver,GateRef key,ProfileOperation callback)7667 GateRef StubBuilder::GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRef key, ProfileOperation callback)
7668 {
7669     auto env = GetEnvironment();
7670     Label entryLabel(env);
7671     env->SubCfgEntry(&entryLabel);
7672     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7673     GateRef properties = GetPropertiesFromJSObject(receiver);
7674     GateRef entry = FindEntryFromNameDictionary(glue, properties, key);
7675     Label notNegtiveOne(env);
7676     Label exit(env);
7677     BRANCH(Int32NotEqual(entry, Int32(-1)), &notNegtiveOne, &exit);
7678     Bind(&notNegtiveOne);
7679     {
7680         result = GetValueFromGlobalDictionary(properties, entry);
7681         Label callGetter(env);
7682         BRANCH(TaggedIsAccessor(*result), &callGetter, &exit);
7683         Bind(&callGetter);
7684         {
7685             result = CallGetterHelper(glue, receiver, receiver, *result, callback);
7686             Jump(&exit);
7687         }
7688     }
7689     Bind(&exit);
7690     auto ret = *result;
7691     env->SubCfgExit();
7692     return ret;
7693 }
7694 
GetConstPoolFromFunction(GateRef jsFunc)7695 GateRef StubBuilder::GetConstPoolFromFunction(GateRef jsFunc)
7696 {
7697     return env_->GetBuilder()->GetConstPoolFromFunction(jsFunc);
7698 }
7699 
GetStringFromConstPool(GateRef glue,GateRef constpool,GateRef index)7700 GateRef StubBuilder::GetStringFromConstPool(GateRef glue, GateRef constpool, GateRef index)
7701 {
7702     GateRef module = Circuit::NullGate();
7703     GateRef hirGate = Circuit::NullGate();
7704     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
7705                                                       ConstPoolType::STRING);
7706 }
7707 
GetMethodFromConstPool(GateRef glue,GateRef constpool,GateRef index)7708 GateRef StubBuilder::GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index)
7709 {
7710     GateRef module = Circuit::NullGate();
7711     GateRef hirGate = Circuit::NullGate();
7712     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
7713                                                       ConstPoolType::METHOD);
7714 }
7715 
GetArrayLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)7716 GateRef StubBuilder::GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
7717 {
7718     GateRef hirGate = Circuit::NullGate();
7719     GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
7720     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
7721                                                       ConstPoolType::ARRAY_LITERAL);
7722 }
7723 
GetObjectLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)7724 GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
7725 {
7726     GateRef hirGate = Circuit::NullGate();
7727     GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
7728     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
7729                                                       ConstPoolType::OBJECT_LITERAL);
7730 }
7731 
JSAPIContainerGet(GateRef glue,GateRef receiver,GateRef index)7732 GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)
7733 {
7734     auto env = GetEnvironment();
7735     Label entry(env);
7736     env->SubCfgEntry(&entry);
7737     Label exit(env);
7738     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7739 
7740     GateRef lengthOffset = IntPtr(panda::ecmascript::JSAPIArrayList::LENGTH_OFFSET);
7741     GateRef length = GetInt32OfTInt(Load(VariableType::INT64(), receiver, lengthOffset));
7742     Label isVailedIndex(env);
7743     Label notValidIndex(env);
7744     BRANCH(BitAnd(Int32GreaterThanOrEqual(index, Int32(0)),
7745         Int32UnsignedLessThan(index, length)), &isVailedIndex, &notValidIndex);
7746     Bind(&isVailedIndex);
7747     {
7748         GateRef elements = GetElementsArray(receiver);
7749         result = GetValueFromTaggedArray(elements, index);
7750         Jump(&exit);
7751     }
7752     Bind(&notValidIndex);
7753     {
7754         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(GetPropertyOutOfBounds));
7755         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
7756         result = Exception();
7757         Jump(&exit);
7758     }
7759 
7760     Bind(&exit);
7761     auto ret = *result;
7762     env->SubCfgExit();
7763     return ret;
7764 }
7765 
GetEnumCacheKind(GateRef glue,GateRef enumCache)7766 GateRef StubBuilder::GetEnumCacheKind(GateRef glue, GateRef enumCache)
7767 {
7768     return env_->GetBuilder()->GetEnumCacheKind(glue, enumCache);
7769 }
7770 
IsEnumCacheValid(GateRef receiver,GateRef cachedHclass,GateRef kind)7771 GateRef StubBuilder::IsEnumCacheValid(GateRef receiver, GateRef cachedHclass, GateRef kind)
7772 {
7773     return env_->GetBuilder()->IsEnumCacheValid(receiver, cachedHclass, kind);
7774 }
7775 
NeedCheckProperty(GateRef receiver)7776 GateRef StubBuilder::NeedCheckProperty(GateRef receiver)
7777 {
7778     return env_->GetBuilder()->NeedCheckProperty(receiver);
7779 }
7780 
NextInternal(GateRef glue,GateRef iter)7781 GateRef StubBuilder::NextInternal(GateRef glue, GateRef iter)
7782 {
7783     auto env = GetEnvironment();
7784     Label entry(env);
7785     env->SubCfgEntry(&entry);
7786     Label exit(env);
7787     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
7788 
7789     Label notFinish(env);
7790     Label notEnumCacheValid(env);
7791     Label fastGetKey(env);
7792     Label slowpath(env);
7793 
7794     GateRef index = GetIndexFromForInIterator(iter);
7795     GateRef length = GetLengthFromForInIterator(iter);
7796     BRANCH(Int32GreaterThanOrEqual(index, length), &exit, &notFinish);
7797     Bind(&notFinish);
7798     GateRef keys = GetKeysFromForInIterator(iter);
7799     GateRef receiver = GetObjectFromForInIterator(iter);
7800     GateRef cachedHclass = GetCachedHclassFromForInIterator(iter);
7801     GateRef kind = GetEnumCacheKind(glue, keys);
7802     BRANCH(IsEnumCacheValid(receiver, cachedHclass, kind), &fastGetKey, &notEnumCacheValid);
7803     Bind(&notEnumCacheValid);
7804     BRANCH(NeedCheckProperty(receiver), &slowpath, &fastGetKey);
7805     Bind(&fastGetKey);
7806     {
7807         result = GetValueFromTaggedArray(keys, index);
7808         IncreaseInteratorIndex(glue, iter, index);
7809         Jump(&exit);
7810     }
7811     Bind(&slowpath);
7812     {
7813         result = CallRuntime(glue, RTSTUB_ID(GetNextPropNameSlowpath), { iter });
7814         Jump(&exit);
7815     }
7816     Bind(&exit);
7817     auto ret = *result;
7818     env->SubCfgExit();
7819     return ret;
7820 }
7821 
GetFunctionPrototype(GateRef glue,size_t index)7822 GateRef StubBuilder::GetFunctionPrototype(GateRef glue, size_t index)
7823 {
7824     auto env = GetEnvironment();
7825     Label entry(env);
7826     env->SubCfgEntry(&entry);
7827     Label exit(env);
7828     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
7829 
7830     Label isHeapObject(env);
7831     Label isJSHclass(env);
7832 
7833     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env_->Is32Bit()));
7834     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
7835     GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
7836     GateRef protoOrHclass = Load(VariableType::JS_ANY(), func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
7837     result = protoOrHclass;
7838     BRANCH(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &exit);
7839     Bind(&isHeapObject);
7840     BRANCH(IsJSHClass(protoOrHclass), &isJSHclass, &exit);
7841     Bind(&isJSHclass);
7842     {
7843         result = GetPrototypeFromHClass(protoOrHclass);
7844         Jump(&exit);
7845     }
7846     Bind(&exit);
7847     auto ret = *result;
7848     env->SubCfgExit();
7849     return ret;
7850 }
7851 
DeletePropertyOrThrow(GateRef glue,GateRef obj,GateRef value)7852 GateRef StubBuilder::DeletePropertyOrThrow(GateRef glue, GateRef obj, GateRef value)
7853 {
7854     auto env = GetEnvironment();
7855     Label entry(env);
7856     env->SubCfgEntry(&entry);
7857     Label exit(env);
7858     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
7859     DEFVARIABLE(key, VariableType::JS_ANY(), value);
7860     Label toObject(env);
7861     Label isNotExceptiont(env);
7862     Label objectIsEcmaObject(env);
7863     Label objectIsHeapObject(env);
7864     GateRef object = ToObject(glue, obj);
7865     BRANCH(TaggedIsException(object), &exit, &isNotExceptiont);
7866     Bind(&isNotExceptiont);
7867     {
7868         Label deleteProper(env);
7869         Label notStringOrSymbol(env);
7870         Label notPrimitive(env);
7871         BRANCH(TaggedIsStringOrSymbol(value), &deleteProper, &notStringOrSymbol);
7872         Bind(&notStringOrSymbol);
7873         {
7874             BRANCH(TaggedIsNumber(value), &deleteProper, &notPrimitive);
7875             Bind(&notPrimitive);
7876             {
7877                 key = CallRuntime(glue, RTSTUB_ID(ToPropertyKey), {value});
7878                 BRANCH(TaggedIsException(*key), &exit, &deleteProper);
7879             }
7880         }
7881         Bind(&deleteProper);
7882         {
7883             result = DeleteProperty(glue, object, *key);
7884             Jump(&exit);
7885         }
7886     }
7887     Bind(&exit);
7888     auto ret = *result;
7889     env->SubCfgExit();
7890     return ret;
7891 }
7892 
DeleteProperty(GateRef glue,GateRef obj,GateRef value)7893 GateRef StubBuilder::DeleteProperty(GateRef glue, GateRef obj, GateRef value)
7894 {
7895     auto env = GetEnvironment();
7896     Label entry(env);
7897     env->SubCfgEntry(&entry);
7898     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7899     Label exit(env);
7900     Label notRegularJSObject(env);
7901     Label regularJSObjDeletePrototype(env);
7902     BRANCH(TaggedIsRegularObject(obj), &regularJSObjDeletePrototype, &notRegularJSObject);
7903     Bind(&regularJSObjDeletePrototype);
7904     {
7905         result = CallRuntime(glue, RTSTUB_ID(RegularJSObjDeletePrototype), { obj, value});
7906         Jump(&exit);
7907     }
7908     Bind(&notRegularJSObject);
7909     {
7910         result = CallRuntime(glue, RTSTUB_ID(CallJSObjDeletePrototype), { obj, value});
7911         Jump(&exit);
7912     }
7913 
7914     Bind(&exit);
7915     auto ret = *result;
7916     env->SubCfgExit();
7917     return ret;
7918 }
7919 
ToPrototypeOrObj(GateRef glue,GateRef obj)7920 GateRef StubBuilder::ToPrototypeOrObj(GateRef glue, GateRef obj)
7921 {
7922     auto env = GetEnvironment();
7923     Label entry(env);
7924     env->SubCfgEntry(&entry);
7925     Label exit(env);
7926     DEFVARIABLE(result, VariableType::JS_ANY(), obj);
7927 
7928     Label isNumber(env);
7929     Label notNumber(env);
7930     Label isBoolean(env);
7931     Label notBoolean(env);
7932     Label isString(env);
7933     Label notString(env);
7934     Label isSymbol(env);
7935     Label notSymbol(env);
7936     Label isBigInt(env);
7937     BRANCH(TaggedIsNumber(obj), &isNumber, &notNumber);
7938     Bind(&isNumber);
7939     {
7940         result = GetFunctionPrototype(glue, GlobalEnv::NUMBER_FUNCTION_INDEX);
7941         Jump(&exit);
7942     }
7943     Bind(&notNumber);
7944     BRANCH(TaggedIsBoolean(obj), &isBoolean, &notBoolean);
7945     Bind(&isBoolean);
7946     {
7947         result = GetFunctionPrototype(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
7948         Jump(&exit);
7949     }
7950     Bind(&notBoolean);
7951     BRANCH(TaggedIsString(obj), &isString, &notString);
7952     Bind(&isString);
7953     {
7954         result = GetFunctionPrototype(glue, GlobalEnv::STRING_FUNCTION_INDEX);
7955         Jump(&exit);
7956     }
7957     Bind(&notString);
7958     BRANCH(TaggedIsSymbol(obj), &isSymbol, &notSymbol);
7959     Bind(&isSymbol);
7960     {
7961         result = GetFunctionPrototype(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX);
7962         Jump(&exit);
7963     }
7964     Bind(&notSymbol);
7965     BRANCH(TaggedIsBigInt(obj), &isBigInt, &exit);
7966     Bind(&isBigInt);
7967     {
7968         result = GetFunctionPrototype(glue, GlobalEnv::BIGINT_FUNCTION_INDEX);
7969         Jump(&exit);
7970     }
7971     Bind(&exit);
7972     auto ret = *result;
7973     env->SubCfgExit();
7974     return ret;
7975 }
7976 
IsSpecialKeysObject(GateRef obj)7977 GateRef StubBuilder::IsSpecialKeysObject(GateRef obj)
7978 {
7979     return LogicOrBuilder(env_).Or(IsTypedArray(obj)).Or(IsModuleNamespace(obj)).Or(ObjIsSpecialContainer(obj)).Done();
7980 }
7981 
IsSlowKeysObject(GateRef obj)7982 GateRef StubBuilder::IsSlowKeysObject(GateRef obj)
7983 {
7984     auto env = GetEnvironment();
7985     Label entry(env);
7986     env->SubCfgEntry(&entry);
7987     Label exit(env);
7988     DEFVARIABLE(result, VariableType::BOOL(), False());
7989 
7990     Label isHeapObject(env);
7991     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
7992     Bind(&isHeapObject);
7993     {
7994         result = LogicOrBuilder(env).Or(IsJSGlobalObject(obj)).Or(IsJsProxy(obj)).Or(IsSpecialKeysObject(obj)).Done();
7995         Jump(&exit);
7996     }
7997     Bind(&exit);
7998     auto ret = *result;
7999     env->SubCfgExit();
8000     return ret;
8001 }
8002 
GetNumberOfElements(GateRef obj)8003 GateRef StubBuilder::GetNumberOfElements(GateRef obj)
8004 {
8005     auto env = GetEnvironment();
8006     Label entry(env);
8007     env->SubCfgEntry(&entry);
8008     Label exit(env);
8009     DEFVARIABLE(numOfElements, VariableType::INT32(), Int32(0));
8010     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
8011 
8012     Label isJSPrimitiveRef(env);
8013     Label isPrimitiveString(env);
8014     Label notPrimitiveString(env);
8015     Label isDictMode(env);
8016     Label notDictMode(env);
8017 
8018     BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, &notPrimitiveString);
8019     Bind(&isJSPrimitiveRef);
8020     GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
8021     BRANCH(TaggedIsString(value), &isPrimitiveString, &notPrimitiveString);
8022     Bind(&isPrimitiveString);
8023     {
8024         numOfElements = GetLengthFromString(value);
8025         Jump(&notPrimitiveString);
8026     }
8027     Bind(&notPrimitiveString);
8028     GateRef elements = GetElementsArray(obj);
8029     BRANCH(IsDictionaryMode(elements), &isDictMode, &notDictMode);
8030     Bind(&notDictMode);
8031     {
8032         Label loopHead(env);
8033         Label loopEnd(env);
8034         Label iLessLength(env);
8035         Label notHole(env);
8036         GateRef elementsLen = GetLengthOfTaggedArray(elements);
8037         Jump(&loopHead);
8038         LoopBegin(&loopHead);
8039         {
8040             BRANCH(Int32UnsignedLessThan(*i, elementsLen), &iLessLength, &exit);
8041             Bind(&iLessLength);
8042             {
8043                 GateRef element = GetTaggedValueWithElementsKind(obj, *i);
8044                 BRANCH(TaggedIsHole(element), &loopEnd, &notHole);
8045                 Bind(&notHole);
8046                 numOfElements = Int32Add(*numOfElements, Int32(1));
8047                 Jump(&loopEnd);
8048             }
8049             Bind(&loopEnd);
8050             i = Int32Add(*i, Int32(1));
8051             LoopEnd(&loopHead);
8052         }
8053     }
8054     Bind(&isDictMode);
8055     {
8056         GateRef entryCount = TaggedGetInt(
8057             GetValueFromTaggedArray(elements, Int32(TaggedHashTable<NumberDictionary>::NUMBER_OF_ENTRIES_INDEX)));
8058         numOfElements = Int32Add(*numOfElements, entryCount);
8059         Jump(&exit);
8060     }
8061     Bind(&exit);
8062     auto ret = *numOfElements;
8063     env->SubCfgExit();
8064     return ret;
8065 }
8066 
IsSimpleEnumCacheValid(GateRef obj)8067 GateRef StubBuilder::IsSimpleEnumCacheValid(GateRef obj)
8068 {
8069     auto env = GetEnvironment();
8070     Label entry(env);
8071     env->SubCfgEntry(&entry);
8072     Label exit(env);
8073     DEFVARIABLE(result, VariableType::BOOL(), False());
8074     DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
8075 
8076     Label receiverHasNoElements(env);
8077 
8078     GateRef numOfElements = GetNumberOfElements(obj);
8079     BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
8080     Bind(&receiverHasNoElements);
8081     {
8082         Label loopHead(env);
8083         Label loopEnd(env);
8084         Label afterLoop(env);
8085         Label currentHasNoElements(env);
8086         Label enumCacheIsUndefined(env);
8087         current = GetPrototypeFromHClass(LoadHClass(obj));
8088         BRANCH(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
8089         LoopBegin(&loopHead);
8090         {
8091             GateRef numOfCurrentElements = GetNumberOfElements(*current);
8092             BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, &currentHasNoElements);
8093             Bind(&currentHasNoElements);
8094             GateRef hclass = LoadHClass(*current);
8095             GateRef protoEnumCache = GetEnumCacheFromHClass(hclass);
8096             BRANCH(TaggedIsUndefined(protoEnumCache), &enumCacheIsUndefined, &exit);
8097             Bind(&enumCacheIsUndefined);
8098             current = GetPrototypeFromHClass(hclass);
8099             BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
8100         }
8101         Bind(&loopEnd);
8102         LoopEnd(&loopHead);
8103         Bind(&afterLoop);
8104         {
8105             result = True();
8106             Jump(&exit);
8107         }
8108     }
8109     Bind(&exit);
8110     auto ret = *result;
8111     env->SubCfgExit();
8112     return ret;
8113 }
8114 
IsEnumCacheWithProtoChainInfoValid(GateRef obj)8115 GateRef StubBuilder::IsEnumCacheWithProtoChainInfoValid(GateRef obj)
8116 {
8117     auto env = GetEnvironment();
8118     Label entry(env);
8119     env->SubCfgEntry(&entry);
8120     Label exit(env);
8121     DEFVARIABLE(result, VariableType::BOOL(), False());
8122     DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
8123 
8124     Label receiverHasNoElements(env);
8125     Label prototypeIsEcmaObj(env);
8126     Label isProtoChangeMarker(env);
8127     Label protoNotChanged(env);
8128 
8129     GateRef numOfElements = GetNumberOfElements(obj);
8130     BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
8131     Bind(&receiverHasNoElements);
8132     GateRef prototype = GetPrototypeFromHClass(LoadHClass(obj));
8133     BRANCH(IsEcmaObject(prototype), &prototypeIsEcmaObj, &exit);
8134     Bind(&prototypeIsEcmaObj);
8135     GateRef protoChangeMarker = GetProtoChangeMarkerFromHClass(LoadHClass(prototype));
8136     BRANCH(TaggedIsProtoChangeMarker(protoChangeMarker), &isProtoChangeMarker, &exit);
8137     Bind(&isProtoChangeMarker);
8138     BRANCH(GetHasChanged(protoChangeMarker), &exit, &protoNotChanged);
8139     Bind(&protoNotChanged);
8140     {
8141         Label loopHead(env);
8142         Label loopEnd(env);
8143         Label afterLoop(env);
8144         Label currentHasNoElements(env);
8145         current = prototype;
8146         BRANCH(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
8147         LoopBegin(&loopHead);
8148         {
8149             GateRef numOfCurrentElements = GetNumberOfElements(*current);
8150             BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, &currentHasNoElements);
8151             Bind(&currentHasNoElements);
8152             current = GetPrototypeFromHClass(LoadHClass(*current));
8153             BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
8154         }
8155         Bind(&loopEnd);
8156         LoopEnd(&loopHead);
8157         Bind(&afterLoop);
8158         {
8159             result = True();
8160             Jump(&exit);
8161         }
8162     }
8163     Bind(&exit);
8164     auto ret = *result;
8165     env->SubCfgExit();
8166     return ret;
8167 }
8168 
TryGetEnumCache(GateRef glue,GateRef obj)8169 GateRef StubBuilder::TryGetEnumCache(GateRef glue, GateRef obj)
8170 {
8171     auto env = GetEnvironment();
8172     Label entry(env);
8173     env->SubCfgEntry(&entry);
8174     Label exit(env);
8175     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8176 
8177     Label notSlowKeys(env);
8178     Label notDictionaryMode(env);
8179     Label checkSimpleEnumCache(env);
8180     Label notSimpleEnumCache(env);
8181     Label checkEnumCacheWithProtoChainInfo(env);
8182     Label enumCacheValid(env);
8183 
8184     BRANCH(IsSlowKeysObject(obj), &exit, &notSlowKeys);
8185     Bind(&notSlowKeys);
8186     GateRef hclass = LoadHClass(obj);
8187     BRANCH(IsDictionaryModeByHClass(hclass), &exit, &notDictionaryMode);
8188     Bind(&notDictionaryMode);
8189     GateRef enumCache = GetEnumCacheFromHClass(hclass);
8190     GateRef kind = GetEnumCacheKind(glue, enumCache);
8191     BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE))),
8192            &checkSimpleEnumCache, &notSimpleEnumCache);
8193     Bind(&checkSimpleEnumCache);
8194     {
8195         BRANCH(IsSimpleEnumCacheValid(obj), &enumCacheValid, &exit);
8196     }
8197     Bind(&notSimpleEnumCache);
8198     BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::PROTOCHAIN))),
8199            &checkEnumCacheWithProtoChainInfo, &exit);
8200     Bind(&checkEnumCacheWithProtoChainInfo);
8201     {
8202         BRANCH(IsEnumCacheWithProtoChainInfoValid(obj), &enumCacheValid, &exit);
8203     }
8204     Bind(&enumCacheValid);
8205     {
8206         result = enumCache;
8207         Jump(&exit);
8208     }
8209     Bind(&exit);
8210     auto ret = *result;
8211     env->SubCfgExit();
8212     return ret;
8213 }
8214 
DoubleToInt(GateRef glue,GateRef x,size_t typeBits)8215 GateRef StubBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits)
8216 {
8217     auto env = GetEnvironment();
8218     Label entry(env);
8219     env->SubCfgEntry(&entry);
8220     Label exit(env);
8221     Label overflow(env);
8222 
8223     GateRef xInt = ChangeFloat64ToInt32(x);
8224     DEFVARIABLE(result, VariableType::INT32(), xInt);
8225 
8226     if (env->IsAmd64()) {
8227         // 0x80000000: amd64 overflow return value
8228         BRANCH(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit);
8229     } else {
8230         GateRef xInt64 = CastDoubleToInt64(x);
8231         // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
8232         GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
8233         exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
8234         exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
8235         GateRef bits = Int32(typeBits - 1);
8236         // exp < 32 - 1
8237         BRANCH(Int32LessThan(exp, bits), &exit, &overflow);
8238     }
8239     Bind(&overflow);
8240     {
8241         result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), { x, IntPtr(typeBits) });
8242         Jump(&exit);
8243     }
8244     Bind(&exit);
8245     auto ret = *result;
8246     env->SubCfgExit();
8247     return ret;
8248 }
8249 
ReturnExceptionIfAbruptCompletion(GateRef glue)8250 void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue)
8251 {
8252     auto env = GetEnvironment();
8253     Label entry(env);
8254     env->SubCfgEntry(&entry);
8255     Label exit(env);
8256     Label hasPendingException(env);
8257     GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env->IsArch32Bit()));
8258     GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
8259     BRANCH(TaggedIsNotHole(exception), &hasPendingException, &exit);
8260     Bind(&hasPendingException);
8261     Return(Exception());
8262     Bind(&exit);
8263     env->SubCfgExit();
8264     return;
8265 }
8266 
CalcHashcodeForInt(GateRef value)8267 GateRef StubBuilder::CalcHashcodeForInt(GateRef value)
8268 {
8269     return env_->GetBuilder()->CalcHashcodeForInt(value);
8270 }
8271 
CanDoubleRepresentInt(GateRef exp,GateRef expBits,GateRef fractionBits)8272 GateRef StubBuilder::CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits)
8273 {
8274     return LogicOrBuilder(env_)
8275         .Or(Int64Equal(expBits, Int64(base::DOUBLE_EXPONENT_MASK)))
8276         .Or(BitAnd(Int64Equal(expBits, Int64(0)), Int64NotEqual(fractionBits, Int64(0))))
8277         .Or(Int64LessThan(exp, Int64(0)))
8278         .Or(Int64GreaterThanOrEqual(exp, Int64(31U)))
8279         .Or(Int64NotEqual(Int64And(Int64LSL(fractionBits, exp), Int64(base::DOUBLE_SIGNIFICAND_MASK)),
8280                           Int64(0)))
8281         .Done();
8282 }
8283 
CalcHashcodeForDouble(GateRef x,Variable * res,Label * exit)8284 void StubBuilder::CalcHashcodeForDouble(GateRef x, Variable *res, Label *exit)
8285 {
8286     auto env = GetEnvironment();
8287     GateRef xInt64 = Int64Sub(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
8288     GateRef fractionBits = Int64And(xInt64, Int64(base::DOUBLE_SIGNIFICAND_MASK));
8289     GateRef expBits = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
8290     GateRef isZero = BitAnd(
8291         Int64Equal(expBits, Int64(0)),
8292         Int64Equal(fractionBits, Int64(0)));
8293     Label zero(env);
8294     Label nonZero(env);
8295 
8296     BRANCH(isZero, &zero, &nonZero);
8297     Bind(&nonZero);
8298     {
8299         DEFVARIABLE(value, VariableType::JS_ANY(), x);
8300         // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
8301         GateRef exp = Int64Sub(
8302             Int64LSR(expBits, Int64(base::DOUBLE_SIGNIFICAND_SIZE)),
8303             Int64(base::DOUBLE_EXPONENT_BIAS));
8304         Label convertToInt(env);
8305         Label calcHash(env);
8306         BRANCH(CanDoubleRepresentInt(exp, expBits, fractionBits), &calcHash, &convertToInt);
8307         Bind(&convertToInt);
8308         {
8309             *res = ChangeFloat64ToInt32(CastInt64ToFloat64(xInt64));
8310             Jump(exit);
8311         }
8312         Bind(&calcHash);
8313         {
8314             *res = env_->GetBuilder()->CalcHashcodeForInt(*value);
8315             Jump(exit);
8316         }
8317     }
8318 
8319     Bind(&zero);
8320     *res = Int32(0);
8321     Jump(exit);
8322 }
8323 
GetHash(GateRef object)8324 GateRef StubBuilder::GetHash(GateRef object)
8325 {
8326     auto env = GetEnvironment();
8327     Label subentry(env);
8328     Label isHeapObject(env);
8329     Label exit(env);
8330     env->SubCfgEntry(&subentry);
8331     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
8332     GateRef value = Load(VariableType::JS_ANY(), object, hashOffset);
8333     DEFVARIABLE(res, VariableType::INT32(), GetInt32OfTInt(value));
8334     BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit);
8335 
8336     Bind(&isHeapObject);
8337     {
8338         Label isTaggedArray(env);
8339         Label notTaggedArray(env);
8340         BRANCH(IsTaggedArray(value), &isTaggedArray, &notTaggedArray);
8341         Bind(&isTaggedArray);
8342         GateRef extlen = GetExtraLengthOfTaggedArray(value);
8343         GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
8344         res = GetInt32OfTInt(GetValueFromTaggedArray(value, index));
8345         Jump(&exit);
8346         Bind(&notTaggedArray);
8347         res = Int32(0);
8348         Jump(&exit);
8349     }
8350     Bind(&exit);
8351     auto ret = *res;
8352     env->SubCfgExit();
8353     return ret;
8354 }
8355 
SetHash(GateRef glue,GateRef object,GateRef hash)8356 void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash)
8357 {
8358     auto env = GetEnvironment();
8359     Label subentry(env);
8360     Label isHeapObject(env);
8361     Label notHeapObject(env);
8362     Label exit(env);
8363     env->SubCfgEntry(&subentry);
8364     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
8365     GateRef value = Load(VariableType::JS_ANY(), object, hashOffset);
8366     DEFVARIABLE(res, VariableType::JS_ANY(), object);
8367     BRANCH(TaggedIsHeapObject(value), &isHeapObject, &notHeapObject);
8368 
8369     Bind(&isHeapObject);
8370     {
8371         Label isTaggedArray(env);
8372         Label notTaggedArray(env);
8373         BRANCH(IsTaggedArray(value), &isTaggedArray, &notTaggedArray);
8374         Bind(&isTaggedArray);
8375         {
8376             GateRef extlen = GetExtraLengthOfTaggedArray(value);
8377             GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
8378             SetValueToTaggedArray(VariableType::JS_ANY(), glue, value, index, IntToTaggedInt(hash));
8379             Jump(&exit);
8380         }
8381         Bind(&notTaggedArray);
8382         {
8383             Label isNativePointer(env);
8384             Label notNativePointer(env);
8385             BRANCH(IsNativePointer(value), &isNativePointer, &notNativePointer);
8386             Bind(&isNativePointer);
8387             {
8388                 NewObjectStubBuilder newBuilder(this);
8389                 GateRef array = newBuilder.NewTaggedArray(glue, Int32(ECMAObject::RESOLVED_MAX_SIZE));
8390                 SetExtraLengthOfTaggedArray(glue, array, Int32(0));
8391                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
8392                                       Int32(ECMAObject::HASH_INDEX), IntToTaggedInt(hash));
8393                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
8394                                       Int32(ECMAObject::FUNCTION_EXTRA_INDEX), value);
8395                 Store(VariableType::JS_ANY(), glue, object, hashOffset, array);
8396                 Jump(&exit);
8397             }
8398             Bind(&notNativePointer);
8399             FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
8400             Jump(&exit);
8401         }
8402     }
8403     Bind(&notHeapObject);
8404     {
8405         Store(VariableType::JS_ANY(), glue, object, hashOffset, IntToTaggedInt(hash), MemoryAttribute::NoBarrier());
8406         Jump(&exit);
8407     }
8408     Bind(&exit);
8409     env->SubCfgExit();
8410 }
8411 
CalcHashcodeForObject(GateRef glue,GateRef value,Variable * res,Label * exit)8412 void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit)
8413 {
8414     auto env = GetEnvironment();
8415 
8416     GateRef hash = GetHash(value);
8417     *res = hash;
8418     Label calcHash(env);
8419     BRANCH(Int32Equal(**res, Int32(0)), &calcHash, exit);
8420     Bind(&calcHash);
8421     GateRef offset = IntPtr(JSThread::GlueData::GetRandomStatePtrOffset(env_->Is32Bit()));
8422     GateRef randomStatePtr = Load(VariableType::NATIVE_POINTER(), glue, offset);
8423     GateRef randomState = Load(VariableType::INT64(), randomStatePtr, IntPtr(0));
8424     GateRef k1 = Int64Xor(randomState, Int64LSR(randomState, Int64(base::RIGHT12)));
8425     GateRef k2 = Int64Xor(k1, Int64LSL(k1, Int64(base::LEFT25)));
8426     GateRef k3 = Int64Xor(k2, Int64LSR(k2, Int64(base::RIGHT27)));
8427     Store(VariableType::INT64(), glue, randomStatePtr, IntPtr(0), k3);
8428     GateRef k4 = Int64Mul(k3, Int64(base::GET_MULTIPLY));
8429     GateRef k5 = Int64LSR(k4, Int64(base::INT64_BITS - base::INT32_BITS));
8430     GateRef k6 = Int32And(TruncInt64ToInt32(k5), Int32(INT32_MAX));
8431     SetHash(glue, value, k6);
8432     *res = k6;
8433     Jump(exit);
8434 }
8435 
GetHashcodeFromString(GateRef glue,GateRef value,GateRef hir)8436 GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir)
8437 {
8438     return env_->GetBuilder()->GetHashcodeFromString(glue, value, hir);
8439 }
8440 
ConstructorCheck(GateRef glue,GateRef ctor,GateRef outPut,GateRef thisObj)8441 GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj)
8442 {
8443     auto env = GetEnvironment();
8444     Label entryPass(env);
8445     Label exit(env);
8446     env->SubCfgEntry(&entryPass);
8447     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
8448     Label isHeapObject(env);
8449     Label isEcmaObj(env);
8450     Label notEcmaObj(env);
8451     BRANCH(TaggedIsHeapObject(outPut), &isHeapObject, &notEcmaObj);
8452     Bind(&isHeapObject);
8453     BRANCH(TaggedObjectIsEcmaObject(outPut), &isEcmaObj, &notEcmaObj);
8454     Bind(&isEcmaObj);
8455     {
8456         result = outPut;
8457         Jump(&exit);
8458     }
8459     Bind(&notEcmaObj);
8460     {
8461         Label ctorIsBase(env);
8462         Label ctorNotBase(env);
8463         BRANCH(IsBase(ctor), &ctorIsBase, &ctorNotBase);
8464         Bind(&ctorIsBase);
8465         {
8466             result = thisObj;
8467             Jump(&exit);
8468         }
8469         Bind(&ctorNotBase);
8470         {
8471             Label throwExeption(env);
8472             Label returnObj(env);
8473             BRANCH(TaggedIsUndefined(outPut), &returnObj, &throwExeption);
8474             Bind(&returnObj);
8475             result = thisObj;
8476             Jump(&exit);
8477             Bind(&throwExeption);
8478             {
8479                 CallRuntime(glue, RTSTUB_ID(ThrowNonConstructorException), {});
8480                 Jump(&exit);
8481             }
8482         }
8483     }
8484     Bind(&exit);
8485     auto ret = *result;
8486     env->SubCfgExit();
8487     return ret;
8488 }
8489 
CalIteratorKey(GateRef glue)8490 GateRef StubBuilder::CalIteratorKey(GateRef glue)
8491 {
8492     auto env = GetEnvironment();
8493     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
8494     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
8495     GateRef iteratorKey = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ITERATOR_SYMBOL_INDEX);
8496     return iteratorKey;
8497 }
8498 
GetIterator(GateRef glue,GateRef obj,ProfileOperation callback)8499 GateRef StubBuilder::GetIterator(GateRef glue, GateRef obj, ProfileOperation callback)
8500 {
8501     auto env = GetEnvironment();
8502     Label entryPass(env);
8503     Label exit(env);
8504     env->SubCfgEntry(&entryPass);
8505     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
8506     DEFVARIABLE(taggedId, VariableType::INT32(), Int32(0));
8507 
8508     Label isPendingException(env);
8509     Label noPendingException(env);
8510     Label isHeapObject(env);
8511     Label objIsCallable(env);
8512     Label throwError(env);
8513     Label callExit(env);
8514 
8515     GateRef iteratorKey = CalIteratorKey(glue);
8516     result = FastGetPropertyByName(glue, obj, iteratorKey, ProfileOperation());
8517     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
8518     Bind(&isPendingException);
8519     {
8520         result = Exception();
8521         Jump(&exit);
8522     }
8523     Bind(&noPendingException);
8524     callback.ProfileGetIterator(*result);
8525     BRANCH(TaggedIsHeapObject(*result), &isHeapObject, &throwError);
8526     Bind(&isHeapObject);
8527     BRANCH(IsCallable(*result), &objIsCallable, &throwError);
8528     Bind(&objIsCallable);
8529     {
8530         JSCallArgs callArgs(JSCallMode::CALL_GETTER);
8531         callArgs.callGetterArgs = { obj };
8532         CallStubBuilder callBuilder(this, glue, *result, Int32(0), 0, &result, Circuit::NullGate(), callArgs,
8533             ProfileOperation());
8534         if (env->IsBaselineBuiltin()) {
8535             callBuilder.JSCallDispatchForBaseline(&callExit);
8536             Bind(&callExit);
8537         } else {
8538             result = callBuilder.JSCallDispatch();
8539         }
8540         Jump(&exit);
8541     }
8542     Bind(&throwError);
8543     {
8544         taggedId = Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable));
8545         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(*taggedId) });
8546         result = Exception();
8547         Jump(&exit);
8548     }
8549     Bind(&exit);
8550     auto ret = *result;
8551     env->SubCfgExit();
8552     return ret;
8553 }
8554 
TryStringOrSymbolToElementIndex(GateRef glue,GateRef key)8555 GateRef StubBuilder::TryStringOrSymbolToElementIndex(GateRef glue, GateRef key)
8556 {
8557     auto env = GetEnvironment();
8558     Label entry(env);
8559     env->SubCfgEntry(&entry);
8560     Label exit(env);
8561     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
8562 
8563     Label keyNotSymbol(env);
8564     BRANCH(IsSymbol(key), &exit, &keyNotSymbol);
8565     Bind(&keyNotSymbol);
8566 
8567     Label greatThanZero(env);
8568     Label inRange(env);
8569     Label flattenFastPath(env);
8570     auto len = GetLengthFromString(key);
8571     BRANCH(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
8572     Bind(&greatThanZero);
8573     BRANCH(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
8574     Bind(&inRange);
8575     {
8576         Label isUtf8(env);
8577         DEFVARIABLE(c, VariableType::INT32(), Int32(0));
8578         BRANCH(IsUtf16String(key), &exit, &isUtf8);
8579         Bind(&isUtf8);
8580         FlatStringStubBuilder thisFlat(this);
8581         thisFlat.FlattenString(glue, key, &flattenFastPath);
8582         Bind(&flattenFastPath);
8583         StringInfoGateRef stringInfoGate(&thisFlat);
8584         GateRef data = GetNormalStringData(stringInfoGate);
8585         c = ZExtInt8ToInt32(Load(VariableType::INT8(), data));
8586         Label isDigitZero(env);
8587         Label notDigitZero(env);
8588         BRANCH(Int32Equal(*c, Int32('0')), &isDigitZero, &notDigitZero);
8589         Bind(&isDigitZero);
8590         {
8591             Label lengthIsOne(env);
8592             BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
8593             Bind(&lengthIsOne);
8594             {
8595                 result = Int32(0);
8596                 Jump(&exit);
8597             }
8598         }
8599         Bind(&notDigitZero);
8600         {
8601             Label isDigit(env);
8602             Label notIsDigit(env);
8603             DEFVARIABLE(i, VariableType::INT32(), Int32(1));
8604             DEFVARIABLE(n, VariableType::INT64(), Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
8605 
8606             BRANCH(IsDigit(*c), &isDigit, &notIsDigit);
8607             Label loopHead(env);
8608             Label loopEnd(env);
8609             Label afterLoop(env);
8610             Bind(&isDigit);
8611             BRANCH(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
8612             LoopBegin(&loopHead);
8613             {
8614                 c = ZExtInt8ToInt32(Load(VariableType::INT8(), data, ZExtInt32ToPtr(*i)));
8615                 Label isDigit2(env);
8616                 Label notDigit2(env);
8617                 BRANCH(IsDigit(*c), &isDigit2, &notDigit2);
8618                 Bind(&isDigit2);
8619                 {
8620                     // 10 means the base of digit is 10.
8621                     n = Int64Add(Int64Mul(*n, Int64(10)),
8622                                  Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
8623                     i = Int32Add(*i, Int32(1));
8624                     BRANCH(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
8625                 }
8626                 Bind(&notDigit2);
8627                 {
8628                     Label hasPoint(env);
8629                     BRANCH(Int32Equal(*c, Int32('.')), &hasPoint, &exit);
8630                     Bind(&hasPoint);
8631                     {
8632                         result = Int32(-2); // -2:return -2 means should goto slow path
8633                         Jump(&exit);
8634                     }
8635                 }
8636             }
8637             Bind(&loopEnd);
8638             LoopEnd(&loopHead, env, glue);
8639             Bind(&afterLoop);
8640             {
8641                 Label lessThanMaxIndex(env);
8642                 BRANCH(Int64LessThan(*n, Int64(JSObject::MAX_ELEMENT_INDEX)),
8643                        &lessThanMaxIndex, &exit);
8644                 Bind(&lessThanMaxIndex);
8645                 {
8646                     result = TruncInt64ToInt32(*n);
8647                     Jump(&exit);
8648                 }
8649             }
8650             Bind(&notIsDigit);
8651             {
8652                 Label isNegative(env);
8653                 BRANCH(Int32Equal(*c, Int32('-')), &isNegative, &exit);
8654                 Bind(&isNegative);
8655                 {
8656                     result = Int32(-2); // -2:return -2 means should goto slow path
8657                     Jump(&exit);
8658                 }
8659             }
8660         }
8661     }
8662     Bind(&exit);
8663     auto ret = *result;
8664     env->SubCfgExit();
8665     return ret;
8666 }
8667 
GetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef jsType)8668 GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder,
8669                                                 GateRef key, GateRef jsType)
8670 {
8671     auto env = GetEnvironment();
8672     Label entry(env);
8673     env->SubCfgEntry(&entry);
8674     Label exit(env);
8675     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8676 
8677     Label notOnProtoChain(env);
8678     BRANCH(Int64NotEqual(receiver, holder), &exit, &notOnProtoChain);
8679     Bind(&notOnProtoChain);
8680 
8681     auto negativeZero = GetGlobalConstantValue(
8682         VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
8683     Label isNegativeZero(env);
8684     Label notNegativeZero(env);
8685     BRANCH(Equal(negativeZero, key), &isNegativeZero, &notNegativeZero);
8686     Bind(&isNegativeZero);
8687     {
8688         result = Undefined();
8689         Jump(&exit);
8690     }
8691     Bind(&notNegativeZero);
8692     {
8693         GateRef index = TryStringOrSymbolToElementIndex(glue, key);
8694         Label validIndex(env);
8695         Label notValidIndex(env);
8696         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
8697         Bind(&validIndex);
8698         {
8699             BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this);
8700             result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, holder, index, jsType);
8701             Jump(&exit);
8702         }
8703         Bind(&notValidIndex);
8704         {
8705             Label returnNull(env);
8706             BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
8707             Bind(&returnNull);
8708             {
8709                 result = Null();
8710                 Jump(&exit);
8711             }
8712         }
8713     }
8714 
8715     Bind(&exit);
8716     auto ret = *result;
8717     env->SubCfgExit();
8718     return ret;
8719 }
8720 
SetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef value,GateRef jsType)8721 GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key,
8722                                                 GateRef value, GateRef jsType)
8723 {
8724     auto env = GetEnvironment();
8725     Label entry(env);
8726     env->SubCfgEntry(&entry);
8727     Label exit(env);
8728     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8729     Label notOnProtoChain(env);
8730     BRANCH(Int64NotEqual(receiver, holder), &exit, &notOnProtoChain);
8731     Bind(&notOnProtoChain);
8732 
8733     auto negativeZero = GetGlobalConstantValue(
8734         VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
8735     Label isNegativeZero(env);
8736     Label notNegativeZero(env);
8737     BRANCH(Equal(negativeZero, key), &isNegativeZero, &notNegativeZero);
8738     Bind(&isNegativeZero);
8739     {
8740         Label isObj(env);
8741         Label notObj(env);
8742         BRANCH(IsEcmaObject(value), &isObj, &notObj);
8743         Bind(&isObj);
8744         {
8745             result = Null();
8746             Jump(&exit);
8747         }
8748         Bind(&notObj);
8749         result = Undefined();
8750         Jump(&exit);
8751     }
8752     Bind(&notNegativeZero);
8753     {
8754         GateRef index = TryStringOrSymbolToElementIndex(glue, key);
8755         Label validIndex(env);
8756         Label notValidIndex(env);
8757         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
8758         Bind(&validIndex);
8759         {
8760             result = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
8761                 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType) });
8762             Jump(&exit);
8763         }
8764         Bind(&notValidIndex);
8765         {
8766             Label returnNull(env);
8767             BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
8768             Bind(&returnNull);
8769             {
8770                 result = Null();
8771                 Jump(&exit);
8772             }
8773         }
8774     }
8775 
8776     Bind(&exit);
8777     auto ret = *result;
8778     env->SubCfgExit();
8779     return ret;
8780 }
8781 
Assert(int messageId,int line,GateRef glue,GateRef condition,Label * nextLabel)8782 void StubBuilder::Assert(int messageId, int line, GateRef glue, GateRef condition, Label *nextLabel)
8783 {
8784     auto env = GetEnvironment();
8785     Label ok(env);
8786     Label notOk(env);
8787     BRANCH(condition, &ok, &notOk);
8788     Bind(&ok);
8789     {
8790         Jump(nextLabel);
8791     }
8792     Bind(&notOk);
8793     {
8794         FatalPrint(glue, { Int32(messageId), Int32(line) });
8795         Jump(nextLabel);
8796     }
8797 }
8798 
GetNormalStringData(const StringInfoGateRef & stringInfoGate)8799 GateRef StubBuilder::GetNormalStringData(const StringInfoGateRef &stringInfoGate)
8800 {
8801     auto env = GetEnvironment();
8802     Label entry(env);
8803     env->SubCfgEntry(&entry);
8804     Label exit(env);
8805     Label isConstantString(env);
8806     Label isLineString(env);
8807     Label isUtf8(env);
8808     Label isUtf16(env);
8809     DEFVARIABLE(result, VariableType::NATIVE_POINTER(), Undefined());
8810     BRANCH(IsConstantString(stringInfoGate.GetString()), &isConstantString, &isLineString);
8811     Bind(&isConstantString);
8812     {
8813         GateRef address = PtrAdd(stringInfoGate.GetString(), IntPtr(ConstantString::CONSTANT_DATA_OFFSET));
8814         result = PtrAdd(Load(VariableType::NATIVE_POINTER(), address, IntPtr(0)),
8815             ZExtInt32ToPtr(stringInfoGate.GetStartIndex()));
8816         Jump(&exit);
8817     }
8818     Bind(&isLineString);
8819     {
8820         GateRef data = ChangeTaggedPointerToInt64(
8821             PtrAdd(stringInfoGate.GetString(), IntPtr(LineEcmaString::DATA_OFFSET)));
8822         BRANCH(IsUtf8String(stringInfoGate.GetString()), &isUtf8, &isUtf16);
8823         Bind(&isUtf8);
8824         {
8825             result = PtrAdd(data, ZExtInt32ToPtr(stringInfoGate.GetStartIndex()));
8826             Jump(&exit);
8827         }
8828         Bind(&isUtf16);
8829         {
8830             GateRef offset = PtrMul(ZExtInt32ToPtr(stringInfoGate.GetStartIndex()), IntPtr(sizeof(uint16_t)));
8831             result = PtrAdd(data, offset);
8832             Jump(&exit);
8833         }
8834     }
8835     Bind(&exit);
8836     auto ret = *result;
8837     env->SubCfgExit();
8838     return ret;
8839 }
8840 
ToNumber(GateRef glue,GateRef tagged)8841 GateRef StubBuilder::ToNumber(GateRef glue, GateRef tagged)
8842 {
8843     auto env = GetEnvironment();
8844     Label entry(env);
8845     env->SubCfgEntry(&entry);
8846     Label exit(env);
8847     Label isNumber(env);
8848     Label notNumber(env);
8849     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8850     BRANCH(TaggedIsNumber(tagged), &isNumber, &notNumber);
8851     Bind(&isNumber);
8852     {
8853         result = tagged;
8854         Jump(&exit);
8855     }
8856     Bind(&notNumber);
8857     {
8858         result = CallRuntime(glue, RTSTUB_ID(ToNumber), { tagged });
8859         Jump(&exit);
8860     }
8861     Bind(&exit);
8862     auto ret = *result;
8863     env->SubCfgExit();
8864     return ret;
8865 }
8866 
ToLength(GateRef glue,GateRef target)8867 GateRef StubBuilder::ToLength(GateRef glue, GateRef target)
8868 {
8869     auto env = GetEnvironment();
8870     Label subentry(env);
8871     env->SubCfgEntry(&subentry);
8872     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
8873     Label exit(env);
8874 
8875     GateRef number = ToNumber(glue, target);
8876     Label isPendingException(env);
8877     Label noPendingException(env);
8878     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
8879     Bind(&isPendingException);
8880     {
8881         Jump(&exit);
8882     }
8883     Bind(&noPendingException);
8884     {
8885         GateRef num = GetDoubleOfTNumber(number);
8886         Label targetLessThanZero(env);
8887         Label targetGreaterThanZero(env);
8888         Label targetLessThanSafeNumber(env);
8889         Label targetGreaterThanSafeNumber(env);
8890         BRANCH(DoubleLessThan(num, Double(0.0)), &targetLessThanZero, &targetGreaterThanZero);
8891         Bind(&targetLessThanZero);
8892         {
8893             res = DoubleToTaggedDoublePtr(Double(0.0));
8894             Jump(&exit);
8895         }
8896         Bind(&targetGreaterThanZero);
8897         BRANCH(DoubleGreaterThan(num, Double(SAFE_NUMBER)), &targetGreaterThanSafeNumber, &targetLessThanSafeNumber);
8898         Bind(&targetGreaterThanSafeNumber);
8899         {
8900             res = DoubleToTaggedDoublePtr(Double(SAFE_NUMBER));
8901             Jump(&exit);
8902         }
8903         Bind(&targetLessThanSafeNumber);
8904         {
8905             res = number;
8906             Jump(&exit);
8907         }
8908     }
8909     Bind(&exit);
8910     auto ret = *res;
8911     env->SubCfgExit();
8912     return ret;
8913 }
8914 
TaggedGetNumber(GateRef x)8915 GateRef StubBuilder::TaggedGetNumber(GateRef x)
8916 {
8917     auto env = GetEnvironment();
8918     Label subentry(env);
8919     Label exit(env);
8920     env->SubCfgEntry(&subentry);
8921 
8922     Label targetIsInt(env);
8923     Label targetIsDouble(env);
8924     DEFVALUE(number, env_, VariableType::FLOAT64(), Double(0));
8925     BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
8926     Bind(&targetIsInt);
8927     {
8928         number = ChangeInt32ToFloat64(TaggedGetInt(x));
8929         Jump(&exit);
8930     }
8931     Bind(&targetIsDouble);
8932     {
8933         number = GetDoubleOfTDouble(x);
8934         Jump(&exit);
8935     }
8936     Bind(&exit);
8937     GateRef ret = *number;
8938     env->SubCfgExit();
8939     return ret;
8940 }
8941 
NumberGetInt(GateRef glue,GateRef x)8942 GateRef StubBuilder::NumberGetInt(GateRef glue, GateRef x)
8943 {
8944     auto env = GetEnvironment();
8945     Label subentry(env);
8946     Label exit(env);
8947     env->SubCfgEntry(&subentry);
8948 
8949     Label targetIsInt(env);
8950     Label targetIsDouble(env);
8951     DEFVALUE(number, env_, VariableType::INT32(), Int32(0));
8952     BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
8953     Bind(&targetIsInt);
8954     {
8955         number = TaggedGetInt(x);
8956         Jump(&exit);
8957     }
8958     Bind(&targetIsDouble);
8959     {
8960         number = DoubleToInt(glue, GetDoubleOfTDouble(x));
8961         Jump(&exit);
8962     }
8963     Bind(&exit);
8964     GateRef ret = *number;
8965     env->SubCfgExit();
8966     return ret;
8967 }
8968 
HasStableElements(GateRef glue,GateRef obj)8969 GateRef StubBuilder::HasStableElements(GateRef glue, GateRef obj)
8970 {
8971     auto env = GetEnvironment();
8972     Label subentry(env);
8973     env->SubCfgEntry(&subentry);
8974     DEFVARIABLE(result, VariableType::BOOL(), False());
8975     Label exit(env);
8976     Label targetIsHeapObject(env);
8977     Label targetIsStableElements(env);
8978     BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
8979     Bind(&targetIsHeapObject);
8980     {
8981         GateRef jsHclass = LoadHClass(obj);
8982         BRANCH(IsStableElements(jsHclass), &targetIsStableElements, &exit);
8983         Bind(&targetIsStableElements);
8984         {
8985             GateRef guardiansOffset =
8986                 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
8987             result = Load(VariableType::BOOL(), glue, guardiansOffset);
8988             Jump(&exit);
8989         }
8990     }
8991     Bind(&exit);
8992     auto res = *result;
8993     env->SubCfgExit();
8994     return res;
8995 }
8996 
IsStableJSArguments(GateRef glue,GateRef obj)8997 GateRef StubBuilder::IsStableJSArguments(GateRef glue, GateRef obj)
8998 {
8999     auto env = GetEnvironment();
9000     Label subentry(env);
9001     env->SubCfgEntry(&subentry);
9002     DEFVARIABLE(result, VariableType::BOOL(), False());
9003     Label exit(env);
9004     Label targetIsHeapObject(env);
9005     Label targetIsStableArguments(env);
9006 
9007     BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
9008     Bind(&targetIsHeapObject);
9009     {
9010         GateRef jsHclass = LoadHClass(obj);
9011         BRANCH(IsStableArguments(jsHclass), &targetIsStableArguments, &exit);
9012         Bind(&targetIsStableArguments);
9013         {
9014             GateRef guardiansOffset =
9015                 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
9016             result = Load(VariableType::BOOL(), glue, guardiansOffset);
9017             Jump(&exit);
9018         }
9019     }
9020     Bind(&exit);
9021     auto res = *result;
9022     env->SubCfgExit();
9023     return res;
9024 }
9025 
IsStableJSArray(GateRef glue,GateRef obj)9026 GateRef StubBuilder::IsStableJSArray(GateRef glue, GateRef obj)
9027 {
9028     auto env = GetEnvironment();
9029     Label subentry(env);
9030     env->SubCfgEntry(&subentry);
9031     DEFVARIABLE(result, VariableType::BOOL(), False());
9032     Label exit(env);
9033     Label targetIsHeapObject(env);
9034     Label targetIsStableArray(env);
9035 
9036     BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
9037     Bind(&targetIsHeapObject);
9038     {
9039         GateRef jsHclass = LoadHClass(obj);
9040         BRANCH(IsStableArray(jsHclass), &targetIsStableArray, &exit);
9041         Bind(&targetIsStableArray);
9042         {
9043             GateRef guardiansOffset =
9044                 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
9045             GateRef guardians = Load(VariableType::BOOL(), glue, guardiansOffset);
9046             result.WriteVariable(guardians);
9047             Jump(&exit);
9048         }
9049     }
9050     Bind(&exit);
9051     auto res = *result;
9052     env->SubCfgExit();
9053     return res;
9054 }
9055 
UpdateProfileTypeInfo(GateRef glue,GateRef jsFunc)9056 GateRef StubBuilder::UpdateProfileTypeInfo(GateRef glue, GateRef jsFunc)
9057 {
9058     auto env = GetEnvironment();
9059     Label entry(env);
9060     env->SubCfgEntry(&entry);
9061     Label needUpdate(env);
9062     Label exit(env);
9063     DEFVARIABLE(profileTypeInfo, VariableType::JS_POINTER(), GetProfileTypeInfo(jsFunc));
9064     BRANCH(TaggedIsUndefined(*profileTypeInfo), &needUpdate, &exit);
9065     Bind(&needUpdate);
9066     {
9067         profileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounter), { jsFunc });
9068         Jump(&exit);
9069     }
9070     Bind(&exit);
9071     auto ret = *profileTypeInfo;
9072     env->SubCfgExit();
9073     return ret;
9074 }
9075 
GetFuncKind(GateRef method)9076 GateRef StubBuilder::GetFuncKind(GateRef method)
9077 {
9078     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
9079     GateRef bitfield = Load(VariableType::INT32(), method, extraLiteralInfoOffset);
9080 
9081     GateRef kind = Int32And(Int32LSR(bitfield, Int32(Method::FunctionKindBits::START_BIT)),
9082                             Int32((1LU << Method::FunctionKindBits::SIZE) - 1));
9083     return kind;
9084 }
9085 
GetCallSpreadArgs(GateRef glue,GateRef array,ProfileOperation callBack)9086 GateRef StubBuilder::GetCallSpreadArgs(GateRef glue, GateRef array, ProfileOperation callBack)
9087 {
9088     auto env = GetEnvironment();
9089     Label subEntry(env);
9090     env->SubCfgEntry(&subEntry);
9091     DEFVARIABLE(result, VariableType::JS_POINTER(), NullPtr());
9092     Label fastPath(env);
9093     Label noCopyPath(env);
9094     Label exit(env);
9095     Label noException(env);
9096     Label isException(env);
9097 
9098     GateRef itor = GetIterator(glue, array, callBack);
9099     BRANCH(TaggedIsException(itor), &isException, &noException);
9100     Bind(&isException);
9101     {
9102         result = Exception();
9103         Jump(&exit);
9104     }
9105     Bind(&noException);
9106     GateRef needCopy = LogicAndBuilder(env)
9107         .And(Int32Equal(GetObjectType(LoadHClass(itor)), Int32(static_cast<int32_t>(JSType::JS_ARRAY_ITERATOR))))
9108         .And(IsStableJSArray(glue, array))
9109         .Done();
9110     BRANCH(needCopy, &fastPath, &noCopyPath);
9111     Bind(&fastPath);
9112     {
9113         // copy operation is omitted
9114         result = CopyJSArrayToTaggedArrayArgs(glue, array);
9115         Jump(&exit);
9116     }
9117     Bind(&noCopyPath);
9118     {
9119         result = CallRuntime(glue, RTSTUB_ID(GetCallSpreadArgs), { array });
9120         Jump(&exit);
9121     }
9122     Bind(&exit);
9123     auto ret = *result;
9124     env->SubCfgExit();
9125     return ret;
9126 }
9127 
CalArrayRelativePos(GateRef index,GateRef arrayLen)9128 GateRef StubBuilder::CalArrayRelativePos(GateRef index, GateRef arrayLen)
9129 {
9130     auto env = GetEnvironment();
9131     Label entryPass(env);
9132     env->SubCfgEntry(&entryPass);
9133     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
9134 
9135     Label indexLessZero(env);
9136     Label indexNotLessZero(env);
9137     Label exit(env);
9138     BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
9139     Bind(&indexLessZero);
9140     {
9141         GateRef tempBeginIndex = Int32Add(arrayLen, index);
9142         Label beginIndexLargeZero(env);
9143         BRANCH(Int32GreaterThan(tempBeginIndex, Int32(0)), &beginIndexLargeZero, &exit);
9144         Bind(&beginIndexLargeZero);
9145         {
9146             result = tempBeginIndex;
9147             Jump(&exit);
9148         }
9149     }
9150     Bind(&indexNotLessZero);
9151     {
9152         Label lessLen(env);
9153         Label largeLen(env);
9154         BRANCH(Int32LessThan(index, arrayLen), &lessLen, &largeLen);
9155         Bind(&lessLen);
9156         {
9157             result = index;
9158             Jump(&exit);
9159         }
9160         Bind(&largeLen);
9161         {
9162             result = arrayLen;
9163             Jump(&exit);
9164         }
9165     }
9166 
9167     Bind(&exit);
9168     auto ret = *result;
9169     env->SubCfgExit();
9170     return ret;
9171 }
9172 
AppendSkipHole(GateRef glue,GateRef first,GateRef second,GateRef copyLength)9173 GateRef StubBuilder::AppendSkipHole(GateRef glue, GateRef first, GateRef second, GateRef copyLength)
9174 {
9175     auto env = GetEnvironment();
9176     Label subEntry(env);
9177     env->SubCfgEntry(&subEntry);
9178     Label exit(env);
9179     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
9180     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9181     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
9182 
9183     GateRef firstLength = GetLengthOfTaggedArray(first);
9184     GateRef secondLength = GetLengthOfTaggedArray(second);
9185     NewObjectStubBuilder newBuilder(this);
9186     GateRef array = newBuilder.NewTaggedArray(glue, copyLength);
9187     Label loopHead(env);
9188     Label loopEnd(env);
9189     Label afterLoop(env);
9190     Label storeValue(env);
9191     Label notHole(env);
9192     Jump(&loopHead);
9193     LoopBegin(&loopHead);
9194     {
9195         BRANCH(Int32UnsignedLessThan(*index, firstLength), &storeValue, &afterLoop);
9196         Bind(&storeValue);
9197         {
9198             GateRef value = GetValueFromTaggedArray(first, *index);
9199             BRANCH(TaggedIsHole(value), &afterLoop, &notHole);
9200             Bind(&notHole);
9201             SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value);
9202             index = Int32Add(*index, Int32(1));
9203             Jump(&loopEnd);
9204         }
9205     }
9206     Bind(&loopEnd);
9207     LoopEnd(&loopHead, env, glue);
9208     Bind(&afterLoop);
9209     {
9210         Label loopHead1(env);
9211         Label loopEnd1(env);
9212         Label storeValue1(env);
9213         Label notHole1(env);
9214         Jump(&loopHead1);
9215         LoopBegin(&loopHead1);
9216         {
9217             BRANCH(Int32UnsignedLessThan(*i, secondLength), &storeValue1, &exit);
9218             Bind(&storeValue1);
9219             {
9220                 GateRef value1 = GetValueFromTaggedArray(second, *i);
9221                 BRANCH(TaggedIsHole(value1), &exit, &notHole1);
9222                 Bind(&notHole1);
9223                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value1);
9224                 i = Int32Add(*i, Int32(1));
9225                 index = Int32Add(*index, Int32(1));
9226                 Jump(&loopEnd1);
9227             }
9228         }
9229         Bind(&loopEnd1);
9230         LoopEnd(&loopHead1);
9231     }
9232     Bind(&exit);
9233     res = array;
9234     auto ret = *res;
9235     env->SubCfgExit();
9236     return ret;
9237 }
9238 
ToCharCode(GateRef number)9239 GateRef StubBuilder::ToCharCode(GateRef number)
9240 {
9241     auto env = GetEnvironment();
9242     Label subEntry(env);
9243     env->SubCfgEntry(&subEntry);
9244     Label exit(env);
9245     DEFVARIABLE(result, VariableType::INT32(), number);
9246 
9247     Label lessThanTen(env);
9248     Label notLessThanTen(env);
9249     BRANCH(Int32LessThan(number, Int32(10)), &lessThanTen, &notLessThanTen); // 10: means number
9250     Bind(&lessThanTen);
9251     {
9252         result = Int32Add(Int32('0'), *result);
9253         Jump(&exit);
9254     }
9255     Bind(&notLessThanTen);
9256     {
9257         result = Int32Sub(*result, Int32(10)); // 10: means number
9258         result = Int32Add(Int32('a'), *result);
9259         Jump(&exit);
9260     }
9261     Bind(&exit);
9262     auto ret = *result;
9263     env->SubCfgExit();
9264     return ret;
9265 }
9266 
IntToEcmaString(GateRef glue,GateRef number)9267 GateRef StubBuilder::IntToEcmaString(GateRef glue, GateRef number)
9268 {
9269     auto env = GetEnvironment();
9270     Label subEntry(env);
9271     env->SubCfgEntry(&subEntry);
9272     Label exit(env);
9273     DEFVARIABLE(n, VariableType::INT32(), number);
9274     DEFVARIABLE(result, VariableType::JS_POINTER(), Hole());
9275 
9276     GateRef isPositive = Int32GreaterThanOrEqual(number, Int32(0));
9277     GateRef isSingle = Int32LessThan(number, Int32(10));
9278     Label process(env);
9279     Label callRuntime(env);
9280     Label afterNew(env);
9281     BRANCH(BitAnd(isPositive, isSingle), &process, &callRuntime);
9282     Bind(&process);
9283     {
9284         NewObjectStubBuilder newBuilder(this);
9285         newBuilder.SetParameters(glue, 0);
9286         newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), true);
9287         Bind(&afterNew);
9288         n = Int32Add(Int32('0'), *n);
9289         GateRef dst = ChangeTaggedPointerToInt64(PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET)));
9290         Store(VariableType::INT8(), glue, dst, IntPtr(0), TruncInt32ToInt8(*n));
9291         Jump(&exit);
9292     }
9293     Bind(&callRuntime);
9294     {
9295         result = CallRuntime(glue, RTSTUB_ID(IntToString), { IntToTaggedInt(*n) });
9296         Jump(&exit);
9297     }
9298     Bind(&exit);
9299     auto ret = *result;
9300     env->SubCfgExit();
9301     return ret;
9302 }
9303 
NumberToString(GateRef glue,GateRef number)9304 GateRef StubBuilder::NumberToString(GateRef glue, GateRef number)
9305 {
9306     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
9307     res = CallRuntime(glue, RTSTUB_ID(NumberToString), { number });
9308     return *res;
9309 }
9310 
RestoreElementsKindToGeneric(GateRef glue,GateRef jsHClass)9311 void StubBuilder::RestoreElementsKindToGeneric(GateRef glue, GateRef jsHClass)
9312 {
9313     GateRef newKind = Int32(static_cast<int32_t>(ElementsKind::GENERIC));
9314     SetElementsKindToJSHClass(glue, jsHClass, newKind);
9315 }
9316 
GetTaggedValueWithElementsKind(GateRef receiver,GateRef index)9317 GateRef StubBuilder::GetTaggedValueWithElementsKind(GateRef receiver, GateRef index)
9318 {
9319     auto env = GetEnvironment();
9320     Label entryPass(env);
9321     env->SubCfgEntry(&entryPass);
9322     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
9323     Label exit(env);
9324 
9325     GateRef hclass = LoadHClass(receiver);
9326     DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
9327     Label isMutantTaggedArray(env);
9328     Label isNotMutantTaggedArray(env);
9329     GateRef elements = GetElementsArray(receiver);
9330     BRANCH(IsMutantTaggedArray(elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
9331     Bind(&isNotMutantTaggedArray);
9332     {
9333         elementsKind = Int32(static_cast<int32_t>(ElementsKind::GENERIC));
9334         Jump(&isMutantTaggedArray);
9335     }
9336     Bind(&isMutantTaggedArray);
9337     GateRef rawValue = GetValueFromMutantTaggedArray(elements, index);
9338     Label isSpecialHole(env);
9339     Label isNotSpecialHole(env);
9340     BRANCH(Int64Equal(rawValue, SpecialHole()), &isSpecialHole, &isNotSpecialHole);
9341     Bind(&isSpecialHole);
9342     {
9343         Jump(&exit);
9344     }
9345     Bind(&isNotSpecialHole);
9346     {
9347         Label isInt(env);
9348         Label isNotInt(env);
9349         GateRef elementsKindIntLowerBound = Int32GreaterThanOrEqual(*elementsKind,
9350                                                                     Int32(static_cast<int32_t>(ElementsKind::INT)));
9351         GateRef elementsKindIntUpperBound = Int32LessThanOrEqual(*elementsKind,
9352                                                                  Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)));
9353         GateRef checkIntKind = BitAnd(elementsKindIntLowerBound, elementsKindIntUpperBound);
9354         BRANCH(checkIntKind, &isInt, &isNotInt);
9355         Bind(&isInt);
9356         {
9357             result = Int64ToTaggedIntPtr(rawValue);
9358             Jump(&exit);
9359         }
9360         Bind(&isNotInt);
9361         {
9362             Label isNumber(env);
9363             Label isNotNumber(env);
9364             GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
9365                                                                    Int32(static_cast<int32_t>(ElementsKind::NUMBER)));
9366             GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
9367                                                                 Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)));
9368             GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
9369             BRANCH(checkNumberKind, &isNumber, &isNotNumber);
9370             Bind(&isNumber);
9371             {
9372                 GateRef numberValue = CastInt64ToFloat64(rawValue);
9373                 result = DoubleToTaggedDoublePtr(numberValue);
9374                 Jump(&exit);
9375             }
9376             Bind(&isNotNumber);
9377             {
9378                 result = Int64ToTaggedPtr(rawValue);
9379                 Jump(&exit);
9380             }
9381         }
9382     }
9383     Bind(&exit);
9384     auto ret = *result;
9385     env->SubCfgExit();
9386     return ret;
9387 }
9388 
SetValueWithElementsKind(GateRef glue,GateRef receiver,GateRef rawValue,GateRef index,GateRef needTransition,GateRef extraKind)9389 GateRef StubBuilder::SetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef rawValue,
9390                                               GateRef index, GateRef needTransition, GateRef extraKind)
9391 {
9392     auto env = GetEnvironment();
9393     Label entryPass(env);
9394     env->SubCfgEntry(&entryPass);
9395     DEFVARIABLE(result, VariableType::INT64(), SpecialHole());
9396     Label exit(env);
9397 
9398     Label transitElementsKind(env);
9399     Label finishTransition(env);
9400     BRANCH(needTransition, &transitElementsKind, &finishTransition);
9401     Bind(&transitElementsKind);
9402     {
9403         TransitToElementsKind(glue, receiver, rawValue, extraKind);
9404         Jump(&finishTransition);
9405     }
9406     Bind(&finishTransition);
9407     GateRef hclass = LoadHClass(receiver);
9408     DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
9409     Label setValue(env);
9410     Label isMutantTaggedArray(env);
9411     Label isNotMutantTaggedArray(env);
9412     GateRef elements = GetElementsArray(receiver);
9413     BRANCH(IsMutantTaggedArray(elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
9414     Bind(&isNotMutantTaggedArray);
9415     {
9416         elementsKind = Int32(static_cast<int32_t>(ElementsKind::GENERIC));
9417         Jump(&isMutantTaggedArray);
9418     }
9419     Bind(&isMutantTaggedArray);
9420     Label isHole(env);
9421     Label isNotHole(env);
9422     GateRef elementsKindVal = *elementsKind;
9423     GateRef checkInNumersKind = LogicAndBuilder(env)
9424         .And(TaggedIsHole(rawValue))
9425         .And(Int32GreaterThanOrEqual(elementsKindVal, Int32(static_cast<int32_t>(ElementsKind::HOLE))))
9426         .And(Int32LessThan(elementsKindVal, Int32(static_cast<int32_t>(ElementsKind::STRING))))
9427         .Done();
9428     BRANCH(checkInNumersKind, &isHole, &isNotHole);
9429     Bind(&isHole);
9430     {
9431         Jump(&setValue);
9432     }
9433     Bind(&isNotHole);
9434     {
9435         Label isInt(env);
9436         Label isNotInt(env);
9437         GateRef elementsKindIntLB = Int32GreaterThanOrEqual(*elementsKind,
9438                                                             Int32(static_cast<int32_t>(ElementsKind::INT)));
9439         GateRef elementsKindIntUB = Int32LessThanOrEqual(*elementsKind,
9440                                                          Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)));
9441         GateRef checkIntKind = BitAnd(elementsKindIntLB, elementsKindIntUB);
9442         BRANCH(checkIntKind, &isInt, &isNotInt);
9443         Bind(&isInt);
9444         {
9445             result = GetInt64OfTInt(rawValue);
9446             Jump(&setValue);
9447         }
9448         Bind(&isNotInt);
9449         {
9450             Label isNumber(env);
9451             Label isNotNumber(env);
9452             GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
9453                                                                    Int32(static_cast<int32_t>(ElementsKind::NUMBER)));
9454             GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
9455                                                                 Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)));
9456             GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
9457             BRANCH(checkNumberKind, &isNumber, &isNotNumber);
9458             Bind(&isNumber);
9459             {
9460                 Label isNumberInt(env);
9461                 Label isNotNumberInt(env);
9462                 BRANCH(TaggedIsInt(rawValue), &isNumberInt, &isNotNumberInt);
9463                 Bind(&isNumberInt);
9464                 {
9465                     result = CastDoubleToInt64(GetDoubleOfTInt(rawValue));
9466                     Jump(&setValue);
9467                 }
9468                 Bind(&isNotNumberInt);
9469                 {
9470                     result = CastDoubleToInt64(GetDoubleOfTDouble(rawValue));
9471                     Jump(&setValue);
9472                 }
9473             }
9474             Bind(&isNotNumber);
9475             {
9476                 result = ChangeTaggedPointerToInt64(rawValue);
9477                 Jump(&setValue);
9478             }
9479         }
9480     }
9481     Bind(&setValue);
9482     Label storeToNormalArray(env);
9483     Label storeToMutantArray(env);
9484     BRANCH(TaggedIsHeapObject(rawValue), &storeToNormalArray, &storeToMutantArray);
9485     Bind(&storeToNormalArray);
9486     {
9487         SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, *result);
9488         Jump(&exit);
9489     }
9490     Bind(&storeToMutantArray);
9491     {
9492         SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, *result);
9493         Jump(&exit);
9494     }
9495     Bind(&exit);
9496     auto ret = *result;
9497     env->SubCfgExit();
9498     return ret;
9499 }
9500 
FastSetValueWithElementsKind(GateRef glue,GateRef elements,GateRef rawValue,GateRef index,ElementsKind kind)9501 void StubBuilder::FastSetValueWithElementsKind(GateRef glue, GateRef elements, GateRef rawValue,
9502                                                GateRef index, ElementsKind kind)
9503 {
9504     auto env = GetEnvironment();
9505     Label entryPass(env);
9506     env->SubCfgEntry(&entryPass);
9507     Label exit(env);
9508     if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
9509         SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
9510         Jump(&exit);
9511     } else {
9512         Label storeToNormalArray(env);
9513         Label storeToMutantArray(env);
9514         BRANCH(TaggedIsHeapObject(rawValue), &storeToNormalArray, &storeToMutantArray);
9515         Bind(&storeToNormalArray);
9516         {
9517             SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, rawValue);
9518             Jump(&exit);
9519         }
9520         Bind(&storeToMutantArray);
9521         {
9522             SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
9523             Jump(&exit);
9524         }
9525     }
9526     Bind(&exit);
9527     env->SubCfgExit();
9528 }
9529 
CopyJSArrayToTaggedArrayArgs(GateRef glue,GateRef srcObj)9530 GateRef StubBuilder::CopyJSArrayToTaggedArrayArgs(GateRef glue, GateRef srcObj)
9531 {
9532     auto env = GetEnvironment();
9533     Label entryPass(env);
9534     env->SubCfgEntry(&entryPass);
9535     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
9536     Label exit(env);
9537 
9538     Label isMutantTaggedArray(env);
9539     result = GetElementsArray(srcObj);
9540     BRANCH(IsMutantTaggedArray(*result), &isMutantTaggedArray, &exit);
9541     Bind(&isMutantTaggedArray);
9542     {
9543         GateRef argvLength = GetLengthOfTaggedArray(*result);
9544         NewObjectStubBuilder newBuilder(this);
9545         GateRef argv = newBuilder.NewTaggedArray(glue, argvLength);
9546         DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9547         Label loopHead(env);
9548         Label loopEnd(env);
9549         Label afterLoop(env);
9550         Label storeValue(env);
9551         Jump(&loopHead);
9552         LoopBegin(&loopHead);
9553         {
9554             BRANCH(Int32UnsignedLessThan(*index, argvLength), &storeValue, &afterLoop);
9555             Bind(&storeValue);
9556             {
9557                 GateRef value = GetTaggedValueWithElementsKind(srcObj, *index);
9558                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argv, *index, value);
9559                 index = Int32Add(*index, Int32(1));
9560                 Jump(&loopEnd);
9561             }
9562         }
9563         Bind(&loopEnd);
9564         LoopEnd(&loopHead);
9565         Bind(&afterLoop);
9566         {
9567             result = argv;
9568             Jump(&exit);
9569         }
9570     }
9571     Bind(&exit);
9572     auto ret = *result;
9573     env->SubCfgExit();
9574     return ret;
9575 }
9576 
MigrateArrayWithKind(GateRef glue,GateRef object,GateRef oldKind,GateRef newKind)9577 void StubBuilder::MigrateArrayWithKind(GateRef glue, GateRef object, GateRef oldKind, GateRef newKind)
9578 {
9579     auto env = GetEnvironment();
9580     Label entryPass(env);
9581     env->SubCfgEntry(&entryPass);
9582     Label exit(env);
9583 
9584     Label elementsKindOn(env);
9585     GateRef isElementsKindEnabled = IsEnableElementsKind(glue);
9586     BRANCH(isElementsKindEnabled, &elementsKindOn, &exit);
9587     Bind(&elementsKindOn);
9588 
9589     DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
9590     Label doMigration(env);
9591     Label migrateFromInt(env);
9592     Label migrateOtherKinds(env);
9593 
9594     GateRef noNeedMigration = LogicOrBuilder(env)
9595         .Or(Int32Equal(oldKind, newKind))
9596         .Or(BitAnd(Int32Equal(oldKind, Int32(static_cast<uint32_t>(ElementsKind::INT))),
9597                    Int32Equal(newKind, Int32(static_cast<uint32_t>(ElementsKind::HOLE_INT)))))
9598         .Or(BitAnd(Int32Equal(oldKind, Int32(static_cast<uint32_t>(ElementsKind::NUMBER))),
9599                    Int32Equal(newKind, Int32(static_cast<uint32_t>(ElementsKind::HOLE_NUMBER)))))
9600         .Done();
9601     BRANCH(noNeedMigration, &exit, &doMigration);
9602     Bind(&doMigration);
9603     GateRef needCOW = IsJsCOWArray(object);
9604     BRANCH(ElementsKindIsIntOrHoleInt(oldKind), &migrateFromInt, &migrateOtherKinds);
9605     Bind(&migrateFromInt);
9606     {
9607         Label migrateToHeapValuesFromInt(env);
9608         Label migrateToRawValuesFromInt(env);
9609         Label migrateToNumbersFromInt(env);
9610         BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromInt, &migrateToRawValuesFromInt);
9611         Bind(&migrateToHeapValuesFromInt);
9612         {
9613             newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, True());
9614             SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9615             Jump(&exit);
9616         }
9617         Bind(&migrateToRawValuesFromInt);
9618         {
9619             BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumbersFromInt, &exit);
9620             Bind(&migrateToNumbersFromInt);
9621             {
9622                 MigrateFromHoleIntToHoleNumber(glue, object);
9623                 Jump(&exit);
9624             }
9625         }
9626     }
9627     Bind(&migrateOtherKinds);
9628     {
9629         Label migrateFromNumber(env);
9630         Label migrateToHeapValuesFromNum(env);
9631         Label migrateToRawValuesFromNum(env);
9632         Label migrateToIntFromNum(env);
9633         Label migrateToRawValueFromTagged(env);
9634         BRANCH(ElementsKindIsNumOrHoleNum(oldKind), &migrateFromNumber, &migrateToRawValueFromTagged);
9635         Bind(&migrateFromNumber);
9636         {
9637             BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromNum, &migrateToRawValuesFromNum);
9638             Bind(&migrateToHeapValuesFromNum);
9639             {
9640                 Label migrateToTaggedFromNum(env);
9641                 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToTaggedFromNum, &exit);
9642                 Bind(&migrateToTaggedFromNum);
9643                 {
9644                     newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, False());
9645                     SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9646                     Jump(&exit);
9647                 }
9648             }
9649             Bind(&migrateToRawValuesFromNum);
9650             {
9651                 BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromNum, &exit);
9652                 Bind(&migrateToIntFromNum);
9653                 {
9654                     MigrateFromHoleNumberToHoleInt(glue, object);
9655                     Jump(&exit);
9656                 }
9657             }
9658         }
9659         Bind(&migrateToRawValueFromTagged);
9660         {
9661             Label migrateToIntFromTagged(env);
9662             Label migrateToOthersFromTagged(env);
9663             BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromTagged, &migrateToOthersFromTagged);
9664             Bind(&migrateToIntFromTagged);
9665             {
9666                 newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, True());
9667                 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9668                 Jump(&exit);
9669             }
9670             Bind(&migrateToOthersFromTagged);
9671             {
9672                 Label migrateToNumFromTagged(env);
9673                 BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumFromTagged, &exit);
9674                 Bind(&migrateToNumFromTagged);
9675                 {
9676                     newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, False());
9677                     SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9678                     Jump(&exit);
9679                 }
9680             }
9681         }
9682     }
9683     Bind(&exit);
9684     env->SubCfgExit();
9685 }
9686 
MigrateFromRawValueToHeapValues(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)9687 GateRef StubBuilder::MigrateFromRawValueToHeapValues(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
9688 {
9689     auto env = GetEnvironment();
9690     Label entryPass(env);
9691     env->SubCfgEntry(&entryPass);
9692     DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
9693     Label exit(env);
9694 
9695     GateRef elements = GetElementsArray(object);
9696     GateRef length = GetLengthOfTaggedArray(elements);
9697     Label createCOW(env);
9698     Label createNormal(env);
9699     Label finishElementsInit(env);
9700     BRANCH(needCOW, &createCOW, &createNormal);
9701     Bind(&createCOW);
9702     {
9703         newElements = CallRuntime(glue, RTSTUB_ID(NewCOWTaggedArray), { IntToTaggedPtr(length) });
9704         Jump(&finishElementsInit);
9705     }
9706     Bind(&createNormal);
9707     {
9708         newElements = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedPtr(length) });
9709         Jump(&finishElementsInit);
9710     }
9711     Bind(&finishElementsInit);
9712 
9713     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9714     Label loopHead(env);
9715     Label loopEnd(env);
9716     Label afterLoop(env);
9717     Label storeValue(env);
9718     Jump(&loopHead);
9719     LoopBegin(&loopHead);
9720     {
9721         Label storeHole(env);
9722         Label storeNormalValue(env);
9723         Label finishStore(env);
9724         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9725         Bind(&storeValue);
9726         {
9727             Label rawValueIsInt(env);
9728             Label rawValueIsNumber(env);
9729             GateRef value = GetValueFromMutantTaggedArray(elements, *index);
9730             BRANCH(ValueIsSpecialHole(value), &storeHole, &storeNormalValue);
9731             Bind(&storeHole);
9732             {
9733                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, Hole());
9734                 Jump(&finishStore);
9735             }
9736             Bind(&storeNormalValue);
9737             {
9738                 BRANCH(isIntKind, &rawValueIsInt, &rawValueIsNumber);
9739                 Bind(&rawValueIsInt);
9740                 {
9741                     GateRef convertedInt = Int64ToTaggedIntPtr(value);
9742                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedInt);
9743                     Jump(&finishStore);
9744                 }
9745                 Bind(&rawValueIsNumber);
9746                 {
9747                     GateRef tmpDouble = CastInt64ToFloat64(value);
9748                     GateRef convertedDouble = DoubleToTaggedDoublePtr(tmpDouble);
9749                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedDouble);
9750                     Jump(&finishStore);
9751                 }
9752             }
9753             Bind(&finishStore);
9754             {
9755                 index = Int32Add(*index, Int32(1));
9756                 Jump(&loopEnd);
9757             }
9758         }
9759     }
9760     Bind(&loopEnd);
9761     LoopEnd(&loopHead);
9762     Bind(&afterLoop);
9763     {
9764         Jump(&exit);
9765     }
9766     Bind(&exit);
9767     auto ret = *newElements;
9768     env->SubCfgExit();
9769     return ret;
9770 }
9771 
MigrateFromHeapValueToRawValue(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)9772 GateRef StubBuilder::MigrateFromHeapValueToRawValue(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
9773 {
9774     auto env = GetEnvironment();
9775     Label entryPass(env);
9776     env->SubCfgEntry(&entryPass);
9777     DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
9778     Label exit(env);
9779 
9780     GateRef elements = GetElementsArray(object);
9781     GateRef length = GetLengthOfTaggedArray(elements);
9782     Label createCOW(env);
9783     Label createNormal(env);
9784     Label finishElementsInit(env);
9785     BRANCH(needCOW, &createCOW, &createNormal);
9786     Bind(&createCOW);
9787     {
9788         newElements = CallRuntime(glue, RTSTUB_ID(NewCOWMutantTaggedArray), { IntToTaggedPtr(length) });
9789         Jump(&finishElementsInit);
9790     }
9791     Bind(&createNormal);
9792     {
9793         newElements = CallRuntime(glue, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedPtr(length) });
9794         Jump(&finishElementsInit);
9795     }
9796     Bind(&finishElementsInit);
9797 
9798     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9799     Label loopHead(env);
9800     Label loopEnd(env);
9801     Label afterLoop(env);
9802     Label storeValue(env);
9803     Jump(&loopHead);
9804     LoopBegin(&loopHead);
9805     {
9806         Label storeSpecialHole(env);
9807         Label storeNormalValue(env);
9808         Label finishStore(env);
9809         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9810         Bind(&storeValue);
9811         {
9812             Label convertToInt(env);
9813             Label convertToDouble(env);
9814             GateRef value = GetValueFromTaggedArray(elements, *index);
9815             BRANCH(TaggedIsHole(value), &storeSpecialHole, &storeNormalValue);
9816             Bind(&storeSpecialHole);
9817             {
9818                 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, SpecialHole());
9819                 Jump(&finishStore);
9820             }
9821             Bind(&storeNormalValue);
9822             {
9823                 Label valueIsInt(env);
9824                 Label valueIsDouble(env);
9825                 BRANCH(isIntKind, &convertToInt, &convertToDouble);
9826                 Bind(&convertToInt);
9827                 {
9828                     GateRef convertedInt = GetInt64OfTInt(value);
9829                     SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, convertedInt);
9830                     Jump(&finishStore);
9831                 }
9832                 Bind(&convertToDouble);
9833                 {
9834                     BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsDouble);
9835                     Bind(&valueIsInt);
9836                     {
9837                         GateRef convertedDoubleFromTInt = CastDoubleToInt64(GetDoubleOfTInt(value));
9838                         SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
9839                                               convertedDoubleFromTInt);
9840                         Jump(&finishStore);
9841                     }
9842                     Bind(&valueIsDouble);
9843                     {
9844                         GateRef convertedDoubleFromTDouble = CastDoubleToInt64(GetDoubleOfTDouble(value));
9845                         SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
9846                                               convertedDoubleFromTDouble);
9847                         Jump(&finishStore);
9848                     }
9849                 }
9850             }
9851             Bind(&finishStore);
9852             {
9853                 index = Int32Add(*index, Int32(1));
9854                 Jump(&loopEnd);
9855             }
9856         }
9857     }
9858     Bind(&loopEnd);
9859     LoopEnd(&loopHead);
9860     Bind(&afterLoop);
9861     {
9862         Jump(&exit);
9863     }
9864     Bind(&exit);
9865     auto ret = *newElements;
9866     env->SubCfgExit();
9867     return ret;
9868 }
9869 
MigrateFromHoleIntToHoleNumber(GateRef glue,GateRef object)9870 void StubBuilder::MigrateFromHoleIntToHoleNumber(GateRef glue, GateRef object)
9871 {
9872     auto env = GetEnvironment();
9873     Label entryPass(env);
9874     env->SubCfgEntry(&entryPass);
9875     Label exit(env);
9876 
9877     GateRef elements = GetElementsArray(object);
9878     GateRef length = GetLengthOfTaggedArray(elements);
9879     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9880     Label loopHead(env);
9881     Label loopEnd(env);
9882     Label afterLoop(env);
9883     Label storeValue(env);
9884     Jump(&loopHead);
9885     LoopBegin(&loopHead);
9886     {
9887         Label storeNormalValue(env);
9888         Label finishStore(env);
9889         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9890         Bind(&storeValue);
9891         {
9892             GateRef value = GetValueFromMutantTaggedArray(elements, *index);
9893             BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
9894             Bind(&storeNormalValue);
9895             {
9896                 GateRef intVal = TruncInt64ToInt32(value);
9897                 GateRef convertedValue = CastDoubleToInt64(ChangeInt32ToFloat64(intVal));
9898                 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
9899                                       convertedValue);
9900                 Jump(&finishStore);
9901             }
9902             Bind(&finishStore);
9903             {
9904                 index = Int32Add(*index, Int32(1));
9905                 Jump(&loopEnd);
9906             }
9907         }
9908     }
9909     Bind(&loopEnd);
9910     LoopEnd(&loopHead);
9911     Bind(&afterLoop);
9912     {
9913         Jump(&exit);
9914     }
9915     Bind(&exit);
9916     env->SubCfgExit();
9917 }
9918 
MigrateFromHoleNumberToHoleInt(GateRef glue,GateRef object)9919 void StubBuilder::MigrateFromHoleNumberToHoleInt(GateRef glue, GateRef object)
9920 {
9921     auto env = GetEnvironment();
9922     Label entryPass(env);
9923     env->SubCfgEntry(&entryPass);
9924     Label exit(env);
9925 
9926     GateRef elements = GetElementsArray(object);
9927     GateRef length = GetLengthOfTaggedArray(elements);
9928     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9929     Label loopHead(env);
9930     Label loopEnd(env);
9931     Label afterLoop(env);
9932     Label storeValue(env);
9933     Jump(&loopHead);
9934     LoopBegin(&loopHead);
9935     {
9936         Label storeNormalValue(env);
9937         Label finishStore(env);
9938         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9939         Bind(&storeValue);
9940         {
9941             GateRef value = GetValueFromMutantTaggedArray(elements, *index);
9942             BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
9943             Bind(&storeNormalValue);
9944             {
9945                 GateRef doubleVal = CastInt64ToFloat64(value);
9946                 GateRef convertedValue = SExtInt32ToInt64(ChangeFloat64ToInt32(doubleVal));
9947                 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
9948                                       convertedValue);
9949                 Jump(&finishStore);
9950             }
9951             Bind(&finishStore);
9952             {
9953                 index = Int32Add(*index, Int32(1));
9954                 Jump(&loopEnd);
9955             }
9956         }
9957     }
9958     Bind(&loopEnd);
9959     LoopEnd(&loopHead);
9960     Bind(&afterLoop);
9961     {
9962         Jump(&exit);
9963     }
9964     Bind(&exit);
9965     env->SubCfgExit();
9966 }
9967 
IsDetachedBuffer(GateRef buffer)9968 GateRef StubBuilder::IsDetachedBuffer(GateRef buffer)
9969 {
9970     auto env = GetEnvironment();
9971     Label entryPass(env);
9972     env->SubCfgEntry(&entryPass);
9973     Label isNull(env);
9974     Label exit(env);
9975     Label isByteArray(env);
9976     Label notByteArray(env);
9977     DEFVARIABLE(result, VariableType::BOOL(), False());
9978     BRANCH(IsByteArray(buffer), &isByteArray, &notByteArray);
9979     Bind(&isByteArray);
9980     {
9981         Jump(&exit);
9982     }
9983     Bind(&notByteArray);
9984     {
9985         GateRef dataSlot = GetArrayBufferData(buffer);
9986         BRANCH(TaggedIsNull(dataSlot), &isNull, &exit);
9987         Bind(&isNull);
9988         {
9989             result = True();
9990             Jump(&exit);
9991         }
9992     }
9993     Bind(&exit);
9994     auto ret = *result;
9995     env->SubCfgExit();
9996     return ret;
9997 }
9998 
DefineFunc(GateRef glue,GateRef constpool,GateRef index,FunctionKind targetKind)9999 GateRef StubBuilder::DefineFunc(GateRef glue, GateRef constpool, GateRef index, FunctionKind targetKind)
10000 {
10001     auto env = GetEnvironment();
10002     Label subentry(env);
10003     env->SubCfgEntry(&subentry);
10004     Label exit(env);
10005     DEFVARIABLE(ihc, VariableType::JS_ANY(), Undefined());
10006     DEFVARIABLE(val, VariableType::JS_ANY(), Undefined());
10007     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
10008 
10009     Label isHeapObject(env);
10010     Label afterAOTLiteral(env);
10011     Label tryGetAOTIhc(env);
10012     //AOT ihc infos always in unshareConstpool
10013     //If is runing on AOT,unshareConstpool is definitely not a hole
10014     //So wo can skip if unshareConstpool is hole
10015     GateRef unsharedConstpool = GetUnsharedConstpoolFromGlue(glue, constpool);
10016     BRANCH(TaggedIsHole(unsharedConstpool), &afterAOTLiteral, &tryGetAOTIhc);
10017     Bind(&tryGetAOTIhc);
10018     {
10019         val = GetValueFromTaggedArray(unsharedConstpool, index);
10020         BRANCH(TaggedIsHeapObject(*val), &isHeapObject, &afterAOTLiteral);
10021         {
10022             Bind(&isHeapObject);
10023             Label isAOTLiteral(env);
10024             BRANCH(IsAOTLiteralInfo(*val), &isAOTLiteral, &afterAOTLiteral);
10025             {
10026                 Bind(&isAOTLiteral);
10027                 {
10028                     ihc = GetIhcFromAOTLiteralInfo(*val);
10029                     Jump(&afterAOTLiteral);
10030                 }
10031             }
10032         }
10033     }
10034     Bind(&afterAOTLiteral);
10035     GateRef method = GetMethodFromConstPool(glue, constpool, index);
10036     Label isSendableFunc(env);
10037     Label isNotSendableFunc(env);
10038     Label afterDealWithCompiledStatus(env);
10039     BRANCH(IsSendableFunction(method), &isSendableFunc, &isNotSendableFunc);
10040     Bind(&isSendableFunc);
10041     {
10042         NewObjectStubBuilder newBuilder(this);
10043         result = newBuilder.NewJSSendableFunction(glue, method, targetKind);
10044         Jump(&afterDealWithCompiledStatus);
10045     }
10046     Bind(&isNotSendableFunc);
10047     {
10048         NewObjectStubBuilder newBuilder(this);
10049         result = newBuilder.NewJSFunction(glue, method, targetKind);
10050         Jump(&afterDealWithCompiledStatus);
10051     }
10052     Bind(&afterDealWithCompiledStatus);
10053 
10054     Label ihcNotUndefined(env);
10055     BRANCH(TaggedIsUndefined(*ihc), &exit, &ihcNotUndefined);
10056     Bind(&ihcNotUndefined);
10057     {
10058         CallRuntime(glue, RTSTUB_ID(AOTEnableProtoChangeMarker), {*result, *ihc, *val});
10059         Jump(&exit);
10060     }
10061     Bind(&exit);
10062     auto ret = *result;
10063     env->SubCfgExit();
10064     return ret;
10065 }
10066 
SetCompiledCodeFlagToFunctionFromMethod(GateRef glue,GateRef function,GateRef method)10067 void StubBuilder::SetCompiledCodeFlagToFunctionFromMethod(GateRef glue, GateRef function, GateRef method)
10068 {
10069     // set compiled code & fast call flag
10070     GateRef isFastCall = IsFastCall(method);
10071     GateRef compiledCodeField = Int32LSL(Int32(1U), Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT));
10072     GateRef compiledCodeFlag = Int32Or(compiledCodeField, Int32LSL(ZExtInt1ToInt32(isFastCall),
10073         Int32(JSFunctionBase::IsFastCallBit::START_BIT)));
10074     SetCompiledCodeFlagToFunction(glue, function, compiledCodeFlag);
10075 }
10076 
UpdateProfileTypeInfoCellToFunction(GateRef glue,GateRef function,GateRef profileTypeInfo,GateRef slotId)10077 void StubBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
10078                                                       GateRef profileTypeInfo, GateRef slotId)
10079 {
10080     Label subEntry(env_);
10081     env_->SubCfgEntry(&subEntry);
10082 
10083     Label profileTypeInfoNotUndefined(env_);
10084     Label slotValueUpdate(env_);
10085     Label slotValueNotUndefined(env_);
10086     Label profileTypeInfoEnd(env_);
10087     NewObjectStubBuilder newBuilder(env_);
10088     BRANCH(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined);
10089     Bind(&profileTypeInfoNotUndefined);
10090     {
10091         GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
10092         BRANCH(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
10093         Bind(&slotValueUpdate);
10094         {
10095             GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined());
10096             SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
10097             SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell);
10098             Jump(&profileTypeInfoEnd);
10099         }
10100         Bind(&slotValueNotUndefined);
10101         UpdateProfileTypeInfoCellType(glue, slotValue);
10102         SetRawProfileTypeInfoToFunction(glue, function, slotValue);
10103         Jump(&profileTypeInfoEnd);
10104     }
10105     Bind(&profileTypeInfoEnd);
10106 
10107     env_->SubCfgExit();
10108 }
10109 
Loadlocalmodulevar(GateRef glue,GateRef index,GateRef module)10110 GateRef StubBuilder::Loadlocalmodulevar(GateRef glue, GateRef index, GateRef module)
10111 {
10112     auto env = GetEnvironment();
10113     Label subentry(env);
10114     env->SubCfgEntry(&subentry);
10115     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10116     Label notSendableFunctionModule(env);
10117     Label sendableFunctionModule(env);
10118     Label exit(env);
10119     BRANCH_UNLIKELY(IsSendableFunctionModule(module), &sendableFunctionModule, &notSendableFunctionModule);
10120     Bind(&sendableFunctionModule);
10121     {
10122         result = CallRuntime(glue, RTSTUB_ID(LdLocalModuleVarByIndexWithModule),
10123                              {Int8ToTaggedInt(index), module});
10124         Jump(&exit);
10125     }
10126     Bind(&notSendableFunctionModule);
10127     {
10128         GateRef nameDictionaryOffset = IntPtr(SourceTextModule::NAME_DICTIONARY_OFFSET);
10129         GateRef dictionary = Load(VariableType::JS_ANY(), module, nameDictionaryOffset);
10130         Label dataIsNotUndefined(env);
10131         BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &exit, &dataIsNotUndefined);
10132         Bind(&dataIsNotUndefined);
10133         {
10134             GateRef dataOffset = Int32(TaggedArray::DATA_OFFSET);
10135             GateRef indexOffset = Int32Mul(ZExtInt8ToInt32(index), Int32(JSTaggedValue::TaggedTypeSize()));
10136             GateRef offset = Int32Add(indexOffset, dataOffset);
10137             result = Load(VariableType::JS_ANY(), dictionary, offset);
10138             Jump(&exit);
10139         }
10140     }
10141     Bind(&exit);
10142     auto ret = *result;
10143     env->SubCfgExit();
10144     return ret;
10145 }
10146 
GetArgumentsElements(GateRef glue,GateRef argvTaggedArray,GateRef argv)10147 GateRef StubBuilder::GetArgumentsElements(GateRef glue, GateRef argvTaggedArray, GateRef argv)
10148 {
10149     auto env = GetEnvironment();
10150     Label entry(env);
10151     env->SubCfgEntry(&entry);
10152     Label exit(env);
10153     DEFVARIABLE(result, VariableType::NATIVE_POINTER(), NullPtr());
10154     DEFVARIABLE(argvVar, VariableType::NATIVE_POINTER(), argv);
10155 
10156     Label calcArgv(env);
10157     Label hasArgv(env);
10158     Label argvTaggedArrayUndef(env);
10159     Label argvTaggedArrayDef(env);
10160 
10161     BRANCH(TaggedIsUndefined(argvTaggedArray), &argvTaggedArrayUndef, &argvTaggedArrayDef);
10162     Bind(&argvTaggedArrayUndef);
10163 
10164     BRANCH(Equal(*argvVar, IntPtr(0)), &calcArgv, &hasArgv);
10165     Bind(&calcArgv);
10166     argvVar = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
10167     Jump(&hasArgv);
10168 
10169     Bind(&argvTaggedArrayDef);
10170     argvVar = PtrAdd(TaggedCastToIntPtr(argvTaggedArray), IntPtr(TaggedArray::DATA_OFFSET));
10171     Jump(&hasArgv);
10172 
10173     Bind(&hasArgv);
10174     result = PtrAdd(*argvVar, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
10175     Jump(&exit);
10176     Bind(&exit);
10177     auto ret = *result;
10178     env->SubCfgExit();
10179     return ret;
10180 }
10181 
10182 }  // namespace panda::ecmascript::kungfu
10183