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