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