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