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