• 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_proxy_stub_builder.h"
20 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
21 #include "ecmascript/compiler/builtins/builtins_collection_stub_builder.h"
22 #include "ecmascript/compiler/new_object_stub_builder.h"
23 #include "ecmascript/compiler/object_operator_stub_builder.h"
24 #include "ecmascript/compiler/profiler_stub_builder.h"
25 #include "ecmascript/elements.h"
26 #include "ecmascript/compiler/stub_builder.h"
27 #include "ecmascript/ic/mega_ic_cache.h"
28 #include "ecmascript/js_api/js_api_arraylist.h"
29 #include "ecmascript/js_primitive_ref.h"
30 #include "ecmascript/lexical_env.h"
31 #include "ecmascript/marker_cell.h"
32 #include "ecmascript/require/js_cjs_module_cache.h"
33 #include "ecmascript/transitions_dictionary.h"
34 #include "common_components/heap/allocator/region_desc.h"
35 #include "objects/base_state_word.h"
36 
37 namespace panda::ecmascript::kungfu {
Jump(Label * label)38 void StubBuilder::Jump(Label *label)
39 {
40     ASSERT(label);
41     auto currentLabel = env_->GetCurrentLabel();
42     auto currentControl = currentLabel->GetControl();
43     auto jump = env_->GetBuilder()->Goto(currentControl);
44     currentLabel->SetControl(jump);
45     label->AppendPredecessor(currentLabel);
46     label->MergeControl(currentLabel->GetControl());
47     env_->SetCurrentLabel(nullptr);
48 }
49 
Branch(GateRef condition,Label * trueLabel,Label * falseLabel,uint32_t trueWeight,uint32_t falseWeight,const char * comment)50 void StubBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel,
51                         uint32_t trueWeight, uint32_t falseWeight, const char *comment)
52 {
53     auto currentLabel = env_->GetCurrentLabel();
54     auto currentControl = currentLabel->GetControl();
55     GateRef ifBranch = env_->GetBuilder()->Branch(currentControl, condition, trueWeight, falseWeight, comment);
56     currentLabel->SetControl(ifBranch);
57     GateRef ifTrue = env_->GetBuilder()->IfTrue(ifBranch);
58     trueLabel->AppendPredecessor(env_->GetCurrentLabel());
59     trueLabel->MergeControl(ifTrue);
60     GateRef ifFalse = env_->GetBuilder()->IfFalse(ifBranch);
61     falseLabel->AppendPredecessor(env_->GetCurrentLabel());
62     falseLabel->MergeControl(ifFalse);
63     env_->SetCurrentLabel(nullptr);
64 }
65 
66 template <class LabelPtrGetter>
SwitchGeneric(GateRef index,Label * defaultLabel,Span<const int64_t> keysValue,LabelPtrGetter getIthLabelFn)67 void StubBuilder::SwitchGeneric(GateRef index, Label *defaultLabel, Span<const int64_t> keysValue,
68                                 LabelPtrGetter getIthLabelFn)
69 {
70     static_assert(std::is_invocable_r_v<Label*, LabelPtrGetter, size_t>, "Invalid call signature.");
71     size_t numberOfKeys = keysValue.Size();
72     auto currentLabel = env_->GetCurrentLabel();
73     auto currentControl = currentLabel->GetControl();
74     GateRef switchBranch = env_->GetBuilder()->SwitchBranch(currentControl, index, numberOfKeys);
75     currentLabel->SetControl(switchBranch);
76     for (size_t i = 0; i < numberOfKeys; i++) {
77         GateRef switchCase = env_->GetBuilder()->SwitchCase(switchBranch, keysValue[i]);
78         Label *curLabel = std::invoke(getIthLabelFn, i);
79         curLabel->AppendPredecessor(currentLabel);
80         curLabel->MergeControl(switchCase);
81     }
82 
83     GateRef defaultCase = env_->GetBuilder()->DefaultCase(switchBranch);
84     defaultLabel->AppendPredecessor(currentLabel);
85     defaultLabel->MergeControl(defaultCase);
86     env_->SetCurrentLabel(nullptr);
87 }
88 
Switch(GateRef index,Label * defaultLabel,const int64_t * keysValue,Label * keysLabel,int numberOfKeys)89 void StubBuilder::Switch(GateRef index, Label *defaultLabel,
90                          const int64_t *keysValue, Label *keysLabel, int numberOfKeys)
91 {
92     return SwitchGeneric(index, defaultLabel, {keysValue, numberOfKeys}, [keysLabel](size_t i) {
93         return &keysLabel[i];
94     });
95 }
96 
Switch(GateRef index,Label * defaultLabel,const int64_t * keysValue,Label * const * keysLabel,int numberOfKeys)97 void StubBuilder::Switch(GateRef index, Label *defaultLabel,
98                          const int64_t *keysValue, Label *const *keysLabel, int numberOfKeys)
99 {
100     return SwitchGeneric(index, defaultLabel, {keysValue, numberOfKeys}, [keysLabel](size_t i) {
101         return keysLabel[i];
102     });
103 }
104 
LoopBegin(Label * loopHead)105 void StubBuilder::LoopBegin(Label *loopHead)
106 {
107     ASSERT(loopHead);
108     auto loopControl = env_->GetBuilder()->LoopBegin(loopHead->GetControl());
109     loopHead->SetControl(loopControl);
110     loopHead->SetPreControl(loopControl);
111     loopHead->Bind();
112     env_->SetCurrentLabel(loopHead);
113 }
114 
CheckSuspend(GateRef glue)115 GateRef StubBuilder::CheckSuspend(GateRef glue)
116 {
117     GateRef stateAndFlagsOffset = IntPtr(JSThread::GlueData::GetStateAndFlagsOffset(env_->IsArch32Bit()));
118     GateRef stateAndFlags = LoadPrimitive(VariableType::INT16(), glue, stateAndFlagsOffset);
119     return Int32And(ZExtInt16ToInt32(stateAndFlags), Int32(ThreadFlag::SUSPEND_REQUEST));
120 }
121 
CheckSuspendForCMCGC(GateRef glue)122 GateRef StubBuilder::CheckSuspendForCMCGC(GateRef glue)
123 {
124     GateRef threadHolderOffset = IntPtr(JSThread::GlueData::GetThreadHolderOffset(env_->IsArch32Bit()));
125     GateRef threadHolder = LoadPrimitive(VariableType::NATIVE_POINTER(), glue, threadHolderOffset);
126     GateRef mutatorBase = LoadPrimitive(VariableType::NATIVE_POINTER(), threadHolder, IntPtr(ThreadHolder::GetMutatorBaseOffset()));
127     GateRef safepointActive = LoadPrimitive(VariableType::INT32(), mutatorBase, IntPtr(common::MutatorBase::GetSafepointActiveOffset()));
128     return safepointActive;
129 }
130 
LoopEndWithCheckSafePoint(Label * loopHead,Environment * env,GateRef glue)131 void StubBuilder::LoopEndWithCheckSafePoint(Label *loopHead, Environment *env, GateRef glue)
132 {
133     Label loopEnd(env);
134     Label needSuspend(env);
135     Label checkSuspendForCMCGC(env);
136     Label checkSuspend(env);
137     BRANCH_UNLIKELY(LoadPrimitive(
138         VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
139         &checkSuspendForCMCGC, &checkSuspend);
140     Bind(&checkSuspend);
141     BRANCH_UNLIKELY(Int32Equal(Int32(ThreadFlag::SUSPEND_REQUEST), CheckSuspend(glue)), &needSuspend, &loopEnd);
142     Bind(&checkSuspendForCMCGC);
143     BRANCH_UNLIKELY(Int32Equal(Int32(ThreadFlag::SUSPEND_REQUEST), CheckSuspendForCMCGC(glue)), &needSuspend, &loopEnd);
144     Bind(&needSuspend);
145     {
146         CallRuntime(glue, RTSTUB_ID(CheckSafePoint), {});
147         Jump(&loopEnd);
148     }
149     Bind(&loopEnd);
150     LoopEnd(loopHead);
151 }
152 
LoopEnd(Label * loopHead)153 void StubBuilder::LoopEnd(Label *loopHead)
154 {
155     ASSERT(loopHead);
156     auto currentLabel = env_->GetCurrentLabel();
157     auto currentControl = currentLabel->GetControl();
158     auto loopend = env_->GetBuilder()->LoopEnd(currentControl);
159     currentLabel->SetControl(loopend);
160     loopHead->AppendPredecessor(currentLabel);
161     loopHead->MergeControl(loopend);
162     loopHead->Seal();
163     loopHead->MergeAllControl();
164     loopHead->MergeAllDepend();
165     env_->SetCurrentLabel(nullptr);
166 }
167 
MatchFieldType(GateRef glue,GateRef fieldType,GateRef value,Label * executeSetProp,Label * typeMismatch)168 void StubBuilder::MatchFieldType(
169     GateRef glue, GateRef fieldType, GateRef value, Label *executeSetProp, Label *typeMismatch)
170 {
171     auto *env = GetEnvironment();
172     Label valueIsUndefined(env);
173     Label checkNumber(env);
174     Label isNumber(env);
175     Label checkBoolean(env);
176     Label isBoolean(env);
177     Label checkString(env);
178     Label isString(env);
179     Label checkJSShared(env);
180     Label isJSShared(env);
181     Label checkBigInt(env);
182     Label isBigInt(env);
183     Label checkNoneOrGeneric(env);
184     Label isNoneOrGeneric(env);
185     Label checkNull(env);
186     Label isNull(env);
187     Label checkUndefined(env);
188     Label isUndefined(env);
189     Label exit(env);
190     Label mismatch(env);
191     Label checkMatch(env);
192     DEFVARIABLE(result, VariableType::BOOL(), False());
193     GateRef checkType = TaggedIsUndefined(value);
194     BRANCH(checkType, &valueIsUndefined, &checkNumber);
195     Bind(&valueIsUndefined);
196     {
197         result = True();
198         Jump(&exit);
199     }
200     Bind(&checkNumber);
201     {
202         checkType = LogicAndBuilder(env)
203             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NUMBER))), Int32(0)))
204             .And(TaggedIsNumber(value))
205             .Done();
206         BRANCH(checkType, &isNumber, &checkBoolean);
207         Bind(&isNumber);
208         {
209             result = True();
210             Jump(&exit);
211         }
212     }
213     Bind(&checkBoolean);
214     {
215         checkType = LogicAndBuilder(env)
216             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::BOOLEAN))), Int32(0)))
217             .And(TaggedIsBoolean(value))
218             .Done();
219         BRANCH(checkType, &isBoolean, &checkString);
220         Bind(&isBoolean);
221         {
222             result = True();
223             Jump(&exit);
224         }
225     }
226     Bind(&checkString);
227     {
228         checkType = LogicAndBuilder(env)
229             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::STRING))), Int32(0)))
230             .And(LogicOrBuilder(env).Or(TaggedIsString(glue, value)).Or(TaggedIsNull(value)).Done())
231             .Done();
232         BRANCH(checkType, &isString, &checkJSShared);
233         Bind(&isString);
234         {
235             result = True();
236             Jump(&exit);
237         }
238     }
239     Bind(&checkJSShared);
240     {
241         checkType = LogicAndBuilder(env)
242             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::SENDABLE))), Int32(0)))
243             .And(LogicOrBuilder(env).Or(TaggedIsSharedObj(glue, value)).Or(TaggedIsNull(value)).Done())
244             .Done();
245         BRANCH(checkType, &isJSShared, &checkBigInt);
246         Bind(&isJSShared);
247         {
248             result = True();
249             Jump(&exit);
250         }
251     }
252     Bind(&checkBigInt);
253     {
254         checkType = LogicAndBuilder(env)
255             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::BIG_INT))), Int32(0)))
256             .And(TaggedIsBigInt(glue, value))
257             .Done();
258         BRANCH(checkType, &isBigInt, &checkNoneOrGeneric);
259         Bind(&isBigInt);
260         {
261             result = True();
262             Jump(&exit);
263         }
264     }
265     Bind(&checkNoneOrGeneric);
266     {
267         GateRef fieldTypeCheck = LogicOrBuilder(env)
268             .Or(Equal(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NONE))))
269             .Or(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::GENERIC))), Int32(0)))
270             .Done();
271         checkType = LogicAndBuilder(env)
272             .And(fieldTypeCheck)
273             .And(LogicOrBuilder(env).Or(BoolNot(TaggedIsHeapObject(value))).Or(TaggedIsSharedObj(glue, value)).Done())
274             .Done();
275         BRANCH(checkType, &isNoneOrGeneric, &checkNull);
276         Bind(&isNoneOrGeneric);
277         {
278             // (none || generic) && (jsShared || !heapObject)
279             result = True();
280             Jump(&exit);
281         }
282     }
283     Bind(&checkNull);
284     {
285         checkType = LogicAndBuilder(env)
286             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NULL_TYPE))), Int32(0)))
287             .And(TaggedIsNull(value))
288             .Done();
289         BRANCH(checkType, &isNull, &checkUndefined);
290         Bind(&isNull);
291         {
292             result = True();
293             Jump(&exit);
294         }
295     }
296     Bind(&checkUndefined);
297     {
298         checkType = LogicAndBuilder(env)
299             .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::UNDEFINED))), Int32(0)))
300             .And(TaggedIsUndefined(value))
301             .Done();
302         BRANCH(checkType, &isUndefined, &exit);
303         Bind(&isUndefined);
304         {
305             result = True();
306             Jump(&exit);
307         }
308     }
309     Bind(&exit);
310     Branch(BoolNot(*result), &mismatch, &checkMatch);
311     Bind(&mismatch);
312     {
313         CallRuntime(glue, RTSTUB_ID(MismatchError), {IntToTaggedInt(fieldType), value});
314         Jump(&checkMatch);
315     }
316     Bind(&checkMatch);
317     BRANCH(*result, executeSetProp, typeMismatch);
318 }
319 
320 // FindElementWithCache in ecmascript/layout_info-inl.h
FindElementWithCache(GateRef glue,GateRef layoutInfo,GateRef hclass,GateRef key,GateRef propsNum,GateRef hir)321 GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, GateRef hclass,
322     GateRef key, GateRef propsNum, GateRef hir)
323 {
324     auto env = GetEnvironment();
325     Label subEntry(env);
326     env->SubCfgEntry(&subEntry);
327     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
328     Label exit(env);
329     Label notExceedUpper(env);
330     Label exceedUpper(env);
331     // 9 : Builtins Object properties number is nine
332     constexpr int32_t maxPropsNum = 9;
333     BRANCH(Int32LessThanOrEqual(propsNum, Int32(maxPropsNum)), &notExceedUpper, &exceedUpper);
334     Bind(&notExceedUpper);
335     {
336         Label labels[maxPropsNum] = {Label(env), Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
337                                      Label(env), Label(env)};
338         Label notFount(env);
339         GateRef elementAddr = GetPropertiesAddrFromLayoutInfo(layoutInfo);
340         Jump(&labels[0]);
341         for (int32_t idx = 0; idx < maxPropsNum; idx++) {
342             bool isLast = (idx == maxPropsNum - 1);
343             Label check(env);
344             Bind(&labels[idx]);
345             {
346                 BRANCH_LIKELY(Int32LessThan(Int32(idx), propsNum), &check, &notFount);
347                 // Not real "likely", just to make the code layout of labels and check block tightly.
348             }
349             Bind(&check);
350             {
351                 result = Int32(idx);
352                 GateRef keyInProperty = Load(VariableType::JS_ANY(), glue, elementAddr,
353                                              PtrMul(ZExtInt32ToPtr(Int32(idx)),
354                                                     IntPtr(sizeof(panda::ecmascript::Properties))));
355                 if (!isLast) {
356                     BRANCH_UNLIKELY(Equal(keyInProperty, key), &exit, &labels[idx + 1]);
357                     // Not real "unlikely", just to make the code layout of labels and check block tightly.
358                 } else {
359                     BRANCH(Equal(keyInProperty, key), &exit, &notFount);
360                 }
361             }
362         }
363         Bind(&notFount);
364         result = Int32(-1);
365         Jump(&exit);
366     }
367     Bind(&exceedUpper);
368     Label find(env);
369     Label notFind(env);
370     Label setCache(env);
371     GateRef cache = GetPropertiesCache(glue);
372     GateRef index = GetIndexFromPropertiesCache(glue, cache, hclass, key, hir);
373     BRANCH(Int32Equal(index, Int32(PropertiesCache::NOT_FOUND)), &notFind, &find);
374     Bind(&notFind);
375     {
376         result = BinarySearch(glue, layoutInfo, key, propsNum, hir);
377         BRANCH(Int32Equal(*result, Int32(PropertiesCache::NOT_FOUND)), &exit, &setCache);
378         Bind(&setCache);
379         SetToPropertiesCache(glue, cache, hclass, key, *result, hir);
380         Jump(&exit);
381     }
382     Bind(&find);
383     {
384         result = index;
385         Jump(&exit);
386     }
387     Bind(&exit);
388     auto ret = *result;
389     env->SubCfgExit();
390     return ret;
391 }
392 
GetIndexFromPropertiesCache(GateRef glue,GateRef cache,GateRef cls,GateRef key,GateRef hir)393 GateRef StubBuilder::GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef hir)
394 {
395     auto env = GetEnvironment();
396     Label subentry(env);
397     env->SubCfgEntry(&subentry);
398     DEFVARIABLE(result, VariableType::INT32(), Int32(PropertiesCache::NOT_FOUND));
399 
400     Label exit(env);
401     Label find(env);
402     GateRef hash = HashFromHclassAndKey(glue, cls, key, hir);
403     GateRef prop =
404         PtrAdd(cache, PtrMul(ZExtInt32ToPtr(hash), IntPtr(PropertiesCache::PropertyKey::GetPropertyKeySize())));
405     size_t propHclassOffset = PropertiesCache::PropertyKey::GetHclassOffset();
406     size_t propKeyOffset = PropertiesCache::PropertyKey::GetKeyOffset();
407     BRANCH(LogicAndBuilder(env)
408         .And(IntPtrEqual(cls, Load(VariableType::JS_POINTER(), glue, prop, IntPtr(propHclassOffset))))
409         .And(IntPtrEqual(key, Load(VariableType::JS_ANY(), glue, prop, IntPtr(propKeyOffset))))
410         .Done(), &find, &exit);
411     Bind(&find);
412     {
413         result = LoadPrimitive(VariableType::INT32(), prop, IntPtr(PropertiesCache::PropertyKey::GetResultsOffset()));
414         Jump(&exit);
415     }
416     Bind(&exit);
417     auto ret = *result;
418     env->SubCfgExit();
419     return ret;
420 }
421 
GetHandlerFromMegaICCache(GateRef glue,GateRef cache,GateRef cls,GateRef key)422 GateRef StubBuilder::GetHandlerFromMegaICCache(GateRef glue, GateRef cache, GateRef cls, GateRef key)
423 {
424     auto env = GetEnvironment();
425     Label subentry(env);
426     env->SubCfgEntry(&subentry);
427     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
428     Label exit(env);
429     Label find(env);
430     GateRef hash = HashFromHclassAndStringKey(glue, cls, key);
431 
432     GateRef prop = PtrAdd(cache, PtrMul(ZExtInt32ToPtr(hash), IntPtr(MegaICCache::PropertyKey::GetPropertyKeySize())));
433     GateRef propHclass = Load(VariableType::JS_POINTER(), glue, prop, IntPtr(MegaICCache::PropertyKey::GetHclassOffset()));
434     GateRef propKey = Load(VariableType::JS_ANY(), glue, prop, IntPtr(MegaICCache::PropertyKey::GetKeyOffset()));
435 
436     GateRef hclassIsEqual = IntPtrEqual(cls, propHclass);
437     GateRef keyIsEqual = IntPtrEqual(key, propKey);
438     IncMegaProbeCount(glue);
439     BRANCH(BitAnd(hclassIsEqual, keyIsEqual), &find, &exit);
440     Bind(&find);
441     {
442         result = Load(VariableType::JS_ANY(), glue, prop, IntPtr(MegaICCache::PropertyKey::GetResultsOffset()));
443         IncMegaHitCount(glue);
444         Jump(&exit);
445     }
446     Bind(&exit);
447     auto ret = *result;
448     env->SubCfgExit();
449     return ret;
450 }
451 
452 
BinarySearch(GateRef glue,GateRef layoutInfo,GateRef key,GateRef propsNum,GateRef hir)453 GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum, GateRef hir)
454 {
455     auto env = GetEnvironment();
456     Label subentry(env);
457     env->SubCfgEntry(&subentry);
458     DEFVARIABLE(low, VariableType::INT32(), Int32(0));
459     Label exit(env);
460     GateRef elements = GetExtraLengthOfTaggedArray(layoutInfo);
461     DEFVARIABLE(high, VariableType::INT32(), Int32Sub(elements, Int32(1)));
462     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
463     DEFVARIABLE(mid, VariableType::INT32(), Int32(-1));
464 
465     GateRef keyHash = GetKeyHashCode(glue, key, hir);
466     Label loopHead(env);
467     Label loopEnd(env);
468     Label afterLoop(env);
469     Label midGreaterKey(env);
470     Label midnotGreaterKey(env);
471     Label midLessKey(env);
472     Label midEqualKey(env);
473     Label next(env);
474     Jump(&loopHead);
475     LoopBegin(&loopHead);
476     {
477         BRANCH(Int32LessThanOrEqual(*low, *high), &next, &exit);
478         Bind(&next);
479         mid = Int32Add(*low, Int32Div(Int32Sub(*high, *low), Int32(2)));  // 2: half
480         GateRef midKey = GetSortedKey(glue, layoutInfo, *mid);
481         GateRef midHash = GetKeyHashCode(glue, midKey, hir);
482         BRANCH(Int32UnsignedGreaterThan(midHash, keyHash), &midGreaterKey, &midnotGreaterKey);
483         Bind(&midGreaterKey);
484         {
485             high = Int32Sub(*mid, Int32(1));
486             Jump(&loopEnd);
487         }
488         Bind(&midnotGreaterKey);
489         {
490             BRANCH(Int32UnsignedLessThan(midHash, keyHash), &midLessKey, &midEqualKey);
491             Bind(&midLessKey);
492             {
493                 low = Int32Add(*mid, Int32(1));
494                 Jump(&loopEnd);
495             }
496             Bind(&midEqualKey);
497             {
498                 Label retIndex(env);
499                 Label nextLoop(env);
500                 DEFVARIABLE(sortIndex, VariableType::INT32(), GetSortedIndex(glue, layoutInfo, *mid));
501                 DEFVARIABLE(currentKey, VariableType::JS_ANY(), midKey);
502                 BRANCH(IntPtrEqual(midKey, key), &retIndex, &nextLoop);
503                 Bind(&retIndex);
504                 {
505                     Label retSortIndex(env);
506                     BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
507                     Bind(&retSortIndex);
508                     {
509                         result = *sortIndex;
510                         Jump(&exit);
511                     }
512                 }
513                 Bind(&nextLoop);
514                 {
515                     DEFVARIABLE(midLeft, VariableType::INT32(), *mid);
516                     DEFVARIABLE(midRight, VariableType::INT32(), *mid);
517                     Label loopHead1(env);
518                     Label loopEnd1(env);
519                     Label afterLoop1(env);
520                     Label nextCount(env);
521                     Jump(&loopHead1);
522                     LoopBegin(&loopHead1);
523                     {
524                         BRANCH(Int32GreaterThanOrEqual(Int32Sub(*midLeft, Int32(1)), Int32(0)),
525                             &nextCount, &afterLoop1);
526                         Bind(&nextCount);
527                         {
528                             Label hashEqual(env);
529                             midLeft = Int32Sub(*midLeft, Int32(1));
530                             sortIndex = GetSortedIndex(glue, layoutInfo, *midLeft);
531                             currentKey = GetKey(glue, layoutInfo, *sortIndex);
532                             BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual,
533                                    &afterLoop1);
534                             Bind(&hashEqual);
535                             {
536                                 Label retIndex1(env);
537                                 BRANCH(IntPtrEqual(*currentKey, key), &retIndex1, &loopEnd1);
538                                 Bind(&retIndex1);
539                                 {
540                                     Label retSortIndex(env);
541                                     BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
542                                     Bind(&retSortIndex);
543                                     {
544                                         result = *sortIndex;
545                                         Jump(&exit);
546                                     }
547                                 }
548                             }
549                         }
550                         Bind(&loopEnd1);
551                         {
552                             LoopEnd(&loopHead1);
553                         }
554                     }
555                     Bind(&afterLoop1);
556                     {
557                         Label loopHead2(env);
558                         Label loopEnd2(env);
559                         Label nextCount1(env);
560                         Jump(&loopHead2);
561                         LoopBegin(&loopHead2);
562                         {
563                             BRANCH(Int32LessThan(Int32Add(*midRight, Int32(1)), elements), &nextCount1, &exit);
564                             Bind(&nextCount1);
565                             {
566                                 Label hashEqual(env);
567                                 midRight = Int32Add(*midRight, Int32(1));
568                                 sortIndex = GetSortedIndex(glue, layoutInfo, *midRight);
569                                 currentKey = GetKey(glue, layoutInfo, *sortIndex);
570                                 BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual, &exit);
571                                 Bind(&hashEqual);
572                                 {
573                                     Label retIndex2(env);
574                                     BRANCH(IntPtrEqual(*currentKey, key), &retIndex2, &loopEnd2);
575                                     Bind(&retIndex2);
576                                     {
577                                         Label retSortIndex(env);
578                                         BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
579                                         Bind(&retSortIndex);
580                                         {
581                                             result = *sortIndex;
582                                             Jump(&exit);
583                                         }
584                                     }
585                                 }
586                             }
587                             Bind(&loopEnd2);
588                             {
589                                 LoopEnd(&loopHead2);
590                             }
591                         }
592                     }
593                 }
594             }
595         }
596     }
597 
598     Bind(&loopEnd);
599     {
600         LoopEnd(&loopHead);
601     }
602 
603     Bind(&exit);
604     auto ret = *result;
605     env->SubCfgExit();
606     return ret;
607 }
608 
GetKeyHashCode(GateRef glue,GateRef key,GateRef hir)609 GateRef StubBuilder::GetKeyHashCode(GateRef glue, GateRef key, GateRef hir)
610 {
611     auto env = GetEnvironment();
612     Label subentry(env);
613     env->SubCfgEntry(&subentry);
614     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
615 
616     Label exit(env);
617     Label isString(env);
618     Label isSymblo(env);
619     BRANCH(TaggedIsString(glue, key), &isString, &isSymblo);
620     Bind(&isString);
621     {
622         result = GetHashcodeFromString(glue, key, hir);
623         Jump(&exit);
624     }
625     Bind(&isSymblo);
626     {
627         result = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), key,
628             IntPtr(JSSymbol::HASHFIELD_OFFSET)));
629         Jump(&exit);
630     }
631     Bind(&exit);
632     auto ret = *result;
633     env->SubCfgExit();
634     return ret;
635 }
636 
637 // JSObject::CreateDataProperty
CreateDataProperty(GateRef glue,GateRef obj,GateRef propKey,GateRef value)638 GateRef StubBuilder::CreateDataProperty(GateRef glue, GateRef obj, GateRef propKey, GateRef value)
639 {
640     auto env = GetEnvironment();
641     Label subentry(env);
642     env->SubCfgEntry(&subentry);
643     Label exit(env);
644     Label next(env);
645     Label objIsShared(env);
646     Label objIsNotShared(env);
647     Label isHole(env);
648     Label notHole(env);
649     Label hasPendingException(env);
650 
651     DEFVARIABLE(result, VariableType::BOOL(), True());
652     GateRef SCheckModelIsCHECK = Boolean(true);
653     auto flag = DefinePropertyByValue(glue, obj, propKey, value, SCheckModelIsCHECK, ProfileOperation());
654     BRANCH(HasPendingException(glue), &hasPendingException, &next);
655     Bind(&hasPendingException);
656     {
657         result = False();
658         Jump(&exit);
659     }
660     Bind(&next);
661     {
662         BRANCH(TaggedIsHole(flag), &isHole, &notHole);
663         Bind(&isHole);
664         {
665             GateRef temp = CallRuntime(glue, RTSTUB_ID(DefineOwnProperty), {obj, propKey, value});
666             result = TaggedIsTrue(temp);
667             Jump(&exit);
668         }
669         Bind(&notHole);
670         {
671             result = BoolNot(TaggedIsException(flag));
672             Jump(&exit);
673         }
674     }
675     Bind(&exit);
676     auto ret = *result;
677     env->SubCfgExit();
678     return ret;
679 }
680 
CreateDataPropertyOrThrow(GateRef glue,GateRef obj,GateRef key,GateRef value)681 GateRef StubBuilder::CreateDataPropertyOrThrow(GateRef glue, GateRef obj, GateRef key, GateRef value)
682 {
683     auto env = GetEnvironment();
684     Label subentry(env);
685     env->SubCfgEntry(&subentry);
686     Label exit(env);
687     Label newThrow(env);
688     Label isThrow(env);
689 
690     DEFVARIABLE(result, VariableType::BOOL(), True());
691 
692     CanNotConvertNotValidObject(glue, obj);
693     IsNotPropertyKey(TaggedIsPropertyKey(glue, key));
694 
695     result = CreateDataProperty(glue, obj, key, value);
696     BRANCH(*result, &exit, &isThrow);
697 
698     Bind(&isThrow);
699     {
700         BRANCH(HasPendingException(glue), &exit, &newThrow);
701         Bind(&newThrow);
702         {
703             GateRef msgIntId = Int32(GET_MESSAGE_STRING_ID(CreateDataPropertyFailed));
704             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId)});
705             Jump(&exit);
706         }
707     }
708 
709     Bind(&exit);
710     auto ret = *result;
711     env->SubCfgExit();
712     return ret;
713 }
714 
DefineField(GateRef glue,GateRef obj,GateRef propKey,GateRef value)715 GateRef StubBuilder::DefineField(GateRef glue, GateRef obj, GateRef propKey, GateRef value)
716 {
717     auto env = GetEnvironment();
718     Label entry(env);
719     env->SubCfgEntry(&entry);
720     Label exit(env);
721     Label next(env);
722     Label notObj(env);
723     Label newThrow(env);
724     Label isObj(env);
725     Label hasPendingException(env);
726     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
727     DEFVARIABLE(key, VariableType::JS_ANY(), Undefined());
728     BRANCH(IsEcmaObject(glue, obj), &isObj, &notObj);
729     Bind(&isObj);
730     {
731 #if ENABLE_NEXT_OPTIMIZATION
732         key = ToPropertyKey(glue, propKey);
733 #else
734         key = CallRuntime(glue, RTSTUB_ID(ToPropertyKey), {propKey});
735 #endif
736         BRANCH(HasPendingException(glue), &hasPendingException, &next);
737     }
738     Bind(&next);
739     {
740         CreateDataPropertyOrThrow(glue, obj, *key, value);
741         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
742     }
743     Bind(&notObj);
744     {
745         BRANCH(HasPendingException(glue), &hasPendingException, &newThrow);
746     }
747     Bind(&hasPendingException);
748     {
749         result = Exception();
750         Jump(&exit);
751     }
752     Bind(&newThrow);
753     {
754         GateRef msgIntId = Int32(GET_MESSAGE_STRING_ID(DefineFieldField));
755         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId)});
756         result = Exception();
757         Jump(&exit);
758     }
759 
760     Bind(&exit);
761     auto ret = *result;
762     env->SubCfgExit();
763     return ret;
764 }
765 
FindElementFromNumberDictionary(GateRef glue,GateRef elements,GateRef index)766 GateRef StubBuilder::FindElementFromNumberDictionary(GateRef glue, GateRef elements, GateRef index)
767 {
768     auto env = GetEnvironment();
769     Label subentry(env);
770     env->SubCfgEntry(&subentry);
771     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
772     Label exit(env);
773     GateRef capcityoffset =
774         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
775                IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
776     GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
777     GateRef capacity = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), elements,
778                                            PtrAdd(dataoffset, capcityoffset)));
779     DEFVARIABLE(count, VariableType::INT32(), Int32(1));
780     GateRef len = Int32(sizeof(int) / sizeof(uint8_t));
781     GateRef hash = CallRuntime(glue, RTSTUB_ID(GetHash32),
782         { IntToTaggedInt(index), IntToTaggedInt(len) });
783     DEFVARIABLE(entry, VariableType::INT32(),
784         Int32And(TruncInt64ToInt32(ChangeTaggedPointerToInt64(hash)), Int32Sub(capacity, Int32(1))));
785     Label loopHead(env);
786     Label loopEnd(env);
787     Label afterLoop(env);
788     Jump(&loopHead);
789     LoopBegin(&loopHead);
790     GateRef element = GetKeyFromDictionary<NumberDictionary>(glue, elements, *entry);
791     Label isHole(env);
792     Label notHole(env);
793     BRANCH(TaggedIsHole(element), &isHole, &notHole);
794     Bind(&isHole);
795     Jump(&loopEnd);
796     Bind(&notHole);
797     Label isUndefined(env);
798     Label notUndefined(env);
799     BRANCH(TaggedIsUndefined(element), &isUndefined, &notUndefined);
800     Bind(&isUndefined);
801     result = Int32(-1);
802     Jump(&exit);
803     Bind(&notUndefined);
804     Label isMatch(env);
805     Label notMatch(env);
806     BRANCH(Int32Equal(index, GetInt32OfTInt(element)), &isMatch, &notMatch);
807     Bind(&isMatch);
808     result = *entry;
809     Jump(&exit);
810     Bind(&notMatch);
811     Jump(&loopEnd);
812     Bind(&loopEnd);
813     entry = GetNextPositionForHash(*entry, *count, capacity);
814     count = Int32Add(*count, Int32(1));
815     LoopEndWithCheckSafePoint(&loopHead, env, glue);
816     Bind(&exit);
817     auto ret = *result;
818     env->SubCfgExit();
819     return ret;
820 }
821 
822 // int TaggedHashTable<Derived>::FindEntry(const JSTaggedValue &key) in tagged_hash_table.h
823 template<typename HashTableT>
FindEntryFromHashTable(GateRef glue,GateRef elements,GateRef key,GateRef hir)824 GateRef StubBuilder::FindEntryFromHashTable(GateRef glue, GateRef elements, GateRef key, GateRef hir)
825 {
826     auto env = GetEnvironment();
827     Label funcEntry(env);
828     env->SubCfgEntry(&funcEntry);
829     Label exit(env);
830     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
831     GateRef capcityoffset =
832         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
833                IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
834     GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
835     GateRef capacity = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), elements,
836                                            PtrAdd(dataoffset, capcityoffset)));
837     DEFVARIABLE(count, VariableType::INT32(), Int32(1));
838     DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
839     // NameDictionary::hash
840     Label isSymbol(env);
841     Label notSymbol(env);
842     Label loopHead(env);
843     Label loopEnd(env);
844     Label afterLoop(env);
845     Label beforeDefineHash(env);
846     BRANCH(IsSymbol(glue, key), &isSymbol, &notSymbol);
847     Bind(&isSymbol);
848     {
849         hash = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), key,
850             IntPtr(JSSymbol::HASHFIELD_OFFSET)));
851         Jump(&beforeDefineHash);
852     }
853     Bind(&notSymbol);
854     {
855         Label isString(env);
856         Label notString(env);
857         BRANCH(IsString(glue, key), &isString, &notString);
858         Bind(&isString);
859         {
860             hash = GetHashcodeFromString(glue, key, hir);
861             Jump(&beforeDefineHash);
862         }
863         Bind(&notString);
864         {
865             Jump(&beforeDefineHash);
866         }
867     }
868     Bind(&beforeDefineHash);
869     // GetFirstPosition(hash, size)
870     DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
871     Jump(&loopHead);
872     LoopBegin(&loopHead);
873     {
874         GateRef element = GetKeyFromDictionary<HashTableT>(glue, elements, *entry);
875         Label isHole(env);
876         Label notHole(env);
877         BRANCH(TaggedIsHole(element), &isHole, &notHole);
878         {
879             Bind(&isHole);
880             {
881                 Jump(&loopEnd);
882             }
883             Bind(&notHole);
884             {
885                 Label isUndefined(env);
886                 Label notUndefined(env);
887                 BRANCH(TaggedIsUndefined(element), &isUndefined, &notUndefined);
888                 {
889                     Bind(&isUndefined);
890                     {
891                         result = Int32(-1);
892                         Jump(&exit);
893                     }
894                     Bind(&notUndefined);
895                     {
896                         Label isMatch(env);
897                         Label notMatch(env);
898                         BRANCH(Equal(key, element), &isMatch, &notMatch);
899                         {
900                             Bind(&isMatch);
901                             {
902                                 result = *entry;
903                                 Jump(&exit);
904                             }
905                             Bind(&notMatch);
906                             {
907                                 Jump(&loopEnd);
908                             }
909                         }
910                     }
911                 }
912             }
913         }
914         Bind(&loopEnd);
915         {
916             entry = GetNextPositionForHash(*entry, *count, capacity);
917             count = Int32Add(*count, Int32(1));
918             LoopEndWithCheckSafePoint(&loopHead, env, glue);
919         }
920     }
921     Bind(&exit);
922     auto ret = *result;
923     env->SubCfgExit();
924     return ret;
925 }
926 
IsMatchInTransitionDictionary(GateRef element,GateRef key,GateRef metaData,GateRef attr)927 GateRef StubBuilder::IsMatchInTransitionDictionary(GateRef element, GateRef key, GateRef metaData, GateRef attr)
928 {
929     return BitAnd(Equal(element, key), Int32Equal(metaData, attr));
930 }
931 
FindEntryFromTransitionDictionary(GateRef glue,GateRef elements,GateRef key,GateRef metaData)932 GateRef StubBuilder::FindEntryFromTransitionDictionary(GateRef glue, GateRef elements, GateRef key, GateRef metaData)
933 {
934     auto env = GetEnvironment();
935     Label funcEntry(env);
936     env->SubCfgEntry(&funcEntry);
937     Label exit(env);
938     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
939     GateRef capcityoffset =
940         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
941                IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
942     GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
943     GateRef capacity = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), elements,
944                                            PtrAdd(dataoffset, capcityoffset)));
945     DEFVARIABLE(count, VariableType::INT32(), Int32(1));
946     DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
947     // TransitionDictionary::hash
948     Label isSymbol(env);
949     Label notSymbol(env);
950     Label loopHead(env);
951     Label loopEnd(env);
952     Label afterLoop(env);
953     Label beforeDefineHash(env);
954     BRANCH(IsSymbol(glue, key), &isSymbol, &notSymbol);
955     Bind(&isSymbol);
956     {
957         hash = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), key,
958             IntPtr(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET)));
959         Jump(&beforeDefineHash);
960     }
961     Bind(&notSymbol);
962     {
963         Label isString(env);
964         Label notString(env);
965         BRANCH(IsString(glue, key), &isString, &notString);
966         Bind(&isString);
967         {
968             hash = GetHashcodeFromString(glue, key);
969             Jump(&beforeDefineHash);
970         }
971         Bind(&notString);
972         {
973             Jump(&beforeDefineHash);
974         }
975     }
976     Bind(&beforeDefineHash);
977     hash = Int32Add(*hash, metaData);
978     // GetFirstPosition(hash, size)
979     DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
980     Jump(&loopHead);
981     LoopBegin(&loopHead);
982     {
983         GateRef element = GetKeyFromDictionary<TransitionsDictionary>(glue, elements, *entry);
984         Label isHole(env);
985         Label notHole(env);
986         BRANCH(TaggedIsHole(element), &isHole, &notHole);
987         {
988             Bind(&isHole);
989             {
990                 Jump(&loopEnd);
991             }
992             Bind(&notHole);
993             {
994                 Label isUndefined(env);
995                 Label notUndefined(env);
996                 BRANCH(TaggedIsUndefined(element), &isUndefined, &notUndefined);
997                 {
998                     Bind(&isUndefined);
999                     {
1000                         result = Int32(-1);
1001                         Jump(&exit);
1002                     }
1003                     Bind(&notUndefined);
1004                     {
1005                         Label isMatch(env);
1006                         Label notMatch(env);
1007                         BRANCH(IsMatchInTransitionDictionary(element, key, metaData,
1008                             // metaData is int32 type
1009                             TruncInt64ToInt32(GetAttributesFromDictionary<TransitionsDictionary>(glue, elements, *entry))),
1010                             &isMatch, &notMatch);
1011                         {
1012                             Bind(&isMatch);
1013                             {
1014                                 result = *entry;
1015                                 Jump(&exit);
1016                             }
1017                             Bind(&notMatch);
1018                             {
1019                                 Jump(&loopEnd);
1020                             }
1021                         }
1022                     }
1023                 }
1024             }
1025         }
1026         Bind(&loopEnd);
1027         {
1028             entry = GetNextPositionForHash(*entry, *count, capacity);
1029             count = Int32Add(*count, Int32(1));
1030             LoopEndWithCheckSafePoint(&loopHead, env, glue);
1031         }
1032     }
1033     Bind(&exit);
1034     auto ret = *result;
1035     env->SubCfgExit();
1036     return ret;
1037 }
1038 
1039 // JSObject::HasProperty
JSObjectHasProperty(GateRef glue,GateRef obj,GateRef key,GateRef hir)1040 GateRef StubBuilder::JSObjectHasProperty(GateRef glue, GateRef obj, GateRef key, GateRef hir)
1041 {
1042     auto env = GetEnvironment();
1043     Label entry(env);
1044     env->SubCfgEntry(&entry);
1045     Label exit(env);
1046     Label checkHolder(env);
1047     DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
1048 
1049     IsNotPropertyKey(TaggedIsPropertyKey(glue, key));
1050 
1051     ObjectOperatorStubBuilder opStubBuilder(this, GetCurrentGlobalEnv());
1052 
1053     ObjectOperatorStubBuilder::ObjectOperatorOptions opOptions;
1054     opOptions.lookupKind = ObjectOperatorStubBuilder::LookupKind::KIND_HAS_PROPERTY;
1055 
1056     ObjectOperatorStubBuilder::ObjectOperatorResult opResult;
1057     opStubBuilder.InitializeOperatorResults(opResult);
1058     opResult.holder->WriteVariable(obj);
1059 
1060     opStubBuilder.StartLookup<ObjectOperatorStubBuilder::StartLookupType::NO_RECEIVER>(
1061         glue, key, &checkHolder, opOptions, opResult, hir);
1062 
1063     // if holder is JSProxy, op's lookup will return. This will be handled by CallRuntime.
1064     Bind(&checkHolder);
1065     {
1066         Label isJSProxy(env);
1067         Label isFound(env);
1068         BRANCH(TaggedIsJSProxy(glue, opResult.GetHolder()), &isJSProxy, &isFound);
1069         Bind(&isJSProxy);
1070         {
1071             result = CallRuntime(glue, RTSTUB_ID(JSProxyHasProperty), {opResult.GetHolder(), key});
1072             Jump(&exit);
1073         }
1074         Bind(&isFound);
1075         {
1076             result = BooleanToTaggedBooleanPtr(opStubBuilder.IsFound(opResult.metaData));
1077             Jump(&exit);
1078         }
1079     }
1080 
1081     Bind(&exit);
1082     auto ret = *result;
1083     opStubBuilder.FinalizeOperatorResults(opResult);
1084     env->SubCfgExit();
1085     return ret;
1086 }
1087 
JSObjectGetPropertyWithRep(GateRef glue,GateRef obj,GateRef hclass,GateRef attr)1088 GateRef StubBuilder::JSObjectGetPropertyWithRep(GateRef glue, GateRef obj, GateRef hclass, GateRef attr)
1089 {
1090     auto env = GetEnvironment();
1091     Label entry(env);
1092     env->SubCfgEntry(&entry);
1093     Label exit(env);
1094     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1095     Label inlinedProp(env);
1096     Label notInlinedProp(env);
1097     Label post(env);
1098     GateRef attrOffset = GetOffsetFieldInPropAttr(attr);
1099     GateRef rep = GetRepInPropAttr(attr);
1100     BRANCH(IsInlinedProperty(attr), &inlinedProp, &notInlinedProp);
1101     {
1102         Bind(&inlinedProp);
1103         {
1104             result = GetPropertyInlinedProps(glue, obj, hclass, attrOffset);
1105             Jump(&post);
1106         }
1107         Bind(&notInlinedProp);
1108         {
1109             // compute outOfLineProp offset, get it and return
1110             GateRef array =
1111                 Load(VariableType::JS_ANY(), glue, obj, IntPtr(JSObject::PROPERTIES_OFFSET));
1112             result = GetValueFromTaggedArray(glue, array, Int32Sub(attrOffset,
1113                 GetInlinedPropertiesFromHClass(hclass)));
1114             Jump(&post);
1115         }
1116     }
1117     Bind(&post);
1118     {
1119         Label nonDoubleToTagged(env);
1120         Label doubleToTagged(env);
1121         BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
1122         Bind(&doubleToTagged);
1123         {
1124             result = TaggedPtrToTaggedDoublePtr(*result);
1125             Jump(&exit);
1126         }
1127         Bind(&nonDoubleToTagged);
1128         {
1129             Label intToTagged(env);
1130             BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit);
1131             Bind(&intToTagged);
1132             {
1133                 result = TaggedPtrToTaggedIntPtr(*result);
1134                 Jump(&exit);
1135             }
1136         }
1137     }
1138     Bind(&exit);
1139     auto ret = *result;
1140     env->SubCfgExit();
1141     return ret;
1142 }
1143 
JSObjectSetProperty(GateRef glue,GateRef obj,GateRef hclass,GateRef attr,GateRef key,GateRef value)1144 void StubBuilder::JSObjectSetProperty(
1145     GateRef glue, GateRef obj, GateRef hclass, GateRef attr, GateRef key, GateRef value)
1146 {
1147     auto env = GetEnvironment();
1148     Label subEntry(env);
1149     env->SubCfgEntry(&subEntry);
1150     Label exit(env);
1151     Label inlinedProp(env);
1152     Label notInlinedProp(env);
1153     GateRef attrIndex = GetOffsetFieldInPropAttr(attr);
1154     BRANCH(IsInlinedProperty(attr), &inlinedProp, &notInlinedProp);
1155     {
1156         Bind(&inlinedProp);
1157         {
1158             GateRef offset = GetInlinedPropOffsetFromHClass(hclass, attrIndex);
1159             SetValueWithAttr(glue, obj, offset, key, value, attr);
1160             Jump(&exit);
1161         }
1162         Bind(&notInlinedProp);
1163         {
1164             // compute outOfLineProp offset, get it and return
1165             GateRef array = Load(VariableType::JS_POINTER(), glue, obj,
1166                                  IntPtr(JSObject::PROPERTIES_OFFSET));
1167             GateRef offset = Int32Sub(attrIndex, GetInlinedPropertiesFromHClass(hclass));
1168             SetValueToTaggedArrayWithAttr(glue, array, offset, key, value, attr);
1169             Jump(&exit);
1170         }
1171     }
1172     Bind(&exit);
1173     env->SubCfgExit();
1174     return;
1175 }
1176 
ComputeNonInlinedFastPropsCapacity(GateRef glue,GateRef oldLength,GateRef maxNonInlinedFastPropsCapacity)1177 GateRef StubBuilder::ComputeNonInlinedFastPropsCapacity(GateRef glue, GateRef oldLength,
1178                                                         GateRef maxNonInlinedFastPropsCapacity)
1179 {
1180     auto env = GetEnvironment();
1181     Label subEntry(env);
1182     env->SubCfgEntry(&subEntry);
1183     Label exit(env);
1184     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1185     GateRef propertiesStep = LoadPrimitive(VariableType::INT32(), glue,
1186         IntPtr(JSThread::GlueData::GetPropertiesGrowStepOffset(env->Is32Bit())));
1187     GateRef newL = Int32Add(oldLength, propertiesStep);
1188     Label reachMax(env);
1189     Label notReachMax(env);
1190     BRANCH(Int32GreaterThan(newL, maxNonInlinedFastPropsCapacity), &reachMax, &notReachMax);
1191     {
1192         Bind(&reachMax);
1193         result = maxNonInlinedFastPropsCapacity;
1194         Jump(&exit);
1195         Bind(&notReachMax);
1196         result = newL;
1197         Jump(&exit);
1198     }
1199     Bind(&exit);
1200     auto ret = *result;
1201     env->SubCfgExit();
1202     return ret;
1203 }
1204 #if ENABLE_NEXT_OPTIMIZATION
ComputeElementCapacity(GateRef oldLength)1205 GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength)
1206 {
1207     auto env = GetEnvironment();
1208     Label subEntry(env);
1209     env->SubCfgEntry(&subEntry);
1210     Label exit(env);
1211     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1212     GateRef newL = Int32Add(oldLength, Int32LSR(oldLength, Int32(1)));
1213     // Handle small array edge cases: for small arrays, 1.5 times expansion may not provide sufficient growth,
1214     // so adding a fixed value (like 16) avoids frequent capacity expansion in the short term.
1215     newL = Int32Add(newL, Int32(16));
1216     result = newL;
1217     Jump(&exit);
1218     Bind(&exit);
1219     auto ret = *result;
1220     env->SubCfgExit();
1221     return ret;
1222 }
1223 #else
ComputeElementCapacity(GateRef oldLength)1224 GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength)
1225 {
1226     auto env = GetEnvironment();
1227     Label subEntry(env);
1228     env->SubCfgEntry(&subEntry);
1229     Label exit(env);
1230     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1231     GateRef newL = Int32Add(oldLength, Int32LSR(oldLength, Int32(1)));
1232     Label reachMin(env);
1233     Label notReachMin(env);
1234     BRANCH(Int32GreaterThan(newL, Int32(JSObject::MIN_ELEMENTS_LENGTH)), &reachMin, &notReachMin);
1235     {
1236         Bind(&reachMin);
1237         result = newL;
1238         Jump(&exit);
1239         Bind(&notReachMin);
1240         result = Int32(JSObject::MIN_ELEMENTS_LENGTH);
1241         Jump(&exit);
1242     }
1243     Bind(&exit);
1244     auto ret = *result;
1245     env->SubCfgExit();
1246     return ret;
1247 }
1248 #endif
CallGetterHelper(GateRef glue,GateRef receiver,GateRef holder,GateRef accessor,ProfileOperation callback,GateRef hir)1249 GateRef StubBuilder::CallGetterHelper(
1250     GateRef glue, GateRef receiver, GateRef holder, GateRef accessor, ProfileOperation callback, GateRef hir)
1251 {
1252     auto env = GetEnvironment();
1253     Label subEntry(env);
1254     env->SubCfgEntry(&subEntry);
1255     Label exit(env);
1256     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
1257 
1258     Label isInternal(env);
1259     Label notInternal(env);
1260     BRANCH(IsAccessorInternal(glue, accessor), &isInternal, &notInternal);
1261     Bind(&isInternal);
1262     {
1263         Label arrayLength(env);
1264         Label tryContinue(env);
1265         auto lengthAccessor = GetGlobalConstantValue(
1266             VariableType::JS_POINTER(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1267         BRANCH(Equal(accessor, lengthAccessor), &arrayLength, &tryContinue);
1268         Bind(&arrayLength);
1269         {
1270             auto length = LoadPrimitive(VariableType::INT32(), holder, IntPtr(JSArray::LENGTH_OFFSET));
1271             // TaggedInt supports up to INT32_MAX.
1272             // If length is greater than Int32_MAX, needs to be converted to TaggedDouble.
1273             auto condition = Int32UnsignedGreaterThan(length, Int32(INT32_MAX));
1274             Label overflow(env);
1275             Label notOverflow(env);
1276             BRANCH(condition, &overflow, &notOverflow);
1277             Bind(&overflow);
1278             {
1279                 result = DoubleToTaggedDoublePtr(ChangeUInt32ToFloat64(length));
1280                 Jump(&exit);
1281             }
1282             Bind(&notOverflow);
1283             {
1284                 result = IntToTaggedPtr(length);
1285                 Jump(&exit);
1286             }
1287         }
1288         Bind(&tryContinue);
1289         result = CallRuntime(glue, RTSTUB_ID(CallInternalGetter), { accessor, holder });
1290         Jump(&exit);
1291     }
1292     Bind(&notInternal);
1293     {
1294         auto getter = Load(VariableType::JS_ANY(), glue, accessor,
1295                            IntPtr(AccessorData::GETTER_OFFSET));
1296         Label objIsUndefined(env);
1297         Label objNotUndefined(env);
1298         Label callExit(env);
1299         BRANCH(TaggedIsUndefined(getter), &objIsUndefined, &objNotUndefined);
1300         // if getter is undefined, return undefiend
1301         Bind(&objIsUndefined);
1302         {
1303             result = Undefined();
1304             Jump(&exit);
1305         }
1306         Bind(&objNotUndefined);
1307         {
1308             DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Exception());
1309             JSCallArgs callArgs(JSCallMode::CALL_GETTER);
1310             callArgs.callGetterArgs = { receiver };
1311             CallStubBuilder callBuilder(this, glue, getter, Int32(0), 0, &tmpResult, Circuit::NullGate(), callArgs,
1312                 callback, true, hir);
1313             if (env->IsBaselineBuiltin()) {
1314                 callBuilder.JSCallDispatchForBaseline(&callExit);
1315                 Bind(&callExit);
1316             } else {
1317                 tmpResult = callBuilder.JSCallDispatch();
1318             }
1319             Label noPendingException(env);
1320             BRANCH(HasPendingException(glue), &exit, &noPendingException);
1321             Bind(&noPendingException);
1322             {
1323                 result = *tmpResult;
1324                 Jump(&exit);
1325             }
1326         }
1327     }
1328     Bind(&exit);
1329     auto ret = *result;
1330     env->SubCfgExit();
1331     return ret;
1332 }
1333 
CallSetterHelper(GateRef glue,GateRef receiver,GateRef accessor,GateRef value,ProfileOperation callback,bool mayThrow)1334 GateRef StubBuilder::CallSetterHelper(
1335     GateRef glue, GateRef receiver, GateRef accessor, GateRef value, ProfileOperation callback, bool mayThrow)
1336 {
1337     auto env = GetEnvironment();
1338     Label subEntry(env);
1339     env->SubCfgEntry(&subEntry);
1340     Label exit(env);
1341     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
1342 
1343     Label isInternal(env);
1344     Label notInternal(env);
1345     BRANCH(IsAccessorInternal(glue, accessor), &isInternal, &notInternal);
1346     Bind(&isInternal);
1347     {
1348         if (mayThrow) {
1349             result = CallRuntime(glue, RTSTUB_ID(CallInternalSetter), {receiver, accessor, value});
1350         } else {
1351             result = CallRuntime(glue, RTSTUB_ID(CallInternalSetterNoThrow), {receiver, accessor, value});
1352         }
1353         Jump(&exit);
1354     }
1355     Bind(&notInternal);
1356     {
1357         auto setter = Load(VariableType::JS_ANY(), glue, accessor, IntPtr(AccessorData::SETTER_OFFSET));
1358         Label objIsUndefined(env);
1359         Label objNotUndefined(env);
1360         Label callExit(env);
1361         BRANCH(TaggedIsUndefined(setter), &objIsUndefined, &objNotUndefined);
1362         Bind(&objIsUndefined);
1363         {
1364             if (mayThrow) {
1365                 CallRuntime(glue, RTSTUB_ID(ThrowSetterIsUndefinedException), {});
1366                 result = Exception();
1367             } else {
1368                 result = TaggedFalse();
1369             }
1370             Jump(&exit);
1371         }
1372         Bind(&objNotUndefined);
1373         {
1374             DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Exception());
1375             JSCallArgs callArgs(JSCallMode::CALL_SETTER);
1376             callArgs.callSetterArgs = { receiver, value };
1377             CallStubBuilder callBuilder(this, glue, setter, Int32(1), 0, &tmpResult, Circuit::NullGate(), callArgs,
1378                 callback);
1379             if (env->IsBaselineBuiltin()) {
1380                 callBuilder.JSCallDispatchForBaseline(&callExit);
1381                 Bind(&callExit);
1382             } else {
1383                 tmpResult = callBuilder.JSCallDispatch();
1384             }
1385             Label noPendingException(env);
1386             BRANCH(HasPendingException(glue), &exit, &noPendingException);
1387             Bind(&noPendingException);
1388             {
1389                 if (mayThrow) {
1390                     result = *tmpResult;
1391                 } else {
1392                     result = Undefined();
1393                 }
1394                 Jump(&exit);
1395             }
1396         }
1397     }
1398     Bind(&exit);
1399     auto ret = *result;
1400     env->SubCfgExit();
1401     return ret;
1402 }
1403 
ShouldCallSetter(GateRef glue,GateRef receiver,GateRef holder,GateRef accessor,GateRef attr)1404 GateRef StubBuilder::ShouldCallSetter(GateRef glue, GateRef receiver, GateRef holder, GateRef accessor, GateRef attr)
1405 {
1406     auto env = GetEnvironment();
1407     Label subEntry(env);
1408     env->SubCfgEntry(&subEntry);
1409     Label exit(env);
1410     DEFVARIABLE(result, VariableType::BOOL(), True());
1411     Label isInternal(env);
1412     Label notInternal(env);
1413     BRANCH(IsAccessorInternal(glue, accessor), &isInternal, &notInternal);
1414     Bind(&isInternal);
1415     {
1416         Label receiverEqualsHolder(env);
1417         Label receiverNotEqualsHolder(env);
1418         BRANCH(Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder);
1419         Bind(&receiverEqualsHolder);
1420         {
1421             result = IsWritable(attr);
1422             Jump(&exit);
1423         }
1424         Bind(&receiverNotEqualsHolder);
1425         {
1426             result = False();
1427             Jump(&exit);
1428         }
1429     }
1430     Bind(&notInternal);
1431     {
1432         result = True();
1433         Jump(&exit);
1434     }
1435     Bind(&exit);
1436     auto ret = *result;
1437     env->SubCfgExit();
1438     return ret;
1439 }
1440 
JSHClassAddProperty(GateRef glue,GateRef receiver,GateRef key,GateRef attr,GateRef value)1441 void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef key, GateRef attr, GateRef value)
1442 {
1443     auto env = GetEnvironment();
1444     Label subEntry(env);
1445     env->SubCfgEntry(&subEntry);
1446     Label exit(env);
1447     GateRef hclass = LoadHClass(glue, receiver);
1448     GateRef metaData = GetPropertyMetaDataFromAttr(attr);
1449     GateRef newClass = FindTransitions(glue, hclass, key, metaData, value);
1450     Label findHClass(env);
1451     Label notFindHClass(env);
1452     BRANCH(Equal(newClass, Undefined()), &notFindHClass, &findHClass);
1453     Bind(&findHClass);
1454     {
1455         GateRef isAOTHClass = IsAOTHClass(newClass);
1456         Label setPrototype(env);
1457         Label endSetPrototypeCheck(env);
1458         Branch(isAOTHClass, &setPrototype, &endSetPrototypeCheck);
1459         Bind(&setPrototype);
1460         {
1461             GateRef prototype = GetPrototypeFromHClass(glue, hclass);
1462             StorePrototype(glue, newClass, prototype);
1463             Jump(&endSetPrototypeCheck);
1464         }
1465         Bind(&endSetPrototypeCheck);
1466         GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
1467         RestoreElementsKindToGeneric(glue, newClass);
1468         TransitionHClass(glue, receiver, newClass);
1469 #if ECMASCRIPT_ENABLE_IC
1470         Label needUpdateAOTHClass(env);
1471         Label normalNotify(env);
1472         Label endUpdate(env);
1473         GateRef updateCondition = LogicAndBuilder(env).And(isAOTHClass).And(IsPrototypeHClass(newClass)).Done();
1474         Branch(updateCondition, &needUpdateAOTHClass, &normalNotify);
1475         Bind(&needUpdateAOTHClass);
1476         {
1477             TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1478             CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass),
1479                         { hclass, newClass, key });
1480             Jump(&endUpdate);
1481         }
1482         Bind(&normalNotify);
1483         {
1484             // Because we currently only supports Fast ElementsKind
1485             TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1486             NotifyHClassChanged(glue, hclass, newClass);
1487             Jump(&endUpdate);
1488         }
1489         Bind(&endUpdate);
1490 #else
1491         // Because we currently only supports Fast ElementsKind
1492         CallRuntime(glue, RTSTUB_ID(TryRestoreElementsKind), { receiver, newClass });
1493 #endif
1494         Jump(&exit);
1495     }
1496     Bind(&notFindHClass);
1497     {
1498         GateRef type = GetObjectType(hclass);
1499         GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
1500                                 Int32(JSTaggedValue::TaggedTypeSize()));
1501         GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
1502         GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
1503             { IntToTaggedInt(size), IntToTaggedInt(type),
1504               IntToTaggedInt(inlineProps) });
1505         CopyAllHClass(glue, newJshclass, hclass);
1506         CallRuntime(glue, RTSTUB_ID(UpdateLayOutAndAddTransition),
1507                     { hclass, newJshclass, key, Int64ToTaggedInt(attr) });
1508 #if ECMASCRIPT_ENABLE_IC
1509         NotifyHClassChanged(glue, hclass, newJshclass);
1510 #endif
1511         // Because we currently only supports Fast ElementsKind
1512         RestoreElementsKindToGeneric(glue, newJshclass);
1513         TransitionHClass(glue, receiver, newJshclass);
1514         Jump(&exit);
1515     }
1516     Bind(&exit);
1517     env->SubCfgExit();
1518     return;
1519 }
1520 
1521 // Note: set return exit node
AddPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef propertyAttributes,ProfileOperation callback)1522 GateRef StubBuilder::AddPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
1523                                        GateRef propertyAttributes, ProfileOperation callback)
1524 {
1525     auto env = GetEnvironment();
1526     Label subentry(env);
1527     env->SubCfgEntry(&subentry);
1528     Label exit(env);
1529     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1530     GateRef hclass = LoadHClass(glue, receiver);
1531     // 0x111 : default attribute for property: writable, enumerable, configurable
1532     DEFVARIABLE(attr, VariableType::INT64(), propertyAttributes);
1533     GateRef numberOfProps = GetNumberOfPropsFromHClass(hclass);
1534     GateRef inlinedProperties = GetInlinedPropertiesFromHClass(hclass);
1535     Label hasUnusedInProps(env);
1536     Label noUnusedInProps(env);
1537     Label afterInPropsCon(env);
1538     BRANCH(Int32UnsignedLessThan(numberOfProps, inlinedProperties), &hasUnusedInProps, &noUnusedInProps);
1539     {
1540         Bind(&noUnusedInProps);
1541         Jump(&afterInPropsCon);
1542         Bind(&hasUnusedInProps);
1543         {
1544             attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
1545             attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(1)); // 1: set inInlineProps true
1546             attr = SetTaggedRepInPropAttr(*attr);
1547             attr = ProfilerStubBuilder(env).UpdateTrackTypeInPropAttr(*attr, value, callback);
1548             GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
1549             JSHClassAddProperty(glue, receiver, key, *attr, value);
1550             TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1551             GateRef newHclass = LoadHClass(glue, receiver);
1552             GateRef newLayoutInfo = GetLayoutFromHClass(glue, newHclass);
1553             GateRef offset = GetInlinedPropOffsetFromHClass(hclass, numberOfProps);
1554             attr = GetPropAttrFromLayoutInfo(glue, newLayoutInfo, numberOfProps);
1555             SetValueWithAttr(glue, receiver, offset, key, value, *attr);
1556             result = Undefined();
1557             Jump(&exit);
1558         }
1559     }
1560     Bind(&afterInPropsCon);
1561     DEFVARIABLE(array, VariableType::JS_POINTER(), GetPropertiesArray(glue, receiver));
1562     DEFVARIABLE(length, VariableType::INT32(), GetLengthOfTaggedArray(*array));
1563     Label lenIsZero(env);
1564     Label lenNotZero(env);
1565     Label afterLenCon(env);
1566     BRANCH(Int32Equal(*length, Int32(0)), &lenIsZero, &lenNotZero);
1567     {
1568         Bind(&lenIsZero);
1569         {
1570             length = Int32(JSObject::MIN_PROPERTIES_LENGTH);
1571             array = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(*length) });
1572             SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
1573             Jump(&afterLenCon);
1574         }
1575         Bind(&lenNotZero);
1576         Jump(&afterLenCon);
1577     }
1578     Bind(&afterLenCon);
1579     Label isDictMode(env);
1580     Label notDictMode(env);
1581     BRANCH(IsDictionaryMode(glue, *array), &isDictMode, &notDictMode);
1582     {
1583         Bind(&isDictMode);
1584         {
1585             GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
1586                                       {receiver, *array, key, value, Int64ToTaggedInt(*attr), TaggedFalse()});
1587             SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
1588             Jump(&exit);
1589         }
1590         Bind(&notDictMode);
1591         {
1592             attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(0));
1593             GateRef outProps = Int32Sub(numberOfProps, inlinedProperties);
1594             Label ChangeToDict(env);
1595             Label notChangeToDict(env);
1596             Label afterDictChangeCon(env);
1597             BRANCH(Int32GreaterThanOrEqual(numberOfProps, Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY)),
1598                 &ChangeToDict, &notChangeToDict);
1599             {
1600                 Bind(&ChangeToDict);
1601                 {
1602                     attr = SetDictionaryOrderFieldInPropAttr(*attr,
1603                         Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY));
1604                     GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
1605                         { receiver, *array, key, value, Int64ToTaggedInt(*attr), TaggedTrue() });
1606                     Label isPendingException(env);
1607                     Label noPendingException(env);
1608                     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
1609                     Bind(&isPendingException);
1610                     {
1611                         result = Exception();
1612                         Jump(&exit);
1613                     }
1614                     Bind(&noPendingException);
1615                     SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
1616                     result = Undefined();
1617                     Jump(&exit);
1618                 }
1619                 Bind(&notChangeToDict);
1620                 Jump(&afterDictChangeCon);
1621             }
1622             Bind(&afterDictChangeCon);
1623             Label isArrayFull(env);
1624             Label arrayNotFull(env);
1625             Label afterArrLenCon(env);
1626             BRANCH(Int32Equal(*length, outProps), &isArrayFull, &arrayNotFull);
1627             {
1628                 Bind(&isArrayFull);
1629                 {
1630                     GateRef maxNonInlinedFastPropsCapacity =
1631                         Int32Sub(Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY), inlinedProperties);
1632                     GateRef capacity = ComputeNonInlinedFastPropsCapacity(glue, *length,
1633                         maxNonInlinedFastPropsCapacity);
1634                     NewObjectStubBuilder newBuilder(this, glue);
1635                     array = newBuilder.CopyArray(glue, *array, *length, capacity);
1636                     SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
1637                     Jump(&afterArrLenCon);
1638                 }
1639                 Bind(&arrayNotFull);
1640                 Jump(&afterArrLenCon);
1641             }
1642             Bind(&afterArrLenCon);
1643             {
1644                 attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
1645                 attr = SetTaggedRepInPropAttr(*attr);
1646                 attr = ProfilerStubBuilder(env).UpdateTrackTypeInPropAttr(*attr, value, callback);
1647                 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
1648                 JSHClassAddProperty(glue, receiver, key, *attr, value);
1649                 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1650                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, outProps, value);
1651                 Jump(&exit);
1652             }
1653         }
1654     }
1655     Bind(&exit);
1656     auto ret = *result;
1657     env->SubCfgExit();
1658     return ret;
1659 }
1660 
ThrowTypeAndReturn(GateRef glue,int messageId,GateRef val)1661 void StubBuilder::ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val)
1662 {
1663     GateRef msgIntId = Int32(messageId);
1664     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId) });
1665     Return(val);
1666 }
1667 
TaggedToRepresentation(GateRef value)1668 GateRef StubBuilder::TaggedToRepresentation(GateRef value)
1669 {
1670     auto env = GetEnvironment();
1671     Label entry(env);
1672     env->SubCfgEntry(&entry);
1673     Label exit(env);
1674     DEFVARIABLE(resultRep, VariableType::INT64(),
1675                 Int64(static_cast<int32_t>(Representation::TAGGED)));
1676     Label isInt(env);
1677     Label notInt(env);
1678 
1679     BRANCH(TaggedIsInt(value), &isInt, &notInt);
1680     Bind(&isInt);
1681     {
1682         resultRep = Int64(static_cast<int32_t>(Representation::INT));
1683         Jump(&exit);
1684     }
1685     Bind(&notInt);
1686     {
1687         Label isDouble(env);
1688         Label notDouble(env);
1689         BRANCH(TaggedIsDouble(value), &isDouble, &notDouble);
1690         Bind(&isDouble);
1691         {
1692             resultRep = Int64(static_cast<int32_t>(Representation::DOUBLE));
1693             Jump(&exit);
1694         }
1695         Bind(&notDouble);
1696         {
1697             resultRep = Int64(static_cast<int32_t>(Representation::TAGGED));
1698             Jump(&exit);
1699         }
1700     }
1701     Bind(&exit);
1702     auto ret = *resultRep;
1703     env->SubCfgExit();
1704     return ret;
1705 }
1706 
TaggedToElementKind(GateRef glue,GateRef value)1707 GateRef StubBuilder::TaggedToElementKind(GateRef glue, GateRef value)
1708 {
1709     auto env = GetEnvironment();
1710     Label entry(env);
1711     env->SubCfgEntry(&entry);
1712     Label exit(env);
1713 
1714     DEFVARIABLE(result, VariableType::INT32(), Int32(Elements::ToUint(ElementsKind::TAGGED)));
1715     Label isHole(env);
1716     Label isNotHole(env);
1717     BRANCH(TaggedIsHole(value), &isHole, &isNotHole);
1718     Bind(&isHole);
1719     {
1720         result = Int32(Elements::ToUint(ElementsKind::HOLE));
1721         Jump(&exit);
1722     }
1723     Bind(&isNotHole);
1724     {
1725         Label isInt(env);
1726         Label isNotInt(env);
1727         BRANCH(TaggedIsInt(value), &isInt, &isNotInt);
1728         Bind(&isInt);
1729         {
1730             result = Int32(Elements::ToUint(ElementsKind::INT));
1731             Jump(&exit);
1732         }
1733         Bind(&isNotInt);
1734         {
1735             Label isObject(env);
1736             Label isDouble(env);
1737             BRANCH(TaggedIsObject(value), &isObject, &isDouble);
1738             Bind(&isDouble);
1739             {
1740                 result = Int32(Elements::ToUint(ElementsKind::NUMBER));
1741                 Jump(&exit);
1742             }
1743             Bind(&isObject);
1744             {
1745                 Label isHeapObject(env);
1746                 BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit);
1747                 Bind(&isHeapObject);
1748                 {
1749                     Label isString(env);
1750                     Label isNonString(env);
1751                     BRANCH(TaggedIsString(glue, value), &isString, &isNonString);
1752                     Bind(&isString);
1753                     {
1754                         result = Int32(Elements::ToUint(ElementsKind::STRING));
1755                         Jump(&exit);
1756                     }
1757                     Bind(&isNonString);
1758                     {
1759                         result = Int32(Elements::ToUint(ElementsKind::OBJECT));
1760                         Jump(&exit);
1761                     }
1762                 }
1763             }
1764         }
1765     }
1766     Bind(&exit);
1767     auto ret = *result;
1768     env->SubCfgExit();
1769     return ret;
1770 }
1771 
Store(VariableType type,GateRef glue,GateRef base,GateRef offset,GateRef value,MemoryAttribute mAttr)1772 void StubBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value,
1773                         MemoryAttribute mAttr)
1774 {
1775     if (!env_->IsAsmInterp()) {
1776         env_->GetBuilder()->Store(type, glue, base, offset, value, mAttr);
1777     } else {
1778         auto depend = env_->GetCurrentLabel()->GetDepend();
1779         auto bit = LoadStoreAccessor::ToValue(mAttr);
1780         GateRef result = env_->GetCircuit()->NewGate(
1781             env_->GetCircuit()->Store(bit), MachineType::NOVALUE,
1782             { depend, glue, base, offset, value, value }, type.GetGateType());
1783         env_->GetCurrentLabel()->SetDepend(result);
1784     }
1785 }
1786 
SetValueWithAttr(GateRef glue,GateRef obj,GateRef offset,GateRef key,GateRef value,GateRef attr)1787 void StubBuilder::SetValueWithAttr(GateRef glue, GateRef obj, GateRef offset, GateRef key, GateRef value, GateRef attr)
1788 {
1789     auto env = GetEnvironment();
1790     Label entry(env);
1791     env->SubCfgEntry(&entry);
1792 
1793     Label exit(env);
1794     Label repChange(env);
1795     GateRef rep = GetRepInPropAttr(attr);
1796     SetValueWithRep(glue, obj, offset, value, rep, &repChange);
1797     Jump(&exit);
1798     Bind(&repChange);
1799     {
1800         attr = SetTaggedRepInPropAttr(attr);
1801         TransitionForRepChange(glue, obj, key, attr);
1802         Store(VariableType::JS_ANY(), glue, obj, offset, value);
1803         Jump(&exit);
1804     }
1805     Bind(&exit);
1806     env->SubCfgExit();
1807 }
1808 
SetValueWithRep(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef rep,Label * repChange)1809 void StubBuilder::SetValueWithRep(
1810     GateRef glue, GateRef obj, GateRef offset, GateRef value, GateRef rep, Label *repChange)
1811 {
1812     auto env = GetEnvironment();
1813     Label entry(env);
1814     env->SubCfgEntry(&entry);
1815 
1816     Label exit(env);
1817     Label repIsDouble(env);
1818     Label repIsNonDouble(env);
1819     BRANCH(IsDoubleRepInPropAttr(rep), &repIsDouble, &repIsNonDouble);
1820     Bind(&repIsDouble);
1821     {
1822         Label valueIsInt(env);
1823         Label valueIsNotInt(env);
1824         BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsNotInt);
1825         Bind(&valueIsInt);
1826         {
1827             GateRef result = GetDoubleOfTInt(value);
1828             Store(VariableType::FLOAT64(), glue, obj, offset, result);
1829             Jump(&exit);
1830         }
1831         Bind(&valueIsNotInt);
1832         {
1833             Label valueIsObject(env);
1834             Label valueIsDouble(env);
1835             BRANCH(TaggedIsObject(value), &valueIsObject, &valueIsDouble);
1836             Bind(&valueIsDouble);
1837             {
1838                 // TaggedDouble to double
1839                 GateRef result = GetDoubleOfTDouble(value);
1840                 Store(VariableType::FLOAT64(), glue, obj, offset, result);
1841                 Jump(&exit);
1842             }
1843             Bind(&valueIsObject);
1844             {
1845                 Jump(repChange);
1846             }
1847         }
1848     }
1849     Bind(&repIsNonDouble);
1850     {
1851         Label repIsInt(env);
1852         Label repIsTagged(env);
1853         BRANCH(IsIntRepInPropAttr(rep), &repIsInt, &repIsTagged);
1854         Bind(&repIsInt);
1855         {
1856             Label valueIsInt(env);
1857             Label valueIsNotInt(env);
1858             BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsNotInt);
1859             Bind(&valueIsInt);
1860             {
1861                 GateRef result = GetInt32OfTInt(value);
1862                 Store(VariableType::INT32(), glue, obj, offset, result);
1863                 Jump(&exit);
1864             }
1865             Bind(&valueIsNotInt);
1866             {
1867                 Jump(repChange);
1868             }
1869         }
1870         Bind(&repIsTagged);
1871         {
1872             Store(VariableType::JS_ANY(), glue, obj, offset, value);
1873             Jump(&exit);
1874         }
1875     }
1876 
1877     Bind(&exit);
1878     env->SubCfgExit();
1879     return;
1880 }
1881 
VerifyBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value)1882 void StubBuilder::VerifyBarrier(GateRef glue, GateRef obj, [[maybe_unused]] GateRef offset, GateRef value)
1883 {
1884     auto env = GetEnvironment();
1885     Label entry(env);
1886     env->SubCfgEntry(&entry);
1887     Label exit(env);
1888     Label checkNext(env);
1889     BRANCH_UNLIKELY(LoadPrimitive(
1890         VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
1891         &exit, &checkNext);
1892     Bind(&checkNext);
1893     // ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj.
1894     GateRef objectRegion = ObjectAddressToRange(obj);
1895     GateRef valueRegion = ObjectAddressToRange(value);
1896     Label fatal(env);
1897     Label noFatal(env);
1898     int msgId = GET_MESSAGE_STRING_ID(SharedObjectRefersLocalObject);
1899     BRANCH(BitAnd(InSharedHeap(objectRegion), BoolNot(InSharedHeap(valueRegion))), &fatal, &exit);
1900     Bind(&fatal);
1901     {
1902         FatalPrint(glue, {Int32(msgId)});
1903         Jump(&exit);
1904     }
1905     Bind(&exit);
1906     env->SubCfgExit();
1907 }
1908 
GetCMCRegionRSet(GateRef obj)1909 GateRef StubBuilder::GetCMCRegionRSet(GateRef obj)
1910 {
1911     GateRef metaDataAddr = IntPtrAnd(TaggedCastToIntPtr(obj),
1912                                      IntPtr(~static_cast<uint64_t>(common::RegionDesc::DEFAULT_REGION_UNIT_MASK)));
1913     GateRef regionRSet = LoadPrimitive(VariableType::NATIVE_POINTER(), metaDataAddr,
1914                                        IntPtr(common::RegionDesc::REGION_RSET_IN_INLINED_METADATA_OFFSET));
1915     return regionRSet;
1916 }
1917 
GetCMCRegionType(GateRef obj)1918 GateRef StubBuilder::GetCMCRegionType(GateRef obj)
1919 {
1920 
1921     GateRef metaDataAddr = IntPtrAnd(TaggedCastToIntPtr(obj), IntPtr(~common::RegionDesc::DEFAULT_REGION_UNIT_MASK));
1922     GateRef regionDescAddr = LoadPrimitive(VariableType::INT8(), metaDataAddr,
1923                                    IntPtr(common::RegionDesc::REGION_TYPE_IN_INLINED_METADATA_OFFSET));
1924     return regionDescAddr;
1925 }
1926 
CMCIsInYoungSpace(GateRef regionType)1927 GateRef StubBuilder::CMCIsInYoungSpace(GateRef regionType)
1928 {
1929     auto env = GetEnvironment();
1930     GateRef ret = LogicOrBuilder(env)
1931         .Or(Int8Equal(regionType, Int8(static_cast<int8_t>(common::RegionDesc::RegionType::THREAD_LOCAL_REGION))))
1932         .Or(Int8Equal(regionType, Int8(static_cast<int8_t>(common::RegionDesc::RegionType::RECENT_FULL_REGION))))
1933         .Or(Int8Equal(regionType, Int8(static_cast<int8_t>(common::RegionDesc::RegionType::FROM_REGION))))
1934         .Done();
1935     return ret;
1936 }
1937 
IsOldToYoung(GateRef objRegionType,GateRef valueRegionType)1938 GateRef StubBuilder::IsOldToYoung(GateRef objRegionType, GateRef valueRegionType)
1939 {
1940     auto env = GetEnvironment();
1941     GateRef isOldToYoung = LogicAndBuilder(env)
1942         .And(BoolNot(CMCIsInYoungSpace(objRegionType)))
1943         .And(CMCIsInYoungSpace(valueRegionType)).Done();
1944     return isOldToYoung;
1945 }
1946 
GetGCPhase(GateRef glue)1947 GateRef StubBuilder::GetGCPhase(GateRef glue)
1948 {
1949     GateRef gcPhase = LoadPrimitive(VariableType::INT8(), glue,
1950         Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(false) +
1951         JSThread::CMCGCPhaseBits::START_BIT / BITS_PER_BYTE));
1952     return gcPhase;
1953 }
1954 
GetGCReason(GateRef glue)1955 GateRef StubBuilder::GetGCReason(GateRef glue)
1956 {
1957     GateRef gcReason = LoadPrimitive(VariableType::INT32(), glue,
1958         Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(false) +
1959         JSThread::CMCGCReasonBits::START_BIT / BITS_PER_BYTE));
1960     return gcReason;
1961 }
1962 
MarkRSetCardTable(GateRef obj,Label * exit)1963 void StubBuilder::MarkRSetCardTable(GateRef obj, Label *exit)
1964 {
1965     auto env = GetEnvironment();
1966     Label markBit(env);
1967     GateRef regionBase = IntPtrAnd(TaggedCastToIntPtr(obj),
1968         IntPtr(~static_cast<uint64_t>(common::RegionDesc::DEFAULT_REGION_UNIT_MASK)));
1969     GateRef objOffset = PtrSub(TaggedCastToIntPtr(obj), regionBase);
1970     GateRef rset = GetCMCRegionRSet(obj);
1971     GateRef cardIdx = IntPtrDiv(IntPtrDiv(objOffset, IntPtr(common::kMarkedBytesPerBit)),
1972                                 IntPtr(common::kBitsPerWord));
1973     GateRef headMaskBitStart = IntPtrMod(IntPtrDiv(objOffset, IntPtr(common::kMarkedBytesPerBit)),
1974                                             IntPtr(common::kBitsPerWord));
1975     GateRef headMaskBits = Int64LSL(Int64(1), headMaskBitStart);
1976     GateRef cardOffset = PtrMul(cardIdx, IntPtr(common::kBytesPerWord));
1977     GateRef cardTable = PtrAdd(rset, IntPtr(common::RegionRSet::CARD_TABLE_DATA_OFFSET));
1978     GateRef card = LoadPrimitive(VariableType::INT64(), cardTable, cardOffset);
1979     GateRef isMarked = Int64NotEqual(Int64And(card, headMaskBits), Int64(0));
1980     BRANCH_NO_WEIGHT(isMarked, exit, &markBit);
1981     Bind(&markBit);
1982     {
1983         Int64FetchOr(PtrAdd(cardTable, cardOffset), headMaskBits, MemoryAttribute::Default());
1984         Jump(exit);
1985     }
1986 }
1987 
ShouldGetGCReason(GateRef gcPhase)1988 GateRef StubBuilder::ShouldGetGCReason(GateRef gcPhase)
1989 {
1990     auto env = GetEnvironment();
1991     GateRef shouldGetGCReason = LogicOrBuilder(env)
1992         .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_ENUM)))
1993         .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_MARK)))
1994         .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_POST_MARK)))
1995         .Done();
1996     return shouldGetGCReason;
1997 }
1998 
ShouldProcessSATB(GateRef gcPhase)1999 GateRef StubBuilder::ShouldProcessSATB(GateRef gcPhase)
2000 {
2001     auto env = GetEnvironment();
2002     GateRef shouldProcessSATB = LogicOrBuilder(env)
2003         .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_ENUM)))
2004         .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_MARK)))
2005         .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_FINAL_MARK)))
2006         .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_REMARK_SATB)))
2007         .Done();
2008     return shouldProcessSATB;
2009 }
2010 
ShouldUpdateRememberSet(GateRef glue,GateRef gcPhase)2011 GateRef StubBuilder::ShouldUpdateRememberSet(GateRef glue, GateRef gcPhase)
2012 {
2013     auto env = GetEnvironment();
2014     Label entry(env);
2015     env->SubCfgEntry(&entry);
2016     Label checkOldToYoung(env);
2017     Label exit(env);
2018     Label notMarkRSet(env);
2019     Label notIdlePhase(env);
2020     DEFVARIABLE(result, VariableType::BOOL(), True());
2021     BRANCH(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_IDLE)), &exit, &notIdlePhase);
2022     Bind(&notIdlePhase);
2023     GateRef gcReason = GetGCReason(glue);
2024     Label reasonNotYoung(env);
2025     BRANCH(Int32Equal(gcReason, Int32(common::GCReason::GC_REASON_YOUNG)), &exit, &reasonNotYoung);
2026     Bind(&reasonNotYoung);
2027     GateRef shouldGetGCReason = ShouldGetGCReason(gcPhase);
2028     BRANCH(BoolNot(shouldGetGCReason), &exit, &notMarkRSet);
2029     Bind(&notMarkRSet);
2030     result = False();
2031     Jump(&exit);
2032     Bind(&exit);
2033     auto ret = *result;
2034     env->SubCfgExit();
2035     return ret;
2036 }
2037 
CMCSetValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value)2038 void StubBuilder::CMCSetValueWithBarrier(GateRef glue, GateRef obj, [[maybe_unused]]GateRef offset, GateRef value)
2039 {
2040     auto env = GetEnvironment();
2041     Label entry(env);
2042     env->SubCfgEntry(&entry);
2043     Label exit(env);
2044     Label checkOldToYoung(env);
2045     Label markRSet(env);
2046     Label notMarkRSet(env);
2047     GateRef gcPhase = GetGCPhase(glue);
2048     BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, &notMarkRSet);
2049     Bind(&checkOldToYoung);
2050     {
2051         GateRef objRegionType = GetCMCRegionType(obj);
2052         GateRef valueRegionType = GetCMCRegionType(value);
2053         GateRef isOldToYoung = IsOldToYoung(objRegionType, valueRegionType);
2054         BRANCH_UNLIKELY(isOldToYoung, &markRSet, &notMarkRSet);
2055         Bind(&markRSet);
2056         MarkRSetCardTable(obj, &notMarkRSet);
2057     }
2058     Bind(&notMarkRSet);
2059     Label markInBuffer(env);
2060     GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase);
2061     BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit);
2062     Bind(&markInBuffer);
2063     {
2064         CallNGCRuntime(glue, RTSTUB_ID(MarkInBuffer), {value});
2065         Jump(&exit);
2066     }
2067     Bind(&exit);
2068     env->SubCfgExit();
2069 }
2070 
CMCArrayCopyWriteBarrier(GateRef glue,GateRef dstObj,GateRef src,GateRef dst,GateRef count)2071 void StubBuilder::CMCArrayCopyWriteBarrier(GateRef glue, GateRef dstObj, GateRef src, GateRef dst, GateRef count)
2072 {
2073     auto env = GetEnvironment();
2074     Label entry(env);
2075     env->SubCfgEntry(&entry);
2076     Label exit(env);
2077     Label iLessLength(env);
2078     Label isTaggedObject(env);
2079     Label loopHead(env);
2080     Label loopEnd(env);
2081     Label markRSet(env);
2082     Label notMarkRSet(env);
2083     GateRef objRegionType = GetCMCRegionType(dstObj);
2084     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2085     GateRef gcPhase = GetGCPhase(glue);
2086     Label checkOldToYoung(env);
2087     BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, &notMarkRSet);
2088     Bind(&checkOldToYoung);
2089     Jump(&loopHead);
2090     LoopBegin(&loopHead);
2091     {
2092         BRANCH(Int32UnsignedLessThan(*i, count), &iLessLength, &notMarkRSet);
2093         Bind(&iLessLength);
2094         GateRef offset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(JSTaggedValue::TaggedTypeSize()));
2095         GateRef ref = LoadPrimitive(VariableType::JS_ANY(), src, offset);
2096         BRANCH(TaggedIsHeapObject(ref), &isTaggedObject, &loopEnd);
2097         Bind(&isTaggedObject);
2098         GateRef isOldToYoung = IsOldToYoung(objRegionType, GetCMCRegionType(ref));
2099         BRANCH_UNLIKELY(isOldToYoung, &markRSet, &loopEnd);
2100         Bind(&markRSet);
2101         MarkRSetCardTable(dstObj, &notMarkRSet);
2102         Bind(&loopEnd);
2103         i = Int32Add(*i, Int32(1));
2104         LoopEnd(&loopHead);
2105     }
2106     Bind(&notMarkRSet);
2107     Label markInBuffer(env);
2108     GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase);
2109     BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit);
2110     Bind(&markInBuffer);
2111     CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {TaggedCastToIntPtr(src), count});
2112     Jump(&exit);
2113     Bind(&exit);
2114     env->SubCfgExit();
2115 }
2116 
CMCArrayCopyWriteBarrierSameArray(GateRef glue,GateRef dstObj,GateRef src,GateRef dst,GateRef count)2117 void StubBuilder::CMCArrayCopyWriteBarrierSameArray(GateRef glue, GateRef dstObj, GateRef src, GateRef dst, GateRef count)
2118 {
2119     auto env = GetEnvironment();
2120     Label entry(env);
2121     env->SubCfgEntry(&entry);
2122     Label exit(env);
2123     Label iLessLength(env);
2124     Label isTaggedObject(env);
2125     Label loopHead(env);
2126     Label loopEnd(env);
2127     Label markRSet(env);
2128     Label notMarkRSet(env);
2129     Label notIdlePhase(env);
2130     GateRef objRegionType = GetCMCRegionType(dstObj);
2131     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2132     GateRef gcPhase = GetGCPhase(glue);
2133     BRANCH(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_IDLE)), &exit, &notIdlePhase);
2134     Bind(&notIdlePhase);
2135     {
2136         Label checkOldToYoung(env);
2137         BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, &notMarkRSet);
2138         Bind(&checkOldToYoung);
2139         Jump(&loopHead);
2140         LoopBegin(&loopHead);
2141         {
2142             BRANCH(Int32UnsignedLessThan(*i, count), &iLessLength, &notMarkRSet);
2143             Bind(&iLessLength);
2144             GateRef offset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(JSTaggedValue::TaggedTypeSize()));
2145             GateRef ref = LoadPrimitive(VariableType::JS_ANY(), src, offset);
2146             BRANCH(TaggedIsHeapObject(ref), &isTaggedObject, &loopEnd);
2147             Bind(&isTaggedObject);
2148             GateRef isOldToYoung = IsOldToYoung(objRegionType, GetCMCRegionType(ref));
2149             BRANCH_UNLIKELY(isOldToYoung, &markRSet, &loopEnd);
2150             Bind(&markRSet);
2151             MarkRSetCardTable(dstObj, &notMarkRSet);
2152             Bind(&loopEnd);
2153             i = Int32Add(*i, Int32(1));
2154             LoopEnd(&loopHead);
2155         }
2156         Bind(&notMarkRSet);
2157         Label markInBuffer(env);
2158         GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase);
2159         BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit);
2160         Bind(&markInBuffer);
2161         CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {TaggedCastToIntPtr(src), count});
2162         Jump(&exit);
2163     }
2164     Bind(&exit);
2165     env->SubCfgExit();
2166 }
2167 
SetValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,MemoryAttribute::ShareFlag share)2168 void StubBuilder::SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value,
2169                                       MemoryAttribute::ShareFlag share)
2170 {
2171     auto env = GetEnvironment();
2172     Label entry(env);
2173     env->SubCfgEntry(&entry);
2174     Label exit(env);
2175     Label callRuntime(env);
2176     Label checkNext(env);
2177     BRANCH_LIKELY(LoadPrimitive(
2178         VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
2179         &callRuntime, &checkNext);
2180     Bind(&callRuntime);
2181     {
2182         CMCSetValueWithBarrier(glue, obj, offset, value);
2183         Jump(&exit);
2184     }
2185     Bind(&checkNext);
2186     // ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj.
2187     GateRef objectRegion = ObjectAddressToRange(obj);
2188     GateRef valueRegion = ObjectAddressToRange(value);
2189 #ifndef NDEBUG
2190     Label fatal(env);
2191     Label noFatal(env);
2192     int msgId = GET_MESSAGE_STRING_ID(SharedObjectRefersLocalObject);
2193     if (share == MemoryAttribute::SHARED) {
2194         BRANCH(BoolNot(InSharedHeap(valueRegion)), &fatal, &noFatal);
2195         msgId = GET_MESSAGE_STRING_ID(ValueIsNonSObject);
2196     }
2197     if (share == MemoryAttribute::NON_SHARE) {
2198         BRANCH(InSharedHeap(objectRegion), &fatal, &noFatal);
2199     }
2200     if (share == MemoryAttribute::UNKNOWN) {
2201         BRANCH(BitAnd(InSharedHeap(objectRegion), BoolNot(InSharedHeap(valueRegion))), &fatal, &noFatal);
2202     }
2203     Bind(&fatal);
2204     {
2205         FatalPrint(glue, {Int32(msgId)});
2206         Jump(&exit);
2207     }
2208     Bind(&noFatal);
2209 #endif
2210     switch (share) {
2211         case MemoryAttribute::SHARED: {
2212             SetSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2213             Jump(&exit);
2214             break;
2215         }
2216         case MemoryAttribute::NON_SHARE: {
2217             SetNonSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2218             Jump(&exit);
2219             break;
2220         }
2221         case MemoryAttribute::UNKNOWN: {
2222             Label valueIsShared(env);
2223             Label valueIsNotShared(env);
2224             BRANCH_UNLIKELY(InSharedHeap(valueRegion), &valueIsShared, &valueIsNotShared);
2225             Bind(&valueIsShared);
2226             {
2227                 SetSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2228                 Jump(&exit);
2229             }
2230             Bind(&valueIsNotShared);
2231             {
2232                 SetNonSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2233                 Jump(&exit);
2234             }
2235             break;
2236         }
2237         default:
2238             UNREACHABLE();
2239     }
2240     Bind(&exit);
2241     env->SubCfgExit();
2242 }
2243 
SetSValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef objectRegion,GateRef valueRegion)2244 void StubBuilder::SetSValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, GateRef objectRegion,
2245                                        GateRef valueRegion)
2246 {
2247     auto env = GetEnvironment();
2248     Label entry(env);
2249     env->SubCfgEntry(&entry);
2250     Label exit(env);
2251 
2252     Label needBarrier(env);
2253     GateRef valueRegionInSweepableShare = InSharedSweepableSpace(valueRegion);
2254     BRANCH(valueRegionInSweepableShare, &needBarrier, &exit);
2255     Bind(&needBarrier);
2256     {
2257         Label updateLocalToShareRSet(env);
2258         Label checkBarrierForSharedValue(env);
2259         GateRef objectNotInShare = BoolNot(InSharedHeap(objectRegion));
2260         BRANCH(objectNotInShare, &updateLocalToShareRSet, &checkBarrierForSharedValue);
2261         Bind(&updateLocalToShareRSet);
2262         {
2263             Label callSharedBarrier(env);
2264             Label storeToSharedRSet(env);
2265             GateRef loadOffset = IntPtr(Region::PackedData::GetLocalToShareSetOffset(env_->Is32Bit()));
2266             auto localToShareSet = LoadPrimitive(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
2267             BRANCH(IntPtrEqual(localToShareSet, IntPtr(0)), &callSharedBarrier, &storeToSharedRSet);
2268             Bind(&storeToSharedRSet);
2269             {
2270                 GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
2271                 // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
2272                 GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
2273                 GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
2274                 GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
2275                 GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
2276                 // bitOffset >> BIT_PER_WORD_LOG2
2277                 GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
2278                 GateRef byteIndex = Int32Mul(index, bytePerWord);
2279                 // bitset_[index] |= mask;
2280                 GateRef bitsetData = PtrAdd(localToShareSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
2281                 GateRef oldsetValue = LoadPrimitive(VariableType::INT32(), bitsetData, byteIndex);
2282                 GateRef mask = GetBitMask(bitOffset);
2283                 GateRef flag = Int32And(oldsetValue, mask);
2284                 // Load the bit using relaxed memory order.
2285                 // If the bit is set, do nothing (local->shared barrier is done).
2286                 Label needSet(env);
2287                 BRANCH(Int32NotEqual(flag, Int32(0)), &checkBarrierForSharedValue, &needSet);
2288                 Bind(&needSet);
2289                 {
2290                     GateRef newMapValue = Int32Or(oldsetValue, mask);
2291                     Store(VariableType::INT32(), glue, bitsetData, byteIndex, newMapValue);
2292                     Jump(&checkBarrierForSharedValue);
2293                 }
2294             }
2295             Bind(&callSharedBarrier);
2296             {
2297                 CallNGCRuntime(glue, RTSTUB_ID(InsertLocalToShareRSet), { glue, obj, offset });
2298                 Jump(&checkBarrierForSharedValue);
2299             }
2300         }
2301         Bind(&checkBarrierForSharedValue);
2302         {
2303             Label sharedMarking(env);
2304             bool isArch32 = GetEnvironment()->Is32Bit();
2305             GateRef stateBitField = LoadPrimitive(VariableType::INT64(), glue,
2306                                          Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(isArch32)));
2307             GateRef state = Int64And(stateBitField, Int64(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK));
2308             BRANCH(Int64Equal(state, Int64(static_cast<int64_t>(SharedMarkStatus::READY_TO_CONCURRENT_MARK))),
2309                    &exit, &sharedMarking);
2310 
2311             Bind(&sharedMarking);
2312             CallNGCRuntime(glue, RTSTUB_ID(SharedGCMarkingBarrier), {glue, obj, offset, value});
2313             Jump(&exit);
2314         }
2315     }
2316     Bind(&exit);
2317     env->SubCfgExit();
2318 }
2319 
SetNonSValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef objectRegion,GateRef valueRegion)2320 void StubBuilder::SetNonSValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value,
2321                                           GateRef objectRegion, GateRef valueRegion)
2322 {
2323     auto env = GetEnvironment();
2324     Label entry(env);
2325     env->SubCfgEntry(&entry);
2326     Label exit(env);
2327 
2328     Label checkMarkStatus(env);
2329     Label isOldToYoung(env);
2330     GateRef objectNotInYoung = BoolNot(InYoungGeneration(objectRegion));
2331     GateRef valueRegionInYoung = InYoungGeneration(valueRegion);
2332     BRANCH_UNLIKELY(BitAnd(objectNotInYoung, valueRegionInYoung), &isOldToYoung, &checkMarkStatus);
2333 
2334     Bind(&isOldToYoung);
2335     {
2336         GateRef loadOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env_->Is32Bit()));
2337         auto oldToNewSet = LoadPrimitive(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
2338         Label isNullPtr(env);
2339         Label notNullPtr(env);
2340         BRANCH(IntPtrEuqal(oldToNewSet, IntPtr(0)), &isNullPtr, &notNullPtr);
2341         Bind(&notNullPtr);
2342         {
2343             GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
2344             // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
2345             GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
2346             GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
2347             GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
2348             GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
2349             // bitOffset >> BIT_PER_WORD_LOG2
2350             GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
2351             GateRef byteIndex = Int32Mul(index, bytePerWord);
2352             // bitset_[index] |= mask;
2353             GateRef bitsetData = PtrAdd(oldToNewSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
2354             GateRef oldsetValue = LoadPrimitive(VariableType::INT32(), bitsetData, byteIndex);
2355             GateRef newmapValue = Int32Or(oldsetValue, GetBitMask(bitOffset));
2356 
2357             Store(VariableType::INT32(), glue, bitsetData, byteIndex, newmapValue);
2358             Jump(&checkMarkStatus);
2359         }
2360         Bind(&isNullPtr);
2361         {
2362             CallNGCRuntime(glue, RTSTUB_ID(InsertOldToNewRSet), { glue, obj, offset });
2363             Jump(&checkMarkStatus);
2364         }
2365     }
2366     Bind(&checkMarkStatus);
2367     {
2368         Label marking(env);
2369         bool isArch32 = GetEnvironment()->Is32Bit();
2370         GateRef stateBitField = LoadPrimitive(VariableType::INT64(), glue,
2371                                      Int64(JSThread::GlueData::GetGCStateBitFieldOffset(isArch32)));
2372         GateRef state = Int64And(stateBitField, Int64(JSThread::CONCURRENT_MARKING_BITFIELD_MASK));
2373         BRANCH_LIKELY(Int64Equal(state, Int64(static_cast<int64_t>(MarkStatus::READY_TO_MARK))), &exit, &marking);
2374 
2375         Bind(&marking);
2376         {
2377             // Check fresh region, and directly mark value instead of call runtime.
2378             CallNGCRuntime(glue, RTSTUB_ID(MarkingBarrier), {glue, obj, offset, value});
2379             Jump(&exit);
2380         }
2381     }
2382     Bind(&exit);
2383     env->SubCfgExit();
2384 }
2385 
GetValueWithBarrier(GateRef glue,GateRef addr)2386 GateRef StubBuilder::GetValueWithBarrier(GateRef glue, GateRef addr)
2387 {
2388     auto env = GetEnvironment();
2389     Label entry(env);
2390     env->SubCfgEntry(&entry);
2391     Label notHeapObject(env);
2392     Label isHeapObject(env);
2393     Label exit(env);
2394 
2395     // TODO: should be atomic
2396     GateRef value = LoadZeroOffsetPrimitive(VariableType::JS_ANY(), addr);
2397 
2398     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2399 
2400     BRANCH(BoolNot(TaggedIsHeapObject(value)), &notHeapObject, &isHeapObject);
2401     Bind(&notHeapObject);
2402     {
2403         result = value;
2404         Jump(&exit);
2405     }
2406     Bind(&isHeapObject);
2407     {
2408         Label isHeapAddress(env);
2409         Label notHeapAddress(env);
2410         BRANCH(IsHeapAddress(glue, value), &isHeapAddress, &notHeapAddress);
2411         Bind(&notHeapAddress);
2412         {
2413             result = value;
2414             Jump(&exit);
2415         }
2416         Bind(&isHeapAddress);
2417         {
2418             result = FastReadBarrier(glue, addr, value);
2419             Jump(&exit);
2420         }
2421     }
2422 
2423     Bind(&exit);
2424     auto ret = *result;
2425     env->SubCfgExit();
2426     return ret;
2427 }
2428 
FastReadBarrier(GateRef glue,GateRef addr,GateRef value)2429 GateRef StubBuilder::FastReadBarrier(GateRef glue, GateRef addr, GateRef value)
2430 {
2431     auto env = GetEnvironment();
2432     Label entry(env);
2433     env->SubCfgEntry(&entry);
2434     Label exit(env);
2435     DEFVARIABLE(result, VariableType::JS_ANY(), value);
2436 
2437     GateRef intValue = ChangeTaggedPointerToInt64(value);
2438     GateRef regionType = GetCMCRegionType(value);
2439     Label isFromeSpace(env);
2440     GateRef fromType = Int8(static_cast<int8_t>(common::RegionDesc::RegionType::FROM_REGION));
2441     Branch(Int8Equal(regionType, fromType), &isFromeSpace, &exit);
2442     Bind(&isFromeSpace);
2443     {
2444         GateRef weakMask = Int64And(intValue, Int64(JSTaggedValue::TAG_WEAK));
2445         GateRef obj = Int64And(intValue, Int64(~JSTaggedValue::TAG_WEAK));
2446 
2447         GateRef forwardedAddr = LoadPrimitive(VariableType::INT64(), obj, IntPtr(0));
2448         GateRef forwardState =
2449             Int64LSR(forwardedAddr, Int64(common::BaseStateWord::PADDING_WIDTH + common::BaseStateWord::FORWARD_WIDTH));
2450         Label forwarded(env);
2451         Label notForwarded(env);
2452         Branch(Int64Equal(forwardState, Int64(static_cast<int64_t>(common::BaseStateWord::ForwardState::FORWARDED))),
2453             &forwarded, &notForwarded);
2454         Bind(&forwarded);
2455         {
2456             result = Int64ToTaggedPtr(Int64Or(Int64And(forwardedAddr, Int64(TaggedStateWord::ADDRESS_MASK)), weakMask));
2457             Jump(&exit);
2458         }
2459         Bind(&notForwarded);
2460         {
2461             result = CallNGCRuntime(glue, RTSTUB_ID(ReadBarrier), { glue, addr });
2462             Jump(&exit);
2463         }
2464     }
2465 
2466     Bind(&exit);
2467     auto ret = *result;
2468     env->SubCfgExit();
2469     return ret;
2470 }
2471 
IsHeapAddress(GateRef glue,GateRef value)2472 GateRef StubBuilder::IsHeapAddress(GateRef glue, GateRef value)
2473 {
2474     bool isArch32 = GetEnvironment()->Is32Bit();
2475     GateRef heapStartAddr = LoadPrimitive(
2476         VariableType::NATIVE_POINTER(), glue, IntPtr(JSThread::GlueData::GetHeapStartAddrOffset(isArch32)));
2477     GateRef heapCurrentEnd = LoadPrimitive(
2478         VariableType::NATIVE_POINTER(), glue, IntPtr(JSThread::GlueData::GetHeapCurrentEndOffset(isArch32)));
2479     auto IntPtrValue =  ChangeTaggedPointerToInt64(value);
2480     return BitAnd(IntPtrGreaterThanOrEqual(IntPtrValue, heapStartAddr), IntPtrLessThan(IntPtrValue, heapCurrentEnd));
2481 }
2482 
TaggedIsBigInt(GateRef glue,GateRef obj)2483 GateRef StubBuilder::TaggedIsBigInt(GateRef glue, GateRef obj)
2484 {
2485     auto env = GetEnvironment();
2486     Label entry(env);
2487     env->SubCfgEntry(&entry);
2488     Label exit(env);
2489     Label isHeapObject(env);
2490     DEFVARIABLE(result, VariableType::BOOL(), False());
2491     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
2492     Bind(&isHeapObject);
2493     {
2494         result = Int32Equal(GetObjectType(LoadHClass(glue, obj)),
2495                             Int32(static_cast<int32_t>(JSType::BIGINT)));
2496         Jump(&exit);
2497     }
2498     Bind(&exit);
2499     auto ret = *result;
2500     env->SubCfgExit();
2501     return ret;
2502 }
2503 
TaggedIsPropertyBox(GateRef glue,GateRef obj)2504 GateRef StubBuilder::TaggedIsPropertyBox(GateRef glue, GateRef obj)
2505 {
2506     auto env = GetEnvironment();
2507     Label entry(env);
2508     env->SubCfgEntry(&entry);
2509     Label exit(env);
2510     Label isHeapObject(env);
2511     DEFVARIABLE(result, VariableType::BOOL(), False());
2512     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
2513     Bind(&isHeapObject);
2514     {
2515         GateRef type = GetObjectType(LoadHClass(glue, obj));
2516         result = Int32Equal(type, Int32(static_cast<int32_t>(JSType::PROPERTY_BOX)));
2517         Jump(&exit);
2518     }
2519     Bind(&exit);
2520     auto ret = *result;
2521     env->SubCfgExit();
2522     return ret;
2523 }
2524 
TaggedIsAccessor(GateRef glue,GateRef x)2525 GateRef StubBuilder::TaggedIsAccessor(GateRef glue, GateRef x)
2526 {
2527     auto env = GetEnvironment();
2528     Label entry(env);
2529     env->SubCfgEntry(&entry);
2530     Label exit(env);
2531     Label isHeapObject(env);
2532     DEFVARIABLE(result, VariableType::BOOL(), False());
2533     BRANCH(TaggedIsHeapObject(x), &isHeapObject, &exit);
2534     Bind(&isHeapObject);
2535     {
2536         GateRef type = GetObjectType(LoadHClass(glue, x));
2537         result = BitOr(Int32Equal(type, Int32(static_cast<int32_t>(JSType::ACCESSOR_DATA))),
2538                         Int32Equal(type, Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR))));
2539         Jump(&exit);
2540     }
2541     Bind(&exit);
2542     auto ret = *result;
2543     env->SubCfgExit();
2544     return ret;
2545 }
2546 
TaggedIsInternalAccessor(GateRef glue,GateRef x)2547 GateRef StubBuilder::TaggedIsInternalAccessor(GateRef glue, GateRef x)
2548 {
2549     auto env = GetEnvironment();
2550     Label entry(env);
2551     env->SubCfgEntry(&entry);
2552     Label exit(env);
2553     Label isHeapObject(env);
2554     DEFVARIABLE(result, VariableType::BOOL(), False());
2555     BRANCH(TaggedIsHeapObject(x), &isHeapObject, &exit);
2556     Bind(&isHeapObject);
2557     {
2558         GateRef type = GetObjectType(LoadHClass(glue, x));
2559         result = Int32Equal(type, Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR)));
2560         Jump(&exit);
2561     }
2562     Bind(&exit);
2563     auto ret = *result;
2564     env->SubCfgExit();
2565     return ret;
2566 }
2567 
IsUtf16String(GateRef string)2568 GateRef StubBuilder::IsUtf16String(GateRef string)
2569 {
2570     // compressedStringsEnabled fixed to true constant
2571     GateRef len = LoadPrimitive(VariableType::INT32(), string, IntPtr(BaseString::LENGTH_AND_FLAGS_OFFSET));
2572     return Int32Equal(
2573         Int32And(len, Int32((1 << BaseString::CompressedStatusBit::SIZE) - 1)),
2574         Int32(BaseString::STRING_UNCOMPRESSED));
2575 }
2576 
IsUtf8String(GateRef string)2577 GateRef StubBuilder::IsUtf8String(GateRef string)
2578 {
2579     // compressedStringsEnabled fixed to true constant
2580     GateRef len = LoadPrimitive(VariableType::INT32(), string, IntPtr(BaseString::LENGTH_AND_FLAGS_OFFSET));
2581     return Int32Equal(
2582         Int32And(len, Int32((1 << BaseString::CompressedStatusBit::SIZE) - 1)),
2583         Int32(BaseString::STRING_COMPRESSED));
2584 }
2585 
IsDigit(GateRef ch)2586 GateRef StubBuilder::IsDigit(GateRef ch)
2587 {
2588     return BitAnd(Int32LessThanOrEqual(ch, Int32('9')),
2589         Int32GreaterThanOrEqual(ch, Int32('0')));
2590 }
2591 
TryToElementsIndex(GateRef glue,GateRef key)2592 GateRef StubBuilder::TryToElementsIndex(GateRef glue, GateRef key)
2593 {
2594     auto env = GetEnvironment();
2595     Label entry(env);
2596     env->SubCfgEntry(&entry);
2597     Label exit(env);
2598     Label isKeyInt(env);
2599     Label notKeyInt(env);
2600 
2601     DEFVARIABLE(resultKey, VariableType::INT64(), Int64(-1));
2602     BRANCH(TaggedIsInt(key), &isKeyInt, &notKeyInt);
2603     Bind(&isKeyInt);
2604     {
2605         resultKey = GetInt64OfTInt(key);
2606         Jump(&exit);
2607     }
2608     Bind(&notKeyInt);
2609     {
2610         Label isString(env);
2611         Label notString(env);
2612         BRANCH(TaggedIsString(glue, key), &isString, &notString);
2613         Bind(&isString);
2614         {
2615             BuiltinsStringStubBuilder stringStub(this, GetCurrentGlobalEnv());
2616             resultKey = stringStub.StringToUint(glue, key, JSObject::MAX_ELEMENT_INDEX - 1);
2617             Jump(&exit);
2618         }
2619         Bind(&notString);
2620         {
2621             Label isDouble(env);
2622             BRANCH(TaggedIsDouble(key), &isDouble, &exit);
2623             Bind(&isDouble);
2624             {
2625                 GateRef number = GetDoubleOfTDouble(key);
2626                 GateRef integer = ChangeFloat64ToInt32(number);
2627                 Label isEqual(env);
2628                 BRANCH(DoubleEqual(number, ChangeInt32ToFloat64(integer)), &isEqual, &exit);
2629                 Bind(&isEqual);
2630                 {
2631                     resultKey = SExtInt32ToInt64(integer);
2632                     Jump(&exit);
2633                 }
2634             }
2635         }
2636     }
2637     Bind(&exit);
2638     auto ret = *resultKey;
2639     env->SubCfgExit();
2640     return ret;
2641 }
2642 
LdGlobalRecord(GateRef glue,GateRef key)2643 GateRef StubBuilder::LdGlobalRecord(GateRef glue, GateRef key)
2644 {
2645     auto env = GetEnvironment();
2646     Label entry(env);
2647     env->SubCfgEntry(&entry);
2648     Label exit(env);
2649 
2650     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2651     GateRef globalEnv = GetCurrentGlobalEnv();
2652     GateRef globalRecord = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::GLOBAL_RECORD);
2653     GateRef recordEntry = FindEntryFromHashTable<NameDictionary>(glue, globalRecord, key);
2654     Label foundInGlobalRecord(env);
2655     BRANCH(Int32NotEqual(recordEntry, Int32(-1)), &foundInGlobalRecord, &exit);
2656     Bind(&foundInGlobalRecord);
2657     {
2658         result = GetBoxFromGlobalDictionary(glue, globalRecord, recordEntry);
2659         Jump(&exit);
2660     }
2661     Bind(&exit);
2662     auto ret = *result;
2663     env->SubCfgExit();
2664     return ret;
2665 }
2666 
LoadFromField(GateRef glue,GateRef receiver,GateRef handlerInfo)2667 GateRef StubBuilder::LoadFromField(GateRef glue, GateRef receiver, GateRef handlerInfo)
2668 {
2669     auto env = GetEnvironment();
2670     Label entry(env);
2671     env->SubCfgEntry(&entry);
2672     Label exit(env);
2673     Label handlerInfoIsInlinedProps(env);
2674     Label handlerInfoNotInlinedProps(env);
2675     Label handlerPost(env);
2676     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2677     GateRef index = HandlerBaseGetOffset(handlerInfo);
2678 #if ENABLE_NEXT_OPTIMIZATION
2679     BRANCH_LIKELY(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
2680 #else
2681     BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
2682 #endif
2683     Bind(&handlerInfoIsInlinedProps);
2684     {
2685         result = Load(VariableType::JS_ANY(), glue, receiver, PtrMul(ZExtInt32ToPtr(index),
2686             IntPtr(JSTaggedValue::TaggedTypeSize())));
2687         Jump(&handlerPost);
2688     }
2689     Bind(&handlerInfoNotInlinedProps);
2690     {
2691         result = GetValueFromTaggedArray(glue, GetPropertiesArray(glue, receiver), index);
2692         Jump(&handlerPost);
2693     }
2694     Bind(&handlerPost);
2695     {
2696         Label nonDoubleToTagged(env);
2697         Label doubleToTagged(env);
2698         GateRef rep = HandlerBaseGetRep(handlerInfo);
2699 #if ENABLE_NEXT_OPTIMIZATION
2700         BRANCH_UNLIKELY(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
2701 #else
2702         BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
2703 #endif
2704         Bind(&doubleToTagged);
2705         {
2706             result = TaggedPtrToTaggedDoublePtr(*result);
2707             Jump(&exit);
2708         }
2709         Bind(&nonDoubleToTagged);
2710         {
2711             Label intToTagged(env);
2712 #if ENABLE_NEXT_OPTIMIZATION
2713             BRANCH_UNLIKELY(IsIntRepInPropAttr(rep), &intToTagged, &exit);
2714 #else
2715             BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit);
2716 #endif
2717             Bind(&intToTagged);
2718             {
2719                 result = TaggedPtrToTaggedIntPtr(*result);
2720                 Jump(&exit);
2721             }
2722         }
2723     }
2724     Bind(&exit);
2725     auto ret = *result;
2726     env->SubCfgExit();
2727     return ret;
2728 }
2729 
LoadGlobal(GateRef glue,GateRef cell)2730 GateRef StubBuilder::LoadGlobal(GateRef glue, GateRef cell)
2731 {
2732     auto env = GetEnvironment();
2733     Label entry(env);
2734     env->SubCfgEntry(&entry);
2735     Label exit(env);
2736     Label cellNotInvalid(env);
2737     Label cellNotAccessor(env);
2738     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2739     BRANCH(IsInvalidPropertyBox(glue, cell), &exit, &cellNotInvalid);
2740     Bind(&cellNotInvalid);
2741     {
2742         BRANCH(IsAccessorPropertyBox(glue, cell), &exit, &cellNotAccessor);
2743         Bind(&cellNotAccessor);
2744         {
2745             result = GetValueFromPropertyBox(glue, cell);
2746             Jump(&exit);
2747         }
2748     }
2749     Bind(&exit);
2750     auto ret = *result;
2751     env->SubCfgExit();
2752     return ret;
2753 }
2754 
CheckPolyHClass(GateRef glue,GateRef cachedValue,GateRef hclass)2755 GateRef StubBuilder::CheckPolyHClass(GateRef glue, GateRef cachedValue, GateRef hclass)
2756 {
2757     auto env = GetEnvironment();
2758     Label entry(env);
2759     env->SubCfgEntry(&entry);
2760     Label exit(env);
2761     Label loopHead(env);
2762     Label loopEnd(env);
2763     Label iLessLength(env);
2764     Label hasHclass(env);
2765     Label cachedValueNotWeak(env);
2766     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2767     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2768     BRANCH(TaggedIsWeak(cachedValue), &exit, &cachedValueNotWeak);
2769     Bind(&cachedValueNotWeak);
2770     {
2771         Label isTaggedArray(env);
2772         Branch(IsTaggedArray(glue, cachedValue), &isTaggedArray, &exit);
2773         Bind(&isTaggedArray);
2774         {
2775             GateRef length = GetLengthOfTaggedArray(cachedValue);
2776             Jump(&loopHead);
2777             LoopBegin(&loopHead);
2778             {
2779                 BRANCH(Int32UnsignedLessThan(*i, length), &iLessLength, &exit);
2780                 Bind(&iLessLength);
2781                 {
2782                     GateRef element = GetValueFromTaggedArray(glue, cachedValue, *i);
2783                     BRANCH(Equal(LoadObjectFromWeakRef(element), hclass), &hasHclass, &loopEnd);
2784                     Bind(&hasHclass);
2785                     result = GetValueFromTaggedArray(glue, cachedValue, Int32Add(*i, Int32(1)));
2786                     Jump(&exit);
2787                 }
2788                 Bind(&loopEnd);
2789                 i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot
2790                 LoopEnd(&loopHead);
2791             }
2792         }
2793     }
2794     Bind(&exit);
2795     auto ret = *result;
2796     env->SubCfgExit();
2797     return ret;
2798 }
2799 
LoadICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef argHandler,ProfileOperation callback)2800 GateRef StubBuilder::LoadICWithHandler(
2801     GateRef glue, GateRef receiver, GateRef argHolder, GateRef argHandler, ProfileOperation callback)
2802 {
2803     auto env = GetEnvironment();
2804     Label entry(env);
2805     env->SubCfgEntry(&entry);
2806     Label exit(env);
2807     Label handlerIsInt(env);
2808     Label handlerNotInt(env);
2809     Label handleInfoIsFound(env);
2810     Label handleInfoIsNotFound(env);
2811     Label handlerInfoIsField(env);
2812     Label handlerInfoNotField(env);
2813     Label handlerInfoIsNonExist(env);
2814     Label handlerInfoExist(env);
2815     Label handlerInfoIsPrimitive(env);
2816     Label handlerInfoNotPrimitive(env);
2817     Label handlerInfoNotStringOrNumber(env);
2818     Label handlerInfoIsStringLength(env);
2819     Label handlerInfoNotStringLength(env);
2820     Label handlerIsPrototypeHandler(env);
2821     Label handlerNotPrototypeHandler(env);
2822     Label cellHasChanged(env);
2823     Label cellNotFoundHasChanged(env);
2824     Label cellNotFoundNotChanged(env);
2825     Label cellNotUndefined(env);
2826     Label loopHead(env);
2827     Label loopEnd(env);
2828     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2829     DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
2830     DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
2831 
2832     Jump(&loopHead);
2833     LoopBegin(&loopHead);
2834     {
2835         BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
2836         Bind(&handlerIsInt);
2837         {
2838             GateRef handlerInfo = GetInt64OfTInt(*handler);
2839 #if ENABLE_NEXT_OPTIMIZATION
2840             BRANCH_LIKELY(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2841 #else
2842             BRANCH(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2843 #endif
2844             Bind(&handlerInfoIsField);
2845             {
2846                 result = LoadFromField(glue, *holder, handlerInfo);
2847                 Jump(&exit);
2848             }
2849             Bind(&handlerInfoNotField);
2850             {
2851                 BRANCH(BitOr(IsStringElement(handlerInfo), IsNumberHandler(handlerInfo)),
2852                     &handlerInfoIsPrimitive, &handlerInfoNotStringOrNumber);
2853                 Bind(&handlerInfoNotStringOrNumber);
2854                 {
2855                     BRANCH(IsBooleanHandler(handlerInfo), &handlerInfoIsPrimitive, &handlerInfoNotPrimitive);
2856                 }
2857                 Bind(&handlerInfoIsPrimitive);
2858                 {
2859                     result = LoadFromField(glue, *holder, handlerInfo);
2860                     Jump(&exit);
2861                 }
2862                 Bind(&handlerInfoNotPrimitive);
2863                 {
2864                     BRANCH(IsNonExist(handlerInfo), &handlerInfoIsNonExist, &handlerInfoExist);
2865                     // For the special "Not Found" case we may generate ic by "LoadHandler::LoadProperty".
2866                     // In this situation, you can trust ic without ChangeMarker.
2867                     Bind(&handlerInfoIsNonExist);
2868                     {
2869                         result = Undefined();
2870                         Jump(&exit);
2871                     }
2872                     Bind(&handlerInfoExist);
2873                     {
2874                         BRANCH(IsStringLength(handlerInfo), &handlerInfoIsStringLength, &handlerInfoNotStringLength);
2875                         Bind(&handlerInfoNotStringLength);
2876                         {
2877                             GateRef accessor = LoadFromField(glue, *holder, handlerInfo);
2878                             // The getter may involve nested calls, so it is better to end (or return) early.
2879                             EndTraceLoad(glue);
2880                             result = CallGetterHelper(glue, receiver, *holder, accessor, callback);
2881                             StartTraceLoadGetter(glue);
2882                             Jump(&exit);
2883                         }
2884                         Bind(&handlerInfoIsStringLength);
2885                         {
2886                             result = IntToTaggedPtr(GetLengthFromString(receiver));
2887                             Jump(&exit);
2888                         }
2889                     }
2890                 }
2891             }
2892         }
2893         Bind(&handlerNotInt);
2894         BRANCH_LIKELY(TaggedIsPrototypeHandler(glue, *handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
2895         Bind(&handlerIsPrototypeHandler);
2896         {
2897             GateRef cellValue = GetPrototypeHandlerProtoCell(glue, *handler);
2898             BRANCH_UNLIKELY(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
2899             Bind(&cellNotUndefined);
2900             BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2901             Bind(&cellHasChanged);
2902             {
2903                 result = Hole();
2904                 Jump(&exit);
2905             }
2906             Bind(&loopEnd);
2907             holder = GetPrototypeHandlerHolder(glue, *handler);
2908             BRANCH(Equal(*holder, Undefined()), &handleInfoIsNotFound, &handleInfoIsFound);
2909             Bind(&handleInfoIsFound);
2910             {
2911             handler = GetPrototypeHandlerHandlerInfo(glue, *handler);
2912             LoopEndWithCheckSafePoint(&loopHead, env, glue);
2913             }
2914 
2915             // For "Not Found" case (holder equals Undefined()),
2916             // we should ensure that both GetNotFoundHasChanged() and GetHasChanged() return false.
2917             Bind(&handleInfoIsNotFound);
2918             {
2919                 BRANCH(GetNotFoundHasChanged(cellValue), &cellNotFoundHasChanged, &cellNotFoundNotChanged);
2920                 Bind(&cellNotFoundHasChanged);
2921                 {
2922                     result = Hole();
2923                     Jump(&exit);
2924                 }
2925                 Bind(&cellNotFoundNotChanged);
2926                 {
2927                     result = Undefined();
2928                     Jump(&exit);
2929                 }
2930             }
2931         }
2932     }
2933     Bind(&handlerNotPrototypeHandler);
2934     {
2935     result = LoadGlobal(glue, *handler);
2936     Jump(&exit);
2937     }
2938     Bind(&exit);
2939     auto ret = *result;
2940     env->SubCfgExit();
2941     return ret;
2942 }
2943 
LoadElement(GateRef glue,GateRef receiver,GateRef key)2944 GateRef StubBuilder::LoadElement(GateRef glue, GateRef receiver, GateRef key)
2945 {
2946     auto env = GetEnvironment();
2947     Label entry(env);
2948     env->SubCfgEntry(&entry);
2949     Label exit(env);
2950     Label indexLessZero(env);
2951     Label indexNotLessZero(env);
2952     Label lengthLessIndex(env);
2953     Label lengthNotLessIndex(env);
2954     Label greaterThanInt32Max(env);
2955     Label notGreaterThanInt32Max(env);
2956     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2957     GateRef index64 = TryToElementsIndex(glue, key);
2958     BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
2959     Bind(&greaterThanInt32Max);
2960     {
2961         Jump(&exit);
2962     }
2963     Bind(&notGreaterThanInt32Max);
2964     GateRef index = TruncInt64ToInt32(index64);
2965     BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2966     Bind(&indexLessZero);
2967     {
2968         Jump(&exit);
2969     }
2970     Bind(&indexNotLessZero);
2971     {
2972         GateRef elements = GetElementsArray(glue, receiver);
2973         BRANCH(Int32LessThanOrEqual(GetLengthOfTaggedArray(elements), index), &lengthLessIndex, &lengthNotLessIndex);
2974         Bind(&lengthLessIndex);
2975         Jump(&exit);
2976         Bind(&lengthNotLessIndex);
2977         result = GetTaggedValueWithElementsKind(glue, receiver, index);
2978         Jump(&exit);
2979     }
2980     Bind(&exit);
2981     auto ret = *result;
2982     env->SubCfgExit();
2983     return ret;
2984 }
2985 
LoadStringElement(GateRef glue,GateRef receiver,GateRef key)2986 GateRef StubBuilder::LoadStringElement(GateRef glue, GateRef receiver, GateRef key)
2987 {
2988     auto env = GetEnvironment();
2989     Label entry(env);
2990     env->SubCfgEntry(&entry);
2991     Label exit(env);
2992     Label indexLessZero(env);
2993     Label indexNotLessZero(env);
2994     Label lengthLessIndex(env);
2995     Label lengthNotLessIndex(env);
2996     Label greaterThanInt32Max(env);
2997     Label notGreaterThanInt32Max(env);
2998     Label flattenFastPath(env);
2999 
3000     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3001     GateRef index64 = TryToElementsIndex(glue, key);
3002     BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
3003     Bind(&greaterThanInt32Max);
3004     {
3005         Jump(&exit);
3006     }
3007     Bind(&notGreaterThanInt32Max);
3008     GateRef index = TruncInt64ToInt32(index64);
3009     BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
3010     Bind(&indexLessZero);
3011     {
3012         Jump(&exit);
3013     }
3014     Bind(&indexNotLessZero);
3015     {
3016         FlatStringStubBuilder thisFlat(this);
3017         thisFlat.FlattenString(glue, receiver, &flattenFastPath);
3018         Bind(&flattenFastPath);
3019         BRANCH(Int32LessThanOrEqual(GetLengthFromString(receiver), index), &lengthLessIndex, &lengthNotLessIndex);
3020         Bind(&lengthLessIndex);
3021         Jump(&exit);
3022         Bind(&lengthNotLessIndex);
3023         BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
3024         StringInfoGateRef stringInfoGate(&thisFlat);
3025         result = stringBuilder.CreateFromEcmaString(glue, index, stringInfoGate);
3026         Jump(&exit);
3027     }
3028     Bind(&exit);
3029     auto ret = *result;
3030     env->SubCfgExit();
3031     return ret;
3032 }
3033 
TaggedArraySetValue(GateRef glue,GateRef receiver,GateRef value,GateRef index,GateRef capacity)3034 GateRef StubBuilder::TaggedArraySetValue(GateRef glue, GateRef receiver, GateRef value, GateRef index, GateRef capacity)
3035 {
3036     auto env = GetEnvironment();
3037     Label entryPass(env);
3038     env->SubCfgEntry(&entryPass);
3039     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3040     Label indexGreaterLen(env);
3041     Label storeElement(env);
3042     Label isTransToDict(env);
3043     Label notTransToDict(env);
3044     Label exit(env);
3045     BRANCH(Int32UnsignedGreaterThanOrEqual(index, capacity), &indexGreaterLen, &storeElement);
3046     Bind(&indexGreaterLen);
3047     {
3048         BRANCH(ShouldTransToDict(capacity, index), &isTransToDict, &notTransToDict);
3049         Bind(&isTransToDict);
3050         result = Hole();
3051         Jump(&exit);
3052         Bind(&notTransToDict);
3053         GrowElementsCapacity(glue, receiver, Int32Add(index, Int32(1)));
3054         Jump(&storeElement);
3055     }
3056     Bind(&storeElement);
3057     {
3058         SetValueWithElementsKind(glue, receiver, value, index, Boolean(true),
3059             Int32(Elements::ToUint(ElementsKind::NONE)));
3060         result = Undefined();
3061         Jump(&exit);
3062     }
3063     Bind(&exit);
3064     auto ret = *result;
3065     env->SubCfgExit();
3066     return ret;
3067 }
3068 
ICStoreElement(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef handler,bool updateHandler,GateRef profileTypeInfo,GateRef slotId)3069 GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef handler,
3070                                     bool updateHandler, GateRef profileTypeInfo, GateRef slotId)
3071 {
3072     auto env = GetEnvironment();
3073     Label entry(env);
3074     env->SubCfgEntry(&entry);
3075     Label exit(env);
3076     Label indexLessZero(env);
3077     Label indexNotLessZero(env);
3078     Label handlerInfoIsTypedArray(env);
3079     Label handerInfoNotTypedArray(env);
3080     Label handerInfoIsJSArray(env);
3081     Label handerInfoNotJSArray(env);
3082     Label isJsCOWArray(env);
3083     Label isNotJsCOWArray(env);
3084     Label setElementsLength(env);
3085     Label indexGreaterLength(env);
3086     Label indexGreaterCapacity(env);
3087     Label storeElement(env);
3088     Label handlerIsInt(env);
3089     Label handlerNotInt(env);
3090     Label loopHead(env);
3091     Label loopEnd(env);
3092     Label greaterThanInt32Max(env);
3093     Label notGreaterThanInt32Max(env);
3094     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3095     DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler);
3096     GateRef index64 = TryToElementsIndex(glue, key);
3097     BRANCH_UNLIKELY(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
3098     Bind(&greaterThanInt32Max);
3099     {
3100         Jump(&exit);
3101     }
3102     Bind(&notGreaterThanInt32Max);
3103     GateRef index = TruncInt64ToInt32(index64);
3104     BRANCH_UNLIKELY(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
3105     Bind(&indexLessZero);
3106     {
3107         Jump(&exit);
3108     }
3109     Bind(&indexNotLessZero);
3110     {
3111         DEFVARIABLE(isOnPrototype, VariableType::BOOL(), False());
3112         Jump(&loopHead);
3113         LoopBegin(&loopHead);
3114         BRANCH(TaggedIsInt(*varHandler), &handlerIsInt, &handlerNotInt);
3115         Bind(&handlerIsInt);
3116         {
3117             GateRef handlerInfo = GetInt64OfTInt(*varHandler);
3118             BRANCH(IsTypedArrayElement(handlerInfo), &handlerInfoIsTypedArray, &handerInfoNotTypedArray);
3119             Bind(&handlerInfoIsTypedArray);
3120             {
3121                 GateRef hclass = LoadHClass(glue, receiver);
3122                 GateRef jsType = GetObjectType(hclass);
3123                 BuiltinsTypedArrayStubBuilder typedArrayBuilder(this, GetCurrentGlobalEnv());
3124                 result = typedArrayBuilder.StoreTypedArrayElement(glue, receiver, index64, value, jsType);
3125                 Jump(&exit);
3126             }
3127             Bind(&handerInfoNotTypedArray);
3128             BRANCH(HandlerBaseIsJSArray(handlerInfo), &handerInfoIsJSArray, &handerInfoNotJSArray);
3129             Bind(&handerInfoIsJSArray);
3130             {
3131                 BRANCH(IsJsCOWArray(glue, receiver), &isJsCOWArray, &isNotJsCOWArray);
3132                 Bind(&isJsCOWArray);
3133                 {
3134                     CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {receiver});
3135                     Jump(&setElementsLength);
3136                 }
3137                 Bind(&isNotJsCOWArray);
3138                 {
3139                     Jump(&setElementsLength);
3140                 }
3141                 Bind(&setElementsLength);
3142                 {
3143                     GateRef oldLength = GetArrayLength(receiver);
3144                     BRANCH(Int32UnsignedGreaterThanOrEqual(index, oldLength), &indexGreaterLength, &handerInfoNotJSArray);
3145                     Bind(&indexGreaterLength);
3146                     Store(VariableType::INT32(), glue, receiver,
3147                         IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET),
3148                         Int32Add(index, Int32(1)));
3149                     if (updateHandler) {
3150                         Label update(env);
3151                         Label setObject(env);
3152                         Label setPrototype(env);
3153                         GateRef oldHandler = GetValueFromTaggedArray(glue, profileTypeInfo, slotId);
3154                         BRANCH(Equal(oldHandler, Hole()), &handerInfoNotJSArray, &update);
3155                         Bind(&update);
3156                         {
3157                             handler = Int64ToTaggedInt(UpdateSOutOfBoundsForHandler(handlerInfo));
3158                             BRANCH(Equal(*isOnPrototype, False()), &setObject, &setPrototype);
3159                             Bind(&setObject);
3160                             {
3161                                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, handler);
3162                                 Jump(&handerInfoNotJSArray);
3163                             }
3164                             Bind(&setPrototype);
3165                             {
3166                                 SetPrototypeHandlerHandlerInfo(glue, oldHandler, handler);
3167                             }
3168                         }
3169                     }
3170                 }
3171                 Jump(&handerInfoNotJSArray);
3172             }
3173             Bind(&handerInfoNotJSArray);
3174             {
3175                 GateRef elements = GetElementsArray(glue, receiver);
3176                 GateRef capacity = GetLengthOfTaggedArray(elements);
3177                 BRANCH(Int32UnsignedGreaterThanOrEqual(index, capacity), &indexGreaterCapacity, &storeElement);
3178                 Bind(&indexGreaterCapacity);
3179                 {
3180                     result = TaggedArraySetValue(glue, receiver, value, index, capacity);
3181                     Label transition(env);
3182                     BRANCH(TaggedIsHole(*result), &exit, &transition);
3183                     Bind(&transition);
3184                     {
3185                         Label hole(env);
3186                         DEFVARIABLE(kind, VariableType::INT32(), Int32(Elements::ToUint(ElementsKind::NONE)));
3187                         BRANCH(Int32UnsignedGreaterThan(index, capacity), &hole, &exit);
3188                         Bind(&hole);
3189                         {
3190                             kind = Int32(Elements::ToUint(ElementsKind::HOLE));
3191                             SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
3192                             Jump(&exit);
3193                         }
3194                     }
3195                 }
3196                 Bind(&storeElement);
3197                 {
3198                     SetValueWithElementsKind(glue, receiver, value, index, Boolean(true),
3199                                              Int32(Elements::ToUint(ElementsKind::NONE)));
3200                     result = Undefined();
3201                     Jump(&exit);
3202                 }
3203             }
3204         }
3205         Bind(&handlerNotInt);
3206         {
3207             Label handlerIsPrototypeHandler(env);
3208             Label handlerNotPrototypeHandler(env);
3209             Label handlerIsTransWithProtoHandler(env);
3210             Label handlerIsTransitionHandler(env);
3211 
3212             BRANCH(TaggedIsPrototypeHandler(glue, *varHandler), &handlerIsPrototypeHandler,
3213                    &handlerNotPrototypeHandler);
3214             Bind(&handlerIsPrototypeHandler);
3215             {
3216                 // If the handler is a prototypehandler, we need to check protochangemarker.
3217                 Label cellNotNullOrUndefined(env);
3218                 Label getPrototypeHandlerHandlerInfo(env);
3219                 GateRef cellValue = GetPrototypeHandlerProtoCell(glue, *varHandler);
3220                 BRANCH(TaggedIsUndefinedOrNull(cellValue), &exit, &cellNotNullOrUndefined);
3221 
3222                 Bind(&cellNotNullOrUndefined);
3223                 BRANCH(GetHasChanged(cellValue), &exit, &getPrototypeHandlerHandlerInfo);
3224                 Bind(&getPrototypeHandlerHandlerInfo);
3225                 {
3226                     isOnPrototype = True();
3227                     varHandler = GetPrototypeHandlerHandlerInfo(glue, *varHandler);
3228                     Jump(&loopEnd);
3229                 }
3230             }
3231 
3232             Bind(&handlerNotPrototypeHandler);
3233             {
3234                 BRANCH(TaggedIsTransWithProtoHandler(glue, *varHandler), &handlerIsTransWithProtoHandler,
3235                        &handlerIsTransitionHandler);
3236                 Bind(&handlerIsTransWithProtoHandler);
3237                 {
3238                     // If the handler is a transwithprotohandler, we need to check protochangemarker.
3239                     Label cellNotNullOrUndefined(env);
3240                     Label getTransWithProtoHandlerInfo(env);
3241                     GateRef cellValue = GetTransWithProtoHandlerProtoCell(glue, *varHandler);
3242                     BRANCH(TaggedIsUndefinedOrNull(cellValue), &exit, &cellNotNullOrUndefined);
3243 
3244                     Bind(&cellNotNullOrUndefined);
3245                     BRANCH(GetHasChanged(cellValue), &exit, &getTransWithProtoHandlerInfo);
3246                     Bind(&getTransWithProtoHandlerInfo);
3247                     {
3248                         isOnPrototype = True();
3249                         varHandler = GetTransWithProtoHandlerInfo(glue, *varHandler);
3250                         Jump(&loopEnd);
3251                     }
3252                 }
3253                 Bind(&handlerIsTransitionHandler);
3254                 {
3255                     // If the handler is a transitionhandler, we just get handlerinfo.
3256                     varHandler = GetTransitionHandlerInfo(glue, *varHandler);
3257                     Jump(&loopEnd);
3258                 }
3259             }
3260 
3261             Bind(&loopEnd);
3262             {
3263                 LoopEndWithCheckSafePoint(&loopHead, env, glue);
3264             }
3265         }
3266     }
3267     Bind(&exit);
3268     auto ret = *result;
3269     env->SubCfgExit();
3270     return ret;
3271 }
3272 
GetArrayLength(GateRef object)3273 GateRef StubBuilder::GetArrayLength(GateRef object)
3274 {
3275     GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
3276     GateRef result = LoadPrimitive(VariableType::INT32(), object, lengthOffset);
3277     return result;
3278 }
3279 
SetArrayLength(GateRef glue,GateRef object,GateRef len)3280 void StubBuilder::SetArrayLength(GateRef glue, GateRef object, GateRef len)
3281 {
3282     GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
3283     Store(VariableType::INT32(), glue, object, lengthOffset, len);
3284 }
3285 
StoreICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef value,GateRef argHandler,ProfileOperation callback)3286 GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder,
3287                                         GateRef value, GateRef argHandler, ProfileOperation callback)
3288 {
3289     auto env = GetEnvironment();
3290     Label entry(env);
3291     env->SubCfgEntry(&entry);
3292     Label exit(env);
3293     Label handlerIsInt(env);
3294     Label handlerNotInt(env);
3295     Label handlerInfoIsField(env);
3296     Label handlerInfoNotField(env);
3297     Label isShared(env);
3298     Label notShared(env);
3299     Label sharedObjectStoreBarrier(env);
3300     Label prepareIntHandlerLoop(env);
3301     Label handlerIsTransitionHandler(env);
3302     Label handlerNotTransitionHandler(env);
3303     Label handlerIsTransWithProtoHandler(env);
3304     Label handlerNotTransWithProtoHandler(env);
3305     Label handlerIsPrototypeHandler(env);
3306     Label handlerNotPrototypeHandler(env);
3307     Label handlerIsPropertyBox(env);
3308     Label handlerNotPropertyBox(env);
3309     Label handlerIsStoreAOTHandler(env);
3310     Label handlerNotStoreAOTHandler(env);
3311     Label aotHandlerInfoIsField(env);
3312     Label aotHandlerInfoNotField(env);
3313     Label cellHasChanged(env);
3314     Label cellNotChanged(env);
3315     Label cellNotUndefined(env);
3316     Label aotCellNotChanged(env);
3317     Label loopHead(env);
3318     Label loopEnd(env);
3319     Label JumpLoopHead(env);
3320     Label cellNotNull(env);
3321     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3322     DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
3323     DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
3324     DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
3325     Jump(&loopHead);
3326     LoopBegin(&loopHead);
3327     {
3328         BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
3329         Bind(&handlerIsInt);
3330         {
3331             GateRef handlerInfo = GetInt64OfTInt(*handler);
3332             BRANCH(IsNonSharedStoreField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
3333             Bind(&handlerInfoIsField);
3334             {
3335                 result = StoreField(glue, receiver, *actualValue, handlerInfo, callback);
3336                 Jump(&exit);
3337             }
3338             Bind(&handlerInfoNotField);
3339             {
3340                 BRANCH(IsStoreShared(handlerInfo), &isShared, &notShared);
3341                 Bind(&isShared);
3342                 {
3343                     BRANCH(HandlerBaseIsAccessor(handlerInfo), &prepareIntHandlerLoop, &sharedObjectStoreBarrier);
3344                     Bind(&sharedObjectStoreBarrier);
3345                     {
3346                         GateRef field = GetFieldTypeFromHandler(handlerInfo);
3347                         SharedObjectStoreBarrierWithTypeCheck(&result, glue, field, value, &actualValue,
3348                             &prepareIntHandlerLoop, &exit);
3349                     }
3350                     Bind(&prepareIntHandlerLoop);
3351                     {
3352                         handler = IntToTaggedPtr(ClearSharedStoreKind(handlerInfo));
3353                         Jump(&JumpLoopHead);
3354                     }
3355                 }
3356                 Bind(&notShared);
3357                 GateRef accessor = LoadFromField(glue, *holder, handlerInfo);
3358                 result = CallSetterHelper(glue, receiver, accessor, *actualValue, callback);
3359                 Jump(&exit);
3360             }
3361         }
3362         Bind(&handlerNotInt);
3363         {
3364             BRANCH(TaggedIsTransitionHandler(glue, *handler), &handlerIsTransitionHandler, &handlerNotTransitionHandler);
3365             Bind(&handlerIsTransitionHandler);
3366             {
3367                 result = StoreWithTransition(glue, receiver, *actualValue, *handler, callback);
3368                 Jump(&exit);
3369             }
3370             Bind(&handlerNotTransitionHandler);
3371             {
3372                 BRANCH(TaggedIsTransWithProtoHandler(glue, *handler), &handlerIsTransWithProtoHandler,
3373                     &handlerNotTransWithProtoHandler);
3374                 Bind(&handlerIsTransWithProtoHandler);
3375                 {
3376                     GateRef cellValue = GetTransWithProtoHandlerProtoCell(glue, *handler);
3377                     BRANCH(GetHasChanged(cellValue), &cellHasChanged, &cellNotChanged);
3378                     Bind(&cellNotChanged);
3379                     {
3380                         result = StoreWithTransition(glue, receiver, *actualValue, *handler, callback, true);
3381                         Jump(&exit);
3382                     }
3383                 }
3384                 Bind(&handlerNotTransWithProtoHandler);
3385                 {
3386                     BRANCH(TaggedIsPrototypeHandler(glue, *handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
3387                     Bind(&handlerNotPrototypeHandler);
3388                     {
3389                         BRANCH(TaggedIsPropertyBox(glue, *handler), &handlerIsPropertyBox, &handlerNotPropertyBox);
3390                         Bind(&handlerIsPropertyBox);
3391                         StoreGlobal(glue, *actualValue, *handler);
3392                         Jump(&exit);
3393                     }
3394                 }
3395             }
3396         }
3397         Bind(&handlerIsPrototypeHandler);
3398         {
3399             GateRef cellValue = GetPrototypeHandlerProtoCell(glue, *handler);
3400             BRANCH(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
3401             Bind(&cellNotUndefined);
3402             BRANCH(TaggedIsNull(cellValue), &cellHasChanged, &cellNotNull);
3403             Bind(&cellNotNull);
3404             {
3405                 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
3406             }
3407             Bind(&loopEnd);
3408             {
3409                 holder = GetPrototypeHandlerHolder(glue, *handler);
3410                 handler = GetPrototypeHandlerHandlerInfo(glue, *handler);
3411                 Jump(&JumpLoopHead);
3412             }
3413         }
3414         Bind(&handlerNotPropertyBox);
3415         {
3416             BRANCH(TaggedIsStoreAOTHandler(glue, *handler), &handlerIsStoreAOTHandler, &handlerNotStoreAOTHandler);
3417             Bind(&handlerIsStoreAOTHandler);
3418             {
3419                 GateRef cellValue = GetStoreAOTHandlerProtoCell(glue, *handler);
3420                 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &aotCellNotChanged);
3421                 Bind(&aotCellNotChanged);
3422                 {
3423                     holder = GetStoreAOTHandlerHolder(glue, *handler);
3424                     handler = GetStoreAOTHandlerHandlerInfo(glue, *handler);
3425                     GateRef handlerInfo = GetInt64OfTInt(*handler);
3426                     BRANCH(IsField(handlerInfo), &aotHandlerInfoIsField, &aotHandlerInfoNotField);
3427                     Bind(&aotHandlerInfoIsField);
3428                     {
3429                         result = StoreField(glue, receiver, *actualValue, handlerInfo, callback);
3430                         Jump(&exit);
3431                     }
3432                     Bind(&aotHandlerInfoNotField);
3433                     {
3434                         GateRef accessor = LoadFromField(glue, *holder, handlerInfo);
3435                         result = CallSetterHelper(glue, receiver, accessor, *actualValue, callback);
3436                         Jump(&exit);
3437                     }
3438                 }
3439             }
3440             Bind(&handlerNotStoreAOTHandler);
3441             Jump(&exit);
3442         }
3443         Bind(&cellHasChanged);
3444         {
3445             result = Hole();
3446             Jump(&exit);
3447         }
3448         Bind(&JumpLoopHead);
3449         {
3450             LoopEndWithCheckSafePoint(&loopHead, env, glue);
3451         }
3452     }
3453     Bind(&exit);
3454     auto ret = *result;
3455     env->SubCfgExit();
3456     return ret;
3457 }
3458 
StoreField(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback)3459 GateRef StubBuilder::StoreField(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
3460     ProfileOperation callback)
3461 {
3462     auto env = GetEnvironment();
3463     Label entry(env);
3464     env->SubCfgEntry(&entry);
3465     ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handler, callback);
3466     Label exit(env);
3467     Label handlerIsInlinedProperty(env);
3468     Label handlerNotInlinedProperty(env);
3469     GateRef index = HandlerBaseGetOffset(handler);
3470     GateRef rep = HandlerBaseGetRep(handler);
3471     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3472     Label repChange(env);
3473     BRANCH(HandlerBaseIsInlinedProperty(handler), &handlerIsInlinedProperty, &handlerNotInlinedProperty);
3474     Bind(&handlerIsInlinedProperty);
3475     {
3476         GateRef toOffset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
3477         SetValueWithRep(glue, receiver, toOffset, value, rep, &repChange);
3478         Jump(&exit);
3479     }
3480     Bind(&handlerNotInlinedProperty);
3481     {
3482         GateRef array = GetPropertiesArray(glue, receiver);
3483         SetValueToTaggedArrayWithRep(glue, array, index, value, rep, &repChange);
3484         Jump(&exit);
3485     }
3486     Bind(&repChange);
3487     {
3488         result = Hole();
3489         Jump(&exit);
3490     }
3491 
3492     Bind(&exit);
3493     auto ret = *result;
3494     env->SubCfgExit();
3495     return ret;
3496 }
3497 
StoreWithTransition(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback,bool withPrototype)3498 GateRef StubBuilder::StoreWithTransition(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
3499                                          ProfileOperation callback, bool withPrototype)
3500 {
3501     auto env = GetEnvironment();
3502     Label entry(env);
3503     env->SubCfgEntry(&entry);
3504     Label exit(env);
3505 
3506     Label handlerInfoIsInlinedProps(env);
3507     Label handlerInfoNotInlinedProps(env);
3508     Label indexMoreCapacity(env);
3509     Label indexLessCapacity(env);
3510     Label capacityIsZero(env);
3511     Label capacityNotZero(env);
3512     Label isPrototype(env);
3513     Label notPrototype(env);
3514     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3515     GateRef newHClass;
3516     GateRef handlerInfo;
3517     if (withPrototype) {
3518         newHClass = GetTransWithProtoHClass(glue, handler);
3519         handlerInfo = GetInt64OfTInt(GetTransWithProtoHandlerInfo(glue, handler));
3520     } else {
3521         newHClass = GetTransitionHClass(glue, handler);
3522         handlerInfo = GetInt64OfTInt(GetTransitionHandlerInfo(glue, handler));
3523     }
3524 
3525     GateRef oldHClass = LoadHClass(glue, receiver);
3526     GateRef prototype = GetPrototypeFromHClass(glue, oldHClass);
3527     StorePrototype(glue, newHClass, prototype);
3528     BRANCH(IsPrototypeHClass(newHClass), &isPrototype, &notPrototype);
3529     Bind(&isPrototype);
3530     {
3531         SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, newHClass, GetProtoChangeDetails(glue, oldHClass));
3532         Jump(&notPrototype);
3533     }
3534     Bind(&notPrototype);
3535     // Because we currently only supports Fast ElementsKind
3536     GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
3537     RestoreElementsKindToGeneric(glue, newHClass);
3538     TransitionHClass(glue, receiver, newHClass);
3539     TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
3540     BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
3541     Bind(&handlerInfoNotInlinedProps);
3542     {
3543         ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handlerInfo, callback);
3544         Label repChange(env);
3545         GateRef array = GetPropertiesArray(glue, receiver);
3546         GateRef capacity = GetLengthOfTaggedArray(array);
3547         GateRef index = HandlerBaseGetOffset(handlerInfo);
3548         BRANCH(Int32GreaterThanOrEqual(index, capacity), &indexMoreCapacity, &indexLessCapacity);
3549         Bind(&indexMoreCapacity);
3550         {
3551             NewObjectStubBuilder newBuilder(this);
3552             BRANCH(Int32Equal(capacity, Int32(0)), &capacityIsZero, &capacityNotZero);
3553             Bind(&capacityIsZero);
3554             {
3555                 GateRef properties = newBuilder.NewTaggedArray(glue, Int32(JSObject::MIN_PROPERTIES_LENGTH));
3556                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3557                 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3558                 Jump(&exit);
3559             }
3560             Bind(&capacityNotZero);
3561             {
3562                 GateRef inlinedProperties = GetInlinedPropertiesFromHClass(newHClass);
3563                 GateRef maxNonInlinedFastPropsCapacity =
3564                                 Int32Sub(Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY), inlinedProperties);
3565                 GateRef newLen = ComputeNonInlinedFastPropsCapacity(glue, capacity, maxNonInlinedFastPropsCapacity);
3566                 GateRef properties = newBuilder.CopyArray(glue, array, capacity, newLen);
3567                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3568                 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3569                 Jump(&exit);
3570             }
3571         }
3572         Bind(&indexLessCapacity);
3573         {
3574             GateRef rep = HandlerBaseGetRep(handlerInfo);
3575             GateRef toIndex = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
3576             Label isCMCGC(env);
3577             Label notCMCGC(env);
3578             BRANCH_UNLIKELY(LoadPrimitive(
3579                 VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
3580                 &isCMCGC, &notCMCGC);
3581             Bind(&isCMCGC);
3582             {
3583                 GateRef offset = PtrAdd(toIndex, IntPtr(TaggedArray::DATA_OFFSET));
3584                 SetValueWithRep(glue, array, offset, value, rep, &repChange);
3585                 Jump(&exit);
3586             }
3587             Bind(&notCMCGC);
3588             {
3589                 GateRef base = PtrAdd(array, IntPtr(TaggedArray::DATA_OFFSET));
3590                 SetValueWithRep(glue, base, toIndex, value, rep, &repChange);
3591                 Jump(&exit);
3592             }
3593         }
3594         Bind(&repChange);
3595         {
3596             result = Hole();
3597             Jump(&exit);
3598         }
3599     }
3600     Bind(&handlerInfoIsInlinedProps);
3601     {
3602         result = StoreField(glue, receiver, value, handlerInfo, callback);
3603         Jump(&exit);
3604     }
3605     Bind(&exit);
3606     auto ret = *result;
3607     env->SubCfgExit();
3608     return ret;
3609 }
3610 
StoreGlobal(GateRef glue,GateRef value,GateRef cell)3611 GateRef StubBuilder::StoreGlobal(GateRef glue, GateRef value, GateRef cell)
3612 {
3613     auto env = GetEnvironment();
3614     Label entry(env);
3615     env->SubCfgEntry(&entry);
3616     Label exit(env);
3617     Label cellNotInvalid(env);
3618     Label cellIsNotAccessorData(env);
3619     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3620     BRANCH(IsInvalidPropertyBox(glue, cell), &exit, &cellNotInvalid);
3621     Bind(&cellNotInvalid);
3622     {
3623         BRANCH(IsAccessorPropertyBox(glue, cell), &exit, &cellIsNotAccessorData);
3624         Bind(&cellIsNotAccessorData);
3625         {
3626             Store(VariableType::JS_ANY(), glue, cell, IntPtr(PropertyBox::VALUE_OFFSET), value);
3627             result = Undefined();
3628             Jump(&exit);
3629         }
3630     }
3631     Bind(&exit);
3632     auto ret = *result;
3633     env->SubCfgExit();
3634     return ret;
3635 }
3636 
3637 template<typename DictionaryT>
GetAttributesFromDictionary(GateRef glue,GateRef elements,GateRef entry)3638 GateRef StubBuilder::GetAttributesFromDictionary(GateRef glue, GateRef elements, GateRef entry)
3639 {
3640     GateRef arrayIndex =
3641     Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3642              Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3643     GateRef attributesIndex =
3644         Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_DETAILS_INDEX));
3645     auto attrValue = GetValueFromTaggedArray(glue, elements, attributesIndex);
3646     return GetInt64OfTInt(attrValue);
3647 }
3648 
3649 template<typename DictionaryT>
GetValueFromDictionary(GateRef glue,GateRef elements,GateRef entry)3650 GateRef StubBuilder::GetValueFromDictionary(GateRef glue, GateRef elements, GateRef entry)
3651 {
3652     GateRef arrayIndex =
3653         Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3654                  Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3655     GateRef valueIndex =
3656         Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3657     return GetValueFromTaggedArray(glue, elements, valueIndex);
3658 }
3659 
3660 template<typename DictionaryT>
GetKeyFromDictionary(GateRef glue,GateRef elements,GateRef entry)3661 GateRef StubBuilder::GetKeyFromDictionary(GateRef glue, GateRef elements, GateRef entry)
3662 {
3663     auto env = GetEnvironment();
3664     Label subentry(env);
3665     env->SubCfgEntry(&subentry);
3666     Label exit(env);
3667     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3668     Label ltZero(env);
3669     Label notLtZero(env);
3670     Label gtLength(env);
3671     Label notGtLength(env);
3672     GateRef dictionaryLength =
3673         LoadPrimitive(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
3674     GateRef arrayIndex =
3675         Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3676                  Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3677     BRANCH(Int32LessThan(arrayIndex, Int32(0)), &ltZero, &notLtZero);
3678     Bind(&ltZero);
3679     Jump(&exit);
3680     Bind(&notLtZero);
3681     BRANCH(Int32GreaterThan(arrayIndex, dictionaryLength), &gtLength, &notGtLength);
3682     Bind(&gtLength);
3683     Jump(&exit);
3684     Bind(&notGtLength);
3685     result = GetValueFromTaggedArray(glue, elements, arrayIndex);
3686     Jump(&exit);
3687     Bind(&exit);
3688     auto ret = *result;
3689     env->SubCfgExit();
3690     return ret;
3691 }
3692 
UpdateValueAndAttributes(GateRef glue,GateRef elements,GateRef index,GateRef value,GateRef attr)3693 inline void StubBuilder::UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index,
3694                                                   GateRef value, GateRef attr)
3695 {
3696     GateRef arrayIndex =
3697         Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
3698                  Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
3699     GateRef valueIndex =
3700         Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
3701     GateRef attributesIndex =
3702         Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_DETAILS_INDEX));
3703     SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3704     GateRef attroffset =
3705         PtrMul(ZExtInt32ToPtr(attributesIndex), IntPtr(JSTaggedValue::TaggedTypeSize()));
3706     GateRef dataOffset = PtrAdd(attroffset, IntPtr(TaggedArray::DATA_OFFSET));
3707     Store(VariableType::INT64(), glue, elements, dataOffset, Int64ToTaggedInt(attr));
3708 }
3709 
3710 template<typename DictionaryT>
UpdateValueInDict(GateRef glue,GateRef elements,GateRef index,GateRef value)3711 inline void StubBuilder::UpdateValueInDict(GateRef glue, GateRef elements, GateRef index, GateRef value)
3712 {
3713     GateRef arrayIndex = Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3714         Int32Mul(index, Int32(DictionaryT::ENTRY_SIZE)));
3715     GateRef valueIndex = Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3716     SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3717 }
3718 
GetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,ProfileOperation callback,GateRef hir)3719 GateRef StubBuilder::GetPropertyByIndex(GateRef glue, GateRef receiver,
3720                                         GateRef index, ProfileOperation callback, GateRef hir)
3721 {
3722     auto env = GetEnvironment();
3723     Label entry(env);
3724     env->SubCfgEntry(&entry);
3725     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3726     DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
3727     Label exit(env);
3728     Label loopHead(env);
3729     Label loopEnd(env);
3730     Label loopExit(env);
3731     Label afterLoop(env);
3732     Jump(&loopHead);
3733     LoopBegin(&loopHead);
3734     {
3735         GateRef hclass = LoadHClass(glue, *holder);
3736         GateRef jsType = GetObjectType(hclass);
3737         Label isSpecialIndexed(env);
3738         Label notSpecialIndexed(env);
3739         BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndexed, &notSpecialIndexed);
3740         Bind(&isSpecialIndexed);
3741         {
3742             // TypeArray
3743             Label isFastTypeArray(env);
3744             Label notFastTypeArray(env);
3745             Label notTypedArrayProto(env);
3746             BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, &notTypedArrayProto);
3747             Bind(&notTypedArrayProto);
3748             BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
3749             Bind(&isFastTypeArray);
3750             {
3751                 BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this, GetCurrentGlobalEnv());
3752                 result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, *holder, index, jsType);
3753                 Jump(&exit);
3754             }
3755             Bind(&notFastTypeArray);
3756 
3757             Label isSpecialContainer(env);
3758             Label notSpecialContainer(env);
3759             // Add SpecialContainer
3760             BRANCH(IsArrayListOrVector(jsType), &isSpecialContainer, &notSpecialContainer);
3761             Bind(&isSpecialContainer);
3762             {
3763                 result = JSAPIContainerGet(glue, *holder, index);
3764                 Jump(&exit);
3765             }
3766             Bind(&notSpecialContainer);
3767 
3768             Label isString(env);
3769             Label notString(env);
3770             Label getSubString(env);
3771             BRANCH(TaggedIsString(glue, *holder), &isString, &notString);
3772             Bind(&isString);
3773             {
3774                 GateRef length = GetLengthFromString(*holder);
3775                 BRANCH(Int32LessThan(index, length), &getSubString, &notString);
3776                 Bind(&getSubString);
3777                 Label flattenFastPath(env);
3778                 BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
3779                 FlatStringStubBuilder thisFlat(this);
3780                 thisFlat.FlattenString(glue, *holder, &flattenFastPath);
3781                 Bind(&flattenFastPath);
3782                 StringInfoGateRef stringInfoGate(&thisFlat);
3783                 result = stringBuilder.FastSubString(glue, *holder, index, Int32(1), stringInfoGate);
3784                 Jump(&exit);
3785             }
3786             Bind(&notString);
3787             {
3788                 result = Hole();
3789                 Jump(&exit);
3790             }
3791         }
3792         Bind(&notSpecialIndexed);
3793         {
3794             GateRef elements = GetElementsArray(glue, *holder);
3795             Label isDictionaryElement(env);
3796             Label notDictionaryElement(env);
3797             BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, &notDictionaryElement);
3798             Bind(&notDictionaryElement);
3799             {
3800                 Label lessThanLength(env);
3801                 Label notLessThanLength(env);
3802                 BRANCH(Int32UnsignedLessThan(index, GetLengthOfTaggedArray(elements)),
3803                        &lessThanLength, &notLessThanLength);
3804                 Bind(&lessThanLength);
3805                 {
3806                     DEFVARIABLE(value, VariableType::JS_ANY(), Hole());
3807                     Label notHole(env);
3808                     Label isHole(env);
3809                     value = GetTaggedValueWithElementsKind(glue, *holder, index);
3810                     BRANCH(TaggedIsNotHole(*value), &notHole, &isHole);
3811                     Bind(&notHole);
3812                     {
3813                         result = *value;
3814                         Jump(&exit);
3815                     }
3816                     Bind(&isHole);
3817                     {
3818                         Jump(&loopExit);
3819                     }
3820                 }
3821                 Bind(&notLessThanLength);
3822                 {
3823                     Jump(&loopExit);
3824                 }
3825             }
3826             Bind(&isDictionaryElement);
3827             {
3828                 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
3829                 Label notNegtiveOne(env);
3830                 Label negtiveOne(env);
3831                 BRANCH(Int32NotEqual(entryA, Int32(-1)), &notNegtiveOne, &negtiveOne);
3832                 Bind(&notNegtiveOne);
3833                 {
3834                     GateRef attr = GetAttributesFromDictionary<NumberDictionary>(glue, elements, entryA);
3835                     GateRef value = GetValueFromDictionary<NumberDictionary>(glue, elements, entryA);
3836                     Label isAccessor(env);
3837                     Label notAccessor(env);
3838                     BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
3839                     Bind(&isAccessor);
3840                     {
3841                         result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
3842                         Jump(&exit);
3843                     }
3844                     Bind(&notAccessor);
3845                     {
3846                         result = value;
3847                         Jump(&exit);
3848                     }
3849                 }
3850                 Bind(&negtiveOne);
3851                 Jump(&loopExit);
3852             }
3853             Bind(&loopExit);
3854             {
3855                 holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
3856                 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3857             }
3858         }
3859         Bind(&loopEnd);
3860         LoopEndWithCheckSafePoint(&loopHead, env, glue);
3861         Bind(&afterLoop);
3862         {
3863             result = Undefined();
3864             Jump(&exit);
3865         }
3866     }
3867     Bind(&exit);
3868     auto ret = *result;
3869     env->SubCfgExit();
3870     return ret;
3871 }
3872 
GetPropertyByValue(GateRef glue,GateRef target,GateRef propKey,GateRef receiver,ProfileOperation callback)3873 GateRef StubBuilder::GetPropertyByValue(
3874     GateRef glue, GateRef target, GateRef propKey, GateRef receiver, ProfileOperation callback)
3875 {
3876     auto env = GetEnvironment();
3877     Label entry(env);
3878     env->SubCfgEntry(&entry);
3879     DEFVARIABLE(key, VariableType::JS_ANY(), propKey);
3880     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3881     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
3882     Label isPropertyKey(env);
3883     Label exit(env);
3884 
3885     BRANCH(TaggedIsPropertyKey(glue, *key), &isPropertyKey, &exit);
3886 
3887     Bind(&isPropertyKey);
3888     {
3889         GateRef index64 = TryToElementsIndex(glue, *key);
3890         Label validIndex(env);
3891         Label notValidIndex(env);
3892         Label greaterThanInt32Max(env);
3893         Label notGreaterThanInt32Max(env);
3894         BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
3895         Bind(&greaterThanInt32Max);
3896         {
3897             Jump(&exit);
3898         }
3899         Bind(&notGreaterThanInt32Max);
3900         GateRef index = TruncInt64ToInt32(index64);
3901         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
3902         Bind(&validIndex);
3903         {
3904             result = GetPropertyByIndex(glue, target, index, callback);
3905             Jump(&exit);
3906         }
3907         Bind(&notValidIndex);
3908         {
3909             Label notNumber1(env);
3910             Label getByName(env);
3911             BRANCH(TaggedIsNumber(*key), &exit, &notNumber1);
3912             Bind(&notNumber1);
3913             {
3914                 Label isString(env);
3915                 Label notString(env);
3916                 Label isInternalString(env);
3917                 Label notIntenalString(env);
3918                 BRANCH(TaggedIsString(glue, *key), &isString, &notString);
3919                 Bind(&isString);
3920                 {
3921                     BRANCH(IsInternalString(*key), &isInternalString, &notIntenalString);
3922                     Bind(&isInternalString);
3923                     Jump(&getByName);
3924                     Bind(&notIntenalString);
3925                     {
3926                         Label notFind(env);
3927                         Label find(env);
3928                         // if key can't find in stringtabele, key is not propertyname for a object
3929                         GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *key });
3930                         BRANCH(TaggedIsHole(res), &notFind, &find);
3931                         Bind(&notFind);
3932                         {
3933                             isInternal = False();
3934                             Jump(&getByName);
3935                         }
3936                         Bind(&find);
3937                         {
3938                             key = res;
3939                             Jump(&getByName);
3940                         }
3941                     }
3942                 }
3943                 Bind(&notString);
3944                 {
3945                     Jump(&getByName);
3946                 }
3947             }
3948             Bind(&getByName);
3949             {
3950                 result = GetPropertyByName(glue, target, *key, receiver, callback, *isInternal, true);
3951                 Jump(&exit);
3952             }
3953         }
3954     }
3955     Bind(&exit);
3956     auto ret = *result;
3957     env->SubCfgExit();
3958     return ret;
3959 }
3960 
GetPropertyByName(GateRef glue,GateRef target,GateRef propKey,GateRef receiver,ProfileOperation callback,GateRef isInternal,bool canUseIsInternal,GateRef hir)3961 GateRef StubBuilder::GetPropertyByName(GateRef glue,
3962                                        GateRef target,
3963                                        GateRef propKey,
3964                                        GateRef receiver,
3965                                        ProfileOperation callback,
3966                                        GateRef isInternal,
3967                                        bool canUseIsInternal,
3968                                        GateRef hir)
3969 {
3970     auto env = GetEnvironment();
3971     Label entry(env);
3972     env->SubCfgEntry(&entry);
3973     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3974     DEFVARIABLE(holder, VariableType::JS_ANY(), target);
3975     Label exit(env);
3976     Label loopHead(env);
3977     Label loopEnd(env);
3978     Label loopExit(env);
3979     Label afterLoop(env);
3980     Label findProperty(env);
3981     Jump(&loopHead);
3982     LoopBegin(&loopHead);
3983     {
3984         GateRef hclass = LoadHClass(glue, *holder);
3985         GateRef jsType = GetObjectType(hclass);
3986         Label isSIndexObj(env);
3987         Label notSIndexObj(env);
3988         BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, &notSIndexObj);
3989         Bind(&isSIndexObj);
3990         {
3991             // TypeArray
3992             Label isFastTypeArray(env);
3993             Label notFastTypeArray(env);
3994             BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
3995             Bind(&isFastTypeArray);
3996             {
3997                 result = GetTypeArrayPropertyByName(glue, target, *holder, propKey, jsType);
3998                 Label isNull(env);
3999                 Label notNull(env);
4000                 BRANCH(TaggedIsNull(*result), &isNull, &notNull);
4001                 Bind(&isNull);
4002                 {
4003                     result = Hole();
4004                     Jump(&exit);
4005                 }
4006                 Bind(&notNull);
4007                 BRANCH(TaggedIsHole(*result), &notSIndexObj, &exit);
4008             }
4009             Bind(&notFastTypeArray);
4010 
4011             Label isString(env);
4012             Label notString(env);
4013             Label notJsPrimitiveRef(env);
4014             auto holderValue = *holder;
4015             BRANCH(LogicAndBuilder(env).And(TaggedIsString(glue, holderValue)).And(TaggedIsString(glue, propKey))
4016                 .Done(), &isString, &notString);
4017             Bind(&isString);
4018             {
4019                 Label getStringLength(env);
4020                 Label getStringPrototype(env);
4021                 GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
4022                                                               ConstantIndex::LENGTH_STRING_INDEX);
4023                 BRANCH(FastStringEqual(glue, propKey, lengthString), &getStringLength, &getStringPrototype);
4024                 Bind(&getStringLength);
4025                 {
4026                     result = IntToTaggedPtr(GetLengthFromString(*holder));
4027                     Jump(&exit);
4028                 }
4029                 Bind(&getStringPrototype);
4030                 {
4031                     GateRef globalEnv = GetCurrentGlobalEnv();
4032                     GateRef stringPrototype = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
4033                                                                 GlobalEnv::STRING_PROTOTYPE_INDEX);
4034                     holder = stringPrototype;
4035                     BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4036                 }
4037             }
4038             Bind(&notString);
4039             BRANCH(IsJSPrimitiveRef(glue, *holder), &notSIndexObj, &notJsPrimitiveRef);
4040             Bind(&notJsPrimitiveRef);  // not string prototype etc.
4041             {
4042 #if ENABLE_NEXT_OPTIMIZATION
4043                 Label isJsProxy(env);
4044                 Label notJsProxy(env);
4045                 BRANCH(IsJSProxy(jsType), &isJsProxy, &notJsProxy);
4046                 Bind(&isJsProxy);
4047                 {
4048                     result = CallCommonStub(glue, CommonStubCSigns::JSProxyGetProperty,
4049                                             {glue, *holder, propKey, target, GetCurrentGlobalEnv()}, hir);
4050                     Label isPendingException(env);
4051                     Label noPendingException(env);
4052                     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
4053                     Bind(&isPendingException);
4054                     {
4055                         result = Exception();
4056                         Jump(&exit);
4057                     }
4058                     Bind(&noPendingException);
4059                     Jump(&exit);
4060                 }
4061                 Bind(&notJsProxy);
4062                 {
4063                     result = Hole();
4064                     Jump(&exit);
4065                 }
4066 #else
4067                 result = Hole();
4068                 Jump(&exit);
4069 #endif
4070             }
4071         }
4072         Bind(&notSIndexObj);
4073         {
4074             if (canUseIsInternal) {
4075                 BRANCH(isInternal, &findProperty, &loopExit);
4076             } else {
4077                 Jump(&findProperty);
4078             }
4079             Label isDicMode(env);
4080             Label notDicMode(env);
4081             Bind(&findProperty);
4082             BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
4083             Bind(&notDicMode);
4084             {
4085                 GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
4086                 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4087                 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
4088                 GateRef entryA = FindElementWithCache(glue, layOutInfo, hclass, propKey, propsNum, hir);
4089                 Label hasEntry(env);
4090                 Label noEntry(env);
4091                 // if branch condition : entry != -1
4092                 BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, &noEntry);
4093                 Bind(&hasEntry);
4094                 {
4095                     // PropertyAttributes attr(layoutInfo->GetAttr(entry))
4096                     GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entryA);
4097                     GateRef value = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
4098                     Label isAccessor(env);
4099                     Label notAccessor(env);
4100                     BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
4101                     Bind(&isAccessor);
4102                     {
4103                         // The getter may involve nested calls, so it is better to end (or return) early
4104                         EndTraceLoad(glue);
4105                         if (receiver == Circuit::NullGate()) {
4106                             result = CallGetterHelper(glue, target, *holder, value, callback, hir);
4107                         } else {
4108                             result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
4109                         }
4110                         StartTraceLoadGetter(glue);
4111                         Jump(&exit);
4112                     }
4113                     Bind(&notAccessor);
4114                     {
4115                         Label notHole(env);
4116                         BRANCH(TaggedIsHole(value), &noEntry, &notHole);
4117                         Bind(&notHole);
4118                         {
4119                             result = value;
4120                             Jump(&exit);
4121                         }
4122                     }
4123                 }
4124                 Bind(&noEntry);
4125                 {
4126                     Jump(&loopExit);
4127                 }
4128             }
4129             Bind(&isDicMode);
4130             {
4131                 GateRef array = GetPropertiesArray(glue, *holder);
4132                 // int entry = dict->FindEntry(key)
4133                 GateRef entryB = FindEntryFromHashTable<NameDictionary>(glue, array, propKey, hir);
4134                 Label notNegtiveOne(env);
4135                 Label negtiveOne(env);
4136                 // if branch condition : entry != -1
4137                 BRANCH(Int32NotEqual(entryB, Int32(-1)), &notNegtiveOne, &negtiveOne);
4138                 Bind(&notNegtiveOne);
4139                 {
4140                     // auto value = dict->GetValue(entry)
4141                     GateRef attr = GetAttributesFromDictionary<NameDictionary>(glue, array, entryB);
4142                     // auto attr = dict->GetAttributes(entry)
4143                     GateRef value = GetValueFromDictionary<NameDictionary>(glue, array, entryB);
4144                     Label isAccessor1(env);
4145                     Label notAccessor1(env);
4146                     BRANCH(IsAccessor(attr), &isAccessor1, &notAccessor1);
4147                     Bind(&isAccessor1);
4148                     {
4149                         // The getter may involve nested calls, so it is better to end (or return) early
4150                         EndTraceLoad(glue);
4151                         if (receiver == Circuit::NullGate()) {
4152                             result = CallGetterHelper(glue, target, *holder, value, callback, hir);
4153                         } else {
4154                             result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
4155                         }
4156                         StartTraceLoadGetter(glue);
4157                         Jump(&exit);
4158                     }
4159                     Bind(&notAccessor1);
4160                     {
4161                         result = value;
4162                         Jump(&exit);
4163                     }
4164                 }
4165                 Bind(&negtiveOne);
4166                 Jump(&loopExit);
4167             }
4168             Bind(&loopExit);
4169             {
4170                 holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
4171                 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4172             }
4173         }
4174         Bind(&loopEnd);
4175         LoopEndWithCheckSafePoint(&loopHead, env, glue);
4176         Bind(&afterLoop);
4177         {
4178             result = Undefined();
4179             Jump(&exit);
4180         }
4181     }
4182     Bind(&exit);
4183     auto ret = *result;
4184     env->SubCfgExit();
4185     return ret;
4186 }
4187 
CallGetterIfAccessor(GateRef glue,GateRef holder,Variable * value,Variable * attr,Label * isFoundData,Label * isFoundAccessor)4188 void StubBuilder::CallGetterIfAccessor(GateRef glue, GateRef holder, Variable *value, Variable *attr,
4189                                        Label *isFoundData, Label *isFoundAccessor)
4190 {
4191     auto env = GetEnvironment();
4192     Label isAccessor(env);
4193     GateRef attrVal = attr->ReadVariable();
4194     GateRef valueVal = value->ReadVariable();
4195     BRANCH(IsAccessor(attrVal), &isAccessor, isFoundData);
4196     Bind(&isAccessor);
4197     {
4198         Label isAccessorInternal(env);
4199         BRANCH_UNLIKELY(IsAccessorInternal(glue, valueVal), &isAccessorInternal, isFoundAccessor);
4200         Bind(&isAccessorInternal);
4201         {
4202             value->WriteVariable(CallGetterHelper(glue, holder, holder, valueVal, ProfileOperation()));
4203             Jump(isFoundData);
4204         }
4205     }
4206 }
4207 
TryGetOwnProperty(GateRef glue,GateRef holder,GateRef key,GateRef hir,Variable * rValue,Variable * rAttr,Label * isFoundData,Label * isFoundAccessor,Label * notFound,Label * callRuntime)4208 void StubBuilder::TryGetOwnProperty(GateRef glue, GateRef holder, GateRef key, GateRef hir,
4209                                     Variable *rValue, Variable *rAttr,
4210                                     Label *isFoundData, Label *isFoundAccessor, Label *notFound, Label *callRuntime)
4211 {
4212     auto env = GetEnvironment();
4213     Label exit(env);
4214     Label findProperty(env);
4215     Label found(env);
4216     GateRef hclass = LoadHClass(glue, holder);
4217     GateRef jsType = GetObjectType(hclass);
4218     Label isSIndexObj(env);
4219     Label notSIndexObj(env);
4220     BRANCH(IsSpecialIndexedObj(jsType), callRuntime, &notSIndexObj);
4221     Bind(&notSIndexObj);
4222     {
4223         Label isDicMode(env);
4224         Label notDicMode(env);
4225         BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
4226         Bind(&notDicMode);
4227         {
4228             GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
4229             GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4230             // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
4231             GateRef entryA = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum, hir);
4232             Label hasEntry(env);
4233             // if branch condition : entry != -1
4234             BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, notFound);
4235             Bind(&hasEntry);
4236             {
4237                 // PropertyAttributes attr(layoutInfo->GetAttr(entry))
4238                 GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entryA);
4239                 GateRef value = JSObjectGetPropertyWithRep(glue, holder, hclass, attr);
4240                 Label notHole(env);
4241                 BRANCH(TaggedIsHole(value), notFound, &notHole);
4242                 Bind(&notHole);
4243                 {
4244                     rValue->WriteVariable(value);
4245                     rAttr->WriteVariable(attr);
4246                     Jump(&found);
4247                 }
4248             }
4249         }
4250         Bind(&isDicMode);
4251         {
4252             GateRef array = GetPropertiesArray(glue, holder);
4253             // int entry = dict->FindEntry(key)
4254             GateRef entryB = FindEntryFromHashTable<NameDictionary>(glue, array, key, hir);
4255             Label notNegtiveOne(env);
4256             // if branch condition : entry != -1
4257             BRANCH(Int32NotEqual(entryB, Int32(-1)), &notNegtiveOne, notFound);
4258             Bind(&notNegtiveOne);
4259             {
4260                 // auto value = dict->GetValue(entry)
4261                 rAttr->WriteVariable(GetAttributesFromDictionary<NameDictionary>(glue, array, entryB));
4262                 // auto attr = dict->GetAttributes(entry)
4263                 rValue->WriteVariable(GetValueFromDictionary<NameDictionary>(glue, array, entryB));
4264                 Jump(&found);
4265             }
4266         }
4267         Bind(&found);
4268         {
4269             CallGetterIfAccessor(glue, holder, rValue, rAttr, isFoundData, isFoundAccessor);
4270         }
4271     }
4272 }
4273 
CopyAllHClass(GateRef glue,GateRef dstHClass,GateRef srcHClass)4274 void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHClass)
4275 {
4276     auto env = GetEnvironment();
4277     Label entry(env);
4278     Label isAOT(env);
4279     Label isNotAOT(env);
4280     env->SubCfgEntry(&entry);
4281     auto proto = GetPrototypeFromHClass(glue, srcHClass);
4282     SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto);
4283     GateRef bitField = GetBitFieldFromHClass(srcHClass);
4284     GateRef afterSetStableBitField = SetIsStableToBitField(bitField, Int32(1));
4285     SetBitFieldToHClass(glue, dstHClass, afterSetStableBitField);
4286     SetIsAllTaggedProp(glue, dstHClass, GetIsAllTaggedPropFromHClass(srcHClass));
4287     SetNumberOfPropsToHClass(glue, dstHClass, GetNumberOfPropsFromHClass(srcHClass));
4288     SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
4289     SetParentToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
4290     SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, dstHClass, Null());
4291     SetEnumCacheToHClass(VariableType::INT64(), glue, dstHClass, Null());
4292     SetDependentInfosToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
4293     SetLayoutToHClass(VariableType::JS_POINTER(),
4294                       glue,
4295                       dstHClass,
4296                       GetLayoutFromHClass(glue, srcHClass),
4297                       MemoryAttribute::NeedBarrierAndAtomic());
4298     BRANCH(IsAOTHClass(srcHClass), &isAOT, &isNotAOT);
4299     Bind(&isAOT);
4300     {
4301         SetIsAOT(glue, dstHClass, False());
4302         Jump(&isNotAOT);
4303     }
4304     Bind(&isNotAOT);
4305     env->SubCfgExit();
4306     return;
4307 }
4308 
TransitionForRepChange(GateRef glue,GateRef receiver,GateRef key,GateRef attr)4309 void StubBuilder::TransitionForRepChange(GateRef glue, GateRef receiver, GateRef key, GateRef attr)
4310 {
4311     auto env = GetEnvironment();
4312     Label subEntry(env);
4313     env->SubCfgEntry(&subEntry);
4314     GateRef hclass = LoadHClass(glue, receiver);
4315     GateRef type = GetObjectType(hclass);
4316     GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
4317                             Int32(JSTaggedValue::TaggedTypeSize()));
4318     GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
4319     GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
4320         { IntToTaggedInt(size), IntToTaggedInt(type),
4321           IntToTaggedInt(inlineProps) });
4322     CopyAllHClass(glue, newJshclass, hclass);
4323     CallRuntime(glue, RTSTUB_ID(CopyAndUpdateObjLayout),
4324                 { hclass, newJshclass, key, Int64ToTaggedInt(attr) });
4325 #if ECMASCRIPT_ENABLE_IC
4326     NotifyHClassChanged(glue, hclass, newJshclass);
4327 #endif
4328     // Because we currently only supports Fast ElementsKind
4329     GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
4330     RestoreElementsKindToGeneric(glue, newJshclass);
4331     TransitionHClass(glue, receiver, newJshclass);
4332     TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
4333     env->SubCfgExit();
4334 }
4335 
TransitToElementsKind(GateRef glue,GateRef receiver,GateRef value,GateRef kind)4336 void StubBuilder::TransitToElementsKind(GateRef glue, GateRef receiver, GateRef value, GateRef kind)
4337 {
4338     auto env = GetEnvironment();
4339     Label subEntry(env);
4340     env->SubCfgEntry(&subEntry);
4341     Label exit(env);
4342 
4343     GateRef hclass = LoadHClass(glue, receiver);
4344     GateRef elementsKind = GetElementsKindFromHClass(hclass);
4345 
4346     Label isNoneDefault(env);
4347     BRANCH(Int32Equal(elementsKind, Int32(Elements::ToUint(ElementsKind::GENERIC))), &exit, &isNoneDefault);
4348     Bind(&isNoneDefault);
4349     {
4350         GateRef newKind = TaggedToElementKind(glue, value);
4351         newKind = Int32Or(newKind, kind);
4352         newKind = Int32Or(newKind, elementsKind);
4353         Label change(env);
4354         BRANCH(Int32Equal(elementsKind, newKind), &exit, &change);
4355         Bind(&change);
4356         {
4357             CallRuntime(glue, RTSTUB_ID(UpdateHClassForElementsKind), { receiver, newKind });
4358             MigrateArrayWithKind(glue, receiver, elementsKind, newKind);
4359             Jump(&exit);
4360         }
4361     }
4362 
4363     Bind(&exit);
4364     env->SubCfgExit();
4365 }
4366 
TryMigrateToGenericKindForJSObject(GateRef glue,GateRef receiver,GateRef oldKind)4367 void StubBuilder::TryMigrateToGenericKindForJSObject(GateRef glue, GateRef receiver, GateRef oldKind)
4368 {
4369     auto env = GetEnvironment();
4370     Label subEntry(env);
4371     env->SubCfgEntry(&subEntry);
4372     Label exit(env);
4373 
4374     Label isJSArray(env);
4375     BRANCH(TaggedIsJSArray(glue, receiver), &isJSArray, &exit);
4376     Bind(&isJSArray);
4377     {
4378         Label elementsIsMutantTaggedArray(env);
4379         GateRef elements = GetElementsArray(glue, receiver);
4380         BRANCH(IsMutantTaggedArray(glue, elements), &elementsIsMutantTaggedArray, &exit);
4381         Bind(&elementsIsMutantTaggedArray);
4382         {
4383             MigrateArrayWithKind(glue, receiver, oldKind, Int32(Elements::ToUint(ElementsKind::GENERIC)));
4384             Jump(&exit);
4385         }
4386     }
4387 
4388     Bind(&exit);
4389     env->SubCfgExit();
4390 }
4391 
AddElementInternal(GateRef glue,GateRef receiver,GateRef index,GateRef value,GateRef attr)4392 GateRef StubBuilder::AddElementInternal(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef attr)
4393 {
4394     auto env = GetEnvironment();
4395     Label subEntry(env);
4396     env->SubCfgEntry(&subEntry);
4397     Label exit(env);
4398     DEFVARIABLE(kind, VariableType::INT32(), Int32(Elements::ToUint(ElementsKind::NONE)));
4399     DEFVARIABLE(result, VariableType::BOOL(), False());
4400     Label isArray(env);
4401     Label notArray(env);
4402     BRANCH(IsJsArray(glue, receiver), &isArray, &notArray);
4403     Bind(&isArray);
4404     {
4405         GateRef oldLen = GetArrayLength(receiver);
4406         Label indexGreaterOrEq(env);
4407         BRANCH(Int32GreaterThanOrEqual(index, oldLen), &indexGreaterOrEq, &notArray);
4408         Bind(&indexGreaterOrEq);
4409         {
4410             Label isArrLenWritable(env);
4411             Label notArrLenWritable(env);
4412             BRANCH(IsArrayLengthWritable(glue, receiver), &isArrLenWritable, &notArrLenWritable);
4413             Bind(&isArrLenWritable);
4414             {
4415                 SetArrayLength(glue, receiver, Int32Add(index, Int32(1)));
4416                 Label indexGreater(env);
4417                 BRANCH(Int32GreaterThan(index, oldLen), &indexGreater, &notArray);
4418                 Bind(&indexGreater);
4419                 kind = Int32(Elements::ToUint(ElementsKind::HOLE));
4420                 Jump(&notArray);
4421             }
4422             Bind(&notArrLenWritable);
4423             result = False();
4424             Jump(&exit);
4425         }
4426     }
4427     Bind(&notArray);
4428     {
4429         NotifyArrayPrototypeChangedGuardians(glue, receiver);
4430         GateRef hclass = LoadHClass(glue, receiver);
4431         GateRef elements = GetElementsArray(glue, receiver);
4432         Label isDicMode(env);
4433         Label notDicMode(env);
4434         BRANCH(IsDictionaryElement(hclass), &isDicMode, &notDicMode);
4435         Bind(&isDicMode);
4436         {
4437             GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
4438                 { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedFalse() });
4439             SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
4440             result = True();
4441             Jump(&exit);
4442         }
4443         Bind(&notDicMode);
4444         {
4445             GateRef capacity = GetLengthOfTaggedArray(elements);
4446             GateRef notDefault = BoolNot(IsDefaultAttribute(attr));
4447             Label indexGreaterLen(env);
4448             Label notGreaterLen(env);
4449             BRANCH(BitOr(notDefault, Int32GreaterThanOrEqual(index, capacity)), &indexGreaterLen, &notGreaterLen);
4450             Bind(&indexGreaterLen);
4451             {
4452                 Label isTransToDict(env);
4453                 Label notTransToDict(env);
4454                 BRANCH(LogicOrBuilder(env).Or(notDefault).Or(ShouldTransToDict(capacity, index)).Done(),
4455                     &isTransToDict, &notTransToDict);
4456                 Bind(&isTransToDict);
4457                 {
4458                     GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
4459                         { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedTrue() });
4460                     Label isPendingException(env);
4461                     Label noPendingException(env);
4462                     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
4463                     Bind(&isPendingException);
4464                     {
4465                         result = False();
4466                         Jump(&exit);
4467                     }
4468                     Bind(&noPendingException);
4469                     SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
4470                     result = True();
4471                     Jump(&exit);
4472                 }
4473                 Bind(&notTransToDict);
4474                 {
4475                     GrowElementsCapacity(glue, receiver, Int32Add(index, Int32(1)));
4476                     SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
4477                     result = True();
4478                     Jump(&exit);
4479                 }
4480             }
4481             Bind(&notGreaterLen);
4482             {
4483                 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
4484                 result = True();
4485                 Jump(&exit);
4486             }
4487         }
4488     }
4489     Bind(&exit);
4490     auto ret = *result;
4491     env->SubCfgExit();
4492     return ret;
4493 }
4494 
GrowElementsCapacity(GateRef glue,GateRef receiver,GateRef capacity)4495 GateRef StubBuilder::GrowElementsCapacity(GateRef glue, GateRef receiver, GateRef capacity)
4496 {
4497     auto env = GetEnvironment();
4498     Label subEntry(env);
4499     env->SubCfgEntry(&subEntry);
4500     DEFVARIABLE(newElements, VariableType::JS_ANY(), Hole());
4501     NewObjectStubBuilder newBuilder(this);
4502     GateRef newCapacity = ComputeElementCapacity(capacity);
4503     GateRef elements = GetElementsArray(glue, receiver);
4504     newElements = newBuilder.ExtendArrayWithOptimizationCheck(glue, elements, newCapacity);
4505     SetElementsArray(VariableType::JS_POINTER(), glue, receiver, *newElements);
4506     auto ret = *newElements;
4507     env->SubCfgExit();
4508     return ret;
4509 }
4510 
ShouldTransToDict(GateRef capacity,GateRef index)4511 GateRef StubBuilder::ShouldTransToDict(GateRef capacity, GateRef index)
4512 {
4513     auto env = GetEnvironment();
4514     Label subEntry(env);
4515     env->SubCfgEntry(&subEntry);
4516     Label exit(env);
4517     DEFVARIABLE(result, VariableType::BOOL(), True());
4518     Label isGreaterThanCapcity(env);
4519     Label notGreaterThanCapcity(env);
4520     BRANCH(Int32GreaterThanOrEqual(index, capacity), &isGreaterThanCapcity, &notGreaterThanCapcity);
4521     Bind(&isGreaterThanCapcity);
4522     {
4523         Label isLessThanMax(env);
4524         Label notLessThanMax(env);
4525         BRANCH(Int32LessThanOrEqual(Int32Sub(index, capacity),
4526             Int32(JSObject::MAX_GAP)), &isLessThanMax, &notLessThanMax);
4527         Bind(&isLessThanMax);
4528         {
4529             Label isLessThanInt32Max(env);
4530             Label notLessThanInt32Max(env);
4531             BRANCH(Int32LessThan(index, Int32(INT32_MAX)), &isLessThanInt32Max, &notLessThanInt32Max);
4532             Bind(&isLessThanInt32Max);
4533             {
4534                 Label isLessThanMin(env);
4535                 Label notLessThanMin(env);
4536                 BRANCH(Int32LessThan(capacity, Int32(JSObject::MIN_GAP)), &isLessThanMin, &notLessThanMin);
4537                 Bind(&isLessThanMin);
4538                 {
4539                     result = False();
4540                     Jump(&exit);
4541                 }
4542                 Bind(&notLessThanMin);
4543                 {
4544                     result = Int32GreaterThan(index, Int32Mul(capacity, Int32(JSObject::FAST_ELEMENTS_FACTOR)));
4545                     Jump(&exit);
4546                 }
4547             }
4548             Bind(&notLessThanInt32Max);
4549             {
4550                 result = True();
4551                 Jump(&exit);
4552             }
4553         }
4554         Bind(&notLessThanMax);
4555         {
4556             result = True();
4557             Jump(&exit);
4558         }
4559     }
4560     Bind(&notGreaterThanCapcity);
4561     {
4562         result = False();
4563         Jump(&exit);
4564     }
4565     Bind(&exit);
4566     auto ret = *result;
4567     env->SubCfgExit();
4568     return ret;
4569 }
4570 
NotifyArrayPrototypeChangedGuardians(GateRef glue,GateRef receiver)4571 void StubBuilder::NotifyArrayPrototypeChangedGuardians(GateRef glue, GateRef receiver)
4572 {
4573     auto env = GetEnvironment();
4574     Label subEntry(env);
4575     env->SubCfgEntry(&subEntry);
4576     Label exit(env);
4577     GateRef globalEnv = GetCurrentGlobalEnv();
4578     GateRef guardians = GetArrayElementsGuardians(globalEnv);
4579 
4580     Label isGuardians(env);
4581     BRANCH(Equal(guardians, True()), &isGuardians, &exit);
4582     Bind(&isGuardians);
4583     {
4584         GateRef hclass = LoadHClass(glue, receiver);
4585         Label isPrototype(env);
4586         BRANCH(BitOr(IsPrototypeHClass(hclass), IsJsArray(glue, receiver)), &isPrototype, &exit);
4587         Bind(&isPrototype);
4588         {
4589             Label isEnvPrototype(env);
4590             GateRef isEnvPrototypeCheck = LogicOrBuilder(env)
4591                 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
4592                                             GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX), receiver))
4593                 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
4594                                             GlobalEnv::ARRAY_PROTOTYPE_INDEX), receiver))
4595                 .Done();
4596             BRANCH(isEnvPrototypeCheck, &isEnvPrototype, &exit);
4597             Bind(&isEnvPrototype);
4598             CallRuntime(glue, RTSTUB_ID(NotifyArrayPrototypeChanged), {});
4599             SetArrayElementsGuardians(glue, globalEnv, False());
4600             Jump(&exit);
4601         }
4602     }
4603     Bind(&exit);
4604     env->SubCfgExit();
4605     return;
4606 }
4607 
IsArrayLengthWritable(GateRef glue,GateRef receiver)4608 GateRef StubBuilder::IsArrayLengthWritable(GateRef glue, GateRef receiver)
4609 {
4610     auto env = GetEnvironment();
4611     Label subEntry(env);
4612     env->SubCfgEntry(&subEntry);
4613     Label exit(env);
4614     GateRef hclass = LoadHClass(glue, receiver);
4615     Label isDicMode(env);
4616     Label notDicMode(env);
4617     DEFVARIABLE(result, VariableType::BOOL(), False());
4618     BRANCH_UNLIKELY(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
4619     Bind(&isDicMode);
4620     {
4621         GateRef array = GetPropertiesArray(glue, receiver);
4622         GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
4623                                                       ConstantIndex::LENGTH_STRING_INDEX);
4624         GateRef entry = CallCommonStub(glue, CommonStubCSigns::FindEntryFromNameDictionary,
4625                                        {glue, array, lengthString});
4626         Label notNegtiveOne(env);
4627         Label isNegtiveOne(env);
4628         BRANCH(Int32NotEqual(entry, Int32(-1)), &notNegtiveOne, &isNegtiveOne);
4629         Bind(&notNegtiveOne);
4630         {
4631             GateRef attr = GetAttributesFromDictionary<NameDictionary>(glue, array, entry);
4632             result = IsWritable(attr);
4633             Jump(&exit);
4634         }
4635         Bind(&isNegtiveOne);
4636         {
4637             GateRef attr1 = Int64(PropertyAttributes::GetDefaultAttributes());
4638             result = IsWritable(attr1);
4639             Jump(&exit);
4640         }
4641     }
4642     Bind(&notDicMode);
4643     {
4644         result = IsArrayLengthWritableForNonDictMode(glue, receiver);
4645         Jump(&exit);
4646     }
4647     Bind(&exit);
4648     auto ret = *result;
4649     env->SubCfgExit();
4650     return ret;
4651 }
4652 
IsArrayLengthWritableForNonDictMode(GateRef glue,GateRef receiver)4653 GateRef StubBuilder::IsArrayLengthWritableForNonDictMode(GateRef glue, GateRef receiver)
4654 {
4655     auto env = GetEnvironment();
4656     Label subEntry(env);
4657     env->SubCfgEntry(&subEntry);
4658     Label exit(env);
4659     DEFVARIABLE(result, VariableType::BOOL(), False());
4660     GateRef hclass = LoadHClass(glue, receiver);
4661     GateRef layoutInfo = GetLayoutFromHClass(glue, hclass);
4662     GateRef attr = GetPropAttrFromLayoutInfo(glue, layoutInfo, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4663     result = IsWritable(attr);
4664     auto ret = *result;
4665     env->SubCfgExit();
4666     return ret;
4667 }
4668 
CheckHClassForRep(GateRef glue,GateRef hclass,GateRef value)4669 GateRef StubBuilder::CheckHClassForRep(GateRef glue, GateRef hclass, GateRef value)
4670 {
4671     auto env = GetEnvironment();
4672     Label subEntry(env);
4673     env->SubCfgEntry(&subEntry);
4674     Label exit(env);
4675     Label isAOTHClass(env);
4676     DEFVARIABLE(result, VariableType::BOOL(), Boolean(true));
4677     Branch(IsAOTHClass(hclass), &isAOTHClass, &exit);
4678     Bind(&isAOTHClass);
4679     {
4680         GateRef propNums = GetNumberOfPropsFromHClass(hclass);
4681         GateRef last = Int32Sub(propNums, Int32(1));
4682         GateRef layoutInfo = GetLayoutFromHClass(glue, hclass);
4683         GateRef cachedAttr = GetPropAttrFromLayoutInfo(glue, layoutInfo, last);
4684         GateRef lastRep = GetRepInPropAttr(cachedAttr);
4685         Label repIsInt(env);
4686         Label repIsNotInt(env);
4687         Label repIsDouble(env);
4688         Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::INT))), &repIsInt, &repIsNotInt);
4689         Bind(&repIsInt);
4690         {
4691             GateRef valueRep = TranslateToRep(value);
4692             Label valueRepIsNotInt(env);
4693             Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4694             Bind(&valueRepIsNotInt);
4695             {
4696                 result = Boolean(false);
4697                 Jump(&exit);
4698             }
4699         }
4700         Bind(&repIsNotInt);
4701         {
4702             Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &repIsDouble, &exit);
4703             Bind(&repIsDouble);
4704             GateRef valueRep = TranslateToRep(value);
4705             Label valueRepIsNotInt(env);
4706             Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4707             Bind(&valueRepIsNotInt);
4708             {
4709                 Label valueRepIsNotDouble(env);
4710                 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &exit,
4711                     &valueRepIsNotDouble);
4712                 Bind(&valueRepIsNotDouble);
4713                 {
4714                     result = Boolean(false);
4715                     Jump(&exit);
4716                 }
4717             }
4718         }
4719     }
4720     Bind(&exit);
4721     auto ret = *result;
4722     env->SubCfgExit();
4723     return ret;
4724 }
4725 
FindTransitions(GateRef glue,GateRef hclass,GateRef key,GateRef metaData,GateRef value)4726 GateRef StubBuilder::FindTransitions(GateRef glue, GateRef hclass, GateRef key, GateRef metaData, GateRef value)
4727 {
4728     auto env = GetEnvironment();
4729     Label entry(env);
4730     env->SubCfgEntry(&entry);
4731     Label exit(env);
4732     GateRef transition = GetTransitionsFromHClass(glue, hclass);
4733     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
4734 
4735     Label notUndefined(env);
4736     BRANCH(Equal(transition, Undefined()), &exit, &notUndefined);
4737     Bind(&notUndefined);
4738     {
4739         Label isWeak(env);
4740         Label notWeak(env);
4741         BRANCH(TaggedIsWeak(transition), &isWeak, &notWeak);
4742         Bind(&isWeak);
4743         {
4744             GateRef transitionHClass = LoadObjectFromWeakRef(transition);
4745             GateRef propNums = GetNumberOfPropsFromHClass(transitionHClass);
4746             GateRef last = Int32Sub(propNums, Int32(1));
4747             GateRef layoutInfo = GetLayoutFromHClass(glue, transitionHClass);
4748             GateRef cachedKey = GetKeyFromLayoutInfo(glue, layoutInfo, last);
4749             GateRef cachedAttr = GetPropAttrFromLayoutInfo(glue, layoutInfo, last);
4750             GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
4751             Label keyMatch(env);
4752             Label isMatch(env);
4753             Label repMatch(env);
4754             BRANCH(Equal(cachedKey, key), &keyMatch, &exit);
4755             Bind(&keyMatch);
4756             {
4757                 BRANCH(Int32Equal(metaData, cachedMetaData), &isMatch, &exit);
4758                 Bind(&isMatch);
4759                 {
4760                     BRANCH(CheckHClassForRep(glue, transitionHClass, value), &repMatch, &exit);
4761                     Bind(&repMatch);
4762                     result = transitionHClass;
4763                     Jump(&exit);
4764                 }
4765             }
4766         }
4767         Bind(&notWeak);
4768         {
4769             // need to find from dictionary
4770             GateRef entryA = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
4771             Label isFound(env);
4772             BRANCH(Int32NotEqual(entryA, Int32(-1)), &isFound, &exit);
4773             Bind(&isFound);
4774             auto cachedValue = GetValueFromDictionary<TransitionsDictionary>(glue, transition, entryA);
4775             Label valueNotUndefined(env);
4776             Label repMatch(env);
4777             BRANCH(Int64NotEqual(cachedValue, Undefined()), &valueNotUndefined, &exit);
4778             Bind(&valueNotUndefined);
4779             {
4780                 GateRef newHClass = LoadObjectFromWeakRef(cachedValue);
4781                 BRANCH(CheckHClassForRep(glue, newHClass, value), &repMatch, &exit);
4782                 Bind(&repMatch);
4783                 result = newHClass;
4784                 Jump(&exit);
4785             }
4786         }
4787     }
4788     Bind(&exit);
4789     auto ret = *result;
4790     env->SubCfgExit();
4791     return ret;
4792 }
4793 
SetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics,bool mayThrow)4794 GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn,
4795                                         ProfileOperation callback, bool defineSemantics, bool mayThrow)
4796 {
4797     auto env = GetEnvironment();
4798     Label entry(env);
4799     env->SubCfgEntry(&entry);
4800     DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
4801     DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
4802     Label exit(env);
4803     Label ifEnd(env);
4804     Label loopHead(env);
4805     Label loopEnd(env);
4806     Label loopExit(env);
4807     Label afterLoop(env);
4808     Label isJsCOWArray(env);
4809     Label isNotJsCOWArray(env);
4810     Label setElementsArray(env);
4811     if (!useOwn && !defineSemantics) {
4812         Jump(&loopHead);
4813         LoopBegin(&loopHead);
4814     }
4815     GateRef hclass = LoadHClass(glue, *holder);
4816     GateRef jsType = GetObjectType(hclass);
4817     Label isSpecialIndex(env);
4818     Label notSpecialIndex(env);
4819     BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, &notSpecialIndex);
4820     Bind(&isSpecialIndex);
4821     {
4822         // TypeArray
4823         Label isFastTypeArray(env);
4824         Label notFastTypeArray(env);
4825         Label checkIsOnPrototypeChain(env);
4826         Label notTypedArrayProto(env);
4827         BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, &notTypedArrayProto);
4828         Bind(&notTypedArrayProto);
4829         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
4830         Bind(&isFastTypeArray);
4831         {
4832             BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
4833             Bind(&checkIsOnPrototypeChain);
4834             {
4835                 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
4836                     { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
4837                 Jump(&exit);
4838             }
4839         }
4840         Bind(&notFastTypeArray);
4841         returnValue = Hole();
4842         Jump(&exit);
4843     }
4844     Bind(&notSpecialIndex);
4845     {
4846         GateRef elements = GetElementsArray(glue, *holder);
4847         Label isDictionaryElement(env);
4848         Label notDictionaryElement(env);
4849         BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, &notDictionaryElement);
4850         Bind(&notDictionaryElement);
4851         {
4852             Label isReceiver(env);
4853             if (useOwn) {
4854                 BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
4855             } else {
4856                 BRANCH(Equal(*holder, receiver), &isReceiver, &afterLoop);
4857             }
4858             Bind(&isReceiver);
4859             {
4860                 GateRef length = GetLengthOfTaggedArray(elements);
4861                 Label inRange(env);
4862                 if (useOwn) {
4863                     BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
4864                 } else {
4865                     BRANCH(Int64LessThan(index, length), &inRange, &loopExit);
4866                 }
4867                 Bind(&inRange);
4868                 {
4869                     GateRef value1 = GetTaggedValueWithElementsKind(glue, *holder, index);
4870                     Label notHole(env);
4871                     if (useOwn) {
4872                         BRANCH(Int64NotEqual(value1, Hole()), &notHole, &ifEnd);
4873                     } else {
4874                         BRANCH(Int64NotEqual(value1, Hole()), &notHole, &loopExit);
4875                     }
4876                     Bind(&notHole);
4877                     {
4878                         BRANCH(IsJsCOWArray(glue, *holder), &isJsCOWArray, &isNotJsCOWArray);
4879                         Bind(&isJsCOWArray);
4880                         {
4881                             CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
4882                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4883                                                      Int32(Elements::ToUint(ElementsKind::NONE)));
4884                             returnValue = Undefined();
4885                             Jump(&exit);
4886                         }
4887                         Bind(&isNotJsCOWArray);
4888                         {
4889                             Jump(&setElementsArray);
4890                         }
4891                         Bind(&setElementsArray);
4892                         {
4893                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4894                                                      Int32(Elements::ToUint(ElementsKind::NONE)));
4895                             returnValue = Undefined();
4896                             Jump(&exit);
4897                         }
4898                     }
4899                 }
4900             }
4901         }
4902         Bind(&isDictionaryElement);
4903         {
4904             GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
4905             Label negtiveOne(env);
4906             Label notNegtiveOne(env);
4907             BRANCH(Int32NotEqual(entryA, Int32(-1)), &notNegtiveOne, &negtiveOne);
4908             Bind(&notNegtiveOne);
4909             {
4910                 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(glue, elements, entryA);
4911                 Label isWritandConfig(env);
4912                 Label notWritandConfig(env);
4913                 BRANCH(BitOr(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
4914                     IsJSShared(glue, *holder)), &isWritandConfig, &notWritandConfig);
4915                 Bind(&isWritandConfig);
4916                 {
4917                     Label isAccessor(env);
4918                     Label notAccessor(env);
4919                     BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
4920                     Bind(&isAccessor);
4921                     if (defineSemantics) {
4922                         Jump(&exit);
4923                     } else {
4924                         GateRef accessor = GetValueFromDictionary<NumberDictionary>(glue, elements, entryA);
4925                         Label shouldCall(env);
4926                         BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor, attr), &shouldCall, &notAccessor);
4927                         Bind(&shouldCall);
4928                         {
4929                             returnValue = CallSetterHelper(glue, receiver, accessor, value, callback, mayThrow);
4930                             Jump(&exit);
4931                         }
4932                     }
4933                     Bind(&notAccessor);
4934                     {
4935                         Label holdEqualsRecv(env);
4936                         if (useOwn) {
4937                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4938                         } else {
4939                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
4940                         }
4941                         Bind(&holdEqualsRecv);
4942                         {
4943                             UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
4944                             returnValue = Undefined();
4945                             Jump(&exit);
4946                         }
4947                     }
4948                 }
4949                 Bind(&notWritandConfig);
4950                 {
4951                     returnValue = Hole();
4952                     Jump(&exit);
4953                 }
4954             }
4955             Bind(&negtiveOne);
4956             returnValue = Hole();
4957             Jump(&exit);
4958         }
4959     }
4960     if (useOwn) {
4961         Bind(&ifEnd);
4962     } else {
4963         Bind(&loopExit);
4964         {
4965             holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
4966             BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4967         }
4968         Bind(&loopEnd);
4969         LoopEndWithCheckSafePoint(&loopHead, env, glue);
4970         Bind(&afterLoop);
4971     }
4972     Label isExtensible(env);
4973     Label notExtensible(env);
4974     Label throwNotExtensible(env);
4975     BRANCH(IsExtensible(glue, receiver), &isExtensible, &notExtensible);
4976     Bind(&notExtensible);
4977     {
4978         // fixme(hzzhouzebin) this makes SharedArray's frozen no sense.
4979         BRANCH(IsJsSArray(glue, receiver), &isExtensible, &throwNotExtensible);
4980     }
4981     Bind(&isExtensible);
4982     {
4983         Label success(env);
4984         Label failed(env);
4985         BRANCH(AddElementInternal(glue, receiver, index, value, Int64(PropertyAttributes::GetDefaultAttributes())),
4986                &success, &failed);
4987         Bind(&success);
4988         {
4989             returnValue = Undefined();
4990             Jump(&exit);
4991         }
4992         Bind(&failed);
4993         {
4994             returnValue = Exception();
4995             Jump(&exit);
4996         }
4997     }
4998     Bind(&throwNotExtensible);
4999     {
5000         if (mayThrow) {
5001             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5002             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5003             returnValue = Exception();
5004         } else {
5005             returnValue = TaggedFalse();
5006         }
5007         Jump(&exit);
5008     }
5009     Bind(&exit);
5010     auto ret = *returnValue;
5011     env->SubCfgExit();
5012     return ret;
5013 }
5014 
DefinePropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)5015 GateRef StubBuilder::DefinePropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
5016 {
5017     auto env = GetEnvironment();
5018     Label entry(env);
5019     env->SubCfgEntry(&entry);
5020     DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
5021     DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
5022     Label exit(env);
5023     Label ifEnd(env);
5024     Label loopHead(env);
5025     Label loopEnd(env);
5026     Label loopExit(env);
5027     Label afterLoop(env);
5028     Label isJsCOWArray(env);
5029     Label isNotJsCOWArray(env);
5030     Label setElementsArray(env);
5031     GateRef hclass = LoadHClass(glue, *holder);
5032     GateRef jsType = GetObjectType(hclass);
5033     Label isSpecialIndex(env);
5034     Label notSpecialIndex(env);
5035     BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, &notSpecialIndex);
5036     Bind(&isSpecialIndex);
5037     {
5038         Label isFastTypeArray(env);
5039         Label notFastTypeArray(env);
5040         Label checkIsOnPrototypeChain(env);
5041         Label notTypedArrayProto(env);
5042         BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, &notTypedArrayProto);
5043         Bind(&notTypedArrayProto);
5044         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
5045         Bind(&isFastTypeArray);
5046         {
5047             BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
5048             Bind(&checkIsOnPrototypeChain);
5049             {
5050                 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
5051                     { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
5052                 Jump(&exit);
5053             }
5054         }
5055         Bind(&notFastTypeArray);
5056         returnValue = Hole();
5057         Jump(&exit);
5058     }
5059     Bind(&notSpecialIndex);
5060     {
5061         GateRef elements = GetElementsArray(glue, *holder);
5062         Label isDictionaryElement(env);
5063         Label notDictionaryElement(env);
5064         BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, &notDictionaryElement);
5065         Bind(&notDictionaryElement);
5066         {
5067             Label isReceiver(env);
5068             BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
5069             Bind(&isReceiver);
5070             {
5071                 GateRef length = GetLengthOfTaggedArray(elements);
5072                 Label inRange(env);
5073                 BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
5074                 Bind(&inRange);
5075                 {
5076                     GateRef value1 = GetTaggedValueWithElementsKind(glue, *holder, index);
5077                     Label notHole(env);
5078                     BRANCH(Int64NotEqual(value1, Hole()), &notHole, &ifEnd);
5079                     Bind(&notHole);
5080                     {
5081                         BRANCH(IsJsCOWArray(glue, *holder), &isJsCOWArray, &isNotJsCOWArray);
5082                         Bind(&isJsCOWArray);
5083                         {
5084                             CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
5085                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
5086                                                      Int32(Elements::ToUint(ElementsKind::NONE)));
5087                             returnValue = Undefined();
5088                             Jump(&exit);
5089                         }
5090                         Bind(&isNotJsCOWArray);
5091                         {
5092                             Jump(&setElementsArray);
5093                         }
5094                         Bind(&setElementsArray);
5095                         {
5096                             SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
5097                                                      Int32(Elements::ToUint(ElementsKind::NONE)));
5098                             returnValue = Undefined();
5099                             Jump(&exit);
5100                         }
5101                     }
5102                 }
5103             }
5104         }
5105         Bind(&isDictionaryElement);
5106         {
5107             GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
5108             Label negtiveOne(env);
5109             Label notNegtiveOne(env);
5110             BRANCH(Int32NotEqual(entryA, Int32(-1)), &notNegtiveOne, &negtiveOne);
5111             Bind(&notNegtiveOne);
5112             {
5113                 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(glue, elements, entryA);
5114                 Label isWritandConfig(env);
5115                 Label notWritandConfig(env);
5116                 BRANCH(BitOr(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
5117                     IsJSShared(glue, *holder)), &isWritandConfig, &notWritandConfig);
5118                 Bind(&isWritandConfig);
5119                 {
5120                     Label notAccessor(env);
5121                     BRANCH(IsAccessor(attr), &exit, &notAccessor);
5122                     Bind(&notAccessor);
5123                     {
5124                         Label holdEqualsRecv(env);
5125                         BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
5126                         Bind(&holdEqualsRecv);
5127                         {
5128                             UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
5129                             returnValue = Undefined();
5130                             Jump(&exit);
5131                         }
5132                     }
5133                 }
5134                 Bind(&notWritandConfig);
5135                 {
5136                     returnValue = Hole();
5137                     Jump(&exit);
5138                 }
5139             }
5140             Bind(&negtiveOne);
5141             returnValue = Hole();
5142             Jump(&exit);
5143         }
5144     }
5145     Bind(&ifEnd);
5146     Label isExtensible(env);
5147     Label notExtensible(env);
5148     Label throwNotExtensible(env);
5149     BRANCH(IsExtensible(glue, receiver), &isExtensible, &notExtensible);
5150     Bind(&notExtensible);
5151     {
5152         BRANCH(IsJsSArray(glue, receiver), &isExtensible, &throwNotExtensible);
5153     }
5154     Bind(&isExtensible);
5155     {
5156         Label success(env);
5157         Label failed(env);
5158         BRANCH(AddElementInternal(glue, receiver, index, value, Int64(PropertyAttributes::GetDefaultAttributes())),
5159                &success, &failed);
5160         Bind(&success);
5161         {
5162             returnValue = Undefined();
5163             Jump(&exit);
5164         }
5165         Bind(&failed);
5166         {
5167             returnValue = Exception();
5168             Jump(&exit);
5169         }
5170     }
5171     Bind(&throwNotExtensible);
5172     {
5173         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5174         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5175         returnValue = Exception();
5176         Jump(&exit);
5177     }
5178     Bind(&exit);
5179     auto ret = *returnValue;
5180     env->SubCfgExit();
5181     return ret;
5182 }
5183 
SetPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,GateRef isInternal,ProfileOperation callback,bool canUseIsInternal,bool defineSemantics,bool mayThrow)5184 GateRef StubBuilder::SetPropertyByName(GateRef glue,
5185                                        GateRef receiver,
5186                                        GateRef key,
5187                                        GateRef value,
5188                                        bool useOwn,
5189                                        GateRef isInternal,
5190                                        ProfileOperation callback,
5191                                        bool canUseIsInternal,
5192                                        bool defineSemantics,
5193                                        bool mayThrow)
5194 {
5195     auto env = GetEnvironment();
5196     Label entryPass(env);
5197     env->SubCfgEntry(&entryPass);
5198     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5199     DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
5200     DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
5201     Label exit(env);
5202     Label ifEnd(env);
5203     Label loopHead(env);
5204     Label loopEnd(env);
5205     Label loopExit(env);
5206     Label afterLoop(env);
5207     Label findProperty(env);
5208     if (!useOwn) {
5209         Jump(&loopHead);
5210         LoopBegin(&loopHead);
5211     }
5212     GateRef hclass = LoadHClass(glue, *holder);
5213     GateRef jsType = GetObjectType(hclass);
5214     Label isSIndexObj(env);
5215     Label notSIndexObj(env);
5216     BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, &notSIndexObj);
5217     Bind(&isSIndexObj);
5218     {
5219         Label isFastTypeArray(env);
5220         Label notFastTypeArray(env);
5221         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
5222         Bind(&isFastTypeArray);
5223         {
5224             result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
5225             Label isNull(env);
5226             Label notNull(env);
5227             BRANCH(TaggedIsNull(*result), &isNull, &notNull);
5228             Bind(&isNull);
5229             {
5230                 result = Hole();
5231                 Jump(&exit);
5232             }
5233             Bind(&notNull);
5234             BRANCH(TaggedIsHole(*result), &notSIndexObj, &exit);
5235         }
5236         Bind(&notFastTypeArray);
5237 
5238         Label isSpecialContainer(env);
5239         Label notSpecialContainer(env);
5240         BRANCH(IsArrayListOrVector(jsType), &isSpecialContainer, &notSpecialContainer);
5241         Bind(&isSpecialContainer);
5242         {
5243             if (mayThrow) {
5244                 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
5245                 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5246                 result = Exception();
5247             } else {
5248                 result = TaggedFalse();
5249             }
5250             Jump(&exit);
5251         }
5252         Bind(&notSpecialContainer);
5253         {
5254 #if ENABLE_NEXT_OPTIMIZATION
5255             Label isJsProxy(env);
5256             Label notJsProxy(env);
5257             BRANCH(IsJSProxy(jsType), &isJsProxy, &notJsProxy);
5258             Bind(&isJsProxy);
5259             {
5260                 if (defineSemantics) {
5261                     Jump(&exit);
5262                 } else {
5263                     Label returnException(env);
5264                     Label noPendingException(env);
5265                     if (mayThrow) {
5266                         result = CallCommonStub(glue, CommonStubCSigns::JSProxySetProperty,
5267                                                 {glue, *holder, key, value, receiver, GetCurrentGlobalEnv()});
5268                     } else {
5269                         result = CallCommonStub(glue, CommonStubCSigns::JSProxySetPropertyNoThrow,
5270                                                 {glue, *holder, key, value, receiver, GetCurrentGlobalEnv()});
5271                     }
5272                     BRANCH(HasPendingException(glue), &returnException, &exit);
5273                     Bind(&returnException);
5274                     {
5275                         result = Exception();
5276                         Jump(&exit);
5277                     }
5278                 }
5279             }
5280             Bind(&notJsProxy);
5281             {
5282                 result = Hole();
5283                 Jump(&exit);
5284             }
5285 #else
5286             result = Hole();
5287             Jump(&exit);
5288 #endif
5289         }
5290     }
5291     Bind(&notSIndexObj);
5292     {
5293         if (canUseIsInternal) {
5294             if (useOwn) {
5295                 BRANCH(isInternal, &findProperty, &ifEnd);
5296             } else {
5297                 BRANCH(isInternal, &findProperty, &loopExit);
5298             }
5299         } else {
5300             Jump(&findProperty);
5301         }
5302         Label isDicMode(env);
5303         Label notDicMode(env);
5304         Bind(&findProperty);
5305         BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
5306         Bind(&notDicMode);
5307         {
5308             GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
5309             GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
5310             GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
5311             Label hasEntry(env);
5312             if (useOwn || defineSemantics) {
5313                 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
5314             } else {
5315                 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &loopExit);
5316             }
5317             Bind(&hasEntry);
5318             {
5319                 GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entry);
5320                 Label isAccessor(env);
5321                 Label notAccessor(env);
5322                 BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
5323                 Bind(&isAccessor);
5324                 if (defineSemantics) {
5325                     Jump(&exit);
5326                 } else {
5327                     GateRef accessor = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5328                     Label shouldCall(env);
5329                     BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor, attr), &shouldCall, &notAccessor);
5330                     Bind(&shouldCall);
5331                     {
5332                         result = CallSetterHelper(glue, receiver, accessor, value, callback, mayThrow);
5333                         Jump(&exit);
5334                     }
5335                 }
5336                 Bind(&notAccessor);
5337                 {
5338                     Label writable(env);
5339                     Label notWritable(env);
5340                     BRANCH(IsWritable(attr), &writable, &notWritable);
5341                     Bind(&notWritable);
5342                     if (defineSemantics) {
5343                         Jump(&exit);
5344                     } else {
5345                         if (mayThrow) {
5346                             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5347                             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5348                             result = Exception();
5349                         } else {
5350                             result = TaggedFalse();
5351                         }
5352                         Jump(&exit);
5353                     }
5354                     Bind(&writable);
5355                     {
5356                         Label isAOT(env);
5357                         Label notAOT(env);
5358                         BRANCH(IsAOTHClass(hclass), &isAOT, &notAOT);
5359                         Bind(&isAOT);
5360                         {
5361                             GateRef attrVal = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5362                             Label attrValIsHole(env);
5363                             BRANCH(TaggedIsHole(attrVal), &attrValIsHole, &notAOT);
5364                             Bind(&attrValIsHole);
5365                             {
5366                                 Label storeReceiverHoleEntry(env);
5367                                 Label noNeedStore(env);
5368                                 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
5369                                 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
5370                                 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
5371                                     &storeReceiverHoleEntry, &noNeedStore);
5372                                 Bind(&storeReceiverHoleEntry);
5373                                 {
5374                                     receiverHoleEntry = entry;
5375                                     Jump(&noNeedStore);
5376                                 }
5377                                 Bind(&noNeedStore);
5378                                 if (useOwn || defineSemantics) {
5379                                     Jump(&ifEnd);
5380                                 } else {
5381                                     Jump(&loopExit);
5382                                 }
5383                             }
5384                         }
5385                         Bind(&notAOT);
5386                         Label holdEqualsRecv(env);
5387                         if (useOwn || defineSemantics) {
5388                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
5389                         } else {
5390                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
5391                         }
5392                         Bind(&holdEqualsRecv);
5393                         {
5394                             Label isJSShared(env);
5395                             Label executeSetProp(env);
5396                             BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5397                             Bind(&isJSShared);
5398                             {
5399                                 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5400                                 Label executeSharedSetProp(env);
5401                                 SharedObjectStoreBarrierWithTypeCheck(false, &result, glue, attr, value, &actualValue,
5402                                     &executeSharedSetProp, &exit);
5403                                 Bind(&executeSharedSetProp);
5404                                 {
5405                                     JSObjectSetProperty(glue, *holder, hclass, attr, key, *actualValue);
5406                                     ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr,
5407                                         *actualValue, callback);
5408                                     result = Undefined();
5409                                     Jump(&exit);
5410                                 }
5411                             }
5412                             Bind(&executeSetProp);
5413                             {
5414                                 JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
5415                                 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value,
5416                                     callback);
5417                                 result = Undefined();
5418                                 Jump(&exit);
5419                             }
5420                         }
5421                     }
5422                 }
5423             }
5424         }
5425         Bind(&isDicMode);
5426         {
5427             GateRef array = GetPropertiesArray(glue, *holder);
5428             GateRef entry1 = FindEntryFromHashTable<NameDictionary>(glue, array, key);
5429             Label notNegtiveOne(env);
5430             if (useOwn || defineSemantics) {
5431                 BRANCH(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &ifEnd);
5432             } else {
5433                 BRANCH(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &loopExit);
5434             }
5435             Bind(&notNegtiveOne);
5436             {
5437                 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(glue, array, entry1);
5438                 Label isAccessor1(env);
5439                 Label notAccessor1(env);
5440                 BRANCH(IsAccessor(attr1), &isAccessor1, &notAccessor1);
5441                 Bind(&isAccessor1);
5442                 if (defineSemantics) {
5443                     Jump(&exit);
5444                 } else {
5445                     GateRef accessor1 = GetValueFromDictionary<NameDictionary>(glue, array, entry1);
5446                     Label shouldCall1(env);
5447                     BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor1, attr1), &shouldCall1, &notAccessor1);
5448                     Bind(&shouldCall1);
5449                     {
5450                         result = CallSetterHelper(glue, receiver, accessor1, value, callback, mayThrow);
5451                         Jump(&exit);
5452                     }
5453                 }
5454                 Bind(&notAccessor1);
5455                 {
5456                     Label writable1(env);
5457                     Label notWritable1(env);
5458                     BRANCH(IsWritable(attr1), &writable1, &notWritable1);
5459                     Bind(&notWritable1);
5460                     if (defineSemantics) {
5461                         Jump(&exit);
5462                     } else {
5463                         if (mayThrow) {
5464                             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5465                             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5466                             result = Exception();
5467                         } else {
5468                             result = TaggedFalse();
5469                         }
5470                         Jump(&exit);
5471                     }
5472                     Bind(&writable1);
5473                     {
5474                         Label holdEqualsRecv1(env);
5475                         if (useOwn) {
5476                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
5477                         } else {
5478                             BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &afterLoop);
5479                         }
5480                         Bind(&holdEqualsRecv1);
5481                         {
5482                             Label isJSShared(env);
5483                             Label executeSetProp(env);
5484                             BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5485                             Bind(&isJSShared);
5486                             {
5487                                 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5488                                 Label executeSharedSetProp(env);
5489                                 SharedObjectStoreBarrierWithTypeCheck(true, &result, glue, attr1, value, &actualValue,
5490                                     &executeSharedSetProp, &exit);
5491                                 Bind(&executeSharedSetProp);
5492                                 {
5493                                     UpdateValueInDict<NameDictionary>(glue, array, entry1, *actualValue);
5494                                     result = Undefined();
5495                                     Jump(&exit);
5496                                 }
5497                             }
5498                             Bind(&executeSetProp);
5499                             {
5500                                 UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
5501                                 result = Undefined();
5502                                 Jump(&exit);
5503                             }
5504                         }
5505                     }
5506                 }
5507             }
5508         }
5509     }
5510     if (useOwn || defineSemantics) {
5511         Bind(&ifEnd);
5512     } else {
5513         Bind(&loopExit);
5514         {
5515             holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
5516             BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
5517         }
5518         Bind(&loopEnd);
5519         LoopEndWithCheckSafePoint(&loopHead, env, glue);
5520         Bind(&afterLoop);
5521     }
5522     Label holeEntryNotNegtiveOne(env);
5523     Label holeEntryIfEnd(env);
5524     BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
5525     Bind(&holeEntryNotNegtiveOne);
5526     {
5527         GateRef receiverHClass = LoadHClass(glue, receiver);
5528         GateRef receiverLayoutInfo = GetLayoutFromHClass(glue, receiverHClass);
5529         GateRef holeAttr = GetPropAttrFromLayoutInfo(glue, receiverLayoutInfo, *receiverHoleEntry);
5530         JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
5531         ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
5532         result = Undefined();
5533         Jump(&exit);
5534     }
5535     Bind(&holeEntryIfEnd);
5536 
5537     Label extensible(env);
5538     Label inextensible(env);
5539     BRANCH(IsExtensible(glue, receiver), &extensible, &inextensible);
5540     Bind(&inextensible);
5541     {
5542         if (mayThrow) {
5543             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5544             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5545             result = Exception();
5546         } else {
5547             result = TaggedFalse();
5548         }
5549         Jump(&exit);
5550     }
5551     Bind(&extensible);
5552     {
5553         result = AddPropertyByName(glue, receiver, key, value,
5554             Int64(PropertyAttributes::GetDefaultAttributes()), callback);
5555         Jump(&exit);
5556     }
5557     Bind(&exit);
5558     auto ret = *result;
5559     env->SubCfgExit();
5560     return ret;
5561 }
5562 
DefinePropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef isInternal,GateRef SCheckModelIsCHECK,ProfileOperation callback)5563 GateRef StubBuilder::DefinePropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
5564     GateRef isInternal, GateRef SCheckModelIsCHECK, ProfileOperation callback)
5565 {
5566     auto env = GetEnvironment();
5567     Label entryPass(env);
5568     env->SubCfgEntry(&entryPass);
5569     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5570     DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
5571     DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
5572     Label exit(env);
5573     Label ifEnd(env);
5574     Label loopHead(env);
5575     Label loopEnd(env);
5576     Label loopExit(env);
5577     Label afterLoop(env);
5578     Label findProperty(env);
5579 
5580     GateRef hclass = LoadHClass(glue, *holder);
5581     GateRef jsType = GetObjectType(hclass);
5582     Label isSIndexObj(env);
5583     Label notSIndexObj(env);
5584     BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, &notSIndexObj);
5585     Bind(&isSIndexObj);
5586     {
5587         Label isFastTypeArray(env);
5588         Label notFastTypeArray(env);
5589         BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, &notFastTypeArray);
5590         Bind(&isFastTypeArray);
5591         {
5592             result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
5593             Label isNull(env);
5594             Label notNull(env);
5595             BRANCH(TaggedIsNull(*result), &isNull, &notNull);
5596             Bind(&isNull);
5597             {
5598                 result = Hole();
5599                 Jump(&exit);
5600             }
5601             Bind(&notNull);
5602             BRANCH(TaggedIsHole(*result), &notSIndexObj, &exit);
5603         }
5604         Bind(&notFastTypeArray);
5605 
5606         Label isSpecialContainer(env);
5607         Label notSpecialContainer(env);
5608         BRANCH(IsArrayListOrVector(jsType), &isSpecialContainer, &notSpecialContainer);
5609         Bind(&isSpecialContainer);
5610         {
5611             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
5612             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5613             result = Exception();
5614             Jump(&exit);
5615         }
5616         Bind(&notSpecialContainer);
5617         {
5618             result = Hole();
5619             Jump(&exit);
5620         }
5621     }
5622     Bind(&notSIndexObj);
5623     {
5624         BRANCH(isInternal, &findProperty, &ifEnd);
5625         Label isDicMode(env);
5626         Label notDicMode(env);
5627         Bind(&findProperty);
5628         BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
5629         Bind(&notDicMode);
5630         {
5631             GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
5632             GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
5633             GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
5634             Label hasEntry(env);
5635             BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
5636             Bind(&hasEntry);
5637             {
5638                 GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entry);
5639                 Label isAccessor(env);
5640                 Label notAccessor(env);
5641                 Label isSCheckModelIsCHECK1(env);
5642                 Label isNotSCheckModelIsCHECK1(env);
5643                 BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
5644                 Bind(&isAccessor);
5645                 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK1, &isNotSCheckModelIsCHECK1);
5646                 Bind(&isSCheckModelIsCHECK1);
5647                 {
5648                     Jump(&exit);
5649                 }
5650                 Bind(&isNotSCheckModelIsCHECK1);
5651                 GateRef accessor = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5652                 Label shouldCall(env);
5653                 BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor, attr), &shouldCall, &notAccessor);
5654                 Bind(&shouldCall);
5655                 {
5656                     result = CallSetterHelper(glue, receiver, accessor, value, callback);
5657                     Jump(&exit);
5658                 }
5659                 Bind(&notAccessor);
5660                 {
5661                     Label writable(env);
5662                     Label notWritable(env);
5663                     Label isSCheckModelIsCHECK2(env);
5664                     Label isNotSCheckModelIsCHECK2(env);
5665                     BRANCH(IsWritable(attr), &writable, &notWritable);
5666                     Bind(&notWritable);
5667                     BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK2, &isNotSCheckModelIsCHECK2);
5668                     Bind(&isSCheckModelIsCHECK2);
5669                     {
5670                         Jump(&exit);
5671                     }
5672                     Bind(&isNotSCheckModelIsCHECK2);
5673                     GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5674                     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5675                     result = Exception();
5676                     Jump(&exit);
5677                     Bind(&writable);
5678                     {
5679                         Label isAOT(env);
5680                         Label notAOT(env);
5681                         BRANCH(IsAOTHClass(hclass), &isAOT, &notAOT);
5682                         Bind(&isAOT);
5683                         {
5684                             GateRef attrVal = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5685                             Label attrValIsHole(env);
5686                             BRANCH(TaggedIsHole(attrVal), &attrValIsHole, &notAOT);
5687                             Bind(&attrValIsHole);
5688                             {
5689                                 Label storeReceiverHoleEntry(env);
5690                                 Label noNeedStore(env);
5691                                 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
5692                                 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
5693                                 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
5694                                     &storeReceiverHoleEntry, &ifEnd);
5695                                 Bind(&storeReceiverHoleEntry);
5696                                 {
5697                                     receiverHoleEntry = entry;
5698                                     Jump(&ifEnd);
5699                                 }
5700                             }
5701                         }
5702                         Bind(&notAOT);
5703                         Label holdEqualsRecv(env);
5704                         BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
5705                         Bind(&holdEqualsRecv);
5706                         {
5707                             Label isJSShared(env);
5708                             Label executeSetProp(env);
5709                             BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5710                             Bind(&isJSShared);
5711                             {
5712                                 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5713                                 Label executeSharedSetProp(env);
5714                                 SharedObjectStoreBarrierWithTypeCheck(false, &result, glue, attr, value, &actualValue,
5715                                     &executeSharedSetProp, &exit, SCheckModelIsCHECK);
5716                                 Bind(&executeSharedSetProp);
5717                                 {
5718                                     JSObjectSetProperty(glue, *holder, hclass, attr, key, *actualValue);
5719                                     ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr,
5720                                         *actualValue, callback);
5721                                     result = Undefined();
5722                                     Jump(&exit);
5723                                 }
5724                             }
5725                             Bind(&executeSetProp);
5726                             {
5727                                 JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
5728                                 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value,
5729                                     callback);
5730                                 result = Undefined();
5731                                 Jump(&exit);
5732                             }
5733                         }
5734                     }
5735                 }
5736             }
5737         }
5738         Bind(&isDicMode);
5739         {
5740             GateRef array = GetPropertiesArray(glue, *holder);
5741             GateRef entry1 = FindEntryFromHashTable<NameDictionary>(glue, array, key);
5742             Label notNegtiveOne(env);
5743             BRANCH(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &ifEnd);
5744             Bind(&notNegtiveOne);
5745             {
5746                 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(glue, array, entry1);
5747                 Label isAccessor1(env);
5748                 Label notAccessor1(env);
5749                 Label isSCheckModelIsCHECK3(env);
5750                 Label isNotSCheckModelIsCHECK3(env);
5751                 BRANCH(IsAccessor(attr1), &isAccessor1, &notAccessor1);
5752                 Bind(&isAccessor1);
5753                 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK3, &isNotSCheckModelIsCHECK3);
5754                 Bind(&isSCheckModelIsCHECK3);
5755                 {
5756                     Jump(&exit);
5757                 }
5758                 Bind(&isNotSCheckModelIsCHECK3);
5759                 GateRef accessor1 = GetValueFromDictionary<NameDictionary>(glue, array, entry1);
5760                 Label shouldCall1(env);
5761                 BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor1, attr1), &shouldCall1, &notAccessor1);
5762                 Bind(&shouldCall1);
5763                 {
5764                     result = CallSetterHelper(glue, receiver, accessor1, value, callback);
5765                     Jump(&exit);
5766                 }
5767                 Bind(&notAccessor1);
5768                 {
5769                     Label writable1(env);
5770                     Label notWritable1(env);
5771                     Label isSCheckModelIsCHECK4(env);
5772                     Label isNotSCheckModelIsCHECK4(env);
5773                     BRANCH(IsWritable(attr1), &writable1, &notWritable1);
5774                     Bind(&notWritable1);
5775                     BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK4, &isNotSCheckModelIsCHECK4);
5776                     Bind(&isSCheckModelIsCHECK4);
5777                     {
5778                         Jump(&exit);
5779                     }
5780                     Bind(&isNotSCheckModelIsCHECK4);
5781                     GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5782                     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5783                     result = Exception();
5784                     Jump(&exit);
5785                     Bind(&writable1);
5786                     {
5787                         Label holdEqualsRecv1(env);
5788                         BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
5789                         Bind(&holdEqualsRecv1);
5790                         {
5791                             Label isJSShared(env);
5792                             Label executeSetProp(env);
5793                             BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5794                             Bind(&isJSShared);
5795                             {
5796                                 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5797                                 Label executeSharedSetProp(env);
5798                                 SharedObjectStoreBarrierWithTypeCheck(true, &result, glue, attr1, value, &actualValue,
5799                                     &executeSharedSetProp, &exit, SCheckModelIsCHECK);
5800                                 Bind(&executeSharedSetProp);
5801                                 {
5802                                     UpdateValueInDict<NameDictionary>(glue, array, entry1, *actualValue);
5803                                     result = Undefined();
5804                                     Jump(&exit);
5805                                 }
5806                             }
5807                             Bind(&executeSetProp);
5808                             {
5809                                 UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
5810                                 result = Undefined();
5811                                 Jump(&exit);
5812                             }
5813                         }
5814                     }
5815                 }
5816             }
5817         }
5818     }
5819     Bind(&ifEnd);
5820     Label holeEntryNotNegtiveOne(env);
5821     Label holeEntryIfEnd(env);
5822     BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
5823     Bind(&holeEntryNotNegtiveOne);
5824     {
5825         GateRef receiverHClass = LoadHClass(glue, receiver);
5826         GateRef receiverLayoutInfo = GetLayoutFromHClass(glue, receiverHClass);
5827         GateRef holeAttr = GetPropAttrFromLayoutInfo(glue, receiverLayoutInfo, *receiverHoleEntry);
5828         JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
5829         ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
5830         result = Undefined();
5831         Jump(&exit);
5832     }
5833     Bind(&holeEntryIfEnd);
5834 
5835     Label extensible(env);
5836     Label inextensible(env);
5837     BRANCH(IsExtensible(glue, receiver), &extensible, &inextensible);
5838     Bind(&inextensible);
5839     {
5840         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5841         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5842         result = Exception();
5843         Jump(&exit);
5844     }
5845     Bind(&extensible);
5846     {
5847         result = AddPropertyByName(glue, receiver, key, value,
5848             Int64(PropertyAttributes::GetDefaultAttributes()), callback);
5849         Jump(&exit);
5850     }
5851     Bind(&exit);
5852     auto ret = *result;
5853     env->SubCfgExit();
5854     return ret;
5855 }
5856 
5857 /**
5858     Ruturn value: Hole means try fastPath fail, caller should go slow path, undefined is try fastPath succsee.
5859     only when mayThrow, will return TaggedFalse, it means some step has exception but not throw in
5860     thread, same as C interpreter SetProperty
5861     In ANY situation, exception means that an error must have occurred and been thrown on the thread.
5862  */
5863 
SetPropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics,bool mayThrow)5864 GateRef StubBuilder::SetPropertyByValue(GateRef glue,
5865                                         GateRef receiver,
5866                                         GateRef key,
5867                                         GateRef value,
5868                                         bool useOwn,
5869                                         ProfileOperation callback,
5870                                         bool defineSemantics,
5871                                         bool mayThrow)
5872 {
5873     auto env = GetEnvironment();
5874     Label subEntry1(env);
5875     env->SubCfgEntry(&subEntry1);
5876     DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5877     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5878     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5879     Label isPropertyKey(env);
5880     Label exit(env);
5881 
5882     BRANCH(TaggedIsPropertyKey(glue, *varKey), &isPropertyKey, &exit);
5883 
5884     Bind(&isPropertyKey);
5885     {
5886         GateRef index64 = TryToElementsIndex(glue, *varKey);
5887         Label validIndex(env);
5888         Label notValidIndex(env);
5889         Label greaterThanInt32Max(env);
5890         Label notGreaterThanInt32Max(env);
5891         BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
5892         Bind(&greaterThanInt32Max);
5893         {
5894             Jump(&exit);
5895         }
5896         Bind(&notGreaterThanInt32Max);
5897         GateRef index = TruncInt64ToInt32(index64);
5898         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
5899         Bind(&validIndex);
5900         {
5901             result = SetPropertyByIndex(glue, receiver, index, value, useOwn, callback, defineSemantics, mayThrow);
5902             Jump(&exit);
5903         }
5904         Bind(&notValidIndex);
5905         {
5906             Label isNumber1(env);
5907             Label notNumber1(env);
5908             Label setByName(env);
5909             BRANCH(TaggedIsNumber(*varKey), &isNumber1, &notNumber1);
5910             Bind(&isNumber1);
5911             {
5912                 result = Hole();
5913                 Jump(&exit);
5914             }
5915             Label isString(env);
5916             Label checkDetector(env);
5917             Bind(&notNumber1);
5918             {
5919                 Label notIntenalString(env);
5920                 BRANCH(TaggedIsString(glue, *varKey), &isString, &checkDetector);
5921                 Bind(&isString);
5922                 {
5923                     BRANCH(IsInternalString(*varKey), &setByName, &notIntenalString);
5924                     Bind(&notIntenalString);
5925                     {
5926                     #if ENABLE_NEXT_OPTIMIZATION
5927                         GateRef res = CallRuntime(glue, RTSTUB_ID(GetOrInternStringFromHashTrieTable), { *varKey });
5928                         varKey = res;
5929                         Jump(&checkDetector);
5930                     #else
5931                         Label notFind(env);
5932                         Label find(env);
5933                         GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
5934                         BRANCH(TaggedIsHole(res), &notFind, &find);
5935                         Bind(&notFind);
5936                         {
5937                             varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
5938                             isInternal = False();
5939                             Jump(&checkDetector);
5940                         }
5941                         Bind(&find);
5942                         {
5943                             varKey = res;
5944                             Jump(&checkDetector);
5945                         }
5946                     #endif
5947                     }
5948                 }
5949             }
5950             Bind(&checkDetector);
5951             CheckDetectorName(glue, *varKey, &setByName, &exit);
5952             Bind(&setByName);
5953             {
5954                 result = SetPropertyByName(
5955                     glue, receiver, *varKey, value, useOwn, *isInternal, callback, true, defineSemantics, mayThrow);
5956                 Jump(&exit);
5957             }
5958         }
5959     }
5960     Bind(&exit);
5961     auto ret = *result;
5962     env->SubCfgExit();
5963     return ret;
5964 }
5965 
5966 // ObjectFastOperator::SetPropertyByValue
DefinePropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef SCheckModelIsCHECK,ProfileOperation callback)5967 GateRef StubBuilder::DefinePropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value,
5968     GateRef SCheckModelIsCHECK, ProfileOperation callback)
5969 {
5970     auto env = GetEnvironment();
5971     Label subEntry1(env);
5972     env->SubCfgEntry(&subEntry1);
5973     DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5974     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5975     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5976     Label isPropertyKey(env);
5977     Label exit(env);
5978 
5979     BRANCH(TaggedIsPropertyKey(glue, *varKey), &isPropertyKey, &exit);
5980 
5981     Bind(&isPropertyKey);
5982     {
5983         GateRef index64 = TryToElementsIndex(glue, *varKey);
5984         Label validIndex(env);
5985         Label notValidIndex(env);
5986         Label greaterThanInt32Max(env);
5987         Label notGreaterThanInt32Max(env);
5988         BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, &notGreaterThanInt32Max);
5989         Bind(&greaterThanInt32Max);
5990         {
5991             Jump(&exit);
5992         }
5993         Bind(&notGreaterThanInt32Max);
5994         GateRef index = TruncInt64ToInt32(index64);
5995         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
5996         Bind(&validIndex);
5997         {
5998             result = DefinePropertyByIndex(glue, receiver, index, value);
5999             Jump(&exit);
6000         }
6001         Bind(&notValidIndex);
6002         {
6003             Label isNumber1(env);
6004             Label notNumber1(env);
6005             Label setByName(env);
6006             BRANCH(TaggedIsNumber(*varKey), &isNumber1, &notNumber1);
6007             Bind(&isNumber1);
6008             {
6009                 result = Hole();
6010                 Jump(&exit);
6011             }
6012             Label isString(env);
6013             Label checkDetector(env);
6014             Bind(&notNumber1);
6015             {
6016                 Label notIntenalString(env);
6017                 BRANCH(TaggedIsString(glue, *varKey), &isString, &checkDetector);
6018                 Bind(&isString);
6019                 {
6020                     BRANCH(IsInternalString(*varKey), &setByName, &notIntenalString);
6021                     Bind(&notIntenalString);
6022                     {
6023                     #if ENABLE_NEXT_OPTIMIZATION
6024                         GateRef res = CallRuntime(glue, RTSTUB_ID(GetOrInternStringFromHashTrieTable), { *varKey });
6025                         varKey = res;
6026                         Jump(&checkDetector);
6027                     #else
6028                         Label notFind(env);
6029                         Label find(env);
6030                         GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
6031                         BRANCH(TaggedIsHole(res), &notFind, &find);
6032                         Bind(&notFind);
6033                         {
6034                             varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
6035                             isInternal = False();
6036                             Jump(&checkDetector);
6037                         }
6038                         Bind(&find);
6039                         {
6040                             varKey = res;
6041                             Jump(&checkDetector);
6042                         }
6043                     #endif
6044                     }
6045                 }
6046             }
6047             Bind(&checkDetector);
6048             CheckDetectorName(glue, *varKey, &setByName, &exit);
6049             Bind(&setByName);
6050             {
6051                 result = DefinePropertyByName(glue, receiver, *varKey, value, *isInternal,
6052                     SCheckModelIsCHECK, callback);
6053                 Jump(&exit);
6054             }
6055         }
6056     }
6057     Bind(&exit);
6058     auto ret = *result;
6059     env->SubCfgExit();
6060     return ret;
6061 }
6062 
SetPropertiesToLexicalEnv(GateRef glue,GateRef object,GateRef index,GateRef value)6063 void StubBuilder::SetPropertiesToLexicalEnv(GateRef glue, GateRef object, GateRef index, GateRef value)
6064 {
6065     GateRef valueIndex = Int32Add(index, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
6066     SetValueToTaggedArray(VariableType::JS_ANY(), glue, object, valueIndex, value);
6067 }
6068 
NotifyHClassChanged(GateRef glue,GateRef oldHClass,GateRef newHClass)6069 void StubBuilder::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef newHClass)
6070 {
6071     auto env = GetEnvironment();
6072     Label entry(env);
6073     env->SubCfgEntry(&entry);
6074     Label exit(env);
6075     Label isPrototype(env);
6076     BRANCH(IsPrototypeHClass(oldHClass), &isPrototype, &exit);
6077     Bind(&isPrototype);
6078     {
6079         Label notEqualHClass(env);
6080         BRANCH(Equal(oldHClass, newHClass), &exit, &notEqualHClass);
6081         Bind(&notEqualHClass);
6082         {
6083             CallRuntime(glue, RTSTUB_ID(NoticeThroughChainAndRefreshUser), { oldHClass, newHClass });
6084             Jump(&exit);
6085         }
6086     }
6087     Bind(&exit);
6088     env->SubCfgExit();
6089     return;
6090 }
6091 
FastTypeOf(GateRef glue,GateRef obj)6092 GateRef StubBuilder::FastTypeOf(GateRef glue, GateRef obj)
6093 {
6094     auto env = GetEnvironment();
6095     Label entry(env);
6096     env->SubCfgEntry(&entry);
6097     Label exit(env);
6098 
6099     GateRef gConstAddr = LoadPrimitive(VariableType::JS_ANY(), glue,
6100         IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
6101     GateRef undefinedIndex = GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX);
6102     GateRef gConstUndefinedStr = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr, undefinedIndex);
6103     DEFVARIABLE(result, VariableType::JS_POINTER(), gConstUndefinedStr);
6104     Label objIsTrue(env);
6105     Label objNotTrue(env);
6106     Label defaultLabel(env);
6107     GateRef gConstBooleanStr = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6108         GetGlobalConstantOffset(ConstantIndex::BOOLEAN_STRING_INDEX));
6109     BRANCH(TaggedIsTrue(obj), &objIsTrue, &objNotTrue);
6110     Bind(&objIsTrue);
6111     {
6112         result = gConstBooleanStr;
6113         Jump(&exit);
6114     }
6115     Bind(&objNotTrue);
6116     {
6117         Label objIsFalse(env);
6118         Label objNotFalse(env);
6119         BRANCH(TaggedIsFalse(obj), &objIsFalse, &objNotFalse);
6120         Bind(&objIsFalse);
6121         {
6122             result = gConstBooleanStr;
6123             Jump(&exit);
6124         }
6125         Bind(&objNotFalse);
6126         {
6127             Label objIsNull(env);
6128             Label objNotNull(env);
6129             BRANCH(TaggedIsNull(obj), &objIsNull, &objNotNull);
6130             Bind(&objIsNull);
6131             {
6132                 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6133                     GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
6134                 Jump(&exit);
6135             }
6136             Bind(&objNotNull);
6137             {
6138                 Label objIsUndefined(env);
6139                 Label objNotUndefined(env);
6140                 BRANCH(TaggedIsUndefined(obj), &objIsUndefined, &objNotUndefined);
6141                 Bind(&objIsUndefined);
6142                 {
6143                     result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6144                         GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX));
6145                     Jump(&exit);
6146                 }
6147                 Bind(&objNotUndefined);
6148                 Jump(&defaultLabel);
6149             }
6150         }
6151     }
6152     Bind(&defaultLabel);
6153     {
6154         Label objIsHeapObject(env);
6155         Label objNotHeapObject(env);
6156         BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
6157         Bind(&objIsHeapObject);
6158         {
6159             Label objIsString(env);
6160             Label objNotString(env);
6161             BRANCH(IsString(glue, obj), &objIsString, &objNotString);
6162             Bind(&objIsString);
6163             {
6164                 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6165                     GetGlobalConstantOffset(ConstantIndex::STRING_STRING_INDEX));
6166                 Jump(&exit);
6167             }
6168             Bind(&objNotString);
6169             {
6170                 Label objIsSymbol(env);
6171                 Label objNotSymbol(env);
6172                 BRANCH_UNLIKELY(IsSymbol(glue, obj), &objIsSymbol, &objNotSymbol);
6173                 Bind(&objIsSymbol);
6174                 {
6175                     result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6176                         GetGlobalConstantOffset(ConstantIndex::SYMBOL_STRING_INDEX));
6177                     Jump(&exit);
6178                 }
6179                 Bind(&objNotSymbol);
6180                 {
6181                     Label objIsCallable(env);
6182                     Label objNotCallable(env);
6183                     BRANCH_UNLIKELY(IsCallable(glue, obj), &objIsCallable, &objNotCallable);
6184                     Bind(&objIsCallable);
6185                     {
6186                         result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6187                             GetGlobalConstantOffset(ConstantIndex::FUNCTION_STRING_INDEX));
6188                         Jump(&exit);
6189                     }
6190                     Bind(&objNotCallable);
6191                     {
6192                         Label objIsBigInt(env);
6193                         Label objNotBigInt(env);
6194                         BRANCH_UNLIKELY(TaggedObjectIsBigInt(glue, obj), &objIsBigInt, &objNotBigInt);
6195                         Bind(&objIsBigInt);
6196                         {
6197                             result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6198                                 GetGlobalConstantOffset(ConstantIndex::BIGINT_STRING_INDEX));
6199                             Jump(&exit);
6200                         }
6201                         Bind(&objNotBigInt);
6202                         {
6203                             Label objIsNativeModuleFailureInfo(env);
6204                             Label objNotNativeModuleFailureInfo(env);
6205                             BRANCH_UNLIKELY(IsNativeModuleFailureInfo(glue, obj), &objIsNativeModuleFailureInfo,
6206                                 &objNotNativeModuleFailureInfo);
6207                             Bind(&objIsNativeModuleFailureInfo);
6208                             {
6209                                 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6210                                     GetGlobalConstantOffset(ConstantIndex::NATIVE_MODULE_FAILURE_INFO_STRING_INDEX));
6211                                 Jump(&exit);
6212                             }
6213                             Bind(&objNotNativeModuleFailureInfo);
6214                             {
6215                                 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6216                                     GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
6217                                 Jump(&exit);
6218                             }
6219                         }
6220                     }
6221                 }
6222             }
6223         }
6224         Bind(&objNotHeapObject);
6225         {
6226             Label objIsNum(env);
6227             Label objNotNum(env);
6228             BRANCH(TaggedIsNumber(obj), &objIsNum, &objNotNum);
6229             Bind(&objIsNum);
6230             {
6231                 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6232                     GetGlobalConstantOffset(ConstantIndex::NUMBER_STRING_INDEX));
6233                 Jump(&exit);
6234             }
6235             Bind(&objNotNum);
6236             Jump(&exit);
6237         }
6238     }
6239     Bind(&exit);
6240     auto ret = *result;
6241     env->SubCfgExit();
6242     return ret;
6243 }
6244 
InstanceOf(GateRef glue,GateRef object,GateRef target,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)6245 GateRef StubBuilder::InstanceOf(
6246     GateRef glue, GateRef object, GateRef target, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
6247 {
6248     auto env = GetEnvironment();
6249     Label entry(env);
6250     env->SubCfgEntry(&entry);
6251     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6252     Label exit(env);
6253 
6254     // 1.If Type(target) is not Object, throw a TypeError exception.
6255     Label targetIsHeapObject(env);
6256     Label targetIsEcmaObject(env);
6257     Label targetNotEcmaObject(env);
6258     BRANCH(TaggedIsHeapObject(target), &targetIsHeapObject, &targetNotEcmaObject);
6259     Bind(&targetIsHeapObject);
6260     BRANCH(TaggedObjectIsEcmaObject(glue, target), &targetIsEcmaObject, &targetNotEcmaObject);
6261     Bind(&targetNotEcmaObject);
6262     {
6263         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
6264         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6265         result = Exception();
6266         Jump(&exit);
6267     }
6268     Bind(&targetIsEcmaObject);
6269     {
6270         // 2.Let instOfHandler be GetMethod(target, @@hasInstance).
6271         GateRef globalEnv = GetCurrentGlobalEnv();
6272         GateRef hasInstanceSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
6273                                                       GlobalEnv::HASINSTANCE_SYMBOL_INDEX);
6274         GateRef instof = GetMethod(glue, target, hasInstanceSymbol, profileTypeInfo, slotId);
6275 
6276         // 3.ReturnIfAbrupt(instOfHandler).
6277         Label isPendingException(env);
6278         Label noPendingException(env);
6279         BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
6280         Bind(&isPendingException);
6281         {
6282             result = Exception();
6283             Jump(&exit);
6284         }
6285         Bind(&noPendingException);
6286 
6287         // 4.If instOfHandler is not undefined, then
6288         Label instOfNotUndefined(env);
6289         Label instOfIsUndefined(env);
6290         Label fastPath(env);
6291         Label targetNotCallable(env);
6292         BRANCH(TaggedIsUndefined(instof), &instOfIsUndefined, &instOfNotUndefined);
6293         Bind(&instOfNotUndefined);
6294         {
6295             TryFastHasInstance(glue, instof, target, object, &fastPath, &exit, &result, callback);
6296         }
6297         Bind(&instOfIsUndefined);
6298         {
6299             // 5.If IsCallable(glue, target) is false, throw a TypeError exception.
6300             BRANCH(IsCallable(glue, target), &fastPath, &targetNotCallable);
6301             Bind(&targetNotCallable);
6302             {
6303                 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
6304                 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6305                 result = Exception();
6306                 Jump(&exit);
6307             }
6308         }
6309         Bind(&fastPath);
6310         {
6311             // 6.Return ? OrdinaryHasInstance(target, object).
6312             result = OrdinaryHasInstance(glue, target, object);
6313             Jump(&exit);
6314         }
6315     }
6316     Bind(&exit);
6317     auto ret = *result;
6318     env->SubCfgExit();
6319     return ret;
6320 }
6321 
TryFastHasInstance(GateRef glue,GateRef instof,GateRef target,GateRef object,Label * fastPath,Label * exit,Variable * result,ProfileOperation callback)6322 void StubBuilder::TryFastHasInstance(GateRef glue, GateRef instof, GateRef target, GateRef object, Label *fastPath,
6323                                      Label *exit, Variable *result, ProfileOperation callback)
6324 {
6325     auto env = GetEnvironment();
6326 
6327     GateRef globalEnv = GetCurrentGlobalEnv();
6328     GateRef function = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
6329                                          GlobalEnv::HASINSTANCE_FUNCTION_INDEX);
6330 
6331     Label slowPath(env);
6332     Label tryFastPath(env);
6333     Label callExit(env);
6334     GateRef isEqual = IntPtrEqual(instof, function);
6335     BRANCH(isEqual, &tryFastPath, &slowPath);
6336     Bind(&tryFastPath);
6337     Jump(fastPath);
6338     Bind(&slowPath);
6339     {
6340         JSCallArgs callArgs(JSCallMode::CALL_SETTER);
6341         callArgs.callSetterArgs = { target, object };
6342         if (env->IsBaselineBuiltin()) {
6343             DEFVARIABLE(callRes, VariableType::JS_ANY(), Undefined());
6344             CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, &callRes, Circuit::NullGate(), callArgs,
6345                 callback);
6346             callBuilder.JSCallDispatchForBaseline(&callExit);
6347             Bind(&callExit);
6348             result->WriteVariable(FastToBoolean(glue, *callRes));
6349         } else {
6350             CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, nullptr, Circuit::NullGate(), callArgs,
6351                 callback);
6352             GateRef retValue = callBuilder.JSCallDispatch();
6353             result->WriteVariable(FastToBoolean(glue, retValue));
6354         }
6355         Jump(exit);
6356     }
6357 }
6358 
GetMethod(GateRef glue,GateRef obj,GateRef key,GateRef profileTypeInfo,GateRef slotId)6359 GateRef StubBuilder::GetMethod(GateRef glue, GateRef obj, GateRef key, GateRef profileTypeInfo, GateRef slotId)
6360 {
6361     auto env = GetEnvironment();
6362     Label entry(env);
6363     env->SubCfgEntry(&entry);
6364     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6365     Label exit(env);
6366 
6367     StringIdInfo info;
6368     AccessObjectStubBuilder builder(this, GetCurrentGlobalEnv());
6369     GateRef value = builder.LoadObjByName(glue, obj, key, info, profileTypeInfo, slotId, ProfileOperation());
6370 
6371     Label isPendingException(env);
6372     Label noPendingException(env);
6373     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
6374     Bind(&isPendingException);
6375     {
6376         result = Exception();
6377         Jump(&exit);
6378     }
6379     Bind(&noPendingException);
6380     Label valueIsUndefinedOrNull(env);
6381     Label valueNotUndefinedOrNull(env);
6382     BRANCH(TaggedIsUndefinedOrNull(value), &valueIsUndefinedOrNull, &valueNotUndefinedOrNull);
6383     Bind(&valueIsUndefinedOrNull);
6384     {
6385         result = Undefined();
6386         Jump(&exit);
6387     }
6388     Bind(&valueNotUndefinedOrNull);
6389     {
6390         Label valueIsCallable(env);
6391         Label valueNotCallable(env);
6392         Label valueIsHeapObject(env);
6393         BRANCH(TaggedIsHeapObject(value), &valueIsHeapObject, &valueNotCallable);
6394         Bind(&valueIsHeapObject);
6395         BRANCH(IsCallable(glue, value), &valueIsCallable, &valueNotCallable);
6396         Bind(&valueNotCallable);
6397         {
6398             GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(NonCallable));
6399             CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6400             result = Exception();
6401             Jump(&exit);
6402         }
6403         Bind(&valueIsCallable);
6404         {
6405             result = value;
6406             Jump(&exit);
6407         }
6408     }
6409     Bind(&exit);
6410     auto ret = *result;
6411     env->SubCfgExit();
6412     return ret;
6413 }
6414 
FastGetPropertyByName(GateRef glue,GateRef obj,GateRef key,ProfileOperation callback,GateRef hir)6415 GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key,
6416                                            ProfileOperation callback, GateRef hir)
6417 {
6418     auto env = GetEnvironment();
6419     Label entry(env);
6420     env->SubCfgEntry(&entry);
6421     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6422     Label exit(env);
6423     Label checkResult(env);
6424     Label fastpath(env);
6425     Label slowpath(env);
6426 
6427     BRANCH(TaggedIsHeapObject(obj), &fastpath, &slowpath);
6428     Bind(&fastpath);
6429     {
6430         result = GetPropertyByName(glue, obj, key, Circuit::NullGate(), callback, True(), false, hir);
6431         BRANCH(TaggedIsHole(*result), &slowpath, &exit);
6432     }
6433     Bind(&slowpath);
6434     {
6435         result = CallRuntime(glue, RTSTUB_ID(LoadICByName), { Undefined(), obj, key, IntToTaggedInt(Int32(0)) });
6436         Jump(&exit);
6437     }
6438     Bind(&exit);
6439     auto ret = *result;
6440     env->SubCfgExit();
6441     return ret;
6442 }
6443 
FastGetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,ProfileOperation callback,GateRef hir)6444 GateRef StubBuilder::FastGetPropertyByIndex(GateRef glue, GateRef obj,
6445                                             GateRef index, ProfileOperation callback, GateRef hir)
6446 {
6447     auto env = GetEnvironment();
6448     Label entry(env);
6449     env->SubCfgEntry(&entry);
6450     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6451     Label exit(env);
6452     Label fastPath(env);
6453     Label slowPath(env);
6454 
6455     BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
6456     Bind(&fastPath);
6457     {
6458         result = GetPropertyByIndex(glue, obj, index, callback, hir);
6459         Label notHole(env);
6460         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
6461     }
6462     Bind(&slowPath);
6463     {
6464         result = CallRuntime(glue, RTSTUB_ID(LdObjByIndex),
6465             { obj, IntToTaggedInt(index), TaggedFalse(), Undefined() });
6466         Jump(&exit);
6467     }
6468     Bind(&exit);
6469     auto ret = *result;
6470     env->SubCfgExit();
6471     return ret;
6472 }
6473 
FastSetPropertyByName(GateRef glue,GateRef obj,GateRef key,GateRef value,ProfileOperation callback)6474 void StubBuilder::FastSetPropertyByName(GateRef glue, GateRef obj, GateRef key, GateRef value,
6475     ProfileOperation callback)
6476 {
6477     auto env = GetEnvironment();
6478     Label entry(env);
6479     env->SubCfgEntry(&entry);
6480     DEFVARIABLE(keyVar, VariableType::JS_ANY(), key);
6481     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6482     DEFVARIABLE(isInternal, VariableType::BOOL(), True());
6483     Label exit(env);
6484     Label fastPath(env);
6485     Label slowPath(env);
6486     BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
6487     Bind(&fastPath);
6488     {
6489         Label isString(env);
6490         Label getByName(env);
6491         Label isInternalString(env);
6492         Label notIntenalString(env);
6493         BRANCH(TaggedIsString(glue, *keyVar), &isString, &getByName);
6494         Bind(&isString);
6495         {
6496             BRANCH(IsInternalString(*keyVar), &isInternalString, &notIntenalString);
6497             Bind(&isInternalString);
6498             Jump(&getByName);
6499             Bind(&notIntenalString);
6500             {
6501             #if ENABLE_NEXT_OPTIMIZATION
6502                 GateRef res = CallRuntime(glue, RTSTUB_ID(GetOrInternStringFromHashTrieTable), { *keyVar });
6503                 keyVar = res;
6504                 Jump(&getByName);
6505             #else
6506                 Label notFind(env);
6507                 Label find(env);
6508                 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *keyVar });
6509                 BRANCH(TaggedIsHole(res), &notFind, &find);
6510                 Bind(&notFind);
6511                 {
6512                     keyVar = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { key });
6513                     isInternal = False();
6514                     Jump(&getByName);
6515                 }
6516                 Bind(&find);
6517                 {
6518                     keyVar = res;
6519                     Jump(&getByName);
6520                 }
6521             #endif
6522             }
6523         }
6524         Bind(&getByName);
6525 
6526         result = SetPropertyByName(glue, obj, *keyVar, value, false, *isInternal, callback, true);
6527         Label notHole(env);
6528         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
6529     }
6530     Bind(&slowPath);
6531     {
6532         result = CallRuntime(glue, RTSTUB_ID(StObjByValue), { obj, *keyVar, value });
6533         Jump(&exit);
6534     }
6535     Bind(&exit);
6536     env->SubCfgExit();
6537 }
6538 
FastSetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,GateRef value)6539 void StubBuilder::FastSetPropertyByIndex(GateRef glue, GateRef obj, GateRef index, GateRef value)
6540 {
6541     auto env = GetEnvironment();
6542     Label entry(env);
6543     env->SubCfgEntry(&entry);
6544     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6545     Label exit(env);
6546     Label fastPath(env);
6547     Label slowPath(env);
6548 
6549     BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
6550     Bind(&fastPath);
6551     {
6552         result = SetPropertyByIndex(glue, obj, index, value, false);
6553         Label notHole(env);
6554         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
6555     }
6556     Bind(&slowPath);
6557     {
6558         result = CallRuntime(glue, RTSTUB_ID(StObjByIndex),
6559             { obj, IntToTaggedInt(index), value });
6560         Jump(&exit);
6561     }
6562     Bind(&exit);
6563     env->SubCfgExit();
6564 }
6565 
GetCtorPrototype(GateRef glue,GateRef ctor)6566 GateRef StubBuilder::GetCtorPrototype(GateRef glue, GateRef ctor)
6567 {
6568     auto env = GetEnvironment();
6569     Label entry(env);
6570     env->SubCfgEntry(&entry);
6571     DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
6572     Label exit(env);
6573     Label isHClass(env);
6574     Label isPrototype(env);
6575     Label isHeapObject(env);
6576     Label notHeapObject(env);
6577 
6578     GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), glue, ctor, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
6579     BRANCH(TaggedIsHeapObject(ctorProtoOrHC), &isHeapObject, &notHeapObject);
6580     Bind(&notHeapObject);
6581     {
6582         // If go slow path, return hole.
6583         constructorPrototype = Hole();
6584         Jump(&exit);
6585     }
6586     Bind(&isHeapObject);
6587     BRANCH(IsJSHClass(glue, ctorProtoOrHC), &isHClass, &isPrototype);
6588     Bind(&isHClass);
6589     {
6590         constructorPrototype = GetPrototypeFromHClass(glue, ctorProtoOrHC);
6591         Jump(&exit);
6592     }
6593     Bind(&isPrototype);
6594     {
6595         constructorPrototype = ctorProtoOrHC;
6596         Jump(&exit);
6597     }
6598 
6599     Bind(&exit);
6600     auto ret = *constructorPrototype;
6601     env->SubCfgExit();
6602     return ret;
6603 }
6604 
HasFunctionPrototype(GateRef glue,GateRef ctor)6605 GateRef StubBuilder::HasFunctionPrototype(GateRef glue, GateRef ctor)
6606 {
6607     auto env = GetEnvironment();
6608     Label entry(env);
6609     env->SubCfgEntry(&entry);
6610     DEFVARIABLE(result, VariableType::BOOL(), True());
6611     Label exit(env);
6612     Label isHole(env);
6613 
6614     GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), glue, ctor, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
6615     BRANCH(TaggedIsHole(ctorProtoOrHC), &isHole, &exit);
6616     Bind(&isHole);
6617     {
6618         result = False();
6619         Jump(&exit);
6620     }
6621     Bind(&exit);
6622     auto ret = *result;
6623     env->SubCfgExit();
6624     return ret;
6625 }
6626 
OrdinaryHasInstance(GateRef glue,GateRef target,GateRef obj)6627 GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj)
6628 {
6629     auto env = GetEnvironment();
6630     Label entry(env);
6631     env->SubCfgEntry(&entry);
6632     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6633     Label exit(env);
6634     DEFVARIABLE(object, VariableType::JS_ANY(), obj);
6635 
6636     // 1. If IsCallable(glue, C) is false, return false.
6637     Label targetIsCallable(env);
6638     Label targetNotCallable(env);
6639     BRANCH(IsCallable(glue, target), &targetIsCallable, &targetNotCallable);
6640     Bind(&targetNotCallable);
6641     {
6642         result = TaggedFalse();
6643         Jump(&exit);
6644     }
6645     Bind(&targetIsCallable);
6646     {
6647         // 2. If C has a [[BoundTargetFunction]] internal slot, then
6648         //    a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
6649         //    b. Return InstanceofOperator(O,BC)  (see 12.9.4).
6650         Label targetIsBoundFunction(env);
6651         Label targetNotBoundFunction(env);
6652         BRANCH(IsBoundFunction(glue, target), &targetIsBoundFunction, &targetNotBoundFunction);
6653         Bind(&targetIsBoundFunction);
6654         {
6655             GateRef boundTarget = Load(VariableType::JS_ANY(), glue, target, IntPtr(JSBoundFunction::BOUND_TARGET_OFFSET));
6656             result = CallRuntime(glue, RTSTUB_ID(InstanceOf), { obj, boundTarget });
6657             Jump(&exit);
6658         }
6659         Bind(&targetNotBoundFunction);
6660         {
6661             // 3. If Type(O) is not Object, return false
6662             Label objIsHeapObject(env);
6663             Label objIsEcmaObject(env);
6664             Label objNotEcmaObject(env);
6665             BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotEcmaObject);
6666             Bind(&objIsHeapObject);
6667             BRANCH(TaggedObjectIsEcmaObject(glue, obj), &objIsEcmaObject, &objNotEcmaObject);
6668             Bind(&objNotEcmaObject);
6669             {
6670                 result = TaggedFalse();
6671                 Jump(&exit);
6672             }
6673             Bind(&objIsEcmaObject);
6674             {
6675                 // 4. Let P be Get(C, "prototype").
6676                 Label getCtorProtoSlowPath(env);
6677                 Label ctorIsJSFunction(env);
6678                 Label gotCtorPrototype(env);
6679                 DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
6680                 BRANCH(IsJSFunction(glue, target), &ctorIsJSFunction, &getCtorProtoSlowPath);
6681                 Bind(&ctorIsJSFunction);
6682                 {
6683                     Label getCtorProtoFastPath(env);
6684                     GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), glue, target,
6685                                                  IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
6686 
6687                     BRANCH(TaggedIsHole(ctorProtoOrHC), &getCtorProtoSlowPath, &getCtorProtoFastPath);
6688                     Bind(&getCtorProtoFastPath);
6689                     {
6690                         constructorPrototype = GetCtorPrototype(glue, target);
6691                         BRANCH(TaggedIsHole(*constructorPrototype), &getCtorProtoSlowPath, &gotCtorPrototype);
6692                     }
6693                 }
6694                 Bind(&getCtorProtoSlowPath);
6695                 {
6696                     auto prototypeString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
6697                                                                   ConstantIndex::PROTOTYPE_STRING_INDEX);
6698                     constructorPrototype = FastGetPropertyByName(glue, target, prototypeString, ProfileOperation());
6699                     Jump(&gotCtorPrototype);
6700                 }
6701                 Bind(&gotCtorPrototype);
6702 
6703                 // 5. ReturnIfAbrupt(P).
6704                 // no throw exception, so needn't return
6705                 Label isPendingException(env);
6706                 Label noPendingException(env);
6707                 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
6708                 Bind(&isPendingException);
6709                 {
6710                     result = Exception();
6711                     Jump(&exit);
6712                 }
6713                 Bind(&noPendingException);
6714 
6715                 // 6. If Type(P) is not Object, throw a TypeError exception.
6716                 Label constructorPrototypeIsHeapObject(env);
6717                 Label constructorPrototypeIsEcmaObject(env);
6718                 Label constructorPrototypeNotEcmaObject(env);
6719                 BRANCH(TaggedIsHeapObject(*constructorPrototype), &constructorPrototypeIsHeapObject,
6720                     &constructorPrototypeNotEcmaObject);
6721                 Bind(&constructorPrototypeIsHeapObject);
6722                 BRANCH(TaggedObjectIsEcmaObject(glue, *constructorPrototype), &constructorPrototypeIsEcmaObject,
6723                     &constructorPrototypeNotEcmaObject);
6724                 Bind(&constructorPrototypeNotEcmaObject);
6725                 {
6726                     GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
6727                     CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6728                     result = Exception();
6729                     Jump(&exit);
6730                 }
6731                 Bind(&constructorPrototypeIsEcmaObject);
6732                 {
6733                     // 7. Repeat
6734                     //    a.Let O be O.[[GetPrototypeOf]]().
6735                     //    b.ReturnIfAbrupt(O).
6736                     //    c.If O is null, return false.
6737                     //    d.If SameValue(P, O) is true, return true.
6738                     Label loopHead(env);
6739                     Label loopEnd(env);
6740                     Label afterLoop(env);
6741                     Label strictEqual1(env);
6742                     Label notStrictEqual1(env);
6743                     Label shouldReturn(env);
6744                     Label shouldContinue(env);
6745 
6746                     BRANCH(TaggedIsNull(*object), &afterLoop, &loopHead);
6747                     LoopBegin(&loopHead);
6748                     {
6749                         GateRef isEqual = SameValue(glue, *object, *constructorPrototype);
6750 
6751                         BRANCH(isEqual, &strictEqual1, &notStrictEqual1);
6752                         Bind(&strictEqual1);
6753                         {
6754                             result = TaggedTrue();
6755                             Jump(&exit);
6756                         }
6757                         Bind(&notStrictEqual1);
6758                         {
6759                             object = GetPrototype(glue, *object);
6760 
6761                             BRANCH(HasPendingException(glue), &shouldReturn, &shouldContinue);
6762                             Bind(&shouldReturn);
6763                             {
6764                                 result = Exception();
6765                                 Jump(&exit);
6766                             }
6767                         }
6768                         Bind(&shouldContinue);
6769                         BRANCH(TaggedIsNull(*object), &afterLoop, &loopEnd);
6770                     }
6771                     Bind(&loopEnd);
6772                     LoopEndWithCheckSafePoint(&loopHead, env, glue);
6773                     Bind(&afterLoop);
6774                     {
6775                         result = TaggedFalse();
6776                         Jump(&exit);
6777                     }
6778                 }
6779             }
6780         }
6781     }
6782     Bind(&exit);
6783     auto ret = *result;
6784     env->SubCfgExit();
6785     return ret;
6786 }
6787 
SameValue(GateRef glue,GateRef left,GateRef right)6788 GateRef StubBuilder::SameValue(GateRef glue, GateRef left, GateRef right)
6789 {
6790     auto env = GetEnvironment();
6791     Label entry(env);
6792     env->SubCfgEntry(&entry);
6793     DEFVARIABLE(result, VariableType::BOOL(), False());
6794     Label exit(env);
6795     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6796     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6797     Label strictEqual(env);
6798     Label stringEqualCheck(env);
6799     Label stringCompare(env);
6800     Label bigIntEqualCheck(env);
6801     Label numberEqualCheck1(env);
6802 
6803     BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6804     Bind(&strictEqual);
6805     {
6806         result = True();
6807         Jump(&exit);
6808     }
6809     Bind(&numberEqualCheck1);
6810     {
6811         Label leftIsNumber(env);
6812         Label leftIsNotNumber(env);
6813         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6814         Bind(&leftIsNumber);
6815         {
6816             Label rightIsNumber(env);
6817             BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6818             Bind(&rightIsNumber);
6819             {
6820                 Label numberEqualCheck2(env);
6821                 Label leftIsInt(env);
6822                 Label leftNotInt(env);
6823                 Label getRight(env);
6824 
6825                 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6826                 Bind(&leftIsInt);
6827                 {
6828                     Label fastPath(env);
6829                     Label slowPath(env);
6830                     BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6831                     Bind(&fastPath);
6832                     {
6833                         result = False();
6834                         Jump(&exit);
6835                     }
6836                     Bind(&slowPath);
6837                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6838                     doubleRight = GetDoubleOfTDouble(right);
6839                     Jump(&numberEqualCheck2);
6840                 }
6841                 Bind(&leftNotInt);
6842                 {
6843                     doubleLeft = GetDoubleOfTDouble(left);
6844                     Jump(&getRight);
6845                 }
6846                 Bind(&getRight);
6847                 {
6848                     Label rightIsInt(env);
6849                     Label rightNotInt(env);
6850                     BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6851                     Bind(&rightIsInt);
6852                     {
6853                         doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6854                         Jump(&numberEqualCheck2);
6855                     }
6856                     Bind(&rightNotInt);
6857                     {
6858                         doubleRight = GetDoubleOfTDouble(right);
6859                         Jump(&numberEqualCheck2);
6860                     }
6861                 }
6862                 Bind(&numberEqualCheck2);
6863                 {
6864                     Label boolAndCheck(env);
6865                     Label signbitCheck(env);
6866                     BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &signbitCheck, &boolAndCheck);
6867                     Bind(&signbitCheck);
6868                     {
6869                         GateRef leftEncoding = CastDoubleToInt64(*doubleLeft);
6870                         GateRef RightEncoding = CastDoubleToInt64(*doubleRight);
6871                         Label leftIsMinusZero(env);
6872                         Label leftNotMinusZero(env);
6873                         BRANCH(Int64Equal(leftEncoding, Int64(base::MINUS_ZERO_BITS)),
6874                             &leftIsMinusZero, &leftNotMinusZero);
6875                         Bind(&leftIsMinusZero);
6876                         {
6877                             Label rightIsMinusZero(env);
6878                             BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &rightIsMinusZero, &exit);
6879                             Bind(&rightIsMinusZero);
6880                             {
6881                                 result = True();
6882                                 Jump(&exit);
6883                             }
6884                         }
6885                         Bind(&leftNotMinusZero);
6886                         {
6887                             Label rightNotMinusZero(env);
6888                             BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &exit, &rightNotMinusZero);
6889                             Bind(&rightNotMinusZero);
6890                             {
6891                                 result = True();
6892                                 Jump(&exit);
6893                             }
6894                         }
6895                     }
6896                     Bind(&boolAndCheck);
6897                     {
6898                         GateRef doubleLeftVal = *doubleLeft;
6899                         GateRef doubleRightVal = *doubleRight;
6900                         result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
6901                             .And(DoubleIsNAN(doubleRightVal)).Done();
6902                         Jump(&exit);
6903                     }
6904                 }
6905             }
6906         }
6907         Bind(&leftIsNotNumber);
6908         BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
6909         Bind(&stringEqualCheck);
6910         BRANCH(BothAreString(glue, left, right), &stringCompare, &bigIntEqualCheck);
6911         Bind(&stringCompare);
6912         {
6913             result = FastStringEqual(glue, left, right);
6914             Jump(&exit);
6915         }
6916         Bind(&bigIntEqualCheck);
6917         {
6918             Label leftIsBigInt(env);
6919             Label leftIsNotBigInt(env);
6920             BRANCH(TaggedIsBigInt(glue, left), &leftIsBigInt, &exit);
6921             Bind(&leftIsBigInt);
6922             {
6923                 Label rightIsBigInt(env);
6924                 BRANCH(TaggedIsBigInt(glue, right), &rightIsBigInt, &exit);
6925                 Bind(&rightIsBigInt);
6926                 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
6927                 Jump(&exit);
6928             }
6929         }
6930     }
6931     Bind(&exit);
6932     auto ret = *result;
6933     env->SubCfgExit();
6934     return ret;
6935 }
6936 
SameValueZero(GateRef glue,GateRef left,GateRef right)6937 GateRef StubBuilder::SameValueZero(GateRef glue, GateRef left, GateRef right)
6938 {
6939     auto env = GetEnvironment();
6940     Label entry(env);
6941     env->SubCfgEntry(&entry);
6942     DEFVARIABLE(result, VariableType::BOOL(), False());
6943     Label exit(env);
6944     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6945     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6946     Label strictEqual(env);
6947     Label stringEqualCheck(env);
6948     Label stringCompare(env);
6949     Label bigIntEqualCheck(env);
6950     Label numberEqualCheck1(env);
6951 
6952     BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6953     Bind(&strictEqual);
6954     {
6955         result = True();
6956         Jump(&exit);
6957     }
6958     Bind(&numberEqualCheck1);
6959     {
6960         Label leftIsNumber(env);
6961         Label leftIsNotNumber(env);
6962         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6963         Bind(&leftIsNumber);
6964         {
6965             Label rightIsNumber(env);
6966             BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6967             Bind(&rightIsNumber);
6968             {
6969                 Label numberEqualCheck2(env);
6970                 Label leftIsInt(env);
6971                 Label leftNotInt(env);
6972                 Label getRight(env);
6973                 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6974                 Bind(&leftIsInt);
6975                 {
6976                     Label fastPath(env);
6977                     Label slowPath(env);
6978                     BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6979                     Bind(&fastPath);
6980                     {
6981                         result = False();
6982                         Jump(&exit);
6983                     }
6984                     Bind(&slowPath);
6985                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6986                     doubleRight = GetDoubleOfTDouble(right);
6987                     Jump(&numberEqualCheck2);
6988                 }
6989                 Bind(&leftNotInt);
6990                 {
6991                     doubleLeft = GetDoubleOfTDouble(left);
6992                     Jump(&getRight);
6993                 }
6994                 Bind(&getRight);
6995                 {
6996                     Label rightIsInt(env);
6997                     Label rightNotInt(env);
6998                     BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6999                     Bind(&rightIsInt);
7000                     {
7001                         doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7002                         Jump(&numberEqualCheck2);
7003                     }
7004                     Bind(&rightNotInt);
7005                     {
7006                         doubleRight = GetDoubleOfTDouble(right);
7007                         Jump(&numberEqualCheck2);
7008                     }
7009                 }
7010                 Bind(&numberEqualCheck2);
7011                 {
7012                     Label nanCheck(env);
7013                     Label doubleEqual(env);
7014                     BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &doubleEqual, &nanCheck);
7015                     Bind(&doubleEqual);
7016                     {
7017                         result = True();
7018                         Jump(&exit);
7019                     }
7020                     Bind(&nanCheck);
7021                     {
7022                         GateRef doubleLeftVal = *doubleLeft;
7023                         GateRef doubleRightVal = *doubleRight;
7024                         result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
7025                             .And(DoubleIsNAN(doubleRightVal)).Done();
7026                         Jump(&exit);
7027                     }
7028                 }
7029             }
7030         }
7031         Bind(&leftIsNotNumber);
7032         BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
7033         Bind(&stringEqualCheck);
7034         BRANCH(BothAreString(glue, left, right), &stringCompare, &bigIntEqualCheck);
7035         Bind(&stringCompare);
7036         {
7037             result = FastStringEqual(glue, left, right);
7038             Jump(&exit);
7039         }
7040         Bind(&bigIntEqualCheck);
7041         {
7042             Label leftIsBigInt(env);
7043             Label leftIsNotBigInt(env);
7044             BRANCH(TaggedIsBigInt(glue, left), &leftIsBigInt, &exit);
7045             Bind(&leftIsBigInt);
7046             {
7047                 Label rightIsBigInt(env);
7048                 BRANCH(TaggedIsBigInt(glue, right), &rightIsBigInt, &exit);
7049                 Bind(&rightIsBigInt);
7050                 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntSameValueZero), { left, right });
7051                 Jump(&exit);
7052             }
7053         }
7054     }
7055     Bind(&exit);
7056     auto ret = *result;
7057     env->SubCfgExit();
7058     return ret;
7059 }
7060 
FastStringEqual(GateRef glue,GateRef left,GateRef right)7061 GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right)
7062 {
7063     auto env = GetEnvironment();
7064     Label entry(env);
7065     env->SubCfgEntry(&entry);
7066     DEFVARIABLE(result, VariableType::BOOL(), False());
7067     Label exit(env);
7068     Label hashcodeCompare(env);
7069     Label contentsCompare(env);
7070     Label lenEqualOneCheck(env);
7071     Label lenIsOne(env);
7072     BRANCH(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &lenEqualOneCheck, &exit);
7073     Bind(&lenEqualOneCheck);
7074     BRANCH(Int32Equal(GetLengthFromString(left), Int32(1)), &lenIsOne, &hashcodeCompare);
7075     Bind(&lenIsOne);
7076     {
7077         Label leftFlattenFastPath(env);
7078         FlatStringStubBuilder leftFlat(this);
7079         leftFlat.FlattenString(glue, left, &leftFlattenFastPath);
7080         Bind(&leftFlattenFastPath);
7081         {
7082             Label rightFlattenFastPath(env);
7083             FlatStringStubBuilder rightFlat(this);
7084             rightFlat.FlattenString(glue, right, &rightFlattenFastPath);
7085             Bind(&rightFlattenFastPath);
7086             {
7087                 BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
7088                 StringInfoGateRef leftStrInfoGate(&leftFlat);
7089                 StringInfoGateRef rightStrInfoGate(&rightFlat);
7090                 GateRef leftStrToInt = stringBuilder.StringAt(glue, leftStrInfoGate, Int32(0));
7091                 GateRef rightStrToInt = stringBuilder.StringAt(glue, rightStrInfoGate, Int32(0));
7092                 result = Equal(leftStrToInt, rightStrToInt);
7093                 Jump(&exit);
7094             }
7095         }
7096     }
7097 
7098     Bind(&hashcodeCompare);
7099     Label leftNotNeg(env);
7100     GateRef leftHash = TryGetHashcodeFromString(left);
7101     GateRef rightHash = TryGetHashcodeFromString(right);
7102     BRANCH(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg);
7103     Bind(&leftNotNeg);
7104     {
7105         Label rightNotNeg(env);
7106         BRANCH(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg);
7107         Bind(&rightNotNeg);
7108         BRANCH(Int64Equal(leftHash, rightHash), &contentsCompare, &exit);
7109     }
7110 
7111     Bind(&contentsCompare);
7112     {
7113         GateRef stringEqual = CallRuntime(glue, RTSTUB_ID(StringEqual), { left, right });
7114         result = Equal(stringEqual, TaggedTrue());
7115         Jump(&exit);
7116     }
7117 
7118     Bind(&exit);
7119     auto ret = *result;
7120     env->SubCfgExit();
7121     return ret;
7122 }
7123 
7124 // init is -1 if leftLength  < rightLength;
7125 //          0 if leftLength == rightLength;
7126 //         +1 if leftLength  > rightLength.
StringCompareContents(GateRef glue,GateRef left,GateRef right,GateRef init,GateRef minLength)7127 GateRef StubBuilder::StringCompareContents(GateRef glue, GateRef left, GateRef right, GateRef init, GateRef minLength)
7128 {
7129     auto env = GetEnvironment();
7130     Label entry(env);
7131     env->SubCfgEntry(&entry);
7132     Label exit(env);
7133 
7134     Label loopHead(env);
7135     Label loopEnd(env);
7136     Label loopBody(env);
7137     Label leftFlattenFastPath(env);
7138     DEFVARIABLE(result, VariableType::INT32(), init);
7139 
7140     FlatStringStubBuilder leftFlat(this);
7141     leftFlat.FlattenString(glue, left, &leftFlattenFastPath);
7142     Bind(&leftFlattenFastPath);
7143 
7144     Label rightFlattenFastPath(env);
7145     FlatStringStubBuilder rightFlat(this);
7146     rightFlat.FlattenString(glue, right, &rightFlattenFastPath);
7147     Bind(&rightFlattenFastPath);
7148 
7149     StringInfoGateRef leftStrInfoGate(&leftFlat);
7150     StringInfoGateRef rightStrInfoGate(&rightFlat);
7151     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
7152     GateRef isBothUtf8 = LogicAndBuilder(env).And(IsUtf8String(leftStrInfoGate.GetString()))
7153                                              .And(IsUtf8String(rightStrInfoGate.GetString())).Done();
7154     Label bothUtf8(env);
7155     Label slowCompare(env);
7156     BRANCH_LIKELY(isBothUtf8, &bothUtf8, &slowCompare);
7157     Bind(&bothUtf8);
7158     {
7159         GateRef leftData = GetNormalStringData(glue, leftStrInfoGate);
7160         GateRef rightData = GetNormalStringData(glue, rightStrInfoGate);
7161         Label utf8LoopHead(env);
7162         Label utf8LoopEnd(env);
7163         Label utf8LoopBody(env);
7164         Jump(&utf8LoopHead);
7165         LoopBegin(&utf8LoopHead);
7166         {
7167             BRANCH(Int32UnsignedLessThan(*i, minLength), &utf8LoopBody, &exit);
7168             Bind(&utf8LoopBody);
7169             {
7170                 GateRef leftChar = LoadPrimitive(VariableType::INT8(), leftData, *i);
7171                 GateRef rightChar = LoadPrimitive(VariableType::INT8(), rightData, *i);
7172                 Label notEqual(env);
7173                 BRANCH_NO_WEIGHT(Int8Equal(leftChar, rightChar), &utf8LoopEnd, &notEqual);
7174                 Bind(&notEqual);
7175                 {
7176                     Label leftIsLess(env);
7177                     Label rightIsLess(env);
7178                     BRANCH_NO_WEIGHT(Int32LessThan(ZExtInt8ToInt32(leftChar), ZExtInt8ToInt32(rightChar)), &leftIsLess, &rightIsLess);
7179                     Bind(&leftIsLess);
7180                     {
7181                         result = Int32(-1);
7182                         Jump(&exit);
7183                     }
7184                     Bind(&rightIsLess);
7185                     {
7186                         result = Int32(1);
7187                         Jump(&exit);
7188                     }
7189                 }
7190             }
7191             Bind(&utf8LoopEnd);
7192             i = Int32Add(*i, Int32(1));
7193             LoopEnd(&utf8LoopHead);
7194         }
7195     }
7196     Bind(&slowCompare);
7197     Jump(&loopHead);
7198     LoopBegin(&loopHead);
7199     {
7200         BRANCH(Int32UnsignedLessThan(*i, minLength), &loopBody, &exit);
7201         Bind(&loopBody);
7202         {
7203             BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
7204             GateRef leftStrToInt = stringBuilder.StringAt(glue, leftStrInfoGate, *i);
7205             GateRef rightStrToInt = stringBuilder.StringAt(glue, rightStrInfoGate, *i);
7206             Label notEqual(env);
7207             BRANCH_NO_WEIGHT(Int32Equal(leftStrToInt, rightStrToInt), &loopEnd, &notEqual);
7208             Bind(&notEqual);
7209             {
7210                 Label leftIsLess(env);
7211                 Label rightIsLess(env);
7212                 BRANCH_NO_WEIGHT(Int32UnsignedLessThan(leftStrToInt, rightStrToInt), &leftIsLess, &rightIsLess);
7213                 Bind(&leftIsLess);
7214                 {
7215                     result = Int32(-1);
7216                     Jump(&exit);
7217                 }
7218                 Bind(&rightIsLess);
7219                 {
7220                     result = Int32(1);
7221                     Jump(&exit);
7222                 }
7223             }
7224         }
7225         Bind(&loopEnd);
7226         i = Int32Add(*i, Int32(1));
7227         LoopEnd(&loopHead);
7228     }
7229     Bind(&exit);
7230     auto ret = *result;
7231     env->SubCfgExit();
7232     return ret;
7233 }
7234 
FastStringEqualWithoutRTStub(GateRef glue,GateRef left,GateRef right)7235 GateRef StubBuilder::FastStringEqualWithoutRTStub(GateRef glue, GateRef left, GateRef right)
7236 {
7237     auto env = GetEnvironment();
7238     Label entry(env);
7239     env->SubCfgEntry(&entry);
7240     DEFVARIABLE(result, VariableType::BOOL(), False());
7241     Label exit(env);
7242     Label hashcodeCompare(env);
7243     Label contentsCompare(env);
7244     Label lenIsOne(env);
7245 
7246     GateRef leftLen = GetLengthFromString(left);
7247     GateRef rightLen = GetLengthFromString(right);
7248     BRANCH(Int32Equal(leftLen, rightLen), &hashcodeCompare, &exit);
7249     Bind(&hashcodeCompare);
7250     Label leftNotNeg(env);
7251     GateRef leftHash = TryGetHashcodeFromString(left);
7252     GateRef rightHash = TryGetHashcodeFromString(right);
7253     BRANCH(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg);
7254     Bind(&leftNotNeg);
7255     {
7256         Label rightNotNeg(env);
7257         BRANCH(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg);
7258         Bind(&rightNotNeg);
7259         BRANCH(Int64Equal(leftHash, rightHash), &contentsCompare, &exit);
7260     }
7261 
7262     Bind(&contentsCompare);
7263     {
7264         GateRef compareResult = StringCompareContents(glue, left, right, Int32(0), Int32Min(leftLen, rightLen));
7265         result = Equal(Int32(0), compareResult);
7266         Jump(&exit);
7267     }
7268 
7269     Bind(&exit);
7270     auto ret = *result;
7271     env->SubCfgExit();
7272     return ret;
7273 }
7274 
StringCompare(GateRef glue,GateRef left,GateRef right)7275 GateRef StubBuilder::StringCompare(GateRef glue, GateRef left, GateRef right)
7276 {
7277     auto env = GetEnvironment();
7278     Label entry(env);
7279     env->SubCfgEntry(&entry);
7280     Label exit(env);
7281     Label compareContent(env);
7282     Label compareLength(env);
7283     GateRef leftLength = GetLengthFromString(left);
7284     GateRef rightLength = GetLengthFromString(right);
7285     DEFVARIABLE(minLength, VariableType::INT32(), leftLength);
7286     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
7287     BRANCH_NO_WEIGHT(Int32Equal(leftLength, rightLength), &compareContent, &compareLength);
7288     Bind(&compareLength);
7289     {
7290         Label rightLengthIsLess(env);
7291         Label leftLengthIsLess(env);
7292         BRANCH(Int32GreaterThan(leftLength, rightLength), &rightLengthIsLess, &leftLengthIsLess);
7293         Bind(&rightLengthIsLess);
7294         {
7295             result = Int32(1);
7296             minLength = rightLength;
7297             Jump(&compareContent);
7298         }
7299         Bind(&leftLengthIsLess);
7300         {
7301             result = Int32(-1);
7302             minLength = leftLength;
7303             Jump(&compareContent);
7304         }
7305     }
7306 
7307     Bind(&compareContent);
7308     result = StringCompareContents(glue, left, right, *result, *minLength);
7309     Jump(&exit);
7310 
7311     Bind(&exit);
7312     auto ret = *result;
7313     env->SubCfgExit();
7314     return ret;
7315 }
7316 
FastStrictEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7317 GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7318 {
7319     auto env = GetEnvironment();
7320     Label entry(env);
7321     env->SubCfgEntry(&entry);
7322     DEFVARIABLE(result, VariableType::BOOL(), False());
7323     Label leftIsNumber(env);
7324     Label leftIsNotNumber(env);
7325     Label sameVariableCheck(env);
7326     Label stringEqualCheck(env);
7327     Label stringCompare(env);
7328     Label updataPGOTypeWithInternString(env);
7329     Label bigIntEqualCheck(env);
7330     Label undefinedCheck(env);
7331     Label exit(env);
7332     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
7333     Bind(&leftIsNumber);
7334     {
7335         Label rightIsNumber(env);
7336         BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
7337         Bind(&rightIsNumber);
7338         {
7339             DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
7340             DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
7341             DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType()));
7342             Label leftIsInt(env);
7343             Label leftNotInt(env);
7344             Label getRight(env);
7345             Label numberEqualCheck(env);
7346 
7347             BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
7348             Bind(&leftIsInt);
7349             {
7350                 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7351                 Jump(&getRight);
7352             }
7353             Bind(&leftNotInt);
7354             {
7355                 curType = TaggedInt(PGOSampleType::DoubleType());
7356                 doubleLeft = GetDoubleOfTDouble(left);
7357                 Jump(&getRight);
7358             }
7359             Bind(&getRight);
7360             {
7361                 Label rightIsInt(env);
7362                 Label rightNotInt(env);
7363                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
7364                 Bind(&rightIsInt);
7365                 {
7366                     GateRef type = TaggedInt(PGOSampleType::IntType());
7367                     COMBINE_TYPE_CALL_BACK(curType, type);
7368                     doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7369                     Jump(&numberEqualCheck);
7370                 }
7371                 Bind(&rightNotInt);
7372                 {
7373                     GateRef type = TaggedInt(PGOSampleType::DoubleType());
7374                     COMBINE_TYPE_CALL_BACK(curType, type);
7375                     doubleRight = GetDoubleOfTDouble(right);
7376                     Jump(&numberEqualCheck);
7377                 }
7378             }
7379             Bind(&numberEqualCheck);
7380             {
7381                 Label doubleEqualCheck(env);
7382                 BRANCH(BitOr(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight)), &exit, &doubleEqualCheck);
7383                 Bind(&doubleEqualCheck);
7384                 {
7385                     result = DoubleEqual(*doubleLeft, *doubleRight);
7386                     Jump(&exit);
7387                 }
7388             }
7389         }
7390     }
7391     Bind(&leftIsNotNumber);
7392     BRANCH(TaggedIsNumber(right), &exit, &sameVariableCheck);
7393     Bind(&sameVariableCheck);
7394     {
7395         Label ifSameVariable(env);
7396         BRANCH(Equal(left, right), &ifSameVariable, &stringEqualCheck);
7397         Bind(&ifSameVariable);
7398         {
7399             result = True();
7400             if (!callback.IsEmpty()) {
7401                 Label bothAreString(env);
7402                 Label updataPGOTypeWithAny(env);
7403                 BRANCH(TaggedIsString(glue, left), &bothAreString, &updataPGOTypeWithAny);
7404                 Bind(&bothAreString);
7405                 {
7406                     Label updataPGOTypeWithString(env);
7407                     BRANCH(IsInternalString(left), &updataPGOTypeWithInternString, &updataPGOTypeWithString);
7408                     Bind(&updataPGOTypeWithString);
7409                     {
7410                         callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7411                         Jump(&exit);
7412                     }
7413                 }
7414                 Bind(&updataPGOTypeWithAny);
7415                 {
7416                     callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7417                     Jump(&exit);
7418                 }
7419             } else {
7420                 Jump(&exit);
7421             }
7422         }
7423     }
7424     Bind(&stringEqualCheck);
7425     BRANCH(BothAreString(glue, left, right), &stringCompare, &bigIntEqualCheck);
7426     Bind(&stringCompare);
7427     {
7428         Label executeFastStringEqual(env);
7429         BRANCH(LogicAndBuilder(env).And(IsInternalString(left)).And(IsInternalString(right)).Done(),
7430                // if not same variable and both sides are intern strings,
7431                // then the comparison result of the strings must be false.
7432                &updataPGOTypeWithInternString, &executeFastStringEqual);
7433         Bind(&executeFastStringEqual);
7434         {
7435             callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7436             result = FastStringEqual(glue, left, right);
7437             Jump(&exit);
7438         }
7439     }
7440     Bind(&bigIntEqualCheck);
7441     {
7442         Label leftIsBigInt(env);
7443         Label leftIsNotBigInt(env);
7444         BRANCH(TaggedIsBigInt(glue, left), &leftIsBigInt, &undefinedCheck);
7445         Bind(&leftIsBigInt);
7446         {
7447             Label rightIsBigInt(env);
7448             BRANCH(TaggedIsBigInt(glue, right), &rightIsBigInt, &exit);
7449             Bind(&rightIsBigInt);
7450             callback.ProfileOpType(TaggedInt(PGOSampleType::BigIntType()));
7451             result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
7452             Jump(&exit);
7453         }
7454     }
7455     Bind(&updataPGOTypeWithInternString);
7456     {
7457         callback.ProfileOpType(TaggedInt(PGOSampleType::InternStringType()));
7458         Jump(&exit);
7459     }
7460     Bind(&undefinedCheck);
7461     {
7462         if (!callback.IsEmpty()) {
7463             Label updateProfileOpTypeWithAny(env);
7464             BRANCH(TaggedIsUndefined(left), &updateProfileOpTypeWithAny, &exit);
7465             Bind(&updateProfileOpTypeWithAny);
7466             callback.ProfileOpType(TaggedInt(PGOSampleType::UndefinedOrNullType()));
7467         }
7468         Jump(&exit);
7469     }
7470     Bind(&exit);
7471     auto ret = *result;
7472     env->SubCfgExit();
7473     return ret;
7474 }
7475 
FastEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7476 GateRef StubBuilder::FastEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7477 {
7478     auto env = GetEnvironment();
7479     Label entry(env);
7480     env->SubCfgEntry(&entry);
7481     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7482     Label leftEqualRight(env);
7483     Label leftNotEqualRight(env);
7484     Label exit(env);
7485     BRANCH(Equal(left, right), &leftEqualRight, &leftNotEqualRight);
7486     Bind(&leftEqualRight);
7487     {
7488         Label leftIsDouble(env);
7489         Label leftNotDoubleOrLeftNotNan(env);
7490         BRANCH(TaggedIsDouble(left), &leftIsDouble, &leftNotDoubleOrLeftNotNan);
7491         Bind(&leftIsDouble);
7492         {
7493             callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
7494             GateRef doubleLeft = GetDoubleOfTDouble(left);
7495             Label leftIsNan(env);
7496             Label leftIsNotNan(env);
7497             BRANCH(DoubleIsNAN(doubleLeft), &leftIsNan, &leftIsNotNan);
7498             Bind(&leftIsNan);
7499             {
7500                 result = TaggedFalse();
7501                 Jump(&exit);
7502             }
7503             Bind(&leftIsNotNan);
7504             {
7505                 result = TaggedTrue();
7506                 Jump(&exit);
7507             }
7508         }
7509         Bind(&leftNotDoubleOrLeftNotNan);
7510         {
7511             // Collect the type of left value
7512             result = TaggedTrue();
7513             if (callback.IsEmpty()) {
7514                 Jump(&exit);
7515             } else {
7516                 Label leftIsInt(env);
7517                 Label leftIsNotInt(env);
7518                 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsNotInt);
7519                 Bind(&leftIsInt);
7520                 {
7521                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
7522                     Jump(&exit);
7523                 }
7524                 Bind(&leftIsNotInt);
7525                 {
7526                     Label leftIsString(env);
7527                     Label leftIsNotString(env);
7528                     BRANCH(TaggedIsString(glue, left), &leftIsString, &leftIsNotString);
7529                     Bind(&leftIsString);
7530                     {
7531                         callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7532                         Jump(&exit);
7533                     }
7534                     Bind(&leftIsNotString);
7535                     {
7536                         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7537                         Jump(&exit);
7538                     }
7539                 }
7540             }
7541         }
7542     }
7543     Bind(&leftNotEqualRight);
7544     {
7545         Label leftIsNumber(env);
7546         Label leftNotNumberOrLeftNotIntOrRightNotInt(env);
7547         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrLeftNotIntOrRightNotInt);
7548         Bind(&leftIsNumber);
7549         {
7550             Label leftIsInt(env);
7551             BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
7552             Bind(&leftIsInt);
7553             {
7554                 Label rightIsInt(env);
7555                 BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
7556                 Bind(&rightIsInt);
7557                 {
7558                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
7559                     result = TaggedFalse();
7560                     Jump(&exit);
7561                 }
7562             }
7563         }
7564         Bind(&leftNotNumberOrLeftNotIntOrRightNotInt);
7565         {
7566             DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None()));
7567             Label rightIsUndefinedOrNull(env);
7568             Label rightIsNotUndefinedOrNull(env);
7569             BRANCH(TaggedIsUndefinedOrNull(right), &rightIsUndefinedOrNull, &rightIsNotUndefinedOrNull);
7570             Bind(&rightIsUndefinedOrNull);
7571             {
7572                 curType = TaggedInt(PGOSampleType::UndefinedOrNullType());
7573                 Label leftIsHeapObject(env);
7574                 Label leftNotHeapObject(env);
7575                 BRANCH(TaggedIsHeapObject(left), &leftIsHeapObject, &leftNotHeapObject);
7576                 Bind(&leftIsHeapObject);
7577                 {
7578                     GateRef type = TaggedInt(PGOSampleType::HeapObjectType());
7579                     COMBINE_TYPE_CALL_BACK(curType, type);
7580                     result = TaggedFalse();
7581                     Jump(&exit);
7582                 }
7583                 Bind(&leftNotHeapObject);
7584                 {
7585                     Label leftIsUndefinedOrNull(env);
7586                     Label leftIsNotUndefinedOrNull(env);
7587                     // if left is undefined or null, then result is true, otherwise result is false
7588                     BRANCH(TaggedIsUndefinedOrNull(left), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
7589                     Bind(&leftIsUndefinedOrNull);
7590                     {
7591                         callback.ProfileOpType(*curType);
7592                         result = TaggedTrue();
7593                         Jump(&exit);
7594                     }
7595                     Bind(&leftIsNotUndefinedOrNull);
7596                     {
7597                         callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7598                         result = TaggedFalse();
7599                         Jump(&exit);
7600                     }
7601                 }
7602             }
7603             Bind(&rightIsNotUndefinedOrNull);
7604             {
7605                 Label bothString(env);
7606                 Label eitherNotString(env);
7607                 Label isHeapObject(env);
7608                 Label notHeapObject(env);
7609                 BRANCH(BitAnd(TaggedIsHeapObject(left), TaggedIsHeapObject(right)), &isHeapObject, &notHeapObject);
7610                 Bind(&isHeapObject);
7611                 {
7612                     Label typeEqual(env);
7613                     GateRef leftType = GetObjectType(LoadHClass(glue, left));
7614                     GateRef rightType = GetObjectType(LoadHClass(glue, right));
7615                     BRANCH(Equal(leftType, rightType), &typeEqual, &notHeapObject);
7616                     Bind(&typeEqual);
7617                     {
7618                         Label eitherNotString1(env);
7619                         Label bothBigInt(env);
7620                         Label eitherNotBigInt(env);
7621                         BRANCH(BothAreString(glue, left, right), &bothString, &eitherNotString1);
7622                         Bind(&eitherNotString1);
7623                         BRANCH(BitAnd(TaggedIsBigInt(glue, left),TaggedIsBigInt(glue, right)), &bothBigInt, &eitherNotBigInt);
7624                         Bind(&bothBigInt);
7625                         {
7626                             callback.ProfileOpType(TaggedInt(PGOSampleType::BigIntType()));
7627                             result =BooleanToTaggedBooleanPtr(CallNGCRuntime(glue,
7628                                                                 RTSTUB_ID(BigIntEquals), {left, right}));
7629                             Jump(&exit);
7630                         }
7631                         Bind(&eitherNotBigInt);
7632                         {
7633                             callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7634                             result = TaggedFalse();
7635                             Jump(&exit);
7636                         }
7637                     }
7638                 }
7639                 Bind(&notHeapObject);
7640                 Label leftIsUndefinedOrNull(env);
7641                 Label leftIsNotUndefinedOrNull(env);
7642                 BRANCH(TaggedIsUndefinedOrNull(right), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
7643                 // If left is undefined or null, result will always be false
7644                 // because we can ensure that right is not null here.
7645                 Bind(&leftIsUndefinedOrNull);
7646                 {
7647                     callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7648                     result = TaggedFalse();
7649                     Jump(&exit);
7650                 }
7651                 Bind(&leftIsNotUndefinedOrNull);
7652                 {
7653                     Label leftIsBool(env);
7654                     Label leftNotBoolOrRightNotSpecial(env);
7655                     BRANCH(TaggedIsBoolean(left), &leftIsBool, &leftNotBoolOrRightNotSpecial);
7656                     Bind(&leftIsBool);
7657                     {
7658                         curType = TaggedInt(PGOSampleType::BooleanType());
7659                         Label rightIsSpecial(env);
7660                         BRANCH(TaggedIsSpecial(right), &rightIsSpecial, &leftNotBoolOrRightNotSpecial);
7661                         Bind(&rightIsSpecial);
7662                         {
7663                             GateRef type = TaggedInt(PGOSampleType::SpecialType());
7664                             COMBINE_TYPE_CALL_BACK(curType, type);
7665                             result = TaggedFalse();
7666                             Jump(&exit);
7667                         }
7668                     }
7669                     Bind(&leftNotBoolOrRightNotSpecial);
7670                     {
7671                         BRANCH(BothAreString(glue, left, right), &bothString, &eitherNotString);
7672                     }
7673                     Bind(&bothString);
7674                     {
7675                         callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7676                         Label stringEqual(env);
7677                         Label stringNotEqual(env);
7678                         BRANCH(FastStringEqual(glue, left, right), &stringEqual, &stringNotEqual);
7679                         Bind(&stringEqual);
7680                         result = TaggedTrue();
7681                         Jump(&exit);
7682                         Bind(&stringNotEqual);
7683                         result = TaggedFalse();
7684                         Jump(&exit);
7685                     }
7686                     Bind(&eitherNotString);
7687                     callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7688                     Jump(&exit);
7689                 }
7690             }
7691         }
7692     }
7693     Bind(&exit);
7694     auto ret = *result;
7695     env->SubCfgExit();
7696     return ret;
7697 }
7698 
FastToBoolean(GateRef glue,GateRef value,bool flag)7699 GateRef StubBuilder::FastToBoolean(GateRef glue, GateRef value, bool flag)
7700 {
7701     auto env = GetEnvironment();
7702     Label entry(env);
7703     env->SubCfgEntry(&entry);
7704     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7705     Label exit(env);
7706 
7707     Label isSpecial(env);
7708     Label notSpecial(env);
7709     Label isNumber(env);
7710     Label isInt(env);
7711     Label isDouble(env);
7712     Label notNumber(env);
7713     Label notNan(env);
7714     Label isString(env);
7715     Label notString(env);
7716     Label isBigint(env);
7717     Label lengthIsOne(env);
7718     Label returnTrue(env);
7719     Label returnFalse(env);
7720 
7721     BRANCH(TaggedIsSpecial(value), &isSpecial, &notSpecial);
7722     Bind(&isSpecial);
7723     {
7724         BRANCH(TaggedIsTrue(value), &returnTrue, &returnFalse);
7725     }
7726     Bind(&notSpecial);
7727     {
7728         BRANCH(TaggedIsNumber(value), &isNumber, &notNumber);
7729         Bind(&notNumber);
7730         {
7731             BRANCH(IsString(glue, value), &isString, &notString);
7732             Bind(&isString);
7733             {
7734                 auto len = GetLengthFromString(value);
7735                 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7736             }
7737             Bind(&notString);
7738             BRANCH(TaggedObjectIsBigInt(glue, value), &isBigint, &returnTrue);
7739             Bind(&isBigint);
7740             {
7741                 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7742                 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7743                 Bind(&lengthIsOne);
7744                 {
7745                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7746                     auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
7747                     BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7748                 }
7749             }
7750         }
7751         Bind(&isNumber);
7752         {
7753             BRANCH(TaggedIsInt(value), &isInt, &isDouble);
7754             Bind(&isInt);
7755             {
7756                 auto intValue = GetInt32OfTInt(value);
7757                 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7758             }
7759             Bind(&isDouble);
7760             {
7761                 auto doubleValue = GetDoubleOfTDouble(value);
7762                 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
7763                 Bind(&notNan);
7764                 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
7765             }
7766         }
7767     }
7768     if (flag == 1) {
7769         Bind(&returnTrue);
7770         {
7771             result = TaggedTrue();
7772             Jump(&exit);
7773         }
7774         Bind(&returnFalse);
7775         {
7776             result = TaggedFalse();
7777             Jump(&exit);
7778         }
7779     } else {
7780         Bind(&returnFalse);
7781         {
7782             result = TaggedTrue();
7783             Jump(&exit);
7784         }
7785         Bind(&returnTrue);
7786         {
7787             result = TaggedFalse();
7788             Jump(&exit);
7789         }
7790     }
7791 
7792     Bind(&exit);
7793     auto ret = *result;
7794     env->SubCfgExit();
7795     return ret;
7796 }
7797 
FastToBooleanBaseline(GateRef glue,GateRef value,bool flag)7798 GateRef StubBuilder::FastToBooleanBaseline(GateRef glue, GateRef value, bool flag)
7799 {
7800     auto env = GetEnvironment();
7801     Label entry(env);
7802     env->SubCfgEntry(&entry);
7803     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7804     Label exit(env);
7805 
7806     Label isSpecial(env);
7807     Label notSpecial(env);
7808     Label isNumber(env);
7809     Label isInt(env);
7810     Label isDouble(env);
7811     Label notNumber(env);
7812     Label notNan(env);
7813     Label isString(env);
7814     Label notString(env);
7815     Label isBigint(env);
7816     Label lengthIsOne(env);
7817     Label returnTrue(env);
7818     Label returnFalse(env);
7819 
7820     Branch(TaggedIsSpecial(value), &isSpecial, &notSpecial);
7821     Bind(&isSpecial);
7822     {
7823         Branch(TaggedIsTrue(value), &returnTrue, &returnFalse);
7824     }
7825     Bind(&notSpecial);
7826     {
7827         Branch(TaggedIsNumber(value), &isNumber, &notNumber);
7828         Bind(&notNumber);
7829         {
7830             Branch(IsString(glue, value), &isString, &notString);
7831             Bind(&isString);
7832             {
7833                 auto len = GetLengthFromString(value);
7834                 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7835             }
7836             Bind(&notString);
7837             Branch(TaggedObjectIsBigInt(glue, value), &isBigint, &returnTrue);
7838             Bind(&isBigint);
7839             {
7840                 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7841                 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7842                 Bind(&lengthIsOne);
7843                 {
7844                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7845                     auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
7846                     Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7847                 }
7848             }
7849         }
7850         Bind(&isNumber);
7851         {
7852             Branch(TaggedIsInt(value), &isInt, &isDouble);
7853             Bind(&isInt);
7854             {
7855                 auto intValue = GetInt32OfTInt(value);
7856                 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7857             }
7858             Bind(&isDouble);
7859             {
7860                 auto doubleValue = GetDoubleOfTDouble(value);
7861                 Branch(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
7862                 Bind(&notNan);
7863                 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
7864             }
7865         }
7866     }
7867     if (flag == 1) {
7868         Bind(&returnTrue);
7869         {
7870             result = TaggedTrue();
7871             Jump(&exit);
7872         }
7873         Bind(&returnFalse);
7874         {
7875             result = TaggedFalse();
7876             Jump(&exit);
7877         }
7878     } else {
7879         Bind(&returnFalse);
7880         {
7881             result = TaggedTrue();
7882             Jump(&exit);
7883         }
7884         Bind(&returnTrue);
7885         {
7886             result = TaggedFalse();
7887             Jump(&exit);
7888         }
7889     }
7890 
7891     Bind(&exit);
7892     auto ret = *result;
7893     env->SubCfgExit();
7894     return ret;
7895 }
7896 
FastToBooleanWithProfile(GateRef glue,GateRef value,ProfileOperation callback,bool flag)7897 GateRef StubBuilder::FastToBooleanWithProfile(GateRef glue, GateRef value, ProfileOperation callback, bool flag)
7898 {
7899     auto env = GetEnvironment();
7900     Label entry(env);
7901     env->SubCfgEntry(&entry);
7902     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7903     Label exit(env);
7904 
7905     Label isSpecial(env);
7906     Label notSpecial(env);
7907     Label isNumber(env);
7908     Label isInt(env);
7909     Label isDouble(env);
7910     Label notNumber(env);
7911     Label notNan(env);
7912     Label isString(env);
7913     Label notString(env);
7914     Label isBigint(env);
7915     Label lengthIsOne(env);
7916     Label returnTrue(env);
7917     Label returnFalse(env);
7918     Label isTrue(env);
7919     Label isNotTrue(env);
7920     Label isFalse(env);
7921     Label isNotFalse(env);
7922     Label isUndefinedOrNull(env);
7923     Label isHole(env);
7924     Label isNotBigInt(env);
7925 
7926     BRANCH(TaggedIsSpecial(value), &isSpecial, &notSpecial);
7927     Bind(&isSpecial);
7928     {
7929         BRANCH(TaggedIsTrue(value), &isTrue, &isNotTrue);
7930         Bind(&isTrue);
7931         {
7932             callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
7933             Jump(&returnTrue);
7934         }
7935         Bind(&isNotTrue);
7936         {
7937             BRANCH(TaggedIsFalse(value), &isFalse, &isNotFalse);
7938             Bind(&isFalse);
7939             {
7940                 callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
7941                 Jump(&returnFalse);
7942             }
7943             Bind(&isNotFalse);
7944             BRANCH(TaggedIsUndefinedOrNull(value), &isUndefinedOrNull, &isHole);
7945             Bind(&isUndefinedOrNull);
7946             {
7947                 callback.ProfileOpType(TaggedInt(PGOSampleType::UndefinedOrNullType()));
7948                 Jump(&returnFalse);
7949             }
7950             Bind(&isHole);
7951             {
7952                 // value will never be hole, this branch shouldn't be entered
7953                 callback.ProfileOpType(TaggedInt(PGOSampleType::SpecialType()));
7954                 Jump(&returnFalse);
7955             }
7956         }
7957     }
7958     Bind(&notSpecial);
7959     {
7960         BRANCH(TaggedIsNumber(value), &isNumber, &notNumber);
7961         Bind(&notNumber);
7962         {
7963             BRANCH(IsString(glue, value), &isString, &notString);
7964             Bind(&isString);
7965             {
7966                 callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7967                 auto len = GetLengthFromString(value);
7968                 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7969             }
7970             Bind(&notString);
7971             BRANCH(TaggedObjectIsBigInt(glue, value), &isBigint, &isNotBigInt);
7972             Bind(&isBigint);
7973             {
7974                 callback.ProfileOpType(TaggedInt(PGOSampleType::BigIntType()));
7975                 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7976                 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7977                 Bind(&lengthIsOne);
7978                 {
7979                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7980                     auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
7981                     BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7982                 }
7983             }
7984             Bind(&isNotBigInt);
7985             {
7986                 callback.ProfileOpType(TaggedInt(PGOSampleType::HeapObjectType()));
7987                 Jump(&returnTrue);
7988             }
7989         }
7990         Bind(&isNumber);
7991         {
7992             callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
7993             BRANCH(TaggedIsInt(value), &isInt, &isDouble);
7994             Bind(&isInt);
7995             {
7996                 auto intValue = GetInt32OfTInt(value);
7997                 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7998             }
7999             Bind(&isDouble);
8000             {
8001                 auto doubleValue = GetDoubleOfTDouble(value);
8002                 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
8003                 Bind(&notNan);
8004                 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
8005             }
8006         }
8007     }
8008     if (flag == 1) {
8009         Bind(&returnTrue);
8010         {
8011             result = TaggedTrue();
8012             Jump(&exit);
8013         }
8014         Bind(&returnFalse);
8015         {
8016             result = TaggedFalse();
8017             Jump(&exit);
8018         }
8019     } else {
8020         Bind(&returnFalse);
8021         {
8022             result = TaggedTrue();
8023             Jump(&exit);
8024         }
8025         Bind(&returnTrue);
8026         {
8027             result = TaggedFalse();
8028             Jump(&exit);
8029         }
8030     }
8031 
8032     Bind(&exit);
8033     auto ret = *result;
8034     env->SubCfgExit();
8035     return ret;
8036 }
8037 
FastToBooleanWithProfileBaseline(GateRef glue,GateRef value,ProfileOperation callback,bool flag)8038 GateRef StubBuilder::FastToBooleanWithProfileBaseline(GateRef glue, GateRef value, ProfileOperation callback, bool flag)
8039 {
8040     auto env = GetEnvironment();
8041     Label entry(env);
8042     env->SubCfgEntry(&entry);
8043     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8044     Label exit(env);
8045 
8046     Label isSpecial(env);
8047     Label notSpecial(env);
8048     Label isNumber(env);
8049     Label isInt(env);
8050     Label isDouble(env);
8051     Label notNumber(env);
8052     Label notNan(env);
8053     Label isString(env);
8054     Label notString(env);
8055     Label isBigint(env);
8056     Label lengthIsOne(env);
8057     Label returnTrue(env);
8058     Label returnFalse(env);
8059     Label isTrue(env);
8060     Label isNotTrue(env);
8061     Label isFalse(env);
8062     Label isNotFalse(env);
8063     Label isUndefinedOrNull(env);
8064 
8065     Branch(TaggedIsSpecial(value), &isSpecial, &notSpecial);
8066     Bind(&isSpecial);
8067     {
8068         Branch(TaggedIsTrue(value), &isTrue, &isNotTrue);
8069         Bind(&isTrue);
8070         {
8071             callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
8072             Jump(&returnTrue);
8073         }
8074         Bind(&isNotTrue);
8075         {
8076             BRANCH(TaggedIsFalse(value), &isFalse, &isNotFalse);
8077             Bind(&isFalse);
8078             {
8079                 callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
8080                 Jump(&returnFalse);
8081             }
8082             Bind(&isNotFalse);
8083             BRANCH(TaggedIsUndefinedOrNull(value), &isUndefinedOrNull, &returnFalse);
8084             Bind(&isUndefinedOrNull);
8085             {
8086                 callback.ProfileOpType(TaggedInt(PGOSampleType::UndefinedOrNullType()));
8087                 Jump(&returnFalse);
8088             }
8089         }
8090     }
8091     Bind(&notSpecial);
8092     {
8093         Branch(TaggedIsNumber(value), &isNumber, &notNumber);
8094         Bind(&notNumber);
8095         {
8096             Branch(IsString(glue, value), &isString, &notString);
8097             Bind(&isString);
8098             {
8099                 auto len = GetLengthFromString(value);
8100                 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
8101             }
8102             Bind(&notString);
8103             Branch(TaggedObjectIsBigInt(glue, value), &isBigint, &returnTrue);
8104             Bind(&isBigint);
8105             {
8106                 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
8107                 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
8108                 Bind(&lengthIsOne);
8109                 {
8110                     auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
8111                     auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
8112                     Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
8113                 }
8114             }
8115         }
8116         Bind(&isNumber);
8117         {
8118             callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
8119             Branch(TaggedIsInt(value), &isInt, &isDouble);
8120             Bind(&isInt);
8121             {
8122                 auto intValue = GetInt32OfTInt(value);
8123                 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
8124             }
8125             Bind(&isDouble);
8126             {
8127                 auto doubleValue = GetDoubleOfTDouble(value);
8128                 Branch(DoubleIsNAN(doubleValue), &returnFalse, &notNan);
8129                 Bind(&notNan);
8130                 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
8131             }
8132         }
8133     }
8134     if (flag == 1) {
8135         Bind(&returnTrue);
8136         {
8137             result = TaggedTrue();
8138             Jump(&exit);
8139         }
8140         Bind(&returnFalse);
8141         {
8142             result = TaggedFalse();
8143             Jump(&exit);
8144         }
8145     } else {
8146         Bind(&returnFalse);
8147         {
8148             result = TaggedTrue();
8149             Jump(&exit);
8150         }
8151         Bind(&returnTrue);
8152         {
8153             result = TaggedFalse();
8154             Jump(&exit);
8155         }
8156     }
8157 
8158     Bind(&exit);
8159     auto ret = *result;
8160     env->SubCfgExit();
8161     return ret;
8162 }
8163 
FastDiv(GateRef left,GateRef right,ProfileOperation callback)8164 GateRef StubBuilder::FastDiv(GateRef left, GateRef right, ProfileOperation callback)
8165 {
8166     auto env = GetEnvironment();
8167     Label entry(env);
8168     env->SubCfgEntry(&entry);
8169     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8170     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8171     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8172     DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None()));
8173     Label leftIsNumber(env);
8174     Label leftNotNumberOrRightNotNumber(env);
8175     Label leftIsNumberAndRightIsNumber(env);
8176     Label leftIsDoubleAndRightIsDouble(env);
8177     Label exit(env);
8178     BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
8179     Bind(&leftIsNumber);
8180     {
8181         Label rightIsNumber(env);
8182         BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
8183         Bind(&rightIsNumber);
8184         {
8185             Label leftIsInt(env);
8186             Label leftNotInt(env);
8187             BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
8188             Bind(&leftIsInt);
8189             {
8190                 Label rightIsInt(env);
8191                 Label bailout(env);
8192                 BRANCH(TaggedIsInt(right), &rightIsInt, &bailout);
8193                 Bind(&rightIsInt);
8194                 {
8195                     result = FastIntDiv(left, right, &bailout, callback);
8196                     Jump(&exit);
8197                 }
8198                 Bind(&bailout);
8199                 {
8200                     curType = TaggedInt(PGOSampleType::IntOverFlowType());
8201                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8202                     Jump(&leftIsNumberAndRightIsNumber);
8203                 }
8204             }
8205             Bind(&leftNotInt);
8206             {
8207                 curType = TaggedInt(PGOSampleType::DoubleType());
8208                 doubleLeft = GetDoubleOfTDouble(left);
8209                 Jump(&leftIsNumberAndRightIsNumber);
8210             }
8211         }
8212     }
8213     Bind(&leftNotNumberOrRightNotNumber);
8214     {
8215         Jump(&exit);
8216     }
8217     Bind(&leftIsNumberAndRightIsNumber);
8218     {
8219         Label rightIsInt(env);
8220         Label rightNotInt(env);
8221         BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
8222         Bind(&rightIsInt);
8223         {
8224             GateRef type = TaggedInt(PGOSampleType::IntType());
8225             COMBINE_TYPE_CALL_BACK(curType, type);
8226             doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8227             Jump(&leftIsDoubleAndRightIsDouble);
8228         }
8229         Bind(&rightNotInt);
8230         {
8231             GateRef type = TaggedInt(PGOSampleType::DoubleType());
8232             COMBINE_TYPE_CALL_BACK(curType, type);
8233             doubleRight = GetDoubleOfTDouble(right);
8234             Jump(&leftIsDoubleAndRightIsDouble);
8235         }
8236     }
8237     Bind(&leftIsDoubleAndRightIsDouble);
8238     {
8239         Label rightIsZero(env);
8240         Label rightNotZero(env);
8241         BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZero, &rightNotZero);
8242         Bind(&rightIsZero);
8243         {
8244             Label leftIsZero(env);
8245             Label leftNotZero(env);
8246             Label leftIsZeroOrNan(env);
8247             Label leftNotZeroAndNotNan(env);
8248             BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZero, &leftNotZero);
8249             Bind(&leftIsZero);
8250             {
8251                 Jump(&leftIsZeroOrNan);
8252             }
8253             Bind(&leftNotZero);
8254             {
8255                 Label leftIsNan(env);
8256                 BRANCH(DoubleIsNAN(*doubleLeft), &leftIsNan, &leftNotZeroAndNotNan);
8257                 Bind(&leftIsNan);
8258                 {
8259                     Jump(&leftIsZeroOrNan);
8260                 }
8261             }
8262             Bind(&leftIsZeroOrNan);
8263             {
8264                 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
8265                 Jump(&exit);
8266             }
8267             Bind(&leftNotZeroAndNotNan);
8268             {
8269                 GateRef intLeftTmp = CastDoubleToInt64(*doubleLeft);
8270                 GateRef intRightTmp = CastDoubleToInt64(*doubleRight);
8271                 GateRef flagBit = Int64And(Int64Xor(intLeftTmp, intRightTmp), Int64(base::DOUBLE_SIGN_MASK));
8272                 GateRef tmpResult = Int64Xor(flagBit, CastDoubleToInt64(Double(base::POSITIVE_INFINITY)));
8273                 result = DoubleToTaggedDoublePtr(CastInt64ToFloat64(tmpResult));
8274                 Jump(&exit);
8275             }
8276         }
8277         Bind(&rightNotZero);
8278         {
8279             result = DoubleToTaggedDoublePtr(DoubleDiv(*doubleLeft, *doubleRight));
8280             Jump(&exit);
8281         }
8282     }
8283     Bind(&exit);
8284     auto ret = *result;
8285     env->SubCfgExit();
8286     return ret;
8287 }
8288 
NumberOperation(Environment * env,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)8289 GateRef StubBuilder::NumberOperation(Environment *env, GateRef left, GateRef right,
8290                                      const BinaryOperation& intOp,
8291                                      const BinaryOperation& floatOp,
8292                                      ProfileOperation callback)
8293 {
8294     Label entry(env);
8295     env->SubCfgEntry(&entry);
8296     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8297     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8298     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8299     Label exit(env);
8300     Label doFloatOp(env);
8301     Label doIntOp(env);
8302     Label leftIsNumber(env);
8303     Label leftIsIntRightIsDouble(env);
8304     Label rightIsDouble(env);
8305     Label rightIsInt(env);
8306     Label rightIsNumber(env);
8307     BRANCH(TaggedIsNumber(left), &leftIsNumber, &exit);
8308     Bind(&leftIsNumber);
8309     {
8310         BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
8311         Bind(&rightIsNumber);
8312         {
8313             Label leftIsInt(env);
8314             Label leftIsDouble(env);
8315             BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
8316             Bind(&leftIsInt);
8317             {
8318                 BRANCH(TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
8319                 Bind(&leftIsIntRightIsDouble);
8320                 {
8321                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
8322                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8323                     doubleRight = GetDoubleOfTDouble(right);
8324                     Jump(&doFloatOp);
8325                 }
8326             }
8327             Bind(&leftIsDouble);
8328             {
8329                 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
8330                 Bind(&rightIsInt);
8331                 {
8332                     callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
8333                     doubleLeft = GetDoubleOfTDouble(left);
8334                     doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8335                     Jump(&doFloatOp);
8336                 }
8337                 Bind(&rightIsDouble);
8338                 {
8339                     callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
8340                     doubleLeft = GetDoubleOfTDouble(left);
8341                     doubleRight = GetDoubleOfTDouble(right);
8342                     Jump(&doFloatOp);
8343                 }
8344             }
8345         }
8346     }
8347     Bind(&doIntOp);
8348     {
8349         result = intOp(env, left, right);
8350         Jump(&exit);
8351     }
8352     Bind(&doFloatOp);
8353     {
8354         result = floatOp(env, *doubleLeft, *doubleRight);
8355         Jump(&exit);
8356     }
8357     Bind(&exit);
8358     auto ret = *result;
8359     env->SubCfgExit();
8360     return ret;
8361 }
8362 
TryStringAdd(Environment * env,GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)8363 GateRef StubBuilder::TryStringAdd(Environment *env, GateRef glue, GateRef left, GateRef right,
8364                                   const BinaryOperation& intOp,
8365                                   const BinaryOperation& floatOp,
8366                                   ProfileOperation callback)
8367 {
8368     Label entry(env);
8369     env->SubCfgEntry(&entry);
8370     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8371     Label exit(env);
8372     Label leftIsNotSpecial(env);
8373     Label leftIsNotString(env);
8374     Label leftIsString(env);
8375     Label rightIsNotSpecial(env);
8376     Label rightIsNotString(env);
8377     Label rightIsString(env);
8378     Label stringLeftAddNumberRight(env);
8379     Label numberLeftAddStringRight(env);
8380     Label stringLeftAddStringRight(env);
8381     Label notStringAdd(env);
8382     BRANCH(TaggedIsString(glue, left), &leftIsString, &leftIsNotString);
8383     Bind(&leftIsString);
8384     {
8385         BRANCH(TaggedIsString(glue, right), &stringLeftAddStringRight, &rightIsNotString);
8386         Bind(&rightIsNotString);
8387         {
8388             BRANCH(TaggedIsSpecial(right), &notStringAdd, &rightIsNotSpecial);
8389             Bind(&rightIsNotSpecial);
8390             {
8391                 BRANCH(TaggedIsNumber(right), &stringLeftAddNumberRight, &notStringAdd);
8392             }
8393         }
8394     }
8395     Bind(&leftIsNotString);
8396     {
8397         BRANCH(TaggedIsString(glue, right), &rightIsString, &notStringAdd);
8398         Bind(&rightIsString);
8399         {
8400             BRANCH(TaggedIsSpecial(left), &notStringAdd, &leftIsNotSpecial);
8401             Bind(&leftIsNotSpecial);
8402             {
8403                 BRANCH(TaggedIsNumber(left), &numberLeftAddStringRight, &notStringAdd);
8404             }
8405         }
8406     }
8407     Bind(&stringLeftAddNumberRight);
8408     {
8409         Label hasPendingException(env);
8410         // NOTICE-PGO: support string and number
8411         callback.ProfileOpType(TaggedInt(PGOSampleType::NumberOrStringType()));
8412         BuiltinsStringStubBuilder builtinsStringStubBuilder(this, GetCurrentGlobalEnv());
8413         result = builtinsStringStubBuilder.StringConcat(glue, left, NumberToString(glue, right));
8414         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
8415         Bind(&hasPendingException);
8416         result = Exception();
8417         Jump(&exit);
8418     }
8419     Bind(&numberLeftAddStringRight);
8420     {
8421         Label hasPendingException(env);
8422         // NOTICE-PGO: support string and number
8423         callback.ProfileOpType(TaggedInt(PGOSampleType::NumberOrStringType()));
8424         BuiltinsStringStubBuilder builtinsStringStubBuilder(this, GetCurrentGlobalEnv());
8425         result = builtinsStringStubBuilder.StringConcat(glue, NumberToString(glue, left), right);
8426         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
8427         Bind(&hasPendingException);
8428         result = Exception();
8429         Jump(&exit);
8430     }
8431     Bind(&stringLeftAddStringRight);
8432     {
8433         Label hasPendingException(env);
8434         callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
8435         BuiltinsStringStubBuilder builtinsStringStubBuilder(this, GetCurrentGlobalEnv());
8436         result = builtinsStringStubBuilder.StringConcat(glue, left, right);
8437         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
8438         Bind(&hasPendingException);
8439         result = Exception();
8440         Jump(&exit);
8441     }
8442     Bind(&notStringAdd);
8443     {
8444         result = NumberOperation(env, left, right, intOp, floatOp, callback);
8445         Jump(&exit);
8446     }
8447     Bind(&exit);
8448     auto ret = *result;
8449     env->SubCfgExit();
8450     return ret;
8451 }
8452 
8453 template<OpCode Op>
FastBinaryOp(GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)8454 GateRef StubBuilder::FastBinaryOp(GateRef glue, GateRef left, GateRef right,
8455                                   const BinaryOperation& intOp,
8456                                   const BinaryOperation& floatOp,
8457                                   ProfileOperation callback)
8458 {
8459     auto env = GetEnvironment();
8460     Label entry(env);
8461     env->SubCfgEntry(&entry);
8462     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8463     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8464     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8465 
8466     if (Op == OpCode::ADD) { // Try string Add
8467         result = TryStringAdd(env, glue, left, right, intOp, floatOp, callback);
8468     } else {
8469         result = NumberOperation(env, left, right, intOp, floatOp, callback);
8470     }
8471     auto ret = *result;
8472     env->SubCfgExit();
8473     return ret;
8474 }
8475 
8476 template<OpCode Op>
FastAddSubAndMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8477 GateRef StubBuilder::FastAddSubAndMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8478 {
8479     auto intOperation = [=](Environment *env, GateRef left, GateRef right) {
8480         Label entry(env);
8481         env->SubCfgEntry(&entry);
8482         DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8483         Label exit(env);
8484         Label overflow(env);
8485         Label notOverflow(env);
8486         auto res = BinaryOpWithOverflow<Op, MachineType::I32>(GetInt32OfTInt(left), GetInt32OfTInt(right));
8487         GateRef condition = env->GetBuilder()->ExtractValue(MachineType::I1, res, Int32(1));
8488         BRANCH(condition, &overflow, &notOverflow);
8489         Bind(&overflow);
8490         {
8491             auto doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8492             auto doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8493             auto ret = BinaryOp<Op, MachineType::F64>(doubleLeft, doubleRight);
8494             result = DoubleToTaggedDoublePtr(ret);
8495             callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType()));
8496             Jump(&exit);
8497         }
8498         Bind(&notOverflow);
8499         {
8500             res = env->GetBuilder()->ExtractValue(MachineType::I32, res, Int32(0));
8501             if (Op == OpCode::MUL) {
8502                 Label resultIsZero(env);
8503                 Label returnNegativeZero(env);
8504                 Label returnResult(env);
8505                 BRANCH(Int32Equal(res, Int32(0)), &resultIsZero, &returnResult);
8506                 Bind(&resultIsZero);
8507                 BRANCH(LogicOrBuilder(env).Or(Int32LessThan(GetInt32OfTInt(left), Int32(0)))
8508                     .Or(Int32LessThan(GetInt32OfTInt(right), Int32(0))).Done(),
8509                     &returnNegativeZero, &returnResult);
8510                 Bind(&returnNegativeZero);
8511                 result = DoubleToTaggedDoublePtr(Double(-0.0));
8512                 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
8513                 Jump(&exit);
8514                 Bind(&returnResult);
8515                 result = IntToTaggedPtr(res);
8516                 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8517                 Jump(&exit);
8518             } else {
8519                 result = IntToTaggedPtr(res);
8520                 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8521                 Jump(&exit);
8522             }
8523         }
8524         Bind(&exit);
8525         auto ret = *result;
8526         env->SubCfgExit();
8527         return ret;
8528     };
8529     auto floatOperation = [=]([[maybe_unused]] Environment *env, GateRef left, GateRef right) {
8530         auto res = BinaryOp<Op, MachineType::F64>(left, right);
8531         return DoubleToTaggedDoublePtr(res);
8532     };
8533     return FastBinaryOp<Op>(glue, left, right, intOperation, floatOperation, callback);
8534 }
8535 
FastIntDiv(GateRef left,GateRef right,Label * bailout,ProfileOperation callback)8536 GateRef StubBuilder::FastIntDiv(GateRef left, GateRef right, Label *bailout, ProfileOperation callback)
8537 {
8538     auto env = GetEnvironment();
8539     Label entry(env);
8540     env->SubCfgEntry(&entry);
8541     DEFVARIABLE(intResult, VariableType::INT32(), Int32(0));
8542 
8543     GateRef intLeft = GetInt32OfTInt(left);
8544     GateRef intRight = GetInt32OfTInt(right);
8545     Label exit(env);
8546     Label rightIsNotZero(env);
8547     Label leftIsIntMin(env);
8548     Label leftAndRightIsNotBoundary(env);
8549     BRANCH(Int32Equal(intRight, Int32(0)), bailout, &rightIsNotZero);
8550     Bind(&rightIsNotZero);
8551     BRANCH(Int32Equal(intLeft, Int32(INT_MIN)), &leftIsIntMin, &leftAndRightIsNotBoundary);
8552     Bind(&leftIsIntMin);
8553     BRANCH(Int32Equal(intRight, Int32(-1)), bailout, &leftAndRightIsNotBoundary);
8554     Bind(&leftAndRightIsNotBoundary);
8555     {
8556         Label leftIsZero(env);
8557         Label leftIsNotZero(env);
8558         BRANCH(Int32Equal(intLeft, Int32(0)), &leftIsZero, &leftIsNotZero);
8559         Bind(&leftIsZero);
8560         {
8561             BRANCH(Int32LessThan(intRight, Int32(0)), bailout, &leftIsNotZero);
8562         }
8563         Bind(&leftIsNotZero);
8564         {
8565             intResult = Int32Div(intLeft, intRight);
8566             GateRef truncated = Int32Mul(*intResult, intRight);
8567             BRANCH(Equal(intLeft, truncated), &exit, bailout);
8568         }
8569     }
8570     Bind(&exit);
8571     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8572     auto ret = IntToTaggedPtr(*intResult);
8573     env->SubCfgExit();
8574     return ret;
8575 }
8576 
FastAdd(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8577 GateRef StubBuilder::FastAdd(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8578 {
8579     return FastAddSubAndMul<OpCode::ADD>(glue, left, right, callback);
8580 }
8581 
FastSub(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8582 GateRef StubBuilder::FastSub(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8583 {
8584     return FastAddSubAndMul<OpCode::SUB>(glue, left, right, callback);
8585 }
8586 
FastMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8587 GateRef StubBuilder::FastMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8588 {
8589     return FastAddSubAndMul<OpCode::MUL>(glue, left, right, callback);
8590 }
8591 
FastMod(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8592 GateRef StubBuilder::FastMod(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8593 {
8594     auto env = GetEnvironment();
8595     Label entry(env);
8596     env->SubCfgEntry(&entry);
8597     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8598     DEFVARIABLE(intLeft, VariableType::INT32(), Int32(0));
8599     DEFVARIABLE(intRight, VariableType::INT32(), Int32(0));
8600     DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8601     DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8602     Label leftIsInt(env);
8603     Label leftNotIntOrRightNotInt(env);
8604     Label exit(env);
8605     BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotIntOrRightNotInt);
8606     Bind(&leftIsInt);
8607     {
8608         Label rightIsInt(env);
8609         BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotIntOrRightNotInt);
8610         Bind(&rightIsInt);
8611         {
8612             intLeft = GetInt32OfTInt(left);
8613             intRight = GetInt32OfTInt(right);
8614             Label leftGreaterZero(env);
8615             BRANCH(Int32GreaterThanOrEqual(*intLeft, Int32(0)), &leftGreaterZero, &leftNotIntOrRightNotInt);
8616             Bind(&leftGreaterZero);
8617             {
8618                 Label rightGreaterZero(env);
8619                 BRANCH(Int32GreaterThan(*intRight, Int32(0)), &rightGreaterZero, &leftNotIntOrRightNotInt);
8620                 Bind(&rightGreaterZero);
8621                 {
8622                     callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8623                     result = IntToTaggedPtr(Int32Mod(*intLeft, *intRight));
8624                     Jump(&exit);
8625                 }
8626             }
8627         }
8628     }
8629     Bind(&leftNotIntOrRightNotInt);
8630     {
8631         Label leftIsNumber(env);
8632         Label leftNotNumberOrRightNotNumber(env);
8633         Label leftIsNumberAndRightIsNumber(env);
8634         Label leftIsDoubleAndRightIsDouble(env);
8635         DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None()));
8636         // less than 0 result should be double
8637         curType = TaggedInt(PGOSampleType::DoubleType());
8638         BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
8639         Bind(&leftIsNumber);
8640         {
8641             Label rightIsNumber(env);
8642             BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
8643             Bind(&rightIsNumber);
8644             {
8645                 Label leftIsInt1(env);
8646                 Label leftNotInt1(env);
8647                 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
8648                 Bind(&leftIsInt1);
8649                 {
8650                     GateRef type = TaggedInt(PGOSampleType::IntType());
8651                     COMBINE_TYPE_CALL_BACK(curType, type);
8652                     doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8653                     Jump(&leftIsNumberAndRightIsNumber);
8654                 }
8655                 Bind(&leftNotInt1);
8656                 {
8657                     GateRef type = TaggedInt(PGOSampleType::DoubleType());
8658                     COMBINE_TYPE_CALL_BACK(curType, type);
8659                     doubleLeft = GetDoubleOfTDouble(left);
8660                     Jump(&leftIsNumberAndRightIsNumber);
8661                 }
8662             }
8663         }
8664         Bind(&leftNotNumberOrRightNotNumber);
8665         {
8666             Jump(&exit);
8667         }
8668         Bind(&leftIsNumberAndRightIsNumber);
8669         {
8670             Label rightIsInt1(env);
8671             Label rightNotInt1(env);
8672             BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
8673             Bind(&rightIsInt1);
8674             {
8675                 GateRef type = TaggedInt(PGOSampleType::IntType());
8676                 COMBINE_TYPE_CALL_BACK(curType, type);
8677                 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8678                 Jump(&leftIsDoubleAndRightIsDouble);
8679             }
8680             Bind(&rightNotInt1);
8681             {
8682                 GateRef type = TaggedInt(PGOSampleType::DoubleType());
8683                 COMBINE_TYPE_CALL_BACK(curType, type);
8684                 doubleRight = GetDoubleOfTDouble(right);
8685                 Jump(&leftIsDoubleAndRightIsDouble);
8686             }
8687         }
8688         Bind(&leftIsDoubleAndRightIsDouble);
8689         {
8690             Label rightNotZero(env);
8691             Label rightIsZeroOrNanOrLeftIsNanOrInf(env);
8692             Label rightNotZeroAndNanAndLeftNotNanAndInf(env);
8693             BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotZero);
8694             Bind(&rightNotZero);
8695             {
8696                 Label rightNotNan(env);
8697                 BRANCH(DoubleIsNAN(*doubleRight), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotNan);
8698                 Bind(&rightNotNan);
8699                 {
8700                     Label leftNotNan(env);
8701                     BRANCH(DoubleIsNAN(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf, &leftNotNan);
8702                     Bind(&leftNotNan);
8703                     {
8704                         BRANCH(DoubleIsINF(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf,
8705                             &rightNotZeroAndNanAndLeftNotNanAndInf);
8706                     }
8707                 }
8708             }
8709             Bind(&rightIsZeroOrNanOrLeftIsNanOrInf);
8710             {
8711                 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
8712                 Jump(&exit);
8713             }
8714             Bind(&rightNotZeroAndNanAndLeftNotNanAndInf);
8715             {
8716                 Label leftNotZero(env);
8717                 Label leftIsZeroOrRightIsInf(env);
8718                 BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZeroOrRightIsInf, &leftNotZero);
8719                 Bind(&leftNotZero);
8720                 {
8721                     Label rightNotInf(env);
8722                     BRANCH(DoubleIsINF(*doubleRight), &leftIsZeroOrRightIsInf, &rightNotInf);
8723                     Bind(&rightNotInf);
8724                     {
8725                         result = DoubleToTaggedDoublePtr(CallNGCRuntime(glue, RTSTUB_ID(FloatMod),
8726                             { *doubleLeft, *doubleRight }));
8727                         Jump(&exit);
8728                     }
8729                 }
8730                 Bind(&leftIsZeroOrRightIsInf);
8731                 {
8732                     result = DoubleToTaggedDoublePtr(*doubleLeft);
8733                     Jump(&exit);
8734                 }
8735             }
8736         }
8737     }
8738     Bind(&exit);
8739     auto ret = *result;
8740     env->SubCfgExit();
8741     return ret;
8742 }
8743 
GetGlobalOwnProperty(GateRef glue,GateRef receiver,GateRef key,ProfileOperation callback)8744 GateRef StubBuilder::GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRef key, ProfileOperation callback)
8745 {
8746     auto env = GetEnvironment();
8747     Label entryLabel(env);
8748     env->SubCfgEntry(&entryLabel);
8749     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8750     GateRef properties = GetPropertiesFromJSObject(glue, receiver);
8751     GateRef entry = FindEntryFromHashTable<NameDictionary>(glue, properties, key);
8752     Label notNegtiveOne(env);
8753     Label exit(env);
8754     BRANCH(Int32NotEqual(entry, Int32(-1)), &notNegtiveOne, &exit);
8755     Bind(&notNegtiveOne);
8756     {
8757         result = GetValueFromGlobalDictionary(glue, properties, entry);
8758         Label callGetter(env);
8759         BRANCH(TaggedIsAccessor(glue, *result), &callGetter, &exit);
8760         Bind(&callGetter);
8761         {
8762             result = CallGetterHelper(glue, receiver, receiver, *result, callback);
8763             Jump(&exit);
8764         }
8765     }
8766     Bind(&exit);
8767     auto ret = *result;
8768     env->SubCfgExit();
8769     return ret;
8770 }
8771 
GetConstPoolFromFunction(GateRef glue,GateRef jsFunc)8772 GateRef StubBuilder::GetConstPoolFromFunction(GateRef glue, GateRef jsFunc)
8773 {
8774     return env_->GetBuilder()->GetConstPoolFromFunction(glue, jsFunc);
8775 }
8776 
GetStringFromConstPool(GateRef glue,GateRef constpool,GateRef index)8777 GateRef StubBuilder::GetStringFromConstPool(GateRef glue, GateRef constpool, GateRef index)
8778 {
8779     GateRef module = Circuit::NullGate();
8780     GateRef hirGate = Circuit::NullGate();
8781     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
8782                                                       ConstPoolType::STRING);
8783 }
8784 
GetMethodFromConstPool(GateRef glue,GateRef constpool,GateRef index)8785 GateRef StubBuilder::GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index)
8786 {
8787     GateRef module = Circuit::NullGate();
8788     GateRef hirGate = Circuit::NullGate();
8789     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
8790                                                       ConstPoolType::METHOD);
8791 }
8792 
GetArrayLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)8793 GateRef StubBuilder::GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
8794 {
8795     GateRef hirGate = Circuit::NullGate();
8796     GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
8797     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
8798                                                       ConstPoolType::ARRAY_LITERAL);
8799 }
8800 
GetObjectLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)8801 GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
8802 {
8803     GateRef hirGate = Circuit::NullGate();
8804     GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
8805     return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
8806                                                       ConstPoolType::OBJECT_LITERAL);
8807 }
8808 
JSAPIContainerGet(GateRef glue,GateRef receiver,GateRef index)8809 GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)
8810 {
8811     auto env = GetEnvironment();
8812     Label entry(env);
8813     env->SubCfgEntry(&entry);
8814     Label exit(env);
8815     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8816 
8817     GateRef lengthOffset = IntPtr(panda::ecmascript::JSAPIArrayList::LENGTH_OFFSET);
8818     GateRef length = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), receiver, lengthOffset));
8819     Label isVailedIndex(env);
8820     Label notValidIndex(env);
8821     BRANCH(BitAnd(Int32GreaterThanOrEqual(index, Int32(0)),
8822         Int32UnsignedLessThan(index, length)), &isVailedIndex, &notValidIndex);
8823     Bind(&isVailedIndex);
8824     {
8825         GateRef elements = GetElementsArray(glue, receiver);
8826         result = GetValueFromTaggedArray(glue, elements, index);
8827         Jump(&exit);
8828     }
8829     Bind(&notValidIndex);
8830     {
8831         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(GetPropertyOutOfBounds));
8832         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
8833         result = Exception();
8834         Jump(&exit);
8835     }
8836 
8837     Bind(&exit);
8838     auto ret = *result;
8839     env->SubCfgExit();
8840     return ret;
8841 }
8842 
GetEnumCacheKindFromEnumCache(GateRef enumCache)8843 GateRef StubBuilder::GetEnumCacheKindFromEnumCache(GateRef enumCache)
8844 {
8845     return env_->GetBuilder()->GetEnumCacheKindFromEnumCache(enumCache);
8846 }
8847 
GetEnumCacheOwnFromEnumCache(GateRef glue,GateRef enumCache)8848 GateRef StubBuilder::GetEnumCacheOwnFromEnumCache(GateRef glue, GateRef enumCache)
8849 {
8850     return env_->GetBuilder()->GetEnumCacheOwnFromEnumCache(glue, enumCache);
8851 }
8852 
GetEnumCacheAllFromEnumCache(GateRef glue,GateRef enumCache)8853 GateRef StubBuilder::GetEnumCacheAllFromEnumCache(GateRef glue, GateRef enumCache)
8854 {
8855     return env_->GetBuilder()->GetEnumCacheAllFromEnumCache(glue, enumCache);
8856 }
8857 
GetProtoChainInfoEnumCacheFromEnumCache(GateRef glue,GateRef enumCache)8858 GateRef StubBuilder::GetProtoChainInfoEnumCacheFromEnumCache(GateRef glue, GateRef enumCache)
8859 {
8860     return env_->GetBuilder()->GetProtoChainInfoEnumCacheFromEnumCache(glue, enumCache);
8861 }
8862 
IsEnumCacheValid(GateRef glue,GateRef receiver,GateRef cachedHclass,GateRef kind)8863 GateRef StubBuilder::IsEnumCacheValid(GateRef glue, GateRef receiver, GateRef cachedHclass, GateRef kind)
8864 {
8865     return env_->GetBuilder()->IsEnumCacheValid(glue, receiver, cachedHclass, kind);
8866 }
8867 
NeedCheckProperty(GateRef glue,GateRef receiver)8868 GateRef StubBuilder::NeedCheckProperty(GateRef glue, GateRef receiver)
8869 {
8870     return env_->GetBuilder()->NeedCheckProperty(glue, receiver);
8871 }
8872 
NextInternal(GateRef glue,GateRef iter)8873 GateRef StubBuilder::NextInternal(GateRef glue, GateRef iter)
8874 {
8875     auto env = GetEnvironment();
8876     Label entry(env);
8877     env->SubCfgEntry(&entry);
8878     Label exit(env);
8879     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8880 
8881     Label notFinish(env);
8882     Label notEnumCacheValid(env);
8883     Label fastGetKey(env);
8884     Label slowpath(env);
8885 
8886     GateRef index = GetIndexFromForInIterator(iter);
8887     GateRef length = GetLengthFromForInIterator(iter);
8888     BRANCH(Int32GreaterThanOrEqual(index, length), &exit, &notFinish);
8889     Bind(&notFinish);
8890     GateRef keys = GetKeysFromForInIterator(glue, iter);
8891     GateRef receiver = GetObjectFromForInIterator(glue, iter);
8892     GateRef cachedHclass = GetCachedHClassFromForInIterator(glue, iter);
8893     GateRef kind = GetCacheKindFromForInIterator(iter);
8894     BRANCH(IsEnumCacheValid(glue, receiver, cachedHclass, kind), &fastGetKey, &notEnumCacheValid);
8895     Bind(&notEnumCacheValid);
8896     BRANCH(NeedCheckProperty(glue, receiver), &slowpath, &fastGetKey);
8897     Bind(&fastGetKey);
8898     {
8899         result = GetValueFromTaggedArray(glue, keys, index);
8900         IncreaseIteratorIndex(glue, iter, index);
8901         Jump(&exit);
8902     }
8903     Bind(&slowpath);
8904     {
8905         result = CallRuntime(glue, RTSTUB_ID(GetNextPropNameSlowpath), { iter });
8906         Jump(&exit);
8907     }
8908     Bind(&exit);
8909     auto ret = *result;
8910     env->SubCfgExit();
8911     return ret;
8912 }
8913 
GetOrCreateEnumCacheFromHClass(GateRef glue,GateRef hClass)8914 GateRef StubBuilder::GetOrCreateEnumCacheFromHClass(GateRef glue, GateRef hClass)
8915 {
8916     auto env = GetEnvironment();
8917     Label entry(env);
8918     env->SubCfgEntry(&entry);
8919 
8920     Label isEnumCache(env);
8921     Label notEnumCache(env);
8922     Label exit(env);
8923     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8924 
8925     GateRef enumCache = GetEnumCacheFromHClass(glue, hClass);
8926     BRANCH(TaggedIsEnumCache(glue, enumCache), &isEnumCache, &notEnumCache);
8927     Bind(&isEnumCache);
8928     {
8929         result = enumCache;
8930         Jump(&exit);
8931     }
8932     Bind(&notEnumCache);
8933     {
8934         NewObjectStubBuilder newBuilder(this);
8935         GateRef enumCacheNew = newBuilder.NewEnumCache(glue);
8936         SetEnumCacheToHClass(VariableType::JS_POINTER(), glue, hClass, enumCacheNew);
8937         result = enumCacheNew;
8938         Jump(&exit);
8939     }
8940     Bind(&exit);
8941     auto ret = *result;
8942     env->SubCfgExit();
8943     return ret;
8944 }
8945 
GetFunctionPrototype(GateRef glue,size_t index)8946 GateRef StubBuilder::GetFunctionPrototype(GateRef glue, size_t index)
8947 {
8948     auto env = GetEnvironment();
8949     Label entry(env);
8950     env->SubCfgEntry(&entry);
8951     Label exit(env);
8952     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8953 
8954     Label isHeapObject(env);
8955     Label isJSHclass(env);
8956 
8957     GateRef globalEnv = GetCurrentGlobalEnv();
8958     GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, index);
8959     GateRef protoOrHclass = Load(VariableType::JS_ANY(), glue, func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
8960     result = protoOrHclass;
8961     BRANCH(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &exit);
8962     Bind(&isHeapObject);
8963     BRANCH(IsJSHClass(glue, protoOrHclass), &isJSHclass, &exit);
8964     Bind(&isJSHclass);
8965     {
8966         result = GetPrototypeFromHClass(glue, protoOrHclass);
8967         Jump(&exit);
8968     }
8969     Bind(&exit);
8970     auto ret = *result;
8971     env->SubCfgExit();
8972     return ret;
8973 }
8974 
DeletePropertyOrThrow(GateRef glue,GateRef obj,GateRef value)8975 GateRef StubBuilder::DeletePropertyOrThrow(GateRef glue, GateRef obj, GateRef value)
8976 {
8977     auto env = GetEnvironment();
8978     Label entry(env);
8979     env->SubCfgEntry(&entry);
8980     Label exit(env);
8981     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
8982     DEFVARIABLE(key, VariableType::JS_ANY(), value);
8983     Label toObject(env);
8984     Label isNotExceptiont(env);
8985     Label objectIsEcmaObject(env);
8986     Label objectIsHeapObject(env);
8987     GateRef object = ToObject(glue, GetCurrentGlobalEnv(), obj);
8988     BRANCH(TaggedIsException(object), &exit, &isNotExceptiont);
8989     Bind(&isNotExceptiont);
8990     {
8991         Label deleteProper(env);
8992 #if ENABLE_NEXT_OPTIMIZATION
8993         key = ToPropertyKey(glue, value);
8994 #else
8995         key = CallRuntime(glue, RTSTUB_ID(ToPropertyKey), {value});
8996 #endif
8997         BRANCH(HasPendingException(glue), &exit, &deleteProper);
8998         Bind(&deleteProper);
8999         {
9000             result = DeleteProperty(glue, object, *key);
9001             Jump(&exit);
9002         }
9003     }
9004     Bind(&exit);
9005     auto ret = *result;
9006     env->SubCfgExit();
9007     return ret;
9008 }
9009 
DeleteProperty(GateRef glue,GateRef obj,GateRef value)9010 GateRef StubBuilder::DeleteProperty(GateRef glue, GateRef obj, GateRef value)
9011 {
9012     auto env = GetEnvironment();
9013     Label entry(env);
9014     env->SubCfgEntry(&entry);
9015     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
9016     Label exit(env);
9017     Label notRegularJSObject(env);
9018     Label regularJSObjDeletePrototype(env);
9019     BRANCH(TaggedIsRegularObject(glue, obj), &regularJSObjDeletePrototype, &notRegularJSObject);
9020     Bind(&regularJSObjDeletePrototype);
9021     {
9022         result = CallRuntime(glue, RTSTUB_ID(RegularJSObjDeletePrototype), { obj, value});
9023         Jump(&exit);
9024     }
9025     Bind(&notRegularJSObject);
9026     {
9027         result = CallRuntime(glue, RTSTUB_ID(CallJSObjDeletePrototype), { obj, value});
9028         Jump(&exit);
9029     }
9030 
9031     Bind(&exit);
9032     auto ret = *result;
9033     env->SubCfgExit();
9034     return ret;
9035 }
9036 
ToPrototypeOrObj(GateRef glue,GateRef obj)9037 GateRef StubBuilder::ToPrototypeOrObj(GateRef glue, GateRef obj)
9038 {
9039     auto env = GetEnvironment();
9040     Label entry(env);
9041     env->SubCfgEntry(&entry);
9042     Label exit(env);
9043     DEFVARIABLE(result, VariableType::JS_ANY(), obj);
9044     Label isNotEcmaObject(env);
9045     Label isNumber(env);
9046     Label notNumber(env);
9047     Label isBoolean(env);
9048     Label notBoolean(env);
9049     Label isString(env);
9050     Label notString(env);
9051     Label isSymbol(env);
9052     Label notSymbol(env);
9053     Label isBigInt(env);
9054     BRANCH(IsEcmaObject(glue, obj), &exit, &isNotEcmaObject);
9055     Bind(&isNotEcmaObject);
9056     BRANCH(TaggedIsNumber(obj), &isNumber, &notNumber);
9057     Bind(&isNumber);
9058     {
9059         result = GetFunctionPrototype(glue, GlobalEnv::NUMBER_FUNCTION_INDEX);
9060         Jump(&exit);
9061     }
9062     Bind(&notNumber);
9063     BRANCH(TaggedIsBoolean(obj), &isBoolean, &notBoolean);
9064     Bind(&isBoolean);
9065     {
9066         result = GetFunctionPrototype(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
9067         Jump(&exit);
9068     }
9069     Bind(&notBoolean);
9070     BRANCH(TaggedIsString(glue, obj), &isString, &notString);
9071     Bind(&isString);
9072     {
9073         result = GetFunctionPrototype(glue, GlobalEnv::STRING_FUNCTION_INDEX);
9074         Jump(&exit);
9075     }
9076     Bind(&notString);
9077     BRANCH(TaggedIsSymbol(glue, obj), &isSymbol, &notSymbol);
9078     Bind(&isSymbol);
9079     {
9080         result = GetFunctionPrototype(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX);
9081         Jump(&exit);
9082     }
9083     Bind(&notSymbol);
9084     BRANCH(TaggedIsBigInt(glue, obj), &isBigInt, &exit);
9085     Bind(&isBigInt);
9086     {
9087         result = GetFunctionPrototype(glue, GlobalEnv::BIGINT_FUNCTION_INDEX);
9088         Jump(&exit);
9089     }
9090     Bind(&exit);
9091     auto ret = *result;
9092     env->SubCfgExit();
9093     return ret;
9094 }
9095 
ToPropertyKey(GateRef glue,GateRef tagged)9096 GateRef StubBuilder::ToPropertyKey(GateRef glue, GateRef tagged)
9097 {
9098     auto env = GetEnvironment();
9099     Label entry(env);
9100     env->SubCfgEntry(&entry);
9101     Label exit(env);
9102     Label notPrimitive(env);
9103     Label hasPendingException(env);
9104     Label checkSymbol(env);
9105     Label castKey(env);
9106     DEFVARIABLE(result, VariableType::JS_ANY(), tagged);
9107 
9108     BRANCH(TaggedIsPropertyKey(glue, tagged), &exit, &notPrimitive);
9109 
9110     Bind(&notPrimitive);
9111     {
9112         result = ToPrimitive(glue, tagged, PreferredPrimitiveType::PREFER_STRING);
9113         BRANCH(HasPendingException(glue), &hasPendingException, &checkSymbol);
9114     }
9115 
9116     Bind(&checkSymbol);
9117     {
9118         BRANCH(TaggedIsSymbol(glue, *result), &exit, &castKey);
9119     }
9120 
9121     Bind(&castKey);
9122     {
9123         result = JSTaggedValueToString(glue, *result);
9124         BRANCH(HasPendingException(glue), &hasPendingException, &exit);
9125     }
9126 
9127     Bind(&hasPendingException);
9128     {
9129         result = Exception();
9130         Jump(&exit);
9131     }
9132 
9133     Bind(&exit);
9134     auto ret = *result;
9135     env->SubCfgExit();
9136     return ret;
9137 }
9138 
TaggedIsPropertyKey(GateRef glue,GateRef obj)9139 GateRef StubBuilder::TaggedIsPropertyKey(GateRef glue, GateRef obj)
9140 {
9141     return LogicOrBuilder(env_).Or(TaggedIsStringOrSymbol(glue, obj)).Or(TaggedIsNumber(obj)).Done();
9142 }
9143 
9144 // JSTaggedValue::HasProperty (O, P)
HasProperty(GateRef glue,GateRef obj,GateRef key,GateRef hir)9145 GateRef StubBuilder::HasProperty(GateRef glue, GateRef obj, GateRef key, GateRef hir)
9146 {
9147     auto env = GetEnvironment();
9148     Label entry(env);
9149     env->SubCfgEntry(&entry);
9150     Label exit(env);
9151     Label slowpath(env);
9152     Label isJSProxy(env);
9153     Label notJSProxy(env);
9154     Label isTypedArray(env);
9155     Label notTypedArray(env);
9156     Label isModuleNamespace(env);
9157     Label notModuleNamespace(env);
9158     Label isSpecialContainer(env);
9159     Label defaultObj(env);
9160     DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
9161 
9162     BRANCH(IsJsProxy(glue, obj), &isJSProxy, &notJSProxy);
9163     Bind(&isJSProxy);
9164     {
9165         result = CallRuntime(glue, RTSTUB_ID(JSProxyHasProperty), {obj, key});
9166         Jump(&exit);
9167     }
9168 
9169     Bind(&notJSProxy);
9170     BRANCH(BitOr(IsTypedArray(glue, obj), IsSharedTypedArray(glue, obj)), &isTypedArray, &notTypedArray);
9171     Bind(&isTypedArray);
9172     {
9173         result = CallRuntime(glue, RTSTUB_ID(JSTypedArrayHasProperty), {obj, key});
9174         Jump(&exit);
9175     }
9176 
9177     Bind(&notTypedArray);
9178     BRANCH(IsModuleNamespace(glue, obj), &isModuleNamespace, &notModuleNamespace);
9179     Bind(&isModuleNamespace);
9180     {
9181         result = CallRuntime(glue, RTSTUB_ID(ModuleNamespaceHasProperty), {obj, key});
9182         Jump(&exit);
9183     }
9184 
9185     Bind(&notModuleNamespace);
9186     BRANCH(IsSpecialContainer(glue, obj), &isSpecialContainer, &defaultObj);
9187     Bind(&isSpecialContainer);
9188     {
9189         Jump(&slowpath);
9190     }
9191 
9192     Bind(&defaultObj);
9193     {
9194         result = JSObjectHasProperty(glue, obj, key, hir);
9195         Jump(&exit);
9196     }
9197 
9198     Bind(&slowpath);
9199     {
9200         result = CallRuntime(glue, RTSTUB_ID(HasProperty), {obj, key});
9201         Jump(&exit);
9202     }
9203 
9204     Bind(&exit);
9205     auto res = *result;
9206     env->SubCfgExit();
9207     return res;
9208 }
9209 
IsIn(GateRef glue,GateRef prop,GateRef obj)9210 GateRef StubBuilder::IsIn(GateRef glue, GateRef prop, GateRef obj)
9211 {
9212     auto env = GetEnvironment();
9213     Label entry(env);
9214     env->SubCfgEntry(&entry);
9215     Label exit(env);
9216     Label isEcmaObject(env);
9217     Label notEcmaObject(env);
9218     Label checkProperty(env);
9219     Label isPendingException(env);
9220 
9221     DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
9222     DEFVARIABLE(propKey, VariableType::JS_ANY(), Undefined());
9223 
9224     BRANCH(IsEcmaObject(glue, obj), &isEcmaObject, &notEcmaObject);
9225 
9226     Bind(&notEcmaObject);
9227     {
9228         auto taggedId = Int32(GET_MESSAGE_STRING_ID(InOperatorOnNonObject));
9229         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
9230         result = Exception();
9231         Jump(&exit);
9232     }
9233 
9234     Bind(&isEcmaObject);
9235     {
9236         propKey = ToPropertyKey(glue, prop);
9237         BRANCH(HasPendingException(glue), &isPendingException, &checkProperty);
9238     }
9239 
9240     Bind(&checkProperty);
9241     {
9242         result = CallCommonStub(glue, CommonStubCSigns::JSTaggedValueHasProperty,
9243                                 { glue, obj, *propKey, GetCurrentGlobalEnv() });
9244         BRANCH(HasPendingException(glue), &isPendingException, &exit);
9245     }
9246 
9247     Bind(&isPendingException);
9248     {
9249         result = Exception();
9250         Jump(&exit);
9251     }
9252 
9253     Bind(&exit);
9254     auto ret = *result;
9255     env->SubCfgExit();
9256     return ret;
9257 }
9258 
IsSpecialKeysObject(GateRef glue,GateRef obj)9259 GateRef StubBuilder::IsSpecialKeysObject(GateRef glue, GateRef obj)
9260 {
9261     return LogicOrBuilder(env_).Or(IsTypedArray(glue, obj)).Or(IsModuleNamespace(glue, obj)).Or(IsSpecialContainer(glue, obj)).Done();
9262 }
9263 
IsSlowKeysObject(GateRef glue,GateRef obj)9264 GateRef StubBuilder::IsSlowKeysObject(GateRef glue, GateRef obj)
9265 {
9266     auto env = GetEnvironment();
9267     Label entry(env);
9268     env->SubCfgEntry(&entry);
9269     Label exit(env);
9270     DEFVARIABLE(result, VariableType::BOOL(), False());
9271 
9272     Label isHeapObject(env);
9273     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
9274     Bind(&isHeapObject);
9275     {
9276         result = LogicOrBuilder(env).Or(IsJSGlobalObject(glue, obj)).Or(IsJsProxy(glue, obj)).Or(IsSpecialKeysObject(glue, obj)).Done();
9277         Jump(&exit);
9278     }
9279     Bind(&exit);
9280     auto ret = *result;
9281     env->SubCfgExit();
9282     return ret;
9283 }
9284 
GetNumberOfElements(GateRef glue,GateRef obj)9285 GateRef StubBuilder::GetNumberOfElements(GateRef glue, GateRef obj)
9286 {
9287     auto env = GetEnvironment();
9288     Label entry(env);
9289     env->SubCfgEntry(&entry);
9290     Label exit(env);
9291     DEFVARIABLE(numOfElements, VariableType::INT32(), Int32(0));
9292     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
9293 
9294     Label isJSPrimitiveRef(env);
9295     Label isPrimitiveString(env);
9296     Label notPrimitiveString(env);
9297     Label isDictMode(env);
9298     Label notDictMode(env);
9299 
9300     BRANCH(IsJSPrimitiveRef(glue, obj), &isJSPrimitiveRef, &notPrimitiveString);
9301     Bind(&isJSPrimitiveRef);
9302     GateRef value = Load(VariableType::JS_ANY(), glue, obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
9303     BRANCH(TaggedIsString(glue, value), &isPrimitiveString, &notPrimitiveString);
9304     Bind(&isPrimitiveString);
9305     {
9306         numOfElements = GetLengthFromString(value);
9307         Jump(&notPrimitiveString);
9308     }
9309     Bind(&notPrimitiveString);
9310     GateRef elements = GetElementsArray(glue, obj);
9311     BRANCH(IsDictionaryMode(glue, elements), &isDictMode, &notDictMode);
9312     Bind(&notDictMode);
9313     {
9314         Label loopHead(env);
9315         Label loopEnd(env);
9316         Label iLessLength(env);
9317         Label notHole(env);
9318         GateRef elementsLen = GetLengthOfTaggedArray(elements);
9319         Jump(&loopHead);
9320         LoopBegin(&loopHead);
9321         {
9322             BRANCH(Int32UnsignedLessThan(*i, elementsLen), &iLessLength, &exit);
9323             Bind(&iLessLength);
9324             {
9325                 GateRef element = GetTaggedValueWithElementsKind(glue, obj, *i);
9326                 BRANCH(TaggedIsHole(element), &loopEnd, &notHole);
9327                 Bind(&notHole);
9328                 numOfElements = Int32Add(*numOfElements, Int32(1));
9329                 Jump(&loopEnd);
9330             }
9331             Bind(&loopEnd);
9332             i = Int32Add(*i, Int32(1));
9333             LoopEnd(&loopHead);
9334         }
9335     }
9336     Bind(&isDictMode);
9337     {
9338         GateRef entryCount = TaggedGetInt(
9339             GetValueFromTaggedArray(glue, elements, Int32(TaggedHashTable<NumberDictionary>::NUMBER_OF_ENTRIES_INDEX)));
9340         numOfElements = Int32Add(*numOfElements, entryCount);
9341         Jump(&exit);
9342     }
9343     Bind(&exit);
9344     auto ret = *numOfElements;
9345     env->SubCfgExit();
9346     return ret;
9347 }
9348 
9349 // When receiver and receiver's prototype chain have no elements
9350 // and ProtoChainInfoEnumCache of receiver's proto == JSTaggedValue::Undefined,
9351 // the SimpleEnumCache valid.
IsSimpleEnumCacheValid(GateRef glue,GateRef obj)9352 GateRef StubBuilder::IsSimpleEnumCacheValid(GateRef glue, GateRef obj)
9353 {
9354     auto env = GetEnvironment();
9355     Label entry(env);
9356     env->SubCfgEntry(&entry);
9357     Label exit(env);
9358     DEFVARIABLE(result, VariableType::BOOL(), False());
9359     DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
9360 
9361     Label receiverHasNoElements(env);
9362     Label protoIsHeapObject(env);
9363     Label afterLoop(env);
9364     Label isProtoEnumCache(env);
9365     Label isKeyUndefined(env);
9366 
9367     // Check no elements on self.
9368     GateRef numOfElements = GetNumberOfElements(glue, obj);
9369     BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
9370 
9371     Bind(&receiverHasNoElements);
9372     // Since current isn't a heapObject, the receiver's proto chain has no keys.
9373     current = GetPrototypeFromHClass(glue, LoadHClass(glue, obj));
9374     BRANCH_LIKELY(TaggedIsHeapObject(*current), &protoIsHeapObject, &afterLoop);
9375 
9376     // Check protoChainInfoEnumCache of receiver's proto == JSTaggedValue::Undefined.
9377     Bind(&protoIsHeapObject);
9378     {
9379         GateRef protoHClass = LoadHClass(glue, *current);
9380         GateRef enumCacheProto = GetEnumCacheFromHClass(glue, protoHClass);
9381         BRANCH(TaggedIsEnumCache(glue, enumCacheProto), &isProtoEnumCache, &exit);
9382         Bind(&isProtoEnumCache);
9383         GateRef keyProto = GetProtoChainInfoEnumCacheFromEnumCache(glue, enumCacheProto);
9384         BRANCH(TaggedIsUndefined(keyProto), &isKeyUndefined, &exit);
9385     }
9386 
9387     // Check no elements on prototype chain.
9388     Bind(&isKeyUndefined);
9389     {
9390         Label loopHead(env);
9391         Label loopEnd(env);
9392         Label currentHasNoElements(env);
9393         Jump(&loopHead);
9394         LoopBegin(&loopHead);
9395         {
9396             GateRef numOfCurrentElements = GetNumberOfElements(glue, *current);
9397             BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, &currentHasNoElements);
9398             Bind(&currentHasNoElements);
9399             GateRef hclass = LoadHClass(glue, *current);
9400             current = GetPrototypeFromHClass(glue, hclass);
9401             BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
9402         }
9403         Bind(&loopEnd);
9404         LoopEnd(&loopHead);
9405     }
9406 
9407     Bind(&afterLoop);
9408     {
9409         result = True();
9410         Jump(&exit);
9411     }
9412 
9413     Bind(&exit);
9414     auto ret = *result;
9415     env->SubCfgExit();
9416     return ret;
9417 }
9418 
9419 // When receiver and receiver's prototype chain have no elements,
9420 // and receiver.proto.EnumCacheAll == receiver.ProtoChainInfoEnumCache,
9421 // the ProtoChainEnumCache valid.
IsProtoChainCacheValid(GateRef glue,GateRef obj)9422 GateRef StubBuilder::IsProtoChainCacheValid(GateRef glue, GateRef obj)
9423 {
9424     auto env = GetEnvironment();
9425     Label entry(env);
9426     env->SubCfgEntry(&entry);
9427     Label exit(env);
9428     DEFVARIABLE(result, VariableType::BOOL(), False());
9429     DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
9430 
9431     Label receiverHasNoElements(env);
9432     Label prototypeIsHeapObj(env);
9433     Label isEnumCache(env);
9434     Label isCacheEqual(env);
9435 
9436     // Check no elements on self.
9437     GateRef numOfElements = GetNumberOfElements(glue, obj);
9438     BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
9439 
9440     Bind(&receiverHasNoElements);
9441     GateRef hClass = LoadHClass(glue, obj);
9442     GateRef prototype = GetPrototypeFromHClass(glue, hClass);
9443     BRANCH(TaggedIsHeapObject(prototype), &prototypeIsHeapObj, &exit);
9444 
9445     // Check receiver.proto.EnumCacheAll == receiver.ProtoChainInfoEnumCache.
9446     Bind(&prototypeIsHeapObj);
9447     GateRef protoHClass = LoadHClass(glue, prototype);
9448     GateRef enumCacheOwn = GetEnumCacheFromHClass(glue, hClass);
9449     GateRef enumCacheProto = GetEnumCacheFromHClass(glue, protoHClass);
9450     GateRef checkEnumCache = LogicAndBuilder(env)
9451                              .And(TaggedIsEnumCache(glue, enumCacheOwn))
9452                              .And(TaggedIsEnumCache(glue, enumCacheProto))
9453                              .Done();
9454     BRANCH(checkEnumCache, &isEnumCache, &exit);
9455     Bind(&isEnumCache);
9456     GateRef keyOwn = GetProtoChainInfoEnumCacheFromEnumCache(glue, enumCacheOwn);
9457     GateRef keyProto = GetEnumCacheAllFromEnumCache(glue, enumCacheProto);
9458     GateRef checkKey = LogicAndBuilder(env)
9459                        .And(Equal(keyOwn, keyProto))
9460                        .And(TaggedIsNotNull(keyOwn))
9461                        .Done();
9462     BRANCH(checkKey, &isCacheEqual, &exit);
9463 
9464     // Check no elements on prototype chain.
9465     Bind(&isCacheEqual);
9466     {
9467         Label loopHead(env);
9468         Label loopEnd(env);
9469         Label afterLoop(env);
9470         Label currentHasNoElements(env);
9471         current = prototype;
9472         BRANCH(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
9473         LoopBegin(&loopHead);
9474         {
9475             GateRef numOfCurrentElements = GetNumberOfElements(glue, *current);
9476             BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, &currentHasNoElements);
9477             Bind(&currentHasNoElements);
9478             current = GetPrototypeFromHClass(glue, LoadHClass(glue, *current));
9479             BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
9480         }
9481         Bind(&loopEnd);
9482         LoopEnd(&loopHead);
9483         Bind(&afterLoop);
9484         {
9485             result = True();
9486             Jump(&exit);
9487         }
9488     }
9489 
9490     Bind(&exit);
9491     auto ret = *result;
9492     env->SubCfgExit();
9493     return ret;
9494 }
9495 
TryGetEnumCache(GateRef glue,GateRef obj)9496 GateRef StubBuilder::TryGetEnumCache(GateRef glue, GateRef obj)
9497 {
9498     auto env = GetEnvironment();
9499     Label entry(env);
9500     env->SubCfgEntry(&entry);
9501     Label exit(env);
9502     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
9503 
9504     Label isEnumCache(env);
9505     Label notSlowKeys(env);
9506     Label notDictionaryMode(env);
9507     Label checkSimpleEnumCache(env);
9508     Label notSimpleEnumCache(env);
9509     Label checkEnumCacheWithProtoChainInfo(env);
9510     Label enumCacheValid(env);
9511 
9512     BRANCH(IsSlowKeysObject(glue, obj), &exit, &notSlowKeys);
9513     Bind(&notSlowKeys);
9514     GateRef hclass = LoadHClass(glue, obj);
9515     BRANCH(IsDictionaryModeByHClass(hclass), &exit, &notDictionaryMode);
9516     Bind(&notDictionaryMode);
9517     GateRef enumCache = GetEnumCacheFromHClass(glue, hclass);
9518     BRANCH(TaggedIsEnumCache(glue, enumCache), &isEnumCache, &exit);
9519     Bind(&isEnumCache);
9520     GateRef kind = GetEnumCacheKindFromEnumCache(enumCache);
9521     BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE))),
9522            &checkSimpleEnumCache, &notSimpleEnumCache);
9523     Bind(&checkSimpleEnumCache);
9524     {
9525         BRANCH(IsSimpleEnumCacheValid(glue, obj), &enumCacheValid, &exit);
9526     }
9527     Bind(&notSimpleEnumCache);
9528     {
9529         BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::PROTOCHAIN))),
9530             &checkEnumCacheWithProtoChainInfo, &exit);
9531     }
9532     Bind(&checkEnumCacheWithProtoChainInfo);
9533     {
9534         BRANCH(IsProtoChainCacheValid(glue, obj), &enumCacheValid, &exit);
9535     }
9536     Bind(&enumCacheValid);
9537     {
9538         result = GetEnumCacheAllFromEnumCache(glue, enumCache);
9539         Jump(&exit);
9540     }
9541     Bind(&exit);
9542     auto ret = *result;
9543     env->SubCfgExit();
9544     return ret;
9545 }
9546 
DoubleToInt(GateRef glue,GateRef x,size_t typeBits)9547 GateRef StubBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits)
9548 {
9549     auto env = GetEnvironment();
9550     Label entry(env);
9551     env->SubCfgEntry(&entry);
9552     Label exit(env);
9553     Label overflow(env);
9554 
9555     GateRef xInt = ChangeFloat64ToInt32(x);
9556     DEFVARIABLE(result, VariableType::INT32(), xInt);
9557 
9558     if (env->IsAmd64()) {
9559         // 0x80000000: amd64 overflow return value
9560         BRANCH(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit);
9561     } else {
9562         GateRef xInt64 = CastDoubleToInt64(x);
9563         // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
9564         GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
9565         exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
9566         exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
9567         GateRef bits = Int32(typeBits - 1);
9568         // exp < 32 - 1
9569         BRANCH(Int32LessThan(exp, bits), &exit, &overflow);
9570     }
9571     Bind(&overflow);
9572     {
9573         result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), { x, IntPtr(typeBits) });
9574         Jump(&exit);
9575     }
9576     Bind(&exit);
9577     auto ret = *result;
9578     env->SubCfgExit();
9579     return ret;
9580 }
9581 
ReturnExceptionIfAbruptCompletion(GateRef glue)9582 void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue)
9583 {
9584     auto env = GetEnvironment();
9585     Label entry(env);
9586     env->SubCfgEntry(&entry);
9587     Label exit(env);
9588     Label hasPendingException(env);
9589     BRANCH(HasPendingException(glue), &hasPendingException, &exit);
9590     Bind(&hasPendingException);
9591     Return(Exception());
9592     Bind(&exit);
9593     env->SubCfgExit();
9594     return;
9595 }
9596 
CalcHashcodeForInt(GateRef value)9597 GateRef StubBuilder::CalcHashcodeForInt(GateRef value)
9598 {
9599     return env_->GetBuilder()->CalcHashcodeForInt(value);
9600 }
9601 
CanDoubleRepresentInt(GateRef exp,GateRef expBits,GateRef fractionBits)9602 GateRef StubBuilder::CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits)
9603 {
9604     return LogicOrBuilder(env_)
9605         .Or(Int64Equal(expBits, Int64(base::DOUBLE_EXPONENT_MASK)))
9606         .Or(BitAnd(Int64Equal(expBits, Int64(0)), Int64NotEqual(fractionBits, Int64(0))))
9607         .Or(Int64LessThan(exp, Int64(0)))
9608         .Or(Int64GreaterThanOrEqual(exp, Int64(31U)))
9609         .Or(Int64NotEqual(Int64And(Int64LSL(fractionBits, exp), Int64(base::DOUBLE_SIGNIFICAND_MASK)),
9610                           Int64(0)))
9611         .Done();
9612 }
9613 
CalcHashcodeForDouble(GateRef x,Variable * res,Label * exit)9614 void StubBuilder::CalcHashcodeForDouble(GateRef x, Variable *res, Label *exit)
9615 {
9616     auto env = GetEnvironment();
9617     GateRef xInt64 = Int64Sub(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
9618     GateRef fractionBits = Int64And(xInt64, Int64(base::DOUBLE_SIGNIFICAND_MASK));
9619     GateRef expBits = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
9620     GateRef isZero = BitAnd(
9621         Int64Equal(expBits, Int64(0)),
9622         Int64Equal(fractionBits, Int64(0)));
9623     Label zero(env);
9624     Label nonZero(env);
9625 
9626     BRANCH(isZero, &zero, &nonZero);
9627     Bind(&nonZero);
9628     {
9629         DEFVARIABLE(value, VariableType::JS_ANY(), x);
9630         // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
9631         GateRef exp = Int64Sub(
9632             Int64LSR(expBits, Int64(base::DOUBLE_SIGNIFICAND_SIZE)),
9633             Int64(base::DOUBLE_EXPONENT_BIAS));
9634         Label convertToInt(env);
9635         Label calcHash(env);
9636         BRANCH(CanDoubleRepresentInt(exp, expBits, fractionBits), &calcHash, &convertToInt);
9637         Bind(&convertToInt);
9638         {
9639             *res = ChangeFloat64ToInt32(CastInt64ToFloat64(xInt64));
9640             Jump(exit);
9641         }
9642         Bind(&calcHash);
9643         {
9644             *res = env_->GetBuilder()->CalcHashcodeForInt(*value);
9645             Jump(exit);
9646         }
9647     }
9648 
9649     Bind(&zero);
9650     *res = Int32(0);
9651     Jump(exit);
9652 }
9653 
GetHash(GateRef glue,GateRef object)9654 GateRef StubBuilder::GetHash(GateRef glue, GateRef object)
9655 {
9656     auto env = GetEnvironment();
9657     Label subentry(env);
9658     Label isHeapObject(env);
9659     Label exit(env);
9660     env->SubCfgEntry(&subentry);
9661     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
9662     GateRef value = Load(VariableType::JS_ANY(), glue, object, hashOffset);
9663     DEFVARIABLE(res, VariableType::INT32(), GetInt32OfTInt(value));
9664     BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit);
9665 
9666     Bind(&isHeapObject);
9667     {
9668         Label isTaggedArray(env);
9669         Label notTaggedArray(env);
9670         BRANCH(IsTaggedArray(glue, value), &isTaggedArray, &notTaggedArray);
9671         Bind(&isTaggedArray);
9672         GateRef extlen = GetExtraLengthOfTaggedArray(value);
9673         GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
9674         res = GetInt32OfTInt(GetValueFromTaggedArray(glue, value, index));
9675         Jump(&exit);
9676         Bind(&notTaggedArray);
9677         res = Int32(0);
9678         Jump(&exit);
9679     }
9680     Bind(&exit);
9681     auto ret = *res;
9682     env->SubCfgExit();
9683     return ret;
9684 }
9685 
SetHash(GateRef glue,GateRef object,GateRef hash)9686 void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash)
9687 {
9688     auto env = GetEnvironment();
9689     Label subentry(env);
9690     Label isHeapObject(env);
9691     Label notHeapObject(env);
9692     Label exit(env);
9693     env->SubCfgEntry(&subentry);
9694     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
9695     GateRef value = Load(VariableType::JS_ANY(), glue, object, hashOffset);
9696     DEFVARIABLE(res, VariableType::JS_ANY(), object);
9697     BRANCH(TaggedIsHeapObject(value), &isHeapObject, &notHeapObject);
9698 
9699     Bind(&isHeapObject);
9700     {
9701         Label isTaggedArray(env);
9702         Label notTaggedArray(env);
9703         BRANCH(IsTaggedArray(glue, value), &isTaggedArray, &notTaggedArray);
9704         Bind(&isTaggedArray);
9705         {
9706             GateRef extlen = GetExtraLengthOfTaggedArray(value);
9707             GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
9708             SetValueToTaggedArray(VariableType::JS_ANY(), glue, value, index, IntToTaggedInt(hash));
9709             Jump(&exit);
9710         }
9711         Bind(&notTaggedArray);
9712         {
9713             Label isNativePointer(env);
9714             Label notNativePointer(env);
9715             BRANCH(IsNativePointer(glue, value), &isNativePointer, &notNativePointer);
9716             Bind(&isNativePointer);
9717             {
9718                 NewObjectStubBuilder newBuilder(this);
9719                 GateRef array = newBuilder.NewTaggedArray(glue, Int32(ECMAObject::RESOLVED_MAX_SIZE));
9720                 SetExtraLengthOfTaggedArray(glue, array, Int32(0));
9721                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
9722                                       Int32(ECMAObject::HASH_INDEX), IntToTaggedInt(hash));
9723                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
9724                                       Int32(ECMAObject::FUNCTION_EXTRA_INDEX), value);
9725                 Store(VariableType::JS_ANY(), glue, object, hashOffset, array);
9726                 Jump(&exit);
9727             }
9728             Bind(&notNativePointer);
9729             FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
9730             Jump(&exit);
9731         }
9732     }
9733     Bind(&notHeapObject);
9734     {
9735         Store(VariableType::JS_ANY(), glue, object, hashOffset, IntToTaggedInt(hash), MemoryAttribute::NoBarrier());
9736         Jump(&exit);
9737     }
9738     Bind(&exit);
9739     env->SubCfgExit();
9740 }
9741 
CalcHashcodeForObject(GateRef glue,GateRef value,Variable * res,Label * exit)9742 void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit)
9743 {
9744     auto env = GetEnvironment();
9745 
9746     GateRef hash = GetHash(glue, value);
9747     *res = hash;
9748     Label calcHash(env);
9749     BRANCH(Int32Equal(**res, Int32(0)), &calcHash, exit);
9750     Bind(&calcHash);
9751     GateRef offset = IntPtr(JSThread::GlueData::GetRandomStatePtrOffset(env_->Is32Bit()));
9752     GateRef randomStatePtr = LoadPrimitive(VariableType::NATIVE_POINTER(), glue, offset);
9753     GateRef randomState = LoadPrimitive(VariableType::INT64(), randomStatePtr, IntPtr(0));
9754     GateRef k1 = Int64Xor(randomState, Int64LSR(randomState, Int64(base::RIGHT12)));
9755     GateRef k2 = Int64Xor(k1, Int64LSL(k1, Int64(base::LEFT25)));
9756     GateRef k3 = Int64Xor(k2, Int64LSR(k2, Int64(base::RIGHT27)));
9757     Store(VariableType::INT64(), glue, randomStatePtr, IntPtr(0), k3);
9758     GateRef k4 = Int64Mul(k3, Int64(base::GET_MULTIPLY));
9759     GateRef k5 = Int64LSR(k4, Int64(base::INT64_BITS - base::INT32_BITS));
9760     GateRef k6 = Int32And(TruncInt64ToInt32(k5), Int32(INT32_MAX));
9761     SetHash(glue, value, k6);
9762     *res = k6;
9763     Jump(exit);
9764 }
9765 
GetHashcodeFromString(GateRef glue,GateRef value,GateRef hir)9766 GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir)
9767 {
9768     return env_->GetBuilder()->GetHashcodeFromString(glue, value, hir);
9769 }
9770 
ConstructorCheck(GateRef glue,GateRef ctor,GateRef outPut,GateRef thisObj)9771 GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj)
9772 {
9773     auto env = GetEnvironment();
9774     Label entryPass(env);
9775     Label exit(env);
9776     env->SubCfgEntry(&entryPass);
9777     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
9778     Label isHeapObject(env);
9779     Label isEcmaObj(env);
9780     Label notEcmaObj(env);
9781     BRANCH(TaggedIsHeapObject(outPut), &isHeapObject, &notEcmaObj);
9782     Bind(&isHeapObject);
9783     BRANCH(TaggedObjectIsEcmaObject(glue, outPut), &isEcmaObj, &notEcmaObj);
9784     Bind(&isEcmaObj);
9785     {
9786         result = outPut;
9787         Jump(&exit);
9788     }
9789     Bind(&notEcmaObj);
9790     {
9791         Label ctorIsBase(env);
9792         Label ctorNotBase(env);
9793         BRANCH(IsBase(glue, ctor), &ctorIsBase, &ctorNotBase);
9794         Bind(&ctorIsBase);
9795         {
9796             result = thisObj;
9797             Jump(&exit);
9798         }
9799         Bind(&ctorNotBase);
9800         {
9801             Label throwExeption(env);
9802             Label returnObj(env);
9803             BRANCH(TaggedIsUndefined(outPut), &returnObj, &throwExeption);
9804             Bind(&returnObj);
9805             result = thisObj;
9806             Jump(&exit);
9807             Bind(&throwExeption);
9808             {
9809                 CallRuntime(glue, RTSTUB_ID(ThrowNonConstructorException), {});
9810                 Jump(&exit);
9811             }
9812         }
9813     }
9814     Bind(&exit);
9815     auto ret = *result;
9816     env->SubCfgExit();
9817     return ret;
9818 }
9819 
CalIteratorKey(GateRef glue)9820 GateRef StubBuilder::CalIteratorKey(GateRef glue)
9821 {
9822     GateRef globalEnv = GetCurrentGlobalEnv();
9823     GateRef iteratorKey = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::ITERATOR_SYMBOL_INDEX);
9824     return iteratorKey;
9825 }
9826 
FuncOrHClassCompare(GateRef glue,GateRef funcOrHClass,Label * match,Label * slowPath,size_t index)9827 void StubBuilder::FuncOrHClassCompare(GateRef glue, GateRef funcOrHClass,
9828                                       Label *match, Label *slowPath, size_t index)
9829 {
9830     GateRef globalEnv = GetCurrentGlobalEnv();
9831     GateRef globalRecord = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, index);
9832     BRANCH(Equal(globalRecord, funcOrHClass), match, slowPath);
9833 }
9834 
IsDetectorInvalid(GateRef glue,size_t indexDetector)9835 GateRef StubBuilder::IsDetectorInvalid(GateRef glue, size_t indexDetector)
9836 {
9837     GateRef globalEnv = GetCurrentGlobalEnv();
9838     GateRef value = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, indexDetector);
9839     GateRef bitFieldOffset = IntPtr(MarkerCell::BIT_FIELD_OFFSET);
9840     GateRef bitField = LoadPrimitive(VariableType::INT32(), value, bitFieldOffset);
9841     GateRef mask = Int32(1LLU << (MarkerCell::IS_DETECTOR_INVALID_BITS - 1));
9842     return Int32NotEqual(Int32And(bitField, mask), Int32(0));
9843 }
9844 
HClassCompareAndCheckDetector(GateRef glue,GateRef hclass,Label * match,Label * slowPath,size_t indexHClass,bool isMap)9845 void StubBuilder::HClassCompareAndCheckDetector(GateRef glue, GateRef hclass,
9846                                                 Label *match, Label *slowPath,
9847                                                 size_t indexHClass, bool isMap)
9848 {
9849     auto env = GetEnvironment();
9850     Label matchHClass(env);
9851     FuncOrHClassCompare(glue, hclass, &matchHClass, slowPath, indexHClass);
9852     Bind(&matchHClass);
9853     GateRef globalEnv = GetCurrentGlobalEnv();
9854     if (isMap) {
9855         BRANCH(GetMapIteratorDetector(globalEnv), slowPath, match);
9856     } else {
9857         BRANCH(GetSetIteratorDetector(globalEnv), slowPath, match);
9858     }
9859 }
9860 
GetIteratorResult(GateRef glue,Variable * result,GateRef obj,Label * isPendingException,Label * noPendingException)9861 void StubBuilder::GetIteratorResult(GateRef glue, Variable *result, GateRef obj,
9862                                     Label *isPendingException, Label *noPendingException)
9863 {
9864     GateRef iteratorKey = CalIteratorKey(glue);
9865     *result = FastGetPropertyByName(glue, obj, iteratorKey, ProfileOperation());
9866     BRANCH(HasPendingException(glue), isPendingException, noPendingException);
9867 }
9868 
9869 // If the jsType of the obj is JS_ARRAY and
9870 // its elementsKind is not GENERIC or it's hclass == GENERIC array's ihc
9871 // the obj doesn't have symbol.iterator within itself.
9872 // So when the Array.prototype[symbol.iterator] remains unchanged, we call FastPath.
TryFastGetArrayIterator(GateRef glue,GateRef hclass,GateRef jsType,Label * slowPath2,Label * matchArray)9873 void StubBuilder::TryFastGetArrayIterator(GateRef glue, GateRef hclass, GateRef jsType,
9874                                           Label *slowPath2, Label *matchArray)
9875 {
9876     auto env = GetEnvironment();
9877     Label arrayDetectorValid(env);
9878     Label tryArray(env);
9879     BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))), &tryArray, slowPath2);
9880     Bind(&tryArray);
9881     {
9882         GateRef globalEnv = GetCurrentGlobalEnv();
9883         BRANCH(GetArrayIteratorDetector(globalEnv), slowPath2, &arrayDetectorValid);
9884         Bind(&arrayDetectorValid);
9885         {
9886             BuiltinsArrayStubBuilder arrayStubBuilder(this, globalEnv);
9887             arrayStubBuilder.ElementsKindHclassCompare(glue, hclass, matchArray, slowPath2);
9888         }
9889     }
9890 }
9891 
TryFastGetIterator(GateRef glue,GateRef obj,GateRef hclass,Variable & result,Label * slowPath,Label * exit,Label * isPendingException)9892 void StubBuilder::TryFastGetIterator(GateRef glue, GateRef obj, GateRef hclass,
9893                                      Variable &result, Label *slowPath, Label *exit,
9894                                      Label *isPendingException)
9895 {
9896     auto env = GetEnvironment();
9897     Label matchMap(env);
9898     Label notmatchMap(env);
9899     Label matchSet(env);
9900     Label notmatchSet(env);
9901     Label tryArray(env);
9902     Label matchArray(env);
9903     Label isMap(env);
9904     Label isNotMap(env);
9905     Label isSet(env);
9906     Label isNotSet(env);
9907     Label isArray(env);
9908     Label noPendingException(env);
9909     Label slowPath2(env);
9910 
9911     // When the symbol.iterator method remains unmodified
9912     // it is used to quickly process instances of Map, Set whose hclass == Map/Set's ihc.
9913     // In this situation we don't need to perform FastGetPropertyByName and CallRuntime.
9914     HClassCompareAndCheckDetector(glue, hclass, &matchMap, &notmatchMap, GlobalEnv::MAP_CLASS_INDEX, true);
9915     Bind(&notmatchMap);
9916     HClassCompareAndCheckDetector(glue, hclass, &matchSet, &notmatchSet, GlobalEnv::SET_CLASS_INDEX, false);
9917     Bind(&notmatchSet);
9918 
9919     GateRef jsType = GetObjectType(hclass);
9920     TryFastGetArrayIterator(glue, hclass, jsType, &slowPath2, &matchArray);
9921 
9922     Bind(&slowPath2);
9923     GetIteratorResult(glue, &result, obj, isPendingException, &noPendingException);
9924     // Mainly solve the situation with inheritance
9925     // and the symbol.iterator method remains unmodified.
9926     // In this situation we need to perform FastGetPropertyByName but needn't CallRuntime.
9927     Bind(&noPendingException);
9928     {
9929         BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_MAP))), &isMap, &isNotMap);
9930         Bind(&isMap);
9931         {
9932             FuncOrHClassCompare(glue, *result, &matchMap, slowPath, GlobalEnv::MAP_PROTO_ENTRIES_FUNCTION_INDEX);
9933         }
9934         Bind(&isNotMap);
9935         BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_SET))), &isSet, &isNotSet);
9936         Bind(&isSet);
9937         {
9938             FuncOrHClassCompare(glue, *result, &matchSet, slowPath, GlobalEnv::SET_PROTO_VALUES_FUNCTION_INDEX);
9939         }
9940         Bind(&isNotSet);
9941         BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))), &isArray, slowPath);
9942         Bind(&isArray);
9943         {
9944             FuncOrHClassCompare(glue, *result, &matchArray, slowPath, GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
9945         }
9946     }
9947 
9948     Bind(&matchMap);
9949     {
9950         BuiltinsCollectionStubBuilder<JSMap> collectionStubBuilder(this, glue, obj, Int32(0), GetCurrentGlobalEnv());
9951         collectionStubBuilder.Entries(&result, exit, slowPath);
9952     }
9953     Bind(&matchSet);
9954     {
9955         BuiltinsCollectionStubBuilder<JSSet> collectionStubBuilder(this, glue, obj, Int32(0), GetCurrentGlobalEnv());
9956         collectionStubBuilder.Values(&result, exit, slowPath);
9957     }
9958     Bind(&matchArray);
9959     {
9960         BuiltinsArrayStubBuilder arrayStubBuilder(this, GetCurrentGlobalEnv());
9961         arrayStubBuilder.Values(glue, obj, Int32(0), &result, exit, slowPath);
9962     }
9963 }
9964 
9965 #if ENABLE_NEXT_OPTIMIZATION
GetIterator(GateRef glue,GateRef obj,ProfileOperation callback)9966 GateRef StubBuilder::GetIterator(GateRef glue, GateRef obj, ProfileOperation callback)
9967 {
9968     auto env = GetEnvironment();
9969     Label entryPass(env);
9970     Label exit(env);
9971     env->SubCfgEntry(&entryPass);
9972     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
9973     DEFVARIABLE(taggedId, VariableType::INT32(), Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable)));
9974 
9975     Label isHeapObject(env);
9976     Label objIsHeapObject(env);
9977     Label objIsCallable(env);
9978     Label throwError(env);
9979     Label callExit(env);
9980     Label slowPath(env);
9981     Label slowPath3(env);
9982     Label isPendingException(env);
9983 
9984     BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &slowPath3);
9985     Bind(&objIsHeapObject);
9986     GateRef hclass = LoadHClass(glue, obj);
9987     TryFastGetIterator(glue, obj, hclass, result, &slowPath, &exit, &isPendingException);
9988 
9989     Bind(&slowPath3);
9990     GetIteratorResult(glue, &result, obj, &isPendingException, &slowPath);
9991 
9992     Bind(&slowPath);
9993     callback.ProfileGetIterator(*result);
9994     BRANCH(TaggedIsHeapObject(*result), &isHeapObject, &throwError);
9995     Bind(&isHeapObject);
9996     BRANCH(IsCallable(glue, *result), &objIsCallable, &throwError);
9997     Bind(&objIsCallable);
9998     {
9999         JSCallArgs callArgs(JSCallMode::CALL_GETTER);
10000         callArgs.callGetterArgs = { obj };
10001         CallStubBuilder callBuilder(this, glue, *result, Int32(0), 0, &result, Circuit::NullGate(), callArgs,
10002             ProfileOperation());
10003         if (env->IsBaselineBuiltin()) {
10004             callBuilder.JSCallDispatchForBaseline(&callExit);
10005             Bind(&callExit);
10006             Jump(&exit);
10007         } else {
10008             result = callBuilder.JSCallDispatch();
10009             Label modifyErrorInfo(env);
10010             BRANCH(TaggedIsHeapObject(*result), &exit, &modifyErrorInfo);
10011             Bind(&modifyErrorInfo);
10012             taggedId = Int32(GET_MESSAGE_STRING_ID(IterNotObject));
10013             Jump(&throwError);
10014         }
10015     }
10016     Bind(&isPendingException);
10017     {
10018         result = Exception();
10019         Jump(&exit);
10020     }
10021     Bind(&throwError);
10022     {
10023         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(*taggedId) });
10024         result = Exception();
10025         Jump(&exit);
10026     }
10027     Bind(&exit);
10028     auto ret = *result;
10029     env->SubCfgExit();
10030     return ret;
10031 }
10032 #else
GetIterator(GateRef glue,GateRef obj,ProfileOperation callback)10033 GateRef StubBuilder::GetIterator(GateRef glue, GateRef obj, ProfileOperation callback)
10034 {
10035     auto env = GetEnvironment();
10036     Label entryPass(env);
10037     Label exit(env);
10038     env->SubCfgEntry(&entryPass);
10039     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
10040     DEFVARIABLE(taggedId, VariableType::INT32(), Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable)));
10041 
10042     Label isPendingException(env);
10043     Label noPendingException(env);
10044     Label isHeapObject(env);
10045     Label objIsCallable(env);
10046     Label throwError(env);
10047     Label callExit(env);
10048 
10049     GateRef iteratorKey = CalIteratorKey(glue);
10050     result = FastGetPropertyByName(glue, obj, iteratorKey, ProfileOperation());
10051     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
10052     Bind(&isPendingException);
10053     {
10054         result = Exception();
10055         Jump(&exit);
10056     }
10057     Bind(&noPendingException);
10058     callback.ProfileGetIterator(*result);
10059     BRANCH(TaggedIsHeapObject(*result), &isHeapObject, &throwError);
10060     Bind(&isHeapObject);
10061     BRANCH(IsCallable(glue, *result), &objIsCallable, &throwError);
10062     Bind(&objIsCallable);
10063     {
10064         JSCallArgs callArgs(JSCallMode::CALL_GETTER);
10065         callArgs.callGetterArgs = { obj };
10066         CallStubBuilder callBuilder(this, glue, *result, Int32(0), 0, &result, Circuit::NullGate(), callArgs,
10067             ProfileOperation());
10068         if (env->IsBaselineBuiltin()) {
10069             callBuilder.JSCallDispatchForBaseline(&callExit);
10070             Bind(&callExit);
10071             Jump(&exit);
10072         } else {
10073             result = callBuilder.JSCallDispatch();
10074             Label modifyErrorInfo(env);
10075             BRANCH(TaggedIsHeapObject(*result), &exit, &modifyErrorInfo);
10076             Bind(&modifyErrorInfo);
10077             taggedId = Int32(GET_MESSAGE_STRING_ID(IterNotObject));
10078             Jump(&throwError);
10079         }
10080     }
10081     Bind(&throwError);
10082     {
10083         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(*taggedId) });
10084         result = Exception();
10085         Jump(&exit);
10086     }
10087     Bind(&exit);
10088     auto ret = *result;
10089     env->SubCfgExit();
10090     return ret;
10091 }
10092 #endif
10093 
TryStringOrSymbolToElementIndex(GateRef glue,GateRef key)10094 GateRef StubBuilder::TryStringOrSymbolToElementIndex(GateRef glue, GateRef key)
10095 {
10096     auto env = GetEnvironment();
10097     Label entry(env);
10098     env->SubCfgEntry(&entry);
10099     Label exit(env);
10100     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
10101 
10102     Label keyNotSymbol(env);
10103     BRANCH(IsSymbol(glue, key), &exit, &keyNotSymbol);
10104     Bind(&keyNotSymbol);
10105 
10106     Label greatThanZero(env);
10107     Label inRange(env);
10108     Label flattenFastPath(env);
10109     auto len = GetLengthFromString(key);
10110     BRANCH(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
10111     Bind(&greatThanZero);
10112     BRANCH(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
10113     Bind(&inRange);
10114     {
10115         Label isUtf8(env);
10116         DEFVARIABLE(c, VariableType::INT32(), Int32(0));
10117         BRANCH(IsUtf16String(key), &exit, &isUtf8);
10118         Bind(&isUtf8);
10119         FlatStringStubBuilder thisFlat(this);
10120         thisFlat.FlattenString(glue, key, &flattenFastPath);
10121         Bind(&flattenFastPath);
10122         StringInfoGateRef stringInfoGate(&thisFlat);
10123         GateRef data = GetNormalStringData(glue, stringInfoGate);
10124         c = ZExtInt8ToInt32(LoadZeroOffsetPrimitive(VariableType::INT8(), data));
10125         Label isDigitZero(env);
10126         Label notDigitZero(env);
10127         BRANCH(Int32Equal(*c, Int32('0')), &isDigitZero, &notDigitZero);
10128         Bind(&isDigitZero);
10129         {
10130             Label lengthIsOne(env);
10131             BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
10132             Bind(&lengthIsOne);
10133             {
10134                 result = Int32(0);
10135                 Jump(&exit);
10136             }
10137         }
10138         Bind(&notDigitZero);
10139         {
10140             Label isDigit(env);
10141             Label notIsDigit(env);
10142             DEFVARIABLE(i, VariableType::INT32(), Int32(1));
10143             DEFVARIABLE(n, VariableType::INT64(), Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
10144 
10145             BRANCH(IsDigit(*c), &isDigit, &notIsDigit);
10146             Label loopHead(env);
10147             Label loopEnd(env);
10148             Label afterLoop(env);
10149             Bind(&isDigit);
10150             BRANCH(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
10151             LoopBegin(&loopHead);
10152             {
10153                 c = ZExtInt8ToInt32(LoadPrimitive(VariableType::INT8(), data, ZExtInt32ToPtr(*i)));
10154                 Label isDigit2(env);
10155                 Label notDigit2(env);
10156                 BRANCH(IsDigit(*c), &isDigit2, &notDigit2);
10157                 Bind(&isDigit2);
10158                 {
10159                     // 10 means the base of digit is 10.
10160                     n = Int64Add(Int64Mul(*n, Int64(10)),
10161                                  Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
10162                     i = Int32Add(*i, Int32(1));
10163                     BRANCH(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
10164                 }
10165                 Bind(&notDigit2);
10166                 {
10167                     Label hasPoint(env);
10168                     BRANCH(Int32Equal(*c, Int32('.')), &hasPoint, &exit);
10169                     Bind(&hasPoint);
10170                     {
10171                         result = Int32(-2); // -2:return -2 means should goto slow path
10172                         Jump(&exit);
10173                     }
10174                 }
10175             }
10176             Bind(&loopEnd);
10177             LoopEnd(&loopHead);
10178             Bind(&afterLoop);
10179             {
10180                 Label lessThanMaxIndex(env);
10181                 BRANCH(Int64LessThan(*n, Int64(JSObject::MAX_ELEMENT_INDEX)),
10182                        &lessThanMaxIndex, &exit);
10183                 Bind(&lessThanMaxIndex);
10184                 {
10185                     result = TruncInt64ToInt32(*n);
10186                     Jump(&exit);
10187                 }
10188             }
10189             Bind(&notIsDigit);
10190             {
10191                 Label isNegative(env);
10192                 BRANCH(Int32Equal(*c, Int32('-')), &isNegative, &exit);
10193                 Bind(&isNegative);
10194                 {
10195                     result = Int32(-2); // -2:return -2 means should goto slow path
10196                     Jump(&exit);
10197                 }
10198             }
10199         }
10200     }
10201     Bind(&exit);
10202     auto ret = *result;
10203     env->SubCfgExit();
10204     return ret;
10205 }
10206 
GetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef jsType)10207 GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder,
10208                                                 GateRef key, GateRef jsType)
10209 {
10210     auto env = GetEnvironment();
10211     Label entry(env);
10212     env->SubCfgEntry(&entry);
10213     Label exit(env);
10214     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10215 
10216     Label notOnProtoChain(env);
10217     BRANCH(Int64NotEqual(receiver, holder), &exit, &notOnProtoChain);
10218     Bind(&notOnProtoChain);
10219 
10220     auto negativeZero = GetGlobalConstantValue(
10221         VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
10222     Label isNegativeZero(env);
10223     Label notNegativeZero(env);
10224     BRANCH(Equal(negativeZero, key), &isNegativeZero, &notNegativeZero);
10225     Bind(&isNegativeZero);
10226     {
10227         result = Undefined();
10228         Jump(&exit);
10229     }
10230     Bind(&notNegativeZero);
10231     {
10232         GateRef index = TryStringOrSymbolToElementIndex(glue, key);
10233         Label validIndex(env);
10234         Label notValidIndex(env);
10235         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
10236         Bind(&validIndex);
10237         {
10238             BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this, GetCurrentGlobalEnv());
10239             result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, holder, index, jsType);
10240             Jump(&exit);
10241         }
10242         Bind(&notValidIndex);
10243         {
10244             Label returnNull(env);
10245             BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
10246             Bind(&returnNull);
10247             {
10248                 result = Null();
10249                 Jump(&exit);
10250             }
10251         }
10252     }
10253 
10254     Bind(&exit);
10255     auto ret = *result;
10256     env->SubCfgExit();
10257     return ret;
10258 }
10259 
SetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef value,GateRef jsType)10260 GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key,
10261                                                 GateRef value, GateRef jsType)
10262 {
10263     auto env = GetEnvironment();
10264     Label entry(env);
10265     env->SubCfgEntry(&entry);
10266     Label exit(env);
10267     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10268     Label notOnProtoChain(env);
10269     BRANCH(Int64NotEqual(receiver, holder), &exit, &notOnProtoChain);
10270     Bind(&notOnProtoChain);
10271 
10272     auto negativeZero = GetGlobalConstantValue(
10273         VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
10274     Label isNegativeZero(env);
10275     Label notNegativeZero(env);
10276     BRANCH(Equal(negativeZero, key), &isNegativeZero, &notNegativeZero);
10277     Bind(&isNegativeZero);
10278     {
10279         Label isObj(env);
10280         Label notObj(env);
10281         BRANCH(IsEcmaObject(glue, value), &isObj, &notObj);
10282         Bind(&isObj);
10283         {
10284             result = Null();
10285             Jump(&exit);
10286         }
10287         Bind(&notObj);
10288         result = Undefined();
10289         Jump(&exit);
10290     }
10291     Bind(&notNegativeZero);
10292     {
10293         GateRef index = TryStringOrSymbolToElementIndex(glue, key);
10294         Label validIndex(env);
10295         Label notValidIndex(env);
10296         BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
10297         Bind(&validIndex);
10298         {
10299             result = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
10300                 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType) });
10301             Jump(&exit);
10302         }
10303         Bind(&notValidIndex);
10304         {
10305             Label returnNull(env);
10306             BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
10307             Bind(&returnNull);
10308             {
10309                 result = Null();
10310                 Jump(&exit);
10311             }
10312         }
10313     }
10314 
10315     Bind(&exit);
10316     auto ret = *result;
10317     env->SubCfgExit();
10318     return ret;
10319 }
10320 
Assert(int messageId,int line,GateRef glue,GateRef condition,Label * nextLabel)10321 void StubBuilder::Assert(int messageId, int line, GateRef glue, GateRef condition, Label *nextLabel)
10322 {
10323     auto env = GetEnvironment();
10324     Label ok(env);
10325     Label notOk(env);
10326     BRANCH(condition, &ok, &notOk);
10327     Bind(&ok);
10328     {
10329         Jump(nextLabel);
10330     }
10331     Bind(&notOk);
10332     {
10333         FatalPrint(glue, { Int32(messageId), Int32(line) });
10334         Jump(nextLabel);
10335     }
10336 }
10337 
GetNormalStringData(GateRef glue,const StringInfoGateRef & stringInfoGate)10338 GateRef StubBuilder::GetNormalStringData([[maybe_unused]] GateRef glue, const StringInfoGateRef &stringInfoGate)
10339 {
10340     auto env = GetEnvironment();
10341     Label entry(env);
10342     env->SubCfgEntry(&entry);
10343     Label exit(env);
10344     Label isUtf8(env);
10345     Label isUtf16(env);
10346     DEFVARIABLE(result, VariableType::NATIVE_POINTER(), Undefined());
10347     GateRef data = ChangeTaggedPointerToInt64(
10348         PtrAdd(stringInfoGate.GetString(), IntPtr(LineString::DATA_OFFSET)));
10349     BRANCH(IsUtf8String(stringInfoGate.GetString()), &isUtf8, &isUtf16);
10350     Bind(&isUtf8);
10351     {
10352         result = PtrAdd(data, ZExtInt32ToPtr(stringInfoGate.GetStartIndex()));
10353         Jump(&exit);
10354     }
10355     Bind(&isUtf16);
10356     {
10357         GateRef offset = PtrMul(ZExtInt32ToPtr(stringInfoGate.GetStartIndex()), IntPtr(sizeof(uint16_t)));
10358         result = PtrAdd(data, offset);
10359         Jump(&exit);
10360     }
10361     Bind(&exit);
10362     auto ret = *result;
10363     env->SubCfgExit();
10364     return ret;
10365 }
10366 
ToNumber(GateRef glue,GateRef tagged)10367 GateRef StubBuilder::ToNumber(GateRef glue, GateRef tagged)
10368 {
10369     auto env = GetEnvironment();
10370     Label entry(env);
10371     env->SubCfgEntry(&entry);
10372     Label exit(env);
10373     Label isNumber(env);
10374     Label notNumber(env);
10375     Label isUndefinedOrNull(env);
10376     Label notUndefinedOrNull(env);
10377     Label defaultLabel(env);
10378     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10379     BRANCH(TaggedIsNumber(tagged), &isNumber, &notNumber);
10380     Bind(&isNumber);
10381     {
10382         result = tagged;
10383         Jump(&exit);
10384     }
10385     Bind(&notNumber);
10386     {
10387         GateRef flag = LogicOrBuilder(env)
10388             .Or(TaggedIsUndefined(tagged))
10389             .Or(TaggedIsHole(tagged))
10390             .Done();
10391         BRANCH(flag, &isUndefinedOrNull, &notUndefinedOrNull);
10392         Bind(&isUndefinedOrNull);
10393         {
10394             result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
10395             Jump(&exit);
10396         }
10397         Bind(&notUndefinedOrNull);
10398         {
10399             Label isTrue(env);
10400             Label notTrue(env);
10401             BRANCH(TaggedIsTrue(tagged), &isTrue, &notTrue);
10402             Bind(&isTrue);
10403             {
10404                 result = DoubleToTaggedDoublePtr(Double(1));
10405                 Jump(&exit);
10406             }
10407             Bind(&notTrue);
10408             {
10409                 Label isFlaseOrNull(env);
10410                 GateRef flag1 = LogicOrBuilder(env)
10411                     .Or(TaggedIsFalse(tagged))
10412                     .Or(TaggedIsNull(tagged))
10413                     .Done();
10414                 BRANCH(flag1, &isFlaseOrNull, &defaultLabel);
10415                 Bind(&isFlaseOrNull);
10416                 {
10417                     result = DoubleToTaggedDoublePtr(Double(0));
10418                     Jump(&exit);
10419                 }
10420             }
10421         }
10422     }
10423     Bind(&defaultLabel);
10424     {
10425         result = CallRuntime(glue, RTSTUB_ID(ToNumber), { tagged });
10426         Jump(&exit);
10427     }
10428     Bind(&exit);
10429     auto ret = *result;
10430     env->SubCfgExit();
10431     return ret;
10432 }
10433 
ToIndex(GateRef glue,GateRef tagged)10434 GateRef StubBuilder::ToIndex(GateRef glue, GateRef tagged)
10435 {
10436     auto env = GetEnvironment();
10437     Label entry(env);
10438     env->SubCfgEntry(&entry);
10439     Label exit(env);
10440     Label isInt(env);
10441     Label notInt(env);
10442     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10443     BRANCH(TaggedIsInt(tagged), &isInt, &notInt);
10444     Bind(&isInt);
10445     {
10446         Label lessThanZero(env);
10447         Label greaterOrEqualZero(env);
10448         BRANCH(Int32GreaterThanOrEqual(TaggedGetInt(tagged), Int32(0)), &greaterOrEqualZero, &notInt);
10449         Bind(&greaterOrEqualZero);
10450         {
10451             result = tagged;
10452             Jump(&exit);
10453         }
10454     }
10455     Bind(&notInt);
10456     {
10457         Label isUndef(env);
10458         Label notUndef(env);
10459         BRANCH(TaggedIsUndefined(tagged), &isUndef, &notUndef);
10460         Bind(&isUndef);
10461         {
10462             result = IntToTaggedPtr(Int32(0));
10463             Jump(&exit);
10464         }
10465         Bind(&notUndef);
10466         {
10467             result = CallRuntime(glue, RTSTUB_ID(ToIndex), { tagged });
10468             Jump(&exit);
10469         }
10470     }
10471     Bind(&exit);
10472     auto ret = *result;
10473     env->SubCfgExit();
10474     return ret;
10475 }
10476 
ToLength(GateRef glue,GateRef target)10477 GateRef StubBuilder::ToLength(GateRef glue, GateRef target)
10478 {
10479     auto env = GetEnvironment();
10480     Label subentry(env);
10481     env->SubCfgEntry(&subentry);
10482     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
10483     Label exit(env);
10484 
10485     GateRef number = ToNumber(glue, target);
10486     Label isPendingException(env);
10487     Label noPendingException(env);
10488     BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
10489     Bind(&isPendingException);
10490     {
10491         Jump(&exit);
10492     }
10493     Bind(&noPendingException);
10494     {
10495         GateRef num = GetDoubleOfTNumber(number);
10496         Label targetLessThanZero(env);
10497         Label targetGreaterThanZero(env);
10498         Label targetLessThanSafeNumber(env);
10499         Label targetGreaterThanSafeNumber(env);
10500         BRANCH(DoubleLessThan(num, Double(0.0)), &targetLessThanZero, &targetGreaterThanZero);
10501         Bind(&targetLessThanZero);
10502         {
10503             res = DoubleToTaggedDoublePtr(Double(0.0));
10504             Jump(&exit);
10505         }
10506         Bind(&targetGreaterThanZero);
10507         BRANCH(DoubleGreaterThan(num, Double(SAFE_NUMBER)), &targetGreaterThanSafeNumber, &targetLessThanSafeNumber);
10508         Bind(&targetGreaterThanSafeNumber);
10509         {
10510             res = DoubleToTaggedDoublePtr(Double(SAFE_NUMBER));
10511             Jump(&exit);
10512         }
10513         Bind(&targetLessThanSafeNumber);
10514         {
10515             res = number;
10516             Jump(&exit);
10517         }
10518     }
10519     Bind(&exit);
10520     auto ret = *res;
10521     env->SubCfgExit();
10522     return ret;
10523 }
10524 
TaggedGetNumber(GateRef x)10525 GateRef StubBuilder::TaggedGetNumber(GateRef x)
10526 {
10527     auto env = GetEnvironment();
10528     Label subentry(env);
10529     Label exit(env);
10530     env->SubCfgEntry(&subentry);
10531 
10532     Label targetIsInt(env);
10533     Label targetIsDouble(env);
10534     DEFVALUE(number, env_, VariableType::FLOAT64(), Double(0));
10535     BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
10536     Bind(&targetIsInt);
10537     {
10538         number = ChangeInt32ToFloat64(TaggedGetInt(x));
10539         Jump(&exit);
10540     }
10541     Bind(&targetIsDouble);
10542     {
10543         number = GetDoubleOfTDouble(x);
10544         Jump(&exit);
10545     }
10546     Bind(&exit);
10547     GateRef ret = *number;
10548     env->SubCfgExit();
10549     return ret;
10550 }
10551 
NumberGetInt(GateRef glue,GateRef x)10552 GateRef StubBuilder::NumberGetInt(GateRef glue, GateRef x)
10553 {
10554     auto env = GetEnvironment();
10555     Label subentry(env);
10556     Label exit(env);
10557     env->SubCfgEntry(&subentry);
10558 
10559     Label targetIsInt(env);
10560     Label targetIsDouble(env);
10561     DEFVALUE(number, env_, VariableType::INT32(), Int32(0));
10562     BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
10563     Bind(&targetIsInt);
10564     {
10565         number = TaggedGetInt(x);
10566         Jump(&exit);
10567     }
10568     Bind(&targetIsDouble);
10569     {
10570         number = DoubleToInt(glue, GetDoubleOfTDouble(x));
10571         Jump(&exit);
10572     }
10573     Bind(&exit);
10574     GateRef ret = *number;
10575     env->SubCfgExit();
10576     return ret;
10577 }
10578 
IsStableJSArguments(GateRef glue,GateRef obj)10579 GateRef StubBuilder::IsStableJSArguments(GateRef glue, GateRef obj)
10580 {
10581     auto env = GetEnvironment();
10582     Label subentry(env);
10583     env->SubCfgEntry(&subentry);
10584     DEFVARIABLE(result, VariableType::BOOL(), False());
10585     Label exit(env);
10586     Label targetIsHeapObject(env);
10587     Label targetIsStableArguments(env);
10588 
10589     BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
10590     Bind(&targetIsHeapObject);
10591     {
10592         GateRef jsHclass = LoadHClass(glue, obj);
10593         BRANCH(IsStableArguments(jsHclass), &targetIsStableArguments, &exit);
10594         Bind(&targetIsStableArguments);
10595         {
10596             GateRef globalEnv = GetCurrentGlobalEnv();
10597             result = GetArrayElementsGuardians(globalEnv);
10598             Jump(&exit);
10599         }
10600     }
10601     Bind(&exit);
10602     auto res = *result;
10603     env->SubCfgExit();
10604     return res;
10605 }
10606 
IsStableJSArray(GateRef glue,GateRef obj)10607 GateRef StubBuilder::IsStableJSArray(GateRef glue, GateRef obj)
10608 {
10609     auto env = GetEnvironment();
10610     Label subentry(env);
10611     env->SubCfgEntry(&subentry);
10612     DEFVARIABLE(result, VariableType::BOOL(), False());
10613     Label exit(env);
10614     Label targetIsHeapObject(env);
10615     Label targetIsStableArray(env);
10616     BRANCH_LIKELY(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
10617     Bind(&targetIsHeapObject);
10618     {
10619         GateRef jsHclass = LoadHClass(glue, obj);
10620         BRANCH_LIKELY(IsStableArray(jsHclass), &targetIsStableArray, &exit);
10621         Bind(&targetIsStableArray);
10622         {
10623             Label isPrototypeNotModified(env);
10624             BRANCH_UNLIKELY(IsJSArrayPrototypeModified(jsHclass), &exit, &isPrototypeNotModified);
10625             Bind(&isPrototypeNotModified);
10626             {
10627                 GateRef globalEnv = GetCurrentGlobalEnv();
10628                 GateRef guardians = GetArrayElementsGuardians(globalEnv);
10629                 result.WriteVariable(guardians);
10630                 Jump(&exit);
10631             }
10632         }
10633     }
10634     Bind(&exit);
10635     auto res = *result;
10636     env->SubCfgExit();
10637     return res;
10638 }
10639 
UpdateProfileTypeInfo(GateRef glue,GateRef jsFunc)10640 GateRef StubBuilder::UpdateProfileTypeInfo(GateRef glue, GateRef jsFunc)
10641 {
10642     auto env = GetEnvironment();
10643     Label entry(env);
10644     env->SubCfgEntry(&entry);
10645     Label needUpdate(env);
10646     Label exit(env);
10647     DEFVARIABLE(profileTypeInfo, VariableType::JS_POINTER(), GetProfileTypeInfo(glue, jsFunc));
10648     BRANCH(TaggedIsUndefined(*profileTypeInfo), &needUpdate, &exit);
10649     Bind(&needUpdate);
10650     {
10651         profileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounter), { jsFunc });
10652         Jump(&exit);
10653     }
10654     Bind(&exit);
10655     auto ret = *profileTypeInfo;
10656     env->SubCfgExit();
10657     return ret;
10658 }
10659 
GetFuncKind(GateRef method)10660 GateRef StubBuilder::GetFuncKind(GateRef method)
10661 {
10662     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
10663     GateRef bitfield = LoadPrimitive(VariableType::INT32(), method, extraLiteralInfoOffset);
10664 
10665     GateRef kind = Int32And(Int32LSR(bitfield, Int32(Method::FunctionKindBits::START_BIT)),
10666                             Int32((1LU << Method::FunctionKindBits::SIZE) - 1));
10667     return kind;
10668 }
10669 
GetCallSpreadArgs(GateRef glue,GateRef array,ProfileOperation callBack)10670 GateRef StubBuilder::GetCallSpreadArgs(GateRef glue, GateRef array, ProfileOperation callBack)
10671 {
10672     auto env = GetEnvironment();
10673     Label subEntry(env);
10674     env->SubCfgEntry(&subEntry);
10675     DEFVARIABLE(result, VariableType::JS_POINTER(), NullPtr());
10676     Label fastPath(env);
10677     Label noCopyPath(env);
10678     Label exit(env);
10679     Label noException(env);
10680     Label isException(env);
10681 
10682     GateRef itor = GetIterator(glue, array, callBack);
10683     BRANCH(TaggedIsException(itor), &isException, &noException);
10684     Bind(&isException);
10685     {
10686         result = Exception();
10687         Jump(&exit);
10688     }
10689     Bind(&noException);
10690     GateRef needCopy = LogicAndBuilder(env)
10691         .And(Int32Equal(GetObjectType(LoadHClass(glue, itor)), Int32(static_cast<int32_t>(JSType::JS_ARRAY_ITERATOR))))
10692         .And(IsStableJSArray(glue, array))
10693         .Done();
10694     BRANCH(needCopy, &fastPath, &noCopyPath);
10695     Bind(&fastPath);
10696     {
10697         // copy operation is omitted
10698         result = CopyJSArrayToTaggedArrayArgs(glue, array);
10699         Jump(&exit);
10700     }
10701     Bind(&noCopyPath);
10702     {
10703         result = CallRuntime(glue, RTSTUB_ID(GetCallSpreadArgs), { array });
10704         Jump(&exit);
10705     }
10706     Bind(&exit);
10707     auto ret = *result;
10708     env->SubCfgExit();
10709     return ret;
10710 }
10711 
CalArrayRelativePos(GateRef index,GateRef arrayLen)10712 GateRef StubBuilder::CalArrayRelativePos(GateRef index, GateRef arrayLen)
10713 {
10714     auto env = GetEnvironment();
10715     Label entryPass(env);
10716     env->SubCfgEntry(&entryPass);
10717     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
10718 
10719     Label indexLessZero(env);
10720     Label indexNotLessZero(env);
10721     Label exit(env);
10722     BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
10723     Bind(&indexLessZero);
10724     {
10725         GateRef tempBeginIndex = Int32Add(arrayLen, index);
10726         Label beginIndexLargeZero(env);
10727         BRANCH(Int32GreaterThan(tempBeginIndex, Int32(0)), &beginIndexLargeZero, &exit);
10728         Bind(&beginIndexLargeZero);
10729         {
10730             result = tempBeginIndex;
10731             Jump(&exit);
10732         }
10733     }
10734     Bind(&indexNotLessZero);
10735     {
10736         Label lessLen(env);
10737         Label largeLen(env);
10738         BRANCH(Int32LessThan(index, arrayLen), &lessLen, &largeLen);
10739         Bind(&lessLen);
10740         {
10741             result = index;
10742             Jump(&exit);
10743         }
10744         Bind(&largeLen);
10745         {
10746             result = arrayLen;
10747             Jump(&exit);
10748         }
10749     }
10750 
10751     Bind(&exit);
10752     auto ret = *result;
10753     env->SubCfgExit();
10754     return ret;
10755 }
10756 
AppendSkipHole(GateRef glue,GateRef first,GateRef second,GateRef copyLength)10757 GateRef StubBuilder::AppendSkipHole(GateRef glue, GateRef first, GateRef second, GateRef copyLength)
10758 {
10759     auto env = GetEnvironment();
10760     Label subEntry(env);
10761     env->SubCfgEntry(&subEntry);
10762     Label exit(env);
10763     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
10764     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
10765     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
10766 
10767     GateRef firstLength = GetLengthOfTaggedArray(first);
10768     GateRef secondLength = GetLengthOfTaggedArray(second);
10769     NewObjectStubBuilder newBuilder(this);
10770     GateRef array = newBuilder.NewTaggedArray(glue, copyLength);
10771     Label loopHead(env);
10772     Label loopEnd(env);
10773     Label afterLoop(env);
10774     Label storeValue(env);
10775     Label notHole(env);
10776     Jump(&loopHead);
10777     LoopBegin(&loopHead);
10778     {
10779         BRANCH(Int32UnsignedLessThan(*index, firstLength), &storeValue, &afterLoop);
10780         Bind(&storeValue);
10781         {
10782             GateRef value = GetValueFromTaggedArray(glue, first, *index);
10783             BRANCH(TaggedIsHole(value), &afterLoop, &notHole);
10784             Bind(&notHole);
10785             SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value);
10786             index = Int32Add(*index, Int32(1));
10787             Jump(&loopEnd);
10788         }
10789     }
10790     Bind(&loopEnd);
10791     LoopEndWithCheckSafePoint(&loopHead, env, glue);
10792     Bind(&afterLoop);
10793     {
10794         Label loopHead1(env);
10795         Label loopEnd1(env);
10796         Label storeValue1(env);
10797         Label notHole1(env);
10798         Jump(&loopHead1);
10799         LoopBegin(&loopHead1);
10800         {
10801             BRANCH(Int32UnsignedLessThan(*i, secondLength), &storeValue1, &exit);
10802             Bind(&storeValue1);
10803             {
10804                 GateRef value1 = GetValueFromTaggedArray(glue, second, *i);
10805                 BRANCH(TaggedIsHole(value1), &exit, &notHole1);
10806                 Bind(&notHole1);
10807                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value1);
10808                 i = Int32Add(*i, Int32(1));
10809                 index = Int32Add(*index, Int32(1));
10810                 Jump(&loopEnd1);
10811             }
10812         }
10813         Bind(&loopEnd1);
10814         LoopEnd(&loopHead1);
10815     }
10816     Bind(&exit);
10817     res = array;
10818     auto ret = *res;
10819     env->SubCfgExit();
10820     return ret;
10821 }
10822 
ToCharCode(GateRef number)10823 GateRef StubBuilder::ToCharCode(GateRef number)
10824 {
10825     auto env = GetEnvironment();
10826     Label subEntry(env);
10827     env->SubCfgEntry(&subEntry);
10828     Label exit(env);
10829     DEFVARIABLE(result, VariableType::INT32(), number);
10830 
10831     Label lessThanTen(env);
10832     Label notLessThanTen(env);
10833     BRANCH(Int32LessThan(number, Int32(10)), &lessThanTen, &notLessThanTen); // 10: means number
10834     Bind(&lessThanTen);
10835     {
10836         result = Int32Add(Int32('0'), *result);
10837         Jump(&exit);
10838     }
10839     Bind(&notLessThanTen);
10840     {
10841         result = Int32Sub(*result, Int32(10)); // 10: means number
10842         result = Int32Add(Int32('a'), *result);
10843         Jump(&exit);
10844     }
10845     Bind(&exit);
10846     auto ret = *result;
10847     env->SubCfgExit();
10848     return ret;
10849 }
10850 
IntToEcmaString(GateRef glue,GateRef number)10851 GateRef StubBuilder::IntToEcmaString(GateRef glue, GateRef number)
10852 {
10853     auto env = GetEnvironment();
10854     Label subEntry(env);
10855     env->SubCfgEntry(&subEntry);
10856     Label exit(env);
10857     DEFVARIABLE(n, VariableType::INT32(), number);
10858     DEFVARIABLE(result, VariableType::JS_POINTER(), Hole());
10859 
10860     GateRef isPositive = Int32GreaterThanOrEqual(number, Int32(0));
10861     GateRef isSingle = Int32LessThan(number, Int32(10));
10862     Label process(env);
10863     Label callRuntime(env);
10864     Label afterNew(env);
10865     BRANCH(BitAnd(isPositive, isSingle), &process, &callRuntime);
10866     Bind(&process);
10867     {
10868         NewObjectStubBuilder newBuilder(this);
10869         newBuilder.SetParameters(glue, 0);
10870         newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), true);
10871         Bind(&afterNew);
10872         n = Int32Add(Int32('0'), *n);
10873         GateRef dst = ChangeTaggedPointerToInt64(PtrAdd(*result, IntPtr(LineString::DATA_OFFSET)));
10874         Store(VariableType::INT8(), glue, dst, IntPtr(0), TruncInt32ToInt8(*n));
10875         Jump(&exit);
10876     }
10877     Bind(&callRuntime);
10878     {
10879         result = CallRuntime(glue, RTSTUB_ID(IntToString), { IntToTaggedInt(*n) });
10880         Jump(&exit);
10881     }
10882     Bind(&exit);
10883     auto ret = *result;
10884     env->SubCfgExit();
10885     return ret;
10886 }
10887 
NumberToString(GateRef glue,GateRef number)10888 GateRef StubBuilder::NumberToString(GateRef glue, GateRef number)
10889 {
10890     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
10891     res = CallRuntime(glue, RTSTUB_ID(NumberToString), { number });
10892     return *res;
10893 }
10894 
RestoreElementsKindToGeneric(GateRef glue,GateRef jsHClass)10895 void StubBuilder::RestoreElementsKindToGeneric(GateRef glue, GateRef jsHClass)
10896 {
10897     GateRef newKind = Int32(Elements::ToUint(ElementsKind::GENERIC));
10898     SetElementsKindToJSHClass(glue, jsHClass, newKind);
10899 }
10900 
GetTaggedValueWithElementsKind(GateRef glue,GateRef receiver,GateRef index)10901 GateRef StubBuilder::GetTaggedValueWithElementsKind(GateRef glue, GateRef receiver, GateRef index)
10902 {
10903     auto env = GetEnvironment();
10904     Label entryPass(env);
10905     env->SubCfgEntry(&entryPass);
10906     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10907     Label exit(env);
10908     Label enableMutantArray(env);
10909     Label disableMutantArray(env);
10910     Label isMutantTaggedArray(env);
10911     Label isNotMutantTaggedArray(env);
10912     GateRef elements = GetElementsArray(glue, receiver);
10913     BRANCH_UNLIKELY(IsEnableMutantArray(glue), &enableMutantArray, &disableMutantArray);
10914     Bind(&disableMutantArray);
10915     {
10916         result = GetValueFromTaggedArray(glue, elements, index);
10917         Jump(&exit);
10918     }
10919     Bind(&enableMutantArray);
10920     GateRef hclass = LoadHClass(glue, receiver);
10921     DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
10922     BRANCH(IsMutantTaggedArray(glue, elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
10923     Bind(&isNotMutantTaggedArray);
10924     {
10925         elementsKind = Int32(Elements::ToUint(ElementsKind::GENERIC));
10926         Jump(&isMutantTaggedArray);
10927     }
10928     Bind(&isMutantTaggedArray);
10929     GateRef rawValue = GetValueFromMutantTaggedArray(elements, index);
10930     Label isSpecialHole(env);
10931     Label isNotSpecialHole(env);
10932     BRANCH(Int64Equal(rawValue, SpecialHole()), &isSpecialHole, &isNotSpecialHole);
10933     Bind(&isSpecialHole);
10934     {
10935         Jump(&exit);
10936     }
10937     Bind(&isNotSpecialHole);
10938     {
10939         Label isInt(env);
10940         Label isNotInt(env);
10941         GateRef elementsKindIntLowerBound = Int32GreaterThanOrEqual(*elementsKind,
10942                                                                     Int32(Elements::ToUint(ElementsKind::INT)));
10943         GateRef elementsKindIntUpperBound = Int32LessThanOrEqual(*elementsKind,
10944                                                                  Int32(Elements::ToUint(ElementsKind::HOLE_INT)));
10945         GateRef checkIntKind = BitAnd(elementsKindIntLowerBound, elementsKindIntUpperBound);
10946         BRANCH(checkIntKind, &isInt, &isNotInt);
10947         Bind(&isInt);
10948         {
10949             result = Int64ToTaggedIntPtr(rawValue);
10950             Jump(&exit);
10951         }
10952         Bind(&isNotInt);
10953         {
10954             Label isNumber(env);
10955             Label isNotNumber(env);
10956             GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
10957                                                                    Int32(Elements::ToUint(ElementsKind::NUMBER)));
10958             GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
10959                                                                 Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)));
10960             GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
10961             BRANCH(checkNumberKind, &isNumber, &isNotNumber);
10962             Bind(&isNumber);
10963             {
10964                 GateRef numberValue = CastInt64ToFloat64(rawValue);
10965                 result = DoubleToTaggedDoublePtr(numberValue);
10966                 Jump(&exit);
10967             }
10968             Bind(&isNotNumber);
10969             {
10970                 result = Int64ToTaggedPtr(rawValue);
10971                 Jump(&exit);
10972             }
10973         }
10974     }
10975     Bind(&exit);
10976     auto ret = *result;
10977     env->SubCfgExit();
10978     return ret;
10979 }
10980 
ConvertTaggedValueWithElementsKind(GateRef glue,GateRef value,GateRef extraKind)10981 GateRef StubBuilder::ConvertTaggedValueWithElementsKind([[maybe_unused]] GateRef glue, GateRef value, GateRef  extraKind)
10982 {
10983     auto env = GetEnvironment();
10984     Label entryPass(env);
10985     env->SubCfgEntry(&entryPass);
10986     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10987     Label exit(env);
10988     Label isHole(env);
10989     Label isNotHole(env);
10990     GateRef valueIsHole = TaggedIsHole(value);
10991     GateRef elementsKindInNumbersLB = Int32GreaterThanOrEqual(extraKind,
10992                                                               Int32(Elements::ToUint(ElementsKind::HOLE)));
10993     GateRef elementsKindInNumbersUB = Int32LessThan(extraKind, Int32(Elements::ToUint(ElementsKind::STRING)));
10994     GateRef checkInNumersKind = LogicAndBuilder(env)
10995         .And(valueIsHole)
10996         .And(elementsKindInNumbersLB)
10997         .And(elementsKindInNumbersUB).Done();
10998     BRANCH(checkInNumersKind, &isHole, &isNotHole);
10999     Bind(&isHole);
11000     {
11001         Jump(&exit);
11002     }
11003     Bind(&isNotHole);
11004     {
11005         Label isInt(env);
11006         Label isNotInt(env);
11007         GateRef elementsKindIntLB = Int32GreaterThanOrEqual(extraKind,
11008                                                             Int32(Elements::ToUint(ElementsKind::INT)));
11009         GateRef elementsKindIntUB = Int32LessThanOrEqual(extraKind,
11010                                                          Int32(Elements::ToUint(ElementsKind::HOLE_INT)));
11011         GateRef checkIntKind = LogicAndBuilder(env)
11012             .And(elementsKindIntLB)
11013             .And(elementsKindIntUB)
11014             .Done();
11015         BRANCH(checkIntKind, &isInt, &isNotInt);
11016         Bind(&isInt);
11017         {
11018             result = Int64ToTaggedPtr(GetInt64OfTInt(value));
11019             Jump(&exit);
11020         }
11021         Bind(&isNotInt);
11022         {
11023             Label isNumber(env);
11024             Label isNotNumber(env);
11025             GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(extraKind,
11026                                                                    Int32(Elements::ToUint(ElementsKind::NUMBER)));
11027             GateRef elementsKindNumberUB = Int32LessThanOrEqual(extraKind,
11028                                                                 Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)));
11029             GateRef checkNumberKind = LogicAndBuilder(env)
11030                 .And(elementsKindNumberLB)
11031                 .And(elementsKindNumberUB)
11032                 .Done();
11033             BRANCH(checkNumberKind, &isNumber, &isNotNumber);
11034             Bind(&isNumber);
11035             {
11036                 Label isNumberInt(env);
11037                 Label isNotNumberInt(env);
11038                 BRANCH(TaggedIsInt(value), &isNumberInt, &isNotNumberInt);
11039                 Bind(&isNumberInt);
11040                 {
11041                     result = Int64ToTaggedPtr(CastDoubleToInt64(GetDoubleOfTInt(value)));
11042                     Jump(&exit);
11043                 }
11044                 Bind(&isNotNumberInt);
11045                 {
11046                     result = Int64ToTaggedPtr(CastDoubleToInt64(GetDoubleOfTDouble(value)));
11047                     Jump(&exit);
11048                 }
11049             }
11050             Bind(&isNotNumber);
11051             {
11052                 result = value;
11053                 Jump(&exit);
11054             }
11055         }
11056     }
11057     Bind(&exit);
11058     auto ret = *result;
11059     env->SubCfgExit();
11060     return ret;
11061 }
11062 
SetValueWithElementsKind(GateRef glue,GateRef receiver,GateRef rawValue,GateRef index,GateRef needTransition,GateRef extraKind)11063 GateRef StubBuilder::SetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef rawValue,
11064                                               GateRef index, GateRef needTransition, GateRef extraKind)
11065 {
11066     auto env = GetEnvironment();
11067     Label entryPass(env);
11068     env->SubCfgEntry(&entryPass);
11069     DEFVARIABLE(result, VariableType::INT64(), SpecialHole());
11070     Label exit(env);
11071 
11072     Label transitElementsKind(env);
11073     Label finishTransition(env);
11074     BRANCH(needTransition, &transitElementsKind, &finishTransition);
11075     Bind(&transitElementsKind);
11076     {
11077         TransitToElementsKind(glue, receiver, rawValue, extraKind);
11078         Jump(&finishTransition);
11079     }
11080     Bind(&finishTransition);
11081     GateRef elements = GetElementsArray(glue, receiver);
11082     Label enableMutantArray(env);
11083     Label disableMutantArray(env);
11084     BRANCH_UNLIKELY(IsEnableMutantArray(glue), &enableMutantArray, &disableMutantArray);
11085     Bind(&disableMutantArray);
11086     {
11087         SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, rawValue);
11088         Jump(&exit);
11089     }
11090     Bind(&enableMutantArray);
11091     Label setValue(env);
11092     Label isMutantTaggedArray(env);
11093     Label isNotMutantTaggedArray(env);
11094     GateRef hclass = LoadHClass(glue, receiver);
11095     DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
11096     BRANCH(IsMutantTaggedArray(glue, elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
11097     Bind(&isNotMutantTaggedArray);
11098     {
11099         elementsKind = Int32(Elements::ToUint(ElementsKind::GENERIC));
11100         Jump(&isMutantTaggedArray);
11101     }
11102     Bind(&isMutantTaggedArray);
11103     Label isHole(env);
11104     Label isNotHole(env);
11105     GateRef elementsKindVal = *elementsKind;
11106     GateRef checkInNumersKind = LogicAndBuilder(env)
11107         .And(TaggedIsHole(rawValue))
11108         .And(Int32GreaterThanOrEqual(elementsKindVal, Int32(Elements::ToUint(ElementsKind::HOLE))))
11109         .And(Int32LessThan(elementsKindVal, Int32(Elements::ToUint(ElementsKind::STRING))))
11110         .Done();
11111     BRANCH(checkInNumersKind, &isHole, &isNotHole);
11112     Bind(&isHole);
11113     {
11114         Jump(&setValue);
11115     }
11116     Bind(&isNotHole);
11117     {
11118         Label isInt(env);
11119         Label isNotInt(env);
11120         GateRef elementsKindIntLB = Int32GreaterThanOrEqual(*elementsKind,
11121                                                             Int32(Elements::ToUint(ElementsKind::INT)));
11122         GateRef elementsKindIntUB = Int32LessThanOrEqual(*elementsKind,
11123                                                          Int32(Elements::ToUint(ElementsKind::HOLE_INT)));
11124         GateRef checkIntKind = BitAnd(elementsKindIntLB, elementsKindIntUB);
11125         BRANCH(checkIntKind, &isInt, &isNotInt);
11126         Bind(&isInt);
11127         {
11128             result = GetInt64OfTInt(rawValue);
11129             Jump(&setValue);
11130         }
11131         Bind(&isNotInt);
11132         {
11133             Label isNumber(env);
11134             Label isNotNumber(env);
11135             GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
11136                                                                    Int32(Elements::ToUint(ElementsKind::NUMBER)));
11137             GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
11138                                                                 Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)));
11139             GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
11140             BRANCH(checkNumberKind, &isNumber, &isNotNumber);
11141             Bind(&isNumber);
11142             {
11143                 Label isNumberInt(env);
11144                 Label isNotNumberInt(env);
11145                 BRANCH(TaggedIsInt(rawValue), &isNumberInt, &isNotNumberInt);
11146                 Bind(&isNumberInt);
11147                 {
11148                     result = CastDoubleToInt64(GetDoubleOfTInt(rawValue));
11149                     Jump(&setValue);
11150                 }
11151                 Bind(&isNotNumberInt);
11152                 {
11153                     result = CastDoubleToInt64(GetDoubleOfTDouble(rawValue));
11154                     Jump(&setValue);
11155                 }
11156             }
11157             Bind(&isNotNumber);
11158             {
11159                 result = ChangeTaggedPointerToInt64(rawValue);
11160                 Jump(&setValue);
11161             }
11162         }
11163     }
11164     Bind(&setValue);
11165     Label storeToNormalArray(env);
11166     Label storeToMutantArray(env);
11167     BRANCH(TaggedIsHeapObject(rawValue), &storeToNormalArray, &storeToMutantArray);
11168     Bind(&storeToNormalArray);
11169     {
11170         SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, *result);
11171         Jump(&exit);
11172     }
11173     Bind(&storeToMutantArray);
11174     {
11175         SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, *result);
11176         Jump(&exit);
11177     }
11178     Bind(&exit);
11179     auto ret = *result;
11180     env->SubCfgExit();
11181     return ret;
11182 }
11183 
FastSetValueWithElementsKind(GateRef glue,GateRef receiver,GateRef elements,GateRef rawValue,GateRef index,ElementsKind kind,bool needTransition)11184 void StubBuilder::FastSetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef elements, GateRef rawValue,
11185                                                GateRef index, ElementsKind kind, bool needTransition)
11186 {
11187     auto env = GetEnvironment();
11188     Label entryPass(env);
11189     env->SubCfgEntry(&entryPass);
11190     Label exit(env);
11191     if (needTransition) {
11192         TransitToElementsKind(glue, receiver, rawValue, Int32(Elements::ToUint(ElementsKind::NONE)));
11193     }
11194     if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
11195         SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
11196         Jump(&exit);
11197     } else {
11198         SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, rawValue);
11199         Jump(&exit);
11200     }
11201     Bind(&exit);
11202     env->SubCfgExit();
11203 }
11204 
CopyJSArrayToTaggedArrayArgs(GateRef glue,GateRef srcObj)11205 GateRef StubBuilder::CopyJSArrayToTaggedArrayArgs(GateRef glue, GateRef srcObj)
11206 {
11207     auto env = GetEnvironment();
11208     Label entryPass(env);
11209     env->SubCfgEntry(&entryPass);
11210     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
11211     Label exit(env);
11212 
11213     Label isMutantTaggedArray(env);
11214     result = GetElementsArray(glue, srcObj);
11215     BRANCH(IsMutantTaggedArray(glue, *result), &isMutantTaggedArray, &exit);
11216     Bind(&isMutantTaggedArray);
11217     {
11218         GateRef argvLength = GetLengthOfTaggedArray(*result);
11219         NewObjectStubBuilder newBuilder(this);
11220         GateRef argv = newBuilder.NewTaggedArray(glue, argvLength);
11221         DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11222         Label loopHead(env);
11223         Label loopEnd(env);
11224         Label afterLoop(env);
11225         Label storeValue(env);
11226         Jump(&loopHead);
11227         LoopBegin(&loopHead);
11228         {
11229             BRANCH(Int32UnsignedLessThan(*index, argvLength), &storeValue, &afterLoop);
11230             Bind(&storeValue);
11231             {
11232                 GateRef value = GetTaggedValueWithElementsKind(glue, srcObj, *index);
11233                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argv, *index, value);
11234                 index = Int32Add(*index, Int32(1));
11235                 Jump(&loopEnd);
11236             }
11237         }
11238         Bind(&loopEnd);
11239         LoopEnd(&loopHead);
11240         Bind(&afterLoop);
11241         {
11242             result = argv;
11243             Jump(&exit);
11244         }
11245     }
11246     Bind(&exit);
11247     auto ret = *result;
11248     env->SubCfgExit();
11249     return ret;
11250 }
11251 
MigrateArrayWithKind(GateRef glue,GateRef object,GateRef oldKind,GateRef newKind)11252 void StubBuilder::MigrateArrayWithKind(GateRef glue, GateRef object, GateRef oldKind, GateRef newKind)
11253 {
11254     auto env = GetEnvironment();
11255     Label entryPass(env);
11256     env->SubCfgEntry(&entryPass);
11257     Label exit(env);
11258 
11259     Label mutantArrayOn(env);
11260     BRANCH(IsEnableMutantArray(glue), &mutantArrayOn, &exit);
11261     Bind(&mutantArrayOn);
11262 
11263     DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
11264     Label doMigration(env);
11265     Label migrateFromInt(env);
11266     Label migrateOtherKinds(env);
11267 
11268     GateRef noNeedMigration = LogicOrBuilder(env)
11269         .Or(Int32Equal(oldKind, newKind))
11270         .Or(BitAnd(Int32Equal(oldKind, Int32(Elements::ToUint(ElementsKind::INT))),
11271                    Int32Equal(newKind, Int32(Elements::ToUint(ElementsKind::HOLE_INT)))))
11272         .Or(BitAnd(Int32Equal(oldKind, Int32(Elements::ToUint(ElementsKind::NUMBER))),
11273                    Int32Equal(newKind, Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)))))
11274         .Done();
11275     BRANCH(noNeedMigration, &exit, &doMigration);
11276     Bind(&doMigration);
11277     GateRef needCOW = IsJsCOWArray(glue, object);
11278     BRANCH(ElementsKindIsIntOrHoleInt(oldKind), &migrateFromInt, &migrateOtherKinds);
11279     Bind(&migrateFromInt);
11280     {
11281         Label migrateToHeapValuesFromInt(env);
11282         Label migrateToRawValuesFromInt(env);
11283         Label migrateToNumbersFromInt(env);
11284         BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromInt, &migrateToRawValuesFromInt);
11285         Bind(&migrateToHeapValuesFromInt);
11286         {
11287             newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, True());
11288             SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11289             Jump(&exit);
11290         }
11291         Bind(&migrateToRawValuesFromInt);
11292         {
11293             BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumbersFromInt, &exit);
11294             Bind(&migrateToNumbersFromInt);
11295             {
11296                 MigrateFromHoleIntToHoleNumber(glue, object);
11297                 Jump(&exit);
11298             }
11299         }
11300     }
11301     Bind(&migrateOtherKinds);
11302     {
11303         Label migrateFromNumber(env);
11304         Label migrateToHeapValuesFromNum(env);
11305         Label migrateToRawValuesFromNum(env);
11306         Label migrateToIntFromNum(env);
11307         Label migrateToRawValueFromTagged(env);
11308         BRANCH(ElementsKindIsNumOrHoleNum(oldKind), &migrateFromNumber, &migrateToRawValueFromTagged);
11309         Bind(&migrateFromNumber);
11310         {
11311             BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromNum, &migrateToRawValuesFromNum);
11312             Bind(&migrateToHeapValuesFromNum);
11313             {
11314                 Label migrateToTaggedFromNum(env);
11315                 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToTaggedFromNum, &exit);
11316                 Bind(&migrateToTaggedFromNum);
11317                 {
11318                     newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, False());
11319                     SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11320                     Jump(&exit);
11321                 }
11322             }
11323             Bind(&migrateToRawValuesFromNum);
11324             {
11325                 BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromNum, &exit);
11326                 Bind(&migrateToIntFromNum);
11327                 {
11328                     MigrateFromHoleNumberToHoleInt(glue, object);
11329                     Jump(&exit);
11330                 }
11331             }
11332         }
11333         Bind(&migrateToRawValueFromTagged);
11334         {
11335             Label migrateToIntFromTagged(env);
11336             Label migrateToOthersFromTagged(env);
11337             BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromTagged, &migrateToOthersFromTagged);
11338             Bind(&migrateToIntFromTagged);
11339             {
11340                 newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, True());
11341                 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11342                 Jump(&exit);
11343             }
11344             Bind(&migrateToOthersFromTagged);
11345             {
11346                 Label migrateToNumFromTagged(env);
11347                 BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumFromTagged, &exit);
11348                 Bind(&migrateToNumFromTagged);
11349                 {
11350                     newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, False());
11351                     SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11352                     Jump(&exit);
11353                 }
11354             }
11355         }
11356     }
11357     Bind(&exit);
11358     env->SubCfgExit();
11359 }
11360 
MigrateFromRawValueToHeapValues(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)11361 GateRef StubBuilder::MigrateFromRawValueToHeapValues(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
11362 {
11363     auto env = GetEnvironment();
11364     Label entryPass(env);
11365     env->SubCfgEntry(&entryPass);
11366     DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
11367     Label exit(env);
11368 
11369     GateRef elements = GetElementsArray(glue, object);
11370     GateRef length = GetLengthOfTaggedArray(elements);
11371     Label createCOW(env);
11372     Label createNormal(env);
11373     Label finishElementsInit(env);
11374     BRANCH(needCOW, &createCOW, &createNormal);
11375     Bind(&createCOW);
11376     {
11377         newElements = CallRuntime(glue, RTSTUB_ID(NewCOWTaggedArray), { IntToTaggedPtr(length) });
11378         Jump(&finishElementsInit);
11379     }
11380     Bind(&createNormal);
11381     {
11382         newElements = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedPtr(length) });
11383         Jump(&finishElementsInit);
11384     }
11385     Bind(&finishElementsInit);
11386 
11387     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11388     Label loopHead(env);
11389     Label loopEnd(env);
11390     Label afterLoop(env);
11391     Label storeValue(env);
11392     Jump(&loopHead);
11393     LoopBegin(&loopHead);
11394     {
11395         Label storeHole(env);
11396         Label storeNormalValue(env);
11397         Label finishStore(env);
11398         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11399         Bind(&storeValue);
11400         {
11401             Label rawValueIsInt(env);
11402             Label rawValueIsNumber(env);
11403             GateRef value = GetValueFromMutantTaggedArray(elements, *index);
11404             BRANCH(ValueIsSpecialHole(value), &storeHole, &storeNormalValue);
11405             Bind(&storeHole);
11406             {
11407                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, Hole());
11408                 Jump(&finishStore);
11409             }
11410             Bind(&storeNormalValue);
11411             {
11412                 BRANCH(isIntKind, &rawValueIsInt, &rawValueIsNumber);
11413                 Bind(&rawValueIsInt);
11414                 {
11415                     GateRef convertedInt = Int64ToTaggedIntPtr(value);
11416                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedInt);
11417                     Jump(&finishStore);
11418                 }
11419                 Bind(&rawValueIsNumber);
11420                 {
11421                     GateRef tmpDouble = CastInt64ToFloat64(value);
11422                     GateRef convertedDouble = DoubleToTaggedDoublePtr(tmpDouble);
11423                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedDouble);
11424                     Jump(&finishStore);
11425                 }
11426             }
11427             Bind(&finishStore);
11428             {
11429                 index = Int32Add(*index, Int32(1));
11430                 Jump(&loopEnd);
11431             }
11432         }
11433     }
11434     Bind(&loopEnd);
11435     LoopEnd(&loopHead);
11436     Bind(&afterLoop);
11437     {
11438         Jump(&exit);
11439     }
11440     Bind(&exit);
11441     auto ret = *newElements;
11442     env->SubCfgExit();
11443     return ret;
11444 }
11445 
MigrateFromHeapValueToRawValue(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)11446 GateRef StubBuilder::MigrateFromHeapValueToRawValue(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
11447 {
11448     auto env = GetEnvironment();
11449     Label entryPass(env);
11450     env->SubCfgEntry(&entryPass);
11451     DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
11452     Label exit(env);
11453 
11454     GateRef elements = GetElementsArray(glue, object);
11455     GateRef length = GetLengthOfTaggedArray(elements);
11456     Label createCOW(env);
11457     Label createNormal(env);
11458     Label finishElementsInit(env);
11459     BRANCH(needCOW, &createCOW, &createNormal);
11460     Bind(&createCOW);
11461     {
11462         newElements = CallRuntime(glue, RTSTUB_ID(NewCOWMutantTaggedArray), { IntToTaggedPtr(length) });
11463         Jump(&finishElementsInit);
11464     }
11465     Bind(&createNormal);
11466     {
11467         newElements = CallRuntime(glue, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedPtr(length) });
11468         Jump(&finishElementsInit);
11469     }
11470     Bind(&finishElementsInit);
11471 
11472     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11473     Label loopHead(env);
11474     Label loopEnd(env);
11475     Label afterLoop(env);
11476     Label storeValue(env);
11477     Jump(&loopHead);
11478     LoopBegin(&loopHead);
11479     {
11480         Label storeSpecialHole(env);
11481         Label storeNormalValue(env);
11482         Label finishStore(env);
11483         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11484         Bind(&storeValue);
11485         {
11486             Label convertToInt(env);
11487             Label convertToDouble(env);
11488             GateRef value = GetValueFromTaggedArray(glue, elements, *index);
11489             BRANCH(TaggedIsHole(value), &storeSpecialHole, &storeNormalValue);
11490             Bind(&storeSpecialHole);
11491             {
11492                 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, SpecialHole());
11493                 Jump(&finishStore);
11494             }
11495             Bind(&storeNormalValue);
11496             {
11497                 Label valueIsInt(env);
11498                 Label valueIsDouble(env);
11499                 BRANCH(isIntKind, &convertToInt, &convertToDouble);
11500                 Bind(&convertToInt);
11501                 {
11502                     GateRef convertedInt = GetInt64OfTInt(value);
11503                     SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, convertedInt);
11504                     Jump(&finishStore);
11505                 }
11506                 Bind(&convertToDouble);
11507                 {
11508                     BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsDouble);
11509                     Bind(&valueIsInt);
11510                     {
11511                         GateRef convertedDoubleFromTInt = CastDoubleToInt64(GetDoubleOfTInt(value));
11512                         SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
11513                                               convertedDoubleFromTInt);
11514                         Jump(&finishStore);
11515                     }
11516                     Bind(&valueIsDouble);
11517                     {
11518                         GateRef convertedDoubleFromTDouble = CastDoubleToInt64(GetDoubleOfTDouble(value));
11519                         SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
11520                                               convertedDoubleFromTDouble);
11521                         Jump(&finishStore);
11522                     }
11523                 }
11524             }
11525             Bind(&finishStore);
11526             {
11527                 index = Int32Add(*index, Int32(1));
11528                 Jump(&loopEnd);
11529             }
11530         }
11531     }
11532     Bind(&loopEnd);
11533     LoopEnd(&loopHead);
11534     Bind(&afterLoop);
11535     {
11536         Jump(&exit);
11537     }
11538     Bind(&exit);
11539     auto ret = *newElements;
11540     env->SubCfgExit();
11541     return ret;
11542 }
11543 
MigrateFromHoleIntToHoleNumber(GateRef glue,GateRef object)11544 void StubBuilder::MigrateFromHoleIntToHoleNumber(GateRef glue, GateRef object)
11545 {
11546     auto env = GetEnvironment();
11547     Label entryPass(env);
11548     env->SubCfgEntry(&entryPass);
11549     Label exit(env);
11550 
11551     GateRef elements = GetElementsArray(glue, object);
11552     GateRef length = GetLengthOfTaggedArray(elements);
11553     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11554     Label loopHead(env);
11555     Label loopEnd(env);
11556     Label afterLoop(env);
11557     Label storeValue(env);
11558     Jump(&loopHead);
11559     LoopBegin(&loopHead);
11560     {
11561         Label storeNormalValue(env);
11562         Label finishStore(env);
11563         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11564         Bind(&storeValue);
11565         {
11566             GateRef value = GetValueFromMutantTaggedArray(elements, *index);
11567             BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
11568             Bind(&storeNormalValue);
11569             {
11570                 GateRef intVal = TruncInt64ToInt32(value);
11571                 GateRef convertedValue = CastDoubleToInt64(ChangeInt32ToFloat64(intVal));
11572                 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
11573                                       convertedValue);
11574                 Jump(&finishStore);
11575             }
11576             Bind(&finishStore);
11577             {
11578                 index = Int32Add(*index, Int32(1));
11579                 Jump(&loopEnd);
11580             }
11581         }
11582     }
11583     Bind(&loopEnd);
11584     LoopEnd(&loopHead);
11585     Bind(&afterLoop);
11586     {
11587         Jump(&exit);
11588     }
11589     Bind(&exit);
11590     env->SubCfgExit();
11591 }
11592 
MigrateFromHoleNumberToHoleInt(GateRef glue,GateRef object)11593 void StubBuilder::MigrateFromHoleNumberToHoleInt(GateRef glue, GateRef object)
11594 {
11595     auto env = GetEnvironment();
11596     Label entryPass(env);
11597     env->SubCfgEntry(&entryPass);
11598     Label exit(env);
11599 
11600     GateRef elements = GetElementsArray(glue, object);
11601     GateRef length = GetLengthOfTaggedArray(elements);
11602     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11603     Label loopHead(env);
11604     Label loopEnd(env);
11605     Label afterLoop(env);
11606     Label storeValue(env);
11607     Jump(&loopHead);
11608     LoopBegin(&loopHead);
11609     {
11610         Label storeNormalValue(env);
11611         Label finishStore(env);
11612         BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11613         Bind(&storeValue);
11614         {
11615             GateRef value = GetValueFromMutantTaggedArray(elements, *index);
11616             BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
11617             Bind(&storeNormalValue);
11618             {
11619                 GateRef doubleVal = CastInt64ToFloat64(value);
11620                 GateRef convertedValue = SExtInt32ToInt64(ChangeFloat64ToInt32(doubleVal));
11621                 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
11622                                       convertedValue);
11623                 Jump(&finishStore);
11624             }
11625             Bind(&finishStore);
11626             {
11627                 index = Int32Add(*index, Int32(1));
11628                 Jump(&loopEnd);
11629             }
11630         }
11631     }
11632     Bind(&loopEnd);
11633     LoopEnd(&loopHead);
11634     Bind(&afterLoop);
11635     {
11636         Jump(&exit);
11637     }
11638     Bind(&exit);
11639     env->SubCfgExit();
11640 }
11641 
IsDetachedBuffer(GateRef glue,GateRef buffer)11642 GateRef StubBuilder::IsDetachedBuffer(GateRef glue, GateRef buffer)
11643 {
11644     auto env = GetEnvironment();
11645     Label entryPass(env);
11646     env->SubCfgEntry(&entryPass);
11647     Label isNull(env);
11648     Label exit(env);
11649     Label isByteArray(env);
11650     Label notByteArray(env);
11651     DEFVARIABLE(result, VariableType::BOOL(), False());
11652     BRANCH(IsByteArray(glue, buffer), &isByteArray, &notByteArray);
11653     Bind(&isByteArray);
11654     {
11655         Jump(&exit);
11656     }
11657     Bind(&notByteArray);
11658     {
11659         GateRef dataSlot = GetArrayBufferData(glue, buffer);
11660         BRANCH(TaggedIsNull(dataSlot), &isNull, &exit);
11661         Bind(&isNull);
11662         {
11663             result = True();
11664             Jump(&exit);
11665         }
11666     }
11667     Bind(&exit);
11668     auto ret = *result;
11669     env->SubCfgExit();
11670     return ret;
11671 }
11672 
DefineFunc(GateRef glue,GateRef constpool,GateRef index,FunctionKind targetKind)11673 GateRef StubBuilder::DefineFunc(GateRef glue, GateRef constpool, GateRef index, FunctionKind targetKind)
11674 {
11675     auto env = GetEnvironment();
11676     Label subentry(env);
11677     env->SubCfgEntry(&subentry);
11678     Label exit(env);
11679     DEFVARIABLE(ihc, VariableType::JS_ANY(), Undefined());
11680     DEFVARIABLE(val, VariableType::JS_ANY(), Undefined());
11681     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
11682 
11683     Label isHeapObject(env);
11684     Label afterAOTLiteral(env);
11685     Label tryGetAOTIhc(env);
11686     //AOT ihc infos always in unshareConstpool
11687     //If is runing on AOT,unshareConstpool is definitely not a hole
11688     //So wo can skip if unshareConstpool is hole
11689     GateRef unsharedConstpool = GetUnsharedConstpoolFromGlue(glue, constpool);
11690     BRANCH(TaggedIsHole(unsharedConstpool), &afterAOTLiteral, &tryGetAOTIhc);
11691     Bind(&tryGetAOTIhc);
11692     {
11693         val = GetValueFromTaggedArray(glue, unsharedConstpool, index);
11694         BRANCH(TaggedIsHeapObject(*val), &isHeapObject, &afterAOTLiteral);
11695         {
11696             Bind(&isHeapObject);
11697             Label isAOTLiteral(env);
11698             BRANCH(IsAOTLiteralInfo(glue, *val), &isAOTLiteral, &afterAOTLiteral);
11699             {
11700                 Bind(&isAOTLiteral);
11701                 {
11702                     ihc = GetIhcFromAOTLiteralInfo(glue, *val);
11703                     Jump(&afterAOTLiteral);
11704                 }
11705             }
11706         }
11707     }
11708     Bind(&afterAOTLiteral);
11709     GateRef method = GetMethodFromConstPool(glue, constpool, index);
11710     Label isSendableFunc(env);
11711     Label isNotSendableFunc(env);
11712     Label afterDealWithCompiledStatus(env);
11713     BRANCH(IsSendableFunction(method), &isSendableFunc, &isNotSendableFunc);
11714     Bind(&isSendableFunc);
11715     {
11716         GateRef globalEnv = GetCurrentGlobalEnv();
11717         NewObjectStubBuilder newBuilder(this, globalEnv);
11718         result = newBuilder.NewJSSendableFunction(glue, method, targetKind);
11719         Jump(&afterDealWithCompiledStatus);
11720     }
11721     Bind(&isNotSendableFunc);
11722     {
11723         GateRef globalEnv = GetCurrentGlobalEnv();
11724         NewObjectStubBuilder newBuilder(this, globalEnv);
11725         result = newBuilder.NewJSFunction(glue, method, targetKind);
11726         Jump(&afterDealWithCompiledStatus);
11727     }
11728     Bind(&afterDealWithCompiledStatus);
11729 
11730     Label ihcNotUndefined(env);
11731     BRANCH(TaggedIsUndefined(*ihc), &exit, &ihcNotUndefined);
11732     Bind(&ihcNotUndefined);
11733     {
11734         CallRuntime(glue, RTSTUB_ID(AOTEnableProtoChangeMarker), {*result, *ihc, *val});
11735         Jump(&exit);
11736     }
11737     Bind(&exit);
11738     auto ret = *result;
11739     env->SubCfgExit();
11740     return ret;
11741 }
11742 
SetCompiledCodeFlagToFunctionFromMethod(GateRef glue,GateRef function,GateRef method)11743 void StubBuilder::SetCompiledCodeFlagToFunctionFromMethod(GateRef glue, GateRef function, GateRef method)
11744 {
11745     // set compiled code & fast call flag
11746     GateRef isFastCall = IsFastCall(method);
11747     GateRef compiledCodeField = Int32LSL(Int32(1U), Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT));
11748     GateRef compiledCodeFlag = Int32Or(compiledCodeField, Int32LSL(ZExtInt1ToInt32(isFastCall),
11749         Int32(JSFunctionBase::IsFastCallBit::START_BIT)));
11750     SetCompiledCodeFlagToFunction(glue, function, compiledCodeFlag);
11751 }
11752 
UpdateProfileTypeInfoCellToFunction(GateRef glue,GateRef function,GateRef profileTypeInfo,GateRef slotId)11753 void StubBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
11754                                                       GateRef profileTypeInfo, GateRef slotId)
11755 {
11756     Label subEntry(env_);
11757     env_->SubCfgEntry(&subEntry);
11758 
11759     Label profileTypeInfoNotUndefined(env_);
11760     Label slotValueUpdate(env_);
11761     Label slotValueNotUndefined(env_);
11762     Label profileTypeInfoEnd(env_);
11763     NewObjectStubBuilder newBuilder(env_);
11764     BRANCH(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined);
11765     Bind(&profileTypeInfoNotUndefined);
11766     {
11767         GateRef slotValue = GetValueFromTaggedArray(glue, profileTypeInfo, slotId);
11768         BRANCH(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
11769         Bind(&slotValueUpdate);
11770         {
11771             GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined());
11772             SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
11773             SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell);
11774             Jump(&profileTypeInfoEnd);
11775         }
11776         Bind(&slotValueNotUndefined);
11777         {
11778             UpdateProfileTypeInfoCellType(glue, slotValue);
11779             SetRawProfileTypeInfoToFunction(glue, function, slotValue);
11780             TryToJitReuseCompiledFunc(glue, function, slotValue);
11781             Jump(&profileTypeInfoEnd);
11782         }
11783     }
11784     Bind(&profileTypeInfoEnd);
11785 
11786     env_->SubCfgExit();
11787 }
11788 
Loadlocalmodulevar(GateRef glue,GateRef index,GateRef module)11789 GateRef StubBuilder::Loadlocalmodulevar(GateRef glue, GateRef index, GateRef module)
11790 {
11791     auto env = GetEnvironment();
11792     Label subentry(env);
11793     env->SubCfgEntry(&subentry);
11794     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11795     Label notSendableFunctionModule(env);
11796     Label sendableFunctionModule(env);
11797     Label exit(env);
11798     BRANCH_UNLIKELY(IsSendableFunctionModule(glue, module), &sendableFunctionModule, &notSendableFunctionModule);
11799     Bind(&sendableFunctionModule);
11800     {
11801         result = CallRuntime(glue, RTSTUB_ID(LdLocalModuleVarByIndexWithModule),
11802                              {Int8ToTaggedInt(index), module});
11803         Jump(&exit);
11804     }
11805     Bind(&notSendableFunctionModule);
11806     {
11807         GateRef dictionary = GetNameDictionary(glue, module);
11808         Label dataIsNotUndefined(env);
11809         BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &exit, &dataIsNotUndefined);
11810         Bind(&dataIsNotUndefined);
11811         {
11812             result = GetValueFromTaggedArray(glue, dictionary, ZExtInt8ToInt32(index));
11813             Jump(&exit);
11814         }
11815     }
11816     Bind(&exit);
11817     auto ret = *result;
11818     env->SubCfgExit();
11819     return ret;
11820 }
11821 
ModuleEnvMustBeValid(GateRef glue,GateRef curEnv)11822 void StubBuilder::ModuleEnvMustBeValid(GateRef glue, GateRef curEnv)
11823 {
11824     GateRef objectType = GetObjectType(LoadHClass(glue, curEnv));
11825     [[maybe_unused]] GateRef isTaggedArray = LogicOrBuilder(env_)
11826         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::TAGGED_ARRAY))))
11827         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::TAGGED_DICTIONARY))))
11828         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::LEXICAL_ENV))))
11829         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::SENDABLE_ENV))))
11830         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::CONSTANT_POOL))))
11831         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::PROFILE_TYPE_INFO))))
11832         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::AOT_LITERAL_INFO))))
11833         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::VTABLE))))
11834         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::COW_TAGGED_ARRAY))))
11835         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::MUTANT_TAGGED_ARRAY))))
11836         .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::COW_MUTANT_TAGGED_ARRAY))))
11837         .Done();
11838     ASSERT(isTaggedArray);
11839 }
11840 
SearchFromModuleCache(GateRef glue,GateRef moduleName)11841 GateRef StubBuilder::SearchFromModuleCache(GateRef glue, GateRef moduleName)
11842 {
11843     auto env = GetEnvironment();
11844     Label subentry(env);
11845     env->SubCfgEntry(&subentry);
11846 
11847     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11848     Label isContainModule(env);
11849     Label exit(env);
11850     GateRef moduleObj = GetCjsModuleFunction(glue);
11851     GateRef cacheName = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::CJS_CACHE_INDEX);
11852     GateRef moduleCache = FastGetPropertyByName(glue, moduleObj, cacheName, ProfileOperation());
11853     GateRef containsModuleIndex = FindEntryFromHashTable<CjsModuleCache>(glue, moduleCache, moduleName);
11854     BRANCH(Int32NotEqual(containsModuleIndex, Int32(-1)), &isContainModule, &exit);
11855 
11856     Bind(&isContainModule);
11857     {
11858         GateRef cachedModule = GetValueFromDictionary<CjsModuleCache>(glue, moduleCache, containsModuleIndex);
11859         GateRef exportsName = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::CJS_EXPORTS_INDEX);
11860         result = FastGetPropertyByName(glue, cachedModule, exportsName, ProfileOperation());
11861         Jump(&exit);
11862     }
11863 
11864     Bind(&exit);
11865     auto ret = *result;
11866     env->SubCfgExit();
11867     return ret;
11868 }
11869 
GetNativeOrCjsExports(GateRef glue,GateRef resolvedModule)11870 GateRef StubBuilder::GetNativeOrCjsExports(GateRef glue, GateRef resolvedModule)
11871 {
11872     auto env = GetEnvironment();
11873     Label subentry(env);
11874     env->SubCfgEntry(&subentry);
11875 
11876     DEFVARIABLE(exports, VariableType::JS_ANY(), Undefined());
11877     Label isNativeModule(env);
11878     Label judgeCjsModule(env);
11879     Label exit(env);
11880     BRANCH(IsNativeModule(resolvedModule), &isNativeModule, &judgeCjsModule);
11881 
11882     Bind(&isNativeModule);
11883     {
11884         Label notJSObject(env);
11885         exports = GetModuleValueByIndex(glue, resolvedModule, Int32(0), TaggedFalse());
11886         BRANCH(IsJSObject(glue, *exports), &exit, &notJSObject);
11887 
11888         Bind(&notJSObject);
11889         {
11890             CallNGCRuntime(glue, RTSTUB_ID(LoadNativeModuleFailed), {resolvedModule});
11891             Jump(&exit);
11892         }
11893     }
11894 
11895     Bind(&judgeCjsModule);
11896     {
11897         Label isCjsModule(env);
11898         BRANCH(IsCjsModule(resolvedModule), &isCjsModule, &exit);
11899 
11900         Bind(&isCjsModule);
11901         Label exportsIsHole(env);
11902         GateRef moduleName = CallRuntime(glue, RTSTUB_ID(GetModuleName), {resolvedModule});
11903         exports = SearchFromModuleCache(glue, moduleName);
11904         BRANCH(TaggedIsHole(*exports), &exportsIsHole, &exit);
11905 
11906         Bind(&exportsIsHole);
11907         {
11908             exports = CallRuntime(glue, RTSTUB_ID(ThrowExportsIsHole), {resolvedModule});
11909             Jump(&exit);
11910         }
11911     }
11912 
11913     Bind(&exit);
11914     auto ret = *exports;
11915     env->SubCfgExit();
11916     return ret;
11917 }
11918 
GetValueFromExportObject(GateRef glue,GateRef exports,GateRef index)11919 GateRef StubBuilder::GetValueFromExportObject(GateRef glue, GateRef exports, GateRef index)
11920 {
11921     auto env = GetEnvironment();
11922     Label subentry(env);
11923     env->SubCfgEntry(&subentry);
11924 
11925     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11926     Label isUndefinedIdx(env);
11927     Label validIdx(env);
11928     Label checkResultIsAccessor(env);
11929     Label exit(env);
11930     BRANCH(Int32Equal(index, Int32(SourceTextModule::UNDEFINED_INDEX)), &isUndefinedIdx, &validIdx);
11931 
11932     Bind(&isUndefinedIdx);
11933     {
11934         result = exports;
11935         Jump(&exit);
11936     }
11937 
11938     Bind(&validIdx);
11939     {
11940         Label isDictionaryMode(env);
11941         Label notDictionaryMode(env);
11942         GateRef properties = GetPropertiesFromJSObject(glue, exports);
11943         BRANCH(IsDictionaryMode(glue, properties), &isDictionaryMode, &notDictionaryMode);
11944 
11945         Bind(&isDictionaryMode);
11946         {
11947             result = GetValueFromDictionary<NameDictionary>(glue, properties, index);
11948             Jump(&checkResultIsAccessor);
11949         }
11950 
11951         Bind(&notDictionaryMode);
11952         {
11953             GateRef hClass = LoadHClass(glue, exports);
11954             GateRef layoutInfo = GetLayoutFromHClass(glue, hClass);
11955             GateRef attr = GetAttr(glue, layoutInfo, index);
11956             result = JSObjectGetPropertyWithRep(glue, exports, hClass, attr);
11957             Jump(&checkResultIsAccessor);
11958         }
11959     }
11960 
11961     Bind(&checkResultIsAccessor);
11962     {
11963         Label isAccessor(env);
11964         BRANCH_UNLIKELY(TaggedIsAccessor(glue, *result), &isAccessor, &exit);
11965 
11966         Bind(&isAccessor);
11967         {
11968             result = CallGetterHelper(glue, exports, exports, *result, ProfileOperation());
11969             Jump(&exit);
11970         }
11971     }
11972 
11973     Bind(&exit);
11974     auto ret = *result;
11975     env->SubCfgExit();
11976     return ret;
11977 }
11978 
GetNativeOrCjsModuleValue(GateRef glue,GateRef module,GateRef index)11979 GateRef StubBuilder::GetNativeOrCjsModuleValue(GateRef glue, GateRef module, GateRef index)
11980 {
11981     auto env = GetEnvironment();
11982     Label subentry(env);
11983     env->SubCfgEntry(&subentry);
11984 
11985     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11986     Label hasException(env);
11987     Label noException(env);
11988     Label exit(env);
11989     GateRef exports = GetNativeOrCjsExports(glue, module);
11990     BRANCH(HasPendingException(glue), &hasException, &noException);
11991 
11992     Bind(&hasException);
11993     {
11994         result = Exception();
11995         Jump(&exit);
11996     }
11997 
11998     Bind(&noException);
11999     {
12000         result = GetValueFromExportObject(glue, exports, index);
12001         Jump(&exit);
12002     }
12003 
12004     Bind(&exit);
12005     auto ret = *result;
12006     env->SubCfgExit();
12007     return ret;
12008 }
12009 
GetModuleValueByIndex(GateRef glue,GateRef module,GateRef index,GateRef isThrow)12010 GateRef StubBuilder::GetModuleValueByIndex(GateRef glue, GateRef module, GateRef index, GateRef isThrow)
12011 {
12012     auto env = GetEnvironment();
12013     Label subentry(env);
12014     env->SubCfgEntry(&subentry);
12015 
12016     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12017     Label isUndefined(env);
12018     Label notUndefined(env);
12019     Label exit(env);
12020     GateRef dictionary = GetNameDictionary(glue, module);
12021     BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &isUndefined, &notUndefined);
12022 
12023     Bind(&notUndefined);
12024     {
12025         result = GetValueFromTaggedArray(glue, dictionary, index);
12026         Jump(&exit);
12027     }
12028 
12029     Bind(&isUndefined);
12030     {
12031         result = CallRuntime(glue, RTSTUB_ID(CheckAndThrowModuleError), {module, isThrow});
12032         Jump(&exit);
12033     }
12034 
12035     Bind(&exit);
12036     auto ret = *result;
12037     env->SubCfgExit();
12038     return ret;
12039 }
12040 
GetModuleValue(GateRef glue,GateRef module,GateRef index)12041 GateRef StubBuilder::GetModuleValue(GateRef glue, GateRef module, GateRef index)
12042 {
12043     auto env = GetEnvironment();
12044     Label subentry(env);
12045     env->SubCfgEntry(&subentry);
12046 
12047     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12048     Label isNativeOrCjsModule(env);
12049     Label notNativeOrCjsModule(env);
12050     Label exit(env);
12051     GateRef checkNativeOrCjsModule = BitOr(IsNativeModule(module), IsCjsModule(module));
12052     BRANCH(checkNativeOrCjsModule, &isNativeOrCjsModule, &notNativeOrCjsModule);
12053 
12054     Bind(&isNativeOrCjsModule);
12055     {
12056         result = GetNativeOrCjsModuleValue(glue, module, index);
12057         Jump(&exit);
12058     }
12059 
12060     Bind(&notNativeOrCjsModule);
12061     {
12062         result = GetModuleValueByIndex(glue, module, index, TaggedFalse());
12063         Jump(&exit);
12064     }
12065 
12066     Bind(&exit);
12067     auto ret = *result;
12068     env->SubCfgExit();
12069     return ret;
12070 }
12071 
GetNativeOrCjsModuleValueByName(GateRef glue,GateRef module,GateRef bindingName)12072 GateRef StubBuilder::GetNativeOrCjsModuleValueByName(GateRef glue, GateRef module, GateRef bindingName)
12073 {
12074     auto env = GetEnvironment();
12075     Label subentry(env);
12076     env->SubCfgEntry(&subentry);
12077 
12078     GateRef exports = GetNativeOrCjsExports(glue, module);
12079     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12080     Label hasPendingException(env);
12081     Label noPendingException(env);
12082     Label exit(env);
12083     BRANCH(HasPendingException(glue), &hasPendingException, &noPendingException);
12084 
12085     Bind(&hasPendingException);
12086     {
12087         result = Exception();
12088         Jump(&exit);
12089     }
12090 
12091     Bind(&noPendingException);
12092     {
12093         GateRef defaultString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::DEFAULT_INDEX);
12094         Label isSameVal(env);
12095         Label notSameVal(env);
12096         BRANCH_UNLIKELY(SameValue(glue, bindingName, defaultString), &isSameVal, &notSameVal);
12097 
12098         Bind(&isSameVal);
12099         {
12100             result = exports;
12101             Jump(&exit);
12102         }
12103 
12104         Bind(&notSameVal);
12105         {
12106             result = FastGetPropertyByName(glue, exports, bindingName, ProfileOperation());
12107             Jump(&exit);
12108         }
12109     }
12110 
12111     Bind(&exit);
12112     auto ret = *result;
12113     env->SubCfgExit();
12114     return ret;
12115 }
12116 
ResolveElementOfObject(GateRef glue,GateRef hClass,GateRef exportName,GateRef module,GateRef layOutInfo)12117 GateRef StubBuilder::ResolveElementOfObject(GateRef glue, GateRef hClass, GateRef exportName,
12118                                             GateRef module, GateRef layOutInfo)
12119 {
12120     auto env = GetEnvironment();
12121     Label subentry(env);
12122     env->SubCfgEntry(&subentry);
12123 
12124     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12125     Label validIdx(env);
12126     Label invalidIdx(env);
12127     Label exit(env);
12128     GateRef propsNum = GetNumberOfPropsFromHClass(hClass);
12129     GateRef idx = FindElementWithCache(glue, layOutInfo, hClass, exportName, propsNum);
12130     BRANCH(Int32NotEqual(idx, Int32(-1)), &validIdx, &invalidIdx);
12131 
12132     Bind(&validIdx);
12133     {
12134         result = CallRuntime(glue, RTSTUB_ID(NewResolvedIndexBindingRecord), {module, IntToTaggedInt(idx)});
12135         Jump(&exit);
12136     }
12137 
12138     Bind(&invalidIdx);
12139     {
12140         result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::UNDEFINED_INDEX);
12141         Jump(&exit);
12142     }
12143 
12144     Bind(&exit);
12145     auto ret = *result;
12146     env->SubCfgExit();
12147     return ret;
12148 }
12149 
ResolveExportObject(GateRef glue,GateRef module,GateRef exports,GateRef exportName)12150 GateRef StubBuilder::ResolveExportObject(GateRef glue, GateRef module, GateRef exports, GateRef exportName)
12151 {
12152     auto env = GetEnvironment();
12153     Label subentry(env);
12154     env->SubCfgEntry(&subentry);
12155 
12156     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12157     Label defaultCallNewBindingRecord(env);
12158     Label notSameVal(env);
12159     Label exportsIsHeapObj(env);
12160     Label notNativeModuleFailureInfo(env);
12161     Label exit(env);
12162     GateRef defaultString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::DEFAULT_INDEX);
12163     BRANCH(SameValue(glue, exportName, defaultString), &defaultCallNewBindingRecord, &notSameVal);
12164 
12165     Bind(&notSameVal);
12166     BRANCH(TaggedIsHeapObject(exports), &exportsIsHeapObj, &notNativeModuleFailureInfo);
12167 
12168     Bind(&exportsIsHeapObj);
12169     BRANCH(IsNativeModuleFailureInfo(glue, exports), &defaultCallNewBindingRecord, &notNativeModuleFailureInfo);
12170 
12171     Bind(&notNativeModuleFailureInfo);
12172     Label exportsIsJSObject(env);
12173     Label exportsNotJSObject(env);
12174     BRANCH(IsJSObject(glue, exports), &exportsIsJSObject, &exportsNotJSObject);
12175 
12176     Bind(&exportsIsJSObject);
12177     {
12178         Label isDictionaryMode(env);
12179         Label notDictionaryMode(env);
12180         Label checkResultIsUndefined(env);
12181         GateRef properties = GetPropertiesFromJSObject(glue, exports);
12182         BRANCH(IsDictionaryMode(glue, properties), &isDictionaryMode, &notDictionaryMode);
12183 
12184         Bind(&isDictionaryMode);
12185         {
12186             Label validEntry(env);
12187             GateRef entry = FindEntryFromHashTable<NameDictionary>(glue, properties, exportName);
12188             BRANCH(Int32NotEqual(entry, Int32(-1)), &validEntry, &checkResultIsUndefined);
12189 
12190             Bind(&validEntry);
12191             result = CallRuntime(glue, RTSTUB_ID(NewResolvedIndexBindingRecord), {module, IntToTaggedInt(entry)});
12192             Jump(&checkResultIsUndefined);
12193         }
12194 
12195         Bind(&notDictionaryMode);
12196         {
12197             Label notEqualZero(env);
12198             GateRef hClass = LoadHClass(glue, exports);
12199             GateRef layoutInfo = GetLayoutFromHClass(glue, hClass);
12200             GateRef eleNum = GetNumberOfPropsFromHClass(hClass);
12201             BRANCH(Int32NotEqual(eleNum, Int32(0)), &notEqualZero, &checkResultIsUndefined);
12202 
12203             Bind(&notEqualZero);
12204             result = ResolveElementOfObject(glue, hClass, exportName, module, layoutInfo);
12205             Jump(&checkResultIsUndefined);
12206         }
12207 
12208         Bind(&checkResultIsUndefined);
12209         BRANCH(TaggedIsUndefined(*result), &exportsNotJSObject, &exit);
12210     }
12211 
12212     Bind(&defaultCallNewBindingRecord);
12213     {
12214         result = CallRuntime(glue, RTSTUB_ID(NewResolvedIndexBindingRecord), {module, IntToTaggedInt(Int32(-1))});
12215         Jump(&exit);
12216     }
12217 
12218     Bind(&exportsNotJSObject);
12219     {
12220         result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::NULL_INDEX);
12221         Jump(&exit);
12222     }
12223 
12224     Bind(&exit);
12225     auto ret = *result;
12226     env->SubCfgExit();
12227     return ret;
12228 }
12229 
UpdateBindingAndGetModuleValue(GateRef glue,GateRef module,GateRef requiredModule,GateRef index,GateRef bindingName)12230 GateRef StubBuilder::UpdateBindingAndGetModuleValue(GateRef glue, GateRef module, GateRef requiredModule,
12231                                                     GateRef index, GateRef bindingName)
12232 {
12233     auto env = GetEnvironment();
12234     Label subentry(env);
12235     env->SubCfgEntry(&subentry);
12236 
12237     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12238     Label hasException(env);
12239     Label noException(env);
12240     Label exit(env);
12241     GateRef curModuleEnv = GetCurrentModuleEnv(glue, module);
12242     ModuleEnvMustBeDefined(curModuleEnv);
12243     GateRef exports = GetNativeOrCjsExports(glue, requiredModule);
12244     BRANCH(HasPendingException(glue), &hasException, &noException);
12245 
12246     Bind(&noException);
12247     {
12248         Label isNullOrString(env);
12249         Label notNullOrString(env);
12250         GateRef resolution = ResolveExportObject(glue, requiredModule, exports, bindingName);
12251         BRANCH(BitOr(TaggedIsNull(resolution), TaggedIsString(glue, resolution)), &isNullOrString, &notNullOrString);
12252 
12253         Bind(&isNullOrString);
12254         {
12255             result = CallRuntime(glue, RTSTUB_ID(HandleResolutionIsNullOrString),
12256                                  {module, requiredModule, bindingName, resolution});
12257             Jump(&exit);
12258         }
12259 
12260         Bind(&notNullOrString);
12261         {
12262             CheckIsResolvedIndexBinding(glue, resolution);
12263             SetIsUpdatedFromResolvedBindingOfResolvedIndexBinding(glue, resolution, True());
12264             SetValueToTaggedArray(VariableType::JS_ANY(), glue, curModuleEnv, index, resolution);
12265             result = GetValueFromExportObject(glue, exports, GetIdxOfResolvedIndexBinding(resolution));
12266             Jump(&exit);
12267         }
12268     }
12269 
12270     Bind(&hasException);
12271     {
12272         result = Exception();
12273         Jump(&exit);
12274     }
12275 
12276     Bind(&exit);
12277     auto ret = *result;
12278     env->SubCfgExit();
12279     return ret;
12280 }
12281 
GetResolvedRecordIndexBindingModule(GateRef glue,GateRef module,GateRef resolvedBinding)12282 GateRef StubBuilder::GetResolvedRecordIndexBindingModule(GateRef glue, GateRef module, GateRef resolvedBinding)
12283 {
12284     GateRef recordName = GetModuleRecord(glue, resolvedBinding);
12285     RecordNameMustBeString(glue, recordName);
12286     GateRef moduleManager = GetModuleManager(glue);
12287     GateRef result = CallRuntime(glue, RTSTUB_ID(GetResolvedRecordIndexBindingModule),
12288                                  {module, resolvedBinding, moduleManager, recordName});
12289     return result;
12290 }
12291 
GetResolvedRecordBindingModule(GateRef glue,GateRef module,GateRef resolvedBinding)12292 GateRef StubBuilder::GetResolvedRecordBindingModule(GateRef glue, GateRef module, GateRef resolvedBinding)
12293 {
12294     GateRef recordName = GetModuleRecord(glue, resolvedBinding);
12295     RecordNameMustBeString(glue, recordName);
12296     GateRef moduleManager = GetModuleManager(glue);
12297     GateRef result = CallRuntime(glue, RTSTUB_ID(GetResolvedRecordBindingModule),
12298                                  {module, moduleManager, recordName});
12299     return result;
12300 }
12301 
LoadExternalmodulevar(GateRef glue,GateRef index,GateRef curModule)12302 GateRef StubBuilder::LoadExternalmodulevar(GateRef glue, GateRef index, GateRef curModule)
12303 {
12304     auto env = GetEnvironment();
12305     Label subentry(env);
12306     env->SubCfgEntry(&subentry);
12307 
12308     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12309     Label notSendableFunctionModule(env);
12310     Label moduleUndefined(env);
12311     Label moduleIsdefined(env);
12312     Label moduleEnvUndefined(env);
12313     Label moduleEnvIsdefined(env);
12314     Label isSendableFunctionModule(env);
12315     Label isNullPtr(env);
12316     Label notNullPtr(env);
12317     Label resolvedBindingIsHeapObj(env);
12318     Label misstakenResolvedBinding(env);
12319     Label judgeResolvedBinding(env);
12320     Label judgeResolvedRecordIndexBinding(env);
12321     Label judgeResolvedRecordBinding(env);
12322     Label exit(env);
12323     BRANCH(IsSendableFunctionModule(glue, curModule), &isSendableFunctionModule, &notSendableFunctionModule);
12324 
12325     Bind(&notSendableFunctionModule);
12326     BRANCH_UNLIKELY(TaggedIsUndefined(curModule), &moduleUndefined, &moduleIsdefined);
12327 
12328     Bind(&moduleIsdefined);
12329     GateRef curModuleEnv = GetCurrentModuleEnv(glue, curModule);
12330     BRANCH(TaggedIsUndefined(curModuleEnv), &moduleEnvUndefined, &moduleEnvIsdefined);
12331 
12332     Bind(&moduleEnvIsdefined);
12333     ModuleEnvMustBeValid(glue, curModuleEnv);
12334     GateRef resolvedBinding = GetValueFromTaggedArray(glue, curModuleEnv, index);
12335     BRANCH_LIKELY(IntPtrEuqal(GetModuleLogger(glue), IntPtr(0)), &isNullPtr, &notNullPtr);
12336 
12337     Bind(&isNullPtr);
12338     BRANCH(TaggedIsHeapObject(resolvedBinding), &resolvedBindingIsHeapObj, &misstakenResolvedBinding);
12339 
12340     Bind(&resolvedBindingIsHeapObj);
12341     {
12342         Label isResolvedIndexBinding(env);
12343         BRANCH(IsResolvedIndexBinding(glue, resolvedBinding), &isResolvedIndexBinding, &judgeResolvedBinding);
12344 
12345         Bind(&isResolvedIndexBinding);
12346         {
12347             Label isLdEndExecPatchMain(env);
12348             Label notLdEndExecPatchMain(env);
12349             Label notHole(env);
12350             DEFVARIABLE(resolvedModule, VariableType::JS_ANY(), Hole());
12351             resolvedModule = GetResolveModuleFromResolvedIndexBinding(glue, resolvedBinding);
12352             ResolvedModuleMustBeSourceTextModule(glue, *resolvedModule);
12353             GateRef idxOfResolvedBinding = GetIdxOfResolvedIndexBinding(resolvedBinding);
12354             BRANCH(IsLdEndExecPatchMain(glue), &isLdEndExecPatchMain, &notLdEndExecPatchMain);
12355 
12356             Bind(&isLdEndExecPatchMain);
12357             GateRef resolvedModuleOfHotReload = CallNGCRuntime(glue, RTSTUB_ID(FindPatchModule),
12358                                                                {glue, *resolvedModule});
12359             BRANCH(TaggedIsHole(resolvedModuleOfHotReload), &notLdEndExecPatchMain, &notHole);
12360 
12361             Bind(&notLdEndExecPatchMain);
12362             Label isSharedModule(env);
12363             Label notSharedModule(env);
12364             BRANCH(IsSharedModule(*resolvedModule), &isSharedModule, &notSharedModule);
12365             Bind(&isSharedModule);
12366             resolvedModule = CallNGCRuntime(glue, RTSTUB_ID(UpdateSharedModule), {glue, *resolvedModule});
12367             Jump(&notSharedModule);
12368             Bind(&notSharedModule);
12369             result = GetModuleValue(glue, *resolvedModule, idxOfResolvedBinding);
12370             Jump(&exit);
12371 
12372             Bind(&notHole);
12373             result = GetModuleValue(glue, resolvedModuleOfHotReload, idxOfResolvedBinding);
12374             Jump(&exit);
12375         }
12376     }
12377 
12378     Bind(&judgeResolvedBinding);
12379     {
12380         Label isResolvedBinding(env);
12381         BRANCH(IsResolvedBinding(glue, resolvedBinding), &isResolvedBinding, &judgeResolvedRecordIndexBinding);
12382 
12383         Bind(&isResolvedBinding);
12384         {
12385             GateRef resolvedModule = GetResolveModuleFromResolvedBinding(glue, resolvedBinding);
12386             ResolvedModuleMustBeSourceTextModule(glue, resolvedModule);
12387             Label isNativeOrCjsModule(env);
12388             GateRef checkNativeOrCjsModule = BitOr(IsNativeModule(resolvedModule), IsCjsModule(resolvedModule));
12389             BRANCH(checkNativeOrCjsModule, &isNativeOrCjsModule, &misstakenResolvedBinding);
12390 
12391             Bind(&isNativeOrCjsModule);
12392             {
12393                 result = UpdateBindingAndGetModuleValue(glue, curModule, resolvedModule, index,
12394                                                         GetBindingName(glue, resolvedBinding));
12395                 Jump(&exit);
12396             }
12397         }
12398     }
12399 
12400     Bind(&judgeResolvedRecordIndexBinding);
12401     {
12402         Label isResolvedRecordIndexBinding(env);
12403         BRANCH(IsResolvedRecordIndexBinding(glue, resolvedBinding), &isResolvedRecordIndexBinding,
12404                &judgeResolvedRecordBinding);
12405 
12406         Bind(&isResolvedRecordIndexBinding);
12407         {
12408             GateRef resolvedModule = GetResolvedRecordIndexBindingModule(glue, curModule, resolvedBinding);
12409             GateRef idxOfResolvedRecordIndexBinding = GetIdxOfResolvedRecordIndexBinding(resolvedBinding);
12410             result = GetModuleValue(glue, resolvedModule, idxOfResolvedRecordIndexBinding);
12411             Jump(&exit);
12412         }
12413     }
12414 
12415     Bind(&judgeResolvedRecordBinding);
12416     {
12417         Label isResolvedRecordBinding(env);
12418         BRANCH(IsResolvedRecordBinding(glue, resolvedBinding), &isResolvedRecordBinding, &misstakenResolvedBinding);
12419         Bind(&isResolvedRecordBinding);
12420         {
12421             GateRef resolvedModule = GetResolvedRecordBindingModule(glue, curModule, resolvedBinding);
12422             result = GetNativeOrCjsModuleValueByName(glue, resolvedModule, GetBindingName(glue, resolvedBinding));
12423             Jump(&exit);
12424         }
12425     }
12426 
12427     Bind(&isSendableFunctionModule);
12428     {
12429         result = CallRuntime(glue, RTSTUB_ID(LdExternalModuleVarByIndexWithModule),
12430                              {IntToTaggedInt(index), curModule});
12431         Jump(&exit);
12432     }
12433 
12434     Bind(&moduleUndefined);
12435     {
12436         FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(CurrentModuleUndefined))});
12437         Jump(&exit);
12438     }
12439 
12440     Bind(&moduleEnvUndefined);
12441     {
12442         result = Undefined();
12443         Jump(&exit);
12444     }
12445 
12446     Bind(&notNullPtr);
12447     {
12448         result = CallRuntime(glue, RTSTUB_ID(GetModuleValueOuterInternal),
12449                              {curModule, IntToTaggedInt(index)});
12450         Jump(&exit);
12451     }
12452 
12453     Bind(&misstakenResolvedBinding);
12454     {
12455         CallNGCRuntime(glue, RTSTUB_ID(FatalPrintMisstakenResolvedBinding), {index, curModule});
12456         Jump(&exit);
12457     }
12458 
12459     Bind(&exit);
12460     auto ret = *result;
12461     env->SubCfgExit();
12462     return ret;
12463 }
12464 
LoadModuleNamespaceByIndex(GateRef glue,GateRef index,GateRef module)12465 GateRef StubBuilder::LoadModuleNamespaceByIndex(GateRef glue, GateRef index, GateRef module)
12466 {
12467     auto env = GetEnvironment();
12468     Label subentry(env);
12469     env->SubCfgEntry(&subentry);
12470     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12471     Label moduleUndefined(env);
12472     Label moduleNotUndefined(env);
12473     Label notSendableFunctionModule(env);
12474     Label requestedModulesNotUndefined(env);
12475     Label requiredModuleIsHeapObj(env);
12476     Label requiredModuleIsSourceTextModule(env);
12477     Label isNullPtr(env);
12478     Label isNativeModule(env);
12479     Label dictionaryNotUndefined(env);
12480     Label notNativeModule(env);
12481     Label isCjsModule(env);
12482     Label notCjsModule(env);
12483     Label namespaceNotUndefined(env);
12484     Label slowPath(env);
12485     Label exit(env);
12486     BRANCH_UNLIKELY(TaggedIsUndefined(module), &moduleUndefined, &moduleNotUndefined);
12487     Bind(&moduleUndefined);
12488     {
12489         FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(CurrentModuleUndefined))});
12490         Jump(&exit);
12491     }
12492     Bind(&moduleNotUndefined);
12493     BRANCH_UNLIKELY(IsSendableFunctionModule(glue, module), &slowPath, &notSendableFunctionModule);
12494     Bind(&notSendableFunctionModule);
12495     {
12496         GateRef requestedModules = GetRequestedModules(glue, module);
12497         BRANCH_UNLIKELY(TaggedIsUndefined(requestedModules), &slowPath, &requestedModulesNotUndefined);
12498         Bind(&requestedModulesNotUndefined);
12499         GateRef requiredModule = GetValueFromTaggedArray(glue, requestedModules, index);
12500         BRANCH_LIKELY(TaggedIsHeapObject(requiredModule), &requiredModuleIsHeapObj, &slowPath);
12501         Bind(&requiredModuleIsHeapObj);
12502         BRANCH_LIKELY(IsSourceTextModule(glue, requiredModule), &requiredModuleIsSourceTextModule, &slowPath);
12503         Bind(&requiredModuleIsSourceTextModule);
12504         BRANCH_LIKELY(IntPtrEuqal(GetModuleLogger(glue), IntPtr(0)), &isNullPtr, &slowPath);
12505         Bind(&isNullPtr);
12506         BRANCH(IsNativeModule(requiredModule), &isNativeModule, &notNativeModule);
12507         Bind(&isNativeModule);
12508         {
12509             GateRef dictionary = GetNameDictionary(glue, requiredModule);
12510             BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &slowPath, &dictionaryNotUndefined);
12511             Bind(&dictionaryNotUndefined);
12512             result = GetValueFromTaggedArray(glue, dictionary, Int32(0));
12513             Jump(&exit);
12514         }
12515         Bind(&notNativeModule);
12516         BRANCH(IsCjsModule(requiredModule), &isCjsModule, &notCjsModule);
12517         Bind(&isCjsModule);
12518         {
12519             // CommonJS module involves CString, jump to slowPath here
12520             Jump(&slowPath);
12521         }
12522         Bind(&notCjsModule);
12523         {
12524             // requiredModule is ESM
12525             GateRef moduleNamespace = GetNamespaceFromSourceTextModule(glue, requiredModule);
12526             BRANCH_UNLIKELY(TaggedIsUndefined(moduleNamespace), &slowPath, &namespaceNotUndefined);
12527             Bind(&namespaceNotUndefined);
12528             result = moduleNamespace;
12529             Jump(&exit);
12530         }
12531     }
12532     Bind(&slowPath);
12533     {
12534         result = CallRuntime(glue, RTSTUB_ID(GetModuleNamespaceByIndex), { IntToTaggedInt(index) });
12535         Jump(&exit);
12536     }
12537     Bind(&exit);
12538     auto ret = *result;
12539     env->SubCfgExit();
12540     return ret;
12541 }
12542 
12543 // Used for jit machine code reusing of inner functions have the same method to improve performance.
TryToJitReuseCompiledFunc(GateRef glue,GateRef jsFunc,GateRef profileTypeInfoCell)12544 void StubBuilder::TryToJitReuseCompiledFunc(GateRef glue, GateRef jsFunc, GateRef profileTypeInfoCell)
12545 {
12546     Label subEntry(env_);
12547     env_->SubCfgEntry(&subEntry);
12548 
12549     Label machineCodeIsNotHole(env_);
12550     Label exitPoint(env_);
12551     Label hasNotDisable(env_);
12552     GateRef weakMachineCode = Load(VariableType::JS_ANY(), glue, profileTypeInfoCell,
12553                                    IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET));
12554     BRANCH(TaggedIsHole(weakMachineCode), &exitPoint, &machineCodeIsNotHole);
12555     Bind(&machineCodeIsNotHole);
12556     {
12557         Label hasProfileTypeInfo(env_);
12558         GateRef profileTypeInfo = Load(VariableType::JS_ANY(), glue, profileTypeInfoCell,
12559                                        IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
12560         BRANCH(TaggedIsUndefined(profileTypeInfo), &exitPoint, &hasProfileTypeInfo);
12561         Bind(&hasProfileTypeInfo);
12562         {
12563             GateRef jitHotnessThreshold = ProfilerStubBuilder(env_).GetJitHotnessThreshold(profileTypeInfo);
12564             BRANCH(Int32Equal(jitHotnessThreshold, Int32(ProfileTypeInfo::JIT_DISABLE_FLAG)), &exitPoint, &hasNotDisable);
12565             Bind(&hasNotDisable);
12566             {
12567                 Label machineCodeIsUndefine(env_);
12568                 Label machineCodeIsNotUndefine(env_);
12569                 BRANCH(TaggedIsUndefined(weakMachineCode), &machineCodeIsUndefine, &machineCodeIsNotUndefine);
12570                 Bind(&machineCodeIsUndefine);
12571                 {
12572                     ProfilerStubBuilder(env_).SetJitHotnessCnt(glue, profileTypeInfo, Int16(0));
12573                     Store(VariableType::JS_POINTER(), glue, profileTypeInfoCell,
12574                         IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET), Hole());
12575                     Jump(&exitPoint);
12576                 }
12577                 Bind(&machineCodeIsNotUndefine);
12578                 {
12579                     GateRef machineCode = TaggedCastToIntPtr(RemoveTaggedWeakTag(weakMachineCode));
12580                     GateRef codeAddr = Load(VariableType::NATIVE_POINTER(), glue, machineCode,
12581                                             IntPtr(MachineCode::FUNCADDR_OFFSET));
12582                     ASSERT(IntPtrNotEqual(codeAddr, IntPtr(0)));
12583                     GateRef isFastCall = GetIsFastCall(machineCode);
12584                     SetCompiledFuncEntry(glue, jsFunc, codeAddr, ZExtInt1ToInt32(isFastCall));
12585                     SetMachineCodeToFunction(glue, jsFunc, machineCode);
12586                     Jump(&exitPoint);
12587                 }
12588             }
12589         }
12590     }
12591     Bind(&exitPoint);
12592     env_->SubCfgExit();
12593 }
12594 
GetArgumentsElements(GateRef glue,GateRef argvTaggedArray,GateRef argv)12595 GateRef StubBuilder::GetArgumentsElements(GateRef glue, GateRef argvTaggedArray, GateRef argv)
12596 {
12597     auto env = GetEnvironment();
12598     Label entry(env);
12599     env->SubCfgEntry(&entry);
12600     Label exit(env);
12601     DEFVARIABLE(result, VariableType::NATIVE_POINTER(), NullPtr());
12602     DEFVARIABLE(argvVar, VariableType::NATIVE_POINTER(), argv);
12603 
12604     Label calcArgv(env);
12605     Label hasArgv(env);
12606     Label argvTaggedArrayUndef(env);
12607     Label argvTaggedArrayDef(env);
12608 
12609     BRANCH(TaggedIsUndefined(argvTaggedArray), &argvTaggedArrayUndef, &argvTaggedArrayDef);
12610     Bind(&argvTaggedArrayUndef);
12611 
12612     BRANCH(Equal(*argvVar, IntPtr(0)), &calcArgv, &hasArgv);
12613     Bind(&calcArgv);
12614     argvVar = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
12615     Jump(&hasArgv);
12616 
12617     Bind(&argvTaggedArrayDef);
12618     argvVar = PtrAdd(TaggedCastToIntPtr(argvTaggedArray), IntPtr(TaggedArray::DATA_OFFSET));
12619     Jump(&hasArgv);
12620 
12621     Bind(&hasArgv);
12622     result = PtrAdd(*argvVar, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
12623     Jump(&exit);
12624     Bind(&exit);
12625     auto ret = *result;
12626     env->SubCfgExit();
12627     return ret;
12628 }
12629 
ComputeTaggedArrayElementKind(GateRef glue,GateRef array,GateRef offset,GateRef end)12630 GateRef StubBuilder::ComputeTaggedArrayElementKind(GateRef glue, GateRef array, GateRef offset, GateRef end)
12631 {
12632     auto env = GetEnvironment();
12633     Label entry(env);
12634     env->SubCfgEntry(&entry);
12635     Label exit(env);
12636     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
12637     GateRef elements = GetElementsArray(glue, array);
12638     GateRef kind = GetElementsKindFromHClass(LoadHClass(glue, array));
12639     Label fastCompute(env);
12640     Label slowCompute(env);
12641     GateRef checkType = LogicOrBuilder(env)
12642                         .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::NONE))))
12643                         .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::INT))))
12644                         .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::STRING))))
12645                         .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::OBJECT))))
12646                         .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::HOLE))))
12647                         .Done();
12648     BRANCH(checkType, &fastCompute, &slowCompute);
12649     Bind(&fastCompute);
12650     {
12651         result = kind;
12652         Jump(&exit);
12653     }
12654     Bind(&slowCompute);
12655     Label loopHead(env);
12656     Label loopEnd(env);
12657     Label doLoop(env);
12658     Label loopExit(env);
12659     DEFVARIABLE(i, VariableType::INT64(), offset);
12660     GateRef generic = Int32(Elements::ToUint(ElementsKind::GENERIC));
12661     Jump(&loopHead);
12662     LoopBegin(&loopHead);
12663     {
12664         GateRef checkType2 = BitAnd(Int64LessThan(*i, end), Int32LessThan(*result, generic));
12665         BRANCH(checkType2, &doLoop, &loopExit);
12666         Bind(&doLoop);
12667         GateRef value = GetValueFromTaggedArray(glue, elements, *i);
12668         result = Int32Or(TaggedToElementKind(glue, value), *result);
12669         i = Int64Add(*i, Int64(1));
12670         Jump(&loopEnd);
12671     }
12672     Bind(&loopEnd);
12673     LoopEnd(&loopHead);
12674     Bind(&loopExit);
12675     Jump(&exit);
12676     Bind(&exit);
12677     auto ret = *result;
12678     env->SubCfgExit();
12679     return ret;
12680 }
12681 
GetElementsKindHClass(GateRef glue,GateRef elementKind)12682 GateRef StubBuilder::GetElementsKindHClass(GateRef glue, GateRef elementKind)
12683 {
12684     auto env = GetEnvironment();
12685     GateRef offset = PtrMul(ZExtInt32ToPtr(elementKind), IntPtr(sizeof(ElementsHClassEntries::Entry)));
12686     GateRef arrayHClassIndexesOff = IntPtr(JSThread::GlueData::GetArrayHClassIndexesIndexOffset(env->Is32Bit()));
12687     GateRef arrayIndexes = PtrAdd(glue, arrayHClassIndexesOff);
12688     GateRef elementIdx = LoadPrimitive(VariableType::INT16(), arrayIndexes, offset);
12689     GateRef currentEnv = GetCurrentGlobalEnv();
12690     GateRef elementOffset = PtrAdd(IntPtr(GlobalEnv::HEADER_SIZE),
12691                                    PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), ZExtInt16ToPtr(elementIdx)));
12692     return Load(VariableType::JS_ANY(), glue, currentEnv, elementOffset);
12693 }
12694 
NeedBarrier(GateRef kind)12695 GateRef StubBuilder::NeedBarrier(GateRef kind){
12696     auto env = GetEnvironment();
12697     Label entry(env);
12698     env->SubCfgEntry(&entry);
12699     DEFVARIABLE(result, VariableType::BOOL(), True());
12700     GateRef isInt = LogicAndBuilder(env)
12701                     .And(Int32GreaterThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::INT))))
12702                     .And(Int32LessThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::HOLE_INT))))
12703                     .Done();
12704     GateRef isNumber = LogicAndBuilder(env)
12705                        .And(Int32GreaterThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::NUMBER))))
12706                        .And(Int32LessThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER))))
12707                        .Done();
12708     GateRef check = LogicOrBuilder(env).Or(isInt).Or(isNumber)
12709                     .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::HOLE)))).Done();
12710     result = BoolNot(check);
12711     auto ret = *result;
12712     env->SubCfgExit();
12713     return ret;
12714 }
12715 
StartTraceLoadValueDetail(GateRef glue,GateRef receiver,GateRef profileTypeInfo,GateRef slotId,GateRef key)12716 void StubBuilder::StartTraceLoadValueDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef receiver,
12717     [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId, [[maybe_unused]] GateRef key)
12718 {
12719 #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE
12720     CallRuntime(glue, RTSTUB_ID(TraceLoadValueDetail), {receiver, profileTypeInfo, slotId, key});
12721 #endif
12722 }
12723 
12724 
StartTraceLoadValueSlowPath(GateRef glue)12725 void StubBuilder::StartTraceLoadValueSlowPath([[maybe_unused]]GateRef glue)
12726 {
12727 #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE
12728     CallRuntime(glue, RTSTUB_ID(TraceLoadValueSlowPath), {});
12729 #endif
12730 }
12731 
EndTraceLoadValue(GateRef glue)12732 void StubBuilder::EndTraceLoadValue([[maybe_unused]]GateRef glue)
12733 {
12734 #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE
12735     CallRuntime(glue, RTSTUB_ID(TraceLoadValueEnd), {});
12736 #endif
12737 }
12738 
StartTraceCallDetail(GateRef glue,GateRef profileTypeInfo,GateRef slotId)12739 void StubBuilder::StartTraceCallDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef profileTypeInfo,
12740                                        [[maybe_unused]] GateRef slotId)
12741 {
12742 #if ECMASCRIPT_ENABLE_TRACE_CALL
12743     CallRuntime(glue, RTSTUB_ID(TraceCallDetail), {profileTypeInfo, slotId});
12744 #endif
12745 }
12746 
EndTraceCall(GateRef glue)12747 void StubBuilder::EndTraceCall([[maybe_unused]] GateRef glue)
12748 {
12749 #if ECMASCRIPT_ENABLE_TRACE_CALL
12750     CallRuntime(glue, RTSTUB_ID(TraceLoadValueEnd), {});
12751 #endif
12752 }
12753 
StartTraceLoadDetail(GateRef glue,GateRef receiver,GateRef profileTypeInfo,GateRef slotId)12754 void StubBuilder::StartTraceLoadDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef receiver,
12755                                        [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId)
12756 {
12757 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12758     CallRuntime(glue, RTSTUB_ID(TraceLoadDetail), {receiver, profileTypeInfo, slotId});
12759 #endif
12760 }
12761 
StartTraceLoadGetter(GateRef glue)12762 void StubBuilder::StartTraceLoadGetter([[maybe_unused]]GateRef glue)
12763 {
12764 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12765     CallRuntime(glue, RTSTUB_ID(TraceLoadGetter), {});
12766 #endif
12767 }
12768 
StartTraceLoadSlowPath(GateRef glue)12769 void StubBuilder::StartTraceLoadSlowPath([[maybe_unused]]GateRef glue)
12770 {
12771 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12772     CallRuntime(glue, RTSTUB_ID(TraceLoadSlowPath), {});
12773 #endif
12774 }
12775 
EndTraceLoad(GateRef glue)12776 void StubBuilder::EndTraceLoad([[maybe_unused]]GateRef glue)
12777 {
12778 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12779     CallRuntime(glue, RTSTUB_ID(TraceLoadEnd), {});
12780 #endif
12781 }
12782 
StartTraceStoreDetail(GateRef glue,GateRef receiver,GateRef profileTypeInfo,GateRef slotId)12783 void StubBuilder::StartTraceStoreDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef receiver,
12784                                        [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId)
12785 {
12786 #if ECMASCRIPT_ENABLE_TRACE_STORE
12787     CallRuntime(glue, RTSTUB_ID(TraceStoreDetail), {receiver, profileTypeInfo, slotId});
12788 #endif
12789 }
12790 
StartTraceStoreFastPath(GateRef glue)12791 void StubBuilder::StartTraceStoreFastPath([[maybe_unused]] GateRef glue)
12792 {
12793 #if ECMASCRIPT_ENABLE_TRACE_STORE
12794     CallRuntime(glue, RTSTUB_ID(TraceStoreFastPath), {});
12795 #endif
12796 }
12797 
StartTraceStoreSlowPath(GateRef glue)12798 void StubBuilder::StartTraceStoreSlowPath([[maybe_unused]] GateRef glue)
12799 {
12800 #if ECMASCRIPT_ENABLE_TRACE_STORE
12801     CallRuntime(glue, RTSTUB_ID(TraceStoreSlowPath), {});
12802 #endif
12803 }
12804 
EndTraceStore(GateRef glue)12805 void StubBuilder::EndTraceStore([[maybe_unused]] GateRef glue)
12806 {
12807 #if ECMASCRIPT_ENABLE_TRACE_STORE
12808     CallRuntime(glue, RTSTUB_ID(TraceStoreEnd), {});
12809 #endif
12810 }
12811 
StartTraceDefineFunc(GateRef glue,GateRef methodId,GateRef profileTypeInfo,GateRef slotId)12812 void StubBuilder::StartTraceDefineFunc([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef methodId,
12813                                        [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId)
12814 {
12815 #if ECMASCRIPT_ENABLE_TRACE_DEFINEFUNC
12816     CallRuntime(glue, RTSTUB_ID(TraceDefineFunc), {methodId, profileTypeInfo, IntToTaggedInt(slotId)});
12817 #endif
12818 }
EndTraceDefineFunc(GateRef glue)12819 void StubBuilder::EndTraceDefineFunc([[maybe_unused]] GateRef glue)
12820 {
12821 #if ECMASCRIPT_ENABLE_TRACE_DEFINEFUNC
12822     CallRuntime(glue, RTSTUB_ID(TraceDefineFuncEnd), {});
12823 #endif
12824 }
12825 
UpdateProfileTypeInfoAsMega(GateRef glue,GateRef profileTypeInfo,GateRef slotId)12826 void StubBuilder::UpdateProfileTypeInfoAsMega(GateRef glue, GateRef profileTypeInfo, GateRef slotId)
12827 {
12828     auto env = GetEnvironment();
12829     Label entry(env);
12830     env->SubCfgEntry(&entry);
12831     Label pgoOn(env);
12832     Label pgoOff(env);
12833     BRANCH(TaggedIsUndefined(profileTypeInfo), &pgoOff, &pgoOn);
12834     Bind(&pgoOn);
12835     SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, Hole(), MemoryAttribute::NoBarrier());
12836     Jump(&pgoOff);
12837     Bind(&pgoOff);
12838     env->SubCfgExit();
12839 }
JSTaggedValueToString(GateRef glue,GateRef val,GateRef hir)12840 GateRef StubBuilder::JSTaggedValueToString(GateRef glue, GateRef val, GateRef hir)
12841 {
12842     auto env = GetEnvironment();
12843     Label entry(env);
12844     env->SubCfgEntry(&entry);
12845     DEFVARIABLE(value, VariableType::JS_ANY(), val);
12846     Label exit(env);
12847     Label notString(env);
12848     Label isSpecial(env);
12849     Label notSpecial(env);
12850     Label loopHead(env);
12851     Label loopEnd(env);
12852     Label loopExit(env);
12853     Jump(&loopHead);
12854     LoopBegin(&loopHead);
12855     {
12856         BRANCH(TaggedIsString(glue, *value), &exit, &notString);
12857         Bind(&notString);
12858         {
12859             BRANCH(TaggedIsSpecial(*value), &isSpecial, &notSpecial);
12860             Bind(&isSpecial);
12861             {
12862                 value = SpecialToString(glue, *value);
12863                 Jump(&exit);
12864             }
12865             Bind(&notSpecial);
12866             {
12867                 Label numberBigIntPointer(env);
12868                 Label notNumberBigIntPointer(env);
12869                 GateRef checkValue = *value;
12870                 GateRef checkType = LogicOrBuilder(env)
12871                                     .Or(TaggedIsNumber(checkValue))
12872                                     .Or(TaggedIsBigInt(glue, checkValue))
12873                                     .Or(TaggedIsNativePointer(glue, checkValue))
12874                                     .Done();
12875                 BRANCH(checkType, &numberBigIntPointer, &notNumberBigIntPointer);
12876                 Bind(&numberBigIntPointer);
12877                 {
12878                     value = CallRuntime(glue, RTSTUB_ID(NumberBigIntNativePointerToString), { *value });
12879                     Jump(&exit);
12880                 }
12881                 Bind(&notNumberBigIntPointer);
12882                 {
12883                     Label isEcmaObject1(env);
12884                     Label notEcmaObject1(env);
12885                     BRANCH(IsEcmaObject(glue, *value), &isEcmaObject1, &notEcmaObject1);
12886                     Bind(&isEcmaObject1);
12887                     {
12888                         value = ToPrimitive(glue, *value, PreferredPrimitiveType::PREFER_STRING, hir);
12889                         Label hasException(env);
12890                         BRANCH(HasPendingException(glue), &hasException, &loopEnd);
12891                         Bind(&hasException);
12892                         {
12893                             value = GetGlobalConstantValue(VariableType::JS_POINTER(),
12894                                                            glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
12895                             Jump(&exit);
12896                         }
12897                     }
12898                     Bind(&notEcmaObject1);
12899                     {
12900                         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertIllageValueToString));
12901                         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
12902                         value = GetGlobalConstantValue(VariableType::JS_POINTER(),
12903                                                        glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
12904                         Jump(&exit);
12905                     }
12906                 }
12907             }
12908         }
12909     }
12910     Bind(&loopEnd);
12911     LoopEnd(&loopHead);
12912     Bind(&exit);
12913     auto ret = *value;
12914     env->SubCfgExit();
12915     return ret;
12916 }
12917 
SpecialToString(GateRef glue,GateRef specialVal)12918 GateRef StubBuilder::SpecialToString(GateRef glue, GateRef specialVal)
12919 {
12920     auto env = GetEnvironment();
12921     Label entry(env);
12922     Label exit(env);
12923     env->SubCfgEntry(&entry);
12924     DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
12925     Label labelBuffer[5] = { Label(env), Label(env), Label(env), Label(env), Label(env) };
12926     Label defaultLabel(env);
12927     Switch(ChangeTaggedPointerToInt64(specialVal), &defaultLabel, SPECIAL_VALUE, labelBuffer, SPECIAL_VALUE_NUM);
12928     for (int i = 0; i < SPECIAL_VALUE_NUM; i++) {
12929         Bind(&labelBuffer[i]);
12930         value = GetGlobalConstantValue(VariableType::JS_ANY(), glue, SPECIAL_STRING_INDEX[i]);
12931         Jump(&exit);
12932     }
12933     Bind(&defaultLabel);
12934     {
12935         FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))});
12936         Jump(&exit);
12937     }
12938     Bind(&exit);
12939     auto ret = *value;
12940     env->SubCfgExit();
12941     return ret;
12942 }
12943 
ToPrimitive(GateRef glue,GateRef value,PreferredPrimitiveType type,GateRef hir)12944 GateRef StubBuilder::ToPrimitive(GateRef glue, GateRef value, PreferredPrimitiveType type, GateRef hir)
12945 {
12946     auto env = GetEnvironment();
12947     Label entry(env);
12948     env->SubCfgEntry(&entry);
12949     Label isEcmaObject(env);
12950     Label exit(env);
12951     Label hasException(env);
12952     Label notHasException(env);
12953     Label notHasException1(env);
12954     Label notHasException2(env);
12955     DEFVARIABLE(result, VariableType::JS_ANY(), value);
12956     BRANCH(IsEcmaObject(glue, value), &isEcmaObject, &exit);
12957     Bind(&isEcmaObject);
12958     {
12959         Label isUndefined(env);
12960         Label notUndefined(env);
12961         GateRef globalEnv = GetCurrentGlobalEnv();
12962         GateRef primitiveKey = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
12963                                                  GlobalEnv::TOPRIMITIVE_SYMBOL_INDEX);
12964         GateRef name = FastGetPropertyByName(glue, value, primitiveKey, ProfileOperation(), hir);
12965         BRANCH(HasPendingException(glue), &hasException, &notHasException);
12966         Bind(&notHasException);
12967         GateRef exoticToprim = CallFunction(glue, name);
12968         BRANCH(HasPendingException(glue), &hasException, &notHasException1);
12969         Bind(&notHasException1);
12970         BRANCH(TaggedIsUndefined(exoticToprim), &isUndefined, &notUndefined);
12971         Bind(&notUndefined);
12972         {
12973             GateRef typeValue = GetPrimitiveTypeString(glue, type);
12974             DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Undefined());
12975             JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG2_WITH_RETURN);
12976             callArgs.callThisArg2WithReturnArgs = {value, typeValue, Undefined()};
12977             CallStubBuilder callBuilder(this, glue, exoticToprim, Int32(2), 0, &tmpResult, Circuit::NullGate(),
12978                                         callArgs, ProfileOperation(), true, hir);
12979             Label callExit(env);
12980             if (env->IsBaselineBuiltin()) {
12981                 callBuilder.JSCallDispatchForBaseline(&callExit);
12982                 Bind(&callExit);
12983             } else {
12984                 tmpResult = callBuilder.JSCallDispatch();
12985             }
12986             BRANCH(HasPendingException(glue), &hasException, &notHasException2);
12987             Bind(&notHasException2);
12988             Label isEcmaObject1(env);
12989             Label notEcmaObject1(env);
12990             BRANCH(IsEcmaObject(glue, *tmpResult), &isEcmaObject1, &notEcmaObject1);
12991             Bind(&isEcmaObject1);
12992             {
12993                 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertObjectToPrimitiveValue));
12994                 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
12995                 Jump(&hasException);
12996             }
12997             Bind(&notEcmaObject1);
12998             {
12999                 result = *tmpResult;
13000                 Jump(&exit);
13001             }
13002         }
13003         Bind(&isUndefined);
13004         {
13005             Label numberPreference(env);
13006             Label defaultPreference(env);
13007             BRANCH(Int32Equal(Int32(static_cast<uint8_t>(type)),
13008                 Int32(static_cast<uint8_t>(PreferredPrimitiveType::NO_PREFERENCE))),
13009                 &numberPreference, &defaultPreference);
13010             Bind(&numberPreference);
13011             {
13012                 result = OrdinaryToPrimitive(glue, value, PreferredPrimitiveType::PREFER_NUMBER, hir);
13013                 Jump(&exit);
13014             }
13015             Bind(&defaultPreference);
13016             {
13017                 result = OrdinaryToPrimitive(glue, value, type, hir);
13018                 Jump(&exit);
13019             }
13020         }
13021     }
13022     Bind(&hasException);
13023     {
13024         result = Exception();
13025         Jump(&exit);
13026     }
13027     Bind(&exit);
13028     auto ret = *result;
13029     env->SubCfgExit();
13030     return ret;
13031 }
13032 
GetPrimitiveTypeString(GateRef glue,PreferredPrimitiveType type)13033 GateRef StubBuilder::GetPrimitiveTypeString(GateRef glue, PreferredPrimitiveType type)
13034 {
13035     auto env = GetEnvironment();
13036     Label entry(env);
13037     env->SubCfgEntry(&entry);
13038     DEFVARIABLE(typeValue, VariableType::JS_ANY(),
13039         GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13040         ConstantIndex::STRING_STRING_INDEX));
13041     Label labelBuffer[2] = {Label(env), Label(env)};
13042     Label labelDefault(env);
13043     int64_t valueBuffer[2] = {
13044         static_cast<int64_t>(PreferredPrimitiveType::NO_PREFERENCE),
13045         static_cast<int64_t>(PreferredPrimitiveType::PREFER_NUMBER),
13046     };
13047     Switch(Int64(static_cast<int64_t>(type)), &labelDefault, valueBuffer, labelBuffer, 2);
13048     Bind(&labelBuffer[0]);
13049     {
13050         typeValue = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13051                                            ConstantIndex::DEFAULT_INDEX);
13052         Jump(&labelDefault);
13053     }
13054     Bind(&labelBuffer[1]);
13055     {
13056         typeValue = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13057                                            ConstantIndex::NUMBER_STRING_INDEX);
13058         Jump(&labelDefault);
13059     }
13060     Bind(&labelDefault);
13061     auto ret = *typeValue;
13062     env->SubCfgExit();
13063     return ret;
13064 }
13065 
OrdinaryToPrimitive(GateRef glue,GateRef value,PreferredPrimitiveType type,GateRef hir)13066 GateRef StubBuilder::OrdinaryToPrimitive(GateRef glue, GateRef value, PreferredPrimitiveType type, GateRef hir)
13067 {
13068     auto env = GetEnvironment();
13069     Label entry(env);
13070     env->SubCfgEntry(&entry);
13071     Label isEcmaObject(env);
13072     Label exit(env);
13073     Label hasException(env);
13074     Label notHasException1(env);
13075     Label notHasException2(env);
13076     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
13077     BRANCH(IsEcmaObject(glue, value), &isEcmaObject, &exit);
13078     Bind(&isEcmaObject);
13079     DEFVARIABLE(valType, VariableType::INT32(), Int32(static_cast<uint8_t>(type)));
13080     GateRef numberInt32 = Int32(static_cast<uint8_t>(PreferredPrimitiveType::PREFER_NUMBER));
13081     GateRef stringInt32 = Int32(static_cast<uint8_t>(PreferredPrimitiveType::PREFER_STRING));
13082     GateRef len = Int32(2);
13083     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
13084     Label loopHead(env);
13085     Label loopEnd(env);
13086     Label next(env);
13087     Label loopExit(env);
13088     Jump(&loopHead);
13089     LoopBegin(&loopHead);
13090     {
13091         DEFVARIABLE(keyString, VariableType::JS_ANY(), Undefined());
13092         BRANCH(Int32LessThan(*i, len), &next, &loopExit);
13093         Bind(&next);
13094         Label toString(env);
13095         Label valueOf(env);
13096         Label checkExit(env);
13097         BRANCH(Int32Equal(*valType, stringInt32), &toString, &valueOf);
13098         Bind(&toString);
13099         {
13100             keyString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13101                                                ConstantIndex::TO_STRING_STRING_INDEX);
13102             valType = numberInt32;
13103             Jump(&checkExit);
13104         }
13105         Bind(&valueOf);
13106         {
13107             keyString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13108                                                ConstantIndex::VALUE_OF_STRING_INDEX);
13109             valType = stringInt32;
13110             Jump(&checkExit);
13111         }
13112         Bind(&checkExit);
13113         GateRef entryfunc = FastGetPropertyByName(glue, value, *keyString, ProfileOperation(), hir);
13114         BRANCH(HasPendingException(glue), &hasException, &notHasException1);
13115         Bind(&notHasException1);
13116         Label isCallable1(env);
13117         BRANCH(TaggedIsCallable(glue, entryfunc), &isCallable1, &loopEnd);
13118         Bind(&isCallable1);
13119         {
13120             DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Undefined());
13121             JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG2_WITH_RETURN);
13122             callArgs.callThisArg2WithReturnArgs = { value, Undefined(), Undefined() };
13123             CallStubBuilder callBuilder(this, glue, entryfunc, Int32(2), 0, &tmpResult, Circuit::NullGate(),
13124                                         callArgs, ProfileOperation(), true, hir);
13125             Label callExit(env);
13126             if (env->IsBaselineBuiltin()) {
13127                 callBuilder.JSCallDispatchForBaseline(&callExit);
13128                 Bind(&callExit);
13129             } else {
13130                 tmpResult = callBuilder.JSCallDispatch();
13131             }
13132             BRANCH(HasPendingException(glue), &hasException, &notHasException2);
13133             Bind(&notHasException2);
13134             Label notEcmaObject1(env);
13135             BRANCH(IsEcmaObject(glue, *tmpResult), &loopEnd, &notEcmaObject1);
13136             Bind(&notEcmaObject1);
13137             {
13138                 result = *tmpResult;
13139                 Jump(&exit);
13140             }
13141         }
13142     }
13143     Bind(&loopEnd);
13144     i = Int32Add(*i, Int32(1));
13145     LoopEnd(&loopHead);
13146     Bind(&loopExit);
13147     {
13148         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertIllageValueToPrimitive));
13149         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
13150         result = Undefined();
13151         Jump(&exit);
13152     }
13153     Bind(&hasException);
13154     {
13155         result = Exception();
13156         Jump(&exit);
13157     }
13158     Bind(&exit);
13159     auto ret = *result;
13160     env->SubCfgExit();
13161     return ret;
13162 }
13163 
CallFunction(GateRef glue,GateRef func)13164 GateRef StubBuilder::CallFunction(GateRef glue, GateRef func)
13165 {
13166     auto env = GetEnvironment();
13167     Label entry(env);
13168     env->SubCfgEntry(&entry);
13169     Label exit(env);
13170     Label undefinedOrNull(env);
13171     Label notUndefinedAndNull(env);
13172     Label notCallable(env);
13173     DEFVARIABLE(result, VariableType::JS_ANY(), func);
13174     BRANCH(TaggedIsUndefinedOrNull(func), &undefinedOrNull, &notUndefinedAndNull);
13175     Bind(&undefinedOrNull);
13176     {
13177         result = Undefined();
13178         Jump(&exit);
13179     }
13180     Bind(&notUndefinedAndNull);
13181     BRANCH(TaggedIsCallable(glue, func), &exit, &notCallable);
13182     Bind(&notCallable);
13183     {
13184         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable));
13185         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
13186         Jump(&exit);
13187     }
13188     Bind(&exit);
13189     auto ret = *result;
13190     env->SubCfgExit();
13191     return ret;
13192 }
13193 
ArrayCopy(GateRef glue,GateRef srcObj,GateRef srcAddr,GateRef dstObj,GateRef dstAddr,GateRef taggedValueCount,GateRef needBarrier,CopyKind copyKind)13194 void StubBuilder::ArrayCopy(GateRef glue, GateRef srcObj, GateRef srcAddr, GateRef dstObj,
13195                             GateRef dstAddr, GateRef taggedValueCount, GateRef needBarrier,
13196                             CopyKind copyKind)
13197 {
13198     auto env = GetEnvironment();
13199     Label entry(env);
13200     env->SubCfgEntry(&entry);
13201     Label exit(env);
13202     Label isEnableCMCGC(env);
13203     Label notCMCGC(env);
13204     BRANCH_UNLIKELY(LoadPrimitive(
13205         VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
13206         &isEnableCMCGC, &notCMCGC);
13207 
13208     Bind(&isEnableCMCGC);
13209     {
13210         CallNGCRuntime(glue, RTSTUB_ID(CopyObjectPrimitive),
13211             {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(srcAddr), taggedValueCount});
13212         Label handleBarrier(env);
13213         BRANCH_NO_WEIGHT(needBarrier, &handleBarrier, &exit);
13214         Bind(&handleBarrier);
13215         {
13216             if (copyKind == SameArray) {
13217                 CMCArrayCopyWriteBarrierSameArray(glue, dstObj, srcAddr, dstAddr, taggedValueCount);
13218             } else {
13219                 CMCArrayCopyWriteBarrier(glue, dstObj, srcAddr, dstAddr, taggedValueCount);
13220             }
13221             Jump(&exit);
13222         }
13223     }
13224     Bind(&notCMCGC);
13225     {
13226         CallNGCRuntime(glue, RTSTUB_ID(ObjectCopy),
13227             {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(srcAddr), taggedValueCount});
13228         Label handleBarrier(env);
13229         BRANCH_NO_WEIGHT(needBarrier, &handleBarrier, &exit);
13230         Bind(&handleBarrier);
13231         {
13232             if (copyKind == SameArray) {
13233                 CallCommonStub(glue, CommonStubCSigns::MoveBarrierInRegion,
13234                     {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), taggedValueCount,
13235                     TaggedCastToIntPtr(srcAddr)});
13236             } else {
13237                 ASSERT(copyKind == DifferentArray);
13238                 CallCommonStub(glue, CommonStubCSigns::MoveBarrierCrossRegion,
13239                     {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), taggedValueCount,
13240                     TaggedCastToIntPtr(srcAddr), TaggedCastToIntPtr(srcObj)});
13241             }
13242             Jump(&exit);
13243         }
13244     }
13245     Bind(&exit);
13246     env->SubCfgExit();
13247 }
13248 
ArrayCopyAndHoleToUndefined(GateRef glue,GateRef srcObj,GateRef srcAddr,GateRef dstObj,GateRef dstAddr,GateRef length,GateRef needBarrier)13249 void StubBuilder::ArrayCopyAndHoleToUndefined(GateRef glue, GateRef srcObj, GateRef srcAddr, GateRef dstObj,
13250                                               GateRef dstAddr, GateRef length, GateRef needBarrier)
13251 {
13252     auto env = GetEnvironment();
13253     Label entry(env);
13254     env->SubCfgEntry(&entry);
13255     Label loopExit(env);
13256     Label exit(env);
13257     Label begin(env);
13258     Label body(env);
13259     Label handleBarrier(env);
13260     Label endLoop(env);
13261     GateRef dstOff = PtrSub(TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(dstObj));
13262     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
13263     Jump(&begin);
13264     LoopBegin(&begin);
13265     {
13266         BRANCH_LIKELY(Int32UnsignedLessThan(*index, length), &body, &loopExit);
13267         Bind(&body);
13268         {
13269             GateRef offset = PtrMul(ZExtInt32ToPtr(*index), IntPtr(JSTaggedValue::TaggedTypeSize()));
13270             GateRef value = Load(VariableType::JS_ANY(), glue, srcAddr, offset);
13271 
13272             Label isHole(env);
13273             Label isNotHole(env);
13274             BRANCH_UNLIKELY(TaggedIsHole(value), &isHole, &isNotHole);
13275             Bind(&isHole);
13276             {
13277                 Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, offset), Undefined(),
13278                       MemoryAttribute::NoBarrier());
13279                 Jump(&endLoop);
13280             }
13281             Bind(&isNotHole);
13282             Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, offset), value, MemoryAttribute::NoBarrier());
13283             Jump(&endLoop);
13284         }
13285     }
13286     Bind(&endLoop);
13287     index = Int32Add(*index, Int32(1));
13288     LoopEnd(&begin);
13289     Bind(&loopExit);
13290     Label checkNext(env);
13291     BRANCH_NO_WEIGHT(needBarrier, &checkNext, &exit);
13292     Bind(&checkNext);
13293     BRANCH_UNLIKELY(LoadPrimitive(
13294         VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
13295         &exit, &handleBarrier);
13296     Bind(&handleBarrier);
13297     {
13298         CallCommonStub(glue, CommonStubCSigns::MoveBarrierCrossRegion,
13299                        {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), length,
13300                        TaggedCastToIntPtr(srcAddr), TaggedCastToIntPtr(srcObj)});
13301 
13302         Jump(&exit);
13303     }
13304     Bind(&exit);
13305     env->SubCfgExit();
13306 }
13307 
Int64BitReverse(GateRef x)13308 GateRef StubBuilder::Int64BitReverse(GateRef x)
13309 {
13310     return env_->GetBuilder()->Int64Rev(x);
13311 }
13312 
Int32BitReverse(GateRef x)13313 GateRef StubBuilder::Int32BitReverse(GateRef x)
13314 {
13315     return env_->GetBuilder()->Int32Rev(x);
13316 }
13317 
Int16BitReverse(GateRef x)13318 GateRef StubBuilder::Int16BitReverse(GateRef x)
13319 {
13320     return env_->GetBuilder()->Int16Rev(x);
13321 }
13322 
Int8BitReverse(GateRef x)13323 GateRef StubBuilder::Int8BitReverse(GateRef x)
13324 {
13325     return env_->GetBuilder()->Int8Rev(x);
13326 }
13327 
13328 int64_t StubBuilder::SPECIAL_VALUE[SPECIAL_VALUE_NUM] = {
13329     static_cast<int64_t>(JSTaggedValue::VALUE_UNDEFINED),
13330     static_cast<int64_t>(JSTaggedValue::VALUE_NULL),
13331     static_cast<int64_t>(JSTaggedValue::VALUE_TRUE),
13332     static_cast<int64_t>(JSTaggedValue::VALUE_FALSE),
13333     static_cast<int64_t>(JSTaggedValue::VALUE_HOLE)
13334 };
13335 
13336 ConstantIndex StubBuilder::SPECIAL_STRING_INDEX[SPECIAL_VALUE_NUM] = {
13337     ConstantIndex::UNDEFINED_STRING_INDEX,
13338     ConstantIndex::NULL_STRING_INDEX,
13339     ConstantIndex::TRUE_STRING_INDEX,
13340     ConstantIndex::FALSE_STRING_INDEX,
13341     ConstantIndex::EMPTY_STRING_OBJECT_INDEX
13342 };
13343 
13344 
ThreeInt64Min(GateRef first,GateRef second,GateRef third)13345 GateRef StubBuilder::ThreeInt64Min(GateRef first, GateRef second, GateRef third)
13346 {
13347     return env_->GetBuilder()->ThreeInt64Min(first, second, third);
13348 }
13349 
GetCurrentGlobalEnv(GateRef glue,GateRef currentEnv)13350 GateRef StubBuilder::GetCurrentGlobalEnv(GateRef glue, GateRef currentEnv)
13351 {
13352     auto env0 = GetEnvironment();
13353     {
13354         ASM_ASSERT(GET_MESSAGE_STRING_ID(CurrentEnvIsInvalid),
13355             LogicAndBuilder(env0).And(TaggedIsHeapObject(currentEnv))
13356                                  .And(LogicOrBuilder(env0).Or(IsGlobalEnv(glue, currentEnv))
13357                                       .Or(IsLexicalEnv(glue, currentEnv))
13358                                       .Or(IsSFunctionEnv(glue, currentEnv)).Done())
13359                                  .Done());
13360     }
13361     Label entry(env0);
13362     env0->SubCfgEntry(&entry);
13363     Label fromGlue(env0);
13364     Label exit(env0);
13365     DEFVARIABLE(globalEnv, VariableType::JS_ANY(), Undefined());
13366 
13367     globalEnv = GetValueFromTaggedArray(glue, currentEnv, Int32(BaseEnv::GLOBAL_ENV_INDEX));
13368     BRANCH_UNLIKELY(TaggedIsHole(*globalEnv), &fromGlue, &exit);
13369     Bind(&fromGlue);
13370     {
13371         globalEnv = GetGlobalEnv(glue);
13372         Jump(&exit);
13373     }
13374     Bind(&exit);
13375     auto ret = *globalEnv;
13376     env0->SubCfgExit();
13377     return ret;
13378 }
13379 }  // namespace panda::ecmascript::kungfu
13380