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