• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &notDictionaryMode);
258     Bind(&notDictionaryMode);
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, &notHole);
275             Bind(&notHole);
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, &notHole);
324                     Bind(&notHole);
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, &notHole);
478                 Bind(&notHole);
479                 {
480                     Label isAccessor(env);
481                     Label notAccessor(env);
482                     BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
483                     Bind(&isAccessor);
484                     {
485                         value = CallGetterHelper(glue_, source, source, *value, ProfileOperation());
486                         // exception
487                         Label exception(env);
488                         BRANCH(HasPendingException(glue_), &exception, &notAccessor);
489                         Bind(&exception);
490                         {
491                             *result = Exception();
492                             Jump(funcExit);
493                         }
494                     }
495                     Bind(&notAccessor);
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, &notDictionaryMode);
532     Bind(&notDictionaryMode);
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, &notTwoArg); // 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(&notTwoArg);
619         Label threeArg(env);
620         Label notThreeArg(env);
621         BRANCH(Int64Equal(numArgs_, IntPtr(3)), &threeArg, &notThreeArg); // 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(&notThreeArg);
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, &notIndex);
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, &notDictionaryElement);
679                     Bind(&notDictionaryElement);
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), &notHole, exit);
689                             Bind(&notHole);
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)), &notNegtiveOne, exit);
701                         Bind(&notNegtiveOne);
702                         {
703                             *result = TaggedTrue();
704                             Jump(exit);
705                         }
706                     }
707                 }
708             }
709             Bind(&notIndex);
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, &notDicMode);
719                     Bind(&notDicMode);
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)), &notNegtiveOne, exit);
742                         Bind(&notNegtiveOne);
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, &notDictionary);
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(&notDictionary);
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, &notHasProps);
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, &notOnlyOwnKeys);
1036             Bind(&isOnlyOwnKeys);
1037             {
1038                 result = CopyFromEnumCache(glue, enumCache);
1039                 Jump(&exit);
1040             }
1041             Bind(&notOnlyOwnKeys);
1042             {
1043                 Label numNotZero(env);
1044                 Label inSharedHeap(env);
1045                 Label notInSharedHeap(env);
1046                 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &numNotZero, &notHasProps);
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, &notInSharedHeap);
1057                 Bind(&inSharedHeap);
1058                 {
1059                     result = CopyFromEnumCache(glue, keyArray);
1060                     Jump(&exit);
1061                 }
1062                 Bind(&notInSharedHeap);
1063                 {
1064                     SetEnumCacheToHClass(VariableType::JS_ANY(), glue, hclass, keyArray);
1065                     result = CopyFromEnumCache(glue, keyArray);
1066                     Jump(&exit);
1067                 }
1068             }
1069         }
1070         Bind(&notHasProps);
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, &notPrimitiveString);
1109         Bind(&isJSPrimitiveRef);
1110         GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1111         BRANCH(TaggedIsString(value), &isPrimitiveString, &notPrimitiveString);
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, &notPrimitiveString);
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(&notPrimitiveString);
1136         GateRef elements = GetElementsArray(obj);
1137         BRANCH(IsDictionaryMode(elements), &isDictMode, &notDictMode);
1138         Bind(&notDictMode);
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, &notHole);
1154                     Bind(&notHole);
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, &notJsProxy);
1290             Bind(&notJsProxy);
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, &notEcmaObject);
1321             Bind(&isEcmaObject);
1322             Jump(&setProto);
1323             Bind(&notEcmaObject);
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, &notFunction);
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, &notFunction);
1353             Bind(&isDerivedCtor);
1354             auto cachedJSHClass = GetPrototypeFromHClass(protoOrHclass);
1355             SetProtoOrHClassToFunction(glue_, obj, cachedJSHClass);
1356             Jump(&notFunction);
1357         }
1358         Bind(&notFunction);
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, &notEqual);
1391     Bind(&isEqual);
1392     {
1393         result = True();
1394         Jump(&exit);
1395     }
1396     Bind(&notEqual);
1397     {
1398         BRANCH(IsExtensible(obj), &isExtensible, &notExtensible);
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, &notNull);
1422                     Bind(&isNull);
1423                     {
1424                         done = True();
1425                         Jump(&loopEnd);
1426                     }
1427                     Bind(&notNull);
1428                     {
1429                         BRANCH(IntPtrEqual(*tempProto, obj), &isEqual2, &notEqual2);
1430                         Bind(&isEqual2);
1431                         {
1432                             result = False();
1433                             Jump(&exit);
1434                         }
1435                         Bind(&notEqual2);
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(&notExtensible);
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, &notDictMode);
1488             Bind(&notDictMode);
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, &notDictMode);
1596             Bind(&notDictMode);
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, &notPrimitiveString);
1696     Bind(&isJSPrimitiveRef);
1697     {
1698         GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1699         BRANCH(TaggedIsString(value), &isPrimitiveString, &notPrimitiveString);
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, &notPrimitiveString);
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(&notPrimitiveString);
1724     {
1725         Label isDictMode(env);
1726         Label notDictMode(env);
1727         Label exit(env);
1728         GateRef elements = GetElementsArray(obj);
1729         BRANCH(IsDictionaryMode(elements), &isDictMode, &notDictMode);
1730         Bind(&isDictMode);
1731         {
1732             FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1733             Jump(&exit);
1734         }
1735         Bind(&notDictMode);
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, &notHole);
1751                     Bind(&notHole);
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, &notDictionary);
1788     Bind(&isDictionary);
1789     {
1790         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1791         Jump(&exit);
1792     }
1793     Bind(&notDictionary);
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, &notDictMode);
1863             Bind(&notDictMode);
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, &notPrimitiveString);
1932     Bind(&isJSPrimitiveRef);
1933     GateRef els = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1934     BRANCH(TaggedIsString(els), slowPath, &notPrimitiveString);
1935     Bind(&notPrimitiveString);
1936     BRANCH(IsDictionaryMode(elements), slowPath, &notDictMode);
1937     Bind(&notDictMode);
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, &notHole);
1952             Bind(&notHole);
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, &notDictionary);
1985     Bind(&notDictionary);
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)), &notEcmaObj, &isEcmaObj);
2052     Bind(&notEcmaObj);
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)), &notEcmaObj, &isEcmaObj);
2084     Bind(&notEcmaObj);
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, &notDicMode);
2136     Bind(&notDicMode);
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)), &notHasElementKey, slowPath);
2142     Bind(&notHasElementKey);
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, &notConfigable);
2179                     Bind(&configable);
2180                     {
2181                         result = False();
2182                         Jump(&exit);
2183                     }
2184                     Bind(&notConfigable);
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, &notFrozen, &loopEnd);
2190                         Bind(&notFrozen);
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, &notDictMode);
2233     Bind(&notDictMode);
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, &notInternalAccesstor);
2289                 Bind(&isInternalAccesstor);
2290                 {
2291                     value = CallGetterHelper(glue_, obj, obj, *value, ProfileOperation());
2292                     Jump(&setValueAndIsWritable);
2293                 }
2294                 Bind(&notInternalAccesstor);
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, &notWritable);
2322                 Bind(&isWritable);
2323                 {
2324                     FastSetPropertyByName(glue_, descriptor, writableStr, TaggedTrue());
2325                     Jump(&setIsEnumerable);
2326                 }
2327                 Bind(&notWritable);
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, &notEnumerable);
2338                 Bind(&isEnumerable);
2339                 {
2340                     FastSetPropertyByName(glue_, descriptor, enumerableStr, TaggedTrue());
2341                     Jump(&setIsConfigable);
2342                 }
2343                 Bind(&notEnumerable);
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, &notConfigable);
2354                 Bind(&isConfigable);
2355                 {
2356                     FastSetPropertyByName(glue_, descriptor, configurableStr, TaggedTrue());
2357                     Jump(&setDescriptor);
2358                 }
2359                 Bind(&notConfigable);
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