1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/compiler/call_stub_builder.h"
17 #include "ecmascript/compiler/access_object_stub_builder.h"
18 #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h"
19 #include "ecmascript/compiler/builtins/builtins_proxy_stub_builder.h"
20 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
21 #include "ecmascript/compiler/builtins/builtins_collection_stub_builder.h"
22 #include "ecmascript/compiler/new_object_stub_builder.h"
23 #include "ecmascript/compiler/object_operator_stub_builder.h"
24 #include "ecmascript/compiler/profiler_stub_builder.h"
25 #include "ecmascript/elements.h"
26 #include "ecmascript/compiler/stub_builder.h"
27 #include "ecmascript/ic/mega_ic_cache.h"
28 #include "ecmascript/js_api/js_api_arraylist.h"
29 #include "ecmascript/js_primitive_ref.h"
30 #include "ecmascript/lexical_env.h"
31 #include "ecmascript/marker_cell.h"
32 #include "ecmascript/require/js_cjs_module_cache.h"
33 #include "ecmascript/transitions_dictionary.h"
34 #include "common_components/heap/allocator/region_desc.h"
35 #include "objects/base_state_word.h"
36
37 namespace panda::ecmascript::kungfu {
Jump(Label * label)38 void StubBuilder::Jump(Label *label)
39 {
40 ASSERT(label);
41 auto currentLabel = env_->GetCurrentLabel();
42 auto currentControl = currentLabel->GetControl();
43 auto jump = env_->GetBuilder()->Goto(currentControl);
44 currentLabel->SetControl(jump);
45 label->AppendPredecessor(currentLabel);
46 label->MergeControl(currentLabel->GetControl());
47 env_->SetCurrentLabel(nullptr);
48 }
49
Branch(GateRef condition,Label * trueLabel,Label * falseLabel,uint32_t trueWeight,uint32_t falseWeight,const char * comment)50 void StubBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel,
51 uint32_t trueWeight, uint32_t falseWeight, const char *comment)
52 {
53 auto currentLabel = env_->GetCurrentLabel();
54 auto currentControl = currentLabel->GetControl();
55 GateRef ifBranch = env_->GetBuilder()->Branch(currentControl, condition, trueWeight, falseWeight, comment);
56 currentLabel->SetControl(ifBranch);
57 GateRef ifTrue = env_->GetBuilder()->IfTrue(ifBranch);
58 trueLabel->AppendPredecessor(env_->GetCurrentLabel());
59 trueLabel->MergeControl(ifTrue);
60 GateRef ifFalse = env_->GetBuilder()->IfFalse(ifBranch);
61 falseLabel->AppendPredecessor(env_->GetCurrentLabel());
62 falseLabel->MergeControl(ifFalse);
63 env_->SetCurrentLabel(nullptr);
64 }
65
66 template <class LabelPtrGetter>
SwitchGeneric(GateRef index,Label * defaultLabel,Span<const int64_t> keysValue,LabelPtrGetter getIthLabelFn)67 void StubBuilder::SwitchGeneric(GateRef index, Label *defaultLabel, Span<const int64_t> keysValue,
68 LabelPtrGetter getIthLabelFn)
69 {
70 static_assert(std::is_invocable_r_v<Label*, LabelPtrGetter, size_t>, "Invalid call signature.");
71 size_t numberOfKeys = keysValue.Size();
72 auto currentLabel = env_->GetCurrentLabel();
73 auto currentControl = currentLabel->GetControl();
74 GateRef switchBranch = env_->GetBuilder()->SwitchBranch(currentControl, index, numberOfKeys);
75 currentLabel->SetControl(switchBranch);
76 for (size_t i = 0; i < numberOfKeys; i++) {
77 GateRef switchCase = env_->GetBuilder()->SwitchCase(switchBranch, keysValue[i]);
78 Label *curLabel = std::invoke(getIthLabelFn, i);
79 curLabel->AppendPredecessor(currentLabel);
80 curLabel->MergeControl(switchCase);
81 }
82
83 GateRef defaultCase = env_->GetBuilder()->DefaultCase(switchBranch);
84 defaultLabel->AppendPredecessor(currentLabel);
85 defaultLabel->MergeControl(defaultCase);
86 env_->SetCurrentLabel(nullptr);
87 }
88
Switch(GateRef index,Label * defaultLabel,const int64_t * keysValue,Label * keysLabel,int numberOfKeys)89 void StubBuilder::Switch(GateRef index, Label *defaultLabel,
90 const int64_t *keysValue, Label *keysLabel, int numberOfKeys)
91 {
92 return SwitchGeneric(index, defaultLabel, {keysValue, numberOfKeys}, [keysLabel](size_t i) {
93 return &keysLabel[i];
94 });
95 }
96
Switch(GateRef index,Label * defaultLabel,const int64_t * keysValue,Label * const * keysLabel,int numberOfKeys)97 void StubBuilder::Switch(GateRef index, Label *defaultLabel,
98 const int64_t *keysValue, Label *const *keysLabel, int numberOfKeys)
99 {
100 return SwitchGeneric(index, defaultLabel, {keysValue, numberOfKeys}, [keysLabel](size_t i) {
101 return keysLabel[i];
102 });
103 }
104
LoopBegin(Label * loopHead)105 void StubBuilder::LoopBegin(Label *loopHead)
106 {
107 ASSERT(loopHead);
108 auto loopControl = env_->GetBuilder()->LoopBegin(loopHead->GetControl());
109 loopHead->SetControl(loopControl);
110 loopHead->SetPreControl(loopControl);
111 loopHead->Bind();
112 env_->SetCurrentLabel(loopHead);
113 }
114
CheckSuspend(GateRef glue)115 GateRef StubBuilder::CheckSuspend(GateRef glue)
116 {
117 GateRef stateAndFlagsOffset = IntPtr(JSThread::GlueData::GetStateAndFlagsOffset(env_->IsArch32Bit()));
118 GateRef stateAndFlags = LoadPrimitive(VariableType::INT16(), glue, stateAndFlagsOffset);
119 return Int32And(ZExtInt16ToInt32(stateAndFlags), Int32(ThreadFlag::SUSPEND_REQUEST));
120 }
121
CheckSuspendForCMCGC(GateRef glue)122 GateRef StubBuilder::CheckSuspendForCMCGC(GateRef glue)
123 {
124 GateRef threadHolderOffset = IntPtr(JSThread::GlueData::GetThreadHolderOffset(env_->IsArch32Bit()));
125 GateRef threadHolder = LoadPrimitive(VariableType::NATIVE_POINTER(), glue, threadHolderOffset);
126 GateRef mutatorBase = LoadPrimitive(VariableType::NATIVE_POINTER(), threadHolder, IntPtr(ThreadHolder::GetMutatorBaseOffset()));
127 GateRef safepointActive = LoadPrimitive(VariableType::INT32(), mutatorBase, IntPtr(common::MutatorBase::GetSafepointActiveOffset()));
128 return safepointActive;
129 }
130
LoopEndWithCheckSafePoint(Label * loopHead,Environment * env,GateRef glue)131 void StubBuilder::LoopEndWithCheckSafePoint(Label *loopHead, Environment *env, GateRef glue)
132 {
133 Label loopEnd(env);
134 Label needSuspend(env);
135 Label checkSuspendForCMCGC(env);
136 Label checkSuspend(env);
137 BRANCH_UNLIKELY(LoadPrimitive(
138 VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
139 &checkSuspendForCMCGC, &checkSuspend);
140 Bind(&checkSuspend);
141 BRANCH_UNLIKELY(Int32Equal(Int32(ThreadFlag::SUSPEND_REQUEST), CheckSuspend(glue)), &needSuspend, &loopEnd);
142 Bind(&checkSuspendForCMCGC);
143 BRANCH_UNLIKELY(Int32Equal(Int32(ThreadFlag::SUSPEND_REQUEST), CheckSuspendForCMCGC(glue)), &needSuspend, &loopEnd);
144 Bind(&needSuspend);
145 {
146 CallRuntime(glue, RTSTUB_ID(CheckSafePoint), {});
147 Jump(&loopEnd);
148 }
149 Bind(&loopEnd);
150 LoopEnd(loopHead);
151 }
152
LoopEnd(Label * loopHead)153 void StubBuilder::LoopEnd(Label *loopHead)
154 {
155 ASSERT(loopHead);
156 auto currentLabel = env_->GetCurrentLabel();
157 auto currentControl = currentLabel->GetControl();
158 auto loopend = env_->GetBuilder()->LoopEnd(currentControl);
159 currentLabel->SetControl(loopend);
160 loopHead->AppendPredecessor(currentLabel);
161 loopHead->MergeControl(loopend);
162 loopHead->Seal();
163 loopHead->MergeAllControl();
164 loopHead->MergeAllDepend();
165 env_->SetCurrentLabel(nullptr);
166 }
167
MatchFieldType(GateRef glue,GateRef fieldType,GateRef value,Label * executeSetProp,Label * typeMismatch)168 void StubBuilder::MatchFieldType(
169 GateRef glue, GateRef fieldType, GateRef value, Label *executeSetProp, Label *typeMismatch)
170 {
171 auto *env = GetEnvironment();
172 Label valueIsUndefined(env);
173 Label checkNumber(env);
174 Label isNumber(env);
175 Label checkBoolean(env);
176 Label isBoolean(env);
177 Label checkString(env);
178 Label isString(env);
179 Label checkJSShared(env);
180 Label isJSShared(env);
181 Label checkBigInt(env);
182 Label isBigInt(env);
183 Label checkNoneOrGeneric(env);
184 Label isNoneOrGeneric(env);
185 Label checkNull(env);
186 Label isNull(env);
187 Label checkUndefined(env);
188 Label isUndefined(env);
189 Label exit(env);
190 Label mismatch(env);
191 Label checkMatch(env);
192 DEFVARIABLE(result, VariableType::BOOL(), False());
193 GateRef checkType = TaggedIsUndefined(value);
194 BRANCH(checkType, &valueIsUndefined, &checkNumber);
195 Bind(&valueIsUndefined);
196 {
197 result = True();
198 Jump(&exit);
199 }
200 Bind(&checkNumber);
201 {
202 checkType = LogicAndBuilder(env)
203 .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NUMBER))), Int32(0)))
204 .And(TaggedIsNumber(value))
205 .Done();
206 BRANCH(checkType, &isNumber, &checkBoolean);
207 Bind(&isNumber);
208 {
209 result = True();
210 Jump(&exit);
211 }
212 }
213 Bind(&checkBoolean);
214 {
215 checkType = LogicAndBuilder(env)
216 .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::BOOLEAN))), Int32(0)))
217 .And(TaggedIsBoolean(value))
218 .Done();
219 BRANCH(checkType, &isBoolean, &checkString);
220 Bind(&isBoolean);
221 {
222 result = True();
223 Jump(&exit);
224 }
225 }
226 Bind(&checkString);
227 {
228 checkType = LogicAndBuilder(env)
229 .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::STRING))), Int32(0)))
230 .And(LogicOrBuilder(env).Or(TaggedIsString(glue, value)).Or(TaggedIsNull(value)).Done())
231 .Done();
232 BRANCH(checkType, &isString, &checkJSShared);
233 Bind(&isString);
234 {
235 result = True();
236 Jump(&exit);
237 }
238 }
239 Bind(&checkJSShared);
240 {
241 checkType = LogicAndBuilder(env)
242 .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::SENDABLE))), Int32(0)))
243 .And(LogicOrBuilder(env).Or(TaggedIsSharedObj(glue, value)).Or(TaggedIsNull(value)).Done())
244 .Done();
245 BRANCH(checkType, &isJSShared, &checkBigInt);
246 Bind(&isJSShared);
247 {
248 result = True();
249 Jump(&exit);
250 }
251 }
252 Bind(&checkBigInt);
253 {
254 checkType = LogicAndBuilder(env)
255 .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::BIG_INT))), Int32(0)))
256 .And(TaggedIsBigInt(glue, value))
257 .Done();
258 BRANCH(checkType, &isBigInt, &checkNoneOrGeneric);
259 Bind(&isBigInt);
260 {
261 result = True();
262 Jump(&exit);
263 }
264 }
265 Bind(&checkNoneOrGeneric);
266 {
267 GateRef fieldTypeCheck = LogicOrBuilder(env)
268 .Or(Equal(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NONE))))
269 .Or(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::GENERIC))), Int32(0)))
270 .Done();
271 checkType = LogicAndBuilder(env)
272 .And(fieldTypeCheck)
273 .And(LogicOrBuilder(env).Or(BoolNot(TaggedIsHeapObject(value))).Or(TaggedIsSharedObj(glue, value)).Done())
274 .Done();
275 BRANCH(checkType, &isNoneOrGeneric, &checkNull);
276 Bind(&isNoneOrGeneric);
277 {
278 // (none || generic) && (jsShared || !heapObject)
279 result = True();
280 Jump(&exit);
281 }
282 }
283 Bind(&checkNull);
284 {
285 checkType = LogicAndBuilder(env)
286 .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::NULL_TYPE))), Int32(0)))
287 .And(TaggedIsNull(value))
288 .Done();
289 BRANCH(checkType, &isNull, &checkUndefined);
290 Bind(&isNull);
291 {
292 result = True();
293 Jump(&exit);
294 }
295 }
296 Bind(&checkUndefined);
297 {
298 checkType = LogicAndBuilder(env)
299 .And(Int32NotEqual(Int32And(fieldType, Int32(static_cast<int32_t>(SharedFieldType::UNDEFINED))), Int32(0)))
300 .And(TaggedIsUndefined(value))
301 .Done();
302 BRANCH(checkType, &isUndefined, &exit);
303 Bind(&isUndefined);
304 {
305 result = True();
306 Jump(&exit);
307 }
308 }
309 Bind(&exit);
310 Branch(BoolNot(*result), &mismatch, &checkMatch);
311 Bind(&mismatch);
312 {
313 CallRuntime(glue, RTSTUB_ID(MismatchError), {IntToTaggedInt(fieldType), value});
314 Jump(&checkMatch);
315 }
316 Bind(&checkMatch);
317 BRANCH(*result, executeSetProp, typeMismatch);
318 }
319
320 // FindElementWithCache in ecmascript/layout_info-inl.h
FindElementWithCache(GateRef glue,GateRef layoutInfo,GateRef hclass,GateRef key,GateRef propsNum,GateRef hir)321 GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, GateRef hclass,
322 GateRef key, GateRef propsNum, GateRef hir)
323 {
324 auto env = GetEnvironment();
325 Label subEntry(env);
326 env->SubCfgEntry(&subEntry);
327 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
328 Label exit(env);
329 Label notExceedUpper(env);
330 Label exceedUpper(env);
331 // 9 : Builtins Object properties number is nine
332 constexpr int32_t maxPropsNum = 9;
333 BRANCH(Int32LessThanOrEqual(propsNum, Int32(maxPropsNum)), ¬ExceedUpper, &exceedUpper);
334 Bind(¬ExceedUpper);
335 {
336 Label labels[maxPropsNum] = {Label(env), Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
337 Label(env), Label(env)};
338 Label notFount(env);
339 GateRef elementAddr = GetPropertiesAddrFromLayoutInfo(layoutInfo);
340 Jump(&labels[0]);
341 for (int32_t idx = 0; idx < maxPropsNum; idx++) {
342 bool isLast = (idx == maxPropsNum - 1);
343 Label check(env);
344 Bind(&labels[idx]);
345 {
346 BRANCH_LIKELY(Int32LessThan(Int32(idx), propsNum), &check, ¬Fount);
347 // Not real "likely", just to make the code layout of labels and check block tightly.
348 }
349 Bind(&check);
350 {
351 result = Int32(idx);
352 GateRef keyInProperty = Load(VariableType::JS_ANY(), glue, elementAddr,
353 PtrMul(ZExtInt32ToPtr(Int32(idx)),
354 IntPtr(sizeof(panda::ecmascript::Properties))));
355 if (!isLast) {
356 BRANCH_UNLIKELY(Equal(keyInProperty, key), &exit, &labels[idx + 1]);
357 // Not real "unlikely", just to make the code layout of labels and check block tightly.
358 } else {
359 BRANCH(Equal(keyInProperty, key), &exit, ¬Fount);
360 }
361 }
362 }
363 Bind(¬Fount);
364 result = Int32(-1);
365 Jump(&exit);
366 }
367 Bind(&exceedUpper);
368 Label find(env);
369 Label notFind(env);
370 Label setCache(env);
371 GateRef cache = GetPropertiesCache(glue);
372 GateRef index = GetIndexFromPropertiesCache(glue, cache, hclass, key, hir);
373 BRANCH(Int32Equal(index, Int32(PropertiesCache::NOT_FOUND)), ¬Find, &find);
374 Bind(¬Find);
375 {
376 result = BinarySearch(glue, layoutInfo, key, propsNum, hir);
377 BRANCH(Int32Equal(*result, Int32(PropertiesCache::NOT_FOUND)), &exit, &setCache);
378 Bind(&setCache);
379 SetToPropertiesCache(glue, cache, hclass, key, *result, hir);
380 Jump(&exit);
381 }
382 Bind(&find);
383 {
384 result = index;
385 Jump(&exit);
386 }
387 Bind(&exit);
388 auto ret = *result;
389 env->SubCfgExit();
390 return ret;
391 }
392
GetIndexFromPropertiesCache(GateRef glue,GateRef cache,GateRef cls,GateRef key,GateRef hir)393 GateRef StubBuilder::GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef hir)
394 {
395 auto env = GetEnvironment();
396 Label subentry(env);
397 env->SubCfgEntry(&subentry);
398 DEFVARIABLE(result, VariableType::INT32(), Int32(PropertiesCache::NOT_FOUND));
399
400 Label exit(env);
401 Label find(env);
402 GateRef hash = HashFromHclassAndKey(glue, cls, key, hir);
403 GateRef prop =
404 PtrAdd(cache, PtrMul(ZExtInt32ToPtr(hash), IntPtr(PropertiesCache::PropertyKey::GetPropertyKeySize())));
405 size_t propHclassOffset = PropertiesCache::PropertyKey::GetHclassOffset();
406 size_t propKeyOffset = PropertiesCache::PropertyKey::GetKeyOffset();
407 BRANCH(LogicAndBuilder(env)
408 .And(IntPtrEqual(cls, Load(VariableType::JS_POINTER(), glue, prop, IntPtr(propHclassOffset))))
409 .And(IntPtrEqual(key, Load(VariableType::JS_ANY(), glue, prop, IntPtr(propKeyOffset))))
410 .Done(), &find, &exit);
411 Bind(&find);
412 {
413 result = LoadPrimitive(VariableType::INT32(), prop, IntPtr(PropertiesCache::PropertyKey::GetResultsOffset()));
414 Jump(&exit);
415 }
416 Bind(&exit);
417 auto ret = *result;
418 env->SubCfgExit();
419 return ret;
420 }
421
GetHandlerFromMegaICCache(GateRef glue,GateRef cache,GateRef cls,GateRef key)422 GateRef StubBuilder::GetHandlerFromMegaICCache(GateRef glue, GateRef cache, GateRef cls, GateRef key)
423 {
424 auto env = GetEnvironment();
425 Label subentry(env);
426 env->SubCfgEntry(&subentry);
427 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
428 Label exit(env);
429 Label find(env);
430 GateRef hash = HashFromHclassAndStringKey(glue, cls, key);
431
432 GateRef prop = PtrAdd(cache, PtrMul(ZExtInt32ToPtr(hash), IntPtr(MegaICCache::PropertyKey::GetPropertyKeySize())));
433 GateRef propHclass = Load(VariableType::JS_POINTER(), glue, prop, IntPtr(MegaICCache::PropertyKey::GetHclassOffset()));
434 GateRef propKey = Load(VariableType::JS_ANY(), glue, prop, IntPtr(MegaICCache::PropertyKey::GetKeyOffset()));
435
436 GateRef hclassIsEqual = IntPtrEqual(cls, propHclass);
437 GateRef keyIsEqual = IntPtrEqual(key, propKey);
438 IncMegaProbeCount(glue);
439 BRANCH(BitAnd(hclassIsEqual, keyIsEqual), &find, &exit);
440 Bind(&find);
441 {
442 result = Load(VariableType::JS_ANY(), glue, prop, IntPtr(MegaICCache::PropertyKey::GetResultsOffset()));
443 IncMegaHitCount(glue);
444 Jump(&exit);
445 }
446 Bind(&exit);
447 auto ret = *result;
448 env->SubCfgExit();
449 return ret;
450 }
451
452
BinarySearch(GateRef glue,GateRef layoutInfo,GateRef key,GateRef propsNum,GateRef hir)453 GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum, GateRef hir)
454 {
455 auto env = GetEnvironment();
456 Label subentry(env);
457 env->SubCfgEntry(&subentry);
458 DEFVARIABLE(low, VariableType::INT32(), Int32(0));
459 Label exit(env);
460 GateRef elements = GetExtraLengthOfTaggedArray(layoutInfo);
461 DEFVARIABLE(high, VariableType::INT32(), Int32Sub(elements, Int32(1)));
462 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
463 DEFVARIABLE(mid, VariableType::INT32(), Int32(-1));
464
465 GateRef keyHash = GetKeyHashCode(glue, key, hir);
466 Label loopHead(env);
467 Label loopEnd(env);
468 Label afterLoop(env);
469 Label midGreaterKey(env);
470 Label midnotGreaterKey(env);
471 Label midLessKey(env);
472 Label midEqualKey(env);
473 Label next(env);
474 Jump(&loopHead);
475 LoopBegin(&loopHead);
476 {
477 BRANCH(Int32LessThanOrEqual(*low, *high), &next, &exit);
478 Bind(&next);
479 mid = Int32Add(*low, Int32Div(Int32Sub(*high, *low), Int32(2))); // 2: half
480 GateRef midKey = GetSortedKey(glue, layoutInfo, *mid);
481 GateRef midHash = GetKeyHashCode(glue, midKey, hir);
482 BRANCH(Int32UnsignedGreaterThan(midHash, keyHash), &midGreaterKey, &midnotGreaterKey);
483 Bind(&midGreaterKey);
484 {
485 high = Int32Sub(*mid, Int32(1));
486 Jump(&loopEnd);
487 }
488 Bind(&midnotGreaterKey);
489 {
490 BRANCH(Int32UnsignedLessThan(midHash, keyHash), &midLessKey, &midEqualKey);
491 Bind(&midLessKey);
492 {
493 low = Int32Add(*mid, Int32(1));
494 Jump(&loopEnd);
495 }
496 Bind(&midEqualKey);
497 {
498 Label retIndex(env);
499 Label nextLoop(env);
500 DEFVARIABLE(sortIndex, VariableType::INT32(), GetSortedIndex(glue, layoutInfo, *mid));
501 DEFVARIABLE(currentKey, VariableType::JS_ANY(), midKey);
502 BRANCH(IntPtrEqual(midKey, key), &retIndex, &nextLoop);
503 Bind(&retIndex);
504 {
505 Label retSortIndex(env);
506 BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
507 Bind(&retSortIndex);
508 {
509 result = *sortIndex;
510 Jump(&exit);
511 }
512 }
513 Bind(&nextLoop);
514 {
515 DEFVARIABLE(midLeft, VariableType::INT32(), *mid);
516 DEFVARIABLE(midRight, VariableType::INT32(), *mid);
517 Label loopHead1(env);
518 Label loopEnd1(env);
519 Label afterLoop1(env);
520 Label nextCount(env);
521 Jump(&loopHead1);
522 LoopBegin(&loopHead1);
523 {
524 BRANCH(Int32GreaterThanOrEqual(Int32Sub(*midLeft, Int32(1)), Int32(0)),
525 &nextCount, &afterLoop1);
526 Bind(&nextCount);
527 {
528 Label hashEqual(env);
529 midLeft = Int32Sub(*midLeft, Int32(1));
530 sortIndex = GetSortedIndex(glue, layoutInfo, *midLeft);
531 currentKey = GetKey(glue, layoutInfo, *sortIndex);
532 BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual,
533 &afterLoop1);
534 Bind(&hashEqual);
535 {
536 Label retIndex1(env);
537 BRANCH(IntPtrEqual(*currentKey, key), &retIndex1, &loopEnd1);
538 Bind(&retIndex1);
539 {
540 Label retSortIndex(env);
541 BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
542 Bind(&retSortIndex);
543 {
544 result = *sortIndex;
545 Jump(&exit);
546 }
547 }
548 }
549 }
550 Bind(&loopEnd1);
551 {
552 LoopEnd(&loopHead1);
553 }
554 }
555 Bind(&afterLoop1);
556 {
557 Label loopHead2(env);
558 Label loopEnd2(env);
559 Label nextCount1(env);
560 Jump(&loopHead2);
561 LoopBegin(&loopHead2);
562 {
563 BRANCH(Int32LessThan(Int32Add(*midRight, Int32(1)), elements), &nextCount1, &exit);
564 Bind(&nextCount1);
565 {
566 Label hashEqual(env);
567 midRight = Int32Add(*midRight, Int32(1));
568 sortIndex = GetSortedIndex(glue, layoutInfo, *midRight);
569 currentKey = GetKey(glue, layoutInfo, *sortIndex);
570 BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual, &exit);
571 Bind(&hashEqual);
572 {
573 Label retIndex2(env);
574 BRANCH(IntPtrEqual(*currentKey, key), &retIndex2, &loopEnd2);
575 Bind(&retIndex2);
576 {
577 Label retSortIndex(env);
578 BRANCH(Int32LessThan(*sortIndex, propsNum), &retSortIndex, &exit);
579 Bind(&retSortIndex);
580 {
581 result = *sortIndex;
582 Jump(&exit);
583 }
584 }
585 }
586 }
587 Bind(&loopEnd2);
588 {
589 LoopEnd(&loopHead2);
590 }
591 }
592 }
593 }
594 }
595 }
596 }
597
598 Bind(&loopEnd);
599 {
600 LoopEnd(&loopHead);
601 }
602
603 Bind(&exit);
604 auto ret = *result;
605 env->SubCfgExit();
606 return ret;
607 }
608
GetKeyHashCode(GateRef glue,GateRef key,GateRef hir)609 GateRef StubBuilder::GetKeyHashCode(GateRef glue, GateRef key, GateRef hir)
610 {
611 auto env = GetEnvironment();
612 Label subentry(env);
613 env->SubCfgEntry(&subentry);
614 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
615
616 Label exit(env);
617 Label isString(env);
618 Label isSymblo(env);
619 BRANCH(TaggedIsString(glue, key), &isString, &isSymblo);
620 Bind(&isString);
621 {
622 result = GetHashcodeFromString(glue, key, hir);
623 Jump(&exit);
624 }
625 Bind(&isSymblo);
626 {
627 result = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), key,
628 IntPtr(JSSymbol::HASHFIELD_OFFSET)));
629 Jump(&exit);
630 }
631 Bind(&exit);
632 auto ret = *result;
633 env->SubCfgExit();
634 return ret;
635 }
636
637 // JSObject::CreateDataProperty
CreateDataProperty(GateRef glue,GateRef obj,GateRef propKey,GateRef value)638 GateRef StubBuilder::CreateDataProperty(GateRef glue, GateRef obj, GateRef propKey, GateRef value)
639 {
640 auto env = GetEnvironment();
641 Label subentry(env);
642 env->SubCfgEntry(&subentry);
643 Label exit(env);
644 Label next(env);
645 Label objIsShared(env);
646 Label objIsNotShared(env);
647 Label isHole(env);
648 Label notHole(env);
649 Label hasPendingException(env);
650
651 DEFVARIABLE(result, VariableType::BOOL(), True());
652 GateRef SCheckModelIsCHECK = Boolean(true);
653 auto flag = DefinePropertyByValue(glue, obj, propKey, value, SCheckModelIsCHECK, ProfileOperation());
654 BRANCH(HasPendingException(glue), &hasPendingException, &next);
655 Bind(&hasPendingException);
656 {
657 result = False();
658 Jump(&exit);
659 }
660 Bind(&next);
661 {
662 BRANCH(TaggedIsHole(flag), &isHole, ¬Hole);
663 Bind(&isHole);
664 {
665 GateRef temp = CallRuntime(glue, RTSTUB_ID(DefineOwnProperty), {obj, propKey, value});
666 result = TaggedIsTrue(temp);
667 Jump(&exit);
668 }
669 Bind(¬Hole);
670 {
671 result = BoolNot(TaggedIsException(flag));
672 Jump(&exit);
673 }
674 }
675 Bind(&exit);
676 auto ret = *result;
677 env->SubCfgExit();
678 return ret;
679 }
680
CreateDataPropertyOrThrow(GateRef glue,GateRef obj,GateRef key,GateRef value)681 GateRef StubBuilder::CreateDataPropertyOrThrow(GateRef glue, GateRef obj, GateRef key, GateRef value)
682 {
683 auto env = GetEnvironment();
684 Label subentry(env);
685 env->SubCfgEntry(&subentry);
686 Label exit(env);
687 Label newThrow(env);
688 Label isThrow(env);
689
690 DEFVARIABLE(result, VariableType::BOOL(), True());
691
692 CanNotConvertNotValidObject(glue, obj);
693 IsNotPropertyKey(TaggedIsPropertyKey(glue, key));
694
695 result = CreateDataProperty(glue, obj, key, value);
696 BRANCH(*result, &exit, &isThrow);
697
698 Bind(&isThrow);
699 {
700 BRANCH(HasPendingException(glue), &exit, &newThrow);
701 Bind(&newThrow);
702 {
703 GateRef msgIntId = Int32(GET_MESSAGE_STRING_ID(CreateDataPropertyFailed));
704 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId)});
705 Jump(&exit);
706 }
707 }
708
709 Bind(&exit);
710 auto ret = *result;
711 env->SubCfgExit();
712 return ret;
713 }
714
DefineField(GateRef glue,GateRef obj,GateRef propKey,GateRef value)715 GateRef StubBuilder::DefineField(GateRef glue, GateRef obj, GateRef propKey, GateRef value)
716 {
717 auto env = GetEnvironment();
718 Label entry(env);
719 env->SubCfgEntry(&entry);
720 Label exit(env);
721 Label next(env);
722 Label notObj(env);
723 Label newThrow(env);
724 Label isObj(env);
725 Label hasPendingException(env);
726 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
727 DEFVARIABLE(key, VariableType::JS_ANY(), Undefined());
728 BRANCH(IsEcmaObject(glue, obj), &isObj, ¬Obj);
729 Bind(&isObj);
730 {
731 #if ENABLE_NEXT_OPTIMIZATION
732 key = ToPropertyKey(glue, propKey);
733 #else
734 key = CallRuntime(glue, RTSTUB_ID(ToPropertyKey), {propKey});
735 #endif
736 BRANCH(HasPendingException(glue), &hasPendingException, &next);
737 }
738 Bind(&next);
739 {
740 CreateDataPropertyOrThrow(glue, obj, *key, value);
741 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
742 }
743 Bind(¬Obj);
744 {
745 BRANCH(HasPendingException(glue), &hasPendingException, &newThrow);
746 }
747 Bind(&hasPendingException);
748 {
749 result = Exception();
750 Jump(&exit);
751 }
752 Bind(&newThrow);
753 {
754 GateRef msgIntId = Int32(GET_MESSAGE_STRING_ID(DefineFieldField));
755 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId)});
756 result = Exception();
757 Jump(&exit);
758 }
759
760 Bind(&exit);
761 auto ret = *result;
762 env->SubCfgExit();
763 return ret;
764 }
765
FindElementFromNumberDictionary(GateRef glue,GateRef elements,GateRef index)766 GateRef StubBuilder::FindElementFromNumberDictionary(GateRef glue, GateRef elements, GateRef index)
767 {
768 auto env = GetEnvironment();
769 Label subentry(env);
770 env->SubCfgEntry(&subentry);
771 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
772 Label exit(env);
773 GateRef capcityoffset =
774 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
775 IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
776 GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
777 GateRef capacity = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), elements,
778 PtrAdd(dataoffset, capcityoffset)));
779 DEFVARIABLE(count, VariableType::INT32(), Int32(1));
780 GateRef len = Int32(sizeof(int) / sizeof(uint8_t));
781 GateRef hash = CallRuntime(glue, RTSTUB_ID(GetHash32),
782 { IntToTaggedInt(index), IntToTaggedInt(len) });
783 DEFVARIABLE(entry, VariableType::INT32(),
784 Int32And(TruncInt64ToInt32(ChangeTaggedPointerToInt64(hash)), Int32Sub(capacity, Int32(1))));
785 Label loopHead(env);
786 Label loopEnd(env);
787 Label afterLoop(env);
788 Jump(&loopHead);
789 LoopBegin(&loopHead);
790 GateRef element = GetKeyFromDictionary<NumberDictionary>(glue, elements, *entry);
791 Label isHole(env);
792 Label notHole(env);
793 BRANCH(TaggedIsHole(element), &isHole, ¬Hole);
794 Bind(&isHole);
795 Jump(&loopEnd);
796 Bind(¬Hole);
797 Label isUndefined(env);
798 Label notUndefined(env);
799 BRANCH(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
800 Bind(&isUndefined);
801 result = Int32(-1);
802 Jump(&exit);
803 Bind(¬Undefined);
804 Label isMatch(env);
805 Label notMatch(env);
806 BRANCH(Int32Equal(index, GetInt32OfTInt(element)), &isMatch, ¬Match);
807 Bind(&isMatch);
808 result = *entry;
809 Jump(&exit);
810 Bind(¬Match);
811 Jump(&loopEnd);
812 Bind(&loopEnd);
813 entry = GetNextPositionForHash(*entry, *count, capacity);
814 count = Int32Add(*count, Int32(1));
815 LoopEndWithCheckSafePoint(&loopHead, env, glue);
816 Bind(&exit);
817 auto ret = *result;
818 env->SubCfgExit();
819 return ret;
820 }
821
822 // int TaggedHashTable<Derived>::FindEntry(const JSTaggedValue &key) in tagged_hash_table.h
823 template<typename HashTableT>
FindEntryFromHashTable(GateRef glue,GateRef elements,GateRef key,GateRef hir)824 GateRef StubBuilder::FindEntryFromHashTable(GateRef glue, GateRef elements, GateRef key, GateRef hir)
825 {
826 auto env = GetEnvironment();
827 Label funcEntry(env);
828 env->SubCfgEntry(&funcEntry);
829 Label exit(env);
830 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
831 GateRef capcityoffset =
832 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
833 IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
834 GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
835 GateRef capacity = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), elements,
836 PtrAdd(dataoffset, capcityoffset)));
837 DEFVARIABLE(count, VariableType::INT32(), Int32(1));
838 DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
839 // NameDictionary::hash
840 Label isSymbol(env);
841 Label notSymbol(env);
842 Label loopHead(env);
843 Label loopEnd(env);
844 Label afterLoop(env);
845 Label beforeDefineHash(env);
846 BRANCH(IsSymbol(glue, key), &isSymbol, ¬Symbol);
847 Bind(&isSymbol);
848 {
849 hash = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), key,
850 IntPtr(JSSymbol::HASHFIELD_OFFSET)));
851 Jump(&beforeDefineHash);
852 }
853 Bind(¬Symbol);
854 {
855 Label isString(env);
856 Label notString(env);
857 BRANCH(IsString(glue, key), &isString, ¬String);
858 Bind(&isString);
859 {
860 hash = GetHashcodeFromString(glue, key, hir);
861 Jump(&beforeDefineHash);
862 }
863 Bind(¬String);
864 {
865 Jump(&beforeDefineHash);
866 }
867 }
868 Bind(&beforeDefineHash);
869 // GetFirstPosition(hash, size)
870 DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
871 Jump(&loopHead);
872 LoopBegin(&loopHead);
873 {
874 GateRef element = GetKeyFromDictionary<HashTableT>(glue, elements, *entry);
875 Label isHole(env);
876 Label notHole(env);
877 BRANCH(TaggedIsHole(element), &isHole, ¬Hole);
878 {
879 Bind(&isHole);
880 {
881 Jump(&loopEnd);
882 }
883 Bind(¬Hole);
884 {
885 Label isUndefined(env);
886 Label notUndefined(env);
887 BRANCH(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
888 {
889 Bind(&isUndefined);
890 {
891 result = Int32(-1);
892 Jump(&exit);
893 }
894 Bind(¬Undefined);
895 {
896 Label isMatch(env);
897 Label notMatch(env);
898 BRANCH(Equal(key, element), &isMatch, ¬Match);
899 {
900 Bind(&isMatch);
901 {
902 result = *entry;
903 Jump(&exit);
904 }
905 Bind(¬Match);
906 {
907 Jump(&loopEnd);
908 }
909 }
910 }
911 }
912 }
913 }
914 Bind(&loopEnd);
915 {
916 entry = GetNextPositionForHash(*entry, *count, capacity);
917 count = Int32Add(*count, Int32(1));
918 LoopEndWithCheckSafePoint(&loopHead, env, glue);
919 }
920 }
921 Bind(&exit);
922 auto ret = *result;
923 env->SubCfgExit();
924 return ret;
925 }
926
IsMatchInTransitionDictionary(GateRef element,GateRef key,GateRef metaData,GateRef attr)927 GateRef StubBuilder::IsMatchInTransitionDictionary(GateRef element, GateRef key, GateRef metaData, GateRef attr)
928 {
929 return BitAnd(Equal(element, key), Int32Equal(metaData, attr));
930 }
931
FindEntryFromTransitionDictionary(GateRef glue,GateRef elements,GateRef key,GateRef metaData)932 GateRef StubBuilder::FindEntryFromTransitionDictionary(GateRef glue, GateRef elements, GateRef key, GateRef metaData)
933 {
934 auto env = GetEnvironment();
935 Label funcEntry(env);
936 env->SubCfgEntry(&funcEntry);
937 Label exit(env);
938 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
939 GateRef capcityoffset =
940 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
941 IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
942 GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
943 GateRef capacity = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), elements,
944 PtrAdd(dataoffset, capcityoffset)));
945 DEFVARIABLE(count, VariableType::INT32(), Int32(1));
946 DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
947 // TransitionDictionary::hash
948 Label isSymbol(env);
949 Label notSymbol(env);
950 Label loopHead(env);
951 Label loopEnd(env);
952 Label afterLoop(env);
953 Label beforeDefineHash(env);
954 BRANCH(IsSymbol(glue, key), &isSymbol, ¬Symbol);
955 Bind(&isSymbol);
956 {
957 hash = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), key,
958 IntPtr(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET)));
959 Jump(&beforeDefineHash);
960 }
961 Bind(¬Symbol);
962 {
963 Label isString(env);
964 Label notString(env);
965 BRANCH(IsString(glue, key), &isString, ¬String);
966 Bind(&isString);
967 {
968 hash = GetHashcodeFromString(glue, key);
969 Jump(&beforeDefineHash);
970 }
971 Bind(¬String);
972 {
973 Jump(&beforeDefineHash);
974 }
975 }
976 Bind(&beforeDefineHash);
977 hash = Int32Add(*hash, metaData);
978 // GetFirstPosition(hash, size)
979 DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
980 Jump(&loopHead);
981 LoopBegin(&loopHead);
982 {
983 GateRef element = GetKeyFromDictionary<TransitionsDictionary>(glue, elements, *entry);
984 Label isHole(env);
985 Label notHole(env);
986 BRANCH(TaggedIsHole(element), &isHole, ¬Hole);
987 {
988 Bind(&isHole);
989 {
990 Jump(&loopEnd);
991 }
992 Bind(¬Hole);
993 {
994 Label isUndefined(env);
995 Label notUndefined(env);
996 BRANCH(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
997 {
998 Bind(&isUndefined);
999 {
1000 result = Int32(-1);
1001 Jump(&exit);
1002 }
1003 Bind(¬Undefined);
1004 {
1005 Label isMatch(env);
1006 Label notMatch(env);
1007 BRANCH(IsMatchInTransitionDictionary(element, key, metaData,
1008 // metaData is int32 type
1009 TruncInt64ToInt32(GetAttributesFromDictionary<TransitionsDictionary>(glue, elements, *entry))),
1010 &isMatch, ¬Match);
1011 {
1012 Bind(&isMatch);
1013 {
1014 result = *entry;
1015 Jump(&exit);
1016 }
1017 Bind(¬Match);
1018 {
1019 Jump(&loopEnd);
1020 }
1021 }
1022 }
1023 }
1024 }
1025 }
1026 Bind(&loopEnd);
1027 {
1028 entry = GetNextPositionForHash(*entry, *count, capacity);
1029 count = Int32Add(*count, Int32(1));
1030 LoopEndWithCheckSafePoint(&loopHead, env, glue);
1031 }
1032 }
1033 Bind(&exit);
1034 auto ret = *result;
1035 env->SubCfgExit();
1036 return ret;
1037 }
1038
1039 // JSObject::HasProperty
JSObjectHasProperty(GateRef glue,GateRef obj,GateRef key,GateRef hir)1040 GateRef StubBuilder::JSObjectHasProperty(GateRef glue, GateRef obj, GateRef key, GateRef hir)
1041 {
1042 auto env = GetEnvironment();
1043 Label entry(env);
1044 env->SubCfgEntry(&entry);
1045 Label exit(env);
1046 Label checkHolder(env);
1047 DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
1048
1049 IsNotPropertyKey(TaggedIsPropertyKey(glue, key));
1050
1051 ObjectOperatorStubBuilder opStubBuilder(this, GetCurrentGlobalEnv());
1052
1053 ObjectOperatorStubBuilder::ObjectOperatorOptions opOptions;
1054 opOptions.lookupKind = ObjectOperatorStubBuilder::LookupKind::KIND_HAS_PROPERTY;
1055
1056 ObjectOperatorStubBuilder::ObjectOperatorResult opResult;
1057 opStubBuilder.InitializeOperatorResults(opResult);
1058 opResult.holder->WriteVariable(obj);
1059
1060 opStubBuilder.StartLookup<ObjectOperatorStubBuilder::StartLookupType::NO_RECEIVER>(
1061 glue, key, &checkHolder, opOptions, opResult, hir);
1062
1063 // if holder is JSProxy, op's lookup will return. This will be handled by CallRuntime.
1064 Bind(&checkHolder);
1065 {
1066 Label isJSProxy(env);
1067 Label isFound(env);
1068 BRANCH(TaggedIsJSProxy(glue, opResult.GetHolder()), &isJSProxy, &isFound);
1069 Bind(&isJSProxy);
1070 {
1071 result = CallRuntime(glue, RTSTUB_ID(JSProxyHasProperty), {opResult.GetHolder(), key});
1072 Jump(&exit);
1073 }
1074 Bind(&isFound);
1075 {
1076 result = BooleanToTaggedBooleanPtr(opStubBuilder.IsFound(opResult.metaData));
1077 Jump(&exit);
1078 }
1079 }
1080
1081 Bind(&exit);
1082 auto ret = *result;
1083 opStubBuilder.FinalizeOperatorResults(opResult);
1084 env->SubCfgExit();
1085 return ret;
1086 }
1087
JSObjectGetPropertyWithRep(GateRef glue,GateRef obj,GateRef hclass,GateRef attr)1088 GateRef StubBuilder::JSObjectGetPropertyWithRep(GateRef glue, GateRef obj, GateRef hclass, GateRef attr)
1089 {
1090 auto env = GetEnvironment();
1091 Label entry(env);
1092 env->SubCfgEntry(&entry);
1093 Label exit(env);
1094 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1095 Label inlinedProp(env);
1096 Label notInlinedProp(env);
1097 Label post(env);
1098 GateRef attrOffset = GetOffsetFieldInPropAttr(attr);
1099 GateRef rep = GetRepInPropAttr(attr);
1100 BRANCH(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp);
1101 {
1102 Bind(&inlinedProp);
1103 {
1104 result = GetPropertyInlinedProps(glue, obj, hclass, attrOffset);
1105 Jump(&post);
1106 }
1107 Bind(¬InlinedProp);
1108 {
1109 // compute outOfLineProp offset, get it and return
1110 GateRef array =
1111 Load(VariableType::JS_ANY(), glue, obj, IntPtr(JSObject::PROPERTIES_OFFSET));
1112 result = GetValueFromTaggedArray(glue, array, Int32Sub(attrOffset,
1113 GetInlinedPropertiesFromHClass(hclass)));
1114 Jump(&post);
1115 }
1116 }
1117 Bind(&post);
1118 {
1119 Label nonDoubleToTagged(env);
1120 Label doubleToTagged(env);
1121 BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
1122 Bind(&doubleToTagged);
1123 {
1124 result = TaggedPtrToTaggedDoublePtr(*result);
1125 Jump(&exit);
1126 }
1127 Bind(&nonDoubleToTagged);
1128 {
1129 Label intToTagged(env);
1130 BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit);
1131 Bind(&intToTagged);
1132 {
1133 result = TaggedPtrToTaggedIntPtr(*result);
1134 Jump(&exit);
1135 }
1136 }
1137 }
1138 Bind(&exit);
1139 auto ret = *result;
1140 env->SubCfgExit();
1141 return ret;
1142 }
1143
JSObjectSetProperty(GateRef glue,GateRef obj,GateRef hclass,GateRef attr,GateRef key,GateRef value)1144 void StubBuilder::JSObjectSetProperty(
1145 GateRef glue, GateRef obj, GateRef hclass, GateRef attr, GateRef key, GateRef value)
1146 {
1147 auto env = GetEnvironment();
1148 Label subEntry(env);
1149 env->SubCfgEntry(&subEntry);
1150 Label exit(env);
1151 Label inlinedProp(env);
1152 Label notInlinedProp(env);
1153 GateRef attrIndex = GetOffsetFieldInPropAttr(attr);
1154 BRANCH(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp);
1155 {
1156 Bind(&inlinedProp);
1157 {
1158 GateRef offset = GetInlinedPropOffsetFromHClass(hclass, attrIndex);
1159 SetValueWithAttr(glue, obj, offset, key, value, attr);
1160 Jump(&exit);
1161 }
1162 Bind(¬InlinedProp);
1163 {
1164 // compute outOfLineProp offset, get it and return
1165 GateRef array = Load(VariableType::JS_POINTER(), glue, obj,
1166 IntPtr(JSObject::PROPERTIES_OFFSET));
1167 GateRef offset = Int32Sub(attrIndex, GetInlinedPropertiesFromHClass(hclass));
1168 SetValueToTaggedArrayWithAttr(glue, array, offset, key, value, attr);
1169 Jump(&exit);
1170 }
1171 }
1172 Bind(&exit);
1173 env->SubCfgExit();
1174 return;
1175 }
1176
ComputeNonInlinedFastPropsCapacity(GateRef glue,GateRef oldLength,GateRef maxNonInlinedFastPropsCapacity)1177 GateRef StubBuilder::ComputeNonInlinedFastPropsCapacity(GateRef glue, GateRef oldLength,
1178 GateRef maxNonInlinedFastPropsCapacity)
1179 {
1180 auto env = GetEnvironment();
1181 Label subEntry(env);
1182 env->SubCfgEntry(&subEntry);
1183 Label exit(env);
1184 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1185 GateRef propertiesStep = LoadPrimitive(VariableType::INT32(), glue,
1186 IntPtr(JSThread::GlueData::GetPropertiesGrowStepOffset(env->Is32Bit())));
1187 GateRef newL = Int32Add(oldLength, propertiesStep);
1188 Label reachMax(env);
1189 Label notReachMax(env);
1190 BRANCH(Int32GreaterThan(newL, maxNonInlinedFastPropsCapacity), &reachMax, ¬ReachMax);
1191 {
1192 Bind(&reachMax);
1193 result = maxNonInlinedFastPropsCapacity;
1194 Jump(&exit);
1195 Bind(¬ReachMax);
1196 result = newL;
1197 Jump(&exit);
1198 }
1199 Bind(&exit);
1200 auto ret = *result;
1201 env->SubCfgExit();
1202 return ret;
1203 }
1204 #if ENABLE_NEXT_OPTIMIZATION
ComputeElementCapacity(GateRef oldLength)1205 GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength)
1206 {
1207 auto env = GetEnvironment();
1208 Label subEntry(env);
1209 env->SubCfgEntry(&subEntry);
1210 Label exit(env);
1211 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1212 GateRef newL = Int32Add(oldLength, Int32LSR(oldLength, Int32(1)));
1213 // Handle small array edge cases: for small arrays, 1.5 times expansion may not provide sufficient growth,
1214 // so adding a fixed value (like 16) avoids frequent capacity expansion in the short term.
1215 newL = Int32Add(newL, Int32(16));
1216 result = newL;
1217 Jump(&exit);
1218 Bind(&exit);
1219 auto ret = *result;
1220 env->SubCfgExit();
1221 return ret;
1222 }
1223 #else
ComputeElementCapacity(GateRef oldLength)1224 GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength)
1225 {
1226 auto env = GetEnvironment();
1227 Label subEntry(env);
1228 env->SubCfgEntry(&subEntry);
1229 Label exit(env);
1230 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1231 GateRef newL = Int32Add(oldLength, Int32LSR(oldLength, Int32(1)));
1232 Label reachMin(env);
1233 Label notReachMin(env);
1234 BRANCH(Int32GreaterThan(newL, Int32(JSObject::MIN_ELEMENTS_LENGTH)), &reachMin, ¬ReachMin);
1235 {
1236 Bind(&reachMin);
1237 result = newL;
1238 Jump(&exit);
1239 Bind(¬ReachMin);
1240 result = Int32(JSObject::MIN_ELEMENTS_LENGTH);
1241 Jump(&exit);
1242 }
1243 Bind(&exit);
1244 auto ret = *result;
1245 env->SubCfgExit();
1246 return ret;
1247 }
1248 #endif
CallGetterHelper(GateRef glue,GateRef receiver,GateRef holder,GateRef accessor,ProfileOperation callback,GateRef hir)1249 GateRef StubBuilder::CallGetterHelper(
1250 GateRef glue, GateRef receiver, GateRef holder, GateRef accessor, ProfileOperation callback, GateRef hir)
1251 {
1252 auto env = GetEnvironment();
1253 Label subEntry(env);
1254 env->SubCfgEntry(&subEntry);
1255 Label exit(env);
1256 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
1257
1258 Label isInternal(env);
1259 Label notInternal(env);
1260 BRANCH(IsAccessorInternal(glue, accessor), &isInternal, ¬Internal);
1261 Bind(&isInternal);
1262 {
1263 Label arrayLength(env);
1264 Label tryContinue(env);
1265 auto lengthAccessor = GetGlobalConstantValue(
1266 VariableType::JS_POINTER(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1267 BRANCH(Equal(accessor, lengthAccessor), &arrayLength, &tryContinue);
1268 Bind(&arrayLength);
1269 {
1270 auto length = LoadPrimitive(VariableType::INT32(), holder, IntPtr(JSArray::LENGTH_OFFSET));
1271 // TaggedInt supports up to INT32_MAX.
1272 // If length is greater than Int32_MAX, needs to be converted to TaggedDouble.
1273 auto condition = Int32UnsignedGreaterThan(length, Int32(INT32_MAX));
1274 Label overflow(env);
1275 Label notOverflow(env);
1276 BRANCH(condition, &overflow, ¬Overflow);
1277 Bind(&overflow);
1278 {
1279 result = DoubleToTaggedDoublePtr(ChangeUInt32ToFloat64(length));
1280 Jump(&exit);
1281 }
1282 Bind(¬Overflow);
1283 {
1284 result = IntToTaggedPtr(length);
1285 Jump(&exit);
1286 }
1287 }
1288 Bind(&tryContinue);
1289 result = CallRuntime(glue, RTSTUB_ID(CallInternalGetter), { accessor, holder });
1290 Jump(&exit);
1291 }
1292 Bind(¬Internal);
1293 {
1294 auto getter = Load(VariableType::JS_ANY(), glue, accessor,
1295 IntPtr(AccessorData::GETTER_OFFSET));
1296 Label objIsUndefined(env);
1297 Label objNotUndefined(env);
1298 Label callExit(env);
1299 BRANCH(TaggedIsUndefined(getter), &objIsUndefined, &objNotUndefined);
1300 // if getter is undefined, return undefiend
1301 Bind(&objIsUndefined);
1302 {
1303 result = Undefined();
1304 Jump(&exit);
1305 }
1306 Bind(&objNotUndefined);
1307 {
1308 DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Exception());
1309 JSCallArgs callArgs(JSCallMode::CALL_GETTER);
1310 callArgs.callGetterArgs = { receiver };
1311 CallStubBuilder callBuilder(this, glue, getter, Int32(0), 0, &tmpResult, Circuit::NullGate(), callArgs,
1312 callback, true, hir);
1313 if (env->IsBaselineBuiltin()) {
1314 callBuilder.JSCallDispatchForBaseline(&callExit);
1315 Bind(&callExit);
1316 } else {
1317 tmpResult = callBuilder.JSCallDispatch();
1318 }
1319 Label noPendingException(env);
1320 BRANCH(HasPendingException(glue), &exit, &noPendingException);
1321 Bind(&noPendingException);
1322 {
1323 result = *tmpResult;
1324 Jump(&exit);
1325 }
1326 }
1327 }
1328 Bind(&exit);
1329 auto ret = *result;
1330 env->SubCfgExit();
1331 return ret;
1332 }
1333
CallSetterHelper(GateRef glue,GateRef receiver,GateRef accessor,GateRef value,ProfileOperation callback,bool mayThrow)1334 GateRef StubBuilder::CallSetterHelper(
1335 GateRef glue, GateRef receiver, GateRef accessor, GateRef value, ProfileOperation callback, bool mayThrow)
1336 {
1337 auto env = GetEnvironment();
1338 Label subEntry(env);
1339 env->SubCfgEntry(&subEntry);
1340 Label exit(env);
1341 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
1342
1343 Label isInternal(env);
1344 Label notInternal(env);
1345 BRANCH(IsAccessorInternal(glue, accessor), &isInternal, ¬Internal);
1346 Bind(&isInternal);
1347 {
1348 if (mayThrow) {
1349 result = CallRuntime(glue, RTSTUB_ID(CallInternalSetter), {receiver, accessor, value});
1350 } else {
1351 result = CallRuntime(glue, RTSTUB_ID(CallInternalSetterNoThrow), {receiver, accessor, value});
1352 }
1353 Jump(&exit);
1354 }
1355 Bind(¬Internal);
1356 {
1357 auto setter = Load(VariableType::JS_ANY(), glue, accessor, IntPtr(AccessorData::SETTER_OFFSET));
1358 Label objIsUndefined(env);
1359 Label objNotUndefined(env);
1360 Label callExit(env);
1361 BRANCH(TaggedIsUndefined(setter), &objIsUndefined, &objNotUndefined);
1362 Bind(&objIsUndefined);
1363 {
1364 if (mayThrow) {
1365 CallRuntime(glue, RTSTUB_ID(ThrowSetterIsUndefinedException), {});
1366 result = Exception();
1367 } else {
1368 result = TaggedFalse();
1369 }
1370 Jump(&exit);
1371 }
1372 Bind(&objNotUndefined);
1373 {
1374 DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Exception());
1375 JSCallArgs callArgs(JSCallMode::CALL_SETTER);
1376 callArgs.callSetterArgs = { receiver, value };
1377 CallStubBuilder callBuilder(this, glue, setter, Int32(1), 0, &tmpResult, Circuit::NullGate(), callArgs,
1378 callback);
1379 if (env->IsBaselineBuiltin()) {
1380 callBuilder.JSCallDispatchForBaseline(&callExit);
1381 Bind(&callExit);
1382 } else {
1383 tmpResult = callBuilder.JSCallDispatch();
1384 }
1385 Label noPendingException(env);
1386 BRANCH(HasPendingException(glue), &exit, &noPendingException);
1387 Bind(&noPendingException);
1388 {
1389 if (mayThrow) {
1390 result = *tmpResult;
1391 } else {
1392 result = Undefined();
1393 }
1394 Jump(&exit);
1395 }
1396 }
1397 }
1398 Bind(&exit);
1399 auto ret = *result;
1400 env->SubCfgExit();
1401 return ret;
1402 }
1403
ShouldCallSetter(GateRef glue,GateRef receiver,GateRef holder,GateRef accessor,GateRef attr)1404 GateRef StubBuilder::ShouldCallSetter(GateRef glue, GateRef receiver, GateRef holder, GateRef accessor, GateRef attr)
1405 {
1406 auto env = GetEnvironment();
1407 Label subEntry(env);
1408 env->SubCfgEntry(&subEntry);
1409 Label exit(env);
1410 DEFVARIABLE(result, VariableType::BOOL(), True());
1411 Label isInternal(env);
1412 Label notInternal(env);
1413 BRANCH(IsAccessorInternal(glue, accessor), &isInternal, ¬Internal);
1414 Bind(&isInternal);
1415 {
1416 Label receiverEqualsHolder(env);
1417 Label receiverNotEqualsHolder(env);
1418 BRANCH(Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder);
1419 Bind(&receiverEqualsHolder);
1420 {
1421 result = IsWritable(attr);
1422 Jump(&exit);
1423 }
1424 Bind(&receiverNotEqualsHolder);
1425 {
1426 result = False();
1427 Jump(&exit);
1428 }
1429 }
1430 Bind(¬Internal);
1431 {
1432 result = True();
1433 Jump(&exit);
1434 }
1435 Bind(&exit);
1436 auto ret = *result;
1437 env->SubCfgExit();
1438 return ret;
1439 }
1440
JSHClassAddProperty(GateRef glue,GateRef receiver,GateRef key,GateRef attr,GateRef value)1441 void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef key, GateRef attr, GateRef value)
1442 {
1443 auto env = GetEnvironment();
1444 Label subEntry(env);
1445 env->SubCfgEntry(&subEntry);
1446 Label exit(env);
1447 GateRef hclass = LoadHClass(glue, receiver);
1448 GateRef metaData = GetPropertyMetaDataFromAttr(attr);
1449 GateRef newClass = FindTransitions(glue, hclass, key, metaData, value);
1450 Label findHClass(env);
1451 Label notFindHClass(env);
1452 BRANCH(Equal(newClass, Undefined()), ¬FindHClass, &findHClass);
1453 Bind(&findHClass);
1454 {
1455 GateRef isAOTHClass = IsAOTHClass(newClass);
1456 Label setPrototype(env);
1457 Label endSetPrototypeCheck(env);
1458 Branch(isAOTHClass, &setPrototype, &endSetPrototypeCheck);
1459 Bind(&setPrototype);
1460 {
1461 GateRef prototype = GetPrototypeFromHClass(glue, hclass);
1462 StorePrototype(glue, newClass, prototype);
1463 Jump(&endSetPrototypeCheck);
1464 }
1465 Bind(&endSetPrototypeCheck);
1466 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
1467 RestoreElementsKindToGeneric(glue, newClass);
1468 TransitionHClass(glue, receiver, newClass);
1469 #if ECMASCRIPT_ENABLE_IC
1470 Label needUpdateAOTHClass(env);
1471 Label normalNotify(env);
1472 Label endUpdate(env);
1473 GateRef updateCondition = LogicAndBuilder(env).And(isAOTHClass).And(IsPrototypeHClass(newClass)).Done();
1474 Branch(updateCondition, &needUpdateAOTHClass, &normalNotify);
1475 Bind(&needUpdateAOTHClass);
1476 {
1477 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1478 CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass),
1479 { hclass, newClass, key });
1480 Jump(&endUpdate);
1481 }
1482 Bind(&normalNotify);
1483 {
1484 // Because we currently only supports Fast ElementsKind
1485 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1486 NotifyHClassChanged(glue, hclass, newClass);
1487 Jump(&endUpdate);
1488 }
1489 Bind(&endUpdate);
1490 #else
1491 // Because we currently only supports Fast ElementsKind
1492 CallRuntime(glue, RTSTUB_ID(TryRestoreElementsKind), { receiver, newClass });
1493 #endif
1494 Jump(&exit);
1495 }
1496 Bind(¬FindHClass);
1497 {
1498 GateRef type = GetObjectType(hclass);
1499 GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
1500 Int32(JSTaggedValue::TaggedTypeSize()));
1501 GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
1502 GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
1503 { IntToTaggedInt(size), IntToTaggedInt(type),
1504 IntToTaggedInt(inlineProps) });
1505 CopyAllHClass(glue, newJshclass, hclass);
1506 CallRuntime(glue, RTSTUB_ID(UpdateLayOutAndAddTransition),
1507 { hclass, newJshclass, key, Int64ToTaggedInt(attr) });
1508 #if ECMASCRIPT_ENABLE_IC
1509 NotifyHClassChanged(glue, hclass, newJshclass);
1510 #endif
1511 // Because we currently only supports Fast ElementsKind
1512 RestoreElementsKindToGeneric(glue, newJshclass);
1513 TransitionHClass(glue, receiver, newJshclass);
1514 Jump(&exit);
1515 }
1516 Bind(&exit);
1517 env->SubCfgExit();
1518 return;
1519 }
1520
1521 // Note: set return exit node
AddPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef propertyAttributes,ProfileOperation callback)1522 GateRef StubBuilder::AddPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
1523 GateRef propertyAttributes, ProfileOperation callback)
1524 {
1525 auto env = GetEnvironment();
1526 Label subentry(env);
1527 env->SubCfgEntry(&subentry);
1528 Label exit(env);
1529 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1530 GateRef hclass = LoadHClass(glue, receiver);
1531 // 0x111 : default attribute for property: writable, enumerable, configurable
1532 DEFVARIABLE(attr, VariableType::INT64(), propertyAttributes);
1533 GateRef numberOfProps = GetNumberOfPropsFromHClass(hclass);
1534 GateRef inlinedProperties = GetInlinedPropertiesFromHClass(hclass);
1535 Label hasUnusedInProps(env);
1536 Label noUnusedInProps(env);
1537 Label afterInPropsCon(env);
1538 BRANCH(Int32UnsignedLessThan(numberOfProps, inlinedProperties), &hasUnusedInProps, &noUnusedInProps);
1539 {
1540 Bind(&noUnusedInProps);
1541 Jump(&afterInPropsCon);
1542 Bind(&hasUnusedInProps);
1543 {
1544 attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
1545 attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(1)); // 1: set inInlineProps true
1546 attr = SetTaggedRepInPropAttr(*attr);
1547 attr = ProfilerStubBuilder(env).UpdateTrackTypeInPropAttr(*attr, value, callback);
1548 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
1549 JSHClassAddProperty(glue, receiver, key, *attr, value);
1550 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1551 GateRef newHclass = LoadHClass(glue, receiver);
1552 GateRef newLayoutInfo = GetLayoutFromHClass(glue, newHclass);
1553 GateRef offset = GetInlinedPropOffsetFromHClass(hclass, numberOfProps);
1554 attr = GetPropAttrFromLayoutInfo(glue, newLayoutInfo, numberOfProps);
1555 SetValueWithAttr(glue, receiver, offset, key, value, *attr);
1556 result = Undefined();
1557 Jump(&exit);
1558 }
1559 }
1560 Bind(&afterInPropsCon);
1561 DEFVARIABLE(array, VariableType::JS_POINTER(), GetPropertiesArray(glue, receiver));
1562 DEFVARIABLE(length, VariableType::INT32(), GetLengthOfTaggedArray(*array));
1563 Label lenIsZero(env);
1564 Label lenNotZero(env);
1565 Label afterLenCon(env);
1566 BRANCH(Int32Equal(*length, Int32(0)), &lenIsZero, &lenNotZero);
1567 {
1568 Bind(&lenIsZero);
1569 {
1570 length = Int32(JSObject::MIN_PROPERTIES_LENGTH);
1571 array = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(*length) });
1572 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
1573 Jump(&afterLenCon);
1574 }
1575 Bind(&lenNotZero);
1576 Jump(&afterLenCon);
1577 }
1578 Bind(&afterLenCon);
1579 Label isDictMode(env);
1580 Label notDictMode(env);
1581 BRANCH(IsDictionaryMode(glue, *array), &isDictMode, ¬DictMode);
1582 {
1583 Bind(&isDictMode);
1584 {
1585 GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
1586 {receiver, *array, key, value, Int64ToTaggedInt(*attr), TaggedFalse()});
1587 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
1588 Jump(&exit);
1589 }
1590 Bind(¬DictMode);
1591 {
1592 attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(0));
1593 GateRef outProps = Int32Sub(numberOfProps, inlinedProperties);
1594 Label ChangeToDict(env);
1595 Label notChangeToDict(env);
1596 Label afterDictChangeCon(env);
1597 BRANCH(Int32GreaterThanOrEqual(numberOfProps, Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY)),
1598 &ChangeToDict, ¬ChangeToDict);
1599 {
1600 Bind(&ChangeToDict);
1601 {
1602 attr = SetDictionaryOrderFieldInPropAttr(*attr,
1603 Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY));
1604 GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
1605 { receiver, *array, key, value, Int64ToTaggedInt(*attr), TaggedTrue() });
1606 Label isPendingException(env);
1607 Label noPendingException(env);
1608 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
1609 Bind(&isPendingException);
1610 {
1611 result = Exception();
1612 Jump(&exit);
1613 }
1614 Bind(&noPendingException);
1615 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
1616 result = Undefined();
1617 Jump(&exit);
1618 }
1619 Bind(¬ChangeToDict);
1620 Jump(&afterDictChangeCon);
1621 }
1622 Bind(&afterDictChangeCon);
1623 Label isArrayFull(env);
1624 Label arrayNotFull(env);
1625 Label afterArrLenCon(env);
1626 BRANCH(Int32Equal(*length, outProps), &isArrayFull, &arrayNotFull);
1627 {
1628 Bind(&isArrayFull);
1629 {
1630 GateRef maxNonInlinedFastPropsCapacity =
1631 Int32Sub(Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY), inlinedProperties);
1632 GateRef capacity = ComputeNonInlinedFastPropsCapacity(glue, *length,
1633 maxNonInlinedFastPropsCapacity);
1634 NewObjectStubBuilder newBuilder(this, glue);
1635 array = newBuilder.CopyArray(glue, *array, *length, capacity);
1636 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
1637 Jump(&afterArrLenCon);
1638 }
1639 Bind(&arrayNotFull);
1640 Jump(&afterArrLenCon);
1641 }
1642 Bind(&afterArrLenCon);
1643 {
1644 attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
1645 attr = SetTaggedRepInPropAttr(*attr);
1646 attr = ProfilerStubBuilder(env).UpdateTrackTypeInPropAttr(*attr, value, callback);
1647 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
1648 JSHClassAddProperty(glue, receiver, key, *attr, value);
1649 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
1650 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, outProps, value);
1651 Jump(&exit);
1652 }
1653 }
1654 }
1655 Bind(&exit);
1656 auto ret = *result;
1657 env->SubCfgExit();
1658 return ret;
1659 }
1660
ThrowTypeAndReturn(GateRef glue,int messageId,GateRef val)1661 void StubBuilder::ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val)
1662 {
1663 GateRef msgIntId = Int32(messageId);
1664 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId) });
1665 Return(val);
1666 }
1667
TaggedToRepresentation(GateRef value)1668 GateRef StubBuilder::TaggedToRepresentation(GateRef value)
1669 {
1670 auto env = GetEnvironment();
1671 Label entry(env);
1672 env->SubCfgEntry(&entry);
1673 Label exit(env);
1674 DEFVARIABLE(resultRep, VariableType::INT64(),
1675 Int64(static_cast<int32_t>(Representation::TAGGED)));
1676 Label isInt(env);
1677 Label notInt(env);
1678
1679 BRANCH(TaggedIsInt(value), &isInt, ¬Int);
1680 Bind(&isInt);
1681 {
1682 resultRep = Int64(static_cast<int32_t>(Representation::INT));
1683 Jump(&exit);
1684 }
1685 Bind(¬Int);
1686 {
1687 Label isDouble(env);
1688 Label notDouble(env);
1689 BRANCH(TaggedIsDouble(value), &isDouble, ¬Double);
1690 Bind(&isDouble);
1691 {
1692 resultRep = Int64(static_cast<int32_t>(Representation::DOUBLE));
1693 Jump(&exit);
1694 }
1695 Bind(¬Double);
1696 {
1697 resultRep = Int64(static_cast<int32_t>(Representation::TAGGED));
1698 Jump(&exit);
1699 }
1700 }
1701 Bind(&exit);
1702 auto ret = *resultRep;
1703 env->SubCfgExit();
1704 return ret;
1705 }
1706
TaggedToElementKind(GateRef glue,GateRef value)1707 GateRef StubBuilder::TaggedToElementKind(GateRef glue, GateRef value)
1708 {
1709 auto env = GetEnvironment();
1710 Label entry(env);
1711 env->SubCfgEntry(&entry);
1712 Label exit(env);
1713
1714 DEFVARIABLE(result, VariableType::INT32(), Int32(Elements::ToUint(ElementsKind::TAGGED)));
1715 Label isHole(env);
1716 Label isNotHole(env);
1717 BRANCH(TaggedIsHole(value), &isHole, &isNotHole);
1718 Bind(&isHole);
1719 {
1720 result = Int32(Elements::ToUint(ElementsKind::HOLE));
1721 Jump(&exit);
1722 }
1723 Bind(&isNotHole);
1724 {
1725 Label isInt(env);
1726 Label isNotInt(env);
1727 BRANCH(TaggedIsInt(value), &isInt, &isNotInt);
1728 Bind(&isInt);
1729 {
1730 result = Int32(Elements::ToUint(ElementsKind::INT));
1731 Jump(&exit);
1732 }
1733 Bind(&isNotInt);
1734 {
1735 Label isObject(env);
1736 Label isDouble(env);
1737 BRANCH(TaggedIsObject(value), &isObject, &isDouble);
1738 Bind(&isDouble);
1739 {
1740 result = Int32(Elements::ToUint(ElementsKind::NUMBER));
1741 Jump(&exit);
1742 }
1743 Bind(&isObject);
1744 {
1745 Label isHeapObject(env);
1746 BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit);
1747 Bind(&isHeapObject);
1748 {
1749 Label isString(env);
1750 Label isNonString(env);
1751 BRANCH(TaggedIsString(glue, value), &isString, &isNonString);
1752 Bind(&isString);
1753 {
1754 result = Int32(Elements::ToUint(ElementsKind::STRING));
1755 Jump(&exit);
1756 }
1757 Bind(&isNonString);
1758 {
1759 result = Int32(Elements::ToUint(ElementsKind::OBJECT));
1760 Jump(&exit);
1761 }
1762 }
1763 }
1764 }
1765 }
1766 Bind(&exit);
1767 auto ret = *result;
1768 env->SubCfgExit();
1769 return ret;
1770 }
1771
Store(VariableType type,GateRef glue,GateRef base,GateRef offset,GateRef value,MemoryAttribute mAttr)1772 void StubBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value,
1773 MemoryAttribute mAttr)
1774 {
1775 if (!env_->IsAsmInterp()) {
1776 env_->GetBuilder()->Store(type, glue, base, offset, value, mAttr);
1777 } else {
1778 auto depend = env_->GetCurrentLabel()->GetDepend();
1779 auto bit = LoadStoreAccessor::ToValue(mAttr);
1780 GateRef result = env_->GetCircuit()->NewGate(
1781 env_->GetCircuit()->Store(bit), MachineType::NOVALUE,
1782 { depend, glue, base, offset, value, value }, type.GetGateType());
1783 env_->GetCurrentLabel()->SetDepend(result);
1784 }
1785 }
1786
SetValueWithAttr(GateRef glue,GateRef obj,GateRef offset,GateRef key,GateRef value,GateRef attr)1787 void StubBuilder::SetValueWithAttr(GateRef glue, GateRef obj, GateRef offset, GateRef key, GateRef value, GateRef attr)
1788 {
1789 auto env = GetEnvironment();
1790 Label entry(env);
1791 env->SubCfgEntry(&entry);
1792
1793 Label exit(env);
1794 Label repChange(env);
1795 GateRef rep = GetRepInPropAttr(attr);
1796 SetValueWithRep(glue, obj, offset, value, rep, &repChange);
1797 Jump(&exit);
1798 Bind(&repChange);
1799 {
1800 attr = SetTaggedRepInPropAttr(attr);
1801 TransitionForRepChange(glue, obj, key, attr);
1802 Store(VariableType::JS_ANY(), glue, obj, offset, value);
1803 Jump(&exit);
1804 }
1805 Bind(&exit);
1806 env->SubCfgExit();
1807 }
1808
SetValueWithRep(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef rep,Label * repChange)1809 void StubBuilder::SetValueWithRep(
1810 GateRef glue, GateRef obj, GateRef offset, GateRef value, GateRef rep, Label *repChange)
1811 {
1812 auto env = GetEnvironment();
1813 Label entry(env);
1814 env->SubCfgEntry(&entry);
1815
1816 Label exit(env);
1817 Label repIsDouble(env);
1818 Label repIsNonDouble(env);
1819 BRANCH(IsDoubleRepInPropAttr(rep), &repIsDouble, &repIsNonDouble);
1820 Bind(&repIsDouble);
1821 {
1822 Label valueIsInt(env);
1823 Label valueIsNotInt(env);
1824 BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsNotInt);
1825 Bind(&valueIsInt);
1826 {
1827 GateRef result = GetDoubleOfTInt(value);
1828 Store(VariableType::FLOAT64(), glue, obj, offset, result);
1829 Jump(&exit);
1830 }
1831 Bind(&valueIsNotInt);
1832 {
1833 Label valueIsObject(env);
1834 Label valueIsDouble(env);
1835 BRANCH(TaggedIsObject(value), &valueIsObject, &valueIsDouble);
1836 Bind(&valueIsDouble);
1837 {
1838 // TaggedDouble to double
1839 GateRef result = GetDoubleOfTDouble(value);
1840 Store(VariableType::FLOAT64(), glue, obj, offset, result);
1841 Jump(&exit);
1842 }
1843 Bind(&valueIsObject);
1844 {
1845 Jump(repChange);
1846 }
1847 }
1848 }
1849 Bind(&repIsNonDouble);
1850 {
1851 Label repIsInt(env);
1852 Label repIsTagged(env);
1853 BRANCH(IsIntRepInPropAttr(rep), &repIsInt, &repIsTagged);
1854 Bind(&repIsInt);
1855 {
1856 Label valueIsInt(env);
1857 Label valueIsNotInt(env);
1858 BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsNotInt);
1859 Bind(&valueIsInt);
1860 {
1861 GateRef result = GetInt32OfTInt(value);
1862 Store(VariableType::INT32(), glue, obj, offset, result);
1863 Jump(&exit);
1864 }
1865 Bind(&valueIsNotInt);
1866 {
1867 Jump(repChange);
1868 }
1869 }
1870 Bind(&repIsTagged);
1871 {
1872 Store(VariableType::JS_ANY(), glue, obj, offset, value);
1873 Jump(&exit);
1874 }
1875 }
1876
1877 Bind(&exit);
1878 env->SubCfgExit();
1879 return;
1880 }
1881
VerifyBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value)1882 void StubBuilder::VerifyBarrier(GateRef glue, GateRef obj, [[maybe_unused]] GateRef offset, GateRef value)
1883 {
1884 auto env = GetEnvironment();
1885 Label entry(env);
1886 env->SubCfgEntry(&entry);
1887 Label exit(env);
1888 Label checkNext(env);
1889 BRANCH_UNLIKELY(LoadPrimitive(
1890 VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
1891 &exit, &checkNext);
1892 Bind(&checkNext);
1893 // ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj.
1894 GateRef objectRegion = ObjectAddressToRange(obj);
1895 GateRef valueRegion = ObjectAddressToRange(value);
1896 Label fatal(env);
1897 Label noFatal(env);
1898 int msgId = GET_MESSAGE_STRING_ID(SharedObjectRefersLocalObject);
1899 BRANCH(BitAnd(InSharedHeap(objectRegion), BoolNot(InSharedHeap(valueRegion))), &fatal, &exit);
1900 Bind(&fatal);
1901 {
1902 FatalPrint(glue, {Int32(msgId)});
1903 Jump(&exit);
1904 }
1905 Bind(&exit);
1906 env->SubCfgExit();
1907 }
1908
GetCMCRegionRSet(GateRef obj)1909 GateRef StubBuilder::GetCMCRegionRSet(GateRef obj)
1910 {
1911 GateRef metaDataAddr = IntPtrAnd(TaggedCastToIntPtr(obj),
1912 IntPtr(~static_cast<uint64_t>(common::RegionDesc::DEFAULT_REGION_UNIT_MASK)));
1913 GateRef regionRSet = LoadPrimitive(VariableType::NATIVE_POINTER(), metaDataAddr,
1914 IntPtr(common::RegionDesc::REGION_RSET_IN_INLINED_METADATA_OFFSET));
1915 return regionRSet;
1916 }
1917
GetCMCRegionType(GateRef obj)1918 GateRef StubBuilder::GetCMCRegionType(GateRef obj)
1919 {
1920
1921 GateRef metaDataAddr = IntPtrAnd(TaggedCastToIntPtr(obj), IntPtr(~common::RegionDesc::DEFAULT_REGION_UNIT_MASK));
1922 GateRef regionDescAddr = LoadPrimitive(VariableType::INT8(), metaDataAddr,
1923 IntPtr(common::RegionDesc::REGION_TYPE_IN_INLINED_METADATA_OFFSET));
1924 return regionDescAddr;
1925 }
1926
CMCIsInYoungSpace(GateRef regionType)1927 GateRef StubBuilder::CMCIsInYoungSpace(GateRef regionType)
1928 {
1929 auto env = GetEnvironment();
1930 GateRef ret = LogicOrBuilder(env)
1931 .Or(Int8Equal(regionType, Int8(static_cast<int8_t>(common::RegionDesc::RegionType::THREAD_LOCAL_REGION))))
1932 .Or(Int8Equal(regionType, Int8(static_cast<int8_t>(common::RegionDesc::RegionType::RECENT_FULL_REGION))))
1933 .Or(Int8Equal(regionType, Int8(static_cast<int8_t>(common::RegionDesc::RegionType::FROM_REGION))))
1934 .Done();
1935 return ret;
1936 }
1937
IsOldToYoung(GateRef objRegionType,GateRef valueRegionType)1938 GateRef StubBuilder::IsOldToYoung(GateRef objRegionType, GateRef valueRegionType)
1939 {
1940 auto env = GetEnvironment();
1941 GateRef isOldToYoung = LogicAndBuilder(env)
1942 .And(BoolNot(CMCIsInYoungSpace(objRegionType)))
1943 .And(CMCIsInYoungSpace(valueRegionType)).Done();
1944 return isOldToYoung;
1945 }
1946
GetGCPhase(GateRef glue)1947 GateRef StubBuilder::GetGCPhase(GateRef glue)
1948 {
1949 GateRef gcPhase = LoadPrimitive(VariableType::INT8(), glue,
1950 Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(false) +
1951 JSThread::CMCGCPhaseBits::START_BIT / BITS_PER_BYTE));
1952 return gcPhase;
1953 }
1954
GetGCReason(GateRef glue)1955 GateRef StubBuilder::GetGCReason(GateRef glue)
1956 {
1957 GateRef gcReason = LoadPrimitive(VariableType::INT32(), glue,
1958 Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(false) +
1959 JSThread::CMCGCReasonBits::START_BIT / BITS_PER_BYTE));
1960 return gcReason;
1961 }
1962
MarkRSetCardTable(GateRef obj,Label * exit)1963 void StubBuilder::MarkRSetCardTable(GateRef obj, Label *exit)
1964 {
1965 auto env = GetEnvironment();
1966 Label markBit(env);
1967 GateRef regionBase = IntPtrAnd(TaggedCastToIntPtr(obj),
1968 IntPtr(~static_cast<uint64_t>(common::RegionDesc::DEFAULT_REGION_UNIT_MASK)));
1969 GateRef objOffset = PtrSub(TaggedCastToIntPtr(obj), regionBase);
1970 GateRef rset = GetCMCRegionRSet(obj);
1971 GateRef cardIdx = IntPtrDiv(IntPtrDiv(objOffset, IntPtr(common::kMarkedBytesPerBit)),
1972 IntPtr(common::kBitsPerWord));
1973 GateRef headMaskBitStart = IntPtrMod(IntPtrDiv(objOffset, IntPtr(common::kMarkedBytesPerBit)),
1974 IntPtr(common::kBitsPerWord));
1975 GateRef headMaskBits = Int64LSL(Int64(1), headMaskBitStart);
1976 GateRef cardOffset = PtrMul(cardIdx, IntPtr(common::kBytesPerWord));
1977 GateRef cardTable = PtrAdd(rset, IntPtr(common::RegionRSet::CARD_TABLE_DATA_OFFSET));
1978 GateRef card = LoadPrimitive(VariableType::INT64(), cardTable, cardOffset);
1979 GateRef isMarked = Int64NotEqual(Int64And(card, headMaskBits), Int64(0));
1980 BRANCH_NO_WEIGHT(isMarked, exit, &markBit);
1981 Bind(&markBit);
1982 {
1983 Int64FetchOr(PtrAdd(cardTable, cardOffset), headMaskBits, MemoryAttribute::Default());
1984 Jump(exit);
1985 }
1986 }
1987
ShouldGetGCReason(GateRef gcPhase)1988 GateRef StubBuilder::ShouldGetGCReason(GateRef gcPhase)
1989 {
1990 auto env = GetEnvironment();
1991 GateRef shouldGetGCReason = LogicOrBuilder(env)
1992 .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_ENUM)))
1993 .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_MARK)))
1994 .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_POST_MARK)))
1995 .Done();
1996 return shouldGetGCReason;
1997 }
1998
ShouldProcessSATB(GateRef gcPhase)1999 GateRef StubBuilder::ShouldProcessSATB(GateRef gcPhase)
2000 {
2001 auto env = GetEnvironment();
2002 GateRef shouldProcessSATB = LogicOrBuilder(env)
2003 .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_ENUM)))
2004 .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_MARK)))
2005 .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_FINAL_MARK)))
2006 .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_REMARK_SATB)))
2007 .Done();
2008 return shouldProcessSATB;
2009 }
2010
ShouldUpdateRememberSet(GateRef glue,GateRef gcPhase)2011 GateRef StubBuilder::ShouldUpdateRememberSet(GateRef glue, GateRef gcPhase)
2012 {
2013 auto env = GetEnvironment();
2014 Label entry(env);
2015 env->SubCfgEntry(&entry);
2016 Label checkOldToYoung(env);
2017 Label exit(env);
2018 Label notMarkRSet(env);
2019 Label notIdlePhase(env);
2020 DEFVARIABLE(result, VariableType::BOOL(), True());
2021 BRANCH(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_IDLE)), &exit, ¬IdlePhase);
2022 Bind(¬IdlePhase);
2023 GateRef gcReason = GetGCReason(glue);
2024 Label reasonNotYoung(env);
2025 BRANCH(Int32Equal(gcReason, Int32(common::GCReason::GC_REASON_YOUNG)), &exit, &reasonNotYoung);
2026 Bind(&reasonNotYoung);
2027 GateRef shouldGetGCReason = ShouldGetGCReason(gcPhase);
2028 BRANCH(BoolNot(shouldGetGCReason), &exit, ¬MarkRSet);
2029 Bind(¬MarkRSet);
2030 result = False();
2031 Jump(&exit);
2032 Bind(&exit);
2033 auto ret = *result;
2034 env->SubCfgExit();
2035 return ret;
2036 }
2037
CMCSetValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value)2038 void StubBuilder::CMCSetValueWithBarrier(GateRef glue, GateRef obj, [[maybe_unused]]GateRef offset, GateRef value)
2039 {
2040 auto env = GetEnvironment();
2041 Label entry(env);
2042 env->SubCfgEntry(&entry);
2043 Label exit(env);
2044 Label checkOldToYoung(env);
2045 Label markRSet(env);
2046 Label notMarkRSet(env);
2047 GateRef gcPhase = GetGCPhase(glue);
2048 BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, ¬MarkRSet);
2049 Bind(&checkOldToYoung);
2050 {
2051 GateRef objRegionType = GetCMCRegionType(obj);
2052 GateRef valueRegionType = GetCMCRegionType(value);
2053 GateRef isOldToYoung = IsOldToYoung(objRegionType, valueRegionType);
2054 BRANCH_UNLIKELY(isOldToYoung, &markRSet, ¬MarkRSet);
2055 Bind(&markRSet);
2056 MarkRSetCardTable(obj, ¬MarkRSet);
2057 }
2058 Bind(¬MarkRSet);
2059 Label markInBuffer(env);
2060 GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase);
2061 BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit);
2062 Bind(&markInBuffer);
2063 {
2064 CallNGCRuntime(glue, RTSTUB_ID(MarkInBuffer), {value});
2065 Jump(&exit);
2066 }
2067 Bind(&exit);
2068 env->SubCfgExit();
2069 }
2070
CMCArrayCopyWriteBarrier(GateRef glue,GateRef dstObj,GateRef src,GateRef dst,GateRef count)2071 void StubBuilder::CMCArrayCopyWriteBarrier(GateRef glue, GateRef dstObj, GateRef src, GateRef dst, GateRef count)
2072 {
2073 auto env = GetEnvironment();
2074 Label entry(env);
2075 env->SubCfgEntry(&entry);
2076 Label exit(env);
2077 Label iLessLength(env);
2078 Label isTaggedObject(env);
2079 Label loopHead(env);
2080 Label loopEnd(env);
2081 Label markRSet(env);
2082 Label notMarkRSet(env);
2083 GateRef objRegionType = GetCMCRegionType(dstObj);
2084 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2085 GateRef gcPhase = GetGCPhase(glue);
2086 Label checkOldToYoung(env);
2087 BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, ¬MarkRSet);
2088 Bind(&checkOldToYoung);
2089 Jump(&loopHead);
2090 LoopBegin(&loopHead);
2091 {
2092 BRANCH(Int32UnsignedLessThan(*i, count), &iLessLength, ¬MarkRSet);
2093 Bind(&iLessLength);
2094 GateRef offset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(JSTaggedValue::TaggedTypeSize()));
2095 GateRef ref = LoadPrimitive(VariableType::JS_ANY(), src, offset);
2096 BRANCH(TaggedIsHeapObject(ref), &isTaggedObject, &loopEnd);
2097 Bind(&isTaggedObject);
2098 GateRef isOldToYoung = IsOldToYoung(objRegionType, GetCMCRegionType(ref));
2099 BRANCH_UNLIKELY(isOldToYoung, &markRSet, &loopEnd);
2100 Bind(&markRSet);
2101 MarkRSetCardTable(dstObj, ¬MarkRSet);
2102 Bind(&loopEnd);
2103 i = Int32Add(*i, Int32(1));
2104 LoopEnd(&loopHead);
2105 }
2106 Bind(¬MarkRSet);
2107 Label markInBuffer(env);
2108 GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase);
2109 BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit);
2110 Bind(&markInBuffer);
2111 CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {TaggedCastToIntPtr(src), count});
2112 Jump(&exit);
2113 Bind(&exit);
2114 env->SubCfgExit();
2115 }
2116
CMCArrayCopyWriteBarrierSameArray(GateRef glue,GateRef dstObj,GateRef src,GateRef dst,GateRef count)2117 void StubBuilder::CMCArrayCopyWriteBarrierSameArray(GateRef glue, GateRef dstObj, GateRef src, GateRef dst, GateRef count)
2118 {
2119 auto env = GetEnvironment();
2120 Label entry(env);
2121 env->SubCfgEntry(&entry);
2122 Label exit(env);
2123 Label iLessLength(env);
2124 Label isTaggedObject(env);
2125 Label loopHead(env);
2126 Label loopEnd(env);
2127 Label markRSet(env);
2128 Label notMarkRSet(env);
2129 Label notIdlePhase(env);
2130 GateRef objRegionType = GetCMCRegionType(dstObj);
2131 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2132 GateRef gcPhase = GetGCPhase(glue);
2133 BRANCH(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_IDLE)), &exit, ¬IdlePhase);
2134 Bind(¬IdlePhase);
2135 {
2136 Label checkOldToYoung(env);
2137 BRANCH(ShouldUpdateRememberSet(glue, gcPhase), &checkOldToYoung, ¬MarkRSet);
2138 Bind(&checkOldToYoung);
2139 Jump(&loopHead);
2140 LoopBegin(&loopHead);
2141 {
2142 BRANCH(Int32UnsignedLessThan(*i, count), &iLessLength, ¬MarkRSet);
2143 Bind(&iLessLength);
2144 GateRef offset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(JSTaggedValue::TaggedTypeSize()));
2145 GateRef ref = LoadPrimitive(VariableType::JS_ANY(), src, offset);
2146 BRANCH(TaggedIsHeapObject(ref), &isTaggedObject, &loopEnd);
2147 Bind(&isTaggedObject);
2148 GateRef isOldToYoung = IsOldToYoung(objRegionType, GetCMCRegionType(ref));
2149 BRANCH_UNLIKELY(isOldToYoung, &markRSet, &loopEnd);
2150 Bind(&markRSet);
2151 MarkRSetCardTable(dstObj, ¬MarkRSet);
2152 Bind(&loopEnd);
2153 i = Int32Add(*i, Int32(1));
2154 LoopEnd(&loopHead);
2155 }
2156 Bind(¬MarkRSet);
2157 Label markInBuffer(env);
2158 GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase);
2159 BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit);
2160 Bind(&markInBuffer);
2161 CallNGCRuntime(glue, RTSTUB_ID(BatchMarkInBuffer), {TaggedCastToIntPtr(src), count});
2162 Jump(&exit);
2163 }
2164 Bind(&exit);
2165 env->SubCfgExit();
2166 }
2167
SetValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,MemoryAttribute::ShareFlag share)2168 void StubBuilder::SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value,
2169 MemoryAttribute::ShareFlag share)
2170 {
2171 auto env = GetEnvironment();
2172 Label entry(env);
2173 env->SubCfgEntry(&entry);
2174 Label exit(env);
2175 Label callRuntime(env);
2176 Label checkNext(env);
2177 BRANCH_LIKELY(LoadPrimitive(
2178 VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
2179 &callRuntime, &checkNext);
2180 Bind(&callRuntime);
2181 {
2182 CMCSetValueWithBarrier(glue, obj, offset, value);
2183 Jump(&exit);
2184 }
2185 Bind(&checkNext);
2186 // ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj.
2187 GateRef objectRegion = ObjectAddressToRange(obj);
2188 GateRef valueRegion = ObjectAddressToRange(value);
2189 #ifndef NDEBUG
2190 Label fatal(env);
2191 Label noFatal(env);
2192 int msgId = GET_MESSAGE_STRING_ID(SharedObjectRefersLocalObject);
2193 if (share == MemoryAttribute::SHARED) {
2194 BRANCH(BoolNot(InSharedHeap(valueRegion)), &fatal, &noFatal);
2195 msgId = GET_MESSAGE_STRING_ID(ValueIsNonSObject);
2196 }
2197 if (share == MemoryAttribute::NON_SHARE) {
2198 BRANCH(InSharedHeap(objectRegion), &fatal, &noFatal);
2199 }
2200 if (share == MemoryAttribute::UNKNOWN) {
2201 BRANCH(BitAnd(InSharedHeap(objectRegion), BoolNot(InSharedHeap(valueRegion))), &fatal, &noFatal);
2202 }
2203 Bind(&fatal);
2204 {
2205 FatalPrint(glue, {Int32(msgId)});
2206 Jump(&exit);
2207 }
2208 Bind(&noFatal);
2209 #endif
2210 switch (share) {
2211 case MemoryAttribute::SHARED: {
2212 SetSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2213 Jump(&exit);
2214 break;
2215 }
2216 case MemoryAttribute::NON_SHARE: {
2217 SetNonSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2218 Jump(&exit);
2219 break;
2220 }
2221 case MemoryAttribute::UNKNOWN: {
2222 Label valueIsShared(env);
2223 Label valueIsNotShared(env);
2224 BRANCH_UNLIKELY(InSharedHeap(valueRegion), &valueIsShared, &valueIsNotShared);
2225 Bind(&valueIsShared);
2226 {
2227 SetSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2228 Jump(&exit);
2229 }
2230 Bind(&valueIsNotShared);
2231 {
2232 SetNonSValueWithBarrier(glue, obj, offset, value, objectRegion, valueRegion);
2233 Jump(&exit);
2234 }
2235 break;
2236 }
2237 default:
2238 UNREACHABLE();
2239 }
2240 Bind(&exit);
2241 env->SubCfgExit();
2242 }
2243
SetSValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef objectRegion,GateRef valueRegion)2244 void StubBuilder::SetSValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, GateRef objectRegion,
2245 GateRef valueRegion)
2246 {
2247 auto env = GetEnvironment();
2248 Label entry(env);
2249 env->SubCfgEntry(&entry);
2250 Label exit(env);
2251
2252 Label needBarrier(env);
2253 GateRef valueRegionInSweepableShare = InSharedSweepableSpace(valueRegion);
2254 BRANCH(valueRegionInSweepableShare, &needBarrier, &exit);
2255 Bind(&needBarrier);
2256 {
2257 Label updateLocalToShareRSet(env);
2258 Label checkBarrierForSharedValue(env);
2259 GateRef objectNotInShare = BoolNot(InSharedHeap(objectRegion));
2260 BRANCH(objectNotInShare, &updateLocalToShareRSet, &checkBarrierForSharedValue);
2261 Bind(&updateLocalToShareRSet);
2262 {
2263 Label callSharedBarrier(env);
2264 Label storeToSharedRSet(env);
2265 GateRef loadOffset = IntPtr(Region::PackedData::GetLocalToShareSetOffset(env_->Is32Bit()));
2266 auto localToShareSet = LoadPrimitive(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
2267 BRANCH(IntPtrEqual(localToShareSet, IntPtr(0)), &callSharedBarrier, &storeToSharedRSet);
2268 Bind(&storeToSharedRSet);
2269 {
2270 GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
2271 // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
2272 GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
2273 GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
2274 GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
2275 GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
2276 // bitOffset >> BIT_PER_WORD_LOG2
2277 GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
2278 GateRef byteIndex = Int32Mul(index, bytePerWord);
2279 // bitset_[index] |= mask;
2280 GateRef bitsetData = PtrAdd(localToShareSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
2281 GateRef oldsetValue = LoadPrimitive(VariableType::INT32(), bitsetData, byteIndex);
2282 GateRef mask = GetBitMask(bitOffset);
2283 GateRef flag = Int32And(oldsetValue, mask);
2284 // Load the bit using relaxed memory order.
2285 // If the bit is set, do nothing (local->shared barrier is done).
2286 Label needSet(env);
2287 BRANCH(Int32NotEqual(flag, Int32(0)), &checkBarrierForSharedValue, &needSet);
2288 Bind(&needSet);
2289 {
2290 GateRef newMapValue = Int32Or(oldsetValue, mask);
2291 Store(VariableType::INT32(), glue, bitsetData, byteIndex, newMapValue);
2292 Jump(&checkBarrierForSharedValue);
2293 }
2294 }
2295 Bind(&callSharedBarrier);
2296 {
2297 CallNGCRuntime(glue, RTSTUB_ID(InsertLocalToShareRSet), { glue, obj, offset });
2298 Jump(&checkBarrierForSharedValue);
2299 }
2300 }
2301 Bind(&checkBarrierForSharedValue);
2302 {
2303 Label sharedMarking(env);
2304 bool isArch32 = GetEnvironment()->Is32Bit();
2305 GateRef stateBitField = LoadPrimitive(VariableType::INT64(), glue,
2306 Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(isArch32)));
2307 GateRef state = Int64And(stateBitField, Int64(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK));
2308 BRANCH(Int64Equal(state, Int64(static_cast<int64_t>(SharedMarkStatus::READY_TO_CONCURRENT_MARK))),
2309 &exit, &sharedMarking);
2310
2311 Bind(&sharedMarking);
2312 CallNGCRuntime(glue, RTSTUB_ID(SharedGCMarkingBarrier), {glue, obj, offset, value});
2313 Jump(&exit);
2314 }
2315 }
2316 Bind(&exit);
2317 env->SubCfgExit();
2318 }
2319
SetNonSValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value,GateRef objectRegion,GateRef valueRegion)2320 void StubBuilder::SetNonSValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value,
2321 GateRef objectRegion, GateRef valueRegion)
2322 {
2323 auto env = GetEnvironment();
2324 Label entry(env);
2325 env->SubCfgEntry(&entry);
2326 Label exit(env);
2327
2328 Label checkMarkStatus(env);
2329 Label isOldToYoung(env);
2330 GateRef objectNotInYoung = BoolNot(InYoungGeneration(objectRegion));
2331 GateRef valueRegionInYoung = InYoungGeneration(valueRegion);
2332 BRANCH_UNLIKELY(BitAnd(objectNotInYoung, valueRegionInYoung), &isOldToYoung, &checkMarkStatus);
2333
2334 Bind(&isOldToYoung);
2335 {
2336 GateRef loadOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env_->Is32Bit()));
2337 auto oldToNewSet = LoadPrimitive(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
2338 Label isNullPtr(env);
2339 Label notNullPtr(env);
2340 BRANCH(IntPtrEuqal(oldToNewSet, IntPtr(0)), &isNullPtr, ¬NullPtr);
2341 Bind(¬NullPtr);
2342 {
2343 GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
2344 // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
2345 GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
2346 GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
2347 GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
2348 GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
2349 // bitOffset >> BIT_PER_WORD_LOG2
2350 GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
2351 GateRef byteIndex = Int32Mul(index, bytePerWord);
2352 // bitset_[index] |= mask;
2353 GateRef bitsetData = PtrAdd(oldToNewSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
2354 GateRef oldsetValue = LoadPrimitive(VariableType::INT32(), bitsetData, byteIndex);
2355 GateRef newmapValue = Int32Or(oldsetValue, GetBitMask(bitOffset));
2356
2357 Store(VariableType::INT32(), glue, bitsetData, byteIndex, newmapValue);
2358 Jump(&checkMarkStatus);
2359 }
2360 Bind(&isNullPtr);
2361 {
2362 CallNGCRuntime(glue, RTSTUB_ID(InsertOldToNewRSet), { glue, obj, offset });
2363 Jump(&checkMarkStatus);
2364 }
2365 }
2366 Bind(&checkMarkStatus);
2367 {
2368 Label marking(env);
2369 bool isArch32 = GetEnvironment()->Is32Bit();
2370 GateRef stateBitField = LoadPrimitive(VariableType::INT64(), glue,
2371 Int64(JSThread::GlueData::GetGCStateBitFieldOffset(isArch32)));
2372 GateRef state = Int64And(stateBitField, Int64(JSThread::CONCURRENT_MARKING_BITFIELD_MASK));
2373 BRANCH_LIKELY(Int64Equal(state, Int64(static_cast<int64_t>(MarkStatus::READY_TO_MARK))), &exit, &marking);
2374
2375 Bind(&marking);
2376 {
2377 // Check fresh region, and directly mark value instead of call runtime.
2378 CallNGCRuntime(glue, RTSTUB_ID(MarkingBarrier), {glue, obj, offset, value});
2379 Jump(&exit);
2380 }
2381 }
2382 Bind(&exit);
2383 env->SubCfgExit();
2384 }
2385
GetValueWithBarrier(GateRef glue,GateRef addr)2386 GateRef StubBuilder::GetValueWithBarrier(GateRef glue, GateRef addr)
2387 {
2388 auto env = GetEnvironment();
2389 Label entry(env);
2390 env->SubCfgEntry(&entry);
2391 Label notHeapObject(env);
2392 Label isHeapObject(env);
2393 Label exit(env);
2394
2395 // TODO: should be atomic
2396 GateRef value = LoadZeroOffsetPrimitive(VariableType::JS_ANY(), addr);
2397
2398 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2399
2400 BRANCH(BoolNot(TaggedIsHeapObject(value)), ¬HeapObject, &isHeapObject);
2401 Bind(¬HeapObject);
2402 {
2403 result = value;
2404 Jump(&exit);
2405 }
2406 Bind(&isHeapObject);
2407 {
2408 Label isHeapAddress(env);
2409 Label notHeapAddress(env);
2410 BRANCH(IsHeapAddress(glue, value), &isHeapAddress, ¬HeapAddress);
2411 Bind(¬HeapAddress);
2412 {
2413 result = value;
2414 Jump(&exit);
2415 }
2416 Bind(&isHeapAddress);
2417 {
2418 result = FastReadBarrier(glue, addr, value);
2419 Jump(&exit);
2420 }
2421 }
2422
2423 Bind(&exit);
2424 auto ret = *result;
2425 env->SubCfgExit();
2426 return ret;
2427 }
2428
FastReadBarrier(GateRef glue,GateRef addr,GateRef value)2429 GateRef StubBuilder::FastReadBarrier(GateRef glue, GateRef addr, GateRef value)
2430 {
2431 auto env = GetEnvironment();
2432 Label entry(env);
2433 env->SubCfgEntry(&entry);
2434 Label exit(env);
2435 DEFVARIABLE(result, VariableType::JS_ANY(), value);
2436
2437 GateRef intValue = ChangeTaggedPointerToInt64(value);
2438 GateRef regionType = GetCMCRegionType(value);
2439 Label isFromeSpace(env);
2440 GateRef fromType = Int8(static_cast<int8_t>(common::RegionDesc::RegionType::FROM_REGION));
2441 Branch(Int8Equal(regionType, fromType), &isFromeSpace, &exit);
2442 Bind(&isFromeSpace);
2443 {
2444 GateRef weakMask = Int64And(intValue, Int64(JSTaggedValue::TAG_WEAK));
2445 GateRef obj = Int64And(intValue, Int64(~JSTaggedValue::TAG_WEAK));
2446
2447 GateRef forwardedAddr = LoadPrimitive(VariableType::INT64(), obj, IntPtr(0));
2448 GateRef forwardState =
2449 Int64LSR(forwardedAddr, Int64(common::BaseStateWord::PADDING_WIDTH + common::BaseStateWord::FORWARD_WIDTH));
2450 Label forwarded(env);
2451 Label notForwarded(env);
2452 Branch(Int64Equal(forwardState, Int64(static_cast<int64_t>(common::BaseStateWord::ForwardState::FORWARDED))),
2453 &forwarded, ¬Forwarded);
2454 Bind(&forwarded);
2455 {
2456 result = Int64ToTaggedPtr(Int64Or(Int64And(forwardedAddr, Int64(TaggedStateWord::ADDRESS_MASK)), weakMask));
2457 Jump(&exit);
2458 }
2459 Bind(¬Forwarded);
2460 {
2461 result = CallNGCRuntime(glue, RTSTUB_ID(ReadBarrier), { glue, addr });
2462 Jump(&exit);
2463 }
2464 }
2465
2466 Bind(&exit);
2467 auto ret = *result;
2468 env->SubCfgExit();
2469 return ret;
2470 }
2471
IsHeapAddress(GateRef glue,GateRef value)2472 GateRef StubBuilder::IsHeapAddress(GateRef glue, GateRef value)
2473 {
2474 bool isArch32 = GetEnvironment()->Is32Bit();
2475 GateRef heapStartAddr = LoadPrimitive(
2476 VariableType::NATIVE_POINTER(), glue, IntPtr(JSThread::GlueData::GetHeapStartAddrOffset(isArch32)));
2477 GateRef heapCurrentEnd = LoadPrimitive(
2478 VariableType::NATIVE_POINTER(), glue, IntPtr(JSThread::GlueData::GetHeapCurrentEndOffset(isArch32)));
2479 auto IntPtrValue = ChangeTaggedPointerToInt64(value);
2480 return BitAnd(IntPtrGreaterThanOrEqual(IntPtrValue, heapStartAddr), IntPtrLessThan(IntPtrValue, heapCurrentEnd));
2481 }
2482
TaggedIsBigInt(GateRef glue,GateRef obj)2483 GateRef StubBuilder::TaggedIsBigInt(GateRef glue, GateRef obj)
2484 {
2485 auto env = GetEnvironment();
2486 Label entry(env);
2487 env->SubCfgEntry(&entry);
2488 Label exit(env);
2489 Label isHeapObject(env);
2490 DEFVARIABLE(result, VariableType::BOOL(), False());
2491 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
2492 Bind(&isHeapObject);
2493 {
2494 result = Int32Equal(GetObjectType(LoadHClass(glue, obj)),
2495 Int32(static_cast<int32_t>(JSType::BIGINT)));
2496 Jump(&exit);
2497 }
2498 Bind(&exit);
2499 auto ret = *result;
2500 env->SubCfgExit();
2501 return ret;
2502 }
2503
TaggedIsPropertyBox(GateRef glue,GateRef obj)2504 GateRef StubBuilder::TaggedIsPropertyBox(GateRef glue, GateRef obj)
2505 {
2506 auto env = GetEnvironment();
2507 Label entry(env);
2508 env->SubCfgEntry(&entry);
2509 Label exit(env);
2510 Label isHeapObject(env);
2511 DEFVARIABLE(result, VariableType::BOOL(), False());
2512 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
2513 Bind(&isHeapObject);
2514 {
2515 GateRef type = GetObjectType(LoadHClass(glue, obj));
2516 result = Int32Equal(type, Int32(static_cast<int32_t>(JSType::PROPERTY_BOX)));
2517 Jump(&exit);
2518 }
2519 Bind(&exit);
2520 auto ret = *result;
2521 env->SubCfgExit();
2522 return ret;
2523 }
2524
TaggedIsAccessor(GateRef glue,GateRef x)2525 GateRef StubBuilder::TaggedIsAccessor(GateRef glue, GateRef x)
2526 {
2527 auto env = GetEnvironment();
2528 Label entry(env);
2529 env->SubCfgEntry(&entry);
2530 Label exit(env);
2531 Label isHeapObject(env);
2532 DEFVARIABLE(result, VariableType::BOOL(), False());
2533 BRANCH(TaggedIsHeapObject(x), &isHeapObject, &exit);
2534 Bind(&isHeapObject);
2535 {
2536 GateRef type = GetObjectType(LoadHClass(glue, x));
2537 result = BitOr(Int32Equal(type, Int32(static_cast<int32_t>(JSType::ACCESSOR_DATA))),
2538 Int32Equal(type, Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR))));
2539 Jump(&exit);
2540 }
2541 Bind(&exit);
2542 auto ret = *result;
2543 env->SubCfgExit();
2544 return ret;
2545 }
2546
TaggedIsInternalAccessor(GateRef glue,GateRef x)2547 GateRef StubBuilder::TaggedIsInternalAccessor(GateRef glue, GateRef x)
2548 {
2549 auto env = GetEnvironment();
2550 Label entry(env);
2551 env->SubCfgEntry(&entry);
2552 Label exit(env);
2553 Label isHeapObject(env);
2554 DEFVARIABLE(result, VariableType::BOOL(), False());
2555 BRANCH(TaggedIsHeapObject(x), &isHeapObject, &exit);
2556 Bind(&isHeapObject);
2557 {
2558 GateRef type = GetObjectType(LoadHClass(glue, x));
2559 result = Int32Equal(type, Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR)));
2560 Jump(&exit);
2561 }
2562 Bind(&exit);
2563 auto ret = *result;
2564 env->SubCfgExit();
2565 return ret;
2566 }
2567
IsUtf16String(GateRef string)2568 GateRef StubBuilder::IsUtf16String(GateRef string)
2569 {
2570 // compressedStringsEnabled fixed to true constant
2571 GateRef len = LoadPrimitive(VariableType::INT32(), string, IntPtr(BaseString::LENGTH_AND_FLAGS_OFFSET));
2572 return Int32Equal(
2573 Int32And(len, Int32((1 << BaseString::CompressedStatusBit::SIZE) - 1)),
2574 Int32(BaseString::STRING_UNCOMPRESSED));
2575 }
2576
IsUtf8String(GateRef string)2577 GateRef StubBuilder::IsUtf8String(GateRef string)
2578 {
2579 // compressedStringsEnabled fixed to true constant
2580 GateRef len = LoadPrimitive(VariableType::INT32(), string, IntPtr(BaseString::LENGTH_AND_FLAGS_OFFSET));
2581 return Int32Equal(
2582 Int32And(len, Int32((1 << BaseString::CompressedStatusBit::SIZE) - 1)),
2583 Int32(BaseString::STRING_COMPRESSED));
2584 }
2585
IsDigit(GateRef ch)2586 GateRef StubBuilder::IsDigit(GateRef ch)
2587 {
2588 return BitAnd(Int32LessThanOrEqual(ch, Int32('9')),
2589 Int32GreaterThanOrEqual(ch, Int32('0')));
2590 }
2591
TryToElementsIndex(GateRef glue,GateRef key)2592 GateRef StubBuilder::TryToElementsIndex(GateRef glue, GateRef key)
2593 {
2594 auto env = GetEnvironment();
2595 Label entry(env);
2596 env->SubCfgEntry(&entry);
2597 Label exit(env);
2598 Label isKeyInt(env);
2599 Label notKeyInt(env);
2600
2601 DEFVARIABLE(resultKey, VariableType::INT64(), Int64(-1));
2602 BRANCH(TaggedIsInt(key), &isKeyInt, ¬KeyInt);
2603 Bind(&isKeyInt);
2604 {
2605 resultKey = GetInt64OfTInt(key);
2606 Jump(&exit);
2607 }
2608 Bind(¬KeyInt);
2609 {
2610 Label isString(env);
2611 Label notString(env);
2612 BRANCH(TaggedIsString(glue, key), &isString, ¬String);
2613 Bind(&isString);
2614 {
2615 BuiltinsStringStubBuilder stringStub(this, GetCurrentGlobalEnv());
2616 resultKey = stringStub.StringToUint(glue, key, JSObject::MAX_ELEMENT_INDEX - 1);
2617 Jump(&exit);
2618 }
2619 Bind(¬String);
2620 {
2621 Label isDouble(env);
2622 BRANCH(TaggedIsDouble(key), &isDouble, &exit);
2623 Bind(&isDouble);
2624 {
2625 GateRef number = GetDoubleOfTDouble(key);
2626 GateRef integer = ChangeFloat64ToInt32(number);
2627 Label isEqual(env);
2628 BRANCH(DoubleEqual(number, ChangeInt32ToFloat64(integer)), &isEqual, &exit);
2629 Bind(&isEqual);
2630 {
2631 resultKey = SExtInt32ToInt64(integer);
2632 Jump(&exit);
2633 }
2634 }
2635 }
2636 }
2637 Bind(&exit);
2638 auto ret = *resultKey;
2639 env->SubCfgExit();
2640 return ret;
2641 }
2642
LdGlobalRecord(GateRef glue,GateRef key)2643 GateRef StubBuilder::LdGlobalRecord(GateRef glue, GateRef key)
2644 {
2645 auto env = GetEnvironment();
2646 Label entry(env);
2647 env->SubCfgEntry(&entry);
2648 Label exit(env);
2649
2650 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2651 GateRef globalEnv = GetCurrentGlobalEnv();
2652 GateRef globalRecord = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::GLOBAL_RECORD);
2653 GateRef recordEntry = FindEntryFromHashTable<NameDictionary>(glue, globalRecord, key);
2654 Label foundInGlobalRecord(env);
2655 BRANCH(Int32NotEqual(recordEntry, Int32(-1)), &foundInGlobalRecord, &exit);
2656 Bind(&foundInGlobalRecord);
2657 {
2658 result = GetBoxFromGlobalDictionary(glue, globalRecord, recordEntry);
2659 Jump(&exit);
2660 }
2661 Bind(&exit);
2662 auto ret = *result;
2663 env->SubCfgExit();
2664 return ret;
2665 }
2666
LoadFromField(GateRef glue,GateRef receiver,GateRef handlerInfo)2667 GateRef StubBuilder::LoadFromField(GateRef glue, GateRef receiver, GateRef handlerInfo)
2668 {
2669 auto env = GetEnvironment();
2670 Label entry(env);
2671 env->SubCfgEntry(&entry);
2672 Label exit(env);
2673 Label handlerInfoIsInlinedProps(env);
2674 Label handlerInfoNotInlinedProps(env);
2675 Label handlerPost(env);
2676 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2677 GateRef index = HandlerBaseGetOffset(handlerInfo);
2678 #if ENABLE_NEXT_OPTIMIZATION
2679 BRANCH_LIKELY(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
2680 #else
2681 BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
2682 #endif
2683 Bind(&handlerInfoIsInlinedProps);
2684 {
2685 result = Load(VariableType::JS_ANY(), glue, receiver, PtrMul(ZExtInt32ToPtr(index),
2686 IntPtr(JSTaggedValue::TaggedTypeSize())));
2687 Jump(&handlerPost);
2688 }
2689 Bind(&handlerInfoNotInlinedProps);
2690 {
2691 result = GetValueFromTaggedArray(glue, GetPropertiesArray(glue, receiver), index);
2692 Jump(&handlerPost);
2693 }
2694 Bind(&handlerPost);
2695 {
2696 Label nonDoubleToTagged(env);
2697 Label doubleToTagged(env);
2698 GateRef rep = HandlerBaseGetRep(handlerInfo);
2699 #if ENABLE_NEXT_OPTIMIZATION
2700 BRANCH_UNLIKELY(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
2701 #else
2702 BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
2703 #endif
2704 Bind(&doubleToTagged);
2705 {
2706 result = TaggedPtrToTaggedDoublePtr(*result);
2707 Jump(&exit);
2708 }
2709 Bind(&nonDoubleToTagged);
2710 {
2711 Label intToTagged(env);
2712 #if ENABLE_NEXT_OPTIMIZATION
2713 BRANCH_UNLIKELY(IsIntRepInPropAttr(rep), &intToTagged, &exit);
2714 #else
2715 BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit);
2716 #endif
2717 Bind(&intToTagged);
2718 {
2719 result = TaggedPtrToTaggedIntPtr(*result);
2720 Jump(&exit);
2721 }
2722 }
2723 }
2724 Bind(&exit);
2725 auto ret = *result;
2726 env->SubCfgExit();
2727 return ret;
2728 }
2729
LoadGlobal(GateRef glue,GateRef cell)2730 GateRef StubBuilder::LoadGlobal(GateRef glue, GateRef cell)
2731 {
2732 auto env = GetEnvironment();
2733 Label entry(env);
2734 env->SubCfgEntry(&entry);
2735 Label exit(env);
2736 Label cellNotInvalid(env);
2737 Label cellNotAccessor(env);
2738 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2739 BRANCH(IsInvalidPropertyBox(glue, cell), &exit, &cellNotInvalid);
2740 Bind(&cellNotInvalid);
2741 {
2742 BRANCH(IsAccessorPropertyBox(glue, cell), &exit, &cellNotAccessor);
2743 Bind(&cellNotAccessor);
2744 {
2745 result = GetValueFromPropertyBox(glue, cell);
2746 Jump(&exit);
2747 }
2748 }
2749 Bind(&exit);
2750 auto ret = *result;
2751 env->SubCfgExit();
2752 return ret;
2753 }
2754
CheckPolyHClass(GateRef glue,GateRef cachedValue,GateRef hclass)2755 GateRef StubBuilder::CheckPolyHClass(GateRef glue, GateRef cachedValue, GateRef hclass)
2756 {
2757 auto env = GetEnvironment();
2758 Label entry(env);
2759 env->SubCfgEntry(&entry);
2760 Label exit(env);
2761 Label loopHead(env);
2762 Label loopEnd(env);
2763 Label iLessLength(env);
2764 Label hasHclass(env);
2765 Label cachedValueNotWeak(env);
2766 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2767 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2768 BRANCH(TaggedIsWeak(cachedValue), &exit, &cachedValueNotWeak);
2769 Bind(&cachedValueNotWeak);
2770 {
2771 Label isTaggedArray(env);
2772 Branch(IsTaggedArray(glue, cachedValue), &isTaggedArray, &exit);
2773 Bind(&isTaggedArray);
2774 {
2775 GateRef length = GetLengthOfTaggedArray(cachedValue);
2776 Jump(&loopHead);
2777 LoopBegin(&loopHead);
2778 {
2779 BRANCH(Int32UnsignedLessThan(*i, length), &iLessLength, &exit);
2780 Bind(&iLessLength);
2781 {
2782 GateRef element = GetValueFromTaggedArray(glue, cachedValue, *i);
2783 BRANCH(Equal(LoadObjectFromWeakRef(element), hclass), &hasHclass, &loopEnd);
2784 Bind(&hasHclass);
2785 result = GetValueFromTaggedArray(glue, cachedValue, Int32Add(*i, Int32(1)));
2786 Jump(&exit);
2787 }
2788 Bind(&loopEnd);
2789 i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot
2790 LoopEnd(&loopHead);
2791 }
2792 }
2793 }
2794 Bind(&exit);
2795 auto ret = *result;
2796 env->SubCfgExit();
2797 return ret;
2798 }
2799
LoadICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef argHandler,ProfileOperation callback)2800 GateRef StubBuilder::LoadICWithHandler(
2801 GateRef glue, GateRef receiver, GateRef argHolder, GateRef argHandler, ProfileOperation callback)
2802 {
2803 auto env = GetEnvironment();
2804 Label entry(env);
2805 env->SubCfgEntry(&entry);
2806 Label exit(env);
2807 Label handlerIsInt(env);
2808 Label handlerNotInt(env);
2809 Label handleInfoIsFound(env);
2810 Label handleInfoIsNotFound(env);
2811 Label handlerInfoIsField(env);
2812 Label handlerInfoNotField(env);
2813 Label handlerInfoIsNonExist(env);
2814 Label handlerInfoExist(env);
2815 Label handlerInfoIsPrimitive(env);
2816 Label handlerInfoNotPrimitive(env);
2817 Label handlerInfoNotStringOrNumber(env);
2818 Label handlerInfoIsStringLength(env);
2819 Label handlerInfoNotStringLength(env);
2820 Label handlerIsPrototypeHandler(env);
2821 Label handlerNotPrototypeHandler(env);
2822 Label cellHasChanged(env);
2823 Label cellNotFoundHasChanged(env);
2824 Label cellNotFoundNotChanged(env);
2825 Label cellNotUndefined(env);
2826 Label loopHead(env);
2827 Label loopEnd(env);
2828 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2829 DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
2830 DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
2831
2832 Jump(&loopHead);
2833 LoopBegin(&loopHead);
2834 {
2835 BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
2836 Bind(&handlerIsInt);
2837 {
2838 GateRef handlerInfo = GetInt64OfTInt(*handler);
2839 #if ENABLE_NEXT_OPTIMIZATION
2840 BRANCH_LIKELY(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2841 #else
2842 BRANCH(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2843 #endif
2844 Bind(&handlerInfoIsField);
2845 {
2846 result = LoadFromField(glue, *holder, handlerInfo);
2847 Jump(&exit);
2848 }
2849 Bind(&handlerInfoNotField);
2850 {
2851 BRANCH(BitOr(IsStringElement(handlerInfo), IsNumberHandler(handlerInfo)),
2852 &handlerInfoIsPrimitive, &handlerInfoNotStringOrNumber);
2853 Bind(&handlerInfoNotStringOrNumber);
2854 {
2855 BRANCH(IsBooleanHandler(handlerInfo), &handlerInfoIsPrimitive, &handlerInfoNotPrimitive);
2856 }
2857 Bind(&handlerInfoIsPrimitive);
2858 {
2859 result = LoadFromField(glue, *holder, handlerInfo);
2860 Jump(&exit);
2861 }
2862 Bind(&handlerInfoNotPrimitive);
2863 {
2864 BRANCH(IsNonExist(handlerInfo), &handlerInfoIsNonExist, &handlerInfoExist);
2865 // For the special "Not Found" case we may generate ic by "LoadHandler::LoadProperty".
2866 // In this situation, you can trust ic without ChangeMarker.
2867 Bind(&handlerInfoIsNonExist);
2868 {
2869 result = Undefined();
2870 Jump(&exit);
2871 }
2872 Bind(&handlerInfoExist);
2873 {
2874 BRANCH(IsStringLength(handlerInfo), &handlerInfoIsStringLength, &handlerInfoNotStringLength);
2875 Bind(&handlerInfoNotStringLength);
2876 {
2877 GateRef accessor = LoadFromField(glue, *holder, handlerInfo);
2878 // The getter may involve nested calls, so it is better to end (or return) early.
2879 EndTraceLoad(glue);
2880 result = CallGetterHelper(glue, receiver, *holder, accessor, callback);
2881 StartTraceLoadGetter(glue);
2882 Jump(&exit);
2883 }
2884 Bind(&handlerInfoIsStringLength);
2885 {
2886 result = IntToTaggedPtr(GetLengthFromString(receiver));
2887 Jump(&exit);
2888 }
2889 }
2890 }
2891 }
2892 }
2893 Bind(&handlerNotInt);
2894 BRANCH_LIKELY(TaggedIsPrototypeHandler(glue, *handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
2895 Bind(&handlerIsPrototypeHandler);
2896 {
2897 GateRef cellValue = GetPrototypeHandlerProtoCell(glue, *handler);
2898 BRANCH_UNLIKELY(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
2899 Bind(&cellNotUndefined);
2900 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2901 Bind(&cellHasChanged);
2902 {
2903 result = Hole();
2904 Jump(&exit);
2905 }
2906 Bind(&loopEnd);
2907 holder = GetPrototypeHandlerHolder(glue, *handler);
2908 BRANCH(Equal(*holder, Undefined()), &handleInfoIsNotFound, &handleInfoIsFound);
2909 Bind(&handleInfoIsFound);
2910 {
2911 handler = GetPrototypeHandlerHandlerInfo(glue, *handler);
2912 LoopEndWithCheckSafePoint(&loopHead, env, glue);
2913 }
2914
2915 // For "Not Found" case (holder equals Undefined()),
2916 // we should ensure that both GetNotFoundHasChanged() and GetHasChanged() return false.
2917 Bind(&handleInfoIsNotFound);
2918 {
2919 BRANCH(GetNotFoundHasChanged(cellValue), &cellNotFoundHasChanged, &cellNotFoundNotChanged);
2920 Bind(&cellNotFoundHasChanged);
2921 {
2922 result = Hole();
2923 Jump(&exit);
2924 }
2925 Bind(&cellNotFoundNotChanged);
2926 {
2927 result = Undefined();
2928 Jump(&exit);
2929 }
2930 }
2931 }
2932 }
2933 Bind(&handlerNotPrototypeHandler);
2934 {
2935 result = LoadGlobal(glue, *handler);
2936 Jump(&exit);
2937 }
2938 Bind(&exit);
2939 auto ret = *result;
2940 env->SubCfgExit();
2941 return ret;
2942 }
2943
LoadElement(GateRef glue,GateRef receiver,GateRef key)2944 GateRef StubBuilder::LoadElement(GateRef glue, GateRef receiver, GateRef key)
2945 {
2946 auto env = GetEnvironment();
2947 Label entry(env);
2948 env->SubCfgEntry(&entry);
2949 Label exit(env);
2950 Label indexLessZero(env);
2951 Label indexNotLessZero(env);
2952 Label lengthLessIndex(env);
2953 Label lengthNotLessIndex(env);
2954 Label greaterThanInt32Max(env);
2955 Label notGreaterThanInt32Max(env);
2956 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2957 GateRef index64 = TryToElementsIndex(glue, key);
2958 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
2959 Bind(&greaterThanInt32Max);
2960 {
2961 Jump(&exit);
2962 }
2963 Bind(¬GreaterThanInt32Max);
2964 GateRef index = TruncInt64ToInt32(index64);
2965 BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2966 Bind(&indexLessZero);
2967 {
2968 Jump(&exit);
2969 }
2970 Bind(&indexNotLessZero);
2971 {
2972 GateRef elements = GetElementsArray(glue, receiver);
2973 BRANCH(Int32LessThanOrEqual(GetLengthOfTaggedArray(elements), index), &lengthLessIndex, &lengthNotLessIndex);
2974 Bind(&lengthLessIndex);
2975 Jump(&exit);
2976 Bind(&lengthNotLessIndex);
2977 result = GetTaggedValueWithElementsKind(glue, receiver, index);
2978 Jump(&exit);
2979 }
2980 Bind(&exit);
2981 auto ret = *result;
2982 env->SubCfgExit();
2983 return ret;
2984 }
2985
LoadStringElement(GateRef glue,GateRef receiver,GateRef key)2986 GateRef StubBuilder::LoadStringElement(GateRef glue, GateRef receiver, GateRef key)
2987 {
2988 auto env = GetEnvironment();
2989 Label entry(env);
2990 env->SubCfgEntry(&entry);
2991 Label exit(env);
2992 Label indexLessZero(env);
2993 Label indexNotLessZero(env);
2994 Label lengthLessIndex(env);
2995 Label lengthNotLessIndex(env);
2996 Label greaterThanInt32Max(env);
2997 Label notGreaterThanInt32Max(env);
2998 Label flattenFastPath(env);
2999
3000 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3001 GateRef index64 = TryToElementsIndex(glue, key);
3002 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
3003 Bind(&greaterThanInt32Max);
3004 {
3005 Jump(&exit);
3006 }
3007 Bind(¬GreaterThanInt32Max);
3008 GateRef index = TruncInt64ToInt32(index64);
3009 BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
3010 Bind(&indexLessZero);
3011 {
3012 Jump(&exit);
3013 }
3014 Bind(&indexNotLessZero);
3015 {
3016 FlatStringStubBuilder thisFlat(this);
3017 thisFlat.FlattenString(glue, receiver, &flattenFastPath);
3018 Bind(&flattenFastPath);
3019 BRANCH(Int32LessThanOrEqual(GetLengthFromString(receiver), index), &lengthLessIndex, &lengthNotLessIndex);
3020 Bind(&lengthLessIndex);
3021 Jump(&exit);
3022 Bind(&lengthNotLessIndex);
3023 BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
3024 StringInfoGateRef stringInfoGate(&thisFlat);
3025 result = stringBuilder.CreateFromEcmaString(glue, index, stringInfoGate);
3026 Jump(&exit);
3027 }
3028 Bind(&exit);
3029 auto ret = *result;
3030 env->SubCfgExit();
3031 return ret;
3032 }
3033
TaggedArraySetValue(GateRef glue,GateRef receiver,GateRef value,GateRef index,GateRef capacity)3034 GateRef StubBuilder::TaggedArraySetValue(GateRef glue, GateRef receiver, GateRef value, GateRef index, GateRef capacity)
3035 {
3036 auto env = GetEnvironment();
3037 Label entryPass(env);
3038 env->SubCfgEntry(&entryPass);
3039 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3040 Label indexGreaterLen(env);
3041 Label storeElement(env);
3042 Label isTransToDict(env);
3043 Label notTransToDict(env);
3044 Label exit(env);
3045 BRANCH(Int32UnsignedGreaterThanOrEqual(index, capacity), &indexGreaterLen, &storeElement);
3046 Bind(&indexGreaterLen);
3047 {
3048 BRANCH(ShouldTransToDict(capacity, index), &isTransToDict, ¬TransToDict);
3049 Bind(&isTransToDict);
3050 result = Hole();
3051 Jump(&exit);
3052 Bind(¬TransToDict);
3053 GrowElementsCapacity(glue, receiver, Int32Add(index, Int32(1)));
3054 Jump(&storeElement);
3055 }
3056 Bind(&storeElement);
3057 {
3058 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true),
3059 Int32(Elements::ToUint(ElementsKind::NONE)));
3060 result = Undefined();
3061 Jump(&exit);
3062 }
3063 Bind(&exit);
3064 auto ret = *result;
3065 env->SubCfgExit();
3066 return ret;
3067 }
3068
ICStoreElement(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef handler,bool updateHandler,GateRef profileTypeInfo,GateRef slotId)3069 GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef handler,
3070 bool updateHandler, GateRef profileTypeInfo, GateRef slotId)
3071 {
3072 auto env = GetEnvironment();
3073 Label entry(env);
3074 env->SubCfgEntry(&entry);
3075 Label exit(env);
3076 Label indexLessZero(env);
3077 Label indexNotLessZero(env);
3078 Label handlerInfoIsTypedArray(env);
3079 Label handerInfoNotTypedArray(env);
3080 Label handerInfoIsJSArray(env);
3081 Label handerInfoNotJSArray(env);
3082 Label isJsCOWArray(env);
3083 Label isNotJsCOWArray(env);
3084 Label setElementsLength(env);
3085 Label indexGreaterLength(env);
3086 Label indexGreaterCapacity(env);
3087 Label storeElement(env);
3088 Label handlerIsInt(env);
3089 Label handlerNotInt(env);
3090 Label loopHead(env);
3091 Label loopEnd(env);
3092 Label greaterThanInt32Max(env);
3093 Label notGreaterThanInt32Max(env);
3094 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3095 DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler);
3096 GateRef index64 = TryToElementsIndex(glue, key);
3097 BRANCH_UNLIKELY(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
3098 Bind(&greaterThanInt32Max);
3099 {
3100 Jump(&exit);
3101 }
3102 Bind(¬GreaterThanInt32Max);
3103 GateRef index = TruncInt64ToInt32(index64);
3104 BRANCH_UNLIKELY(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
3105 Bind(&indexLessZero);
3106 {
3107 Jump(&exit);
3108 }
3109 Bind(&indexNotLessZero);
3110 {
3111 DEFVARIABLE(isOnPrototype, VariableType::BOOL(), False());
3112 Jump(&loopHead);
3113 LoopBegin(&loopHead);
3114 BRANCH(TaggedIsInt(*varHandler), &handlerIsInt, &handlerNotInt);
3115 Bind(&handlerIsInt);
3116 {
3117 GateRef handlerInfo = GetInt64OfTInt(*varHandler);
3118 BRANCH(IsTypedArrayElement(handlerInfo), &handlerInfoIsTypedArray, &handerInfoNotTypedArray);
3119 Bind(&handlerInfoIsTypedArray);
3120 {
3121 GateRef hclass = LoadHClass(glue, receiver);
3122 GateRef jsType = GetObjectType(hclass);
3123 BuiltinsTypedArrayStubBuilder typedArrayBuilder(this, GetCurrentGlobalEnv());
3124 result = typedArrayBuilder.StoreTypedArrayElement(glue, receiver, index64, value, jsType);
3125 Jump(&exit);
3126 }
3127 Bind(&handerInfoNotTypedArray);
3128 BRANCH(HandlerBaseIsJSArray(handlerInfo), &handerInfoIsJSArray, &handerInfoNotJSArray);
3129 Bind(&handerInfoIsJSArray);
3130 {
3131 BRANCH(IsJsCOWArray(glue, receiver), &isJsCOWArray, &isNotJsCOWArray);
3132 Bind(&isJsCOWArray);
3133 {
3134 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {receiver});
3135 Jump(&setElementsLength);
3136 }
3137 Bind(&isNotJsCOWArray);
3138 {
3139 Jump(&setElementsLength);
3140 }
3141 Bind(&setElementsLength);
3142 {
3143 GateRef oldLength = GetArrayLength(receiver);
3144 BRANCH(Int32UnsignedGreaterThanOrEqual(index, oldLength), &indexGreaterLength, &handerInfoNotJSArray);
3145 Bind(&indexGreaterLength);
3146 Store(VariableType::INT32(), glue, receiver,
3147 IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET),
3148 Int32Add(index, Int32(1)));
3149 if (updateHandler) {
3150 Label update(env);
3151 Label setObject(env);
3152 Label setPrototype(env);
3153 GateRef oldHandler = GetValueFromTaggedArray(glue, profileTypeInfo, slotId);
3154 BRANCH(Equal(oldHandler, Hole()), &handerInfoNotJSArray, &update);
3155 Bind(&update);
3156 {
3157 handler = Int64ToTaggedInt(UpdateSOutOfBoundsForHandler(handlerInfo));
3158 BRANCH(Equal(*isOnPrototype, False()), &setObject, &setPrototype);
3159 Bind(&setObject);
3160 {
3161 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, handler);
3162 Jump(&handerInfoNotJSArray);
3163 }
3164 Bind(&setPrototype);
3165 {
3166 SetPrototypeHandlerHandlerInfo(glue, oldHandler, handler);
3167 }
3168 }
3169 }
3170 }
3171 Jump(&handerInfoNotJSArray);
3172 }
3173 Bind(&handerInfoNotJSArray);
3174 {
3175 GateRef elements = GetElementsArray(glue, receiver);
3176 GateRef capacity = GetLengthOfTaggedArray(elements);
3177 BRANCH(Int32UnsignedGreaterThanOrEqual(index, capacity), &indexGreaterCapacity, &storeElement);
3178 Bind(&indexGreaterCapacity);
3179 {
3180 result = TaggedArraySetValue(glue, receiver, value, index, capacity);
3181 Label transition(env);
3182 BRANCH(TaggedIsHole(*result), &exit, &transition);
3183 Bind(&transition);
3184 {
3185 Label hole(env);
3186 DEFVARIABLE(kind, VariableType::INT32(), Int32(Elements::ToUint(ElementsKind::NONE)));
3187 BRANCH(Int32UnsignedGreaterThan(index, capacity), &hole, &exit);
3188 Bind(&hole);
3189 {
3190 kind = Int32(Elements::ToUint(ElementsKind::HOLE));
3191 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
3192 Jump(&exit);
3193 }
3194 }
3195 }
3196 Bind(&storeElement);
3197 {
3198 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true),
3199 Int32(Elements::ToUint(ElementsKind::NONE)));
3200 result = Undefined();
3201 Jump(&exit);
3202 }
3203 }
3204 }
3205 Bind(&handlerNotInt);
3206 {
3207 Label handlerIsPrototypeHandler(env);
3208 Label handlerNotPrototypeHandler(env);
3209 Label handlerIsTransWithProtoHandler(env);
3210 Label handlerIsTransitionHandler(env);
3211
3212 BRANCH(TaggedIsPrototypeHandler(glue, *varHandler), &handlerIsPrototypeHandler,
3213 &handlerNotPrototypeHandler);
3214 Bind(&handlerIsPrototypeHandler);
3215 {
3216 // If the handler is a prototypehandler, we need to check protochangemarker.
3217 Label cellNotNullOrUndefined(env);
3218 Label getPrototypeHandlerHandlerInfo(env);
3219 GateRef cellValue = GetPrototypeHandlerProtoCell(glue, *varHandler);
3220 BRANCH(TaggedIsUndefinedOrNull(cellValue), &exit, &cellNotNullOrUndefined);
3221
3222 Bind(&cellNotNullOrUndefined);
3223 BRANCH(GetHasChanged(cellValue), &exit, &getPrototypeHandlerHandlerInfo);
3224 Bind(&getPrototypeHandlerHandlerInfo);
3225 {
3226 isOnPrototype = True();
3227 varHandler = GetPrototypeHandlerHandlerInfo(glue, *varHandler);
3228 Jump(&loopEnd);
3229 }
3230 }
3231
3232 Bind(&handlerNotPrototypeHandler);
3233 {
3234 BRANCH(TaggedIsTransWithProtoHandler(glue, *varHandler), &handlerIsTransWithProtoHandler,
3235 &handlerIsTransitionHandler);
3236 Bind(&handlerIsTransWithProtoHandler);
3237 {
3238 // If the handler is a transwithprotohandler, we need to check protochangemarker.
3239 Label cellNotNullOrUndefined(env);
3240 Label getTransWithProtoHandlerInfo(env);
3241 GateRef cellValue = GetTransWithProtoHandlerProtoCell(glue, *varHandler);
3242 BRANCH(TaggedIsUndefinedOrNull(cellValue), &exit, &cellNotNullOrUndefined);
3243
3244 Bind(&cellNotNullOrUndefined);
3245 BRANCH(GetHasChanged(cellValue), &exit, &getTransWithProtoHandlerInfo);
3246 Bind(&getTransWithProtoHandlerInfo);
3247 {
3248 isOnPrototype = True();
3249 varHandler = GetTransWithProtoHandlerInfo(glue, *varHandler);
3250 Jump(&loopEnd);
3251 }
3252 }
3253 Bind(&handlerIsTransitionHandler);
3254 {
3255 // If the handler is a transitionhandler, we just get handlerinfo.
3256 varHandler = GetTransitionHandlerInfo(glue, *varHandler);
3257 Jump(&loopEnd);
3258 }
3259 }
3260
3261 Bind(&loopEnd);
3262 {
3263 LoopEndWithCheckSafePoint(&loopHead, env, glue);
3264 }
3265 }
3266 }
3267 Bind(&exit);
3268 auto ret = *result;
3269 env->SubCfgExit();
3270 return ret;
3271 }
3272
GetArrayLength(GateRef object)3273 GateRef StubBuilder::GetArrayLength(GateRef object)
3274 {
3275 GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
3276 GateRef result = LoadPrimitive(VariableType::INT32(), object, lengthOffset);
3277 return result;
3278 }
3279
SetArrayLength(GateRef glue,GateRef object,GateRef len)3280 void StubBuilder::SetArrayLength(GateRef glue, GateRef object, GateRef len)
3281 {
3282 GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
3283 Store(VariableType::INT32(), glue, object, lengthOffset, len);
3284 }
3285
StoreICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef value,GateRef argHandler,ProfileOperation callback)3286 GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder,
3287 GateRef value, GateRef argHandler, ProfileOperation callback)
3288 {
3289 auto env = GetEnvironment();
3290 Label entry(env);
3291 env->SubCfgEntry(&entry);
3292 Label exit(env);
3293 Label handlerIsInt(env);
3294 Label handlerNotInt(env);
3295 Label handlerInfoIsField(env);
3296 Label handlerInfoNotField(env);
3297 Label isShared(env);
3298 Label notShared(env);
3299 Label sharedObjectStoreBarrier(env);
3300 Label prepareIntHandlerLoop(env);
3301 Label handlerIsTransitionHandler(env);
3302 Label handlerNotTransitionHandler(env);
3303 Label handlerIsTransWithProtoHandler(env);
3304 Label handlerNotTransWithProtoHandler(env);
3305 Label handlerIsPrototypeHandler(env);
3306 Label handlerNotPrototypeHandler(env);
3307 Label handlerIsPropertyBox(env);
3308 Label handlerNotPropertyBox(env);
3309 Label handlerIsStoreAOTHandler(env);
3310 Label handlerNotStoreAOTHandler(env);
3311 Label aotHandlerInfoIsField(env);
3312 Label aotHandlerInfoNotField(env);
3313 Label cellHasChanged(env);
3314 Label cellNotChanged(env);
3315 Label cellNotUndefined(env);
3316 Label aotCellNotChanged(env);
3317 Label loopHead(env);
3318 Label loopEnd(env);
3319 Label JumpLoopHead(env);
3320 Label cellNotNull(env);
3321 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3322 DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
3323 DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
3324 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
3325 Jump(&loopHead);
3326 LoopBegin(&loopHead);
3327 {
3328 BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
3329 Bind(&handlerIsInt);
3330 {
3331 GateRef handlerInfo = GetInt64OfTInt(*handler);
3332 BRANCH(IsNonSharedStoreField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
3333 Bind(&handlerInfoIsField);
3334 {
3335 result = StoreField(glue, receiver, *actualValue, handlerInfo, callback);
3336 Jump(&exit);
3337 }
3338 Bind(&handlerInfoNotField);
3339 {
3340 BRANCH(IsStoreShared(handlerInfo), &isShared, ¬Shared);
3341 Bind(&isShared);
3342 {
3343 BRANCH(HandlerBaseIsAccessor(handlerInfo), &prepareIntHandlerLoop, &sharedObjectStoreBarrier);
3344 Bind(&sharedObjectStoreBarrier);
3345 {
3346 GateRef field = GetFieldTypeFromHandler(handlerInfo);
3347 SharedObjectStoreBarrierWithTypeCheck(&result, glue, field, value, &actualValue,
3348 &prepareIntHandlerLoop, &exit);
3349 }
3350 Bind(&prepareIntHandlerLoop);
3351 {
3352 handler = IntToTaggedPtr(ClearSharedStoreKind(handlerInfo));
3353 Jump(&JumpLoopHead);
3354 }
3355 }
3356 Bind(¬Shared);
3357 GateRef accessor = LoadFromField(glue, *holder, handlerInfo);
3358 result = CallSetterHelper(glue, receiver, accessor, *actualValue, callback);
3359 Jump(&exit);
3360 }
3361 }
3362 Bind(&handlerNotInt);
3363 {
3364 BRANCH(TaggedIsTransitionHandler(glue, *handler), &handlerIsTransitionHandler, &handlerNotTransitionHandler);
3365 Bind(&handlerIsTransitionHandler);
3366 {
3367 result = StoreWithTransition(glue, receiver, *actualValue, *handler, callback);
3368 Jump(&exit);
3369 }
3370 Bind(&handlerNotTransitionHandler);
3371 {
3372 BRANCH(TaggedIsTransWithProtoHandler(glue, *handler), &handlerIsTransWithProtoHandler,
3373 &handlerNotTransWithProtoHandler);
3374 Bind(&handlerIsTransWithProtoHandler);
3375 {
3376 GateRef cellValue = GetTransWithProtoHandlerProtoCell(glue, *handler);
3377 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &cellNotChanged);
3378 Bind(&cellNotChanged);
3379 {
3380 result = StoreWithTransition(glue, receiver, *actualValue, *handler, callback, true);
3381 Jump(&exit);
3382 }
3383 }
3384 Bind(&handlerNotTransWithProtoHandler);
3385 {
3386 BRANCH(TaggedIsPrototypeHandler(glue, *handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
3387 Bind(&handlerNotPrototypeHandler);
3388 {
3389 BRANCH(TaggedIsPropertyBox(glue, *handler), &handlerIsPropertyBox, &handlerNotPropertyBox);
3390 Bind(&handlerIsPropertyBox);
3391 StoreGlobal(glue, *actualValue, *handler);
3392 Jump(&exit);
3393 }
3394 }
3395 }
3396 }
3397 Bind(&handlerIsPrototypeHandler);
3398 {
3399 GateRef cellValue = GetPrototypeHandlerProtoCell(glue, *handler);
3400 BRANCH(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
3401 Bind(&cellNotUndefined);
3402 BRANCH(TaggedIsNull(cellValue), &cellHasChanged, &cellNotNull);
3403 Bind(&cellNotNull);
3404 {
3405 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
3406 }
3407 Bind(&loopEnd);
3408 {
3409 holder = GetPrototypeHandlerHolder(glue, *handler);
3410 handler = GetPrototypeHandlerHandlerInfo(glue, *handler);
3411 Jump(&JumpLoopHead);
3412 }
3413 }
3414 Bind(&handlerNotPropertyBox);
3415 {
3416 BRANCH(TaggedIsStoreAOTHandler(glue, *handler), &handlerIsStoreAOTHandler, &handlerNotStoreAOTHandler);
3417 Bind(&handlerIsStoreAOTHandler);
3418 {
3419 GateRef cellValue = GetStoreAOTHandlerProtoCell(glue, *handler);
3420 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &aotCellNotChanged);
3421 Bind(&aotCellNotChanged);
3422 {
3423 holder = GetStoreAOTHandlerHolder(glue, *handler);
3424 handler = GetStoreAOTHandlerHandlerInfo(glue, *handler);
3425 GateRef handlerInfo = GetInt64OfTInt(*handler);
3426 BRANCH(IsField(handlerInfo), &aotHandlerInfoIsField, &aotHandlerInfoNotField);
3427 Bind(&aotHandlerInfoIsField);
3428 {
3429 result = StoreField(glue, receiver, *actualValue, handlerInfo, callback);
3430 Jump(&exit);
3431 }
3432 Bind(&aotHandlerInfoNotField);
3433 {
3434 GateRef accessor = LoadFromField(glue, *holder, handlerInfo);
3435 result = CallSetterHelper(glue, receiver, accessor, *actualValue, callback);
3436 Jump(&exit);
3437 }
3438 }
3439 }
3440 Bind(&handlerNotStoreAOTHandler);
3441 Jump(&exit);
3442 }
3443 Bind(&cellHasChanged);
3444 {
3445 result = Hole();
3446 Jump(&exit);
3447 }
3448 Bind(&JumpLoopHead);
3449 {
3450 LoopEndWithCheckSafePoint(&loopHead, env, glue);
3451 }
3452 }
3453 Bind(&exit);
3454 auto ret = *result;
3455 env->SubCfgExit();
3456 return ret;
3457 }
3458
StoreField(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback)3459 GateRef StubBuilder::StoreField(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
3460 ProfileOperation callback)
3461 {
3462 auto env = GetEnvironment();
3463 Label entry(env);
3464 env->SubCfgEntry(&entry);
3465 ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handler, callback);
3466 Label exit(env);
3467 Label handlerIsInlinedProperty(env);
3468 Label handlerNotInlinedProperty(env);
3469 GateRef index = HandlerBaseGetOffset(handler);
3470 GateRef rep = HandlerBaseGetRep(handler);
3471 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3472 Label repChange(env);
3473 BRANCH(HandlerBaseIsInlinedProperty(handler), &handlerIsInlinedProperty, &handlerNotInlinedProperty);
3474 Bind(&handlerIsInlinedProperty);
3475 {
3476 GateRef toOffset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
3477 SetValueWithRep(glue, receiver, toOffset, value, rep, &repChange);
3478 Jump(&exit);
3479 }
3480 Bind(&handlerNotInlinedProperty);
3481 {
3482 GateRef array = GetPropertiesArray(glue, receiver);
3483 SetValueToTaggedArrayWithRep(glue, array, index, value, rep, &repChange);
3484 Jump(&exit);
3485 }
3486 Bind(&repChange);
3487 {
3488 result = Hole();
3489 Jump(&exit);
3490 }
3491
3492 Bind(&exit);
3493 auto ret = *result;
3494 env->SubCfgExit();
3495 return ret;
3496 }
3497
StoreWithTransition(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback,bool withPrototype)3498 GateRef StubBuilder::StoreWithTransition(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
3499 ProfileOperation callback, bool withPrototype)
3500 {
3501 auto env = GetEnvironment();
3502 Label entry(env);
3503 env->SubCfgEntry(&entry);
3504 Label exit(env);
3505
3506 Label handlerInfoIsInlinedProps(env);
3507 Label handlerInfoNotInlinedProps(env);
3508 Label indexMoreCapacity(env);
3509 Label indexLessCapacity(env);
3510 Label capacityIsZero(env);
3511 Label capacityNotZero(env);
3512 Label isPrototype(env);
3513 Label notPrototype(env);
3514 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3515 GateRef newHClass;
3516 GateRef handlerInfo;
3517 if (withPrototype) {
3518 newHClass = GetTransWithProtoHClass(glue, handler);
3519 handlerInfo = GetInt64OfTInt(GetTransWithProtoHandlerInfo(glue, handler));
3520 } else {
3521 newHClass = GetTransitionHClass(glue, handler);
3522 handlerInfo = GetInt64OfTInt(GetTransitionHandlerInfo(glue, handler));
3523 }
3524
3525 GateRef oldHClass = LoadHClass(glue, receiver);
3526 GateRef prototype = GetPrototypeFromHClass(glue, oldHClass);
3527 StorePrototype(glue, newHClass, prototype);
3528 BRANCH(IsPrototypeHClass(newHClass), &isPrototype, ¬Prototype);
3529 Bind(&isPrototype);
3530 {
3531 SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, newHClass, GetProtoChangeDetails(glue, oldHClass));
3532 Jump(¬Prototype);
3533 }
3534 Bind(¬Prototype);
3535 // Because we currently only supports Fast ElementsKind
3536 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
3537 RestoreElementsKindToGeneric(glue, newHClass);
3538 TransitionHClass(glue, receiver, newHClass);
3539 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
3540 BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
3541 Bind(&handlerInfoNotInlinedProps);
3542 {
3543 ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handlerInfo, callback);
3544 Label repChange(env);
3545 GateRef array = GetPropertiesArray(glue, receiver);
3546 GateRef capacity = GetLengthOfTaggedArray(array);
3547 GateRef index = HandlerBaseGetOffset(handlerInfo);
3548 BRANCH(Int32GreaterThanOrEqual(index, capacity), &indexMoreCapacity, &indexLessCapacity);
3549 Bind(&indexMoreCapacity);
3550 {
3551 NewObjectStubBuilder newBuilder(this);
3552 BRANCH(Int32Equal(capacity, Int32(0)), &capacityIsZero, &capacityNotZero);
3553 Bind(&capacityIsZero);
3554 {
3555 GateRef properties = newBuilder.NewTaggedArray(glue, Int32(JSObject::MIN_PROPERTIES_LENGTH));
3556 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3557 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3558 Jump(&exit);
3559 }
3560 Bind(&capacityNotZero);
3561 {
3562 GateRef inlinedProperties = GetInlinedPropertiesFromHClass(newHClass);
3563 GateRef maxNonInlinedFastPropsCapacity =
3564 Int32Sub(Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY), inlinedProperties);
3565 GateRef newLen = ComputeNonInlinedFastPropsCapacity(glue, capacity, maxNonInlinedFastPropsCapacity);
3566 GateRef properties = newBuilder.CopyArray(glue, array, capacity, newLen);
3567 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3568 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3569 Jump(&exit);
3570 }
3571 }
3572 Bind(&indexLessCapacity);
3573 {
3574 GateRef rep = HandlerBaseGetRep(handlerInfo);
3575 GateRef toIndex = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
3576 Label isCMCGC(env);
3577 Label notCMCGC(env);
3578 BRANCH_UNLIKELY(LoadPrimitive(
3579 VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
3580 &isCMCGC, ¬CMCGC);
3581 Bind(&isCMCGC);
3582 {
3583 GateRef offset = PtrAdd(toIndex, IntPtr(TaggedArray::DATA_OFFSET));
3584 SetValueWithRep(glue, array, offset, value, rep, &repChange);
3585 Jump(&exit);
3586 }
3587 Bind(¬CMCGC);
3588 {
3589 GateRef base = PtrAdd(array, IntPtr(TaggedArray::DATA_OFFSET));
3590 SetValueWithRep(glue, base, toIndex, value, rep, &repChange);
3591 Jump(&exit);
3592 }
3593 }
3594 Bind(&repChange);
3595 {
3596 result = Hole();
3597 Jump(&exit);
3598 }
3599 }
3600 Bind(&handlerInfoIsInlinedProps);
3601 {
3602 result = StoreField(glue, receiver, value, handlerInfo, callback);
3603 Jump(&exit);
3604 }
3605 Bind(&exit);
3606 auto ret = *result;
3607 env->SubCfgExit();
3608 return ret;
3609 }
3610
StoreGlobal(GateRef glue,GateRef value,GateRef cell)3611 GateRef StubBuilder::StoreGlobal(GateRef glue, GateRef value, GateRef cell)
3612 {
3613 auto env = GetEnvironment();
3614 Label entry(env);
3615 env->SubCfgEntry(&entry);
3616 Label exit(env);
3617 Label cellNotInvalid(env);
3618 Label cellIsNotAccessorData(env);
3619 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3620 BRANCH(IsInvalidPropertyBox(glue, cell), &exit, &cellNotInvalid);
3621 Bind(&cellNotInvalid);
3622 {
3623 BRANCH(IsAccessorPropertyBox(glue, cell), &exit, &cellIsNotAccessorData);
3624 Bind(&cellIsNotAccessorData);
3625 {
3626 Store(VariableType::JS_ANY(), glue, cell, IntPtr(PropertyBox::VALUE_OFFSET), value);
3627 result = Undefined();
3628 Jump(&exit);
3629 }
3630 }
3631 Bind(&exit);
3632 auto ret = *result;
3633 env->SubCfgExit();
3634 return ret;
3635 }
3636
3637 template<typename DictionaryT>
GetAttributesFromDictionary(GateRef glue,GateRef elements,GateRef entry)3638 GateRef StubBuilder::GetAttributesFromDictionary(GateRef glue, GateRef elements, GateRef entry)
3639 {
3640 GateRef arrayIndex =
3641 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3642 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3643 GateRef attributesIndex =
3644 Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_DETAILS_INDEX));
3645 auto attrValue = GetValueFromTaggedArray(glue, elements, attributesIndex);
3646 return GetInt64OfTInt(attrValue);
3647 }
3648
3649 template<typename DictionaryT>
GetValueFromDictionary(GateRef glue,GateRef elements,GateRef entry)3650 GateRef StubBuilder::GetValueFromDictionary(GateRef glue, GateRef elements, GateRef entry)
3651 {
3652 GateRef arrayIndex =
3653 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3654 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3655 GateRef valueIndex =
3656 Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3657 return GetValueFromTaggedArray(glue, elements, valueIndex);
3658 }
3659
3660 template<typename DictionaryT>
GetKeyFromDictionary(GateRef glue,GateRef elements,GateRef entry)3661 GateRef StubBuilder::GetKeyFromDictionary(GateRef glue, GateRef elements, GateRef entry)
3662 {
3663 auto env = GetEnvironment();
3664 Label subentry(env);
3665 env->SubCfgEntry(&subentry);
3666 Label exit(env);
3667 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3668 Label ltZero(env);
3669 Label notLtZero(env);
3670 Label gtLength(env);
3671 Label notGtLength(env);
3672 GateRef dictionaryLength =
3673 LoadPrimitive(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
3674 GateRef arrayIndex =
3675 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3676 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3677 BRANCH(Int32LessThan(arrayIndex, Int32(0)), <Zero, ¬LtZero);
3678 Bind(<Zero);
3679 Jump(&exit);
3680 Bind(¬LtZero);
3681 BRANCH(Int32GreaterThan(arrayIndex, dictionaryLength), >Length, ¬GtLength);
3682 Bind(>Length);
3683 Jump(&exit);
3684 Bind(¬GtLength);
3685 result = GetValueFromTaggedArray(glue, elements, arrayIndex);
3686 Jump(&exit);
3687 Bind(&exit);
3688 auto ret = *result;
3689 env->SubCfgExit();
3690 return ret;
3691 }
3692
UpdateValueAndAttributes(GateRef glue,GateRef elements,GateRef index,GateRef value,GateRef attr)3693 inline void StubBuilder::UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index,
3694 GateRef value, GateRef attr)
3695 {
3696 GateRef arrayIndex =
3697 Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
3698 Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
3699 GateRef valueIndex =
3700 Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
3701 GateRef attributesIndex =
3702 Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_DETAILS_INDEX));
3703 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3704 GateRef attroffset =
3705 PtrMul(ZExtInt32ToPtr(attributesIndex), IntPtr(JSTaggedValue::TaggedTypeSize()));
3706 GateRef dataOffset = PtrAdd(attroffset, IntPtr(TaggedArray::DATA_OFFSET));
3707 Store(VariableType::INT64(), glue, elements, dataOffset, Int64ToTaggedInt(attr));
3708 }
3709
3710 template<typename DictionaryT>
UpdateValueInDict(GateRef glue,GateRef elements,GateRef index,GateRef value)3711 inline void StubBuilder::UpdateValueInDict(GateRef glue, GateRef elements, GateRef index, GateRef value)
3712 {
3713 GateRef arrayIndex = Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3714 Int32Mul(index, Int32(DictionaryT::ENTRY_SIZE)));
3715 GateRef valueIndex = Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3716 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3717 }
3718
GetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,ProfileOperation callback,GateRef hir)3719 GateRef StubBuilder::GetPropertyByIndex(GateRef glue, GateRef receiver,
3720 GateRef index, ProfileOperation callback, GateRef hir)
3721 {
3722 auto env = GetEnvironment();
3723 Label entry(env);
3724 env->SubCfgEntry(&entry);
3725 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3726 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
3727 Label exit(env);
3728 Label loopHead(env);
3729 Label loopEnd(env);
3730 Label loopExit(env);
3731 Label afterLoop(env);
3732 Jump(&loopHead);
3733 LoopBegin(&loopHead);
3734 {
3735 GateRef hclass = LoadHClass(glue, *holder);
3736 GateRef jsType = GetObjectType(hclass);
3737 Label isSpecialIndexed(env);
3738 Label notSpecialIndexed(env);
3739 BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed);
3740 Bind(&isSpecialIndexed);
3741 {
3742 // TypeArray
3743 Label isFastTypeArray(env);
3744 Label notFastTypeArray(env);
3745 Label notTypedArrayProto(env);
3746 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, ¬TypedArrayProto);
3747 Bind(¬TypedArrayProto);
3748 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
3749 Bind(&isFastTypeArray);
3750 {
3751 BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this, GetCurrentGlobalEnv());
3752 result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, *holder, index, jsType);
3753 Jump(&exit);
3754 }
3755 Bind(¬FastTypeArray);
3756
3757 Label isSpecialContainer(env);
3758 Label notSpecialContainer(env);
3759 // Add SpecialContainer
3760 BRANCH(IsArrayListOrVector(jsType), &isSpecialContainer, ¬SpecialContainer);
3761 Bind(&isSpecialContainer);
3762 {
3763 result = JSAPIContainerGet(glue, *holder, index);
3764 Jump(&exit);
3765 }
3766 Bind(¬SpecialContainer);
3767
3768 Label isString(env);
3769 Label notString(env);
3770 Label getSubString(env);
3771 BRANCH(TaggedIsString(glue, *holder), &isString, ¬String);
3772 Bind(&isString);
3773 {
3774 GateRef length = GetLengthFromString(*holder);
3775 BRANCH(Int32LessThan(index, length), &getSubString, ¬String);
3776 Bind(&getSubString);
3777 Label flattenFastPath(env);
3778 BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
3779 FlatStringStubBuilder thisFlat(this);
3780 thisFlat.FlattenString(glue, *holder, &flattenFastPath);
3781 Bind(&flattenFastPath);
3782 StringInfoGateRef stringInfoGate(&thisFlat);
3783 result = stringBuilder.FastSubString(glue, *holder, index, Int32(1), stringInfoGate);
3784 Jump(&exit);
3785 }
3786 Bind(¬String);
3787 {
3788 result = Hole();
3789 Jump(&exit);
3790 }
3791 }
3792 Bind(¬SpecialIndexed);
3793 {
3794 GateRef elements = GetElementsArray(glue, *holder);
3795 Label isDictionaryElement(env);
3796 Label notDictionaryElement(env);
3797 BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
3798 Bind(¬DictionaryElement);
3799 {
3800 Label lessThanLength(env);
3801 Label notLessThanLength(env);
3802 BRANCH(Int32UnsignedLessThan(index, GetLengthOfTaggedArray(elements)),
3803 &lessThanLength, ¬LessThanLength);
3804 Bind(&lessThanLength);
3805 {
3806 DEFVARIABLE(value, VariableType::JS_ANY(), Hole());
3807 Label notHole(env);
3808 Label isHole(env);
3809 value = GetTaggedValueWithElementsKind(glue, *holder, index);
3810 BRANCH(TaggedIsNotHole(*value), ¬Hole, &isHole);
3811 Bind(¬Hole);
3812 {
3813 result = *value;
3814 Jump(&exit);
3815 }
3816 Bind(&isHole);
3817 {
3818 Jump(&loopExit);
3819 }
3820 }
3821 Bind(¬LessThanLength);
3822 {
3823 Jump(&loopExit);
3824 }
3825 }
3826 Bind(&isDictionaryElement);
3827 {
3828 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
3829 Label notNegtiveOne(env);
3830 Label negtiveOne(env);
3831 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
3832 Bind(¬NegtiveOne);
3833 {
3834 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(glue, elements, entryA);
3835 GateRef value = GetValueFromDictionary<NumberDictionary>(glue, elements, entryA);
3836 Label isAccessor(env);
3837 Label notAccessor(env);
3838 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
3839 Bind(&isAccessor);
3840 {
3841 result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
3842 Jump(&exit);
3843 }
3844 Bind(¬Accessor);
3845 {
3846 result = value;
3847 Jump(&exit);
3848 }
3849 }
3850 Bind(&negtiveOne);
3851 Jump(&loopExit);
3852 }
3853 Bind(&loopExit);
3854 {
3855 holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
3856 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3857 }
3858 }
3859 Bind(&loopEnd);
3860 LoopEndWithCheckSafePoint(&loopHead, env, glue);
3861 Bind(&afterLoop);
3862 {
3863 result = Undefined();
3864 Jump(&exit);
3865 }
3866 }
3867 Bind(&exit);
3868 auto ret = *result;
3869 env->SubCfgExit();
3870 return ret;
3871 }
3872
GetPropertyByValue(GateRef glue,GateRef target,GateRef propKey,GateRef receiver,ProfileOperation callback)3873 GateRef StubBuilder::GetPropertyByValue(
3874 GateRef glue, GateRef target, GateRef propKey, GateRef receiver, ProfileOperation callback)
3875 {
3876 auto env = GetEnvironment();
3877 Label entry(env);
3878 env->SubCfgEntry(&entry);
3879 DEFVARIABLE(key, VariableType::JS_ANY(), propKey);
3880 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3881 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
3882 Label isPropertyKey(env);
3883 Label exit(env);
3884
3885 BRANCH(TaggedIsPropertyKey(glue, *key), &isPropertyKey, &exit);
3886
3887 Bind(&isPropertyKey);
3888 {
3889 GateRef index64 = TryToElementsIndex(glue, *key);
3890 Label validIndex(env);
3891 Label notValidIndex(env);
3892 Label greaterThanInt32Max(env);
3893 Label notGreaterThanInt32Max(env);
3894 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
3895 Bind(&greaterThanInt32Max);
3896 {
3897 Jump(&exit);
3898 }
3899 Bind(¬GreaterThanInt32Max);
3900 GateRef index = TruncInt64ToInt32(index64);
3901 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
3902 Bind(&validIndex);
3903 {
3904 result = GetPropertyByIndex(glue, target, index, callback);
3905 Jump(&exit);
3906 }
3907 Bind(¬ValidIndex);
3908 {
3909 Label notNumber1(env);
3910 Label getByName(env);
3911 BRANCH(TaggedIsNumber(*key), &exit, ¬Number1);
3912 Bind(¬Number1);
3913 {
3914 Label isString(env);
3915 Label notString(env);
3916 Label isInternalString(env);
3917 Label notIntenalString(env);
3918 BRANCH(TaggedIsString(glue, *key), &isString, ¬String);
3919 Bind(&isString);
3920 {
3921 BRANCH(IsInternalString(*key), &isInternalString, ¬IntenalString);
3922 Bind(&isInternalString);
3923 Jump(&getByName);
3924 Bind(¬IntenalString);
3925 {
3926 Label notFind(env);
3927 Label find(env);
3928 // if key can't find in stringtabele, key is not propertyname for a object
3929 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *key });
3930 BRANCH(TaggedIsHole(res), ¬Find, &find);
3931 Bind(¬Find);
3932 {
3933 isInternal = False();
3934 Jump(&getByName);
3935 }
3936 Bind(&find);
3937 {
3938 key = res;
3939 Jump(&getByName);
3940 }
3941 }
3942 }
3943 Bind(¬String);
3944 {
3945 Jump(&getByName);
3946 }
3947 }
3948 Bind(&getByName);
3949 {
3950 result = GetPropertyByName(glue, target, *key, receiver, callback, *isInternal, true);
3951 Jump(&exit);
3952 }
3953 }
3954 }
3955 Bind(&exit);
3956 auto ret = *result;
3957 env->SubCfgExit();
3958 return ret;
3959 }
3960
GetPropertyByName(GateRef glue,GateRef target,GateRef propKey,GateRef receiver,ProfileOperation callback,GateRef isInternal,bool canUseIsInternal,GateRef hir)3961 GateRef StubBuilder::GetPropertyByName(GateRef glue,
3962 GateRef target,
3963 GateRef propKey,
3964 GateRef receiver,
3965 ProfileOperation callback,
3966 GateRef isInternal,
3967 bool canUseIsInternal,
3968 GateRef hir)
3969 {
3970 auto env = GetEnvironment();
3971 Label entry(env);
3972 env->SubCfgEntry(&entry);
3973 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3974 DEFVARIABLE(holder, VariableType::JS_ANY(), target);
3975 Label exit(env);
3976 Label loopHead(env);
3977 Label loopEnd(env);
3978 Label loopExit(env);
3979 Label afterLoop(env);
3980 Label findProperty(env);
3981 Jump(&loopHead);
3982 LoopBegin(&loopHead);
3983 {
3984 GateRef hclass = LoadHClass(glue, *holder);
3985 GateRef jsType = GetObjectType(hclass);
3986 Label isSIndexObj(env);
3987 Label notSIndexObj(env);
3988 BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
3989 Bind(&isSIndexObj);
3990 {
3991 // TypeArray
3992 Label isFastTypeArray(env);
3993 Label notFastTypeArray(env);
3994 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
3995 Bind(&isFastTypeArray);
3996 {
3997 result = GetTypeArrayPropertyByName(glue, target, *holder, propKey, jsType);
3998 Label isNull(env);
3999 Label notNull(env);
4000 BRANCH(TaggedIsNull(*result), &isNull, ¬Null);
4001 Bind(&isNull);
4002 {
4003 result = Hole();
4004 Jump(&exit);
4005 }
4006 Bind(¬Null);
4007 BRANCH(TaggedIsHole(*result), ¬SIndexObj, &exit);
4008 }
4009 Bind(¬FastTypeArray);
4010
4011 Label isString(env);
4012 Label notString(env);
4013 Label notJsPrimitiveRef(env);
4014 auto holderValue = *holder;
4015 BRANCH(LogicAndBuilder(env).And(TaggedIsString(glue, holderValue)).And(TaggedIsString(glue, propKey))
4016 .Done(), &isString, ¬String);
4017 Bind(&isString);
4018 {
4019 Label getStringLength(env);
4020 Label getStringPrototype(env);
4021 GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
4022 ConstantIndex::LENGTH_STRING_INDEX);
4023 BRANCH(FastStringEqual(glue, propKey, lengthString), &getStringLength, &getStringPrototype);
4024 Bind(&getStringLength);
4025 {
4026 result = IntToTaggedPtr(GetLengthFromString(*holder));
4027 Jump(&exit);
4028 }
4029 Bind(&getStringPrototype);
4030 {
4031 GateRef globalEnv = GetCurrentGlobalEnv();
4032 GateRef stringPrototype = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
4033 GlobalEnv::STRING_PROTOTYPE_INDEX);
4034 holder = stringPrototype;
4035 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4036 }
4037 }
4038 Bind(¬String);
4039 BRANCH(IsJSPrimitiveRef(glue, *holder), ¬SIndexObj, ¬JsPrimitiveRef);
4040 Bind(¬JsPrimitiveRef); // not string prototype etc.
4041 {
4042 #if ENABLE_NEXT_OPTIMIZATION
4043 Label isJsProxy(env);
4044 Label notJsProxy(env);
4045 BRANCH(IsJSProxy(jsType), &isJsProxy, ¬JsProxy);
4046 Bind(&isJsProxy);
4047 {
4048 result = CallCommonStub(glue, CommonStubCSigns::JSProxyGetProperty,
4049 {glue, *holder, propKey, target, GetCurrentGlobalEnv()}, hir);
4050 Label isPendingException(env);
4051 Label noPendingException(env);
4052 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
4053 Bind(&isPendingException);
4054 {
4055 result = Exception();
4056 Jump(&exit);
4057 }
4058 Bind(&noPendingException);
4059 Jump(&exit);
4060 }
4061 Bind(¬JsProxy);
4062 {
4063 result = Hole();
4064 Jump(&exit);
4065 }
4066 #else
4067 result = Hole();
4068 Jump(&exit);
4069 #endif
4070 }
4071 }
4072 Bind(¬SIndexObj);
4073 {
4074 if (canUseIsInternal) {
4075 BRANCH(isInternal, &findProperty, &loopExit);
4076 } else {
4077 Jump(&findProperty);
4078 }
4079 Label isDicMode(env);
4080 Label notDicMode(env);
4081 Bind(&findProperty);
4082 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
4083 Bind(¬DicMode);
4084 {
4085 GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
4086 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4087 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
4088 GateRef entryA = FindElementWithCache(glue, layOutInfo, hclass, propKey, propsNum, hir);
4089 Label hasEntry(env);
4090 Label noEntry(env);
4091 // if branch condition : entry != -1
4092 BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, &noEntry);
4093 Bind(&hasEntry);
4094 {
4095 // PropertyAttributes attr(layoutInfo->GetAttr(entry))
4096 GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entryA);
4097 GateRef value = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
4098 Label isAccessor(env);
4099 Label notAccessor(env);
4100 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
4101 Bind(&isAccessor);
4102 {
4103 // The getter may involve nested calls, so it is better to end (or return) early
4104 EndTraceLoad(glue);
4105 if (receiver == Circuit::NullGate()) {
4106 result = CallGetterHelper(glue, target, *holder, value, callback, hir);
4107 } else {
4108 result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
4109 }
4110 StartTraceLoadGetter(glue);
4111 Jump(&exit);
4112 }
4113 Bind(¬Accessor);
4114 {
4115 Label notHole(env);
4116 BRANCH(TaggedIsHole(value), &noEntry, ¬Hole);
4117 Bind(¬Hole);
4118 {
4119 result = value;
4120 Jump(&exit);
4121 }
4122 }
4123 }
4124 Bind(&noEntry);
4125 {
4126 Jump(&loopExit);
4127 }
4128 }
4129 Bind(&isDicMode);
4130 {
4131 GateRef array = GetPropertiesArray(glue, *holder);
4132 // int entry = dict->FindEntry(key)
4133 GateRef entryB = FindEntryFromHashTable<NameDictionary>(glue, array, propKey, hir);
4134 Label notNegtiveOne(env);
4135 Label negtiveOne(env);
4136 // if branch condition : entry != -1
4137 BRANCH(Int32NotEqual(entryB, Int32(-1)), ¬NegtiveOne, &negtiveOne);
4138 Bind(¬NegtiveOne);
4139 {
4140 // auto value = dict->GetValue(entry)
4141 GateRef attr = GetAttributesFromDictionary<NameDictionary>(glue, array, entryB);
4142 // auto attr = dict->GetAttributes(entry)
4143 GateRef value = GetValueFromDictionary<NameDictionary>(glue, array, entryB);
4144 Label isAccessor1(env);
4145 Label notAccessor1(env);
4146 BRANCH(IsAccessor(attr), &isAccessor1, ¬Accessor1);
4147 Bind(&isAccessor1);
4148 {
4149 // The getter may involve nested calls, so it is better to end (or return) early
4150 EndTraceLoad(glue);
4151 if (receiver == Circuit::NullGate()) {
4152 result = CallGetterHelper(glue, target, *holder, value, callback, hir);
4153 } else {
4154 result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
4155 }
4156 StartTraceLoadGetter(glue);
4157 Jump(&exit);
4158 }
4159 Bind(¬Accessor1);
4160 {
4161 result = value;
4162 Jump(&exit);
4163 }
4164 }
4165 Bind(&negtiveOne);
4166 Jump(&loopExit);
4167 }
4168 Bind(&loopExit);
4169 {
4170 holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
4171 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4172 }
4173 }
4174 Bind(&loopEnd);
4175 LoopEndWithCheckSafePoint(&loopHead, env, glue);
4176 Bind(&afterLoop);
4177 {
4178 result = Undefined();
4179 Jump(&exit);
4180 }
4181 }
4182 Bind(&exit);
4183 auto ret = *result;
4184 env->SubCfgExit();
4185 return ret;
4186 }
4187
CallGetterIfAccessor(GateRef glue,GateRef holder,Variable * value,Variable * attr,Label * isFoundData,Label * isFoundAccessor)4188 void StubBuilder::CallGetterIfAccessor(GateRef glue, GateRef holder, Variable *value, Variable *attr,
4189 Label *isFoundData, Label *isFoundAccessor)
4190 {
4191 auto env = GetEnvironment();
4192 Label isAccessor(env);
4193 GateRef attrVal = attr->ReadVariable();
4194 GateRef valueVal = value->ReadVariable();
4195 BRANCH(IsAccessor(attrVal), &isAccessor, isFoundData);
4196 Bind(&isAccessor);
4197 {
4198 Label isAccessorInternal(env);
4199 BRANCH_UNLIKELY(IsAccessorInternal(glue, valueVal), &isAccessorInternal, isFoundAccessor);
4200 Bind(&isAccessorInternal);
4201 {
4202 value->WriteVariable(CallGetterHelper(glue, holder, holder, valueVal, ProfileOperation()));
4203 Jump(isFoundData);
4204 }
4205 }
4206 }
4207
TryGetOwnProperty(GateRef glue,GateRef holder,GateRef key,GateRef hir,Variable * rValue,Variable * rAttr,Label * isFoundData,Label * isFoundAccessor,Label * notFound,Label * callRuntime)4208 void StubBuilder::TryGetOwnProperty(GateRef glue, GateRef holder, GateRef key, GateRef hir,
4209 Variable *rValue, Variable *rAttr,
4210 Label *isFoundData, Label *isFoundAccessor, Label *notFound, Label *callRuntime)
4211 {
4212 auto env = GetEnvironment();
4213 Label exit(env);
4214 Label findProperty(env);
4215 Label found(env);
4216 GateRef hclass = LoadHClass(glue, holder);
4217 GateRef jsType = GetObjectType(hclass);
4218 Label isSIndexObj(env);
4219 Label notSIndexObj(env);
4220 BRANCH(IsSpecialIndexedObj(jsType), callRuntime, ¬SIndexObj);
4221 Bind(¬SIndexObj);
4222 {
4223 Label isDicMode(env);
4224 Label notDicMode(env);
4225 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
4226 Bind(¬DicMode);
4227 {
4228 GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
4229 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4230 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
4231 GateRef entryA = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum, hir);
4232 Label hasEntry(env);
4233 // if branch condition : entry != -1
4234 BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, notFound);
4235 Bind(&hasEntry);
4236 {
4237 // PropertyAttributes attr(layoutInfo->GetAttr(entry))
4238 GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entryA);
4239 GateRef value = JSObjectGetPropertyWithRep(glue, holder, hclass, attr);
4240 Label notHole(env);
4241 BRANCH(TaggedIsHole(value), notFound, ¬Hole);
4242 Bind(¬Hole);
4243 {
4244 rValue->WriteVariable(value);
4245 rAttr->WriteVariable(attr);
4246 Jump(&found);
4247 }
4248 }
4249 }
4250 Bind(&isDicMode);
4251 {
4252 GateRef array = GetPropertiesArray(glue, holder);
4253 // int entry = dict->FindEntry(key)
4254 GateRef entryB = FindEntryFromHashTable<NameDictionary>(glue, array, key, hir);
4255 Label notNegtiveOne(env);
4256 // if branch condition : entry != -1
4257 BRANCH(Int32NotEqual(entryB, Int32(-1)), ¬NegtiveOne, notFound);
4258 Bind(¬NegtiveOne);
4259 {
4260 // auto value = dict->GetValue(entry)
4261 rAttr->WriteVariable(GetAttributesFromDictionary<NameDictionary>(glue, array, entryB));
4262 // auto attr = dict->GetAttributes(entry)
4263 rValue->WriteVariable(GetValueFromDictionary<NameDictionary>(glue, array, entryB));
4264 Jump(&found);
4265 }
4266 }
4267 Bind(&found);
4268 {
4269 CallGetterIfAccessor(glue, holder, rValue, rAttr, isFoundData, isFoundAccessor);
4270 }
4271 }
4272 }
4273
CopyAllHClass(GateRef glue,GateRef dstHClass,GateRef srcHClass)4274 void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHClass)
4275 {
4276 auto env = GetEnvironment();
4277 Label entry(env);
4278 Label isAOT(env);
4279 Label isNotAOT(env);
4280 env->SubCfgEntry(&entry);
4281 auto proto = GetPrototypeFromHClass(glue, srcHClass);
4282 SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto);
4283 GateRef bitField = GetBitFieldFromHClass(srcHClass);
4284 GateRef afterSetStableBitField = SetIsStableToBitField(bitField, Int32(1));
4285 SetBitFieldToHClass(glue, dstHClass, afterSetStableBitField);
4286 SetIsAllTaggedProp(glue, dstHClass, GetIsAllTaggedPropFromHClass(srcHClass));
4287 SetNumberOfPropsToHClass(glue, dstHClass, GetNumberOfPropsFromHClass(srcHClass));
4288 SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
4289 SetParentToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
4290 SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, dstHClass, Null());
4291 SetEnumCacheToHClass(VariableType::INT64(), glue, dstHClass, Null());
4292 SetDependentInfosToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
4293 SetLayoutToHClass(VariableType::JS_POINTER(),
4294 glue,
4295 dstHClass,
4296 GetLayoutFromHClass(glue, srcHClass),
4297 MemoryAttribute::NeedBarrierAndAtomic());
4298 BRANCH(IsAOTHClass(srcHClass), &isAOT, &isNotAOT);
4299 Bind(&isAOT);
4300 {
4301 SetIsAOT(glue, dstHClass, False());
4302 Jump(&isNotAOT);
4303 }
4304 Bind(&isNotAOT);
4305 env->SubCfgExit();
4306 return;
4307 }
4308
TransitionForRepChange(GateRef glue,GateRef receiver,GateRef key,GateRef attr)4309 void StubBuilder::TransitionForRepChange(GateRef glue, GateRef receiver, GateRef key, GateRef attr)
4310 {
4311 auto env = GetEnvironment();
4312 Label subEntry(env);
4313 env->SubCfgEntry(&subEntry);
4314 GateRef hclass = LoadHClass(glue, receiver);
4315 GateRef type = GetObjectType(hclass);
4316 GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
4317 Int32(JSTaggedValue::TaggedTypeSize()));
4318 GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
4319 GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
4320 { IntToTaggedInt(size), IntToTaggedInt(type),
4321 IntToTaggedInt(inlineProps) });
4322 CopyAllHClass(glue, newJshclass, hclass);
4323 CallRuntime(glue, RTSTUB_ID(CopyAndUpdateObjLayout),
4324 { hclass, newJshclass, key, Int64ToTaggedInt(attr) });
4325 #if ECMASCRIPT_ENABLE_IC
4326 NotifyHClassChanged(glue, hclass, newJshclass);
4327 #endif
4328 // Because we currently only supports Fast ElementsKind
4329 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(glue, receiver));
4330 RestoreElementsKindToGeneric(glue, newJshclass);
4331 TransitionHClass(glue, receiver, newJshclass);
4332 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
4333 env->SubCfgExit();
4334 }
4335
TransitToElementsKind(GateRef glue,GateRef receiver,GateRef value,GateRef kind)4336 void StubBuilder::TransitToElementsKind(GateRef glue, GateRef receiver, GateRef value, GateRef kind)
4337 {
4338 auto env = GetEnvironment();
4339 Label subEntry(env);
4340 env->SubCfgEntry(&subEntry);
4341 Label exit(env);
4342
4343 GateRef hclass = LoadHClass(glue, receiver);
4344 GateRef elementsKind = GetElementsKindFromHClass(hclass);
4345
4346 Label isNoneDefault(env);
4347 BRANCH(Int32Equal(elementsKind, Int32(Elements::ToUint(ElementsKind::GENERIC))), &exit, &isNoneDefault);
4348 Bind(&isNoneDefault);
4349 {
4350 GateRef newKind = TaggedToElementKind(glue, value);
4351 newKind = Int32Or(newKind, kind);
4352 newKind = Int32Or(newKind, elementsKind);
4353 Label change(env);
4354 BRANCH(Int32Equal(elementsKind, newKind), &exit, &change);
4355 Bind(&change);
4356 {
4357 CallRuntime(glue, RTSTUB_ID(UpdateHClassForElementsKind), { receiver, newKind });
4358 MigrateArrayWithKind(glue, receiver, elementsKind, newKind);
4359 Jump(&exit);
4360 }
4361 }
4362
4363 Bind(&exit);
4364 env->SubCfgExit();
4365 }
4366
TryMigrateToGenericKindForJSObject(GateRef glue,GateRef receiver,GateRef oldKind)4367 void StubBuilder::TryMigrateToGenericKindForJSObject(GateRef glue, GateRef receiver, GateRef oldKind)
4368 {
4369 auto env = GetEnvironment();
4370 Label subEntry(env);
4371 env->SubCfgEntry(&subEntry);
4372 Label exit(env);
4373
4374 Label isJSArray(env);
4375 BRANCH(TaggedIsJSArray(glue, receiver), &isJSArray, &exit);
4376 Bind(&isJSArray);
4377 {
4378 Label elementsIsMutantTaggedArray(env);
4379 GateRef elements = GetElementsArray(glue, receiver);
4380 BRANCH(IsMutantTaggedArray(glue, elements), &elementsIsMutantTaggedArray, &exit);
4381 Bind(&elementsIsMutantTaggedArray);
4382 {
4383 MigrateArrayWithKind(glue, receiver, oldKind, Int32(Elements::ToUint(ElementsKind::GENERIC)));
4384 Jump(&exit);
4385 }
4386 }
4387
4388 Bind(&exit);
4389 env->SubCfgExit();
4390 }
4391
AddElementInternal(GateRef glue,GateRef receiver,GateRef index,GateRef value,GateRef attr)4392 GateRef StubBuilder::AddElementInternal(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef attr)
4393 {
4394 auto env = GetEnvironment();
4395 Label subEntry(env);
4396 env->SubCfgEntry(&subEntry);
4397 Label exit(env);
4398 DEFVARIABLE(kind, VariableType::INT32(), Int32(Elements::ToUint(ElementsKind::NONE)));
4399 DEFVARIABLE(result, VariableType::BOOL(), False());
4400 Label isArray(env);
4401 Label notArray(env);
4402 BRANCH(IsJsArray(glue, receiver), &isArray, ¬Array);
4403 Bind(&isArray);
4404 {
4405 GateRef oldLen = GetArrayLength(receiver);
4406 Label indexGreaterOrEq(env);
4407 BRANCH(Int32GreaterThanOrEqual(index, oldLen), &indexGreaterOrEq, ¬Array);
4408 Bind(&indexGreaterOrEq);
4409 {
4410 Label isArrLenWritable(env);
4411 Label notArrLenWritable(env);
4412 BRANCH(IsArrayLengthWritable(glue, receiver), &isArrLenWritable, ¬ArrLenWritable);
4413 Bind(&isArrLenWritable);
4414 {
4415 SetArrayLength(glue, receiver, Int32Add(index, Int32(1)));
4416 Label indexGreater(env);
4417 BRANCH(Int32GreaterThan(index, oldLen), &indexGreater, ¬Array);
4418 Bind(&indexGreater);
4419 kind = Int32(Elements::ToUint(ElementsKind::HOLE));
4420 Jump(¬Array);
4421 }
4422 Bind(¬ArrLenWritable);
4423 result = False();
4424 Jump(&exit);
4425 }
4426 }
4427 Bind(¬Array);
4428 {
4429 NotifyArrayPrototypeChangedGuardians(glue, receiver);
4430 GateRef hclass = LoadHClass(glue, receiver);
4431 GateRef elements = GetElementsArray(glue, receiver);
4432 Label isDicMode(env);
4433 Label notDicMode(env);
4434 BRANCH(IsDictionaryElement(hclass), &isDicMode, ¬DicMode);
4435 Bind(&isDicMode);
4436 {
4437 GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
4438 { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedFalse() });
4439 SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
4440 result = True();
4441 Jump(&exit);
4442 }
4443 Bind(¬DicMode);
4444 {
4445 GateRef capacity = GetLengthOfTaggedArray(elements);
4446 GateRef notDefault = BoolNot(IsDefaultAttribute(attr));
4447 Label indexGreaterLen(env);
4448 Label notGreaterLen(env);
4449 BRANCH(BitOr(notDefault, Int32GreaterThanOrEqual(index, capacity)), &indexGreaterLen, ¬GreaterLen);
4450 Bind(&indexGreaterLen);
4451 {
4452 Label isTransToDict(env);
4453 Label notTransToDict(env);
4454 BRANCH(LogicOrBuilder(env).Or(notDefault).Or(ShouldTransToDict(capacity, index)).Done(),
4455 &isTransToDict, ¬TransToDict);
4456 Bind(&isTransToDict);
4457 {
4458 GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
4459 { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedTrue() });
4460 Label isPendingException(env);
4461 Label noPendingException(env);
4462 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
4463 Bind(&isPendingException);
4464 {
4465 result = False();
4466 Jump(&exit);
4467 }
4468 Bind(&noPendingException);
4469 SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
4470 result = True();
4471 Jump(&exit);
4472 }
4473 Bind(¬TransToDict);
4474 {
4475 GrowElementsCapacity(glue, receiver, Int32Add(index, Int32(1)));
4476 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
4477 result = True();
4478 Jump(&exit);
4479 }
4480 }
4481 Bind(¬GreaterLen);
4482 {
4483 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
4484 result = True();
4485 Jump(&exit);
4486 }
4487 }
4488 }
4489 Bind(&exit);
4490 auto ret = *result;
4491 env->SubCfgExit();
4492 return ret;
4493 }
4494
GrowElementsCapacity(GateRef glue,GateRef receiver,GateRef capacity)4495 GateRef StubBuilder::GrowElementsCapacity(GateRef glue, GateRef receiver, GateRef capacity)
4496 {
4497 auto env = GetEnvironment();
4498 Label subEntry(env);
4499 env->SubCfgEntry(&subEntry);
4500 DEFVARIABLE(newElements, VariableType::JS_ANY(), Hole());
4501 NewObjectStubBuilder newBuilder(this);
4502 GateRef newCapacity = ComputeElementCapacity(capacity);
4503 GateRef elements = GetElementsArray(glue, receiver);
4504 newElements = newBuilder.ExtendArrayWithOptimizationCheck(glue, elements, newCapacity);
4505 SetElementsArray(VariableType::JS_POINTER(), glue, receiver, *newElements);
4506 auto ret = *newElements;
4507 env->SubCfgExit();
4508 return ret;
4509 }
4510
ShouldTransToDict(GateRef capacity,GateRef index)4511 GateRef StubBuilder::ShouldTransToDict(GateRef capacity, GateRef index)
4512 {
4513 auto env = GetEnvironment();
4514 Label subEntry(env);
4515 env->SubCfgEntry(&subEntry);
4516 Label exit(env);
4517 DEFVARIABLE(result, VariableType::BOOL(), True());
4518 Label isGreaterThanCapcity(env);
4519 Label notGreaterThanCapcity(env);
4520 BRANCH(Int32GreaterThanOrEqual(index, capacity), &isGreaterThanCapcity, ¬GreaterThanCapcity);
4521 Bind(&isGreaterThanCapcity);
4522 {
4523 Label isLessThanMax(env);
4524 Label notLessThanMax(env);
4525 BRANCH(Int32LessThanOrEqual(Int32Sub(index, capacity),
4526 Int32(JSObject::MAX_GAP)), &isLessThanMax, ¬LessThanMax);
4527 Bind(&isLessThanMax);
4528 {
4529 Label isLessThanInt32Max(env);
4530 Label notLessThanInt32Max(env);
4531 BRANCH(Int32LessThan(index, Int32(INT32_MAX)), &isLessThanInt32Max, ¬LessThanInt32Max);
4532 Bind(&isLessThanInt32Max);
4533 {
4534 Label isLessThanMin(env);
4535 Label notLessThanMin(env);
4536 BRANCH(Int32LessThan(capacity, Int32(JSObject::MIN_GAP)), &isLessThanMin, ¬LessThanMin);
4537 Bind(&isLessThanMin);
4538 {
4539 result = False();
4540 Jump(&exit);
4541 }
4542 Bind(¬LessThanMin);
4543 {
4544 result = Int32GreaterThan(index, Int32Mul(capacity, Int32(JSObject::FAST_ELEMENTS_FACTOR)));
4545 Jump(&exit);
4546 }
4547 }
4548 Bind(¬LessThanInt32Max);
4549 {
4550 result = True();
4551 Jump(&exit);
4552 }
4553 }
4554 Bind(¬LessThanMax);
4555 {
4556 result = True();
4557 Jump(&exit);
4558 }
4559 }
4560 Bind(¬GreaterThanCapcity);
4561 {
4562 result = False();
4563 Jump(&exit);
4564 }
4565 Bind(&exit);
4566 auto ret = *result;
4567 env->SubCfgExit();
4568 return ret;
4569 }
4570
NotifyArrayPrototypeChangedGuardians(GateRef glue,GateRef receiver)4571 void StubBuilder::NotifyArrayPrototypeChangedGuardians(GateRef glue, GateRef receiver)
4572 {
4573 auto env = GetEnvironment();
4574 Label subEntry(env);
4575 env->SubCfgEntry(&subEntry);
4576 Label exit(env);
4577 GateRef globalEnv = GetCurrentGlobalEnv();
4578 GateRef guardians = GetArrayElementsGuardians(globalEnv);
4579
4580 Label isGuardians(env);
4581 BRANCH(Equal(guardians, True()), &isGuardians, &exit);
4582 Bind(&isGuardians);
4583 {
4584 GateRef hclass = LoadHClass(glue, receiver);
4585 Label isPrototype(env);
4586 BRANCH(BitOr(IsPrototypeHClass(hclass), IsJsArray(glue, receiver)), &isPrototype, &exit);
4587 Bind(&isPrototype);
4588 {
4589 Label isEnvPrototype(env);
4590 GateRef isEnvPrototypeCheck = LogicOrBuilder(env)
4591 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
4592 GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX), receiver))
4593 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
4594 GlobalEnv::ARRAY_PROTOTYPE_INDEX), receiver))
4595 .Done();
4596 BRANCH(isEnvPrototypeCheck, &isEnvPrototype, &exit);
4597 Bind(&isEnvPrototype);
4598 CallRuntime(glue, RTSTUB_ID(NotifyArrayPrototypeChanged), {});
4599 SetArrayElementsGuardians(glue, globalEnv, False());
4600 Jump(&exit);
4601 }
4602 }
4603 Bind(&exit);
4604 env->SubCfgExit();
4605 return;
4606 }
4607
IsArrayLengthWritable(GateRef glue,GateRef receiver)4608 GateRef StubBuilder::IsArrayLengthWritable(GateRef glue, GateRef receiver)
4609 {
4610 auto env = GetEnvironment();
4611 Label subEntry(env);
4612 env->SubCfgEntry(&subEntry);
4613 Label exit(env);
4614 GateRef hclass = LoadHClass(glue, receiver);
4615 Label isDicMode(env);
4616 Label notDicMode(env);
4617 DEFVARIABLE(result, VariableType::BOOL(), False());
4618 BRANCH_UNLIKELY(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
4619 Bind(&isDicMode);
4620 {
4621 GateRef array = GetPropertiesArray(glue, receiver);
4622 GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
4623 ConstantIndex::LENGTH_STRING_INDEX);
4624 GateRef entry = CallCommonStub(glue, CommonStubCSigns::FindEntryFromNameDictionary,
4625 {glue, array, lengthString});
4626 Label notNegtiveOne(env);
4627 Label isNegtiveOne(env);
4628 BRANCH(Int32NotEqual(entry, Int32(-1)), ¬NegtiveOne, &isNegtiveOne);
4629 Bind(¬NegtiveOne);
4630 {
4631 GateRef attr = GetAttributesFromDictionary<NameDictionary>(glue, array, entry);
4632 result = IsWritable(attr);
4633 Jump(&exit);
4634 }
4635 Bind(&isNegtiveOne);
4636 {
4637 GateRef attr1 = Int64(PropertyAttributes::GetDefaultAttributes());
4638 result = IsWritable(attr1);
4639 Jump(&exit);
4640 }
4641 }
4642 Bind(¬DicMode);
4643 {
4644 result = IsArrayLengthWritableForNonDictMode(glue, receiver);
4645 Jump(&exit);
4646 }
4647 Bind(&exit);
4648 auto ret = *result;
4649 env->SubCfgExit();
4650 return ret;
4651 }
4652
IsArrayLengthWritableForNonDictMode(GateRef glue,GateRef receiver)4653 GateRef StubBuilder::IsArrayLengthWritableForNonDictMode(GateRef glue, GateRef receiver)
4654 {
4655 auto env = GetEnvironment();
4656 Label subEntry(env);
4657 env->SubCfgEntry(&subEntry);
4658 Label exit(env);
4659 DEFVARIABLE(result, VariableType::BOOL(), False());
4660 GateRef hclass = LoadHClass(glue, receiver);
4661 GateRef layoutInfo = GetLayoutFromHClass(glue, hclass);
4662 GateRef attr = GetPropAttrFromLayoutInfo(glue, layoutInfo, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4663 result = IsWritable(attr);
4664 auto ret = *result;
4665 env->SubCfgExit();
4666 return ret;
4667 }
4668
CheckHClassForRep(GateRef glue,GateRef hclass,GateRef value)4669 GateRef StubBuilder::CheckHClassForRep(GateRef glue, GateRef hclass, GateRef value)
4670 {
4671 auto env = GetEnvironment();
4672 Label subEntry(env);
4673 env->SubCfgEntry(&subEntry);
4674 Label exit(env);
4675 Label isAOTHClass(env);
4676 DEFVARIABLE(result, VariableType::BOOL(), Boolean(true));
4677 Branch(IsAOTHClass(hclass), &isAOTHClass, &exit);
4678 Bind(&isAOTHClass);
4679 {
4680 GateRef propNums = GetNumberOfPropsFromHClass(hclass);
4681 GateRef last = Int32Sub(propNums, Int32(1));
4682 GateRef layoutInfo = GetLayoutFromHClass(glue, hclass);
4683 GateRef cachedAttr = GetPropAttrFromLayoutInfo(glue, layoutInfo, last);
4684 GateRef lastRep = GetRepInPropAttr(cachedAttr);
4685 Label repIsInt(env);
4686 Label repIsNotInt(env);
4687 Label repIsDouble(env);
4688 Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::INT))), &repIsInt, &repIsNotInt);
4689 Bind(&repIsInt);
4690 {
4691 GateRef valueRep = TranslateToRep(value);
4692 Label valueRepIsNotInt(env);
4693 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4694 Bind(&valueRepIsNotInt);
4695 {
4696 result = Boolean(false);
4697 Jump(&exit);
4698 }
4699 }
4700 Bind(&repIsNotInt);
4701 {
4702 Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &repIsDouble, &exit);
4703 Bind(&repIsDouble);
4704 GateRef valueRep = TranslateToRep(value);
4705 Label valueRepIsNotInt(env);
4706 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4707 Bind(&valueRepIsNotInt);
4708 {
4709 Label valueRepIsNotDouble(env);
4710 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &exit,
4711 &valueRepIsNotDouble);
4712 Bind(&valueRepIsNotDouble);
4713 {
4714 result = Boolean(false);
4715 Jump(&exit);
4716 }
4717 }
4718 }
4719 }
4720 Bind(&exit);
4721 auto ret = *result;
4722 env->SubCfgExit();
4723 return ret;
4724 }
4725
FindTransitions(GateRef glue,GateRef hclass,GateRef key,GateRef metaData,GateRef value)4726 GateRef StubBuilder::FindTransitions(GateRef glue, GateRef hclass, GateRef key, GateRef metaData, GateRef value)
4727 {
4728 auto env = GetEnvironment();
4729 Label entry(env);
4730 env->SubCfgEntry(&entry);
4731 Label exit(env);
4732 GateRef transition = GetTransitionsFromHClass(glue, hclass);
4733 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
4734
4735 Label notUndefined(env);
4736 BRANCH(Equal(transition, Undefined()), &exit, ¬Undefined);
4737 Bind(¬Undefined);
4738 {
4739 Label isWeak(env);
4740 Label notWeak(env);
4741 BRANCH(TaggedIsWeak(transition), &isWeak, ¬Weak);
4742 Bind(&isWeak);
4743 {
4744 GateRef transitionHClass = LoadObjectFromWeakRef(transition);
4745 GateRef propNums = GetNumberOfPropsFromHClass(transitionHClass);
4746 GateRef last = Int32Sub(propNums, Int32(1));
4747 GateRef layoutInfo = GetLayoutFromHClass(glue, transitionHClass);
4748 GateRef cachedKey = GetKeyFromLayoutInfo(glue, layoutInfo, last);
4749 GateRef cachedAttr = GetPropAttrFromLayoutInfo(glue, layoutInfo, last);
4750 GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
4751 Label keyMatch(env);
4752 Label isMatch(env);
4753 Label repMatch(env);
4754 BRANCH(Equal(cachedKey, key), &keyMatch, &exit);
4755 Bind(&keyMatch);
4756 {
4757 BRANCH(Int32Equal(metaData, cachedMetaData), &isMatch, &exit);
4758 Bind(&isMatch);
4759 {
4760 BRANCH(CheckHClassForRep(glue, transitionHClass, value), &repMatch, &exit);
4761 Bind(&repMatch);
4762 result = transitionHClass;
4763 Jump(&exit);
4764 }
4765 }
4766 }
4767 Bind(¬Weak);
4768 {
4769 // need to find from dictionary
4770 GateRef entryA = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
4771 Label isFound(env);
4772 BRANCH(Int32NotEqual(entryA, Int32(-1)), &isFound, &exit);
4773 Bind(&isFound);
4774 auto cachedValue = GetValueFromDictionary<TransitionsDictionary>(glue, transition, entryA);
4775 Label valueNotUndefined(env);
4776 Label repMatch(env);
4777 BRANCH(Int64NotEqual(cachedValue, Undefined()), &valueNotUndefined, &exit);
4778 Bind(&valueNotUndefined);
4779 {
4780 GateRef newHClass = LoadObjectFromWeakRef(cachedValue);
4781 BRANCH(CheckHClassForRep(glue, newHClass, value), &repMatch, &exit);
4782 Bind(&repMatch);
4783 result = newHClass;
4784 Jump(&exit);
4785 }
4786 }
4787 }
4788 Bind(&exit);
4789 auto ret = *result;
4790 env->SubCfgExit();
4791 return ret;
4792 }
4793
SetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics,bool mayThrow)4794 GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn,
4795 ProfileOperation callback, bool defineSemantics, bool mayThrow)
4796 {
4797 auto env = GetEnvironment();
4798 Label entry(env);
4799 env->SubCfgEntry(&entry);
4800 DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
4801 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
4802 Label exit(env);
4803 Label ifEnd(env);
4804 Label loopHead(env);
4805 Label loopEnd(env);
4806 Label loopExit(env);
4807 Label afterLoop(env);
4808 Label isJsCOWArray(env);
4809 Label isNotJsCOWArray(env);
4810 Label setElementsArray(env);
4811 if (!useOwn && !defineSemantics) {
4812 Jump(&loopHead);
4813 LoopBegin(&loopHead);
4814 }
4815 GateRef hclass = LoadHClass(glue, *holder);
4816 GateRef jsType = GetObjectType(hclass);
4817 Label isSpecialIndex(env);
4818 Label notSpecialIndex(env);
4819 BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
4820 Bind(&isSpecialIndex);
4821 {
4822 // TypeArray
4823 Label isFastTypeArray(env);
4824 Label notFastTypeArray(env);
4825 Label checkIsOnPrototypeChain(env);
4826 Label notTypedArrayProto(env);
4827 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, ¬TypedArrayProto);
4828 Bind(¬TypedArrayProto);
4829 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
4830 Bind(&isFastTypeArray);
4831 {
4832 BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
4833 Bind(&checkIsOnPrototypeChain);
4834 {
4835 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
4836 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
4837 Jump(&exit);
4838 }
4839 }
4840 Bind(¬FastTypeArray);
4841 returnValue = Hole();
4842 Jump(&exit);
4843 }
4844 Bind(¬SpecialIndex);
4845 {
4846 GateRef elements = GetElementsArray(glue, *holder);
4847 Label isDictionaryElement(env);
4848 Label notDictionaryElement(env);
4849 BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
4850 Bind(¬DictionaryElement);
4851 {
4852 Label isReceiver(env);
4853 if (useOwn) {
4854 BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
4855 } else {
4856 BRANCH(Equal(*holder, receiver), &isReceiver, &afterLoop);
4857 }
4858 Bind(&isReceiver);
4859 {
4860 GateRef length = GetLengthOfTaggedArray(elements);
4861 Label inRange(env);
4862 if (useOwn) {
4863 BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
4864 } else {
4865 BRANCH(Int64LessThan(index, length), &inRange, &loopExit);
4866 }
4867 Bind(&inRange);
4868 {
4869 GateRef value1 = GetTaggedValueWithElementsKind(glue, *holder, index);
4870 Label notHole(env);
4871 if (useOwn) {
4872 BRANCH(Int64NotEqual(value1, Hole()), ¬Hole, &ifEnd);
4873 } else {
4874 BRANCH(Int64NotEqual(value1, Hole()), ¬Hole, &loopExit);
4875 }
4876 Bind(¬Hole);
4877 {
4878 BRANCH(IsJsCOWArray(glue, *holder), &isJsCOWArray, &isNotJsCOWArray);
4879 Bind(&isJsCOWArray);
4880 {
4881 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
4882 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4883 Int32(Elements::ToUint(ElementsKind::NONE)));
4884 returnValue = Undefined();
4885 Jump(&exit);
4886 }
4887 Bind(&isNotJsCOWArray);
4888 {
4889 Jump(&setElementsArray);
4890 }
4891 Bind(&setElementsArray);
4892 {
4893 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4894 Int32(Elements::ToUint(ElementsKind::NONE)));
4895 returnValue = Undefined();
4896 Jump(&exit);
4897 }
4898 }
4899 }
4900 }
4901 }
4902 Bind(&isDictionaryElement);
4903 {
4904 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
4905 Label negtiveOne(env);
4906 Label notNegtiveOne(env);
4907 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
4908 Bind(¬NegtiveOne);
4909 {
4910 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(glue, elements, entryA);
4911 Label isWritandConfig(env);
4912 Label notWritandConfig(env);
4913 BRANCH(BitOr(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
4914 IsJSShared(glue, *holder)), &isWritandConfig, ¬WritandConfig);
4915 Bind(&isWritandConfig);
4916 {
4917 Label isAccessor(env);
4918 Label notAccessor(env);
4919 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
4920 Bind(&isAccessor);
4921 if (defineSemantics) {
4922 Jump(&exit);
4923 } else {
4924 GateRef accessor = GetValueFromDictionary<NumberDictionary>(glue, elements, entryA);
4925 Label shouldCall(env);
4926 BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
4927 Bind(&shouldCall);
4928 {
4929 returnValue = CallSetterHelper(glue, receiver, accessor, value, callback, mayThrow);
4930 Jump(&exit);
4931 }
4932 }
4933 Bind(¬Accessor);
4934 {
4935 Label holdEqualsRecv(env);
4936 if (useOwn) {
4937 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4938 } else {
4939 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
4940 }
4941 Bind(&holdEqualsRecv);
4942 {
4943 UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
4944 returnValue = Undefined();
4945 Jump(&exit);
4946 }
4947 }
4948 }
4949 Bind(¬WritandConfig);
4950 {
4951 returnValue = Hole();
4952 Jump(&exit);
4953 }
4954 }
4955 Bind(&negtiveOne);
4956 returnValue = Hole();
4957 Jump(&exit);
4958 }
4959 }
4960 if (useOwn) {
4961 Bind(&ifEnd);
4962 } else {
4963 Bind(&loopExit);
4964 {
4965 holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
4966 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4967 }
4968 Bind(&loopEnd);
4969 LoopEndWithCheckSafePoint(&loopHead, env, glue);
4970 Bind(&afterLoop);
4971 }
4972 Label isExtensible(env);
4973 Label notExtensible(env);
4974 Label throwNotExtensible(env);
4975 BRANCH(IsExtensible(glue, receiver), &isExtensible, ¬Extensible);
4976 Bind(¬Extensible);
4977 {
4978 // fixme(hzzhouzebin) this makes SharedArray's frozen no sense.
4979 BRANCH(IsJsSArray(glue, receiver), &isExtensible, &throwNotExtensible);
4980 }
4981 Bind(&isExtensible);
4982 {
4983 Label success(env);
4984 Label failed(env);
4985 BRANCH(AddElementInternal(glue, receiver, index, value, Int64(PropertyAttributes::GetDefaultAttributes())),
4986 &success, &failed);
4987 Bind(&success);
4988 {
4989 returnValue = Undefined();
4990 Jump(&exit);
4991 }
4992 Bind(&failed);
4993 {
4994 returnValue = Exception();
4995 Jump(&exit);
4996 }
4997 }
4998 Bind(&throwNotExtensible);
4999 {
5000 if (mayThrow) {
5001 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5002 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5003 returnValue = Exception();
5004 } else {
5005 returnValue = TaggedFalse();
5006 }
5007 Jump(&exit);
5008 }
5009 Bind(&exit);
5010 auto ret = *returnValue;
5011 env->SubCfgExit();
5012 return ret;
5013 }
5014
DefinePropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)5015 GateRef StubBuilder::DefinePropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
5016 {
5017 auto env = GetEnvironment();
5018 Label entry(env);
5019 env->SubCfgEntry(&entry);
5020 DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
5021 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
5022 Label exit(env);
5023 Label ifEnd(env);
5024 Label loopHead(env);
5025 Label loopEnd(env);
5026 Label loopExit(env);
5027 Label afterLoop(env);
5028 Label isJsCOWArray(env);
5029 Label isNotJsCOWArray(env);
5030 Label setElementsArray(env);
5031 GateRef hclass = LoadHClass(glue, *holder);
5032 GateRef jsType = GetObjectType(hclass);
5033 Label isSpecialIndex(env);
5034 Label notSpecialIndex(env);
5035 BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
5036 Bind(&isSpecialIndex);
5037 {
5038 Label isFastTypeArray(env);
5039 Label notFastTypeArray(env);
5040 Label checkIsOnPrototypeChain(env);
5041 Label notTypedArrayProto(env);
5042 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, ¬TypedArrayProto);
5043 Bind(¬TypedArrayProto);
5044 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
5045 Bind(&isFastTypeArray);
5046 {
5047 BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
5048 Bind(&checkIsOnPrototypeChain);
5049 {
5050 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
5051 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
5052 Jump(&exit);
5053 }
5054 }
5055 Bind(¬FastTypeArray);
5056 returnValue = Hole();
5057 Jump(&exit);
5058 }
5059 Bind(¬SpecialIndex);
5060 {
5061 GateRef elements = GetElementsArray(glue, *holder);
5062 Label isDictionaryElement(env);
5063 Label notDictionaryElement(env);
5064 BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
5065 Bind(¬DictionaryElement);
5066 {
5067 Label isReceiver(env);
5068 BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
5069 Bind(&isReceiver);
5070 {
5071 GateRef length = GetLengthOfTaggedArray(elements);
5072 Label inRange(env);
5073 BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
5074 Bind(&inRange);
5075 {
5076 GateRef value1 = GetTaggedValueWithElementsKind(glue, *holder, index);
5077 Label notHole(env);
5078 BRANCH(Int64NotEqual(value1, Hole()), ¬Hole, &ifEnd);
5079 Bind(¬Hole);
5080 {
5081 BRANCH(IsJsCOWArray(glue, *holder), &isJsCOWArray, &isNotJsCOWArray);
5082 Bind(&isJsCOWArray);
5083 {
5084 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
5085 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
5086 Int32(Elements::ToUint(ElementsKind::NONE)));
5087 returnValue = Undefined();
5088 Jump(&exit);
5089 }
5090 Bind(&isNotJsCOWArray);
5091 {
5092 Jump(&setElementsArray);
5093 }
5094 Bind(&setElementsArray);
5095 {
5096 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
5097 Int32(Elements::ToUint(ElementsKind::NONE)));
5098 returnValue = Undefined();
5099 Jump(&exit);
5100 }
5101 }
5102 }
5103 }
5104 }
5105 Bind(&isDictionaryElement);
5106 {
5107 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
5108 Label negtiveOne(env);
5109 Label notNegtiveOne(env);
5110 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
5111 Bind(¬NegtiveOne);
5112 {
5113 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(glue, elements, entryA);
5114 Label isWritandConfig(env);
5115 Label notWritandConfig(env);
5116 BRANCH(BitOr(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
5117 IsJSShared(glue, *holder)), &isWritandConfig, ¬WritandConfig);
5118 Bind(&isWritandConfig);
5119 {
5120 Label notAccessor(env);
5121 BRANCH(IsAccessor(attr), &exit, ¬Accessor);
5122 Bind(¬Accessor);
5123 {
5124 Label holdEqualsRecv(env);
5125 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
5126 Bind(&holdEqualsRecv);
5127 {
5128 UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
5129 returnValue = Undefined();
5130 Jump(&exit);
5131 }
5132 }
5133 }
5134 Bind(¬WritandConfig);
5135 {
5136 returnValue = Hole();
5137 Jump(&exit);
5138 }
5139 }
5140 Bind(&negtiveOne);
5141 returnValue = Hole();
5142 Jump(&exit);
5143 }
5144 }
5145 Bind(&ifEnd);
5146 Label isExtensible(env);
5147 Label notExtensible(env);
5148 Label throwNotExtensible(env);
5149 BRANCH(IsExtensible(glue, receiver), &isExtensible, ¬Extensible);
5150 Bind(¬Extensible);
5151 {
5152 BRANCH(IsJsSArray(glue, receiver), &isExtensible, &throwNotExtensible);
5153 }
5154 Bind(&isExtensible);
5155 {
5156 Label success(env);
5157 Label failed(env);
5158 BRANCH(AddElementInternal(glue, receiver, index, value, Int64(PropertyAttributes::GetDefaultAttributes())),
5159 &success, &failed);
5160 Bind(&success);
5161 {
5162 returnValue = Undefined();
5163 Jump(&exit);
5164 }
5165 Bind(&failed);
5166 {
5167 returnValue = Exception();
5168 Jump(&exit);
5169 }
5170 }
5171 Bind(&throwNotExtensible);
5172 {
5173 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5174 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5175 returnValue = Exception();
5176 Jump(&exit);
5177 }
5178 Bind(&exit);
5179 auto ret = *returnValue;
5180 env->SubCfgExit();
5181 return ret;
5182 }
5183
SetPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,GateRef isInternal,ProfileOperation callback,bool canUseIsInternal,bool defineSemantics,bool mayThrow)5184 GateRef StubBuilder::SetPropertyByName(GateRef glue,
5185 GateRef receiver,
5186 GateRef key,
5187 GateRef value,
5188 bool useOwn,
5189 GateRef isInternal,
5190 ProfileOperation callback,
5191 bool canUseIsInternal,
5192 bool defineSemantics,
5193 bool mayThrow)
5194 {
5195 auto env = GetEnvironment();
5196 Label entryPass(env);
5197 env->SubCfgEntry(&entryPass);
5198 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5199 DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
5200 DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
5201 Label exit(env);
5202 Label ifEnd(env);
5203 Label loopHead(env);
5204 Label loopEnd(env);
5205 Label loopExit(env);
5206 Label afterLoop(env);
5207 Label findProperty(env);
5208 if (!useOwn) {
5209 Jump(&loopHead);
5210 LoopBegin(&loopHead);
5211 }
5212 GateRef hclass = LoadHClass(glue, *holder);
5213 GateRef jsType = GetObjectType(hclass);
5214 Label isSIndexObj(env);
5215 Label notSIndexObj(env);
5216 BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
5217 Bind(&isSIndexObj);
5218 {
5219 Label isFastTypeArray(env);
5220 Label notFastTypeArray(env);
5221 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
5222 Bind(&isFastTypeArray);
5223 {
5224 result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
5225 Label isNull(env);
5226 Label notNull(env);
5227 BRANCH(TaggedIsNull(*result), &isNull, ¬Null);
5228 Bind(&isNull);
5229 {
5230 result = Hole();
5231 Jump(&exit);
5232 }
5233 Bind(¬Null);
5234 BRANCH(TaggedIsHole(*result), ¬SIndexObj, &exit);
5235 }
5236 Bind(¬FastTypeArray);
5237
5238 Label isSpecialContainer(env);
5239 Label notSpecialContainer(env);
5240 BRANCH(IsArrayListOrVector(jsType), &isSpecialContainer, ¬SpecialContainer);
5241 Bind(&isSpecialContainer);
5242 {
5243 if (mayThrow) {
5244 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
5245 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5246 result = Exception();
5247 } else {
5248 result = TaggedFalse();
5249 }
5250 Jump(&exit);
5251 }
5252 Bind(¬SpecialContainer);
5253 {
5254 #if ENABLE_NEXT_OPTIMIZATION
5255 Label isJsProxy(env);
5256 Label notJsProxy(env);
5257 BRANCH(IsJSProxy(jsType), &isJsProxy, ¬JsProxy);
5258 Bind(&isJsProxy);
5259 {
5260 if (defineSemantics) {
5261 Jump(&exit);
5262 } else {
5263 Label returnException(env);
5264 Label noPendingException(env);
5265 if (mayThrow) {
5266 result = CallCommonStub(glue, CommonStubCSigns::JSProxySetProperty,
5267 {glue, *holder, key, value, receiver, GetCurrentGlobalEnv()});
5268 } else {
5269 result = CallCommonStub(glue, CommonStubCSigns::JSProxySetPropertyNoThrow,
5270 {glue, *holder, key, value, receiver, GetCurrentGlobalEnv()});
5271 }
5272 BRANCH(HasPendingException(glue), &returnException, &exit);
5273 Bind(&returnException);
5274 {
5275 result = Exception();
5276 Jump(&exit);
5277 }
5278 }
5279 }
5280 Bind(¬JsProxy);
5281 {
5282 result = Hole();
5283 Jump(&exit);
5284 }
5285 #else
5286 result = Hole();
5287 Jump(&exit);
5288 #endif
5289 }
5290 }
5291 Bind(¬SIndexObj);
5292 {
5293 if (canUseIsInternal) {
5294 if (useOwn) {
5295 BRANCH(isInternal, &findProperty, &ifEnd);
5296 } else {
5297 BRANCH(isInternal, &findProperty, &loopExit);
5298 }
5299 } else {
5300 Jump(&findProperty);
5301 }
5302 Label isDicMode(env);
5303 Label notDicMode(env);
5304 Bind(&findProperty);
5305 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
5306 Bind(¬DicMode);
5307 {
5308 GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
5309 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
5310 GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
5311 Label hasEntry(env);
5312 if (useOwn || defineSemantics) {
5313 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
5314 } else {
5315 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &loopExit);
5316 }
5317 Bind(&hasEntry);
5318 {
5319 GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entry);
5320 Label isAccessor(env);
5321 Label notAccessor(env);
5322 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
5323 Bind(&isAccessor);
5324 if (defineSemantics) {
5325 Jump(&exit);
5326 } else {
5327 GateRef accessor = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5328 Label shouldCall(env);
5329 BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
5330 Bind(&shouldCall);
5331 {
5332 result = CallSetterHelper(glue, receiver, accessor, value, callback, mayThrow);
5333 Jump(&exit);
5334 }
5335 }
5336 Bind(¬Accessor);
5337 {
5338 Label writable(env);
5339 Label notWritable(env);
5340 BRANCH(IsWritable(attr), &writable, ¬Writable);
5341 Bind(¬Writable);
5342 if (defineSemantics) {
5343 Jump(&exit);
5344 } else {
5345 if (mayThrow) {
5346 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5347 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5348 result = Exception();
5349 } else {
5350 result = TaggedFalse();
5351 }
5352 Jump(&exit);
5353 }
5354 Bind(&writable);
5355 {
5356 Label isAOT(env);
5357 Label notAOT(env);
5358 BRANCH(IsAOTHClass(hclass), &isAOT, ¬AOT);
5359 Bind(&isAOT);
5360 {
5361 GateRef attrVal = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5362 Label attrValIsHole(env);
5363 BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬AOT);
5364 Bind(&attrValIsHole);
5365 {
5366 Label storeReceiverHoleEntry(env);
5367 Label noNeedStore(env);
5368 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
5369 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
5370 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
5371 &storeReceiverHoleEntry, &noNeedStore);
5372 Bind(&storeReceiverHoleEntry);
5373 {
5374 receiverHoleEntry = entry;
5375 Jump(&noNeedStore);
5376 }
5377 Bind(&noNeedStore);
5378 if (useOwn || defineSemantics) {
5379 Jump(&ifEnd);
5380 } else {
5381 Jump(&loopExit);
5382 }
5383 }
5384 }
5385 Bind(¬AOT);
5386 Label holdEqualsRecv(env);
5387 if (useOwn || defineSemantics) {
5388 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
5389 } else {
5390 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
5391 }
5392 Bind(&holdEqualsRecv);
5393 {
5394 Label isJSShared(env);
5395 Label executeSetProp(env);
5396 BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5397 Bind(&isJSShared);
5398 {
5399 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5400 Label executeSharedSetProp(env);
5401 SharedObjectStoreBarrierWithTypeCheck(false, &result, glue, attr, value, &actualValue,
5402 &executeSharedSetProp, &exit);
5403 Bind(&executeSharedSetProp);
5404 {
5405 JSObjectSetProperty(glue, *holder, hclass, attr, key, *actualValue);
5406 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr,
5407 *actualValue, callback);
5408 result = Undefined();
5409 Jump(&exit);
5410 }
5411 }
5412 Bind(&executeSetProp);
5413 {
5414 JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
5415 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value,
5416 callback);
5417 result = Undefined();
5418 Jump(&exit);
5419 }
5420 }
5421 }
5422 }
5423 }
5424 }
5425 Bind(&isDicMode);
5426 {
5427 GateRef array = GetPropertiesArray(glue, *holder);
5428 GateRef entry1 = FindEntryFromHashTable<NameDictionary>(glue, array, key);
5429 Label notNegtiveOne(env);
5430 if (useOwn || defineSemantics) {
5431 BRANCH(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &ifEnd);
5432 } else {
5433 BRANCH(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &loopExit);
5434 }
5435 Bind(¬NegtiveOne);
5436 {
5437 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(glue, array, entry1);
5438 Label isAccessor1(env);
5439 Label notAccessor1(env);
5440 BRANCH(IsAccessor(attr1), &isAccessor1, ¬Accessor1);
5441 Bind(&isAccessor1);
5442 if (defineSemantics) {
5443 Jump(&exit);
5444 } else {
5445 GateRef accessor1 = GetValueFromDictionary<NameDictionary>(glue, array, entry1);
5446 Label shouldCall1(env);
5447 BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor1, attr1), &shouldCall1, ¬Accessor1);
5448 Bind(&shouldCall1);
5449 {
5450 result = CallSetterHelper(glue, receiver, accessor1, value, callback, mayThrow);
5451 Jump(&exit);
5452 }
5453 }
5454 Bind(¬Accessor1);
5455 {
5456 Label writable1(env);
5457 Label notWritable1(env);
5458 BRANCH(IsWritable(attr1), &writable1, ¬Writable1);
5459 Bind(¬Writable1);
5460 if (defineSemantics) {
5461 Jump(&exit);
5462 } else {
5463 if (mayThrow) {
5464 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5465 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5466 result = Exception();
5467 } else {
5468 result = TaggedFalse();
5469 }
5470 Jump(&exit);
5471 }
5472 Bind(&writable1);
5473 {
5474 Label holdEqualsRecv1(env);
5475 if (useOwn) {
5476 BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
5477 } else {
5478 BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &afterLoop);
5479 }
5480 Bind(&holdEqualsRecv1);
5481 {
5482 Label isJSShared(env);
5483 Label executeSetProp(env);
5484 BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5485 Bind(&isJSShared);
5486 {
5487 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5488 Label executeSharedSetProp(env);
5489 SharedObjectStoreBarrierWithTypeCheck(true, &result, glue, attr1, value, &actualValue,
5490 &executeSharedSetProp, &exit);
5491 Bind(&executeSharedSetProp);
5492 {
5493 UpdateValueInDict<NameDictionary>(glue, array, entry1, *actualValue);
5494 result = Undefined();
5495 Jump(&exit);
5496 }
5497 }
5498 Bind(&executeSetProp);
5499 {
5500 UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
5501 result = Undefined();
5502 Jump(&exit);
5503 }
5504 }
5505 }
5506 }
5507 }
5508 }
5509 }
5510 if (useOwn || defineSemantics) {
5511 Bind(&ifEnd);
5512 } else {
5513 Bind(&loopExit);
5514 {
5515 holder = GetPrototypeFromHClass(glue, LoadHClass(glue, *holder));
5516 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
5517 }
5518 Bind(&loopEnd);
5519 LoopEndWithCheckSafePoint(&loopHead, env, glue);
5520 Bind(&afterLoop);
5521 }
5522 Label holeEntryNotNegtiveOne(env);
5523 Label holeEntryIfEnd(env);
5524 BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
5525 Bind(&holeEntryNotNegtiveOne);
5526 {
5527 GateRef receiverHClass = LoadHClass(glue, receiver);
5528 GateRef receiverLayoutInfo = GetLayoutFromHClass(glue, receiverHClass);
5529 GateRef holeAttr = GetPropAttrFromLayoutInfo(glue, receiverLayoutInfo, *receiverHoleEntry);
5530 JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
5531 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
5532 result = Undefined();
5533 Jump(&exit);
5534 }
5535 Bind(&holeEntryIfEnd);
5536
5537 Label extensible(env);
5538 Label inextensible(env);
5539 BRANCH(IsExtensible(glue, receiver), &extensible, &inextensible);
5540 Bind(&inextensible);
5541 {
5542 if (mayThrow) {
5543 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5544 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
5545 result = Exception();
5546 } else {
5547 result = TaggedFalse();
5548 }
5549 Jump(&exit);
5550 }
5551 Bind(&extensible);
5552 {
5553 result = AddPropertyByName(glue, receiver, key, value,
5554 Int64(PropertyAttributes::GetDefaultAttributes()), callback);
5555 Jump(&exit);
5556 }
5557 Bind(&exit);
5558 auto ret = *result;
5559 env->SubCfgExit();
5560 return ret;
5561 }
5562
DefinePropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef isInternal,GateRef SCheckModelIsCHECK,ProfileOperation callback)5563 GateRef StubBuilder::DefinePropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
5564 GateRef isInternal, GateRef SCheckModelIsCHECK, ProfileOperation callback)
5565 {
5566 auto env = GetEnvironment();
5567 Label entryPass(env);
5568 env->SubCfgEntry(&entryPass);
5569 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5570 DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
5571 DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
5572 Label exit(env);
5573 Label ifEnd(env);
5574 Label loopHead(env);
5575 Label loopEnd(env);
5576 Label loopExit(env);
5577 Label afterLoop(env);
5578 Label findProperty(env);
5579
5580 GateRef hclass = LoadHClass(glue, *holder);
5581 GateRef jsType = GetObjectType(hclass);
5582 Label isSIndexObj(env);
5583 Label notSIndexObj(env);
5584 BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
5585 Bind(&isSIndexObj);
5586 {
5587 Label isFastTypeArray(env);
5588 Label notFastTypeArray(env);
5589 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
5590 Bind(&isFastTypeArray);
5591 {
5592 result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
5593 Label isNull(env);
5594 Label notNull(env);
5595 BRANCH(TaggedIsNull(*result), &isNull, ¬Null);
5596 Bind(&isNull);
5597 {
5598 result = Hole();
5599 Jump(&exit);
5600 }
5601 Bind(¬Null);
5602 BRANCH(TaggedIsHole(*result), ¬SIndexObj, &exit);
5603 }
5604 Bind(¬FastTypeArray);
5605
5606 Label isSpecialContainer(env);
5607 Label notSpecialContainer(env);
5608 BRANCH(IsArrayListOrVector(jsType), &isSpecialContainer, ¬SpecialContainer);
5609 Bind(&isSpecialContainer);
5610 {
5611 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
5612 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5613 result = Exception();
5614 Jump(&exit);
5615 }
5616 Bind(¬SpecialContainer);
5617 {
5618 result = Hole();
5619 Jump(&exit);
5620 }
5621 }
5622 Bind(¬SIndexObj);
5623 {
5624 BRANCH(isInternal, &findProperty, &ifEnd);
5625 Label isDicMode(env);
5626 Label notDicMode(env);
5627 Bind(&findProperty);
5628 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
5629 Bind(¬DicMode);
5630 {
5631 GateRef layOutInfo = GetLayoutFromHClass(glue, hclass);
5632 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
5633 GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
5634 Label hasEntry(env);
5635 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
5636 Bind(&hasEntry);
5637 {
5638 GateRef attr = GetPropAttrFromLayoutInfo(glue, layOutInfo, entry);
5639 Label isAccessor(env);
5640 Label notAccessor(env);
5641 Label isSCheckModelIsCHECK1(env);
5642 Label isNotSCheckModelIsCHECK1(env);
5643 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
5644 Bind(&isAccessor);
5645 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK1, &isNotSCheckModelIsCHECK1);
5646 Bind(&isSCheckModelIsCHECK1);
5647 {
5648 Jump(&exit);
5649 }
5650 Bind(&isNotSCheckModelIsCHECK1);
5651 GateRef accessor = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5652 Label shouldCall(env);
5653 BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
5654 Bind(&shouldCall);
5655 {
5656 result = CallSetterHelper(glue, receiver, accessor, value, callback);
5657 Jump(&exit);
5658 }
5659 Bind(¬Accessor);
5660 {
5661 Label writable(env);
5662 Label notWritable(env);
5663 Label isSCheckModelIsCHECK2(env);
5664 Label isNotSCheckModelIsCHECK2(env);
5665 BRANCH(IsWritable(attr), &writable, ¬Writable);
5666 Bind(¬Writable);
5667 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK2, &isNotSCheckModelIsCHECK2);
5668 Bind(&isSCheckModelIsCHECK2);
5669 {
5670 Jump(&exit);
5671 }
5672 Bind(&isNotSCheckModelIsCHECK2);
5673 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5674 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5675 result = Exception();
5676 Jump(&exit);
5677 Bind(&writable);
5678 {
5679 Label isAOT(env);
5680 Label notAOT(env);
5681 BRANCH(IsAOTHClass(hclass), &isAOT, ¬AOT);
5682 Bind(&isAOT);
5683 {
5684 GateRef attrVal = JSObjectGetPropertyWithRep(glue, *holder, hclass, attr);
5685 Label attrValIsHole(env);
5686 BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬AOT);
5687 Bind(&attrValIsHole);
5688 {
5689 Label storeReceiverHoleEntry(env);
5690 Label noNeedStore(env);
5691 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
5692 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
5693 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
5694 &storeReceiverHoleEntry, &ifEnd);
5695 Bind(&storeReceiverHoleEntry);
5696 {
5697 receiverHoleEntry = entry;
5698 Jump(&ifEnd);
5699 }
5700 }
5701 }
5702 Bind(¬AOT);
5703 Label holdEqualsRecv(env);
5704 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
5705 Bind(&holdEqualsRecv);
5706 {
5707 Label isJSShared(env);
5708 Label executeSetProp(env);
5709 BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5710 Bind(&isJSShared);
5711 {
5712 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5713 Label executeSharedSetProp(env);
5714 SharedObjectStoreBarrierWithTypeCheck(false, &result, glue, attr, value, &actualValue,
5715 &executeSharedSetProp, &exit, SCheckModelIsCHECK);
5716 Bind(&executeSharedSetProp);
5717 {
5718 JSObjectSetProperty(glue, *holder, hclass, attr, key, *actualValue);
5719 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr,
5720 *actualValue, callback);
5721 result = Undefined();
5722 Jump(&exit);
5723 }
5724 }
5725 Bind(&executeSetProp);
5726 {
5727 JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
5728 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value,
5729 callback);
5730 result = Undefined();
5731 Jump(&exit);
5732 }
5733 }
5734 }
5735 }
5736 }
5737 }
5738 Bind(&isDicMode);
5739 {
5740 GateRef array = GetPropertiesArray(glue, *holder);
5741 GateRef entry1 = FindEntryFromHashTable<NameDictionary>(glue, array, key);
5742 Label notNegtiveOne(env);
5743 BRANCH(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &ifEnd);
5744 Bind(¬NegtiveOne);
5745 {
5746 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(glue, array, entry1);
5747 Label isAccessor1(env);
5748 Label notAccessor1(env);
5749 Label isSCheckModelIsCHECK3(env);
5750 Label isNotSCheckModelIsCHECK3(env);
5751 BRANCH(IsAccessor(attr1), &isAccessor1, ¬Accessor1);
5752 Bind(&isAccessor1);
5753 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK3, &isNotSCheckModelIsCHECK3);
5754 Bind(&isSCheckModelIsCHECK3);
5755 {
5756 Jump(&exit);
5757 }
5758 Bind(&isNotSCheckModelIsCHECK3);
5759 GateRef accessor1 = GetValueFromDictionary<NameDictionary>(glue, array, entry1);
5760 Label shouldCall1(env);
5761 BRANCH(ShouldCallSetter(glue, receiver, *holder, accessor1, attr1), &shouldCall1, ¬Accessor1);
5762 Bind(&shouldCall1);
5763 {
5764 result = CallSetterHelper(glue, receiver, accessor1, value, callback);
5765 Jump(&exit);
5766 }
5767 Bind(¬Accessor1);
5768 {
5769 Label writable1(env);
5770 Label notWritable1(env);
5771 Label isSCheckModelIsCHECK4(env);
5772 Label isNotSCheckModelIsCHECK4(env);
5773 BRANCH(IsWritable(attr1), &writable1, ¬Writable1);
5774 Bind(¬Writable1);
5775 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK4, &isNotSCheckModelIsCHECK4);
5776 Bind(&isSCheckModelIsCHECK4);
5777 {
5778 Jump(&exit);
5779 }
5780 Bind(&isNotSCheckModelIsCHECK4);
5781 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5782 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5783 result = Exception();
5784 Jump(&exit);
5785 Bind(&writable1);
5786 {
5787 Label holdEqualsRecv1(env);
5788 BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
5789 Bind(&holdEqualsRecv1);
5790 {
5791 Label isJSShared(env);
5792 Label executeSetProp(env);
5793 BRANCH(IsJSShared(glue, receiver), &isJSShared, &executeSetProp);
5794 Bind(&isJSShared);
5795 {
5796 DEFVARIABLE(actualValue, VariableType::JS_ANY(), value);
5797 Label executeSharedSetProp(env);
5798 SharedObjectStoreBarrierWithTypeCheck(true, &result, glue, attr1, value, &actualValue,
5799 &executeSharedSetProp, &exit, SCheckModelIsCHECK);
5800 Bind(&executeSharedSetProp);
5801 {
5802 UpdateValueInDict<NameDictionary>(glue, array, entry1, *actualValue);
5803 result = Undefined();
5804 Jump(&exit);
5805 }
5806 }
5807 Bind(&executeSetProp);
5808 {
5809 UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
5810 result = Undefined();
5811 Jump(&exit);
5812 }
5813 }
5814 }
5815 }
5816 }
5817 }
5818 }
5819 Bind(&ifEnd);
5820 Label holeEntryNotNegtiveOne(env);
5821 Label holeEntryIfEnd(env);
5822 BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
5823 Bind(&holeEntryNotNegtiveOne);
5824 {
5825 GateRef receiverHClass = LoadHClass(glue, receiver);
5826 GateRef receiverLayoutInfo = GetLayoutFromHClass(glue, receiverHClass);
5827 GateRef holeAttr = GetPropAttrFromLayoutInfo(glue, receiverLayoutInfo, *receiverHoleEntry);
5828 JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
5829 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
5830 result = Undefined();
5831 Jump(&exit);
5832 }
5833 Bind(&holeEntryIfEnd);
5834
5835 Label extensible(env);
5836 Label inextensible(env);
5837 BRANCH(IsExtensible(glue, receiver), &extensible, &inextensible);
5838 Bind(&inextensible);
5839 {
5840 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5841 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5842 result = Exception();
5843 Jump(&exit);
5844 }
5845 Bind(&extensible);
5846 {
5847 result = AddPropertyByName(glue, receiver, key, value,
5848 Int64(PropertyAttributes::GetDefaultAttributes()), callback);
5849 Jump(&exit);
5850 }
5851 Bind(&exit);
5852 auto ret = *result;
5853 env->SubCfgExit();
5854 return ret;
5855 }
5856
5857 /**
5858 Ruturn value: Hole means try fastPath fail, caller should go slow path, undefined is try fastPath succsee.
5859 only when mayThrow, will return TaggedFalse, it means some step has exception but not throw in
5860 thread, same as C interpreter SetProperty
5861 In ANY situation, exception means that an error must have occurred and been thrown on the thread.
5862 */
5863
SetPropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics,bool mayThrow)5864 GateRef StubBuilder::SetPropertyByValue(GateRef glue,
5865 GateRef receiver,
5866 GateRef key,
5867 GateRef value,
5868 bool useOwn,
5869 ProfileOperation callback,
5870 bool defineSemantics,
5871 bool mayThrow)
5872 {
5873 auto env = GetEnvironment();
5874 Label subEntry1(env);
5875 env->SubCfgEntry(&subEntry1);
5876 DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5877 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5878 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5879 Label isPropertyKey(env);
5880 Label exit(env);
5881
5882 BRANCH(TaggedIsPropertyKey(glue, *varKey), &isPropertyKey, &exit);
5883
5884 Bind(&isPropertyKey);
5885 {
5886 GateRef index64 = TryToElementsIndex(glue, *varKey);
5887 Label validIndex(env);
5888 Label notValidIndex(env);
5889 Label greaterThanInt32Max(env);
5890 Label notGreaterThanInt32Max(env);
5891 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
5892 Bind(&greaterThanInt32Max);
5893 {
5894 Jump(&exit);
5895 }
5896 Bind(¬GreaterThanInt32Max);
5897 GateRef index = TruncInt64ToInt32(index64);
5898 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
5899 Bind(&validIndex);
5900 {
5901 result = SetPropertyByIndex(glue, receiver, index, value, useOwn, callback, defineSemantics, mayThrow);
5902 Jump(&exit);
5903 }
5904 Bind(¬ValidIndex);
5905 {
5906 Label isNumber1(env);
5907 Label notNumber1(env);
5908 Label setByName(env);
5909 BRANCH(TaggedIsNumber(*varKey), &isNumber1, ¬Number1);
5910 Bind(&isNumber1);
5911 {
5912 result = Hole();
5913 Jump(&exit);
5914 }
5915 Label isString(env);
5916 Label checkDetector(env);
5917 Bind(¬Number1);
5918 {
5919 Label notIntenalString(env);
5920 BRANCH(TaggedIsString(glue, *varKey), &isString, &checkDetector);
5921 Bind(&isString);
5922 {
5923 BRANCH(IsInternalString(*varKey), &setByName, ¬IntenalString);
5924 Bind(¬IntenalString);
5925 {
5926 #if ENABLE_NEXT_OPTIMIZATION
5927 GateRef res = CallRuntime(glue, RTSTUB_ID(GetOrInternStringFromHashTrieTable), { *varKey });
5928 varKey = res;
5929 Jump(&checkDetector);
5930 #else
5931 Label notFind(env);
5932 Label find(env);
5933 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
5934 BRANCH(TaggedIsHole(res), ¬Find, &find);
5935 Bind(¬Find);
5936 {
5937 varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
5938 isInternal = False();
5939 Jump(&checkDetector);
5940 }
5941 Bind(&find);
5942 {
5943 varKey = res;
5944 Jump(&checkDetector);
5945 }
5946 #endif
5947 }
5948 }
5949 }
5950 Bind(&checkDetector);
5951 CheckDetectorName(glue, *varKey, &setByName, &exit);
5952 Bind(&setByName);
5953 {
5954 result = SetPropertyByName(
5955 glue, receiver, *varKey, value, useOwn, *isInternal, callback, true, defineSemantics, mayThrow);
5956 Jump(&exit);
5957 }
5958 }
5959 }
5960 Bind(&exit);
5961 auto ret = *result;
5962 env->SubCfgExit();
5963 return ret;
5964 }
5965
5966 // ObjectFastOperator::SetPropertyByValue
DefinePropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef SCheckModelIsCHECK,ProfileOperation callback)5967 GateRef StubBuilder::DefinePropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value,
5968 GateRef SCheckModelIsCHECK, ProfileOperation callback)
5969 {
5970 auto env = GetEnvironment();
5971 Label subEntry1(env);
5972 env->SubCfgEntry(&subEntry1);
5973 DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5974 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5975 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5976 Label isPropertyKey(env);
5977 Label exit(env);
5978
5979 BRANCH(TaggedIsPropertyKey(glue, *varKey), &isPropertyKey, &exit);
5980
5981 Bind(&isPropertyKey);
5982 {
5983 GateRef index64 = TryToElementsIndex(glue, *varKey);
5984 Label validIndex(env);
5985 Label notValidIndex(env);
5986 Label greaterThanInt32Max(env);
5987 Label notGreaterThanInt32Max(env);
5988 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
5989 Bind(&greaterThanInt32Max);
5990 {
5991 Jump(&exit);
5992 }
5993 Bind(¬GreaterThanInt32Max);
5994 GateRef index = TruncInt64ToInt32(index64);
5995 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
5996 Bind(&validIndex);
5997 {
5998 result = DefinePropertyByIndex(glue, receiver, index, value);
5999 Jump(&exit);
6000 }
6001 Bind(¬ValidIndex);
6002 {
6003 Label isNumber1(env);
6004 Label notNumber1(env);
6005 Label setByName(env);
6006 BRANCH(TaggedIsNumber(*varKey), &isNumber1, ¬Number1);
6007 Bind(&isNumber1);
6008 {
6009 result = Hole();
6010 Jump(&exit);
6011 }
6012 Label isString(env);
6013 Label checkDetector(env);
6014 Bind(¬Number1);
6015 {
6016 Label notIntenalString(env);
6017 BRANCH(TaggedIsString(glue, *varKey), &isString, &checkDetector);
6018 Bind(&isString);
6019 {
6020 BRANCH(IsInternalString(*varKey), &setByName, ¬IntenalString);
6021 Bind(¬IntenalString);
6022 {
6023 #if ENABLE_NEXT_OPTIMIZATION
6024 GateRef res = CallRuntime(glue, RTSTUB_ID(GetOrInternStringFromHashTrieTable), { *varKey });
6025 varKey = res;
6026 Jump(&checkDetector);
6027 #else
6028 Label notFind(env);
6029 Label find(env);
6030 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
6031 BRANCH(TaggedIsHole(res), ¬Find, &find);
6032 Bind(¬Find);
6033 {
6034 varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
6035 isInternal = False();
6036 Jump(&checkDetector);
6037 }
6038 Bind(&find);
6039 {
6040 varKey = res;
6041 Jump(&checkDetector);
6042 }
6043 #endif
6044 }
6045 }
6046 }
6047 Bind(&checkDetector);
6048 CheckDetectorName(glue, *varKey, &setByName, &exit);
6049 Bind(&setByName);
6050 {
6051 result = DefinePropertyByName(glue, receiver, *varKey, value, *isInternal,
6052 SCheckModelIsCHECK, callback);
6053 Jump(&exit);
6054 }
6055 }
6056 }
6057 Bind(&exit);
6058 auto ret = *result;
6059 env->SubCfgExit();
6060 return ret;
6061 }
6062
SetPropertiesToLexicalEnv(GateRef glue,GateRef object,GateRef index,GateRef value)6063 void StubBuilder::SetPropertiesToLexicalEnv(GateRef glue, GateRef object, GateRef index, GateRef value)
6064 {
6065 GateRef valueIndex = Int32Add(index, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
6066 SetValueToTaggedArray(VariableType::JS_ANY(), glue, object, valueIndex, value);
6067 }
6068
NotifyHClassChanged(GateRef glue,GateRef oldHClass,GateRef newHClass)6069 void StubBuilder::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef newHClass)
6070 {
6071 auto env = GetEnvironment();
6072 Label entry(env);
6073 env->SubCfgEntry(&entry);
6074 Label exit(env);
6075 Label isPrototype(env);
6076 BRANCH(IsPrototypeHClass(oldHClass), &isPrototype, &exit);
6077 Bind(&isPrototype);
6078 {
6079 Label notEqualHClass(env);
6080 BRANCH(Equal(oldHClass, newHClass), &exit, ¬EqualHClass);
6081 Bind(¬EqualHClass);
6082 {
6083 CallRuntime(glue, RTSTUB_ID(NoticeThroughChainAndRefreshUser), { oldHClass, newHClass });
6084 Jump(&exit);
6085 }
6086 }
6087 Bind(&exit);
6088 env->SubCfgExit();
6089 return;
6090 }
6091
FastTypeOf(GateRef glue,GateRef obj)6092 GateRef StubBuilder::FastTypeOf(GateRef glue, GateRef obj)
6093 {
6094 auto env = GetEnvironment();
6095 Label entry(env);
6096 env->SubCfgEntry(&entry);
6097 Label exit(env);
6098
6099 GateRef gConstAddr = LoadPrimitive(VariableType::JS_ANY(), glue,
6100 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
6101 GateRef undefinedIndex = GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX);
6102 GateRef gConstUndefinedStr = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr, undefinedIndex);
6103 DEFVARIABLE(result, VariableType::JS_POINTER(), gConstUndefinedStr);
6104 Label objIsTrue(env);
6105 Label objNotTrue(env);
6106 Label defaultLabel(env);
6107 GateRef gConstBooleanStr = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6108 GetGlobalConstantOffset(ConstantIndex::BOOLEAN_STRING_INDEX));
6109 BRANCH(TaggedIsTrue(obj), &objIsTrue, &objNotTrue);
6110 Bind(&objIsTrue);
6111 {
6112 result = gConstBooleanStr;
6113 Jump(&exit);
6114 }
6115 Bind(&objNotTrue);
6116 {
6117 Label objIsFalse(env);
6118 Label objNotFalse(env);
6119 BRANCH(TaggedIsFalse(obj), &objIsFalse, &objNotFalse);
6120 Bind(&objIsFalse);
6121 {
6122 result = gConstBooleanStr;
6123 Jump(&exit);
6124 }
6125 Bind(&objNotFalse);
6126 {
6127 Label objIsNull(env);
6128 Label objNotNull(env);
6129 BRANCH(TaggedIsNull(obj), &objIsNull, &objNotNull);
6130 Bind(&objIsNull);
6131 {
6132 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6133 GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
6134 Jump(&exit);
6135 }
6136 Bind(&objNotNull);
6137 {
6138 Label objIsUndefined(env);
6139 Label objNotUndefined(env);
6140 BRANCH(TaggedIsUndefined(obj), &objIsUndefined, &objNotUndefined);
6141 Bind(&objIsUndefined);
6142 {
6143 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6144 GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX));
6145 Jump(&exit);
6146 }
6147 Bind(&objNotUndefined);
6148 Jump(&defaultLabel);
6149 }
6150 }
6151 }
6152 Bind(&defaultLabel);
6153 {
6154 Label objIsHeapObject(env);
6155 Label objNotHeapObject(env);
6156 BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
6157 Bind(&objIsHeapObject);
6158 {
6159 Label objIsString(env);
6160 Label objNotString(env);
6161 BRANCH(IsString(glue, obj), &objIsString, &objNotString);
6162 Bind(&objIsString);
6163 {
6164 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6165 GetGlobalConstantOffset(ConstantIndex::STRING_STRING_INDEX));
6166 Jump(&exit);
6167 }
6168 Bind(&objNotString);
6169 {
6170 Label objIsSymbol(env);
6171 Label objNotSymbol(env);
6172 BRANCH_UNLIKELY(IsSymbol(glue, obj), &objIsSymbol, &objNotSymbol);
6173 Bind(&objIsSymbol);
6174 {
6175 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6176 GetGlobalConstantOffset(ConstantIndex::SYMBOL_STRING_INDEX));
6177 Jump(&exit);
6178 }
6179 Bind(&objNotSymbol);
6180 {
6181 Label objIsCallable(env);
6182 Label objNotCallable(env);
6183 BRANCH_UNLIKELY(IsCallable(glue, obj), &objIsCallable, &objNotCallable);
6184 Bind(&objIsCallable);
6185 {
6186 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6187 GetGlobalConstantOffset(ConstantIndex::FUNCTION_STRING_INDEX));
6188 Jump(&exit);
6189 }
6190 Bind(&objNotCallable);
6191 {
6192 Label objIsBigInt(env);
6193 Label objNotBigInt(env);
6194 BRANCH_UNLIKELY(TaggedObjectIsBigInt(glue, obj), &objIsBigInt, &objNotBigInt);
6195 Bind(&objIsBigInt);
6196 {
6197 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6198 GetGlobalConstantOffset(ConstantIndex::BIGINT_STRING_INDEX));
6199 Jump(&exit);
6200 }
6201 Bind(&objNotBigInt);
6202 {
6203 Label objIsNativeModuleFailureInfo(env);
6204 Label objNotNativeModuleFailureInfo(env);
6205 BRANCH_UNLIKELY(IsNativeModuleFailureInfo(glue, obj), &objIsNativeModuleFailureInfo,
6206 &objNotNativeModuleFailureInfo);
6207 Bind(&objIsNativeModuleFailureInfo);
6208 {
6209 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6210 GetGlobalConstantOffset(ConstantIndex::NATIVE_MODULE_FAILURE_INFO_STRING_INDEX));
6211 Jump(&exit);
6212 }
6213 Bind(&objNotNativeModuleFailureInfo);
6214 {
6215 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6216 GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
6217 Jump(&exit);
6218 }
6219 }
6220 }
6221 }
6222 }
6223 }
6224 Bind(&objNotHeapObject);
6225 {
6226 Label objIsNum(env);
6227 Label objNotNum(env);
6228 BRANCH(TaggedIsNumber(obj), &objIsNum, &objNotNum);
6229 Bind(&objIsNum);
6230 {
6231 result = LoadPrimitive(VariableType::JS_POINTER(), gConstAddr,
6232 GetGlobalConstantOffset(ConstantIndex::NUMBER_STRING_INDEX));
6233 Jump(&exit);
6234 }
6235 Bind(&objNotNum);
6236 Jump(&exit);
6237 }
6238 }
6239 Bind(&exit);
6240 auto ret = *result;
6241 env->SubCfgExit();
6242 return ret;
6243 }
6244
InstanceOf(GateRef glue,GateRef object,GateRef target,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)6245 GateRef StubBuilder::InstanceOf(
6246 GateRef glue, GateRef object, GateRef target, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
6247 {
6248 auto env = GetEnvironment();
6249 Label entry(env);
6250 env->SubCfgEntry(&entry);
6251 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6252 Label exit(env);
6253
6254 // 1.If Type(target) is not Object, throw a TypeError exception.
6255 Label targetIsHeapObject(env);
6256 Label targetIsEcmaObject(env);
6257 Label targetNotEcmaObject(env);
6258 BRANCH(TaggedIsHeapObject(target), &targetIsHeapObject, &targetNotEcmaObject);
6259 Bind(&targetIsHeapObject);
6260 BRANCH(TaggedObjectIsEcmaObject(glue, target), &targetIsEcmaObject, &targetNotEcmaObject);
6261 Bind(&targetNotEcmaObject);
6262 {
6263 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
6264 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6265 result = Exception();
6266 Jump(&exit);
6267 }
6268 Bind(&targetIsEcmaObject);
6269 {
6270 // 2.Let instOfHandler be GetMethod(target, @@hasInstance).
6271 GateRef globalEnv = GetCurrentGlobalEnv();
6272 GateRef hasInstanceSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
6273 GlobalEnv::HASINSTANCE_SYMBOL_INDEX);
6274 GateRef instof = GetMethod(glue, target, hasInstanceSymbol, profileTypeInfo, slotId);
6275
6276 // 3.ReturnIfAbrupt(instOfHandler).
6277 Label isPendingException(env);
6278 Label noPendingException(env);
6279 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
6280 Bind(&isPendingException);
6281 {
6282 result = Exception();
6283 Jump(&exit);
6284 }
6285 Bind(&noPendingException);
6286
6287 // 4.If instOfHandler is not undefined, then
6288 Label instOfNotUndefined(env);
6289 Label instOfIsUndefined(env);
6290 Label fastPath(env);
6291 Label targetNotCallable(env);
6292 BRANCH(TaggedIsUndefined(instof), &instOfIsUndefined, &instOfNotUndefined);
6293 Bind(&instOfNotUndefined);
6294 {
6295 TryFastHasInstance(glue, instof, target, object, &fastPath, &exit, &result, callback);
6296 }
6297 Bind(&instOfIsUndefined);
6298 {
6299 // 5.If IsCallable(glue, target) is false, throw a TypeError exception.
6300 BRANCH(IsCallable(glue, target), &fastPath, &targetNotCallable);
6301 Bind(&targetNotCallable);
6302 {
6303 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
6304 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6305 result = Exception();
6306 Jump(&exit);
6307 }
6308 }
6309 Bind(&fastPath);
6310 {
6311 // 6.Return ? OrdinaryHasInstance(target, object).
6312 result = OrdinaryHasInstance(glue, target, object);
6313 Jump(&exit);
6314 }
6315 }
6316 Bind(&exit);
6317 auto ret = *result;
6318 env->SubCfgExit();
6319 return ret;
6320 }
6321
TryFastHasInstance(GateRef glue,GateRef instof,GateRef target,GateRef object,Label * fastPath,Label * exit,Variable * result,ProfileOperation callback)6322 void StubBuilder::TryFastHasInstance(GateRef glue, GateRef instof, GateRef target, GateRef object, Label *fastPath,
6323 Label *exit, Variable *result, ProfileOperation callback)
6324 {
6325 auto env = GetEnvironment();
6326
6327 GateRef globalEnv = GetCurrentGlobalEnv();
6328 GateRef function = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
6329 GlobalEnv::HASINSTANCE_FUNCTION_INDEX);
6330
6331 Label slowPath(env);
6332 Label tryFastPath(env);
6333 Label callExit(env);
6334 GateRef isEqual = IntPtrEqual(instof, function);
6335 BRANCH(isEqual, &tryFastPath, &slowPath);
6336 Bind(&tryFastPath);
6337 Jump(fastPath);
6338 Bind(&slowPath);
6339 {
6340 JSCallArgs callArgs(JSCallMode::CALL_SETTER);
6341 callArgs.callSetterArgs = { target, object };
6342 if (env->IsBaselineBuiltin()) {
6343 DEFVARIABLE(callRes, VariableType::JS_ANY(), Undefined());
6344 CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, &callRes, Circuit::NullGate(), callArgs,
6345 callback);
6346 callBuilder.JSCallDispatchForBaseline(&callExit);
6347 Bind(&callExit);
6348 result->WriteVariable(FastToBoolean(glue, *callRes));
6349 } else {
6350 CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, nullptr, Circuit::NullGate(), callArgs,
6351 callback);
6352 GateRef retValue = callBuilder.JSCallDispatch();
6353 result->WriteVariable(FastToBoolean(glue, retValue));
6354 }
6355 Jump(exit);
6356 }
6357 }
6358
GetMethod(GateRef glue,GateRef obj,GateRef key,GateRef profileTypeInfo,GateRef slotId)6359 GateRef StubBuilder::GetMethod(GateRef glue, GateRef obj, GateRef key, GateRef profileTypeInfo, GateRef slotId)
6360 {
6361 auto env = GetEnvironment();
6362 Label entry(env);
6363 env->SubCfgEntry(&entry);
6364 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6365 Label exit(env);
6366
6367 StringIdInfo info;
6368 AccessObjectStubBuilder builder(this, GetCurrentGlobalEnv());
6369 GateRef value = builder.LoadObjByName(glue, obj, key, info, profileTypeInfo, slotId, ProfileOperation());
6370
6371 Label isPendingException(env);
6372 Label noPendingException(env);
6373 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
6374 Bind(&isPendingException);
6375 {
6376 result = Exception();
6377 Jump(&exit);
6378 }
6379 Bind(&noPendingException);
6380 Label valueIsUndefinedOrNull(env);
6381 Label valueNotUndefinedOrNull(env);
6382 BRANCH(TaggedIsUndefinedOrNull(value), &valueIsUndefinedOrNull, &valueNotUndefinedOrNull);
6383 Bind(&valueIsUndefinedOrNull);
6384 {
6385 result = Undefined();
6386 Jump(&exit);
6387 }
6388 Bind(&valueNotUndefinedOrNull);
6389 {
6390 Label valueIsCallable(env);
6391 Label valueNotCallable(env);
6392 Label valueIsHeapObject(env);
6393 BRANCH(TaggedIsHeapObject(value), &valueIsHeapObject, &valueNotCallable);
6394 Bind(&valueIsHeapObject);
6395 BRANCH(IsCallable(glue, value), &valueIsCallable, &valueNotCallable);
6396 Bind(&valueNotCallable);
6397 {
6398 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(NonCallable));
6399 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6400 result = Exception();
6401 Jump(&exit);
6402 }
6403 Bind(&valueIsCallable);
6404 {
6405 result = value;
6406 Jump(&exit);
6407 }
6408 }
6409 Bind(&exit);
6410 auto ret = *result;
6411 env->SubCfgExit();
6412 return ret;
6413 }
6414
FastGetPropertyByName(GateRef glue,GateRef obj,GateRef key,ProfileOperation callback,GateRef hir)6415 GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key,
6416 ProfileOperation callback, GateRef hir)
6417 {
6418 auto env = GetEnvironment();
6419 Label entry(env);
6420 env->SubCfgEntry(&entry);
6421 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6422 Label exit(env);
6423 Label checkResult(env);
6424 Label fastpath(env);
6425 Label slowpath(env);
6426
6427 BRANCH(TaggedIsHeapObject(obj), &fastpath, &slowpath);
6428 Bind(&fastpath);
6429 {
6430 result = GetPropertyByName(glue, obj, key, Circuit::NullGate(), callback, True(), false, hir);
6431 BRANCH(TaggedIsHole(*result), &slowpath, &exit);
6432 }
6433 Bind(&slowpath);
6434 {
6435 result = CallRuntime(glue, RTSTUB_ID(LoadICByName), { Undefined(), obj, key, IntToTaggedInt(Int32(0)) });
6436 Jump(&exit);
6437 }
6438 Bind(&exit);
6439 auto ret = *result;
6440 env->SubCfgExit();
6441 return ret;
6442 }
6443
FastGetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,ProfileOperation callback,GateRef hir)6444 GateRef StubBuilder::FastGetPropertyByIndex(GateRef glue, GateRef obj,
6445 GateRef index, ProfileOperation callback, GateRef hir)
6446 {
6447 auto env = GetEnvironment();
6448 Label entry(env);
6449 env->SubCfgEntry(&entry);
6450 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6451 Label exit(env);
6452 Label fastPath(env);
6453 Label slowPath(env);
6454
6455 BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
6456 Bind(&fastPath);
6457 {
6458 result = GetPropertyByIndex(glue, obj, index, callback, hir);
6459 Label notHole(env);
6460 BRANCH(TaggedIsHole(*result), &slowPath, &exit);
6461 }
6462 Bind(&slowPath);
6463 {
6464 result = CallRuntime(glue, RTSTUB_ID(LdObjByIndex),
6465 { obj, IntToTaggedInt(index), TaggedFalse(), Undefined() });
6466 Jump(&exit);
6467 }
6468 Bind(&exit);
6469 auto ret = *result;
6470 env->SubCfgExit();
6471 return ret;
6472 }
6473
FastSetPropertyByName(GateRef glue,GateRef obj,GateRef key,GateRef value,ProfileOperation callback)6474 void StubBuilder::FastSetPropertyByName(GateRef glue, GateRef obj, GateRef key, GateRef value,
6475 ProfileOperation callback)
6476 {
6477 auto env = GetEnvironment();
6478 Label entry(env);
6479 env->SubCfgEntry(&entry);
6480 DEFVARIABLE(keyVar, VariableType::JS_ANY(), key);
6481 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6482 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
6483 Label exit(env);
6484 Label fastPath(env);
6485 Label slowPath(env);
6486 BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
6487 Bind(&fastPath);
6488 {
6489 Label isString(env);
6490 Label getByName(env);
6491 Label isInternalString(env);
6492 Label notIntenalString(env);
6493 BRANCH(TaggedIsString(glue, *keyVar), &isString, &getByName);
6494 Bind(&isString);
6495 {
6496 BRANCH(IsInternalString(*keyVar), &isInternalString, ¬IntenalString);
6497 Bind(&isInternalString);
6498 Jump(&getByName);
6499 Bind(¬IntenalString);
6500 {
6501 #if ENABLE_NEXT_OPTIMIZATION
6502 GateRef res = CallRuntime(glue, RTSTUB_ID(GetOrInternStringFromHashTrieTable), { *keyVar });
6503 keyVar = res;
6504 Jump(&getByName);
6505 #else
6506 Label notFind(env);
6507 Label find(env);
6508 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *keyVar });
6509 BRANCH(TaggedIsHole(res), ¬Find, &find);
6510 Bind(¬Find);
6511 {
6512 keyVar = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { key });
6513 isInternal = False();
6514 Jump(&getByName);
6515 }
6516 Bind(&find);
6517 {
6518 keyVar = res;
6519 Jump(&getByName);
6520 }
6521 #endif
6522 }
6523 }
6524 Bind(&getByName);
6525
6526 result = SetPropertyByName(glue, obj, *keyVar, value, false, *isInternal, callback, true);
6527 Label notHole(env);
6528 BRANCH(TaggedIsHole(*result), &slowPath, &exit);
6529 }
6530 Bind(&slowPath);
6531 {
6532 result = CallRuntime(glue, RTSTUB_ID(StObjByValue), { obj, *keyVar, value });
6533 Jump(&exit);
6534 }
6535 Bind(&exit);
6536 env->SubCfgExit();
6537 }
6538
FastSetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,GateRef value)6539 void StubBuilder::FastSetPropertyByIndex(GateRef glue, GateRef obj, GateRef index, GateRef value)
6540 {
6541 auto env = GetEnvironment();
6542 Label entry(env);
6543 env->SubCfgEntry(&entry);
6544 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6545 Label exit(env);
6546 Label fastPath(env);
6547 Label slowPath(env);
6548
6549 BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
6550 Bind(&fastPath);
6551 {
6552 result = SetPropertyByIndex(glue, obj, index, value, false);
6553 Label notHole(env);
6554 BRANCH(TaggedIsHole(*result), &slowPath, &exit);
6555 }
6556 Bind(&slowPath);
6557 {
6558 result = CallRuntime(glue, RTSTUB_ID(StObjByIndex),
6559 { obj, IntToTaggedInt(index), value });
6560 Jump(&exit);
6561 }
6562 Bind(&exit);
6563 env->SubCfgExit();
6564 }
6565
GetCtorPrototype(GateRef glue,GateRef ctor)6566 GateRef StubBuilder::GetCtorPrototype(GateRef glue, GateRef ctor)
6567 {
6568 auto env = GetEnvironment();
6569 Label entry(env);
6570 env->SubCfgEntry(&entry);
6571 DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
6572 Label exit(env);
6573 Label isHClass(env);
6574 Label isPrototype(env);
6575 Label isHeapObject(env);
6576 Label notHeapObject(env);
6577
6578 GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), glue, ctor, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
6579 BRANCH(TaggedIsHeapObject(ctorProtoOrHC), &isHeapObject, ¬HeapObject);
6580 Bind(¬HeapObject);
6581 {
6582 // If go slow path, return hole.
6583 constructorPrototype = Hole();
6584 Jump(&exit);
6585 }
6586 Bind(&isHeapObject);
6587 BRANCH(IsJSHClass(glue, ctorProtoOrHC), &isHClass, &isPrototype);
6588 Bind(&isHClass);
6589 {
6590 constructorPrototype = GetPrototypeFromHClass(glue, ctorProtoOrHC);
6591 Jump(&exit);
6592 }
6593 Bind(&isPrototype);
6594 {
6595 constructorPrototype = ctorProtoOrHC;
6596 Jump(&exit);
6597 }
6598
6599 Bind(&exit);
6600 auto ret = *constructorPrototype;
6601 env->SubCfgExit();
6602 return ret;
6603 }
6604
HasFunctionPrototype(GateRef glue,GateRef ctor)6605 GateRef StubBuilder::HasFunctionPrototype(GateRef glue, GateRef ctor)
6606 {
6607 auto env = GetEnvironment();
6608 Label entry(env);
6609 env->SubCfgEntry(&entry);
6610 DEFVARIABLE(result, VariableType::BOOL(), True());
6611 Label exit(env);
6612 Label isHole(env);
6613
6614 GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), glue, ctor, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
6615 BRANCH(TaggedIsHole(ctorProtoOrHC), &isHole, &exit);
6616 Bind(&isHole);
6617 {
6618 result = False();
6619 Jump(&exit);
6620 }
6621 Bind(&exit);
6622 auto ret = *result;
6623 env->SubCfgExit();
6624 return ret;
6625 }
6626
OrdinaryHasInstance(GateRef glue,GateRef target,GateRef obj)6627 GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj)
6628 {
6629 auto env = GetEnvironment();
6630 Label entry(env);
6631 env->SubCfgEntry(&entry);
6632 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6633 Label exit(env);
6634 DEFVARIABLE(object, VariableType::JS_ANY(), obj);
6635
6636 // 1. If IsCallable(glue, C) is false, return false.
6637 Label targetIsCallable(env);
6638 Label targetNotCallable(env);
6639 BRANCH(IsCallable(glue, target), &targetIsCallable, &targetNotCallable);
6640 Bind(&targetNotCallable);
6641 {
6642 result = TaggedFalse();
6643 Jump(&exit);
6644 }
6645 Bind(&targetIsCallable);
6646 {
6647 // 2. If C has a [[BoundTargetFunction]] internal slot, then
6648 // a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
6649 // b. Return InstanceofOperator(O,BC) (see 12.9.4).
6650 Label targetIsBoundFunction(env);
6651 Label targetNotBoundFunction(env);
6652 BRANCH(IsBoundFunction(glue, target), &targetIsBoundFunction, &targetNotBoundFunction);
6653 Bind(&targetIsBoundFunction);
6654 {
6655 GateRef boundTarget = Load(VariableType::JS_ANY(), glue, target, IntPtr(JSBoundFunction::BOUND_TARGET_OFFSET));
6656 result = CallRuntime(glue, RTSTUB_ID(InstanceOf), { obj, boundTarget });
6657 Jump(&exit);
6658 }
6659 Bind(&targetNotBoundFunction);
6660 {
6661 // 3. If Type(O) is not Object, return false
6662 Label objIsHeapObject(env);
6663 Label objIsEcmaObject(env);
6664 Label objNotEcmaObject(env);
6665 BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotEcmaObject);
6666 Bind(&objIsHeapObject);
6667 BRANCH(TaggedObjectIsEcmaObject(glue, obj), &objIsEcmaObject, &objNotEcmaObject);
6668 Bind(&objNotEcmaObject);
6669 {
6670 result = TaggedFalse();
6671 Jump(&exit);
6672 }
6673 Bind(&objIsEcmaObject);
6674 {
6675 // 4. Let P be Get(C, "prototype").
6676 Label getCtorProtoSlowPath(env);
6677 Label ctorIsJSFunction(env);
6678 Label gotCtorPrototype(env);
6679 DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
6680 BRANCH(IsJSFunction(glue, target), &ctorIsJSFunction, &getCtorProtoSlowPath);
6681 Bind(&ctorIsJSFunction);
6682 {
6683 Label getCtorProtoFastPath(env);
6684 GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), glue, target,
6685 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
6686
6687 BRANCH(TaggedIsHole(ctorProtoOrHC), &getCtorProtoSlowPath, &getCtorProtoFastPath);
6688 Bind(&getCtorProtoFastPath);
6689 {
6690 constructorPrototype = GetCtorPrototype(glue, target);
6691 BRANCH(TaggedIsHole(*constructorPrototype), &getCtorProtoSlowPath, &gotCtorPrototype);
6692 }
6693 }
6694 Bind(&getCtorProtoSlowPath);
6695 {
6696 auto prototypeString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
6697 ConstantIndex::PROTOTYPE_STRING_INDEX);
6698 constructorPrototype = FastGetPropertyByName(glue, target, prototypeString, ProfileOperation());
6699 Jump(&gotCtorPrototype);
6700 }
6701 Bind(&gotCtorPrototype);
6702
6703 // 5. ReturnIfAbrupt(P).
6704 // no throw exception, so needn't return
6705 Label isPendingException(env);
6706 Label noPendingException(env);
6707 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
6708 Bind(&isPendingException);
6709 {
6710 result = Exception();
6711 Jump(&exit);
6712 }
6713 Bind(&noPendingException);
6714
6715 // 6. If Type(P) is not Object, throw a TypeError exception.
6716 Label constructorPrototypeIsHeapObject(env);
6717 Label constructorPrototypeIsEcmaObject(env);
6718 Label constructorPrototypeNotEcmaObject(env);
6719 BRANCH(TaggedIsHeapObject(*constructorPrototype), &constructorPrototypeIsHeapObject,
6720 &constructorPrototypeNotEcmaObject);
6721 Bind(&constructorPrototypeIsHeapObject);
6722 BRANCH(TaggedObjectIsEcmaObject(glue, *constructorPrototype), &constructorPrototypeIsEcmaObject,
6723 &constructorPrototypeNotEcmaObject);
6724 Bind(&constructorPrototypeNotEcmaObject);
6725 {
6726 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
6727 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
6728 result = Exception();
6729 Jump(&exit);
6730 }
6731 Bind(&constructorPrototypeIsEcmaObject);
6732 {
6733 // 7. Repeat
6734 // a.Let O be O.[[GetPrototypeOf]]().
6735 // b.ReturnIfAbrupt(O).
6736 // c.If O is null, return false.
6737 // d.If SameValue(P, O) is true, return true.
6738 Label loopHead(env);
6739 Label loopEnd(env);
6740 Label afterLoop(env);
6741 Label strictEqual1(env);
6742 Label notStrictEqual1(env);
6743 Label shouldReturn(env);
6744 Label shouldContinue(env);
6745
6746 BRANCH(TaggedIsNull(*object), &afterLoop, &loopHead);
6747 LoopBegin(&loopHead);
6748 {
6749 GateRef isEqual = SameValue(glue, *object, *constructorPrototype);
6750
6751 BRANCH(isEqual, &strictEqual1, ¬StrictEqual1);
6752 Bind(&strictEqual1);
6753 {
6754 result = TaggedTrue();
6755 Jump(&exit);
6756 }
6757 Bind(¬StrictEqual1);
6758 {
6759 object = GetPrototype(glue, *object);
6760
6761 BRANCH(HasPendingException(glue), &shouldReturn, &shouldContinue);
6762 Bind(&shouldReturn);
6763 {
6764 result = Exception();
6765 Jump(&exit);
6766 }
6767 }
6768 Bind(&shouldContinue);
6769 BRANCH(TaggedIsNull(*object), &afterLoop, &loopEnd);
6770 }
6771 Bind(&loopEnd);
6772 LoopEndWithCheckSafePoint(&loopHead, env, glue);
6773 Bind(&afterLoop);
6774 {
6775 result = TaggedFalse();
6776 Jump(&exit);
6777 }
6778 }
6779 }
6780 }
6781 }
6782 Bind(&exit);
6783 auto ret = *result;
6784 env->SubCfgExit();
6785 return ret;
6786 }
6787
SameValue(GateRef glue,GateRef left,GateRef right)6788 GateRef StubBuilder::SameValue(GateRef glue, GateRef left, GateRef right)
6789 {
6790 auto env = GetEnvironment();
6791 Label entry(env);
6792 env->SubCfgEntry(&entry);
6793 DEFVARIABLE(result, VariableType::BOOL(), False());
6794 Label exit(env);
6795 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6796 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6797 Label strictEqual(env);
6798 Label stringEqualCheck(env);
6799 Label stringCompare(env);
6800 Label bigIntEqualCheck(env);
6801 Label numberEqualCheck1(env);
6802
6803 BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6804 Bind(&strictEqual);
6805 {
6806 result = True();
6807 Jump(&exit);
6808 }
6809 Bind(&numberEqualCheck1);
6810 {
6811 Label leftIsNumber(env);
6812 Label leftIsNotNumber(env);
6813 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6814 Bind(&leftIsNumber);
6815 {
6816 Label rightIsNumber(env);
6817 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6818 Bind(&rightIsNumber);
6819 {
6820 Label numberEqualCheck2(env);
6821 Label leftIsInt(env);
6822 Label leftNotInt(env);
6823 Label getRight(env);
6824
6825 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6826 Bind(&leftIsInt);
6827 {
6828 Label fastPath(env);
6829 Label slowPath(env);
6830 BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6831 Bind(&fastPath);
6832 {
6833 result = False();
6834 Jump(&exit);
6835 }
6836 Bind(&slowPath);
6837 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6838 doubleRight = GetDoubleOfTDouble(right);
6839 Jump(&numberEqualCheck2);
6840 }
6841 Bind(&leftNotInt);
6842 {
6843 doubleLeft = GetDoubleOfTDouble(left);
6844 Jump(&getRight);
6845 }
6846 Bind(&getRight);
6847 {
6848 Label rightIsInt(env);
6849 Label rightNotInt(env);
6850 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6851 Bind(&rightIsInt);
6852 {
6853 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6854 Jump(&numberEqualCheck2);
6855 }
6856 Bind(&rightNotInt);
6857 {
6858 doubleRight = GetDoubleOfTDouble(right);
6859 Jump(&numberEqualCheck2);
6860 }
6861 }
6862 Bind(&numberEqualCheck2);
6863 {
6864 Label boolAndCheck(env);
6865 Label signbitCheck(env);
6866 BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &signbitCheck, &boolAndCheck);
6867 Bind(&signbitCheck);
6868 {
6869 GateRef leftEncoding = CastDoubleToInt64(*doubleLeft);
6870 GateRef RightEncoding = CastDoubleToInt64(*doubleRight);
6871 Label leftIsMinusZero(env);
6872 Label leftNotMinusZero(env);
6873 BRANCH(Int64Equal(leftEncoding, Int64(base::MINUS_ZERO_BITS)),
6874 &leftIsMinusZero, &leftNotMinusZero);
6875 Bind(&leftIsMinusZero);
6876 {
6877 Label rightIsMinusZero(env);
6878 BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &rightIsMinusZero, &exit);
6879 Bind(&rightIsMinusZero);
6880 {
6881 result = True();
6882 Jump(&exit);
6883 }
6884 }
6885 Bind(&leftNotMinusZero);
6886 {
6887 Label rightNotMinusZero(env);
6888 BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &exit, &rightNotMinusZero);
6889 Bind(&rightNotMinusZero);
6890 {
6891 result = True();
6892 Jump(&exit);
6893 }
6894 }
6895 }
6896 Bind(&boolAndCheck);
6897 {
6898 GateRef doubleLeftVal = *doubleLeft;
6899 GateRef doubleRightVal = *doubleRight;
6900 result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
6901 .And(DoubleIsNAN(doubleRightVal)).Done();
6902 Jump(&exit);
6903 }
6904 }
6905 }
6906 }
6907 Bind(&leftIsNotNumber);
6908 BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
6909 Bind(&stringEqualCheck);
6910 BRANCH(BothAreString(glue, left, right), &stringCompare, &bigIntEqualCheck);
6911 Bind(&stringCompare);
6912 {
6913 result = FastStringEqual(glue, left, right);
6914 Jump(&exit);
6915 }
6916 Bind(&bigIntEqualCheck);
6917 {
6918 Label leftIsBigInt(env);
6919 Label leftIsNotBigInt(env);
6920 BRANCH(TaggedIsBigInt(glue, left), &leftIsBigInt, &exit);
6921 Bind(&leftIsBigInt);
6922 {
6923 Label rightIsBigInt(env);
6924 BRANCH(TaggedIsBigInt(glue, right), &rightIsBigInt, &exit);
6925 Bind(&rightIsBigInt);
6926 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
6927 Jump(&exit);
6928 }
6929 }
6930 }
6931 Bind(&exit);
6932 auto ret = *result;
6933 env->SubCfgExit();
6934 return ret;
6935 }
6936
SameValueZero(GateRef glue,GateRef left,GateRef right)6937 GateRef StubBuilder::SameValueZero(GateRef glue, GateRef left, GateRef right)
6938 {
6939 auto env = GetEnvironment();
6940 Label entry(env);
6941 env->SubCfgEntry(&entry);
6942 DEFVARIABLE(result, VariableType::BOOL(), False());
6943 Label exit(env);
6944 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6945 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6946 Label strictEqual(env);
6947 Label stringEqualCheck(env);
6948 Label stringCompare(env);
6949 Label bigIntEqualCheck(env);
6950 Label numberEqualCheck1(env);
6951
6952 BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6953 Bind(&strictEqual);
6954 {
6955 result = True();
6956 Jump(&exit);
6957 }
6958 Bind(&numberEqualCheck1);
6959 {
6960 Label leftIsNumber(env);
6961 Label leftIsNotNumber(env);
6962 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6963 Bind(&leftIsNumber);
6964 {
6965 Label rightIsNumber(env);
6966 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6967 Bind(&rightIsNumber);
6968 {
6969 Label numberEqualCheck2(env);
6970 Label leftIsInt(env);
6971 Label leftNotInt(env);
6972 Label getRight(env);
6973 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6974 Bind(&leftIsInt);
6975 {
6976 Label fastPath(env);
6977 Label slowPath(env);
6978 BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6979 Bind(&fastPath);
6980 {
6981 result = False();
6982 Jump(&exit);
6983 }
6984 Bind(&slowPath);
6985 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6986 doubleRight = GetDoubleOfTDouble(right);
6987 Jump(&numberEqualCheck2);
6988 }
6989 Bind(&leftNotInt);
6990 {
6991 doubleLeft = GetDoubleOfTDouble(left);
6992 Jump(&getRight);
6993 }
6994 Bind(&getRight);
6995 {
6996 Label rightIsInt(env);
6997 Label rightNotInt(env);
6998 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6999 Bind(&rightIsInt);
7000 {
7001 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7002 Jump(&numberEqualCheck2);
7003 }
7004 Bind(&rightNotInt);
7005 {
7006 doubleRight = GetDoubleOfTDouble(right);
7007 Jump(&numberEqualCheck2);
7008 }
7009 }
7010 Bind(&numberEqualCheck2);
7011 {
7012 Label nanCheck(env);
7013 Label doubleEqual(env);
7014 BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &doubleEqual, &nanCheck);
7015 Bind(&doubleEqual);
7016 {
7017 result = True();
7018 Jump(&exit);
7019 }
7020 Bind(&nanCheck);
7021 {
7022 GateRef doubleLeftVal = *doubleLeft;
7023 GateRef doubleRightVal = *doubleRight;
7024 result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
7025 .And(DoubleIsNAN(doubleRightVal)).Done();
7026 Jump(&exit);
7027 }
7028 }
7029 }
7030 }
7031 Bind(&leftIsNotNumber);
7032 BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
7033 Bind(&stringEqualCheck);
7034 BRANCH(BothAreString(glue, left, right), &stringCompare, &bigIntEqualCheck);
7035 Bind(&stringCompare);
7036 {
7037 result = FastStringEqual(glue, left, right);
7038 Jump(&exit);
7039 }
7040 Bind(&bigIntEqualCheck);
7041 {
7042 Label leftIsBigInt(env);
7043 Label leftIsNotBigInt(env);
7044 BRANCH(TaggedIsBigInt(glue, left), &leftIsBigInt, &exit);
7045 Bind(&leftIsBigInt);
7046 {
7047 Label rightIsBigInt(env);
7048 BRANCH(TaggedIsBigInt(glue, right), &rightIsBigInt, &exit);
7049 Bind(&rightIsBigInt);
7050 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntSameValueZero), { left, right });
7051 Jump(&exit);
7052 }
7053 }
7054 }
7055 Bind(&exit);
7056 auto ret = *result;
7057 env->SubCfgExit();
7058 return ret;
7059 }
7060
FastStringEqual(GateRef glue,GateRef left,GateRef right)7061 GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right)
7062 {
7063 auto env = GetEnvironment();
7064 Label entry(env);
7065 env->SubCfgEntry(&entry);
7066 DEFVARIABLE(result, VariableType::BOOL(), False());
7067 Label exit(env);
7068 Label hashcodeCompare(env);
7069 Label contentsCompare(env);
7070 Label lenEqualOneCheck(env);
7071 Label lenIsOne(env);
7072 BRANCH(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &lenEqualOneCheck, &exit);
7073 Bind(&lenEqualOneCheck);
7074 BRANCH(Int32Equal(GetLengthFromString(left), Int32(1)), &lenIsOne, &hashcodeCompare);
7075 Bind(&lenIsOne);
7076 {
7077 Label leftFlattenFastPath(env);
7078 FlatStringStubBuilder leftFlat(this);
7079 leftFlat.FlattenString(glue, left, &leftFlattenFastPath);
7080 Bind(&leftFlattenFastPath);
7081 {
7082 Label rightFlattenFastPath(env);
7083 FlatStringStubBuilder rightFlat(this);
7084 rightFlat.FlattenString(glue, right, &rightFlattenFastPath);
7085 Bind(&rightFlattenFastPath);
7086 {
7087 BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
7088 StringInfoGateRef leftStrInfoGate(&leftFlat);
7089 StringInfoGateRef rightStrInfoGate(&rightFlat);
7090 GateRef leftStrToInt = stringBuilder.StringAt(glue, leftStrInfoGate, Int32(0));
7091 GateRef rightStrToInt = stringBuilder.StringAt(glue, rightStrInfoGate, Int32(0));
7092 result = Equal(leftStrToInt, rightStrToInt);
7093 Jump(&exit);
7094 }
7095 }
7096 }
7097
7098 Bind(&hashcodeCompare);
7099 Label leftNotNeg(env);
7100 GateRef leftHash = TryGetHashcodeFromString(left);
7101 GateRef rightHash = TryGetHashcodeFromString(right);
7102 BRANCH(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg);
7103 Bind(&leftNotNeg);
7104 {
7105 Label rightNotNeg(env);
7106 BRANCH(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg);
7107 Bind(&rightNotNeg);
7108 BRANCH(Int64Equal(leftHash, rightHash), &contentsCompare, &exit);
7109 }
7110
7111 Bind(&contentsCompare);
7112 {
7113 GateRef stringEqual = CallRuntime(glue, RTSTUB_ID(StringEqual), { left, right });
7114 result = Equal(stringEqual, TaggedTrue());
7115 Jump(&exit);
7116 }
7117
7118 Bind(&exit);
7119 auto ret = *result;
7120 env->SubCfgExit();
7121 return ret;
7122 }
7123
7124 // init is -1 if leftLength < rightLength;
7125 // 0 if leftLength == rightLength;
7126 // +1 if leftLength > rightLength.
StringCompareContents(GateRef glue,GateRef left,GateRef right,GateRef init,GateRef minLength)7127 GateRef StubBuilder::StringCompareContents(GateRef glue, GateRef left, GateRef right, GateRef init, GateRef minLength)
7128 {
7129 auto env = GetEnvironment();
7130 Label entry(env);
7131 env->SubCfgEntry(&entry);
7132 Label exit(env);
7133
7134 Label loopHead(env);
7135 Label loopEnd(env);
7136 Label loopBody(env);
7137 Label leftFlattenFastPath(env);
7138 DEFVARIABLE(result, VariableType::INT32(), init);
7139
7140 FlatStringStubBuilder leftFlat(this);
7141 leftFlat.FlattenString(glue, left, &leftFlattenFastPath);
7142 Bind(&leftFlattenFastPath);
7143
7144 Label rightFlattenFastPath(env);
7145 FlatStringStubBuilder rightFlat(this);
7146 rightFlat.FlattenString(glue, right, &rightFlattenFastPath);
7147 Bind(&rightFlattenFastPath);
7148
7149 StringInfoGateRef leftStrInfoGate(&leftFlat);
7150 StringInfoGateRef rightStrInfoGate(&rightFlat);
7151 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
7152 GateRef isBothUtf8 = LogicAndBuilder(env).And(IsUtf8String(leftStrInfoGate.GetString()))
7153 .And(IsUtf8String(rightStrInfoGate.GetString())).Done();
7154 Label bothUtf8(env);
7155 Label slowCompare(env);
7156 BRANCH_LIKELY(isBothUtf8, &bothUtf8, &slowCompare);
7157 Bind(&bothUtf8);
7158 {
7159 GateRef leftData = GetNormalStringData(glue, leftStrInfoGate);
7160 GateRef rightData = GetNormalStringData(glue, rightStrInfoGate);
7161 Label utf8LoopHead(env);
7162 Label utf8LoopEnd(env);
7163 Label utf8LoopBody(env);
7164 Jump(&utf8LoopHead);
7165 LoopBegin(&utf8LoopHead);
7166 {
7167 BRANCH(Int32UnsignedLessThan(*i, minLength), &utf8LoopBody, &exit);
7168 Bind(&utf8LoopBody);
7169 {
7170 GateRef leftChar = LoadPrimitive(VariableType::INT8(), leftData, *i);
7171 GateRef rightChar = LoadPrimitive(VariableType::INT8(), rightData, *i);
7172 Label notEqual(env);
7173 BRANCH_NO_WEIGHT(Int8Equal(leftChar, rightChar), &utf8LoopEnd, ¬Equal);
7174 Bind(¬Equal);
7175 {
7176 Label leftIsLess(env);
7177 Label rightIsLess(env);
7178 BRANCH_NO_WEIGHT(Int32LessThan(ZExtInt8ToInt32(leftChar), ZExtInt8ToInt32(rightChar)), &leftIsLess, &rightIsLess);
7179 Bind(&leftIsLess);
7180 {
7181 result = Int32(-1);
7182 Jump(&exit);
7183 }
7184 Bind(&rightIsLess);
7185 {
7186 result = Int32(1);
7187 Jump(&exit);
7188 }
7189 }
7190 }
7191 Bind(&utf8LoopEnd);
7192 i = Int32Add(*i, Int32(1));
7193 LoopEnd(&utf8LoopHead);
7194 }
7195 }
7196 Bind(&slowCompare);
7197 Jump(&loopHead);
7198 LoopBegin(&loopHead);
7199 {
7200 BRANCH(Int32UnsignedLessThan(*i, minLength), &loopBody, &exit);
7201 Bind(&loopBody);
7202 {
7203 BuiltinsStringStubBuilder stringBuilder(this, GetCurrentGlobalEnv());
7204 GateRef leftStrToInt = stringBuilder.StringAt(glue, leftStrInfoGate, *i);
7205 GateRef rightStrToInt = stringBuilder.StringAt(glue, rightStrInfoGate, *i);
7206 Label notEqual(env);
7207 BRANCH_NO_WEIGHT(Int32Equal(leftStrToInt, rightStrToInt), &loopEnd, ¬Equal);
7208 Bind(¬Equal);
7209 {
7210 Label leftIsLess(env);
7211 Label rightIsLess(env);
7212 BRANCH_NO_WEIGHT(Int32UnsignedLessThan(leftStrToInt, rightStrToInt), &leftIsLess, &rightIsLess);
7213 Bind(&leftIsLess);
7214 {
7215 result = Int32(-1);
7216 Jump(&exit);
7217 }
7218 Bind(&rightIsLess);
7219 {
7220 result = Int32(1);
7221 Jump(&exit);
7222 }
7223 }
7224 }
7225 Bind(&loopEnd);
7226 i = Int32Add(*i, Int32(1));
7227 LoopEnd(&loopHead);
7228 }
7229 Bind(&exit);
7230 auto ret = *result;
7231 env->SubCfgExit();
7232 return ret;
7233 }
7234
FastStringEqualWithoutRTStub(GateRef glue,GateRef left,GateRef right)7235 GateRef StubBuilder::FastStringEqualWithoutRTStub(GateRef glue, GateRef left, GateRef right)
7236 {
7237 auto env = GetEnvironment();
7238 Label entry(env);
7239 env->SubCfgEntry(&entry);
7240 DEFVARIABLE(result, VariableType::BOOL(), False());
7241 Label exit(env);
7242 Label hashcodeCompare(env);
7243 Label contentsCompare(env);
7244 Label lenIsOne(env);
7245
7246 GateRef leftLen = GetLengthFromString(left);
7247 GateRef rightLen = GetLengthFromString(right);
7248 BRANCH(Int32Equal(leftLen, rightLen), &hashcodeCompare, &exit);
7249 Bind(&hashcodeCompare);
7250 Label leftNotNeg(env);
7251 GateRef leftHash = TryGetHashcodeFromString(left);
7252 GateRef rightHash = TryGetHashcodeFromString(right);
7253 BRANCH(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg);
7254 Bind(&leftNotNeg);
7255 {
7256 Label rightNotNeg(env);
7257 BRANCH(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg);
7258 Bind(&rightNotNeg);
7259 BRANCH(Int64Equal(leftHash, rightHash), &contentsCompare, &exit);
7260 }
7261
7262 Bind(&contentsCompare);
7263 {
7264 GateRef compareResult = StringCompareContents(glue, left, right, Int32(0), Int32Min(leftLen, rightLen));
7265 result = Equal(Int32(0), compareResult);
7266 Jump(&exit);
7267 }
7268
7269 Bind(&exit);
7270 auto ret = *result;
7271 env->SubCfgExit();
7272 return ret;
7273 }
7274
StringCompare(GateRef glue,GateRef left,GateRef right)7275 GateRef StubBuilder::StringCompare(GateRef glue, GateRef left, GateRef right)
7276 {
7277 auto env = GetEnvironment();
7278 Label entry(env);
7279 env->SubCfgEntry(&entry);
7280 Label exit(env);
7281 Label compareContent(env);
7282 Label compareLength(env);
7283 GateRef leftLength = GetLengthFromString(left);
7284 GateRef rightLength = GetLengthFromString(right);
7285 DEFVARIABLE(minLength, VariableType::INT32(), leftLength);
7286 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
7287 BRANCH_NO_WEIGHT(Int32Equal(leftLength, rightLength), &compareContent, &compareLength);
7288 Bind(&compareLength);
7289 {
7290 Label rightLengthIsLess(env);
7291 Label leftLengthIsLess(env);
7292 BRANCH(Int32GreaterThan(leftLength, rightLength), &rightLengthIsLess, &leftLengthIsLess);
7293 Bind(&rightLengthIsLess);
7294 {
7295 result = Int32(1);
7296 minLength = rightLength;
7297 Jump(&compareContent);
7298 }
7299 Bind(&leftLengthIsLess);
7300 {
7301 result = Int32(-1);
7302 minLength = leftLength;
7303 Jump(&compareContent);
7304 }
7305 }
7306
7307 Bind(&compareContent);
7308 result = StringCompareContents(glue, left, right, *result, *minLength);
7309 Jump(&exit);
7310
7311 Bind(&exit);
7312 auto ret = *result;
7313 env->SubCfgExit();
7314 return ret;
7315 }
7316
FastStrictEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7317 GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7318 {
7319 auto env = GetEnvironment();
7320 Label entry(env);
7321 env->SubCfgEntry(&entry);
7322 DEFVARIABLE(result, VariableType::BOOL(), False());
7323 Label leftIsNumber(env);
7324 Label leftIsNotNumber(env);
7325 Label sameVariableCheck(env);
7326 Label stringEqualCheck(env);
7327 Label stringCompare(env);
7328 Label updataPGOTypeWithInternString(env);
7329 Label bigIntEqualCheck(env);
7330 Label undefinedCheck(env);
7331 Label exit(env);
7332 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
7333 Bind(&leftIsNumber);
7334 {
7335 Label rightIsNumber(env);
7336 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
7337 Bind(&rightIsNumber);
7338 {
7339 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
7340 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
7341 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType()));
7342 Label leftIsInt(env);
7343 Label leftNotInt(env);
7344 Label getRight(env);
7345 Label numberEqualCheck(env);
7346
7347 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
7348 Bind(&leftIsInt);
7349 {
7350 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7351 Jump(&getRight);
7352 }
7353 Bind(&leftNotInt);
7354 {
7355 curType = TaggedInt(PGOSampleType::DoubleType());
7356 doubleLeft = GetDoubleOfTDouble(left);
7357 Jump(&getRight);
7358 }
7359 Bind(&getRight);
7360 {
7361 Label rightIsInt(env);
7362 Label rightNotInt(env);
7363 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
7364 Bind(&rightIsInt);
7365 {
7366 GateRef type = TaggedInt(PGOSampleType::IntType());
7367 COMBINE_TYPE_CALL_BACK(curType, type);
7368 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7369 Jump(&numberEqualCheck);
7370 }
7371 Bind(&rightNotInt);
7372 {
7373 GateRef type = TaggedInt(PGOSampleType::DoubleType());
7374 COMBINE_TYPE_CALL_BACK(curType, type);
7375 doubleRight = GetDoubleOfTDouble(right);
7376 Jump(&numberEqualCheck);
7377 }
7378 }
7379 Bind(&numberEqualCheck);
7380 {
7381 Label doubleEqualCheck(env);
7382 BRANCH(BitOr(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight)), &exit, &doubleEqualCheck);
7383 Bind(&doubleEqualCheck);
7384 {
7385 result = DoubleEqual(*doubleLeft, *doubleRight);
7386 Jump(&exit);
7387 }
7388 }
7389 }
7390 }
7391 Bind(&leftIsNotNumber);
7392 BRANCH(TaggedIsNumber(right), &exit, &sameVariableCheck);
7393 Bind(&sameVariableCheck);
7394 {
7395 Label ifSameVariable(env);
7396 BRANCH(Equal(left, right), &ifSameVariable, &stringEqualCheck);
7397 Bind(&ifSameVariable);
7398 {
7399 result = True();
7400 if (!callback.IsEmpty()) {
7401 Label bothAreString(env);
7402 Label updataPGOTypeWithAny(env);
7403 BRANCH(TaggedIsString(glue, left), &bothAreString, &updataPGOTypeWithAny);
7404 Bind(&bothAreString);
7405 {
7406 Label updataPGOTypeWithString(env);
7407 BRANCH(IsInternalString(left), &updataPGOTypeWithInternString, &updataPGOTypeWithString);
7408 Bind(&updataPGOTypeWithString);
7409 {
7410 callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7411 Jump(&exit);
7412 }
7413 }
7414 Bind(&updataPGOTypeWithAny);
7415 {
7416 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7417 Jump(&exit);
7418 }
7419 } else {
7420 Jump(&exit);
7421 }
7422 }
7423 }
7424 Bind(&stringEqualCheck);
7425 BRANCH(BothAreString(glue, left, right), &stringCompare, &bigIntEqualCheck);
7426 Bind(&stringCompare);
7427 {
7428 Label executeFastStringEqual(env);
7429 BRANCH(LogicAndBuilder(env).And(IsInternalString(left)).And(IsInternalString(right)).Done(),
7430 // if not same variable and both sides are intern strings,
7431 // then the comparison result of the strings must be false.
7432 &updataPGOTypeWithInternString, &executeFastStringEqual);
7433 Bind(&executeFastStringEqual);
7434 {
7435 callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7436 result = FastStringEqual(glue, left, right);
7437 Jump(&exit);
7438 }
7439 }
7440 Bind(&bigIntEqualCheck);
7441 {
7442 Label leftIsBigInt(env);
7443 Label leftIsNotBigInt(env);
7444 BRANCH(TaggedIsBigInt(glue, left), &leftIsBigInt, &undefinedCheck);
7445 Bind(&leftIsBigInt);
7446 {
7447 Label rightIsBigInt(env);
7448 BRANCH(TaggedIsBigInt(glue, right), &rightIsBigInt, &exit);
7449 Bind(&rightIsBigInt);
7450 callback.ProfileOpType(TaggedInt(PGOSampleType::BigIntType()));
7451 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
7452 Jump(&exit);
7453 }
7454 }
7455 Bind(&updataPGOTypeWithInternString);
7456 {
7457 callback.ProfileOpType(TaggedInt(PGOSampleType::InternStringType()));
7458 Jump(&exit);
7459 }
7460 Bind(&undefinedCheck);
7461 {
7462 if (!callback.IsEmpty()) {
7463 Label updateProfileOpTypeWithAny(env);
7464 BRANCH(TaggedIsUndefined(left), &updateProfileOpTypeWithAny, &exit);
7465 Bind(&updateProfileOpTypeWithAny);
7466 callback.ProfileOpType(TaggedInt(PGOSampleType::UndefinedOrNullType()));
7467 }
7468 Jump(&exit);
7469 }
7470 Bind(&exit);
7471 auto ret = *result;
7472 env->SubCfgExit();
7473 return ret;
7474 }
7475
FastEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7476 GateRef StubBuilder::FastEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7477 {
7478 auto env = GetEnvironment();
7479 Label entry(env);
7480 env->SubCfgEntry(&entry);
7481 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7482 Label leftEqualRight(env);
7483 Label leftNotEqualRight(env);
7484 Label exit(env);
7485 BRANCH(Equal(left, right), &leftEqualRight, &leftNotEqualRight);
7486 Bind(&leftEqualRight);
7487 {
7488 Label leftIsDouble(env);
7489 Label leftNotDoubleOrLeftNotNan(env);
7490 BRANCH(TaggedIsDouble(left), &leftIsDouble, &leftNotDoubleOrLeftNotNan);
7491 Bind(&leftIsDouble);
7492 {
7493 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
7494 GateRef doubleLeft = GetDoubleOfTDouble(left);
7495 Label leftIsNan(env);
7496 Label leftIsNotNan(env);
7497 BRANCH(DoubleIsNAN(doubleLeft), &leftIsNan, &leftIsNotNan);
7498 Bind(&leftIsNan);
7499 {
7500 result = TaggedFalse();
7501 Jump(&exit);
7502 }
7503 Bind(&leftIsNotNan);
7504 {
7505 result = TaggedTrue();
7506 Jump(&exit);
7507 }
7508 }
7509 Bind(&leftNotDoubleOrLeftNotNan);
7510 {
7511 // Collect the type of left value
7512 result = TaggedTrue();
7513 if (callback.IsEmpty()) {
7514 Jump(&exit);
7515 } else {
7516 Label leftIsInt(env);
7517 Label leftIsNotInt(env);
7518 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsNotInt);
7519 Bind(&leftIsInt);
7520 {
7521 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
7522 Jump(&exit);
7523 }
7524 Bind(&leftIsNotInt);
7525 {
7526 Label leftIsString(env);
7527 Label leftIsNotString(env);
7528 BRANCH(TaggedIsString(glue, left), &leftIsString, &leftIsNotString);
7529 Bind(&leftIsString);
7530 {
7531 callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7532 Jump(&exit);
7533 }
7534 Bind(&leftIsNotString);
7535 {
7536 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7537 Jump(&exit);
7538 }
7539 }
7540 }
7541 }
7542 }
7543 Bind(&leftNotEqualRight);
7544 {
7545 Label leftIsNumber(env);
7546 Label leftNotNumberOrLeftNotIntOrRightNotInt(env);
7547 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrLeftNotIntOrRightNotInt);
7548 Bind(&leftIsNumber);
7549 {
7550 Label leftIsInt(env);
7551 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
7552 Bind(&leftIsInt);
7553 {
7554 Label rightIsInt(env);
7555 BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
7556 Bind(&rightIsInt);
7557 {
7558 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
7559 result = TaggedFalse();
7560 Jump(&exit);
7561 }
7562 }
7563 }
7564 Bind(&leftNotNumberOrLeftNotIntOrRightNotInt);
7565 {
7566 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None()));
7567 Label rightIsUndefinedOrNull(env);
7568 Label rightIsNotUndefinedOrNull(env);
7569 BRANCH(TaggedIsUndefinedOrNull(right), &rightIsUndefinedOrNull, &rightIsNotUndefinedOrNull);
7570 Bind(&rightIsUndefinedOrNull);
7571 {
7572 curType = TaggedInt(PGOSampleType::UndefinedOrNullType());
7573 Label leftIsHeapObject(env);
7574 Label leftNotHeapObject(env);
7575 BRANCH(TaggedIsHeapObject(left), &leftIsHeapObject, &leftNotHeapObject);
7576 Bind(&leftIsHeapObject);
7577 {
7578 GateRef type = TaggedInt(PGOSampleType::HeapObjectType());
7579 COMBINE_TYPE_CALL_BACK(curType, type);
7580 result = TaggedFalse();
7581 Jump(&exit);
7582 }
7583 Bind(&leftNotHeapObject);
7584 {
7585 Label leftIsUndefinedOrNull(env);
7586 Label leftIsNotUndefinedOrNull(env);
7587 // if left is undefined or null, then result is true, otherwise result is false
7588 BRANCH(TaggedIsUndefinedOrNull(left), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
7589 Bind(&leftIsUndefinedOrNull);
7590 {
7591 callback.ProfileOpType(*curType);
7592 result = TaggedTrue();
7593 Jump(&exit);
7594 }
7595 Bind(&leftIsNotUndefinedOrNull);
7596 {
7597 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7598 result = TaggedFalse();
7599 Jump(&exit);
7600 }
7601 }
7602 }
7603 Bind(&rightIsNotUndefinedOrNull);
7604 {
7605 Label bothString(env);
7606 Label eitherNotString(env);
7607 Label isHeapObject(env);
7608 Label notHeapObject(env);
7609 BRANCH(BitAnd(TaggedIsHeapObject(left), TaggedIsHeapObject(right)), &isHeapObject, ¬HeapObject);
7610 Bind(&isHeapObject);
7611 {
7612 Label typeEqual(env);
7613 GateRef leftType = GetObjectType(LoadHClass(glue, left));
7614 GateRef rightType = GetObjectType(LoadHClass(glue, right));
7615 BRANCH(Equal(leftType, rightType), &typeEqual, ¬HeapObject);
7616 Bind(&typeEqual);
7617 {
7618 Label eitherNotString1(env);
7619 Label bothBigInt(env);
7620 Label eitherNotBigInt(env);
7621 BRANCH(BothAreString(glue, left, right), &bothString, &eitherNotString1);
7622 Bind(&eitherNotString1);
7623 BRANCH(BitAnd(TaggedIsBigInt(glue, left),TaggedIsBigInt(glue, right)), &bothBigInt, &eitherNotBigInt);
7624 Bind(&bothBigInt);
7625 {
7626 callback.ProfileOpType(TaggedInt(PGOSampleType::BigIntType()));
7627 result =BooleanToTaggedBooleanPtr(CallNGCRuntime(glue,
7628 RTSTUB_ID(BigIntEquals), {left, right}));
7629 Jump(&exit);
7630 }
7631 Bind(&eitherNotBigInt);
7632 {
7633 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7634 result = TaggedFalse();
7635 Jump(&exit);
7636 }
7637 }
7638 }
7639 Bind(¬HeapObject);
7640 Label leftIsUndefinedOrNull(env);
7641 Label leftIsNotUndefinedOrNull(env);
7642 BRANCH(TaggedIsUndefinedOrNull(right), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
7643 // If left is undefined or null, result will always be false
7644 // because we can ensure that right is not null here.
7645 Bind(&leftIsUndefinedOrNull);
7646 {
7647 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7648 result = TaggedFalse();
7649 Jump(&exit);
7650 }
7651 Bind(&leftIsNotUndefinedOrNull);
7652 {
7653 Label leftIsBool(env);
7654 Label leftNotBoolOrRightNotSpecial(env);
7655 BRANCH(TaggedIsBoolean(left), &leftIsBool, &leftNotBoolOrRightNotSpecial);
7656 Bind(&leftIsBool);
7657 {
7658 curType = TaggedInt(PGOSampleType::BooleanType());
7659 Label rightIsSpecial(env);
7660 BRANCH(TaggedIsSpecial(right), &rightIsSpecial, &leftNotBoolOrRightNotSpecial);
7661 Bind(&rightIsSpecial);
7662 {
7663 GateRef type = TaggedInt(PGOSampleType::SpecialType());
7664 COMBINE_TYPE_CALL_BACK(curType, type);
7665 result = TaggedFalse();
7666 Jump(&exit);
7667 }
7668 }
7669 Bind(&leftNotBoolOrRightNotSpecial);
7670 {
7671 BRANCH(BothAreString(glue, left, right), &bothString, &eitherNotString);
7672 }
7673 Bind(&bothString);
7674 {
7675 callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7676 Label stringEqual(env);
7677 Label stringNotEqual(env);
7678 BRANCH(FastStringEqual(glue, left, right), &stringEqual, &stringNotEqual);
7679 Bind(&stringEqual);
7680 result = TaggedTrue();
7681 Jump(&exit);
7682 Bind(&stringNotEqual);
7683 result = TaggedFalse();
7684 Jump(&exit);
7685 }
7686 Bind(&eitherNotString);
7687 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType()));
7688 Jump(&exit);
7689 }
7690 }
7691 }
7692 }
7693 Bind(&exit);
7694 auto ret = *result;
7695 env->SubCfgExit();
7696 return ret;
7697 }
7698
FastToBoolean(GateRef glue,GateRef value,bool flag)7699 GateRef StubBuilder::FastToBoolean(GateRef glue, GateRef value, bool flag)
7700 {
7701 auto env = GetEnvironment();
7702 Label entry(env);
7703 env->SubCfgEntry(&entry);
7704 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7705 Label exit(env);
7706
7707 Label isSpecial(env);
7708 Label notSpecial(env);
7709 Label isNumber(env);
7710 Label isInt(env);
7711 Label isDouble(env);
7712 Label notNumber(env);
7713 Label notNan(env);
7714 Label isString(env);
7715 Label notString(env);
7716 Label isBigint(env);
7717 Label lengthIsOne(env);
7718 Label returnTrue(env);
7719 Label returnFalse(env);
7720
7721 BRANCH(TaggedIsSpecial(value), &isSpecial, ¬Special);
7722 Bind(&isSpecial);
7723 {
7724 BRANCH(TaggedIsTrue(value), &returnTrue, &returnFalse);
7725 }
7726 Bind(¬Special);
7727 {
7728 BRANCH(TaggedIsNumber(value), &isNumber, ¬Number);
7729 Bind(¬Number);
7730 {
7731 BRANCH(IsString(glue, value), &isString, ¬String);
7732 Bind(&isString);
7733 {
7734 auto len = GetLengthFromString(value);
7735 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7736 }
7737 Bind(¬String);
7738 BRANCH(TaggedObjectIsBigInt(glue, value), &isBigint, &returnTrue);
7739 Bind(&isBigint);
7740 {
7741 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7742 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7743 Bind(&lengthIsOne);
7744 {
7745 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7746 auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
7747 BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7748 }
7749 }
7750 }
7751 Bind(&isNumber);
7752 {
7753 BRANCH(TaggedIsInt(value), &isInt, &isDouble);
7754 Bind(&isInt);
7755 {
7756 auto intValue = GetInt32OfTInt(value);
7757 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7758 }
7759 Bind(&isDouble);
7760 {
7761 auto doubleValue = GetDoubleOfTDouble(value);
7762 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
7763 Bind(¬Nan);
7764 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
7765 }
7766 }
7767 }
7768 if (flag == 1) {
7769 Bind(&returnTrue);
7770 {
7771 result = TaggedTrue();
7772 Jump(&exit);
7773 }
7774 Bind(&returnFalse);
7775 {
7776 result = TaggedFalse();
7777 Jump(&exit);
7778 }
7779 } else {
7780 Bind(&returnFalse);
7781 {
7782 result = TaggedTrue();
7783 Jump(&exit);
7784 }
7785 Bind(&returnTrue);
7786 {
7787 result = TaggedFalse();
7788 Jump(&exit);
7789 }
7790 }
7791
7792 Bind(&exit);
7793 auto ret = *result;
7794 env->SubCfgExit();
7795 return ret;
7796 }
7797
FastToBooleanBaseline(GateRef glue,GateRef value,bool flag)7798 GateRef StubBuilder::FastToBooleanBaseline(GateRef glue, GateRef value, bool flag)
7799 {
7800 auto env = GetEnvironment();
7801 Label entry(env);
7802 env->SubCfgEntry(&entry);
7803 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7804 Label exit(env);
7805
7806 Label isSpecial(env);
7807 Label notSpecial(env);
7808 Label isNumber(env);
7809 Label isInt(env);
7810 Label isDouble(env);
7811 Label notNumber(env);
7812 Label notNan(env);
7813 Label isString(env);
7814 Label notString(env);
7815 Label isBigint(env);
7816 Label lengthIsOne(env);
7817 Label returnTrue(env);
7818 Label returnFalse(env);
7819
7820 Branch(TaggedIsSpecial(value), &isSpecial, ¬Special);
7821 Bind(&isSpecial);
7822 {
7823 Branch(TaggedIsTrue(value), &returnTrue, &returnFalse);
7824 }
7825 Bind(¬Special);
7826 {
7827 Branch(TaggedIsNumber(value), &isNumber, ¬Number);
7828 Bind(¬Number);
7829 {
7830 Branch(IsString(glue, value), &isString, ¬String);
7831 Bind(&isString);
7832 {
7833 auto len = GetLengthFromString(value);
7834 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7835 }
7836 Bind(¬String);
7837 Branch(TaggedObjectIsBigInt(glue, value), &isBigint, &returnTrue);
7838 Bind(&isBigint);
7839 {
7840 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7841 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7842 Bind(&lengthIsOne);
7843 {
7844 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7845 auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
7846 Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7847 }
7848 }
7849 }
7850 Bind(&isNumber);
7851 {
7852 Branch(TaggedIsInt(value), &isInt, &isDouble);
7853 Bind(&isInt);
7854 {
7855 auto intValue = GetInt32OfTInt(value);
7856 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7857 }
7858 Bind(&isDouble);
7859 {
7860 auto doubleValue = GetDoubleOfTDouble(value);
7861 Branch(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
7862 Bind(¬Nan);
7863 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
7864 }
7865 }
7866 }
7867 if (flag == 1) {
7868 Bind(&returnTrue);
7869 {
7870 result = TaggedTrue();
7871 Jump(&exit);
7872 }
7873 Bind(&returnFalse);
7874 {
7875 result = TaggedFalse();
7876 Jump(&exit);
7877 }
7878 } else {
7879 Bind(&returnFalse);
7880 {
7881 result = TaggedTrue();
7882 Jump(&exit);
7883 }
7884 Bind(&returnTrue);
7885 {
7886 result = TaggedFalse();
7887 Jump(&exit);
7888 }
7889 }
7890
7891 Bind(&exit);
7892 auto ret = *result;
7893 env->SubCfgExit();
7894 return ret;
7895 }
7896
FastToBooleanWithProfile(GateRef glue,GateRef value,ProfileOperation callback,bool flag)7897 GateRef StubBuilder::FastToBooleanWithProfile(GateRef glue, GateRef value, ProfileOperation callback, bool flag)
7898 {
7899 auto env = GetEnvironment();
7900 Label entry(env);
7901 env->SubCfgEntry(&entry);
7902 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7903 Label exit(env);
7904
7905 Label isSpecial(env);
7906 Label notSpecial(env);
7907 Label isNumber(env);
7908 Label isInt(env);
7909 Label isDouble(env);
7910 Label notNumber(env);
7911 Label notNan(env);
7912 Label isString(env);
7913 Label notString(env);
7914 Label isBigint(env);
7915 Label lengthIsOne(env);
7916 Label returnTrue(env);
7917 Label returnFalse(env);
7918 Label isTrue(env);
7919 Label isNotTrue(env);
7920 Label isFalse(env);
7921 Label isNotFalse(env);
7922 Label isUndefinedOrNull(env);
7923 Label isHole(env);
7924 Label isNotBigInt(env);
7925
7926 BRANCH(TaggedIsSpecial(value), &isSpecial, ¬Special);
7927 Bind(&isSpecial);
7928 {
7929 BRANCH(TaggedIsTrue(value), &isTrue, &isNotTrue);
7930 Bind(&isTrue);
7931 {
7932 callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
7933 Jump(&returnTrue);
7934 }
7935 Bind(&isNotTrue);
7936 {
7937 BRANCH(TaggedIsFalse(value), &isFalse, &isNotFalse);
7938 Bind(&isFalse);
7939 {
7940 callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
7941 Jump(&returnFalse);
7942 }
7943 Bind(&isNotFalse);
7944 BRANCH(TaggedIsUndefinedOrNull(value), &isUndefinedOrNull, &isHole);
7945 Bind(&isUndefinedOrNull);
7946 {
7947 callback.ProfileOpType(TaggedInt(PGOSampleType::UndefinedOrNullType()));
7948 Jump(&returnFalse);
7949 }
7950 Bind(&isHole);
7951 {
7952 // value will never be hole, this branch shouldn't be entered
7953 callback.ProfileOpType(TaggedInt(PGOSampleType::SpecialType()));
7954 Jump(&returnFalse);
7955 }
7956 }
7957 }
7958 Bind(¬Special);
7959 {
7960 BRANCH(TaggedIsNumber(value), &isNumber, ¬Number);
7961 Bind(¬Number);
7962 {
7963 BRANCH(IsString(glue, value), &isString, ¬String);
7964 Bind(&isString);
7965 {
7966 callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
7967 auto len = GetLengthFromString(value);
7968 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7969 }
7970 Bind(¬String);
7971 BRANCH(TaggedObjectIsBigInt(glue, value), &isBigint, &isNotBigInt);
7972 Bind(&isBigint);
7973 {
7974 callback.ProfileOpType(TaggedInt(PGOSampleType::BigIntType()));
7975 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7976 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7977 Bind(&lengthIsOne);
7978 {
7979 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7980 auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
7981 BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7982 }
7983 }
7984 Bind(&isNotBigInt);
7985 {
7986 callback.ProfileOpType(TaggedInt(PGOSampleType::HeapObjectType()));
7987 Jump(&returnTrue);
7988 }
7989 }
7990 Bind(&isNumber);
7991 {
7992 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
7993 BRANCH(TaggedIsInt(value), &isInt, &isDouble);
7994 Bind(&isInt);
7995 {
7996 auto intValue = GetInt32OfTInt(value);
7997 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7998 }
7999 Bind(&isDouble);
8000 {
8001 auto doubleValue = GetDoubleOfTDouble(value);
8002 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
8003 Bind(¬Nan);
8004 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
8005 }
8006 }
8007 }
8008 if (flag == 1) {
8009 Bind(&returnTrue);
8010 {
8011 result = TaggedTrue();
8012 Jump(&exit);
8013 }
8014 Bind(&returnFalse);
8015 {
8016 result = TaggedFalse();
8017 Jump(&exit);
8018 }
8019 } else {
8020 Bind(&returnFalse);
8021 {
8022 result = TaggedTrue();
8023 Jump(&exit);
8024 }
8025 Bind(&returnTrue);
8026 {
8027 result = TaggedFalse();
8028 Jump(&exit);
8029 }
8030 }
8031
8032 Bind(&exit);
8033 auto ret = *result;
8034 env->SubCfgExit();
8035 return ret;
8036 }
8037
FastToBooleanWithProfileBaseline(GateRef glue,GateRef value,ProfileOperation callback,bool flag)8038 GateRef StubBuilder::FastToBooleanWithProfileBaseline(GateRef glue, GateRef value, ProfileOperation callback, bool flag)
8039 {
8040 auto env = GetEnvironment();
8041 Label entry(env);
8042 env->SubCfgEntry(&entry);
8043 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8044 Label exit(env);
8045
8046 Label isSpecial(env);
8047 Label notSpecial(env);
8048 Label isNumber(env);
8049 Label isInt(env);
8050 Label isDouble(env);
8051 Label notNumber(env);
8052 Label notNan(env);
8053 Label isString(env);
8054 Label notString(env);
8055 Label isBigint(env);
8056 Label lengthIsOne(env);
8057 Label returnTrue(env);
8058 Label returnFalse(env);
8059 Label isTrue(env);
8060 Label isNotTrue(env);
8061 Label isFalse(env);
8062 Label isNotFalse(env);
8063 Label isUndefinedOrNull(env);
8064
8065 Branch(TaggedIsSpecial(value), &isSpecial, ¬Special);
8066 Bind(&isSpecial);
8067 {
8068 Branch(TaggedIsTrue(value), &isTrue, &isNotTrue);
8069 Bind(&isTrue);
8070 {
8071 callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
8072 Jump(&returnTrue);
8073 }
8074 Bind(&isNotTrue);
8075 {
8076 BRANCH(TaggedIsFalse(value), &isFalse, &isNotFalse);
8077 Bind(&isFalse);
8078 {
8079 callback.ProfileOpType(TaggedInt(PGOSampleType::BooleanType()));
8080 Jump(&returnFalse);
8081 }
8082 Bind(&isNotFalse);
8083 BRANCH(TaggedIsUndefinedOrNull(value), &isUndefinedOrNull, &returnFalse);
8084 Bind(&isUndefinedOrNull);
8085 {
8086 callback.ProfileOpType(TaggedInt(PGOSampleType::UndefinedOrNullType()));
8087 Jump(&returnFalse);
8088 }
8089 }
8090 }
8091 Bind(¬Special);
8092 {
8093 Branch(TaggedIsNumber(value), &isNumber, ¬Number);
8094 Bind(¬Number);
8095 {
8096 Branch(IsString(glue, value), &isString, ¬String);
8097 Bind(&isString);
8098 {
8099 auto len = GetLengthFromString(value);
8100 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
8101 }
8102 Bind(¬String);
8103 Branch(TaggedObjectIsBigInt(glue, value), &isBigint, &returnTrue);
8104 Bind(&isBigint);
8105 {
8106 auto len = LoadPrimitive(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
8107 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
8108 Bind(&lengthIsOne);
8109 {
8110 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
8111 auto data0 = LoadPrimitive(VariableType::INT32(), data, Int32(0));
8112 Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
8113 }
8114 }
8115 }
8116 Bind(&isNumber);
8117 {
8118 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
8119 Branch(TaggedIsInt(value), &isInt, &isDouble);
8120 Bind(&isInt);
8121 {
8122 auto intValue = GetInt32OfTInt(value);
8123 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
8124 }
8125 Bind(&isDouble);
8126 {
8127 auto doubleValue = GetDoubleOfTDouble(value);
8128 Branch(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
8129 Bind(¬Nan);
8130 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
8131 }
8132 }
8133 }
8134 if (flag == 1) {
8135 Bind(&returnTrue);
8136 {
8137 result = TaggedTrue();
8138 Jump(&exit);
8139 }
8140 Bind(&returnFalse);
8141 {
8142 result = TaggedFalse();
8143 Jump(&exit);
8144 }
8145 } else {
8146 Bind(&returnFalse);
8147 {
8148 result = TaggedTrue();
8149 Jump(&exit);
8150 }
8151 Bind(&returnTrue);
8152 {
8153 result = TaggedFalse();
8154 Jump(&exit);
8155 }
8156 }
8157
8158 Bind(&exit);
8159 auto ret = *result;
8160 env->SubCfgExit();
8161 return ret;
8162 }
8163
FastDiv(GateRef left,GateRef right,ProfileOperation callback)8164 GateRef StubBuilder::FastDiv(GateRef left, GateRef right, ProfileOperation callback)
8165 {
8166 auto env = GetEnvironment();
8167 Label entry(env);
8168 env->SubCfgEntry(&entry);
8169 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8170 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8171 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8172 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None()));
8173 Label leftIsNumber(env);
8174 Label leftNotNumberOrRightNotNumber(env);
8175 Label leftIsNumberAndRightIsNumber(env);
8176 Label leftIsDoubleAndRightIsDouble(env);
8177 Label exit(env);
8178 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
8179 Bind(&leftIsNumber);
8180 {
8181 Label rightIsNumber(env);
8182 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
8183 Bind(&rightIsNumber);
8184 {
8185 Label leftIsInt(env);
8186 Label leftNotInt(env);
8187 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
8188 Bind(&leftIsInt);
8189 {
8190 Label rightIsInt(env);
8191 Label bailout(env);
8192 BRANCH(TaggedIsInt(right), &rightIsInt, &bailout);
8193 Bind(&rightIsInt);
8194 {
8195 result = FastIntDiv(left, right, &bailout, callback);
8196 Jump(&exit);
8197 }
8198 Bind(&bailout);
8199 {
8200 curType = TaggedInt(PGOSampleType::IntOverFlowType());
8201 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8202 Jump(&leftIsNumberAndRightIsNumber);
8203 }
8204 }
8205 Bind(&leftNotInt);
8206 {
8207 curType = TaggedInt(PGOSampleType::DoubleType());
8208 doubleLeft = GetDoubleOfTDouble(left);
8209 Jump(&leftIsNumberAndRightIsNumber);
8210 }
8211 }
8212 }
8213 Bind(&leftNotNumberOrRightNotNumber);
8214 {
8215 Jump(&exit);
8216 }
8217 Bind(&leftIsNumberAndRightIsNumber);
8218 {
8219 Label rightIsInt(env);
8220 Label rightNotInt(env);
8221 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
8222 Bind(&rightIsInt);
8223 {
8224 GateRef type = TaggedInt(PGOSampleType::IntType());
8225 COMBINE_TYPE_CALL_BACK(curType, type);
8226 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8227 Jump(&leftIsDoubleAndRightIsDouble);
8228 }
8229 Bind(&rightNotInt);
8230 {
8231 GateRef type = TaggedInt(PGOSampleType::DoubleType());
8232 COMBINE_TYPE_CALL_BACK(curType, type);
8233 doubleRight = GetDoubleOfTDouble(right);
8234 Jump(&leftIsDoubleAndRightIsDouble);
8235 }
8236 }
8237 Bind(&leftIsDoubleAndRightIsDouble);
8238 {
8239 Label rightIsZero(env);
8240 Label rightNotZero(env);
8241 BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZero, &rightNotZero);
8242 Bind(&rightIsZero);
8243 {
8244 Label leftIsZero(env);
8245 Label leftNotZero(env);
8246 Label leftIsZeroOrNan(env);
8247 Label leftNotZeroAndNotNan(env);
8248 BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZero, &leftNotZero);
8249 Bind(&leftIsZero);
8250 {
8251 Jump(&leftIsZeroOrNan);
8252 }
8253 Bind(&leftNotZero);
8254 {
8255 Label leftIsNan(env);
8256 BRANCH(DoubleIsNAN(*doubleLeft), &leftIsNan, &leftNotZeroAndNotNan);
8257 Bind(&leftIsNan);
8258 {
8259 Jump(&leftIsZeroOrNan);
8260 }
8261 }
8262 Bind(&leftIsZeroOrNan);
8263 {
8264 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
8265 Jump(&exit);
8266 }
8267 Bind(&leftNotZeroAndNotNan);
8268 {
8269 GateRef intLeftTmp = CastDoubleToInt64(*doubleLeft);
8270 GateRef intRightTmp = CastDoubleToInt64(*doubleRight);
8271 GateRef flagBit = Int64And(Int64Xor(intLeftTmp, intRightTmp), Int64(base::DOUBLE_SIGN_MASK));
8272 GateRef tmpResult = Int64Xor(flagBit, CastDoubleToInt64(Double(base::POSITIVE_INFINITY)));
8273 result = DoubleToTaggedDoublePtr(CastInt64ToFloat64(tmpResult));
8274 Jump(&exit);
8275 }
8276 }
8277 Bind(&rightNotZero);
8278 {
8279 result = DoubleToTaggedDoublePtr(DoubleDiv(*doubleLeft, *doubleRight));
8280 Jump(&exit);
8281 }
8282 }
8283 Bind(&exit);
8284 auto ret = *result;
8285 env->SubCfgExit();
8286 return ret;
8287 }
8288
NumberOperation(Environment * env,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)8289 GateRef StubBuilder::NumberOperation(Environment *env, GateRef left, GateRef right,
8290 const BinaryOperation& intOp,
8291 const BinaryOperation& floatOp,
8292 ProfileOperation callback)
8293 {
8294 Label entry(env);
8295 env->SubCfgEntry(&entry);
8296 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8297 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8298 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8299 Label exit(env);
8300 Label doFloatOp(env);
8301 Label doIntOp(env);
8302 Label leftIsNumber(env);
8303 Label leftIsIntRightIsDouble(env);
8304 Label rightIsDouble(env);
8305 Label rightIsInt(env);
8306 Label rightIsNumber(env);
8307 BRANCH(TaggedIsNumber(left), &leftIsNumber, &exit);
8308 Bind(&leftIsNumber);
8309 {
8310 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
8311 Bind(&rightIsNumber);
8312 {
8313 Label leftIsInt(env);
8314 Label leftIsDouble(env);
8315 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
8316 Bind(&leftIsInt);
8317 {
8318 BRANCH(TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
8319 Bind(&leftIsIntRightIsDouble);
8320 {
8321 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
8322 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8323 doubleRight = GetDoubleOfTDouble(right);
8324 Jump(&doFloatOp);
8325 }
8326 }
8327 Bind(&leftIsDouble);
8328 {
8329 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
8330 Bind(&rightIsInt);
8331 {
8332 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType()));
8333 doubleLeft = GetDoubleOfTDouble(left);
8334 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8335 Jump(&doFloatOp);
8336 }
8337 Bind(&rightIsDouble);
8338 {
8339 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
8340 doubleLeft = GetDoubleOfTDouble(left);
8341 doubleRight = GetDoubleOfTDouble(right);
8342 Jump(&doFloatOp);
8343 }
8344 }
8345 }
8346 }
8347 Bind(&doIntOp);
8348 {
8349 result = intOp(env, left, right);
8350 Jump(&exit);
8351 }
8352 Bind(&doFloatOp);
8353 {
8354 result = floatOp(env, *doubleLeft, *doubleRight);
8355 Jump(&exit);
8356 }
8357 Bind(&exit);
8358 auto ret = *result;
8359 env->SubCfgExit();
8360 return ret;
8361 }
8362
TryStringAdd(Environment * env,GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)8363 GateRef StubBuilder::TryStringAdd(Environment *env, GateRef glue, GateRef left, GateRef right,
8364 const BinaryOperation& intOp,
8365 const BinaryOperation& floatOp,
8366 ProfileOperation callback)
8367 {
8368 Label entry(env);
8369 env->SubCfgEntry(&entry);
8370 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8371 Label exit(env);
8372 Label leftIsNotSpecial(env);
8373 Label leftIsNotString(env);
8374 Label leftIsString(env);
8375 Label rightIsNotSpecial(env);
8376 Label rightIsNotString(env);
8377 Label rightIsString(env);
8378 Label stringLeftAddNumberRight(env);
8379 Label numberLeftAddStringRight(env);
8380 Label stringLeftAddStringRight(env);
8381 Label notStringAdd(env);
8382 BRANCH(TaggedIsString(glue, left), &leftIsString, &leftIsNotString);
8383 Bind(&leftIsString);
8384 {
8385 BRANCH(TaggedIsString(glue, right), &stringLeftAddStringRight, &rightIsNotString);
8386 Bind(&rightIsNotString);
8387 {
8388 BRANCH(TaggedIsSpecial(right), ¬StringAdd, &rightIsNotSpecial);
8389 Bind(&rightIsNotSpecial);
8390 {
8391 BRANCH(TaggedIsNumber(right), &stringLeftAddNumberRight, ¬StringAdd);
8392 }
8393 }
8394 }
8395 Bind(&leftIsNotString);
8396 {
8397 BRANCH(TaggedIsString(glue, right), &rightIsString, ¬StringAdd);
8398 Bind(&rightIsString);
8399 {
8400 BRANCH(TaggedIsSpecial(left), ¬StringAdd, &leftIsNotSpecial);
8401 Bind(&leftIsNotSpecial);
8402 {
8403 BRANCH(TaggedIsNumber(left), &numberLeftAddStringRight, ¬StringAdd);
8404 }
8405 }
8406 }
8407 Bind(&stringLeftAddNumberRight);
8408 {
8409 Label hasPendingException(env);
8410 // NOTICE-PGO: support string and number
8411 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberOrStringType()));
8412 BuiltinsStringStubBuilder builtinsStringStubBuilder(this, GetCurrentGlobalEnv());
8413 result = builtinsStringStubBuilder.StringConcat(glue, left, NumberToString(glue, right));
8414 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
8415 Bind(&hasPendingException);
8416 result = Exception();
8417 Jump(&exit);
8418 }
8419 Bind(&numberLeftAddStringRight);
8420 {
8421 Label hasPendingException(env);
8422 // NOTICE-PGO: support string and number
8423 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberOrStringType()));
8424 BuiltinsStringStubBuilder builtinsStringStubBuilder(this, GetCurrentGlobalEnv());
8425 result = builtinsStringStubBuilder.StringConcat(glue, NumberToString(glue, left), right);
8426 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
8427 Bind(&hasPendingException);
8428 result = Exception();
8429 Jump(&exit);
8430 }
8431 Bind(&stringLeftAddStringRight);
8432 {
8433 Label hasPendingException(env);
8434 callback.ProfileOpType(TaggedInt(PGOSampleType::StringType()));
8435 BuiltinsStringStubBuilder builtinsStringStubBuilder(this, GetCurrentGlobalEnv());
8436 result = builtinsStringStubBuilder.StringConcat(glue, left, right);
8437 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
8438 Bind(&hasPendingException);
8439 result = Exception();
8440 Jump(&exit);
8441 }
8442 Bind(¬StringAdd);
8443 {
8444 result = NumberOperation(env, left, right, intOp, floatOp, callback);
8445 Jump(&exit);
8446 }
8447 Bind(&exit);
8448 auto ret = *result;
8449 env->SubCfgExit();
8450 return ret;
8451 }
8452
8453 template<OpCode Op>
FastBinaryOp(GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)8454 GateRef StubBuilder::FastBinaryOp(GateRef glue, GateRef left, GateRef right,
8455 const BinaryOperation& intOp,
8456 const BinaryOperation& floatOp,
8457 ProfileOperation callback)
8458 {
8459 auto env = GetEnvironment();
8460 Label entry(env);
8461 env->SubCfgEntry(&entry);
8462 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8463 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8464 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8465
8466 if (Op == OpCode::ADD) { // Try string Add
8467 result = TryStringAdd(env, glue, left, right, intOp, floatOp, callback);
8468 } else {
8469 result = NumberOperation(env, left, right, intOp, floatOp, callback);
8470 }
8471 auto ret = *result;
8472 env->SubCfgExit();
8473 return ret;
8474 }
8475
8476 template<OpCode Op>
FastAddSubAndMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8477 GateRef StubBuilder::FastAddSubAndMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8478 {
8479 auto intOperation = [=](Environment *env, GateRef left, GateRef right) {
8480 Label entry(env);
8481 env->SubCfgEntry(&entry);
8482 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8483 Label exit(env);
8484 Label overflow(env);
8485 Label notOverflow(env);
8486 auto res = BinaryOpWithOverflow<Op, MachineType::I32>(GetInt32OfTInt(left), GetInt32OfTInt(right));
8487 GateRef condition = env->GetBuilder()->ExtractValue(MachineType::I1, res, Int32(1));
8488 BRANCH(condition, &overflow, ¬Overflow);
8489 Bind(&overflow);
8490 {
8491 auto doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8492 auto doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8493 auto ret = BinaryOp<Op, MachineType::F64>(doubleLeft, doubleRight);
8494 result = DoubleToTaggedDoublePtr(ret);
8495 callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType()));
8496 Jump(&exit);
8497 }
8498 Bind(¬Overflow);
8499 {
8500 res = env->GetBuilder()->ExtractValue(MachineType::I32, res, Int32(0));
8501 if (Op == OpCode::MUL) {
8502 Label resultIsZero(env);
8503 Label returnNegativeZero(env);
8504 Label returnResult(env);
8505 BRANCH(Int32Equal(res, Int32(0)), &resultIsZero, &returnResult);
8506 Bind(&resultIsZero);
8507 BRANCH(LogicOrBuilder(env).Or(Int32LessThan(GetInt32OfTInt(left), Int32(0)))
8508 .Or(Int32LessThan(GetInt32OfTInt(right), Int32(0))).Done(),
8509 &returnNegativeZero, &returnResult);
8510 Bind(&returnNegativeZero);
8511 result = DoubleToTaggedDoublePtr(Double(-0.0));
8512 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType()));
8513 Jump(&exit);
8514 Bind(&returnResult);
8515 result = IntToTaggedPtr(res);
8516 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8517 Jump(&exit);
8518 } else {
8519 result = IntToTaggedPtr(res);
8520 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8521 Jump(&exit);
8522 }
8523 }
8524 Bind(&exit);
8525 auto ret = *result;
8526 env->SubCfgExit();
8527 return ret;
8528 };
8529 auto floatOperation = [=]([[maybe_unused]] Environment *env, GateRef left, GateRef right) {
8530 auto res = BinaryOp<Op, MachineType::F64>(left, right);
8531 return DoubleToTaggedDoublePtr(res);
8532 };
8533 return FastBinaryOp<Op>(glue, left, right, intOperation, floatOperation, callback);
8534 }
8535
FastIntDiv(GateRef left,GateRef right,Label * bailout,ProfileOperation callback)8536 GateRef StubBuilder::FastIntDiv(GateRef left, GateRef right, Label *bailout, ProfileOperation callback)
8537 {
8538 auto env = GetEnvironment();
8539 Label entry(env);
8540 env->SubCfgEntry(&entry);
8541 DEFVARIABLE(intResult, VariableType::INT32(), Int32(0));
8542
8543 GateRef intLeft = GetInt32OfTInt(left);
8544 GateRef intRight = GetInt32OfTInt(right);
8545 Label exit(env);
8546 Label rightIsNotZero(env);
8547 Label leftIsIntMin(env);
8548 Label leftAndRightIsNotBoundary(env);
8549 BRANCH(Int32Equal(intRight, Int32(0)), bailout, &rightIsNotZero);
8550 Bind(&rightIsNotZero);
8551 BRANCH(Int32Equal(intLeft, Int32(INT_MIN)), &leftIsIntMin, &leftAndRightIsNotBoundary);
8552 Bind(&leftIsIntMin);
8553 BRANCH(Int32Equal(intRight, Int32(-1)), bailout, &leftAndRightIsNotBoundary);
8554 Bind(&leftAndRightIsNotBoundary);
8555 {
8556 Label leftIsZero(env);
8557 Label leftIsNotZero(env);
8558 BRANCH(Int32Equal(intLeft, Int32(0)), &leftIsZero, &leftIsNotZero);
8559 Bind(&leftIsZero);
8560 {
8561 BRANCH(Int32LessThan(intRight, Int32(0)), bailout, &leftIsNotZero);
8562 }
8563 Bind(&leftIsNotZero);
8564 {
8565 intResult = Int32Div(intLeft, intRight);
8566 GateRef truncated = Int32Mul(*intResult, intRight);
8567 BRANCH(Equal(intLeft, truncated), &exit, bailout);
8568 }
8569 }
8570 Bind(&exit);
8571 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8572 auto ret = IntToTaggedPtr(*intResult);
8573 env->SubCfgExit();
8574 return ret;
8575 }
8576
FastAdd(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8577 GateRef StubBuilder::FastAdd(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8578 {
8579 return FastAddSubAndMul<OpCode::ADD>(glue, left, right, callback);
8580 }
8581
FastSub(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8582 GateRef StubBuilder::FastSub(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8583 {
8584 return FastAddSubAndMul<OpCode::SUB>(glue, left, right, callback);
8585 }
8586
FastMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8587 GateRef StubBuilder::FastMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8588 {
8589 return FastAddSubAndMul<OpCode::MUL>(glue, left, right, callback);
8590 }
8591
FastMod(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)8592 GateRef StubBuilder::FastMod(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
8593 {
8594 auto env = GetEnvironment();
8595 Label entry(env);
8596 env->SubCfgEntry(&entry);
8597 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8598 DEFVARIABLE(intLeft, VariableType::INT32(), Int32(0));
8599 DEFVARIABLE(intRight, VariableType::INT32(), Int32(0));
8600 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
8601 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
8602 Label leftIsInt(env);
8603 Label leftNotIntOrRightNotInt(env);
8604 Label exit(env);
8605 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotIntOrRightNotInt);
8606 Bind(&leftIsInt);
8607 {
8608 Label rightIsInt(env);
8609 BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotIntOrRightNotInt);
8610 Bind(&rightIsInt);
8611 {
8612 intLeft = GetInt32OfTInt(left);
8613 intRight = GetInt32OfTInt(right);
8614 Label leftGreaterZero(env);
8615 BRANCH(Int32GreaterThanOrEqual(*intLeft, Int32(0)), &leftGreaterZero, &leftNotIntOrRightNotInt);
8616 Bind(&leftGreaterZero);
8617 {
8618 Label rightGreaterZero(env);
8619 BRANCH(Int32GreaterThan(*intRight, Int32(0)), &rightGreaterZero, &leftNotIntOrRightNotInt);
8620 Bind(&rightGreaterZero);
8621 {
8622 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType()));
8623 result = IntToTaggedPtr(Int32Mod(*intLeft, *intRight));
8624 Jump(&exit);
8625 }
8626 }
8627 }
8628 }
8629 Bind(&leftNotIntOrRightNotInt);
8630 {
8631 Label leftIsNumber(env);
8632 Label leftNotNumberOrRightNotNumber(env);
8633 Label leftIsNumberAndRightIsNumber(env);
8634 Label leftIsDoubleAndRightIsDouble(env);
8635 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None()));
8636 // less than 0 result should be double
8637 curType = TaggedInt(PGOSampleType::DoubleType());
8638 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
8639 Bind(&leftIsNumber);
8640 {
8641 Label rightIsNumber(env);
8642 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
8643 Bind(&rightIsNumber);
8644 {
8645 Label leftIsInt1(env);
8646 Label leftNotInt1(env);
8647 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
8648 Bind(&leftIsInt1);
8649 {
8650 GateRef type = TaggedInt(PGOSampleType::IntType());
8651 COMBINE_TYPE_CALL_BACK(curType, type);
8652 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
8653 Jump(&leftIsNumberAndRightIsNumber);
8654 }
8655 Bind(&leftNotInt1);
8656 {
8657 GateRef type = TaggedInt(PGOSampleType::DoubleType());
8658 COMBINE_TYPE_CALL_BACK(curType, type);
8659 doubleLeft = GetDoubleOfTDouble(left);
8660 Jump(&leftIsNumberAndRightIsNumber);
8661 }
8662 }
8663 }
8664 Bind(&leftNotNumberOrRightNotNumber);
8665 {
8666 Jump(&exit);
8667 }
8668 Bind(&leftIsNumberAndRightIsNumber);
8669 {
8670 Label rightIsInt1(env);
8671 Label rightNotInt1(env);
8672 BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
8673 Bind(&rightIsInt1);
8674 {
8675 GateRef type = TaggedInt(PGOSampleType::IntType());
8676 COMBINE_TYPE_CALL_BACK(curType, type);
8677 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
8678 Jump(&leftIsDoubleAndRightIsDouble);
8679 }
8680 Bind(&rightNotInt1);
8681 {
8682 GateRef type = TaggedInt(PGOSampleType::DoubleType());
8683 COMBINE_TYPE_CALL_BACK(curType, type);
8684 doubleRight = GetDoubleOfTDouble(right);
8685 Jump(&leftIsDoubleAndRightIsDouble);
8686 }
8687 }
8688 Bind(&leftIsDoubleAndRightIsDouble);
8689 {
8690 Label rightNotZero(env);
8691 Label rightIsZeroOrNanOrLeftIsNanOrInf(env);
8692 Label rightNotZeroAndNanAndLeftNotNanAndInf(env);
8693 BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotZero);
8694 Bind(&rightNotZero);
8695 {
8696 Label rightNotNan(env);
8697 BRANCH(DoubleIsNAN(*doubleRight), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotNan);
8698 Bind(&rightNotNan);
8699 {
8700 Label leftNotNan(env);
8701 BRANCH(DoubleIsNAN(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf, &leftNotNan);
8702 Bind(&leftNotNan);
8703 {
8704 BRANCH(DoubleIsINF(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf,
8705 &rightNotZeroAndNanAndLeftNotNanAndInf);
8706 }
8707 }
8708 }
8709 Bind(&rightIsZeroOrNanOrLeftIsNanOrInf);
8710 {
8711 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
8712 Jump(&exit);
8713 }
8714 Bind(&rightNotZeroAndNanAndLeftNotNanAndInf);
8715 {
8716 Label leftNotZero(env);
8717 Label leftIsZeroOrRightIsInf(env);
8718 BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZeroOrRightIsInf, &leftNotZero);
8719 Bind(&leftNotZero);
8720 {
8721 Label rightNotInf(env);
8722 BRANCH(DoubleIsINF(*doubleRight), &leftIsZeroOrRightIsInf, &rightNotInf);
8723 Bind(&rightNotInf);
8724 {
8725 result = DoubleToTaggedDoublePtr(CallNGCRuntime(glue, RTSTUB_ID(FloatMod),
8726 { *doubleLeft, *doubleRight }));
8727 Jump(&exit);
8728 }
8729 }
8730 Bind(&leftIsZeroOrRightIsInf);
8731 {
8732 result = DoubleToTaggedDoublePtr(*doubleLeft);
8733 Jump(&exit);
8734 }
8735 }
8736 }
8737 }
8738 Bind(&exit);
8739 auto ret = *result;
8740 env->SubCfgExit();
8741 return ret;
8742 }
8743
GetGlobalOwnProperty(GateRef glue,GateRef receiver,GateRef key,ProfileOperation callback)8744 GateRef StubBuilder::GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRef key, ProfileOperation callback)
8745 {
8746 auto env = GetEnvironment();
8747 Label entryLabel(env);
8748 env->SubCfgEntry(&entryLabel);
8749 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8750 GateRef properties = GetPropertiesFromJSObject(glue, receiver);
8751 GateRef entry = FindEntryFromHashTable<NameDictionary>(glue, properties, key);
8752 Label notNegtiveOne(env);
8753 Label exit(env);
8754 BRANCH(Int32NotEqual(entry, Int32(-1)), ¬NegtiveOne, &exit);
8755 Bind(¬NegtiveOne);
8756 {
8757 result = GetValueFromGlobalDictionary(glue, properties, entry);
8758 Label callGetter(env);
8759 BRANCH(TaggedIsAccessor(glue, *result), &callGetter, &exit);
8760 Bind(&callGetter);
8761 {
8762 result = CallGetterHelper(glue, receiver, receiver, *result, callback);
8763 Jump(&exit);
8764 }
8765 }
8766 Bind(&exit);
8767 auto ret = *result;
8768 env->SubCfgExit();
8769 return ret;
8770 }
8771
GetConstPoolFromFunction(GateRef glue,GateRef jsFunc)8772 GateRef StubBuilder::GetConstPoolFromFunction(GateRef glue, GateRef jsFunc)
8773 {
8774 return env_->GetBuilder()->GetConstPoolFromFunction(glue, jsFunc);
8775 }
8776
GetStringFromConstPool(GateRef glue,GateRef constpool,GateRef index)8777 GateRef StubBuilder::GetStringFromConstPool(GateRef glue, GateRef constpool, GateRef index)
8778 {
8779 GateRef module = Circuit::NullGate();
8780 GateRef hirGate = Circuit::NullGate();
8781 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
8782 ConstPoolType::STRING);
8783 }
8784
GetMethodFromConstPool(GateRef glue,GateRef constpool,GateRef index)8785 GateRef StubBuilder::GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index)
8786 {
8787 GateRef module = Circuit::NullGate();
8788 GateRef hirGate = Circuit::NullGate();
8789 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
8790 ConstPoolType::METHOD);
8791 }
8792
GetArrayLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)8793 GateRef StubBuilder::GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
8794 {
8795 GateRef hirGate = Circuit::NullGate();
8796 GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
8797 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
8798 ConstPoolType::ARRAY_LITERAL);
8799 }
8800
GetObjectLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)8801 GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
8802 {
8803 GateRef hirGate = Circuit::NullGate();
8804 GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
8805 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
8806 ConstPoolType::OBJECT_LITERAL);
8807 }
8808
JSAPIContainerGet(GateRef glue,GateRef receiver,GateRef index)8809 GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)
8810 {
8811 auto env = GetEnvironment();
8812 Label entry(env);
8813 env->SubCfgEntry(&entry);
8814 Label exit(env);
8815 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8816
8817 GateRef lengthOffset = IntPtr(panda::ecmascript::JSAPIArrayList::LENGTH_OFFSET);
8818 GateRef length = GetInt32OfTInt(LoadPrimitive(VariableType::INT64(), receiver, lengthOffset));
8819 Label isVailedIndex(env);
8820 Label notValidIndex(env);
8821 BRANCH(BitAnd(Int32GreaterThanOrEqual(index, Int32(0)),
8822 Int32UnsignedLessThan(index, length)), &isVailedIndex, ¬ValidIndex);
8823 Bind(&isVailedIndex);
8824 {
8825 GateRef elements = GetElementsArray(glue, receiver);
8826 result = GetValueFromTaggedArray(glue, elements, index);
8827 Jump(&exit);
8828 }
8829 Bind(¬ValidIndex);
8830 {
8831 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(GetPropertyOutOfBounds));
8832 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
8833 result = Exception();
8834 Jump(&exit);
8835 }
8836
8837 Bind(&exit);
8838 auto ret = *result;
8839 env->SubCfgExit();
8840 return ret;
8841 }
8842
GetEnumCacheKindFromEnumCache(GateRef enumCache)8843 GateRef StubBuilder::GetEnumCacheKindFromEnumCache(GateRef enumCache)
8844 {
8845 return env_->GetBuilder()->GetEnumCacheKindFromEnumCache(enumCache);
8846 }
8847
GetEnumCacheOwnFromEnumCache(GateRef glue,GateRef enumCache)8848 GateRef StubBuilder::GetEnumCacheOwnFromEnumCache(GateRef glue, GateRef enumCache)
8849 {
8850 return env_->GetBuilder()->GetEnumCacheOwnFromEnumCache(glue, enumCache);
8851 }
8852
GetEnumCacheAllFromEnumCache(GateRef glue,GateRef enumCache)8853 GateRef StubBuilder::GetEnumCacheAllFromEnumCache(GateRef glue, GateRef enumCache)
8854 {
8855 return env_->GetBuilder()->GetEnumCacheAllFromEnumCache(glue, enumCache);
8856 }
8857
GetProtoChainInfoEnumCacheFromEnumCache(GateRef glue,GateRef enumCache)8858 GateRef StubBuilder::GetProtoChainInfoEnumCacheFromEnumCache(GateRef glue, GateRef enumCache)
8859 {
8860 return env_->GetBuilder()->GetProtoChainInfoEnumCacheFromEnumCache(glue, enumCache);
8861 }
8862
IsEnumCacheValid(GateRef glue,GateRef receiver,GateRef cachedHclass,GateRef kind)8863 GateRef StubBuilder::IsEnumCacheValid(GateRef glue, GateRef receiver, GateRef cachedHclass, GateRef kind)
8864 {
8865 return env_->GetBuilder()->IsEnumCacheValid(glue, receiver, cachedHclass, kind);
8866 }
8867
NeedCheckProperty(GateRef glue,GateRef receiver)8868 GateRef StubBuilder::NeedCheckProperty(GateRef glue, GateRef receiver)
8869 {
8870 return env_->GetBuilder()->NeedCheckProperty(glue, receiver);
8871 }
8872
NextInternal(GateRef glue,GateRef iter)8873 GateRef StubBuilder::NextInternal(GateRef glue, GateRef iter)
8874 {
8875 auto env = GetEnvironment();
8876 Label entry(env);
8877 env->SubCfgEntry(&entry);
8878 Label exit(env);
8879 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8880
8881 Label notFinish(env);
8882 Label notEnumCacheValid(env);
8883 Label fastGetKey(env);
8884 Label slowpath(env);
8885
8886 GateRef index = GetIndexFromForInIterator(iter);
8887 GateRef length = GetLengthFromForInIterator(iter);
8888 BRANCH(Int32GreaterThanOrEqual(index, length), &exit, ¬Finish);
8889 Bind(¬Finish);
8890 GateRef keys = GetKeysFromForInIterator(glue, iter);
8891 GateRef receiver = GetObjectFromForInIterator(glue, iter);
8892 GateRef cachedHclass = GetCachedHClassFromForInIterator(glue, iter);
8893 GateRef kind = GetCacheKindFromForInIterator(iter);
8894 BRANCH(IsEnumCacheValid(glue, receiver, cachedHclass, kind), &fastGetKey, ¬EnumCacheValid);
8895 Bind(¬EnumCacheValid);
8896 BRANCH(NeedCheckProperty(glue, receiver), &slowpath, &fastGetKey);
8897 Bind(&fastGetKey);
8898 {
8899 result = GetValueFromTaggedArray(glue, keys, index);
8900 IncreaseIteratorIndex(glue, iter, index);
8901 Jump(&exit);
8902 }
8903 Bind(&slowpath);
8904 {
8905 result = CallRuntime(glue, RTSTUB_ID(GetNextPropNameSlowpath), { iter });
8906 Jump(&exit);
8907 }
8908 Bind(&exit);
8909 auto ret = *result;
8910 env->SubCfgExit();
8911 return ret;
8912 }
8913
GetOrCreateEnumCacheFromHClass(GateRef glue,GateRef hClass)8914 GateRef StubBuilder::GetOrCreateEnumCacheFromHClass(GateRef glue, GateRef hClass)
8915 {
8916 auto env = GetEnvironment();
8917 Label entry(env);
8918 env->SubCfgEntry(&entry);
8919
8920 Label isEnumCache(env);
8921 Label notEnumCache(env);
8922 Label exit(env);
8923 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8924
8925 GateRef enumCache = GetEnumCacheFromHClass(glue, hClass);
8926 BRANCH(TaggedIsEnumCache(glue, enumCache), &isEnumCache, ¬EnumCache);
8927 Bind(&isEnumCache);
8928 {
8929 result = enumCache;
8930 Jump(&exit);
8931 }
8932 Bind(¬EnumCache);
8933 {
8934 NewObjectStubBuilder newBuilder(this);
8935 GateRef enumCacheNew = newBuilder.NewEnumCache(glue);
8936 SetEnumCacheToHClass(VariableType::JS_POINTER(), glue, hClass, enumCacheNew);
8937 result = enumCacheNew;
8938 Jump(&exit);
8939 }
8940 Bind(&exit);
8941 auto ret = *result;
8942 env->SubCfgExit();
8943 return ret;
8944 }
8945
GetFunctionPrototype(GateRef glue,size_t index)8946 GateRef StubBuilder::GetFunctionPrototype(GateRef glue, size_t index)
8947 {
8948 auto env = GetEnvironment();
8949 Label entry(env);
8950 env->SubCfgEntry(&entry);
8951 Label exit(env);
8952 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8953
8954 Label isHeapObject(env);
8955 Label isJSHclass(env);
8956
8957 GateRef globalEnv = GetCurrentGlobalEnv();
8958 GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, index);
8959 GateRef protoOrHclass = Load(VariableType::JS_ANY(), glue, func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
8960 result = protoOrHclass;
8961 BRANCH(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &exit);
8962 Bind(&isHeapObject);
8963 BRANCH(IsJSHClass(glue, protoOrHclass), &isJSHclass, &exit);
8964 Bind(&isJSHclass);
8965 {
8966 result = GetPrototypeFromHClass(glue, protoOrHclass);
8967 Jump(&exit);
8968 }
8969 Bind(&exit);
8970 auto ret = *result;
8971 env->SubCfgExit();
8972 return ret;
8973 }
8974
DeletePropertyOrThrow(GateRef glue,GateRef obj,GateRef value)8975 GateRef StubBuilder::DeletePropertyOrThrow(GateRef glue, GateRef obj, GateRef value)
8976 {
8977 auto env = GetEnvironment();
8978 Label entry(env);
8979 env->SubCfgEntry(&entry);
8980 Label exit(env);
8981 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
8982 DEFVARIABLE(key, VariableType::JS_ANY(), value);
8983 Label toObject(env);
8984 Label isNotExceptiont(env);
8985 Label objectIsEcmaObject(env);
8986 Label objectIsHeapObject(env);
8987 GateRef object = ToObject(glue, GetCurrentGlobalEnv(), obj);
8988 BRANCH(TaggedIsException(object), &exit, &isNotExceptiont);
8989 Bind(&isNotExceptiont);
8990 {
8991 Label deleteProper(env);
8992 #if ENABLE_NEXT_OPTIMIZATION
8993 key = ToPropertyKey(glue, value);
8994 #else
8995 key = CallRuntime(glue, RTSTUB_ID(ToPropertyKey), {value});
8996 #endif
8997 BRANCH(HasPendingException(glue), &exit, &deleteProper);
8998 Bind(&deleteProper);
8999 {
9000 result = DeleteProperty(glue, object, *key);
9001 Jump(&exit);
9002 }
9003 }
9004 Bind(&exit);
9005 auto ret = *result;
9006 env->SubCfgExit();
9007 return ret;
9008 }
9009
DeleteProperty(GateRef glue,GateRef obj,GateRef value)9010 GateRef StubBuilder::DeleteProperty(GateRef glue, GateRef obj, GateRef value)
9011 {
9012 auto env = GetEnvironment();
9013 Label entry(env);
9014 env->SubCfgEntry(&entry);
9015 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
9016 Label exit(env);
9017 Label notRegularJSObject(env);
9018 Label regularJSObjDeletePrototype(env);
9019 BRANCH(TaggedIsRegularObject(glue, obj), ®ularJSObjDeletePrototype, ¬RegularJSObject);
9020 Bind(®ularJSObjDeletePrototype);
9021 {
9022 result = CallRuntime(glue, RTSTUB_ID(RegularJSObjDeletePrototype), { obj, value});
9023 Jump(&exit);
9024 }
9025 Bind(¬RegularJSObject);
9026 {
9027 result = CallRuntime(glue, RTSTUB_ID(CallJSObjDeletePrototype), { obj, value});
9028 Jump(&exit);
9029 }
9030
9031 Bind(&exit);
9032 auto ret = *result;
9033 env->SubCfgExit();
9034 return ret;
9035 }
9036
ToPrototypeOrObj(GateRef glue,GateRef obj)9037 GateRef StubBuilder::ToPrototypeOrObj(GateRef glue, GateRef obj)
9038 {
9039 auto env = GetEnvironment();
9040 Label entry(env);
9041 env->SubCfgEntry(&entry);
9042 Label exit(env);
9043 DEFVARIABLE(result, VariableType::JS_ANY(), obj);
9044 Label isNotEcmaObject(env);
9045 Label isNumber(env);
9046 Label notNumber(env);
9047 Label isBoolean(env);
9048 Label notBoolean(env);
9049 Label isString(env);
9050 Label notString(env);
9051 Label isSymbol(env);
9052 Label notSymbol(env);
9053 Label isBigInt(env);
9054 BRANCH(IsEcmaObject(glue, obj), &exit, &isNotEcmaObject);
9055 Bind(&isNotEcmaObject);
9056 BRANCH(TaggedIsNumber(obj), &isNumber, ¬Number);
9057 Bind(&isNumber);
9058 {
9059 result = GetFunctionPrototype(glue, GlobalEnv::NUMBER_FUNCTION_INDEX);
9060 Jump(&exit);
9061 }
9062 Bind(¬Number);
9063 BRANCH(TaggedIsBoolean(obj), &isBoolean, ¬Boolean);
9064 Bind(&isBoolean);
9065 {
9066 result = GetFunctionPrototype(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
9067 Jump(&exit);
9068 }
9069 Bind(¬Boolean);
9070 BRANCH(TaggedIsString(glue, obj), &isString, ¬String);
9071 Bind(&isString);
9072 {
9073 result = GetFunctionPrototype(glue, GlobalEnv::STRING_FUNCTION_INDEX);
9074 Jump(&exit);
9075 }
9076 Bind(¬String);
9077 BRANCH(TaggedIsSymbol(glue, obj), &isSymbol, ¬Symbol);
9078 Bind(&isSymbol);
9079 {
9080 result = GetFunctionPrototype(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX);
9081 Jump(&exit);
9082 }
9083 Bind(¬Symbol);
9084 BRANCH(TaggedIsBigInt(glue, obj), &isBigInt, &exit);
9085 Bind(&isBigInt);
9086 {
9087 result = GetFunctionPrototype(glue, GlobalEnv::BIGINT_FUNCTION_INDEX);
9088 Jump(&exit);
9089 }
9090 Bind(&exit);
9091 auto ret = *result;
9092 env->SubCfgExit();
9093 return ret;
9094 }
9095
ToPropertyKey(GateRef glue,GateRef tagged)9096 GateRef StubBuilder::ToPropertyKey(GateRef glue, GateRef tagged)
9097 {
9098 auto env = GetEnvironment();
9099 Label entry(env);
9100 env->SubCfgEntry(&entry);
9101 Label exit(env);
9102 Label notPrimitive(env);
9103 Label hasPendingException(env);
9104 Label checkSymbol(env);
9105 Label castKey(env);
9106 DEFVARIABLE(result, VariableType::JS_ANY(), tagged);
9107
9108 BRANCH(TaggedIsPropertyKey(glue, tagged), &exit, ¬Primitive);
9109
9110 Bind(¬Primitive);
9111 {
9112 result = ToPrimitive(glue, tagged, PreferredPrimitiveType::PREFER_STRING);
9113 BRANCH(HasPendingException(glue), &hasPendingException, &checkSymbol);
9114 }
9115
9116 Bind(&checkSymbol);
9117 {
9118 BRANCH(TaggedIsSymbol(glue, *result), &exit, &castKey);
9119 }
9120
9121 Bind(&castKey);
9122 {
9123 result = JSTaggedValueToString(glue, *result);
9124 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
9125 }
9126
9127 Bind(&hasPendingException);
9128 {
9129 result = Exception();
9130 Jump(&exit);
9131 }
9132
9133 Bind(&exit);
9134 auto ret = *result;
9135 env->SubCfgExit();
9136 return ret;
9137 }
9138
TaggedIsPropertyKey(GateRef glue,GateRef obj)9139 GateRef StubBuilder::TaggedIsPropertyKey(GateRef glue, GateRef obj)
9140 {
9141 return LogicOrBuilder(env_).Or(TaggedIsStringOrSymbol(glue, obj)).Or(TaggedIsNumber(obj)).Done();
9142 }
9143
9144 // JSTaggedValue::HasProperty (O, P)
HasProperty(GateRef glue,GateRef obj,GateRef key,GateRef hir)9145 GateRef StubBuilder::HasProperty(GateRef glue, GateRef obj, GateRef key, GateRef hir)
9146 {
9147 auto env = GetEnvironment();
9148 Label entry(env);
9149 env->SubCfgEntry(&entry);
9150 Label exit(env);
9151 Label slowpath(env);
9152 Label isJSProxy(env);
9153 Label notJSProxy(env);
9154 Label isTypedArray(env);
9155 Label notTypedArray(env);
9156 Label isModuleNamespace(env);
9157 Label notModuleNamespace(env);
9158 Label isSpecialContainer(env);
9159 Label defaultObj(env);
9160 DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
9161
9162 BRANCH(IsJsProxy(glue, obj), &isJSProxy, ¬JSProxy);
9163 Bind(&isJSProxy);
9164 {
9165 result = CallRuntime(glue, RTSTUB_ID(JSProxyHasProperty), {obj, key});
9166 Jump(&exit);
9167 }
9168
9169 Bind(¬JSProxy);
9170 BRANCH(BitOr(IsTypedArray(glue, obj), IsSharedTypedArray(glue, obj)), &isTypedArray, ¬TypedArray);
9171 Bind(&isTypedArray);
9172 {
9173 result = CallRuntime(glue, RTSTUB_ID(JSTypedArrayHasProperty), {obj, key});
9174 Jump(&exit);
9175 }
9176
9177 Bind(¬TypedArray);
9178 BRANCH(IsModuleNamespace(glue, obj), &isModuleNamespace, ¬ModuleNamespace);
9179 Bind(&isModuleNamespace);
9180 {
9181 result = CallRuntime(glue, RTSTUB_ID(ModuleNamespaceHasProperty), {obj, key});
9182 Jump(&exit);
9183 }
9184
9185 Bind(¬ModuleNamespace);
9186 BRANCH(IsSpecialContainer(glue, obj), &isSpecialContainer, &defaultObj);
9187 Bind(&isSpecialContainer);
9188 {
9189 Jump(&slowpath);
9190 }
9191
9192 Bind(&defaultObj);
9193 {
9194 result = JSObjectHasProperty(glue, obj, key, hir);
9195 Jump(&exit);
9196 }
9197
9198 Bind(&slowpath);
9199 {
9200 result = CallRuntime(glue, RTSTUB_ID(HasProperty), {obj, key});
9201 Jump(&exit);
9202 }
9203
9204 Bind(&exit);
9205 auto res = *result;
9206 env->SubCfgExit();
9207 return res;
9208 }
9209
IsIn(GateRef glue,GateRef prop,GateRef obj)9210 GateRef StubBuilder::IsIn(GateRef glue, GateRef prop, GateRef obj)
9211 {
9212 auto env = GetEnvironment();
9213 Label entry(env);
9214 env->SubCfgEntry(&entry);
9215 Label exit(env);
9216 Label isEcmaObject(env);
9217 Label notEcmaObject(env);
9218 Label checkProperty(env);
9219 Label isPendingException(env);
9220
9221 DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
9222 DEFVARIABLE(propKey, VariableType::JS_ANY(), Undefined());
9223
9224 BRANCH(IsEcmaObject(glue, obj), &isEcmaObject, ¬EcmaObject);
9225
9226 Bind(¬EcmaObject);
9227 {
9228 auto taggedId = Int32(GET_MESSAGE_STRING_ID(InOperatorOnNonObject));
9229 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
9230 result = Exception();
9231 Jump(&exit);
9232 }
9233
9234 Bind(&isEcmaObject);
9235 {
9236 propKey = ToPropertyKey(glue, prop);
9237 BRANCH(HasPendingException(glue), &isPendingException, &checkProperty);
9238 }
9239
9240 Bind(&checkProperty);
9241 {
9242 result = CallCommonStub(glue, CommonStubCSigns::JSTaggedValueHasProperty,
9243 { glue, obj, *propKey, GetCurrentGlobalEnv() });
9244 BRANCH(HasPendingException(glue), &isPendingException, &exit);
9245 }
9246
9247 Bind(&isPendingException);
9248 {
9249 result = Exception();
9250 Jump(&exit);
9251 }
9252
9253 Bind(&exit);
9254 auto ret = *result;
9255 env->SubCfgExit();
9256 return ret;
9257 }
9258
IsSpecialKeysObject(GateRef glue,GateRef obj)9259 GateRef StubBuilder::IsSpecialKeysObject(GateRef glue, GateRef obj)
9260 {
9261 return LogicOrBuilder(env_).Or(IsTypedArray(glue, obj)).Or(IsModuleNamespace(glue, obj)).Or(IsSpecialContainer(glue, obj)).Done();
9262 }
9263
IsSlowKeysObject(GateRef glue,GateRef obj)9264 GateRef StubBuilder::IsSlowKeysObject(GateRef glue, GateRef obj)
9265 {
9266 auto env = GetEnvironment();
9267 Label entry(env);
9268 env->SubCfgEntry(&entry);
9269 Label exit(env);
9270 DEFVARIABLE(result, VariableType::BOOL(), False());
9271
9272 Label isHeapObject(env);
9273 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
9274 Bind(&isHeapObject);
9275 {
9276 result = LogicOrBuilder(env).Or(IsJSGlobalObject(glue, obj)).Or(IsJsProxy(glue, obj)).Or(IsSpecialKeysObject(glue, obj)).Done();
9277 Jump(&exit);
9278 }
9279 Bind(&exit);
9280 auto ret = *result;
9281 env->SubCfgExit();
9282 return ret;
9283 }
9284
GetNumberOfElements(GateRef glue,GateRef obj)9285 GateRef StubBuilder::GetNumberOfElements(GateRef glue, GateRef obj)
9286 {
9287 auto env = GetEnvironment();
9288 Label entry(env);
9289 env->SubCfgEntry(&entry);
9290 Label exit(env);
9291 DEFVARIABLE(numOfElements, VariableType::INT32(), Int32(0));
9292 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
9293
9294 Label isJSPrimitiveRef(env);
9295 Label isPrimitiveString(env);
9296 Label notPrimitiveString(env);
9297 Label isDictMode(env);
9298 Label notDictMode(env);
9299
9300 BRANCH(IsJSPrimitiveRef(glue, obj), &isJSPrimitiveRef, ¬PrimitiveString);
9301 Bind(&isJSPrimitiveRef);
9302 GateRef value = Load(VariableType::JS_ANY(), glue, obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
9303 BRANCH(TaggedIsString(glue, value), &isPrimitiveString, ¬PrimitiveString);
9304 Bind(&isPrimitiveString);
9305 {
9306 numOfElements = GetLengthFromString(value);
9307 Jump(¬PrimitiveString);
9308 }
9309 Bind(¬PrimitiveString);
9310 GateRef elements = GetElementsArray(glue, obj);
9311 BRANCH(IsDictionaryMode(glue, elements), &isDictMode, ¬DictMode);
9312 Bind(¬DictMode);
9313 {
9314 Label loopHead(env);
9315 Label loopEnd(env);
9316 Label iLessLength(env);
9317 Label notHole(env);
9318 GateRef elementsLen = GetLengthOfTaggedArray(elements);
9319 Jump(&loopHead);
9320 LoopBegin(&loopHead);
9321 {
9322 BRANCH(Int32UnsignedLessThan(*i, elementsLen), &iLessLength, &exit);
9323 Bind(&iLessLength);
9324 {
9325 GateRef element = GetTaggedValueWithElementsKind(glue, obj, *i);
9326 BRANCH(TaggedIsHole(element), &loopEnd, ¬Hole);
9327 Bind(¬Hole);
9328 numOfElements = Int32Add(*numOfElements, Int32(1));
9329 Jump(&loopEnd);
9330 }
9331 Bind(&loopEnd);
9332 i = Int32Add(*i, Int32(1));
9333 LoopEnd(&loopHead);
9334 }
9335 }
9336 Bind(&isDictMode);
9337 {
9338 GateRef entryCount = TaggedGetInt(
9339 GetValueFromTaggedArray(glue, elements, Int32(TaggedHashTable<NumberDictionary>::NUMBER_OF_ENTRIES_INDEX)));
9340 numOfElements = Int32Add(*numOfElements, entryCount);
9341 Jump(&exit);
9342 }
9343 Bind(&exit);
9344 auto ret = *numOfElements;
9345 env->SubCfgExit();
9346 return ret;
9347 }
9348
9349 // When receiver and receiver's prototype chain have no elements
9350 // and ProtoChainInfoEnumCache of receiver's proto == JSTaggedValue::Undefined,
9351 // the SimpleEnumCache valid.
IsSimpleEnumCacheValid(GateRef glue,GateRef obj)9352 GateRef StubBuilder::IsSimpleEnumCacheValid(GateRef glue, GateRef obj)
9353 {
9354 auto env = GetEnvironment();
9355 Label entry(env);
9356 env->SubCfgEntry(&entry);
9357 Label exit(env);
9358 DEFVARIABLE(result, VariableType::BOOL(), False());
9359 DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
9360
9361 Label receiverHasNoElements(env);
9362 Label protoIsHeapObject(env);
9363 Label afterLoop(env);
9364 Label isProtoEnumCache(env);
9365 Label isKeyUndefined(env);
9366
9367 // Check no elements on self.
9368 GateRef numOfElements = GetNumberOfElements(glue, obj);
9369 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
9370
9371 Bind(&receiverHasNoElements);
9372 // Since current isn't a heapObject, the receiver's proto chain has no keys.
9373 current = GetPrototypeFromHClass(glue, LoadHClass(glue, obj));
9374 BRANCH_LIKELY(TaggedIsHeapObject(*current), &protoIsHeapObject, &afterLoop);
9375
9376 // Check protoChainInfoEnumCache of receiver's proto == JSTaggedValue::Undefined.
9377 Bind(&protoIsHeapObject);
9378 {
9379 GateRef protoHClass = LoadHClass(glue, *current);
9380 GateRef enumCacheProto = GetEnumCacheFromHClass(glue, protoHClass);
9381 BRANCH(TaggedIsEnumCache(glue, enumCacheProto), &isProtoEnumCache, &exit);
9382 Bind(&isProtoEnumCache);
9383 GateRef keyProto = GetProtoChainInfoEnumCacheFromEnumCache(glue, enumCacheProto);
9384 BRANCH(TaggedIsUndefined(keyProto), &isKeyUndefined, &exit);
9385 }
9386
9387 // Check no elements on prototype chain.
9388 Bind(&isKeyUndefined);
9389 {
9390 Label loopHead(env);
9391 Label loopEnd(env);
9392 Label currentHasNoElements(env);
9393 Jump(&loopHead);
9394 LoopBegin(&loopHead);
9395 {
9396 GateRef numOfCurrentElements = GetNumberOfElements(glue, *current);
9397 BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, ¤tHasNoElements);
9398 Bind(¤tHasNoElements);
9399 GateRef hclass = LoadHClass(glue, *current);
9400 current = GetPrototypeFromHClass(glue, hclass);
9401 BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
9402 }
9403 Bind(&loopEnd);
9404 LoopEnd(&loopHead);
9405 }
9406
9407 Bind(&afterLoop);
9408 {
9409 result = True();
9410 Jump(&exit);
9411 }
9412
9413 Bind(&exit);
9414 auto ret = *result;
9415 env->SubCfgExit();
9416 return ret;
9417 }
9418
9419 // When receiver and receiver's prototype chain have no elements,
9420 // and receiver.proto.EnumCacheAll == receiver.ProtoChainInfoEnumCache,
9421 // the ProtoChainEnumCache valid.
IsProtoChainCacheValid(GateRef glue,GateRef obj)9422 GateRef StubBuilder::IsProtoChainCacheValid(GateRef glue, GateRef obj)
9423 {
9424 auto env = GetEnvironment();
9425 Label entry(env);
9426 env->SubCfgEntry(&entry);
9427 Label exit(env);
9428 DEFVARIABLE(result, VariableType::BOOL(), False());
9429 DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
9430
9431 Label receiverHasNoElements(env);
9432 Label prototypeIsHeapObj(env);
9433 Label isEnumCache(env);
9434 Label isCacheEqual(env);
9435
9436 // Check no elements on self.
9437 GateRef numOfElements = GetNumberOfElements(glue, obj);
9438 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
9439
9440 Bind(&receiverHasNoElements);
9441 GateRef hClass = LoadHClass(glue, obj);
9442 GateRef prototype = GetPrototypeFromHClass(glue, hClass);
9443 BRANCH(TaggedIsHeapObject(prototype), &prototypeIsHeapObj, &exit);
9444
9445 // Check receiver.proto.EnumCacheAll == receiver.ProtoChainInfoEnumCache.
9446 Bind(&prototypeIsHeapObj);
9447 GateRef protoHClass = LoadHClass(glue, prototype);
9448 GateRef enumCacheOwn = GetEnumCacheFromHClass(glue, hClass);
9449 GateRef enumCacheProto = GetEnumCacheFromHClass(glue, protoHClass);
9450 GateRef checkEnumCache = LogicAndBuilder(env)
9451 .And(TaggedIsEnumCache(glue, enumCacheOwn))
9452 .And(TaggedIsEnumCache(glue, enumCacheProto))
9453 .Done();
9454 BRANCH(checkEnumCache, &isEnumCache, &exit);
9455 Bind(&isEnumCache);
9456 GateRef keyOwn = GetProtoChainInfoEnumCacheFromEnumCache(glue, enumCacheOwn);
9457 GateRef keyProto = GetEnumCacheAllFromEnumCache(glue, enumCacheProto);
9458 GateRef checkKey = LogicAndBuilder(env)
9459 .And(Equal(keyOwn, keyProto))
9460 .And(TaggedIsNotNull(keyOwn))
9461 .Done();
9462 BRANCH(checkKey, &isCacheEqual, &exit);
9463
9464 // Check no elements on prototype chain.
9465 Bind(&isCacheEqual);
9466 {
9467 Label loopHead(env);
9468 Label loopEnd(env);
9469 Label afterLoop(env);
9470 Label currentHasNoElements(env);
9471 current = prototype;
9472 BRANCH(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
9473 LoopBegin(&loopHead);
9474 {
9475 GateRef numOfCurrentElements = GetNumberOfElements(glue, *current);
9476 BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, ¤tHasNoElements);
9477 Bind(¤tHasNoElements);
9478 current = GetPrototypeFromHClass(glue, LoadHClass(glue, *current));
9479 BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
9480 }
9481 Bind(&loopEnd);
9482 LoopEnd(&loopHead);
9483 Bind(&afterLoop);
9484 {
9485 result = True();
9486 Jump(&exit);
9487 }
9488 }
9489
9490 Bind(&exit);
9491 auto ret = *result;
9492 env->SubCfgExit();
9493 return ret;
9494 }
9495
TryGetEnumCache(GateRef glue,GateRef obj)9496 GateRef StubBuilder::TryGetEnumCache(GateRef glue, GateRef obj)
9497 {
9498 auto env = GetEnvironment();
9499 Label entry(env);
9500 env->SubCfgEntry(&entry);
9501 Label exit(env);
9502 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
9503
9504 Label isEnumCache(env);
9505 Label notSlowKeys(env);
9506 Label notDictionaryMode(env);
9507 Label checkSimpleEnumCache(env);
9508 Label notSimpleEnumCache(env);
9509 Label checkEnumCacheWithProtoChainInfo(env);
9510 Label enumCacheValid(env);
9511
9512 BRANCH(IsSlowKeysObject(glue, obj), &exit, ¬SlowKeys);
9513 Bind(¬SlowKeys);
9514 GateRef hclass = LoadHClass(glue, obj);
9515 BRANCH(IsDictionaryModeByHClass(hclass), &exit, ¬DictionaryMode);
9516 Bind(¬DictionaryMode);
9517 GateRef enumCache = GetEnumCacheFromHClass(glue, hclass);
9518 BRANCH(TaggedIsEnumCache(glue, enumCache), &isEnumCache, &exit);
9519 Bind(&isEnumCache);
9520 GateRef kind = GetEnumCacheKindFromEnumCache(enumCache);
9521 BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE))),
9522 &checkSimpleEnumCache, ¬SimpleEnumCache);
9523 Bind(&checkSimpleEnumCache);
9524 {
9525 BRANCH(IsSimpleEnumCacheValid(glue, obj), &enumCacheValid, &exit);
9526 }
9527 Bind(¬SimpleEnumCache);
9528 {
9529 BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::PROTOCHAIN))),
9530 &checkEnumCacheWithProtoChainInfo, &exit);
9531 }
9532 Bind(&checkEnumCacheWithProtoChainInfo);
9533 {
9534 BRANCH(IsProtoChainCacheValid(glue, obj), &enumCacheValid, &exit);
9535 }
9536 Bind(&enumCacheValid);
9537 {
9538 result = GetEnumCacheAllFromEnumCache(glue, enumCache);
9539 Jump(&exit);
9540 }
9541 Bind(&exit);
9542 auto ret = *result;
9543 env->SubCfgExit();
9544 return ret;
9545 }
9546
DoubleToInt(GateRef glue,GateRef x,size_t typeBits)9547 GateRef StubBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits)
9548 {
9549 auto env = GetEnvironment();
9550 Label entry(env);
9551 env->SubCfgEntry(&entry);
9552 Label exit(env);
9553 Label overflow(env);
9554
9555 GateRef xInt = ChangeFloat64ToInt32(x);
9556 DEFVARIABLE(result, VariableType::INT32(), xInt);
9557
9558 if (env->IsAmd64()) {
9559 // 0x80000000: amd64 overflow return value
9560 BRANCH(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit);
9561 } else {
9562 GateRef xInt64 = CastDoubleToInt64(x);
9563 // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
9564 GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
9565 exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
9566 exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
9567 GateRef bits = Int32(typeBits - 1);
9568 // exp < 32 - 1
9569 BRANCH(Int32LessThan(exp, bits), &exit, &overflow);
9570 }
9571 Bind(&overflow);
9572 {
9573 result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), { x, IntPtr(typeBits) });
9574 Jump(&exit);
9575 }
9576 Bind(&exit);
9577 auto ret = *result;
9578 env->SubCfgExit();
9579 return ret;
9580 }
9581
ReturnExceptionIfAbruptCompletion(GateRef glue)9582 void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue)
9583 {
9584 auto env = GetEnvironment();
9585 Label entry(env);
9586 env->SubCfgEntry(&entry);
9587 Label exit(env);
9588 Label hasPendingException(env);
9589 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
9590 Bind(&hasPendingException);
9591 Return(Exception());
9592 Bind(&exit);
9593 env->SubCfgExit();
9594 return;
9595 }
9596
CalcHashcodeForInt(GateRef value)9597 GateRef StubBuilder::CalcHashcodeForInt(GateRef value)
9598 {
9599 return env_->GetBuilder()->CalcHashcodeForInt(value);
9600 }
9601
CanDoubleRepresentInt(GateRef exp,GateRef expBits,GateRef fractionBits)9602 GateRef StubBuilder::CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits)
9603 {
9604 return LogicOrBuilder(env_)
9605 .Or(Int64Equal(expBits, Int64(base::DOUBLE_EXPONENT_MASK)))
9606 .Or(BitAnd(Int64Equal(expBits, Int64(0)), Int64NotEqual(fractionBits, Int64(0))))
9607 .Or(Int64LessThan(exp, Int64(0)))
9608 .Or(Int64GreaterThanOrEqual(exp, Int64(31U)))
9609 .Or(Int64NotEqual(Int64And(Int64LSL(fractionBits, exp), Int64(base::DOUBLE_SIGNIFICAND_MASK)),
9610 Int64(0)))
9611 .Done();
9612 }
9613
CalcHashcodeForDouble(GateRef x,Variable * res,Label * exit)9614 void StubBuilder::CalcHashcodeForDouble(GateRef x, Variable *res, Label *exit)
9615 {
9616 auto env = GetEnvironment();
9617 GateRef xInt64 = Int64Sub(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
9618 GateRef fractionBits = Int64And(xInt64, Int64(base::DOUBLE_SIGNIFICAND_MASK));
9619 GateRef expBits = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
9620 GateRef isZero = BitAnd(
9621 Int64Equal(expBits, Int64(0)),
9622 Int64Equal(fractionBits, Int64(0)));
9623 Label zero(env);
9624 Label nonZero(env);
9625
9626 BRANCH(isZero, &zero, &nonZero);
9627 Bind(&nonZero);
9628 {
9629 DEFVARIABLE(value, VariableType::JS_ANY(), x);
9630 // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
9631 GateRef exp = Int64Sub(
9632 Int64LSR(expBits, Int64(base::DOUBLE_SIGNIFICAND_SIZE)),
9633 Int64(base::DOUBLE_EXPONENT_BIAS));
9634 Label convertToInt(env);
9635 Label calcHash(env);
9636 BRANCH(CanDoubleRepresentInt(exp, expBits, fractionBits), &calcHash, &convertToInt);
9637 Bind(&convertToInt);
9638 {
9639 *res = ChangeFloat64ToInt32(CastInt64ToFloat64(xInt64));
9640 Jump(exit);
9641 }
9642 Bind(&calcHash);
9643 {
9644 *res = env_->GetBuilder()->CalcHashcodeForInt(*value);
9645 Jump(exit);
9646 }
9647 }
9648
9649 Bind(&zero);
9650 *res = Int32(0);
9651 Jump(exit);
9652 }
9653
GetHash(GateRef glue,GateRef object)9654 GateRef StubBuilder::GetHash(GateRef glue, GateRef object)
9655 {
9656 auto env = GetEnvironment();
9657 Label subentry(env);
9658 Label isHeapObject(env);
9659 Label exit(env);
9660 env->SubCfgEntry(&subentry);
9661 GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
9662 GateRef value = Load(VariableType::JS_ANY(), glue, object, hashOffset);
9663 DEFVARIABLE(res, VariableType::INT32(), GetInt32OfTInt(value));
9664 BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit);
9665
9666 Bind(&isHeapObject);
9667 {
9668 Label isTaggedArray(env);
9669 Label notTaggedArray(env);
9670 BRANCH(IsTaggedArray(glue, value), &isTaggedArray, ¬TaggedArray);
9671 Bind(&isTaggedArray);
9672 GateRef extlen = GetExtraLengthOfTaggedArray(value);
9673 GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
9674 res = GetInt32OfTInt(GetValueFromTaggedArray(glue, value, index));
9675 Jump(&exit);
9676 Bind(¬TaggedArray);
9677 res = Int32(0);
9678 Jump(&exit);
9679 }
9680 Bind(&exit);
9681 auto ret = *res;
9682 env->SubCfgExit();
9683 return ret;
9684 }
9685
SetHash(GateRef glue,GateRef object,GateRef hash)9686 void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash)
9687 {
9688 auto env = GetEnvironment();
9689 Label subentry(env);
9690 Label isHeapObject(env);
9691 Label notHeapObject(env);
9692 Label exit(env);
9693 env->SubCfgEntry(&subentry);
9694 GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
9695 GateRef value = Load(VariableType::JS_ANY(), glue, object, hashOffset);
9696 DEFVARIABLE(res, VariableType::JS_ANY(), object);
9697 BRANCH(TaggedIsHeapObject(value), &isHeapObject, ¬HeapObject);
9698
9699 Bind(&isHeapObject);
9700 {
9701 Label isTaggedArray(env);
9702 Label notTaggedArray(env);
9703 BRANCH(IsTaggedArray(glue, value), &isTaggedArray, ¬TaggedArray);
9704 Bind(&isTaggedArray);
9705 {
9706 GateRef extlen = GetExtraLengthOfTaggedArray(value);
9707 GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
9708 SetValueToTaggedArray(VariableType::JS_ANY(), glue, value, index, IntToTaggedInt(hash));
9709 Jump(&exit);
9710 }
9711 Bind(¬TaggedArray);
9712 {
9713 Label isNativePointer(env);
9714 Label notNativePointer(env);
9715 BRANCH(IsNativePointer(glue, value), &isNativePointer, ¬NativePointer);
9716 Bind(&isNativePointer);
9717 {
9718 NewObjectStubBuilder newBuilder(this);
9719 GateRef array = newBuilder.NewTaggedArray(glue, Int32(ECMAObject::RESOLVED_MAX_SIZE));
9720 SetExtraLengthOfTaggedArray(glue, array, Int32(0));
9721 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
9722 Int32(ECMAObject::HASH_INDEX), IntToTaggedInt(hash));
9723 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
9724 Int32(ECMAObject::FUNCTION_EXTRA_INDEX), value);
9725 Store(VariableType::JS_ANY(), glue, object, hashOffset, array);
9726 Jump(&exit);
9727 }
9728 Bind(¬NativePointer);
9729 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
9730 Jump(&exit);
9731 }
9732 }
9733 Bind(¬HeapObject);
9734 {
9735 Store(VariableType::JS_ANY(), glue, object, hashOffset, IntToTaggedInt(hash), MemoryAttribute::NoBarrier());
9736 Jump(&exit);
9737 }
9738 Bind(&exit);
9739 env->SubCfgExit();
9740 }
9741
CalcHashcodeForObject(GateRef glue,GateRef value,Variable * res,Label * exit)9742 void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit)
9743 {
9744 auto env = GetEnvironment();
9745
9746 GateRef hash = GetHash(glue, value);
9747 *res = hash;
9748 Label calcHash(env);
9749 BRANCH(Int32Equal(**res, Int32(0)), &calcHash, exit);
9750 Bind(&calcHash);
9751 GateRef offset = IntPtr(JSThread::GlueData::GetRandomStatePtrOffset(env_->Is32Bit()));
9752 GateRef randomStatePtr = LoadPrimitive(VariableType::NATIVE_POINTER(), glue, offset);
9753 GateRef randomState = LoadPrimitive(VariableType::INT64(), randomStatePtr, IntPtr(0));
9754 GateRef k1 = Int64Xor(randomState, Int64LSR(randomState, Int64(base::RIGHT12)));
9755 GateRef k2 = Int64Xor(k1, Int64LSL(k1, Int64(base::LEFT25)));
9756 GateRef k3 = Int64Xor(k2, Int64LSR(k2, Int64(base::RIGHT27)));
9757 Store(VariableType::INT64(), glue, randomStatePtr, IntPtr(0), k3);
9758 GateRef k4 = Int64Mul(k3, Int64(base::GET_MULTIPLY));
9759 GateRef k5 = Int64LSR(k4, Int64(base::INT64_BITS - base::INT32_BITS));
9760 GateRef k6 = Int32And(TruncInt64ToInt32(k5), Int32(INT32_MAX));
9761 SetHash(glue, value, k6);
9762 *res = k6;
9763 Jump(exit);
9764 }
9765
GetHashcodeFromString(GateRef glue,GateRef value,GateRef hir)9766 GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir)
9767 {
9768 return env_->GetBuilder()->GetHashcodeFromString(glue, value, hir);
9769 }
9770
ConstructorCheck(GateRef glue,GateRef ctor,GateRef outPut,GateRef thisObj)9771 GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj)
9772 {
9773 auto env = GetEnvironment();
9774 Label entryPass(env);
9775 Label exit(env);
9776 env->SubCfgEntry(&entryPass);
9777 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
9778 Label isHeapObject(env);
9779 Label isEcmaObj(env);
9780 Label notEcmaObj(env);
9781 BRANCH(TaggedIsHeapObject(outPut), &isHeapObject, ¬EcmaObj);
9782 Bind(&isHeapObject);
9783 BRANCH(TaggedObjectIsEcmaObject(glue, outPut), &isEcmaObj, ¬EcmaObj);
9784 Bind(&isEcmaObj);
9785 {
9786 result = outPut;
9787 Jump(&exit);
9788 }
9789 Bind(¬EcmaObj);
9790 {
9791 Label ctorIsBase(env);
9792 Label ctorNotBase(env);
9793 BRANCH(IsBase(glue, ctor), &ctorIsBase, &ctorNotBase);
9794 Bind(&ctorIsBase);
9795 {
9796 result = thisObj;
9797 Jump(&exit);
9798 }
9799 Bind(&ctorNotBase);
9800 {
9801 Label throwExeption(env);
9802 Label returnObj(env);
9803 BRANCH(TaggedIsUndefined(outPut), &returnObj, &throwExeption);
9804 Bind(&returnObj);
9805 result = thisObj;
9806 Jump(&exit);
9807 Bind(&throwExeption);
9808 {
9809 CallRuntime(glue, RTSTUB_ID(ThrowNonConstructorException), {});
9810 Jump(&exit);
9811 }
9812 }
9813 }
9814 Bind(&exit);
9815 auto ret = *result;
9816 env->SubCfgExit();
9817 return ret;
9818 }
9819
CalIteratorKey(GateRef glue)9820 GateRef StubBuilder::CalIteratorKey(GateRef glue)
9821 {
9822 GateRef globalEnv = GetCurrentGlobalEnv();
9823 GateRef iteratorKey = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::ITERATOR_SYMBOL_INDEX);
9824 return iteratorKey;
9825 }
9826
FuncOrHClassCompare(GateRef glue,GateRef funcOrHClass,Label * match,Label * slowPath,size_t index)9827 void StubBuilder::FuncOrHClassCompare(GateRef glue, GateRef funcOrHClass,
9828 Label *match, Label *slowPath, size_t index)
9829 {
9830 GateRef globalEnv = GetCurrentGlobalEnv();
9831 GateRef globalRecord = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, index);
9832 BRANCH(Equal(globalRecord, funcOrHClass), match, slowPath);
9833 }
9834
IsDetectorInvalid(GateRef glue,size_t indexDetector)9835 GateRef StubBuilder::IsDetectorInvalid(GateRef glue, size_t indexDetector)
9836 {
9837 GateRef globalEnv = GetCurrentGlobalEnv();
9838 GateRef value = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, indexDetector);
9839 GateRef bitFieldOffset = IntPtr(MarkerCell::BIT_FIELD_OFFSET);
9840 GateRef bitField = LoadPrimitive(VariableType::INT32(), value, bitFieldOffset);
9841 GateRef mask = Int32(1LLU << (MarkerCell::IS_DETECTOR_INVALID_BITS - 1));
9842 return Int32NotEqual(Int32And(bitField, mask), Int32(0));
9843 }
9844
HClassCompareAndCheckDetector(GateRef glue,GateRef hclass,Label * match,Label * slowPath,size_t indexHClass,bool isMap)9845 void StubBuilder::HClassCompareAndCheckDetector(GateRef glue, GateRef hclass,
9846 Label *match, Label *slowPath,
9847 size_t indexHClass, bool isMap)
9848 {
9849 auto env = GetEnvironment();
9850 Label matchHClass(env);
9851 FuncOrHClassCompare(glue, hclass, &matchHClass, slowPath, indexHClass);
9852 Bind(&matchHClass);
9853 GateRef globalEnv = GetCurrentGlobalEnv();
9854 if (isMap) {
9855 BRANCH(GetMapIteratorDetector(globalEnv), slowPath, match);
9856 } else {
9857 BRANCH(GetSetIteratorDetector(globalEnv), slowPath, match);
9858 }
9859 }
9860
GetIteratorResult(GateRef glue,Variable * result,GateRef obj,Label * isPendingException,Label * noPendingException)9861 void StubBuilder::GetIteratorResult(GateRef glue, Variable *result, GateRef obj,
9862 Label *isPendingException, Label *noPendingException)
9863 {
9864 GateRef iteratorKey = CalIteratorKey(glue);
9865 *result = FastGetPropertyByName(glue, obj, iteratorKey, ProfileOperation());
9866 BRANCH(HasPendingException(glue), isPendingException, noPendingException);
9867 }
9868
9869 // If the jsType of the obj is JS_ARRAY and
9870 // its elementsKind is not GENERIC or it's hclass == GENERIC array's ihc
9871 // the obj doesn't have symbol.iterator within itself.
9872 // So when the Array.prototype[symbol.iterator] remains unchanged, we call FastPath.
TryFastGetArrayIterator(GateRef glue,GateRef hclass,GateRef jsType,Label * slowPath2,Label * matchArray)9873 void StubBuilder::TryFastGetArrayIterator(GateRef glue, GateRef hclass, GateRef jsType,
9874 Label *slowPath2, Label *matchArray)
9875 {
9876 auto env = GetEnvironment();
9877 Label arrayDetectorValid(env);
9878 Label tryArray(env);
9879 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))), &tryArray, slowPath2);
9880 Bind(&tryArray);
9881 {
9882 GateRef globalEnv = GetCurrentGlobalEnv();
9883 BRANCH(GetArrayIteratorDetector(globalEnv), slowPath2, &arrayDetectorValid);
9884 Bind(&arrayDetectorValid);
9885 {
9886 BuiltinsArrayStubBuilder arrayStubBuilder(this, globalEnv);
9887 arrayStubBuilder.ElementsKindHclassCompare(glue, hclass, matchArray, slowPath2);
9888 }
9889 }
9890 }
9891
TryFastGetIterator(GateRef glue,GateRef obj,GateRef hclass,Variable & result,Label * slowPath,Label * exit,Label * isPendingException)9892 void StubBuilder::TryFastGetIterator(GateRef glue, GateRef obj, GateRef hclass,
9893 Variable &result, Label *slowPath, Label *exit,
9894 Label *isPendingException)
9895 {
9896 auto env = GetEnvironment();
9897 Label matchMap(env);
9898 Label notmatchMap(env);
9899 Label matchSet(env);
9900 Label notmatchSet(env);
9901 Label tryArray(env);
9902 Label matchArray(env);
9903 Label isMap(env);
9904 Label isNotMap(env);
9905 Label isSet(env);
9906 Label isNotSet(env);
9907 Label isArray(env);
9908 Label noPendingException(env);
9909 Label slowPath2(env);
9910
9911 // When the symbol.iterator method remains unmodified
9912 // it is used to quickly process instances of Map, Set whose hclass == Map/Set's ihc.
9913 // In this situation we don't need to perform FastGetPropertyByName and CallRuntime.
9914 HClassCompareAndCheckDetector(glue, hclass, &matchMap, ¬matchMap, GlobalEnv::MAP_CLASS_INDEX, true);
9915 Bind(¬matchMap);
9916 HClassCompareAndCheckDetector(glue, hclass, &matchSet, ¬matchSet, GlobalEnv::SET_CLASS_INDEX, false);
9917 Bind(¬matchSet);
9918
9919 GateRef jsType = GetObjectType(hclass);
9920 TryFastGetArrayIterator(glue, hclass, jsType, &slowPath2, &matchArray);
9921
9922 Bind(&slowPath2);
9923 GetIteratorResult(glue, &result, obj, isPendingException, &noPendingException);
9924 // Mainly solve the situation with inheritance
9925 // and the symbol.iterator method remains unmodified.
9926 // In this situation we need to perform FastGetPropertyByName but needn't CallRuntime.
9927 Bind(&noPendingException);
9928 {
9929 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_MAP))), &isMap, &isNotMap);
9930 Bind(&isMap);
9931 {
9932 FuncOrHClassCompare(glue, *result, &matchMap, slowPath, GlobalEnv::MAP_PROTO_ENTRIES_FUNCTION_INDEX);
9933 }
9934 Bind(&isNotMap);
9935 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_SET))), &isSet, &isNotSet);
9936 Bind(&isSet);
9937 {
9938 FuncOrHClassCompare(glue, *result, &matchSet, slowPath, GlobalEnv::SET_PROTO_VALUES_FUNCTION_INDEX);
9939 }
9940 Bind(&isNotSet);
9941 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))), &isArray, slowPath);
9942 Bind(&isArray);
9943 {
9944 FuncOrHClassCompare(glue, *result, &matchArray, slowPath, GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
9945 }
9946 }
9947
9948 Bind(&matchMap);
9949 {
9950 BuiltinsCollectionStubBuilder<JSMap> collectionStubBuilder(this, glue, obj, Int32(0), GetCurrentGlobalEnv());
9951 collectionStubBuilder.Entries(&result, exit, slowPath);
9952 }
9953 Bind(&matchSet);
9954 {
9955 BuiltinsCollectionStubBuilder<JSSet> collectionStubBuilder(this, glue, obj, Int32(0), GetCurrentGlobalEnv());
9956 collectionStubBuilder.Values(&result, exit, slowPath);
9957 }
9958 Bind(&matchArray);
9959 {
9960 BuiltinsArrayStubBuilder arrayStubBuilder(this, GetCurrentGlobalEnv());
9961 arrayStubBuilder.Values(glue, obj, Int32(0), &result, exit, slowPath);
9962 }
9963 }
9964
9965 #if ENABLE_NEXT_OPTIMIZATION
GetIterator(GateRef glue,GateRef obj,ProfileOperation callback)9966 GateRef StubBuilder::GetIterator(GateRef glue, GateRef obj, ProfileOperation callback)
9967 {
9968 auto env = GetEnvironment();
9969 Label entryPass(env);
9970 Label exit(env);
9971 env->SubCfgEntry(&entryPass);
9972 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
9973 DEFVARIABLE(taggedId, VariableType::INT32(), Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable)));
9974
9975 Label isHeapObject(env);
9976 Label objIsHeapObject(env);
9977 Label objIsCallable(env);
9978 Label throwError(env);
9979 Label callExit(env);
9980 Label slowPath(env);
9981 Label slowPath3(env);
9982 Label isPendingException(env);
9983
9984 BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &slowPath3);
9985 Bind(&objIsHeapObject);
9986 GateRef hclass = LoadHClass(glue, obj);
9987 TryFastGetIterator(glue, obj, hclass, result, &slowPath, &exit, &isPendingException);
9988
9989 Bind(&slowPath3);
9990 GetIteratorResult(glue, &result, obj, &isPendingException, &slowPath);
9991
9992 Bind(&slowPath);
9993 callback.ProfileGetIterator(*result);
9994 BRANCH(TaggedIsHeapObject(*result), &isHeapObject, &throwError);
9995 Bind(&isHeapObject);
9996 BRANCH(IsCallable(glue, *result), &objIsCallable, &throwError);
9997 Bind(&objIsCallable);
9998 {
9999 JSCallArgs callArgs(JSCallMode::CALL_GETTER);
10000 callArgs.callGetterArgs = { obj };
10001 CallStubBuilder callBuilder(this, glue, *result, Int32(0), 0, &result, Circuit::NullGate(), callArgs,
10002 ProfileOperation());
10003 if (env->IsBaselineBuiltin()) {
10004 callBuilder.JSCallDispatchForBaseline(&callExit);
10005 Bind(&callExit);
10006 Jump(&exit);
10007 } else {
10008 result = callBuilder.JSCallDispatch();
10009 Label modifyErrorInfo(env);
10010 BRANCH(TaggedIsHeapObject(*result), &exit, &modifyErrorInfo);
10011 Bind(&modifyErrorInfo);
10012 taggedId = Int32(GET_MESSAGE_STRING_ID(IterNotObject));
10013 Jump(&throwError);
10014 }
10015 }
10016 Bind(&isPendingException);
10017 {
10018 result = Exception();
10019 Jump(&exit);
10020 }
10021 Bind(&throwError);
10022 {
10023 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(*taggedId) });
10024 result = Exception();
10025 Jump(&exit);
10026 }
10027 Bind(&exit);
10028 auto ret = *result;
10029 env->SubCfgExit();
10030 return ret;
10031 }
10032 #else
GetIterator(GateRef glue,GateRef obj,ProfileOperation callback)10033 GateRef StubBuilder::GetIterator(GateRef glue, GateRef obj, ProfileOperation callback)
10034 {
10035 auto env = GetEnvironment();
10036 Label entryPass(env);
10037 Label exit(env);
10038 env->SubCfgEntry(&entryPass);
10039 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
10040 DEFVARIABLE(taggedId, VariableType::INT32(), Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable)));
10041
10042 Label isPendingException(env);
10043 Label noPendingException(env);
10044 Label isHeapObject(env);
10045 Label objIsCallable(env);
10046 Label throwError(env);
10047 Label callExit(env);
10048
10049 GateRef iteratorKey = CalIteratorKey(glue);
10050 result = FastGetPropertyByName(glue, obj, iteratorKey, ProfileOperation());
10051 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
10052 Bind(&isPendingException);
10053 {
10054 result = Exception();
10055 Jump(&exit);
10056 }
10057 Bind(&noPendingException);
10058 callback.ProfileGetIterator(*result);
10059 BRANCH(TaggedIsHeapObject(*result), &isHeapObject, &throwError);
10060 Bind(&isHeapObject);
10061 BRANCH(IsCallable(glue, *result), &objIsCallable, &throwError);
10062 Bind(&objIsCallable);
10063 {
10064 JSCallArgs callArgs(JSCallMode::CALL_GETTER);
10065 callArgs.callGetterArgs = { obj };
10066 CallStubBuilder callBuilder(this, glue, *result, Int32(0), 0, &result, Circuit::NullGate(), callArgs,
10067 ProfileOperation());
10068 if (env->IsBaselineBuiltin()) {
10069 callBuilder.JSCallDispatchForBaseline(&callExit);
10070 Bind(&callExit);
10071 Jump(&exit);
10072 } else {
10073 result = callBuilder.JSCallDispatch();
10074 Label modifyErrorInfo(env);
10075 BRANCH(TaggedIsHeapObject(*result), &exit, &modifyErrorInfo);
10076 Bind(&modifyErrorInfo);
10077 taggedId = Int32(GET_MESSAGE_STRING_ID(IterNotObject));
10078 Jump(&throwError);
10079 }
10080 }
10081 Bind(&throwError);
10082 {
10083 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(*taggedId) });
10084 result = Exception();
10085 Jump(&exit);
10086 }
10087 Bind(&exit);
10088 auto ret = *result;
10089 env->SubCfgExit();
10090 return ret;
10091 }
10092 #endif
10093
TryStringOrSymbolToElementIndex(GateRef glue,GateRef key)10094 GateRef StubBuilder::TryStringOrSymbolToElementIndex(GateRef glue, GateRef key)
10095 {
10096 auto env = GetEnvironment();
10097 Label entry(env);
10098 env->SubCfgEntry(&entry);
10099 Label exit(env);
10100 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
10101
10102 Label keyNotSymbol(env);
10103 BRANCH(IsSymbol(glue, key), &exit, &keyNotSymbol);
10104 Bind(&keyNotSymbol);
10105
10106 Label greatThanZero(env);
10107 Label inRange(env);
10108 Label flattenFastPath(env);
10109 auto len = GetLengthFromString(key);
10110 BRANCH(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
10111 Bind(&greatThanZero);
10112 BRANCH(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
10113 Bind(&inRange);
10114 {
10115 Label isUtf8(env);
10116 DEFVARIABLE(c, VariableType::INT32(), Int32(0));
10117 BRANCH(IsUtf16String(key), &exit, &isUtf8);
10118 Bind(&isUtf8);
10119 FlatStringStubBuilder thisFlat(this);
10120 thisFlat.FlattenString(glue, key, &flattenFastPath);
10121 Bind(&flattenFastPath);
10122 StringInfoGateRef stringInfoGate(&thisFlat);
10123 GateRef data = GetNormalStringData(glue, stringInfoGate);
10124 c = ZExtInt8ToInt32(LoadZeroOffsetPrimitive(VariableType::INT8(), data));
10125 Label isDigitZero(env);
10126 Label notDigitZero(env);
10127 BRANCH(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero);
10128 Bind(&isDigitZero);
10129 {
10130 Label lengthIsOne(env);
10131 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
10132 Bind(&lengthIsOne);
10133 {
10134 result = Int32(0);
10135 Jump(&exit);
10136 }
10137 }
10138 Bind(¬DigitZero);
10139 {
10140 Label isDigit(env);
10141 Label notIsDigit(env);
10142 DEFVARIABLE(i, VariableType::INT32(), Int32(1));
10143 DEFVARIABLE(n, VariableType::INT64(), Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
10144
10145 BRANCH(IsDigit(*c), &isDigit, ¬IsDigit);
10146 Label loopHead(env);
10147 Label loopEnd(env);
10148 Label afterLoop(env);
10149 Bind(&isDigit);
10150 BRANCH(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
10151 LoopBegin(&loopHead);
10152 {
10153 c = ZExtInt8ToInt32(LoadPrimitive(VariableType::INT8(), data, ZExtInt32ToPtr(*i)));
10154 Label isDigit2(env);
10155 Label notDigit2(env);
10156 BRANCH(IsDigit(*c), &isDigit2, ¬Digit2);
10157 Bind(&isDigit2);
10158 {
10159 // 10 means the base of digit is 10.
10160 n = Int64Add(Int64Mul(*n, Int64(10)),
10161 Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
10162 i = Int32Add(*i, Int32(1));
10163 BRANCH(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
10164 }
10165 Bind(¬Digit2);
10166 {
10167 Label hasPoint(env);
10168 BRANCH(Int32Equal(*c, Int32('.')), &hasPoint, &exit);
10169 Bind(&hasPoint);
10170 {
10171 result = Int32(-2); // -2:return -2 means should goto slow path
10172 Jump(&exit);
10173 }
10174 }
10175 }
10176 Bind(&loopEnd);
10177 LoopEnd(&loopHead);
10178 Bind(&afterLoop);
10179 {
10180 Label lessThanMaxIndex(env);
10181 BRANCH(Int64LessThan(*n, Int64(JSObject::MAX_ELEMENT_INDEX)),
10182 &lessThanMaxIndex, &exit);
10183 Bind(&lessThanMaxIndex);
10184 {
10185 result = TruncInt64ToInt32(*n);
10186 Jump(&exit);
10187 }
10188 }
10189 Bind(¬IsDigit);
10190 {
10191 Label isNegative(env);
10192 BRANCH(Int32Equal(*c, Int32('-')), &isNegative, &exit);
10193 Bind(&isNegative);
10194 {
10195 result = Int32(-2); // -2:return -2 means should goto slow path
10196 Jump(&exit);
10197 }
10198 }
10199 }
10200 }
10201 Bind(&exit);
10202 auto ret = *result;
10203 env->SubCfgExit();
10204 return ret;
10205 }
10206
GetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef jsType)10207 GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder,
10208 GateRef key, GateRef jsType)
10209 {
10210 auto env = GetEnvironment();
10211 Label entry(env);
10212 env->SubCfgEntry(&entry);
10213 Label exit(env);
10214 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10215
10216 Label notOnProtoChain(env);
10217 BRANCH(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
10218 Bind(¬OnProtoChain);
10219
10220 auto negativeZero = GetGlobalConstantValue(
10221 VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
10222 Label isNegativeZero(env);
10223 Label notNegativeZero(env);
10224 BRANCH(Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
10225 Bind(&isNegativeZero);
10226 {
10227 result = Undefined();
10228 Jump(&exit);
10229 }
10230 Bind(¬NegativeZero);
10231 {
10232 GateRef index = TryStringOrSymbolToElementIndex(glue, key);
10233 Label validIndex(env);
10234 Label notValidIndex(env);
10235 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
10236 Bind(&validIndex);
10237 {
10238 BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this, GetCurrentGlobalEnv());
10239 result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, holder, index, jsType);
10240 Jump(&exit);
10241 }
10242 Bind(¬ValidIndex);
10243 {
10244 Label returnNull(env);
10245 BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
10246 Bind(&returnNull);
10247 {
10248 result = Null();
10249 Jump(&exit);
10250 }
10251 }
10252 }
10253
10254 Bind(&exit);
10255 auto ret = *result;
10256 env->SubCfgExit();
10257 return ret;
10258 }
10259
SetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef value,GateRef jsType)10260 GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key,
10261 GateRef value, GateRef jsType)
10262 {
10263 auto env = GetEnvironment();
10264 Label entry(env);
10265 env->SubCfgEntry(&entry);
10266 Label exit(env);
10267 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10268 Label notOnProtoChain(env);
10269 BRANCH(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
10270 Bind(¬OnProtoChain);
10271
10272 auto negativeZero = GetGlobalConstantValue(
10273 VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
10274 Label isNegativeZero(env);
10275 Label notNegativeZero(env);
10276 BRANCH(Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
10277 Bind(&isNegativeZero);
10278 {
10279 Label isObj(env);
10280 Label notObj(env);
10281 BRANCH(IsEcmaObject(glue, value), &isObj, ¬Obj);
10282 Bind(&isObj);
10283 {
10284 result = Null();
10285 Jump(&exit);
10286 }
10287 Bind(¬Obj);
10288 result = Undefined();
10289 Jump(&exit);
10290 }
10291 Bind(¬NegativeZero);
10292 {
10293 GateRef index = TryStringOrSymbolToElementIndex(glue, key);
10294 Label validIndex(env);
10295 Label notValidIndex(env);
10296 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
10297 Bind(&validIndex);
10298 {
10299 result = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
10300 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType) });
10301 Jump(&exit);
10302 }
10303 Bind(¬ValidIndex);
10304 {
10305 Label returnNull(env);
10306 BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
10307 Bind(&returnNull);
10308 {
10309 result = Null();
10310 Jump(&exit);
10311 }
10312 }
10313 }
10314
10315 Bind(&exit);
10316 auto ret = *result;
10317 env->SubCfgExit();
10318 return ret;
10319 }
10320
Assert(int messageId,int line,GateRef glue,GateRef condition,Label * nextLabel)10321 void StubBuilder::Assert(int messageId, int line, GateRef glue, GateRef condition, Label *nextLabel)
10322 {
10323 auto env = GetEnvironment();
10324 Label ok(env);
10325 Label notOk(env);
10326 BRANCH(condition, &ok, ¬Ok);
10327 Bind(&ok);
10328 {
10329 Jump(nextLabel);
10330 }
10331 Bind(¬Ok);
10332 {
10333 FatalPrint(glue, { Int32(messageId), Int32(line) });
10334 Jump(nextLabel);
10335 }
10336 }
10337
GetNormalStringData(GateRef glue,const StringInfoGateRef & stringInfoGate)10338 GateRef StubBuilder::GetNormalStringData([[maybe_unused]] GateRef glue, const StringInfoGateRef &stringInfoGate)
10339 {
10340 auto env = GetEnvironment();
10341 Label entry(env);
10342 env->SubCfgEntry(&entry);
10343 Label exit(env);
10344 Label isUtf8(env);
10345 Label isUtf16(env);
10346 DEFVARIABLE(result, VariableType::NATIVE_POINTER(), Undefined());
10347 GateRef data = ChangeTaggedPointerToInt64(
10348 PtrAdd(stringInfoGate.GetString(), IntPtr(LineString::DATA_OFFSET)));
10349 BRANCH(IsUtf8String(stringInfoGate.GetString()), &isUtf8, &isUtf16);
10350 Bind(&isUtf8);
10351 {
10352 result = PtrAdd(data, ZExtInt32ToPtr(stringInfoGate.GetStartIndex()));
10353 Jump(&exit);
10354 }
10355 Bind(&isUtf16);
10356 {
10357 GateRef offset = PtrMul(ZExtInt32ToPtr(stringInfoGate.GetStartIndex()), IntPtr(sizeof(uint16_t)));
10358 result = PtrAdd(data, offset);
10359 Jump(&exit);
10360 }
10361 Bind(&exit);
10362 auto ret = *result;
10363 env->SubCfgExit();
10364 return ret;
10365 }
10366
ToNumber(GateRef glue,GateRef tagged)10367 GateRef StubBuilder::ToNumber(GateRef glue, GateRef tagged)
10368 {
10369 auto env = GetEnvironment();
10370 Label entry(env);
10371 env->SubCfgEntry(&entry);
10372 Label exit(env);
10373 Label isNumber(env);
10374 Label notNumber(env);
10375 Label isUndefinedOrNull(env);
10376 Label notUndefinedOrNull(env);
10377 Label defaultLabel(env);
10378 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10379 BRANCH(TaggedIsNumber(tagged), &isNumber, ¬Number);
10380 Bind(&isNumber);
10381 {
10382 result = tagged;
10383 Jump(&exit);
10384 }
10385 Bind(¬Number);
10386 {
10387 GateRef flag = LogicOrBuilder(env)
10388 .Or(TaggedIsUndefined(tagged))
10389 .Or(TaggedIsHole(tagged))
10390 .Done();
10391 BRANCH(flag, &isUndefinedOrNull, ¬UndefinedOrNull);
10392 Bind(&isUndefinedOrNull);
10393 {
10394 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
10395 Jump(&exit);
10396 }
10397 Bind(¬UndefinedOrNull);
10398 {
10399 Label isTrue(env);
10400 Label notTrue(env);
10401 BRANCH(TaggedIsTrue(tagged), &isTrue, ¬True);
10402 Bind(&isTrue);
10403 {
10404 result = DoubleToTaggedDoublePtr(Double(1));
10405 Jump(&exit);
10406 }
10407 Bind(¬True);
10408 {
10409 Label isFlaseOrNull(env);
10410 GateRef flag1 = LogicOrBuilder(env)
10411 .Or(TaggedIsFalse(tagged))
10412 .Or(TaggedIsNull(tagged))
10413 .Done();
10414 BRANCH(flag1, &isFlaseOrNull, &defaultLabel);
10415 Bind(&isFlaseOrNull);
10416 {
10417 result = DoubleToTaggedDoublePtr(Double(0));
10418 Jump(&exit);
10419 }
10420 }
10421 }
10422 }
10423 Bind(&defaultLabel);
10424 {
10425 result = CallRuntime(glue, RTSTUB_ID(ToNumber), { tagged });
10426 Jump(&exit);
10427 }
10428 Bind(&exit);
10429 auto ret = *result;
10430 env->SubCfgExit();
10431 return ret;
10432 }
10433
ToIndex(GateRef glue,GateRef tagged)10434 GateRef StubBuilder::ToIndex(GateRef glue, GateRef tagged)
10435 {
10436 auto env = GetEnvironment();
10437 Label entry(env);
10438 env->SubCfgEntry(&entry);
10439 Label exit(env);
10440 Label isInt(env);
10441 Label notInt(env);
10442 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10443 BRANCH(TaggedIsInt(tagged), &isInt, ¬Int);
10444 Bind(&isInt);
10445 {
10446 Label lessThanZero(env);
10447 Label greaterOrEqualZero(env);
10448 BRANCH(Int32GreaterThanOrEqual(TaggedGetInt(tagged), Int32(0)), &greaterOrEqualZero, ¬Int);
10449 Bind(&greaterOrEqualZero);
10450 {
10451 result = tagged;
10452 Jump(&exit);
10453 }
10454 }
10455 Bind(¬Int);
10456 {
10457 Label isUndef(env);
10458 Label notUndef(env);
10459 BRANCH(TaggedIsUndefined(tagged), &isUndef, ¬Undef);
10460 Bind(&isUndef);
10461 {
10462 result = IntToTaggedPtr(Int32(0));
10463 Jump(&exit);
10464 }
10465 Bind(¬Undef);
10466 {
10467 result = CallRuntime(glue, RTSTUB_ID(ToIndex), { tagged });
10468 Jump(&exit);
10469 }
10470 }
10471 Bind(&exit);
10472 auto ret = *result;
10473 env->SubCfgExit();
10474 return ret;
10475 }
10476
ToLength(GateRef glue,GateRef target)10477 GateRef StubBuilder::ToLength(GateRef glue, GateRef target)
10478 {
10479 auto env = GetEnvironment();
10480 Label subentry(env);
10481 env->SubCfgEntry(&subentry);
10482 DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
10483 Label exit(env);
10484
10485 GateRef number = ToNumber(glue, target);
10486 Label isPendingException(env);
10487 Label noPendingException(env);
10488 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
10489 Bind(&isPendingException);
10490 {
10491 Jump(&exit);
10492 }
10493 Bind(&noPendingException);
10494 {
10495 GateRef num = GetDoubleOfTNumber(number);
10496 Label targetLessThanZero(env);
10497 Label targetGreaterThanZero(env);
10498 Label targetLessThanSafeNumber(env);
10499 Label targetGreaterThanSafeNumber(env);
10500 BRANCH(DoubleLessThan(num, Double(0.0)), &targetLessThanZero, &targetGreaterThanZero);
10501 Bind(&targetLessThanZero);
10502 {
10503 res = DoubleToTaggedDoublePtr(Double(0.0));
10504 Jump(&exit);
10505 }
10506 Bind(&targetGreaterThanZero);
10507 BRANCH(DoubleGreaterThan(num, Double(SAFE_NUMBER)), &targetGreaterThanSafeNumber, &targetLessThanSafeNumber);
10508 Bind(&targetGreaterThanSafeNumber);
10509 {
10510 res = DoubleToTaggedDoublePtr(Double(SAFE_NUMBER));
10511 Jump(&exit);
10512 }
10513 Bind(&targetLessThanSafeNumber);
10514 {
10515 res = number;
10516 Jump(&exit);
10517 }
10518 }
10519 Bind(&exit);
10520 auto ret = *res;
10521 env->SubCfgExit();
10522 return ret;
10523 }
10524
TaggedGetNumber(GateRef x)10525 GateRef StubBuilder::TaggedGetNumber(GateRef x)
10526 {
10527 auto env = GetEnvironment();
10528 Label subentry(env);
10529 Label exit(env);
10530 env->SubCfgEntry(&subentry);
10531
10532 Label targetIsInt(env);
10533 Label targetIsDouble(env);
10534 DEFVALUE(number, env_, VariableType::FLOAT64(), Double(0));
10535 BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
10536 Bind(&targetIsInt);
10537 {
10538 number = ChangeInt32ToFloat64(TaggedGetInt(x));
10539 Jump(&exit);
10540 }
10541 Bind(&targetIsDouble);
10542 {
10543 number = GetDoubleOfTDouble(x);
10544 Jump(&exit);
10545 }
10546 Bind(&exit);
10547 GateRef ret = *number;
10548 env->SubCfgExit();
10549 return ret;
10550 }
10551
NumberGetInt(GateRef glue,GateRef x)10552 GateRef StubBuilder::NumberGetInt(GateRef glue, GateRef x)
10553 {
10554 auto env = GetEnvironment();
10555 Label subentry(env);
10556 Label exit(env);
10557 env->SubCfgEntry(&subentry);
10558
10559 Label targetIsInt(env);
10560 Label targetIsDouble(env);
10561 DEFVALUE(number, env_, VariableType::INT32(), Int32(0));
10562 BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
10563 Bind(&targetIsInt);
10564 {
10565 number = TaggedGetInt(x);
10566 Jump(&exit);
10567 }
10568 Bind(&targetIsDouble);
10569 {
10570 number = DoubleToInt(glue, GetDoubleOfTDouble(x));
10571 Jump(&exit);
10572 }
10573 Bind(&exit);
10574 GateRef ret = *number;
10575 env->SubCfgExit();
10576 return ret;
10577 }
10578
IsStableJSArguments(GateRef glue,GateRef obj)10579 GateRef StubBuilder::IsStableJSArguments(GateRef glue, GateRef obj)
10580 {
10581 auto env = GetEnvironment();
10582 Label subentry(env);
10583 env->SubCfgEntry(&subentry);
10584 DEFVARIABLE(result, VariableType::BOOL(), False());
10585 Label exit(env);
10586 Label targetIsHeapObject(env);
10587 Label targetIsStableArguments(env);
10588
10589 BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
10590 Bind(&targetIsHeapObject);
10591 {
10592 GateRef jsHclass = LoadHClass(glue, obj);
10593 BRANCH(IsStableArguments(jsHclass), &targetIsStableArguments, &exit);
10594 Bind(&targetIsStableArguments);
10595 {
10596 GateRef globalEnv = GetCurrentGlobalEnv();
10597 result = GetArrayElementsGuardians(globalEnv);
10598 Jump(&exit);
10599 }
10600 }
10601 Bind(&exit);
10602 auto res = *result;
10603 env->SubCfgExit();
10604 return res;
10605 }
10606
IsStableJSArray(GateRef glue,GateRef obj)10607 GateRef StubBuilder::IsStableJSArray(GateRef glue, GateRef obj)
10608 {
10609 auto env = GetEnvironment();
10610 Label subentry(env);
10611 env->SubCfgEntry(&subentry);
10612 DEFVARIABLE(result, VariableType::BOOL(), False());
10613 Label exit(env);
10614 Label targetIsHeapObject(env);
10615 Label targetIsStableArray(env);
10616 BRANCH_LIKELY(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
10617 Bind(&targetIsHeapObject);
10618 {
10619 GateRef jsHclass = LoadHClass(glue, obj);
10620 BRANCH_LIKELY(IsStableArray(jsHclass), &targetIsStableArray, &exit);
10621 Bind(&targetIsStableArray);
10622 {
10623 Label isPrototypeNotModified(env);
10624 BRANCH_UNLIKELY(IsJSArrayPrototypeModified(jsHclass), &exit, &isPrototypeNotModified);
10625 Bind(&isPrototypeNotModified);
10626 {
10627 GateRef globalEnv = GetCurrentGlobalEnv();
10628 GateRef guardians = GetArrayElementsGuardians(globalEnv);
10629 result.WriteVariable(guardians);
10630 Jump(&exit);
10631 }
10632 }
10633 }
10634 Bind(&exit);
10635 auto res = *result;
10636 env->SubCfgExit();
10637 return res;
10638 }
10639
UpdateProfileTypeInfo(GateRef glue,GateRef jsFunc)10640 GateRef StubBuilder::UpdateProfileTypeInfo(GateRef glue, GateRef jsFunc)
10641 {
10642 auto env = GetEnvironment();
10643 Label entry(env);
10644 env->SubCfgEntry(&entry);
10645 Label needUpdate(env);
10646 Label exit(env);
10647 DEFVARIABLE(profileTypeInfo, VariableType::JS_POINTER(), GetProfileTypeInfo(glue, jsFunc));
10648 BRANCH(TaggedIsUndefined(*profileTypeInfo), &needUpdate, &exit);
10649 Bind(&needUpdate);
10650 {
10651 profileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounter), { jsFunc });
10652 Jump(&exit);
10653 }
10654 Bind(&exit);
10655 auto ret = *profileTypeInfo;
10656 env->SubCfgExit();
10657 return ret;
10658 }
10659
GetFuncKind(GateRef method)10660 GateRef StubBuilder::GetFuncKind(GateRef method)
10661 {
10662 GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
10663 GateRef bitfield = LoadPrimitive(VariableType::INT32(), method, extraLiteralInfoOffset);
10664
10665 GateRef kind = Int32And(Int32LSR(bitfield, Int32(Method::FunctionKindBits::START_BIT)),
10666 Int32((1LU << Method::FunctionKindBits::SIZE) - 1));
10667 return kind;
10668 }
10669
GetCallSpreadArgs(GateRef glue,GateRef array,ProfileOperation callBack)10670 GateRef StubBuilder::GetCallSpreadArgs(GateRef glue, GateRef array, ProfileOperation callBack)
10671 {
10672 auto env = GetEnvironment();
10673 Label subEntry(env);
10674 env->SubCfgEntry(&subEntry);
10675 DEFVARIABLE(result, VariableType::JS_POINTER(), NullPtr());
10676 Label fastPath(env);
10677 Label noCopyPath(env);
10678 Label exit(env);
10679 Label noException(env);
10680 Label isException(env);
10681
10682 GateRef itor = GetIterator(glue, array, callBack);
10683 BRANCH(TaggedIsException(itor), &isException, &noException);
10684 Bind(&isException);
10685 {
10686 result = Exception();
10687 Jump(&exit);
10688 }
10689 Bind(&noException);
10690 GateRef needCopy = LogicAndBuilder(env)
10691 .And(Int32Equal(GetObjectType(LoadHClass(glue, itor)), Int32(static_cast<int32_t>(JSType::JS_ARRAY_ITERATOR))))
10692 .And(IsStableJSArray(glue, array))
10693 .Done();
10694 BRANCH(needCopy, &fastPath, &noCopyPath);
10695 Bind(&fastPath);
10696 {
10697 // copy operation is omitted
10698 result = CopyJSArrayToTaggedArrayArgs(glue, array);
10699 Jump(&exit);
10700 }
10701 Bind(&noCopyPath);
10702 {
10703 result = CallRuntime(glue, RTSTUB_ID(GetCallSpreadArgs), { array });
10704 Jump(&exit);
10705 }
10706 Bind(&exit);
10707 auto ret = *result;
10708 env->SubCfgExit();
10709 return ret;
10710 }
10711
CalArrayRelativePos(GateRef index,GateRef arrayLen)10712 GateRef StubBuilder::CalArrayRelativePos(GateRef index, GateRef arrayLen)
10713 {
10714 auto env = GetEnvironment();
10715 Label entryPass(env);
10716 env->SubCfgEntry(&entryPass);
10717 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
10718
10719 Label indexLessZero(env);
10720 Label indexNotLessZero(env);
10721 Label exit(env);
10722 BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
10723 Bind(&indexLessZero);
10724 {
10725 GateRef tempBeginIndex = Int32Add(arrayLen, index);
10726 Label beginIndexLargeZero(env);
10727 BRANCH(Int32GreaterThan(tempBeginIndex, Int32(0)), &beginIndexLargeZero, &exit);
10728 Bind(&beginIndexLargeZero);
10729 {
10730 result = tempBeginIndex;
10731 Jump(&exit);
10732 }
10733 }
10734 Bind(&indexNotLessZero);
10735 {
10736 Label lessLen(env);
10737 Label largeLen(env);
10738 BRANCH(Int32LessThan(index, arrayLen), &lessLen, &largeLen);
10739 Bind(&lessLen);
10740 {
10741 result = index;
10742 Jump(&exit);
10743 }
10744 Bind(&largeLen);
10745 {
10746 result = arrayLen;
10747 Jump(&exit);
10748 }
10749 }
10750
10751 Bind(&exit);
10752 auto ret = *result;
10753 env->SubCfgExit();
10754 return ret;
10755 }
10756
AppendSkipHole(GateRef glue,GateRef first,GateRef second,GateRef copyLength)10757 GateRef StubBuilder::AppendSkipHole(GateRef glue, GateRef first, GateRef second, GateRef copyLength)
10758 {
10759 auto env = GetEnvironment();
10760 Label subEntry(env);
10761 env->SubCfgEntry(&subEntry);
10762 Label exit(env);
10763 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
10764 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
10765 DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
10766
10767 GateRef firstLength = GetLengthOfTaggedArray(first);
10768 GateRef secondLength = GetLengthOfTaggedArray(second);
10769 NewObjectStubBuilder newBuilder(this);
10770 GateRef array = newBuilder.NewTaggedArray(glue, copyLength);
10771 Label loopHead(env);
10772 Label loopEnd(env);
10773 Label afterLoop(env);
10774 Label storeValue(env);
10775 Label notHole(env);
10776 Jump(&loopHead);
10777 LoopBegin(&loopHead);
10778 {
10779 BRANCH(Int32UnsignedLessThan(*index, firstLength), &storeValue, &afterLoop);
10780 Bind(&storeValue);
10781 {
10782 GateRef value = GetValueFromTaggedArray(glue, first, *index);
10783 BRANCH(TaggedIsHole(value), &afterLoop, ¬Hole);
10784 Bind(¬Hole);
10785 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value);
10786 index = Int32Add(*index, Int32(1));
10787 Jump(&loopEnd);
10788 }
10789 }
10790 Bind(&loopEnd);
10791 LoopEndWithCheckSafePoint(&loopHead, env, glue);
10792 Bind(&afterLoop);
10793 {
10794 Label loopHead1(env);
10795 Label loopEnd1(env);
10796 Label storeValue1(env);
10797 Label notHole1(env);
10798 Jump(&loopHead1);
10799 LoopBegin(&loopHead1);
10800 {
10801 BRANCH(Int32UnsignedLessThan(*i, secondLength), &storeValue1, &exit);
10802 Bind(&storeValue1);
10803 {
10804 GateRef value1 = GetValueFromTaggedArray(glue, second, *i);
10805 BRANCH(TaggedIsHole(value1), &exit, ¬Hole1);
10806 Bind(¬Hole1);
10807 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value1);
10808 i = Int32Add(*i, Int32(1));
10809 index = Int32Add(*index, Int32(1));
10810 Jump(&loopEnd1);
10811 }
10812 }
10813 Bind(&loopEnd1);
10814 LoopEnd(&loopHead1);
10815 }
10816 Bind(&exit);
10817 res = array;
10818 auto ret = *res;
10819 env->SubCfgExit();
10820 return ret;
10821 }
10822
ToCharCode(GateRef number)10823 GateRef StubBuilder::ToCharCode(GateRef number)
10824 {
10825 auto env = GetEnvironment();
10826 Label subEntry(env);
10827 env->SubCfgEntry(&subEntry);
10828 Label exit(env);
10829 DEFVARIABLE(result, VariableType::INT32(), number);
10830
10831 Label lessThanTen(env);
10832 Label notLessThanTen(env);
10833 BRANCH(Int32LessThan(number, Int32(10)), &lessThanTen, ¬LessThanTen); // 10: means number
10834 Bind(&lessThanTen);
10835 {
10836 result = Int32Add(Int32('0'), *result);
10837 Jump(&exit);
10838 }
10839 Bind(¬LessThanTen);
10840 {
10841 result = Int32Sub(*result, Int32(10)); // 10: means number
10842 result = Int32Add(Int32('a'), *result);
10843 Jump(&exit);
10844 }
10845 Bind(&exit);
10846 auto ret = *result;
10847 env->SubCfgExit();
10848 return ret;
10849 }
10850
IntToEcmaString(GateRef glue,GateRef number)10851 GateRef StubBuilder::IntToEcmaString(GateRef glue, GateRef number)
10852 {
10853 auto env = GetEnvironment();
10854 Label subEntry(env);
10855 env->SubCfgEntry(&subEntry);
10856 Label exit(env);
10857 DEFVARIABLE(n, VariableType::INT32(), number);
10858 DEFVARIABLE(result, VariableType::JS_POINTER(), Hole());
10859
10860 GateRef isPositive = Int32GreaterThanOrEqual(number, Int32(0));
10861 GateRef isSingle = Int32LessThan(number, Int32(10));
10862 Label process(env);
10863 Label callRuntime(env);
10864 Label afterNew(env);
10865 BRANCH(BitAnd(isPositive, isSingle), &process, &callRuntime);
10866 Bind(&process);
10867 {
10868 NewObjectStubBuilder newBuilder(this);
10869 newBuilder.SetParameters(glue, 0);
10870 newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), true);
10871 Bind(&afterNew);
10872 n = Int32Add(Int32('0'), *n);
10873 GateRef dst = ChangeTaggedPointerToInt64(PtrAdd(*result, IntPtr(LineString::DATA_OFFSET)));
10874 Store(VariableType::INT8(), glue, dst, IntPtr(0), TruncInt32ToInt8(*n));
10875 Jump(&exit);
10876 }
10877 Bind(&callRuntime);
10878 {
10879 result = CallRuntime(glue, RTSTUB_ID(IntToString), { IntToTaggedInt(*n) });
10880 Jump(&exit);
10881 }
10882 Bind(&exit);
10883 auto ret = *result;
10884 env->SubCfgExit();
10885 return ret;
10886 }
10887
NumberToString(GateRef glue,GateRef number)10888 GateRef StubBuilder::NumberToString(GateRef glue, GateRef number)
10889 {
10890 DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
10891 res = CallRuntime(glue, RTSTUB_ID(NumberToString), { number });
10892 return *res;
10893 }
10894
RestoreElementsKindToGeneric(GateRef glue,GateRef jsHClass)10895 void StubBuilder::RestoreElementsKindToGeneric(GateRef glue, GateRef jsHClass)
10896 {
10897 GateRef newKind = Int32(Elements::ToUint(ElementsKind::GENERIC));
10898 SetElementsKindToJSHClass(glue, jsHClass, newKind);
10899 }
10900
GetTaggedValueWithElementsKind(GateRef glue,GateRef receiver,GateRef index)10901 GateRef StubBuilder::GetTaggedValueWithElementsKind(GateRef glue, GateRef receiver, GateRef index)
10902 {
10903 auto env = GetEnvironment();
10904 Label entryPass(env);
10905 env->SubCfgEntry(&entryPass);
10906 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10907 Label exit(env);
10908 Label enableMutantArray(env);
10909 Label disableMutantArray(env);
10910 Label isMutantTaggedArray(env);
10911 Label isNotMutantTaggedArray(env);
10912 GateRef elements = GetElementsArray(glue, receiver);
10913 BRANCH_UNLIKELY(IsEnableMutantArray(glue), &enableMutantArray, &disableMutantArray);
10914 Bind(&disableMutantArray);
10915 {
10916 result = GetValueFromTaggedArray(glue, elements, index);
10917 Jump(&exit);
10918 }
10919 Bind(&enableMutantArray);
10920 GateRef hclass = LoadHClass(glue, receiver);
10921 DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
10922 BRANCH(IsMutantTaggedArray(glue, elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
10923 Bind(&isNotMutantTaggedArray);
10924 {
10925 elementsKind = Int32(Elements::ToUint(ElementsKind::GENERIC));
10926 Jump(&isMutantTaggedArray);
10927 }
10928 Bind(&isMutantTaggedArray);
10929 GateRef rawValue = GetValueFromMutantTaggedArray(elements, index);
10930 Label isSpecialHole(env);
10931 Label isNotSpecialHole(env);
10932 BRANCH(Int64Equal(rawValue, SpecialHole()), &isSpecialHole, &isNotSpecialHole);
10933 Bind(&isSpecialHole);
10934 {
10935 Jump(&exit);
10936 }
10937 Bind(&isNotSpecialHole);
10938 {
10939 Label isInt(env);
10940 Label isNotInt(env);
10941 GateRef elementsKindIntLowerBound = Int32GreaterThanOrEqual(*elementsKind,
10942 Int32(Elements::ToUint(ElementsKind::INT)));
10943 GateRef elementsKindIntUpperBound = Int32LessThanOrEqual(*elementsKind,
10944 Int32(Elements::ToUint(ElementsKind::HOLE_INT)));
10945 GateRef checkIntKind = BitAnd(elementsKindIntLowerBound, elementsKindIntUpperBound);
10946 BRANCH(checkIntKind, &isInt, &isNotInt);
10947 Bind(&isInt);
10948 {
10949 result = Int64ToTaggedIntPtr(rawValue);
10950 Jump(&exit);
10951 }
10952 Bind(&isNotInt);
10953 {
10954 Label isNumber(env);
10955 Label isNotNumber(env);
10956 GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
10957 Int32(Elements::ToUint(ElementsKind::NUMBER)));
10958 GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
10959 Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)));
10960 GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
10961 BRANCH(checkNumberKind, &isNumber, &isNotNumber);
10962 Bind(&isNumber);
10963 {
10964 GateRef numberValue = CastInt64ToFloat64(rawValue);
10965 result = DoubleToTaggedDoublePtr(numberValue);
10966 Jump(&exit);
10967 }
10968 Bind(&isNotNumber);
10969 {
10970 result = Int64ToTaggedPtr(rawValue);
10971 Jump(&exit);
10972 }
10973 }
10974 }
10975 Bind(&exit);
10976 auto ret = *result;
10977 env->SubCfgExit();
10978 return ret;
10979 }
10980
ConvertTaggedValueWithElementsKind(GateRef glue,GateRef value,GateRef extraKind)10981 GateRef StubBuilder::ConvertTaggedValueWithElementsKind([[maybe_unused]] GateRef glue, GateRef value, GateRef extraKind)
10982 {
10983 auto env = GetEnvironment();
10984 Label entryPass(env);
10985 env->SubCfgEntry(&entryPass);
10986 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10987 Label exit(env);
10988 Label isHole(env);
10989 Label isNotHole(env);
10990 GateRef valueIsHole = TaggedIsHole(value);
10991 GateRef elementsKindInNumbersLB = Int32GreaterThanOrEqual(extraKind,
10992 Int32(Elements::ToUint(ElementsKind::HOLE)));
10993 GateRef elementsKindInNumbersUB = Int32LessThan(extraKind, Int32(Elements::ToUint(ElementsKind::STRING)));
10994 GateRef checkInNumersKind = LogicAndBuilder(env)
10995 .And(valueIsHole)
10996 .And(elementsKindInNumbersLB)
10997 .And(elementsKindInNumbersUB).Done();
10998 BRANCH(checkInNumersKind, &isHole, &isNotHole);
10999 Bind(&isHole);
11000 {
11001 Jump(&exit);
11002 }
11003 Bind(&isNotHole);
11004 {
11005 Label isInt(env);
11006 Label isNotInt(env);
11007 GateRef elementsKindIntLB = Int32GreaterThanOrEqual(extraKind,
11008 Int32(Elements::ToUint(ElementsKind::INT)));
11009 GateRef elementsKindIntUB = Int32LessThanOrEqual(extraKind,
11010 Int32(Elements::ToUint(ElementsKind::HOLE_INT)));
11011 GateRef checkIntKind = LogicAndBuilder(env)
11012 .And(elementsKindIntLB)
11013 .And(elementsKindIntUB)
11014 .Done();
11015 BRANCH(checkIntKind, &isInt, &isNotInt);
11016 Bind(&isInt);
11017 {
11018 result = Int64ToTaggedPtr(GetInt64OfTInt(value));
11019 Jump(&exit);
11020 }
11021 Bind(&isNotInt);
11022 {
11023 Label isNumber(env);
11024 Label isNotNumber(env);
11025 GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(extraKind,
11026 Int32(Elements::ToUint(ElementsKind::NUMBER)));
11027 GateRef elementsKindNumberUB = Int32LessThanOrEqual(extraKind,
11028 Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)));
11029 GateRef checkNumberKind = LogicAndBuilder(env)
11030 .And(elementsKindNumberLB)
11031 .And(elementsKindNumberUB)
11032 .Done();
11033 BRANCH(checkNumberKind, &isNumber, &isNotNumber);
11034 Bind(&isNumber);
11035 {
11036 Label isNumberInt(env);
11037 Label isNotNumberInt(env);
11038 BRANCH(TaggedIsInt(value), &isNumberInt, &isNotNumberInt);
11039 Bind(&isNumberInt);
11040 {
11041 result = Int64ToTaggedPtr(CastDoubleToInt64(GetDoubleOfTInt(value)));
11042 Jump(&exit);
11043 }
11044 Bind(&isNotNumberInt);
11045 {
11046 result = Int64ToTaggedPtr(CastDoubleToInt64(GetDoubleOfTDouble(value)));
11047 Jump(&exit);
11048 }
11049 }
11050 Bind(&isNotNumber);
11051 {
11052 result = value;
11053 Jump(&exit);
11054 }
11055 }
11056 }
11057 Bind(&exit);
11058 auto ret = *result;
11059 env->SubCfgExit();
11060 return ret;
11061 }
11062
SetValueWithElementsKind(GateRef glue,GateRef receiver,GateRef rawValue,GateRef index,GateRef needTransition,GateRef extraKind)11063 GateRef StubBuilder::SetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef rawValue,
11064 GateRef index, GateRef needTransition, GateRef extraKind)
11065 {
11066 auto env = GetEnvironment();
11067 Label entryPass(env);
11068 env->SubCfgEntry(&entryPass);
11069 DEFVARIABLE(result, VariableType::INT64(), SpecialHole());
11070 Label exit(env);
11071
11072 Label transitElementsKind(env);
11073 Label finishTransition(env);
11074 BRANCH(needTransition, &transitElementsKind, &finishTransition);
11075 Bind(&transitElementsKind);
11076 {
11077 TransitToElementsKind(glue, receiver, rawValue, extraKind);
11078 Jump(&finishTransition);
11079 }
11080 Bind(&finishTransition);
11081 GateRef elements = GetElementsArray(glue, receiver);
11082 Label enableMutantArray(env);
11083 Label disableMutantArray(env);
11084 BRANCH_UNLIKELY(IsEnableMutantArray(glue), &enableMutantArray, &disableMutantArray);
11085 Bind(&disableMutantArray);
11086 {
11087 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, rawValue);
11088 Jump(&exit);
11089 }
11090 Bind(&enableMutantArray);
11091 Label setValue(env);
11092 Label isMutantTaggedArray(env);
11093 Label isNotMutantTaggedArray(env);
11094 GateRef hclass = LoadHClass(glue, receiver);
11095 DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
11096 BRANCH(IsMutantTaggedArray(glue, elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
11097 Bind(&isNotMutantTaggedArray);
11098 {
11099 elementsKind = Int32(Elements::ToUint(ElementsKind::GENERIC));
11100 Jump(&isMutantTaggedArray);
11101 }
11102 Bind(&isMutantTaggedArray);
11103 Label isHole(env);
11104 Label isNotHole(env);
11105 GateRef elementsKindVal = *elementsKind;
11106 GateRef checkInNumersKind = LogicAndBuilder(env)
11107 .And(TaggedIsHole(rawValue))
11108 .And(Int32GreaterThanOrEqual(elementsKindVal, Int32(Elements::ToUint(ElementsKind::HOLE))))
11109 .And(Int32LessThan(elementsKindVal, Int32(Elements::ToUint(ElementsKind::STRING))))
11110 .Done();
11111 BRANCH(checkInNumersKind, &isHole, &isNotHole);
11112 Bind(&isHole);
11113 {
11114 Jump(&setValue);
11115 }
11116 Bind(&isNotHole);
11117 {
11118 Label isInt(env);
11119 Label isNotInt(env);
11120 GateRef elementsKindIntLB = Int32GreaterThanOrEqual(*elementsKind,
11121 Int32(Elements::ToUint(ElementsKind::INT)));
11122 GateRef elementsKindIntUB = Int32LessThanOrEqual(*elementsKind,
11123 Int32(Elements::ToUint(ElementsKind::HOLE_INT)));
11124 GateRef checkIntKind = BitAnd(elementsKindIntLB, elementsKindIntUB);
11125 BRANCH(checkIntKind, &isInt, &isNotInt);
11126 Bind(&isInt);
11127 {
11128 result = GetInt64OfTInt(rawValue);
11129 Jump(&setValue);
11130 }
11131 Bind(&isNotInt);
11132 {
11133 Label isNumber(env);
11134 Label isNotNumber(env);
11135 GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
11136 Int32(Elements::ToUint(ElementsKind::NUMBER)));
11137 GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
11138 Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)));
11139 GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
11140 BRANCH(checkNumberKind, &isNumber, &isNotNumber);
11141 Bind(&isNumber);
11142 {
11143 Label isNumberInt(env);
11144 Label isNotNumberInt(env);
11145 BRANCH(TaggedIsInt(rawValue), &isNumberInt, &isNotNumberInt);
11146 Bind(&isNumberInt);
11147 {
11148 result = CastDoubleToInt64(GetDoubleOfTInt(rawValue));
11149 Jump(&setValue);
11150 }
11151 Bind(&isNotNumberInt);
11152 {
11153 result = CastDoubleToInt64(GetDoubleOfTDouble(rawValue));
11154 Jump(&setValue);
11155 }
11156 }
11157 Bind(&isNotNumber);
11158 {
11159 result = ChangeTaggedPointerToInt64(rawValue);
11160 Jump(&setValue);
11161 }
11162 }
11163 }
11164 Bind(&setValue);
11165 Label storeToNormalArray(env);
11166 Label storeToMutantArray(env);
11167 BRANCH(TaggedIsHeapObject(rawValue), &storeToNormalArray, &storeToMutantArray);
11168 Bind(&storeToNormalArray);
11169 {
11170 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, *result);
11171 Jump(&exit);
11172 }
11173 Bind(&storeToMutantArray);
11174 {
11175 SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, *result);
11176 Jump(&exit);
11177 }
11178 Bind(&exit);
11179 auto ret = *result;
11180 env->SubCfgExit();
11181 return ret;
11182 }
11183
FastSetValueWithElementsKind(GateRef glue,GateRef receiver,GateRef elements,GateRef rawValue,GateRef index,ElementsKind kind,bool needTransition)11184 void StubBuilder::FastSetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef elements, GateRef rawValue,
11185 GateRef index, ElementsKind kind, bool needTransition)
11186 {
11187 auto env = GetEnvironment();
11188 Label entryPass(env);
11189 env->SubCfgEntry(&entryPass);
11190 Label exit(env);
11191 if (needTransition) {
11192 TransitToElementsKind(glue, receiver, rawValue, Int32(Elements::ToUint(ElementsKind::NONE)));
11193 }
11194 if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
11195 SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
11196 Jump(&exit);
11197 } else {
11198 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, rawValue);
11199 Jump(&exit);
11200 }
11201 Bind(&exit);
11202 env->SubCfgExit();
11203 }
11204
CopyJSArrayToTaggedArrayArgs(GateRef glue,GateRef srcObj)11205 GateRef StubBuilder::CopyJSArrayToTaggedArrayArgs(GateRef glue, GateRef srcObj)
11206 {
11207 auto env = GetEnvironment();
11208 Label entryPass(env);
11209 env->SubCfgEntry(&entryPass);
11210 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
11211 Label exit(env);
11212
11213 Label isMutantTaggedArray(env);
11214 result = GetElementsArray(glue, srcObj);
11215 BRANCH(IsMutantTaggedArray(glue, *result), &isMutantTaggedArray, &exit);
11216 Bind(&isMutantTaggedArray);
11217 {
11218 GateRef argvLength = GetLengthOfTaggedArray(*result);
11219 NewObjectStubBuilder newBuilder(this);
11220 GateRef argv = newBuilder.NewTaggedArray(glue, argvLength);
11221 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11222 Label loopHead(env);
11223 Label loopEnd(env);
11224 Label afterLoop(env);
11225 Label storeValue(env);
11226 Jump(&loopHead);
11227 LoopBegin(&loopHead);
11228 {
11229 BRANCH(Int32UnsignedLessThan(*index, argvLength), &storeValue, &afterLoop);
11230 Bind(&storeValue);
11231 {
11232 GateRef value = GetTaggedValueWithElementsKind(glue, srcObj, *index);
11233 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argv, *index, value);
11234 index = Int32Add(*index, Int32(1));
11235 Jump(&loopEnd);
11236 }
11237 }
11238 Bind(&loopEnd);
11239 LoopEnd(&loopHead);
11240 Bind(&afterLoop);
11241 {
11242 result = argv;
11243 Jump(&exit);
11244 }
11245 }
11246 Bind(&exit);
11247 auto ret = *result;
11248 env->SubCfgExit();
11249 return ret;
11250 }
11251
MigrateArrayWithKind(GateRef glue,GateRef object,GateRef oldKind,GateRef newKind)11252 void StubBuilder::MigrateArrayWithKind(GateRef glue, GateRef object, GateRef oldKind, GateRef newKind)
11253 {
11254 auto env = GetEnvironment();
11255 Label entryPass(env);
11256 env->SubCfgEntry(&entryPass);
11257 Label exit(env);
11258
11259 Label mutantArrayOn(env);
11260 BRANCH(IsEnableMutantArray(glue), &mutantArrayOn, &exit);
11261 Bind(&mutantArrayOn);
11262
11263 DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
11264 Label doMigration(env);
11265 Label migrateFromInt(env);
11266 Label migrateOtherKinds(env);
11267
11268 GateRef noNeedMigration = LogicOrBuilder(env)
11269 .Or(Int32Equal(oldKind, newKind))
11270 .Or(BitAnd(Int32Equal(oldKind, Int32(Elements::ToUint(ElementsKind::INT))),
11271 Int32Equal(newKind, Int32(Elements::ToUint(ElementsKind::HOLE_INT)))))
11272 .Or(BitAnd(Int32Equal(oldKind, Int32(Elements::ToUint(ElementsKind::NUMBER))),
11273 Int32Equal(newKind, Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)))))
11274 .Done();
11275 BRANCH(noNeedMigration, &exit, &doMigration);
11276 Bind(&doMigration);
11277 GateRef needCOW = IsJsCOWArray(glue, object);
11278 BRANCH(ElementsKindIsIntOrHoleInt(oldKind), &migrateFromInt, &migrateOtherKinds);
11279 Bind(&migrateFromInt);
11280 {
11281 Label migrateToHeapValuesFromInt(env);
11282 Label migrateToRawValuesFromInt(env);
11283 Label migrateToNumbersFromInt(env);
11284 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromInt, &migrateToRawValuesFromInt);
11285 Bind(&migrateToHeapValuesFromInt);
11286 {
11287 newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, True());
11288 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11289 Jump(&exit);
11290 }
11291 Bind(&migrateToRawValuesFromInt);
11292 {
11293 BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumbersFromInt, &exit);
11294 Bind(&migrateToNumbersFromInt);
11295 {
11296 MigrateFromHoleIntToHoleNumber(glue, object);
11297 Jump(&exit);
11298 }
11299 }
11300 }
11301 Bind(&migrateOtherKinds);
11302 {
11303 Label migrateFromNumber(env);
11304 Label migrateToHeapValuesFromNum(env);
11305 Label migrateToRawValuesFromNum(env);
11306 Label migrateToIntFromNum(env);
11307 Label migrateToRawValueFromTagged(env);
11308 BRANCH(ElementsKindIsNumOrHoleNum(oldKind), &migrateFromNumber, &migrateToRawValueFromTagged);
11309 Bind(&migrateFromNumber);
11310 {
11311 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromNum, &migrateToRawValuesFromNum);
11312 Bind(&migrateToHeapValuesFromNum);
11313 {
11314 Label migrateToTaggedFromNum(env);
11315 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToTaggedFromNum, &exit);
11316 Bind(&migrateToTaggedFromNum);
11317 {
11318 newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, False());
11319 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11320 Jump(&exit);
11321 }
11322 }
11323 Bind(&migrateToRawValuesFromNum);
11324 {
11325 BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromNum, &exit);
11326 Bind(&migrateToIntFromNum);
11327 {
11328 MigrateFromHoleNumberToHoleInt(glue, object);
11329 Jump(&exit);
11330 }
11331 }
11332 }
11333 Bind(&migrateToRawValueFromTagged);
11334 {
11335 Label migrateToIntFromTagged(env);
11336 Label migrateToOthersFromTagged(env);
11337 BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromTagged, &migrateToOthersFromTagged);
11338 Bind(&migrateToIntFromTagged);
11339 {
11340 newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, True());
11341 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11342 Jump(&exit);
11343 }
11344 Bind(&migrateToOthersFromTagged);
11345 {
11346 Label migrateToNumFromTagged(env);
11347 BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumFromTagged, &exit);
11348 Bind(&migrateToNumFromTagged);
11349 {
11350 newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, False());
11351 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
11352 Jump(&exit);
11353 }
11354 }
11355 }
11356 }
11357 Bind(&exit);
11358 env->SubCfgExit();
11359 }
11360
MigrateFromRawValueToHeapValues(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)11361 GateRef StubBuilder::MigrateFromRawValueToHeapValues(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
11362 {
11363 auto env = GetEnvironment();
11364 Label entryPass(env);
11365 env->SubCfgEntry(&entryPass);
11366 DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
11367 Label exit(env);
11368
11369 GateRef elements = GetElementsArray(glue, object);
11370 GateRef length = GetLengthOfTaggedArray(elements);
11371 Label createCOW(env);
11372 Label createNormal(env);
11373 Label finishElementsInit(env);
11374 BRANCH(needCOW, &createCOW, &createNormal);
11375 Bind(&createCOW);
11376 {
11377 newElements = CallRuntime(glue, RTSTUB_ID(NewCOWTaggedArray), { IntToTaggedPtr(length) });
11378 Jump(&finishElementsInit);
11379 }
11380 Bind(&createNormal);
11381 {
11382 newElements = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedPtr(length) });
11383 Jump(&finishElementsInit);
11384 }
11385 Bind(&finishElementsInit);
11386
11387 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11388 Label loopHead(env);
11389 Label loopEnd(env);
11390 Label afterLoop(env);
11391 Label storeValue(env);
11392 Jump(&loopHead);
11393 LoopBegin(&loopHead);
11394 {
11395 Label storeHole(env);
11396 Label storeNormalValue(env);
11397 Label finishStore(env);
11398 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11399 Bind(&storeValue);
11400 {
11401 Label rawValueIsInt(env);
11402 Label rawValueIsNumber(env);
11403 GateRef value = GetValueFromMutantTaggedArray(elements, *index);
11404 BRANCH(ValueIsSpecialHole(value), &storeHole, &storeNormalValue);
11405 Bind(&storeHole);
11406 {
11407 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, Hole());
11408 Jump(&finishStore);
11409 }
11410 Bind(&storeNormalValue);
11411 {
11412 BRANCH(isIntKind, &rawValueIsInt, &rawValueIsNumber);
11413 Bind(&rawValueIsInt);
11414 {
11415 GateRef convertedInt = Int64ToTaggedIntPtr(value);
11416 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedInt);
11417 Jump(&finishStore);
11418 }
11419 Bind(&rawValueIsNumber);
11420 {
11421 GateRef tmpDouble = CastInt64ToFloat64(value);
11422 GateRef convertedDouble = DoubleToTaggedDoublePtr(tmpDouble);
11423 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedDouble);
11424 Jump(&finishStore);
11425 }
11426 }
11427 Bind(&finishStore);
11428 {
11429 index = Int32Add(*index, Int32(1));
11430 Jump(&loopEnd);
11431 }
11432 }
11433 }
11434 Bind(&loopEnd);
11435 LoopEnd(&loopHead);
11436 Bind(&afterLoop);
11437 {
11438 Jump(&exit);
11439 }
11440 Bind(&exit);
11441 auto ret = *newElements;
11442 env->SubCfgExit();
11443 return ret;
11444 }
11445
MigrateFromHeapValueToRawValue(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)11446 GateRef StubBuilder::MigrateFromHeapValueToRawValue(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
11447 {
11448 auto env = GetEnvironment();
11449 Label entryPass(env);
11450 env->SubCfgEntry(&entryPass);
11451 DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
11452 Label exit(env);
11453
11454 GateRef elements = GetElementsArray(glue, object);
11455 GateRef length = GetLengthOfTaggedArray(elements);
11456 Label createCOW(env);
11457 Label createNormal(env);
11458 Label finishElementsInit(env);
11459 BRANCH(needCOW, &createCOW, &createNormal);
11460 Bind(&createCOW);
11461 {
11462 newElements = CallRuntime(glue, RTSTUB_ID(NewCOWMutantTaggedArray), { IntToTaggedPtr(length) });
11463 Jump(&finishElementsInit);
11464 }
11465 Bind(&createNormal);
11466 {
11467 newElements = CallRuntime(glue, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedPtr(length) });
11468 Jump(&finishElementsInit);
11469 }
11470 Bind(&finishElementsInit);
11471
11472 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11473 Label loopHead(env);
11474 Label loopEnd(env);
11475 Label afterLoop(env);
11476 Label storeValue(env);
11477 Jump(&loopHead);
11478 LoopBegin(&loopHead);
11479 {
11480 Label storeSpecialHole(env);
11481 Label storeNormalValue(env);
11482 Label finishStore(env);
11483 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11484 Bind(&storeValue);
11485 {
11486 Label convertToInt(env);
11487 Label convertToDouble(env);
11488 GateRef value = GetValueFromTaggedArray(glue, elements, *index);
11489 BRANCH(TaggedIsHole(value), &storeSpecialHole, &storeNormalValue);
11490 Bind(&storeSpecialHole);
11491 {
11492 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, SpecialHole());
11493 Jump(&finishStore);
11494 }
11495 Bind(&storeNormalValue);
11496 {
11497 Label valueIsInt(env);
11498 Label valueIsDouble(env);
11499 BRANCH(isIntKind, &convertToInt, &convertToDouble);
11500 Bind(&convertToInt);
11501 {
11502 GateRef convertedInt = GetInt64OfTInt(value);
11503 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, convertedInt);
11504 Jump(&finishStore);
11505 }
11506 Bind(&convertToDouble);
11507 {
11508 BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsDouble);
11509 Bind(&valueIsInt);
11510 {
11511 GateRef convertedDoubleFromTInt = CastDoubleToInt64(GetDoubleOfTInt(value));
11512 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
11513 convertedDoubleFromTInt);
11514 Jump(&finishStore);
11515 }
11516 Bind(&valueIsDouble);
11517 {
11518 GateRef convertedDoubleFromTDouble = CastDoubleToInt64(GetDoubleOfTDouble(value));
11519 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
11520 convertedDoubleFromTDouble);
11521 Jump(&finishStore);
11522 }
11523 }
11524 }
11525 Bind(&finishStore);
11526 {
11527 index = Int32Add(*index, Int32(1));
11528 Jump(&loopEnd);
11529 }
11530 }
11531 }
11532 Bind(&loopEnd);
11533 LoopEnd(&loopHead);
11534 Bind(&afterLoop);
11535 {
11536 Jump(&exit);
11537 }
11538 Bind(&exit);
11539 auto ret = *newElements;
11540 env->SubCfgExit();
11541 return ret;
11542 }
11543
MigrateFromHoleIntToHoleNumber(GateRef glue,GateRef object)11544 void StubBuilder::MigrateFromHoleIntToHoleNumber(GateRef glue, GateRef object)
11545 {
11546 auto env = GetEnvironment();
11547 Label entryPass(env);
11548 env->SubCfgEntry(&entryPass);
11549 Label exit(env);
11550
11551 GateRef elements = GetElementsArray(glue, object);
11552 GateRef length = GetLengthOfTaggedArray(elements);
11553 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11554 Label loopHead(env);
11555 Label loopEnd(env);
11556 Label afterLoop(env);
11557 Label storeValue(env);
11558 Jump(&loopHead);
11559 LoopBegin(&loopHead);
11560 {
11561 Label storeNormalValue(env);
11562 Label finishStore(env);
11563 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11564 Bind(&storeValue);
11565 {
11566 GateRef value = GetValueFromMutantTaggedArray(elements, *index);
11567 BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
11568 Bind(&storeNormalValue);
11569 {
11570 GateRef intVal = TruncInt64ToInt32(value);
11571 GateRef convertedValue = CastDoubleToInt64(ChangeInt32ToFloat64(intVal));
11572 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
11573 convertedValue);
11574 Jump(&finishStore);
11575 }
11576 Bind(&finishStore);
11577 {
11578 index = Int32Add(*index, Int32(1));
11579 Jump(&loopEnd);
11580 }
11581 }
11582 }
11583 Bind(&loopEnd);
11584 LoopEnd(&loopHead);
11585 Bind(&afterLoop);
11586 {
11587 Jump(&exit);
11588 }
11589 Bind(&exit);
11590 env->SubCfgExit();
11591 }
11592
MigrateFromHoleNumberToHoleInt(GateRef glue,GateRef object)11593 void StubBuilder::MigrateFromHoleNumberToHoleInt(GateRef glue, GateRef object)
11594 {
11595 auto env = GetEnvironment();
11596 Label entryPass(env);
11597 env->SubCfgEntry(&entryPass);
11598 Label exit(env);
11599
11600 GateRef elements = GetElementsArray(glue, object);
11601 GateRef length = GetLengthOfTaggedArray(elements);
11602 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
11603 Label loopHead(env);
11604 Label loopEnd(env);
11605 Label afterLoop(env);
11606 Label storeValue(env);
11607 Jump(&loopHead);
11608 LoopBegin(&loopHead);
11609 {
11610 Label storeNormalValue(env);
11611 Label finishStore(env);
11612 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
11613 Bind(&storeValue);
11614 {
11615 GateRef value = GetValueFromMutantTaggedArray(elements, *index);
11616 BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
11617 Bind(&storeNormalValue);
11618 {
11619 GateRef doubleVal = CastInt64ToFloat64(value);
11620 GateRef convertedValue = SExtInt32ToInt64(ChangeFloat64ToInt32(doubleVal));
11621 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
11622 convertedValue);
11623 Jump(&finishStore);
11624 }
11625 Bind(&finishStore);
11626 {
11627 index = Int32Add(*index, Int32(1));
11628 Jump(&loopEnd);
11629 }
11630 }
11631 }
11632 Bind(&loopEnd);
11633 LoopEnd(&loopHead);
11634 Bind(&afterLoop);
11635 {
11636 Jump(&exit);
11637 }
11638 Bind(&exit);
11639 env->SubCfgExit();
11640 }
11641
IsDetachedBuffer(GateRef glue,GateRef buffer)11642 GateRef StubBuilder::IsDetachedBuffer(GateRef glue, GateRef buffer)
11643 {
11644 auto env = GetEnvironment();
11645 Label entryPass(env);
11646 env->SubCfgEntry(&entryPass);
11647 Label isNull(env);
11648 Label exit(env);
11649 Label isByteArray(env);
11650 Label notByteArray(env);
11651 DEFVARIABLE(result, VariableType::BOOL(), False());
11652 BRANCH(IsByteArray(glue, buffer), &isByteArray, ¬ByteArray);
11653 Bind(&isByteArray);
11654 {
11655 Jump(&exit);
11656 }
11657 Bind(¬ByteArray);
11658 {
11659 GateRef dataSlot = GetArrayBufferData(glue, buffer);
11660 BRANCH(TaggedIsNull(dataSlot), &isNull, &exit);
11661 Bind(&isNull);
11662 {
11663 result = True();
11664 Jump(&exit);
11665 }
11666 }
11667 Bind(&exit);
11668 auto ret = *result;
11669 env->SubCfgExit();
11670 return ret;
11671 }
11672
DefineFunc(GateRef glue,GateRef constpool,GateRef index,FunctionKind targetKind)11673 GateRef StubBuilder::DefineFunc(GateRef glue, GateRef constpool, GateRef index, FunctionKind targetKind)
11674 {
11675 auto env = GetEnvironment();
11676 Label subentry(env);
11677 env->SubCfgEntry(&subentry);
11678 Label exit(env);
11679 DEFVARIABLE(ihc, VariableType::JS_ANY(), Undefined());
11680 DEFVARIABLE(val, VariableType::JS_ANY(), Undefined());
11681 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
11682
11683 Label isHeapObject(env);
11684 Label afterAOTLiteral(env);
11685 Label tryGetAOTIhc(env);
11686 //AOT ihc infos always in unshareConstpool
11687 //If is runing on AOT,unshareConstpool is definitely not a hole
11688 //So wo can skip if unshareConstpool is hole
11689 GateRef unsharedConstpool = GetUnsharedConstpoolFromGlue(glue, constpool);
11690 BRANCH(TaggedIsHole(unsharedConstpool), &afterAOTLiteral, &tryGetAOTIhc);
11691 Bind(&tryGetAOTIhc);
11692 {
11693 val = GetValueFromTaggedArray(glue, unsharedConstpool, index);
11694 BRANCH(TaggedIsHeapObject(*val), &isHeapObject, &afterAOTLiteral);
11695 {
11696 Bind(&isHeapObject);
11697 Label isAOTLiteral(env);
11698 BRANCH(IsAOTLiteralInfo(glue, *val), &isAOTLiteral, &afterAOTLiteral);
11699 {
11700 Bind(&isAOTLiteral);
11701 {
11702 ihc = GetIhcFromAOTLiteralInfo(glue, *val);
11703 Jump(&afterAOTLiteral);
11704 }
11705 }
11706 }
11707 }
11708 Bind(&afterAOTLiteral);
11709 GateRef method = GetMethodFromConstPool(glue, constpool, index);
11710 Label isSendableFunc(env);
11711 Label isNotSendableFunc(env);
11712 Label afterDealWithCompiledStatus(env);
11713 BRANCH(IsSendableFunction(method), &isSendableFunc, &isNotSendableFunc);
11714 Bind(&isSendableFunc);
11715 {
11716 GateRef globalEnv = GetCurrentGlobalEnv();
11717 NewObjectStubBuilder newBuilder(this, globalEnv);
11718 result = newBuilder.NewJSSendableFunction(glue, method, targetKind);
11719 Jump(&afterDealWithCompiledStatus);
11720 }
11721 Bind(&isNotSendableFunc);
11722 {
11723 GateRef globalEnv = GetCurrentGlobalEnv();
11724 NewObjectStubBuilder newBuilder(this, globalEnv);
11725 result = newBuilder.NewJSFunction(glue, method, targetKind);
11726 Jump(&afterDealWithCompiledStatus);
11727 }
11728 Bind(&afterDealWithCompiledStatus);
11729
11730 Label ihcNotUndefined(env);
11731 BRANCH(TaggedIsUndefined(*ihc), &exit, &ihcNotUndefined);
11732 Bind(&ihcNotUndefined);
11733 {
11734 CallRuntime(glue, RTSTUB_ID(AOTEnableProtoChangeMarker), {*result, *ihc, *val});
11735 Jump(&exit);
11736 }
11737 Bind(&exit);
11738 auto ret = *result;
11739 env->SubCfgExit();
11740 return ret;
11741 }
11742
SetCompiledCodeFlagToFunctionFromMethod(GateRef glue,GateRef function,GateRef method)11743 void StubBuilder::SetCompiledCodeFlagToFunctionFromMethod(GateRef glue, GateRef function, GateRef method)
11744 {
11745 // set compiled code & fast call flag
11746 GateRef isFastCall = IsFastCall(method);
11747 GateRef compiledCodeField = Int32LSL(Int32(1U), Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT));
11748 GateRef compiledCodeFlag = Int32Or(compiledCodeField, Int32LSL(ZExtInt1ToInt32(isFastCall),
11749 Int32(JSFunctionBase::IsFastCallBit::START_BIT)));
11750 SetCompiledCodeFlagToFunction(glue, function, compiledCodeFlag);
11751 }
11752
UpdateProfileTypeInfoCellToFunction(GateRef glue,GateRef function,GateRef profileTypeInfo,GateRef slotId)11753 void StubBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
11754 GateRef profileTypeInfo, GateRef slotId)
11755 {
11756 Label subEntry(env_);
11757 env_->SubCfgEntry(&subEntry);
11758
11759 Label profileTypeInfoNotUndefined(env_);
11760 Label slotValueUpdate(env_);
11761 Label slotValueNotUndefined(env_);
11762 Label profileTypeInfoEnd(env_);
11763 NewObjectStubBuilder newBuilder(env_);
11764 BRANCH(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined);
11765 Bind(&profileTypeInfoNotUndefined);
11766 {
11767 GateRef slotValue = GetValueFromTaggedArray(glue, profileTypeInfo, slotId);
11768 BRANCH(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
11769 Bind(&slotValueUpdate);
11770 {
11771 GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined());
11772 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
11773 SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell);
11774 Jump(&profileTypeInfoEnd);
11775 }
11776 Bind(&slotValueNotUndefined);
11777 {
11778 UpdateProfileTypeInfoCellType(glue, slotValue);
11779 SetRawProfileTypeInfoToFunction(glue, function, slotValue);
11780 TryToJitReuseCompiledFunc(glue, function, slotValue);
11781 Jump(&profileTypeInfoEnd);
11782 }
11783 }
11784 Bind(&profileTypeInfoEnd);
11785
11786 env_->SubCfgExit();
11787 }
11788
Loadlocalmodulevar(GateRef glue,GateRef index,GateRef module)11789 GateRef StubBuilder::Loadlocalmodulevar(GateRef glue, GateRef index, GateRef module)
11790 {
11791 auto env = GetEnvironment();
11792 Label subentry(env);
11793 env->SubCfgEntry(&subentry);
11794 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11795 Label notSendableFunctionModule(env);
11796 Label sendableFunctionModule(env);
11797 Label exit(env);
11798 BRANCH_UNLIKELY(IsSendableFunctionModule(glue, module), &sendableFunctionModule, ¬SendableFunctionModule);
11799 Bind(&sendableFunctionModule);
11800 {
11801 result = CallRuntime(glue, RTSTUB_ID(LdLocalModuleVarByIndexWithModule),
11802 {Int8ToTaggedInt(index), module});
11803 Jump(&exit);
11804 }
11805 Bind(¬SendableFunctionModule);
11806 {
11807 GateRef dictionary = GetNameDictionary(glue, module);
11808 Label dataIsNotUndefined(env);
11809 BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &exit, &dataIsNotUndefined);
11810 Bind(&dataIsNotUndefined);
11811 {
11812 result = GetValueFromTaggedArray(glue, dictionary, ZExtInt8ToInt32(index));
11813 Jump(&exit);
11814 }
11815 }
11816 Bind(&exit);
11817 auto ret = *result;
11818 env->SubCfgExit();
11819 return ret;
11820 }
11821
ModuleEnvMustBeValid(GateRef glue,GateRef curEnv)11822 void StubBuilder::ModuleEnvMustBeValid(GateRef glue, GateRef curEnv)
11823 {
11824 GateRef objectType = GetObjectType(LoadHClass(glue, curEnv));
11825 [[maybe_unused]] GateRef isTaggedArray = LogicOrBuilder(env_)
11826 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::TAGGED_ARRAY))))
11827 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::TAGGED_DICTIONARY))))
11828 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::LEXICAL_ENV))))
11829 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::SENDABLE_ENV))))
11830 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::CONSTANT_POOL))))
11831 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::PROFILE_TYPE_INFO))))
11832 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::AOT_LITERAL_INFO))))
11833 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::VTABLE))))
11834 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::COW_TAGGED_ARRAY))))
11835 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::MUTANT_TAGGED_ARRAY))))
11836 .Or(Int32Equal(objectType, Int32(static_cast<int>(JSType::COW_MUTANT_TAGGED_ARRAY))))
11837 .Done();
11838 ASSERT(isTaggedArray);
11839 }
11840
SearchFromModuleCache(GateRef glue,GateRef moduleName)11841 GateRef StubBuilder::SearchFromModuleCache(GateRef glue, GateRef moduleName)
11842 {
11843 auto env = GetEnvironment();
11844 Label subentry(env);
11845 env->SubCfgEntry(&subentry);
11846
11847 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11848 Label isContainModule(env);
11849 Label exit(env);
11850 GateRef moduleObj = GetCjsModuleFunction(glue);
11851 GateRef cacheName = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::CJS_CACHE_INDEX);
11852 GateRef moduleCache = FastGetPropertyByName(glue, moduleObj, cacheName, ProfileOperation());
11853 GateRef containsModuleIndex = FindEntryFromHashTable<CjsModuleCache>(glue, moduleCache, moduleName);
11854 BRANCH(Int32NotEqual(containsModuleIndex, Int32(-1)), &isContainModule, &exit);
11855
11856 Bind(&isContainModule);
11857 {
11858 GateRef cachedModule = GetValueFromDictionary<CjsModuleCache>(glue, moduleCache, containsModuleIndex);
11859 GateRef exportsName = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::CJS_EXPORTS_INDEX);
11860 result = FastGetPropertyByName(glue, cachedModule, exportsName, ProfileOperation());
11861 Jump(&exit);
11862 }
11863
11864 Bind(&exit);
11865 auto ret = *result;
11866 env->SubCfgExit();
11867 return ret;
11868 }
11869
GetNativeOrCjsExports(GateRef glue,GateRef resolvedModule)11870 GateRef StubBuilder::GetNativeOrCjsExports(GateRef glue, GateRef resolvedModule)
11871 {
11872 auto env = GetEnvironment();
11873 Label subentry(env);
11874 env->SubCfgEntry(&subentry);
11875
11876 DEFVARIABLE(exports, VariableType::JS_ANY(), Undefined());
11877 Label isNativeModule(env);
11878 Label judgeCjsModule(env);
11879 Label exit(env);
11880 BRANCH(IsNativeModule(resolvedModule), &isNativeModule, &judgeCjsModule);
11881
11882 Bind(&isNativeModule);
11883 {
11884 Label notJSObject(env);
11885 exports = GetModuleValueByIndex(glue, resolvedModule, Int32(0), TaggedFalse());
11886 BRANCH(IsJSObject(glue, *exports), &exit, ¬JSObject);
11887
11888 Bind(¬JSObject);
11889 {
11890 CallNGCRuntime(glue, RTSTUB_ID(LoadNativeModuleFailed), {resolvedModule});
11891 Jump(&exit);
11892 }
11893 }
11894
11895 Bind(&judgeCjsModule);
11896 {
11897 Label isCjsModule(env);
11898 BRANCH(IsCjsModule(resolvedModule), &isCjsModule, &exit);
11899
11900 Bind(&isCjsModule);
11901 Label exportsIsHole(env);
11902 GateRef moduleName = CallRuntime(glue, RTSTUB_ID(GetModuleName), {resolvedModule});
11903 exports = SearchFromModuleCache(glue, moduleName);
11904 BRANCH(TaggedIsHole(*exports), &exportsIsHole, &exit);
11905
11906 Bind(&exportsIsHole);
11907 {
11908 exports = CallRuntime(glue, RTSTUB_ID(ThrowExportsIsHole), {resolvedModule});
11909 Jump(&exit);
11910 }
11911 }
11912
11913 Bind(&exit);
11914 auto ret = *exports;
11915 env->SubCfgExit();
11916 return ret;
11917 }
11918
GetValueFromExportObject(GateRef glue,GateRef exports,GateRef index)11919 GateRef StubBuilder::GetValueFromExportObject(GateRef glue, GateRef exports, GateRef index)
11920 {
11921 auto env = GetEnvironment();
11922 Label subentry(env);
11923 env->SubCfgEntry(&subentry);
11924
11925 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11926 Label isUndefinedIdx(env);
11927 Label validIdx(env);
11928 Label checkResultIsAccessor(env);
11929 Label exit(env);
11930 BRANCH(Int32Equal(index, Int32(SourceTextModule::UNDEFINED_INDEX)), &isUndefinedIdx, &validIdx);
11931
11932 Bind(&isUndefinedIdx);
11933 {
11934 result = exports;
11935 Jump(&exit);
11936 }
11937
11938 Bind(&validIdx);
11939 {
11940 Label isDictionaryMode(env);
11941 Label notDictionaryMode(env);
11942 GateRef properties = GetPropertiesFromJSObject(glue, exports);
11943 BRANCH(IsDictionaryMode(glue, properties), &isDictionaryMode, ¬DictionaryMode);
11944
11945 Bind(&isDictionaryMode);
11946 {
11947 result = GetValueFromDictionary<NameDictionary>(glue, properties, index);
11948 Jump(&checkResultIsAccessor);
11949 }
11950
11951 Bind(¬DictionaryMode);
11952 {
11953 GateRef hClass = LoadHClass(glue, exports);
11954 GateRef layoutInfo = GetLayoutFromHClass(glue, hClass);
11955 GateRef attr = GetAttr(glue, layoutInfo, index);
11956 result = JSObjectGetPropertyWithRep(glue, exports, hClass, attr);
11957 Jump(&checkResultIsAccessor);
11958 }
11959 }
11960
11961 Bind(&checkResultIsAccessor);
11962 {
11963 Label isAccessor(env);
11964 BRANCH_UNLIKELY(TaggedIsAccessor(glue, *result), &isAccessor, &exit);
11965
11966 Bind(&isAccessor);
11967 {
11968 result = CallGetterHelper(glue, exports, exports, *result, ProfileOperation());
11969 Jump(&exit);
11970 }
11971 }
11972
11973 Bind(&exit);
11974 auto ret = *result;
11975 env->SubCfgExit();
11976 return ret;
11977 }
11978
GetNativeOrCjsModuleValue(GateRef glue,GateRef module,GateRef index)11979 GateRef StubBuilder::GetNativeOrCjsModuleValue(GateRef glue, GateRef module, GateRef index)
11980 {
11981 auto env = GetEnvironment();
11982 Label subentry(env);
11983 env->SubCfgEntry(&subentry);
11984
11985 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
11986 Label hasException(env);
11987 Label noException(env);
11988 Label exit(env);
11989 GateRef exports = GetNativeOrCjsExports(glue, module);
11990 BRANCH(HasPendingException(glue), &hasException, &noException);
11991
11992 Bind(&hasException);
11993 {
11994 result = Exception();
11995 Jump(&exit);
11996 }
11997
11998 Bind(&noException);
11999 {
12000 result = GetValueFromExportObject(glue, exports, index);
12001 Jump(&exit);
12002 }
12003
12004 Bind(&exit);
12005 auto ret = *result;
12006 env->SubCfgExit();
12007 return ret;
12008 }
12009
GetModuleValueByIndex(GateRef glue,GateRef module,GateRef index,GateRef isThrow)12010 GateRef StubBuilder::GetModuleValueByIndex(GateRef glue, GateRef module, GateRef index, GateRef isThrow)
12011 {
12012 auto env = GetEnvironment();
12013 Label subentry(env);
12014 env->SubCfgEntry(&subentry);
12015
12016 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12017 Label isUndefined(env);
12018 Label notUndefined(env);
12019 Label exit(env);
12020 GateRef dictionary = GetNameDictionary(glue, module);
12021 BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &isUndefined, ¬Undefined);
12022
12023 Bind(¬Undefined);
12024 {
12025 result = GetValueFromTaggedArray(glue, dictionary, index);
12026 Jump(&exit);
12027 }
12028
12029 Bind(&isUndefined);
12030 {
12031 result = CallRuntime(glue, RTSTUB_ID(CheckAndThrowModuleError), {module, isThrow});
12032 Jump(&exit);
12033 }
12034
12035 Bind(&exit);
12036 auto ret = *result;
12037 env->SubCfgExit();
12038 return ret;
12039 }
12040
GetModuleValue(GateRef glue,GateRef module,GateRef index)12041 GateRef StubBuilder::GetModuleValue(GateRef glue, GateRef module, GateRef index)
12042 {
12043 auto env = GetEnvironment();
12044 Label subentry(env);
12045 env->SubCfgEntry(&subentry);
12046
12047 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12048 Label isNativeOrCjsModule(env);
12049 Label notNativeOrCjsModule(env);
12050 Label exit(env);
12051 GateRef checkNativeOrCjsModule = BitOr(IsNativeModule(module), IsCjsModule(module));
12052 BRANCH(checkNativeOrCjsModule, &isNativeOrCjsModule, ¬NativeOrCjsModule);
12053
12054 Bind(&isNativeOrCjsModule);
12055 {
12056 result = GetNativeOrCjsModuleValue(glue, module, index);
12057 Jump(&exit);
12058 }
12059
12060 Bind(¬NativeOrCjsModule);
12061 {
12062 result = GetModuleValueByIndex(glue, module, index, TaggedFalse());
12063 Jump(&exit);
12064 }
12065
12066 Bind(&exit);
12067 auto ret = *result;
12068 env->SubCfgExit();
12069 return ret;
12070 }
12071
GetNativeOrCjsModuleValueByName(GateRef glue,GateRef module,GateRef bindingName)12072 GateRef StubBuilder::GetNativeOrCjsModuleValueByName(GateRef glue, GateRef module, GateRef bindingName)
12073 {
12074 auto env = GetEnvironment();
12075 Label subentry(env);
12076 env->SubCfgEntry(&subentry);
12077
12078 GateRef exports = GetNativeOrCjsExports(glue, module);
12079 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12080 Label hasPendingException(env);
12081 Label noPendingException(env);
12082 Label exit(env);
12083 BRANCH(HasPendingException(glue), &hasPendingException, &noPendingException);
12084
12085 Bind(&hasPendingException);
12086 {
12087 result = Exception();
12088 Jump(&exit);
12089 }
12090
12091 Bind(&noPendingException);
12092 {
12093 GateRef defaultString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::DEFAULT_INDEX);
12094 Label isSameVal(env);
12095 Label notSameVal(env);
12096 BRANCH_UNLIKELY(SameValue(glue, bindingName, defaultString), &isSameVal, ¬SameVal);
12097
12098 Bind(&isSameVal);
12099 {
12100 result = exports;
12101 Jump(&exit);
12102 }
12103
12104 Bind(¬SameVal);
12105 {
12106 result = FastGetPropertyByName(glue, exports, bindingName, ProfileOperation());
12107 Jump(&exit);
12108 }
12109 }
12110
12111 Bind(&exit);
12112 auto ret = *result;
12113 env->SubCfgExit();
12114 return ret;
12115 }
12116
ResolveElementOfObject(GateRef glue,GateRef hClass,GateRef exportName,GateRef module,GateRef layOutInfo)12117 GateRef StubBuilder::ResolveElementOfObject(GateRef glue, GateRef hClass, GateRef exportName,
12118 GateRef module, GateRef layOutInfo)
12119 {
12120 auto env = GetEnvironment();
12121 Label subentry(env);
12122 env->SubCfgEntry(&subentry);
12123
12124 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12125 Label validIdx(env);
12126 Label invalidIdx(env);
12127 Label exit(env);
12128 GateRef propsNum = GetNumberOfPropsFromHClass(hClass);
12129 GateRef idx = FindElementWithCache(glue, layOutInfo, hClass, exportName, propsNum);
12130 BRANCH(Int32NotEqual(idx, Int32(-1)), &validIdx, &invalidIdx);
12131
12132 Bind(&validIdx);
12133 {
12134 result = CallRuntime(glue, RTSTUB_ID(NewResolvedIndexBindingRecord), {module, IntToTaggedInt(idx)});
12135 Jump(&exit);
12136 }
12137
12138 Bind(&invalidIdx);
12139 {
12140 result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::UNDEFINED_INDEX);
12141 Jump(&exit);
12142 }
12143
12144 Bind(&exit);
12145 auto ret = *result;
12146 env->SubCfgExit();
12147 return ret;
12148 }
12149
ResolveExportObject(GateRef glue,GateRef module,GateRef exports,GateRef exportName)12150 GateRef StubBuilder::ResolveExportObject(GateRef glue, GateRef module, GateRef exports, GateRef exportName)
12151 {
12152 auto env = GetEnvironment();
12153 Label subentry(env);
12154 env->SubCfgEntry(&subentry);
12155
12156 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12157 Label defaultCallNewBindingRecord(env);
12158 Label notSameVal(env);
12159 Label exportsIsHeapObj(env);
12160 Label notNativeModuleFailureInfo(env);
12161 Label exit(env);
12162 GateRef defaultString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::DEFAULT_INDEX);
12163 BRANCH(SameValue(glue, exportName, defaultString), &defaultCallNewBindingRecord, ¬SameVal);
12164
12165 Bind(¬SameVal);
12166 BRANCH(TaggedIsHeapObject(exports), &exportsIsHeapObj, ¬NativeModuleFailureInfo);
12167
12168 Bind(&exportsIsHeapObj);
12169 BRANCH(IsNativeModuleFailureInfo(glue, exports), &defaultCallNewBindingRecord, ¬NativeModuleFailureInfo);
12170
12171 Bind(¬NativeModuleFailureInfo);
12172 Label exportsIsJSObject(env);
12173 Label exportsNotJSObject(env);
12174 BRANCH(IsJSObject(glue, exports), &exportsIsJSObject, &exportsNotJSObject);
12175
12176 Bind(&exportsIsJSObject);
12177 {
12178 Label isDictionaryMode(env);
12179 Label notDictionaryMode(env);
12180 Label checkResultIsUndefined(env);
12181 GateRef properties = GetPropertiesFromJSObject(glue, exports);
12182 BRANCH(IsDictionaryMode(glue, properties), &isDictionaryMode, ¬DictionaryMode);
12183
12184 Bind(&isDictionaryMode);
12185 {
12186 Label validEntry(env);
12187 GateRef entry = FindEntryFromHashTable<NameDictionary>(glue, properties, exportName);
12188 BRANCH(Int32NotEqual(entry, Int32(-1)), &validEntry, &checkResultIsUndefined);
12189
12190 Bind(&validEntry);
12191 result = CallRuntime(glue, RTSTUB_ID(NewResolvedIndexBindingRecord), {module, IntToTaggedInt(entry)});
12192 Jump(&checkResultIsUndefined);
12193 }
12194
12195 Bind(¬DictionaryMode);
12196 {
12197 Label notEqualZero(env);
12198 GateRef hClass = LoadHClass(glue, exports);
12199 GateRef layoutInfo = GetLayoutFromHClass(glue, hClass);
12200 GateRef eleNum = GetNumberOfPropsFromHClass(hClass);
12201 BRANCH(Int32NotEqual(eleNum, Int32(0)), ¬EqualZero, &checkResultIsUndefined);
12202
12203 Bind(¬EqualZero);
12204 result = ResolveElementOfObject(glue, hClass, exportName, module, layoutInfo);
12205 Jump(&checkResultIsUndefined);
12206 }
12207
12208 Bind(&checkResultIsUndefined);
12209 BRANCH(TaggedIsUndefined(*result), &exportsNotJSObject, &exit);
12210 }
12211
12212 Bind(&defaultCallNewBindingRecord);
12213 {
12214 result = CallRuntime(glue, RTSTUB_ID(NewResolvedIndexBindingRecord), {module, IntToTaggedInt(Int32(-1))});
12215 Jump(&exit);
12216 }
12217
12218 Bind(&exportsNotJSObject);
12219 {
12220 result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::NULL_INDEX);
12221 Jump(&exit);
12222 }
12223
12224 Bind(&exit);
12225 auto ret = *result;
12226 env->SubCfgExit();
12227 return ret;
12228 }
12229
UpdateBindingAndGetModuleValue(GateRef glue,GateRef module,GateRef requiredModule,GateRef index,GateRef bindingName)12230 GateRef StubBuilder::UpdateBindingAndGetModuleValue(GateRef glue, GateRef module, GateRef requiredModule,
12231 GateRef index, GateRef bindingName)
12232 {
12233 auto env = GetEnvironment();
12234 Label subentry(env);
12235 env->SubCfgEntry(&subentry);
12236
12237 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12238 Label hasException(env);
12239 Label noException(env);
12240 Label exit(env);
12241 GateRef curModuleEnv = GetCurrentModuleEnv(glue, module);
12242 ModuleEnvMustBeDefined(curModuleEnv);
12243 GateRef exports = GetNativeOrCjsExports(glue, requiredModule);
12244 BRANCH(HasPendingException(glue), &hasException, &noException);
12245
12246 Bind(&noException);
12247 {
12248 Label isNullOrString(env);
12249 Label notNullOrString(env);
12250 GateRef resolution = ResolveExportObject(glue, requiredModule, exports, bindingName);
12251 BRANCH(BitOr(TaggedIsNull(resolution), TaggedIsString(glue, resolution)), &isNullOrString, ¬NullOrString);
12252
12253 Bind(&isNullOrString);
12254 {
12255 result = CallRuntime(glue, RTSTUB_ID(HandleResolutionIsNullOrString),
12256 {module, requiredModule, bindingName, resolution});
12257 Jump(&exit);
12258 }
12259
12260 Bind(¬NullOrString);
12261 {
12262 CheckIsResolvedIndexBinding(glue, resolution);
12263 SetIsUpdatedFromResolvedBindingOfResolvedIndexBinding(glue, resolution, True());
12264 SetValueToTaggedArray(VariableType::JS_ANY(), glue, curModuleEnv, index, resolution);
12265 result = GetValueFromExportObject(glue, exports, GetIdxOfResolvedIndexBinding(resolution));
12266 Jump(&exit);
12267 }
12268 }
12269
12270 Bind(&hasException);
12271 {
12272 result = Exception();
12273 Jump(&exit);
12274 }
12275
12276 Bind(&exit);
12277 auto ret = *result;
12278 env->SubCfgExit();
12279 return ret;
12280 }
12281
GetResolvedRecordIndexBindingModule(GateRef glue,GateRef module,GateRef resolvedBinding)12282 GateRef StubBuilder::GetResolvedRecordIndexBindingModule(GateRef glue, GateRef module, GateRef resolvedBinding)
12283 {
12284 GateRef recordName = GetModuleRecord(glue, resolvedBinding);
12285 RecordNameMustBeString(glue, recordName);
12286 GateRef moduleManager = GetModuleManager(glue);
12287 GateRef result = CallRuntime(glue, RTSTUB_ID(GetResolvedRecordIndexBindingModule),
12288 {module, resolvedBinding, moduleManager, recordName});
12289 return result;
12290 }
12291
GetResolvedRecordBindingModule(GateRef glue,GateRef module,GateRef resolvedBinding)12292 GateRef StubBuilder::GetResolvedRecordBindingModule(GateRef glue, GateRef module, GateRef resolvedBinding)
12293 {
12294 GateRef recordName = GetModuleRecord(glue, resolvedBinding);
12295 RecordNameMustBeString(glue, recordName);
12296 GateRef moduleManager = GetModuleManager(glue);
12297 GateRef result = CallRuntime(glue, RTSTUB_ID(GetResolvedRecordBindingModule),
12298 {module, moduleManager, recordName});
12299 return result;
12300 }
12301
LoadExternalmodulevar(GateRef glue,GateRef index,GateRef curModule)12302 GateRef StubBuilder::LoadExternalmodulevar(GateRef glue, GateRef index, GateRef curModule)
12303 {
12304 auto env = GetEnvironment();
12305 Label subentry(env);
12306 env->SubCfgEntry(&subentry);
12307
12308 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12309 Label notSendableFunctionModule(env);
12310 Label moduleUndefined(env);
12311 Label moduleIsdefined(env);
12312 Label moduleEnvUndefined(env);
12313 Label moduleEnvIsdefined(env);
12314 Label isSendableFunctionModule(env);
12315 Label isNullPtr(env);
12316 Label notNullPtr(env);
12317 Label resolvedBindingIsHeapObj(env);
12318 Label misstakenResolvedBinding(env);
12319 Label judgeResolvedBinding(env);
12320 Label judgeResolvedRecordIndexBinding(env);
12321 Label judgeResolvedRecordBinding(env);
12322 Label exit(env);
12323 BRANCH(IsSendableFunctionModule(glue, curModule), &isSendableFunctionModule, ¬SendableFunctionModule);
12324
12325 Bind(¬SendableFunctionModule);
12326 BRANCH_UNLIKELY(TaggedIsUndefined(curModule), &moduleUndefined, &moduleIsdefined);
12327
12328 Bind(&moduleIsdefined);
12329 GateRef curModuleEnv = GetCurrentModuleEnv(glue, curModule);
12330 BRANCH(TaggedIsUndefined(curModuleEnv), &moduleEnvUndefined, &moduleEnvIsdefined);
12331
12332 Bind(&moduleEnvIsdefined);
12333 ModuleEnvMustBeValid(glue, curModuleEnv);
12334 GateRef resolvedBinding = GetValueFromTaggedArray(glue, curModuleEnv, index);
12335 BRANCH_LIKELY(IntPtrEuqal(GetModuleLogger(glue), IntPtr(0)), &isNullPtr, ¬NullPtr);
12336
12337 Bind(&isNullPtr);
12338 BRANCH(TaggedIsHeapObject(resolvedBinding), &resolvedBindingIsHeapObj, &misstakenResolvedBinding);
12339
12340 Bind(&resolvedBindingIsHeapObj);
12341 {
12342 Label isResolvedIndexBinding(env);
12343 BRANCH(IsResolvedIndexBinding(glue, resolvedBinding), &isResolvedIndexBinding, &judgeResolvedBinding);
12344
12345 Bind(&isResolvedIndexBinding);
12346 {
12347 Label isLdEndExecPatchMain(env);
12348 Label notLdEndExecPatchMain(env);
12349 Label notHole(env);
12350 DEFVARIABLE(resolvedModule, VariableType::JS_ANY(), Hole());
12351 resolvedModule = GetResolveModuleFromResolvedIndexBinding(glue, resolvedBinding);
12352 ResolvedModuleMustBeSourceTextModule(glue, *resolvedModule);
12353 GateRef idxOfResolvedBinding = GetIdxOfResolvedIndexBinding(resolvedBinding);
12354 BRANCH(IsLdEndExecPatchMain(glue), &isLdEndExecPatchMain, ¬LdEndExecPatchMain);
12355
12356 Bind(&isLdEndExecPatchMain);
12357 GateRef resolvedModuleOfHotReload = CallNGCRuntime(glue, RTSTUB_ID(FindPatchModule),
12358 {glue, *resolvedModule});
12359 BRANCH(TaggedIsHole(resolvedModuleOfHotReload), ¬LdEndExecPatchMain, ¬Hole);
12360
12361 Bind(¬LdEndExecPatchMain);
12362 Label isSharedModule(env);
12363 Label notSharedModule(env);
12364 BRANCH(IsSharedModule(*resolvedModule), &isSharedModule, ¬SharedModule);
12365 Bind(&isSharedModule);
12366 resolvedModule = CallNGCRuntime(glue, RTSTUB_ID(UpdateSharedModule), {glue, *resolvedModule});
12367 Jump(¬SharedModule);
12368 Bind(¬SharedModule);
12369 result = GetModuleValue(glue, *resolvedModule, idxOfResolvedBinding);
12370 Jump(&exit);
12371
12372 Bind(¬Hole);
12373 result = GetModuleValue(glue, resolvedModuleOfHotReload, idxOfResolvedBinding);
12374 Jump(&exit);
12375 }
12376 }
12377
12378 Bind(&judgeResolvedBinding);
12379 {
12380 Label isResolvedBinding(env);
12381 BRANCH(IsResolvedBinding(glue, resolvedBinding), &isResolvedBinding, &judgeResolvedRecordIndexBinding);
12382
12383 Bind(&isResolvedBinding);
12384 {
12385 GateRef resolvedModule = GetResolveModuleFromResolvedBinding(glue, resolvedBinding);
12386 ResolvedModuleMustBeSourceTextModule(glue, resolvedModule);
12387 Label isNativeOrCjsModule(env);
12388 GateRef checkNativeOrCjsModule = BitOr(IsNativeModule(resolvedModule), IsCjsModule(resolvedModule));
12389 BRANCH(checkNativeOrCjsModule, &isNativeOrCjsModule, &misstakenResolvedBinding);
12390
12391 Bind(&isNativeOrCjsModule);
12392 {
12393 result = UpdateBindingAndGetModuleValue(glue, curModule, resolvedModule, index,
12394 GetBindingName(glue, resolvedBinding));
12395 Jump(&exit);
12396 }
12397 }
12398 }
12399
12400 Bind(&judgeResolvedRecordIndexBinding);
12401 {
12402 Label isResolvedRecordIndexBinding(env);
12403 BRANCH(IsResolvedRecordIndexBinding(glue, resolvedBinding), &isResolvedRecordIndexBinding,
12404 &judgeResolvedRecordBinding);
12405
12406 Bind(&isResolvedRecordIndexBinding);
12407 {
12408 GateRef resolvedModule = GetResolvedRecordIndexBindingModule(glue, curModule, resolvedBinding);
12409 GateRef idxOfResolvedRecordIndexBinding = GetIdxOfResolvedRecordIndexBinding(resolvedBinding);
12410 result = GetModuleValue(glue, resolvedModule, idxOfResolvedRecordIndexBinding);
12411 Jump(&exit);
12412 }
12413 }
12414
12415 Bind(&judgeResolvedRecordBinding);
12416 {
12417 Label isResolvedRecordBinding(env);
12418 BRANCH(IsResolvedRecordBinding(glue, resolvedBinding), &isResolvedRecordBinding, &misstakenResolvedBinding);
12419 Bind(&isResolvedRecordBinding);
12420 {
12421 GateRef resolvedModule = GetResolvedRecordBindingModule(glue, curModule, resolvedBinding);
12422 result = GetNativeOrCjsModuleValueByName(glue, resolvedModule, GetBindingName(glue, resolvedBinding));
12423 Jump(&exit);
12424 }
12425 }
12426
12427 Bind(&isSendableFunctionModule);
12428 {
12429 result = CallRuntime(glue, RTSTUB_ID(LdExternalModuleVarByIndexWithModule),
12430 {IntToTaggedInt(index), curModule});
12431 Jump(&exit);
12432 }
12433
12434 Bind(&moduleUndefined);
12435 {
12436 FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(CurrentModuleUndefined))});
12437 Jump(&exit);
12438 }
12439
12440 Bind(&moduleEnvUndefined);
12441 {
12442 result = Undefined();
12443 Jump(&exit);
12444 }
12445
12446 Bind(¬NullPtr);
12447 {
12448 result = CallRuntime(glue, RTSTUB_ID(GetModuleValueOuterInternal),
12449 {curModule, IntToTaggedInt(index)});
12450 Jump(&exit);
12451 }
12452
12453 Bind(&misstakenResolvedBinding);
12454 {
12455 CallNGCRuntime(glue, RTSTUB_ID(FatalPrintMisstakenResolvedBinding), {index, curModule});
12456 Jump(&exit);
12457 }
12458
12459 Bind(&exit);
12460 auto ret = *result;
12461 env->SubCfgExit();
12462 return ret;
12463 }
12464
LoadModuleNamespaceByIndex(GateRef glue,GateRef index,GateRef module)12465 GateRef StubBuilder::LoadModuleNamespaceByIndex(GateRef glue, GateRef index, GateRef module)
12466 {
12467 auto env = GetEnvironment();
12468 Label subentry(env);
12469 env->SubCfgEntry(&subentry);
12470 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
12471 Label moduleUndefined(env);
12472 Label moduleNotUndefined(env);
12473 Label notSendableFunctionModule(env);
12474 Label requestedModulesNotUndefined(env);
12475 Label requiredModuleIsHeapObj(env);
12476 Label requiredModuleIsSourceTextModule(env);
12477 Label isNullPtr(env);
12478 Label isNativeModule(env);
12479 Label dictionaryNotUndefined(env);
12480 Label notNativeModule(env);
12481 Label isCjsModule(env);
12482 Label notCjsModule(env);
12483 Label namespaceNotUndefined(env);
12484 Label slowPath(env);
12485 Label exit(env);
12486 BRANCH_UNLIKELY(TaggedIsUndefined(module), &moduleUndefined, &moduleNotUndefined);
12487 Bind(&moduleUndefined);
12488 {
12489 FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(CurrentModuleUndefined))});
12490 Jump(&exit);
12491 }
12492 Bind(&moduleNotUndefined);
12493 BRANCH_UNLIKELY(IsSendableFunctionModule(glue, module), &slowPath, ¬SendableFunctionModule);
12494 Bind(¬SendableFunctionModule);
12495 {
12496 GateRef requestedModules = GetRequestedModules(glue, module);
12497 BRANCH_UNLIKELY(TaggedIsUndefined(requestedModules), &slowPath, &requestedModulesNotUndefined);
12498 Bind(&requestedModulesNotUndefined);
12499 GateRef requiredModule = GetValueFromTaggedArray(glue, requestedModules, index);
12500 BRANCH_LIKELY(TaggedIsHeapObject(requiredModule), &requiredModuleIsHeapObj, &slowPath);
12501 Bind(&requiredModuleIsHeapObj);
12502 BRANCH_LIKELY(IsSourceTextModule(glue, requiredModule), &requiredModuleIsSourceTextModule, &slowPath);
12503 Bind(&requiredModuleIsSourceTextModule);
12504 BRANCH_LIKELY(IntPtrEuqal(GetModuleLogger(glue), IntPtr(0)), &isNullPtr, &slowPath);
12505 Bind(&isNullPtr);
12506 BRANCH(IsNativeModule(requiredModule), &isNativeModule, ¬NativeModule);
12507 Bind(&isNativeModule);
12508 {
12509 GateRef dictionary = GetNameDictionary(glue, requiredModule);
12510 BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &slowPath, &dictionaryNotUndefined);
12511 Bind(&dictionaryNotUndefined);
12512 result = GetValueFromTaggedArray(glue, dictionary, Int32(0));
12513 Jump(&exit);
12514 }
12515 Bind(¬NativeModule);
12516 BRANCH(IsCjsModule(requiredModule), &isCjsModule, ¬CjsModule);
12517 Bind(&isCjsModule);
12518 {
12519 // CommonJS module involves CString, jump to slowPath here
12520 Jump(&slowPath);
12521 }
12522 Bind(¬CjsModule);
12523 {
12524 // requiredModule is ESM
12525 GateRef moduleNamespace = GetNamespaceFromSourceTextModule(glue, requiredModule);
12526 BRANCH_UNLIKELY(TaggedIsUndefined(moduleNamespace), &slowPath, &namespaceNotUndefined);
12527 Bind(&namespaceNotUndefined);
12528 result = moduleNamespace;
12529 Jump(&exit);
12530 }
12531 }
12532 Bind(&slowPath);
12533 {
12534 result = CallRuntime(glue, RTSTUB_ID(GetModuleNamespaceByIndex), { IntToTaggedInt(index) });
12535 Jump(&exit);
12536 }
12537 Bind(&exit);
12538 auto ret = *result;
12539 env->SubCfgExit();
12540 return ret;
12541 }
12542
12543 // Used for jit machine code reusing of inner functions have the same method to improve performance.
TryToJitReuseCompiledFunc(GateRef glue,GateRef jsFunc,GateRef profileTypeInfoCell)12544 void StubBuilder::TryToJitReuseCompiledFunc(GateRef glue, GateRef jsFunc, GateRef profileTypeInfoCell)
12545 {
12546 Label subEntry(env_);
12547 env_->SubCfgEntry(&subEntry);
12548
12549 Label machineCodeIsNotHole(env_);
12550 Label exitPoint(env_);
12551 Label hasNotDisable(env_);
12552 GateRef weakMachineCode = Load(VariableType::JS_ANY(), glue, profileTypeInfoCell,
12553 IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET));
12554 BRANCH(TaggedIsHole(weakMachineCode), &exitPoint, &machineCodeIsNotHole);
12555 Bind(&machineCodeIsNotHole);
12556 {
12557 Label hasProfileTypeInfo(env_);
12558 GateRef profileTypeInfo = Load(VariableType::JS_ANY(), glue, profileTypeInfoCell,
12559 IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
12560 BRANCH(TaggedIsUndefined(profileTypeInfo), &exitPoint, &hasProfileTypeInfo);
12561 Bind(&hasProfileTypeInfo);
12562 {
12563 GateRef jitHotnessThreshold = ProfilerStubBuilder(env_).GetJitHotnessThreshold(profileTypeInfo);
12564 BRANCH(Int32Equal(jitHotnessThreshold, Int32(ProfileTypeInfo::JIT_DISABLE_FLAG)), &exitPoint, &hasNotDisable);
12565 Bind(&hasNotDisable);
12566 {
12567 Label machineCodeIsUndefine(env_);
12568 Label machineCodeIsNotUndefine(env_);
12569 BRANCH(TaggedIsUndefined(weakMachineCode), &machineCodeIsUndefine, &machineCodeIsNotUndefine);
12570 Bind(&machineCodeIsUndefine);
12571 {
12572 ProfilerStubBuilder(env_).SetJitHotnessCnt(glue, profileTypeInfo, Int16(0));
12573 Store(VariableType::JS_POINTER(), glue, profileTypeInfoCell,
12574 IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET), Hole());
12575 Jump(&exitPoint);
12576 }
12577 Bind(&machineCodeIsNotUndefine);
12578 {
12579 GateRef machineCode = TaggedCastToIntPtr(RemoveTaggedWeakTag(weakMachineCode));
12580 GateRef codeAddr = Load(VariableType::NATIVE_POINTER(), glue, machineCode,
12581 IntPtr(MachineCode::FUNCADDR_OFFSET));
12582 ASSERT(IntPtrNotEqual(codeAddr, IntPtr(0)));
12583 GateRef isFastCall = GetIsFastCall(machineCode);
12584 SetCompiledFuncEntry(glue, jsFunc, codeAddr, ZExtInt1ToInt32(isFastCall));
12585 SetMachineCodeToFunction(glue, jsFunc, machineCode);
12586 Jump(&exitPoint);
12587 }
12588 }
12589 }
12590 }
12591 Bind(&exitPoint);
12592 env_->SubCfgExit();
12593 }
12594
GetArgumentsElements(GateRef glue,GateRef argvTaggedArray,GateRef argv)12595 GateRef StubBuilder::GetArgumentsElements(GateRef glue, GateRef argvTaggedArray, GateRef argv)
12596 {
12597 auto env = GetEnvironment();
12598 Label entry(env);
12599 env->SubCfgEntry(&entry);
12600 Label exit(env);
12601 DEFVARIABLE(result, VariableType::NATIVE_POINTER(), NullPtr());
12602 DEFVARIABLE(argvVar, VariableType::NATIVE_POINTER(), argv);
12603
12604 Label calcArgv(env);
12605 Label hasArgv(env);
12606 Label argvTaggedArrayUndef(env);
12607 Label argvTaggedArrayDef(env);
12608
12609 BRANCH(TaggedIsUndefined(argvTaggedArray), &argvTaggedArrayUndef, &argvTaggedArrayDef);
12610 Bind(&argvTaggedArrayUndef);
12611
12612 BRANCH(Equal(*argvVar, IntPtr(0)), &calcArgv, &hasArgv);
12613 Bind(&calcArgv);
12614 argvVar = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
12615 Jump(&hasArgv);
12616
12617 Bind(&argvTaggedArrayDef);
12618 argvVar = PtrAdd(TaggedCastToIntPtr(argvTaggedArray), IntPtr(TaggedArray::DATA_OFFSET));
12619 Jump(&hasArgv);
12620
12621 Bind(&hasArgv);
12622 result = PtrAdd(*argvVar, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
12623 Jump(&exit);
12624 Bind(&exit);
12625 auto ret = *result;
12626 env->SubCfgExit();
12627 return ret;
12628 }
12629
ComputeTaggedArrayElementKind(GateRef glue,GateRef array,GateRef offset,GateRef end)12630 GateRef StubBuilder::ComputeTaggedArrayElementKind(GateRef glue, GateRef array, GateRef offset, GateRef end)
12631 {
12632 auto env = GetEnvironment();
12633 Label entry(env);
12634 env->SubCfgEntry(&entry);
12635 Label exit(env);
12636 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
12637 GateRef elements = GetElementsArray(glue, array);
12638 GateRef kind = GetElementsKindFromHClass(LoadHClass(glue, array));
12639 Label fastCompute(env);
12640 Label slowCompute(env);
12641 GateRef checkType = LogicOrBuilder(env)
12642 .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::NONE))))
12643 .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::INT))))
12644 .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::STRING))))
12645 .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::OBJECT))))
12646 .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::HOLE))))
12647 .Done();
12648 BRANCH(checkType, &fastCompute, &slowCompute);
12649 Bind(&fastCompute);
12650 {
12651 result = kind;
12652 Jump(&exit);
12653 }
12654 Bind(&slowCompute);
12655 Label loopHead(env);
12656 Label loopEnd(env);
12657 Label doLoop(env);
12658 Label loopExit(env);
12659 DEFVARIABLE(i, VariableType::INT64(), offset);
12660 GateRef generic = Int32(Elements::ToUint(ElementsKind::GENERIC));
12661 Jump(&loopHead);
12662 LoopBegin(&loopHead);
12663 {
12664 GateRef checkType2 = BitAnd(Int64LessThan(*i, end), Int32LessThan(*result, generic));
12665 BRANCH(checkType2, &doLoop, &loopExit);
12666 Bind(&doLoop);
12667 GateRef value = GetValueFromTaggedArray(glue, elements, *i);
12668 result = Int32Or(TaggedToElementKind(glue, value), *result);
12669 i = Int64Add(*i, Int64(1));
12670 Jump(&loopEnd);
12671 }
12672 Bind(&loopEnd);
12673 LoopEnd(&loopHead);
12674 Bind(&loopExit);
12675 Jump(&exit);
12676 Bind(&exit);
12677 auto ret = *result;
12678 env->SubCfgExit();
12679 return ret;
12680 }
12681
GetElementsKindHClass(GateRef glue,GateRef elementKind)12682 GateRef StubBuilder::GetElementsKindHClass(GateRef glue, GateRef elementKind)
12683 {
12684 auto env = GetEnvironment();
12685 GateRef offset = PtrMul(ZExtInt32ToPtr(elementKind), IntPtr(sizeof(ElementsHClassEntries::Entry)));
12686 GateRef arrayHClassIndexesOff = IntPtr(JSThread::GlueData::GetArrayHClassIndexesIndexOffset(env->Is32Bit()));
12687 GateRef arrayIndexes = PtrAdd(glue, arrayHClassIndexesOff);
12688 GateRef elementIdx = LoadPrimitive(VariableType::INT16(), arrayIndexes, offset);
12689 GateRef currentEnv = GetCurrentGlobalEnv();
12690 GateRef elementOffset = PtrAdd(IntPtr(GlobalEnv::HEADER_SIZE),
12691 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), ZExtInt16ToPtr(elementIdx)));
12692 return Load(VariableType::JS_ANY(), glue, currentEnv, elementOffset);
12693 }
12694
NeedBarrier(GateRef kind)12695 GateRef StubBuilder::NeedBarrier(GateRef kind){
12696 auto env = GetEnvironment();
12697 Label entry(env);
12698 env->SubCfgEntry(&entry);
12699 DEFVARIABLE(result, VariableType::BOOL(), True());
12700 GateRef isInt = LogicAndBuilder(env)
12701 .And(Int32GreaterThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::INT))))
12702 .And(Int32LessThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::HOLE_INT))))
12703 .Done();
12704 GateRef isNumber = LogicAndBuilder(env)
12705 .And(Int32GreaterThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::NUMBER))))
12706 .And(Int32LessThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER))))
12707 .Done();
12708 GateRef check = LogicOrBuilder(env).Or(isInt).Or(isNumber)
12709 .Or(Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::HOLE)))).Done();
12710 result = BoolNot(check);
12711 auto ret = *result;
12712 env->SubCfgExit();
12713 return ret;
12714 }
12715
StartTraceLoadValueDetail(GateRef glue,GateRef receiver,GateRef profileTypeInfo,GateRef slotId,GateRef key)12716 void StubBuilder::StartTraceLoadValueDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef receiver,
12717 [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId, [[maybe_unused]] GateRef key)
12718 {
12719 #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE
12720 CallRuntime(glue, RTSTUB_ID(TraceLoadValueDetail), {receiver, profileTypeInfo, slotId, key});
12721 #endif
12722 }
12723
12724
StartTraceLoadValueSlowPath(GateRef glue)12725 void StubBuilder::StartTraceLoadValueSlowPath([[maybe_unused]]GateRef glue)
12726 {
12727 #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE
12728 CallRuntime(glue, RTSTUB_ID(TraceLoadValueSlowPath), {});
12729 #endif
12730 }
12731
EndTraceLoadValue(GateRef glue)12732 void StubBuilder::EndTraceLoadValue([[maybe_unused]]GateRef glue)
12733 {
12734 #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE
12735 CallRuntime(glue, RTSTUB_ID(TraceLoadValueEnd), {});
12736 #endif
12737 }
12738
StartTraceCallDetail(GateRef glue,GateRef profileTypeInfo,GateRef slotId)12739 void StubBuilder::StartTraceCallDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef profileTypeInfo,
12740 [[maybe_unused]] GateRef slotId)
12741 {
12742 #if ECMASCRIPT_ENABLE_TRACE_CALL
12743 CallRuntime(glue, RTSTUB_ID(TraceCallDetail), {profileTypeInfo, slotId});
12744 #endif
12745 }
12746
EndTraceCall(GateRef glue)12747 void StubBuilder::EndTraceCall([[maybe_unused]] GateRef glue)
12748 {
12749 #if ECMASCRIPT_ENABLE_TRACE_CALL
12750 CallRuntime(glue, RTSTUB_ID(TraceLoadValueEnd), {});
12751 #endif
12752 }
12753
StartTraceLoadDetail(GateRef glue,GateRef receiver,GateRef profileTypeInfo,GateRef slotId)12754 void StubBuilder::StartTraceLoadDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef receiver,
12755 [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId)
12756 {
12757 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12758 CallRuntime(glue, RTSTUB_ID(TraceLoadDetail), {receiver, profileTypeInfo, slotId});
12759 #endif
12760 }
12761
StartTraceLoadGetter(GateRef glue)12762 void StubBuilder::StartTraceLoadGetter([[maybe_unused]]GateRef glue)
12763 {
12764 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12765 CallRuntime(glue, RTSTUB_ID(TraceLoadGetter), {});
12766 #endif
12767 }
12768
StartTraceLoadSlowPath(GateRef glue)12769 void StubBuilder::StartTraceLoadSlowPath([[maybe_unused]]GateRef glue)
12770 {
12771 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12772 CallRuntime(glue, RTSTUB_ID(TraceLoadSlowPath), {});
12773 #endif
12774 }
12775
EndTraceLoad(GateRef glue)12776 void StubBuilder::EndTraceLoad([[maybe_unused]]GateRef glue)
12777 {
12778 #if ECMASCRIPT_ENABLE_TRACE_LOAD
12779 CallRuntime(glue, RTSTUB_ID(TraceLoadEnd), {});
12780 #endif
12781 }
12782
StartTraceStoreDetail(GateRef glue,GateRef receiver,GateRef profileTypeInfo,GateRef slotId)12783 void StubBuilder::StartTraceStoreDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef receiver,
12784 [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId)
12785 {
12786 #if ECMASCRIPT_ENABLE_TRACE_STORE
12787 CallRuntime(glue, RTSTUB_ID(TraceStoreDetail), {receiver, profileTypeInfo, slotId});
12788 #endif
12789 }
12790
StartTraceStoreFastPath(GateRef glue)12791 void StubBuilder::StartTraceStoreFastPath([[maybe_unused]] GateRef glue)
12792 {
12793 #if ECMASCRIPT_ENABLE_TRACE_STORE
12794 CallRuntime(glue, RTSTUB_ID(TraceStoreFastPath), {});
12795 #endif
12796 }
12797
StartTraceStoreSlowPath(GateRef glue)12798 void StubBuilder::StartTraceStoreSlowPath([[maybe_unused]] GateRef glue)
12799 {
12800 #if ECMASCRIPT_ENABLE_TRACE_STORE
12801 CallRuntime(glue, RTSTUB_ID(TraceStoreSlowPath), {});
12802 #endif
12803 }
12804
EndTraceStore(GateRef glue)12805 void StubBuilder::EndTraceStore([[maybe_unused]] GateRef glue)
12806 {
12807 #if ECMASCRIPT_ENABLE_TRACE_STORE
12808 CallRuntime(glue, RTSTUB_ID(TraceStoreEnd), {});
12809 #endif
12810 }
12811
StartTraceDefineFunc(GateRef glue,GateRef methodId,GateRef profileTypeInfo,GateRef slotId)12812 void StubBuilder::StartTraceDefineFunc([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef methodId,
12813 [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId)
12814 {
12815 #if ECMASCRIPT_ENABLE_TRACE_DEFINEFUNC
12816 CallRuntime(glue, RTSTUB_ID(TraceDefineFunc), {methodId, profileTypeInfo, IntToTaggedInt(slotId)});
12817 #endif
12818 }
EndTraceDefineFunc(GateRef glue)12819 void StubBuilder::EndTraceDefineFunc([[maybe_unused]] GateRef glue)
12820 {
12821 #if ECMASCRIPT_ENABLE_TRACE_DEFINEFUNC
12822 CallRuntime(glue, RTSTUB_ID(TraceDefineFuncEnd), {});
12823 #endif
12824 }
12825
UpdateProfileTypeInfoAsMega(GateRef glue,GateRef profileTypeInfo,GateRef slotId)12826 void StubBuilder::UpdateProfileTypeInfoAsMega(GateRef glue, GateRef profileTypeInfo, GateRef slotId)
12827 {
12828 auto env = GetEnvironment();
12829 Label entry(env);
12830 env->SubCfgEntry(&entry);
12831 Label pgoOn(env);
12832 Label pgoOff(env);
12833 BRANCH(TaggedIsUndefined(profileTypeInfo), &pgoOff, &pgoOn);
12834 Bind(&pgoOn);
12835 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, Hole(), MemoryAttribute::NoBarrier());
12836 Jump(&pgoOff);
12837 Bind(&pgoOff);
12838 env->SubCfgExit();
12839 }
JSTaggedValueToString(GateRef glue,GateRef val,GateRef hir)12840 GateRef StubBuilder::JSTaggedValueToString(GateRef glue, GateRef val, GateRef hir)
12841 {
12842 auto env = GetEnvironment();
12843 Label entry(env);
12844 env->SubCfgEntry(&entry);
12845 DEFVARIABLE(value, VariableType::JS_ANY(), val);
12846 Label exit(env);
12847 Label notString(env);
12848 Label isSpecial(env);
12849 Label notSpecial(env);
12850 Label loopHead(env);
12851 Label loopEnd(env);
12852 Label loopExit(env);
12853 Jump(&loopHead);
12854 LoopBegin(&loopHead);
12855 {
12856 BRANCH(TaggedIsString(glue, *value), &exit, ¬String);
12857 Bind(¬String);
12858 {
12859 BRANCH(TaggedIsSpecial(*value), &isSpecial, ¬Special);
12860 Bind(&isSpecial);
12861 {
12862 value = SpecialToString(glue, *value);
12863 Jump(&exit);
12864 }
12865 Bind(¬Special);
12866 {
12867 Label numberBigIntPointer(env);
12868 Label notNumberBigIntPointer(env);
12869 GateRef checkValue = *value;
12870 GateRef checkType = LogicOrBuilder(env)
12871 .Or(TaggedIsNumber(checkValue))
12872 .Or(TaggedIsBigInt(glue, checkValue))
12873 .Or(TaggedIsNativePointer(glue, checkValue))
12874 .Done();
12875 BRANCH(checkType, &numberBigIntPointer, ¬NumberBigIntPointer);
12876 Bind(&numberBigIntPointer);
12877 {
12878 value = CallRuntime(glue, RTSTUB_ID(NumberBigIntNativePointerToString), { *value });
12879 Jump(&exit);
12880 }
12881 Bind(¬NumberBigIntPointer);
12882 {
12883 Label isEcmaObject1(env);
12884 Label notEcmaObject1(env);
12885 BRANCH(IsEcmaObject(glue, *value), &isEcmaObject1, ¬EcmaObject1);
12886 Bind(&isEcmaObject1);
12887 {
12888 value = ToPrimitive(glue, *value, PreferredPrimitiveType::PREFER_STRING, hir);
12889 Label hasException(env);
12890 BRANCH(HasPendingException(glue), &hasException, &loopEnd);
12891 Bind(&hasException);
12892 {
12893 value = GetGlobalConstantValue(VariableType::JS_POINTER(),
12894 glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
12895 Jump(&exit);
12896 }
12897 }
12898 Bind(¬EcmaObject1);
12899 {
12900 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertIllageValueToString));
12901 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
12902 value = GetGlobalConstantValue(VariableType::JS_POINTER(),
12903 glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
12904 Jump(&exit);
12905 }
12906 }
12907 }
12908 }
12909 }
12910 Bind(&loopEnd);
12911 LoopEnd(&loopHead);
12912 Bind(&exit);
12913 auto ret = *value;
12914 env->SubCfgExit();
12915 return ret;
12916 }
12917
SpecialToString(GateRef glue,GateRef specialVal)12918 GateRef StubBuilder::SpecialToString(GateRef glue, GateRef specialVal)
12919 {
12920 auto env = GetEnvironment();
12921 Label entry(env);
12922 Label exit(env);
12923 env->SubCfgEntry(&entry);
12924 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
12925 Label labelBuffer[5] = { Label(env), Label(env), Label(env), Label(env), Label(env) };
12926 Label defaultLabel(env);
12927 Switch(ChangeTaggedPointerToInt64(specialVal), &defaultLabel, SPECIAL_VALUE, labelBuffer, SPECIAL_VALUE_NUM);
12928 for (int i = 0; i < SPECIAL_VALUE_NUM; i++) {
12929 Bind(&labelBuffer[i]);
12930 value = GetGlobalConstantValue(VariableType::JS_ANY(), glue, SPECIAL_STRING_INDEX[i]);
12931 Jump(&exit);
12932 }
12933 Bind(&defaultLabel);
12934 {
12935 FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))});
12936 Jump(&exit);
12937 }
12938 Bind(&exit);
12939 auto ret = *value;
12940 env->SubCfgExit();
12941 return ret;
12942 }
12943
ToPrimitive(GateRef glue,GateRef value,PreferredPrimitiveType type,GateRef hir)12944 GateRef StubBuilder::ToPrimitive(GateRef glue, GateRef value, PreferredPrimitiveType type, GateRef hir)
12945 {
12946 auto env = GetEnvironment();
12947 Label entry(env);
12948 env->SubCfgEntry(&entry);
12949 Label isEcmaObject(env);
12950 Label exit(env);
12951 Label hasException(env);
12952 Label notHasException(env);
12953 Label notHasException1(env);
12954 Label notHasException2(env);
12955 DEFVARIABLE(result, VariableType::JS_ANY(), value);
12956 BRANCH(IsEcmaObject(glue, value), &isEcmaObject, &exit);
12957 Bind(&isEcmaObject);
12958 {
12959 Label isUndefined(env);
12960 Label notUndefined(env);
12961 GateRef globalEnv = GetCurrentGlobalEnv();
12962 GateRef primitiveKey = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
12963 GlobalEnv::TOPRIMITIVE_SYMBOL_INDEX);
12964 GateRef name = FastGetPropertyByName(glue, value, primitiveKey, ProfileOperation(), hir);
12965 BRANCH(HasPendingException(glue), &hasException, ¬HasException);
12966 Bind(¬HasException);
12967 GateRef exoticToprim = CallFunction(glue, name);
12968 BRANCH(HasPendingException(glue), &hasException, ¬HasException1);
12969 Bind(¬HasException1);
12970 BRANCH(TaggedIsUndefined(exoticToprim), &isUndefined, ¬Undefined);
12971 Bind(¬Undefined);
12972 {
12973 GateRef typeValue = GetPrimitiveTypeString(glue, type);
12974 DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Undefined());
12975 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG2_WITH_RETURN);
12976 callArgs.callThisArg2WithReturnArgs = {value, typeValue, Undefined()};
12977 CallStubBuilder callBuilder(this, glue, exoticToprim, Int32(2), 0, &tmpResult, Circuit::NullGate(),
12978 callArgs, ProfileOperation(), true, hir);
12979 Label callExit(env);
12980 if (env->IsBaselineBuiltin()) {
12981 callBuilder.JSCallDispatchForBaseline(&callExit);
12982 Bind(&callExit);
12983 } else {
12984 tmpResult = callBuilder.JSCallDispatch();
12985 }
12986 BRANCH(HasPendingException(glue), &hasException, ¬HasException2);
12987 Bind(¬HasException2);
12988 Label isEcmaObject1(env);
12989 Label notEcmaObject1(env);
12990 BRANCH(IsEcmaObject(glue, *tmpResult), &isEcmaObject1, ¬EcmaObject1);
12991 Bind(&isEcmaObject1);
12992 {
12993 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertObjectToPrimitiveValue));
12994 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
12995 Jump(&hasException);
12996 }
12997 Bind(¬EcmaObject1);
12998 {
12999 result = *tmpResult;
13000 Jump(&exit);
13001 }
13002 }
13003 Bind(&isUndefined);
13004 {
13005 Label numberPreference(env);
13006 Label defaultPreference(env);
13007 BRANCH(Int32Equal(Int32(static_cast<uint8_t>(type)),
13008 Int32(static_cast<uint8_t>(PreferredPrimitiveType::NO_PREFERENCE))),
13009 &numberPreference, &defaultPreference);
13010 Bind(&numberPreference);
13011 {
13012 result = OrdinaryToPrimitive(glue, value, PreferredPrimitiveType::PREFER_NUMBER, hir);
13013 Jump(&exit);
13014 }
13015 Bind(&defaultPreference);
13016 {
13017 result = OrdinaryToPrimitive(glue, value, type, hir);
13018 Jump(&exit);
13019 }
13020 }
13021 }
13022 Bind(&hasException);
13023 {
13024 result = Exception();
13025 Jump(&exit);
13026 }
13027 Bind(&exit);
13028 auto ret = *result;
13029 env->SubCfgExit();
13030 return ret;
13031 }
13032
GetPrimitiveTypeString(GateRef glue,PreferredPrimitiveType type)13033 GateRef StubBuilder::GetPrimitiveTypeString(GateRef glue, PreferredPrimitiveType type)
13034 {
13035 auto env = GetEnvironment();
13036 Label entry(env);
13037 env->SubCfgEntry(&entry);
13038 DEFVARIABLE(typeValue, VariableType::JS_ANY(),
13039 GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13040 ConstantIndex::STRING_STRING_INDEX));
13041 Label labelBuffer[2] = {Label(env), Label(env)};
13042 Label labelDefault(env);
13043 int64_t valueBuffer[2] = {
13044 static_cast<int64_t>(PreferredPrimitiveType::NO_PREFERENCE),
13045 static_cast<int64_t>(PreferredPrimitiveType::PREFER_NUMBER),
13046 };
13047 Switch(Int64(static_cast<int64_t>(type)), &labelDefault, valueBuffer, labelBuffer, 2);
13048 Bind(&labelBuffer[0]);
13049 {
13050 typeValue = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13051 ConstantIndex::DEFAULT_INDEX);
13052 Jump(&labelDefault);
13053 }
13054 Bind(&labelBuffer[1]);
13055 {
13056 typeValue = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13057 ConstantIndex::NUMBER_STRING_INDEX);
13058 Jump(&labelDefault);
13059 }
13060 Bind(&labelDefault);
13061 auto ret = *typeValue;
13062 env->SubCfgExit();
13063 return ret;
13064 }
13065
OrdinaryToPrimitive(GateRef glue,GateRef value,PreferredPrimitiveType type,GateRef hir)13066 GateRef StubBuilder::OrdinaryToPrimitive(GateRef glue, GateRef value, PreferredPrimitiveType type, GateRef hir)
13067 {
13068 auto env = GetEnvironment();
13069 Label entry(env);
13070 env->SubCfgEntry(&entry);
13071 Label isEcmaObject(env);
13072 Label exit(env);
13073 Label hasException(env);
13074 Label notHasException1(env);
13075 Label notHasException2(env);
13076 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
13077 BRANCH(IsEcmaObject(glue, value), &isEcmaObject, &exit);
13078 Bind(&isEcmaObject);
13079 DEFVARIABLE(valType, VariableType::INT32(), Int32(static_cast<uint8_t>(type)));
13080 GateRef numberInt32 = Int32(static_cast<uint8_t>(PreferredPrimitiveType::PREFER_NUMBER));
13081 GateRef stringInt32 = Int32(static_cast<uint8_t>(PreferredPrimitiveType::PREFER_STRING));
13082 GateRef len = Int32(2);
13083 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
13084 Label loopHead(env);
13085 Label loopEnd(env);
13086 Label next(env);
13087 Label loopExit(env);
13088 Jump(&loopHead);
13089 LoopBegin(&loopHead);
13090 {
13091 DEFVARIABLE(keyString, VariableType::JS_ANY(), Undefined());
13092 BRANCH(Int32LessThan(*i, len), &next, &loopExit);
13093 Bind(&next);
13094 Label toString(env);
13095 Label valueOf(env);
13096 Label checkExit(env);
13097 BRANCH(Int32Equal(*valType, stringInt32), &toString, &valueOf);
13098 Bind(&toString);
13099 {
13100 keyString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13101 ConstantIndex::TO_STRING_STRING_INDEX);
13102 valType = numberInt32;
13103 Jump(&checkExit);
13104 }
13105 Bind(&valueOf);
13106 {
13107 keyString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
13108 ConstantIndex::VALUE_OF_STRING_INDEX);
13109 valType = stringInt32;
13110 Jump(&checkExit);
13111 }
13112 Bind(&checkExit);
13113 GateRef entryfunc = FastGetPropertyByName(glue, value, *keyString, ProfileOperation(), hir);
13114 BRANCH(HasPendingException(glue), &hasException, ¬HasException1);
13115 Bind(¬HasException1);
13116 Label isCallable1(env);
13117 BRANCH(TaggedIsCallable(glue, entryfunc), &isCallable1, &loopEnd);
13118 Bind(&isCallable1);
13119 {
13120 DEFVARIABLE(tmpResult, VariableType::JS_ANY(), Undefined());
13121 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG2_WITH_RETURN);
13122 callArgs.callThisArg2WithReturnArgs = { value, Undefined(), Undefined() };
13123 CallStubBuilder callBuilder(this, glue, entryfunc, Int32(2), 0, &tmpResult, Circuit::NullGate(),
13124 callArgs, ProfileOperation(), true, hir);
13125 Label callExit(env);
13126 if (env->IsBaselineBuiltin()) {
13127 callBuilder.JSCallDispatchForBaseline(&callExit);
13128 Bind(&callExit);
13129 } else {
13130 tmpResult = callBuilder.JSCallDispatch();
13131 }
13132 BRANCH(HasPendingException(glue), &hasException, ¬HasException2);
13133 Bind(¬HasException2);
13134 Label notEcmaObject1(env);
13135 BRANCH(IsEcmaObject(glue, *tmpResult), &loopEnd, ¬EcmaObject1);
13136 Bind(¬EcmaObject1);
13137 {
13138 result = *tmpResult;
13139 Jump(&exit);
13140 }
13141 }
13142 }
13143 Bind(&loopEnd);
13144 i = Int32Add(*i, Int32(1));
13145 LoopEnd(&loopHead);
13146 Bind(&loopExit);
13147 {
13148 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertIllageValueToPrimitive));
13149 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
13150 result = Undefined();
13151 Jump(&exit);
13152 }
13153 Bind(&hasException);
13154 {
13155 result = Exception();
13156 Jump(&exit);
13157 }
13158 Bind(&exit);
13159 auto ret = *result;
13160 env->SubCfgExit();
13161 return ret;
13162 }
13163
CallFunction(GateRef glue,GateRef func)13164 GateRef StubBuilder::CallFunction(GateRef glue, GateRef func)
13165 {
13166 auto env = GetEnvironment();
13167 Label entry(env);
13168 env->SubCfgEntry(&entry);
13169 Label exit(env);
13170 Label undefinedOrNull(env);
13171 Label notUndefinedAndNull(env);
13172 Label notCallable(env);
13173 DEFVARIABLE(result, VariableType::JS_ANY(), func);
13174 BRANCH(TaggedIsUndefinedOrNull(func), &undefinedOrNull, ¬UndefinedAndNull);
13175 Bind(&undefinedOrNull);
13176 {
13177 result = Undefined();
13178 Jump(&exit);
13179 }
13180 Bind(¬UndefinedAndNull);
13181 BRANCH(TaggedIsCallable(glue, func), &exit, ¬Callable);
13182 Bind(¬Callable);
13183 {
13184 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable));
13185 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
13186 Jump(&exit);
13187 }
13188 Bind(&exit);
13189 auto ret = *result;
13190 env->SubCfgExit();
13191 return ret;
13192 }
13193
ArrayCopy(GateRef glue,GateRef srcObj,GateRef srcAddr,GateRef dstObj,GateRef dstAddr,GateRef taggedValueCount,GateRef needBarrier,CopyKind copyKind)13194 void StubBuilder::ArrayCopy(GateRef glue, GateRef srcObj, GateRef srcAddr, GateRef dstObj,
13195 GateRef dstAddr, GateRef taggedValueCount, GateRef needBarrier,
13196 CopyKind copyKind)
13197 {
13198 auto env = GetEnvironment();
13199 Label entry(env);
13200 env->SubCfgEntry(&entry);
13201 Label exit(env);
13202 Label isEnableCMCGC(env);
13203 Label notCMCGC(env);
13204 BRANCH_UNLIKELY(LoadPrimitive(
13205 VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
13206 &isEnableCMCGC, ¬CMCGC);
13207
13208 Bind(&isEnableCMCGC);
13209 {
13210 CallNGCRuntime(glue, RTSTUB_ID(CopyObjectPrimitive),
13211 {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(srcAddr), taggedValueCount});
13212 Label handleBarrier(env);
13213 BRANCH_NO_WEIGHT(needBarrier, &handleBarrier, &exit);
13214 Bind(&handleBarrier);
13215 {
13216 if (copyKind == SameArray) {
13217 CMCArrayCopyWriteBarrierSameArray(glue, dstObj, srcAddr, dstAddr, taggedValueCount);
13218 } else {
13219 CMCArrayCopyWriteBarrier(glue, dstObj, srcAddr, dstAddr, taggedValueCount);
13220 }
13221 Jump(&exit);
13222 }
13223 }
13224 Bind(¬CMCGC);
13225 {
13226 CallNGCRuntime(glue, RTSTUB_ID(ObjectCopy),
13227 {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(srcAddr), taggedValueCount});
13228 Label handleBarrier(env);
13229 BRANCH_NO_WEIGHT(needBarrier, &handleBarrier, &exit);
13230 Bind(&handleBarrier);
13231 {
13232 if (copyKind == SameArray) {
13233 CallCommonStub(glue, CommonStubCSigns::MoveBarrierInRegion,
13234 {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), taggedValueCount,
13235 TaggedCastToIntPtr(srcAddr)});
13236 } else {
13237 ASSERT(copyKind == DifferentArray);
13238 CallCommonStub(glue, CommonStubCSigns::MoveBarrierCrossRegion,
13239 {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), taggedValueCount,
13240 TaggedCastToIntPtr(srcAddr), TaggedCastToIntPtr(srcObj)});
13241 }
13242 Jump(&exit);
13243 }
13244 }
13245 Bind(&exit);
13246 env->SubCfgExit();
13247 }
13248
ArrayCopyAndHoleToUndefined(GateRef glue,GateRef srcObj,GateRef srcAddr,GateRef dstObj,GateRef dstAddr,GateRef length,GateRef needBarrier)13249 void StubBuilder::ArrayCopyAndHoleToUndefined(GateRef glue, GateRef srcObj, GateRef srcAddr, GateRef dstObj,
13250 GateRef dstAddr, GateRef length, GateRef needBarrier)
13251 {
13252 auto env = GetEnvironment();
13253 Label entry(env);
13254 env->SubCfgEntry(&entry);
13255 Label loopExit(env);
13256 Label exit(env);
13257 Label begin(env);
13258 Label body(env);
13259 Label handleBarrier(env);
13260 Label endLoop(env);
13261 GateRef dstOff = PtrSub(TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(dstObj));
13262 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
13263 Jump(&begin);
13264 LoopBegin(&begin);
13265 {
13266 BRANCH_LIKELY(Int32UnsignedLessThan(*index, length), &body, &loopExit);
13267 Bind(&body);
13268 {
13269 GateRef offset = PtrMul(ZExtInt32ToPtr(*index), IntPtr(JSTaggedValue::TaggedTypeSize()));
13270 GateRef value = Load(VariableType::JS_ANY(), glue, srcAddr, offset);
13271
13272 Label isHole(env);
13273 Label isNotHole(env);
13274 BRANCH_UNLIKELY(TaggedIsHole(value), &isHole, &isNotHole);
13275 Bind(&isHole);
13276 {
13277 Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, offset), Undefined(),
13278 MemoryAttribute::NoBarrier());
13279 Jump(&endLoop);
13280 }
13281 Bind(&isNotHole);
13282 Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, offset), value, MemoryAttribute::NoBarrier());
13283 Jump(&endLoop);
13284 }
13285 }
13286 Bind(&endLoop);
13287 index = Int32Add(*index, Int32(1));
13288 LoopEnd(&begin);
13289 Bind(&loopExit);
13290 Label checkNext(env);
13291 BRANCH_NO_WEIGHT(needBarrier, &checkNext, &exit);
13292 Bind(&checkNext);
13293 BRANCH_UNLIKELY(LoadPrimitive(
13294 VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
13295 &exit, &handleBarrier);
13296 Bind(&handleBarrier);
13297 {
13298 CallCommonStub(glue, CommonStubCSigns::MoveBarrierCrossRegion,
13299 {glue, TaggedCastToIntPtr(dstObj), TaggedCastToIntPtr(dstAddr), length,
13300 TaggedCastToIntPtr(srcAddr), TaggedCastToIntPtr(srcObj)});
13301
13302 Jump(&exit);
13303 }
13304 Bind(&exit);
13305 env->SubCfgExit();
13306 }
13307
Int64BitReverse(GateRef x)13308 GateRef StubBuilder::Int64BitReverse(GateRef x)
13309 {
13310 return env_->GetBuilder()->Int64Rev(x);
13311 }
13312
Int32BitReverse(GateRef x)13313 GateRef StubBuilder::Int32BitReverse(GateRef x)
13314 {
13315 return env_->GetBuilder()->Int32Rev(x);
13316 }
13317
Int16BitReverse(GateRef x)13318 GateRef StubBuilder::Int16BitReverse(GateRef x)
13319 {
13320 return env_->GetBuilder()->Int16Rev(x);
13321 }
13322
Int8BitReverse(GateRef x)13323 GateRef StubBuilder::Int8BitReverse(GateRef x)
13324 {
13325 return env_->GetBuilder()->Int8Rev(x);
13326 }
13327
13328 int64_t StubBuilder::SPECIAL_VALUE[SPECIAL_VALUE_NUM] = {
13329 static_cast<int64_t>(JSTaggedValue::VALUE_UNDEFINED),
13330 static_cast<int64_t>(JSTaggedValue::VALUE_NULL),
13331 static_cast<int64_t>(JSTaggedValue::VALUE_TRUE),
13332 static_cast<int64_t>(JSTaggedValue::VALUE_FALSE),
13333 static_cast<int64_t>(JSTaggedValue::VALUE_HOLE)
13334 };
13335
13336 ConstantIndex StubBuilder::SPECIAL_STRING_INDEX[SPECIAL_VALUE_NUM] = {
13337 ConstantIndex::UNDEFINED_STRING_INDEX,
13338 ConstantIndex::NULL_STRING_INDEX,
13339 ConstantIndex::TRUE_STRING_INDEX,
13340 ConstantIndex::FALSE_STRING_INDEX,
13341 ConstantIndex::EMPTY_STRING_OBJECT_INDEX
13342 };
13343
13344
ThreeInt64Min(GateRef first,GateRef second,GateRef third)13345 GateRef StubBuilder::ThreeInt64Min(GateRef first, GateRef second, GateRef third)
13346 {
13347 return env_->GetBuilder()->ThreeInt64Min(first, second, third);
13348 }
13349
GetCurrentGlobalEnv(GateRef glue,GateRef currentEnv)13350 GateRef StubBuilder::GetCurrentGlobalEnv(GateRef glue, GateRef currentEnv)
13351 {
13352 auto env0 = GetEnvironment();
13353 {
13354 ASM_ASSERT(GET_MESSAGE_STRING_ID(CurrentEnvIsInvalid),
13355 LogicAndBuilder(env0).And(TaggedIsHeapObject(currentEnv))
13356 .And(LogicOrBuilder(env0).Or(IsGlobalEnv(glue, currentEnv))
13357 .Or(IsLexicalEnv(glue, currentEnv))
13358 .Or(IsSFunctionEnv(glue, currentEnv)).Done())
13359 .Done());
13360 }
13361 Label entry(env0);
13362 env0->SubCfgEntry(&entry);
13363 Label fromGlue(env0);
13364 Label exit(env0);
13365 DEFVARIABLE(globalEnv, VariableType::JS_ANY(), Undefined());
13366
13367 globalEnv = GetValueFromTaggedArray(glue, currentEnv, Int32(BaseEnv::GLOBAL_ENV_INDEX));
13368 BRANCH_UNLIKELY(TaggedIsHole(*globalEnv), &fromGlue, &exit);
13369 Bind(&fromGlue);
13370 {
13371 globalEnv = GetGlobalEnv(glue);
13372 Jump(&exit);
13373 }
13374 Bind(&exit);
13375 auto ret = *globalEnv;
13376 env0->SubCfgExit();
13377 return ret;
13378 }
13379 } // namespace panda::ecmascript::kungfu
13380