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