1 /*
2 * Copyright (c) 2023 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/builtins/builtins_object_stub_builder.h"
17
18 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
19 #include "ecmascript/compiler/new_object_stub_builder.h"
20 #include "ecmascript/js_primitive_ref.h"
21
22 namespace panda::ecmascript::kungfu {
ToStringFunc(Variable * result,Label * exit,Label * slowPath)23 void BuiltinsObjectStubBuilder::ToStringFunc(Variable *result, Label *exit, Label *slowPath)
24 {
25 auto env = GetEnvironment();
26 Label ecmaObj(env);
27 // undefined
28 Label undefined(env);
29 Label checknull(env);
30 BRANCH(TaggedIsUndefined(thisValue_), &undefined, &checknull);
31 Bind(&undefined);
32 {
33 *result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::UNDEFINED_TO_STRING_INDEX);
34 Jump(exit);
35 }
36 // null
37 Bind(&checknull);
38 Label null(env);
39 Label checkObject(env);
40 BRANCH(TaggedIsUndefined(thisValue_), &null, &checkObject);
41 Bind(&null);
42 {
43 *result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::NULL_TO_STRING_INDEX);
44 Jump(exit);
45 }
46
47 Bind(&checkObject);
48 BRANCH(IsEcmaObject(thisValue_), &ecmaObj, slowPath);
49 Bind(&ecmaObj);
50 {
51 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
52 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset);
53 GateRef toStringTagSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
54 GlobalEnv::TOSTRINGTAG_SYMBOL_INDEX);
55 GateRef tag = FastGetPropertyByName(glue_, thisValue_, toStringTagSymbol, ProfileOperation());
56
57 Label defaultToString(env);
58 BRANCH(TaggedIsString(tag), slowPath, &defaultToString);
59 Bind(&defaultToString);
60 {
61 // default object
62 Label objectTag(env);
63 BRANCH(IsJSObjectType(thisValue_, JSType::JS_OBJECT), &objectTag, slowPath);
64 Bind(&objectTag);
65 {
66 // [object object]
67 *result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
68 ConstantIndex::OBJECT_TO_STRING_INDEX);
69 Jump(exit);
70 }
71 }
72 }
73 }
74
Create(Variable * result,Label * exit,Label * slowPath)75 void BuiltinsObjectStubBuilder::Create(Variable *result, Label *exit, Label *slowPath)
76 {
77 auto env = GetEnvironment();
78 Label newObject(env);
79
80 GateRef proto = GetCallArg0(numArgs_);
81 GateRef protoCheck = LogicAndBuilder(env).And(BoolNot(IsEcmaObject(proto)))
82 .And(BoolNot(TaggedIsNull(proto))).Done();
83 BRANCH(LogicOrBuilder(env).Or(protoCheck).Or(TaggedIsSharedObj(proto)).Done(), slowPath, &newObject);
84 Bind(&newObject);
85 {
86 Label noProperties(env);
87 GateRef propertiesObject = GetCallArg1(numArgs_);
88 BRANCH(TaggedIsUndefined(propertiesObject), &noProperties, slowPath);
89 Bind(&noProperties);
90 {
91 // OrdinaryNewJSObjectCreate
92 *result = OrdinaryNewJSObjectCreate(glue_, proto);
93 Jump(exit);
94 }
95 }
96 }
97
AssignEnumElementProperty(Variable * result,Label * funcExit,GateRef toAssign,GateRef source)98 void BuiltinsObjectStubBuilder::AssignEnumElementProperty(Variable *result, Label *funcExit,
99 GateRef toAssign, GateRef source)
100 {
101 auto env = GetEnvironment();
102 Label entryLabel(env);
103 env->SubCfgEntry(&entryLabel);
104 Label exit(env);
105
106 GateRef elements = GetElementsArray(source);
107 Label dictionaryMode(env);
108 Label notDictionaryMode(env);
109 BRANCH(IsDictionaryMode(elements), &dictionaryMode, ¬DictionaryMode);
110 Bind(¬DictionaryMode);
111 {
112 GateRef len = GetLengthOfTaggedArray(elements);
113 DEFVARIABLE(idx, VariableType::INT32(), Int32(0));
114 Label loopHead(env);
115 Label loopEnd(env);
116 Label next(env);
117 Label loopExit(env);
118
119 Jump(&loopHead);
120 LoopBegin(&loopHead);
121 {
122 BRANCH(Int32LessThan(*idx, len), &next, &loopExit);
123 Bind(&next);
124 GateRef value = GetTaggedValueWithElementsKind(glue_, source, *idx);
125 Label notHole(env);
126 BRANCH(TaggedIsHole(value), &loopEnd, ¬Hole);
127 Bind(¬Hole);
128 {
129 // key, value
130 FastSetPropertyByIndex(glue_, toAssign, *idx, value);
131 Label exception(env);
132 BRANCH(HasPendingException(glue_), &exception, &loopEnd);
133 Bind(&exception);
134 {
135 *result = Exception();
136 Jump(funcExit);
137 }
138 }
139 }
140 Bind(&loopEnd);
141 idx = Int32Add(*idx, Int32(1));
142 LoopEnd(&loopHead, env, glue_);
143 Bind(&loopExit);
144 Jump(&exit);
145 }
146 Bind(&dictionaryMode);
147 {
148 // NumberDictionary::VisitAllEnumProperty
149 GateRef sizeIndex = Int32(TaggedHashTable<NumberDictionary>::SIZE_INDEX);
150 GateRef size = GetInt32OfTInt(GetValueFromTaggedArray(elements, sizeIndex));
151 DEFVARIABLE(idx, VariableType::INT32(), Int32(0));
152 Label loopHead(env);
153 Label loopEnd(env);
154 Label next(env);
155 Label loopExit(env);
156
157 Jump(&loopHead);
158 LoopBegin(&loopHead);
159 {
160 BRANCH(Int32LessThan(*idx, size), &next, &loopExit);
161 Bind(&next);
162 GateRef key = GetKeyFromDictionary<NumberDictionary>(elements, *idx);
163 Label checkEnumerable(env);
164 BRANCH(LogicOrBuilder(env).Or(TaggedIsUndefined(key)).Or(TaggedIsHole(key)).Done(),
165 &loopEnd, &checkEnumerable);
166 Bind(&checkEnumerable);
167 {
168 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, *idx);
169 Label enumerable(env);
170 BRANCH(IsEnumerable(attr), &enumerable, &loopEnd);
171 Bind(&enumerable);
172 {
173 GateRef value = GetValueFromDictionary<NumberDictionary>(elements, *idx);
174 Label notHole(env);
175 BRANCH(TaggedIsHole(value), &loopEnd, ¬Hole);
176 Bind(¬Hole);
177 {
178 // value
179 FastSetPropertyByIndex(glue_, toAssign, *idx, value);
180 Label exception(env);
181 BRANCH(HasPendingException(glue_), &exception, &loopEnd);
182 Bind(&exception);
183 {
184 *result = Exception();
185 Jump(funcExit);
186 }
187 }
188 }
189 }
190 }
191 Bind(&loopEnd);
192 idx = Int32Add(*idx, Int32(1));
193 LoopEnd(&loopHead, env, glue_);
194 Bind(&loopExit);
195 Jump(&exit);
196 }
197 Bind(&exit);
198 env->SubCfgExit();
199 }
200
LayoutInfoAssignAllEnumProperty(Variable * result,Label * funcExit,GateRef toAssign,GateRef source)201 void BuiltinsObjectStubBuilder::LayoutInfoAssignAllEnumProperty(Variable *result, Label *funcExit,
202 GateRef toAssign, GateRef source)
203 {
204 auto env = GetEnvironment();
205 Label entryLabel(env);
206 env->SubCfgEntry(&entryLabel);
207 Label exit(env);
208
209 // LayoutInfo::VisitAllEnumProperty
210 GateRef cls = LoadHClass(source);
211 GateRef num = GetNumberOfPropsFromHClass(cls);
212 GateRef layout = GetLayoutFromHClass(cls);
213 DEFVARIABLE(idx, VariableType::INT32(), Int32(0));
214 Label loopHead(env);
215 Label loopEnd(env);
216 Label next(env);
217 Label loopExit(env);
218
219 Jump(&loopHead);
220 LoopBegin(&loopHead);
221 {
222 BRANCH(Int32LessThan(*idx, num), &next, &loopExit);
223 Bind(&next);
224
225 GateRef key = GetKeyFromLayoutInfo(layout, *idx);
226 GateRef attr = GetPropAttrFromLayoutInfo(layout, *idx);
227 Label stringKey(env);
228 BRANCH(TaggedIsStringOrSymbol(key), &stringKey, &loopEnd);
229 Bind(&stringKey);
230 {
231 Label enumerable(env);
232 BRANCH(IsEnumerable(attr), &enumerable, &loopEnd);
233 Bind(&enumerable);
234 {
235 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
236 value = JSObjectGetProperty(source, cls, attr);
237 // exception
238 Label exception0(env);
239 Label noexception0(env);
240 BRANCH(HasPendingException(glue_), &exception0, &noexception0);
241 Bind(&exception0);
242 {
243 *result = Exception();
244 Jump(funcExit);
245 }
246 Bind(&noexception0);
247 Label propertyBox(env);
248 Label checkAccessor(env);
249 Label setValue(env);
250 BRANCH(TaggedIsPropertyBox(*value), &propertyBox, &checkAccessor);
251 Bind(&propertyBox);
252 {
253 value = GetValueFromPropertyBox(*value);
254 Jump(&setValue);
255 }
256 Bind(&checkAccessor);
257 Label isAccessor(env);
258 BRANCH(IsAccessor(attr), &isAccessor, &setValue);
259 Bind(&isAccessor);
260 {
261 value = CallGetterHelper(glue_, source, source, *value, ProfileOperation());
262 Label exception(env);
263 BRANCH(HasPendingException(glue_), &exception, &setValue);
264 Bind(&exception);
265 {
266 *result = Exception();
267 Jump(funcExit);
268 }
269 }
270 Bind(&setValue);
271 {
272 FastSetPropertyByName(glue_, toAssign, key, *value);
273 Label exception(env);
274 BRANCH(HasPendingException(glue_), &exception, &loopEnd);
275 Bind(&exception);
276 {
277 *result = Exception();
278 Jump(funcExit);
279 }
280 }
281 }
282 }
283 }
284 Bind(&loopEnd);
285 idx = Int32Add(*idx, Int32(1));
286 LoopEnd(&loopHead, env, glue_);
287 Bind(&loopExit);
288 Jump(&exit);
289
290 Bind(&exit);
291 env->SubCfgExit();
292 }
293
NameDictionaryAssignAllEnumProperty(Variable * result,Label * funcExit,GateRef toAssign,GateRef source,GateRef properties)294 void BuiltinsObjectStubBuilder::NameDictionaryAssignAllEnumProperty(Variable *result, Label *funcExit,
295 GateRef toAssign, GateRef source, GateRef properties)
296 {
297 // NameDictionary::VisitAllEnumProperty
298 auto env = GetEnvironment();
299 Label entryLabel(env);
300 env->SubCfgEntry(&entryLabel);
301 Label exit(env);
302
303 GateRef sizeIndex = Int32(TaggedHashTable<NameDictionary>::SIZE_INDEX);
304 GateRef size = GetInt32OfTInt(GetValueFromTaggedArray(properties, sizeIndex));
305 DEFVARIABLE(idx, VariableType::INT32(), Int32(0));
306 Label loopHead(env);
307 Label loopEnd(env);
308 Label next(env);
309 Label loopExit(env);
310
311 Jump(&loopHead);
312 LoopBegin(&loopHead);
313 {
314 BRANCH(Int32LessThan(*idx, size), &next, &loopExit);
315 Bind(&next);
316 GateRef key = GetKeyFromDictionary<NameDictionary>(properties, *idx);
317 Label stringKey(env);
318 BRANCH(TaggedIsStringOrSymbol(key), &stringKey, &loopEnd);
319 Bind(&stringKey);
320 {
321 GateRef attr = GetAttributesFromDictionary<NameDictionary>(properties, *idx);
322 Label enumerable(env);
323 BRANCH(IsEnumerable(attr), &enumerable, &loopEnd);
324 Bind(&enumerable);
325 {
326 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
327 value = GetValueFromDictionary<NameDictionary>(properties, *idx);
328 Label notHole(env);
329 BRANCH(TaggedIsHole(*value), &loopEnd, ¬Hole);
330 Bind(¬Hole);
331 {
332 Label isAccessor(env);
333 Label notAccessor(env);
334 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor);
335 Bind(&isAccessor);
336 {
337 value = CallGetterHelper(glue_, source, source, *value, ProfileOperation());
338 // exception
339 Label exception(env);
340 BRANCH(HasPendingException(glue_), &exception, ¬Accessor);
341 Bind(&exception);
342 {
343 *result = Exception();
344 Jump(funcExit);
345 }
346 }
347 Bind(¬Accessor);
348 {
349 FastSetPropertyByName(glue_, toAssign, key, *value);
350 Label exception(env);
351 BRANCH(HasPendingException(glue_), &exception, &loopEnd);
352 Bind(&exception);
353 {
354 *result = Exception();
355 Jump(funcExit);
356 }
357 }
358 }
359 }
360 }
361 }
362 Bind(&loopEnd);
363 idx = Int32Add(*idx, Int32(1));
364 LoopEnd(&loopHead, env, glue_);
365 Bind(&loopExit);
366 Jump(&exit);
367
368 Bind(&exit);
369 env->SubCfgExit();
370 }
371
AssignAllEnumProperty(Variable * res,Label * funcExit,GateRef toAssign,GateRef source)372 void BuiltinsObjectStubBuilder::AssignAllEnumProperty(Variable *res, Label *funcExit,
373 GateRef toAssign, GateRef source)
374 {
375 auto env = GetEnvironment();
376 Label entryLabel(env);
377 env->SubCfgEntry(&entryLabel);
378 Label exit(env);
379
380 GateRef properties = GetPropertiesArray(source);
381 Label dictionaryMode(env);
382 Label notDictionaryMode(env);
383 BRANCH(IsDictionaryMode(properties), &dictionaryMode, ¬DictionaryMode);
384 Bind(¬DictionaryMode);
385 {
386 LayoutInfoAssignAllEnumProperty(res, funcExit, toAssign, source);
387 Jump(&exit);
388 }
389 Bind(&dictionaryMode);
390 {
391 NameDictionaryAssignAllEnumProperty(res, funcExit, toAssign, source, properties);
392 Jump(&exit);
393 }
394 Bind(&exit);
395 env->SubCfgExit();
396 }
397
SlowAssign(Variable * result,Label * funcExit,GateRef toAssign,GateRef source)398 void BuiltinsObjectStubBuilder::SlowAssign(Variable *result, Label *funcExit, GateRef toAssign, GateRef source)
399 {
400 auto env = GetEnvironment();
401 Label entryLabel(env);
402 env->SubCfgEntry(&entryLabel);
403 Label exit(env);
404 CallRuntime(glue_, RTSTUB_ID(ObjectSlowAssign), { toAssign, source });
405
406 Label exception(env);
407 BRANCH(HasPendingException(glue_), &exception, &exit);
408 Bind(&exception);
409 {
410 *result = Exception();
411 Jump(funcExit);
412 }
413 Bind(&exit);
414 env->SubCfgExit();
415 }
416
FastAssign(Variable * res,Label * funcExit,GateRef toAssign,GateRef source)417 void BuiltinsObjectStubBuilder::FastAssign(Variable *res, Label *funcExit, GateRef toAssign, GateRef source)
418 {
419 // visit elements
420 AssignEnumElementProperty(res, funcExit, toAssign, source);
421 AssignAllEnumProperty(res, funcExit, toAssign, source);
422 }
423
Assign(Variable * res,Label * nextIt,Label * funcExit,GateRef toAssign,GateRef source)424 void BuiltinsObjectStubBuilder::Assign(Variable *res, Label *nextIt, Label *funcExit,
425 GateRef toAssign, GateRef source)
426 {
427 auto env = GetEnvironment();
428 Label checkJsObj(env);
429 BRANCH(TaggedIsUndefinedOrNull(source), nextIt, &checkJsObj);
430 Bind(&checkJsObj);
431 {
432 Label fastAssign(env);
433 Label slowAssign(env);
434 BRANCH(IsJSObjectType(source, JSType::JS_OBJECT), &fastAssign, &slowAssign);
435 Bind(&fastAssign);
436 {
437 FastAssign(res, funcExit, toAssign, source);
438 Jump(nextIt);
439 }
440 Bind(&slowAssign);
441 {
442 SlowAssign(res, funcExit, toAssign, source);
443 Jump(nextIt);
444 }
445 }
446 }
447
Assign(Variable * result,Label * exit,Label * slowPath)448 void BuiltinsObjectStubBuilder::Assign(Variable *result, Label *exit, Label *slowPath)
449 {
450 auto env = GetEnvironment();
451 Label thisCollectionObj(env);
452
453 GateRef target = GetCallArg0(numArgs_);
454 *result = target;
455 Label jsObject(env);
456 BRANCH(IsJSObjectType(target, JSType::JS_OBJECT), &jsObject, slowPath);
457 Bind(&jsObject);
458 {
459 Label twoArg(env);
460 Label notTwoArg(env);
461 BRANCH(Int64Equal(numArgs_, IntPtr(2)), &twoArg, ¬TwoArg); // 2 : two args
462 Bind(&twoArg);
463 {
464 GateRef source = GetCallArg1(numArgs_);
465 Label next(env);
466 Assign(result, &next, exit, target, source);
467 Bind(&next);
468 Jump(exit);
469 }
470 Bind(¬TwoArg);
471 Label threeArg(env);
472 Label notThreeArg(env);
473 BRANCH(Int64Equal(numArgs_, IntPtr(3)), &threeArg, ¬ThreeArg); // 3 : three args
474 Bind(&threeArg);
475 {
476 Label nextArg(env);
477 GateRef source = GetCallArg1(numArgs_);
478 Label next(env);
479 Assign(result, &next, exit, target, source);
480 Bind(&next);
481 Label next1(env);
482 GateRef source1 = GetCallArg2(numArgs_);
483 Assign(result, &next1, exit, target, source1);
484 Bind(&next1);
485 Jump(exit);
486 }
487 Bind(¬ThreeArg);
488 {
489 Jump(slowPath);
490 }
491 }
492 }
493
HasOwnProperty(Variable * result,Label * exit,Label * slowPath)494 void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, Label *slowPath)
495 {
496 GateRef prop = GetCallArg0(numArgs_);
497 HasOwnProperty(result, exit, slowPath, thisValue_, prop);
498 }
499
HasOwnProperty(Variable * result,Label * exit,Label * slowPath,GateRef thisValue,GateRef prop,GateRef hir)500 void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, Label *slowPath, GateRef thisValue,
501 GateRef prop, GateRef hir)
502 {
503 auto env = GetEnvironment();
504 Label keyIsString(env);
505 Label valid(env);
506 Label isHeapObject(env);
507 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
508 Bind(&isHeapObject);
509 BRANCH(TaggedIsRegularObject(thisValue), &valid, slowPath);
510 Bind(&valid);
511 {
512 Label isIndex(env);
513 Label notIndex(env);
514 BRANCH(TaggedIsString(prop), &keyIsString, slowPath); // 2 : two args
515 Bind(&keyIsString);
516 {
517 GateRef res = StringToElementIndex(glue_, prop);
518 // -1: not find element index
519 BRANCH(Int64NotEqual(res, Int64(-1)), &isIndex, ¬Index);
520 Bind(&isIndex);
521 {
522 GateRef index = TruncInt64ToInt32(res);
523 Label findByIndex(env);
524 GateRef elements = GetElementsArray(thisValue);
525 GateRef len = GetLengthOfTaggedArray(elements);
526 BRANCH(Int32Equal(len, Int32(0)), exit, &findByIndex);
527 Bind(&findByIndex);
528 {
529 Label isDictionaryElement(env);
530 Label notDictionaryElement(env);
531 BRANCH(IsDictionaryMode(elements), &isDictionaryElement, ¬DictionaryElement);
532 Bind(¬DictionaryElement);
533 {
534 Label lessThanLength(env);
535 Label notLessThanLength(env);
536 BRANCH(Int32UnsignedLessThanOrEqual(len, index), exit, &lessThanLength);
537 Bind(&lessThanLength);
538 {
539 Label notHole(env);
540 GateRef value = GetTaggedValueWithElementsKind(glue_, thisValue, index);
541 BRANCH(TaggedIsNotHole(value), ¬Hole, exit);
542 Bind(¬Hole);
543 {
544 *result = TaggedTrue();
545 Jump(exit);
546 }
547 }
548 }
549 Bind(&isDictionaryElement);
550 {
551 GateRef entryA = FindElementFromNumberDictionary(glue_, elements, index);
552 Label notNegtiveOne(env);
553 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, exit);
554 Bind(¬NegtiveOne);
555 {
556 *result = TaggedTrue();
557 Jump(exit);
558 }
559 }
560 }
561 }
562 Bind(¬Index);
563 {
564 Label findInStringTabel(env);
565 Label notInternString(env);
566 DEFVARIABLE(stringTable, VariableType::JS_ANY(), prop);
567 BRANCH(IsInternalString(prop), &findInStringTabel, ¬InternString);
568 Bind(¬InternString);
569 {
570 GateRef internString = CallRuntime(glue_, RTSTUB_ID(TryGetInternString), { prop });
571 stringTable = internString;
572 BRANCH(TaggedIsHole(internString), exit, &findInStringTabel)
573 }
574 Bind(&findInStringTabel);
575 {
576 Label isDicMode(env);
577 Label notDicMode(env);
578 GateRef hclass = LoadHClass(thisValue);
579 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode);
580 Bind(¬DicMode);
581 {
582 GateRef layOutInfo = GetLayoutFromHClass(hclass);
583 GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
584 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
585 GateRef entryA = FindElementWithCache(glue_, layOutInfo, hclass, *stringTable, propsNum, hir);
586 Label hasEntry(env);
587 // if branch condition : entry != -1
588 BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, exit);
589 Bind(&hasEntry);
590 {
591 *result = TaggedTrue();
592 Jump(exit);
593 }
594 }
595 Bind(&isDicMode);
596 {
597 GateRef array = GetPropertiesArray(thisValue);
598 // int entry = dict->FindEntry(key)
599 GateRef entryB = FindEntryFromNameDictionary(glue_, array, *stringTable, hir);
600 Label notNegtiveOne(env);
601 // if branch condition : entry != -1
602 BRANCH(Int32NotEqual(entryB, Int32(-1)), ¬NegtiveOne, exit);
603 Bind(¬NegtiveOne);
604 {
605 *result = TaggedTrue();
606 Jump(exit);
607 }
608 }
609 }
610 }
611 }
612 }
613 }
614
GetNumKeysFromLayoutInfo(GateRef end,GateRef layoutInfo)615 GateRef BuiltinsObjectStubBuilder::GetNumKeysFromLayoutInfo(GateRef end, GateRef layoutInfo)
616 {
617 auto env = GetEnvironment();
618 Label entry(env);
619 env->SubCfgEntry(&entry);
620 Label exit(env);
621 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
622 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
623
624 Label loopHead(env);
625 Label loopEnd(env);
626 Label iLessEnd(env);
627 Label isString(env);
628 Label isEnumerable(env);
629 Jump(&loopHead);
630 LoopBegin(&loopHead);
631 {
632 BRANCH(Int32UnsignedLessThan(*i, end), &iLessEnd, &exit);
633 Bind(&iLessEnd);
634 {
635 GateRef key = GetKey(layoutInfo, *i);
636 BRANCH(TaggedIsString(key), &isString, &loopEnd);
637 Bind(&isString);
638 BRANCH(IsEnumerable(GetAttr(layoutInfo, *i)), &isEnumerable, &loopEnd);
639 Bind(&isEnumerable);
640 result = Int32Add(*result, Int32(1));
641 Jump(&loopEnd);
642 }
643 Bind(&loopEnd);
644 i = Int32Add(*i, Int32(1));
645 LoopEnd(&loopHead, env, glue_);
646 }
647 Bind(&exit);
648 auto ret = *result;
649 env->SubCfgExit();
650 return ret;
651 }
652
GetNumKeysFromDictionary(GateRef array)653 GateRef BuiltinsObjectStubBuilder::GetNumKeysFromDictionary(GateRef array)
654 {
655 auto env = GetEnvironment();
656 Label entry(env);
657 env->SubCfgEntry(&entry);
658 Label exit(env);
659
660 GateRef sizeIndex = Int32(TaggedHashTable<NameDictionary>::SIZE_INDEX);
661 GateRef size = GetInt32OfTInt(GetValueFromTaggedArray(array, sizeIndex));
662 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
663 DEFVARIABLE(result, VariableType::INT32(), Int32(0));
664
665 Label loopHead(env);
666 Label loopEnd(env);
667 Label afterLoop(env);
668 Label iLessSize(env);
669 Label isString(env);
670 Label isEnumerable(env);
671
672 Jump(&loopHead);
673 LoopBegin(&loopHead);
674 {
675 BRANCH(Int32UnsignedLessThan(*i, size), &iLessSize, &afterLoop);
676 Bind(&iLessSize);
677 {
678 GateRef key = GetKeyFromDictionary<NameDictionary>(array, *i);
679 BRANCH(TaggedIsString(key), &isString, &loopEnd);
680 Bind(&isString);
681 GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, *i);
682 BRANCH(IsEnumerable(attr), &isEnumerable, &loopEnd);
683 Bind(&isEnumerable);
684 result = Int32Add(*result, Int32(1));
685 Jump(&loopEnd);
686 }
687 Bind(&loopEnd);
688 i = Int32Add(*i, Int32(1));
689 LoopEnd(&loopHead, env, glue_);
690 }
691 Bind(&afterLoop);
692 Jump(&exit);
693
694 Bind(&exit);
695 auto ret = *result;
696 env->SubCfgExit();
697 return ret;
698 }
699
LayoutInfoGetAllEnumKeys(GateRef end,GateRef offset,GateRef array,GateRef layoutInfo)700 void BuiltinsObjectStubBuilder::LayoutInfoGetAllEnumKeys(GateRef end, GateRef offset, GateRef array, GateRef layoutInfo)
701 {
702 auto env = GetEnvironment();
703 Label entry(env);
704 env->SubCfgEntry(&entry);
705 Label exit(env);
706 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
707 DEFVARIABLE(enumKeys, VariableType::INT32(), Int32(0));
708 Label loopHead(env);
709 Label loopEnd(env);
710 Label afterLoop(env);
711 Label iLessEnd(env);
712 Label isEnumerable(env);
713 Jump(&loopHead);
714 LoopBegin(&loopHead);
715 {
716 BRANCH(Int32UnsignedLessThan(*i, end), &iLessEnd, &afterLoop);
717 Bind(&iLessEnd);
718 {
719 GateRef key = GetKey(layoutInfo, *i);
720 GateRef iVal = *i;
721 BRANCH(LogicAndBuilder(env).And(TaggedIsString(key)).And(IsEnumerable(GetAttr(layoutInfo, iVal))).Done(),
722 &isEnumerable, &loopEnd);
723 Bind(&isEnumerable);
724 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, array, Int32Add(*enumKeys, offset), key);
725 enumKeys = Int32Add(*enumKeys, Int32(1));
726 Jump(&loopEnd);
727 }
728 Bind(&loopEnd);
729 i = Int32Add(*i, Int32(1));
730 LoopEnd(&loopHead, env, glue_);
731 }
732 Bind(&afterLoop);
733 Jump(&exit);
734 Bind(&exit);
735 env->SubCfgExit();
736 }
737
CopyFromEnumCache(GateRef glue,GateRef elements)738 GateRef BuiltinsObjectStubBuilder::CopyFromEnumCache(GateRef glue, GateRef elements)
739 {
740 auto env = GetEnvironment();
741 Label subEntry(env);
742 env->SubCfgEntry(&subEntry);
743 Label exit(env);
744 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
745 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
746 DEFVARIABLE(newLen, VariableType::INT32(), Int32(0));
747 NewObjectStubBuilder newBuilder(this);
748
749 Label lenIsZero(env);
750 Label lenNotZero(env);
751 Label afterLenCon(env);
752 GateRef oldLen = GetLengthOfTaggedArray(elements);
753 BRANCH(Int32Equal(oldLen, Int32(0)), &lenIsZero, &lenNotZero);
754 {
755 Bind(&lenIsZero);
756 {
757 newLen = Int32(0);
758 Jump(&afterLenCon);
759 }
760 Bind(&lenNotZero);
761 newLen = Int32Sub(oldLen, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE));
762 Jump(&afterLenCon);
763 }
764 Bind(&afterLenCon);
765 GateRef array = newBuilder.NewTaggedArray(glue, *newLen);
766 Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::LENGTH_OFFSET), *newLen);
767 GateRef oldExtractLen = GetExtraLengthOfTaggedArray(elements);
768 Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
769 Label loopHead(env);
770 Label loopEnd(env);
771 Label afterLoop(env);
772 Label storeValue(env);
773 Jump(&loopHead);
774 LoopBegin(&loopHead);
775 {
776 BRANCH(Int32UnsignedLessThan(*index, *newLen), &storeValue, &afterLoop);
777 Bind(&storeValue);
778 {
779 GateRef value = GetValueFromTaggedArray(elements, Int32Add(*index,
780 Int32(EnumCache::ENUM_CACHE_HEADER_SIZE)));
781 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value);
782 index = Int32Add(*index, Int32(1));
783 Jump(&loopEnd);
784 }
785 }
786 Bind(&loopEnd);
787 LoopEnd(&loopHead, env, glue);
788 Bind(&afterLoop);
789 {
790 result = array;
791 Jump(&exit);
792 }
793 Bind(&exit);
794 auto ret = *result;
795 env->SubCfgExit();
796 return ret;
797 }
798
GetAllEnumKeys(GateRef glue,GateRef obj)799 GateRef BuiltinsObjectStubBuilder::GetAllEnumKeys(GateRef glue, GateRef obj)
800 {
801 auto env = GetEnvironment();
802 Label subEntry(env);
803 env->SubCfgEntry(&subEntry);
804 Label exit(env);
805 Label isDictionary(env);
806 Label notDictionary(env);
807 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
808 GateRef array = GetPropertiesArray(obj);
809 BRANCH(IsDictionaryMode(array), &isDictionary, ¬Dictionary);
810 Bind(&isDictionary);
811 {
812 Label propsNotZero(env);
813 Label propsIsZero(env);
814 GateRef numOfKeys = GetNumKeysFromDictionary(array);
815 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &propsNotZero, &propsIsZero);
816 Bind(&propsNotZero);
817 result = CallRuntime(glue, RTSTUB_ID(NameDictionaryGetAllEnumKeys), { obj, IntToTaggedInt(numOfKeys) });
818 Jump(&exit);
819 Bind(&propsIsZero);
820 GateRef emptyArray = GetEmptyArray(glue);
821 result = emptyArray;
822 Jump(&exit);
823 }
824 Bind(¬Dictionary);
825 {
826 Label hasProps(env);
827 Label notHasProps(env);
828 GateRef hclass = LoadHClass(obj);
829 // JSObject::GetNumberOfEnumKeys()
830 GateRef num = GetNumberOfPropsFromHClass(hclass);
831 BRANCH(Int32GreaterThan(num, Int32(0)), &hasProps, ¬HasProps);
832 Bind(&hasProps);
833 {
834 Label isOnlyOwnKeys(env);
835 Label notOnlyOwnKeys(env);
836 GateRef layout = GetLayoutFromHClass(hclass);
837 GateRef numOfKeys = GetNumKeysFromLayoutInfo(num, layout);
838 // JSObject::GetAllEnumKeys
839 GateRef enumCache = GetEnumCacheFromHClass(hclass);
840 GateRef kind = GetEnumCacheKind(glue, enumCache);
841 BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::ONLY_OWN_KEYS))),
842 &isOnlyOwnKeys, ¬OnlyOwnKeys);
843 Bind(&isOnlyOwnKeys);
844 {
845 result = CopyFromEnumCache(glue, enumCache);
846 Jump(&exit);
847 }
848 Bind(¬OnlyOwnKeys);
849 {
850 Label numNotZero(env);
851 Label inSharedHeap(env);
852 Label notInSharedHeap(env);
853 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &numNotZero, ¬HasProps);
854 Bind(&numNotZero);
855 NewObjectStubBuilder newBuilder(this);
856 GateRef keyArray = newBuilder.NewTaggedArray(glue,
857 Int32Add(numOfKeys, Int32(static_cast<int32_t>(EnumCache::ENUM_CACHE_HEADER_SIZE))));
858 LayoutInfoGetAllEnumKeys(num, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE), keyArray, layout);
859 SetValueToTaggedArray(VariableType::JS_ANY(), glue, keyArray,
860 Int32(EnumCache::ENUM_CACHE_KIND_OFFSET),
861 IntToTaggedInt(Int32(static_cast<int32_t>(EnumCacheKind::ONLY_OWN_KEYS))));
862 GateRef hclassRegion = ObjectAddressToRange(hclass);
863 BRANCH(InSharedHeap(hclassRegion), &inSharedHeap, ¬InSharedHeap);
864 Bind(&inSharedHeap);
865 {
866 result = CopyFromEnumCache(glue, keyArray);
867 Jump(&exit);
868 }
869 Bind(¬InSharedHeap);
870 {
871 SetEnumCacheToHClass(VariableType::JS_ANY(), glue, hclass, keyArray);
872 result = CopyFromEnumCache(glue, keyArray);
873 Jump(&exit);
874 }
875 }
876 }
877 Bind(¬HasProps);
878 {
879 GateRef emptyArray = GetEmptyArray(glue);
880 result = emptyArray;
881 Jump(&exit);
882 }
883 }
884 Bind(&exit);
885 auto ret = *result;
886 env->SubCfgExit();
887 return ret;
888 }
889
GetEnumElementKeys(GateRef glue,GateRef obj)890 GateRef BuiltinsObjectStubBuilder::GetEnumElementKeys(GateRef glue, GateRef obj)
891 {
892 auto env = GetEnvironment();
893 Label subEntry(env);
894 env->SubCfgEntry(&subEntry);
895 Label exit(env);
896 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
897 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
898 DEFVARIABLE(j, VariableType::INT32(), Int32(0));
899 DEFVARIABLE(elementIndex, VariableType::INT32(), Int32(0));
900
901 Label propsNotZero(env);
902 Label propsIsZero(env);
903 GateRef numOfElements = GetNumberOfElements(glue, obj);
904 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &propsNotZero, &propsIsZero);
905 Bind(&propsNotZero);
906 {
907 Label isJSPrimitiveRef(env);
908 Label isPrimitiveString(env);
909 Label notPrimitiveString(env);
910 Label isDictMode(env);
911 Label notDictMode(env);
912
913 NewObjectStubBuilder newBuilder(this);
914 GateRef elementArray = newBuilder.NewTaggedArray(glue, numOfElements);
915 BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, ¬PrimitiveString);
916 Bind(&isJSPrimitiveRef);
917 GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
918 BRANCH(TaggedIsString(value), &isPrimitiveString, ¬PrimitiveString);
919 Bind(&isPrimitiveString);
920 {
921 Label loopHead(env);
922 Label loopEnd(env);
923 Label iLessLength(env);
924 GateRef strLen = GetLengthFromString(value);
925 Jump(&loopHead);
926 LoopBegin(&loopHead);
927 {
928 BRANCH(Int32UnsignedLessThan(*i, strLen), &iLessLength, ¬PrimitiveString);
929 Bind(&iLessLength);
930 {
931 GateRef str = IntToEcmaString(glue, *i);
932 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elementArray,
933 *elementIndex, str);
934 elementIndex = Int32Add(*elementIndex, Int32(1));
935 Jump(&loopEnd);
936 }
937 Bind(&loopEnd);
938 i = Int32Add(*i, Int32(1));
939 LoopEnd(&loopHead, env, glue);
940 }
941 }
942 Bind(¬PrimitiveString);
943 GateRef elements = GetElementsArray(obj);
944 BRANCH(IsDictionaryMode(elements), &isDictMode, ¬DictMode);
945 Bind(¬DictMode);
946 {
947 Label loopHead(env);
948 Label loopEnd(env);
949 Label iLessLength(env);
950 Label notHole(env);
951 Label afterLoop(env);
952 GateRef elementsLen = GetLengthOfTaggedArray(elements);
953 Jump(&loopHead);
954 LoopBegin(&loopHead);
955 {
956 BRANCH(Int32UnsignedLessThan(*j, elementsLen), &iLessLength, &afterLoop);
957 Bind(&iLessLength);
958 {
959 GateRef element = GetTaggedValueWithElementsKind(glue, obj, *j);
960 BRANCH(TaggedIsHole(element), &loopEnd, ¬Hole);
961 Bind(¬Hole);
962 GateRef str = IntToEcmaString(glue, *j);
963 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elementArray,
964 *elementIndex, str);
965 elementIndex = Int32Add(*elementIndex, Int32(1));
966 Jump(&loopEnd);
967 }
968 Bind(&loopEnd);
969 j = Int32Add(*j, Int32(1));
970 LoopEnd(&loopHead, env, glue);
971 Bind(&afterLoop);
972 {
973 result = elementArray;
974 Label needTrim(env);
975 BRANCH(Int32LessThan(*elementIndex, numOfElements), &needTrim, &exit);
976 Bind(&needTrim);
977 {
978 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim),
979 {glue, elementArray, ZExtInt32ToInt64(*elementIndex)});
980 Jump(&exit);
981 }
982 }
983 }
984 }
985 Bind(&isDictMode);
986 {
987 CallRuntime(glue, RTSTUB_ID(NumberDictionaryGetAllEnumKeys),
988 { elements, elementArray, IntToTaggedInt(*elementIndex) });
989 result = elementArray;
990 Jump(&exit);
991 }
992 }
993 Bind(&propsIsZero);
994 {
995 GateRef emptyArray = GetEmptyArray(glue);
996 result = emptyArray;
997 Jump(&exit);
998 }
999 Bind(&exit);
1000 auto ret = *result;
1001 env->SubCfgExit();
1002 return ret;
1003 }
1004
IsNotSlowObjectKey(GateRef obj)1005 GateRef BuiltinsObjectStubBuilder::IsNotSlowObjectKey(GateRef obj)
1006 {
1007 auto env = GetEnvironment();
1008 return LogicAndBuilder(env)
1009 .And(IsJSObject(obj))
1010 .And(BoolNot(LogicOrBuilder(env).Or(IsTypedArray(obj)).Or(IsModuleNamespace(obj))
1011 .Or(IsJSGlobalObject(obj)).Done()))
1012 .Done();
1013 }
1014
Keys(Variable * result,Label * exit,Label * slowPath)1015 void BuiltinsObjectStubBuilder::Keys(Variable *result, Label *exit, Label *slowPath)
1016 {
1017 auto env = GetEnvironment();
1018 NewObjectStubBuilder newBuilder(this);
1019 GateRef msg = GetCallArg0(numArgs_);
1020 // 1. Let obj be ToObject(O).
1021 GateRef obj = ToObject(glue_, msg);
1022 Label isPendingException(env);
1023 Label noPendingException(env);
1024 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException);
1025 Bind(&isPendingException);
1026 Jump(exit);
1027 Bind(&noPendingException);
1028 Label isFast(env);
1029 // EnumerableOwnNames(obj)
1030 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath);
1031 Bind(&isFast);
1032 {
1033 Label hasKeyAndEle(env);
1034 Label nonKeyAndEle(env);
1035 // need to caclulate elementKind
1036 GateRef elementKind = Int32(Elements::ToUint(ElementsKind::TAGGED));
1037 GateRef elementArray = GetEnumElementKeys(glue_, obj);
1038 GateRef keyArray = GetAllEnumKeys(glue_, obj);
1039 GateRef lengthOfKeys = GetLengthOfTaggedArray(keyArray);
1040 GateRef lengthOfElements = GetLengthOfTaggedArray(elementArray);
1041 GateRef KeyAndEle = BitAnd(Int32NotEqual(lengthOfElements, Int32(0)), Int32NotEqual(lengthOfKeys, Int32(0)));
1042 BRANCH(KeyAndEle, &hasKeyAndEle, &nonKeyAndEle);
1043 Bind(&hasKeyAndEle);
1044 {
1045 GateRef allKeys = AppendSkipHole(glue_, elementArray, keyArray, Int32Add(lengthOfKeys, lengthOfElements));
1046 *result = newBuilder.CreateArrayFromList(glue_, allKeys, elementKind);
1047 Jump(exit);
1048 }
1049 Bind(&nonKeyAndEle);
1050 {
1051 Label hasKey(env);
1052 Label nonKey(env);
1053 BRANCH(Int32NotEqual(lengthOfKeys, Int32(0)), &hasKey, &nonKey);
1054 Bind(&hasKey);
1055 {
1056 *result = newBuilder.CreateArrayFromList(glue_, keyArray, elementKind);
1057 Jump(exit);
1058 }
1059 Bind(&nonKey);
1060 {
1061 Label hasEle(env);
1062 Label nonEle(env);
1063 BRANCH(Int32NotEqual(lengthOfElements, Int32(0)), &hasEle, &nonEle);
1064 Bind(&hasEle);
1065 {
1066 *result = newBuilder.CreateArrayFromList(glue_, elementArray, elementKind);
1067 Jump(exit);
1068 }
1069 Bind(&nonEle);
1070 {
1071 GateRef emptyArray = GetEmptyArray(glue_);
1072 *result = newBuilder.CreateArrayFromList(glue_, emptyArray, elementKind);
1073 Jump(exit);
1074 }
1075 }
1076 }
1077 }
1078 }
1079
GetPrototypeOf(Variable * result,Label * exit,Label * slowPath)1080 void BuiltinsObjectStubBuilder::GetPrototypeOf(Variable *result, Label *exit, Label *slowPath)
1081 {
1082 auto env = GetEnvironment();
1083 Label isPendingException(env);
1084 Label noPendingException(env);
1085 GateRef msg = GetCallArg0(numArgs_);
1086 GateRef obj = ToObject(glue_, msg);
1087 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException);
1088 Bind(&isPendingException);
1089 {
1090 Jump(exit);
1091 }
1092 Bind(&noPendingException);
1093 {
1094 Label isEcmaObject(env);
1095 Label notJsProxy(env);
1096 BRANCH(IsEcmaObject(obj), &isEcmaObject, slowPath);
1097 Bind(&isEcmaObject);
1098 {
1099 BRANCH(IsJsProxy(obj), slowPath, ¬JsProxy);
1100 Bind(¬JsProxy);
1101 {
1102 GateRef hClass = LoadHClass(obj);
1103 GateRef prototype = GetPrototypeFromHClass(hClass);
1104 *result = prototype;
1105 Jump(exit);
1106 }
1107 }
1108 }
1109 }
1110
SetPrototypeOf(Variable * result,Label * exit,Label * slowPath)1111 void BuiltinsObjectStubBuilder::SetPrototypeOf(Variable *result, Label *exit, Label *slowPath)
1112 {
1113 auto env = GetEnvironment();
1114 GateRef obj = GetCallArg0(numArgs_);
1115 DEFVARIABLE(proto, VariableType::JS_ANY(), Undefined());
1116 Label checkJsObj(env);
1117 Label setProto(env);
1118 BRANCH(TaggedIsUndefinedOrNull(obj), slowPath, &checkJsObj);
1119 Bind(&checkJsObj);
1120 {
1121 Label checkProto(env);
1122 proto = GetCallArg1(numArgs_);
1123 GateRef protoVal = *proto;
1124 BRANCH(LogicOrBuilder(env).Or(TaggedIsNull(protoVal)).Or(IsEcmaObject(protoVal)).Done(),
1125 &checkProto, slowPath);
1126 Bind(&checkProto);
1127 {
1128 Label isEcmaObject(env);
1129 Label notEcmaObject(env);
1130 BRANCH(IsEcmaObject(obj), &isEcmaObject, ¬EcmaObject);
1131 Bind(&isEcmaObject);
1132 Jump(&setProto);
1133 Bind(¬EcmaObject);
1134 {
1135 *result = obj;
1136 Jump(exit);
1137 }
1138 }
1139 }
1140 Bind(&setProto);
1141 {
1142 Label objNotSpecial(env);
1143 GateRef protoVal = *proto;
1144 GateRef isSpecialobj = LogicOrBuilder(env).Or(IsJsProxy(obj)).Or(TaggedIsSharedObj(obj))
1145 .Or(TaggedIsSharedObj(protoVal)).Or(IsSpecialContainer(obj)).Or(IsModuleNamespace(obj)).Done();
1146 BRANCH(isSpecialobj, slowPath, &objNotSpecial);
1147 Bind(&objNotSpecial);
1148 Label isFunction(env);
1149 Label notFunction(env);
1150 GateRef isFunc = LogicAndBuilder(env)
1151 .And(TaggedIsHeapObject(obj)).And(TaggedIsHeapObject(protoVal))
1152 .And(IsJSFunction(obj)).And(IsJSFunction(protoVal))
1153 .Done();
1154 BRANCH(isFunc, &isFunction, ¬Function);
1155 Bind(&isFunction);
1156 {
1157 Label isDerivedCtor(env);
1158 auto protoOrHclass = Load(VariableType::JS_ANY(), obj,
1159 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1160 GateRef isDerivedCtorCheck = LogicAndBuilder(env).And(TaggedIsHeapObject(protoOrHclass))
1161 .And(IsJSHClass(protoOrHclass)).And(IsDerived(obj)).Done();
1162 BRANCH(isDerivedCtorCheck, &isDerivedCtor, ¬Function);
1163 Bind(&isDerivedCtor);
1164 auto cachedJSHClass = GetPrototypeFromHClass(protoOrHclass);
1165 SetProtoOrHClassToFunction(glue_, obj, cachedJSHClass);
1166 Jump(¬Function);
1167 }
1168 Bind(¬Function);
1169 {
1170 Label statusIsTrue(env);
1171 Label statusIsFalse(env);
1172 BRANCH(ObjectSetPrototype(glue_, obj, *proto), &statusIsTrue, &statusIsFalse);
1173 Bind(&statusIsTrue);
1174 *result = obj;
1175 Jump(exit);
1176 Bind(&statusIsFalse);
1177 {
1178 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPrototypeOfFailed));
1179 CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
1180 *result = Exception();
1181 Jump(exit);
1182 }
1183 }
1184 }
1185 }
1186
ObjectSetPrototype(GateRef glue,GateRef obj,GateRef proto)1187 GateRef BuiltinsObjectStubBuilder::ObjectSetPrototype(GateRef glue, GateRef obj, GateRef proto)
1188 {
1189 auto env = GetEnvironment();
1190 Label subEntry(env);
1191 env->SubCfgEntry(&subEntry);
1192 Label exit(env);
1193
1194 DEFVARIABLE(result, VariableType::BOOL(), False());
1195 Label isEqual(env);
1196 Label notEqual(env);
1197 Label isExtensible(env);
1198 Label notExtensible(env);
1199 GateRef current = GetPrototype(glue, obj);
1200 BRANCH(IntPtrEqual(proto, current), &isEqual, ¬Equal);
1201 Bind(&isEqual);
1202 {
1203 result = True();
1204 Jump(&exit);
1205 }
1206 Bind(¬Equal);
1207 {
1208 BRANCH(IsExtensible(obj), &isExtensible, ¬Extensible);
1209 Bind(&isExtensible);
1210 {
1211 DEFVARIABLE(done, VariableType::BOOL(), False());
1212 DEFVARIABLE(tempProto, VariableType::JS_ANY(), proto);
1213 Label loopHead(env);
1214 Label loopEnd(env);
1215 Label next(env);
1216 Label loopExit(env);
1217 Jump(&loopHead);
1218 LoopBegin(&loopHead);
1219 {
1220 BRANCH(BoolNot(*done), &next, &loopExit);
1221 Bind(&next);
1222 {
1223 Label isNull(env);
1224 Label notNull(env);
1225 Label isEqual2(env);
1226 Label notEqual2(env);
1227 Label protoNotProxy(env);
1228 GateRef tempProtoVal = *tempProto;
1229 GateRef protoIsNull = LogicOrBuilder(env).Or(TaggedIsNull(tempProtoVal))
1230 .Or(BoolNot(IsEcmaObject(tempProtoVal))).Done();
1231 BRANCH(protoIsNull, &isNull, ¬Null);
1232 Bind(&isNull);
1233 {
1234 done = True();
1235 Jump(&loopEnd);
1236 }
1237 Bind(¬Null);
1238 {
1239 BRANCH(IntPtrEqual(*tempProto, obj), &isEqual2, ¬Equal2);
1240 Bind(&isEqual2);
1241 {
1242 result = False();
1243 Jump(&exit);
1244 }
1245 Bind(¬Equal2);
1246 {
1247 BRANCH(IsJsProxy(*tempProto), &loopExit, &protoNotProxy);
1248 Bind(&protoNotProxy);
1249 {
1250 tempProto = GetPrototype(glue, *tempProto);
1251 Jump(&loopEnd);
1252 }
1253 }
1254 }
1255 }
1256 Bind(&loopEnd);
1257 LoopEnd(&loopHead, env, glue_);
1258 }
1259 Bind(&loopExit);
1260 CallRuntime(glue, RTSTUB_ID(SetPrototypeTransition), { obj, proto});
1261 result = True();
1262 Jump(&exit);
1263 }
1264 Bind(¬Extensible);
1265 {
1266 result = False();
1267 Jump(&exit);
1268 }
1269 }
1270 Bind(&exit);
1271 auto ret = *result;
1272 env->SubCfgExit();
1273 return ret;
1274 }
1275
GetOwnPropertyNames(Variable * result,Label * exit,Label * slowPath)1276 void BuiltinsObjectStubBuilder::GetOwnPropertyNames(Variable *result, Label *exit, Label *slowPath)
1277 {
1278 auto env = GetEnvironment();
1279 Label isPendingException(env);
1280 Label noPendingException(env);
1281 GateRef msg = GetCallArg0(numArgs_);
1282 GateRef obj = ToObject(glue_, msg);
1283 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException);
1284 Bind(&isPendingException);
1285 {
1286 Jump(exit);
1287 }
1288 Bind(&noPendingException);
1289 {
1290 Label isFast(env);
1291 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath);
1292 Bind(&isFast);
1293 {
1294 Label notDictMode(env);
1295 GateRef isDictMode = LogicOrBuilder(env).Or(IsDictionaryMode(GetElementsArray(obj)))
1296 .Or(IsDictionaryMode(GetPropertiesArray(obj))).Done();
1297 BRANCH(isDictMode, slowPath, ¬DictMode);
1298 Bind(¬DictMode);
1299 {
1300 Label getAllElementKeys(env);
1301 Label checkNumOfKeys(env);
1302 GateRef hclass = LoadHClass(obj);
1303 GateRef numOfElements = GetNumberOfElements(glue_, obj);
1304 GateRef numOfKeys = GetNumberOfPropsFromHClass(hclass);
1305 GateRef keyLen = Int32Add(numOfElements, numOfKeys);
1306 GateRef elementKind = Int32(Elements::ToUint(ElementsKind::TAGGED));
1307 NewObjectStubBuilder newBuilder(this);
1308 GateRef keyArray = newBuilder.NewTaggedArray(glue_, keyLen);
1309 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &getAllElementKeys, &checkNumOfKeys);
1310 Bind(&getAllElementKeys);
1311 {
1312 GetAllElementKeys(glue_, obj, Int32(0), keyArray);
1313 Jump(&checkNumOfKeys);
1314 }
1315 Bind(&checkNumOfKeys);
1316 {
1317 Label getAllPropertyKeys(env);
1318 Label checkElementType(env);
1319 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &getAllPropertyKeys, &checkElementType);
1320 Bind(&getAllPropertyKeys);
1321 {
1322 GetAllPropertyKeys(glue_, obj, numOfElements, keyArray);
1323 Jump(&checkElementType);
1324 }
1325 Bind(&checkElementType);
1326 {
1327 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1328 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
1329 Label loopHead(env);
1330 Label loopEnd(env);
1331 Label next(env);
1332 Label loopExit(env);
1333 Label needTrim(env);
1334 Label setResult(env);
1335 Jump(&loopHead);
1336 LoopBegin(&loopHead);
1337 {
1338 BRANCH(Int32UnsignedLessThan(*i, keyLen), &next, &loopExit);
1339 Bind(&next);
1340 {
1341 Label isString(env);
1342 Label setValue(env);
1343 Label adjustPos(env);
1344 GateRef element = GetValueFromTaggedArray(keyArray, *i);
1345 BRANCH(TaggedIsString(element), &isString, &loopEnd);
1346 Bind(&isString);
1347 {
1348 // compare pos and i to skip holes
1349 BRANCH(Int32Equal(*pos, *i), &adjustPos, &setValue);
1350 Bind(&setValue);
1351 {
1352 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, keyArray, *pos, element);
1353 Jump(&adjustPos);
1354 }
1355 Bind(&adjustPos);
1356 {
1357 pos = Int32Add(*pos, Int32(1));
1358 Jump(&loopEnd);
1359 }
1360 }
1361 }
1362 Bind(&loopEnd);
1363 i = Int32Add(*i, Int32(1));
1364 LoopEnd(&loopHead, env, glue_);
1365 }
1366 Bind(&loopExit);
1367 BRANCH(Int32UnsignedLessThan(*pos, keyLen), &needTrim, &setResult);
1368 Bind(&needTrim);
1369 {
1370 CallNGCRuntime(glue_, RTSTUB_ID(ArrayTrim), {glue_, keyArray, ZExtInt32ToInt64(*pos)});
1371 Jump(&setResult);
1372 }
1373 Bind(&setResult);
1374 {
1375 *result = newBuilder.CreateArrayFromList(glue_, keyArray, elementKind);
1376 Jump(exit);
1377 }
1378 }
1379 }
1380 }
1381 }
1382 }
1383 }
1384
GetOwnPropertySymbols(Variable * result,Label * exit,Label * slowPath)1385 void BuiltinsObjectStubBuilder::GetOwnPropertySymbols(Variable *result, Label *exit, Label *slowPath)
1386 {
1387 auto env = GetEnvironment();
1388 Label isPendingException(env);
1389 Label noPendingException(env);
1390 GateRef msg = GetCallArg0(numArgs_);
1391 GateRef obj = ToObject(glue_, msg);
1392 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException);
1393 Bind(&isPendingException);
1394 {
1395 Jump(exit);
1396 }
1397 Bind(&noPendingException);
1398 {
1399 Label isFast(env);
1400 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath);
1401 Bind(&isFast);
1402 {
1403 Label notDictMode(env);
1404 GateRef isDictMode = LogicOrBuilder(env).Or(IsDictionaryMode(GetElementsArray(obj)))
1405 .Or(IsDictionaryMode(GetPropertiesArray(obj))).Done();
1406 BRANCH(isDictMode, slowPath, ¬DictMode);
1407 Bind(¬DictMode);
1408 {
1409 Label getAllElementKeys(env);
1410 Label checkNumOfKeys(env);
1411 GateRef hclass = LoadHClass(obj);
1412 GateRef numOfElements = GetNumberOfElements(glue_, obj);
1413 GateRef numOfKeys = GetNumberOfPropsFromHClass(hclass);
1414 GateRef keyLen = Int32Add(numOfElements, numOfKeys);
1415 // need to caclulate elementKind
1416 GateRef elementKind = Int32(Elements::ToUint(ElementsKind::TAGGED));
1417 NewObjectStubBuilder newBuilder(this);
1418 GateRef keyArray = newBuilder.NewTaggedArray(glue_, keyLen);
1419 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &getAllElementKeys, &checkNumOfKeys);
1420 Bind(&getAllElementKeys);
1421 {
1422 GetAllElementKeys(glue_, obj, Int32(0), keyArray);
1423 Jump(&checkNumOfKeys);
1424 }
1425 Bind(&checkNumOfKeys);
1426 {
1427 Label getAllPropertyKeys(env);
1428 Label checkElementType(env);
1429 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &getAllPropertyKeys, &checkElementType);
1430 Bind(&getAllPropertyKeys);
1431 {
1432 GetAllPropertyKeys(glue_, obj, numOfElements, keyArray);
1433 Jump(&checkElementType);
1434 }
1435 Bind(&checkElementType);
1436 {
1437 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1438 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
1439 Label loopHead(env);
1440 Label loopEnd(env);
1441 Label next(env);
1442 Label loopExit(env);
1443 Label needTrim(env);
1444 Label setResult(env);
1445 Jump(&loopHead);
1446 LoopBegin(&loopHead);
1447 {
1448 BRANCH(Int32UnsignedLessThan(*i, keyLen), &next, &loopExit);
1449 Bind(&next);
1450 {
1451 Label isSymbol(env);
1452 Label setValue(env);
1453 Label adjustPos(env);
1454 GateRef element = GetValueFromTaggedArray(keyArray, *i);
1455 BRANCH(TaggedIsSymbol(element), &isSymbol, &loopEnd);
1456 Bind(&isSymbol);
1457 {
1458 // compare pos and i to skip holes
1459 BRANCH(Int32Equal(*pos, *i), &adjustPos, &setValue);
1460 Bind(&setValue);
1461 {
1462 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, keyArray, *pos, element);
1463 Jump(&adjustPos);
1464 }
1465 Bind(&adjustPos);
1466 {
1467 pos = Int32Add(*pos, Int32(1));
1468 Jump(&loopEnd);
1469 }
1470 }
1471 }
1472 Bind(&loopEnd);
1473 i = Int32Add(*i, Int32(1));
1474 LoopEnd(&loopHead, env, glue_);
1475 }
1476 Bind(&loopExit);
1477 BRANCH(Int32UnsignedLessThan(*pos, keyLen), &needTrim, &setResult);
1478 Bind(&needTrim);
1479 {
1480 CallNGCRuntime(glue_, RTSTUB_ID(ArrayTrim), {glue_, keyArray, ZExtInt32ToInt64(*pos)});
1481 Jump(&setResult);
1482 }
1483 Bind(&setResult);
1484 {
1485 *result = newBuilder.CreateArrayFromList(glue_, keyArray, elementKind);
1486 Jump(exit);
1487 }
1488 }
1489 }
1490 }
1491 }
1492 }
1493 }
1494
GetAllElementKeys(GateRef glue,GateRef obj,GateRef offset,GateRef array)1495 GateRef BuiltinsObjectStubBuilder::GetAllElementKeys(GateRef glue, GateRef obj, GateRef offset, GateRef array)
1496 {
1497 auto env = GetEnvironment();
1498 Label subEntry(env);
1499 env->SubCfgEntry(&subEntry);
1500
1501 DEFVARIABLE(i, VariableType::INT32(), offset);
1502 DEFVARIABLE(j, VariableType::INT32(), Int32(0));
1503 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
1504 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1505 Label isJSPrimitiveRef(env);
1506 Label isPrimitiveString(env);
1507 Label notPrimitiveString(env);
1508 BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, ¬PrimitiveString);
1509 Bind(&isJSPrimitiveRef);
1510 {
1511 GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1512 BRANCH(TaggedIsString(value), &isPrimitiveString, ¬PrimitiveString);
1513 Bind(&isPrimitiveString);
1514 {
1515 Label loopHead(env);
1516 Label loopEnd(env);
1517 Label next(env);
1518 GateRef elementIndex = Int32Add(GetLengthFromString(value), offset);
1519 Jump(&loopHead);
1520 LoopBegin(&loopHead);
1521 {
1522 BRANCH(Int32UnsignedLessThan(*i, elementIndex), &next, ¬PrimitiveString);
1523 Bind(&next);
1524 {
1525 GateRef str = IntToEcmaString(glue, *i);
1526 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *pos, str);
1527 pos = Int32Add(*pos, Int32(1));
1528 Jump(&loopEnd);
1529 }
1530 Bind(&loopEnd);
1531 i = Int32Add(*i, Int32(1));
1532 LoopEnd(&loopHead, env, glue);
1533 }
1534 }
1535 }
1536 Bind(¬PrimitiveString);
1537 {
1538 Label isDictMode(env);
1539 Label notDictMode(env);
1540 Label exit(env);
1541 GateRef elements = GetElementsArray(obj);
1542 BRANCH(IsDictionaryMode(elements), &isDictMode, ¬DictMode);
1543 Bind(&isDictMode);
1544 {
1545 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1546 Jump(&exit);
1547 }
1548 Bind(¬DictMode);
1549 {
1550 Label loopHead(env);
1551 Label loopEnd(env);
1552 Label next(env);
1553 Label loopExit(env);
1554 GateRef elementsLen = GetLengthOfTaggedArray(elements);
1555 Jump(&loopHead);
1556 LoopBegin(&loopHead);
1557 {
1558 Label notHole(env);
1559 BRANCH(Int32UnsignedLessThan(*j, elementsLen), &next, &loopExit);
1560 Bind(&next);
1561 {
1562 GateRef element = GetTaggedValueWithElementsKind(glue, obj, *j);
1563 BRANCH(TaggedIsHole(element), &loopEnd, ¬Hole);
1564 Bind(¬Hole);
1565 {
1566 GateRef str = IntToEcmaString(glue, *j);
1567 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *pos, str);
1568 pos = Int32Add(*pos, Int32(1));
1569 Jump(&loopEnd);
1570 }
1571 }
1572 Bind(&loopEnd);
1573 j = Int32Add(*j, Int32(1));
1574 LoopEnd(&loopHead, env, glue);
1575 Bind(&loopExit);
1576 result = array;
1577 Jump(&exit);
1578 }
1579 }
1580 Bind(&exit);
1581 auto ret = *result;
1582 env->SubCfgExit();
1583 return ret;
1584 }
1585 }
1586
GetAllPropertyKeys(GateRef glue,GateRef obj,GateRef offset,GateRef array)1587 GateRef BuiltinsObjectStubBuilder::GetAllPropertyKeys(GateRef glue, GateRef obj, GateRef offset, GateRef array)
1588 {
1589 auto env = GetEnvironment();
1590 Label subEntry(env);
1591 env->SubCfgEntry(&subEntry);
1592
1593 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1594 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
1595 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1596 Label isDictionary(env);
1597 Label notDictionary(env);
1598 Label exit(env);
1599 GateRef properties = GetPropertiesArray(obj);
1600 BRANCH(IsDictionaryMode(properties), &isDictionary, ¬Dictionary);
1601 Bind(&isDictionary);
1602 {
1603 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1604 Jump(&exit);
1605 }
1606 Bind(¬Dictionary);
1607 {
1608 Label loopHead(env);
1609 Label loopEnd(env);
1610 Label next(env);
1611 Label loopExit(env);
1612 GateRef hclass = LoadHClass(obj);
1613 GateRef layout = GetLayoutFromHClass(hclass);
1614 GateRef number = GetNumberOfPropsFromHClass(hclass);
1615 Jump(&loopHead);
1616 LoopBegin(&loopHead);
1617 {
1618 BRANCH(Int32UnsignedLessThan(*i, number), &next, &loopExit);
1619 Bind(&next);
1620 {
1621 Label checkSymbol(env);
1622 Label setValue(env);
1623 GateRef key = GetKey(layout, *i);
1624 BRANCH(TaggedIsString(key), &setValue, &checkSymbol);
1625 Bind(&checkSymbol);
1626 {
1627 BRANCH(TaggedIsSymbol(key), &setValue, &loopEnd);
1628 }
1629 Bind(&setValue);
1630 {
1631 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, array, Int32Add(*pos, offset), key);
1632 pos = Int32Add(*pos, Int32(1));
1633 Jump(&loopEnd);
1634 }
1635 }
1636 Bind(&loopEnd);
1637 i = Int32Add(*i, Int32(1));
1638 LoopEnd(&loopHead, env, glue_);
1639 }
1640 Bind(&loopExit);
1641 Jump(&exit);
1642 }
1643 Bind(&exit);
1644 auto ret = *result;
1645 env->SubCfgExit();
1646 return ret;
1647 }
1648
Entries(Variable * result,Label * exit,Label * slowPath)1649 void BuiltinsObjectStubBuilder::Entries(Variable* result, Label* exit, Label* slowPath)
1650 {
1651 auto env = GetEnvironment();
1652 Label isPendingException(env);
1653 Label noPendingException(env);
1654 GateRef msg = GetCallArg0(numArgs_);
1655 GateRef obj = ToObject(glue_, msg);
1656 NewObjectStubBuilder newBuilder(this);
1657 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException);
1658 Bind(&isPendingException);
1659 {
1660 Jump(exit);
1661 }
1662 Bind(&noPendingException);
1663 {
1664 Label isFast(env);
1665 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath);
1666 Bind(&isFast);
1667 {
1668 Label notDictMode(env);
1669 GateRef isDictMode = LogicOrBuilder(env).Or(IsDictionaryMode(GetElementsArray(obj)))
1670 .Or(IsDictionaryMode(GetPropertiesArray(obj))).Done();
1671 BRANCH(isDictMode, slowPath, ¬DictMode);
1672 Bind(¬DictMode);
1673 {
1674 Label hasKeyAndEle(env);
1675 Label nonKeyAndEle(env);
1676 GateRef elementArray = GetEnumElementEntries(glue_, obj, slowPath);
1677 GateRef propertyArray = GetEnumPropertyEntries(glue_, obj, slowPath);
1678 GateRef elementLen = GetLengthOfTaggedArray(elementArray);
1679 GateRef propertyLen = GetLengthOfTaggedArray(propertyArray);
1680 // need to caclulate elementKind
1681 GateRef elementKind = Int32(Elements::ToUint(ElementsKind::GENERIC));
1682 GateRef keyAndEle = BitAnd(Int32NotEqual(elementLen, Int32(0)), Int32NotEqual(propertyLen, Int32(0)));
1683 BRANCH(keyAndEle, &hasKeyAndEle, &nonKeyAndEle);
1684 Bind(&hasKeyAndEle);
1685 {
1686 GateRef allEntries = AppendSkipHole(glue_, elementArray, propertyArray,
1687 Int32Add(elementLen, propertyLen));
1688 *result = newBuilder.CreateArrayFromList(glue_, allEntries, elementKind);
1689 Jump(exit);
1690 }
1691 Bind(&nonKeyAndEle);
1692 {
1693 Label hasKey(env);
1694 Label nonKey(env);
1695 BRANCH(Int32NotEqual(propertyLen, Int32(0)), &hasKey, &nonKey);
1696 Bind(&hasKey);
1697 {
1698 *result = newBuilder.CreateArrayFromList(glue_, propertyArray, elementKind);
1699 Jump(exit);
1700 }
1701 Bind(&nonKey);
1702 {
1703 Label hasEle(env);
1704 Label nonEle(env);
1705 BRANCH(Int32NotEqual(elementLen, Int32(0)), &hasEle, &nonEle);
1706 Bind(&hasEle);
1707 {
1708 *result = newBuilder.CreateArrayFromList(glue_, elementArray, elementKind);
1709 Jump(exit);
1710 }
1711 Bind(&nonEle);
1712 {
1713 GateRef emptyArray = GetEmptyArray(glue_);
1714 *result = newBuilder.CreateArrayFromList(glue_, emptyArray, elementKind);
1715 Jump(exit);
1716 }
1717 }
1718 }
1719 }
1720 }
1721 }
1722 }
1723
GetEnumElementEntries(GateRef glue,GateRef obj,Label * slowPath)1724 GateRef BuiltinsObjectStubBuilder::GetEnumElementEntries(GateRef glue, GateRef obj, Label* slowPath)
1725 {
1726 auto env = GetEnvironment();
1727 Label subEntry(env);
1728 env->SubCfgEntry(&subEntry);
1729
1730 DEFVARIABLE(idx, VariableType::INT32(), Int32(0));
1731 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
1732 GateRef elementKeys = GetEnumElementKeys(glue, obj);
1733 GateRef elements = GetElementsArray(obj);
1734 GateRef len = GetLengthOfTaggedArray(elements);
1735 GateRef realLen = GetLengthOfTaggedArray(elementKeys);
1736 NewObjectStubBuilder newBuilder(this);
1737 GateRef numElementArray = newBuilder.NewTaggedArray(glue, realLen);
1738 // need to caclulate elementKind
1739 GateRef elementKind = Int32(Elements::ToUint(ElementsKind::TAGGED));
1740 Label isJSPrimitiveRef(env);
1741 Label notPrimitiveString(env);
1742 Label notDictMode(env);
1743 BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, ¬PrimitiveString);
1744 Bind(&isJSPrimitiveRef);
1745 GateRef els = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1746 BRANCH(TaggedIsString(els), slowPath, ¬PrimitiveString);
1747 Bind(¬PrimitiveString);
1748 BRANCH(IsDictionaryMode(elements), slowPath, ¬DictMode);
1749 Bind(¬DictMode);
1750 {
1751 Label loopHead(env);
1752 Label loopEnd(env);
1753 Label LoopNext(env);
1754 Label loopExit(env);
1755
1756 Jump(&loopHead);
1757 LoopBegin(&loopHead);
1758 {
1759 BRANCH(Int32LessThan(*idx, len), &LoopNext, &loopExit);
1760 Bind(&LoopNext);
1761 GateRef value = GetTaggedValueWithElementsKind(glue, obj, *idx);
1762 Label notHole(env);
1763 BRANCH(TaggedIsHole(value), &loopEnd, ¬Hole);
1764 Bind(¬Hole);
1765 {
1766 GateRef arrayProp = newBuilder.NewTaggedArray(glue, Int32(2));
1767 GateRef str = IntToEcmaString(glue, *idx);
1768 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(0), str);
1769 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(1), value);
1770 GateRef propArray = newBuilder.CreateArrayFromList(glue, arrayProp, elementKind);
1771 SetValueToTaggedArray(VariableType::JS_ANY(), glue, numElementArray, *pos, propArray);
1772 pos = Int32Add(*pos, Int32(1));
1773 Jump(&loopEnd);
1774 }
1775 }
1776
1777 Bind(&loopEnd);
1778 idx = Int32Add(*idx, Int32(1));
1779 LoopEnd(&loopHead, env, glue);
1780 Bind(&loopExit);
1781 auto ret = numElementArray;
1782 env->SubCfgExit();
1783 return ret;
1784 }
1785 }
1786
GetEnumPropertyEntries(GateRef glue,GateRef obj,Label * slowPath)1787 GateRef BuiltinsObjectStubBuilder::GetEnumPropertyEntries(GateRef glue, GateRef obj, Label* slowPath)
1788 {
1789 auto env = GetEnvironment();
1790 Label subEntry(env);
1791 env->SubCfgEntry(&subEntry);
1792 Label exit(env);
1793 Label notDictionary(env);
1794 GateRef array = GetPropertiesArray(obj);
1795 BRANCH(IsDictionaryMode(array), slowPath, ¬Dictionary);
1796 Bind(¬Dictionary);
1797
1798 DEFVARIABLE(idx, VariableType::INT32(), Int32(0));
1799 DEFVARIABLE(length, VariableType::INT32(), Int32(0));
1800 GateRef cls = LoadHClass(obj);
1801 GateRef len = GetNumberOfPropsFromHClass(cls);
1802 GateRef layout = GetLayoutFromHClass(cls);
1803
1804 NewObjectStubBuilder newBuilder(this);
1805 GateRef allEnumArray = newBuilder.NewTaggedArray(glue, len);
1806 // need to caclulate elementKind
1807 GateRef elementKind = Int32(Elements::ToUint(ElementsKind::TAGGED));
1808 Label loopHead(env);
1809 Label loopEnd(env);
1810 Label LoopNext(env);
1811 Label loopExit(env);
1812 Label propertyIsEnumerable(env);
1813 Label propertyIsString(env);
1814
1815 Jump(&loopHead);
1816 LoopBegin(&loopHead);
1817 {
1818 BRANCH(Int32LessThan(*idx, len), &LoopNext, &loopExit);
1819 Bind(&LoopNext);
1820 GateRef arrayProp = newBuilder.NewTaggedArray(glue, Int32(2)); // 2: length of array to store [key, value] is 2
1821 GateRef key = GetKeyFromLayoutInfo(layout, *idx);
1822 GateRef attr = GetPropAttrFromLayoutInfo(layout, *idx);
1823 GateRef value = JSObjectGetProperty(obj, cls, attr);
1824 BRANCH(IsEnumerable(attr), &propertyIsEnumerable, &loopEnd);
1825 Bind(&propertyIsEnumerable);
1826 {
1827 BRANCH(TaggedIsString(key), &propertyIsString, &loopEnd);
1828 Bind(&propertyIsString);
1829 {
1830 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(0), key);
1831 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(1), value);
1832 GateRef propArray = newBuilder.CreateArrayFromList(glue, arrayProp, elementKind);
1833 SetValueToTaggedArray(VariableType::JS_ANY(), glue, allEnumArray, *length, propArray);
1834 length = Int32Add(*length, Int32(1));
1835 Jump(&loopEnd);
1836 }
1837 }
1838 }
1839 Bind(&loopEnd);
1840 idx = Int32Add(*idx, Int32(1));
1841 LoopEnd(&loopHead, env, glue);
1842 Bind(&loopExit);
1843 Label needTrim(env);
1844 BRANCH(Int32LessThan(*length, len), &needTrim, &exit);
1845 Bind(&needTrim);
1846 {
1847 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, allEnumArray, ZExtInt32ToInt64(*length)});
1848 Jump(&exit);
1849 }
1850 Bind(&exit);
1851 auto ret = allEnumArray;
1852 env->SubCfgExit();
1853 return ret;
1854 }
1855
IsFrozen(Variable * result,Label * exit,Label * slowPath)1856 void BuiltinsObjectStubBuilder::IsFrozen(Variable *result, Label *exit, Label *slowPath)
1857 {
1858 auto env = GetEnvironment();
1859 GateRef obj = GetCallArg0(numArgs_);
1860 Label isEcmaObj(env);
1861 Label notEcmaObj(env);
1862 BRANCH(BoolNot(IsEcmaObject(obj)), ¬EcmaObj, &isEcmaObj);
1863 Bind(¬EcmaObj);
1864 {
1865 result->WriteVariable(TaggedTrue());
1866 Jump(exit);
1867 }
1868 Bind(&isEcmaObj);
1869 {
1870 // 1: IntegrityLevel::FROZEN
1871 GateRef status = TestIntegrityLevel(glue_, obj, Int32(1), slowPath);
1872 Label statusIsTrue(env);
1873 Label statusIsFalse(env);
1874 BRANCH(status, &statusIsTrue, &statusIsFalse);
1875 Bind(&statusIsTrue);
1876 {
1877 result->WriteVariable(TaggedTrue());
1878 Jump(exit);
1879 }
1880 Bind(&statusIsFalse);
1881 {
1882 result->WriteVariable(TaggedFalse());
1883 Jump(exit);
1884 }
1885 }
1886 }
1887
IsSealed(Variable * result,Label * exit,Label * slowPath)1888 void BuiltinsObjectStubBuilder::IsSealed(Variable *result, Label *exit, Label *slowPath)
1889 {
1890 auto env = GetEnvironment();
1891 GateRef obj = GetCallArg0(numArgs_);
1892 Label isEcmaObj(env);
1893 Label notEcmaObj(env);
1894 BRANCH(BoolNot(IsEcmaObject(obj)), ¬EcmaObj, &isEcmaObj);
1895 Bind(¬EcmaObj);
1896 {
1897 result->WriteVariable(TaggedTrue());
1898 Jump(exit);
1899 }
1900 Bind(&isEcmaObj);
1901 {
1902 // 0: IntegrityLevel::SEALED
1903 GateRef status = TestIntegrityLevel(glue_, obj, Int32(0), slowPath);
1904 Label statusIsTrue(env);
1905 Label statusIsFalse(env);
1906 BRANCH(status, &statusIsTrue, &statusIsFalse);
1907 Bind(&statusIsTrue);
1908 {
1909 result->WriteVariable(TaggedTrue());
1910 Jump(exit);
1911 }
1912 Bind(&statusIsFalse);
1913 {
1914 result->WriteVariable(TaggedFalse());
1915 Jump(exit);
1916 }
1917 }
1918 }
1919
TestIntegrityLevel(GateRef glue,GateRef obj,GateRef level,Label * slowPath)1920 GateRef BuiltinsObjectStubBuilder::TestIntegrityLevel(GateRef glue,
1921 GateRef obj, GateRef level, Label *slowPath)
1922 {
1923 auto env = GetEnvironment();
1924 Label entryPass(env);
1925 env->SubCfgEntry(&entryPass);
1926 DEFVARIABLE(result, VariableType::BOOL(), False());
1927 Label isExtensible(env);
1928 Label isNotExtensible(env);
1929 Label exit(env);
1930
1931 Label isNotJsProxy(env);
1932 Label isNotTypedArray(env);
1933 Label isNotModuleNamespace(env);
1934 Label isNotSpecialContainer(env);
1935 Label notDicMode(env);
1936 Label notHasElementKey(env);
1937 BRANCH(IsJsProxy(obj), slowPath, &isNotJsProxy);
1938 Bind(&isNotJsProxy);
1939 BRANCH(IsTypedArray(obj), slowPath, &isNotTypedArray);
1940 Bind(&isNotTypedArray);
1941 BRANCH(IsModuleNamespace(obj), slowPath, &isNotModuleNamespace);
1942 Bind(&isNotModuleNamespace);
1943 BRANCH(IsArrayListOrVector(GetObjectType(LoadHClass(obj))), slowPath, &isNotSpecialContainer);
1944 Bind(&isNotSpecialContainer);
1945 GateRef cls = LoadHClass(obj);
1946 BRANCH(IsDictionaryModeByHClass(cls), slowPath, ¬DicMode);
1947 Bind(¬DicMode);
1948 GateRef layout = GetLayoutFromHClass(cls);
1949 GateRef lengthOfKeys = GetNumberOfPropsFromHClass(cls);
1950 GateRef elementArray = GetEnumElementKeys(glue_, obj);
1951 GateRef lengthOfElements = GetLengthOfTaggedArray(elementArray);
1952 BRANCH(Int32Equal(lengthOfElements, Int32(0)), ¬HasElementKey, slowPath);
1953 Bind(¬HasElementKey);
1954
1955 GateRef status = IsExtensible(obj);
1956 BRANCH(status, &isExtensible, &isNotExtensible);
1957 Bind(&isExtensible);
1958 {
1959 result = False();
1960 Jump(&exit);
1961 }
1962 Bind(&isNotExtensible);
1963 {
1964 Label lengthIsZero(env);
1965 Label lengthNotZero(env);
1966 BRANCH(Int32Equal(lengthOfKeys, Int32(0)), &lengthIsZero, &lengthNotZero);
1967 Bind(&lengthIsZero);
1968 {
1969 result = True();
1970 Jump(&exit);
1971 }
1972 Bind(&lengthNotZero);
1973 {
1974 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
1975 Label loopHead(env);
1976 Label loopEnd(env);
1977 Label afterLoop(env);
1978 Label inRange(env);
1979 Jump(&loopHead);
1980 LoopBegin(&loopHead);
1981 {
1982 BRANCH(Int32LessThan(*index, lengthOfKeys), &inRange, &afterLoop);
1983 Bind(&inRange);
1984 {
1985 GateRef attr = GetPropAttrFromLayoutInfo(layout, *index);
1986 Label configable(env);
1987 Label notConfigable(env);
1988 Label notFrozen(env);
1989 BRANCH(IsConfigable(attr), &configable, ¬Configable);
1990 Bind(&configable);
1991 {
1992 result = False();
1993 Jump(&exit);
1994 }
1995 Bind(¬Configable);
1996 {
1997 // 1: IntegrityLevel::FROZEN
1998 GateRef isFrozen = LogicAndBuilder(env).And(Int32Equal(level, Int32(1)))
1999 .And(BoolNot(IsAccessor(attr))).And(IsWritable(attr)).Done();
2000 BRANCH(isFrozen, ¬Frozen, &loopEnd);
2001 Bind(¬Frozen);
2002 {
2003 result = False();
2004 Jump(&exit);
2005 }
2006 }
2007 }
2008 }
2009 Bind(&loopEnd);
2010 index = Int32Add(*index, Int32(1));
2011 LoopEnd(&loopHead, env, glue);
2012 Bind(&afterLoop);
2013 {
2014 result = True();
2015 Jump(&exit);
2016 }
2017 }
2018 }
2019 Bind(&exit);
2020 auto ret = *result;
2021 env->SubCfgExit();
2022 return ret;
2023 }
2024
GetOwnPropertyDescriptors(Variable * result,Label * exit,Label * slowPath)2025 void BuiltinsObjectStubBuilder::GetOwnPropertyDescriptors(Variable *result, Label *exit, Label *slowPath)
2026 {
2027 auto env = GetEnvironment();
2028 GateRef msg = GetCallArg0(numArgs_);
2029 GateRef obj = ToObject(glue_, msg);
2030 Label isPendingException(env);
2031 Label noPendingException(env);
2032 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException);
2033 Bind(&isPendingException);
2034 {
2035 Jump(exit);
2036 }
2037 Bind(&noPendingException);
2038 Label isFast(env);
2039 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath);
2040 Bind(&isFast);
2041 Label notDictMode(env);
2042 GateRef properties = GetPropertiesArray(obj);
2043 BRANCH(IsDictionaryMode(properties), slowPath, ¬DictMode);
2044 Bind(¬DictMode);
2045 Label onlyProperties(env);
2046 GateRef numOfElements = GetNumberOfElements(glue_, obj);
2047 BRANCH(Int32Equal(numOfElements, Int32(0)), &onlyProperties, slowPath);
2048 Bind(&onlyProperties);
2049 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2050 GateRef hclass = LoadHClass(obj);
2051 GateRef layout = GetLayoutFromHClass(hclass);
2052 GateRef number = GetNumberOfPropsFromHClass(hclass);
2053 GateRef valueStr = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::VALUE_STRING_INDEX);
2054 GateRef getterStr = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::GET_STRING_INDEX);
2055 GateRef setterStr = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::SET_STRING_INDEX);
2056 GateRef writableStr = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
2057 ConstantIndex::WRITABLE_STRING_INDEX);
2058 GateRef enumerableStr = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
2059 ConstantIndex::ENUMERABLE_STRING_INDEX);
2060 GateRef configurableStr = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
2061 ConstantIndex::CONFIGURABLE_STRING_INDEX);
2062 NewObjectStubBuilder newBuilder(this);
2063 newBuilder.SetParameters(glue_, 0);
2064 GateRef descriptors = newBuilder.CreateEmptyObject(glue_);
2065 Label loopHead(env);
2066 Label loopEnd(env);
2067 Label next(env);
2068 Label loopExit(env);
2069 Jump(&loopHead);
2070 LoopBegin(&loopHead);
2071 {
2072 BRANCH(Int32UnsignedLessThan(*i, number), &next, &loopExit);
2073 Bind(&next);
2074 {
2075 Label isAccessor(env);
2076 Label setValueAndIsWritable(env);
2077 Label setIsEnumerable(env);
2078 Label setIsConfigable(env);
2079 Label setDescriptor(env);
2080 GateRef key = GetKey(layout, *i);
2081 GateRef attr = GetAttr(layout, *i);
2082 GateRef descriptor = newBuilder.CreateEmptyObject(glue_);
2083 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
2084 value = JSObjectGetProperty(obj, hclass, attr);
2085 BRANCH(IsAccessor(attr), &isAccessor, &setValueAndIsWritable);
2086 Bind(&isAccessor);
2087 {
2088 Label propertyBox(env);
2089 Label checkInternalAccessor(env);
2090 BRANCH(TaggedIsPropertyBox(*value), &propertyBox, &checkInternalAccessor);
2091 Bind(&propertyBox);
2092 {
2093 value = GetValueFromPropertyBox(*value);
2094 Jump(&checkInternalAccessor);
2095 }
2096 Bind(&checkInternalAccessor);
2097 Label isInternalAccesstor(env);
2098 Label notInternalAccesstor(env);
2099 BRANCH_UNLIKELY(TaggedIsInternalAccessor(*value), &isInternalAccesstor, ¬InternalAccesstor);
2100 Bind(&isInternalAccesstor);
2101 {
2102 value = CallGetterHelper(glue_, obj, obj, *value, ProfileOperation());
2103 Jump(&setValueAndIsWritable);
2104 }
2105 Bind(¬InternalAccesstor);
2106 {
2107 Label setGetter(env);
2108 Label getSetter(env);
2109 Label setSetter(env);
2110 GateRef getter = GetAccGetter(*value);
2111 BRANCH(TaggedIsHeapObject(getter), &setGetter, &getSetter);
2112 Bind(&setGetter);
2113 {
2114 FastSetPropertyByName(glue_, descriptor, getterStr, getter);
2115 Jump(&getSetter);
2116 }
2117 Bind(&getSetter);
2118 GateRef setter = GetAccSetter(*value);
2119 BRANCH(TaggedIsHeapObject(setter), &setSetter, &setIsEnumerable);
2120 Bind(&setSetter);
2121 {
2122 FastSetPropertyByName(glue_, descriptor, setterStr, setter);
2123 Jump(&setIsEnumerable);
2124 }
2125 }
2126 }
2127 Bind(&setValueAndIsWritable);
2128 {
2129 Label isWritable(env);
2130 Label notWritable(env);
2131 FastSetPropertyByName(glue_, descriptor, valueStr, *value);
2132 BRANCH(IsWritable(attr), &isWritable, ¬Writable);
2133 Bind(&isWritable);
2134 {
2135 FastSetPropertyByName(glue_, descriptor, writableStr, TaggedTrue());
2136 Jump(&setIsEnumerable);
2137 }
2138 Bind(¬Writable);
2139 {
2140 FastSetPropertyByName(glue_, descriptor, writableStr, TaggedFalse());
2141 Jump(&setIsEnumerable);
2142 }
2143 }
2144 Bind(&setIsEnumerable);
2145 {
2146 Label isEnumerable(env);
2147 Label notEnumerable(env);
2148 BRANCH(IsEnumerable(attr), &isEnumerable, ¬Enumerable);
2149 Bind(&isEnumerable);
2150 {
2151 FastSetPropertyByName(glue_, descriptor, enumerableStr, TaggedTrue());
2152 Jump(&setIsConfigable);
2153 }
2154 Bind(¬Enumerable);
2155 {
2156 FastSetPropertyByName(glue_, descriptor, enumerableStr, TaggedFalse());
2157 Jump(&setIsConfigable);
2158 }
2159 }
2160 Bind(&setIsConfigable);
2161 {
2162 Label isConfigable(env);
2163 Label notConfigable(env);
2164 BRANCH(IsConfigable(attr), &isConfigable, ¬Configable);
2165 Bind(&isConfigable);
2166 {
2167 FastSetPropertyByName(glue_, descriptor, configurableStr, TaggedTrue());
2168 Jump(&setDescriptor);
2169 }
2170 Bind(¬Configable);
2171 {
2172 FastSetPropertyByName(glue_, descriptor, configurableStr, TaggedFalse());
2173 Jump(&setDescriptor);
2174 }
2175 }
2176 Bind(&setDescriptor);
2177 {
2178 FastSetPropertyByName(glue_, descriptors, key, descriptor);
2179 Jump(&loopEnd);
2180 }
2181 }
2182 }
2183 Bind(&loopEnd);
2184 i = Int32Add(*i, Int32(1));
2185 LoopEnd(&loopHead, env, glue_);
2186 Bind(&loopExit);
2187 *result = descriptors;
2188 Jump(exit);
2189 }
2190
2191 } // namespace panda::ecmascript::kungfu
2192