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