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
IsUtf16String(GateRef string)2107 GateRef StubBuilder::IsUtf16String(GateRef string)
2108 {
2109 // compressedStringsEnabled fixed to true constant
2110 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
2111 return Int32Equal(
2112 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
2113 Int32(EcmaString::STRING_UNCOMPRESSED));
2114 }
2115
IsUtf8String(GateRef string)2116 GateRef StubBuilder::IsUtf8String(GateRef string)
2117 {
2118 // compressedStringsEnabled fixed to true constant
2119 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
2120 return Int32Equal(
2121 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
2122 Int32(EcmaString::STRING_COMPRESSED));
2123 }
2124
IsInternalString(GateRef string)2125 GateRef StubBuilder::IsInternalString(GateRef string)
2126 {
2127 // compressedStringsEnabled fixed to true constant
2128 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
2129 return Int32NotEqual(
2130 Int32And(len, Int32(EcmaString::STRING_INTERN_BIT)),
2131 Int32(0));
2132 }
2133
IsDigit(GateRef ch)2134 GateRef StubBuilder::IsDigit(GateRef ch)
2135 {
2136 return BitAnd(Int32LessThanOrEqual(ch, Int32('9')),
2137 Int32GreaterThanOrEqual(ch, Int32('0')));
2138 }
2139
TryToGetInteger(GateRef string,Variable * num,Label * success,Label * failed)2140 void StubBuilder::TryToGetInteger(GateRef string, Variable *num, Label *success, Label *failed)
2141 {
2142 auto env = GetEnvironment();
2143 Label exit(env);
2144 Label inRange(env);
2145 Label isInteger(env);
2146
2147 GateRef len = GetLengthFromString(string);
2148 BRANCH(Int32LessThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &inRange, failed);
2149 Bind(&inRange);
2150 {
2151 BRANCH(IsIntegerString(string), &isInteger, failed);
2152 Bind(&isInteger);
2153 {
2154 GateRef integerNum = ZExtInt32ToInt64(GetRawHashFromString(string));
2155 num->WriteVariable(integerNum);
2156 Jump(success);
2157 }
2158 }
2159 }
2160
StringToElementIndex(GateRef glue,GateRef string)2161 GateRef StubBuilder::StringToElementIndex(GateRef glue, GateRef string)
2162 {
2163 auto env = GetEnvironment();
2164 Label entry(env);
2165 env->SubCfgEntry(&entry);
2166 Label exit(env);
2167 DEFVARIABLE(result, VariableType::INT64(), Int64(-1));
2168 Label greatThanZero(env);
2169 Label inRange(env);
2170 Label flattenFastPath(env);
2171 auto len = GetLengthFromString(string);
2172 BRANCH(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
2173 Bind(&greatThanZero);
2174 BRANCH(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
2175 Bind(&inRange);
2176 {
2177 Label isUtf8(env);
2178 GateRef isUtf16String = IsUtf16String(string);
2179 BRANCH(isUtf16String, &exit, &isUtf8);
2180 Bind(&isUtf8);
2181 {
2182 Label getFailed(env);
2183 TryToGetInteger(string, &result, &exit, &getFailed);
2184 Bind(&getFailed);
2185 DEFVARIABLE(c, VariableType::INT32(), Int32(0));
2186 FlatStringStubBuilder thisFlat(this);
2187 thisFlat.FlattenString(glue, string, &flattenFastPath);
2188 Bind(&flattenFastPath);
2189 StringInfoGateRef stringInfoGate(&thisFlat);
2190 GateRef dataUtf8 = GetNormalStringData(stringInfoGate);
2191 c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8));
2192 Label isDigitZero(env);
2193 Label notDigitZero(env);
2194 BRANCH(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero);
2195 Bind(&isDigitZero);
2196 {
2197 Label lengthIsOne(env);
2198 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
2199 Bind(&lengthIsOne);
2200 {
2201 result = Int64(0);
2202 Jump(&exit);
2203 }
2204 }
2205 Bind(¬DigitZero);
2206 {
2207 Label isDigit(env);
2208 DEFVARIABLE(i, VariableType::INT32(), Int32(1));
2209 DEFVARIABLE(n, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(*c), Int64('0')));
2210 BRANCH(IsDigit(*c), &isDigit, &exit);
2211 Label loopHead(env);
2212 Label loopEnd(env);
2213 Label afterLoop(env);
2214 Bind(&isDigit);
2215 BRANCH(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
2216 LoopBegin(&loopHead);
2217 {
2218 c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8, ZExtInt32ToPtr(*i)));
2219 Label isDigit2(env);
2220 Label notDigit2(env);
2221 BRANCH(IsDigit(*c), &isDigit2, ¬Digit2);
2222 Bind(&isDigit2);
2223 {
2224 // 10 means the base of digit is 10.
2225 n = Int64Add(Int64Mul(*n, Int64(10)), Int64Sub(ZExtInt32ToInt64(*c), Int64('0')));
2226 i = Int32Add(*i, Int32(1));
2227 BRANCH(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
2228 }
2229 Bind(¬Digit2);
2230 Jump(&exit);
2231 }
2232 Bind(&loopEnd);
2233 LoopEnd(&loopHead, env, glue);
2234 Bind(&afterLoop);
2235 {
2236 Label lessThanMaxIndex(env);
2237 BRANCH(Int64LessThan(*n, Int64(JSObject::MAX_ELEMENT_INDEX)),
2238 &lessThanMaxIndex, &exit);
2239 Bind(&lessThanMaxIndex);
2240 {
2241 result = *n;
2242 Jump(&exit);
2243 }
2244 }
2245 }
2246 }
2247 }
2248 Bind(&exit);
2249 auto ret = *result;
2250 env->SubCfgExit();
2251 return ret;
2252 }
2253
TryToElementsIndex(GateRef glue,GateRef key)2254 GateRef StubBuilder::TryToElementsIndex(GateRef glue, GateRef key)
2255 {
2256 auto env = GetEnvironment();
2257 Label entry(env);
2258 env->SubCfgEntry(&entry);
2259 Label exit(env);
2260 Label isKeyInt(env);
2261 Label notKeyInt(env);
2262
2263 DEFVARIABLE(resultKey, VariableType::INT64(), Int64(-1));
2264 BRANCH(TaggedIsInt(key), &isKeyInt, ¬KeyInt);
2265 Bind(&isKeyInt);
2266 {
2267 resultKey = GetInt64OfTInt(key);
2268 Jump(&exit);
2269 }
2270 Bind(¬KeyInt);
2271 {
2272 Label isString(env);
2273 Label notString(env);
2274 BRANCH(TaggedIsString(key), &isString, ¬String);
2275 Bind(&isString);
2276 {
2277 resultKey = StringToElementIndex(glue, key);
2278 Jump(&exit);
2279 }
2280 Bind(¬String);
2281 {
2282 Label isDouble(env);
2283 BRANCH(TaggedIsDouble(key), &isDouble, &exit);
2284 Bind(&isDouble);
2285 {
2286 GateRef number = GetDoubleOfTDouble(key);
2287 GateRef integer = ChangeFloat64ToInt32(number);
2288 Label isEqual(env);
2289 BRANCH(DoubleEqual(number, ChangeInt32ToFloat64(integer)), &isEqual, &exit);
2290 Bind(&isEqual);
2291 {
2292 resultKey = SExtInt32ToInt64(integer);
2293 Jump(&exit);
2294 }
2295 }
2296 }
2297 }
2298 Bind(&exit);
2299 auto ret = *resultKey;
2300 env->SubCfgExit();
2301 return ret;
2302 }
2303
LdGlobalRecord(GateRef glue,GateRef key)2304 GateRef StubBuilder::LdGlobalRecord(GateRef glue, GateRef key)
2305 {
2306 auto env = GetEnvironment();
2307 Label entry(env);
2308 env->SubCfgEntry(&entry);
2309 Label exit(env);
2310
2311 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2312 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2313 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2314 GateRef globalRecord = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::GLOBAL_RECORD);
2315 GateRef recordEntry = FindEntryFromNameDictionary(glue, globalRecord, key);
2316 Label foundInGlobalRecord(env);
2317 BRANCH(Int32NotEqual(recordEntry, Int32(-1)), &foundInGlobalRecord, &exit);
2318 Bind(&foundInGlobalRecord);
2319 {
2320 result = GetBoxFromGlobalDictionary(globalRecord, recordEntry);
2321 Jump(&exit);
2322 }
2323 Bind(&exit);
2324 auto ret = *result;
2325 env->SubCfgExit();
2326 return ret;
2327 }
2328
LoadFromField(GateRef receiver,GateRef handlerInfo)2329 GateRef StubBuilder::LoadFromField(GateRef receiver, GateRef handlerInfo)
2330 {
2331 auto env = GetEnvironment();
2332 Label entry(env);
2333 env->SubCfgEntry(&entry);
2334 Label exit(env);
2335 Label handlerInfoIsInlinedProps(env);
2336 Label handlerInfoNotInlinedProps(env);
2337 Label handlerPost(env);
2338 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2339 GateRef index = HandlerBaseGetOffset(handlerInfo);
2340 BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
2341 Bind(&handlerInfoIsInlinedProps);
2342 {
2343 result = Load(VariableType::JS_ANY(), receiver, PtrMul(ZExtInt32ToPtr(index),
2344 IntPtr(JSTaggedValue::TaggedTypeSize())));
2345 Jump(&handlerPost);
2346 }
2347 Bind(&handlerInfoNotInlinedProps);
2348 {
2349 result = GetValueFromTaggedArray(GetPropertiesArray(receiver), index);
2350 Jump(&handlerPost);
2351 }
2352 Bind(&handlerPost);
2353 {
2354 Label nonDoubleToTagged(env);
2355 Label doubleToTagged(env);
2356 GateRef rep = HandlerBaseGetRep(handlerInfo);
2357 BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged);
2358 Bind(&doubleToTagged);
2359 {
2360 result = TaggedPtrToTaggedDoublePtr(*result);
2361 Jump(&exit);
2362 }
2363 Bind(&nonDoubleToTagged);
2364 {
2365 Label intToTagged(env);
2366 BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit);
2367 Bind(&intToTagged);
2368 {
2369 result = TaggedPtrToTaggedIntPtr(*result);
2370 Jump(&exit);
2371 }
2372 }
2373 }
2374 Bind(&exit);
2375 auto ret = *result;
2376 env->SubCfgExit();
2377 return ret;
2378 }
2379
LoadGlobal(GateRef cell)2380 GateRef StubBuilder::LoadGlobal(GateRef cell)
2381 {
2382 auto env = GetEnvironment();
2383 Label entry(env);
2384 env->SubCfgEntry(&entry);
2385 Label exit(env);
2386 Label cellNotInvalid(env);
2387 Label cellNotAccessor(env);
2388 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2389 BRANCH(IsInvalidPropertyBox(cell), &exit, &cellNotInvalid);
2390 Bind(&cellNotInvalid);
2391 {
2392 BRANCH(IsAccessorPropertyBox(cell), &exit, &cellNotAccessor);
2393 Bind(&cellNotAccessor);
2394 {
2395 result = GetValueFromPropertyBox(cell);
2396 Jump(&exit);
2397 }
2398 }
2399 Bind(&exit);
2400 auto ret = *result;
2401 env->SubCfgExit();
2402 return ret;
2403 }
2404
CheckPolyHClass(GateRef cachedValue,GateRef hclass)2405 GateRef StubBuilder::CheckPolyHClass(GateRef cachedValue, GateRef hclass)
2406 {
2407 auto env = GetEnvironment();
2408 Label entry(env);
2409 env->SubCfgEntry(&entry);
2410 Label exit(env);
2411 Label loopHead(env);
2412 Label loopEnd(env);
2413 Label iLessLength(env);
2414 Label hasHclass(env);
2415 Label cachedValueNotWeak(env);
2416 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2417 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2418 BRANCH(TaggedIsWeak(cachedValue), &exit, &cachedValueNotWeak);
2419 Bind(&cachedValueNotWeak);
2420 {
2421 Label isTaggedArray(env);
2422 Branch(IsTaggedArray(cachedValue), &isTaggedArray, &exit);
2423 Bind(&isTaggedArray);
2424 {
2425 GateRef length = GetLengthOfTaggedArray(cachedValue);
2426 Jump(&loopHead);
2427 LoopBegin(&loopHead);
2428 {
2429 BRANCH(Int32UnsignedLessThan(*i, length), &iLessLength, &exit);
2430 Bind(&iLessLength);
2431 {
2432 GateRef element = GetValueFromTaggedArray(cachedValue, *i);
2433 BRANCH(Equal(LoadObjectFromWeakRef(element), hclass), &hasHclass, &loopEnd);
2434 Bind(&hasHclass);
2435 result = GetValueFromTaggedArray(cachedValue, Int32Add(*i, Int32(1)));
2436 Jump(&exit);
2437 }
2438 Bind(&loopEnd);
2439 i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot
2440 LoopEnd(&loopHead);
2441 }
2442 }
2443 }
2444 Bind(&exit);
2445 auto ret = *result;
2446 env->SubCfgExit();
2447 return ret;
2448 }
2449
LoadICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef argHandler,ProfileOperation callback)2450 GateRef StubBuilder::LoadICWithHandler(
2451 GateRef glue, GateRef receiver, GateRef argHolder, GateRef argHandler, ProfileOperation callback)
2452 {
2453 auto env = GetEnvironment();
2454 Label entry(env);
2455 env->SubCfgEntry(&entry);
2456 Label exit(env);
2457 Label handlerIsInt(env);
2458 Label handlerNotInt(env);
2459 Label handlerInfoIsField(env);
2460 Label handlerInfoNotField(env);
2461 Label handlerInfoIsNonExist(env);
2462 Label handlerInfoNotNonExist(env);
2463 Label handlerInfoIsPrimitive(env);
2464 Label handlerInfoNotPrimitive(env);
2465 Label handlerInfoIsStringLength(env);
2466 Label handlerInfoNotStringLength(env);
2467 Label handlerIsPrototypeHandler(env);
2468 Label handlerNotPrototypeHandler(env);
2469 Label cellHasChanged(env);
2470 Label cellNotUndefined(env);
2471 Label loopHead(env);
2472 Label loopEnd(env);
2473 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2474 DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
2475 DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
2476
2477 Jump(&loopHead);
2478 LoopBegin(&loopHead);
2479 {
2480 BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
2481 Bind(&handlerIsInt);
2482 {
2483 GateRef handlerInfo = GetInt64OfTInt(*handler);
2484 BRANCH(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2485 Bind(&handlerInfoIsField);
2486 {
2487 result = LoadFromField(*holder, handlerInfo);
2488 Jump(&exit);
2489 }
2490 Bind(&handlerInfoNotField);
2491 {
2492 BRANCH(BitOr(IsStringElement(handlerInfo), IsNumber(handlerInfo)),
2493 &handlerInfoIsPrimitive, &handlerInfoNotPrimitive);
2494 Bind(&handlerInfoIsPrimitive);
2495 {
2496 result = LoadFromField(*holder, handlerInfo);
2497 Jump(&exit);
2498 }
2499 Bind(&handlerInfoNotPrimitive);
2500 {
2501 BRANCH(IsNonExist(handlerInfo), &handlerInfoIsNonExist, &handlerInfoNotNonExist);
2502 Bind(&handlerInfoIsNonExist);
2503 Jump(&exit);
2504 Bind(&handlerInfoNotNonExist);
2505 {
2506 BRANCH(IsStringLength(handlerInfo), &handlerInfoIsStringLength, &handlerInfoNotStringLength);
2507 Bind(&handlerInfoNotStringLength);
2508 {
2509 GateRef accessor = LoadFromField(*holder, handlerInfo);
2510 result = CallGetterHelper(glue, receiver, *holder, accessor, callback);
2511 Jump(&exit);
2512 }
2513 Bind(&handlerInfoIsStringLength);
2514 {
2515 result = IntToTaggedPtr(GetLengthFromString(receiver));
2516 Jump(&exit);
2517 }
2518 }
2519 }
2520 }
2521 }
2522 Bind(&handlerNotInt);
2523 BRANCH(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
2524 Bind(&handlerIsPrototypeHandler);
2525 {
2526 GateRef cellValue = GetProtoCell(*handler);
2527 BRANCH(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
2528 Bind(&cellNotUndefined);
2529 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2530 Bind(&cellHasChanged);
2531 {
2532 result = Hole();
2533 Jump(&exit);
2534 }
2535 Bind(&loopEnd);
2536 holder = GetPrototypeHandlerHolder(*handler);
2537 handler = GetPrototypeHandlerHandlerInfo(*handler);
2538 LoopEnd(&loopHead, env, glue);
2539 }
2540 }
2541 Bind(&handlerNotPrototypeHandler);
2542 result = LoadGlobal(*handler);
2543 Jump(&exit);
2544
2545 Bind(&exit);
2546 auto ret = *result;
2547 env->SubCfgExit();
2548 return ret;
2549 }
2550
LoadElement(GateRef glue,GateRef receiver,GateRef key)2551 GateRef StubBuilder::LoadElement(GateRef glue, GateRef receiver, GateRef key)
2552 {
2553 auto env = GetEnvironment();
2554 Label entry(env);
2555 env->SubCfgEntry(&entry);
2556 Label exit(env);
2557 Label indexLessZero(env);
2558 Label indexNotLessZero(env);
2559 Label lengthLessIndex(env);
2560 Label lengthNotLessIndex(env);
2561 Label greaterThanInt32Max(env);
2562 Label notGreaterThanInt32Max(env);
2563 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2564 GateRef index64 = TryToElementsIndex(glue, key);
2565 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
2566 Bind(&greaterThanInt32Max);
2567 {
2568 Jump(&exit);
2569 }
2570 Bind(¬GreaterThanInt32Max);
2571 GateRef index = TruncInt64ToInt32(index64);
2572 BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2573 Bind(&indexLessZero);
2574 {
2575 Jump(&exit);
2576 }
2577 Bind(&indexNotLessZero);
2578 {
2579 GateRef elements = GetElementsArray(receiver);
2580 BRANCH(Int32LessThanOrEqual(GetLengthOfTaggedArray(elements), index), &lengthLessIndex, &lengthNotLessIndex);
2581 Bind(&lengthLessIndex);
2582 Jump(&exit);
2583 Bind(&lengthNotLessIndex);
2584 result = GetTaggedValueWithElementsKind(receiver, index);
2585 Jump(&exit);
2586 }
2587 Bind(&exit);
2588 auto ret = *result;
2589 env->SubCfgExit();
2590 return ret;
2591 }
2592
LoadStringElement(GateRef glue,GateRef receiver,GateRef key)2593 GateRef StubBuilder::LoadStringElement(GateRef glue, GateRef receiver, GateRef key)
2594 {
2595 auto env = GetEnvironment();
2596 Label entry(env);
2597 env->SubCfgEntry(&entry);
2598 Label exit(env);
2599 Label indexLessZero(env);
2600 Label indexNotLessZero(env);
2601 Label lengthLessIndex(env);
2602 Label lengthNotLessIndex(env);
2603 Label greaterThanInt32Max(env);
2604 Label notGreaterThanInt32Max(env);
2605 Label flattenFastPath(env);
2606
2607 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2608 GateRef index64 = TryToElementsIndex(glue, key);
2609 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
2610 Bind(&greaterThanInt32Max);
2611 {
2612 Jump(&exit);
2613 }
2614 Bind(¬GreaterThanInt32Max);
2615 GateRef index = TruncInt64ToInt32(index64);
2616 BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2617 Bind(&indexLessZero);
2618 {
2619 Jump(&exit);
2620 }
2621 Bind(&indexNotLessZero);
2622 {
2623 FlatStringStubBuilder thisFlat(this);
2624 thisFlat.FlattenString(glue, receiver, &flattenFastPath);
2625 Bind(&flattenFastPath);
2626 BRANCH(Int32LessThanOrEqual(GetLengthFromString(receiver), index), &lengthLessIndex, &lengthNotLessIndex);
2627 Bind(&lengthLessIndex);
2628 Jump(&exit);
2629 Bind(&lengthNotLessIndex);
2630 BuiltinsStringStubBuilder stringBuilder(this);
2631 StringInfoGateRef stringInfoGate(&thisFlat);
2632 result = stringBuilder.CreateFromEcmaString(glue, index, stringInfoGate);
2633 Jump(&exit);
2634 }
2635 Bind(&exit);
2636 auto ret = *result;
2637 env->SubCfgExit();
2638 return ret;
2639 }
2640
ICStoreElement(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef handler,bool updateHandler,GateRef profileTypeInfo,GateRef slotId)2641 GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef handler,
2642 bool updateHandler, GateRef profileTypeInfo, GateRef slotId)
2643 {
2644 auto env = GetEnvironment();
2645 Label entry(env);
2646 env->SubCfgEntry(&entry);
2647 Label exit(env);
2648 Label indexLessZero(env);
2649 Label indexNotLessZero(env);
2650 Label handlerInfoIsTypedArray(env);
2651 Label handerInfoNotTypedArray(env);
2652 Label handerInfoIsJSArray(env);
2653 Label handerInfoNotJSArray(env);
2654 Label isJsCOWArray(env);
2655 Label isNotJsCOWArray(env);
2656 Label setElementsLength(env);
2657 Label indexGreaterLength(env);
2658 Label indexGreaterCapacity(env);
2659 Label callRuntime(env);
2660 Label storeElement(env);
2661 Label handlerIsInt(env);
2662 Label handlerNotInt(env);
2663 Label cellHasChanged(env);
2664 Label cellHasNotChanged(env);
2665 Label loopHead(env);
2666 Label loopEnd(env);
2667 Label greaterThanInt32Max(env);
2668 Label notGreaterThanInt32Max(env);
2669 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2670 DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler);
2671 GateRef index64 = TryToElementsIndex(glue, key);
2672 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
2673 Bind(&greaterThanInt32Max);
2674 {
2675 Jump(&exit);
2676 }
2677 Bind(¬GreaterThanInt32Max);
2678 GateRef index = TruncInt64ToInt32(index64);
2679 BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
2680 Bind(&indexLessZero);
2681 {
2682 Jump(&exit);
2683 }
2684 Bind(&indexNotLessZero);
2685 {
2686 Jump(&loopHead);
2687 LoopBegin(&loopHead);
2688 BRANCH(TaggedIsInt(*varHandler), &handlerIsInt, &handlerNotInt);
2689 Bind(&handlerIsInt);
2690 {
2691 GateRef handlerInfo = GetInt64OfTInt(*varHandler);
2692 BRANCH(IsTypedArrayElement(handlerInfo), &handlerInfoIsTypedArray, &handerInfoNotTypedArray);
2693 Bind(&handlerInfoIsTypedArray);
2694 {
2695 GateRef hclass = LoadHClass(receiver);
2696 GateRef jsType = GetObjectType(hclass);
2697 BuiltinsTypedArrayStubBuilder typedArrayBuilder(this);
2698 result = typedArrayBuilder.StoreTypedArrayElement(glue, receiver, index64, value, jsType);
2699 Jump(&exit);
2700 }
2701 Bind(&handerInfoNotTypedArray);
2702 BRANCH(HandlerBaseIsJSArray(handlerInfo), &handerInfoIsJSArray, &handerInfoNotJSArray);
2703 Bind(&handerInfoIsJSArray);
2704 {
2705 BRANCH(IsJsCOWArray(receiver), &isJsCOWArray, &isNotJsCOWArray);
2706 Bind(&isJsCOWArray);
2707 {
2708 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {receiver});
2709 Jump(&setElementsLength);
2710 }
2711 Bind(&isNotJsCOWArray);
2712 {
2713 Jump(&setElementsLength);
2714 }
2715 Bind(&setElementsLength);
2716 {
2717 GateRef oldLength = GetArrayLength(receiver);
2718 BRANCH(Int32GreaterThanOrEqual(index, oldLength), &indexGreaterLength, &handerInfoNotJSArray);
2719 Bind(&indexGreaterLength);
2720 Store(VariableType::INT32(), glue, receiver,
2721 IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET),
2722 Int32Add(index, Int32(1)));
2723 if (updateHandler) {
2724 Label update(env);
2725 GateRef oldHandler = GetValueFromTaggedArray(profileTypeInfo, slotId);
2726 BRANCH(Equal(oldHandler, Hole()), &handerInfoNotJSArray, &update);
2727 Bind(&update);
2728 handler = Int64ToTaggedInt(UpdateSOutOfBoundsForHandler(handlerInfo));
2729 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, handler);
2730 }
2731 }
2732 Jump(&handerInfoNotJSArray);
2733 }
2734 Bind(&handerInfoNotJSArray);
2735 {
2736 GateRef elements = GetElementsArray(receiver);
2737 GateRef capacity = GetLengthOfTaggedArray(elements);
2738 BRANCH(Int32GreaterThanOrEqual(index, capacity), &callRuntime, &storeElement);
2739 Bind(&callRuntime);
2740 {
2741 result = CallRuntime(glue,
2742 RTSTUB_ID(TaggedArraySetValue),
2743 { receiver, value, elements, IntToTaggedInt(index),
2744 IntToTaggedInt(capacity) });
2745 Label transition(env);
2746 BRANCH(TaggedIsHole(*result), &exit, &transition);
2747 Bind(&transition);
2748 {
2749 Label hole(env);
2750 Label notHole(env);
2751 DEFVARIABLE(kind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::NONE)));
2752 BRANCH(Int32GreaterThan(index, capacity), &hole, ¬Hole);
2753 Bind(&hole);
2754 {
2755 kind = Int32(static_cast<int32_t>(ElementsKind::HOLE));
2756 Jump(¬Hole);
2757 }
2758 Bind(¬Hole);
2759 {
2760 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
2761 Jump(&exit);
2762 }
2763 }
2764 }
2765 Bind(&storeElement);
2766 {
2767 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true),
2768 Int32(static_cast<int32_t>(ElementsKind::NONE)));
2769 result = Undefined();
2770 Jump(&exit);
2771 }
2772 }
2773 }
2774 Bind(&handlerNotInt);
2775 {
2776 GateRef cellValue = GetProtoCell(*varHandler);
2777 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2778 Bind(&cellHasChanged);
2779 {
2780 Jump(&exit);
2781 }
2782 Bind(&loopEnd);
2783 {
2784 varHandler = GetPrototypeHandlerHandlerInfo(*varHandler);
2785 LoopEnd(&loopHead, env, glue);
2786 }
2787 }
2788 }
2789 Bind(&exit);
2790 auto ret = *result;
2791 env->SubCfgExit();
2792 return ret;
2793 }
2794
GetArrayLength(GateRef object)2795 GateRef StubBuilder::GetArrayLength(GateRef object)
2796 {
2797 GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
2798 GateRef result = Load(VariableType::INT32(), object, lengthOffset);
2799 return result;
2800 }
2801
SetArrayLength(GateRef glue,GateRef object,GateRef len)2802 void StubBuilder::SetArrayLength(GateRef glue, GateRef object, GateRef len)
2803 {
2804 GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
2805 Store(VariableType::INT32(), glue, object, lengthOffset, len);
2806 }
2807
StoreICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef value,GateRef argHandler,ProfileOperation callback)2808 GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder,
2809 GateRef value, GateRef argHandler, ProfileOperation callback)
2810 {
2811 auto env = GetEnvironment();
2812 Label entry(env);
2813 env->SubCfgEntry(&entry);
2814 Label exit(env);
2815 Label handlerIsInt(env);
2816 Label handlerNotInt(env);
2817 Label handlerInfoIsField(env);
2818 Label handlerInfoNotField(env);
2819 Label isShared(env);
2820 Label notShared(env);
2821 Label matchType(env);
2822 Label prepareIntHandlerLoop(env);
2823 Label handlerIsTransitionHandler(env);
2824 Label handlerNotTransitionHandler(env);
2825 Label handlerIsTransWithProtoHandler(env);
2826 Label handlerNotTransWithProtoHandler(env);
2827 Label handlerIsPrototypeHandler(env);
2828 Label handlerNotPrototypeHandler(env);
2829 Label handlerIsPropertyBox(env);
2830 Label handlerNotPropertyBox(env);
2831 Label handlerIsStoreTSHandler(env);
2832 Label handlerNotStoreTSHandler(env);
2833 Label aotHandlerInfoIsField(env);
2834 Label aotHandlerInfoNotField(env);
2835 Label cellHasChanged(env);
2836 Label cellNotChanged(env);
2837 Label cellNotUndefined(env);
2838 Label aotCellNotChanged(env);
2839 Label loopHead(env);
2840 Label loopEnd(env);
2841 Label JumpLoopHead(env);
2842 Label cellNotNull(env);
2843 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2844 DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
2845 DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
2846 Jump(&loopHead);
2847 LoopBegin(&loopHead);
2848 {
2849 BRANCH(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
2850 Bind(&handlerIsInt);
2851 {
2852 GateRef handlerInfo = GetInt64OfTInt(*handler);
2853 BRANCH(IsNonSharedStoreField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
2854 Bind(&handlerInfoIsField);
2855 {
2856 result = StoreField(glue, receiver, value, handlerInfo, callback);
2857 Jump(&exit);
2858 }
2859 Bind(&handlerInfoNotField);
2860 {
2861 BRANCH(IsStoreShared(handlerInfo), &isShared, ¬Shared);
2862 Bind(&isShared);
2863 {
2864 BRANCH(HandlerBaseIsAccessor(handlerInfo), &prepareIntHandlerLoop, &matchType);
2865 Bind(&matchType);
2866 {
2867 GateRef field = GetFieldTypeFromHandler(handlerInfo);
2868 MatchFieldType(&result, glue, field, value, &prepareIntHandlerLoop, &exit);
2869 }
2870 Bind(&prepareIntHandlerLoop);
2871 {
2872 handler = IntToTaggedPtr(ClearSharedStoreKind(handlerInfo));
2873 Jump(&JumpLoopHead);
2874 }
2875 }
2876 Bind(¬Shared);
2877 GateRef accessor = LoadFromField(*holder, handlerInfo);
2878 result = CallSetterHelper(glue, receiver, accessor, value, callback);
2879 Jump(&exit);
2880 }
2881 }
2882 Bind(&handlerNotInt);
2883 {
2884 BRANCH(TaggedIsTransitionHandler(*handler), &handlerIsTransitionHandler, &handlerNotTransitionHandler);
2885 Bind(&handlerIsTransitionHandler);
2886 {
2887 result = StoreWithTransition(glue, receiver, value, *handler, callback);
2888 Jump(&exit);
2889 }
2890 Bind(&handlerNotTransitionHandler);
2891 {
2892 BRANCH(TaggedIsTransWithProtoHandler(*handler), &handlerIsTransWithProtoHandler,
2893 &handlerNotTransWithProtoHandler);
2894 Bind(&handlerIsTransWithProtoHandler);
2895 {
2896 GateRef cellValue = GetProtoCell(*handler);
2897 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &cellNotChanged);
2898 Bind(&cellNotChanged);
2899 {
2900 result = StoreWithTransition(glue, receiver, value, *handler, callback, true);
2901 Jump(&exit);
2902 }
2903 }
2904 Bind(&handlerNotTransWithProtoHandler);
2905 {
2906 BRANCH(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
2907 Bind(&handlerNotPrototypeHandler);
2908 {
2909 BRANCH(TaggedIsPropertyBox(*handler), &handlerIsPropertyBox, &handlerNotPropertyBox);
2910 Bind(&handlerIsPropertyBox);
2911 StoreGlobal(glue, value, *handler);
2912 Jump(&exit);
2913 }
2914 }
2915 }
2916 }
2917 Bind(&handlerIsPrototypeHandler);
2918 {
2919 GateRef cellValue = GetProtoCell(*handler);
2920 BRANCH(TaggedIsUndefined(cellValue), &loopEnd, &cellNotUndefined);
2921 Bind(&cellNotUndefined);
2922 BRANCH(TaggedIsNull(cellValue), &cellHasChanged, &cellNotNull);
2923 Bind(&cellNotNull);
2924 {
2925 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
2926 }
2927 Bind(&loopEnd);
2928 {
2929 holder = GetPrototypeHandlerHolder(*handler);
2930 handler = GetPrototypeHandlerHandlerInfo(*handler);
2931 Jump(&JumpLoopHead);
2932 }
2933 }
2934 Bind(&handlerNotPropertyBox);
2935 {
2936 BRANCH(TaggedIsStoreTSHandler(*handler), &handlerIsStoreTSHandler, &handlerNotStoreTSHandler);
2937 Bind(&handlerIsStoreTSHandler);
2938 {
2939 GateRef cellValue = GetProtoCell(*handler);
2940 BRANCH(GetHasChanged(cellValue), &cellHasChanged, &aotCellNotChanged);
2941 Bind(&aotCellNotChanged);
2942 {
2943 holder = GetStoreTSHandlerHolder(*handler);
2944 handler = GetStoreTSHandlerHandlerInfo(*handler);
2945 GateRef handlerInfo = GetInt64OfTInt(*handler);
2946 BRANCH(IsField(handlerInfo), &aotHandlerInfoIsField, &aotHandlerInfoNotField);
2947 Bind(&aotHandlerInfoIsField);
2948 {
2949 result = StoreField(glue, receiver, value, handlerInfo, callback);
2950 Jump(&exit);
2951 }
2952 Bind(&aotHandlerInfoNotField);
2953 {
2954 GateRef accessor = LoadFromField(*holder, handlerInfo);
2955 result = CallSetterHelper(glue, receiver, accessor, value, callback);
2956 Jump(&exit);
2957 }
2958 }
2959 }
2960 Bind(&handlerNotStoreTSHandler);
2961 Jump(&exit);
2962 }
2963 Bind(&cellHasChanged);
2964 {
2965 result = Hole();
2966 Jump(&exit);
2967 }
2968 Bind(&JumpLoopHead);
2969 {
2970 LoopEnd(&loopHead, env, glue);
2971 }
2972 }
2973 Bind(&exit);
2974 auto ret = *result;
2975 env->SubCfgExit();
2976 return ret;
2977 }
2978
StoreField(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback)2979 GateRef StubBuilder::StoreField(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
2980 ProfileOperation callback)
2981 {
2982 auto env = GetEnvironment();
2983 Label entry(env);
2984 env->SubCfgEntry(&entry);
2985 ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handler, callback);
2986 Label exit(env);
2987 Label handlerIsInlinedProperty(env);
2988 Label handlerNotInlinedProperty(env);
2989 GateRef index = HandlerBaseGetOffset(handler);
2990 GateRef rep = HandlerBaseGetRep(handler);
2991 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2992 Label repChange(env);
2993 BRANCH(HandlerBaseIsInlinedProperty(handler), &handlerIsInlinedProperty, &handlerNotInlinedProperty);
2994 Bind(&handlerIsInlinedProperty);
2995 {
2996 GateRef toOffset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
2997 SetValueWithRep(glue, receiver, toOffset, value, rep, &repChange);
2998 Jump(&exit);
2999 }
3000 Bind(&handlerNotInlinedProperty);
3001 {
3002 GateRef array = GetPropertiesArray(receiver);
3003 SetValueToTaggedArrayWithRep(glue, array, index, value, rep, &repChange);
3004 Jump(&exit);
3005 }
3006 Bind(&repChange);
3007 {
3008 result = Hole();
3009 Jump(&exit);
3010 }
3011
3012 Bind(&exit);
3013 auto ret = *result;
3014 env->SubCfgExit();
3015 return ret;
3016 }
3017
StoreWithTransition(GateRef glue,GateRef receiver,GateRef value,GateRef handler,ProfileOperation callback,bool withPrototype)3018 GateRef StubBuilder::StoreWithTransition(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
3019 ProfileOperation callback, bool withPrototype)
3020 {
3021 auto env = GetEnvironment();
3022 Label entry(env);
3023 env->SubCfgEntry(&entry);
3024 Label exit(env);
3025
3026 Label handlerInfoIsInlinedProps(env);
3027 Label handlerInfoNotInlinedProps(env);
3028 Label indexMoreCapacity(env);
3029 Label indexLessCapacity(env);
3030 Label capacityIsZero(env);
3031 Label capacityNotZero(env);
3032 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3033 GateRef newHClass;
3034 GateRef handlerInfo;
3035 if (withPrototype) {
3036 newHClass = GetTransWithProtoHClass(handler);
3037 handlerInfo = GetInt64OfTInt(GetTransWithProtoHandlerInfo(handler));
3038 } else {
3039 newHClass = GetTransitionHClass(handler);
3040 handlerInfo = GetInt64OfTInt(GetTransitionHandlerInfo(handler));
3041 }
3042
3043 GateRef oldHClass = LoadHClass(receiver);
3044 GateRef prototype = GetPrototypeFromHClass(oldHClass);
3045 StorePrototype(glue, newHClass, prototype);
3046 // Because we currently only supports Fast ElementsKind
3047 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(receiver));
3048 RestoreElementsKindToGeneric(glue, newHClass);
3049 StoreHClass(glue, receiver, newHClass);
3050 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
3051 BRANCH(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
3052 Bind(&handlerInfoNotInlinedProps);
3053 {
3054 ProfilerStubBuilder(env).UpdatePropAttrIC(glue, receiver, value, handlerInfo, callback);
3055 Label repChange(env);
3056 GateRef array = GetPropertiesArray(receiver);
3057 GateRef capacity = GetLengthOfTaggedArray(array);
3058 GateRef index = HandlerBaseGetOffset(handlerInfo);
3059 BRANCH(Int32GreaterThanOrEqual(index, capacity), &indexMoreCapacity, &indexLessCapacity);
3060 Bind(&indexMoreCapacity);
3061 {
3062 NewObjectStubBuilder newBuilder(this);
3063 BRANCH(Int32Equal(capacity, Int32(0)), &capacityIsZero, &capacityNotZero);
3064 Bind(&capacityIsZero);
3065 {
3066 GateRef properties = newBuilder.NewTaggedArray(glue, Int32(JSObject::MIN_PROPERTIES_LENGTH));
3067 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3068 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3069 Jump(&exit);
3070 }
3071 Bind(&capacityNotZero);
3072 {
3073 GateRef inlinedProperties = GetInlinedPropertiesFromHClass(newHClass);
3074 GateRef maxNonInlinedFastPropsCapacity =
3075 Int32Sub(Int32(PropertyAttributes::MAX_FAST_PROPS_CAPACITY), inlinedProperties);
3076 GateRef newLen = ComputeNonInlinedFastPropsCapacity(glue, capacity, maxNonInlinedFastPropsCapacity);
3077 GateRef properties = newBuilder.CopyArray(glue, array, capacity, newLen);
3078 SetValueToTaggedArray(VariableType::JS_ANY(), glue, properties, index, value);
3079 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, properties);
3080 Jump(&exit);
3081 }
3082 }
3083 Bind(&indexLessCapacity);
3084 {
3085 GateRef rep = HandlerBaseGetRep(handlerInfo);
3086 GateRef base = PtrAdd(array, IntPtr(TaggedArray::DATA_OFFSET));
3087 GateRef toIndex = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
3088 SetValueWithRep(glue, base, toIndex, value, rep, &repChange);
3089 Jump(&exit);
3090 }
3091 Bind(&repChange);
3092 {
3093 result = Hole();
3094 Jump(&exit);
3095 }
3096 }
3097 Bind(&handlerInfoIsInlinedProps);
3098 {
3099 result = StoreField(glue, receiver, value, handlerInfo, callback);
3100 Jump(&exit);
3101 }
3102 Bind(&exit);
3103 auto ret = *result;
3104 env->SubCfgExit();
3105 return ret;
3106 }
3107
StoreGlobal(GateRef glue,GateRef value,GateRef cell)3108 GateRef StubBuilder::StoreGlobal(GateRef glue, GateRef value, GateRef cell)
3109 {
3110 auto env = GetEnvironment();
3111 Label entry(env);
3112 env->SubCfgEntry(&entry);
3113 Label exit(env);
3114 Label cellNotInvalid(env);
3115 Label cellIsNotAccessorData(env);
3116 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3117 BRANCH(IsInvalidPropertyBox(cell), &exit, &cellNotInvalid);
3118 Bind(&cellNotInvalid);
3119 {
3120 BRANCH(IsAccessorPropertyBox(cell), &exit, &cellIsNotAccessorData);
3121 Bind(&cellIsNotAccessorData);
3122 {
3123 Store(VariableType::JS_ANY(), glue, cell, IntPtr(PropertyBox::VALUE_OFFSET), value);
3124 result = Undefined();
3125 Jump(&exit);
3126 }
3127 }
3128 Bind(&exit);
3129 auto ret = *result;
3130 env->SubCfgExit();
3131 return ret;
3132 }
3133
3134 template<typename DictionaryT>
GetAttributesFromDictionary(GateRef elements,GateRef entry)3135 GateRef StubBuilder::GetAttributesFromDictionary(GateRef elements, GateRef entry)
3136 {
3137 GateRef arrayIndex =
3138 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3139 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3140 GateRef attributesIndex =
3141 Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_DETAILS_INDEX));
3142 auto attrValue = GetValueFromTaggedArray(elements, attributesIndex);
3143 return GetInt64OfTInt(attrValue);
3144 }
3145
3146 template<typename DictionaryT>
GetValueFromDictionary(GateRef elements,GateRef entry)3147 GateRef StubBuilder::GetValueFromDictionary(GateRef elements, GateRef entry)
3148 {
3149 GateRef arrayIndex =
3150 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3151 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3152 GateRef valueIndex =
3153 Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3154 return GetValueFromTaggedArray(elements, valueIndex);
3155 }
3156
3157 template<typename DictionaryT>
GetKeyFromDictionary(GateRef elements,GateRef entry)3158 GateRef StubBuilder::GetKeyFromDictionary(GateRef elements, GateRef entry)
3159 {
3160 auto env = GetEnvironment();
3161 Label subentry(env);
3162 env->SubCfgEntry(&subentry);
3163 Label exit(env);
3164 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3165 Label ltZero(env);
3166 Label notLtZero(env);
3167 Label gtLength(env);
3168 Label notGtLength(env);
3169 GateRef dictionaryLength =
3170 Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
3171 GateRef arrayIndex =
3172 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3173 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
3174 BRANCH(Int32LessThan(arrayIndex, Int32(0)), <Zero, ¬LtZero);
3175 Bind(<Zero);
3176 Jump(&exit);
3177 Bind(¬LtZero);
3178 BRANCH(Int32GreaterThan(arrayIndex, dictionaryLength), >Length, ¬GtLength);
3179 Bind(>Length);
3180 Jump(&exit);
3181 Bind(¬GtLength);
3182 result = GetValueFromTaggedArray(elements, arrayIndex);
3183 Jump(&exit);
3184 Bind(&exit);
3185 auto ret = *result;
3186 env->SubCfgExit();
3187 return ret;
3188 }
3189
UpdateValueAndAttributes(GateRef glue,GateRef elements,GateRef index,GateRef value,GateRef attr)3190 inline void StubBuilder::UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index,
3191 GateRef value, GateRef attr)
3192 {
3193 GateRef arrayIndex =
3194 Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
3195 Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
3196 GateRef valueIndex =
3197 Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
3198 GateRef attributesIndex =
3199 Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_DETAILS_INDEX));
3200 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3201 GateRef attroffset =
3202 PtrMul(ZExtInt32ToPtr(attributesIndex), IntPtr(JSTaggedValue::TaggedTypeSize()));
3203 GateRef dataOffset = PtrAdd(attroffset, IntPtr(TaggedArray::DATA_OFFSET));
3204 Store(VariableType::INT64(), glue, elements, dataOffset, Int64ToTaggedInt(attr));
3205 }
3206
3207 template<typename DictionaryT>
UpdateValueInDict(GateRef glue,GateRef elements,GateRef index,GateRef value)3208 inline void StubBuilder::UpdateValueInDict(GateRef glue, GateRef elements, GateRef index, GateRef value)
3209 {
3210 GateRef arrayIndex = Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
3211 Int32Mul(index, Int32(DictionaryT::ENTRY_SIZE)));
3212 GateRef valueIndex = Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
3213 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
3214 }
3215
GetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,ProfileOperation callback,GateRef hir)3216 GateRef StubBuilder::GetPropertyByIndex(GateRef glue, GateRef receiver,
3217 GateRef index, ProfileOperation callback, GateRef hir)
3218 {
3219 auto env = GetEnvironment();
3220 Label entry(env);
3221 env->SubCfgEntry(&entry);
3222 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3223 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
3224 Label exit(env);
3225 Label loopHead(env);
3226 Label loopEnd(env);
3227 Label loopExit(env);
3228 Label afterLoop(env);
3229 Jump(&loopHead);
3230 LoopBegin(&loopHead);
3231 {
3232 GateRef hclass = LoadHClass(*holder);
3233 GateRef jsType = GetObjectType(hclass);
3234 Label isSpecialIndexed(env);
3235 Label notSpecialIndexed(env);
3236 BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed);
3237 Bind(&isSpecialIndexed);
3238 {
3239 // TypeArray
3240 Label isFastTypeArray(env);
3241 Label notFastTypeArray(env);
3242 Label notTypedArrayProto(env);
3243 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, ¬TypedArrayProto);
3244 Bind(¬TypedArrayProto);
3245 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
3246 Bind(&isFastTypeArray);
3247 {
3248 BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this);
3249 result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, *holder, index, jsType);
3250 Jump(&exit);
3251 }
3252 Bind(¬FastTypeArray);
3253
3254 Label isSpecialContainer(env);
3255 Label notSpecialContainer(env);
3256 // Add SpecialContainer
3257 BRANCH(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
3258 Bind(&isSpecialContainer);
3259 {
3260 result = GetContainerProperty(glue, *holder, index, jsType);
3261 Jump(&exit);
3262 }
3263 Bind(¬SpecialContainer);
3264
3265 Label isString(env);
3266 Label notString(env);
3267 Label getSubString(env);
3268 BRANCH(TaggedIsString(*holder), &isString, ¬String);
3269 Bind(&isString);
3270 {
3271 GateRef length = GetLengthFromString(*holder);
3272 BRANCH(Int32LessThan(index, length), &getSubString, ¬String);
3273 Bind(&getSubString);
3274 Label flattenFastPath(env);
3275 BuiltinsStringStubBuilder stringBuilder(this);
3276 FlatStringStubBuilder thisFlat(this);
3277 thisFlat.FlattenString(glue, *holder, &flattenFastPath);
3278 Bind(&flattenFastPath);
3279 StringInfoGateRef stringInfoGate(&thisFlat);
3280 result = stringBuilder.FastSubString(glue, *holder, index, Int32(1), stringInfoGate);
3281 Jump(&exit);
3282 }
3283 Bind(¬String);
3284 {
3285 result = Hole();
3286 Jump(&exit);
3287 }
3288 }
3289 Bind(¬SpecialIndexed);
3290 {
3291 GateRef elements = GetElementsArray(*holder);
3292 Label isDictionaryElement(env);
3293 Label notDictionaryElement(env);
3294 BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
3295 Bind(¬DictionaryElement);
3296 {
3297 Label lessThanLength(env);
3298 Label notLessThanLength(env);
3299 BRANCH(Int32UnsignedLessThan(index, GetLengthOfTaggedArray(elements)),
3300 &lessThanLength, ¬LessThanLength);
3301 Bind(&lessThanLength);
3302 {
3303 DEFVARIABLE(value, VariableType::JS_ANY(), Hole());
3304 Label notHole(env);
3305 Label isHole(env);
3306 value = GetTaggedValueWithElementsKind(*holder, index);
3307 BRANCH(TaggedIsNotHole(*value), ¬Hole, &isHole);
3308 Bind(¬Hole);
3309 {
3310 result = *value;
3311 Jump(&exit);
3312 }
3313 Bind(&isHole);
3314 {
3315 Jump(&loopExit);
3316 }
3317 }
3318 Bind(¬LessThanLength);
3319 {
3320 Jump(&loopExit);
3321 }
3322 }
3323 Bind(&isDictionaryElement);
3324 {
3325 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
3326 Label notNegtiveOne(env);
3327 Label negtiveOne(env);
3328 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
3329 Bind(¬NegtiveOne);
3330 {
3331 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
3332 GateRef value = GetValueFromDictionary<NumberDictionary>(elements, entryA);
3333 Label isAccessor(env);
3334 Label notAccessor(env);
3335 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
3336 Bind(&isAccessor);
3337 {
3338 result = CallGetterHelper(glue, receiver, *holder, value, callback, hir);
3339 Jump(&exit);
3340 }
3341 Bind(¬Accessor);
3342 {
3343 result = value;
3344 Jump(&exit);
3345 }
3346 }
3347 Bind(&negtiveOne);
3348 Jump(&loopExit);
3349 }
3350 Bind(&loopExit);
3351 {
3352 holder = GetPrototypeFromHClass(LoadHClass(*holder));
3353 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3354 }
3355 }
3356 Bind(&loopEnd);
3357 LoopEnd(&loopHead, env, glue);
3358 Bind(&afterLoop);
3359 {
3360 result = Undefined();
3361 Jump(&exit);
3362 }
3363 }
3364 Bind(&exit);
3365 auto ret = *result;
3366 env->SubCfgExit();
3367 return ret;
3368 }
3369
GetPropertyByValue(GateRef glue,GateRef receiver,GateRef keyValue,ProfileOperation callback)3370 GateRef StubBuilder::GetPropertyByValue(GateRef glue, GateRef receiver, GateRef keyValue, ProfileOperation callback)
3371 {
3372 auto env = GetEnvironment();
3373 Label entry(env);
3374 env->SubCfgEntry(&entry);
3375 DEFVARIABLE(key, VariableType::JS_ANY(), keyValue);
3376 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3377 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
3378 Label isNumberOrStringSymbol(env);
3379 Label notNumber(env);
3380 Label isStringOrSymbol(env);
3381 Label notStringOrSymbol(env);
3382 Label exit(env);
3383
3384 BRANCH(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number);
3385 Bind(¬Number);
3386 {
3387 BRANCH(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol);
3388 Bind(¬StringOrSymbol);
3389 {
3390 result = Hole();
3391 Jump(&exit);
3392 }
3393 }
3394 Bind(&isNumberOrStringSymbol);
3395 {
3396 GateRef index64 = TryToElementsIndex(glue, *key);
3397 Label validIndex(env);
3398 Label notValidIndex(env);
3399 Label greaterThanInt32Max(env);
3400 Label notGreaterThanInt32Max(env);
3401 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
3402 Bind(&greaterThanInt32Max);
3403 {
3404 Jump(&exit);
3405 }
3406 Bind(¬GreaterThanInt32Max);
3407 GateRef index = TruncInt64ToInt32(index64);
3408 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
3409 Bind(&validIndex);
3410 {
3411 result = GetPropertyByIndex(glue, receiver, index, callback);
3412 Jump(&exit);
3413 }
3414 Bind(¬ValidIndex);
3415 {
3416 Label notNumber1(env);
3417 Label getByName(env);
3418 BRANCH(TaggedIsNumber(*key), &exit, ¬Number1);
3419 Bind(¬Number1);
3420 {
3421 Label isString(env);
3422 Label notString(env);
3423 Label isInternalString(env);
3424 Label notIntenalString(env);
3425 BRANCH(TaggedIsString(*key), &isString, ¬String);
3426 Bind(&isString);
3427 {
3428 BRANCH(IsInternalString(*key), &isInternalString, ¬IntenalString);
3429 Bind(&isInternalString);
3430 Jump(&getByName);
3431 Bind(¬IntenalString);
3432 {
3433 Label notFind(env);
3434 Label find(env);
3435 // if key can't find in stringtabele, key is not propertyname for a object
3436 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *key });
3437 BRANCH(TaggedIsHole(res), ¬Find, &find);
3438 Bind(¬Find);
3439 {
3440 isInternal = False();
3441 Jump(&getByName);
3442 }
3443 Bind(&find);
3444 {
3445 key = res;
3446 Jump(&getByName);
3447 }
3448 }
3449 }
3450 Bind(¬String);
3451 {
3452 Jump(&getByName);
3453 }
3454 }
3455 Bind(&getByName);
3456 {
3457 result = GetPropertyByName(glue, receiver, *key, callback, *isInternal, true);
3458 Jump(&exit);
3459 }
3460 }
3461 }
3462 Bind(&exit);
3463 auto ret = *result;
3464 env->SubCfgExit();
3465 return ret;
3466 }
3467
GetPropertyByName(GateRef glue,GateRef receiver,GateRef key,ProfileOperation callback,GateRef isInternal,bool canUseIsInternal)3468 GateRef StubBuilder::GetPropertyByName(GateRef glue, GateRef receiver, GateRef key,
3469 ProfileOperation callback, GateRef isInternal, bool canUseIsInternal)
3470 {
3471 auto env = GetEnvironment();
3472 Label entry(env);
3473 env->SubCfgEntry(&entry);
3474 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3475 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
3476 Label exit(env);
3477 Label loopHead(env);
3478 Label loopEnd(env);
3479 Label loopExit(env);
3480 Label afterLoop(env);
3481 Label findProperty(env);
3482 Jump(&loopHead);
3483 LoopBegin(&loopHead);
3484 {
3485 GateRef hclass = LoadHClass(*holder);
3486 GateRef jsType = GetObjectType(hclass);
3487 Label isSIndexObj(env);
3488 Label notSIndexObj(env);
3489 BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
3490 Bind(&isSIndexObj);
3491 {
3492 // TypeArray
3493 Label isFastTypeArray(env);
3494 Label notFastTypeArray(env);
3495 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
3496 Bind(&isFastTypeArray);
3497 {
3498 result = GetTypeArrayPropertyByName(glue, receiver, *holder, key, jsType);
3499 Label isNull(env);
3500 Label notNull(env);
3501 BRANCH(TaggedIsNull(*result), &isNull, ¬Null);
3502 Bind(&isNull);
3503 {
3504 result = Hole();
3505 Jump(&exit);
3506 }
3507 Bind(¬Null);
3508 BRANCH(TaggedIsHole(*result), ¬SIndexObj, &exit);
3509 }
3510 Bind(¬FastTypeArray);
3511
3512 Label isString(env);
3513 Label notString(env);
3514 Label notJsPrimitiveRef(env);
3515 auto holderValue = *holder;
3516 BRANCH(LogicAndBuilder(env).And(TaggedIsString(holderValue)).And(TaggedIsString(key)).Done(),
3517 &isString, ¬String);
3518 Bind(&isString);
3519 {
3520 Label getStringLength(env);
3521 Label getStringPrototype(env);
3522 GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
3523 ConstantIndex::LENGTH_STRING_INDEX);
3524 BRANCH(FastStringEqual(glue, key, lengthString), &getStringLength, &getStringPrototype);
3525 Bind(&getStringLength);
3526 {
3527 result = IntToTaggedPtr(GetLengthFromString(*holder));
3528 Jump(&exit);
3529 }
3530 Bind(&getStringPrototype);
3531 {
3532 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
3533 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
3534 GateRef stringPrototype = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
3535 GlobalEnv::STRING_PROTOTYPE_INDEX);
3536 holder = stringPrototype;
3537 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3538 }
3539 }
3540 Bind(¬String);
3541 BRANCH(IsJSPrimitiveRef(*holder), ¬SIndexObj, ¬JsPrimitiveRef);
3542 Bind(¬JsPrimitiveRef); // not string prototype etc.
3543 {
3544 result = Hole();
3545 Jump(&exit);
3546 }
3547 }
3548 Bind(¬SIndexObj);
3549 {
3550 if (canUseIsInternal) {
3551 BRANCH(isInternal, &findProperty, &loopExit);
3552 } else {
3553 Jump(&findProperty);
3554 }
3555 Label isDicMode(env);
3556 Label notDicMode(env);
3557 Bind(&findProperty);
3558 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
3559 Bind(¬DicMode);
3560 {
3561 GateRef layOutInfo = GetLayoutFromHClass(hclass);
3562 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
3563 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
3564 GateRef entryA = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
3565 Label hasEntry(env);
3566 Label noEntry(env);
3567 // if branch condition : entry != -1
3568 BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, &noEntry);
3569 Bind(&hasEntry);
3570 {
3571 // PropertyAttributes attr(layoutInfo->GetAttr(entry))
3572 GateRef attr = GetPropAttrFromLayoutInfo(layOutInfo, entryA);
3573 GateRef value = JSObjectGetProperty(*holder, hclass, attr);
3574 Label isAccessor(env);
3575 Label notAccessor(env);
3576 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
3577 Bind(&isAccessor);
3578 {
3579 result = CallGetterHelper(glue, receiver, *holder, value, callback);
3580 Jump(&exit);
3581 }
3582 Bind(¬Accessor);
3583 {
3584 Label notHole(env);
3585 BRANCH(TaggedIsHole(value), &noEntry, ¬Hole);
3586 Bind(¬Hole);
3587 {
3588 result = value;
3589 Jump(&exit);
3590 }
3591 }
3592 }
3593 Bind(&noEntry);
3594 {
3595 Jump(&loopExit);
3596 }
3597 }
3598 Bind(&isDicMode);
3599 {
3600 GateRef array = GetPropertiesArray(*holder);
3601 // int entry = dict->FindEntry(key)
3602 GateRef entryB = FindEntryFromNameDictionary(glue, array, key);
3603 Label notNegtiveOne(env);
3604 Label negtiveOne(env);
3605 // if branch condition : entry != -1
3606 BRANCH(Int32NotEqual(entryB, Int32(-1)), ¬NegtiveOne, &negtiveOne);
3607 Bind(¬NegtiveOne);
3608 {
3609 // auto value = dict->GetValue(entry)
3610 GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, entryB);
3611 // auto attr = dict->GetAttributes(entry)
3612 GateRef value = GetValueFromDictionary<NameDictionary>(array, entryB);
3613 Label isAccessor1(env);
3614 Label notAccessor1(env);
3615 BRANCH(IsAccessor(attr), &isAccessor1, ¬Accessor1);
3616 Bind(&isAccessor1);
3617 {
3618 result = CallGetterHelper(glue, receiver, *holder, value, callback);
3619 Jump(&exit);
3620 }
3621 Bind(¬Accessor1);
3622 {
3623 result = value;
3624 Jump(&exit);
3625 }
3626 }
3627 Bind(&negtiveOne);
3628 Jump(&loopExit);
3629 }
3630 Bind(&loopExit);
3631 {
3632 holder = GetPrototypeFromHClass(LoadHClass(*holder));
3633 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
3634 }
3635 }
3636 Bind(&loopEnd);
3637 LoopEnd(&loopHead, env, glue);
3638 Bind(&afterLoop);
3639 {
3640 result = Undefined();
3641 Jump(&exit);
3642 }
3643 }
3644 Bind(&exit);
3645 auto ret = *result;
3646 env->SubCfgExit();
3647 return ret;
3648 }
3649
CopyAllHClass(GateRef glue,GateRef dstHClass,GateRef srcHClass)3650 void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHClass)
3651 {
3652 auto env = GetEnvironment();
3653 Label entry(env);
3654 Label isTS(env);
3655 Label isNotTS(env);
3656 env->SubCfgEntry(&entry);
3657 auto proto = GetPrototypeFromHClass(srcHClass);
3658 SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto);
3659 SetBitFieldToHClass(glue, dstHClass, GetBitFieldFromHClass(srcHClass));
3660 SetIsAllTaggedProp(glue, dstHClass, GetIsAllTaggedPropFromHClass(srcHClass));
3661 SetNumberOfPropsToHClass(glue, dstHClass, GetNumberOfPropsFromHClass(srcHClass));
3662 SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
3663 SetParentToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
3664 SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, dstHClass, Null());
3665 SetEnumCacheToHClass(VariableType::INT64(), glue, dstHClass, Null());
3666 SetLayoutToHClass(VariableType::JS_POINTER(),
3667 glue,
3668 dstHClass,
3669 GetLayoutFromHClass(srcHClass),
3670 MemoryAttribute::NeedBarrierAndAtomic());
3671 BRANCH(IsTSHClass(srcHClass), &isTS, &isNotTS);
3672 Bind(&isTS);
3673 {
3674 SetIsTS(glue, dstHClass, False());
3675 Jump(&isNotTS);
3676 }
3677 Bind(&isNotTS);
3678 env->SubCfgExit();
3679 return;
3680 }
3681
TransitionForRepChange(GateRef glue,GateRef receiver,GateRef key,GateRef attr)3682 void StubBuilder::TransitionForRepChange(GateRef glue, GateRef receiver, GateRef key, GateRef attr)
3683 {
3684 auto env = GetEnvironment();
3685 Label subEntry(env);
3686 env->SubCfgEntry(&subEntry);
3687 GateRef hclass = LoadHClass(receiver);
3688 GateRef type = GetObjectType(hclass);
3689 GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
3690 Int32(JSTaggedValue::TaggedTypeSize()));
3691 GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
3692 GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
3693 { IntToTaggedInt(size), IntToTaggedInt(type),
3694 IntToTaggedInt(inlineProps) });
3695 CopyAllHClass(glue, newJshclass, hclass);
3696 CallRuntime(glue, RTSTUB_ID(CopyAndUpdateObjLayout),
3697 { hclass, newJshclass, key, Int64ToTaggedInt(attr) });
3698 #if ECMASCRIPT_ENABLE_IC
3699 NotifyHClassChanged(glue, hclass, newJshclass);
3700 #endif
3701 // Because we currently only supports Fast ElementsKind
3702 GateRef oldKind = GetElementsKindFromHClass(LoadHClass(receiver));
3703 RestoreElementsKindToGeneric(glue, newJshclass);
3704 StoreHClass(glue, receiver, newJshclass);
3705 TryMigrateToGenericKindForJSObject(glue, receiver, oldKind);
3706 env->SubCfgExit();
3707 }
3708
TransitToElementsKind(GateRef glue,GateRef receiver,GateRef value,GateRef kind)3709 void StubBuilder::TransitToElementsKind(GateRef glue, GateRef receiver, GateRef value, GateRef kind)
3710 {
3711 auto env = GetEnvironment();
3712 Label subEntry(env);
3713 env->SubCfgEntry(&subEntry);
3714 Label exit(env);
3715
3716 GateRef hclass = LoadHClass(receiver);
3717 GateRef elementsKind = GetElementsKindFromHClass(hclass);
3718
3719 Label isNoneDefault(env);
3720 BRANCH(Int32Equal(elementsKind, Int32(static_cast<int32_t>(ElementsKind::GENERIC))), &exit, &isNoneDefault);
3721 Bind(&isNoneDefault);
3722 {
3723 GateRef newKind = TaggedToElementKind(value);
3724 newKind = Int32Or(newKind, kind);
3725 newKind = Int32Or(newKind, elementsKind);
3726 Label change(env);
3727 BRANCH(Int32Equal(elementsKind, newKind), &exit, &change);
3728 Bind(&change);
3729 {
3730 CallRuntime(glue, RTSTUB_ID(UpdateHClassForElementsKind), { receiver, newKind });
3731 MigrateArrayWithKind(glue, receiver, elementsKind, newKind);
3732 Jump(&exit);
3733 }
3734 }
3735
3736 Bind(&exit);
3737 env->SubCfgExit();
3738 }
3739
TryMigrateToGenericKindForJSObject(GateRef glue,GateRef receiver,GateRef oldKind)3740 void StubBuilder::TryMigrateToGenericKindForJSObject(GateRef glue, GateRef receiver, GateRef oldKind)
3741 {
3742 auto env = GetEnvironment();
3743 Label subEntry(env);
3744 env->SubCfgEntry(&subEntry);
3745 Label exit(env);
3746
3747 Label isJSArray(env);
3748 BRANCH(TaggedIsJSArray(receiver), &isJSArray, &exit);
3749 Bind(&isJSArray);
3750 {
3751 Label elementsIsMutantTaggedArray(env);
3752 GateRef elements = GetElementsArray(receiver);
3753 BRANCH(IsMutantTaggedArray(elements), &elementsIsMutantTaggedArray, &exit);
3754 Bind(&elementsIsMutantTaggedArray);
3755 {
3756 MigrateArrayWithKind(glue, receiver, oldKind, Int32(static_cast<int32_t>(ElementsKind::GENERIC)));
3757 Jump(&exit);
3758 }
3759 }
3760
3761 Bind(&exit);
3762 env->SubCfgExit();
3763 }
3764
AddElementInternal(GateRef glue,GateRef receiver,GateRef index,GateRef value,GateRef attr)3765 GateRef StubBuilder::AddElementInternal(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef attr)
3766 {
3767 auto env = GetEnvironment();
3768 Label subEntry(env);
3769 env->SubCfgEntry(&subEntry);
3770 Label exit(env);
3771 DEFVARIABLE(kind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::NONE)));
3772 DEFVARIABLE(result, VariableType::BOOL(), False());
3773 Label isArray(env);
3774 Label notArray(env);
3775 BRANCH(IsJsArray(receiver), &isArray, ¬Array);
3776 Bind(&isArray);
3777 {
3778 GateRef oldLen = GetArrayLength(receiver);
3779 Label indexGreaterOrEq(env);
3780 BRANCH(Int32GreaterThanOrEqual(index, oldLen), &indexGreaterOrEq, ¬Array);
3781 Bind(&indexGreaterOrEq);
3782 {
3783 Label isArrLenWritable(env);
3784 Label notArrLenWritable(env);
3785 BRANCH(IsArrayLengthWritable(glue, receiver), &isArrLenWritable, ¬ArrLenWritable);
3786 Bind(&isArrLenWritable);
3787 {
3788 SetArrayLength(glue, receiver, Int32Add(index, Int32(1)));
3789 Label indexGreater(env);
3790 BRANCH(Int32GreaterThan(index, oldLen), &indexGreater, ¬Array);
3791 Bind(&indexGreater);
3792 kind = Int32(static_cast<int32_t>(ElementsKind::HOLE));
3793 Jump(¬Array);
3794 }
3795 Bind(¬ArrLenWritable);
3796 result = False();
3797 Jump(&exit);
3798 }
3799 }
3800 Bind(¬Array);
3801 {
3802 NotifyStableArrayElementsGuardians(glue, receiver);
3803 GateRef hclass = LoadHClass(receiver);
3804 GateRef elements = GetElementsArray(receiver);
3805 Label isDicMode(env);
3806 Label notDicMode(env);
3807 BRANCH(IsDictionaryElement(hclass), &isDicMode, ¬DicMode);
3808 Bind(&isDicMode);
3809 {
3810 GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
3811 { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedFalse() });
3812 SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
3813 result = True();
3814 Jump(&exit);
3815 }
3816 Bind(¬DicMode);
3817 {
3818 GateRef capacity = GetLengthOfTaggedArray(elements);
3819 GateRef notDefault = BoolNot(IsDefaultAttribute(attr));
3820 Label indexGreaterLen(env);
3821 Label notGreaterLen(env);
3822 BRANCH(BitOr(notDefault, Int32GreaterThanOrEqual(index, capacity)), &indexGreaterLen, ¬GreaterLen);
3823 Bind(&indexGreaterLen);
3824 {
3825 Label isTransToDict(env);
3826 Label notTransToDict(env);
3827 BRANCH(LogicOrBuilder(env).Or(notDefault).Or(ShouldTransToDict(capacity, index)).Done(),
3828 &isTransToDict, ¬TransToDict);
3829 Bind(&isTransToDict);
3830 {
3831 GateRef res = CallRuntime(glue, RTSTUB_ID(NumberDictionaryPut),
3832 { receiver, elements, IntToTaggedInt(index), value, Int64ToTaggedInt(attr), TaggedTrue() });
3833 Label isPendingException(env);
3834 Label noPendingException(env);
3835 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
3836 Bind(&isPendingException);
3837 {
3838 result = False();
3839 Jump(&exit);
3840 }
3841 Bind(&noPendingException);
3842 SetElementsArray(VariableType::JS_POINTER(), glue, receiver, res);
3843 result = True();
3844 Jump(&exit);
3845 }
3846 Bind(¬TransToDict);
3847 {
3848 GrowElementsCapacity(glue, receiver, Int32Add(index, Int32(1)));
3849 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
3850 result = True();
3851 Jump(&exit);
3852 }
3853 }
3854 Bind(¬GreaterLen);
3855 {
3856 SetValueWithElementsKind(glue, receiver, value, index, Boolean(true), *kind);
3857 result = True();
3858 Jump(&exit);
3859 }
3860 }
3861 }
3862 Bind(&exit);
3863 auto ret = *result;
3864 env->SubCfgExit();
3865 return ret;
3866 }
3867
GrowElementsCapacity(GateRef glue,GateRef receiver,GateRef capacity)3868 GateRef StubBuilder::GrowElementsCapacity(GateRef glue, GateRef receiver, GateRef capacity)
3869 {
3870 auto env = GetEnvironment();
3871 Label subEntry(env);
3872 env->SubCfgEntry(&subEntry);
3873 DEFVARIABLE(newElements, VariableType::JS_ANY(), Hole());
3874 NewObjectStubBuilder newBuilder(this);
3875 GateRef newCapacity = ComputeElementCapacity(capacity);
3876 GateRef elements = GetElementsArray(receiver);
3877 newElements = newBuilder.CopyArray(glue, elements, capacity, newCapacity);
3878 SetElementsArray(VariableType::JS_POINTER(), glue, receiver, *newElements);
3879 auto ret = *newElements;
3880 env->SubCfgExit();
3881 return ret;
3882 }
3883
ShouldTransToDict(GateRef capacity,GateRef index)3884 GateRef StubBuilder::ShouldTransToDict(GateRef capacity, GateRef index)
3885 {
3886 auto env = GetEnvironment();
3887 Label subEntry(env);
3888 env->SubCfgEntry(&subEntry);
3889 Label exit(env);
3890 DEFVARIABLE(result, VariableType::BOOL(), True());
3891 Label isGreaterThanCapcity(env);
3892 Label notGreaterThanCapcity(env);
3893 BRANCH(Int32GreaterThanOrEqual(index, capacity), &isGreaterThanCapcity, ¬GreaterThanCapcity);
3894 Bind(&isGreaterThanCapcity);
3895 {
3896 Label isLessThanMax(env);
3897 Label notLessThanMax(env);
3898 BRANCH(Int32LessThanOrEqual(Int32Sub(index, capacity),
3899 Int32(JSObject::MAX_GAP)), &isLessThanMax, ¬LessThanMax);
3900 Bind(&isLessThanMax);
3901 {
3902 Label isLessThanInt32Max(env);
3903 Label notLessThanInt32Max(env);
3904 BRANCH(Int32LessThan(index, Int32(INT32_MAX)), &isLessThanInt32Max, ¬LessThanInt32Max);
3905 Bind(&isLessThanInt32Max);
3906 {
3907 Label isLessThanMin(env);
3908 Label notLessThanMin(env);
3909 BRANCH(Int32LessThan(capacity, Int32(JSObject::MIN_GAP)), &isLessThanMin, ¬LessThanMin);
3910 Bind(&isLessThanMin);
3911 {
3912 result = False();
3913 Jump(&exit);
3914 }
3915 Bind(¬LessThanMin);
3916 {
3917 result = Int32GreaterThan(index, Int32Mul(capacity, Int32(JSObject::FAST_ELEMENTS_FACTOR)));
3918 Jump(&exit);
3919 }
3920 }
3921 Bind(¬LessThanInt32Max);
3922 {
3923 result = True();
3924 Jump(&exit);
3925 }
3926 }
3927 Bind(¬LessThanMax);
3928 {
3929 result = True();
3930 Jump(&exit);
3931 }
3932 }
3933 Bind(¬GreaterThanCapcity);
3934 {
3935 result = False();
3936 Jump(&exit);
3937 }
3938 Bind(&exit);
3939 auto ret = *result;
3940 env->SubCfgExit();
3941 return ret;
3942 }
3943
NotifyStableArrayElementsGuardians(GateRef glue,GateRef receiver)3944 void StubBuilder::NotifyStableArrayElementsGuardians(GateRef glue, GateRef receiver)
3945 {
3946 auto env = GetEnvironment();
3947 Label subEntry(env);
3948 env->SubCfgEntry(&subEntry);
3949 Label exit(env);
3950 GateRef guardiansOffset =
3951 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
3952 GateRef guardians = Load(VariableType::BOOL(), glue, guardiansOffset);
3953 Label isGuardians(env);
3954 BRANCH(Equal(guardians, True()), &isGuardians, &exit);
3955 Bind(&isGuardians);
3956 {
3957 GateRef hclass = LoadHClass(receiver);
3958 Label isProtoType(env);
3959 BRANCH(BitOr(IsProtoTypeHClass(hclass), IsJsArray(receiver)), &isProtoType, &exit);
3960 Bind(&isProtoType);
3961 {
3962 Label isEnvProtoType(env);
3963 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
3964 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
3965 GateRef isEnvProtoTypeCheck = LogicOrBuilder(env)
3966 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
3967 GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX), receiver))
3968 .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
3969 GlobalEnv::ARRAY_PROTOTYPE_INDEX), receiver))
3970 .Done();
3971 BRANCH(isEnvProtoTypeCheck, &isEnvProtoType, &exit);
3972 Bind(&isEnvProtoType);
3973 Store(VariableType::BOOL(), glue, glue, guardiansOffset, False());
3974 Jump(&exit);
3975 }
3976 }
3977 Bind(&exit);
3978 env->SubCfgExit();
3979 return;
3980 }
3981
IsArrayLengthWritable(GateRef glue,GateRef receiver)3982 GateRef StubBuilder::IsArrayLengthWritable(GateRef glue, GateRef receiver)
3983 {
3984 auto env = GetEnvironment();
3985 Label subEntry(env);
3986 env->SubCfgEntry(&subEntry);
3987 Label exit(env);
3988 GateRef hclass = LoadHClass(receiver);
3989 Label isDicMode(env);
3990 Label notDicMode(env);
3991 DEFVARIABLE(result, VariableType::BOOL(), False());
3992 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
3993 Bind(&isDicMode);
3994 {
3995 GateRef array = GetPropertiesArray(receiver);
3996 GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
3997 ConstantIndex::LENGTH_STRING_INDEX);
3998 GateRef entry = FindEntryFromNameDictionary(glue, array, lengthString);
3999 Label notNegtiveOne(env);
4000 Label isNegtiveOne(env);
4001 BRANCH(Int32NotEqual(entry, Int32(-1)), ¬NegtiveOne, &isNegtiveOne);
4002 Bind(¬NegtiveOne);
4003 {
4004 GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, entry);
4005 result = IsWritable(attr);
4006 Jump(&exit);
4007 }
4008 Bind(&isNegtiveOne);
4009 {
4010 GateRef attr1 = Int64(PropertyAttributes::GetDefaultAttributes());
4011 result = IsWritable(attr1);
4012 Jump(&exit);
4013 }
4014 }
4015 Bind(¬DicMode);
4016 {
4017 GateRef layoutInfo = GetLayoutFromHClass(hclass);
4018 GateRef attr = GetPropAttrFromLayoutInfo(layoutInfo, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4019 result = IsWritable(attr);
4020 Jump(&exit);
4021 }
4022 Bind(&exit);
4023 auto ret = *result;
4024 env->SubCfgExit();
4025 return ret;
4026 }
4027
CheckHClassForRep(GateRef hclass,GateRef value)4028 GateRef StubBuilder::CheckHClassForRep(GateRef hclass, GateRef value)
4029 {
4030 auto env = GetEnvironment();
4031 Label subEntry(env);
4032 env->SubCfgEntry(&subEntry);
4033 Label exit(env);
4034 Label isTSHClass(env);
4035 DEFVARIABLE(result, VariableType::BOOL(), Boolean(true));
4036 Branch(IsTSHClass(hclass), &isTSHClass, &exit);
4037 Bind(&isTSHClass);
4038 {
4039 GateRef propNums = GetNumberOfPropsFromHClass(hclass);
4040 GateRef last = Int32Sub(propNums, Int32(1));
4041 GateRef layoutInfo = GetLayoutFromHClass(hclass);
4042 GateRef cachedAttr = GetPropAttrFromLayoutInfo(layoutInfo, last);
4043 GateRef lastRep = GetRepInPropAttr(cachedAttr);
4044 Label repIsInt(env);
4045 Label repIsNotInt(env);
4046 Label repIsDouble(env);
4047 Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::INT))), &repIsInt, &repIsNotInt);
4048 Bind(&repIsInt);
4049 {
4050 GateRef valueRep = TranslateToRep(value);
4051 Label valueRepIsNotInt(env);
4052 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4053 Bind(&valueRepIsNotInt);
4054 {
4055 result = Boolean(false);
4056 Jump(&exit);
4057 }
4058 }
4059 Bind(&repIsNotInt);
4060 {
4061 Branch(Equal(lastRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &repIsDouble, &exit);
4062 Bind(&repIsDouble);
4063 GateRef valueRep = TranslateToRep(value);
4064 Label valueRepIsNotInt(env);
4065 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::INT))), &exit, &valueRepIsNotInt);
4066 Bind(&valueRepIsNotInt);
4067 {
4068 Label valueRepIsNotDouble(env);
4069 Branch(Equal(valueRep, Int32(static_cast<int32_t>(Representation::DOUBLE))), &exit,
4070 &valueRepIsNotDouble);
4071 Bind(&valueRepIsNotDouble);
4072 {
4073 result = Boolean(false);
4074 Jump(&exit);
4075 }
4076 }
4077 }
4078 }
4079 Bind(&exit);
4080 auto ret = *result;
4081 env->SubCfgExit();
4082 return ret;
4083 }
4084
FindTransitions(GateRef glue,GateRef hclass,GateRef key,GateRef metaData,GateRef value)4085 GateRef StubBuilder::FindTransitions(GateRef glue, GateRef hclass, GateRef key, GateRef metaData, GateRef value)
4086 {
4087 auto env = GetEnvironment();
4088 Label entry(env);
4089 env->SubCfgEntry(&entry);
4090 Label exit(env);
4091 GateRef transitionOffset = IntPtr(JSHClass::TRANSTIONS_OFFSET);
4092 GateRef transition = Load(VariableType::JS_POINTER(), hclass, transitionOffset);
4093 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
4094
4095 Label notUndefined(env);
4096 BRANCH(Equal(transition, Undefined()), &exit, ¬Undefined);
4097 Bind(¬Undefined);
4098 {
4099 Label isWeak(env);
4100 Label notWeak(env);
4101 BRANCH(TaggedIsWeak(transition), &isWeak, ¬Weak);
4102 Bind(&isWeak);
4103 {
4104 GateRef transitionHClass = LoadObjectFromWeakRef(transition);
4105 GateRef propNums = GetNumberOfPropsFromHClass(transitionHClass);
4106 GateRef last = Int32Sub(propNums, Int32(1));
4107 GateRef layoutInfo = GetLayoutFromHClass(transitionHClass);
4108 GateRef cachedKey = GetKeyFromLayoutInfo(layoutInfo, last);
4109 GateRef cachedAttr = GetPropAttrFromLayoutInfo(layoutInfo, last);
4110 GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
4111 Label keyMatch(env);
4112 Label isMatch(env);
4113 Label repMatch(env);
4114 BRANCH(Equal(cachedKey, key), &keyMatch, &exit);
4115 Bind(&keyMatch);
4116 {
4117 BRANCH(Int32Equal(metaData, cachedMetaData), &isMatch, &exit);
4118 Bind(&isMatch);
4119 {
4120 BRANCH(CheckHClassForRep(transitionHClass, value), &repMatch, &exit);
4121 Bind(&repMatch);
4122 result = transitionHClass;
4123 Jump(&exit);
4124 }
4125 }
4126 }
4127 Bind(¬Weak);
4128 {
4129 // need to find from dictionary
4130 GateRef entryA = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
4131 Label isFound(env);
4132 BRANCH(Int32NotEqual(entryA, Int32(-1)), &isFound, &exit);
4133 Bind(&isFound);
4134 auto cachedValue = GetValueFromDictionary<TransitionsDictionary>(transition, entryA);
4135 Label valueNotUndefined(env);
4136 Label repMatch(env);
4137 BRANCH(Int64NotEqual(cachedValue, Undefined()), &valueNotUndefined, &exit);
4138 Bind(&valueNotUndefined);
4139 {
4140 GateRef newHClass = LoadObjectFromWeakRef(cachedValue);
4141 BRANCH(CheckHClassForRep(newHClass, value), &repMatch, &exit);
4142 Bind(&repMatch);
4143 result = newHClass;
4144 Jump(&exit);
4145 }
4146 }
4147 }
4148 Bind(&exit);
4149 auto ret = *result;
4150 env->SubCfgExit();
4151 return ret;
4152 }
4153
SetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics)4154 GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn,
4155 ProfileOperation callback, bool defineSemantics)
4156 {
4157 auto env = GetEnvironment();
4158 Label entry(env);
4159 env->SubCfgEntry(&entry);
4160 DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
4161 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
4162 Label exit(env);
4163 Label ifEnd(env);
4164 Label loopHead(env);
4165 Label loopEnd(env);
4166 Label loopExit(env);
4167 Label afterLoop(env);
4168 Label isJsCOWArray(env);
4169 Label isNotJsCOWArray(env);
4170 Label setElementsArray(env);
4171 if (!useOwn && !defineSemantics) {
4172 Jump(&loopHead);
4173 LoopBegin(&loopHead);
4174 }
4175 GateRef hclass = LoadHClass(*holder);
4176 GateRef jsType = GetObjectType(hclass);
4177 Label isSpecialIndex(env);
4178 Label notSpecialIndex(env);
4179 BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
4180 Bind(&isSpecialIndex);
4181 {
4182 // TypeArray
4183 Label isFastTypeArray(env);
4184 Label notFastTypeArray(env);
4185 Label checkIsOnPrototypeChain(env);
4186 Label notTypedArrayProto(env);
4187 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, ¬TypedArrayProto);
4188 Bind(¬TypedArrayProto);
4189 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
4190 Bind(&isFastTypeArray);
4191 {
4192 BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
4193 Bind(&checkIsOnPrototypeChain);
4194 {
4195 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
4196 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
4197 Jump(&exit);
4198 }
4199 }
4200 Bind(¬FastTypeArray);
4201 returnValue = Hole();
4202 Jump(&exit);
4203 }
4204 Bind(¬SpecialIndex);
4205 {
4206 GateRef elements = GetElementsArray(*holder);
4207 Label isDictionaryElement(env);
4208 Label notDictionaryElement(env);
4209 BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
4210 Bind(¬DictionaryElement);
4211 {
4212 Label isReceiver(env);
4213 if (useOwn) {
4214 BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
4215 } else {
4216 BRANCH(Equal(*holder, receiver), &isReceiver, &afterLoop);
4217 }
4218 Bind(&isReceiver);
4219 {
4220 GateRef length = GetLengthOfTaggedArray(elements);
4221 Label inRange(env);
4222 if (useOwn) {
4223 BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
4224 } else {
4225 BRANCH(Int64LessThan(index, length), &inRange, &loopExit);
4226 }
4227 Bind(&inRange);
4228 {
4229 GateRef value1 = GetTaggedValueWithElementsKind(*holder, index);
4230 Label notHole(env);
4231 if (useOwn) {
4232 BRANCH(Int64NotEqual(value1, Hole()), ¬Hole, &ifEnd);
4233 } else {
4234 BRANCH(Int64NotEqual(value1, Hole()), ¬Hole, &loopExit);
4235 }
4236 Bind(¬Hole);
4237 {
4238 BRANCH(IsJsCOWArray(*holder), &isJsCOWArray, &isNotJsCOWArray);
4239 Bind(&isJsCOWArray);
4240 {
4241 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
4242 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4243 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4244 returnValue = Undefined();
4245 Jump(&exit);
4246 }
4247 Bind(&isNotJsCOWArray);
4248 {
4249 Jump(&setElementsArray);
4250 }
4251 Bind(&setElementsArray);
4252 {
4253 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4254 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4255 returnValue = Undefined();
4256 Jump(&exit);
4257 }
4258 }
4259 }
4260 }
4261 }
4262 Bind(&isDictionaryElement);
4263 {
4264 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
4265 Label negtiveOne(env);
4266 Label notNegtiveOne(env);
4267 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
4268 Bind(¬NegtiveOne);
4269 {
4270 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
4271 Label isWritandConfig(env);
4272 Label notWritandConfig(env);
4273 BRANCH(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
4274 &isWritandConfig, ¬WritandConfig);
4275 Bind(&isWritandConfig);
4276 {
4277 Label isAccessor(env);
4278 Label notAccessor(env);
4279 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
4280 Bind(&isAccessor);
4281 if (defineSemantics) {
4282 Jump(&exit);
4283 } else {
4284 GateRef accessor = GetValueFromDictionary<NumberDictionary>(elements, entryA);
4285 Label shouldCall(env);
4286 BRANCH(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
4287 Bind(&shouldCall);
4288 {
4289 returnValue = CallSetterHelper(glue, receiver, accessor, value, callback);
4290 Jump(&exit);
4291 }
4292 }
4293 Bind(¬Accessor);
4294 {
4295 Label holdEqualsRecv(env);
4296 if (useOwn) {
4297 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4298 } else {
4299 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
4300 }
4301 Bind(&holdEqualsRecv);
4302 {
4303 UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
4304 returnValue = Undefined();
4305 Jump(&exit);
4306 }
4307 }
4308 }
4309 Bind(¬WritandConfig);
4310 {
4311 returnValue = Hole();
4312 Jump(&exit);
4313 }
4314 }
4315 Bind(&negtiveOne);
4316 returnValue = Hole();
4317 Jump(&exit);
4318 }
4319 }
4320 if (useOwn) {
4321 Bind(&ifEnd);
4322 } else {
4323 Bind(&loopExit);
4324 {
4325 holder = GetPrototypeFromHClass(LoadHClass(*holder));
4326 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4327 }
4328 Bind(&loopEnd);
4329 LoopEnd(&loopHead, env, glue);
4330 Bind(&afterLoop);
4331 }
4332 Label isExtensible(env);
4333 Label notExtensible(env);
4334 Label throwNotExtensible(env);
4335 BRANCH(IsExtensible(receiver), &isExtensible, ¬Extensible);
4336 Bind(¬Extensible);
4337 {
4338 // fixme(hzzhouzebin) this makes SharedArray's frozen no sense.
4339 BRANCH(IsJsSArray(receiver), &isExtensible, &throwNotExtensible);
4340 }
4341 Bind(&isExtensible);
4342 {
4343 Label success(env);
4344 Label failed(env);
4345 BRANCH(AddElementInternal(glue, receiver, index, value,
4346 Int64(PropertyAttributes::GetDefaultAttributes())), &success, &failed);
4347 Bind(&success);
4348 {
4349 returnValue = Undefined();
4350 Jump(&exit);
4351 }
4352 Bind(&failed);
4353 {
4354 returnValue = Exception();
4355 Jump(&exit);
4356 }
4357 }
4358 Bind(&throwNotExtensible);
4359 {
4360 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
4361 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4362 returnValue = Exception();
4363 Jump(&exit);
4364 }
4365 Bind(&exit);
4366 auto ret = *returnValue;
4367 env->SubCfgExit();
4368 return ret;
4369 }
4370
DefinePropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)4371 GateRef StubBuilder::DefinePropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
4372 {
4373 auto env = GetEnvironment();
4374 Label entry(env);
4375 env->SubCfgEntry(&entry);
4376 DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
4377 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
4378 Label exit(env);
4379 Label ifEnd(env);
4380 Label loopHead(env);
4381 Label loopEnd(env);
4382 Label loopExit(env);
4383 Label afterLoop(env);
4384 Label isJsCOWArray(env);
4385 Label isNotJsCOWArray(env);
4386 Label setElementsArray(env);
4387 GateRef hclass = LoadHClass(*holder);
4388 GateRef jsType = GetObjectType(hclass);
4389 Label isSpecialIndex(env);
4390 Label notSpecialIndex(env);
4391 BRANCH(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
4392 Bind(&isSpecialIndex);
4393 {
4394 Label isFastTypeArray(env);
4395 Label notFastTypeArray(env);
4396 Label checkIsOnPrototypeChain(env);
4397 Label notTypedArrayProto(env);
4398 BRANCH(Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY))), &exit, ¬TypedArrayProto);
4399 Bind(¬TypedArrayProto);
4400 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
4401 Bind(&isFastTypeArray);
4402 {
4403 BRANCH(Equal(*holder, receiver), &checkIsOnPrototypeChain, &exit);
4404 Bind(&checkIsOnPrototypeChain);
4405 {
4406 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
4407 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
4408 Jump(&exit);
4409 }
4410 }
4411 Bind(¬FastTypeArray);
4412 returnValue = Hole();
4413 Jump(&exit);
4414 }
4415 Bind(¬SpecialIndex);
4416 {
4417 GateRef elements = GetElementsArray(*holder);
4418 Label isDictionaryElement(env);
4419 Label notDictionaryElement(env);
4420 BRANCH(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
4421 Bind(¬DictionaryElement);
4422 {
4423 Label isReceiver(env);
4424 BRANCH(Equal(*holder, receiver), &isReceiver, &ifEnd);
4425 Bind(&isReceiver);
4426 {
4427 GateRef length = GetLengthOfTaggedArray(elements);
4428 Label inRange(env);
4429 BRANCH(Int64LessThan(index, length), &inRange, &ifEnd);
4430 Bind(&inRange);
4431 {
4432 GateRef value1 = GetTaggedValueWithElementsKind(*holder, index);
4433 Label notHole(env);
4434 BRANCH(Int64NotEqual(value1, Hole()), ¬Hole, &ifEnd);
4435 Bind(¬Hole);
4436 {
4437 BRANCH(IsJsCOWArray(*holder), &isJsCOWArray, &isNotJsCOWArray);
4438 Bind(&isJsCOWArray);
4439 {
4440 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
4441 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4442 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4443 returnValue = Undefined();
4444 Jump(&exit);
4445 }
4446 Bind(&isNotJsCOWArray);
4447 {
4448 Jump(&setElementsArray);
4449 }
4450 Bind(&setElementsArray);
4451 {
4452 SetValueWithElementsKind(glue, *holder, value, index, Boolean(true),
4453 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4454 returnValue = Undefined();
4455 Jump(&exit);
4456 }
4457 }
4458 }
4459 }
4460 }
4461 Bind(&isDictionaryElement);
4462 {
4463 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
4464 Label negtiveOne(env);
4465 Label notNegtiveOne(env);
4466 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
4467 Bind(¬NegtiveOne);
4468 {
4469 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
4470 Label isWritandConfig(env);
4471 Label notWritandConfig(env);
4472 BRANCH(LogicAndBuilder(env).And(IsWritable(attr)).And(IsConfigable(attr)).Done(),
4473 &isWritandConfig, ¬WritandConfig);
4474 Bind(&isWritandConfig);
4475 {
4476 Label notAccessor(env);
4477 BRANCH(IsAccessor(attr), &exit, ¬Accessor);
4478 Bind(¬Accessor);
4479 {
4480 Label holdEqualsRecv(env);
4481 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4482 Bind(&holdEqualsRecv);
4483 {
4484 UpdateValueInDict<NumberDictionary>(glue, elements, entryA, value);
4485 returnValue = Undefined();
4486 Jump(&exit);
4487 }
4488 }
4489 }
4490 Bind(¬WritandConfig);
4491 {
4492 returnValue = Hole();
4493 Jump(&exit);
4494 }
4495 }
4496 Bind(&negtiveOne);
4497 returnValue = Hole();
4498 Jump(&exit);
4499 }
4500 }
4501 Bind(&ifEnd);
4502 Label isExtensible(env);
4503 Label notExtensible(env);
4504 Label throwNotExtensible(env);
4505 BRANCH(IsExtensible(receiver), &isExtensible, ¬Extensible);
4506 Bind(¬Extensible);
4507 {
4508 BRANCH(IsJsSArray(receiver), &isExtensible, &throwNotExtensible);
4509 }
4510 Bind(&isExtensible);
4511 {
4512 Label success(env);
4513 Label failed(env);
4514 BRANCH(AddElementInternal(glue, receiver, index, value, Int64(PropertyAttributes::GetDefaultAttributes())),
4515 &success, &failed);
4516 Bind(&success);
4517 {
4518 returnValue = Undefined();
4519 Jump(&exit);
4520 }
4521 Bind(&failed);
4522 {
4523 returnValue = Exception();
4524 Jump(&exit);
4525 }
4526 }
4527 Bind(&throwNotExtensible);
4528 {
4529 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
4530 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4531 returnValue = Exception();
4532 Jump(&exit);
4533 }
4534 Bind(&exit);
4535 auto ret = *returnValue;
4536 env->SubCfgExit();
4537 return ret;
4538 }
4539
SetPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,GateRef isInternal,ProfileOperation callback,bool canUseIsInternal,bool defineSemantics)4540 GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
4541 bool useOwn, GateRef isInternal, ProfileOperation callback, bool canUseIsInternal, bool defineSemantics)
4542 {
4543 auto env = GetEnvironment();
4544 Label entryPass(env);
4545 env->SubCfgEntry(&entryPass);
4546 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4547 DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
4548 DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
4549 Label exit(env);
4550 Label ifEnd(env);
4551 Label loopHead(env);
4552 Label loopEnd(env);
4553 Label loopExit(env);
4554 Label afterLoop(env);
4555 Label findProperty(env);
4556 if (!useOwn) {
4557 Jump(&loopHead);
4558 LoopBegin(&loopHead);
4559 }
4560 GateRef hclass = LoadHClass(*holder);
4561 GateRef jsType = GetObjectType(hclass);
4562 Label isSIndexObj(env);
4563 Label notSIndexObj(env);
4564 BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
4565 Bind(&isSIndexObj);
4566 {
4567 Label isFastTypeArray(env);
4568 Label notFastTypeArray(env);
4569 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
4570 Bind(&isFastTypeArray);
4571 {
4572 result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
4573 Label isNull(env);
4574 Label notNull(env);
4575 BRANCH(TaggedIsNull(*result), &isNull, ¬Null);
4576 Bind(&isNull);
4577 {
4578 result = Hole();
4579 Jump(&exit);
4580 }
4581 Bind(¬Null);
4582 BRANCH(TaggedIsHole(*result), ¬SIndexObj, &exit);
4583 }
4584 Bind(¬FastTypeArray);
4585
4586 Label isSpecialContainer(env);
4587 Label notSpecialContainer(env);
4588 BRANCH(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
4589 Bind(&isSpecialContainer);
4590 {
4591 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
4592 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4593 result = Exception();
4594 Jump(&exit);
4595 }
4596 Bind(¬SpecialContainer);
4597 {
4598 result = Hole();
4599 Jump(&exit);
4600 }
4601 }
4602 Bind(¬SIndexObj);
4603 {
4604 if (canUseIsInternal) {
4605 if (useOwn) {
4606 BRANCH(isInternal, &findProperty, &ifEnd);
4607 } else {
4608 BRANCH(isInternal, &findProperty, &loopExit);
4609 }
4610 } else {
4611 Jump(&findProperty);
4612 }
4613 Label isDicMode(env);
4614 Label notDicMode(env);
4615 Bind(&findProperty);
4616 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
4617 Bind(¬DicMode);
4618 {
4619 GateRef layOutInfo = GetLayoutFromHClass(hclass);
4620 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4621 GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
4622 Label hasEntry(env);
4623 if (useOwn || defineSemantics) {
4624 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
4625 } else {
4626 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &loopExit);
4627 }
4628 Bind(&hasEntry);
4629 {
4630 GateRef attr = GetPropAttrFromLayoutInfo(layOutInfo, entry);
4631 Label isAccessor(env);
4632 Label notAccessor(env);
4633 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
4634 Bind(&isAccessor);
4635 if (defineSemantics) {
4636 Jump(&exit);
4637 } else {
4638 GateRef accessor = JSObjectGetProperty(*holder, hclass, attr);
4639 Label shouldCall(env);
4640 BRANCH(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
4641 Bind(&shouldCall);
4642 {
4643 result = CallSetterHelper(glue, receiver, accessor, value, callback);
4644 Jump(&exit);
4645 }
4646 }
4647 Bind(¬Accessor);
4648 {
4649 Label writable(env);
4650 Label notWritable(env);
4651 BRANCH(IsWritable(attr), &writable, ¬Writable);
4652 Bind(¬Writable);
4653 if (defineSemantics) {
4654 Jump(&exit);
4655 } else {
4656 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
4657 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4658 result = Exception();
4659 Jump(&exit);
4660 }
4661 Bind(&writable);
4662 {
4663 Label isTS(env);
4664 Label notTS(env);
4665 BRANCH(IsTSHClass(hclass), &isTS, ¬TS);
4666 Bind(&isTS);
4667 {
4668 GateRef attrVal = JSObjectGetProperty(*holder, hclass, attr);
4669 Label attrValIsHole(env);
4670 BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬TS);
4671 Bind(&attrValIsHole);
4672 {
4673 Label storeReceiverHoleEntry(env);
4674 Label noNeedStore(env);
4675 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
4676 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
4677 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
4678 &storeReceiverHoleEntry, &noNeedStore);
4679 Bind(&storeReceiverHoleEntry);
4680 {
4681 receiverHoleEntry = entry;
4682 Jump(&noNeedStore);
4683 }
4684 Bind(&noNeedStore);
4685 if (useOwn || defineSemantics) {
4686 Jump(&ifEnd);
4687 } else {
4688 Jump(&loopExit);
4689 }
4690 }
4691 }
4692 Bind(¬TS);
4693 Label holdEqualsRecv(env);
4694 if (useOwn || defineSemantics) {
4695 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4696 } else {
4697 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
4698 }
4699 Bind(&holdEqualsRecv);
4700 {
4701 Label executeSetProp(env);
4702 CheckUpdateSharedType(false, &result, glue, receiver, attr, value, &executeSetProp, &exit);
4703 Bind(&executeSetProp);
4704 JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
4705 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value, callback);
4706 result = Undefined();
4707 Jump(&exit);
4708 }
4709 }
4710 }
4711 }
4712 }
4713 Bind(&isDicMode);
4714 {
4715 GateRef array = GetPropertiesArray(*holder);
4716 GateRef entry1 = FindEntryFromNameDictionary(glue, array, key);
4717 Label notNegtiveOne(env);
4718 if (useOwn || defineSemantics) {
4719 BRANCH(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &ifEnd);
4720 } else {
4721 BRANCH(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &loopExit);
4722 }
4723 Bind(¬NegtiveOne);
4724 {
4725 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(array, entry1);
4726 Label isAccessor1(env);
4727 Label notAccessor1(env);
4728 BRANCH(IsAccessor(attr1), &isAccessor1, ¬Accessor1);
4729 Bind(&isAccessor1);
4730 if (defineSemantics) {
4731 Jump(&exit);
4732 } else {
4733 GateRef accessor1 = GetValueFromDictionary<NameDictionary>(array, entry1);
4734 Label shouldCall1(env);
4735 BRANCH(ShouldCallSetter(receiver, *holder, accessor1, attr1), &shouldCall1, ¬Accessor1);
4736 Bind(&shouldCall1);
4737 {
4738 result = CallSetterHelper(glue, receiver, accessor1, value, callback);
4739 Jump(&exit);
4740 }
4741 }
4742 Bind(¬Accessor1);
4743 {
4744 Label writable1(env);
4745 Label notWritable1(env);
4746 BRANCH(IsWritable(attr1), &writable1, ¬Writable1);
4747 Bind(¬Writable1);
4748 if (defineSemantics) {
4749 Jump(&exit);
4750 } else {
4751 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
4752 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4753 result = Exception();
4754 Jump(&exit);
4755 }
4756 Bind(&writable1);
4757 {
4758 Label holdEqualsRecv1(env);
4759 if (useOwn) {
4760 BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
4761 } else {
4762 BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &afterLoop);
4763 }
4764 Bind(&holdEqualsRecv1);
4765 {
4766 Label executeSetProp(env);
4767 CheckUpdateSharedType(true, &result, glue, receiver, attr1, value, &executeSetProp, &exit);
4768 Bind(&executeSetProp);
4769 UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
4770 result = Undefined();
4771 Jump(&exit);
4772 }
4773 }
4774 }
4775 }
4776 }
4777 }
4778 if (useOwn || defineSemantics) {
4779 Bind(&ifEnd);
4780 } else {
4781 Bind(&loopExit);
4782 {
4783 holder = GetPrototypeFromHClass(LoadHClass(*holder));
4784 BRANCH(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
4785 }
4786 Bind(&loopEnd);
4787 LoopEnd(&loopHead, env, glue);
4788 Bind(&afterLoop);
4789 }
4790 Label holeEntryNotNegtiveOne(env);
4791 Label holeEntryIfEnd(env);
4792 BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
4793 Bind(&holeEntryNotNegtiveOne);
4794 {
4795 GateRef receiverHClass = LoadHClass(receiver);
4796 GateRef receiverLayoutInfo = GetLayoutFromHClass(receiverHClass);
4797 GateRef holeAttr = GetPropAttrFromLayoutInfo(receiverLayoutInfo, *receiverHoleEntry);
4798 JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
4799 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
4800 result = Undefined();
4801 Jump(&exit);
4802 }
4803 Bind(&holeEntryIfEnd);
4804
4805 Label extensible(env);
4806 Label inextensible(env);
4807 BRANCH(IsExtensible(receiver), &extensible, &inextensible);
4808 Bind(&inextensible);
4809 {
4810 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
4811 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4812 result = Exception();
4813 Jump(&exit);
4814 }
4815 Bind(&extensible);
4816 {
4817 result = AddPropertyByName(glue, receiver, key, value,
4818 Int64(PropertyAttributes::GetDefaultAttributes()), callback);
4819 Jump(&exit);
4820 }
4821 Bind(&exit);
4822 auto ret = *result;
4823 env->SubCfgExit();
4824 return ret;
4825 }
4826
DefinePropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef isInternal,GateRef SCheckModelIsCHECK,ProfileOperation callback)4827 GateRef StubBuilder::DefinePropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
4828 GateRef isInternal, GateRef SCheckModelIsCHECK, ProfileOperation callback)
4829 {
4830 auto env = GetEnvironment();
4831 Label entryPass(env);
4832 env->SubCfgEntry(&entryPass);
4833 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4834 DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
4835 DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
4836 Label exit(env);
4837 Label ifEnd(env);
4838 Label loopHead(env);
4839 Label loopEnd(env);
4840 Label loopExit(env);
4841 Label afterLoop(env);
4842 Label findProperty(env);
4843
4844 GateRef hclass = LoadHClass(*holder);
4845 GateRef jsType = GetObjectType(hclass);
4846 Label isSIndexObj(env);
4847 Label notSIndexObj(env);
4848 BRANCH(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
4849 Bind(&isSIndexObj);
4850 {
4851 Label isFastTypeArray(env);
4852 Label notFastTypeArray(env);
4853 BRANCH(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
4854 Bind(&isFastTypeArray);
4855 {
4856 result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
4857 Label isNull(env);
4858 Label notNull(env);
4859 BRANCH(TaggedIsNull(*result), &isNull, ¬Null);
4860 Bind(&isNull);
4861 {
4862 result = Hole();
4863 Jump(&exit);
4864 }
4865 Bind(¬Null);
4866 BRANCH(TaggedIsHole(*result), ¬SIndexObj, &exit);
4867 }
4868 Bind(¬FastTypeArray);
4869
4870 Label isSpecialContainer(env);
4871 Label notSpecialContainer(env);
4872 BRANCH(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
4873 Bind(&isSpecialContainer);
4874 {
4875 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
4876 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4877 result = Exception();
4878 Jump(&exit);
4879 }
4880 Bind(¬SpecialContainer);
4881 {
4882 result = Hole();
4883 Jump(&exit);
4884 }
4885 }
4886 Bind(¬SIndexObj);
4887 {
4888 BRANCH(isInternal, &findProperty, &ifEnd);
4889 Label isDicMode(env);
4890 Label notDicMode(env);
4891 Bind(&findProperty);
4892 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
4893 Bind(¬DicMode);
4894 {
4895 GateRef layOutInfo = GetLayoutFromHClass(hclass);
4896 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
4897 GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
4898 Label hasEntry(env);
4899 BRANCH(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
4900 Bind(&hasEntry);
4901 {
4902 GateRef attr = GetPropAttrFromLayoutInfo(layOutInfo, entry);
4903 Label isAccessor(env);
4904 Label notAccessor(env);
4905 Label isSCheckModelIsCHECK1(env);
4906 Label isNotSCheckModelIsCHECK1(env);
4907 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
4908 Bind(&isAccessor);
4909 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK1, &isNotSCheckModelIsCHECK1);
4910 Bind(&isSCheckModelIsCHECK1);
4911 {
4912 Jump(&exit);
4913 }
4914 Bind(&isNotSCheckModelIsCHECK1);
4915 GateRef accessor = JSObjectGetProperty(*holder, hclass, attr);
4916 Label shouldCall(env);
4917 BRANCH(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
4918 Bind(&shouldCall);
4919 {
4920 result = CallSetterHelper(glue, receiver, accessor, value, callback);
4921 Jump(&exit);
4922 }
4923 Bind(¬Accessor);
4924 {
4925 Label writable(env);
4926 Label notWritable(env);
4927 Label isSCheckModelIsCHECK2(env);
4928 Label isNotSCheckModelIsCHECK2(env);
4929 BRANCH(IsWritable(attr), &writable, ¬Writable);
4930 Bind(¬Writable);
4931 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK2, &isNotSCheckModelIsCHECK2);
4932 Bind(&isSCheckModelIsCHECK2);
4933 {
4934 Jump(&exit);
4935 }
4936 Bind(&isNotSCheckModelIsCHECK2);
4937 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
4938 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4939 result = Exception();
4940 Jump(&exit);
4941 Bind(&writable);
4942 {
4943 Label isTS(env);
4944 Label notTS(env);
4945 BRANCH(IsTSHClass(hclass), &isTS, ¬TS);
4946 Bind(&isTS);
4947 {
4948 GateRef attrVal = JSObjectGetProperty(*holder, hclass, attr);
4949 Label attrValIsHole(env);
4950 BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬TS);
4951 Bind(&attrValIsHole);
4952 {
4953 Label storeReceiverHoleEntry(env);
4954 Label noNeedStore(env);
4955 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
4956 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
4957 BRANCH(BitAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
4958 &storeReceiverHoleEntry, &ifEnd);
4959 Bind(&storeReceiverHoleEntry);
4960 {
4961 receiverHoleEntry = entry;
4962 Jump(&ifEnd);
4963 }
4964 }
4965 }
4966 Bind(¬TS);
4967 Label holdEqualsRecv(env);
4968 BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
4969 Bind(&holdEqualsRecv);
4970 {
4971 Label executeSetProp(env);
4972 CheckUpdateSharedType(false, &result, glue, receiver, attr, value,
4973 &executeSetProp, &exit, SCheckModelIsCHECK);
4974 Bind(&executeSetProp);
4975 JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
4976 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value, callback);
4977 result = Undefined();
4978 Jump(&exit);
4979 }
4980 }
4981 }
4982 }
4983 }
4984 Bind(&isDicMode);
4985 {
4986 GateRef array = GetPropertiesArray(*holder);
4987 GateRef entry1 = FindEntryFromNameDictionary(glue, array, key);
4988 Label notNegtiveOne(env);
4989 BRANCH(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &ifEnd);
4990 Bind(¬NegtiveOne);
4991 {
4992 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(array, entry1);
4993 Label isAccessor1(env);
4994 Label notAccessor1(env);
4995 Label isSCheckModelIsCHECK3(env);
4996 Label isNotSCheckModelIsCHECK3(env);
4997 BRANCH(IsAccessor(attr1), &isAccessor1, ¬Accessor1);
4998 Bind(&isAccessor1);
4999 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK3, &isNotSCheckModelIsCHECK3);
5000 Bind(&isSCheckModelIsCHECK3);
5001 {
5002 Jump(&exit);
5003 }
5004 Bind(&isNotSCheckModelIsCHECK3);
5005 GateRef accessor1 = GetValueFromDictionary<NameDictionary>(array, entry1);
5006 Label shouldCall1(env);
5007 BRANCH(ShouldCallSetter(receiver, *holder, accessor1, attr1), &shouldCall1, ¬Accessor1);
5008 Bind(&shouldCall1);
5009 {
5010 result = CallSetterHelper(glue, receiver, accessor1, value, callback);
5011 Jump(&exit);
5012 }
5013 Bind(¬Accessor1);
5014 {
5015 Label writable1(env);
5016 Label notWritable1(env);
5017 Label isSCheckModelIsCHECK4(env);
5018 Label isNotSCheckModelIsCHECK4(env);
5019 BRANCH(IsWritable(attr1), &writable1, ¬Writable1);
5020 Bind(¬Writable1);
5021 BRANCH(SCheckModelIsCHECK, &isSCheckModelIsCHECK4, &isNotSCheckModelIsCHECK4);
5022 Bind(&isSCheckModelIsCHECK4);
5023 {
5024 Jump(&exit);
5025 }
5026 Bind(&isNotSCheckModelIsCHECK4);
5027 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
5028 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5029 result = Exception();
5030 Jump(&exit);
5031 Bind(&writable1);
5032 {
5033 Label holdEqualsRecv1(env);
5034 BRANCH(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
5035 Bind(&holdEqualsRecv1);
5036 {
5037 Label executeSetProp(env);
5038 CheckUpdateSharedType(true, &result, glue, receiver, attr1,
5039 value, &executeSetProp, &exit, SCheckModelIsCHECK);
5040 Bind(&executeSetProp);
5041 UpdateValueInDict<NameDictionary>(glue, array, entry1, value);
5042 result = Undefined();
5043 Jump(&exit);
5044 }
5045 }
5046 }
5047 }
5048 }
5049 }
5050 Bind(&ifEnd);
5051 Label holeEntryNotNegtiveOne(env);
5052 Label holeEntryIfEnd(env);
5053 BRANCH(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
5054 Bind(&holeEntryNotNegtiveOne);
5055 {
5056 GateRef receiverHClass = LoadHClass(receiver);
5057 GateRef receiverLayoutInfo = GetLayoutFromHClass(receiverHClass);
5058 GateRef holeAttr = GetPropAttrFromLayoutInfo(receiverLayoutInfo, *receiverHoleEntry);
5059 JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
5060 ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
5061 result = Undefined();
5062 Jump(&exit);
5063 }
5064 Bind(&holeEntryIfEnd);
5065
5066 Label extensible(env);
5067 Label inextensible(env);
5068 BRANCH(IsExtensible(receiver), &extensible, &inextensible);
5069 Bind(&inextensible);
5070 {
5071 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
5072 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5073 result = Exception();
5074 Jump(&exit);
5075 }
5076 Bind(&extensible);
5077 {
5078 result = AddPropertyByName(glue, receiver, key, value,
5079 Int64(PropertyAttributes::GetDefaultAttributes()), callback);
5080 Jump(&exit);
5081 }
5082 Bind(&exit);
5083 auto ret = *result;
5084 env->SubCfgExit();
5085 return ret;
5086 }
5087
SetPropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn,ProfileOperation callback,bool defineSemantics)5088 GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn,
5089 ProfileOperation callback, bool defineSemantics)
5090 {
5091 auto env = GetEnvironment();
5092 Label subEntry1(env);
5093 env->SubCfgEntry(&subEntry1);
5094 DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5095 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5096 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5097 Label isNumberOrStringSymbol(env);
5098 Label notNumber(env);
5099 Label isStringOrSymbol(env);
5100 Label notStringOrSymbol(env);
5101 Label exit(env);
5102 BRANCH(TaggedIsNumber(*varKey), &isNumberOrStringSymbol, ¬Number);
5103 Bind(¬Number);
5104 {
5105 BRANCH(TaggedIsStringOrSymbol(*varKey), &isNumberOrStringSymbol, ¬StringOrSymbol);
5106 Bind(¬StringOrSymbol);
5107 {
5108 result = Hole();
5109 Jump(&exit);
5110 }
5111 }
5112 Bind(&isNumberOrStringSymbol);
5113 {
5114 GateRef index64 = TryToElementsIndex(glue, *varKey);
5115 Label validIndex(env);
5116 Label notValidIndex(env);
5117 Label greaterThanInt32Max(env);
5118 Label notGreaterThanInt32Max(env);
5119 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
5120 Bind(&greaterThanInt32Max);
5121 {
5122 Jump(&exit);
5123 }
5124 Bind(¬GreaterThanInt32Max);
5125 GateRef index = TruncInt64ToInt32(index64);
5126 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
5127 Bind(&validIndex);
5128 {
5129 result = SetPropertyByIndex(glue, receiver, index, value, useOwn, callback, defineSemantics);
5130 Jump(&exit);
5131 }
5132 Bind(¬ValidIndex);
5133 {
5134 Label isNumber1(env);
5135 Label notNumber1(env);
5136 Label setByName(env);
5137 BRANCH(TaggedIsNumber(*varKey), &isNumber1, ¬Number1);
5138 Bind(&isNumber1);
5139 {
5140 result = Hole();
5141 Jump(&exit);
5142 }
5143 Label isString(env);
5144 Label checkDetector(env);
5145 Bind(¬Number1);
5146 {
5147 Label notIntenalString(env);
5148 BRANCH(TaggedIsString(*varKey), &isString, &checkDetector);
5149 Bind(&isString);
5150 {
5151 BRANCH(IsInternalString(*varKey), &setByName, ¬IntenalString);
5152 Bind(¬IntenalString);
5153 {
5154 Label notFind(env);
5155 Label find(env);
5156 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
5157 BRANCH(TaggedIsHole(res), ¬Find, &find);
5158 Bind(¬Find);
5159 {
5160 varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
5161 isInternal = False();
5162 Jump(&checkDetector);
5163 }
5164 Bind(&find);
5165 {
5166 varKey = res;
5167 Jump(&checkDetector);
5168 }
5169 }
5170 }
5171 }
5172 Bind(&checkDetector);
5173 CheckDetectorName(glue, *varKey, &setByName, &exit);
5174 Bind(&setByName);
5175 {
5176 result = SetPropertyByName(glue, receiver, *varKey, value, useOwn, *isInternal,
5177 callback, true, defineSemantics);
5178 Jump(&exit);
5179 }
5180 }
5181 }
5182 Bind(&exit);
5183 auto ret = *result;
5184 env->SubCfgExit();
5185 return ret;
5186 }
5187
DefinePropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef SCheckModelIsCHECK,ProfileOperation callback)5188 GateRef StubBuilder::DefinePropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value,
5189 GateRef SCheckModelIsCHECK, ProfileOperation callback)
5190 {
5191 auto env = GetEnvironment();
5192 Label subEntry1(env);
5193 env->SubCfgEntry(&subEntry1);
5194 DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
5195 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5196 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5197 Label isNumberOrStringSymbol(env);
5198 Label notNumber(env);
5199 Label isStringOrSymbol(env);
5200 Label notStringOrSymbol(env);
5201 Label exit(env);
5202 BRANCH(TaggedIsNumber(*varKey), &isNumberOrStringSymbol, ¬Number);
5203 Bind(¬Number);
5204 {
5205 BRANCH(TaggedIsStringOrSymbol(*varKey), &isNumberOrStringSymbol, ¬StringOrSymbol);
5206 Bind(¬StringOrSymbol);
5207 {
5208 result = Hole();
5209 Jump(&exit);
5210 }
5211 }
5212 Bind(&isNumberOrStringSymbol);
5213 {
5214 GateRef index64 = TryToElementsIndex(glue, *varKey);
5215 Label validIndex(env);
5216 Label notValidIndex(env);
5217 Label greaterThanInt32Max(env);
5218 Label notGreaterThanInt32Max(env);
5219 BRANCH(Int64GreaterThanOrEqual(index64, Int64(INT32_MAX)), &greaterThanInt32Max, ¬GreaterThanInt32Max);
5220 Bind(&greaterThanInt32Max);
5221 {
5222 Jump(&exit);
5223 }
5224 Bind(¬GreaterThanInt32Max);
5225 GateRef index = TruncInt64ToInt32(index64);
5226 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
5227 Bind(&validIndex);
5228 {
5229 result = DefinePropertyByIndex(glue, receiver, index, value);
5230 Jump(&exit);
5231 }
5232 Bind(¬ValidIndex);
5233 {
5234 Label isNumber1(env);
5235 Label notNumber1(env);
5236 Label setByName(env);
5237 BRANCH(TaggedIsNumber(*varKey), &isNumber1, ¬Number1);
5238 Bind(&isNumber1);
5239 {
5240 result = Hole();
5241 Jump(&exit);
5242 }
5243 Label isString(env);
5244 Label checkDetector(env);
5245 Bind(¬Number1);
5246 {
5247 Label notIntenalString(env);
5248 BRANCH(TaggedIsString(*varKey), &isString, &checkDetector);
5249 Bind(&isString);
5250 {
5251 BRANCH(IsInternalString(*varKey), &setByName, ¬IntenalString);
5252 Bind(¬IntenalString);
5253 {
5254 Label notFind(env);
5255 Label find(env);
5256 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *varKey });
5257 BRANCH(TaggedIsHole(res), ¬Find, &find);
5258 Bind(¬Find);
5259 {
5260 varKey = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { *varKey });
5261 isInternal = False();
5262 Jump(&checkDetector);
5263 }
5264 Bind(&find);
5265 {
5266 varKey = res;
5267 Jump(&checkDetector);
5268 }
5269 }
5270 }
5271 }
5272 Bind(&checkDetector);
5273 CheckDetectorName(glue, *varKey, &setByName, &exit);
5274 Bind(&setByName);
5275 {
5276 result = DefinePropertyByName(glue, receiver, *varKey, value, *isInternal,
5277 SCheckModelIsCHECK, callback);
5278 Jump(&exit);
5279 }
5280 }
5281 }
5282 Bind(&exit);
5283 auto ret = *result;
5284 env->SubCfgExit();
5285 return ret;
5286 }
5287
SetPropertiesToLexicalEnv(GateRef glue,GateRef object,GateRef index,GateRef value)5288 void StubBuilder::SetPropertiesToLexicalEnv(GateRef glue, GateRef object, GateRef index, GateRef value)
5289 {
5290 GateRef valueIndex = Int32Add(index, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
5291 SetValueToTaggedArray(VariableType::JS_ANY(), glue, object, valueIndex, value);
5292 }
5293
NotifyHClassChanged(GateRef glue,GateRef oldHClass,GateRef newHClass)5294 void StubBuilder::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef newHClass)
5295 {
5296 auto env = GetEnvironment();
5297 Label entry(env);
5298 env->SubCfgEntry(&entry);
5299 Label exit(env);
5300 Label isProtoType(env);
5301 BRANCH(IsProtoTypeHClass(oldHClass), &isProtoType, &exit);
5302 Bind(&isProtoType);
5303 {
5304 Label notEqualHClass(env);
5305 BRANCH(Equal(oldHClass, newHClass), &exit, ¬EqualHClass);
5306 Bind(¬EqualHClass);
5307 {
5308 SetIsProtoTypeToHClass(glue, newHClass, True());
5309 CallRuntime(glue, RTSTUB_ID(NoticeThroughChainAndRefreshUser), { oldHClass, newHClass });
5310 Jump(&exit);
5311 }
5312 }
5313 Bind(&exit);
5314 env->SubCfgExit();
5315 return;
5316 }
5317
GetContainerProperty(GateRef glue,GateRef receiver,GateRef index,GateRef jsType)5318 GateRef StubBuilder::GetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef jsType)
5319 {
5320 auto env = GetEnvironment();
5321 Label entry(env);
5322 env->SubCfgEntry(&entry);
5323 Label exit(env);
5324 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5325
5326 Label isDefaultLabel(env);
5327 Label noDefaultLabel(env);
5328 BRANCH(IsSpecialContainer(jsType), &noDefaultLabel, &isDefaultLabel);
5329 Bind(&noDefaultLabel);
5330 {
5331 result = JSAPIContainerGet(glue, receiver, index);
5332 Jump(&exit);
5333 }
5334 Bind(&isDefaultLabel);
5335 {
5336 Jump(&exit);
5337 }
5338 Bind(&exit);
5339
5340 auto ret = *result;
5341 env->SubCfgExit();
5342 return ret;
5343 }
5344
FastTypeOf(GateRef glue,GateRef obj)5345 GateRef StubBuilder::FastTypeOf(GateRef glue, GateRef obj)
5346 {
5347 auto env = GetEnvironment();
5348 Label entry(env);
5349 env->SubCfgEntry(&entry);
5350 Label exit(env);
5351
5352 GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
5353 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
5354 GateRef undefinedIndex = GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX);
5355 GateRef gConstUndefinedStr = Load(VariableType::JS_POINTER(), gConstAddr, undefinedIndex);
5356 DEFVARIABLE(result, VariableType::JS_POINTER(), gConstUndefinedStr);
5357 Label objIsTrue(env);
5358 Label objNotTrue(env);
5359 Label defaultLabel(env);
5360 GateRef gConstBooleanStr = Load(VariableType::JS_POINTER(), gConstAddr,
5361 GetGlobalConstantOffset(ConstantIndex::BOOLEAN_STRING_INDEX));
5362 BRANCH(TaggedIsTrue(obj), &objIsTrue, &objNotTrue);
5363 Bind(&objIsTrue);
5364 {
5365 result = gConstBooleanStr;
5366 Jump(&exit);
5367 }
5368 Bind(&objNotTrue);
5369 {
5370 Label objIsFalse(env);
5371 Label objNotFalse(env);
5372 BRANCH(TaggedIsFalse(obj), &objIsFalse, &objNotFalse);
5373 Bind(&objIsFalse);
5374 {
5375 result = gConstBooleanStr;
5376 Jump(&exit);
5377 }
5378 Bind(&objNotFalse);
5379 {
5380 Label objIsNull(env);
5381 Label objNotNull(env);
5382 BRANCH(TaggedIsNull(obj), &objIsNull, &objNotNull);
5383 Bind(&objIsNull);
5384 {
5385 result = Load(VariableType::JS_POINTER(), gConstAddr,
5386 GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
5387 Jump(&exit);
5388 }
5389 Bind(&objNotNull);
5390 {
5391 Label objIsUndefined(env);
5392 Label objNotUndefined(env);
5393 BRANCH(TaggedIsUndefined(obj), &objIsUndefined, &objNotUndefined);
5394 Bind(&objIsUndefined);
5395 {
5396 result = Load(VariableType::JS_POINTER(), gConstAddr,
5397 GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX));
5398 Jump(&exit);
5399 }
5400 Bind(&objNotUndefined);
5401 Jump(&defaultLabel);
5402 }
5403 }
5404 }
5405 Bind(&defaultLabel);
5406 {
5407 Label objIsHeapObject(env);
5408 Label objNotHeapObject(env);
5409 BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
5410 Bind(&objIsHeapObject);
5411 {
5412 Label objIsString(env);
5413 Label objNotString(env);
5414 BRANCH(IsString(obj), &objIsString, &objNotString);
5415 Bind(&objIsString);
5416 {
5417 result = Load(VariableType::JS_POINTER(), gConstAddr,
5418 GetGlobalConstantOffset(ConstantIndex::STRING_STRING_INDEX));
5419 Jump(&exit);
5420 }
5421 Bind(&objNotString);
5422 {
5423 Label objIsSymbol(env);
5424 Label objNotSymbol(env);
5425 BRANCH(IsSymbol(obj), &objIsSymbol, &objNotSymbol);
5426 Bind(&objIsSymbol);
5427 {
5428 result = Load(VariableType::JS_POINTER(), gConstAddr,
5429 GetGlobalConstantOffset(ConstantIndex::SYMBOL_STRING_INDEX));
5430 Jump(&exit);
5431 }
5432 Bind(&objNotSymbol);
5433 {
5434 Label objIsCallable(env);
5435 Label objNotCallable(env);
5436 BRANCH(IsCallable(obj), &objIsCallable, &objNotCallable);
5437 Bind(&objIsCallable);
5438 {
5439 result = Load(VariableType::JS_POINTER(), gConstAddr,
5440 GetGlobalConstantOffset(ConstantIndex::FUNCTION_STRING_INDEX));
5441 Jump(&exit);
5442 }
5443 Bind(&objNotCallable);
5444 {
5445 Label objIsBigInt(env);
5446 Label objNotBigInt(env);
5447 BRANCH(TaggedObjectIsBigInt(obj), &objIsBigInt, &objNotBigInt);
5448 Bind(&objIsBigInt);
5449 {
5450 result = Load(VariableType::JS_POINTER(), gConstAddr,
5451 GetGlobalConstantOffset(ConstantIndex::BIGINT_STRING_INDEX));
5452 Jump(&exit);
5453 }
5454 Bind(&objNotBigInt);
5455 {
5456 Label objIsNativeModuleFailureInfo(env);
5457 Label objNotNativeModuleFailureInfo(env);
5458 BRANCH(IsNativeModuleFailureInfo(obj), &objIsNativeModuleFailureInfo,
5459 &objNotNativeModuleFailureInfo);
5460 Bind(&objIsNativeModuleFailureInfo);
5461 {
5462 result = Load(VariableType::JS_POINTER(), gConstAddr,
5463 GetGlobalConstantOffset(ConstantIndex::NATIVE_MODULE_FAILURE_INFO_STRING_INDEX));
5464 Jump(&exit);
5465 }
5466 Bind(&objNotNativeModuleFailureInfo);
5467 {
5468 result = Load(VariableType::JS_POINTER(), gConstAddr,
5469 GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
5470 Jump(&exit);
5471 }
5472 }
5473 }
5474 }
5475 }
5476 }
5477 Bind(&objNotHeapObject);
5478 {
5479 Label objIsNum(env);
5480 Label objNotNum(env);
5481 BRANCH(TaggedIsNumber(obj), &objIsNum, &objNotNum);
5482 Bind(&objIsNum);
5483 {
5484 result = Load(VariableType::JS_POINTER(), gConstAddr,
5485 GetGlobalConstantOffset(ConstantIndex::NUMBER_STRING_INDEX));
5486 Jump(&exit);
5487 }
5488 Bind(&objNotNum);
5489 Jump(&exit);
5490 }
5491 }
5492 Bind(&exit);
5493 auto ret = *result;
5494 env->SubCfgExit();
5495 return ret;
5496 }
5497
InstanceOf(GateRef glue,GateRef object,GateRef target,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)5498 GateRef StubBuilder::InstanceOf(
5499 GateRef glue, GateRef object, GateRef target, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
5500 {
5501 auto env = GetEnvironment();
5502 Label entry(env);
5503 env->SubCfgEntry(&entry);
5504 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5505 Label exit(env);
5506
5507 // 1.If Type(target) is not Object, throw a TypeError exception.
5508 Label targetIsHeapObject(env);
5509 Label targetIsEcmaObject(env);
5510 Label targetNotEcmaObject(env);
5511 BRANCH(TaggedIsHeapObject(target), &targetIsHeapObject, &targetNotEcmaObject);
5512 Bind(&targetIsHeapObject);
5513 BRANCH(TaggedObjectIsEcmaObject(target), &targetIsEcmaObject, &targetNotEcmaObject);
5514 Bind(&targetNotEcmaObject);
5515 {
5516 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
5517 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5518 result = Exception();
5519 Jump(&exit);
5520 }
5521 Bind(&targetIsEcmaObject);
5522 {
5523 // 2.Let instOfHandler be GetMethod(target, @@hasInstance).
5524 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
5525 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
5526 GateRef hasInstanceSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
5527 GlobalEnv::HASINSTANCE_SYMBOL_INDEX);
5528 GateRef instof = GetMethod(glue, target, hasInstanceSymbol, profileTypeInfo, slotId);
5529
5530 // 3.ReturnIfAbrupt(instOfHandler).
5531 Label isPendingException(env);
5532 Label noPendingException(env);
5533 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
5534 Bind(&isPendingException);
5535 {
5536 result = Exception();
5537 Jump(&exit);
5538 }
5539 Bind(&noPendingException);
5540
5541 // 4.If instOfHandler is not undefined, then
5542 Label instOfNotUndefined(env);
5543 Label instOfIsUndefined(env);
5544 Label fastPath(env);
5545 Label targetNotCallable(env);
5546 BRANCH(TaggedIsUndefined(instof), &instOfIsUndefined, &instOfNotUndefined);
5547 Bind(&instOfNotUndefined);
5548 {
5549 TryFastHasInstance(glue, instof, target, object, &fastPath, &exit, &result, callback);
5550 }
5551 Bind(&instOfIsUndefined);
5552 {
5553 // 5.If IsCallable(target) is false, throw a TypeError exception.
5554 BRANCH(IsCallable(target), &fastPath, &targetNotCallable);
5555 Bind(&targetNotCallable);
5556 {
5557 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
5558 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5559 result = Exception();
5560 Jump(&exit);
5561 }
5562 }
5563 Bind(&fastPath);
5564 {
5565 // 6.Return ? OrdinaryHasInstance(target, object).
5566 result = OrdinaryHasInstance(glue, target, object);
5567 Jump(&exit);
5568 }
5569 }
5570 Bind(&exit);
5571 auto ret = *result;
5572 env->SubCfgExit();
5573 return ret;
5574 }
5575
TryFastHasInstance(GateRef glue,GateRef instof,GateRef target,GateRef object,Label * fastPath,Label * exit,Variable * result,ProfileOperation callback)5576 void StubBuilder::TryFastHasInstance(GateRef glue, GateRef instof, GateRef target, GateRef object, Label *fastPath,
5577 Label *exit, Variable *result, ProfileOperation callback)
5578 {
5579 auto env = GetEnvironment();
5580
5581 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
5582 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
5583 GateRef function = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::HASINSTANCE_FUNCTION_INDEX);
5584
5585 Label slowPath(env);
5586 Label tryFastPath(env);
5587 Label callExit(env);
5588 GateRef isEqual = IntPtrEqual(instof, function);
5589 BRANCH(isEqual, &tryFastPath, &slowPath);
5590 Bind(&tryFastPath);
5591 Jump(fastPath);
5592 Bind(&slowPath);
5593 {
5594 JSCallArgs callArgs(JSCallMode::CALL_SETTER);
5595 callArgs.callSetterArgs = { target, object };
5596 if (env->IsBaselineBuiltin()) {
5597 DEFVARIABLE(callRes, VariableType::JS_ANY(), Undefined());
5598 CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, &callRes, Circuit::NullGate(), callArgs,
5599 callback);
5600 callBuilder.JSCallDispatchForBaseline(&callExit);
5601 Bind(&callExit);
5602 result->WriteVariable(FastToBoolean(*callRes));
5603 } else {
5604 CallStubBuilder callBuilder(this, glue, instof, Int32(1), 0, nullptr, Circuit::NullGate(), callArgs,
5605 callback);
5606 GateRef retValue = callBuilder.JSCallDispatch();
5607 result->WriteVariable(FastToBoolean(retValue));
5608 }
5609 Jump(exit);
5610 }
5611 }
5612
GetMethod(GateRef glue,GateRef obj,GateRef key,GateRef profileTypeInfo,GateRef slotId)5613 GateRef StubBuilder::GetMethod(GateRef glue, GateRef obj, GateRef key, GateRef profileTypeInfo, GateRef slotId)
5614 {
5615 auto env = GetEnvironment();
5616 Label entry(env);
5617 env->SubCfgEntry(&entry);
5618 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5619 Label exit(env);
5620
5621 StringIdInfo info;
5622 AccessObjectStubBuilder builder(this);
5623 GateRef value = builder.LoadObjByName(glue, obj, key, info, profileTypeInfo, slotId, ProfileOperation());
5624
5625 Label isPendingException(env);
5626 Label noPendingException(env);
5627 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
5628 Bind(&isPendingException);
5629 {
5630 result = Exception();
5631 Jump(&exit);
5632 }
5633 Bind(&noPendingException);
5634 Label valueIsUndefinedOrNull(env);
5635 Label valueNotUndefinedOrNull(env);
5636 BRANCH(TaggedIsUndefinedOrNull(value), &valueIsUndefinedOrNull, &valueNotUndefinedOrNull);
5637 Bind(&valueIsUndefinedOrNull);
5638 {
5639 result = Undefined();
5640 Jump(&exit);
5641 }
5642 Bind(&valueNotUndefinedOrNull);
5643 {
5644 Label valueIsCallable(env);
5645 Label valueNotCallable(env);
5646 Label valueIsHeapObject(env);
5647 BRANCH(TaggedIsHeapObject(value), &valueIsHeapObject, &valueNotCallable);
5648 Bind(&valueIsHeapObject);
5649 BRANCH(IsCallable(value), &valueIsCallable, &valueNotCallable);
5650 Bind(&valueNotCallable);
5651 {
5652 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(NonCallable));
5653 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5654 result = Exception();
5655 Jump(&exit);
5656 }
5657 Bind(&valueIsCallable);
5658 {
5659 result = value;
5660 Jump(&exit);
5661 }
5662 }
5663 Bind(&exit);
5664 auto ret = *result;
5665 env->SubCfgExit();
5666 return ret;
5667 }
5668
FastGetPropertyByName(GateRef glue,GateRef obj,GateRef key,ProfileOperation callback)5669 GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key, ProfileOperation callback)
5670 {
5671 auto env = GetEnvironment();
5672 Label entry(env);
5673 env->SubCfgEntry(&entry);
5674 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5675 Label exit(env);
5676 Label checkResult(env);
5677 Label fastpath(env);
5678 Label slowpath(env);
5679
5680 BRANCH(TaggedIsHeapObject(obj), &fastpath, &slowpath);
5681 Bind(&fastpath);
5682 {
5683 result = GetPropertyByName(glue, obj, key, callback, True());
5684 BRANCH(TaggedIsHole(*result), &slowpath, &exit);
5685 }
5686 Bind(&slowpath);
5687 {
5688 result = CallRuntime(glue, RTSTUB_ID(LoadICByName), { Undefined(), obj, key, IntToTaggedInt(Int32(0)) });
5689 Jump(&exit);
5690 }
5691 Bind(&exit);
5692 auto ret = *result;
5693 env->SubCfgExit();
5694 return ret;
5695 }
5696
FastGetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,ProfileOperation callback,GateRef hir)5697 GateRef StubBuilder::FastGetPropertyByIndex(GateRef glue, GateRef obj,
5698 GateRef index, ProfileOperation callback, GateRef hir)
5699 {
5700 auto env = GetEnvironment();
5701 Label entry(env);
5702 env->SubCfgEntry(&entry);
5703 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5704 Label exit(env);
5705 Label fastPath(env);
5706 Label slowPath(env);
5707
5708 BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
5709 Bind(&fastPath);
5710 {
5711 result = GetPropertyByIndex(glue, obj, index, callback, hir);
5712 Label notHole(env);
5713 BRANCH(TaggedIsHole(*result), &slowPath, &exit);
5714 }
5715 Bind(&slowPath);
5716 {
5717 result = CallRuntime(glue, RTSTUB_ID(LdObjByIndex),
5718 { obj, IntToTaggedInt(index), TaggedFalse(), Undefined() });
5719 Jump(&exit);
5720 }
5721 Bind(&exit);
5722 auto ret = *result;
5723 env->SubCfgExit();
5724 return ret;
5725 }
5726
FastSetPropertyByName(GateRef glue,GateRef obj,GateRef key,GateRef value,ProfileOperation callback)5727 void StubBuilder::FastSetPropertyByName(GateRef glue, GateRef obj, GateRef key, GateRef value,
5728 ProfileOperation callback)
5729 {
5730 auto env = GetEnvironment();
5731 Label entry(env);
5732 env->SubCfgEntry(&entry);
5733 DEFVARIABLE(keyVar, VariableType::JS_ANY(), key);
5734 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5735 DEFVARIABLE(isInternal, VariableType::BOOL(), True());
5736 Label exit(env);
5737 Label fastPath(env);
5738 Label slowPath(env);
5739 BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
5740 Bind(&fastPath);
5741 {
5742 Label isString(env);
5743 Label getByName(env);
5744 Label isInternalString(env);
5745 Label notIntenalString(env);
5746 BRANCH(TaggedIsString(*keyVar), &isString, &getByName);
5747 Bind(&isString);
5748 {
5749 BRANCH(IsInternalString(*keyVar), &isInternalString, ¬IntenalString);
5750 Bind(&isInternalString);
5751 Jump(&getByName);
5752 Bind(¬IntenalString);
5753 {
5754 Label notFind(env);
5755 Label find(env);
5756 GateRef res = CallRuntime(glue, RTSTUB_ID(TryGetInternString), { *keyVar });
5757 BRANCH(TaggedIsHole(res), ¬Find, &find);
5758 Bind(¬Find);
5759 {
5760 keyVar = CallRuntime(glue, RTSTUB_ID(InsertStringToTable), { key });
5761 isInternal = False();
5762 Jump(&getByName);
5763 }
5764 Bind(&find);
5765 {
5766 keyVar = res;
5767 Jump(&getByName);
5768 }
5769 }
5770 }
5771 Bind(&getByName);
5772
5773 result = SetPropertyByName(glue, obj, *keyVar, value, false, *isInternal, callback, true);
5774 Label notHole(env);
5775 BRANCH(TaggedIsHole(*result), &slowPath, &exit);
5776 }
5777 Bind(&slowPath);
5778 {
5779 result = CallRuntime(glue, RTSTUB_ID(StoreICByValue), { obj, *keyVar, value, IntToTaggedInt(Int32(0)) });
5780 Jump(&exit);
5781 }
5782 Bind(&exit);
5783 env->SubCfgExit();
5784 }
5785
FastSetPropertyByIndex(GateRef glue,GateRef obj,GateRef index,GateRef value)5786 void StubBuilder::FastSetPropertyByIndex(GateRef glue, GateRef obj, GateRef index, GateRef value)
5787 {
5788 auto env = GetEnvironment();
5789 Label entry(env);
5790 env->SubCfgEntry(&entry);
5791 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5792 Label exit(env);
5793 Label fastPath(env);
5794 Label slowPath(env);
5795
5796 BRANCH(TaggedIsHeapObject(obj), &fastPath, &slowPath);
5797 Bind(&fastPath);
5798 {
5799 result = SetPropertyByIndex(glue, obj, index, value, false);
5800 Label notHole(env);
5801 BRANCH(TaggedIsHole(*result), &slowPath, &exit);
5802 }
5803 Bind(&slowPath);
5804 {
5805 result = CallRuntime(glue, RTSTUB_ID(StObjByIndex),
5806 { obj, IntToTaggedInt(index), value });
5807 Jump(&exit);
5808 }
5809 Bind(&exit);
5810 env->SubCfgExit();
5811 }
5812
GetCtorPrototype(GateRef ctor)5813 GateRef StubBuilder::GetCtorPrototype(GateRef ctor)
5814 {
5815 auto env = GetEnvironment();
5816 Label entry(env);
5817 env->SubCfgEntry(&entry);
5818 DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
5819 Label exit(env);
5820 Label isHClass(env);
5821 Label isPrototype(env);
5822 Label isHeapObject(env);
5823 Label notHeapObject(env);
5824
5825 GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), ctor, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
5826 BRANCH(TaggedIsHeapObject(ctorProtoOrHC), &isHeapObject, ¬HeapObject);
5827 Bind(¬HeapObject);
5828 {
5829 // If go slow path, return hole.
5830 constructorPrototype = Hole();
5831 Jump(&exit);
5832 }
5833 Bind(&isHeapObject);
5834 BRANCH(IsJSHClass(ctorProtoOrHC), &isHClass, &isPrototype);
5835 Bind(&isHClass);
5836 {
5837 constructorPrototype = Load(VariableType::JS_POINTER(), ctorProtoOrHC, IntPtr(JSHClass::PROTOTYPE_OFFSET));
5838 Jump(&exit);
5839 }
5840 Bind(&isPrototype);
5841 {
5842 constructorPrototype = ctorProtoOrHC;
5843 Jump(&exit);
5844 }
5845
5846 Bind(&exit);
5847 auto ret = *constructorPrototype;
5848 env->SubCfgExit();
5849 return ret;
5850 }
5851
OrdinaryHasInstance(GateRef glue,GateRef target,GateRef obj)5852 GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj)
5853 {
5854 auto env = GetEnvironment();
5855 Label entry(env);
5856 env->SubCfgEntry(&entry);
5857 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5858 Label exit(env);
5859 DEFVARIABLE(object, VariableType::JS_ANY(), obj);
5860
5861 // 1. If IsCallable(C) is false, return false.
5862 Label targetIsCallable(env);
5863 Label targetNotCallable(env);
5864 BRANCH(IsCallable(target), &targetIsCallable, &targetNotCallable);
5865 Bind(&targetNotCallable);
5866 {
5867 result = TaggedFalse();
5868 Jump(&exit);
5869 }
5870 Bind(&targetIsCallable);
5871 {
5872 // 2. If C has a [[BoundTargetFunction]] internal slot, then
5873 // a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
5874 // b. Return InstanceofOperator(O,BC) (see 12.9.4).
5875 Label targetIsBoundFunction(env);
5876 Label targetNotBoundFunction(env);
5877 BRANCH(IsBoundFunction(target), &targetIsBoundFunction, &targetNotBoundFunction);
5878 Bind(&targetIsBoundFunction);
5879 {
5880 GateRef boundTarget = Load(VariableType::JS_ANY(), target, IntPtr(JSBoundFunction::BOUND_TARGET_OFFSET));
5881 result = CallRuntime(glue, RTSTUB_ID(InstanceOf), { obj, boundTarget });
5882 Jump(&exit);
5883 }
5884 Bind(&targetNotBoundFunction);
5885 {
5886 // 3. If Type(O) is not Object, return false
5887 Label objIsHeapObject(env);
5888 Label objIsEcmaObject(env);
5889 Label objNotEcmaObject(env);
5890 BRANCH(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotEcmaObject);
5891 Bind(&objIsHeapObject);
5892 BRANCH(TaggedObjectIsEcmaObject(obj), &objIsEcmaObject, &objNotEcmaObject);
5893 Bind(&objNotEcmaObject);
5894 {
5895 result = TaggedFalse();
5896 Jump(&exit);
5897 }
5898 Bind(&objIsEcmaObject);
5899 {
5900 // 4. Let P be Get(C, "prototype").
5901 Label getCtorProtoSlowPath(env);
5902 Label ctorIsJSFunction(env);
5903 Label gotCtorPrototype(env);
5904 DEFVARIABLE(constructorPrototype, VariableType::JS_ANY(), Undefined());
5905 BRANCH(IsJSFunction(target), &ctorIsJSFunction, &getCtorProtoSlowPath);
5906 Bind(&ctorIsJSFunction);
5907 {
5908 Label getCtorProtoFastPath(env);
5909 GateRef ctorProtoOrHC = Load(VariableType::JS_POINTER(), target,
5910 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
5911
5912 BRANCH(TaggedIsHole(ctorProtoOrHC), &getCtorProtoSlowPath, &getCtorProtoFastPath);
5913 Bind(&getCtorProtoFastPath);
5914 {
5915 constructorPrototype = GetCtorPrototype(target);
5916 BRANCH(TaggedIsHole(*constructorPrototype), &getCtorProtoSlowPath, &gotCtorPrototype);
5917 }
5918 }
5919 Bind(&getCtorProtoSlowPath);
5920 {
5921 auto prototypeString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
5922 ConstantIndex::PROTOTYPE_STRING_INDEX);
5923 constructorPrototype = FastGetPropertyByName(glue, target, prototypeString, ProfileOperation());
5924 Jump(&gotCtorPrototype);
5925 }
5926 Bind(&gotCtorPrototype);
5927
5928 // 5. ReturnIfAbrupt(P).
5929 // no throw exception, so needn't return
5930 Label isPendingException(env);
5931 Label noPendingException(env);
5932 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
5933 Bind(&isPendingException);
5934 {
5935 result = Exception();
5936 Jump(&exit);
5937 }
5938 Bind(&noPendingException);
5939
5940 // 6. If Type(P) is not Object, throw a TypeError exception.
5941 Label constructorPrototypeIsHeapObject(env);
5942 Label constructorPrototypeIsEcmaObject(env);
5943 Label constructorPrototypeNotEcmaObject(env);
5944 BRANCH(TaggedIsHeapObject(*constructorPrototype), &constructorPrototypeIsHeapObject,
5945 &constructorPrototypeNotEcmaObject);
5946 Bind(&constructorPrototypeIsHeapObject);
5947 BRANCH(TaggedObjectIsEcmaObject(*constructorPrototype), &constructorPrototypeIsEcmaObject,
5948 &constructorPrototypeNotEcmaObject);
5949 Bind(&constructorPrototypeNotEcmaObject);
5950 {
5951 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
5952 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
5953 result = Exception();
5954 Jump(&exit);
5955 }
5956 Bind(&constructorPrototypeIsEcmaObject);
5957 {
5958 // 7. Repeat
5959 // a.Let O be O.[[GetPrototypeOf]]().
5960 // b.ReturnIfAbrupt(O).
5961 // c.If O is null, return false.
5962 // d.If SameValue(P, O) is true, return true.
5963 Label loopHead(env);
5964 Label loopEnd(env);
5965 Label afterLoop(env);
5966 Label strictEqual1(env);
5967 Label notStrictEqual1(env);
5968 Label shouldReturn(env);
5969 Label shouldContinue(env);
5970
5971 BRANCH(TaggedIsNull(*object), &afterLoop, &loopHead);
5972 LoopBegin(&loopHead);
5973 {
5974 object = GetPrototype(glue, *object);
5975 Branch(HasPendingException(glue), &shouldReturn, &shouldContinue);
5976 Bind(&shouldReturn);
5977 {
5978 result = Exception();
5979 Jump(&exit);
5980 }
5981 Bind(&shouldContinue);
5982 {
5983 GateRef isEqual = SameValue(glue, *object, *constructorPrototype);
5984 Branch(isEqual, &strictEqual1, ¬StrictEqual1);
5985 Bind(&strictEqual1);
5986 {
5987 result = TaggedTrue();
5988 Jump(&exit);
5989 }
5990 Bind(¬StrictEqual1);
5991 Branch(TaggedIsNull(*object), &afterLoop, &loopEnd);
5992 }
5993 }
5994 Bind(&loopEnd);
5995 LoopEnd(&loopHead, env, glue);
5996 Bind(&afterLoop);
5997 {
5998 result = TaggedFalse();
5999 Jump(&exit);
6000 }
6001 }
6002 }
6003 }
6004 }
6005 Bind(&exit);
6006 auto ret = *result;
6007 env->SubCfgExit();
6008 return ret;
6009 }
6010
SameValue(GateRef glue,GateRef left,GateRef right)6011 GateRef StubBuilder::SameValue(GateRef glue, GateRef left, GateRef right)
6012 {
6013 auto env = GetEnvironment();
6014 Label entry(env);
6015 env->SubCfgEntry(&entry);
6016 DEFVARIABLE(result, VariableType::BOOL(), False());
6017 Label exit(env);
6018 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6019 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6020 Label strictEqual(env);
6021 Label stringEqualCheck(env);
6022 Label stringCompare(env);
6023 Label bigIntEqualCheck(env);
6024 Label numberEqualCheck1(env);
6025
6026 BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6027 Bind(&strictEqual);
6028 {
6029 result = True();
6030 Jump(&exit);
6031 }
6032 Bind(&numberEqualCheck1);
6033 {
6034 Label leftIsNumber(env);
6035 Label leftIsNotNumber(env);
6036 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6037 Bind(&leftIsNumber);
6038 {
6039 Label rightIsNumber(env);
6040 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6041 Bind(&rightIsNumber);
6042 {
6043 Label numberEqualCheck2(env);
6044 Label leftIsInt(env);
6045 Label leftNotInt(env);
6046 Label getRight(env);
6047
6048 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6049 Bind(&leftIsInt);
6050 {
6051 Label fastPath(env);
6052 Label slowPath(env);
6053 BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6054 Bind(&fastPath);
6055 {
6056 result = False();
6057 Jump(&exit);
6058 }
6059 Bind(&slowPath);
6060 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6061 doubleRight = GetDoubleOfTDouble(right);
6062 Jump(&numberEqualCheck2);
6063 }
6064 Bind(&leftNotInt);
6065 {
6066 doubleLeft = GetDoubleOfTDouble(left);
6067 Jump(&getRight);
6068 }
6069 Bind(&getRight);
6070 {
6071 Label rightIsInt(env);
6072 Label rightNotInt(env);
6073 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6074 Bind(&rightIsInt);
6075 {
6076 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6077 Jump(&numberEqualCheck2);
6078 }
6079 Bind(&rightNotInt);
6080 {
6081 doubleRight = GetDoubleOfTDouble(right);
6082 Jump(&numberEqualCheck2);
6083 }
6084 }
6085 Bind(&numberEqualCheck2);
6086 {
6087 Label boolAndCheck(env);
6088 Label signbitCheck(env);
6089 BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &signbitCheck, &boolAndCheck);
6090 Bind(&signbitCheck);
6091 {
6092 GateRef leftEncoding = CastDoubleToInt64(*doubleLeft);
6093 GateRef RightEncoding = CastDoubleToInt64(*doubleRight);
6094 Label leftIsMinusZero(env);
6095 Label leftNotMinusZero(env);
6096 BRANCH(Int64Equal(leftEncoding, Int64(base::MINUS_ZERO_BITS)),
6097 &leftIsMinusZero, &leftNotMinusZero);
6098 Bind(&leftIsMinusZero);
6099 {
6100 Label rightIsMinusZero(env);
6101 BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &rightIsMinusZero, &exit);
6102 Bind(&rightIsMinusZero);
6103 {
6104 result = True();
6105 Jump(&exit);
6106 }
6107 }
6108 Bind(&leftNotMinusZero);
6109 {
6110 Label rightNotMinusZero(env);
6111 BRANCH(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &exit, &rightNotMinusZero);
6112 Bind(&rightNotMinusZero);
6113 {
6114 result = True();
6115 Jump(&exit);
6116 }
6117 }
6118 }
6119 Bind(&boolAndCheck);
6120 {
6121 GateRef doubleLeftVal = *doubleLeft;
6122 GateRef doubleRightVal = *doubleRight;
6123 result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
6124 .And(DoubleIsNAN(doubleRightVal)).Done();
6125 Jump(&exit);
6126 }
6127 }
6128 }
6129 }
6130 Bind(&leftIsNotNumber);
6131 BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
6132 Bind(&stringEqualCheck);
6133 BRANCH(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
6134 Bind(&stringCompare);
6135 {
6136 result = FastStringEqual(glue, left, right);
6137 Jump(&exit);
6138 }
6139 Bind(&bigIntEqualCheck);
6140 {
6141 Label leftIsBigInt(env);
6142 Label leftIsNotBigInt(env);
6143 BRANCH(TaggedIsBigInt(left), &leftIsBigInt, &exit);
6144 Bind(&leftIsBigInt);
6145 {
6146 Label rightIsBigInt(env);
6147 BRANCH(TaggedIsBigInt(right), &rightIsBigInt, &exit);
6148 Bind(&rightIsBigInt);
6149 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
6150 Jump(&exit);
6151 }
6152 }
6153 }
6154 Bind(&exit);
6155 auto ret = *result;
6156 env->SubCfgExit();
6157 return ret;
6158 }
6159
SameValueZero(GateRef glue,GateRef left,GateRef right)6160 GateRef StubBuilder::SameValueZero(GateRef glue, GateRef left, GateRef right)
6161 {
6162 auto env = GetEnvironment();
6163 Label entry(env);
6164 env->SubCfgEntry(&entry);
6165 DEFVARIABLE(result, VariableType::BOOL(), False());
6166 Label exit(env);
6167 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6168 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6169 Label strictEqual(env);
6170 Label stringEqualCheck(env);
6171 Label stringCompare(env);
6172 Label bigIntEqualCheck(env);
6173 Label numberEqualCheck1(env);
6174
6175 BRANCH(Equal(left, right), &strictEqual, &numberEqualCheck1);
6176 Bind(&strictEqual);
6177 {
6178 result = True();
6179 Jump(&exit);
6180 }
6181 Bind(&numberEqualCheck1);
6182 {
6183 Label leftIsNumber(env);
6184 Label leftIsNotNumber(env);
6185 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6186 Bind(&leftIsNumber);
6187 {
6188 Label rightIsNumber(env);
6189 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6190 Bind(&rightIsNumber);
6191 {
6192 Label numberEqualCheck2(env);
6193 Label leftIsInt(env);
6194 Label leftNotInt(env);
6195 Label getRight(env);
6196 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6197 Bind(&leftIsInt);
6198 {
6199 Label fastPath(env);
6200 Label slowPath(env);
6201 BRANCH(TaggedIsInt(right), &fastPath, &slowPath);
6202 Bind(&fastPath);
6203 {
6204 result = False();
6205 Jump(&exit);
6206 }
6207 Bind(&slowPath);
6208 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6209 doubleRight = GetDoubleOfTDouble(right);
6210 Jump(&numberEqualCheck2);
6211 }
6212 Bind(&leftNotInt);
6213 {
6214 doubleLeft = GetDoubleOfTDouble(left);
6215 Jump(&getRight);
6216 }
6217 Bind(&getRight);
6218 {
6219 Label rightIsInt(env);
6220 Label rightNotInt(env);
6221 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6222 Bind(&rightIsInt);
6223 {
6224 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6225 Jump(&numberEqualCheck2);
6226 }
6227 Bind(&rightNotInt);
6228 {
6229 doubleRight = GetDoubleOfTDouble(right);
6230 Jump(&numberEqualCheck2);
6231 }
6232 }
6233 Bind(&numberEqualCheck2);
6234 {
6235 Label nanCheck(env);
6236 Label doubleEqual(env);
6237 BRANCH(DoubleEqual(*doubleLeft, *doubleRight), &doubleEqual, &nanCheck);
6238 Bind(&doubleEqual);
6239 {
6240 result = True();
6241 Jump(&exit);
6242 }
6243 Bind(&nanCheck);
6244 {
6245 GateRef doubleLeftVal = *doubleLeft;
6246 GateRef doubleRightVal = *doubleRight;
6247 result = LogicAndBuilder(env).And(DoubleIsNAN(doubleLeftVal))
6248 .And(DoubleIsNAN(doubleRightVal)).Done();
6249 Jump(&exit);
6250 }
6251 }
6252 }
6253 }
6254 Bind(&leftIsNotNumber);
6255 BRANCH(TaggedIsNumber(right), &exit, &stringEqualCheck);
6256 Bind(&stringEqualCheck);
6257 BRANCH(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
6258 Bind(&stringCompare);
6259 {
6260 result = FastStringEqual(glue, left, right);
6261 Jump(&exit);
6262 }
6263 Bind(&bigIntEqualCheck);
6264 {
6265 Label leftIsBigInt(env);
6266 Label leftIsNotBigInt(env);
6267 BRANCH(TaggedIsBigInt(left), &leftIsBigInt, &exit);
6268 Bind(&leftIsBigInt);
6269 {
6270 Label rightIsBigInt(env);
6271 BRANCH(TaggedIsBigInt(right), &rightIsBigInt, &exit);
6272 Bind(&rightIsBigInt);
6273 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntSameValueZero), { left, right });
6274 Jump(&exit);
6275 }
6276 }
6277 }
6278 Bind(&exit);
6279 auto ret = *result;
6280 env->SubCfgExit();
6281 return ret;
6282 }
6283
FastStringEqual(GateRef glue,GateRef left,GateRef right)6284 GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right)
6285 {
6286 auto env = GetEnvironment();
6287 Label entry(env);
6288 env->SubCfgEntry(&entry);
6289 DEFVARIABLE(result, VariableType::BOOL(), False());
6290 Label exit(env);
6291 Label hashcodeCompare(env);
6292 Label contentsCompare(env);
6293 Label lenEqualOneCheck(env);
6294 Label lenIsOne(env);
6295 BRANCH(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &lenEqualOneCheck, &exit);
6296 Bind(&lenEqualOneCheck);
6297 BRANCH(Int32Equal(GetLengthFromString(left), Int32(1)), &lenIsOne, &hashcodeCompare);
6298 Bind(&lenIsOne);
6299 {
6300 Label leftFlattenFastPath(env);
6301 FlatStringStubBuilder leftFlat(this);
6302 leftFlat.FlattenString(glue, left, &leftFlattenFastPath);
6303 Bind(&leftFlattenFastPath);
6304 {
6305 Label rightFlattenFastPath(env);
6306 FlatStringStubBuilder rightFlat(this);
6307 rightFlat.FlattenString(glue, right, &rightFlattenFastPath);
6308 Bind(&rightFlattenFastPath);
6309 {
6310 BuiltinsStringStubBuilder stringBuilder(this);
6311 StringInfoGateRef leftStrInfoGate(&leftFlat);
6312 StringInfoGateRef rightStrInfoGate(&rightFlat);
6313 GateRef leftStrToInt = stringBuilder.StringAt(leftStrInfoGate, Int32(0));
6314 GateRef rightStrToInt = stringBuilder.StringAt(rightStrInfoGate, Int32(0));
6315 result = Equal(leftStrToInt, rightStrToInt);
6316 Jump(&exit);
6317 }
6318 }
6319 }
6320
6321 Bind(&hashcodeCompare);
6322 Label leftNotNeg(env);
6323 GateRef leftHash = TryGetHashcodeFromString(left);
6324 GateRef rightHash = TryGetHashcodeFromString(right);
6325 BRANCH(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg);
6326 Bind(&leftNotNeg);
6327 {
6328 Label rightNotNeg(env);
6329 BRANCH(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg);
6330 Bind(&rightNotNeg);
6331 BRANCH(Int64Equal(leftHash, rightHash), &contentsCompare, &exit);
6332 }
6333
6334 Bind(&contentsCompare);
6335 {
6336 GateRef stringEqual = CallRuntime(glue, RTSTUB_ID(StringEqual), { left, right });
6337 result = Equal(stringEqual, TaggedTrue());
6338 Jump(&exit);
6339 }
6340
6341 Bind(&exit);
6342 auto ret = *result;
6343 env->SubCfgExit();
6344 return ret;
6345 }
6346
FastStrictEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)6347 GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
6348 {
6349 auto env = GetEnvironment();
6350 Label entry(env);
6351 env->SubCfgEntry(&entry);
6352 DEFVARIABLE(result, VariableType::BOOL(), False());
6353 Label strictEqual(env);
6354 Label leftIsNumber(env);
6355 Label leftIsNotNumber(env);
6356 Label sameVariableCheck(env);
6357 Label stringEqualCheck(env);
6358 Label stringCompare(env);
6359 Label bigIntEqualCheck(env);
6360 Label exit(env);
6361 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
6362 Bind(&leftIsNumber);
6363 {
6364 Label rightIsNumber(env);
6365 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
6366 Bind(&rightIsNumber);
6367 {
6368 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
6369 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
6370 DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::IntType()));
6371 Label leftIsInt(env);
6372 Label leftNotInt(env);
6373 Label getRight(env);
6374 Label numberEqualCheck(env);
6375
6376 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
6377 Bind(&leftIsInt);
6378 {
6379 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
6380 Jump(&getRight);
6381 }
6382 Bind(&leftNotInt);
6383 {
6384 curType = Int32(PGOSampleType::DoubleType());
6385 doubleLeft = GetDoubleOfTDouble(left);
6386 Jump(&getRight);
6387 }
6388 Bind(&getRight);
6389 {
6390 Label rightIsInt(env);
6391 Label rightNotInt(env);
6392 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
6393 Bind(&rightIsInt);
6394 {
6395 GateRef type = Int32(PGOSampleType::IntType());
6396 COMBINE_TYPE_CALL_BACK(curType, type);
6397 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
6398 Jump(&numberEqualCheck);
6399 }
6400 Bind(&rightNotInt);
6401 {
6402 GateRef type = Int32(PGOSampleType::DoubleType());
6403 COMBINE_TYPE_CALL_BACK(curType, type);
6404 doubleRight = GetDoubleOfTDouble(right);
6405 Jump(&numberEqualCheck);
6406 }
6407 }
6408 Bind(&numberEqualCheck);
6409 {
6410 Label doubleEqualCheck(env);
6411 BRANCH(BitOr(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight)), &exit, &doubleEqualCheck);
6412 Bind(&doubleEqualCheck);
6413 {
6414 result = DoubleEqual(*doubleLeft, *doubleRight);
6415 Jump(&exit);
6416 }
6417 }
6418 }
6419 }
6420 Bind(&leftIsNotNumber);
6421 BRANCH(TaggedIsNumber(right), &exit, &sameVariableCheck);
6422 Bind(&sameVariableCheck);
6423 BRANCH(Equal(left, right), &strictEqual, &stringEqualCheck);
6424 Bind(&stringEqualCheck);
6425 BRANCH(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
6426 Bind(&stringCompare);
6427 {
6428 callback.ProfileOpType(Int32(PGOSampleType::StringType()));
6429 result = FastStringEqual(glue, left, right);
6430 Jump(&exit);
6431 }
6432 Bind(&bigIntEqualCheck);
6433 {
6434 Label leftIsBigInt(env);
6435 Label leftIsNotBigInt(env);
6436 BRANCH(TaggedIsBigInt(left), &leftIsBigInt, &exit);
6437 Bind(&leftIsBigInt);
6438 {
6439 Label rightIsBigInt(env);
6440 BRANCH(TaggedIsBigInt(right), &rightIsBigInt, &exit);
6441 Bind(&rightIsBigInt);
6442 callback.ProfileOpType(Int32(PGOSampleType::BigIntType()));
6443 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
6444 Jump(&exit);
6445 }
6446 }
6447 Bind(&strictEqual);
6448 {
6449 callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6450 result = True();
6451 Jump(&exit);
6452 }
6453 Bind(&exit);
6454 auto ret = *result;
6455 env->SubCfgExit();
6456 return ret;
6457 }
6458
FastEqual(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)6459 GateRef StubBuilder::FastEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
6460 {
6461 auto env = GetEnvironment();
6462 Label entry(env);
6463 env->SubCfgEntry(&entry);
6464 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6465 Label leftEqualRight(env);
6466 Label leftNotEqualRight(env);
6467 Label exit(env);
6468 BRANCH(Equal(left, right), &leftEqualRight, &leftNotEqualRight);
6469 Bind(&leftEqualRight);
6470 {
6471 Label leftIsDouble(env);
6472 Label leftNotDoubleOrLeftNotNan(env);
6473 BRANCH(TaggedIsDouble(left), &leftIsDouble, &leftNotDoubleOrLeftNotNan);
6474 Bind(&leftIsDouble);
6475 {
6476 callback.ProfileOpType(Int32(PGOSampleType::DoubleType()));
6477 GateRef doubleLeft = GetDoubleOfTDouble(left);
6478 Label leftIsNan(env);
6479 Label leftIsNotNan(env);
6480 BRANCH(DoubleIsNAN(doubleLeft), &leftIsNan, &leftIsNotNan);
6481 Bind(&leftIsNan);
6482 {
6483 result = TaggedFalse();
6484 Jump(&exit);
6485 }
6486 Bind(&leftIsNotNan);
6487 {
6488 result = TaggedTrue();
6489 Jump(&exit);
6490 }
6491 }
6492 Bind(&leftNotDoubleOrLeftNotNan);
6493 {
6494 // Collect the type of left value
6495 result = TaggedTrue();
6496 if (callback.IsEmpty()) {
6497 Jump(&exit);
6498 } else {
6499 Label leftIsInt(env);
6500 Label leftIsNotInt(env);
6501 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsNotInt);
6502 Bind(&leftIsInt);
6503 {
6504 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
6505 Jump(&exit);
6506 }
6507 Bind(&leftIsNotInt);
6508 {
6509 Label leftIsString(env);
6510 Label leftIsNotString(env);
6511 BRANCH(TaggedIsString(left), &leftIsString, &leftIsNotString);
6512 Bind(&leftIsString);
6513 {
6514 callback.ProfileOpType(Int32(PGOSampleType::StringType()));
6515 Jump(&exit);
6516 }
6517 Bind(&leftIsNotString);
6518 {
6519 callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6520 Jump(&exit);
6521 }
6522 }
6523 }
6524 }
6525 }
6526 Bind(&leftNotEqualRight);
6527 {
6528 Label leftIsNumber(env);
6529 Label leftNotNumberOrLeftNotIntOrRightNotInt(env);
6530 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrLeftNotIntOrRightNotInt);
6531 Bind(&leftIsNumber);
6532 {
6533 Label leftIsInt(env);
6534 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
6535 Bind(&leftIsInt);
6536 {
6537 Label rightIsInt(env);
6538 BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
6539 Bind(&rightIsInt);
6540 {
6541 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
6542 result = TaggedFalse();
6543 Jump(&exit);
6544 }
6545 }
6546 }
6547 Bind(&leftNotNumberOrLeftNotIntOrRightNotInt);
6548 {
6549 DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::None()));
6550 Label rightIsUndefinedOrNull(env);
6551 Label rightIsNotUndefinedOrNull(env);
6552 BRANCH(TaggedIsUndefinedOrNull(right), &rightIsUndefinedOrNull, &rightIsNotUndefinedOrNull);
6553 Bind(&rightIsUndefinedOrNull);
6554 {
6555 curType = Int32(PGOSampleType::UndefineOrNullType());
6556 Label leftIsHeapObject(env);
6557 Label leftNotHeapObject(env);
6558 BRANCH(TaggedIsHeapObject(left), &leftIsHeapObject, &leftNotHeapObject);
6559 Bind(&leftIsHeapObject);
6560 {
6561 GateRef type = Int32(PGOSampleType::HeapObjectType());
6562 COMBINE_TYPE_CALL_BACK(curType, type);
6563 result = TaggedFalse();
6564 Jump(&exit);
6565 }
6566 Bind(&leftNotHeapObject);
6567 {
6568 Label leftIsUndefinedOrNull(env);
6569 Label leftIsNotUndefinedOrNull(env);
6570 // if left is undefined or null, then result is true, otherwise result is false
6571 BRANCH(TaggedIsUndefinedOrNull(left), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
6572 Bind(&leftIsUndefinedOrNull);
6573 {
6574 callback.ProfileOpType(*curType);
6575 result = TaggedTrue();
6576 Jump(&exit);
6577 }
6578 Bind(&leftIsNotUndefinedOrNull);
6579 {
6580 callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6581 result = TaggedFalse();
6582 Jump(&exit);
6583 }
6584 }
6585 }
6586 Bind(&rightIsNotUndefinedOrNull);
6587 {
6588 Label leftIsUndefinedOrNull(env);
6589 Label leftIsNotUndefinedOrNull(env);
6590 BRANCH(TaggedIsUndefinedOrNull(right), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull);
6591 // If left is undefined or null, result will always be false
6592 // because we can ensure that right is not null here.
6593 Bind(&leftIsUndefinedOrNull);
6594 {
6595 callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6596 result = TaggedFalse();
6597 Jump(&exit);
6598 }
6599 Bind(&leftIsNotUndefinedOrNull);
6600 {
6601 Label leftIsBool(env);
6602 Label leftNotBoolOrRightNotSpecial(env);
6603 BRANCH(TaggedIsBoolean(left), &leftIsBool, &leftNotBoolOrRightNotSpecial);
6604 Bind(&leftIsBool);
6605 {
6606 curType = Int32(PGOSampleType::BooleanType());
6607 Label rightIsSpecial(env);
6608 BRANCH(TaggedIsSpecial(right), &rightIsSpecial, &leftNotBoolOrRightNotSpecial);
6609 Bind(&rightIsSpecial);
6610 {
6611 GateRef type = Int32(PGOSampleType::SpecialType());
6612 COMBINE_TYPE_CALL_BACK(curType, type);
6613 result = TaggedFalse();
6614 Jump(&exit);
6615 }
6616 }
6617 Bind(&leftNotBoolOrRightNotSpecial);
6618 {
6619 Label bothString(env);
6620 Label eitherNotString(env);
6621 BRANCH(BothAreString(left, right), &bothString, &eitherNotString);
6622 Bind(&bothString);
6623 {
6624 callback.ProfileOpType(Int32(PGOSampleType::StringType()));
6625 Label stringEqual(env);
6626 Label stringNotEqual(env);
6627 BRANCH(FastStringEqual(glue, left, right), &stringEqual, &stringNotEqual);
6628 Bind(&stringEqual);
6629 result = TaggedTrue();
6630 Jump(&exit);
6631 Bind(&stringNotEqual);
6632 result = TaggedFalse();
6633 Jump(&exit);
6634 }
6635 Bind(&eitherNotString);
6636 callback.ProfileOpType(Int32(PGOSampleType::AnyType()));
6637 Jump(&exit);
6638 }
6639 }
6640 }
6641 }
6642 }
6643 Bind(&exit);
6644 auto ret = *result;
6645 env->SubCfgExit();
6646 return ret;
6647 }
6648
FastToBoolean(GateRef value,bool flag)6649 GateRef StubBuilder::FastToBoolean(GateRef value, bool flag)
6650 {
6651 auto env = GetEnvironment();
6652 Label entry(env);
6653 env->SubCfgEntry(&entry);
6654 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6655 Label exit(env);
6656
6657 Label isSpecial(env);
6658 Label notSpecial(env);
6659 Label isNumber(env);
6660 Label isInt(env);
6661 Label isDouble(env);
6662 Label notNumber(env);
6663 Label notNan(env);
6664 Label isString(env);
6665 Label notString(env);
6666 Label isBigint(env);
6667 Label lengthIsOne(env);
6668 Label returnTrue(env);
6669 Label returnFalse(env);
6670
6671 BRANCH(TaggedIsSpecial(value), &isSpecial, ¬Special);
6672 Bind(&isSpecial);
6673 {
6674 BRANCH(TaggedIsTrue(value), &returnTrue, &returnFalse);
6675 }
6676 Bind(¬Special);
6677 {
6678 BRANCH(TaggedIsNumber(value), &isNumber, ¬Number);
6679 Bind(¬Number);
6680 {
6681 BRANCH(IsString(value), &isString, ¬String);
6682 Bind(&isString);
6683 {
6684 auto len = GetLengthFromString(value);
6685 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
6686 }
6687 Bind(¬String);
6688 BRANCH(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
6689 Bind(&isBigint);
6690 {
6691 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
6692 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
6693 Bind(&lengthIsOne);
6694 {
6695 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
6696 auto data0 = Load(VariableType::INT32(), data, Int32(0));
6697 BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
6698 }
6699 }
6700 }
6701 Bind(&isNumber);
6702 {
6703 BRANCH(TaggedIsInt(value), &isInt, &isDouble);
6704 Bind(&isInt);
6705 {
6706 auto intValue = GetInt32OfTInt(value);
6707 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
6708 }
6709 Bind(&isDouble);
6710 {
6711 auto doubleValue = GetDoubleOfTDouble(value);
6712 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
6713 Bind(¬Nan);
6714 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
6715 }
6716 }
6717 }
6718 if (flag == 1) {
6719 Bind(&returnTrue);
6720 {
6721 result = TaggedTrue();
6722 Jump(&exit);
6723 }
6724 Bind(&returnFalse);
6725 {
6726 result = TaggedFalse();
6727 Jump(&exit);
6728 }
6729 } else {
6730 Bind(&returnFalse);
6731 {
6732 result = TaggedTrue();
6733 Jump(&exit);
6734 }
6735 Bind(&returnTrue);
6736 {
6737 result = TaggedFalse();
6738 Jump(&exit);
6739 }
6740 }
6741
6742 Bind(&exit);
6743 auto ret = *result;
6744 env->SubCfgExit();
6745 return ret;
6746 }
6747
FastToBooleanBaseline(GateRef value,bool flag)6748 GateRef StubBuilder::FastToBooleanBaseline(GateRef value, bool flag)
6749 {
6750 auto env = GetEnvironment();
6751 Label entry(env);
6752 env->SubCfgEntry(&entry);
6753 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6754 Label exit(env);
6755
6756 Label isSpecial(env);
6757 Label notSpecial(env);
6758 Label isNumber(env);
6759 Label isInt(env);
6760 Label isDouble(env);
6761 Label notNumber(env);
6762 Label notNan(env);
6763 Label isString(env);
6764 Label notString(env);
6765 Label isBigint(env);
6766 Label lengthIsOne(env);
6767 Label returnTrue(env);
6768 Label returnFalse(env);
6769
6770 Branch(TaggedIsSpecial(value), &isSpecial, ¬Special);
6771 Bind(&isSpecial);
6772 {
6773 Branch(TaggedIsTrue(value), &returnTrue, &returnFalse);
6774 }
6775 Bind(¬Special);
6776 {
6777 Branch(TaggedIsNumber(value), &isNumber, ¬Number);
6778 Bind(¬Number);
6779 {
6780 Branch(IsString(value), &isString, ¬String);
6781 Bind(&isString);
6782 {
6783 auto len = GetLengthFromString(value);
6784 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
6785 }
6786 Bind(¬String);
6787 Branch(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
6788 Bind(&isBigint);
6789 {
6790 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
6791 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
6792 Bind(&lengthIsOne);
6793 {
6794 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
6795 auto data0 = Load(VariableType::INT32(), data, Int32(0));
6796 Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
6797 }
6798 }
6799 }
6800 Bind(&isNumber);
6801 {
6802 Branch(TaggedIsInt(value), &isInt, &isDouble);
6803 Bind(&isInt);
6804 {
6805 auto intValue = GetInt32OfTInt(value);
6806 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
6807 }
6808 Bind(&isDouble);
6809 {
6810 auto doubleValue = GetDoubleOfTDouble(value);
6811 Branch(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
6812 Bind(¬Nan);
6813 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
6814 }
6815 }
6816 }
6817 if (flag == 1) {
6818 Bind(&returnTrue);
6819 {
6820 result = TaggedTrue();
6821 Jump(&exit);
6822 }
6823 Bind(&returnFalse);
6824 {
6825 result = TaggedFalse();
6826 Jump(&exit);
6827 }
6828 } else {
6829 Bind(&returnFalse);
6830 {
6831 result = TaggedTrue();
6832 Jump(&exit);
6833 }
6834 Bind(&returnTrue);
6835 {
6836 result = TaggedFalse();
6837 Jump(&exit);
6838 }
6839 }
6840
6841 Bind(&exit);
6842 auto ret = *result;
6843 env->SubCfgExit();
6844 return ret;
6845 }
6846
FastToBooleanWithProfile(GateRef value,ProfileOperation callback,bool flag)6847 GateRef StubBuilder::FastToBooleanWithProfile(GateRef value, ProfileOperation callback, bool flag)
6848 {
6849 auto env = GetEnvironment();
6850 Label entry(env);
6851 env->SubCfgEntry(&entry);
6852 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6853 Label exit(env);
6854
6855 Label isSpecial(env);
6856 Label notSpecial(env);
6857 Label isNumber(env);
6858 Label isInt(env);
6859 Label isDouble(env);
6860 Label notNumber(env);
6861 Label notNan(env);
6862 Label isString(env);
6863 Label notString(env);
6864 Label isBigint(env);
6865 Label lengthIsOne(env);
6866 Label returnTrue(env);
6867 Label returnFalse(env);
6868 Label isTrue(env);
6869 Label isNotTrue(env);
6870 Label isFalse(env);
6871 Label isNotFalse(env);
6872
6873 BRANCH(TaggedIsSpecial(value), &isSpecial, ¬Special);
6874 Bind(&isSpecial);
6875 {
6876 BRANCH(TaggedIsTrue(value), &isTrue, &isNotTrue);
6877 Bind(&isTrue);
6878 {
6879 callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
6880 Jump(&returnTrue);
6881 }
6882 Bind(&isNotTrue);
6883 {
6884 BRANCH(TaggedIsFalse(value), &isFalse, &isNotFalse);
6885 Bind(&isFalse);
6886 {
6887 callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
6888 Jump(&returnFalse);
6889 }
6890 }
6891 Bind(&isNotFalse);
6892 Jump(&returnFalse);
6893 }
6894 Bind(¬Special);
6895 {
6896 BRANCH(TaggedIsNumber(value), &isNumber, ¬Number);
6897 Bind(¬Number);
6898 {
6899 BRANCH(IsString(value), &isString, ¬String);
6900 Bind(&isString);
6901 {
6902 auto len = GetLengthFromString(value);
6903 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
6904 }
6905 Bind(¬String);
6906 BRANCH(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
6907 Bind(&isBigint);
6908 {
6909 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
6910 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
6911 Bind(&lengthIsOne);
6912 {
6913 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
6914 auto data0 = Load(VariableType::INT32(), data, Int32(0));
6915 BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
6916 }
6917 }
6918 }
6919 Bind(&isNumber);
6920 {
6921 callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
6922 BRANCH(TaggedIsInt(value), &isInt, &isDouble);
6923 Bind(&isInt);
6924 {
6925 auto intValue = GetInt32OfTInt(value);
6926 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
6927 }
6928 Bind(&isDouble);
6929 {
6930 auto doubleValue = GetDoubleOfTDouble(value);
6931 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
6932 Bind(¬Nan);
6933 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
6934 }
6935 }
6936 }
6937 if (flag == 1) {
6938 Bind(&returnTrue);
6939 {
6940 result = TaggedTrue();
6941 Jump(&exit);
6942 }
6943 Bind(&returnFalse);
6944 {
6945 result = TaggedFalse();
6946 Jump(&exit);
6947 }
6948 } else {
6949 Bind(&returnFalse);
6950 {
6951 result = TaggedTrue();
6952 Jump(&exit);
6953 }
6954 Bind(&returnTrue);
6955 {
6956 result = TaggedFalse();
6957 Jump(&exit);
6958 }
6959 }
6960
6961 Bind(&exit);
6962 auto ret = *result;
6963 env->SubCfgExit();
6964 return ret;
6965 }
6966
FastToBooleanWithProfileBaseline(GateRef value,ProfileOperation callback,bool flag)6967 GateRef StubBuilder::FastToBooleanWithProfileBaseline(GateRef value, ProfileOperation callback, bool flag)
6968 {
6969 auto env = GetEnvironment();
6970 Label entry(env);
6971 env->SubCfgEntry(&entry);
6972 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
6973 Label exit(env);
6974
6975 Label isSpecial(env);
6976 Label notSpecial(env);
6977 Label isNumber(env);
6978 Label isInt(env);
6979 Label isDouble(env);
6980 Label notNumber(env);
6981 Label notNan(env);
6982 Label isString(env);
6983 Label notString(env);
6984 Label isBigint(env);
6985 Label lengthIsOne(env);
6986 Label returnTrue(env);
6987 Label returnFalse(env);
6988 Label isTrue(env);
6989 Label isNotTrue(env);
6990 Label isFalse(env);
6991 Label isNotFalse(env);
6992
6993 Branch(TaggedIsSpecial(value), &isSpecial, ¬Special);
6994 Bind(&isSpecial);
6995 {
6996 Branch(TaggedIsTrue(value), &isTrue, &isNotTrue);
6997 Bind(&isTrue);
6998 {
6999 callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
7000 Jump(&returnTrue);
7001 }
7002 Bind(&isNotTrue);
7003 {
7004 Branch(TaggedIsFalse(value), &isFalse, &isNotFalse);
7005 Bind(&isFalse);
7006 {
7007 callback.ProfileOpType(Int32(PGOSampleType::BooleanType()));
7008 Jump(&returnFalse);
7009 }
7010 }
7011 Bind(&isNotFalse);
7012 Jump(&returnFalse);
7013 }
7014 Bind(¬Special);
7015 {
7016 Branch(TaggedIsNumber(value), &isNumber, ¬Number);
7017 Bind(¬Number);
7018 {
7019 Branch(IsString(value), &isString, ¬String);
7020 Bind(&isString);
7021 {
7022 auto len = GetLengthFromString(value);
7023 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
7024 }
7025 Bind(¬String);
7026 Branch(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
7027 Bind(&isBigint);
7028 {
7029 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
7030 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
7031 Bind(&lengthIsOne);
7032 {
7033 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
7034 auto data0 = Load(VariableType::INT32(), data, Int32(0));
7035 Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
7036 }
7037 }
7038 }
7039 Bind(&isNumber);
7040 {
7041 callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
7042 Branch(TaggedIsInt(value), &isInt, &isDouble);
7043 Bind(&isInt);
7044 {
7045 auto intValue = GetInt32OfTInt(value);
7046 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
7047 }
7048 Bind(&isDouble);
7049 {
7050 auto doubleValue = GetDoubleOfTDouble(value);
7051 Branch(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
7052 Bind(¬Nan);
7053 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
7054 }
7055 }
7056 }
7057 if (flag == 1) {
7058 Bind(&returnTrue);
7059 {
7060 result = TaggedTrue();
7061 Jump(&exit);
7062 }
7063 Bind(&returnFalse);
7064 {
7065 result = TaggedFalse();
7066 Jump(&exit);
7067 }
7068 } else {
7069 Bind(&returnFalse);
7070 {
7071 result = TaggedTrue();
7072 Jump(&exit);
7073 }
7074 Bind(&returnTrue);
7075 {
7076 result = TaggedFalse();
7077 Jump(&exit);
7078 }
7079 }
7080
7081 Bind(&exit);
7082 auto ret = *result;
7083 env->SubCfgExit();
7084 return ret;
7085 }
7086
FastDiv(GateRef left,GateRef right,ProfileOperation callback)7087 GateRef StubBuilder::FastDiv(GateRef left, GateRef right, ProfileOperation callback)
7088 {
7089 auto env = GetEnvironment();
7090 Label entry(env);
7091 env->SubCfgEntry(&entry);
7092 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7093 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7094 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7095 DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::None()));
7096 Label leftIsNumber(env);
7097 Label leftNotNumberOrRightNotNumber(env);
7098 Label leftIsNumberAndRightIsNumber(env);
7099 Label leftIsDoubleAndRightIsDouble(env);
7100 Label exit(env);
7101 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
7102 Bind(&leftIsNumber);
7103 {
7104 Label rightIsNumber(env);
7105 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
7106 Bind(&rightIsNumber);
7107 {
7108 Label leftIsInt(env);
7109 Label leftNotInt(env);
7110 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotInt);
7111 Bind(&leftIsInt);
7112 {
7113 Label rightIsInt(env);
7114 Label bailout(env);
7115 BRANCH(TaggedIsInt(right), &rightIsInt, &bailout);
7116 Bind(&rightIsInt);
7117 {
7118 result = FastIntDiv(left, right, &bailout, callback);
7119 Jump(&exit);
7120 }
7121 Bind(&bailout);
7122 {
7123 curType = Int32(PGOSampleType::IntOverFlowType());
7124 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7125 Jump(&leftIsNumberAndRightIsNumber);
7126 }
7127 }
7128 Bind(&leftNotInt);
7129 {
7130 curType = Int32(PGOSampleType::DoubleType());
7131 doubleLeft = GetDoubleOfTDouble(left);
7132 Jump(&leftIsNumberAndRightIsNumber);
7133 }
7134 }
7135 }
7136 Bind(&leftNotNumberOrRightNotNumber);
7137 {
7138 Jump(&exit);
7139 }
7140 Bind(&leftIsNumberAndRightIsNumber);
7141 {
7142 Label rightIsInt(env);
7143 Label rightNotInt(env);
7144 BRANCH(TaggedIsInt(right), &rightIsInt, &rightNotInt);
7145 Bind(&rightIsInt);
7146 {
7147 GateRef type = Int32(PGOSampleType::IntType());
7148 COMBINE_TYPE_CALL_BACK(curType, type);
7149 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7150 Jump(&leftIsDoubleAndRightIsDouble);
7151 }
7152 Bind(&rightNotInt);
7153 {
7154 GateRef type = Int32(PGOSampleType::DoubleType());
7155 COMBINE_TYPE_CALL_BACK(curType, type);
7156 doubleRight = GetDoubleOfTDouble(right);
7157 Jump(&leftIsDoubleAndRightIsDouble);
7158 }
7159 }
7160 Bind(&leftIsDoubleAndRightIsDouble);
7161 {
7162 Label rightIsZero(env);
7163 Label rightNotZero(env);
7164 BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZero, &rightNotZero);
7165 Bind(&rightIsZero);
7166 {
7167 Label leftIsZero(env);
7168 Label leftNotZero(env);
7169 Label leftIsZeroOrNan(env);
7170 Label leftNotZeroAndNotNan(env);
7171 BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZero, &leftNotZero);
7172 Bind(&leftIsZero);
7173 {
7174 Jump(&leftIsZeroOrNan);
7175 }
7176 Bind(&leftNotZero);
7177 {
7178 Label leftIsNan(env);
7179 BRANCH(DoubleIsNAN(*doubleLeft), &leftIsNan, &leftNotZeroAndNotNan);
7180 Bind(&leftIsNan);
7181 {
7182 Jump(&leftIsZeroOrNan);
7183 }
7184 }
7185 Bind(&leftIsZeroOrNan);
7186 {
7187 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
7188 Jump(&exit);
7189 }
7190 Bind(&leftNotZeroAndNotNan);
7191 {
7192 GateRef intLeftTmp = CastDoubleToInt64(*doubleLeft);
7193 GateRef intRightTmp = CastDoubleToInt64(*doubleRight);
7194 GateRef flagBit = Int64And(Int64Xor(intLeftTmp, intRightTmp), Int64(base::DOUBLE_SIGN_MASK));
7195 GateRef tmpResult = Int64Xor(flagBit, CastDoubleToInt64(Double(base::POSITIVE_INFINITY)));
7196 result = DoubleToTaggedDoublePtr(CastInt64ToFloat64(tmpResult));
7197 Jump(&exit);
7198 }
7199 }
7200 Bind(&rightNotZero);
7201 {
7202 result = DoubleToTaggedDoublePtr(DoubleDiv(*doubleLeft, *doubleRight));
7203 Jump(&exit);
7204 }
7205 }
7206 Bind(&exit);
7207 auto ret = *result;
7208 env->SubCfgExit();
7209 return ret;
7210 }
7211
NumberOperation(Environment * env,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)7212 GateRef StubBuilder::NumberOperation(Environment *env, GateRef left, GateRef right,
7213 const BinaryOperation& intOp,
7214 const BinaryOperation& floatOp,
7215 ProfileOperation callback)
7216 {
7217 Label entry(env);
7218 env->SubCfgEntry(&entry);
7219 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7220 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7221 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7222 Label exit(env);
7223 Label doFloatOp(env);
7224 Label doIntOp(env);
7225 Label leftIsNumber(env);
7226 Label leftIsIntRightIsDouble(env);
7227 Label rightIsDouble(env);
7228 Label rightIsInt(env);
7229 Label rightIsNumber(env);
7230 BRANCH(TaggedIsNumber(left), &leftIsNumber, &exit);
7231 Bind(&leftIsNumber);
7232 {
7233 BRANCH(TaggedIsNumber(right), &rightIsNumber, &exit);
7234 Bind(&rightIsNumber);
7235 {
7236 Label leftIsInt(env);
7237 Label leftIsDouble(env);
7238 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
7239 Bind(&leftIsInt);
7240 {
7241 BRANCH(TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
7242 Bind(&leftIsIntRightIsDouble);
7243 {
7244 callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
7245 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7246 doubleRight = GetDoubleOfTDouble(right);
7247 Jump(&doFloatOp);
7248 }
7249 }
7250 Bind(&leftIsDouble);
7251 {
7252 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
7253 Bind(&rightIsInt);
7254 {
7255 callback.ProfileOpType(Int32(PGOSampleType::NumberType()));
7256 doubleLeft = GetDoubleOfTDouble(left);
7257 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7258 Jump(&doFloatOp);
7259 }
7260 Bind(&rightIsDouble);
7261 {
7262 callback.ProfileOpType(Int32(PGOSampleType::DoubleType()));
7263 doubleLeft = GetDoubleOfTDouble(left);
7264 doubleRight = GetDoubleOfTDouble(right);
7265 Jump(&doFloatOp);
7266 }
7267 }
7268 }
7269 }
7270 Bind(&doIntOp);
7271 {
7272 result = intOp(env, left, right);
7273 Jump(&exit);
7274 }
7275 Bind(&doFloatOp);
7276 {
7277 result = floatOp(env, *doubleLeft, *doubleRight);
7278 Jump(&exit);
7279 }
7280 Bind(&exit);
7281 auto ret = *result;
7282 env->SubCfgExit();
7283 return ret;
7284 }
7285
TryStringAdd(Environment * env,GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)7286 GateRef StubBuilder::TryStringAdd(Environment *env, GateRef glue, GateRef left, GateRef right,
7287 const BinaryOperation& intOp,
7288 const BinaryOperation& floatOp,
7289 ProfileOperation callback)
7290 {
7291 Label entry(env);
7292 env->SubCfgEntry(&entry);
7293 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7294 Label exit(env);
7295 Label leftIsNotSpecial(env);
7296 Label leftIsNotString(env);
7297 Label leftIsString(env);
7298 Label rightIsNotSpecial(env);
7299 Label rightIsNotString(env);
7300 Label rightIsString(env);
7301 Label stringLeftAddNumberRight(env);
7302 Label numberLeftAddStringRight(env);
7303 Label stringLeftAddStringRight(env);
7304 Label notStringAdd(env);
7305 BRANCH(TaggedIsString(left), &leftIsString, &leftIsNotString);
7306 Bind(&leftIsString);
7307 {
7308 BRANCH(TaggedIsString(right), &stringLeftAddStringRight, &rightIsNotString);
7309 Bind(&rightIsNotString);
7310 {
7311 BRANCH(TaggedIsSpecial(right), ¬StringAdd, &rightIsNotSpecial);
7312 Bind(&rightIsNotSpecial);
7313 {
7314 BRANCH(TaggedIsNumber(right), &stringLeftAddNumberRight, ¬StringAdd);
7315 }
7316 }
7317 }
7318 Bind(&leftIsNotString);
7319 {
7320 BRANCH(TaggedIsString(right), &rightIsString, ¬StringAdd);
7321 Bind(&rightIsString);
7322 {
7323 BRANCH(TaggedIsSpecial(left), ¬StringAdd, &leftIsNotSpecial);
7324 Bind(&leftIsNotSpecial);
7325 {
7326 BRANCH(TaggedIsNumber(left), &numberLeftAddStringRight, ¬StringAdd);
7327 }
7328 }
7329 }
7330 Bind(&stringLeftAddNumberRight);
7331 {
7332 Label hasPendingException(env);
7333 // NOTICE-PGO: support string and number
7334 callback.ProfileOpType(Int32(PGOSampleType::NumberOrStringType()));
7335 BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
7336 result = builtinsStringStubBuilder.StringConcat(glue, left, NumberToString(glue, right));
7337 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
7338 Bind(&hasPendingException);
7339 result = Exception();
7340 Jump(&exit);
7341 }
7342 Bind(&numberLeftAddStringRight);
7343 {
7344 Label hasPendingException(env);
7345 // NOTICE-PGO: support string and number
7346 callback.ProfileOpType(Int32(PGOSampleType::NumberOrStringType()));
7347 BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
7348 result = builtinsStringStubBuilder.StringConcat(glue, NumberToString(glue, left), right);
7349 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
7350 Bind(&hasPendingException);
7351 result = Exception();
7352 Jump(&exit);
7353 }
7354 Bind(&stringLeftAddStringRight);
7355 {
7356 Label hasPendingException(env);
7357 callback.ProfileOpType(Int32(PGOSampleType::StringType()));
7358 BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
7359 result = builtinsStringStubBuilder.StringConcat(glue, left, right);
7360 BRANCH(HasPendingException(glue), &hasPendingException, &exit);
7361 Bind(&hasPendingException);
7362 result = Exception();
7363 Jump(&exit);
7364 }
7365 Bind(¬StringAdd);
7366 {
7367 result = NumberOperation(env, left, right, intOp, floatOp, callback);
7368 Jump(&exit);
7369 }
7370 Bind(&exit);
7371 auto ret = *result;
7372 env->SubCfgExit();
7373 return ret;
7374 }
7375
7376 template<OpCode Op>
FastBinaryOp(GateRef glue,GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp,ProfileOperation callback)7377 GateRef StubBuilder::FastBinaryOp(GateRef glue, GateRef left, GateRef right,
7378 const BinaryOperation& intOp,
7379 const BinaryOperation& floatOp,
7380 ProfileOperation callback)
7381 {
7382 auto env = GetEnvironment();
7383 Label entry(env);
7384 env->SubCfgEntry(&entry);
7385 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7386 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7387 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7388
7389 if (Op == OpCode::ADD) { // Try string Add
7390 result = TryStringAdd(env, glue, left, right, intOp, floatOp, callback);
7391 } else {
7392 result = NumberOperation(env, left, right, intOp, floatOp, callback);
7393 }
7394 auto ret = *result;
7395 env->SubCfgExit();
7396 return ret;
7397 }
7398
7399 template<OpCode Op>
FastAddSubAndMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7400 GateRef StubBuilder::FastAddSubAndMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7401 {
7402 auto intOperation = [=](Environment *env, GateRef left, GateRef right) {
7403 Label entry(env);
7404 env->SubCfgEntry(&entry);
7405 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7406 Label exit(env);
7407 Label overflow(env);
7408 Label notOverflow(env);
7409 auto res = BinaryOpWithOverflow<Op, MachineType::I32>(GetInt32OfTInt(left), GetInt32OfTInt(right));
7410 GateRef condition = env->GetBuilder()->ExtractValue(MachineType::I1, res, Int32(1));
7411 BRANCH(condition, &overflow, ¬Overflow);
7412 Bind(&overflow);
7413 {
7414 auto doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7415 auto doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7416 auto ret = BinaryOp<Op, MachineType::F64>(doubleLeft, doubleRight);
7417 result = DoubleToTaggedDoublePtr(ret);
7418 callback.ProfileOpType(Int32(PGOSampleType::IntOverFlowType()));
7419 Jump(&exit);
7420 }
7421 Bind(¬Overflow);
7422 {
7423 res = env->GetBuilder()->ExtractValue(MachineType::I32, res, Int32(0));
7424 if (Op == OpCode::MUL) {
7425 Label resultIsZero(env);
7426 Label returnNegativeZero(env);
7427 Label returnResult(env);
7428 BRANCH(Int32Equal(res, Int32(0)), &resultIsZero, &returnResult);
7429 Bind(&resultIsZero);
7430 BRANCH(LogicOrBuilder(env).Or(Int32LessThan(GetInt32OfTInt(left), Int32(0)))
7431 .Or(Int32LessThan(GetInt32OfTInt(right), Int32(0))).Done(),
7432 &returnNegativeZero, &returnResult);
7433 Bind(&returnNegativeZero);
7434 result = DoubleToTaggedDoublePtr(Double(-0.0));
7435 callback.ProfileOpType(Int32(PGOSampleType::DoubleType()));
7436 Jump(&exit);
7437 Bind(&returnResult);
7438 result = IntToTaggedPtr(res);
7439 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7440 Jump(&exit);
7441 } else {
7442 result = IntToTaggedPtr(res);
7443 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7444 Jump(&exit);
7445 }
7446 }
7447 Bind(&exit);
7448 auto ret = *result;
7449 env->SubCfgExit();
7450 return ret;
7451 };
7452 auto floatOperation = [=]([[maybe_unused]] Environment *env, GateRef left, GateRef right) {
7453 auto res = BinaryOp<Op, MachineType::F64>(left, right);
7454 return DoubleToTaggedDoublePtr(res);
7455 };
7456 return FastBinaryOp<Op>(glue, left, right, intOperation, floatOperation, callback);
7457 }
7458
FastIntDiv(GateRef left,GateRef right,Label * bailout,ProfileOperation callback)7459 GateRef StubBuilder::FastIntDiv(GateRef left, GateRef right, Label *bailout, ProfileOperation callback)
7460 {
7461 auto env = GetEnvironment();
7462 Label entry(env);
7463 env->SubCfgEntry(&entry);
7464 DEFVARIABLE(intResult, VariableType::INT32(), Int32(0));
7465
7466 GateRef intLeft = GetInt32OfTInt(left);
7467 GateRef intRight = GetInt32OfTInt(right);
7468 Label exit(env);
7469 Label rightIsNotZero(env);
7470 Label leftIsIntMin(env);
7471 Label leftAndRightIsNotBoundary(env);
7472 BRANCH(Int32Equal(intRight, Int32(0)), bailout, &rightIsNotZero);
7473 Bind(&rightIsNotZero);
7474 BRANCH(Int32Equal(intLeft, Int32(INT_MIN)), &leftIsIntMin, &leftAndRightIsNotBoundary);
7475 Bind(&leftIsIntMin);
7476 BRANCH(Int32Equal(intRight, Int32(-1)), bailout, &leftAndRightIsNotBoundary);
7477 Bind(&leftAndRightIsNotBoundary);
7478 {
7479 Label leftIsZero(env);
7480 Label leftIsNotZero(env);
7481 BRANCH(Int32Equal(intLeft, Int32(0)), &leftIsZero, &leftIsNotZero);
7482 Bind(&leftIsZero);
7483 {
7484 BRANCH(Int32LessThan(intRight, Int32(0)), bailout, &leftIsNotZero);
7485 }
7486 Bind(&leftIsNotZero);
7487 {
7488 intResult = Int32Div(intLeft, intRight);
7489 GateRef truncated = Int32Mul(*intResult, intRight);
7490 BRANCH(Equal(intLeft, truncated), &exit, bailout);
7491 }
7492 }
7493 Bind(&exit);
7494 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7495 auto ret = IntToTaggedPtr(*intResult);
7496 env->SubCfgExit();
7497 return ret;
7498 }
7499
FastAdd(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7500 GateRef StubBuilder::FastAdd(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7501 {
7502 return FastAddSubAndMul<OpCode::ADD>(glue, left, right, callback);
7503 }
7504
FastSub(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7505 GateRef StubBuilder::FastSub(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7506 {
7507 return FastAddSubAndMul<OpCode::SUB>(glue, left, right, callback);
7508 }
7509
FastMul(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7510 GateRef StubBuilder::FastMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7511 {
7512 return FastAddSubAndMul<OpCode::MUL>(glue, left, right, callback);
7513 }
7514
FastMod(GateRef glue,GateRef left,GateRef right,ProfileOperation callback)7515 GateRef StubBuilder::FastMod(GateRef glue, GateRef left, GateRef right, ProfileOperation callback)
7516 {
7517 auto env = GetEnvironment();
7518 Label entry(env);
7519 env->SubCfgEntry(&entry);
7520 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7521 DEFVARIABLE(intLeft, VariableType::INT32(), Int32(0));
7522 DEFVARIABLE(intRight, VariableType::INT32(), Int32(0));
7523 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
7524 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
7525 Label leftIsInt(env);
7526 Label leftNotIntOrRightNotInt(env);
7527 Label exit(env);
7528 BRANCH(TaggedIsInt(left), &leftIsInt, &leftNotIntOrRightNotInt);
7529 Bind(&leftIsInt);
7530 {
7531 Label rightIsInt(env);
7532 BRANCH(TaggedIsInt(right), &rightIsInt, &leftNotIntOrRightNotInt);
7533 Bind(&rightIsInt);
7534 {
7535 intLeft = GetInt32OfTInt(left);
7536 intRight = GetInt32OfTInt(right);
7537 Label leftGreaterZero(env);
7538 BRANCH(Int32GreaterThanOrEqual(*intLeft, Int32(0)), &leftGreaterZero, &leftNotIntOrRightNotInt);
7539 Bind(&leftGreaterZero);
7540 {
7541 Label rightGreaterZero(env);
7542 BRANCH(Int32GreaterThan(*intRight, Int32(0)), &rightGreaterZero, &leftNotIntOrRightNotInt);
7543 Bind(&rightGreaterZero);
7544 {
7545 callback.ProfileOpType(Int32(PGOSampleType::IntType()));
7546 result = IntToTaggedPtr(Int32Mod(*intLeft, *intRight));
7547 Jump(&exit);
7548 }
7549 }
7550 }
7551 }
7552 Bind(&leftNotIntOrRightNotInt);
7553 {
7554 Label leftIsNumber(env);
7555 Label leftNotNumberOrRightNotNumber(env);
7556 Label leftIsNumberAndRightIsNumber(env);
7557 Label leftIsDoubleAndRightIsDouble(env);
7558 DEFVARIABLE(curType, VariableType::INT32(), Int32(PGOSampleType::None()));
7559 // less than 0 result should be double
7560 curType = Int32(PGOSampleType::DoubleType());
7561 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
7562 Bind(&leftIsNumber);
7563 {
7564 Label rightIsNumber(env);
7565 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
7566 Bind(&rightIsNumber);
7567 {
7568 Label leftIsInt1(env);
7569 Label leftNotInt1(env);
7570 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
7571 Bind(&leftIsInt1);
7572 {
7573 GateRef type = Int32(PGOSampleType::IntType());
7574 COMBINE_TYPE_CALL_BACK(curType, type);
7575 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
7576 Jump(&leftIsNumberAndRightIsNumber);
7577 }
7578 Bind(&leftNotInt1);
7579 {
7580 GateRef type = Int32(PGOSampleType::DoubleType());
7581 COMBINE_TYPE_CALL_BACK(curType, type);
7582 doubleLeft = GetDoubleOfTDouble(left);
7583 Jump(&leftIsNumberAndRightIsNumber);
7584 }
7585 }
7586 }
7587 Bind(&leftNotNumberOrRightNotNumber);
7588 {
7589 Jump(&exit);
7590 }
7591 Bind(&leftIsNumberAndRightIsNumber);
7592 {
7593 Label rightIsInt1(env);
7594 Label rightNotInt1(env);
7595 BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
7596 Bind(&rightIsInt1);
7597 {
7598 GateRef type = Int32(PGOSampleType::IntType());
7599 COMBINE_TYPE_CALL_BACK(curType, type);
7600 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
7601 Jump(&leftIsDoubleAndRightIsDouble);
7602 }
7603 Bind(&rightNotInt1);
7604 {
7605 GateRef type = Int32(PGOSampleType::DoubleType());
7606 COMBINE_TYPE_CALL_BACK(curType, type);
7607 doubleRight = GetDoubleOfTDouble(right);
7608 Jump(&leftIsDoubleAndRightIsDouble);
7609 }
7610 }
7611 Bind(&leftIsDoubleAndRightIsDouble);
7612 {
7613 Label rightNotZero(env);
7614 Label rightIsZeroOrNanOrLeftIsNanOrInf(env);
7615 Label rightNotZeroAndNanAndLeftNotNanAndInf(env);
7616 BRANCH(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotZero);
7617 Bind(&rightNotZero);
7618 {
7619 Label rightNotNan(env);
7620 BRANCH(DoubleIsNAN(*doubleRight), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotNan);
7621 Bind(&rightNotNan);
7622 {
7623 Label leftNotNan(env);
7624 BRANCH(DoubleIsNAN(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf, &leftNotNan);
7625 Bind(&leftNotNan);
7626 {
7627 BRANCH(DoubleIsINF(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf,
7628 &rightNotZeroAndNanAndLeftNotNanAndInf);
7629 }
7630 }
7631 }
7632 Bind(&rightIsZeroOrNanOrLeftIsNanOrInf);
7633 {
7634 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
7635 Jump(&exit);
7636 }
7637 Bind(&rightNotZeroAndNanAndLeftNotNanAndInf);
7638 {
7639 Label leftNotZero(env);
7640 Label leftIsZeroOrRightIsInf(env);
7641 BRANCH(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZeroOrRightIsInf, &leftNotZero);
7642 Bind(&leftNotZero);
7643 {
7644 Label rightNotInf(env);
7645 BRANCH(DoubleIsINF(*doubleRight), &leftIsZeroOrRightIsInf, &rightNotInf);
7646 Bind(&rightNotInf);
7647 {
7648 result = DoubleToTaggedDoublePtr(CallNGCRuntime(glue, RTSTUB_ID(FloatMod),
7649 { *doubleLeft, *doubleRight }));
7650 Jump(&exit);
7651 }
7652 }
7653 Bind(&leftIsZeroOrRightIsInf);
7654 {
7655 result = DoubleToTaggedDoublePtr(*doubleLeft);
7656 Jump(&exit);
7657 }
7658 }
7659 }
7660 }
7661 Bind(&exit);
7662 auto ret = *result;
7663 env->SubCfgExit();
7664 return ret;
7665 }
7666
GetGlobalOwnProperty(GateRef glue,GateRef receiver,GateRef key,ProfileOperation callback)7667 GateRef StubBuilder::GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRef key, ProfileOperation callback)
7668 {
7669 auto env = GetEnvironment();
7670 Label entryLabel(env);
7671 env->SubCfgEntry(&entryLabel);
7672 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7673 GateRef properties = GetPropertiesFromJSObject(receiver);
7674 GateRef entry = FindEntryFromNameDictionary(glue, properties, key);
7675 Label notNegtiveOne(env);
7676 Label exit(env);
7677 BRANCH(Int32NotEqual(entry, Int32(-1)), ¬NegtiveOne, &exit);
7678 Bind(¬NegtiveOne);
7679 {
7680 result = GetValueFromGlobalDictionary(properties, entry);
7681 Label callGetter(env);
7682 BRANCH(TaggedIsAccessor(*result), &callGetter, &exit);
7683 Bind(&callGetter);
7684 {
7685 result = CallGetterHelper(glue, receiver, receiver, *result, callback);
7686 Jump(&exit);
7687 }
7688 }
7689 Bind(&exit);
7690 auto ret = *result;
7691 env->SubCfgExit();
7692 return ret;
7693 }
7694
GetConstPoolFromFunction(GateRef jsFunc)7695 GateRef StubBuilder::GetConstPoolFromFunction(GateRef jsFunc)
7696 {
7697 return env_->GetBuilder()->GetConstPoolFromFunction(jsFunc);
7698 }
7699
GetStringFromConstPool(GateRef glue,GateRef constpool,GateRef index)7700 GateRef StubBuilder::GetStringFromConstPool(GateRef glue, GateRef constpool, GateRef index)
7701 {
7702 GateRef module = Circuit::NullGate();
7703 GateRef hirGate = Circuit::NullGate();
7704 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
7705 ConstPoolType::STRING);
7706 }
7707
GetMethodFromConstPool(GateRef glue,GateRef constpool,GateRef index)7708 GateRef StubBuilder::GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index)
7709 {
7710 GateRef module = Circuit::NullGate();
7711 GateRef hirGate = Circuit::NullGate();
7712 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, Circuit::NullGate(), module, index,
7713 ConstPoolType::METHOD);
7714 }
7715
GetArrayLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)7716 GateRef StubBuilder::GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
7717 {
7718 GateRef hirGate = Circuit::NullGate();
7719 GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
7720 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
7721 ConstPoolType::ARRAY_LITERAL);
7722 }
7723
GetObjectLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)7724 GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
7725 {
7726 GateRef hirGate = Circuit::NullGate();
7727 GateRef unsharedConstPool = env_->GetBuilder()->GetUnsharedConstpoolFromGlue(glue, constpool);
7728 return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, unsharedConstPool, module, index,
7729 ConstPoolType::OBJECT_LITERAL);
7730 }
7731
JSAPIContainerGet(GateRef glue,GateRef receiver,GateRef index)7732 GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)
7733 {
7734 auto env = GetEnvironment();
7735 Label entry(env);
7736 env->SubCfgEntry(&entry);
7737 Label exit(env);
7738 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7739
7740 GateRef lengthOffset = IntPtr(panda::ecmascript::JSAPIArrayList::LENGTH_OFFSET);
7741 GateRef length = GetInt32OfTInt(Load(VariableType::INT64(), receiver, lengthOffset));
7742 Label isVailedIndex(env);
7743 Label notValidIndex(env);
7744 BRANCH(BitAnd(Int32GreaterThanOrEqual(index, Int32(0)),
7745 Int32UnsignedLessThan(index, length)), &isVailedIndex, ¬ValidIndex);
7746 Bind(&isVailedIndex);
7747 {
7748 GateRef elements = GetElementsArray(receiver);
7749 result = GetValueFromTaggedArray(elements, index);
7750 Jump(&exit);
7751 }
7752 Bind(¬ValidIndex);
7753 {
7754 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(GetPropertyOutOfBounds));
7755 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
7756 result = Exception();
7757 Jump(&exit);
7758 }
7759
7760 Bind(&exit);
7761 auto ret = *result;
7762 env->SubCfgExit();
7763 return ret;
7764 }
7765
GetEnumCacheKind(GateRef glue,GateRef enumCache)7766 GateRef StubBuilder::GetEnumCacheKind(GateRef glue, GateRef enumCache)
7767 {
7768 return env_->GetBuilder()->GetEnumCacheKind(glue, enumCache);
7769 }
7770
IsEnumCacheValid(GateRef receiver,GateRef cachedHclass,GateRef kind)7771 GateRef StubBuilder::IsEnumCacheValid(GateRef receiver, GateRef cachedHclass, GateRef kind)
7772 {
7773 return env_->GetBuilder()->IsEnumCacheValid(receiver, cachedHclass, kind);
7774 }
7775
NeedCheckProperty(GateRef receiver)7776 GateRef StubBuilder::NeedCheckProperty(GateRef receiver)
7777 {
7778 return env_->GetBuilder()->NeedCheckProperty(receiver);
7779 }
7780
NextInternal(GateRef glue,GateRef iter)7781 GateRef StubBuilder::NextInternal(GateRef glue, GateRef iter)
7782 {
7783 auto env = GetEnvironment();
7784 Label entry(env);
7785 env->SubCfgEntry(&entry);
7786 Label exit(env);
7787 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
7788
7789 Label notFinish(env);
7790 Label notEnumCacheValid(env);
7791 Label fastGetKey(env);
7792 Label slowpath(env);
7793
7794 GateRef index = GetIndexFromForInIterator(iter);
7795 GateRef length = GetLengthFromForInIterator(iter);
7796 BRANCH(Int32GreaterThanOrEqual(index, length), &exit, ¬Finish);
7797 Bind(¬Finish);
7798 GateRef keys = GetKeysFromForInIterator(iter);
7799 GateRef receiver = GetObjectFromForInIterator(iter);
7800 GateRef cachedHclass = GetCachedHclassFromForInIterator(iter);
7801 GateRef kind = GetEnumCacheKind(glue, keys);
7802 BRANCH(IsEnumCacheValid(receiver, cachedHclass, kind), &fastGetKey, ¬EnumCacheValid);
7803 Bind(¬EnumCacheValid);
7804 BRANCH(NeedCheckProperty(receiver), &slowpath, &fastGetKey);
7805 Bind(&fastGetKey);
7806 {
7807 result = GetValueFromTaggedArray(keys, index);
7808 IncreaseInteratorIndex(glue, iter, index);
7809 Jump(&exit);
7810 }
7811 Bind(&slowpath);
7812 {
7813 result = CallRuntime(glue, RTSTUB_ID(GetNextPropNameSlowpath), { iter });
7814 Jump(&exit);
7815 }
7816 Bind(&exit);
7817 auto ret = *result;
7818 env->SubCfgExit();
7819 return ret;
7820 }
7821
GetFunctionPrototype(GateRef glue,size_t index)7822 GateRef StubBuilder::GetFunctionPrototype(GateRef glue, size_t index)
7823 {
7824 auto env = GetEnvironment();
7825 Label entry(env);
7826 env->SubCfgEntry(&entry);
7827 Label exit(env);
7828 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
7829
7830 Label isHeapObject(env);
7831 Label isJSHclass(env);
7832
7833 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env_->Is32Bit()));
7834 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
7835 GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
7836 GateRef protoOrHclass = Load(VariableType::JS_ANY(), func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
7837 result = protoOrHclass;
7838 BRANCH(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &exit);
7839 Bind(&isHeapObject);
7840 BRANCH(IsJSHClass(protoOrHclass), &isJSHclass, &exit);
7841 Bind(&isJSHclass);
7842 {
7843 result = GetPrototypeFromHClass(protoOrHclass);
7844 Jump(&exit);
7845 }
7846 Bind(&exit);
7847 auto ret = *result;
7848 env->SubCfgExit();
7849 return ret;
7850 }
7851
DeletePropertyOrThrow(GateRef glue,GateRef obj,GateRef value)7852 GateRef StubBuilder::DeletePropertyOrThrow(GateRef glue, GateRef obj, GateRef value)
7853 {
7854 auto env = GetEnvironment();
7855 Label entry(env);
7856 env->SubCfgEntry(&entry);
7857 Label exit(env);
7858 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
7859 DEFVARIABLE(key, VariableType::JS_ANY(), value);
7860 Label toObject(env);
7861 Label isNotExceptiont(env);
7862 Label objectIsEcmaObject(env);
7863 Label objectIsHeapObject(env);
7864 GateRef object = ToObject(glue, obj);
7865 BRANCH(TaggedIsException(object), &exit, &isNotExceptiont);
7866 Bind(&isNotExceptiont);
7867 {
7868 Label deleteProper(env);
7869 Label notStringOrSymbol(env);
7870 Label notPrimitive(env);
7871 BRANCH(TaggedIsStringOrSymbol(value), &deleteProper, ¬StringOrSymbol);
7872 Bind(¬StringOrSymbol);
7873 {
7874 BRANCH(TaggedIsNumber(value), &deleteProper, ¬Primitive);
7875 Bind(¬Primitive);
7876 {
7877 key = CallRuntime(glue, RTSTUB_ID(ToPropertyKey), {value});
7878 BRANCH(TaggedIsException(*key), &exit, &deleteProper);
7879 }
7880 }
7881 Bind(&deleteProper);
7882 {
7883 result = DeleteProperty(glue, object, *key);
7884 Jump(&exit);
7885 }
7886 }
7887 Bind(&exit);
7888 auto ret = *result;
7889 env->SubCfgExit();
7890 return ret;
7891 }
7892
DeleteProperty(GateRef glue,GateRef obj,GateRef value)7893 GateRef StubBuilder::DeleteProperty(GateRef glue, GateRef obj, GateRef value)
7894 {
7895 auto env = GetEnvironment();
7896 Label entry(env);
7897 env->SubCfgEntry(&entry);
7898 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
7899 Label exit(env);
7900 Label notRegularJSObject(env);
7901 Label regularJSObjDeletePrototype(env);
7902 BRANCH(TaggedIsRegularObject(obj), ®ularJSObjDeletePrototype, ¬RegularJSObject);
7903 Bind(®ularJSObjDeletePrototype);
7904 {
7905 result = CallRuntime(glue, RTSTUB_ID(RegularJSObjDeletePrototype), { obj, value});
7906 Jump(&exit);
7907 }
7908 Bind(¬RegularJSObject);
7909 {
7910 result = CallRuntime(glue, RTSTUB_ID(CallJSObjDeletePrototype), { obj, value});
7911 Jump(&exit);
7912 }
7913
7914 Bind(&exit);
7915 auto ret = *result;
7916 env->SubCfgExit();
7917 return ret;
7918 }
7919
ToPrototypeOrObj(GateRef glue,GateRef obj)7920 GateRef StubBuilder::ToPrototypeOrObj(GateRef glue, GateRef obj)
7921 {
7922 auto env = GetEnvironment();
7923 Label entry(env);
7924 env->SubCfgEntry(&entry);
7925 Label exit(env);
7926 DEFVARIABLE(result, VariableType::JS_ANY(), obj);
7927
7928 Label isNumber(env);
7929 Label notNumber(env);
7930 Label isBoolean(env);
7931 Label notBoolean(env);
7932 Label isString(env);
7933 Label notString(env);
7934 Label isSymbol(env);
7935 Label notSymbol(env);
7936 Label isBigInt(env);
7937 BRANCH(TaggedIsNumber(obj), &isNumber, ¬Number);
7938 Bind(&isNumber);
7939 {
7940 result = GetFunctionPrototype(glue, GlobalEnv::NUMBER_FUNCTION_INDEX);
7941 Jump(&exit);
7942 }
7943 Bind(¬Number);
7944 BRANCH(TaggedIsBoolean(obj), &isBoolean, ¬Boolean);
7945 Bind(&isBoolean);
7946 {
7947 result = GetFunctionPrototype(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
7948 Jump(&exit);
7949 }
7950 Bind(¬Boolean);
7951 BRANCH(TaggedIsString(obj), &isString, ¬String);
7952 Bind(&isString);
7953 {
7954 result = GetFunctionPrototype(glue, GlobalEnv::STRING_FUNCTION_INDEX);
7955 Jump(&exit);
7956 }
7957 Bind(¬String);
7958 BRANCH(TaggedIsSymbol(obj), &isSymbol, ¬Symbol);
7959 Bind(&isSymbol);
7960 {
7961 result = GetFunctionPrototype(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX);
7962 Jump(&exit);
7963 }
7964 Bind(¬Symbol);
7965 BRANCH(TaggedIsBigInt(obj), &isBigInt, &exit);
7966 Bind(&isBigInt);
7967 {
7968 result = GetFunctionPrototype(glue, GlobalEnv::BIGINT_FUNCTION_INDEX);
7969 Jump(&exit);
7970 }
7971 Bind(&exit);
7972 auto ret = *result;
7973 env->SubCfgExit();
7974 return ret;
7975 }
7976
IsSpecialKeysObject(GateRef obj)7977 GateRef StubBuilder::IsSpecialKeysObject(GateRef obj)
7978 {
7979 return LogicOrBuilder(env_).Or(IsTypedArray(obj)).Or(IsModuleNamespace(obj)).Or(ObjIsSpecialContainer(obj)).Done();
7980 }
7981
IsSlowKeysObject(GateRef obj)7982 GateRef StubBuilder::IsSlowKeysObject(GateRef obj)
7983 {
7984 auto env = GetEnvironment();
7985 Label entry(env);
7986 env->SubCfgEntry(&entry);
7987 Label exit(env);
7988 DEFVARIABLE(result, VariableType::BOOL(), False());
7989
7990 Label isHeapObject(env);
7991 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
7992 Bind(&isHeapObject);
7993 {
7994 result = LogicOrBuilder(env).Or(IsJSGlobalObject(obj)).Or(IsJsProxy(obj)).Or(IsSpecialKeysObject(obj)).Done();
7995 Jump(&exit);
7996 }
7997 Bind(&exit);
7998 auto ret = *result;
7999 env->SubCfgExit();
8000 return ret;
8001 }
8002
GetNumberOfElements(GateRef obj)8003 GateRef StubBuilder::GetNumberOfElements(GateRef obj)
8004 {
8005 auto env = GetEnvironment();
8006 Label entry(env);
8007 env->SubCfgEntry(&entry);
8008 Label exit(env);
8009 DEFVARIABLE(numOfElements, VariableType::INT32(), Int32(0));
8010 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
8011
8012 Label isJSPrimitiveRef(env);
8013 Label isPrimitiveString(env);
8014 Label notPrimitiveString(env);
8015 Label isDictMode(env);
8016 Label notDictMode(env);
8017
8018 BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, ¬PrimitiveString);
8019 Bind(&isJSPrimitiveRef);
8020 GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
8021 BRANCH(TaggedIsString(value), &isPrimitiveString, ¬PrimitiveString);
8022 Bind(&isPrimitiveString);
8023 {
8024 numOfElements = GetLengthFromString(value);
8025 Jump(¬PrimitiveString);
8026 }
8027 Bind(¬PrimitiveString);
8028 GateRef elements = GetElementsArray(obj);
8029 BRANCH(IsDictionaryMode(elements), &isDictMode, ¬DictMode);
8030 Bind(¬DictMode);
8031 {
8032 Label loopHead(env);
8033 Label loopEnd(env);
8034 Label iLessLength(env);
8035 Label notHole(env);
8036 GateRef elementsLen = GetLengthOfTaggedArray(elements);
8037 Jump(&loopHead);
8038 LoopBegin(&loopHead);
8039 {
8040 BRANCH(Int32UnsignedLessThan(*i, elementsLen), &iLessLength, &exit);
8041 Bind(&iLessLength);
8042 {
8043 GateRef element = GetTaggedValueWithElementsKind(obj, *i);
8044 BRANCH(TaggedIsHole(element), &loopEnd, ¬Hole);
8045 Bind(¬Hole);
8046 numOfElements = Int32Add(*numOfElements, Int32(1));
8047 Jump(&loopEnd);
8048 }
8049 Bind(&loopEnd);
8050 i = Int32Add(*i, Int32(1));
8051 LoopEnd(&loopHead);
8052 }
8053 }
8054 Bind(&isDictMode);
8055 {
8056 GateRef entryCount = TaggedGetInt(
8057 GetValueFromTaggedArray(elements, Int32(TaggedHashTable<NumberDictionary>::NUMBER_OF_ENTRIES_INDEX)));
8058 numOfElements = Int32Add(*numOfElements, entryCount);
8059 Jump(&exit);
8060 }
8061 Bind(&exit);
8062 auto ret = *numOfElements;
8063 env->SubCfgExit();
8064 return ret;
8065 }
8066
IsSimpleEnumCacheValid(GateRef obj)8067 GateRef StubBuilder::IsSimpleEnumCacheValid(GateRef obj)
8068 {
8069 auto env = GetEnvironment();
8070 Label entry(env);
8071 env->SubCfgEntry(&entry);
8072 Label exit(env);
8073 DEFVARIABLE(result, VariableType::BOOL(), False());
8074 DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
8075
8076 Label receiverHasNoElements(env);
8077
8078 GateRef numOfElements = GetNumberOfElements(obj);
8079 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
8080 Bind(&receiverHasNoElements);
8081 {
8082 Label loopHead(env);
8083 Label loopEnd(env);
8084 Label afterLoop(env);
8085 Label currentHasNoElements(env);
8086 Label enumCacheIsUndefined(env);
8087 current = GetPrototypeFromHClass(LoadHClass(obj));
8088 BRANCH(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
8089 LoopBegin(&loopHead);
8090 {
8091 GateRef numOfCurrentElements = GetNumberOfElements(*current);
8092 BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, ¤tHasNoElements);
8093 Bind(¤tHasNoElements);
8094 GateRef hclass = LoadHClass(*current);
8095 GateRef protoEnumCache = GetEnumCacheFromHClass(hclass);
8096 BRANCH(TaggedIsUndefined(protoEnumCache), &enumCacheIsUndefined, &exit);
8097 Bind(&enumCacheIsUndefined);
8098 current = GetPrototypeFromHClass(hclass);
8099 BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
8100 }
8101 Bind(&loopEnd);
8102 LoopEnd(&loopHead);
8103 Bind(&afterLoop);
8104 {
8105 result = True();
8106 Jump(&exit);
8107 }
8108 }
8109 Bind(&exit);
8110 auto ret = *result;
8111 env->SubCfgExit();
8112 return ret;
8113 }
8114
IsEnumCacheWithProtoChainInfoValid(GateRef obj)8115 GateRef StubBuilder::IsEnumCacheWithProtoChainInfoValid(GateRef obj)
8116 {
8117 auto env = GetEnvironment();
8118 Label entry(env);
8119 env->SubCfgEntry(&entry);
8120 Label exit(env);
8121 DEFVARIABLE(result, VariableType::BOOL(), False());
8122 DEFVARIABLE(current, VariableType::JS_ANY(), Undefined());
8123
8124 Label receiverHasNoElements(env);
8125 Label prototypeIsEcmaObj(env);
8126 Label isProtoChangeMarker(env);
8127 Label protoNotChanged(env);
8128
8129 GateRef numOfElements = GetNumberOfElements(obj);
8130 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &exit, &receiverHasNoElements);
8131 Bind(&receiverHasNoElements);
8132 GateRef prototype = GetPrototypeFromHClass(LoadHClass(obj));
8133 BRANCH(IsEcmaObject(prototype), &prototypeIsEcmaObj, &exit);
8134 Bind(&prototypeIsEcmaObj);
8135 GateRef protoChangeMarker = GetProtoChangeMarkerFromHClass(LoadHClass(prototype));
8136 BRANCH(TaggedIsProtoChangeMarker(protoChangeMarker), &isProtoChangeMarker, &exit);
8137 Bind(&isProtoChangeMarker);
8138 BRANCH(GetHasChanged(protoChangeMarker), &exit, &protoNotChanged);
8139 Bind(&protoNotChanged);
8140 {
8141 Label loopHead(env);
8142 Label loopEnd(env);
8143 Label afterLoop(env);
8144 Label currentHasNoElements(env);
8145 current = prototype;
8146 BRANCH(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
8147 LoopBegin(&loopHead);
8148 {
8149 GateRef numOfCurrentElements = GetNumberOfElements(*current);
8150 BRANCH(Int32GreaterThan(numOfCurrentElements, Int32(0)), &exit, ¤tHasNoElements);
8151 Bind(¤tHasNoElements);
8152 current = GetPrototypeFromHClass(LoadHClass(*current));
8153 BRANCH(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
8154 }
8155 Bind(&loopEnd);
8156 LoopEnd(&loopHead);
8157 Bind(&afterLoop);
8158 {
8159 result = True();
8160 Jump(&exit);
8161 }
8162 }
8163 Bind(&exit);
8164 auto ret = *result;
8165 env->SubCfgExit();
8166 return ret;
8167 }
8168
TryGetEnumCache(GateRef glue,GateRef obj)8169 GateRef StubBuilder::TryGetEnumCache(GateRef glue, GateRef obj)
8170 {
8171 auto env = GetEnvironment();
8172 Label entry(env);
8173 env->SubCfgEntry(&entry);
8174 Label exit(env);
8175 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
8176
8177 Label notSlowKeys(env);
8178 Label notDictionaryMode(env);
8179 Label checkSimpleEnumCache(env);
8180 Label notSimpleEnumCache(env);
8181 Label checkEnumCacheWithProtoChainInfo(env);
8182 Label enumCacheValid(env);
8183
8184 BRANCH(IsSlowKeysObject(obj), &exit, ¬SlowKeys);
8185 Bind(¬SlowKeys);
8186 GateRef hclass = LoadHClass(obj);
8187 BRANCH(IsDictionaryModeByHClass(hclass), &exit, ¬DictionaryMode);
8188 Bind(¬DictionaryMode);
8189 GateRef enumCache = GetEnumCacheFromHClass(hclass);
8190 GateRef kind = GetEnumCacheKind(glue, enumCache);
8191 BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE))),
8192 &checkSimpleEnumCache, ¬SimpleEnumCache);
8193 Bind(&checkSimpleEnumCache);
8194 {
8195 BRANCH(IsSimpleEnumCacheValid(obj), &enumCacheValid, &exit);
8196 }
8197 Bind(¬SimpleEnumCache);
8198 BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::PROTOCHAIN))),
8199 &checkEnumCacheWithProtoChainInfo, &exit);
8200 Bind(&checkEnumCacheWithProtoChainInfo);
8201 {
8202 BRANCH(IsEnumCacheWithProtoChainInfoValid(obj), &enumCacheValid, &exit);
8203 }
8204 Bind(&enumCacheValid);
8205 {
8206 result = enumCache;
8207 Jump(&exit);
8208 }
8209 Bind(&exit);
8210 auto ret = *result;
8211 env->SubCfgExit();
8212 return ret;
8213 }
8214
DoubleToInt(GateRef glue,GateRef x,size_t typeBits)8215 GateRef StubBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits)
8216 {
8217 auto env = GetEnvironment();
8218 Label entry(env);
8219 env->SubCfgEntry(&entry);
8220 Label exit(env);
8221 Label overflow(env);
8222
8223 GateRef xInt = ChangeFloat64ToInt32(x);
8224 DEFVARIABLE(result, VariableType::INT32(), xInt);
8225
8226 if (env->IsAmd64()) {
8227 // 0x80000000: amd64 overflow return value
8228 BRANCH(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit);
8229 } else {
8230 GateRef xInt64 = CastDoubleToInt64(x);
8231 // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
8232 GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
8233 exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
8234 exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
8235 GateRef bits = Int32(typeBits - 1);
8236 // exp < 32 - 1
8237 BRANCH(Int32LessThan(exp, bits), &exit, &overflow);
8238 }
8239 Bind(&overflow);
8240 {
8241 result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), { x, IntPtr(typeBits) });
8242 Jump(&exit);
8243 }
8244 Bind(&exit);
8245 auto ret = *result;
8246 env->SubCfgExit();
8247 return ret;
8248 }
8249
ReturnExceptionIfAbruptCompletion(GateRef glue)8250 void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue)
8251 {
8252 auto env = GetEnvironment();
8253 Label entry(env);
8254 env->SubCfgEntry(&entry);
8255 Label exit(env);
8256 Label hasPendingException(env);
8257 GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env->IsArch32Bit()));
8258 GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
8259 BRANCH(TaggedIsNotHole(exception), &hasPendingException, &exit);
8260 Bind(&hasPendingException);
8261 Return(Exception());
8262 Bind(&exit);
8263 env->SubCfgExit();
8264 return;
8265 }
8266
CalcHashcodeForInt(GateRef value)8267 GateRef StubBuilder::CalcHashcodeForInt(GateRef value)
8268 {
8269 return env_->GetBuilder()->CalcHashcodeForInt(value);
8270 }
8271
CanDoubleRepresentInt(GateRef exp,GateRef expBits,GateRef fractionBits)8272 GateRef StubBuilder::CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits)
8273 {
8274 return LogicOrBuilder(env_)
8275 .Or(Int64Equal(expBits, Int64(base::DOUBLE_EXPONENT_MASK)))
8276 .Or(BitAnd(Int64Equal(expBits, Int64(0)), Int64NotEqual(fractionBits, Int64(0))))
8277 .Or(Int64LessThan(exp, Int64(0)))
8278 .Or(Int64GreaterThanOrEqual(exp, Int64(31U)))
8279 .Or(Int64NotEqual(Int64And(Int64LSL(fractionBits, exp), Int64(base::DOUBLE_SIGNIFICAND_MASK)),
8280 Int64(0)))
8281 .Done();
8282 }
8283
CalcHashcodeForDouble(GateRef x,Variable * res,Label * exit)8284 void StubBuilder::CalcHashcodeForDouble(GateRef x, Variable *res, Label *exit)
8285 {
8286 auto env = GetEnvironment();
8287 GateRef xInt64 = Int64Sub(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
8288 GateRef fractionBits = Int64And(xInt64, Int64(base::DOUBLE_SIGNIFICAND_MASK));
8289 GateRef expBits = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
8290 GateRef isZero = BitAnd(
8291 Int64Equal(expBits, Int64(0)),
8292 Int64Equal(fractionBits, Int64(0)));
8293 Label zero(env);
8294 Label nonZero(env);
8295
8296 BRANCH(isZero, &zero, &nonZero);
8297 Bind(&nonZero);
8298 {
8299 DEFVARIABLE(value, VariableType::JS_ANY(), x);
8300 // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
8301 GateRef exp = Int64Sub(
8302 Int64LSR(expBits, Int64(base::DOUBLE_SIGNIFICAND_SIZE)),
8303 Int64(base::DOUBLE_EXPONENT_BIAS));
8304 Label convertToInt(env);
8305 Label calcHash(env);
8306 BRANCH(CanDoubleRepresentInt(exp, expBits, fractionBits), &calcHash, &convertToInt);
8307 Bind(&convertToInt);
8308 {
8309 *res = ChangeFloat64ToInt32(CastInt64ToFloat64(xInt64));
8310 Jump(exit);
8311 }
8312 Bind(&calcHash);
8313 {
8314 *res = env_->GetBuilder()->CalcHashcodeForInt(*value);
8315 Jump(exit);
8316 }
8317 }
8318
8319 Bind(&zero);
8320 *res = Int32(0);
8321 Jump(exit);
8322 }
8323
GetHash(GateRef object)8324 GateRef StubBuilder::GetHash(GateRef object)
8325 {
8326 auto env = GetEnvironment();
8327 Label subentry(env);
8328 Label isHeapObject(env);
8329 Label exit(env);
8330 env->SubCfgEntry(&subentry);
8331 GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
8332 GateRef value = Load(VariableType::JS_ANY(), object, hashOffset);
8333 DEFVARIABLE(res, VariableType::INT32(), GetInt32OfTInt(value));
8334 BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit);
8335
8336 Bind(&isHeapObject);
8337 {
8338 Label isTaggedArray(env);
8339 Label notTaggedArray(env);
8340 BRANCH(IsTaggedArray(value), &isTaggedArray, ¬TaggedArray);
8341 Bind(&isTaggedArray);
8342 GateRef extlen = GetExtraLengthOfTaggedArray(value);
8343 GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
8344 res = GetInt32OfTInt(GetValueFromTaggedArray(value, index));
8345 Jump(&exit);
8346 Bind(¬TaggedArray);
8347 res = Int32(0);
8348 Jump(&exit);
8349 }
8350 Bind(&exit);
8351 auto ret = *res;
8352 env->SubCfgExit();
8353 return ret;
8354 }
8355
SetHash(GateRef glue,GateRef object,GateRef hash)8356 void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash)
8357 {
8358 auto env = GetEnvironment();
8359 Label subentry(env);
8360 Label isHeapObject(env);
8361 Label notHeapObject(env);
8362 Label exit(env);
8363 env->SubCfgEntry(&subentry);
8364 GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
8365 GateRef value = Load(VariableType::JS_ANY(), object, hashOffset);
8366 DEFVARIABLE(res, VariableType::JS_ANY(), object);
8367 BRANCH(TaggedIsHeapObject(value), &isHeapObject, ¬HeapObject);
8368
8369 Bind(&isHeapObject);
8370 {
8371 Label isTaggedArray(env);
8372 Label notTaggedArray(env);
8373 BRANCH(IsTaggedArray(value), &isTaggedArray, ¬TaggedArray);
8374 Bind(&isTaggedArray);
8375 {
8376 GateRef extlen = GetExtraLengthOfTaggedArray(value);
8377 GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen);
8378 SetValueToTaggedArray(VariableType::JS_ANY(), glue, value, index, IntToTaggedInt(hash));
8379 Jump(&exit);
8380 }
8381 Bind(¬TaggedArray);
8382 {
8383 Label isNativePointer(env);
8384 Label notNativePointer(env);
8385 BRANCH(IsNativePointer(value), &isNativePointer, ¬NativePointer);
8386 Bind(&isNativePointer);
8387 {
8388 NewObjectStubBuilder newBuilder(this);
8389 GateRef array = newBuilder.NewTaggedArray(glue, Int32(ECMAObject::RESOLVED_MAX_SIZE));
8390 SetExtraLengthOfTaggedArray(glue, array, Int32(0));
8391 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
8392 Int32(ECMAObject::HASH_INDEX), IntToTaggedInt(hash));
8393 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array,
8394 Int32(ECMAObject::FUNCTION_EXTRA_INDEX), value);
8395 Store(VariableType::JS_ANY(), glue, object, hashOffset, array);
8396 Jump(&exit);
8397 }
8398 Bind(¬NativePointer);
8399 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
8400 Jump(&exit);
8401 }
8402 }
8403 Bind(¬HeapObject);
8404 {
8405 Store(VariableType::JS_ANY(), glue, object, hashOffset, IntToTaggedInt(hash), MemoryAttribute::NoBarrier());
8406 Jump(&exit);
8407 }
8408 Bind(&exit);
8409 env->SubCfgExit();
8410 }
8411
CalcHashcodeForObject(GateRef glue,GateRef value,Variable * res,Label * exit)8412 void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit)
8413 {
8414 auto env = GetEnvironment();
8415
8416 GateRef hash = GetHash(value);
8417 *res = hash;
8418 Label calcHash(env);
8419 BRANCH(Int32Equal(**res, Int32(0)), &calcHash, exit);
8420 Bind(&calcHash);
8421 GateRef offset = IntPtr(JSThread::GlueData::GetRandomStatePtrOffset(env_->Is32Bit()));
8422 GateRef randomStatePtr = Load(VariableType::NATIVE_POINTER(), glue, offset);
8423 GateRef randomState = Load(VariableType::INT64(), randomStatePtr, IntPtr(0));
8424 GateRef k1 = Int64Xor(randomState, Int64LSR(randomState, Int64(base::RIGHT12)));
8425 GateRef k2 = Int64Xor(k1, Int64LSL(k1, Int64(base::LEFT25)));
8426 GateRef k3 = Int64Xor(k2, Int64LSR(k2, Int64(base::RIGHT27)));
8427 Store(VariableType::INT64(), glue, randomStatePtr, IntPtr(0), k3);
8428 GateRef k4 = Int64Mul(k3, Int64(base::GET_MULTIPLY));
8429 GateRef k5 = Int64LSR(k4, Int64(base::INT64_BITS - base::INT32_BITS));
8430 GateRef k6 = Int32And(TruncInt64ToInt32(k5), Int32(INT32_MAX));
8431 SetHash(glue, value, k6);
8432 *res = k6;
8433 Jump(exit);
8434 }
8435
GetHashcodeFromString(GateRef glue,GateRef value,GateRef hir)8436 GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir)
8437 {
8438 return env_->GetBuilder()->GetHashcodeFromString(glue, value, hir);
8439 }
8440
ConstructorCheck(GateRef glue,GateRef ctor,GateRef outPut,GateRef thisObj)8441 GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj)
8442 {
8443 auto env = GetEnvironment();
8444 Label entryPass(env);
8445 Label exit(env);
8446 env->SubCfgEntry(&entryPass);
8447 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
8448 Label isHeapObject(env);
8449 Label isEcmaObj(env);
8450 Label notEcmaObj(env);
8451 BRANCH(TaggedIsHeapObject(outPut), &isHeapObject, ¬EcmaObj);
8452 Bind(&isHeapObject);
8453 BRANCH(TaggedObjectIsEcmaObject(outPut), &isEcmaObj, ¬EcmaObj);
8454 Bind(&isEcmaObj);
8455 {
8456 result = outPut;
8457 Jump(&exit);
8458 }
8459 Bind(¬EcmaObj);
8460 {
8461 Label ctorIsBase(env);
8462 Label ctorNotBase(env);
8463 BRANCH(IsBase(ctor), &ctorIsBase, &ctorNotBase);
8464 Bind(&ctorIsBase);
8465 {
8466 result = thisObj;
8467 Jump(&exit);
8468 }
8469 Bind(&ctorNotBase);
8470 {
8471 Label throwExeption(env);
8472 Label returnObj(env);
8473 BRANCH(TaggedIsUndefined(outPut), &returnObj, &throwExeption);
8474 Bind(&returnObj);
8475 result = thisObj;
8476 Jump(&exit);
8477 Bind(&throwExeption);
8478 {
8479 CallRuntime(glue, RTSTUB_ID(ThrowNonConstructorException), {});
8480 Jump(&exit);
8481 }
8482 }
8483 }
8484 Bind(&exit);
8485 auto ret = *result;
8486 env->SubCfgExit();
8487 return ret;
8488 }
8489
CalIteratorKey(GateRef glue)8490 GateRef StubBuilder::CalIteratorKey(GateRef glue)
8491 {
8492 auto env = GetEnvironment();
8493 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
8494 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
8495 GateRef iteratorKey = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ITERATOR_SYMBOL_INDEX);
8496 return iteratorKey;
8497 }
8498
GetIterator(GateRef glue,GateRef obj,ProfileOperation callback)8499 GateRef StubBuilder::GetIterator(GateRef glue, GateRef obj, ProfileOperation callback)
8500 {
8501 auto env = GetEnvironment();
8502 Label entryPass(env);
8503 Label exit(env);
8504 env->SubCfgEntry(&entryPass);
8505 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
8506 DEFVARIABLE(taggedId, VariableType::INT32(), Int32(0));
8507
8508 Label isPendingException(env);
8509 Label noPendingException(env);
8510 Label isHeapObject(env);
8511 Label objIsCallable(env);
8512 Label throwError(env);
8513 Label callExit(env);
8514
8515 GateRef iteratorKey = CalIteratorKey(glue);
8516 result = FastGetPropertyByName(glue, obj, iteratorKey, ProfileOperation());
8517 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
8518 Bind(&isPendingException);
8519 {
8520 result = Exception();
8521 Jump(&exit);
8522 }
8523 Bind(&noPendingException);
8524 callback.ProfileGetIterator(*result);
8525 BRANCH(TaggedIsHeapObject(*result), &isHeapObject, &throwError);
8526 Bind(&isHeapObject);
8527 BRANCH(IsCallable(*result), &objIsCallable, &throwError);
8528 Bind(&objIsCallable);
8529 {
8530 JSCallArgs callArgs(JSCallMode::CALL_GETTER);
8531 callArgs.callGetterArgs = { obj };
8532 CallStubBuilder callBuilder(this, glue, *result, Int32(0), 0, &result, Circuit::NullGate(), callArgs,
8533 ProfileOperation());
8534 if (env->IsBaselineBuiltin()) {
8535 callBuilder.JSCallDispatchForBaseline(&callExit);
8536 Bind(&callExit);
8537 } else {
8538 result = callBuilder.JSCallDispatch();
8539 }
8540 Jump(&exit);
8541 }
8542 Bind(&throwError);
8543 {
8544 taggedId = Int32(GET_MESSAGE_STRING_ID(ObjIsNotCallable));
8545 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(*taggedId) });
8546 result = Exception();
8547 Jump(&exit);
8548 }
8549 Bind(&exit);
8550 auto ret = *result;
8551 env->SubCfgExit();
8552 return ret;
8553 }
8554
TryStringOrSymbolToElementIndex(GateRef glue,GateRef key)8555 GateRef StubBuilder::TryStringOrSymbolToElementIndex(GateRef glue, GateRef key)
8556 {
8557 auto env = GetEnvironment();
8558 Label entry(env);
8559 env->SubCfgEntry(&entry);
8560 Label exit(env);
8561 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
8562
8563 Label keyNotSymbol(env);
8564 BRANCH(IsSymbol(key), &exit, &keyNotSymbol);
8565 Bind(&keyNotSymbol);
8566
8567 Label greatThanZero(env);
8568 Label inRange(env);
8569 Label flattenFastPath(env);
8570 auto len = GetLengthFromString(key);
8571 BRANCH(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
8572 Bind(&greatThanZero);
8573 BRANCH(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
8574 Bind(&inRange);
8575 {
8576 Label isUtf8(env);
8577 DEFVARIABLE(c, VariableType::INT32(), Int32(0));
8578 BRANCH(IsUtf16String(key), &exit, &isUtf8);
8579 Bind(&isUtf8);
8580 FlatStringStubBuilder thisFlat(this);
8581 thisFlat.FlattenString(glue, key, &flattenFastPath);
8582 Bind(&flattenFastPath);
8583 StringInfoGateRef stringInfoGate(&thisFlat);
8584 GateRef data = GetNormalStringData(stringInfoGate);
8585 c = ZExtInt8ToInt32(Load(VariableType::INT8(), data));
8586 Label isDigitZero(env);
8587 Label notDigitZero(env);
8588 BRANCH(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero);
8589 Bind(&isDigitZero);
8590 {
8591 Label lengthIsOne(env);
8592 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
8593 Bind(&lengthIsOne);
8594 {
8595 result = Int32(0);
8596 Jump(&exit);
8597 }
8598 }
8599 Bind(¬DigitZero);
8600 {
8601 Label isDigit(env);
8602 Label notIsDigit(env);
8603 DEFVARIABLE(i, VariableType::INT32(), Int32(1));
8604 DEFVARIABLE(n, VariableType::INT64(), Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
8605
8606 BRANCH(IsDigit(*c), &isDigit, ¬IsDigit);
8607 Label loopHead(env);
8608 Label loopEnd(env);
8609 Label afterLoop(env);
8610 Bind(&isDigit);
8611 BRANCH(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
8612 LoopBegin(&loopHead);
8613 {
8614 c = ZExtInt8ToInt32(Load(VariableType::INT8(), data, ZExtInt32ToPtr(*i)));
8615 Label isDigit2(env);
8616 Label notDigit2(env);
8617 BRANCH(IsDigit(*c), &isDigit2, ¬Digit2);
8618 Bind(&isDigit2);
8619 {
8620 // 10 means the base of digit is 10.
8621 n = Int64Add(Int64Mul(*n, Int64(10)),
8622 Int64Sub(SExtInt32ToInt64(*c), Int64('0')));
8623 i = Int32Add(*i, Int32(1));
8624 BRANCH(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
8625 }
8626 Bind(¬Digit2);
8627 {
8628 Label hasPoint(env);
8629 BRANCH(Int32Equal(*c, Int32('.')), &hasPoint, &exit);
8630 Bind(&hasPoint);
8631 {
8632 result = Int32(-2); // -2:return -2 means should goto slow path
8633 Jump(&exit);
8634 }
8635 }
8636 }
8637 Bind(&loopEnd);
8638 LoopEnd(&loopHead, env, glue);
8639 Bind(&afterLoop);
8640 {
8641 Label lessThanMaxIndex(env);
8642 BRANCH(Int64LessThan(*n, Int64(JSObject::MAX_ELEMENT_INDEX)),
8643 &lessThanMaxIndex, &exit);
8644 Bind(&lessThanMaxIndex);
8645 {
8646 result = TruncInt64ToInt32(*n);
8647 Jump(&exit);
8648 }
8649 }
8650 Bind(¬IsDigit);
8651 {
8652 Label isNegative(env);
8653 BRANCH(Int32Equal(*c, Int32('-')), &isNegative, &exit);
8654 Bind(&isNegative);
8655 {
8656 result = Int32(-2); // -2:return -2 means should goto slow path
8657 Jump(&exit);
8658 }
8659 }
8660 }
8661 }
8662 Bind(&exit);
8663 auto ret = *result;
8664 env->SubCfgExit();
8665 return ret;
8666 }
8667
GetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef jsType)8668 GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder,
8669 GateRef key, GateRef jsType)
8670 {
8671 auto env = GetEnvironment();
8672 Label entry(env);
8673 env->SubCfgEntry(&entry);
8674 Label exit(env);
8675 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8676
8677 Label notOnProtoChain(env);
8678 BRANCH(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
8679 Bind(¬OnProtoChain);
8680
8681 auto negativeZero = GetGlobalConstantValue(
8682 VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
8683 Label isNegativeZero(env);
8684 Label notNegativeZero(env);
8685 BRANCH(Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
8686 Bind(&isNegativeZero);
8687 {
8688 result = Undefined();
8689 Jump(&exit);
8690 }
8691 Bind(¬NegativeZero);
8692 {
8693 GateRef index = TryStringOrSymbolToElementIndex(glue, key);
8694 Label validIndex(env);
8695 Label notValidIndex(env);
8696 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
8697 Bind(&validIndex);
8698 {
8699 BuiltinsTypedArrayStubBuilder typedArrayStubBuilder(this);
8700 result = typedArrayStubBuilder.FastGetPropertyByIndex(glue, holder, index, jsType);
8701 Jump(&exit);
8702 }
8703 Bind(¬ValidIndex);
8704 {
8705 Label returnNull(env);
8706 BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
8707 Bind(&returnNull);
8708 {
8709 result = Null();
8710 Jump(&exit);
8711 }
8712 }
8713 }
8714
8715 Bind(&exit);
8716 auto ret = *result;
8717 env->SubCfgExit();
8718 return ret;
8719 }
8720
SetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef value,GateRef jsType)8721 GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key,
8722 GateRef value, GateRef jsType)
8723 {
8724 auto env = GetEnvironment();
8725 Label entry(env);
8726 env->SubCfgEntry(&entry);
8727 Label exit(env);
8728 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8729 Label notOnProtoChain(env);
8730 BRANCH(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
8731 Bind(¬OnProtoChain);
8732
8733 auto negativeZero = GetGlobalConstantValue(
8734 VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
8735 Label isNegativeZero(env);
8736 Label notNegativeZero(env);
8737 BRANCH(Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
8738 Bind(&isNegativeZero);
8739 {
8740 Label isObj(env);
8741 Label notObj(env);
8742 BRANCH(IsEcmaObject(value), &isObj, ¬Obj);
8743 Bind(&isObj);
8744 {
8745 result = Null();
8746 Jump(&exit);
8747 }
8748 Bind(¬Obj);
8749 result = Undefined();
8750 Jump(&exit);
8751 }
8752 Bind(¬NegativeZero);
8753 {
8754 GateRef index = TryStringOrSymbolToElementIndex(glue, key);
8755 Label validIndex(env);
8756 Label notValidIndex(env);
8757 BRANCH(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
8758 Bind(&validIndex);
8759 {
8760 result = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
8761 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType) });
8762 Jump(&exit);
8763 }
8764 Bind(¬ValidIndex);
8765 {
8766 Label returnNull(env);
8767 BRANCH(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
8768 Bind(&returnNull);
8769 {
8770 result = Null();
8771 Jump(&exit);
8772 }
8773 }
8774 }
8775
8776 Bind(&exit);
8777 auto ret = *result;
8778 env->SubCfgExit();
8779 return ret;
8780 }
8781
Assert(int messageId,int line,GateRef glue,GateRef condition,Label * nextLabel)8782 void StubBuilder::Assert(int messageId, int line, GateRef glue, GateRef condition, Label *nextLabel)
8783 {
8784 auto env = GetEnvironment();
8785 Label ok(env);
8786 Label notOk(env);
8787 BRANCH(condition, &ok, ¬Ok);
8788 Bind(&ok);
8789 {
8790 Jump(nextLabel);
8791 }
8792 Bind(¬Ok);
8793 {
8794 FatalPrint(glue, { Int32(messageId), Int32(line) });
8795 Jump(nextLabel);
8796 }
8797 }
8798
GetNormalStringData(const StringInfoGateRef & stringInfoGate)8799 GateRef StubBuilder::GetNormalStringData(const StringInfoGateRef &stringInfoGate)
8800 {
8801 auto env = GetEnvironment();
8802 Label entry(env);
8803 env->SubCfgEntry(&entry);
8804 Label exit(env);
8805 Label isConstantString(env);
8806 Label isLineString(env);
8807 Label isUtf8(env);
8808 Label isUtf16(env);
8809 DEFVARIABLE(result, VariableType::NATIVE_POINTER(), Undefined());
8810 BRANCH(IsConstantString(stringInfoGate.GetString()), &isConstantString, &isLineString);
8811 Bind(&isConstantString);
8812 {
8813 GateRef address = PtrAdd(stringInfoGate.GetString(), IntPtr(ConstantString::CONSTANT_DATA_OFFSET));
8814 result = PtrAdd(Load(VariableType::NATIVE_POINTER(), address, IntPtr(0)),
8815 ZExtInt32ToPtr(stringInfoGate.GetStartIndex()));
8816 Jump(&exit);
8817 }
8818 Bind(&isLineString);
8819 {
8820 GateRef data = ChangeTaggedPointerToInt64(
8821 PtrAdd(stringInfoGate.GetString(), IntPtr(LineEcmaString::DATA_OFFSET)));
8822 BRANCH(IsUtf8String(stringInfoGate.GetString()), &isUtf8, &isUtf16);
8823 Bind(&isUtf8);
8824 {
8825 result = PtrAdd(data, ZExtInt32ToPtr(stringInfoGate.GetStartIndex()));
8826 Jump(&exit);
8827 }
8828 Bind(&isUtf16);
8829 {
8830 GateRef offset = PtrMul(ZExtInt32ToPtr(stringInfoGate.GetStartIndex()), IntPtr(sizeof(uint16_t)));
8831 result = PtrAdd(data, offset);
8832 Jump(&exit);
8833 }
8834 }
8835 Bind(&exit);
8836 auto ret = *result;
8837 env->SubCfgExit();
8838 return ret;
8839 }
8840
ToNumber(GateRef glue,GateRef tagged)8841 GateRef StubBuilder::ToNumber(GateRef glue, GateRef tagged)
8842 {
8843 auto env = GetEnvironment();
8844 Label entry(env);
8845 env->SubCfgEntry(&entry);
8846 Label exit(env);
8847 Label isNumber(env);
8848 Label notNumber(env);
8849 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
8850 BRANCH(TaggedIsNumber(tagged), &isNumber, ¬Number);
8851 Bind(&isNumber);
8852 {
8853 result = tagged;
8854 Jump(&exit);
8855 }
8856 Bind(¬Number);
8857 {
8858 result = CallRuntime(glue, RTSTUB_ID(ToNumber), { tagged });
8859 Jump(&exit);
8860 }
8861 Bind(&exit);
8862 auto ret = *result;
8863 env->SubCfgExit();
8864 return ret;
8865 }
8866
ToLength(GateRef glue,GateRef target)8867 GateRef StubBuilder::ToLength(GateRef glue, GateRef target)
8868 {
8869 auto env = GetEnvironment();
8870 Label subentry(env);
8871 env->SubCfgEntry(&subentry);
8872 DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
8873 Label exit(env);
8874
8875 GateRef number = ToNumber(glue, target);
8876 Label isPendingException(env);
8877 Label noPendingException(env);
8878 BRANCH(HasPendingException(glue), &isPendingException, &noPendingException);
8879 Bind(&isPendingException);
8880 {
8881 Jump(&exit);
8882 }
8883 Bind(&noPendingException);
8884 {
8885 GateRef num = GetDoubleOfTNumber(number);
8886 Label targetLessThanZero(env);
8887 Label targetGreaterThanZero(env);
8888 Label targetLessThanSafeNumber(env);
8889 Label targetGreaterThanSafeNumber(env);
8890 BRANCH(DoubleLessThan(num, Double(0.0)), &targetLessThanZero, &targetGreaterThanZero);
8891 Bind(&targetLessThanZero);
8892 {
8893 res = DoubleToTaggedDoublePtr(Double(0.0));
8894 Jump(&exit);
8895 }
8896 Bind(&targetGreaterThanZero);
8897 BRANCH(DoubleGreaterThan(num, Double(SAFE_NUMBER)), &targetGreaterThanSafeNumber, &targetLessThanSafeNumber);
8898 Bind(&targetGreaterThanSafeNumber);
8899 {
8900 res = DoubleToTaggedDoublePtr(Double(SAFE_NUMBER));
8901 Jump(&exit);
8902 }
8903 Bind(&targetLessThanSafeNumber);
8904 {
8905 res = number;
8906 Jump(&exit);
8907 }
8908 }
8909 Bind(&exit);
8910 auto ret = *res;
8911 env->SubCfgExit();
8912 return ret;
8913 }
8914
TaggedGetNumber(GateRef x)8915 GateRef StubBuilder::TaggedGetNumber(GateRef x)
8916 {
8917 auto env = GetEnvironment();
8918 Label subentry(env);
8919 Label exit(env);
8920 env->SubCfgEntry(&subentry);
8921
8922 Label targetIsInt(env);
8923 Label targetIsDouble(env);
8924 DEFVALUE(number, env_, VariableType::FLOAT64(), Double(0));
8925 BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
8926 Bind(&targetIsInt);
8927 {
8928 number = ChangeInt32ToFloat64(TaggedGetInt(x));
8929 Jump(&exit);
8930 }
8931 Bind(&targetIsDouble);
8932 {
8933 number = GetDoubleOfTDouble(x);
8934 Jump(&exit);
8935 }
8936 Bind(&exit);
8937 GateRef ret = *number;
8938 env->SubCfgExit();
8939 return ret;
8940 }
8941
NumberGetInt(GateRef glue,GateRef x)8942 GateRef StubBuilder::NumberGetInt(GateRef glue, GateRef x)
8943 {
8944 auto env = GetEnvironment();
8945 Label subentry(env);
8946 Label exit(env);
8947 env->SubCfgEntry(&subentry);
8948
8949 Label targetIsInt(env);
8950 Label targetIsDouble(env);
8951 DEFVALUE(number, env_, VariableType::INT32(), Int32(0));
8952 BRANCH(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
8953 Bind(&targetIsInt);
8954 {
8955 number = TaggedGetInt(x);
8956 Jump(&exit);
8957 }
8958 Bind(&targetIsDouble);
8959 {
8960 number = DoubleToInt(glue, GetDoubleOfTDouble(x));
8961 Jump(&exit);
8962 }
8963 Bind(&exit);
8964 GateRef ret = *number;
8965 env->SubCfgExit();
8966 return ret;
8967 }
8968
HasStableElements(GateRef glue,GateRef obj)8969 GateRef StubBuilder::HasStableElements(GateRef glue, GateRef obj)
8970 {
8971 auto env = GetEnvironment();
8972 Label subentry(env);
8973 env->SubCfgEntry(&subentry);
8974 DEFVARIABLE(result, VariableType::BOOL(), False());
8975 Label exit(env);
8976 Label targetIsHeapObject(env);
8977 Label targetIsStableElements(env);
8978 BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
8979 Bind(&targetIsHeapObject);
8980 {
8981 GateRef jsHclass = LoadHClass(obj);
8982 BRANCH(IsStableElements(jsHclass), &targetIsStableElements, &exit);
8983 Bind(&targetIsStableElements);
8984 {
8985 GateRef guardiansOffset =
8986 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
8987 result = Load(VariableType::BOOL(), glue, guardiansOffset);
8988 Jump(&exit);
8989 }
8990 }
8991 Bind(&exit);
8992 auto res = *result;
8993 env->SubCfgExit();
8994 return res;
8995 }
8996
IsStableJSArguments(GateRef glue,GateRef obj)8997 GateRef StubBuilder::IsStableJSArguments(GateRef glue, GateRef obj)
8998 {
8999 auto env = GetEnvironment();
9000 Label subentry(env);
9001 env->SubCfgEntry(&subentry);
9002 DEFVARIABLE(result, VariableType::BOOL(), False());
9003 Label exit(env);
9004 Label targetIsHeapObject(env);
9005 Label targetIsStableArguments(env);
9006
9007 BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
9008 Bind(&targetIsHeapObject);
9009 {
9010 GateRef jsHclass = LoadHClass(obj);
9011 BRANCH(IsStableArguments(jsHclass), &targetIsStableArguments, &exit);
9012 Bind(&targetIsStableArguments);
9013 {
9014 GateRef guardiansOffset =
9015 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
9016 result = Load(VariableType::BOOL(), glue, guardiansOffset);
9017 Jump(&exit);
9018 }
9019 }
9020 Bind(&exit);
9021 auto res = *result;
9022 env->SubCfgExit();
9023 return res;
9024 }
9025
IsStableJSArray(GateRef glue,GateRef obj)9026 GateRef StubBuilder::IsStableJSArray(GateRef glue, GateRef obj)
9027 {
9028 auto env = GetEnvironment();
9029 Label subentry(env);
9030 env->SubCfgEntry(&subentry);
9031 DEFVARIABLE(result, VariableType::BOOL(), False());
9032 Label exit(env);
9033 Label targetIsHeapObject(env);
9034 Label targetIsStableArray(env);
9035
9036 BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
9037 Bind(&targetIsHeapObject);
9038 {
9039 GateRef jsHclass = LoadHClass(obj);
9040 BRANCH(IsStableArray(jsHclass), &targetIsStableArray, &exit);
9041 Bind(&targetIsStableArray);
9042 {
9043 GateRef guardiansOffset =
9044 IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
9045 GateRef guardians = Load(VariableType::BOOL(), glue, guardiansOffset);
9046 result.WriteVariable(guardians);
9047 Jump(&exit);
9048 }
9049 }
9050 Bind(&exit);
9051 auto res = *result;
9052 env->SubCfgExit();
9053 return res;
9054 }
9055
UpdateProfileTypeInfo(GateRef glue,GateRef jsFunc)9056 GateRef StubBuilder::UpdateProfileTypeInfo(GateRef glue, GateRef jsFunc)
9057 {
9058 auto env = GetEnvironment();
9059 Label entry(env);
9060 env->SubCfgEntry(&entry);
9061 Label needUpdate(env);
9062 Label exit(env);
9063 DEFVARIABLE(profileTypeInfo, VariableType::JS_POINTER(), GetProfileTypeInfo(jsFunc));
9064 BRANCH(TaggedIsUndefined(*profileTypeInfo), &needUpdate, &exit);
9065 Bind(&needUpdate);
9066 {
9067 profileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounter), { jsFunc });
9068 Jump(&exit);
9069 }
9070 Bind(&exit);
9071 auto ret = *profileTypeInfo;
9072 env->SubCfgExit();
9073 return ret;
9074 }
9075
GetFuncKind(GateRef method)9076 GateRef StubBuilder::GetFuncKind(GateRef method)
9077 {
9078 GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
9079 GateRef bitfield = Load(VariableType::INT32(), method, extraLiteralInfoOffset);
9080
9081 GateRef kind = Int32And(Int32LSR(bitfield, Int32(Method::FunctionKindBits::START_BIT)),
9082 Int32((1LU << Method::FunctionKindBits::SIZE) - 1));
9083 return kind;
9084 }
9085
GetCallSpreadArgs(GateRef glue,GateRef array,ProfileOperation callBack)9086 GateRef StubBuilder::GetCallSpreadArgs(GateRef glue, GateRef array, ProfileOperation callBack)
9087 {
9088 auto env = GetEnvironment();
9089 Label subEntry(env);
9090 env->SubCfgEntry(&subEntry);
9091 DEFVARIABLE(result, VariableType::JS_POINTER(), NullPtr());
9092 Label fastPath(env);
9093 Label noCopyPath(env);
9094 Label exit(env);
9095 Label noException(env);
9096 Label isException(env);
9097
9098 GateRef itor = GetIterator(glue, array, callBack);
9099 BRANCH(TaggedIsException(itor), &isException, &noException);
9100 Bind(&isException);
9101 {
9102 result = Exception();
9103 Jump(&exit);
9104 }
9105 Bind(&noException);
9106 GateRef needCopy = LogicAndBuilder(env)
9107 .And(Int32Equal(GetObjectType(LoadHClass(itor)), Int32(static_cast<int32_t>(JSType::JS_ARRAY_ITERATOR))))
9108 .And(IsStableJSArray(glue, array))
9109 .Done();
9110 BRANCH(needCopy, &fastPath, &noCopyPath);
9111 Bind(&fastPath);
9112 {
9113 // copy operation is omitted
9114 result = CopyJSArrayToTaggedArrayArgs(glue, array);
9115 Jump(&exit);
9116 }
9117 Bind(&noCopyPath);
9118 {
9119 result = CallRuntime(glue, RTSTUB_ID(GetCallSpreadArgs), { array });
9120 Jump(&exit);
9121 }
9122 Bind(&exit);
9123 auto ret = *result;
9124 env->SubCfgExit();
9125 return ret;
9126 }
9127
CalArrayRelativePos(GateRef index,GateRef arrayLen)9128 GateRef StubBuilder::CalArrayRelativePos(GateRef index, GateRef arrayLen)
9129 {
9130 auto env = GetEnvironment();
9131 Label entryPass(env);
9132 env->SubCfgEntry(&entryPass);
9133 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
9134
9135 Label indexLessZero(env);
9136 Label indexNotLessZero(env);
9137 Label exit(env);
9138 BRANCH(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
9139 Bind(&indexLessZero);
9140 {
9141 GateRef tempBeginIndex = Int32Add(arrayLen, index);
9142 Label beginIndexLargeZero(env);
9143 BRANCH(Int32GreaterThan(tempBeginIndex, Int32(0)), &beginIndexLargeZero, &exit);
9144 Bind(&beginIndexLargeZero);
9145 {
9146 result = tempBeginIndex;
9147 Jump(&exit);
9148 }
9149 }
9150 Bind(&indexNotLessZero);
9151 {
9152 Label lessLen(env);
9153 Label largeLen(env);
9154 BRANCH(Int32LessThan(index, arrayLen), &lessLen, &largeLen);
9155 Bind(&lessLen);
9156 {
9157 result = index;
9158 Jump(&exit);
9159 }
9160 Bind(&largeLen);
9161 {
9162 result = arrayLen;
9163 Jump(&exit);
9164 }
9165 }
9166
9167 Bind(&exit);
9168 auto ret = *result;
9169 env->SubCfgExit();
9170 return ret;
9171 }
9172
AppendSkipHole(GateRef glue,GateRef first,GateRef second,GateRef copyLength)9173 GateRef StubBuilder::AppendSkipHole(GateRef glue, GateRef first, GateRef second, GateRef copyLength)
9174 {
9175 auto env = GetEnvironment();
9176 Label subEntry(env);
9177 env->SubCfgEntry(&subEntry);
9178 Label exit(env);
9179 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
9180 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9181 DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
9182
9183 GateRef firstLength = GetLengthOfTaggedArray(first);
9184 GateRef secondLength = GetLengthOfTaggedArray(second);
9185 NewObjectStubBuilder newBuilder(this);
9186 GateRef array = newBuilder.NewTaggedArray(glue, copyLength);
9187 Label loopHead(env);
9188 Label loopEnd(env);
9189 Label afterLoop(env);
9190 Label storeValue(env);
9191 Label notHole(env);
9192 Jump(&loopHead);
9193 LoopBegin(&loopHead);
9194 {
9195 BRANCH(Int32UnsignedLessThan(*index, firstLength), &storeValue, &afterLoop);
9196 Bind(&storeValue);
9197 {
9198 GateRef value = GetValueFromTaggedArray(first, *index);
9199 BRANCH(TaggedIsHole(value), &afterLoop, ¬Hole);
9200 Bind(¬Hole);
9201 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value);
9202 index = Int32Add(*index, Int32(1));
9203 Jump(&loopEnd);
9204 }
9205 }
9206 Bind(&loopEnd);
9207 LoopEnd(&loopHead, env, glue);
9208 Bind(&afterLoop);
9209 {
9210 Label loopHead1(env);
9211 Label loopEnd1(env);
9212 Label storeValue1(env);
9213 Label notHole1(env);
9214 Jump(&loopHead1);
9215 LoopBegin(&loopHead1);
9216 {
9217 BRANCH(Int32UnsignedLessThan(*i, secondLength), &storeValue1, &exit);
9218 Bind(&storeValue1);
9219 {
9220 GateRef value1 = GetValueFromTaggedArray(second, *i);
9221 BRANCH(TaggedIsHole(value1), &exit, ¬Hole1);
9222 Bind(¬Hole1);
9223 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value1);
9224 i = Int32Add(*i, Int32(1));
9225 index = Int32Add(*index, Int32(1));
9226 Jump(&loopEnd1);
9227 }
9228 }
9229 Bind(&loopEnd1);
9230 LoopEnd(&loopHead1);
9231 }
9232 Bind(&exit);
9233 res = array;
9234 auto ret = *res;
9235 env->SubCfgExit();
9236 return ret;
9237 }
9238
ToCharCode(GateRef number)9239 GateRef StubBuilder::ToCharCode(GateRef number)
9240 {
9241 auto env = GetEnvironment();
9242 Label subEntry(env);
9243 env->SubCfgEntry(&subEntry);
9244 Label exit(env);
9245 DEFVARIABLE(result, VariableType::INT32(), number);
9246
9247 Label lessThanTen(env);
9248 Label notLessThanTen(env);
9249 BRANCH(Int32LessThan(number, Int32(10)), &lessThanTen, ¬LessThanTen); // 10: means number
9250 Bind(&lessThanTen);
9251 {
9252 result = Int32Add(Int32('0'), *result);
9253 Jump(&exit);
9254 }
9255 Bind(¬LessThanTen);
9256 {
9257 result = Int32Sub(*result, Int32(10)); // 10: means number
9258 result = Int32Add(Int32('a'), *result);
9259 Jump(&exit);
9260 }
9261 Bind(&exit);
9262 auto ret = *result;
9263 env->SubCfgExit();
9264 return ret;
9265 }
9266
IntToEcmaString(GateRef glue,GateRef number)9267 GateRef StubBuilder::IntToEcmaString(GateRef glue, GateRef number)
9268 {
9269 auto env = GetEnvironment();
9270 Label subEntry(env);
9271 env->SubCfgEntry(&subEntry);
9272 Label exit(env);
9273 DEFVARIABLE(n, VariableType::INT32(), number);
9274 DEFVARIABLE(result, VariableType::JS_POINTER(), Hole());
9275
9276 GateRef isPositive = Int32GreaterThanOrEqual(number, Int32(0));
9277 GateRef isSingle = Int32LessThan(number, Int32(10));
9278 Label process(env);
9279 Label callRuntime(env);
9280 Label afterNew(env);
9281 BRANCH(BitAnd(isPositive, isSingle), &process, &callRuntime);
9282 Bind(&process);
9283 {
9284 NewObjectStubBuilder newBuilder(this);
9285 newBuilder.SetParameters(glue, 0);
9286 newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), true);
9287 Bind(&afterNew);
9288 n = Int32Add(Int32('0'), *n);
9289 GateRef dst = ChangeTaggedPointerToInt64(PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET)));
9290 Store(VariableType::INT8(), glue, dst, IntPtr(0), TruncInt32ToInt8(*n));
9291 Jump(&exit);
9292 }
9293 Bind(&callRuntime);
9294 {
9295 result = CallRuntime(glue, RTSTUB_ID(IntToString), { IntToTaggedInt(*n) });
9296 Jump(&exit);
9297 }
9298 Bind(&exit);
9299 auto ret = *result;
9300 env->SubCfgExit();
9301 return ret;
9302 }
9303
NumberToString(GateRef glue,GateRef number)9304 GateRef StubBuilder::NumberToString(GateRef glue, GateRef number)
9305 {
9306 DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
9307 res = CallRuntime(glue, RTSTUB_ID(NumberToString), { number });
9308 return *res;
9309 }
9310
RestoreElementsKindToGeneric(GateRef glue,GateRef jsHClass)9311 void StubBuilder::RestoreElementsKindToGeneric(GateRef glue, GateRef jsHClass)
9312 {
9313 GateRef newKind = Int32(static_cast<int32_t>(ElementsKind::GENERIC));
9314 SetElementsKindToJSHClass(glue, jsHClass, newKind);
9315 }
9316
GetTaggedValueWithElementsKind(GateRef receiver,GateRef index)9317 GateRef StubBuilder::GetTaggedValueWithElementsKind(GateRef receiver, GateRef index)
9318 {
9319 auto env = GetEnvironment();
9320 Label entryPass(env);
9321 env->SubCfgEntry(&entryPass);
9322 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
9323 Label exit(env);
9324
9325 GateRef hclass = LoadHClass(receiver);
9326 DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
9327 Label isMutantTaggedArray(env);
9328 Label isNotMutantTaggedArray(env);
9329 GateRef elements = GetElementsArray(receiver);
9330 BRANCH(IsMutantTaggedArray(elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
9331 Bind(&isNotMutantTaggedArray);
9332 {
9333 elementsKind = Int32(static_cast<int32_t>(ElementsKind::GENERIC));
9334 Jump(&isMutantTaggedArray);
9335 }
9336 Bind(&isMutantTaggedArray);
9337 GateRef rawValue = GetValueFromMutantTaggedArray(elements, index);
9338 Label isSpecialHole(env);
9339 Label isNotSpecialHole(env);
9340 BRANCH(Int64Equal(rawValue, SpecialHole()), &isSpecialHole, &isNotSpecialHole);
9341 Bind(&isSpecialHole);
9342 {
9343 Jump(&exit);
9344 }
9345 Bind(&isNotSpecialHole);
9346 {
9347 Label isInt(env);
9348 Label isNotInt(env);
9349 GateRef elementsKindIntLowerBound = Int32GreaterThanOrEqual(*elementsKind,
9350 Int32(static_cast<int32_t>(ElementsKind::INT)));
9351 GateRef elementsKindIntUpperBound = Int32LessThanOrEqual(*elementsKind,
9352 Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)));
9353 GateRef checkIntKind = BitAnd(elementsKindIntLowerBound, elementsKindIntUpperBound);
9354 BRANCH(checkIntKind, &isInt, &isNotInt);
9355 Bind(&isInt);
9356 {
9357 result = Int64ToTaggedIntPtr(rawValue);
9358 Jump(&exit);
9359 }
9360 Bind(&isNotInt);
9361 {
9362 Label isNumber(env);
9363 Label isNotNumber(env);
9364 GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
9365 Int32(static_cast<int32_t>(ElementsKind::NUMBER)));
9366 GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
9367 Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)));
9368 GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
9369 BRANCH(checkNumberKind, &isNumber, &isNotNumber);
9370 Bind(&isNumber);
9371 {
9372 GateRef numberValue = CastInt64ToFloat64(rawValue);
9373 result = DoubleToTaggedDoublePtr(numberValue);
9374 Jump(&exit);
9375 }
9376 Bind(&isNotNumber);
9377 {
9378 result = Int64ToTaggedPtr(rawValue);
9379 Jump(&exit);
9380 }
9381 }
9382 }
9383 Bind(&exit);
9384 auto ret = *result;
9385 env->SubCfgExit();
9386 return ret;
9387 }
9388
SetValueWithElementsKind(GateRef glue,GateRef receiver,GateRef rawValue,GateRef index,GateRef needTransition,GateRef extraKind)9389 GateRef StubBuilder::SetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef rawValue,
9390 GateRef index, GateRef needTransition, GateRef extraKind)
9391 {
9392 auto env = GetEnvironment();
9393 Label entryPass(env);
9394 env->SubCfgEntry(&entryPass);
9395 DEFVARIABLE(result, VariableType::INT64(), SpecialHole());
9396 Label exit(env);
9397
9398 Label transitElementsKind(env);
9399 Label finishTransition(env);
9400 BRANCH(needTransition, &transitElementsKind, &finishTransition);
9401 Bind(&transitElementsKind);
9402 {
9403 TransitToElementsKind(glue, receiver, rawValue, extraKind);
9404 Jump(&finishTransition);
9405 }
9406 Bind(&finishTransition);
9407 GateRef hclass = LoadHClass(receiver);
9408 DEFVARIABLE(elementsKind, VariableType::INT32(), GetElementsKindFromHClass(hclass));
9409 Label setValue(env);
9410 Label isMutantTaggedArray(env);
9411 Label isNotMutantTaggedArray(env);
9412 GateRef elements = GetElementsArray(receiver);
9413 BRANCH(IsMutantTaggedArray(elements), &isMutantTaggedArray, &isNotMutantTaggedArray);
9414 Bind(&isNotMutantTaggedArray);
9415 {
9416 elementsKind = Int32(static_cast<int32_t>(ElementsKind::GENERIC));
9417 Jump(&isMutantTaggedArray);
9418 }
9419 Bind(&isMutantTaggedArray);
9420 Label isHole(env);
9421 Label isNotHole(env);
9422 GateRef elementsKindVal = *elementsKind;
9423 GateRef checkInNumersKind = LogicAndBuilder(env)
9424 .And(TaggedIsHole(rawValue))
9425 .And(Int32GreaterThanOrEqual(elementsKindVal, Int32(static_cast<int32_t>(ElementsKind::HOLE))))
9426 .And(Int32LessThan(elementsKindVal, Int32(static_cast<int32_t>(ElementsKind::STRING))))
9427 .Done();
9428 BRANCH(checkInNumersKind, &isHole, &isNotHole);
9429 Bind(&isHole);
9430 {
9431 Jump(&setValue);
9432 }
9433 Bind(&isNotHole);
9434 {
9435 Label isInt(env);
9436 Label isNotInt(env);
9437 GateRef elementsKindIntLB = Int32GreaterThanOrEqual(*elementsKind,
9438 Int32(static_cast<int32_t>(ElementsKind::INT)));
9439 GateRef elementsKindIntUB = Int32LessThanOrEqual(*elementsKind,
9440 Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)));
9441 GateRef checkIntKind = BitAnd(elementsKindIntLB, elementsKindIntUB);
9442 BRANCH(checkIntKind, &isInt, &isNotInt);
9443 Bind(&isInt);
9444 {
9445 result = GetInt64OfTInt(rawValue);
9446 Jump(&setValue);
9447 }
9448 Bind(&isNotInt);
9449 {
9450 Label isNumber(env);
9451 Label isNotNumber(env);
9452 GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(*elementsKind,
9453 Int32(static_cast<int32_t>(ElementsKind::NUMBER)));
9454 GateRef elementsKindNumberUB = Int32LessThanOrEqual(*elementsKind,
9455 Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)));
9456 GateRef checkNumberKind = BitAnd(elementsKindNumberLB, elementsKindNumberUB);
9457 BRANCH(checkNumberKind, &isNumber, &isNotNumber);
9458 Bind(&isNumber);
9459 {
9460 Label isNumberInt(env);
9461 Label isNotNumberInt(env);
9462 BRANCH(TaggedIsInt(rawValue), &isNumberInt, &isNotNumberInt);
9463 Bind(&isNumberInt);
9464 {
9465 result = CastDoubleToInt64(GetDoubleOfTInt(rawValue));
9466 Jump(&setValue);
9467 }
9468 Bind(&isNotNumberInt);
9469 {
9470 result = CastDoubleToInt64(GetDoubleOfTDouble(rawValue));
9471 Jump(&setValue);
9472 }
9473 }
9474 Bind(&isNotNumber);
9475 {
9476 result = ChangeTaggedPointerToInt64(rawValue);
9477 Jump(&setValue);
9478 }
9479 }
9480 }
9481 Bind(&setValue);
9482 Label storeToNormalArray(env);
9483 Label storeToMutantArray(env);
9484 BRANCH(TaggedIsHeapObject(rawValue), &storeToNormalArray, &storeToMutantArray);
9485 Bind(&storeToNormalArray);
9486 {
9487 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, *result);
9488 Jump(&exit);
9489 }
9490 Bind(&storeToMutantArray);
9491 {
9492 SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, *result);
9493 Jump(&exit);
9494 }
9495 Bind(&exit);
9496 auto ret = *result;
9497 env->SubCfgExit();
9498 return ret;
9499 }
9500
FastSetValueWithElementsKind(GateRef glue,GateRef elements,GateRef rawValue,GateRef index,ElementsKind kind)9501 void StubBuilder::FastSetValueWithElementsKind(GateRef glue, GateRef elements, GateRef rawValue,
9502 GateRef index, ElementsKind kind)
9503 {
9504 auto env = GetEnvironment();
9505 Label entryPass(env);
9506 env->SubCfgEntry(&entryPass);
9507 Label exit(env);
9508 if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
9509 SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
9510 Jump(&exit);
9511 } else {
9512 Label storeToNormalArray(env);
9513 Label storeToMutantArray(env);
9514 BRANCH(TaggedIsHeapObject(rawValue), &storeToNormalArray, &storeToMutantArray);
9515 Bind(&storeToNormalArray);
9516 {
9517 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, rawValue);
9518 Jump(&exit);
9519 }
9520 Bind(&storeToMutantArray);
9521 {
9522 SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
9523 Jump(&exit);
9524 }
9525 }
9526 Bind(&exit);
9527 env->SubCfgExit();
9528 }
9529
CopyJSArrayToTaggedArrayArgs(GateRef glue,GateRef srcObj)9530 GateRef StubBuilder::CopyJSArrayToTaggedArrayArgs(GateRef glue, GateRef srcObj)
9531 {
9532 auto env = GetEnvironment();
9533 Label entryPass(env);
9534 env->SubCfgEntry(&entryPass);
9535 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
9536 Label exit(env);
9537
9538 Label isMutantTaggedArray(env);
9539 result = GetElementsArray(srcObj);
9540 BRANCH(IsMutantTaggedArray(*result), &isMutantTaggedArray, &exit);
9541 Bind(&isMutantTaggedArray);
9542 {
9543 GateRef argvLength = GetLengthOfTaggedArray(*result);
9544 NewObjectStubBuilder newBuilder(this);
9545 GateRef argv = newBuilder.NewTaggedArray(glue, argvLength);
9546 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9547 Label loopHead(env);
9548 Label loopEnd(env);
9549 Label afterLoop(env);
9550 Label storeValue(env);
9551 Jump(&loopHead);
9552 LoopBegin(&loopHead);
9553 {
9554 BRANCH(Int32UnsignedLessThan(*index, argvLength), &storeValue, &afterLoop);
9555 Bind(&storeValue);
9556 {
9557 GateRef value = GetTaggedValueWithElementsKind(srcObj, *index);
9558 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argv, *index, value);
9559 index = Int32Add(*index, Int32(1));
9560 Jump(&loopEnd);
9561 }
9562 }
9563 Bind(&loopEnd);
9564 LoopEnd(&loopHead);
9565 Bind(&afterLoop);
9566 {
9567 result = argv;
9568 Jump(&exit);
9569 }
9570 }
9571 Bind(&exit);
9572 auto ret = *result;
9573 env->SubCfgExit();
9574 return ret;
9575 }
9576
MigrateArrayWithKind(GateRef glue,GateRef object,GateRef oldKind,GateRef newKind)9577 void StubBuilder::MigrateArrayWithKind(GateRef glue, GateRef object, GateRef oldKind, GateRef newKind)
9578 {
9579 auto env = GetEnvironment();
9580 Label entryPass(env);
9581 env->SubCfgEntry(&entryPass);
9582 Label exit(env);
9583
9584 Label elementsKindOn(env);
9585 GateRef isElementsKindEnabled = IsEnableElementsKind(glue);
9586 BRANCH(isElementsKindEnabled, &elementsKindOn, &exit);
9587 Bind(&elementsKindOn);
9588
9589 DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
9590 Label doMigration(env);
9591 Label migrateFromInt(env);
9592 Label migrateOtherKinds(env);
9593
9594 GateRef noNeedMigration = LogicOrBuilder(env)
9595 .Or(Int32Equal(oldKind, newKind))
9596 .Or(BitAnd(Int32Equal(oldKind, Int32(static_cast<uint32_t>(ElementsKind::INT))),
9597 Int32Equal(newKind, Int32(static_cast<uint32_t>(ElementsKind::HOLE_INT)))))
9598 .Or(BitAnd(Int32Equal(oldKind, Int32(static_cast<uint32_t>(ElementsKind::NUMBER))),
9599 Int32Equal(newKind, Int32(static_cast<uint32_t>(ElementsKind::HOLE_NUMBER)))))
9600 .Done();
9601 BRANCH(noNeedMigration, &exit, &doMigration);
9602 Bind(&doMigration);
9603 GateRef needCOW = IsJsCOWArray(object);
9604 BRANCH(ElementsKindIsIntOrHoleInt(oldKind), &migrateFromInt, &migrateOtherKinds);
9605 Bind(&migrateFromInt);
9606 {
9607 Label migrateToHeapValuesFromInt(env);
9608 Label migrateToRawValuesFromInt(env);
9609 Label migrateToNumbersFromInt(env);
9610 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromInt, &migrateToRawValuesFromInt);
9611 Bind(&migrateToHeapValuesFromInt);
9612 {
9613 newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, True());
9614 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9615 Jump(&exit);
9616 }
9617 Bind(&migrateToRawValuesFromInt);
9618 {
9619 BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumbersFromInt, &exit);
9620 Bind(&migrateToNumbersFromInt);
9621 {
9622 MigrateFromHoleIntToHoleNumber(glue, object);
9623 Jump(&exit);
9624 }
9625 }
9626 }
9627 Bind(&migrateOtherKinds);
9628 {
9629 Label migrateFromNumber(env);
9630 Label migrateToHeapValuesFromNum(env);
9631 Label migrateToRawValuesFromNum(env);
9632 Label migrateToIntFromNum(env);
9633 Label migrateToRawValueFromTagged(env);
9634 BRANCH(ElementsKindIsNumOrHoleNum(oldKind), &migrateFromNumber, &migrateToRawValueFromTagged);
9635 Bind(&migrateFromNumber);
9636 {
9637 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToHeapValuesFromNum, &migrateToRawValuesFromNum);
9638 Bind(&migrateToHeapValuesFromNum);
9639 {
9640 Label migrateToTaggedFromNum(env);
9641 BRANCH(ElementsKindIsHeapKind(newKind), &migrateToTaggedFromNum, &exit);
9642 Bind(&migrateToTaggedFromNum);
9643 {
9644 newElements = MigrateFromRawValueToHeapValues(glue, object, needCOW, False());
9645 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9646 Jump(&exit);
9647 }
9648 }
9649 Bind(&migrateToRawValuesFromNum);
9650 {
9651 BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromNum, &exit);
9652 Bind(&migrateToIntFromNum);
9653 {
9654 MigrateFromHoleNumberToHoleInt(glue, object);
9655 Jump(&exit);
9656 }
9657 }
9658 }
9659 Bind(&migrateToRawValueFromTagged);
9660 {
9661 Label migrateToIntFromTagged(env);
9662 Label migrateToOthersFromTagged(env);
9663 BRANCH(ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromTagged, &migrateToOthersFromTagged);
9664 Bind(&migrateToIntFromTagged);
9665 {
9666 newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, True());
9667 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9668 Jump(&exit);
9669 }
9670 Bind(&migrateToOthersFromTagged);
9671 {
9672 Label migrateToNumFromTagged(env);
9673 BRANCH(ElementsKindIsNumOrHoleNum(newKind), &migrateToNumFromTagged, &exit);
9674 Bind(&migrateToNumFromTagged);
9675 {
9676 newElements = MigrateFromHeapValueToRawValue(glue, object, needCOW, False());
9677 SetElementsArray(VariableType::JS_ANY(), glue, object, *newElements);
9678 Jump(&exit);
9679 }
9680 }
9681 }
9682 }
9683 Bind(&exit);
9684 env->SubCfgExit();
9685 }
9686
MigrateFromRawValueToHeapValues(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)9687 GateRef StubBuilder::MigrateFromRawValueToHeapValues(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
9688 {
9689 auto env = GetEnvironment();
9690 Label entryPass(env);
9691 env->SubCfgEntry(&entryPass);
9692 DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
9693 Label exit(env);
9694
9695 GateRef elements = GetElementsArray(object);
9696 GateRef length = GetLengthOfTaggedArray(elements);
9697 Label createCOW(env);
9698 Label createNormal(env);
9699 Label finishElementsInit(env);
9700 BRANCH(needCOW, &createCOW, &createNormal);
9701 Bind(&createCOW);
9702 {
9703 newElements = CallRuntime(glue, RTSTUB_ID(NewCOWTaggedArray), { IntToTaggedPtr(length) });
9704 Jump(&finishElementsInit);
9705 }
9706 Bind(&createNormal);
9707 {
9708 newElements = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedPtr(length) });
9709 Jump(&finishElementsInit);
9710 }
9711 Bind(&finishElementsInit);
9712
9713 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9714 Label loopHead(env);
9715 Label loopEnd(env);
9716 Label afterLoop(env);
9717 Label storeValue(env);
9718 Jump(&loopHead);
9719 LoopBegin(&loopHead);
9720 {
9721 Label storeHole(env);
9722 Label storeNormalValue(env);
9723 Label finishStore(env);
9724 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9725 Bind(&storeValue);
9726 {
9727 Label rawValueIsInt(env);
9728 Label rawValueIsNumber(env);
9729 GateRef value = GetValueFromMutantTaggedArray(elements, *index);
9730 BRANCH(ValueIsSpecialHole(value), &storeHole, &storeNormalValue);
9731 Bind(&storeHole);
9732 {
9733 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, Hole());
9734 Jump(&finishStore);
9735 }
9736 Bind(&storeNormalValue);
9737 {
9738 BRANCH(isIntKind, &rawValueIsInt, &rawValueIsNumber);
9739 Bind(&rawValueIsInt);
9740 {
9741 GateRef convertedInt = Int64ToTaggedIntPtr(value);
9742 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedInt);
9743 Jump(&finishStore);
9744 }
9745 Bind(&rawValueIsNumber);
9746 {
9747 GateRef tmpDouble = CastInt64ToFloat64(value);
9748 GateRef convertedDouble = DoubleToTaggedDoublePtr(tmpDouble);
9749 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *newElements, *index, convertedDouble);
9750 Jump(&finishStore);
9751 }
9752 }
9753 Bind(&finishStore);
9754 {
9755 index = Int32Add(*index, Int32(1));
9756 Jump(&loopEnd);
9757 }
9758 }
9759 }
9760 Bind(&loopEnd);
9761 LoopEnd(&loopHead);
9762 Bind(&afterLoop);
9763 {
9764 Jump(&exit);
9765 }
9766 Bind(&exit);
9767 auto ret = *newElements;
9768 env->SubCfgExit();
9769 return ret;
9770 }
9771
MigrateFromHeapValueToRawValue(GateRef glue,GateRef object,GateRef needCOW,GateRef isIntKind)9772 GateRef StubBuilder::MigrateFromHeapValueToRawValue(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind)
9773 {
9774 auto env = GetEnvironment();
9775 Label entryPass(env);
9776 env->SubCfgEntry(&entryPass);
9777 DEFVARIABLE(newElements, VariableType::JS_ANY(), Undefined());
9778 Label exit(env);
9779
9780 GateRef elements = GetElementsArray(object);
9781 GateRef length = GetLengthOfTaggedArray(elements);
9782 Label createCOW(env);
9783 Label createNormal(env);
9784 Label finishElementsInit(env);
9785 BRANCH(needCOW, &createCOW, &createNormal);
9786 Bind(&createCOW);
9787 {
9788 newElements = CallRuntime(glue, RTSTUB_ID(NewCOWMutantTaggedArray), { IntToTaggedPtr(length) });
9789 Jump(&finishElementsInit);
9790 }
9791 Bind(&createNormal);
9792 {
9793 newElements = CallRuntime(glue, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedPtr(length) });
9794 Jump(&finishElementsInit);
9795 }
9796 Bind(&finishElementsInit);
9797
9798 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9799 Label loopHead(env);
9800 Label loopEnd(env);
9801 Label afterLoop(env);
9802 Label storeValue(env);
9803 Jump(&loopHead);
9804 LoopBegin(&loopHead);
9805 {
9806 Label storeSpecialHole(env);
9807 Label storeNormalValue(env);
9808 Label finishStore(env);
9809 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9810 Bind(&storeValue);
9811 {
9812 Label convertToInt(env);
9813 Label convertToDouble(env);
9814 GateRef value = GetValueFromTaggedArray(elements, *index);
9815 BRANCH(TaggedIsHole(value), &storeSpecialHole, &storeNormalValue);
9816 Bind(&storeSpecialHole);
9817 {
9818 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, SpecialHole());
9819 Jump(&finishStore);
9820 }
9821 Bind(&storeNormalValue);
9822 {
9823 Label valueIsInt(env);
9824 Label valueIsDouble(env);
9825 BRANCH(isIntKind, &convertToInt, &convertToDouble);
9826 Bind(&convertToInt);
9827 {
9828 GateRef convertedInt = GetInt64OfTInt(value);
9829 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index, convertedInt);
9830 Jump(&finishStore);
9831 }
9832 Bind(&convertToDouble);
9833 {
9834 BRANCH(TaggedIsInt(value), &valueIsInt, &valueIsDouble);
9835 Bind(&valueIsInt);
9836 {
9837 GateRef convertedDoubleFromTInt = CastDoubleToInt64(GetDoubleOfTInt(value));
9838 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
9839 convertedDoubleFromTInt);
9840 Jump(&finishStore);
9841 }
9842 Bind(&valueIsDouble);
9843 {
9844 GateRef convertedDoubleFromTDouble = CastDoubleToInt64(GetDoubleOfTDouble(value));
9845 SetValueToTaggedArray(VariableType::INT64(), glue, *newElements, *index,
9846 convertedDoubleFromTDouble);
9847 Jump(&finishStore);
9848 }
9849 }
9850 }
9851 Bind(&finishStore);
9852 {
9853 index = Int32Add(*index, Int32(1));
9854 Jump(&loopEnd);
9855 }
9856 }
9857 }
9858 Bind(&loopEnd);
9859 LoopEnd(&loopHead);
9860 Bind(&afterLoop);
9861 {
9862 Jump(&exit);
9863 }
9864 Bind(&exit);
9865 auto ret = *newElements;
9866 env->SubCfgExit();
9867 return ret;
9868 }
9869
MigrateFromHoleIntToHoleNumber(GateRef glue,GateRef object)9870 void StubBuilder::MigrateFromHoleIntToHoleNumber(GateRef glue, GateRef object)
9871 {
9872 auto env = GetEnvironment();
9873 Label entryPass(env);
9874 env->SubCfgEntry(&entryPass);
9875 Label exit(env);
9876
9877 GateRef elements = GetElementsArray(object);
9878 GateRef length = GetLengthOfTaggedArray(elements);
9879 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9880 Label loopHead(env);
9881 Label loopEnd(env);
9882 Label afterLoop(env);
9883 Label storeValue(env);
9884 Jump(&loopHead);
9885 LoopBegin(&loopHead);
9886 {
9887 Label storeNormalValue(env);
9888 Label finishStore(env);
9889 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9890 Bind(&storeValue);
9891 {
9892 GateRef value = GetValueFromMutantTaggedArray(elements, *index);
9893 BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
9894 Bind(&storeNormalValue);
9895 {
9896 GateRef intVal = TruncInt64ToInt32(value);
9897 GateRef convertedValue = CastDoubleToInt64(ChangeInt32ToFloat64(intVal));
9898 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
9899 convertedValue);
9900 Jump(&finishStore);
9901 }
9902 Bind(&finishStore);
9903 {
9904 index = Int32Add(*index, Int32(1));
9905 Jump(&loopEnd);
9906 }
9907 }
9908 }
9909 Bind(&loopEnd);
9910 LoopEnd(&loopHead);
9911 Bind(&afterLoop);
9912 {
9913 Jump(&exit);
9914 }
9915 Bind(&exit);
9916 env->SubCfgExit();
9917 }
9918
MigrateFromHoleNumberToHoleInt(GateRef glue,GateRef object)9919 void StubBuilder::MigrateFromHoleNumberToHoleInt(GateRef glue, GateRef object)
9920 {
9921 auto env = GetEnvironment();
9922 Label entryPass(env);
9923 env->SubCfgEntry(&entryPass);
9924 Label exit(env);
9925
9926 GateRef elements = GetElementsArray(object);
9927 GateRef length = GetLengthOfTaggedArray(elements);
9928 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
9929 Label loopHead(env);
9930 Label loopEnd(env);
9931 Label afterLoop(env);
9932 Label storeValue(env);
9933 Jump(&loopHead);
9934 LoopBegin(&loopHead);
9935 {
9936 Label storeNormalValue(env);
9937 Label finishStore(env);
9938 BRANCH(Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
9939 Bind(&storeValue);
9940 {
9941 GateRef value = GetValueFromMutantTaggedArray(elements, *index);
9942 BRANCH(ValueIsSpecialHole(value), &finishStore, &storeNormalValue);
9943 Bind(&storeNormalValue);
9944 {
9945 GateRef doubleVal = CastInt64ToFloat64(value);
9946 GateRef convertedValue = SExtInt32ToInt64(ChangeFloat64ToInt32(doubleVal));
9947 SetValueToTaggedArray(VariableType::INT64(), glue, elements, *index,
9948 convertedValue);
9949 Jump(&finishStore);
9950 }
9951 Bind(&finishStore);
9952 {
9953 index = Int32Add(*index, Int32(1));
9954 Jump(&loopEnd);
9955 }
9956 }
9957 }
9958 Bind(&loopEnd);
9959 LoopEnd(&loopHead);
9960 Bind(&afterLoop);
9961 {
9962 Jump(&exit);
9963 }
9964 Bind(&exit);
9965 env->SubCfgExit();
9966 }
9967
IsDetachedBuffer(GateRef buffer)9968 GateRef StubBuilder::IsDetachedBuffer(GateRef buffer)
9969 {
9970 auto env = GetEnvironment();
9971 Label entryPass(env);
9972 env->SubCfgEntry(&entryPass);
9973 Label isNull(env);
9974 Label exit(env);
9975 Label isByteArray(env);
9976 Label notByteArray(env);
9977 DEFVARIABLE(result, VariableType::BOOL(), False());
9978 BRANCH(IsByteArray(buffer), &isByteArray, ¬ByteArray);
9979 Bind(&isByteArray);
9980 {
9981 Jump(&exit);
9982 }
9983 Bind(¬ByteArray);
9984 {
9985 GateRef dataSlot = GetArrayBufferData(buffer);
9986 BRANCH(TaggedIsNull(dataSlot), &isNull, &exit);
9987 Bind(&isNull);
9988 {
9989 result = True();
9990 Jump(&exit);
9991 }
9992 }
9993 Bind(&exit);
9994 auto ret = *result;
9995 env->SubCfgExit();
9996 return ret;
9997 }
9998
DefineFunc(GateRef glue,GateRef constpool,GateRef index,FunctionKind targetKind)9999 GateRef StubBuilder::DefineFunc(GateRef glue, GateRef constpool, GateRef index, FunctionKind targetKind)
10000 {
10001 auto env = GetEnvironment();
10002 Label subentry(env);
10003 env->SubCfgEntry(&subentry);
10004 Label exit(env);
10005 DEFVARIABLE(ihc, VariableType::JS_ANY(), Undefined());
10006 DEFVARIABLE(val, VariableType::JS_ANY(), Undefined());
10007 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
10008
10009 Label isHeapObject(env);
10010 Label afterAOTLiteral(env);
10011 Label tryGetAOTIhc(env);
10012 //AOT ihc infos always in unshareConstpool
10013 //If is runing on AOT,unshareConstpool is definitely not a hole
10014 //So wo can skip if unshareConstpool is hole
10015 GateRef unsharedConstpool = GetUnsharedConstpoolFromGlue(glue, constpool);
10016 BRANCH(TaggedIsHole(unsharedConstpool), &afterAOTLiteral, &tryGetAOTIhc);
10017 Bind(&tryGetAOTIhc);
10018 {
10019 val = GetValueFromTaggedArray(unsharedConstpool, index);
10020 BRANCH(TaggedIsHeapObject(*val), &isHeapObject, &afterAOTLiteral);
10021 {
10022 Bind(&isHeapObject);
10023 Label isAOTLiteral(env);
10024 BRANCH(IsAOTLiteralInfo(*val), &isAOTLiteral, &afterAOTLiteral);
10025 {
10026 Bind(&isAOTLiteral);
10027 {
10028 ihc = GetIhcFromAOTLiteralInfo(*val);
10029 Jump(&afterAOTLiteral);
10030 }
10031 }
10032 }
10033 }
10034 Bind(&afterAOTLiteral);
10035 GateRef method = GetMethodFromConstPool(glue, constpool, index);
10036 Label isSendableFunc(env);
10037 Label isNotSendableFunc(env);
10038 Label afterDealWithCompiledStatus(env);
10039 BRANCH(IsSendableFunction(method), &isSendableFunc, &isNotSendableFunc);
10040 Bind(&isSendableFunc);
10041 {
10042 NewObjectStubBuilder newBuilder(this);
10043 result = newBuilder.NewJSSendableFunction(glue, method, targetKind);
10044 Jump(&afterDealWithCompiledStatus);
10045 }
10046 Bind(&isNotSendableFunc);
10047 {
10048 NewObjectStubBuilder newBuilder(this);
10049 result = newBuilder.NewJSFunction(glue, method, targetKind);
10050 Jump(&afterDealWithCompiledStatus);
10051 }
10052 Bind(&afterDealWithCompiledStatus);
10053
10054 Label ihcNotUndefined(env);
10055 BRANCH(TaggedIsUndefined(*ihc), &exit, &ihcNotUndefined);
10056 Bind(&ihcNotUndefined);
10057 {
10058 CallRuntime(glue, RTSTUB_ID(AOTEnableProtoChangeMarker), {*result, *ihc, *val});
10059 Jump(&exit);
10060 }
10061 Bind(&exit);
10062 auto ret = *result;
10063 env->SubCfgExit();
10064 return ret;
10065 }
10066
SetCompiledCodeFlagToFunctionFromMethod(GateRef glue,GateRef function,GateRef method)10067 void StubBuilder::SetCompiledCodeFlagToFunctionFromMethod(GateRef glue, GateRef function, GateRef method)
10068 {
10069 // set compiled code & fast call flag
10070 GateRef isFastCall = IsFastCall(method);
10071 GateRef compiledCodeField = Int32LSL(Int32(1U), Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT));
10072 GateRef compiledCodeFlag = Int32Or(compiledCodeField, Int32LSL(ZExtInt1ToInt32(isFastCall),
10073 Int32(JSFunctionBase::IsFastCallBit::START_BIT)));
10074 SetCompiledCodeFlagToFunction(glue, function, compiledCodeFlag);
10075 }
10076
UpdateProfileTypeInfoCellToFunction(GateRef glue,GateRef function,GateRef profileTypeInfo,GateRef slotId)10077 void StubBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
10078 GateRef profileTypeInfo, GateRef slotId)
10079 {
10080 Label subEntry(env_);
10081 env_->SubCfgEntry(&subEntry);
10082
10083 Label profileTypeInfoNotUndefined(env_);
10084 Label slotValueUpdate(env_);
10085 Label slotValueNotUndefined(env_);
10086 Label profileTypeInfoEnd(env_);
10087 NewObjectStubBuilder newBuilder(env_);
10088 BRANCH(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined);
10089 Bind(&profileTypeInfoNotUndefined);
10090 {
10091 GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
10092 BRANCH(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
10093 Bind(&slotValueUpdate);
10094 {
10095 GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined());
10096 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
10097 SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell);
10098 Jump(&profileTypeInfoEnd);
10099 }
10100 Bind(&slotValueNotUndefined);
10101 UpdateProfileTypeInfoCellType(glue, slotValue);
10102 SetRawProfileTypeInfoToFunction(glue, function, slotValue);
10103 Jump(&profileTypeInfoEnd);
10104 }
10105 Bind(&profileTypeInfoEnd);
10106
10107 env_->SubCfgExit();
10108 }
10109
Loadlocalmodulevar(GateRef glue,GateRef index,GateRef module)10110 GateRef StubBuilder::Loadlocalmodulevar(GateRef glue, GateRef index, GateRef module)
10111 {
10112 auto env = GetEnvironment();
10113 Label subentry(env);
10114 env->SubCfgEntry(&subentry);
10115 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
10116 Label notSendableFunctionModule(env);
10117 Label sendableFunctionModule(env);
10118 Label exit(env);
10119 BRANCH_UNLIKELY(IsSendableFunctionModule(module), &sendableFunctionModule, ¬SendableFunctionModule);
10120 Bind(&sendableFunctionModule);
10121 {
10122 result = CallRuntime(glue, RTSTUB_ID(LdLocalModuleVarByIndexWithModule),
10123 {Int8ToTaggedInt(index), module});
10124 Jump(&exit);
10125 }
10126 Bind(¬SendableFunctionModule);
10127 {
10128 GateRef nameDictionaryOffset = IntPtr(SourceTextModule::NAME_DICTIONARY_OFFSET);
10129 GateRef dictionary = Load(VariableType::JS_ANY(), module, nameDictionaryOffset);
10130 Label dataIsNotUndefined(env);
10131 BRANCH_UNLIKELY(TaggedIsUndefined(dictionary), &exit, &dataIsNotUndefined);
10132 Bind(&dataIsNotUndefined);
10133 {
10134 GateRef dataOffset = Int32(TaggedArray::DATA_OFFSET);
10135 GateRef indexOffset = Int32Mul(ZExtInt8ToInt32(index), Int32(JSTaggedValue::TaggedTypeSize()));
10136 GateRef offset = Int32Add(indexOffset, dataOffset);
10137 result = Load(VariableType::JS_ANY(), dictionary, offset);
10138 Jump(&exit);
10139 }
10140 }
10141 Bind(&exit);
10142 auto ret = *result;
10143 env->SubCfgExit();
10144 return ret;
10145 }
10146
GetArgumentsElements(GateRef glue,GateRef argvTaggedArray,GateRef argv)10147 GateRef StubBuilder::GetArgumentsElements(GateRef glue, GateRef argvTaggedArray, GateRef argv)
10148 {
10149 auto env = GetEnvironment();
10150 Label entry(env);
10151 env->SubCfgEntry(&entry);
10152 Label exit(env);
10153 DEFVARIABLE(result, VariableType::NATIVE_POINTER(), NullPtr());
10154 DEFVARIABLE(argvVar, VariableType::NATIVE_POINTER(), argv);
10155
10156 Label calcArgv(env);
10157 Label hasArgv(env);
10158 Label argvTaggedArrayUndef(env);
10159 Label argvTaggedArrayDef(env);
10160
10161 BRANCH(TaggedIsUndefined(argvTaggedArray), &argvTaggedArrayUndef, &argvTaggedArrayDef);
10162 Bind(&argvTaggedArrayUndef);
10163
10164 BRANCH(Equal(*argvVar, IntPtr(0)), &calcArgv, &hasArgv);
10165 Bind(&calcArgv);
10166 argvVar = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
10167 Jump(&hasArgv);
10168
10169 Bind(&argvTaggedArrayDef);
10170 argvVar = PtrAdd(TaggedCastToIntPtr(argvTaggedArray), IntPtr(TaggedArray::DATA_OFFSET));
10171 Jump(&hasArgv);
10172
10173 Bind(&hasArgv);
10174 result = PtrAdd(*argvVar, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
10175 Jump(&exit);
10176 Bind(&exit);
10177 auto ret = *result;
10178 env->SubCfgExit();
10179 return ret;
10180 }
10181
10182 } // namespace panda::ecmascript::kungfu
10183