1 /*
2 * Copyright (c) 2021 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/stub_builder-inl.h"
17
18 #include "ecmascript/compiler/assembler_module.h"
19 #include "ecmascript/compiler/llvm_ir_builder.h"
20 #include "ecmascript/compiler/rt_call_signature.h"
21 #include "ecmascript/js_api/js_api_arraylist.h"
22 #include "ecmascript/js_api/js_api_vector.h"
23 #include "ecmascript/js_object.h"
24 #include "ecmascript/mem/remembered_set.h"
25 #include "ecmascript/message_string.h"
26 #include "ecmascript/tagged_dictionary.h"
27 #include "ecmascript/tagged_hash_table.h"
28
29 namespace panda::ecmascript::kungfu {
Jump(Label * label)30 void StubBuilder::Jump(Label *label)
31 {
32 ASSERT(label);
33 auto currentLabel = env_->GetCurrentLabel();
34 auto currentControl = currentLabel->GetControl();
35 auto jump = env_->GetBuilder()->Goto(currentControl);
36 currentLabel->SetControl(jump);
37 label->AppendPredecessor(currentLabel);
38 label->MergeControl(currentLabel->GetControl());
39 env_->SetCurrentLabel(nullptr);
40 }
41
Branch(GateRef condition,Label * trueLabel,Label * falseLabel)42 void StubBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel)
43 {
44 auto currentLabel = env_->GetCurrentLabel();
45 auto currentControl = currentLabel->GetControl();
46 GateRef ifBranch = env_->GetBuilder()->Branch(currentControl, condition);
47 currentLabel->SetControl(ifBranch);
48 GateRef ifTrue = env_->GetBuilder()->IfTrue(ifBranch);
49 trueLabel->AppendPredecessor(env_->GetCurrentLabel());
50 trueLabel->MergeControl(ifTrue);
51 GateRef ifFalse = env_->GetBuilder()->IfFalse(ifBranch);
52 falseLabel->AppendPredecessor(env_->GetCurrentLabel());
53 falseLabel->MergeControl(ifFalse);
54 env_->SetCurrentLabel(nullptr);
55 }
56
Switch(GateRef index,Label * defaultLabel,int64_t * keysValue,Label * keysLabel,int numberOfKeys)57 void StubBuilder::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
58 {
59 auto currentLabel = env_->GetCurrentLabel();
60 auto currentControl = currentLabel->GetControl();
61 GateRef switchBranch = env_->GetBuilder()->SwitchBranch(currentControl, index, numberOfKeys);
62 currentLabel->SetControl(switchBranch);
63 for (int i = 0; i < numberOfKeys; i++) {
64 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
65 GateRef switchCase = env_->GetBuilder()->SwitchCase(switchBranch, keysValue[i]);
66 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
67 keysLabel[i].AppendPredecessor(currentLabel);
68 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
69 keysLabel[i].MergeControl(switchCase);
70 }
71
72 GateRef defaultCase = env_->GetBuilder()->DefaultCase(switchBranch);
73 defaultLabel->AppendPredecessor(currentLabel);
74 defaultLabel->MergeControl(defaultCase);
75 env_->SetCurrentLabel(nullptr);
76 }
77
LoopBegin(Label * loopHead)78 void StubBuilder::LoopBegin(Label *loopHead)
79 {
80 ASSERT(loopHead);
81 auto loopControl = env_->GetBuilder()->LoopBegin(loopHead->GetControl());
82 loopHead->SetControl(loopControl);
83 loopHead->SetPreControl(loopControl);
84 loopHead->Bind();
85 env_->SetCurrentLabel(loopHead);
86 }
87
LoopEnd(Label * loopHead)88 void StubBuilder::LoopEnd(Label *loopHead)
89 {
90 ASSERT(loopHead);
91 auto currentLabel = env_->GetCurrentLabel();
92 auto currentControl = currentLabel->GetControl();
93 auto loopend = env_->GetBuilder()->LoopEnd(currentControl);
94 currentLabel->SetControl(loopend);
95 loopHead->AppendPredecessor(currentLabel);
96 loopHead->MergeControl(loopend);
97 loopHead->Seal();
98 loopHead->MergeAllControl();
99 loopHead->MergeAllDepend();
100 env_->SetCurrentLabel(nullptr);
101 }
102
103 // FindElementWithCache in ecmascript/layout_info-inl.h
FindElementWithCache(GateRef glue,GateRef layoutInfo,GateRef hclass,GateRef key,GateRef propsNum)104 GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, GateRef hclass,
105 GateRef key, GateRef propsNum)
106 {
107 auto env = GetEnvironment();
108 Label subEntry(env);
109 env->SubCfgEntry(&subEntry);
110 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
111 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
112 Label exit(env);
113 Label notExceedUpper(env);
114 Label exceedUpper(env);
115 Label afterExceedCon(env);
116 // 9 : Builtins Object properties number is nine
117 Branch(Int32LessThanOrEqual(propsNum, Int32(9)), ¬ExceedUpper, &exceedUpper);
118 {
119 Bind(¬ExceedUpper);
120 Label loopHead(env);
121 Label loopEnd(env);
122 Label afterLoop(env);
123 Jump(&loopHead);
124 LoopBegin(&loopHead);
125 {
126 Label propsNumIsZero(env);
127 Label propsNumNotZero(env);
128 Branch(Int32Equal(propsNum, Int32(0)), &propsNumIsZero, &propsNumNotZero);
129 Bind(&propsNumIsZero);
130 Jump(&afterLoop);
131 Bind(&propsNumNotZero);
132 GateRef elementAddr = GetPropertiesAddrFromLayoutInfo(layoutInfo);
133 GateRef keyInProperty = Load(VariableType::JS_ANY(),
134 elementAddr,
135 PtrMul(ZExtInt32ToPtr(*i),
136 IntPtr(sizeof(panda::ecmascript::Properties))));
137 Label equal(env);
138 Label notEqual(env);
139 Label afterEqualCon(env);
140 Branch(Equal(keyInProperty, key), &equal, ¬Equal);
141 Bind(&equal);
142 result = *i;
143 Jump(&exit);
144 Bind(¬Equal);
145 Jump(&afterEqualCon);
146 Bind(&afterEqualCon);
147 i = Int32Add(*i, Int32(1));
148 Branch(Int32UnsignedLessThan(*i, propsNum), &loopEnd, &afterLoop);
149 Bind(&loopEnd);
150 LoopEnd(&loopHead);
151 }
152 Bind(&afterLoop);
153 result = Int32(-1);
154 Jump(&exit);
155 Bind(&exceedUpper);
156 Jump(&afterExceedCon);
157 }
158 Bind(&afterExceedCon);
159 result = CallNGCRuntime(glue, RTSTUB_ID(FindElementWithCache), { glue, hclass, key, propsNum });
160 Jump(&exit);
161 Bind(&exit);
162 auto ret = *result;
163 env->SubCfgExit();
164 return ret;
165 }
166
FindElementFromNumberDictionary(GateRef glue,GateRef elements,GateRef index)167 GateRef StubBuilder::FindElementFromNumberDictionary(GateRef glue, GateRef elements, GateRef index)
168 {
169 auto env = GetEnvironment();
170 Label subentry(env);
171 env->SubCfgEntry(&subentry);
172 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
173 Label exit(env);
174 GateRef capcityoffset =
175 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
176 IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
177 GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
178 GateRef capacity = GetInt32OfTInt(Load(VariableType::INT64(), elements,
179 PtrAdd(dataoffset, capcityoffset)));
180 DEFVARIABLE(count, VariableType::INT32(), Int32(1));
181 GateRef len = Int32(sizeof(int) / sizeof(uint8_t));
182 GateRef hash = CallRuntime(glue, RTSTUB_ID(GetHash32),
183 { IntToTaggedInt(index), IntToTaggedInt(len) });
184 DEFVARIABLE(entry, VariableType::INT32(),
185 Int32And(TruncInt64ToInt32(ChangeTaggedPointerToInt64(hash)), Int32Sub(capacity, Int32(1))));
186 Label loopHead(env);
187 Label loopEnd(env);
188 Label afterLoop(env);
189 Jump(&loopHead);
190 LoopBegin(&loopHead);
191 GateRef element = GetKeyFromDictionary<NumberDictionary>(elements, *entry);
192 Label isHole(env);
193 Label notHole(env);
194 Branch(TaggedIsHole(element), &isHole, ¬Hole);
195 Bind(&isHole);
196 Jump(&loopEnd);
197 Bind(¬Hole);
198 Label isUndefined(env);
199 Label notUndefined(env);
200 Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
201 Bind(&isUndefined);
202 result = Int32(-1);
203 Jump(&exit);
204 Bind(¬Undefined);
205 Label isMatch(env);
206 Label notMatch(env);
207 Branch(Int32Equal(index, GetInt32OfTInt(element)), &isMatch, ¬Match);
208 Bind(&isMatch);
209 result = *entry;
210 Jump(&exit);
211 Bind(¬Match);
212 Jump(&loopEnd);
213 Bind(&loopEnd);
214 entry = GetNextPositionForHash(*entry, *count, capacity);
215 count = Int32Add(*count, Int32(1));
216 LoopEnd(&loopHead);
217 Bind(&exit);
218 auto ret = *result;
219 env->SubCfgExit();
220 return ret;
221 }
222
223 // int TaggedHashTable<Derived>::FindEntry(const JSTaggedValue &key) in tagged_hash_table.h
FindEntryFromNameDictionary(GateRef glue,GateRef elements,GateRef key)224 GateRef StubBuilder::FindEntryFromNameDictionary(GateRef glue, GateRef elements, GateRef key)
225 {
226 auto env = GetEnvironment();
227 Label funcEntry(env);
228 env->SubCfgEntry(&funcEntry);
229 Label exit(env);
230 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
231 GateRef capcityoffset =
232 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
233 IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
234 GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
235 GateRef capacity = GetInt32OfTInt(Load(VariableType::INT64(), elements,
236 PtrAdd(dataoffset, capcityoffset)));
237 DEFVARIABLE(count, VariableType::INT32(), Int32(1));
238 DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
239 // NameDictionary::hash
240 Label isSymbol(env);
241 Label notSymbol(env);
242 Label loopHead(env);
243 Label loopEnd(env);
244 Label afterLoop(env);
245 Label beforeDefineHash(env);
246 Branch(IsSymbol(key), &isSymbol, ¬Symbol);
247 Bind(&isSymbol);
248 {
249 hash = GetInt32OfTInt(Load(VariableType::INT64(), key,
250 IntPtr(JSSymbol::HASHFIELD_OFFSET)));
251 Jump(&beforeDefineHash);
252 }
253 Bind(¬Symbol);
254 {
255 Label isString(env);
256 Label notString(env);
257 Branch(IsString(key), &isString, ¬String);
258 Bind(&isString);
259 {
260 hash = GetHashcodeFromString(glue, key);
261 Jump(&beforeDefineHash);
262 }
263 Bind(¬String);
264 {
265 Jump(&beforeDefineHash);
266 }
267 }
268 Bind(&beforeDefineHash);
269 // GetFirstPosition(hash, size)
270 DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
271 Jump(&loopHead);
272 LoopBegin(&loopHead);
273 {
274 GateRef element = GetKeyFromDictionary<NameDictionary>(elements, *entry);
275 Label isHole(env);
276 Label notHole(env);
277 Branch(TaggedIsHole(element), &isHole, ¬Hole);
278 {
279 Bind(&isHole);
280 {
281 Jump(&loopEnd);
282 }
283 Bind(¬Hole);
284 {
285 Label isUndefined(env);
286 Label notUndefined(env);
287 Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
288 {
289 Bind(&isUndefined);
290 {
291 result = Int32(-1);
292 Jump(&exit);
293 }
294 Bind(¬Undefined);
295 {
296 Label isMatch(env);
297 Label notMatch(env);
298 Branch(Equal(key, element), &isMatch, ¬Match);
299 {
300 Bind(&isMatch);
301 {
302 result = *entry;
303 Jump(&exit);
304 }
305 Bind(¬Match);
306 {
307 Jump(&loopEnd);
308 }
309 }
310 }
311 }
312 }
313 }
314 Bind(&loopEnd);
315 {
316 entry = GetNextPositionForHash(*entry, *count, capacity);
317 count = Int32Add(*count, Int32(1));
318 LoopEnd(&loopHead);
319 }
320 }
321 Bind(&exit);
322 auto ret = *result;
323 env->SubCfgExit();
324 return ret;
325 }
326
IsMatchInTransitionDictionary(GateRef element,GateRef key,GateRef metaData,GateRef attr)327 GateRef StubBuilder::IsMatchInTransitionDictionary(GateRef element, GateRef key, GateRef metaData, GateRef attr)
328 {
329 return BoolAnd(Equal(element, key), Int32Equal(metaData, attr));
330 }
331
332 // metaData is int32 type
FindEntryFromTransitionDictionary(GateRef glue,GateRef elements,GateRef key,GateRef metaData)333 GateRef StubBuilder::FindEntryFromTransitionDictionary(GateRef glue, GateRef elements, GateRef key, GateRef metaData)
334 {
335 auto env = GetEnvironment();
336 Label funcEntry(env);
337 env->SubCfgEntry(&funcEntry);
338 Label exit(env);
339 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
340 GateRef capcityoffset =
341 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
342 IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
343 GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
344 GateRef capacity = GetInt32OfTInt(Load(VariableType::INT64(), elements,
345 PtrAdd(dataoffset, capcityoffset)));
346 DEFVARIABLE(count, VariableType::INT32(), Int32(1));
347 DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
348 // TransitionDictionary::hash
349 Label isSymbol(env);
350 Label notSymbol(env);
351 Label loopHead(env);
352 Label loopEnd(env);
353 Label afterLoop(env);
354 Label beforeDefineHash(env);
355 Branch(IsSymbol(key), &isSymbol, ¬Symbol);
356 Bind(&isSymbol);
357 {
358 hash = GetInt32OfTInt(Load(VariableType::INT64(), key,
359 IntPtr(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET)));
360 Jump(&beforeDefineHash);
361 }
362 Bind(¬Symbol);
363 {
364 Label isString(env);
365 Label notString(env);
366 Branch(IsString(key), &isString, ¬String);
367 Bind(&isString);
368 {
369 hash = GetHashcodeFromString(glue, key);
370 Jump(&beforeDefineHash);
371 }
372 Bind(¬String);
373 {
374 Jump(&beforeDefineHash);
375 }
376 }
377 Bind(&beforeDefineHash);
378 hash = Int32Add(*hash, metaData);
379 // GetFirstPosition(hash, size)
380 DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
381 Jump(&loopHead);
382 LoopBegin(&loopHead);
383 {
384 GateRef element = GetKeyFromDictionary<TransitionsDictionary>(elements, *entry);
385 Label isHole(env);
386 Label notHole(env);
387 Branch(TaggedIsHole(element), &isHole, ¬Hole);
388 {
389 Bind(&isHole);
390 {
391 Jump(&loopEnd);
392 }
393 Bind(¬Hole);
394 {
395 Label isUndefined(env);
396 Label notUndefined(env);
397 Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
398 {
399 Bind(&isUndefined);
400 {
401 result = Int32(-1);
402 Jump(&exit);
403 }
404 Bind(¬Undefined);
405 {
406 Label isMatch(env);
407 Label notMatch(env);
408 Branch(
409 IsMatchInTransitionDictionary(element, key, metaData,
410 GetAttributesFromDictionary<TransitionsDictionary>(elements, *entry)),
411 &isMatch, ¬Match);
412 {
413 Bind(&isMatch);
414 {
415 result = *entry;
416 Jump(&exit);
417 }
418 Bind(¬Match);
419 {
420 Jump(&loopEnd);
421 }
422 }
423 }
424 }
425 }
426 }
427 Bind(&loopEnd);
428 {
429 entry = GetNextPositionForHash(*entry, *count, capacity);
430 count = Int32Add(*count, Int32(1));
431 LoopEnd(&loopHead);
432 }
433 }
434 Bind(&exit);
435 auto ret = *result;
436 env->SubCfgExit();
437 return ret;
438 }
439
JSObjectGetProperty(GateRef obj,GateRef hclass,GateRef attr)440 GateRef StubBuilder::JSObjectGetProperty(GateRef obj, GateRef hclass, GateRef attr)
441 {
442 auto env = GetEnvironment();
443 Label entry(env);
444 env->SubCfgEntry(&entry);
445 Label exit(env);
446 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
447 Label inlinedProp(env);
448 Label notInlinedProp(env);
449 GateRef attrOffset = GetOffsetFieldInPropAttr(attr);
450 Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp);
451 {
452 Bind(&inlinedProp);
453 {
454 result = GetPropertyInlinedProps(obj, hclass, attrOffset);
455 Jump(&exit);
456 }
457 Bind(¬InlinedProp);
458 {
459 // compute outOfLineProp offset, get it and return
460 GateRef array =
461 Load(VariableType::INT64(), obj, IntPtr(JSObject::PROPERTIES_OFFSET));
462 result = GetValueFromTaggedArray(array, Int32Sub(attrOffset,
463 GetInlinedPropertiesFromHClass(hclass)));
464 Jump(&exit);
465 }
466 }
467 Bind(&exit);
468 auto ret = *result;
469 env->SubCfgExit();
470 return ret;
471 }
472
JSObjectSetProperty(GateRef glue,GateRef obj,GateRef hclass,GateRef attr,GateRef value)473 void StubBuilder::JSObjectSetProperty(GateRef glue, GateRef obj, GateRef hclass, GateRef attr, GateRef value)
474 {
475 auto env = GetEnvironment();
476 Label subEntry(env);
477 env->SubCfgEntry(&subEntry);
478 Label exit(env);
479 Label inlinedProp(env);
480 Label notInlinedProp(env);
481 GateRef attrOffset = GetOffsetFieldInPropAttr(attr);
482 Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp);
483 {
484 Bind(&inlinedProp);
485 {
486 SetPropertyInlinedProps(glue, obj, hclass, value, attrOffset);
487 Jump(&exit);
488 }
489 Bind(¬InlinedProp);
490 {
491 // compute outOfLineProp offset, get it and return
492 GateRef array = Load(VariableType::JS_POINTER(), obj,
493 IntPtr(JSObject::PROPERTIES_OFFSET));
494 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, Int32Sub(attrOffset,
495 GetInlinedPropertiesFromHClass(hclass)), value);
496 Jump(&exit);
497 }
498 }
499 Bind(&exit);
500 env->SubCfgExit();
501 return;
502 }
503
ComputePropertyCapacityInJSObj(GateRef oldLength)504 GateRef StubBuilder::ComputePropertyCapacityInJSObj(GateRef oldLength)
505 {
506 auto env = GetEnvironment();
507 Label subEntry(env);
508 env->SubCfgEntry(&subEntry);
509 Label exit(env);
510 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
511 GateRef newL = Int32Add(oldLength, Int32(JSObject::PROPERTIES_GROW_SIZE));
512 Label reachMax(env);
513 Label notReachMax(env);
514 Branch(Int32GreaterThan(newL, Int32(JSHClass::MAX_CAPACITY_OF_OUT_OBJECTS)),
515 &reachMax, ¬ReachMax);
516 {
517 Bind(&reachMax);
518 result = Int32(JSHClass::MAX_CAPACITY_OF_OUT_OBJECTS);
519 Jump(&exit);
520 Bind(¬ReachMax);
521 result = newL;
522 Jump(&exit);
523 }
524 Bind(&exit);
525 auto ret = *result;
526 env->SubCfgExit();
527 return ret;
528 }
529
CallGetterHelper(GateRef glue,GateRef receiver,GateRef holder,GateRef accessor)530 GateRef StubBuilder::CallGetterHelper(GateRef glue, GateRef receiver, GateRef holder, GateRef accessor)
531 {
532 auto env = GetEnvironment();
533 Label subEntry(env);
534 env->SubCfgEntry(&subEntry);
535 Label exit(env);
536 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
537
538 Label isInternal(env);
539 Label notInternal(env);
540 Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal);
541 Bind(&isInternal);
542 {
543 Label arrayLength(env);
544 Label tryContinue(env);
545 auto lengthAccessor = GetGlobalConstantValue(
546 VariableType::JS_POINTER(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
547 Branch(Equal(accessor, lengthAccessor), &arrayLength, &tryContinue);
548 Bind(&arrayLength);
549 {
550 result = Load(VariableType::JS_ANY(), holder,
551 IntPtr(JSArray::LENGTH_OFFSET));
552 Jump(&exit);
553 }
554 Bind(&tryContinue);
555 result = CallRuntime(glue, RTSTUB_ID(CallInternalGetter), { accessor, holder });
556 Jump(&exit);
557 }
558 Bind(¬Internal);
559 {
560 auto getter = Load(VariableType::JS_ANY(), accessor,
561 IntPtr(AccessorData::GETTER_OFFSET));
562 Label objIsUndefined(env);
563 Label objNotUndefined(env);
564 Branch(TaggedIsUndefined(getter), &objIsUndefined, &objNotUndefined);
565 // if getter is undefined, return undefiend
566 Bind(&objIsUndefined);
567 {
568 result = Undefined();
569 Jump(&exit);
570 }
571 Bind(&objNotUndefined);
572 {
573 auto retValue = JSCallDispatch(glue, getter, Int32(0), 0, Circuit::NullGate(),
574 JSCallMode::CALL_GETTER, { receiver });
575 Label noPendingException(env);
576 Branch(HasPendingException(glue), &exit, &noPendingException);
577 Bind(&noPendingException);
578 {
579 result = retValue;
580 Jump(&exit);
581 }
582 }
583 }
584 Bind(&exit);
585 auto ret = *result;
586 env->SubCfgExit();
587 return ret;
588 }
589
CallSetterHelper(GateRef glue,GateRef receiver,GateRef accessor,GateRef value)590 GateRef StubBuilder::CallSetterHelper(GateRef glue, GateRef receiver, GateRef accessor, GateRef value)
591 {
592 auto env = GetEnvironment();
593 Label subEntry(env);
594 env->SubCfgEntry(&subEntry);
595 Label exit(env);
596 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
597
598 Label isInternal(env);
599 Label notInternal(env);
600 Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal);
601 Bind(&isInternal);
602 {
603 result = CallRuntime(glue, RTSTUB_ID(CallInternalSetter), { receiver, accessor, value });
604 Jump(&exit);
605 }
606 Bind(¬Internal);
607 {
608 auto setter = Load(VariableType::JS_ANY(), accessor,
609 IntPtr(AccessorData::SETTER_OFFSET));
610 Label objIsUndefined(env);
611 Label objNotUndefined(env);
612 Branch(TaggedIsUndefined(setter), &objIsUndefined, &objNotUndefined);
613 Bind(&objIsUndefined);
614 {
615 CallRuntime(glue, RTSTUB_ID(ThrowSetterIsUndefinedException), {});
616 result = Exception();
617 Jump(&exit);
618 }
619 Bind(&objNotUndefined);
620 {
621 auto retValue = JSCallDispatch(glue, setter, Int32(1), 0, Circuit::NullGate(),
622 JSCallMode::CALL_SETTER, { receiver, value });
623 Label noPendingException(env);
624 Branch(HasPendingException(glue), &exit, &noPendingException);
625 Bind(&noPendingException);
626 {
627 result = retValue;
628 Jump(&exit);
629 }
630 }
631 }
632 Bind(&exit);
633 auto ret = *result;
634 env->SubCfgExit();
635 return ret;
636 }
637
ShouldCallSetter(GateRef receiver,GateRef holder,GateRef accessor,GateRef attr)638 GateRef StubBuilder::ShouldCallSetter(GateRef receiver, GateRef holder, GateRef accessor, GateRef attr)
639 {
640 auto env = GetEnvironment();
641 Label subEntry(env);
642 env->SubCfgEntry(&subEntry);
643 Label exit(env);
644 DEFVARIABLE(result, VariableType::BOOL(), True());
645 Label isInternal(env);
646 Label notInternal(env);
647 Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal);
648 Bind(&isInternal);
649 {
650 Label receiverEqualsHolder(env);
651 Label receiverNotEqualsHolder(env);
652 Branch(Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder);
653 Bind(&receiverEqualsHolder);
654 {
655 result = IsWritable(attr);
656 Jump(&exit);
657 }
658 Bind(&receiverNotEqualsHolder);
659 {
660 result = False();
661 Jump(&exit);
662 }
663 }
664 Bind(¬Internal);
665 {
666 result = True();
667 Jump(&exit);
668 }
669 Bind(&exit);
670 auto ret = *result;
671 env->SubCfgExit();
672 return ret;
673 }
674
JSHClassAddProperty(GateRef glue,GateRef receiver,GateRef key,GateRef attr)675 void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef key, GateRef attr)
676 {
677 auto env = GetEnvironment();
678 Label subEntry(env);
679 env->SubCfgEntry(&subEntry);
680 Label exit(env);
681 GateRef hclass = LoadHClass(receiver);
682 GateRef metaData = GetPropertyMetaDataFromAttr(attr);
683 GateRef newClass = FindTransitions(glue, receiver, hclass, key, metaData);
684 Label findHClass(env);
685 Label notFindHClass(env);
686 Branch(Equal(newClass, Undefined()), ¬FindHClass, &findHClass);
687 Bind(&findHClass);
688 {
689 Jump(&exit);
690 }
691 Bind(¬FindHClass);
692 {
693 GateRef type = GetObjectType(hclass);
694 GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
695 Int32(JSTaggedValue::TaggedTypeSize()));
696 GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
697 GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaHClass),
698 { IntToTaggedInt(size), IntToTaggedInt(type),
699 IntToTaggedInt(inlineProps) });
700 CopyAllHClass(glue, newJshclass, hclass);
701 CallRuntime(glue, RTSTUB_ID(UpdateLayOutAndAddTransition),
702 { hclass, newJshclass, key, IntToTaggedInt(attr) });
703 #if ECMASCRIPT_ENABLE_IC
704 NotifyHClassChanged(glue, hclass, newJshclass);
705 #endif
706 StoreHClass(glue, receiver, newJshclass);
707 Jump(&exit);
708 }
709 Bind(&exit);
710 env->SubCfgExit();
711 return;
712 }
713
714 // if condition:objHandle->IsJSArray() &&
715 // keyHandle.GetTaggedValue() == thread->GlobalConstants()->GetConstructorString()
SetHasConstructorCondition(GateRef glue,GateRef receiver,GateRef key)716 GateRef StubBuilder::SetHasConstructorCondition(GateRef glue, GateRef receiver, GateRef key)
717 {
718 GateRef gConstOffset = PtrAdd(glue,
719 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
720 GateRef gCtorStr = Load(VariableType::JS_ANY(),
721 gConstOffset,
722 Int64Mul(Int64(sizeof(JSTaggedValue)),
723 Int64(static_cast<uint64_t>(ConstantIndex::CONSTRUCTOR_STRING_INDEX))));
724 GateRef isCtorStr = Equal(key, gCtorStr);
725 return BoolAnd(IsJsArray(receiver), isCtorStr);
726 }
727
728 // Note: set return exit node
AddPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef propertyAttributes)729 GateRef StubBuilder::AddPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
730 GateRef propertyAttributes)
731 {
732 auto env = GetEnvironment();
733 Label subentry(env);
734 env->SubCfgEntry(&subentry);
735 Label exit(env);
736 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
737 Label setHasCtor(env);
738 Label notSetHasCtor(env);
739 Label afterCtorCon(env);
740 GateRef hclass = LoadHClass(receiver);
741 Branch(SetHasConstructorCondition(glue, receiver, key), &setHasCtor, ¬SetHasCtor);
742 {
743 Bind(&setHasCtor);
744 SetHasConstructorToHClass(glue, hclass, Int32(1));
745 Jump(&afterCtorCon);
746 Bind(¬SetHasCtor);
747 Jump(&afterCtorCon);
748 }
749 Bind(&afterCtorCon);
750 // 0x111 : default attribute for property: writable, enumerable, configurable
751 DEFVARIABLE(attr, VariableType::INT32(), propertyAttributes);
752 GateRef numberOfProps = GetNumberOfPropsFromHClass(hclass);
753 GateRef inlinedProperties = GetInlinedPropertiesFromHClass(hclass);
754 Label hasUnusedInProps(env);
755 Label noUnusedInProps(env);
756 Label afterInPropsCon(env);
757 Branch(Int32UnsignedLessThan(numberOfProps, inlinedProperties), &hasUnusedInProps, &noUnusedInProps);
758 {
759 Bind(&noUnusedInProps);
760 Jump(&afterInPropsCon);
761 Bind(&hasUnusedInProps);
762 {
763 SetPropertyInlinedProps(glue, receiver, hclass, value, numberOfProps);
764 attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
765 attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(1)); // 1: set inInlineProps true
766 JSHClassAddProperty(glue, receiver, key, *attr);
767 result = Undefined();
768 Jump(&exit);
769 }
770 }
771 Bind(&afterInPropsCon);
772 DEFVARIABLE(array, VariableType::JS_POINTER(), GetPropertiesArray(receiver));
773 DEFVARIABLE(length, VariableType::INT32(), GetLengthOfTaggedArray(*array));
774 Label lenIsZero(env);
775 Label lenNotZero(env);
776 Label afterLenCon(env);
777 Branch(Int32Equal(*length, Int32(0)), &lenIsZero, &lenNotZero);
778 {
779 Bind(&lenIsZero);
780 {
781 length = Int32(JSObject::MIN_PROPERTIES_LENGTH);
782 array = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(*length) });
783 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
784 Jump(&afterLenCon);
785 }
786 Bind(&lenNotZero);
787 Jump(&afterLenCon);
788 }
789 Bind(&afterLenCon);
790 Label isDictMode(env);
791 Label notDictMode(env);
792 Branch(IsDictionaryMode(*array), &isDictMode, ¬DictMode);
793 {
794 Bind(&isDictMode);
795 {
796 GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
797 {receiver, *array, key, value, IntToTaggedInt(*attr), TaggedFalse()});
798 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
799 Jump(&exit);
800 }
801 Bind(¬DictMode);
802 {
803 attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(0));
804 GateRef outProps = Int32Sub(numberOfProps, inlinedProperties);
805 Label isArrayFull(env);
806 Label arrayNotFull(env);
807 Label afterArrLenCon(env);
808 Branch(Int32Equal(*length, outProps), &isArrayFull, &arrayNotFull);
809 {
810 Bind(&isArrayFull);
811 {
812 Label ChangeToDict(env);
813 Label notChangeToDict(env);
814 Label afterDictChangeCon(env);
815 Branch(Int32Equal(*length, Int32(JSHClass::MAX_CAPACITY_OF_OUT_OBJECTS)),
816 &ChangeToDict, ¬ChangeToDict);
817 {
818 Bind(&ChangeToDict);
819 {
820 attr = SetDictionaryOrderFieldInPropAttr(*attr,
821 Int32(PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES));
822 GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
823 { receiver, *array, key, value, IntToTaggedInt(*attr), TaggedTrue() });
824 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
825 result = Undefined();
826 Jump(&exit);
827 }
828 Bind(¬ChangeToDict);
829 Jump(&afterDictChangeCon);
830 }
831 Bind(&afterDictChangeCon);
832 GateRef capacity = ComputePropertyCapacityInJSObj(*length);
833 array = CallRuntime(glue, RTSTUB_ID(CopyArray),
834 { *array, IntToTaggedInt(*length), IntToTaggedInt(capacity) });
835 SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
836 Jump(&afterArrLenCon);
837 }
838 Bind(&arrayNotFull);
839 Jump(&afterArrLenCon);
840 }
841 Bind(&afterArrLenCon);
842 {
843 attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
844 JSHClassAddProperty(glue, receiver, key, *attr);
845 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, outProps, value);
846 Jump(&exit);
847 }
848 }
849 }
850 Bind(&exit);
851 auto ret = *result;
852 env->SubCfgExit();
853 return ret;
854 }
855
ThrowTypeAndReturn(GateRef glue,int messageId,GateRef val)856 void StubBuilder::ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val)
857 {
858 GateRef msgIntId = Int32(messageId);
859 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId) });
860 Return(val);
861 }
862
TaggedToRepresentation(GateRef value)863 GateRef StubBuilder::TaggedToRepresentation(GateRef value)
864 {
865 auto env = GetEnvironment();
866 Label entry(env);
867 env->SubCfgEntry(&entry);
868 Label exit(env);
869 DEFVARIABLE(resultRep, VariableType::INT64(),
870 Int64(static_cast<int32_t>(Representation::OBJECT)));
871 Label isInt(env);
872 Label notInt(env);
873
874 Branch(TaggedIsInt(value), &isInt, ¬Int);
875 Bind(&isInt);
876 {
877 resultRep = Int64(static_cast<int32_t>(Representation::INT));
878 Jump(&exit);
879 }
880 Bind(¬Int);
881 {
882 Label isDouble(env);
883 Label notDouble(env);
884 Branch(TaggedIsDouble(value), &isDouble, ¬Double);
885 Bind(&isDouble);
886 {
887 resultRep = Int64(static_cast<int32_t>(Representation::DOUBLE));
888 Jump(&exit);
889 }
890 Bind(¬Double);
891 {
892 resultRep = Int64(static_cast<int32_t>(Representation::OBJECT));
893 Jump(&exit);
894 }
895 }
896 Bind(&exit);
897 auto ret = *resultRep;
898 env->SubCfgExit();
899 return ret;
900 }
901
Store(VariableType type,GateRef glue,GateRef base,GateRef offset,GateRef value)902 void StubBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value)
903 {
904 if (!env_->IsAsmInterp()) {
905 env_->GetBuilder()->Store(type, glue, base, offset, value);
906 } else {
907 auto depend = env_->GetCurrentLabel()->GetDepend();
908 GateRef ptr = PtrAdd(base, offset);
909 GateRef result = env_->GetCircuit()->NewGate(
910 env_->GetCircuit()->Store(), MachineType::NOVALUE,
911 { depend, value, ptr }, type.GetGateType());
912 env_->GetCurrentLabel()->SetDepend(result);
913 if (type == VariableType::JS_POINTER() || type == VariableType::JS_ANY()) {
914 auto env = GetEnvironment();
915 Label entry(env);
916 env->SubCfgEntry(&entry);
917 Label exit(env);
918 Label isHeapObject(env);
919
920 Branch(TaggedIsHeapObject(value), &isHeapObject, &exit);
921 Bind(&isHeapObject);
922 {
923 CallNGCRuntime(glue, RTSTUB_ID(StoreBarrier), { glue, base, offset, value });
924 Jump(&exit);
925 }
926 Bind(&exit);
927 env->SubCfgExit();
928 }
929 }
930 }
931
SetValueWithBarrier(GateRef glue,GateRef obj,GateRef offset,GateRef value)932 void StubBuilder::SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value)
933 {
934 auto env = GetEnvironment();
935 Label entry(env);
936 env->SubCfgEntry(&entry);
937 Label exit(env);
938 Label isHeapObject(env);
939 Label isVailedIndex(env);
940 Label notValidIndex(env);
941
942 Branch(TaggedIsHeapObject(value), &isHeapObject, &exit);
943 Bind(&isHeapObject);
944 {
945 // ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj.
946 GateRef objectRegion = ObjectAddressToRange(obj);
947 GateRef valueRegion = ObjectAddressToRange(value);
948 GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
949 GateRef objectNotInYoung = BoolNot(InYoungGeneration(objectRegion));
950 GateRef valueRegionInYoung = InYoungGeneration(valueRegion);
951 Branch(BoolAnd(objectNotInYoung, valueRegionInYoung), &isVailedIndex, ¬ValidIndex);
952 Bind(&isVailedIndex);
953 {
954 GateRef loadOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env_->Is32Bit()));
955 auto oldToNewSet = Load(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
956 Label isNullPtr(env);
957 Label notNullPtr(env);
958 Branch(IntPtrEuqal(oldToNewSet, IntPtr(0)), &isNullPtr, ¬NullPtr);
959 Bind(¬NullPtr);
960 {
961 // (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
962 GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
963 GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
964 GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
965 GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
966 // bitOffset >> BIT_PER_WORD_LOG2
967 GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
968 GateRef byteIndex = Int32Mul(index, bytePerWord);
969 // bitset_[index] |= mask;
970 GateRef bitsetData = PtrAdd(oldToNewSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
971 GateRef oldsetValue = Load(VariableType::INT32(), bitsetData, byteIndex);
972 GateRef newmapValue = Int32Or(oldsetValue, GetBitMask(bitOffset));
973
974 Store(VariableType::INT32(), glue, bitsetData, byteIndex, newmapValue);
975 Jump(¬ValidIndex);
976 }
977 Bind(&isNullPtr);
978 {
979 CallNGCRuntime(glue, RTSTUB_ID(InsertOldToNewRSet), { glue, obj, offset });
980 Jump(¬ValidIndex);
981 }
982 }
983 Bind(¬ValidIndex);
984 {
985 Label marking(env);
986 bool isArch32 = GetEnvironment()->Is32Bit();
987 GateRef stateBitFieldAddr = Int64Add(glue,
988 Int64(JSThread::GlueData::GetStateBitFieldOffset(isArch32)));
989 GateRef stateBitField = Load(VariableType::INT64(), stateBitFieldAddr, Int64(0));
990 // mask: 1 << JSThread::CONCURRENT_MARKING_BITFIELD_NUM - 1
991 GateRef markingBitMask = Int64Sub(
992 Int64LSL(Int64(1), Int64(JSThread::CONCURRENT_MARKING_BITFIELD_NUM)), Int64(1));
993 GateRef state = Int64And(stateBitField, markingBitMask);
994 Branch(Int64Equal(state, Int64(static_cast<int64_t>(MarkStatus::READY_TO_MARK))), &exit, &marking);
995
996 Bind(&marking);
997 CallNGCRuntime(
998 glue,
999 RTSTUB_ID(MarkingBarrier), { glue, obj, offset, value });
1000 Jump(&exit);
1001 }
1002 }
1003 Bind(&exit);
1004 env->SubCfgExit();
1005 }
1006
TaggedIsBigInt(GateRef obj)1007 GateRef StubBuilder::TaggedIsBigInt(GateRef obj)
1008 {
1009 auto env = GetEnvironment();
1010 Label entry(env);
1011 env->SubCfgEntry(&entry);
1012 Label exit(env);
1013 Label isHeapObject(env);
1014 DEFVARIABLE(result, VariableType::BOOL(), False());
1015 Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
1016 Bind(&isHeapObject);
1017 {
1018 result = Int32Equal(GetObjectType(LoadHClass(obj)),
1019 Int32(static_cast<int32_t>(JSType::BIGINT)));
1020 Jump(&exit);
1021 }
1022 Bind(&exit);
1023 auto ret = *result;
1024 env->SubCfgExit();
1025 return ret;
1026 }
1027
TaggedIsPropertyBox(GateRef obj)1028 GateRef StubBuilder::TaggedIsPropertyBox(GateRef obj)
1029 {
1030 auto env = GetEnvironment();
1031 Label entry(env);
1032 env->SubCfgEntry(&entry);
1033 Label exit(env);
1034 Label isHeapObject(env);
1035 DEFVARIABLE(result, VariableType::BOOL(), False());
1036 Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
1037 Bind(&isHeapObject);
1038 {
1039 GateRef type = GetObjectType(LoadHClass(obj));
1040 result = Int32Equal(type, Int32(static_cast<int32_t>(JSType::PROPERTY_BOX)));
1041 Jump(&exit);
1042 }
1043 Bind(&exit);
1044 auto ret = *result;
1045 env->SubCfgExit();
1046 return ret;
1047 }
1048
TaggedIsAccessor(GateRef x)1049 GateRef StubBuilder::TaggedIsAccessor(GateRef x)
1050 {
1051 auto env = GetEnvironment();
1052 Label entry(env);
1053 env->SubCfgEntry(&entry);
1054 Label exit(env);
1055 Label isHeapObject(env);
1056 DEFVARIABLE(result, VariableType::BOOL(), False());
1057 Branch(TaggedIsHeapObject(x), &isHeapObject, &exit);
1058 Bind(&isHeapObject);
1059 {
1060 GateRef type = GetObjectType(LoadHClass(x));
1061 result = BoolOr(Int32Equal(type, Int32(static_cast<int32_t>(JSType::ACCESSOR_DATA))),
1062 Int32Equal(type, Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR))));
1063 Jump(&exit);
1064 }
1065 Bind(&exit);
1066 auto ret = *result;
1067 env->SubCfgExit();
1068 return ret;
1069 }
1070
IsUtf16String(GateRef string)1071 GateRef StubBuilder::IsUtf16String(GateRef string)
1072 {
1073 // compressedStringsEnabled fixed to true constant
1074 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1075 return Int32Equal(
1076 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
1077 Int32(EcmaString::STRING_UNCOMPRESSED));
1078 }
1079
IsUtf8String(GateRef string)1080 GateRef StubBuilder::IsUtf8String(GateRef string)
1081 {
1082 // compressedStringsEnabled fixed to true constant
1083 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1084 return Int32Equal(
1085 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
1086 Int32(EcmaString::STRING_COMPRESSED));
1087 }
1088
IsInternalString(GateRef string)1089 GateRef StubBuilder::IsInternalString(GateRef string)
1090 {
1091 // compressedStringsEnabled fixed to true constant
1092 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1093 return Int32NotEqual(
1094 Int32And(len, Int32(EcmaString::STRING_INTERN_BIT)),
1095 Int32(0));
1096 }
1097
IsDigit(GateRef ch)1098 GateRef StubBuilder::IsDigit(GateRef ch)
1099 {
1100 return BoolAnd(Int32LessThanOrEqual(ch, Int32('9')),
1101 Int32GreaterThanOrEqual(ch, Int32('0')));
1102 }
1103
StringToElementIndex(GateRef string)1104 GateRef StubBuilder::StringToElementIndex(GateRef string)
1105 {
1106 auto env = GetEnvironment();
1107 Label entry(env);
1108 env->SubCfgEntry(&entry);
1109 Label exit(env);
1110 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
1111 Label greatThanZero(env);
1112 Label inRange(env);
1113 auto len = GetLengthFromString(string);
1114 Branch(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
1115 Bind(&greatThanZero);
1116 Branch(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
1117 Bind(&inRange);
1118 {
1119 GateRef dataUtf16 = PtrAdd(string, IntPtr(EcmaString::DATA_OFFSET));
1120 DEFVARIABLE(c, VariableType::INT32(), Int32(0));
1121 Label isUtf16(env);
1122 Label isUtf8(env);
1123 Label getChar1(env);
1124 GateRef isUtf16String = IsUtf16String(string);
1125 Branch(isUtf16String, &isUtf16, &isUtf8);
1126 Bind(&isUtf16);
1127 {
1128 c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16));
1129 Jump(&getChar1);
1130 }
1131 Bind(&isUtf8);
1132 {
1133 c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16));
1134 Jump(&getChar1);
1135 }
1136 Bind(&getChar1);
1137 {
1138 Label isDigitZero(env);
1139 Label notDigitZero(env);
1140 Branch(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero);
1141 Bind(&isDigitZero);
1142 {
1143 Label lengthIsOne(env);
1144 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
1145 Bind(&lengthIsOne);
1146 {
1147 result = Int32(0);
1148 Jump(&exit);
1149 }
1150 }
1151 Bind(¬DigitZero);
1152 {
1153 Label isDigit(env);
1154 DEFVARIABLE(i, VariableType::INT32(), Int32(1));
1155 DEFVARIABLE(n, VariableType::INT32(), Int32Sub(*c, Int32('0')));
1156 Branch(IsDigit(*c), &isDigit, &exit);
1157 Label loopHead(env);
1158 Label loopEnd(env);
1159 Label afterLoop(env);
1160 Bind(&isDigit);
1161 Branch(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
1162 LoopBegin(&loopHead);
1163 {
1164 Label isUtf16A(env);
1165 Label notUtf16(env);
1166 Label getChar2(env);
1167 Branch(isUtf16String, &isUtf16A, ¬Utf16);
1168 Bind(&isUtf16A);
1169 {
1170 // 2 : 2 means utf16 char width is two bytes
1171 auto charOffset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(2));
1172 c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16, charOffset));
1173 Jump(&getChar2);
1174 }
1175 Bind(¬Utf16);
1176 {
1177 c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16, ZExtInt32ToPtr(*i)));
1178 Jump(&getChar2);
1179 }
1180 Bind(&getChar2);
1181 {
1182 Label isDigit2(env);
1183 Label notDigit2(env);
1184 Branch(IsDigit(*c), &isDigit2, ¬Digit2);
1185 Bind(&isDigit2);
1186 {
1187 // 10 means the base of digit is 10.
1188 n = Int32Add(Int32Mul(*n, Int32(10)),
1189 Int32Sub(*c, Int32('0')));
1190 i = Int32Add(*i, Int32(1));
1191 Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
1192 }
1193 Bind(¬Digit2);
1194 Jump(&exit);
1195 }
1196 }
1197 Bind(&loopEnd);
1198 LoopEnd(&loopHead);
1199 Bind(&afterLoop);
1200 {
1201 Label lessThanMaxIndex(env);
1202 Branch(Int32UnsignedLessThan(*n, Int32(JSObject::MAX_ELEMENT_INDEX)),
1203 &lessThanMaxIndex, &exit);
1204 Bind(&lessThanMaxIndex);
1205 {
1206 result = *n;
1207 Jump(&exit);
1208 }
1209 }
1210 }
1211 }
1212 }
1213 Bind(&exit);
1214 auto ret = *result;
1215 env->SubCfgExit();
1216 return ret;
1217 }
1218
TryToElementsIndex(GateRef key)1219 GateRef StubBuilder::TryToElementsIndex(GateRef key)
1220 {
1221 auto env = GetEnvironment();
1222 Label entry(env);
1223 env->SubCfgEntry(&entry);
1224 Label exit(env);
1225 Label isKeyInt(env);
1226 Label notKeyInt(env);
1227
1228 DEFVARIABLE(resultKey, VariableType::INT32(), Int32(-1));
1229 Branch(TaggedIsInt(key), &isKeyInt, ¬KeyInt);
1230 Bind(&isKeyInt);
1231 {
1232 resultKey = GetInt32OfTInt(key);
1233 Jump(&exit);
1234 }
1235 Bind(¬KeyInt);
1236 {
1237 Label isString(env);
1238 Label notString(env);
1239 Branch(TaggedIsString(key), &isString, ¬String);
1240 Bind(&isString);
1241 {
1242 resultKey = StringToElementIndex(key);
1243 Jump(&exit);
1244 }
1245 Bind(¬String);
1246 {
1247 Label isDouble(env);
1248 Branch(TaggedIsDouble(key), &isDouble, &exit);
1249 Bind(&isDouble);
1250 {
1251 GateRef number = GetDoubleOfTDouble(key);
1252 GateRef integer = ChangeFloat64ToInt32(number);
1253 Label isEqual(env);
1254 Branch(DoubleEqual(number, ChangeInt32ToFloat64(integer)), &isEqual, &exit);
1255 Bind(&isEqual);
1256 {
1257 resultKey = integer;
1258 Jump(&exit);
1259 }
1260 }
1261 }
1262 }
1263 Bind(&exit);
1264 auto ret = *resultKey;
1265 env->SubCfgExit();
1266 return ret;
1267 }
1268
LdGlobalRecord(GateRef glue,GateRef key)1269 GateRef StubBuilder::LdGlobalRecord(GateRef glue, GateRef key)
1270 {
1271 auto env = GetEnvironment();
1272 Label entry(env);
1273 env->SubCfgEntry(&entry);
1274 Label exit(env);
1275
1276 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1277 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1278 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1279 GateRef globalRecord = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::GLOBAL_RECORD);
1280 GateRef recordEntry = FindEntryFromNameDictionary(glue, globalRecord, key);
1281 Label foundInGlobalRecord(env);
1282 Branch(Int32NotEqual(recordEntry, Int32(-1)), &foundInGlobalRecord, &exit);
1283 Bind(&foundInGlobalRecord);
1284 {
1285 result = GetBoxFromGlobalDictionary(globalRecord, recordEntry);
1286 Jump(&exit);
1287 }
1288 Bind(&exit);
1289 auto ret = *result;
1290 env->SubCfgExit();
1291 return ret;
1292 }
1293
LoadFromField(GateRef receiver,GateRef handlerInfo)1294 GateRef StubBuilder::LoadFromField(GateRef receiver, GateRef handlerInfo)
1295 {
1296 auto env = GetEnvironment();
1297 Label entry(env);
1298 env->SubCfgEntry(&entry);
1299 Label exit(env);
1300 Label handlerInfoIsInlinedProps(env);
1301 Label handlerInfoNotInlinedProps(env);
1302 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1303 GateRef index = HandlerBaseGetOffset(handlerInfo);
1304 Branch(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
1305 Bind(&handlerInfoIsInlinedProps);
1306 {
1307 result = Load(VariableType::JS_ANY(), receiver, PtrMul(ZExtInt32ToPtr(index),
1308 IntPtr(JSTaggedValue::TaggedTypeSize())));
1309 Jump(&exit);
1310 }
1311 Bind(&handlerInfoNotInlinedProps);
1312 {
1313 result = GetValueFromTaggedArray(GetPropertiesArray(receiver), index);
1314 Jump(&exit);
1315 }
1316 Bind(&exit);
1317 auto ret = *result;
1318 env->SubCfgExit();
1319 return ret;
1320 }
1321
LoadGlobal(GateRef cell)1322 GateRef StubBuilder::LoadGlobal(GateRef cell)
1323 {
1324 auto env = GetEnvironment();
1325 Label entry(env);
1326 env->SubCfgEntry(&entry);
1327 Label exit(env);
1328 Label cellIsInvalid(env);
1329 Label cellNotInvalid(env);
1330 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1331 Branch(IsInvalidPropertyBox(cell), &cellIsInvalid, &cellNotInvalid);
1332 Bind(&cellIsInvalid);
1333 {
1334 Jump(&exit);
1335 }
1336 Bind(&cellNotInvalid);
1337 {
1338 result = GetValueFromPropertyBox(cell);
1339 Jump(&exit);
1340 }
1341 Bind(&exit);
1342 auto ret = *result;
1343 env->SubCfgExit();
1344 return ret;
1345 }
1346
CheckPolyHClass(GateRef cachedValue,GateRef hclass)1347 GateRef StubBuilder::CheckPolyHClass(GateRef cachedValue, GateRef hclass)
1348 {
1349 auto env = GetEnvironment();
1350 Label entry(env);
1351 env->SubCfgEntry(&entry);
1352 Label exit(env);
1353 Label loopHead(env);
1354 Label loopEnd(env);
1355 Label iLessLength(env);
1356 Label hasHclass(env);
1357 Label cachedValueNotWeak(env);
1358 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1359 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1360 Branch(TaggedIsWeak(cachedValue), &exit, &cachedValueNotWeak);
1361 Bind(&cachedValueNotWeak);
1362 {
1363 GateRef length = GetLengthOfTaggedArray(cachedValue);
1364 Jump(&loopHead);
1365 LoopBegin(&loopHead);
1366 {
1367 Branch(Int32UnsignedLessThan(*i, length), &iLessLength, &exit);
1368 Bind(&iLessLength);
1369 {
1370 GateRef element = GetValueFromTaggedArray(cachedValue, *i);
1371 Branch(Equal(LoadObjectFromWeakRef(element), hclass), &hasHclass, &loopEnd);
1372 Bind(&hasHclass);
1373 result = GetValueFromTaggedArray(cachedValue,
1374 Int32Add(*i, Int32(1)));
1375 Jump(&exit);
1376 }
1377 Bind(&loopEnd);
1378 i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot
1379 LoopEnd(&loopHead);
1380 }
1381 }
1382 Bind(&exit);
1383 auto ret = *result;
1384 env->SubCfgExit();
1385 return ret;
1386 }
1387
LoadICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef argHandler)1388 GateRef StubBuilder::LoadICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder, GateRef argHandler)
1389 {
1390 auto env = GetEnvironment();
1391 Label entry(env);
1392 env->SubCfgEntry(&entry);
1393 Label exit(env);
1394 Label handlerIsInt(env);
1395 Label handlerNotInt(env);
1396 Label handlerInfoIsField(env);
1397 Label handlerInfoNotField(env);
1398 Label handlerInfoIsNonExist(env);
1399 Label handlerInfoNotNonExist(env);
1400 Label handlerIsPrototypeHandler(env);
1401 Label handlerNotPrototypeHandler(env);
1402 Label cellHasChanged(env);
1403 Label loopHead(env);
1404 Label loopEnd(env);
1405 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1406 DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
1407 DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
1408
1409 Jump(&loopHead);
1410 LoopBegin(&loopHead);
1411 {
1412 Branch(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
1413 Bind(&handlerIsInt);
1414 {
1415 GateRef handlerInfo = GetInt32OfTInt(*handler);
1416 Branch(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
1417 Bind(&handlerInfoIsField);
1418 {
1419 result = LoadFromField(*holder, handlerInfo);
1420 Jump(&exit);
1421 }
1422 Bind(&handlerInfoNotField);
1423 {
1424 Branch(IsNonExist(handlerInfo), &handlerInfoIsNonExist, &handlerInfoNotNonExist);
1425 Bind(&handlerInfoIsNonExist);
1426 Jump(&exit);
1427 Bind(&handlerInfoNotNonExist);
1428 GateRef accessor = LoadFromField(*holder, handlerInfo);
1429 result = CallGetterHelper(glue, receiver, *holder, accessor);
1430 Jump(&exit);
1431 }
1432 }
1433 Bind(&handlerNotInt);
1434 Branch(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
1435 Bind(&handlerIsPrototypeHandler);
1436 {
1437 GateRef cellValue = GetProtoCell(*handler);
1438 Branch(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
1439 Bind(&cellHasChanged);
1440 {
1441 result = Hole();
1442 Jump(&exit);
1443 }
1444 Bind(&loopEnd);
1445 holder = GetPrototypeHandlerHolder(*handler);
1446 handler = GetPrototypeHandlerHandlerInfo(*handler);
1447 LoopEnd(&loopHead);
1448 }
1449 }
1450 Bind(&handlerNotPrototypeHandler);
1451 result = LoadGlobal(*handler);
1452 Jump(&exit);
1453
1454 Bind(&exit);
1455 auto ret = *result;
1456 env->SubCfgExit();
1457 return ret;
1458 }
1459
LoadElement(GateRef receiver,GateRef key)1460 GateRef StubBuilder::LoadElement(GateRef receiver, GateRef key)
1461 {
1462 auto env = GetEnvironment();
1463 Label entry(env);
1464 env->SubCfgEntry(&entry);
1465 Label exit(env);
1466 Label indexLessZero(env);
1467 Label indexNotLessZero(env);
1468 Label lengthLessIndex(env);
1469 Label lengthNotLessIndex(env);
1470 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1471 GateRef index = TryToElementsIndex(key);
1472 Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
1473 Bind(&indexLessZero);
1474 {
1475 Jump(&exit);
1476 }
1477 Bind(&indexNotLessZero);
1478 {
1479 GateRef elements = GetElementsArray(receiver);
1480 Branch(Int32LessThanOrEqual(GetLengthOfTaggedArray(elements), index), &lengthLessIndex, &lengthNotLessIndex);
1481 Bind(&lengthLessIndex);
1482 Jump(&exit);
1483 Bind(&lengthNotLessIndex);
1484 result = GetValueFromTaggedArray(elements, index);
1485 Jump(&exit);
1486 }
1487 Bind(&exit);
1488 auto ret = *result;
1489 env->SubCfgExit();
1490 return ret;
1491 }
1492
ICStoreElement(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef handler)1493 GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef handler)
1494 {
1495 auto env = GetEnvironment();
1496 Label entry(env);
1497 env->SubCfgEntry(&entry);
1498 Label exit(env);
1499 Label indexLessZero(env);
1500 Label indexNotLessZero(env);
1501 Label handerInfoIsJSArray(env);
1502 Label handerInfoNotJSArray(env);
1503 Label isJsCOWArray(env);
1504 Label isNotJsCOWArray(env);
1505 Label setElementsLength(env);
1506 Label indexGreaterLength(env);
1507 Label indexGreaterCapacity(env);
1508 Label callRuntime(env);
1509 Label storeElement(env);
1510 Label handlerIsInt(env);
1511 Label handlerNotInt(env);
1512 Label cellHasChanged(env);
1513 Label cellHasNotChanged(env);
1514 Label loopHead(env);
1515 Label loopEnd(env);
1516 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1517 DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler);
1518 GateRef index = TryToElementsIndex(key);
1519 Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
1520 Bind(&indexLessZero);
1521 {
1522 Jump(&exit);
1523 }
1524 Bind(&indexNotLessZero);
1525 {
1526 Jump(&loopHead);
1527 LoopBegin(&loopHead);
1528 Branch(TaggedIsInt(*varHandler), &handlerIsInt, &handlerNotInt);
1529 Bind(&handlerIsInt);
1530 {
1531 GateRef handlerInfo = GetInt32OfTInt(*varHandler);
1532 Branch(HandlerBaseIsJSArray(handlerInfo), &handerInfoIsJSArray, &handerInfoNotJSArray);
1533 Bind(&handerInfoIsJSArray);
1534 {
1535 Branch(IsJsCOWArray(receiver), &isJsCOWArray, &isNotJsCOWArray);
1536 Bind(&isJsCOWArray);
1537 {
1538 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {receiver});
1539 Jump(&setElementsLength);
1540 }
1541 Bind(&isNotJsCOWArray);
1542 {
1543 Jump(&setElementsLength);
1544 }
1545 Bind(&setElementsLength);
1546 {
1547 GateRef oldLength = GetArrayLength(receiver);
1548 Branch(Int32GreaterThanOrEqual(index, oldLength), &indexGreaterLength, &handerInfoNotJSArray);
1549 Bind(&indexGreaterLength);
1550 Store(VariableType::INT64(), glue, receiver,
1551 IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET),
1552 IntToTaggedInt(Int32Add(index, Int32(1))));
1553 }
1554 Jump(&handerInfoNotJSArray);
1555 }
1556 Bind(&handerInfoNotJSArray);
1557 {
1558 GateRef elements = GetElementsArray(receiver);
1559 GateRef capacity = GetLengthOfTaggedArray(elements);
1560 Branch(Int32GreaterThanOrEqual(index, capacity), &callRuntime, &storeElement);
1561 Bind(&callRuntime);
1562 {
1563 result = CallRuntime(glue,
1564 RTSTUB_ID(TaggedArraySetValue),
1565 { receiver, value, elements, IntToTaggedInt(index),
1566 IntToTaggedInt(capacity) });
1567 Jump(&exit);
1568 }
1569 Bind(&storeElement);
1570 {
1571 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, value);
1572 result = Undefined();
1573 Jump(&exit);
1574 }
1575 }
1576 }
1577 Bind(&handlerNotInt);
1578 {
1579 GateRef cellValue = GetProtoCell(*varHandler);
1580 Branch(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
1581 Bind(&cellHasChanged);
1582 {
1583 Jump(&exit);
1584 }
1585 Bind(&loopEnd);
1586 {
1587 varHandler = GetPrototypeHandlerHandlerInfo(*varHandler);
1588 LoopEnd(&loopHead);
1589 }
1590 }
1591 }
1592 Bind(&exit);
1593 auto ret = *result;
1594 env->SubCfgExit();
1595 return ret;
1596 }
1597
GetArrayLength(GateRef object)1598 GateRef StubBuilder::GetArrayLength(GateRef object)
1599 {
1600 auto env = GetEnvironment();
1601 Label entry(env);
1602 env->SubCfgEntry(&entry);
1603 Label exit(env);
1604 Label lengthIsInt(env);
1605 Label lengthNotInt(env);
1606 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
1607 GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
1608 GateRef length = Load(VariableType::INT64(), object, lengthOffset);
1609 Branch(TaggedIsInt(length), &lengthIsInt, &lengthNotInt);
1610 Bind(&lengthIsInt);
1611 {
1612 result = GetInt32OfTInt(length);
1613 Jump(&exit);
1614 }
1615 Bind(&lengthNotInt);
1616 {
1617 result = ChangeFloat64ToInt32(GetDoubleOfTDouble(length));
1618 Jump(&exit);
1619 }
1620 Bind(&exit);
1621 auto ret = *result;
1622 env->SubCfgExit();
1623 return ret;
1624 }
1625
StoreICWithHandler(GateRef glue,GateRef receiver,GateRef argHolder,GateRef value,GateRef argHandler)1626 GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder,
1627 GateRef value, GateRef argHandler)
1628 {
1629 auto env = GetEnvironment();
1630 Label entry(env);
1631 env->SubCfgEntry(&entry);
1632 Label exit(env);
1633 Label handlerIsInt(env);
1634 Label handlerNotInt(env);
1635 Label handlerInfoIsField(env);
1636 Label handlerInfoNotField(env);
1637 Label handlerIsTransitionHandler(env);
1638 Label handlerNotTransitionHandler(env);
1639 Label handlerIsTransWithProtoHandler(env);
1640 Label handlerNotTransWithProtoHandler(env);
1641 Label handlerIsPrototypeHandler(env);
1642 Label handlerNotPrototypeHandler(env);
1643 Label handlerIsPropertyBox(env);
1644 Label handlerNotPropertyBox(env);
1645 Label handlerIsStoreTSHandler(env);
1646 Label handlerNotStoreTSHandler(env);
1647 Label aotHandlerInfoIsField(env);
1648 Label aotHandlerInfoNotField(env);
1649 Label cellHasChanged(env);
1650 Label cellNotChanged(env);
1651 Label aotCellNotChanged(env);
1652 Label loopHead(env);
1653 Label loopEnd(env);
1654 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1655 DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
1656 DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
1657 Jump(&loopHead);
1658 LoopBegin(&loopHead);
1659 {
1660 Branch(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
1661 Bind(&handlerIsInt);
1662 {
1663 GateRef handlerInfo = GetInt32OfTInt(*handler);
1664 Branch(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
1665 Bind(&handlerInfoIsField);
1666 {
1667 StoreField(glue, receiver, value, handlerInfo);
1668 Jump(&exit);
1669 }
1670 Bind(&handlerInfoNotField);
1671 {
1672 GateRef accessor = LoadFromField(*holder, handlerInfo);
1673 result = CallSetterHelper(glue, receiver, accessor, value);
1674 Jump(&exit);
1675 }
1676 }
1677 Bind(&handlerNotInt);
1678 {
1679 Branch(TaggedIsTransitionHandler(*handler), &handlerIsTransitionHandler, &handlerNotTransitionHandler);
1680 Bind(&handlerIsTransitionHandler);
1681 {
1682 StoreWithTransition(glue, receiver, value, *handler);
1683 Jump(&exit);
1684 }
1685 Bind(&handlerNotTransitionHandler);
1686 {
1687 Branch(TaggedIsTransWithProtoHandler(*handler), &handlerIsTransWithProtoHandler,
1688 &handlerNotTransWithProtoHandler);
1689 Bind(&handlerIsTransWithProtoHandler);
1690 {
1691 GateRef cellValue = GetProtoCell(*handler);
1692 Branch(GetHasChanged(cellValue), &cellHasChanged, &cellNotChanged);
1693 Bind(&cellNotChanged);
1694 {
1695 StoreWithTransition(glue, receiver, value, *handler, true);
1696 Jump(&exit);
1697 }
1698 }
1699 Bind(&handlerNotTransWithProtoHandler);
1700 {
1701 Branch(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
1702 Bind(&handlerNotPrototypeHandler);
1703 {
1704 Branch(TaggedIsPropertyBox(*handler), &handlerIsPropertyBox, &handlerNotPropertyBox);
1705 Bind(&handlerIsPropertyBox);
1706 StoreGlobal(glue, value, *handler);
1707 Jump(&exit);
1708 }
1709 }
1710 }
1711 }
1712 Bind(&handlerIsPrototypeHandler);
1713 {
1714 GateRef cellValue = GetProtoCell(*handler);
1715 Branch(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
1716 Bind(&loopEnd);
1717 {
1718 holder = GetPrototypeHandlerHolder(*handler);
1719 handler = GetPrototypeHandlerHandlerInfo(*handler);
1720 LoopEnd(&loopHead);
1721 }
1722 }
1723 Bind(&handlerNotPropertyBox);
1724 {
1725 Branch(TaggedIsStoreTSHandler(*handler), &handlerIsStoreTSHandler, &handlerNotStoreTSHandler);
1726 Bind(&handlerIsStoreTSHandler);
1727 {
1728 GateRef cellValue = GetProtoCell(*handler);
1729 Branch(GetHasChanged(cellValue), &cellHasChanged, &aotCellNotChanged);
1730 Bind(&aotCellNotChanged);
1731 {
1732 holder = GetStoreTSHandlerHolder(*handler);
1733 handler = GetStoreTSHandlerHandlerInfo(*handler);
1734 GateRef handlerInfo = GetInt32OfTInt(*handler);
1735 Branch(IsField(handlerInfo), &aotHandlerInfoIsField, &aotHandlerInfoNotField);
1736 Bind(&aotHandlerInfoIsField);
1737 {
1738 StoreField(glue, receiver, value, handlerInfo);
1739 Jump(&exit);
1740 }
1741 Bind(&aotHandlerInfoNotField);
1742 {
1743 GateRef accessor = LoadFromField(*holder, handlerInfo);
1744 result = CallSetterHelper(glue, receiver, accessor, value);
1745 Jump(&exit);
1746 }
1747 }
1748 }
1749 Bind(&handlerNotStoreTSHandler);
1750 Jump(&exit);
1751 }
1752 Bind(&cellHasChanged);
1753 {
1754 result = Hole();
1755 Jump(&exit);
1756 }
1757 }
1758 Bind(&exit);
1759 auto ret = *result;
1760 env->SubCfgExit();
1761 return ret;
1762 }
1763
StoreField(GateRef glue,GateRef receiver,GateRef value,GateRef handler)1764 void StubBuilder::StoreField(GateRef glue, GateRef receiver, GateRef value, GateRef handler)
1765 {
1766 auto env = GetEnvironment();
1767 Label entry(env);
1768 env->SubCfgEntry(&entry);
1769 Label exit(env);
1770 Label handlerIsInlinedProperty(env);
1771 Label handlerNotInlinedProperty(env);
1772 GateRef index = HandlerBaseGetOffset(handler);
1773 Branch(HandlerBaseIsInlinedProperty(handler), &handlerIsInlinedProperty, &handlerNotInlinedProperty);
1774 Bind(&handlerIsInlinedProperty);
1775 {
1776 Store(VariableType::JS_ANY(),
1777 glue,
1778 receiver,
1779 PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())),
1780 value);
1781 Jump(&exit);
1782 }
1783 Bind(&handlerNotInlinedProperty);
1784 {
1785 GateRef array = GetPropertiesArray(receiver);
1786 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, index, value);
1787 Jump(&exit);
1788 }
1789 Bind(&exit);
1790 env->SubCfgExit();
1791 }
1792
StoreWithTransition(GateRef glue,GateRef receiver,GateRef value,GateRef handler,bool withPrototype)1793 void StubBuilder::StoreWithTransition(GateRef glue, GateRef receiver, GateRef value, GateRef handler,
1794 bool withPrototype)
1795 {
1796 auto env = GetEnvironment();
1797 Label entry(env);
1798 env->SubCfgEntry(&entry);
1799 Label exit(env);
1800
1801 Label handlerInfoIsInlinedProps(env);
1802 Label handlerInfoNotInlinedProps(env);
1803 Label indexMoreCapacity(env);
1804 Label indexLessCapacity(env);
1805 GateRef newHClass;
1806 GateRef handlerInfo;
1807 if (withPrototype) {
1808 newHClass = GetTransWithProtoHClass(handler);
1809 handlerInfo = GetInt32OfTInt(GetTransWithProtoHandlerInfo(handler));
1810 } else {
1811 newHClass = GetTransitionHClass(handler);
1812 handlerInfo = GetInt32OfTInt(GetTransitionHandlerInfo(handler));
1813 }
1814
1815 StoreHClass(glue, receiver, newHClass);
1816 Branch(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
1817 Bind(&handlerInfoNotInlinedProps);
1818 {
1819 GateRef array = GetPropertiesArray(receiver);
1820 GateRef capacity = GetLengthOfTaggedArray(array);
1821 GateRef index = HandlerBaseGetOffset(handlerInfo);
1822 Branch(Int32GreaterThanOrEqual(index, capacity), &indexMoreCapacity, &indexLessCapacity);
1823 Bind(&indexMoreCapacity);
1824 {
1825 CallRuntime(glue,
1826 RTSTUB_ID(PropertiesSetValue),
1827 { receiver, value, array, IntToTaggedInt(capacity),
1828 IntToTaggedInt(index) });
1829 Jump(&exit);
1830 }
1831 Bind(&indexLessCapacity);
1832 {
1833 Store(VariableType::JS_ANY(),
1834 glue,
1835 PtrAdd(array, IntPtr(TaggedArray::DATA_OFFSET)),
1836 PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())),
1837 value);
1838 Jump(&exit);
1839 }
1840 }
1841 Bind(&handlerInfoIsInlinedProps);
1842 {
1843 StoreField(glue, receiver, value, handlerInfo);
1844 Jump(&exit);
1845 }
1846 Bind(&exit);
1847 env->SubCfgExit();
1848 }
1849
StoreGlobal(GateRef glue,GateRef value,GateRef cell)1850 GateRef StubBuilder::StoreGlobal(GateRef glue, GateRef value, GateRef cell)
1851 {
1852 auto env = GetEnvironment();
1853 Label entry(env);
1854 env->SubCfgEntry(&entry);
1855 Label exit(env);
1856 Label cellIsInvalid(env);
1857 Label cellNotInvalid(env);
1858 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1859 Branch(IsInvalidPropertyBox(cell), &cellIsInvalid, &cellNotInvalid);
1860 Bind(&cellIsInvalid);
1861 {
1862 Jump(&exit);
1863 }
1864 Bind(&cellNotInvalid);
1865 {
1866 Store(VariableType::JS_ANY(), glue, cell, IntPtr(PropertyBox::VALUE_OFFSET), value);
1867 result = Undefined();
1868 Jump(&exit);
1869 }
1870 Bind(&exit);
1871 auto ret = *result;
1872 env->SubCfgExit();
1873 return ret;
1874 }
1875
1876 template<typename DictionaryT>
GetAttributesFromDictionary(GateRef elements,GateRef entry)1877 GateRef StubBuilder::GetAttributesFromDictionary(GateRef elements, GateRef entry)
1878 {
1879 GateRef arrayIndex =
1880 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
1881 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
1882 GateRef attributesIndex =
1883 Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_DETAILS_INDEX));
1884 auto attrValue = GetValueFromTaggedArray(elements, attributesIndex);
1885 return GetInt32OfTInt(attrValue);
1886 }
1887
1888 template<typename DictionaryT>
GetValueFromDictionary(GateRef elements,GateRef entry)1889 GateRef StubBuilder::GetValueFromDictionary(GateRef elements, GateRef entry)
1890 {
1891 GateRef arrayIndex =
1892 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
1893 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
1894 GateRef valueIndex =
1895 Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
1896 return GetValueFromTaggedArray(elements, valueIndex);
1897 }
1898
1899 template<typename DictionaryT>
GetKeyFromDictionary(GateRef elements,GateRef entry)1900 GateRef StubBuilder::GetKeyFromDictionary(GateRef elements, GateRef entry)
1901 {
1902 auto env = GetEnvironment();
1903 Label subentry(env);
1904 env->SubCfgEntry(&subentry);
1905 Label exit(env);
1906 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1907 Label ltZero(env);
1908 Label notLtZero(env);
1909 Label gtLength(env);
1910 Label notGtLength(env);
1911 GateRef dictionaryLength =
1912 Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
1913 GateRef arrayIndex =
1914 Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
1915 Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
1916 Branch(Int32LessThan(arrayIndex, Int32(0)), <Zero, ¬LtZero);
1917 Bind(<Zero);
1918 Jump(&exit);
1919 Bind(¬LtZero);
1920 Branch(Int32GreaterThan(arrayIndex, dictionaryLength), >Length, ¬GtLength);
1921 Bind(>Length);
1922 Jump(&exit);
1923 Bind(¬GtLength);
1924 result = GetValueFromTaggedArray(elements, arrayIndex);
1925 Jump(&exit);
1926 Bind(&exit);
1927 auto ret = *result;
1928 env->SubCfgExit();
1929 return ret;
1930 }
1931
UpdateValueAndAttributes(GateRef glue,GateRef elements,GateRef index,GateRef value,GateRef attr)1932 inline void StubBuilder::UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index,
1933 GateRef value, GateRef attr)
1934 {
1935 GateRef arrayIndex =
1936 Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
1937 Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
1938 GateRef valueIndex =
1939 Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
1940 GateRef attributesIndex =
1941 Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_DETAILS_INDEX));
1942 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
1943 GateRef attroffset =
1944 PtrMul(ZExtInt32ToPtr(attributesIndex), IntPtr(JSTaggedValue::TaggedTypeSize()));
1945 GateRef dataOffset = PtrAdd(attroffset, IntPtr(TaggedArray::DATA_OFFSET));
1946 Store(VariableType::INT64(), glue, elements, dataOffset, IntToTaggedInt(attr));
1947 }
1948
UpdateValueInDict(GateRef glue,GateRef elements,GateRef index,GateRef value)1949 inline void StubBuilder::UpdateValueInDict(GateRef glue, GateRef elements, GateRef index, GateRef value)
1950 {
1951 GateRef arrayIndex = Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
1952 Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
1953 GateRef valueIndex = Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
1954 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
1955 }
1956
GetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index)1957 GateRef StubBuilder::GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index)
1958 {
1959 auto env = GetEnvironment();
1960 Label entry(env);
1961 env->SubCfgEntry(&entry);
1962 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1963 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
1964 Label exit(env);
1965 Label loopHead(env);
1966 Label loopEnd(env);
1967 Label loopExit(env);
1968 Label afterLoop(env);
1969 Jump(&loopHead);
1970 LoopBegin(&loopHead);
1971 {
1972 GateRef hclass = LoadHClass(*holder);
1973 GateRef jsType = GetObjectType(hclass);
1974 Label isSpecialIndexed(env);
1975 Label notSpecialIndexed(env);
1976 Branch(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed);
1977 Bind(&isSpecialIndexed);
1978 {
1979 // TypeArray
1980 Label isFastTypeArray(env);
1981 Label notFastTypeArray(env);
1982 Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
1983 Bind(&isFastTypeArray);
1984 {
1985 result = CallRuntime(glue, RTSTUB_ID(GetTypeArrayPropertyByIndex),
1986 { *holder, IntToTaggedInt(index), IntToTaggedInt(jsType)});
1987 Jump(&exit);
1988 }
1989 Bind(¬FastTypeArray);
1990
1991 Label isSpecialContainer(env);
1992 Label notSpecialContainer(env);
1993 // Add SpecialContainer
1994 Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
1995 Bind(&isSpecialContainer);
1996 {
1997 result = GetContainerProperty(glue, *holder, index, jsType);
1998 Jump(&exit);
1999 }
2000 Bind(¬SpecialContainer);
2001 {
2002 result = Hole();
2003 Jump(&exit);
2004 }
2005 }
2006 Bind(¬SpecialIndexed);
2007 {
2008 GateRef elements = GetElementsArray(*holder);
2009 Label isDictionaryElement(env);
2010 Label notDictionaryElement(env);
2011 Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
2012 Bind(¬DictionaryElement);
2013 {
2014 Label lessThanLength(env);
2015 Label notLessThanLength(env);
2016 Branch(Int32UnsignedLessThan(index, GetLengthOfTaggedArray(elements)),
2017 &lessThanLength, ¬LessThanLength);
2018 Bind(&lessThanLength);
2019 {
2020 Label notHole(env);
2021 Label isHole(env);
2022 GateRef value = GetValueFromTaggedArray(elements, index);
2023 Branch(TaggedIsNotHole(value), ¬Hole, &isHole);
2024 Bind(¬Hole);
2025 {
2026 result = value;
2027 Jump(&exit);
2028 }
2029 Bind(&isHole);
2030 {
2031 Jump(&loopExit);
2032 }
2033 }
2034 Bind(¬LessThanLength);
2035 {
2036 result = Hole();
2037 Jump(&exit);
2038 }
2039 }
2040 Bind(&isDictionaryElement);
2041 {
2042 GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
2043 Label notNegtiveOne(env);
2044 Label negtiveOne(env);
2045 Branch(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
2046 Bind(¬NegtiveOne);
2047 {
2048 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
2049 GateRef value = GetValueFromDictionary<NumberDictionary>(elements, entryA);
2050 Label isAccessor(env);
2051 Label notAccessor(env);
2052 Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
2053 Bind(&isAccessor);
2054 {
2055 result = CallGetterHelper(glue, receiver, *holder, value);
2056 Jump(&exit);
2057 }
2058 Bind(¬Accessor);
2059 {
2060 result = value;
2061 Jump(&exit);
2062 }
2063 }
2064 Bind(&negtiveOne);
2065 Jump(&loopExit);
2066 }
2067 Bind(&loopExit);
2068 {
2069 holder = GetPrototypeFromHClass(LoadHClass(*holder));
2070 Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
2071 }
2072 }
2073 Bind(&loopEnd);
2074 LoopEnd(&loopHead);
2075 Bind(&afterLoop);
2076 {
2077 result = Undefined();
2078 Jump(&exit);
2079 }
2080 }
2081 Bind(&exit);
2082 auto ret = *result;
2083 env->SubCfgExit();
2084 return ret;
2085 }
2086
GetPropertyByValue(GateRef glue,GateRef receiver,GateRef keyValue)2087 GateRef StubBuilder::GetPropertyByValue(GateRef glue, GateRef receiver, GateRef keyValue)
2088 {
2089 auto env = GetEnvironment();
2090 Label entry(env);
2091 env->SubCfgEntry(&entry);
2092 DEFVARIABLE(key, VariableType::JS_ANY(), keyValue);
2093 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2094 Label isNumberOrStringSymbol(env);
2095 Label notNumber(env);
2096 Label isStringOrSymbol(env);
2097 Label notStringOrSymbol(env);
2098 Label exit(env);
2099
2100 Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number);
2101 Bind(¬Number);
2102 {
2103 Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol);
2104 Bind(¬StringOrSymbol);
2105 {
2106 result = Hole();
2107 Jump(&exit);
2108 }
2109 }
2110 Bind(&isNumberOrStringSymbol);
2111 {
2112 GateRef index = TryToElementsIndex(*key);
2113 Label validIndex(env);
2114 Label notValidIndex(env);
2115 Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
2116 Bind(&validIndex);
2117 {
2118 result = GetPropertyByIndex(glue, receiver, index);
2119 Jump(&exit);
2120 }
2121 Bind(¬ValidIndex);
2122 {
2123 Label notNumber1(env);
2124 Label getByName(env);
2125 Branch(TaggedIsNumber(*key), &exit, ¬Number1);
2126 Bind(¬Number1);
2127 {
2128 Label isString(env);
2129 Label notString(env);
2130 Label isInternalString(env);
2131 Label notIntenalString(env);
2132 Branch(TaggedIsString(*key), &isString, ¬String);
2133 Bind(&isString);
2134 {
2135 Branch(IsInternalString(*key), &isInternalString, ¬IntenalString);
2136 Bind(&isInternalString);
2137 Jump(&getByName);
2138 Bind(¬IntenalString);
2139 {
2140 key = CallRuntime(glue, RTSTUB_ID(NewInternalString), { *key });
2141 Jump(&getByName);
2142 }
2143 }
2144 Bind(¬String);
2145 {
2146 Jump(&getByName);
2147 }
2148 }
2149 Bind(&getByName);
2150 {
2151 result = GetPropertyByName(glue, receiver, *key);
2152 Jump(&exit);
2153 }
2154 }
2155 }
2156 Bind(&exit);
2157 auto ret = *result;
2158 env->SubCfgExit();
2159 return ret;
2160 }
2161
GetPropertyByName(GateRef glue,GateRef receiver,GateRef key)2162 GateRef StubBuilder::GetPropertyByName(GateRef glue, GateRef receiver, GateRef key)
2163 {
2164 auto env = GetEnvironment();
2165 Label entry(env);
2166 env->SubCfgEntry(&entry);
2167 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2168 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
2169 Label exit(env);
2170 Label loopHead(env);
2171 Label loopEnd(env);
2172 Label loopExit(env);
2173 Label afterLoop(env);
2174 Jump(&loopHead);
2175 LoopBegin(&loopHead);
2176 {
2177 GateRef hclass = LoadHClass(*holder);
2178 GateRef jsType = GetObjectType(hclass);
2179 Label isSIndexObj(env);
2180 Label notSIndexObj(env);
2181 Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
2182 Bind(&isSIndexObj);
2183 {
2184 // TypeArray
2185 Label isFastTypeArray(env);
2186 Label notFastTypeArray(env);
2187 Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
2188 Bind(&isFastTypeArray);
2189 {
2190 result = GetTypeArrayPropertyByName(glue, receiver, *holder, key, jsType);
2191 Label isNull(env);
2192 Label notNull(env);
2193 Branch(TaggedIsNull(*result), &isNull, ¬Null);
2194 Bind(&isNull);
2195 {
2196 result = Hole();
2197 Jump(&exit);
2198 }
2199 Bind(¬Null);
2200 Branch(TaggedIsHole(*result), ¬SIndexObj, &exit);
2201 }
2202 Bind(¬FastTypeArray);
2203 {
2204 result = Hole();
2205 Jump(&exit);
2206 }
2207 }
2208 Bind(¬SIndexObj);
2209 {
2210 Label isDicMode(env);
2211 Label notDicMode(env);
2212 Branch(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
2213 Bind(¬DicMode);
2214 {
2215 GateRef layOutInfo = GetLayoutFromHClass(hclass);
2216 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
2217 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
2218 GateRef entryA = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
2219 Label hasEntry(env);
2220 Label noEntry(env);
2221 // if branch condition : entry != -1
2222 Branch(Int32NotEqual(entryA, Int32(-1)), &hasEntry, &noEntry);
2223 Bind(&hasEntry);
2224 {
2225 // PropertyAttributes attr(layoutInfo->GetAttr(entry))
2226 GateRef propAttr = GetPropAttrFromLayoutInfo(layOutInfo, entryA);
2227 GateRef attr = GetInt32OfTInt(propAttr);
2228 GateRef value = JSObjectGetProperty(*holder, hclass, attr);
2229 Label isPropertyBox(env);
2230 Label notPropertyBox(env);
2231 Branch(TaggedIsPropertyBox(value), &isPropertyBox, ¬PropertyBox);
2232 Bind(&isPropertyBox);
2233 {
2234 result = GetValueFromPropertyBox(value);
2235 Jump(&exit);
2236 }
2237 Bind(¬PropertyBox);
2238 Label isAccessor(env);
2239 Label notAccessor(env);
2240 Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
2241 Bind(&isAccessor);
2242 {
2243 result = CallGetterHelper(glue, receiver, *holder, value);
2244 Jump(&exit);
2245 }
2246 Bind(¬Accessor);
2247 {
2248 Label notHole(env);
2249 Branch(TaggedIsHole(value), &noEntry, ¬Hole);
2250 Bind(¬Hole);
2251 {
2252 result = value;
2253 Jump(&exit);
2254 }
2255 }
2256 }
2257 Bind(&noEntry);
2258 {
2259 Jump(&loopExit);
2260 }
2261 }
2262 Bind(&isDicMode);
2263 {
2264 GateRef array = GetPropertiesArray(*holder);
2265 // int entry = dict->FindEntry(key)
2266 GateRef entryB = FindEntryFromNameDictionary(glue, array, key);
2267 Label notNegtiveOne(env);
2268 Label negtiveOne(env);
2269 // if branch condition : entry != -1
2270 Branch(Int32NotEqual(entryB, Int32(-1)), ¬NegtiveOne, &negtiveOne);
2271 Bind(¬NegtiveOne);
2272 {
2273 // auto value = dict->GetValue(entry)
2274 GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, entryB);
2275 // auto attr = dict->GetAttributes(entry)
2276 GateRef value = GetValueFromDictionary<NameDictionary>(array, entryB);
2277 Label isAccessor1(env);
2278 Label notAccessor1(env);
2279 Branch(IsAccessor(attr), &isAccessor1, ¬Accessor1);
2280 Bind(&isAccessor1);
2281 {
2282 result = CallGetterHelper(glue, receiver, *holder, value);
2283 Jump(&exit);
2284 }
2285 Bind(¬Accessor1);
2286 {
2287 result = value;
2288 Jump(&exit);
2289 }
2290 }
2291 Bind(&negtiveOne);
2292 Jump(&loopExit);
2293 }
2294 Bind(&loopExit);
2295 {
2296 holder = GetPrototypeFromHClass(LoadHClass(*holder));
2297 Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
2298 }
2299 }
2300 Bind(&loopEnd);
2301 LoopEnd(&loopHead);
2302 Bind(&afterLoop);
2303 {
2304 result = Undefined();
2305 Jump(&exit);
2306 }
2307 }
2308 Bind(&exit);
2309 auto ret = *result;
2310 env->SubCfgExit();
2311 return ret;
2312 }
2313
CopyAllHClass(GateRef glue,GateRef dstHClass,GateRef srcHClass)2314 void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHClass)
2315 {
2316 auto env = GetEnvironment();
2317 Label entry(env);
2318 env->SubCfgEntry(&entry);
2319 auto proto = GetPrototypeFromHClass(srcHClass);
2320 SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto);
2321 SetBitFieldToHClass(glue, dstHClass, GetBitFieldFromHClass(srcHClass));
2322 SetNumberOfPropsToHClass(glue, dstHClass, GetNumberOfPropsFromHClass(srcHClass));
2323 SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, Undefined());
2324 SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, dstHClass, Null());
2325 SetEnumCacheToHClass(VariableType::INT64(), glue, dstHClass, Null());
2326 SetLayoutToHClass(VariableType::JS_POINTER(), glue, dstHClass, GetLayoutFromHClass(srcHClass));
2327 env->SubCfgExit();
2328 return;
2329 }
2330
FindTransitions(GateRef glue,GateRef receiver,GateRef hclass,GateRef key,GateRef metaData)2331 GateRef StubBuilder::FindTransitions(GateRef glue, GateRef receiver, GateRef hclass, GateRef key, GateRef metaData)
2332 {
2333 auto env = GetEnvironment();
2334 Label entry(env);
2335 env->SubCfgEntry(&entry);
2336 Label exit(env);
2337 GateRef transitionOffset = IntPtr(JSHClass::TRANSTIONS_OFFSET);
2338 GateRef transition = Load(VariableType::JS_POINTER(), hclass, transitionOffset);
2339 DEFVARIABLE(result, VariableType::JS_ANY(), transition);
2340
2341 Label notUndefined(env);
2342 Branch(Equal(transition, Undefined()), &exit, ¬Undefined);
2343 Bind(¬Undefined);
2344 {
2345 Label isWeak(env);
2346 Label notWeak(env);
2347 Branch(TaggedIsWeak(transition), &isWeak, ¬Weak);
2348 Bind(&isWeak);
2349 {
2350 GateRef transitionHClass = LoadObjectFromWeakRef(transition);
2351 GateRef propNums = GetNumberOfPropsFromHClass(transitionHClass);
2352 GateRef last = Int32Sub(propNums, Int32(1));
2353 GateRef layoutInfo = GetLayoutFromHClass(transitionHClass);
2354 GateRef cachedKey = GetKeyFromLayoutInfo(layoutInfo, last);
2355 GateRef cachedAttr = GetInt32OfTInt(GetPropAttrFromLayoutInfo(layoutInfo, last));
2356 GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
2357 Label keyMatch(env);
2358 Label isMatch(env);
2359 Label notMatch(env);
2360 Branch(Equal(cachedKey, key), &keyMatch, ¬Match);
2361 Bind(&keyMatch);
2362 {
2363 Branch(Int32Equal(metaData, cachedMetaData), &isMatch, ¬Match);
2364 Bind(&isMatch);
2365 {
2366 #if ECMASCRIPT_ENABLE_IC
2367 NotifyHClassChanged(glue, hclass, transitionHClass);
2368 #endif
2369 StoreHClass(glue, receiver, transitionHClass);
2370 Jump(&exit);
2371 }
2372 }
2373 Bind(¬Match);
2374 {
2375 result = Undefined();
2376 Jump(&exit);
2377 }
2378 }
2379 Bind(¬Weak);
2380 {
2381 // need to find from dictionary
2382 GateRef entryA = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
2383 Label isFound(env);
2384 Label notFound(env);
2385 Branch(Int32NotEqual(entryA, Int32(-1)), &isFound, ¬Found);
2386 Bind(&isFound);
2387 auto value = GetValueFromDictionary<TransitionsDictionary>(transition, entryA);
2388 Label valueUndefined(env);
2389 Label valueNotUndefined(env);
2390 Branch(Int64NotEqual(value, Undefined()), &valueNotUndefined,
2391 &valueUndefined);
2392 Bind(&valueNotUndefined);
2393 {
2394 GateRef newHClass = LoadObjectFromWeakRef(value);
2395 result = newHClass;
2396 #if ECMASCRIPT_ENABLE_IC
2397 NotifyHClassChanged(glue, hclass, newHClass);
2398 #endif
2399 StoreHClass(glue, receiver, newHClass);
2400 Jump(&exit);
2401 Bind(¬Found);
2402 result = Undefined();
2403 Jump(&exit);
2404 }
2405 Bind(&valueUndefined);
2406 {
2407 result = Undefined();
2408 Jump(&exit);
2409 }
2410 }
2411 }
2412 Bind(&exit);
2413 auto ret = *result;
2414 env->SubCfgExit();
2415 return ret;
2416 }
2417
SetPropertyByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value,bool useOwn)2418 GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn)
2419 {
2420 auto env = GetEnvironment();
2421 Label entry(env);
2422 env->SubCfgEntry(&entry);
2423 DEFVARIABLE(returnValue, VariableType::JS_ANY(), Hole());
2424 DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
2425 Label exit(env);
2426 Label ifEnd(env);
2427 Label loopHead(env);
2428 Label loopEnd(env);
2429 Label loopExit(env);
2430 Label afterLoop(env);
2431 Label isJsCOWArray(env);
2432 Label isNotJsCOWArray(env);
2433 Label setElementsArray(env);
2434 if (!useOwn) {
2435 Jump(&loopHead);
2436 LoopBegin(&loopHead);
2437 }
2438 GateRef hclass = LoadHClass(*holder);
2439 GateRef jsType = GetObjectType(hclass);
2440 Label isSpecialIndex(env);
2441 Label notSpecialIndex(env);
2442 Branch(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
2443 Bind(&isSpecialIndex);
2444 {
2445 // TypeArray
2446 Label isFastTypeArray(env);
2447 Label notFastTypeArray(env);
2448 Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
2449 Bind(&isFastTypeArray);
2450 {
2451 returnValue = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
2452 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
2453 Jump(&exit);
2454 }
2455 Bind(¬FastTypeArray);
2456 returnValue = Hole();
2457 Jump(&exit);
2458 }
2459 Bind(¬SpecialIndex);
2460 {
2461 GateRef elements = GetElementsArray(*holder);
2462 Label isDictionaryElement(env);
2463 Label notDictionaryElement(env);
2464 Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
2465 Bind(¬DictionaryElement);
2466 {
2467 Label isReceiver(env);
2468 if (useOwn) {
2469 Branch(Equal(*holder, receiver), &isReceiver, &ifEnd);
2470 } else {
2471 Branch(Equal(*holder, receiver), &isReceiver, &afterLoop);
2472 }
2473 Bind(&isReceiver);
2474 {
2475 GateRef length = GetLengthOfTaggedArray(elements);
2476 Label inRange(env);
2477 if (useOwn) {
2478 Branch(Int64LessThan(index, length), &inRange, &ifEnd);
2479 } else {
2480 Branch(Int64LessThan(index, length), &inRange, &loopExit);
2481 }
2482 Bind(&inRange);
2483 {
2484 GateRef value1 = GetValueFromTaggedArray(elements, index);
2485 Label notHole(env);
2486 if (useOwn) {
2487 Branch(Int64NotEqual(value1, Hole()), ¬Hole, &ifEnd);
2488 } else {
2489 Branch(Int64NotEqual(value1, Hole()), ¬Hole, &loopExit);
2490 }
2491 Bind(¬Hole);
2492 {
2493 Branch(IsJsCOWArray(*holder), &isJsCOWArray, &isNotJsCOWArray);
2494 Bind(&isJsCOWArray);
2495 {
2496 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), {*holder});
2497 GateRef newElements = GetElementsArray(*holder);
2498 SetValueToTaggedArray(VariableType::JS_ANY(), glue, newElements, index, value);
2499 returnValue = Undefined();
2500 Jump(&exit);
2501 }
2502 Bind(&isNotJsCOWArray);
2503 {
2504 Jump(&setElementsArray);
2505 }
2506 Bind(&setElementsArray);
2507 {
2508 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, value);
2509 returnValue = Undefined();
2510 Jump(&exit);
2511 }
2512 }
2513 }
2514 }
2515 }
2516 Bind(&isDictionaryElement);
2517 {
2518 returnValue = Hole();
2519 Jump(&exit);
2520 }
2521 }
2522 if (useOwn) {
2523 Bind(&ifEnd);
2524 } else {
2525 Bind(&loopExit);
2526 {
2527 holder = GetPrototypeFromHClass(LoadHClass(*holder));
2528 Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
2529 }
2530 Bind(&loopEnd);
2531 LoopEnd(&loopHead);
2532 Bind(&afterLoop);
2533 }
2534 Label isExtensible(env);
2535 Label notExtensible(env);
2536 Branch(IsExtensible(receiver), &isExtensible, ¬Extensible);
2537 Bind(&isExtensible);
2538 {
2539 GateRef result = CallRuntime(glue, RTSTUB_ID(AddElementInternal),
2540 { receiver, IntToTaggedInt(index), value,
2541 IntToTaggedInt(Int32(PropertyAttributes::GetDefaultAttributes())) });
2542 Label success(env);
2543 Label failed(env);
2544 Branch(TaggedIsTrue(result), &success, &failed);
2545 Bind(&success);
2546 {
2547 returnValue = Undefined();
2548 Jump(&exit);
2549 }
2550 Bind(&failed);
2551 {
2552 returnValue = Exception();
2553 Jump(&exit);
2554 }
2555 }
2556 Bind(¬Extensible);
2557 {
2558 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
2559 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2560 returnValue = Exception();
2561 Jump(&exit);
2562 }
2563 Bind(&exit);
2564 auto ret = *returnValue;
2565 env->SubCfgExit();
2566 return ret;
2567 }
2568
SetPropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn)2569 GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn)
2570 {
2571 auto env = GetEnvironment();
2572 Label entryPass(env);
2573 env->SubCfgEntry(&entryPass);
2574 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2575 DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
2576 DEFVARIABLE(receiverHoleEntry, VariableType::INT32(), Int32(-1));
2577 Label exit(env);
2578 Label ifEnd(env);
2579 Label loopHead(env);
2580 Label loopEnd(env);
2581 Label loopExit(env);
2582 Label afterLoop(env);
2583 if (!useOwn) {
2584 // a do-while loop
2585 Jump(&loopHead);
2586 LoopBegin(&loopHead);
2587 }
2588 // auto *hclass = holder.GetTaggedObject()->GetClass()
2589 // JSType jsType = hclass->GetObjectType()
2590 GateRef hclass = LoadHClass(*holder);
2591 GateRef jsType = GetObjectType(hclass);
2592 Label isSIndexObj(env);
2593 Label notSIndexObj(env);
2594 // if branch condition : IsSpecialIndexedObj(jsType)
2595 Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
2596 Bind(&isSIndexObj);
2597 {
2598 Label isFastTypeArray(env);
2599 Label notFastTypeArray(env);
2600 Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
2601 Bind(&isFastTypeArray);
2602 {
2603 result = SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType);
2604 Label isNull(env);
2605 Label notNull(env);
2606 Branch(TaggedIsNull(*result), &isNull, ¬Null);
2607 Bind(&isNull);
2608 {
2609 result = Hole();
2610 Jump(&exit);
2611 }
2612 Bind(¬Null);
2613 Branch(TaggedIsHole(*result), ¬SIndexObj, &exit);
2614 }
2615 Bind(¬FastTypeArray);
2616
2617 Label isSpecialContainer(env);
2618 Label notSpecialContainer(env);
2619 // Add SpecialContainer
2620 Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
2621 Bind(&isSpecialContainer);
2622 {
2623 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
2624 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2625 result = Exception();
2626 Jump(&exit);
2627 }
2628 Bind(¬SpecialContainer);
2629 {
2630 result = Hole();
2631 Jump(&exit);
2632 }
2633 }
2634 Bind(¬SIndexObj);
2635 {
2636 Label isDicMode(env);
2637 Label notDicMode(env);
2638 // if branch condition : LIKELY(!hclass->IsDictionaryMode())
2639 Branch(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
2640 Bind(¬DicMode);
2641 {
2642 // LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetAttributes().GetTaggedObject())
2643 GateRef layOutInfo = GetLayoutFromHClass(hclass);
2644 // int propsNumber = hclass->NumberOfPropsFromHClass()
2645 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
2646 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
2647 GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
2648 Label hasEntry(env);
2649 // if branch condition : entry != -1
2650 if (useOwn) {
2651 Branch(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
2652 } else {
2653 Branch(Int32NotEqual(entry, Int32(-1)), &hasEntry, &loopExit);
2654 }
2655 Bind(&hasEntry);
2656 {
2657 // PropertyAttributes attr(layoutInfo->GetAttr(entry))
2658 GateRef propAttr = GetPropAttrFromLayoutInfo(layOutInfo, entry);
2659 GateRef attr = GetInt32OfTInt(propAttr);
2660 Label isAccessor(env);
2661 Label notAccessor(env);
2662 Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
2663 Bind(&isAccessor);
2664 {
2665 // auto accessor = JSObject::Cast(holder)->GetProperty(hclass, attr)
2666 GateRef accessor = JSObjectGetProperty(*holder, hclass, attr);
2667 Label shouldCall(env);
2668 // ShouldCallSetter(receiver, *holder, accessor, attr)
2669 Branch(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
2670 Bind(&shouldCall);
2671 {
2672 result = CallSetterHelper(glue, receiver, accessor, value);
2673 Jump(&exit);
2674 }
2675 }
2676 Bind(¬Accessor);
2677 {
2678 Label writable(env);
2679 Label notWritable(env);
2680 Branch(IsWritable(attr), &writable, ¬Writable);
2681 Bind(¬Writable);
2682 {
2683 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
2684 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2685 result = Exception();
2686 Jump(&exit);
2687 }
2688 Bind(&writable);
2689 {
2690 Label isTS(env);
2691 Label notTS(env);
2692 Branch(IsTSHClass(hclass), &isTS, ¬TS);
2693 Bind(&isTS);
2694 {
2695 GateRef attrVal = JSObjectGetProperty(*holder, hclass, attr);
2696 Label attrValIsHole(env);
2697 Branch(TaggedIsHole(attrVal), &attrValIsHole, ¬TS);
2698 Bind(&attrValIsHole);
2699 {
2700 Label storeReceiverHoleEntry(env);
2701 Label noNeedStore(env);
2702 GateRef checkReceiverHoleEntry = Int32Equal(*receiverHoleEntry, Int32(-1));
2703 GateRef checkHolderEqualsRecv = Equal(*holder, receiver);
2704 Branch(BoolAnd(checkReceiverHoleEntry, checkHolderEqualsRecv),
2705 &storeReceiverHoleEntry, &noNeedStore);
2706 Bind(&storeReceiverHoleEntry);
2707 {
2708 receiverHoleEntry = entry;
2709 Jump(&noNeedStore);
2710 }
2711 Bind(&noNeedStore);
2712 if (useOwn) {
2713 Jump(&ifEnd);
2714 } else {
2715 Jump(&loopExit);
2716 }
2717 }
2718 }
2719 Bind(¬TS);
2720 Label holdEqualsRecv(env);
2721 if (useOwn) {
2722 Branch(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
2723 } else {
2724 Branch(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
2725 }
2726 Bind(&holdEqualsRecv);
2727 {
2728 // JSObject::Cast(holder)->SetProperty(thread, hclass, attr, value)
2729 // return JSTaggedValue::Undefined()
2730 JSObjectSetProperty(glue, *holder, hclass, attr, value);
2731 result = Undefined();
2732 Jump(&exit);
2733 }
2734 }
2735 }
2736 }
2737 }
2738 Bind(&isDicMode);
2739 {
2740 GateRef array = GetPropertiesArray(*holder);
2741 // int entry = dict->FindEntry(key)
2742 GateRef entry1 = FindEntryFromNameDictionary(glue, array, key);
2743 Label notNegtiveOne(env);
2744 // if branch condition : entry != -1
2745 if (useOwn) {
2746 Branch(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &ifEnd);
2747 } else {
2748 Branch(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &loopExit);
2749 }
2750 Bind(¬NegtiveOne);
2751 {
2752 // auto attr = dict->GetAttributes(entry)
2753 GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(array, entry1);
2754 Label isAccessor1(env);
2755 Label notAccessor1(env);
2756 // if branch condition : UNLIKELY(attr.IsAccessor())
2757 Branch(IsAccessor(attr1), &isAccessor1, ¬Accessor1);
2758 Bind(&isAccessor1);
2759 {
2760 // auto accessor = dict->GetValue(entry)
2761 GateRef accessor1 = GetValueFromDictionary<NameDictionary>(array, entry1);
2762 Label shouldCall1(env);
2763 Branch(ShouldCallSetter(receiver, *holder, accessor1, attr1), &shouldCall1, ¬Accessor1);
2764 Bind(&shouldCall1);
2765 {
2766 result = CallSetterHelper(glue, receiver, accessor1, value);
2767 Jump(&exit);
2768 }
2769 }
2770 Bind(¬Accessor1);
2771 {
2772 Label writable1(env);
2773 Label notWritable1(env);
2774 Branch(IsWritable(attr1), &writable1, ¬Writable1);
2775 Bind(¬Writable1);
2776 {
2777 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
2778 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2779 result = Exception();
2780 Jump(&exit);
2781 }
2782 Bind(&writable1);
2783 {
2784 Label holdEqualsRecv1(env);
2785 if (useOwn) {
2786 Branch(Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
2787 } else {
2788 Branch(Equal(*holder, receiver), &holdEqualsRecv1, &afterLoop);
2789 }
2790 Bind(&holdEqualsRecv1);
2791 {
2792 // dict->UpdateValue(thread, entry, value)
2793 // return JSTaggedValue::Undefined()
2794 UpdateValueInDict(glue, array, entry1, value);
2795 result = Undefined();
2796 Jump(&exit);
2797 }
2798 }
2799 }
2800 }
2801 }
2802 }
2803 if (useOwn) {
2804 Bind(&ifEnd);
2805 } else {
2806 Bind(&loopExit);
2807 {
2808 // holder = hclass->GetPrototype()
2809 holder = GetPrototypeFromHClass(LoadHClass(*holder));
2810 // loop condition for a do-while loop
2811 Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
2812 }
2813 Bind(&loopEnd);
2814 LoopEnd(&loopHead);
2815 Bind(&afterLoop);
2816 }
2817
2818 Label holeEntryNotNegtiveOne(env);
2819 Label holeEntryIfEnd(env);
2820 Branch(Int32NotEqual(*receiverHoleEntry, Int32(-1)), &holeEntryNotNegtiveOne, &holeEntryIfEnd);
2821 Bind(&holeEntryNotNegtiveOne);
2822 {
2823 GateRef receiverHClass = LoadHClass(receiver);
2824 GateRef receiverLayoutInfo = GetLayoutFromHClass(receiverHClass);
2825 GateRef holePropAttr = GetPropAttrFromLayoutInfo(receiverLayoutInfo, *receiverHoleEntry);
2826 GateRef holeAttr = GetInt32OfTInt(holePropAttr);
2827 JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, value);
2828 result = Undefined();
2829 Jump(&exit);
2830 }
2831 Bind(&holeEntryIfEnd);
2832
2833 Label extensible(env);
2834 Label inextensible(env);
2835 Branch(IsExtensible(receiver), &extensible, &inextensible);
2836 Bind(&inextensible);
2837 {
2838 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
2839 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2840 result = Exception();
2841 Jump(&exit);
2842 }
2843 Bind(&extensible);
2844 {
2845 result = AddPropertyByName(glue, receiver, key, value,
2846 Int32(PropertyAttributes::GetDefaultAttributes()));
2847 Jump(&exit);
2848 }
2849 Bind(&exit);
2850 auto ret = *result;
2851 env->SubCfgExit();
2852 return ret;
2853 }
2854
SetPropertyByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,bool useOwn)2855 GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn)
2856 {
2857 auto env = GetEnvironment();
2858 Label subEntry1(env);
2859 env->SubCfgEntry(&subEntry1);
2860 DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
2861 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2862 Label isNumberOrStringSymbol(env);
2863 Label notNumber(env);
2864 Label isStringOrSymbol(env);
2865 Label notStringOrSymbol(env);
2866 Label exit(env);
2867 Branch(TaggedIsNumber(*varKey), &isNumberOrStringSymbol, ¬Number);
2868 Bind(¬Number);
2869 {
2870 Branch(TaggedIsStringOrSymbol(*varKey), &isNumberOrStringSymbol, ¬StringOrSymbol);
2871 Bind(¬StringOrSymbol);
2872 {
2873 result = Hole();
2874 Jump(&exit);
2875 }
2876 }
2877 Bind(&isNumberOrStringSymbol);
2878 {
2879 GateRef index = TryToElementsIndex(*varKey);
2880 Label validIndex(env);
2881 Label notValidIndex(env);
2882 Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
2883 Bind(&validIndex);
2884 {
2885 result = SetPropertyByIndex(glue, receiver, index, value, useOwn);
2886 Jump(&exit);
2887 }
2888 Bind(¬ValidIndex);
2889 {
2890 Label isNumber1(env);
2891 Label notNumber1(env);
2892 Label setByName(env);
2893 Branch(TaggedIsNumber(*varKey), &isNumber1, ¬Number1);
2894 Bind(&isNumber1);
2895 {
2896 result = Hole();
2897 Jump(&exit);
2898 }
2899 Bind(¬Number1);
2900 {
2901 Label isString(env);
2902 Label notIntenalString(env);
2903 Branch(TaggedIsString(*varKey), &isString, &setByName);
2904 Bind(&isString);
2905 {
2906 Branch(IsInternalString(*varKey), &setByName, ¬IntenalString);
2907 Bind(¬IntenalString);
2908 {
2909 varKey = CallRuntime(glue, RTSTUB_ID(NewInternalString), { *varKey });
2910 Jump(&setByName);
2911 }
2912 }
2913 }
2914 Bind(&setByName);
2915 {
2916 result = SetPropertyByName(glue, receiver, *varKey, value, useOwn);
2917 Jump(&exit);
2918 }
2919 }
2920 }
2921 Bind(&exit);
2922 auto ret = *result;
2923 env->SubCfgExit();
2924 return ret;
2925 }
2926
NotifyHClassChanged(GateRef glue,GateRef oldHClass,GateRef newHClass)2927 void StubBuilder::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef newHClass)
2928 {
2929 auto env = GetEnvironment();
2930 Label entry(env);
2931 env->SubCfgEntry(&entry);
2932 Label exit(env);
2933 Label isProtoType(env);
2934 Branch(IsProtoTypeHClass(oldHClass), &isProtoType, &exit);
2935 Bind(&isProtoType);
2936 {
2937 Label notEqualHClass(env);
2938 Branch(Equal(oldHClass, newHClass), &exit, ¬EqualHClass);
2939 Bind(¬EqualHClass);
2940 {
2941 SetIsProtoTypeToHClass(glue, newHClass, True());
2942 CallRuntime(glue, RTSTUB_ID(NoticeThroughChainAndRefreshUser), { oldHClass, newHClass });
2943 Jump(&exit);
2944 }
2945 }
2946 Bind(&exit);
2947 env->SubCfgExit();
2948 return;
2949 }
2950
GetContainerProperty(GateRef glue,GateRef receiver,GateRef index,GateRef jsType)2951 GateRef StubBuilder::GetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef jsType)
2952 {
2953 auto env = GetEnvironment();
2954 Label entry(env);
2955 env->SubCfgEntry(&entry);
2956 Label exit(env);
2957 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
2958
2959 Label isDefaultLabel(env);
2960 Label noDefaultLabel(env);
2961 Branch(IsSpecialContainer(jsType), &noDefaultLabel, &isDefaultLabel);
2962 Bind(&noDefaultLabel);
2963 {
2964 result = JSAPIContainerGet(glue, receiver, index);
2965 Jump(&exit);
2966 }
2967 Bind(&isDefaultLabel);
2968 {
2969 Jump(&exit);
2970 }
2971 Bind(&exit);
2972
2973 auto ret = *result;
2974 env->SubCfgExit();
2975 return ret;
2976 }
2977
FastTypeOf(GateRef glue,GateRef obj)2978 GateRef StubBuilder::FastTypeOf(GateRef glue, GateRef obj)
2979 {
2980 auto env = GetEnvironment();
2981 Label entry(env);
2982 env->SubCfgEntry(&entry);
2983 Label exit(env);
2984
2985 GateRef gConstAddr = PtrAdd(glue,
2986 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit())));
2987 GateRef undefinedIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX);
2988 GateRef gConstUndefinedStr = Load(VariableType::JS_POINTER(), gConstAddr, undefinedIndex);
2989 DEFVARIABLE(result, VariableType::JS_POINTER(), gConstUndefinedStr);
2990 Label objIsTrue(env);
2991 Label objNotTrue(env);
2992 Label defaultLabel(env);
2993 GateRef gConstBooleanStr = Load(VariableType::JS_POINTER(), gConstAddr,
2994 GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX));
2995 Branch(TaggedIsTrue(obj), &objIsTrue, &objNotTrue);
2996 Bind(&objIsTrue);
2997 {
2998 result = gConstBooleanStr;
2999 Jump(&exit);
3000 }
3001 Bind(&objNotTrue);
3002 {
3003 Label objIsFalse(env);
3004 Label objNotFalse(env);
3005 Branch(TaggedIsFalse(obj), &objIsFalse, &objNotFalse);
3006 Bind(&objIsFalse);
3007 {
3008 result = gConstBooleanStr;
3009 Jump(&exit);
3010 }
3011 Bind(&objNotFalse);
3012 {
3013 Label objIsNull(env);
3014 Label objNotNull(env);
3015 Branch(TaggedIsNull(obj), &objIsNull, &objNotNull);
3016 Bind(&objIsNull);
3017 {
3018 result = Load(VariableType::JS_POINTER(), gConstAddr,
3019 GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
3020 Jump(&exit);
3021 }
3022 Bind(&objNotNull);
3023 {
3024 Label objIsUndefined(env);
3025 Label objNotUndefined(env);
3026 Branch(TaggedIsUndefined(obj), &objIsUndefined, &objNotUndefined);
3027 Bind(&objIsUndefined);
3028 {
3029 result = Load(VariableType::JS_POINTER(), gConstAddr,
3030 GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX));
3031 Jump(&exit);
3032 }
3033 Bind(&objNotUndefined);
3034 Jump(&defaultLabel);
3035 }
3036 }
3037 }
3038 Bind(&defaultLabel);
3039 {
3040 Label objIsHeapObject(env);
3041 Label objNotHeapObject(env);
3042 Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
3043 Bind(&objIsHeapObject);
3044 {
3045 Label objIsString(env);
3046 Label objNotString(env);
3047 Branch(IsString(obj), &objIsString, &objNotString);
3048 Bind(&objIsString);
3049 {
3050 result = Load(VariableType::JS_POINTER(), gConstAddr,
3051 GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX));
3052 Jump(&exit);
3053 }
3054 Bind(&objNotString);
3055 {
3056 Label objIsSymbol(env);
3057 Label objNotSymbol(env);
3058 Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol);
3059 Bind(&objIsSymbol);
3060 {
3061 result = Load(VariableType::JS_POINTER(), gConstAddr,
3062 GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX));
3063 Jump(&exit);
3064 }
3065 Bind(&objNotSymbol);
3066 {
3067 Label objIsCallable(env);
3068 Label objNotCallable(env);
3069 Branch(IsCallable(obj), &objIsCallable, &objNotCallable);
3070 Bind(&objIsCallable);
3071 {
3072 result = Load(VariableType::JS_POINTER(), gConstAddr,
3073 GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX));
3074 Jump(&exit);
3075 }
3076 Bind(&objNotCallable);
3077 {
3078 Label objIsBigInt(env);
3079 Label objNotBigInt(env);
3080 Branch(TaggedObjectIsBigInt(obj), &objIsBigInt, &objNotBigInt);
3081 Bind(&objIsBigInt);
3082 {
3083 result = Load(VariableType::JS_POINTER(), gConstAddr,
3084 GetGlobalConstantString(ConstantIndex::BIGINT_STRING_INDEX));
3085 Jump(&exit);
3086 }
3087 Bind(&objNotBigInt);
3088 {
3089 result = Load(VariableType::JS_POINTER(), gConstAddr,
3090 GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
3091 Jump(&exit);
3092 }
3093 }
3094 }
3095 }
3096 }
3097 Bind(&objNotHeapObject);
3098 {
3099 Label objIsNum(env);
3100 Label objNotNum(env);
3101 Branch(TaggedIsNumber(obj), &objIsNum, &objNotNum);
3102 Bind(&objIsNum);
3103 {
3104 result = Load(VariableType::JS_POINTER(), gConstAddr,
3105 GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX));
3106 Jump(&exit);
3107 }
3108 Bind(&objNotNum);
3109 Jump(&exit);
3110 }
3111 }
3112 Bind(&exit);
3113 auto ret = *result;
3114 env->SubCfgExit();
3115 return ret;
3116 }
3117
InstanceOf(GateRef glue,GateRef object,GateRef target)3118 GateRef StubBuilder::InstanceOf(GateRef glue, GateRef object, GateRef target)
3119 {
3120 auto env = GetEnvironment();
3121 Label entry(env);
3122 env->SubCfgEntry(&entry);
3123 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3124 Label exit(env);
3125
3126 // 1.If Type(target) is not Object, throw a TypeError exception.
3127 Label targetIsHeapObject(env);
3128 Label targetIsEcmaObject(env);
3129 Label targetNotEcmaObject(env);
3130 Branch(TaggedIsHeapObject(target), &targetIsHeapObject, &targetNotEcmaObject);
3131 Bind(&targetIsHeapObject);
3132 Branch(TaggedObjectIsEcmaObject(target), &targetIsEcmaObject, &targetNotEcmaObject);
3133 Bind(&targetNotEcmaObject);
3134 {
3135 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
3136 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
3137 result = Exception();
3138 Jump(&exit);
3139 }
3140 Bind(&targetIsEcmaObject);
3141 {
3142 // 2.Let instOfHandler be GetMethod(target, @@hasInstance).
3143 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
3144 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
3145 GateRef hasInstanceSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
3146 GlobalEnv::HASINSTANCE_SYMBOL_INDEX);
3147 GateRef instof = GetMethod(glue, target, hasInstanceSymbol);
3148
3149 // 3.ReturnIfAbrupt(instOfHandler).
3150 Label isPendingException1(env);
3151 Label noPendingException1(env);
3152 Branch(HasPendingException(glue), &isPendingException1, &noPendingException1);
3153 Bind(&isPendingException1);
3154 {
3155 result = Exception();
3156 Jump(&exit);
3157 }
3158 Bind(&noPendingException1);
3159
3160 // 4.If instOfHandler is not undefined, then
3161 Label instOfNotUndefined(env);
3162 Label instOfIsUndefined(env);
3163 Branch(TaggedIsUndefined(instof), &instOfIsUndefined, &instOfNotUndefined);
3164 Bind(&instOfNotUndefined);
3165 {
3166 GateRef retValue = JSCallDispatch(glue, instof, Int32(1), 0, Circuit::NullGate(),
3167 JSCallMode::CALL_SETTER, { target, object });
3168 result = FastToBoolean(retValue);
3169 Jump(&exit);
3170 }
3171 Bind(&instOfIsUndefined);
3172 {
3173 // 5.If IsCallable(target) is false, throw a TypeError exception.
3174 Label targetIsCallable1(env);
3175 Label targetNotCallable1(env);
3176 Branch(IsCallable(target), &targetIsCallable1, &targetNotCallable1);
3177 Bind(&targetNotCallable1);
3178 {
3179 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
3180 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
3181 result = Exception();
3182 Jump(&exit);
3183 }
3184 Bind(&targetIsCallable1);
3185 {
3186 // 6.Return ? OrdinaryHasInstance(target, object).
3187 result = OrdinaryHasInstance(glue, target, object);
3188 Jump(&exit);
3189 }
3190 }
3191 }
3192 Bind(&exit);
3193 auto ret = *result;
3194 env->SubCfgExit();
3195 return ret;
3196 }
3197
GetMethod(GateRef glue,GateRef obj,GateRef key)3198 GateRef StubBuilder::GetMethod(GateRef glue, GateRef obj, GateRef key)
3199 {
3200 auto env = GetEnvironment();
3201 Label entry(env);
3202 env->SubCfgEntry(&entry);
3203 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3204 Label exit(env);
3205
3206 GateRef value = FastGetPropertyByName(glue, obj, key);
3207
3208 Label isPendingException2(env);
3209 Label noPendingException2(env);
3210 Branch(HasPendingException(glue), &isPendingException2, &noPendingException2);
3211 Bind(&isPendingException2);
3212 {
3213 result = Exception();
3214 Jump(&exit);
3215 }
3216 Bind(&noPendingException2);
3217 Label valueIsUndefinedOrNull(env);
3218 Label valueNotUndefinedOrNull(env);
3219 Branch(TaggedIsUndefinedOrNull(value), &valueIsUndefinedOrNull, &valueNotUndefinedOrNull);
3220 Bind(&valueIsUndefinedOrNull);
3221 {
3222 result = Undefined();
3223 Jump(&exit);
3224 }
3225 Bind(&valueNotUndefinedOrNull);
3226 {
3227 Label valueIsCallable(env);
3228 Label valueNotCallable(env);
3229 Branch(IsCallable(value), &valueIsCallable, &valueNotCallable);
3230 Bind(&valueNotCallable);
3231 {
3232 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(NonCallable));
3233 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
3234 result = Exception();
3235 Jump(&exit);
3236 }
3237 Bind(&valueIsCallable);
3238 {
3239 result = value;
3240 Jump(&exit);
3241 }
3242 }
3243 Bind(&exit);
3244 auto ret = *result;
3245 env->SubCfgExit();
3246 return ret;
3247 }
3248
FastGetPropertyByName(GateRef glue,GateRef obj,GateRef key)3249 GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key)
3250 {
3251 auto env = GetEnvironment();
3252 Label entry(env);
3253 env->SubCfgEntry(&entry);
3254 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3255 Label exit(env);
3256 Label checkResult(env);
3257 Label fastpath(env);
3258 Label slowpath(env);
3259
3260 Branch(TaggedIsHeapObject(obj), &fastpath, &slowpath);
3261 Bind(&fastpath);
3262 {
3263 result = GetPropertyByName(glue, obj, key);
3264 Branch(TaggedIsHole(*result), &slowpath, &exit);
3265 }
3266 Bind(&slowpath);
3267 {
3268 result = CallRuntime(glue, RTSTUB_ID(LoadICByName),
3269 { Undefined(), obj, key, Int64ToTaggedPtr(Int32(0)) });
3270 Jump(&exit);
3271 }
3272 Bind(&exit);
3273 auto ret = *result;
3274 env->SubCfgExit();
3275 return ret;
3276 }
3277
OrdinaryHasInstance(GateRef glue,GateRef target,GateRef obj)3278 GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj)
3279 {
3280 auto env = GetEnvironment();
3281 Label entry(env);
3282 env->SubCfgEntry(&entry);
3283 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3284 Label exit(env);
3285 DEFVARIABLE(object, VariableType::JS_ANY(), obj);
3286
3287 // 1. If IsCallable(C) is false, return false.
3288 Label targetIsCallable2(env);
3289 Label targetNotCallable2(env);
3290 Branch(IsCallable(target), &targetIsCallable2, &targetNotCallable2);
3291 Bind(&targetNotCallable2);
3292 {
3293 result = TaggedFalse();
3294 Jump(&exit);
3295 }
3296 Bind(&targetIsCallable2);
3297 {
3298 // 2. If C has a [[BoundTargetFunction]] internal slot, then
3299 // a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
3300 // b. Return InstanceofOperator(O,BC) (see 12.9.4).
3301 Label targetIsBoundFunction(env);
3302 Label targetNotBoundFunction(env);
3303 Branch(IsBoundFunction(target), &targetIsBoundFunction, &targetNotBoundFunction);
3304 Bind(&targetIsBoundFunction);
3305 {
3306 GateRef boundTarget = Load(VariableType::JS_ANY(), target, IntPtr(JSBoundFunction::BOUND_TARGET_OFFSET));
3307 result = CallRuntime(glue, RTSTUB_ID(InstanceOf), { obj, boundTarget });
3308 Jump(&exit);
3309 }
3310 Bind(&targetNotBoundFunction);
3311 {
3312 // 3. If Type(O) is not Object, return false
3313 Label objIsHeapObject(env);
3314 Label objIsEcmaObject(env);
3315 Label objNotEcmaObject(env);
3316 Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotEcmaObject);
3317 Bind(&objIsHeapObject);
3318 Branch(TaggedObjectIsEcmaObject(obj), &objIsEcmaObject, &objNotEcmaObject);
3319 Bind(&objNotEcmaObject);
3320 {
3321 result = TaggedFalse();
3322 Jump(&exit);
3323 }
3324 Bind(&objIsEcmaObject);
3325 {
3326 // 4. Let P be Get(C, "prototype").
3327 auto prototypeString = GetGlobalConstantValue(
3328 VariableType::JS_POINTER(), glue, ConstantIndex::PROTOTYPE_STRING_INDEX);
3329
3330 GateRef constructorPrototype = FastGetPropertyByName(glue, target, prototypeString);
3331
3332 // 5. ReturnIfAbrupt(P).
3333 // no throw exception, so needn't return
3334 Label isPendingException3(env);
3335 Label noPendingException3(env);
3336 Branch(HasPendingException(glue), &isPendingException3, &noPendingException3);
3337 Bind(&isPendingException3);
3338 {
3339 result = Exception();
3340 Jump(&exit);
3341 }
3342 Bind(&noPendingException3);
3343
3344 // 6. If Type(P) is not Object, throw a TypeError exception.
3345 Label constructorPrototypeIsHeapObject(env);
3346 Label constructorPrototypeIsEcmaObject(env);
3347 Label constructorPrototypeNotEcmaObject(env);
3348 Branch(TaggedIsHeapObject(constructorPrototype), &constructorPrototypeIsHeapObject,
3349 &constructorPrototypeNotEcmaObject);
3350 Bind(&constructorPrototypeIsHeapObject);
3351 Branch(TaggedObjectIsEcmaObject(constructorPrototype), &constructorPrototypeIsEcmaObject,
3352 &constructorPrototypeNotEcmaObject);
3353 Bind(&constructorPrototypeNotEcmaObject);
3354 {
3355 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
3356 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
3357 result = Exception();
3358 Jump(&exit);
3359 }
3360 Bind(&constructorPrototypeIsEcmaObject);
3361 {
3362 // 7. Repeat
3363 // a.Let O be O.[[GetPrototypeOf]]().
3364 // b.ReturnIfAbrupt(O).
3365 // c.If O is null, return false.
3366 // d.If SameValue(P, O) is true, return true.
3367 Label loopHead(env);
3368 Label loopEnd(env);
3369 Label afterLoop(env);
3370 Label strictEqual1(env);
3371 Label notStrictEqual1(env);
3372 Label shouldReturn(env);
3373 Label shouldContinue(env);
3374
3375 Branch(TaggedIsNull(*object), &afterLoop, &loopHead);
3376 LoopBegin(&loopHead);
3377 {
3378 GateRef isEqual = SameValue(glue, *object, constructorPrototype);
3379
3380 Branch(isEqual, &strictEqual1, ¬StrictEqual1);
3381 Bind(&strictEqual1);
3382 {
3383 result = TaggedTrue();
3384 Jump(&exit);
3385 }
3386 Bind(¬StrictEqual1);
3387 {
3388 object = GetPrototype(glue, *object);
3389
3390 Branch(HasPendingException(glue), &shouldReturn, &shouldContinue);
3391 Bind(&shouldReturn);
3392 {
3393 result = Exception();
3394 Jump(&exit);
3395 }
3396 }
3397 Bind(&shouldContinue);
3398 Branch(TaggedIsNull(*object), &afterLoop, &loopEnd);
3399 }
3400 Bind(&loopEnd);
3401 LoopEnd(&loopHead);
3402 Bind(&afterLoop);
3403 {
3404 result = TaggedFalse();
3405 Jump(&exit);
3406 }
3407 }
3408 }
3409 }
3410 }
3411 Bind(&exit);
3412 auto ret = *result;
3413 env->SubCfgExit();
3414 return ret;
3415 }
3416
GetPrototype(GateRef glue,GateRef object)3417 GateRef StubBuilder::GetPrototype(GateRef glue, GateRef object)
3418 {
3419 auto env = GetEnvironment();
3420 Label entry(env);
3421 env->SubCfgEntry(&entry);
3422 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3423 Label exit(env);
3424 Label objectIsHeapObject(env);
3425 Label objectIsEcmaObject(env);
3426 Label objectNotEcmaObject(env);
3427
3428 Branch(TaggedIsHeapObject(object), &objectIsHeapObject, &objectNotEcmaObject);
3429 Bind(&objectIsHeapObject);
3430 Branch(TaggedObjectIsEcmaObject(object), &objectIsEcmaObject, &objectNotEcmaObject);
3431 Bind(&objectNotEcmaObject);
3432 {
3433 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
3434 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
3435 result = Exception();
3436 Jump(&exit);
3437 }
3438 Bind(&objectIsEcmaObject);
3439 {
3440 Label objectIsJsProxy(env);
3441 Label objectNotIsJsProxy(env);
3442 Branch(IsJsProxy(object), &objectIsJsProxy, &objectNotIsJsProxy);
3443 Bind(&objectIsJsProxy);
3444 {
3445 result = CallRuntime(glue, RTSTUB_ID(CallGetPrototype), { object });
3446 Jump(&exit);
3447 }
3448 Bind(&objectNotIsJsProxy);
3449 {
3450 result = GetPrototypeFromHClass(LoadHClass(object));
3451 Jump(&exit);
3452 }
3453 }
3454 Bind(&exit);
3455 auto ret = *result;
3456 env->SubCfgExit();
3457 return ret;
3458 }
3459
SameValue(GateRef glue,GateRef left,GateRef right)3460 GateRef StubBuilder::SameValue(GateRef glue, GateRef left, GateRef right)
3461 {
3462 auto env = GetEnvironment();
3463 Label entry(env);
3464 env->SubCfgEntry(&entry);
3465 DEFVARIABLE(result, VariableType::BOOL(), False());
3466 Label exit(env);
3467 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
3468 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
3469 Label strictEqual2(env);
3470 Label stringEqualCheck(env);
3471 Label stringCompare(env);
3472 Label bigIntEqualCheck(env);
3473 Label numberEqualCheck1(env);
3474
3475 Branch(Equal(left, right), &strictEqual2, &numberEqualCheck1);
3476 Bind(&strictEqual2);
3477 {
3478 result = True();
3479 Jump(&exit);
3480 }
3481 Bind(&numberEqualCheck1);
3482 {
3483 Label leftIsNumber(env);
3484 Label leftIsNotNumber(env);
3485 Branch(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
3486 Bind(&leftIsNumber);
3487 {
3488 Label rightIsNumber(env);
3489 Branch(TaggedIsNumber(right), &rightIsNumber, &exit);
3490 Bind(&rightIsNumber);
3491 {
3492 Label numberEqualCheck2(env);
3493 Label leftIsInt(env);
3494 Label leftNotInt(env);
3495 Label getRight(env);
3496 Branch(TaggedIsInt(left), &leftIsInt, &leftNotInt);
3497 Bind(&leftIsInt);
3498 {
3499 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
3500 Jump(&getRight);
3501 }
3502 Bind(&leftNotInt);
3503 {
3504 doubleLeft = GetDoubleOfTDouble(left);
3505 Jump(&getRight);
3506 }
3507 Bind(&getRight);
3508 {
3509 Label rightIsInt(env);
3510 Label rightNotInt(env);
3511 Branch(TaggedIsInt(right), &rightIsInt, &rightNotInt);
3512 Bind(&rightIsInt);
3513 {
3514 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
3515 Jump(&numberEqualCheck2);
3516 }
3517 Bind(&rightNotInt);
3518 {
3519 doubleRight = GetDoubleOfTDouble(right);
3520 Jump(&numberEqualCheck2);
3521 }
3522 }
3523 Bind(&numberEqualCheck2);
3524 {
3525 Label boolAndCheck(env);
3526 Label signbitCheck(env);
3527 Branch(DoubleEqual(*doubleLeft, *doubleRight), &signbitCheck, &boolAndCheck);
3528 Bind(&signbitCheck);
3529 {
3530 GateRef leftEncoding = CastDoubleToInt64(*doubleLeft);
3531 GateRef RightEncoding = CastDoubleToInt64(*doubleRight);
3532 Label leftIsMinusZero(env);
3533 Label leftNotMinusZero(env);
3534 Branch(Int64Equal(leftEncoding, Int64(base::MINUS_ZERO_BITS)),
3535 &leftIsMinusZero, &leftNotMinusZero);
3536 Bind(&leftIsMinusZero);
3537 {
3538 Label rightIsMinusZero(env);
3539 Branch(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &rightIsMinusZero, &exit);
3540 Bind(&rightIsMinusZero);
3541 {
3542 result = True();
3543 Jump(&exit);
3544 }
3545 }
3546 Bind(&leftNotMinusZero);
3547 {
3548 Label rightNotMinusZero(env);
3549 Branch(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &exit, &rightNotMinusZero);
3550 Bind(&rightNotMinusZero);
3551 {
3552 result = True();
3553 Jump(&exit);
3554 }
3555 }
3556 }
3557 Bind(&boolAndCheck);
3558 {
3559 result = BoolAnd(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight));
3560 Jump(&exit);
3561 }
3562 }
3563 }
3564 }
3565 Bind(&leftIsNotNumber);
3566 Branch(TaggedIsNumber(right), &exit, &stringEqualCheck);
3567 Bind(&stringEqualCheck);
3568 Branch(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
3569 Bind(&stringCompare);
3570 {
3571 result = FastStringEqual(glue, left, right);
3572 Jump(&exit);
3573 }
3574 Bind(&bigIntEqualCheck);
3575 {
3576 Label leftIsBigInt(env);
3577 Label leftIsNotBigInt(env);
3578 Branch(TaggedIsBigInt(left), &leftIsBigInt, &exit);
3579 Bind(&leftIsBigInt);
3580 {
3581 Label rightIsBigInt(env);
3582 Branch(TaggedIsBigInt(right), &rightIsBigInt, &exit);
3583 Bind(&rightIsBigInt);
3584 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
3585 Jump(&exit);
3586 }
3587 }
3588 }
3589 Bind(&exit);
3590 auto ret = *result;
3591 env->SubCfgExit();
3592 return ret;
3593 }
3594
FastStringEqual(GateRef glue,GateRef left,GateRef right)3595 GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right)
3596 {
3597 auto env = GetEnvironment();
3598 Label entry(env);
3599 env->SubCfgEntry(&entry);
3600 DEFVARIABLE(result, VariableType::BOOL(), False());
3601 Label exit(env);
3602 Label lengthCompare(env);
3603 Label hashcodeCompare(env);
3604 Label contentsCompare(env);
3605
3606 Branch(Int32Equal(ZExtInt1ToInt32(IsUtf16String(left)), ZExtInt1ToInt32(IsUtf16String(right))),
3607 &lengthCompare, &exit);
3608
3609 Bind(&lengthCompare);
3610 Branch(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &hashcodeCompare,
3611 &exit);
3612
3613 Bind(&hashcodeCompare);
3614 Branch(Int32Equal(GetHashcodeFromString(glue, left), GetHashcodeFromString(glue, right)), &contentsCompare,
3615 &exit);
3616
3617 Bind(&contentsCompare);
3618 {
3619 result = CallNGCRuntime(glue, RTSTUB_ID(StringsAreEquals), { left, right });
3620 Jump(&exit);
3621 }
3622
3623 Bind(&exit);
3624 auto ret = *result;
3625 env->SubCfgExit();
3626 return ret;
3627 }
3628
FastStrictEqual(GateRef glue,GateRef left,GateRef right)3629 GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right)
3630 {
3631 auto env = GetEnvironment();
3632 Label entry(env);
3633 env->SubCfgEntry(&entry);
3634 DEFVARIABLE(result, VariableType::BOOL(), False());
3635 Label strictEqual(env);
3636 Label leftIsNumber(env);
3637 Label leftIsNotNumber(env);
3638 Label sameVariableCheck(env);
3639 Label stringEqualCheck(env);
3640 Label stringCompare(env);
3641 Label bigIntEqualCheck(env);
3642 Label exit(env);
3643 Branch(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
3644 Bind(&leftIsNumber);
3645 {
3646 Label rightIsNumber(env);
3647 Branch(TaggedIsNumber(right), &rightIsNumber, &exit);
3648 Bind(&rightIsNumber);
3649 {
3650 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
3651 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
3652 Label leftIsInt(env);
3653 Label leftNotInt(env);
3654 Label getRight(env);
3655 Label numberEqualCheck(env);
3656 Branch(TaggedIsInt(left), &leftIsInt, &leftNotInt);
3657 Bind(&leftIsInt);
3658 {
3659 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
3660 Jump(&getRight);
3661 }
3662 Bind(&leftNotInt);
3663 {
3664 doubleLeft = GetDoubleOfTDouble(left);
3665 Jump(&getRight);
3666 }
3667 Bind(&getRight);
3668 {
3669 Label rightIsInt(env);
3670 Label rightNotInt(env);
3671 Branch(TaggedIsInt(right), &rightIsInt, &rightNotInt);
3672 Bind(&rightIsInt);
3673 {
3674 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
3675 Jump(&numberEqualCheck);
3676 }
3677 Bind(&rightNotInt);
3678 {
3679 doubleRight = GetDoubleOfTDouble(right);
3680 Jump(&numberEqualCheck);
3681 }
3682 }
3683 Bind(&numberEqualCheck);
3684 {
3685 Label doubleEqualCheck(env);
3686 Branch(BoolOr(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight)), &exit, &doubleEqualCheck);
3687 Bind(&doubleEqualCheck);
3688 {
3689 result = DoubleEqual(*doubleLeft, *doubleRight);
3690 Jump(&exit);
3691 }
3692 }
3693 }
3694 }
3695 Bind(&leftIsNotNumber);
3696 Branch(TaggedIsNumber(right), &exit, &sameVariableCheck);
3697 Bind(&sameVariableCheck);
3698 Branch(Equal(left, right), &strictEqual, &stringEqualCheck);
3699 Bind(&stringEqualCheck);
3700 Branch(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
3701 Bind(&stringCompare);
3702 {
3703 result = FastStringEqual(glue, left, right);
3704 Jump(&exit);
3705 }
3706 Bind(&bigIntEqualCheck);
3707 {
3708 Label leftIsBigInt(env);
3709 Label leftIsNotBigInt(env);
3710 Branch(TaggedIsBigInt(left), &leftIsBigInt, &exit);
3711 Bind(&leftIsBigInt);
3712 {
3713 Label rightIsBigInt(env);
3714 Branch(TaggedIsBigInt(right), &rightIsBigInt, &exit);
3715 Bind(&rightIsBigInt);
3716 result = CallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
3717 Jump(&exit);
3718 }
3719 }
3720 Bind(&strictEqual);
3721 {
3722 result = True();
3723 Jump(&exit);
3724 }
3725 Bind(&exit);
3726 auto ret = *result;
3727 env->SubCfgExit();
3728 return ret;
3729 }
3730
FastEqual(GateRef left,GateRef right)3731 GateRef StubBuilder::FastEqual(GateRef left, GateRef right)
3732 {
3733 auto env = GetEnvironment();
3734 Label entry(env);
3735 env->SubCfgEntry(&entry);
3736 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3737 Label leftEqualRight(env);
3738 Label leftNotEqualRight(env);
3739 Label exit(env);
3740 Branch(Equal(left, right), &leftEqualRight, &leftNotEqualRight);
3741 Bind(&leftEqualRight);
3742 {
3743 Label leftIsDouble(env);
3744 Label leftNotDoubleOrLeftNotNan(env);
3745 Branch(TaggedIsDouble(left), &leftIsDouble, &leftNotDoubleOrLeftNotNan);
3746 Bind(&leftIsDouble);
3747 {
3748 GateRef doubleLeft = GetDoubleOfTDouble(left);
3749 Label leftIsNan(env);
3750 Branch(DoubleIsNAN(doubleLeft), &leftIsNan, &leftNotDoubleOrLeftNotNan);
3751 Bind(&leftIsNan);
3752 {
3753 result = TaggedFalse();
3754 Jump(&exit);
3755 }
3756 }
3757 Bind(&leftNotDoubleOrLeftNotNan);
3758 {
3759 result = TaggedTrue();
3760 Jump(&exit);
3761 }
3762 }
3763 Bind(&leftNotEqualRight);
3764 {
3765 Label leftIsNumber(env);
3766 Label leftNotNumberOrLeftNotIntOrRightNotInt(env);
3767 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrLeftNotIntOrRightNotInt);
3768 Bind(&leftIsNumber);
3769 {
3770 Label leftIsInt(env);
3771 Branch(TaggedIsInt(left), &leftIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
3772 Bind(&leftIsInt);
3773 {
3774 Label rightIsInt(env);
3775 Branch(TaggedIsInt(right), &rightIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
3776 Bind(&rightIsInt);
3777 {
3778 result = TaggedFalse();
3779 Jump(&exit);
3780 }
3781 }
3782 }
3783 Bind(&leftNotNumberOrLeftNotIntOrRightNotInt);
3784 {
3785 Label rightIsUndefinedOrNull(env);
3786 Label leftOrRightNotUndefinedOrNull(env);
3787 Branch(TaggedIsUndefinedOrNull(right), &rightIsUndefinedOrNull, &leftOrRightNotUndefinedOrNull);
3788 Bind(&rightIsUndefinedOrNull);
3789 {
3790 Label leftIsHeapObject(env);
3791 Label leftNotHeapObject(env);
3792 Branch(TaggedIsHeapObject(left), &leftIsHeapObject, &leftNotHeapObject);
3793 Bind(&leftIsHeapObject);
3794 {
3795 result = TaggedFalse();
3796 Jump(&exit);
3797 }
3798 Bind(&leftNotHeapObject);
3799 {
3800 Label leftIsUndefinedOrNull(env);
3801 Branch(TaggedIsUndefinedOrNull(left), &leftIsUndefinedOrNull, &leftOrRightNotUndefinedOrNull);
3802 Bind(&leftIsUndefinedOrNull);
3803 {
3804 result = TaggedTrue();
3805 Jump(&exit);
3806 }
3807 }
3808 }
3809 Bind(&leftOrRightNotUndefinedOrNull);
3810 {
3811 Label leftIsBool(env);
3812 Label leftNotBoolOrRightNotSpecial(env);
3813 Branch(TaggedIsBoolean(left), &leftIsBool, &leftNotBoolOrRightNotSpecial);
3814 Bind(&leftIsBool);
3815 {
3816 Label rightIsSpecial(env);
3817 Branch(TaggedIsSpecial(right), &rightIsSpecial, &leftNotBoolOrRightNotSpecial);
3818 Bind(&rightIsSpecial);
3819 {
3820 result = TaggedFalse();
3821 Jump(&exit);
3822 }
3823 }
3824 Bind(&leftNotBoolOrRightNotSpecial);
3825 {
3826 Jump(&exit);
3827 }
3828 }
3829 }
3830 }
3831 Bind(&exit);
3832 auto ret = *result;
3833 env->SubCfgExit();
3834 return ret;
3835 }
3836
FastToBoolean(GateRef value)3837 GateRef StubBuilder::FastToBoolean(GateRef value)
3838 {
3839 auto env = GetEnvironment();
3840 Label entry(env);
3841 env->SubCfgEntry(&entry);
3842 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3843 Label exit(env);
3844
3845 Label isSpecial(env);
3846 Label notSpecial(env);
3847 Label isNumber(env);
3848 Label isInt(env);
3849 Label isDouble(env);
3850 Label notNumber(env);
3851 Label notNan(env);
3852 Label isString(env);
3853 Label notString(env);
3854 Label isBigint(env);
3855 Label lengthIsOne(env);
3856 Label returnTrue(env);
3857 Label returnFalse(env);
3858
3859 Branch(TaggedIsSpecial(value), &isSpecial, ¬Special);
3860 Bind(&isSpecial);
3861 {
3862 Branch(TaggedIsTrue(value), &returnTrue, &returnFalse);
3863 }
3864 Bind(¬Special);
3865 {
3866 Branch(TaggedIsNumber(value), &isNumber, ¬Number);
3867 Bind(¬Number);
3868 {
3869 Branch(IsString(value), &isString, ¬String);
3870 Bind(&isString);
3871 {
3872 auto len = GetLengthFromString(value);
3873 Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
3874 }
3875 Bind(¬String);
3876 Branch(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
3877 Bind(&isBigint);
3878 {
3879 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
3880 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
3881 Bind(&lengthIsOne);
3882 {
3883 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
3884 auto data0 = Load(VariableType::INT32(), data, Int32(0));
3885 Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
3886 }
3887 }
3888 }
3889 Bind(&isNumber);
3890 {
3891 Branch(TaggedIsInt(value), &isInt, &isDouble);
3892 Bind(&isInt);
3893 {
3894 auto intValue = GetInt32OfTInt(value);
3895 Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
3896 }
3897 Bind(&isDouble);
3898 {
3899 auto doubleValue = GetDoubleOfTDouble(value);
3900 Branch(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
3901 Bind(¬Nan);
3902 Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
3903 }
3904 }
3905 }
3906 Bind(&returnTrue);
3907 {
3908 result = TaggedTrue();
3909 Jump(&exit);
3910 }
3911 Bind(&returnFalse);
3912 {
3913 result = TaggedFalse();
3914 Jump(&exit);
3915 }
3916
3917 Bind(&exit);
3918 auto ret = *result;
3919 env->SubCfgExit();
3920 return ret;
3921 }
3922
FastDiv(GateRef left,GateRef right)3923 GateRef StubBuilder::FastDiv(GateRef left, GateRef right)
3924 {
3925 auto env = GetEnvironment();
3926 Label entry(env);
3927 env->SubCfgEntry(&entry);
3928 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
3929 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
3930 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
3931 Label leftIsNumber(env);
3932 Label leftNotNumberOrRightNotNumber(env);
3933 Label leftIsNumberAndRightIsNumber(env);
3934 Label leftIsDoubleAndRightIsDouble(env);
3935 Label exit(env);
3936 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
3937 Bind(&leftIsNumber);
3938 {
3939 Label rightIsNumber(env);
3940 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
3941 Bind(&rightIsNumber);
3942 {
3943 Label leftIsInt(env);
3944 Label leftNotInt(env);
3945 Branch(TaggedIsInt(left), &leftIsInt, &leftNotInt);
3946 Bind(&leftIsInt);
3947 {
3948 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
3949 Jump(&leftIsNumberAndRightIsNumber);
3950 }
3951 Bind(&leftNotInt);
3952 {
3953 doubleLeft = GetDoubleOfTDouble(left);
3954 Jump(&leftIsNumberAndRightIsNumber);
3955 }
3956 }
3957 }
3958 Bind(&leftNotNumberOrRightNotNumber);
3959 {
3960 Jump(&exit);
3961 }
3962 Bind(&leftIsNumberAndRightIsNumber);
3963 {
3964 Label rightIsInt(env);
3965 Label rightNotInt(env);
3966 Branch(TaggedIsInt(right), &rightIsInt, &rightNotInt);
3967 Bind(&rightIsInt);
3968 {
3969 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
3970 Jump(&leftIsDoubleAndRightIsDouble);
3971 }
3972 Bind(&rightNotInt);
3973 {
3974 doubleRight = GetDoubleOfTDouble(right);
3975 Jump(&leftIsDoubleAndRightIsDouble);
3976 }
3977 }
3978 Bind(&leftIsDoubleAndRightIsDouble);
3979 {
3980 Label rightIsZero(env);
3981 Label rightNotZero(env);
3982 Branch(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZero, &rightNotZero);
3983 Bind(&rightIsZero);
3984 {
3985 Label leftIsZero(env);
3986 Label leftNotZero(env);
3987 Label leftIsZeroOrNan(env);
3988 Label leftNotZeroAndNotNan(env);
3989 Branch(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZero, &leftNotZero);
3990 Bind(&leftIsZero);
3991 {
3992 Jump(&leftIsZeroOrNan);
3993 }
3994 Bind(&leftNotZero);
3995 {
3996 Label leftIsNan(env);
3997 Branch(DoubleIsNAN(*doubleLeft), &leftIsNan, &leftNotZeroAndNotNan);
3998 Bind(&leftIsNan);
3999 {
4000 Jump(&leftIsZeroOrNan);
4001 }
4002 }
4003 Bind(&leftIsZeroOrNan);
4004 {
4005 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
4006 Jump(&exit);
4007 }
4008 Bind(&leftNotZeroAndNotNan);
4009 {
4010 GateRef intLeftTmp = CastDoubleToInt64(*doubleLeft);
4011 GateRef intRightTmp = CastDoubleToInt64(*doubleRight);
4012 GateRef flagBit = Int64And(Int64Xor(intLeftTmp, intRightTmp), Int64(base::DOUBLE_SIGN_MASK));
4013 GateRef tmpResult = Int64Xor(flagBit, CastDoubleToInt64(Double(base::POSITIVE_INFINITY)));
4014 result = DoubleToTaggedDoublePtr(CastInt64ToFloat64(tmpResult));
4015 Jump(&exit);
4016 }
4017 }
4018 Bind(&rightNotZero);
4019 {
4020 result = DoubleToTaggedDoublePtr(DoubleDiv(*doubleLeft, *doubleRight));
4021 Jump(&exit);
4022 }
4023 }
4024 Bind(&exit);
4025 auto ret = *result;
4026 env->SubCfgExit();
4027 return ret;
4028 }
4029
FastBinaryOp(GateRef left,GateRef right,const BinaryOperation & intOp,const BinaryOperation & floatOp)4030 GateRef StubBuilder::FastBinaryOp(GateRef left, GateRef right,
4031 const BinaryOperation& intOp,
4032 const BinaryOperation& floatOp)
4033 {
4034 auto env = GetEnvironment();
4035 Label entry(env);
4036 env->SubCfgEntry(&entry);
4037 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4038 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
4039 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
4040
4041 Label exit(env);
4042 Label doFloatOp(env);
4043 Label doIntOp(env);
4044 Label leftIsNumber(env);
4045 Label rightIsNumber(env);
4046 Label leftIsIntRightIsDouble(env);
4047 Label rightIsInt(env);
4048 Label rightIsDouble(env);
4049
4050 Branch(TaggedIsNumber(left), &leftIsNumber, &exit);
4051 Bind(&leftIsNumber);
4052 {
4053 Branch(TaggedIsNumber(right), &rightIsNumber, &exit);
4054 Bind(&rightIsNumber);
4055 {
4056 Label leftIsInt(env);
4057 Label leftIsDouble(env);
4058 Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
4059 Bind(&leftIsInt);
4060 {
4061 Branch(TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
4062 Bind(&leftIsIntRightIsDouble);
4063 {
4064 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
4065 doubleRight = GetDoubleOfTDouble(right);
4066 Jump(&doFloatOp);
4067 }
4068 }
4069 Bind(&leftIsDouble);
4070 {
4071 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
4072 Bind(&rightIsInt);
4073 {
4074 doubleLeft = GetDoubleOfTDouble(left);
4075 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
4076 Jump(&doFloatOp);
4077 }
4078 Bind(&rightIsDouble);
4079 {
4080 doubleLeft = GetDoubleOfTDouble(left);
4081 doubleRight = GetDoubleOfTDouble(right);
4082 Jump(&doFloatOp);
4083 }
4084 }
4085 }
4086 }
4087 Bind(&doIntOp);
4088 {
4089 result = intOp(env, left, right);
4090 Jump(&exit);
4091 }
4092 Bind(&doFloatOp);
4093 {
4094 result = floatOp(env, *doubleLeft, *doubleRight);
4095 Jump(&exit);
4096 }
4097 Bind(&exit);
4098 auto ret = *result;
4099 env->SubCfgExit();
4100 return ret;
4101 }
4102
4103 template<OpCode Op>
FastAddSubAndMul(GateRef left,GateRef right)4104 GateRef StubBuilder::FastAddSubAndMul(GateRef left, GateRef right)
4105 {
4106 auto intOperation = [=](Environment *env, GateRef left, GateRef right) {
4107 Label entry(env);
4108 env->SubCfgEntry(&entry);
4109 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4110 Label exit(env);
4111 Label overflow(env);
4112 Label notOverflow(env);
4113 auto res = BinaryOp<Op, MachineType::I64>(GetInt64OfTInt(left), GetInt64OfTInt(right));
4114 auto condition1 = Int64GreaterThan(res, Int64(INT32_MAX));
4115 auto condition2 = Int64LessThan(res, Int64(INT32_MIN));
4116 Branch(BoolOr(condition1, condition2), &overflow, ¬Overflow);
4117 Bind(&overflow);
4118 {
4119 auto doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
4120 auto doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
4121 auto ret = BinaryOp<Op, MachineType::F64>(doubleLeft, doubleRight);
4122 result = DoubleToTaggedDoublePtr(ret);
4123 Jump(&exit);
4124 }
4125 Bind(¬Overflow);
4126 {
4127 result = IntToTaggedPtr(TruncInt64ToInt32(res));
4128 Jump(&exit);
4129 }
4130 Bind(&exit);
4131 auto ret = *result;
4132 env->SubCfgExit();
4133 return ret;
4134 };
4135 auto floatOperation = [=]([[maybe_unused]] Environment *env, GateRef left, GateRef right) {
4136 auto res = BinaryOp<Op, MachineType::F64>(left, right);
4137 return DoubleToTaggedDoublePtr(res);
4138 };
4139 return FastBinaryOp(left, right, intOperation, floatOperation);
4140 }
4141
FastAdd(GateRef left,GateRef right)4142 GateRef StubBuilder::FastAdd(GateRef left, GateRef right)
4143 {
4144 return FastAddSubAndMul<OpCode::ADD>(left, right);
4145 }
4146
FastSub(GateRef left,GateRef right)4147 GateRef StubBuilder::FastSub(GateRef left, GateRef right)
4148 {
4149 return FastAddSubAndMul<OpCode::SUB>(left, right);
4150 }
4151
FastMul(GateRef left,GateRef right)4152 GateRef StubBuilder::FastMul(GateRef left, GateRef right)
4153 {
4154 return FastAddSubAndMul<OpCode::MUL>(left, right);
4155 }
4156
FastMod(GateRef glue,GateRef left,GateRef right)4157 GateRef StubBuilder::FastMod(GateRef glue, GateRef left, GateRef right)
4158 {
4159 auto env = GetEnvironment();
4160 Label entry(env);
4161 env->SubCfgEntry(&entry);
4162 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4163 DEFVARIABLE(intLeft, VariableType::INT32(), Int32(0));
4164 DEFVARIABLE(intRight, VariableType::INT32(), Int32(0));
4165 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
4166 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
4167 Label leftIsInt(env);
4168 Label leftNotIntOrRightNotInt(env);
4169 Label exit(env);
4170 Branch(TaggedIsInt(left), &leftIsInt, &leftNotIntOrRightNotInt);
4171 Bind(&leftIsInt);
4172 {
4173 Label rightIsInt(env);
4174 Branch(TaggedIsInt(right), &rightIsInt, &leftNotIntOrRightNotInt);
4175 Bind(&rightIsInt);
4176 {
4177 intLeft = GetInt32OfTInt(left);
4178 intRight = GetInt32OfTInt(right);
4179 Label leftGreaterZero(env);
4180 Branch(Int32GreaterThan(*intLeft, Int32(0)), &leftGreaterZero, &leftNotIntOrRightNotInt);
4181 Bind(&leftGreaterZero);
4182 {
4183 Label rightGreaterZero(env);
4184 Branch(Int32GreaterThan(*intRight, Int32(0)), &rightGreaterZero, &leftNotIntOrRightNotInt);
4185 Bind(&rightGreaterZero);
4186 {
4187 result = IntToTaggedPtr(Int32Mod(*intLeft, *intRight));
4188 Jump(&exit);
4189 }
4190 }
4191 }
4192 }
4193 Bind(&leftNotIntOrRightNotInt);
4194 {
4195 Label leftIsNumber(env);
4196 Label leftNotNumberOrRightNotNumber(env);
4197 Label leftIsNumberAndRightIsNumber(env);
4198 Label leftIsDoubleAndRightIsDouble(env);
4199 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
4200 Bind(&leftIsNumber);
4201 {
4202 Label rightIsNumber(env);
4203 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
4204 Bind(&rightIsNumber);
4205 {
4206 Label leftIsInt1(env);
4207 Label leftNotInt1(env);
4208 Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
4209 Bind(&leftIsInt1);
4210 {
4211 doubleLeft = ChangeInt32ToFloat64(GetInt32OfTInt(left));
4212 Jump(&leftIsNumberAndRightIsNumber);
4213 }
4214 Bind(&leftNotInt1);
4215 {
4216 doubleLeft = GetDoubleOfTDouble(left);
4217 Jump(&leftIsNumberAndRightIsNumber);
4218 }
4219 }
4220 }
4221 Bind(&leftNotNumberOrRightNotNumber);
4222 {
4223 Jump(&exit);
4224 }
4225 Bind(&leftIsNumberAndRightIsNumber);
4226 {
4227 Label rightIsInt1(env);
4228 Label rightNotInt1(env);
4229 Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
4230 Bind(&rightIsInt1);
4231 {
4232 doubleRight = ChangeInt32ToFloat64(GetInt32OfTInt(right));
4233 Jump(&leftIsDoubleAndRightIsDouble);
4234 }
4235 Bind(&rightNotInt1);
4236 {
4237 doubleRight = GetDoubleOfTDouble(right);
4238 Jump(&leftIsDoubleAndRightIsDouble);
4239 }
4240 }
4241 Bind(&leftIsDoubleAndRightIsDouble);
4242 {
4243 Label rightNotZero(env);
4244 Label rightIsZeroOrNanOrLeftIsNanOrInf(env);
4245 Label rightNotZeroAndNanAndLeftNotNanAndInf(env);
4246 Branch(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotZero);
4247 Bind(&rightNotZero);
4248 {
4249 Label rightNotNan(env);
4250 Branch(DoubleIsNAN(*doubleRight), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotNan);
4251 Bind(&rightNotNan);
4252 {
4253 Label leftNotNan(env);
4254 Branch(DoubleIsNAN(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf, &leftNotNan);
4255 Bind(&leftNotNan);
4256 {
4257 Branch(DoubleIsINF(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf,
4258 &rightNotZeroAndNanAndLeftNotNanAndInf);
4259 }
4260 }
4261 }
4262 Bind(&rightIsZeroOrNanOrLeftIsNanOrInf);
4263 {
4264 result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
4265 Jump(&exit);
4266 }
4267 Bind(&rightNotZeroAndNanAndLeftNotNanAndInf);
4268 {
4269 Label leftNotZero(env);
4270 Label leftIsZeroOrRightIsInf(env);
4271 Branch(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZeroOrRightIsInf, &leftNotZero);
4272 Bind(&leftNotZero);
4273 {
4274 Label rightNotInf(env);
4275 Branch(DoubleIsINF(*doubleRight), &leftIsZeroOrRightIsInf, &rightNotInf);
4276 Bind(&rightNotInf);
4277 {
4278 result = CallNGCRuntime(glue, RTSTUB_ID(FloatMod), { *doubleLeft, *doubleRight });
4279 Jump(&exit);
4280 }
4281 }
4282 Bind(&leftIsZeroOrRightIsInf);
4283 {
4284 result = DoubleToTaggedDoublePtr(*doubleLeft);
4285 Jump(&exit);
4286 }
4287 }
4288 }
4289 }
4290 Bind(&exit);
4291 auto ret = *result;
4292 env->SubCfgExit();
4293 return ret;
4294 }
4295
GetGlobalOwnProperty(GateRef glue,GateRef receiver,GateRef key)4296 GateRef StubBuilder::GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRef key)
4297 {
4298 auto env = GetEnvironment();
4299 Label entryLabel(env);
4300 env->SubCfgEntry(&entryLabel);
4301 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4302 GateRef properties = GetPropertiesFromJSObject(receiver);
4303 GateRef entry = FindEntryFromNameDictionary(glue, properties, key);
4304 Label notNegtiveOne(env);
4305 Label exit(env);
4306 Branch(Int32NotEqual(entry, Int32(-1)), ¬NegtiveOne, &exit);
4307 Bind(¬NegtiveOne);
4308 {
4309 result = GetValueFromGlobalDictionary(properties, entry);
4310 Label callGetter(env);
4311 Branch(TaggedIsAccessor(*result), &callGetter, &exit);
4312 Bind(&callGetter);
4313 {
4314 result = CallGetterHelper(glue, receiver, receiver, *result);
4315 Jump(&exit);
4316 }
4317 }
4318 Bind(&exit);
4319 auto ret = *result;
4320 env->SubCfgExit();
4321 return ret;
4322 }
4323
GetStringFromConstPool(GateRef glue,GateRef constpool,GateRef index)4324 GateRef StubBuilder::GetStringFromConstPool(GateRef glue, GateRef constpool, GateRef index)
4325 {
4326 GateRef module = Circuit::NullGate();
4327 return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::STRING);
4328 }
4329
GetMethodFromConstPool(GateRef glue,GateRef constpool,GateRef index)4330 GateRef StubBuilder::GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index)
4331 {
4332 GateRef module = Circuit::NullGate();
4333 return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::METHOD);
4334 }
4335
GetArrayLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)4336 GateRef StubBuilder::GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
4337 {
4338 return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::ARRAY_LITERAL);
4339 }
4340
GetObjectLiteralFromConstPool(GateRef glue,GateRef constpool,GateRef index,GateRef module)4341 GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
4342 {
4343 return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::OBJECT_LITERAL);
4344 }
4345
JSAPIContainerGet(GateRef glue,GateRef receiver,GateRef index)4346 GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)
4347 {
4348 auto env = GetEnvironment();
4349 Label entry(env);
4350 env->SubCfgEntry(&entry);
4351 Label exit(env);
4352 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
4353
4354 GateRef lengthOffset = IntPtr(panda::ecmascript::JSAPIArrayList::LENGTH_OFFSET);
4355 GateRef length = GetInt32OfTInt(Load(VariableType::INT64(), receiver, lengthOffset));
4356 Label isVailedIndex(env);
4357 Label notValidIndex(env);
4358 Branch(BoolAnd(Int32GreaterThanOrEqual(index, Int32(0)),
4359 Int32UnsignedLessThan(index, length)), &isVailedIndex, ¬ValidIndex);
4360 Bind(&isVailedIndex);
4361 {
4362 GateRef elements = GetElementsArray(receiver);
4363 result = GetValueFromTaggedArray(elements, index);
4364 Jump(&exit);
4365 }
4366 Bind(¬ValidIndex);
4367 {
4368 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(GetPropertyOutOfBounds));
4369 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
4370 result = Exception();
4371 Jump(&exit);
4372 }
4373
4374 Bind(&exit);
4375 auto ret = *result;
4376 env->SubCfgExit();
4377 return ret;
4378 }
4379
DoubleToInt(GateRef glue,GateRef x)4380 GateRef StubBuilder::DoubleToInt(GateRef glue, GateRef x)
4381 {
4382 auto env = GetEnvironment();
4383 Label entry(env);
4384 env->SubCfgEntry(&entry);
4385 Label exit(env);
4386 Label overflow(env);
4387
4388 GateRef xInt = ChangeFloat64ToInt32(x);
4389 DEFVARIABLE(result, VariableType::INT32(), xInt);
4390
4391 if (env->IsAmd64()) {
4392 // 0x80000000: amd64 overflow return value
4393 Branch(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit);
4394 } else {
4395 GateRef xInt64 = CastDoubleToInt64(x);
4396 // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
4397 GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
4398 exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
4399 exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
4400 GateRef bits = Int32(base::INT32_BITS - 1);
4401 // exp < 32 - 1
4402 Branch(Int32LessThan(exp, bits), &exit, &overflow);
4403 }
4404 Bind(&overflow);
4405 {
4406 result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), { x });
4407 Jump(&exit);
4408 }
4409 Bind(&exit);
4410 auto ret = *result;
4411 env->SubCfgExit();
4412 return ret;
4413 }
4414
ReturnExceptionIfAbruptCompletion(GateRef glue)4415 void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue)
4416 {
4417 auto env = GetEnvironment();
4418 Label entry(env);
4419 env->SubCfgEntry(&entry);
4420 Label exit(env);
4421 Label hasPendingException(env);
4422 GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env->IsArch32Bit()));
4423 GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
4424 Branch(TaggedIsNotHole(exception), &hasPendingException, &exit);
4425 Bind(&hasPendingException);
4426 Return(Exception());
4427 Bind(&exit);
4428 env->SubCfgExit();
4429 return;
4430 }
4431
GetHashcodeFromString(GateRef glue,GateRef value)4432 GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
4433 {
4434 auto env = GetEnvironment();
4435 Label subentry(env);
4436 env->SubCfgEntry(&subentry);
4437 Label noRawHashcode(env);
4438 Label exit(env);
4439 DEFVARIABLE(hashcode, VariableType::INT32(), Int32(0));
4440 hashcode = Load(VariableType::INT32(), value, IntPtr(EcmaString::HASHCODE_OFFSET));
4441 Branch(Int32Equal(*hashcode, Int32(0)), &noRawHashcode, &exit);
4442 Bind(&noRawHashcode);
4443 {
4444 hashcode = GetInt32OfTInt(CallRuntime(glue, RTSTUB_ID(ComputeHashcode), { value }));
4445 Store(VariableType::INT32(), glue, value, IntPtr(EcmaString::HASHCODE_OFFSET), *hashcode);
4446 Jump(&exit);
4447 }
4448 Bind(&exit);
4449 auto ret = *hashcode;
4450 env->SubCfgExit();
4451 return ret;
4452 }
4453
ConstructorCheck(GateRef glue,GateRef ctor,GateRef outPut,GateRef thisObj)4454 GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj)
4455 {
4456 auto env = GetEnvironment();
4457 Label entryPass(env);
4458 Label exit(env);
4459 env->SubCfgEntry(&entryPass);
4460 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
4461 Label isHeapObject(env);
4462 Label isEcmaObj(env);
4463 Label notEcmaObj(env);
4464 Branch(TaggedIsHeapObject(outPut), &isHeapObject, ¬EcmaObj);
4465 Bind(&isHeapObject);
4466 Branch(TaggedObjectIsEcmaObject(outPut), &isEcmaObj, ¬EcmaObj);
4467 Bind(&isEcmaObj);
4468 {
4469 result = outPut;
4470 Jump(&exit);
4471 }
4472 Bind(¬EcmaObj);
4473 {
4474 Label ctorIsBase(env);
4475 Label ctorNotBase(env);
4476 Branch(IsBase(ctor), &ctorIsBase, &ctorNotBase);
4477 Bind(&ctorIsBase);
4478 {
4479 result = thisObj;
4480 Jump(&exit);
4481 }
4482 Bind(&ctorNotBase);
4483 {
4484 Label throwExeption(env);
4485 Label returnObj(env);
4486 Branch(TaggedIsUndefined(outPut), &returnObj, &throwExeption);
4487 Bind(&returnObj);
4488 result = thisObj;
4489 Jump(&exit);
4490 Bind(&throwExeption);
4491 {
4492 CallRuntime(glue, RTSTUB_ID(ThrowNonConstructorException), {});
4493 Jump(&exit);
4494 }
4495 }
4496 }
4497 Bind(&exit);
4498 auto ret = *result;
4499 env->SubCfgExit();
4500 return ret;
4501 }
4502
JSCallDispatch(GateRef glue,GateRef func,GateRef actualNumArgs,GateRef jumpSize,GateRef hotnessCounter,JSCallMode mode,std::initializer_list<GateRef> args)4503 GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize,
4504 GateRef hotnessCounter, JSCallMode mode, std::initializer_list<GateRef> args)
4505 {
4506 auto env = GetEnvironment();
4507 Label entryPass(env);
4508 Label exit(env);
4509 env->SubCfgEntry(&entryPass);
4510 DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
4511 // 1. call initialize
4512 Label funcIsHeapObject(env);
4513 Label funcIsCallable(env);
4514 Label funcNotCallable(env);
4515 // save pc
4516 SavePcIfNeeded(glue);
4517 GateRef bitfield = 0;
4518 if (!AssemblerModule::IsCallNew(mode)) {
4519 Branch(TaggedIsHeapObject(func), &funcIsHeapObject, &funcNotCallable);
4520 Bind(&funcIsHeapObject);
4521 GateRef hclass = LoadHClass(func);
4522 bitfield = Load(VariableType::INT32(), hclass, IntPtr(JSHClass::BIT_FIELD_OFFSET));
4523 Branch(IsCallableFromBitField(bitfield), &funcIsCallable, &funcNotCallable);
4524 Bind(&funcNotCallable);
4525 {
4526 CallRuntime(glue, RTSTUB_ID(ThrowNotCallableException), {});
4527 Jump(&exit);
4528 }
4529 Bind(&funcIsCallable);
4530 }
4531 GateRef method = GetMethodFromJSFunction(func);
4532 GateRef callField = GetCallFieldFromMethod(method);
4533 GateRef isNativeMask = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsNativeBit::START_BIT);
4534
4535 // 2. call dispatch
4536 Label methodIsNative(env);
4537 Label methodNotNative(env);
4538 Branch(Int64NotEqual(Int64And(callField, isNativeMask), Int64(0)), &methodIsNative, &methodNotNative);
4539 auto data = std::begin(args);
4540 Label notFastBuiltinsArg0(env);
4541 Label notFastBuiltinsArg1(env);
4542 Label notFastBuiltinsArg2(env);
4543 Label notFastBuiltinsArg3(env);
4544 Label notFastBuiltins(env);
4545 // 3. call native
4546 Bind(&methodIsNative);
4547 {
4548 GateRef nativeCode = Load(VariableType::NATIVE_POINTER(), method,
4549 IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
4550 GateRef newTarget = Undefined();
4551 GateRef thisValue = Undefined();
4552 GateRef numArgs = Int32Add(actualNumArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
4553 switch (mode) {
4554 case JSCallMode::CALL_THIS_ARG0: {
4555 thisValue = data[0];
4556 CallFastPath(glue, nativeCode, func, thisValue, actualNumArgs, callField,
4557 method, ¬FastBuiltinsArg0, &exit, &result, args, mode);
4558 Bind(¬FastBuiltinsArg0);
4559 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4560 { nativeCode, glue, numArgs, func, newTarget, thisValue });
4561 break;
4562 }
4563 case JSCallMode::CALL_ARG0:
4564 case JSCallMode::DEPRECATED_CALL_ARG0:
4565 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4566 { nativeCode, glue, numArgs, func, newTarget, thisValue });
4567 break;
4568 case JSCallMode::CALL_THIS_ARG1: {
4569 thisValue = data[1];
4570 CallFastPath(glue, nativeCode, func, thisValue, actualNumArgs, callField,
4571 method, ¬FastBuiltinsArg1, &exit, &result, args, mode);
4572 Bind(¬FastBuiltinsArg1);
4573 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4574 { nativeCode, glue, numArgs, func, newTarget, thisValue, data[0]});
4575 break;
4576 }
4577 case JSCallMode::CALL_ARG1:
4578 case JSCallMode::DEPRECATED_CALL_ARG1:
4579 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4580 { nativeCode, glue, numArgs, func, newTarget, thisValue, data[0]});
4581 break;
4582 case JSCallMode::CALL_THIS_ARG2: {
4583 thisValue = data[2];
4584 CallFastPath(glue, nativeCode, func, thisValue, actualNumArgs, callField,
4585 method, ¬FastBuiltinsArg2, &exit, &result, args, mode);
4586 Bind(¬FastBuiltinsArg2);
4587 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4588 { nativeCode, glue, numArgs, func, newTarget, thisValue, data[0], data[1] });
4589 break;
4590 }
4591 case JSCallMode::CALL_ARG2:
4592 case JSCallMode::DEPRECATED_CALL_ARG2:
4593 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4594 { nativeCode, glue, numArgs, func, newTarget, thisValue, data[0], data[1] });
4595 break;
4596 case JSCallMode::CALL_THIS_ARG3: {
4597 thisValue = data[3];
4598 CallFastPath(glue, nativeCode, func, thisValue, actualNumArgs, callField,
4599 method, ¬FastBuiltinsArg3, &exit, &result, args, mode);
4600 Bind(¬FastBuiltinsArg3);
4601 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4602 { nativeCode, glue, numArgs, func,
4603 newTarget, thisValue, data[0], data[1], data[2] }); // 2: args2
4604 break;
4605 }
4606 case JSCallMode::CALL_ARG3:
4607 case JSCallMode::DEPRECATED_CALL_ARG3:
4608 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4609 { nativeCode, glue, numArgs, func,
4610 newTarget, thisValue, data[0], data[1], data[2] }); // 2: args2
4611 break;
4612 case JSCallMode::CALL_THIS_WITH_ARGV:
4613 case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV: {
4614 thisValue = data[2]; // 2: this input
4615 [[fallthrough]];
4616 }
4617 case JSCallMode::CALL_WITH_ARGV:
4618 case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
4619 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallRangeAndDispatchNative),
4620 { glue, nativeCode, func, thisValue, data[0], data[1] });
4621 break;
4622 case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
4623 case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: {
4624 CallFastPath(glue, nativeCode, func, thisValue, actualNumArgs, callField,
4625 method, ¬FastBuiltins, &exit, &result, args, mode);
4626 Bind(¬FastBuiltins);
4627 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallNewAndDispatchNative),
4628 { glue, nativeCode, func, data[2], data[0], data[1] });
4629 break;
4630 }
4631 case JSCallMode::CALL_GETTER:
4632 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4633 { nativeCode, glue, numArgs, func, newTarget, data[0] });
4634 break;
4635 case JSCallMode::CALL_SETTER:
4636 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4637 { nativeCode, glue, numArgs, func, newTarget, data[0], data[1] });
4638 break;
4639 case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
4640 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
4641 { nativeCode, glue, numArgs, func, newTarget, data[0], data[1], data[2], data[3] });
4642 break;
4643 default:
4644 UNREACHABLE();
4645 }
4646 Jump(&exit);
4647 }
4648 // 4. call nonNative
4649 Bind(&methodNotNative);
4650 Label funcIsClassConstructor(env);
4651 Label funcNotClassConstructor(env);
4652 PGOProfiler(glue, func);
4653 if (!AssemblerModule::IsCallNew(mode)) {
4654 Branch(IsClassConstructorFromBitField(bitfield), &funcIsClassConstructor, &funcNotClassConstructor);
4655 Bind(&funcIsClassConstructor);
4656 {
4657 CallRuntime(glue, RTSTUB_ID(ThrowCallConstructorException), {});
4658 Jump(&exit);
4659 }
4660 Bind(&funcNotClassConstructor);
4661 }
4662 GateRef sp = 0;
4663 if (env->IsAsmInterp()) {
4664 sp = Argument(static_cast<size_t>(InterpreterHandlerInputs::SP));
4665 }
4666 Label methodisAot(env);
4667 Label methodNotAot(env);
4668 {
4669 GateRef isAotMask = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsAotCodeBit::START_BIT);
4670 Branch(Int64Equal(Int64And(callField, isAotMask), Int64(0)), &methodNotAot, &methodisAot);
4671 Bind(&methodisAot);
4672 {
4673 GateRef newTarget = Undefined();
4674 GateRef thisValue = Undefined();
4675 GateRef lexEnv = env_->GetBuilder()->GetFunctionLexicalEnv(func);
4676 GateRef realNumArgs = Int64Add(ZExtInt32ToInt64(actualNumArgs), Int64(NUM_MANDATORY_JSFUNC_ARGS));
4677 switch (mode) {
4678 case JSCallMode::CALL_THIS_ARG0:
4679 thisValue = data[0];
4680 [[fallthrough]];
4681 case JSCallMode::CALL_ARG0:
4682 case JSCallMode::DEPRECATED_CALL_ARG0:
4683 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
4684 { glue, lexEnv, realNumArgs, func, newTarget, thisValue});
4685 Jump(&exit);
4686 break;
4687 case JSCallMode::CALL_THIS_ARG1:
4688 thisValue = data[1];
4689 [[fallthrough]];
4690 case JSCallMode::CALL_ARG1:
4691 case JSCallMode::DEPRECATED_CALL_ARG1:
4692 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
4693 { glue, lexEnv, realNumArgs, func, newTarget, thisValue, data[0] });
4694 Jump(&exit);
4695 break;
4696 case JSCallMode::CALL_THIS_ARG2:
4697 thisValue = data[2];
4698 [[fallthrough]];
4699 case JSCallMode::CALL_ARG2:
4700 case JSCallMode::DEPRECATED_CALL_ARG2:
4701 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
4702 { glue, lexEnv, realNumArgs, func, newTarget, thisValue, data[0], data[1] });
4703 Jump(&exit);
4704 break;
4705 case JSCallMode::CALL_THIS_ARG3:
4706 thisValue = data[3];
4707 [[fallthrough]];
4708 case JSCallMode::CALL_ARG3:
4709 case JSCallMode::DEPRECATED_CALL_ARG3:
4710 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
4711 { glue, lexEnv, realNumArgs, func, newTarget, thisValue,
4712 data[0], data[1], data[2] }); // 2: args2
4713 Jump(&exit);
4714 break;
4715 case JSCallMode::CALL_THIS_WITH_ARGV:
4716 case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
4717 thisValue = data[2]; // 2: this input
4718 [[fallthrough]];
4719 case JSCallMode::CALL_WITH_ARGV:
4720 case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
4721 result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgV),
4722 { glue, ZExtInt32ToInt64(actualNumArgs), func, newTarget, thisValue, data[1] });
4723 Jump(&exit);
4724 break;
4725 case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
4726 case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
4727 result = CallNGCRuntime(glue, RTSTUB_ID(ConstructorJSCallWithArgV),
4728 { glue, ZExtInt32ToInt64(actualNumArgs), func, func, data[2], data[1]});
4729 result = ConstructorCheck(glue, func, *result, data[2]); // 2: the second index
4730 Jump(&exit);
4731 break;
4732 case JSCallMode::CALL_GETTER:
4733 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
4734 { glue, lexEnv, realNumArgs, func, newTarget, data[0]});
4735 Jump(&exit);
4736 break;
4737 case JSCallMode::CALL_SETTER:
4738 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
4739 { glue, lexEnv, realNumArgs, func, newTarget, data[0], data[1]});
4740 Jump(&exit);
4741 break;
4742 case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
4743 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
4744 { glue, lexEnv, realNumArgs, func, newTarget, data[0], data[1], data[2], data[3] });
4745 Jump(&exit);
4746 break;
4747 default:
4748 UNREACHABLE();
4749 }
4750 }
4751 Bind(&methodNotAot);
4752 if (jumpSize != 0) {
4753 SaveJumpSizeIfNeeded(glue, jumpSize);
4754 }
4755 SaveHotnessCounterIfNeeded(glue, sp, hotnessCounter, mode);
4756 switch (mode) {
4757 case JSCallMode::CALL_THIS_ARG0:
4758 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallThisArg0AndDispatch),
4759 { glue, sp, func, method, callField, data[0] });
4760 Return();
4761 break;
4762 case JSCallMode::CALL_ARG0:
4763 case JSCallMode::DEPRECATED_CALL_ARG0:
4764 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArg0AndDispatch),
4765 { glue, sp, func, method, callField });
4766 Return();
4767 break;
4768 case JSCallMode::CALL_THIS_ARG1:
4769 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallThisArg1AndDispatch),
4770 { glue, sp, func, method, callField, data[0], data[1] });
4771 Return();
4772 break;
4773 case JSCallMode::CALL_ARG1:
4774 case JSCallMode::DEPRECATED_CALL_ARG1:
4775 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArg1AndDispatch),
4776 { glue, sp, func, method, callField, data[0] });
4777 Return();
4778 break;
4779 case JSCallMode::CALL_THIS_ARG2:
4780 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallThisArgs2AndDispatch),
4781 { glue, sp, func, method, callField, data[0], data[1], data[2] });
4782 Return();
4783 break;
4784 case JSCallMode::CALL_ARG2:
4785 case JSCallMode::DEPRECATED_CALL_ARG2:
4786 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs2AndDispatch),
4787 { glue, sp, func, method, callField, data[0], data[1] });
4788 Return();
4789 break;
4790 case JSCallMode::CALL_THIS_ARG3:
4791 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallThisArgs3AndDispatch),
4792 { glue, sp, func, method, callField, data[0], data[1], data[2], data[3] });
4793 Return();
4794 break;
4795 case JSCallMode::CALL_ARG3:
4796 case JSCallMode::DEPRECATED_CALL_ARG3:
4797 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs3AndDispatch),
4798 { glue, sp, func, method, callField, data[0], data[1], data[2] }); // 2: args2
4799 Return();
4800 break;
4801 case JSCallMode::CALL_WITH_ARGV:
4802 case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
4803 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallRangeAndDispatch),
4804 { glue, sp, func, method, callField, data[0], data[1] });
4805 Return();
4806 break;
4807 case JSCallMode::CALL_THIS_WITH_ARGV:
4808 case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
4809 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallThisRangeAndDispatch),
4810 { glue, sp, func, method, callField, data[0], data[1], data[2] });
4811 Return();
4812 break;
4813 case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
4814 case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
4815 result = CallNGCRuntime(glue, RTSTUB_ID(PushCallNewAndDispatch),
4816 { glue, sp, func, method, callField, data[0], data[1], data[2] });
4817 Return();
4818 break;
4819 case JSCallMode::CALL_GETTER:
4820 result = CallNGCRuntime(glue, RTSTUB_ID(CallGetter),
4821 { glue, func, method, callField, data[0] });
4822 Jump(&exit);
4823 break;
4824 case JSCallMode::CALL_SETTER:
4825 result = CallNGCRuntime(glue, RTSTUB_ID(CallSetter),
4826 { glue, func, method, callField, data[1], data[0] });
4827 Jump(&exit);
4828 break;
4829 case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
4830 result = CallNGCRuntime(glue, RTSTUB_ID(CallContainersArgs3),
4831 { glue, func, method, callField, data[1], data[2], data[3], data[0] });
4832 Jump(&exit);
4833 break;
4834 default:
4835 UNREACHABLE();
4836 }
4837 }
4838 Bind(&exit);
4839 auto ret = *result;
4840 env->SubCfgExit();
4841 return ret;
4842 }
4843
CallFastPath(GateRef glue,GateRef nativeCode,GateRef func,GateRef thisValue,GateRef actualNumArgs,GateRef callField,GateRef method,Label * notFastBuiltins,Label * exit,Variable * result,std::initializer_list<GateRef> args,JSCallMode mode)4844 void StubBuilder::CallFastPath(GateRef glue, GateRef nativeCode, GateRef func, GateRef thisValue,
4845 GateRef actualNumArgs, GateRef callField, GateRef method, Label* notFastBuiltins, Label* exit, Variable* result,
4846 std::initializer_list<GateRef> args, JSCallMode mode)
4847 {
4848 auto env = GetEnvironment();
4849 Label isFastBuiltins(env);
4850 auto data = std::begin(args);
4851 GateRef numArgs = ZExtInt32ToPtr(actualNumArgs);
4852 GateRef isFastBuiltinsMask = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsFastBuiltinBit::START_BIT);
4853 Branch(Int64NotEqual(Int64And(callField, isFastBuiltinsMask), Int64(0)),
4854 &isFastBuiltins, notFastBuiltins);
4855 Bind(&isFastBuiltins);
4856 {
4857 GateRef builtinId = GetBuiltinId(method);
4858 GateRef ret;
4859 switch (mode) {
4860 case JSCallMode::CALL_THIS_ARG0:
4861 ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue, numArgs });
4862 break;
4863 case JSCallMode::CALL_THIS_ARG1:
4864 ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(),
4865 thisValue, numArgs, data[0] });
4866 break;
4867 case JSCallMode::CALL_THIS_ARG2:
4868 ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue,
4869 numArgs, data[0], data[1] });
4870 break;
4871 case JSCallMode::CALL_THIS_ARG3:
4872 ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue,
4873 numArgs, data[0], data[1], data[2] });
4874 break;
4875 case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
4876 case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
4877 ret = DispatchBuiltinsWithArgv(glue, builtinId, { glue, nativeCode, func, func, thisValue,
4878 numArgs, data[1] });
4879 break;
4880 default:
4881 UNREACHABLE();
4882 }
4883 result->WriteVariable(ret);
4884 Jump(exit);
4885 }
4886 Bind(notFastBuiltins);
4887 }
4888
TryStringOrSymbelToElementIndex(GateRef key)4889 GateRef StubBuilder::TryStringOrSymbelToElementIndex(GateRef key)
4890 {
4891 auto env = GetEnvironment();
4892 Label entry(env);
4893 env->SubCfgEntry(&entry);
4894 Label exit(env);
4895 DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
4896
4897 Label keyNotSymbol(env);
4898 Branch(IsSymbol(key), &exit, &keyNotSymbol);
4899 Bind(&keyNotSymbol);
4900
4901 Label greatThanZero(env);
4902 Label inRange(env);
4903 auto len = GetLengthFromString(key);
4904 Branch(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
4905 Bind(&greatThanZero);
4906 Branch(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
4907 Bind(&inRange);
4908 {
4909 Label isUtf8(env);
4910 Branch(IsUtf16String(key), &exit, &isUtf8);
4911 Bind(&isUtf8);
4912
4913 GateRef data = PtrAdd(key, IntPtr(EcmaString::DATA_OFFSET));
4914 DEFVARIABLE(c, VariableType::INT32(), Int32(0));
4915 c = ZExtInt8ToInt32(Load(VariableType::INT8(), data));
4916 Label isDigitZero(env);
4917 Label notDigitZero(env);
4918 Branch(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero);
4919 Bind(&isDigitZero);
4920 {
4921 Label lengthIsOne(env);
4922 Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
4923 Bind(&lengthIsOne);
4924 {
4925 result = Int32(0);
4926 Jump(&exit);
4927 }
4928 }
4929 Bind(¬DigitZero);
4930 {
4931 Label isDigit(env);
4932 Label notIsDigit(env);
4933 DEFVARIABLE(i, VariableType::INT32(), Int32(1));
4934 DEFVARIABLE(n, VariableType::INT32(), Int32Sub(*c, Int32('0')));
4935
4936 Branch(IsDigit(*c), &isDigit, ¬IsDigit);
4937 Label loopHead(env);
4938 Label loopEnd(env);
4939 Label afterLoop(env);
4940 Bind(&isDigit);
4941 Branch(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
4942 LoopBegin(&loopHead);
4943 {
4944 c = ZExtInt8ToInt32(Load(VariableType::INT8(), data, ZExtInt32ToPtr(*i)));
4945 Label isDigit2(env);
4946 Label notDigit2(env);
4947 Branch(IsDigit(*c), &isDigit2, ¬Digit2);
4948 Bind(&isDigit2);
4949 {
4950 // 10 means the base of digit is 10.
4951 n = Int32Add(Int32Mul(*n, Int32(10)),
4952 Int32Sub(*c, Int32('0')));
4953 i = Int32Add(*i, Int32(1));
4954 Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
4955 }
4956 Bind(¬Digit2);
4957 {
4958 Label hasPoint(env);
4959 Branch(Int32Equal(*c, Int32('.')), &hasPoint, &exit);
4960 Bind(&hasPoint);
4961 {
4962 result = Int32(-2); // -2:return -2 means should goto slow path
4963 Jump(&exit);
4964 }
4965 }
4966 }
4967 Bind(&loopEnd);
4968 LoopEnd(&loopHead);
4969 Bind(&afterLoop);
4970 {
4971 Label lessThanMaxIndex(env);
4972 Branch(Int32UnsignedLessThan(*n, Int32(JSObject::MAX_ELEMENT_INDEX)),
4973 &lessThanMaxIndex, &exit);
4974 Bind(&lessThanMaxIndex);
4975 {
4976 result = *n;
4977 Jump(&exit);
4978 }
4979 }
4980 Bind(¬IsDigit);
4981 {
4982 Label isNegative(env);
4983 Branch(Int32Equal(*c, Int32('-')), &isNegative, &exit);
4984 Bind(&isNegative);
4985 {
4986 result = Int32(-2); // -2:return -2 means should goto slow path
4987 Jump(&exit);
4988 }
4989 }
4990 }
4991 }
4992 Bind(&exit);
4993 auto ret = *result;
4994 env->SubCfgExit();
4995 return ret;
4996 }
4997
GetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef jsType)4998 GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder,
4999 GateRef key, GateRef jsType)
5000 {
5001 auto env = GetEnvironment();
5002 Label entry(env);
5003 env->SubCfgEntry(&entry);
5004 Label exit(env);
5005 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5006
5007 Label notOnProtoChain(env);
5008 Branch(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
5009 Bind(¬OnProtoChain);
5010
5011 auto negativeZero = GetGlobalConstantValue(
5012 VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
5013 Label isNegativeZero(env);
5014 Label notNegativeZero(env);
5015 Branch(Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
5016 Bind(&isNegativeZero);
5017 {
5018 result = Undefined();
5019 Jump(&exit);
5020 }
5021 Bind(¬NegativeZero);
5022 {
5023 GateRef index = TryStringOrSymbelToElementIndex(key);
5024 Label validIndex(env);
5025 Label notValidIndex(env);
5026 Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
5027 Bind(&validIndex);
5028 {
5029 result = CallRuntime(glue, RTSTUB_ID(GetTypeArrayPropertyByIndex),
5030 { holder, IntToTaggedInt(index), IntToTaggedInt(jsType) });
5031 Jump(&exit);
5032 }
5033 Bind(¬ValidIndex);
5034 {
5035 Label returnNull(env);
5036 Branch(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
5037 Bind(&returnNull);
5038 {
5039 result = Null();
5040 Jump(&exit);
5041 }
5042 }
5043 }
5044
5045 Bind(&exit);
5046 auto ret = *result;
5047 env->SubCfgExit();
5048 return ret;
5049 }
5050
SetTypeArrayPropertyByName(GateRef glue,GateRef receiver,GateRef holder,GateRef key,GateRef value,GateRef jsType)5051 GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key,
5052 GateRef value, GateRef jsType)
5053 {
5054 auto env = GetEnvironment();
5055 Label entry(env);
5056 env->SubCfgEntry(&entry);
5057 Label exit(env);
5058 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
5059 Label notOnProtoChain(env);
5060 Branch(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
5061 Bind(¬OnProtoChain);
5062
5063 auto negativeZero = GetGlobalConstantValue(
5064 VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
5065 Label isNegativeZero(env);
5066 Label notNegativeZero(env);
5067 Branch(Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
5068 Bind(&isNegativeZero);
5069 {
5070 Label isObj(env);
5071 Label notObj(env);
5072 Branch(IsEcmaObject(value), &isObj, ¬Obj);
5073 Bind(&isObj);
5074 {
5075 result = Null();
5076 Jump(&exit);
5077 }
5078 Bind(¬Obj);
5079 result = Undefined();
5080 Jump(&exit);
5081 }
5082 Bind(¬NegativeZero);
5083 {
5084 GateRef index = TryStringOrSymbelToElementIndex(key);
5085 Label validIndex(env);
5086 Label notValidIndex(env);
5087 Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
5088 Bind(&validIndex);
5089 {
5090 result = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
5091 { receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType) });
5092 Jump(&exit);
5093 }
5094 Bind(¬ValidIndex);
5095 {
5096 Label returnNull(env);
5097 Branch(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
5098 Bind(&returnNull);
5099 {
5100 result = Null();
5101 Jump(&exit);
5102 }
5103 }
5104 }
5105
5106 Bind(&exit);
5107 auto ret = *result;
5108 env->SubCfgExit();
5109 return ret;
5110 }
5111
PGOProfiler(GateRef glue,GateRef func)5112 void StubBuilder::PGOProfiler(GateRef glue, GateRef func)
5113 {
5114 auto env = GetEnvironment();
5115 if (env->IsAsmInterp()) {
5116 Label subEntry(env);
5117 env->SubCfgEntry(&subEntry);
5118
5119 // Decode bitfield
5120 GateRef stateBitFieldAddr = Int64Add(glue,
5121 Int64(JSThread::GlueData::GetStateBitFieldOffset(env->Is32Bit())));
5122 GateRef stateBitField = Load(VariableType::INT64(), stateBitFieldAddr, Int64(0));
5123 // equal stateBitField >> JSThread::CONCURRENT_MARKING_BITFIELD_NUM
5124 GateRef profilerBitOffset = Int64LSR(stateBitField, Int64(JSThread::CONCURRENT_MARKING_BITFIELD_NUM));
5125 // mask: 1 << JSThread::PGO_PROFILER_BITFIELD_NUM - 1
5126 GateRef profilerBitMask = Int64Sub(Int64LSL(Int64(1), Int64(JSThread::PGO_PROFILER_BITFIELD_NUM)), Int64(1));
5127 GateRef state = Int64And(profilerBitOffset, profilerBitMask);
5128 Label exit(env);
5129 Label pgoProfiler(env);
5130 Branch(Int64Equal(state, Int64(static_cast<int64_t>(PGOProfilerStatus::PGO_PROFILER_ENABLE))),
5131 &pgoProfiler, &exit);
5132 Bind(&pgoProfiler);
5133 {
5134 CallNGCRuntime(glue, RTSTUB_ID(PGOProfiler), { glue, func });
5135 Jump(&exit);
5136 }
5137 Bind(&exit);
5138 env->SubCfgExit();
5139 }
5140 }
5141
Assert(int messageId,int line,GateRef glue,GateRef condition,Label * nextLabel)5142 void StubBuilder::Assert(int messageId, int line, GateRef glue, GateRef condition, Label *nextLabel)
5143 {
5144 auto env = GetEnvironment();
5145 Label ok(env);
5146 Label notOk(env);
5147 Branch(condition, &ok, ¬Ok);
5148 Bind(&ok);
5149 {
5150 Jump(nextLabel);
5151 }
5152 Bind(¬Ok);
5153 {
5154 FatalPrint(glue, { Int32(messageId), Int32(line) });
5155 Jump(nextLabel);
5156 }
5157 }
5158 } // namespace panda::ecmascript::kungfu
5159