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