• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "ecmascript/compiler/access_object_stub_builder.h"
16 #include "ecmascript/compiler/ic_stub_builder.h"
17 #include "ecmascript/compiler/interpreter_stub-inl.h"
18 #include "ecmascript/compiler/profiler_stub_builder.h"
19 #include "ecmascript/compiler/rt_call_signature.h"
20 #include "ecmascript/compiler/stub_builder-inl.h"
21 #include "ecmascript/ic/profile_type_info.h"
22 
23 namespace panda::ecmascript::kungfu {
LoadObjByName(GateRef glue,GateRef receiver,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)24 GateRef AccessObjectStubBuilder::LoadObjByName(GateRef glue, GateRef receiver, GateRef prop, const StringIdInfo &info,
25                                                GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
26 {
27     auto env = GetEnvironment();
28     Label entry(env);
29     env->SubCfgEntry(&entry);
30     Label exit(env);
31     Label tryFastPath(env);
32     Label slowPath(env);
33 
34     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
35     GateRef value = 0;
36     ICStubBuilder builder(this);
37     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
38     builder.LoadICByName(&result, &tryFastPath, &slowPath, &exit, callback);
39     Bind(&tryFastPath);
40     {
41         GateRef propKey = ResolvePropKey(glue, prop, info);
42         result = GetPropertyByName(glue, receiver, propKey, callback, True());
43         Branch(TaggedIsHole(*result), &slowPath, &exit);
44     }
45     Bind(&slowPath);
46     {
47         GateRef propKey = ResolvePropKey(glue, prop, info);
48         result = CallRuntime(glue, RTSTUB_ID(LoadICByName),
49                              { profileTypeInfo, receiver, propKey, IntToTaggedInt(slotId) });
50         callback.TryPreDump();
51         Jump(&exit);
52     }
53     Bind(&exit);
54     auto ret = *result;
55     env->SubCfgExit();
56     return ret;
57 }
58 
59 // Used for deprecated bytecodes which will not support ic
DeprecatedLoadObjByName(GateRef glue,GateRef receiver,GateRef propKey)60 GateRef AccessObjectStubBuilder::DeprecatedLoadObjByName(GateRef glue, GateRef receiver, GateRef propKey)
61 {
62     auto env = GetEnvironment();
63     Label entry(env);
64     env->SubCfgEntry(&entry);
65     Label exit(env);
66     Label fastPath(env);
67     Label slowPath(env);
68 
69     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
70     Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
71     Bind(&fastPath);
72     {
73         result = GetPropertyByName(glue, receiver, propKey, ProfileOperation(), True());
74         Branch(TaggedIsHole(*result), &slowPath, &exit);
75     }
76     Bind(&slowPath);
77     {
78         result = CallRuntime(glue, RTSTUB_ID(LoadICByName),
79             { Undefined(), receiver, propKey, IntToTaggedInt(Int32(0xFF)) });  // 0xFF: invalid slot id
80         Jump(&exit);
81     }
82     Bind(&exit);
83     auto ret = *result;
84     env->SubCfgExit();
85     return ret;
86 }
87 
StoreObjByName(GateRef glue,GateRef receiver,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)88 GateRef AccessObjectStubBuilder::StoreObjByName(GateRef glue, GateRef receiver, GateRef prop, const StringIdInfo &info,
89                                                 GateRef value, GateRef profileTypeInfo, GateRef slotId,
90                                                 ProfileOperation callback)
91 {
92     auto env = GetEnvironment();
93     Label entry(env);
94     env->SubCfgEntry(&entry);
95     Label exit(env);
96     Label tryFastPath(env);
97     Label slowPath(env);
98 
99     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
100     ICStubBuilder builder(this);
101     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, callback);
102     builder.StoreICByName(&result, &tryFastPath, &slowPath, &exit);
103     Bind(&tryFastPath);
104     {
105         GateRef propKey = ResolvePropKey(glue, prop, info);
106         result = SetPropertyByName(glue, receiver, propKey, value, false, True(), callback);
107         Branch(TaggedIsHole(*result), &slowPath, &exit);
108     }
109     Bind(&slowPath);
110     {
111         GateRef propKey = ResolvePropKey(glue, prop, info);
112         result = CallRuntime(glue, RTSTUB_ID(StoreICByName),
113             { profileTypeInfo, receiver, propKey, value, IntToTaggedInt(slotId) });
114         callback.TryPreDump();
115         Jump(&exit);
116     }
117 
118     Bind(&exit);
119     auto ret = *result;
120     env->SubCfgExit();
121     return ret;
122 }
123 
ResolvePropKey(GateRef glue,GateRef prop,const StringIdInfo & info)124 GateRef AccessObjectStubBuilder::ResolvePropKey(GateRef glue, GateRef prop, const StringIdInfo &info)
125 {
126     if (jsFunc_ != Circuit::NullGate()) {
127         GateRef constpool = GetConstPoolFromFunction(jsFunc_);
128         return GetStringFromConstPool(glue, constpool, ChangeIntPtrToInt32(prop));
129     }
130     if (!info.IsValid()) {
131         return prop;
132     }
133     ASSERT(info.IsValid());
134     InterpreterToolsStubBuilder builder(GetCallSignature(), GetEnvironment());
135     GateRef stringId = builder.GetStringId(info);
136     return GetStringFromConstPool(glue, info.constpool, stringId);
137 }
138 
LoadObjByValue(GateRef glue,GateRef receiver,GateRef key,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)139 GateRef AccessObjectStubBuilder::LoadObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo,
140                                                 GateRef slotId, ProfileOperation callback)
141 {
142     auto env = GetEnvironment();
143     Label entry(env);
144     env->SubCfgEntry(&entry);
145     Label exit(env);
146     Label tryFastPath(env);
147     Label slowPath(env);
148 
149     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
150     GateRef value = 0;
151     ICStubBuilder builder(this);
152     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key);
153     builder.LoadICByValue(&result, &tryFastPath, &slowPath, &exit, callback);
154     Bind(&tryFastPath);
155     {
156         result = GetPropertyByValue(glue, receiver, key, callback);
157         Branch(TaggedIsHole(*result), &slowPath, &exit);
158     }
159     Bind(&slowPath);
160     {
161         result = CallRuntime(glue, RTSTUB_ID(LoadICByValue),
162             { profileTypeInfo, receiver, key, IntToTaggedInt(slotId) });
163         callback.TryPreDump();
164         Jump(&exit);
165     }
166     Bind(&exit);
167     auto ret = *result;
168     env->SubCfgExit();
169     return ret;
170 }
171 
172 // Used for deprecated bytecodes which will not support ic
DeprecatedLoadObjByValue(GateRef glue,GateRef receiver,GateRef key)173 GateRef AccessObjectStubBuilder::DeprecatedLoadObjByValue(GateRef glue, GateRef receiver, GateRef key)
174 {
175     auto env = GetEnvironment();
176     Label entry(env);
177     env->SubCfgEntry(&entry);
178     Label exit(env);
179     Label fastPath(env);
180     Label slowPath(env);
181 
182     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
183     Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
184     Bind(&fastPath);
185     {
186         result = GetPropertyByValue(glue, receiver, key, ProfileOperation());
187         Branch(TaggedIsHole(*result), &slowPath, &exit);
188     }
189     Bind(&slowPath);
190     {
191         result = CallRuntime(glue, RTSTUB_ID(LoadICByValue),
192             { Undefined(), receiver, key, IntToTaggedInt(Int32(0xFF)) });  // 0xFF: invalied slot id
193         Jump(&exit);
194     }
195     Bind(&exit);
196     auto ret = *result;
197     env->SubCfgExit();
198     return ret;
199 }
200 
StoreObjByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)201 GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value,
202                                                  GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
203 {
204     auto env = GetEnvironment();
205     Label entry(env);
206     env->SubCfgEntry(&entry);
207     Label exit(env);
208     Label tryFastPath(env);
209     Label slowPath(env);
210 
211     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
212     ICStubBuilder builder(this);
213     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key, callback);
214     builder.StoreICByValue(&result, &tryFastPath, &slowPath, &exit);
215     Bind(&tryFastPath);
216     {
217         result = SetPropertyByValue(glue, receiver, key, value, false, callback);
218         Branch(TaggedIsHole(*result), &slowPath, &exit);
219     }
220     Bind(&slowPath);
221     {
222         result = CallRuntime(glue, RTSTUB_ID(StoreICByValue),
223             { profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId) });
224         callback.TryPreDump();
225         Jump(&exit);
226     }
227     Bind(&exit);
228     auto ret = *result;
229     env->SubCfgExit();
230     return ret;
231 }
232 
StoreOwnByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)233 GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value,
234                                                  GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
235 {
236     auto env = GetEnvironment();
237     Label entry(env);
238     env->SubCfgEntry(&entry);
239     Label exit(env);
240     Label tryFastPath(env);
241     Label slowPath(env);
242     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
243     ICStubBuilder builder(this);
244     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, IntToTaggedPtr(index), callback);
245     builder.StoreICByValue(&result, &tryFastPath, &slowPath, &exit);
246     Bind(&tryFastPath);
247     {
248         Label isHeapObject(env);
249         Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
250         Bind(&isHeapObject);
251         Label notClassConstructor(env);
252         Branch(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
253         Bind(&notClassConstructor);
254         Label notClassPrototype(env);
255         Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
256         Bind(&notClassPrototype);
257         result = SetPropertyByIndex(glue, receiver, index, value, true);
258         Branch(TaggedIsHole(*result), &slowPath, &exit);
259     }
260     Bind(&slowPath);
261     {
262         result = CallRuntime(glue, RTSTUB_ID(StoreOwnICByValue),
263             { profileTypeInfo, receiver, IntToTaggedInt(index), value, IntToTaggedInt(slotId) });
264         callback.TryPreDump();
265         Jump(&exit);
266     }
267     Bind(&exit);
268     auto ret = *result;
269     env->SubCfgExit();
270     return ret;
271 }
272 
TryLoadGlobalByName(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)273 GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
274                                                      GateRef profileTypeInfo, GateRef slotId,
275                                                      ProfileOperation callback)
276 {
277     auto env = GetEnvironment();
278     Label entry(env);
279     env->SubCfgEntry(&entry);
280     Label exit(env);
281     Label tryFastPath(env);
282     Label slowPath(env);
283 
284     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
285     GateRef receiver = 0;
286     GateRef value = 0;
287     ICStubBuilder builder(this);
288     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
289     builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
290     Bind(&tryFastPath);
291     {
292         GateRef propKey = ResolvePropKey(glue, prop, info);
293         GateRef record = LdGlobalRecord(glue, propKey);
294         Label foundInRecord(env);
295         Label notFoundInRecord(env);
296         Branch(TaggedIsUndefined(record), &notFoundInRecord, &foundInRecord);
297         Bind(&foundInRecord);
298         {
299             result = Load(VariableType::JS_ANY(), record, IntPtr(PropertyBox::VALUE_OFFSET));
300             Jump(&exit);
301         }
302         Bind(&notFoundInRecord);
303         {
304             GateRef globalObject = GetGlobalObject(glue);
305             result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
306             Branch(TaggedIsHole(*result), &slowPath, &exit);
307         }
308     }
309     Bind(&slowPath);
310     {
311         GateRef propKey = ResolvePropKey(glue, prop, info);
312         result = CallRuntime(glue, RTSTUB_ID(TryLdGlobalICByName),
313                              { profileTypeInfo, propKey, IntToTaggedInt(slotId) });
314         Jump(&exit);
315     }
316 
317     Bind(&exit);
318     auto ret = *result;
319     env->SubCfgExit();
320     return ret;
321 }
322 
TryStoreGlobalByName(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)323 GateRef AccessObjectStubBuilder::TryStoreGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
324                                                       GateRef value, GateRef profileTypeInfo, GateRef slotId,
325                                                       ProfileOperation callback)
326 {
327     auto env = GetEnvironment();
328     Label entry(env);
329     env->SubCfgEntry(&entry);
330     Label exit(env);
331     Label tryFastPath(env);
332     Label slowPath(env);
333 
334     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
335     GateRef receiver = 0;
336     ICStubBuilder builder(this);
337     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
338     builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
339     Bind(&tryFastPath);
340     {
341         GateRef propKey = ResolvePropKey(glue, prop, info);
342         GateRef record = LdGlobalRecord(glue, propKey);
343         Label foundInRecord(env);
344         Label notFoundInRecord(env);
345         Branch(TaggedIsUndefined(record), &notFoundInRecord, &foundInRecord);
346         Bind(&foundInRecord);
347         {
348             result = CallRuntime(glue, RTSTUB_ID(TryUpdateGlobalRecord), { propKey, value });
349             Jump(&exit);
350         }
351         Bind(&notFoundInRecord);
352         {
353             GateRef globalObject = GetGlobalObject(glue);
354             result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
355             Label isFoundInGlobal(env);
356             Label notFoundInGlobal(env);
357             Branch(TaggedIsHole(*result), &notFoundInGlobal, &isFoundInGlobal);
358             Bind(&isFoundInGlobal);
359             {
360                 result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value });
361                 Jump(&exit);
362             }
363             Bind(&notFoundInGlobal);
364             {
365                 result = CallRuntime(glue, RTSTUB_ID(ThrowReferenceError), { propKey });
366                 Jump(&exit);
367             }
368         }
369     }
370     Bind(&slowPath);
371     {
372         GateRef propKey = ResolvePropKey(glue, prop, info);
373         GateRef globalObject = GetGlobalObject(glue);
374         result = CallRuntime(glue, RTSTUB_ID(StoreMiss),
375                              { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId),
376                                IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalTryStoreIC))) });
377         Jump(&exit);
378     }
379 
380     Bind(&exit);
381     auto ret = *result;
382     env->SubCfgExit();
383     return ret;
384 }
385 
LoadGlobalVar(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)386 GateRef AccessObjectStubBuilder::LoadGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
387                                                GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
388 {
389     auto env = GetEnvironment();
390     Label entry(env);
391     env->SubCfgEntry(&entry);
392     Label exit(env);
393     Label tryFastPath(env);
394     Label slowPath(env);
395 
396     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
397     GateRef receiver = 0;
398     GateRef value = 0;
399     ICStubBuilder builder(this);
400     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
401     builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
402     Bind(&tryFastPath);
403     {
404         GateRef globalObject = GetGlobalObject(glue);
405         GateRef propKey = ResolvePropKey(glue, prop, info);
406         result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
407         Branch(TaggedIsHole(*result), &slowPath, &exit);
408     }
409     Bind(&slowPath);
410     {
411         GateRef globalObject = GetGlobalObject(glue);
412         GateRef propKey = ResolvePropKey(glue, prop, info);
413         result = CallRuntime(glue, RTSTUB_ID(LdGlobalICVar),
414                              { globalObject, propKey, profileTypeInfo, IntToTaggedInt(slotId) });
415         Jump(&exit);
416     }
417 
418     Bind(&exit);
419     auto ret = *result;
420     env->SubCfgExit();
421     return ret;
422 }
423 
StoreGlobalVar(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId)424 GateRef AccessObjectStubBuilder::StoreGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
425                                                 GateRef value, GateRef profileTypeInfo, GateRef slotId)
426 {
427     auto env = GetEnvironment();
428     Label entry(env);
429     env->SubCfgEntry(&entry);
430     Label exit(env);
431     Label tryFastPath(env);
432     Label slowPath(env);
433 
434     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
435     GateRef receiver = 0;
436     ICStubBuilder builder(this);
437     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
438     builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
439     Bind(&tryFastPath);
440     {
441         GateRef propKey = ResolvePropKey(glue, prop, info);
442         // IR later
443         result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value });
444         Jump(&exit);
445     }
446     Bind(&slowPath);
447     {
448         GateRef propKey = ResolvePropKey(glue, prop, info);
449         GateRef globalObject = GetGlobalObject(glue);
450         result = CallRuntime(glue, RTSTUB_ID(StoreMiss),
451                              { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId),
452                                IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalStoreIC))) });
453         Jump(&exit);
454     }
455 
456     Bind(&exit);
457     auto ret = *result;
458     env->SubCfgExit();
459     return ret;
460 }
461 
StOwnByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)462 GateRef AccessObjectStubBuilder::StOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
463 {
464     auto env = GetEnvironment();
465     Label entry(env);
466     env->SubCfgEntry(&entry);
467     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
468     Label isHeapObject(env);
469     Label slowPath(env);
470     Label exit(env);
471     Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
472     Bind(&isHeapObject);
473     Label notClassConstructor(env);
474     Branch(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
475     Bind(&notClassConstructor);
476     Label notClassPrototype(env);
477     Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
478     Bind(&notClassPrototype);
479     {
480         result = SetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), value, true);
481         Branch(TaggedIsHole(*result), &slowPath, &exit);
482     }
483     Bind(&slowPath);
484     {
485         result = CallRuntime(glue, RTSTUB_ID(StOwnByIndex), {receiver, IntToTaggedInt(index), value });
486         Jump(&exit);
487     }
488     Bind(&exit);
489     auto ret = *result;
490     env->SubCfgExit();
491     return ret;
492 }
493 
StOwnByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value)494 GateRef AccessObjectStubBuilder::StOwnByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value)
495 {
496     auto env = GetEnvironment();
497     Label entry(env);
498     env->SubCfgEntry(&entry);
499     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
500     Label isHeapObject(env);
501     Label slowPath(env);
502     Label exit(env);
503     Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
504     Bind(&isHeapObject);
505     Label notClassConstructor(env);
506     Branch(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
507     Bind(&notClassConstructor);
508     Label notClassPrototype(env);
509     Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
510     Bind(&notClassPrototype);
511     {
512         result = SetPropertyByValue(glue, receiver, key, value, true);
513         Branch(TaggedIsHole(*result), &slowPath, &exit);
514     }
515     Bind(&slowPath);
516     {
517         result = CallRuntime(glue, RTSTUB_ID(StOwnByValue), { receiver, key, value });
518         Jump(&exit);
519     }
520     Bind(&exit);
521     auto ret = *result;
522     env->SubCfgExit();
523     return ret;
524 }
525 
StOwnByName(GateRef glue,GateRef receiver,GateRef key,GateRef value)526 GateRef AccessObjectStubBuilder::StOwnByName(GateRef glue, GateRef receiver, GateRef key, GateRef value)
527 {
528     auto env = GetEnvironment();
529     Label entry(env);
530     env->SubCfgEntry(&entry);
531     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
532     Label isJSObject(env);
533     Label slowPath(env);
534     Label exit(env);
535     Branch(IsJSObject(receiver), &isJSObject, &slowPath);
536     Bind(&isJSObject);
537     Label notClassConstructor(env);
538     Branch(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
539     Bind(&notClassConstructor);
540     Label notClassPrototype(env);
541     Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
542     Bind(&notClassPrototype);
543     {
544         result = SetPropertyByName(glue, receiver, key, value, true, True());
545         Branch(TaggedIsHole(*result), &slowPath, &exit);
546     }
547     Bind(&slowPath);
548     {
549         result = CallRuntime(glue, RTSTUB_ID(StOwnByName), { receiver, key, value });
550         Jump(&exit);
551     }
552     Bind(&exit);
553     auto ret = *result;
554     env->SubCfgExit();
555     return ret;
556 }
557 
StOwnByValueWithNameSet(GateRef glue,GateRef receiver,GateRef key,GateRef value)558 GateRef AccessObjectStubBuilder::StOwnByValueWithNameSet(GateRef glue, GateRef receiver, GateRef key, GateRef value)
559 {
560     auto env = GetEnvironment();
561     Label entry(env);
562     env->SubCfgEntry(&entry);
563     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
564     Label isHeapObject(env);
565     Label slowPath(env);
566     Label notClassConstructor(env);
567     Label notClassPrototype(env);
568     Label notHole(env);
569     Label exit(env);
570     Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
571     Bind(&isHeapObject);
572     {
573         Branch(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
574         Bind(&notClassConstructor);
575         {
576             Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
577             Bind(&notClassPrototype);
578             {
579                 result = SetPropertyByValue(glue, receiver, key, value, false);
580                 Branch(TaggedIsHole(*result), &slowPath, &notHole);
581                 Bind(&notHole);
582                 {
583                     Label notexception(env);
584                     Branch(TaggedIsException(*result), &exit, &notexception);
585                     Bind(&notexception);
586                     CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), { value, key });
587                     Jump(&exit);
588                 }
589             }
590         }
591     }
592     Bind(&slowPath);
593     {
594         result = CallRuntime(glue, RTSTUB_ID(StOwnByValueWithNameSet), { receiver, key, value });
595         Jump(&exit);
596     }
597     Bind(&exit);
598     auto ret = *result;
599     env->SubCfgExit();
600     return ret;
601 }
602 
StOwnByNameWithNameSet(GateRef glue,GateRef receiver,GateRef key,GateRef value)603 GateRef AccessObjectStubBuilder::StOwnByNameWithNameSet(GateRef glue, GateRef receiver, GateRef key, GateRef value)
604 {
605     auto env = GetEnvironment();
606     Label entry(env);
607     env->SubCfgEntry(&entry);
608     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
609     Label isJSObject(env);
610     Label notJSObject(env);
611     Label notClassConstructor(env);
612     Label notClassPrototype(env);
613     Label notHole(env);
614     Label exit(env);
615     Branch(IsJSObject(receiver), &isJSObject, &notJSObject);
616     Bind(&isJSObject);
617     {
618         Branch(IsClassConstructor(receiver), &notJSObject, &notClassConstructor);
619         Bind(&notClassConstructor);
620         {
621             Branch(IsClassPrototype(receiver), &notJSObject, &notClassPrototype);
622             Bind(&notClassPrototype);
623             {
624                 result = SetPropertyByName(glue, receiver, key, value, true, True());
625                 Branch(TaggedIsHole(*result), &notJSObject, &notHole);
626                 Bind(&notHole);
627                 {
628                     Label notException(env);
629                     Branch(TaggedIsException(*result), &exit, &notException);
630                     Bind(&notException);
631                     CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), {value, key});
632                     Jump(&exit);
633                 }
634             }
635         }
636     }
637     Bind(&notJSObject);
638     {
639         result = CallRuntime(glue, RTSTUB_ID(StOwnByNameWithNameSet), { receiver, key, value });
640         Jump(&exit);
641     }
642     Bind(&exit);
643     auto ret = *result;
644     env->SubCfgExit();
645     return ret;
646 }
647 
StObjByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)648 GateRef AccessObjectStubBuilder::StObjByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
649 {
650     auto env = GetEnvironment();
651     Label entry(env);
652     env->SubCfgEntry(&entry);
653     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
654     Label exit(env);
655     Label fastPath(env);
656     Label slowPath(env);
657     Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
658     Bind(&fastPath);
659     {
660         result = SetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), value, false);
661         Branch(TaggedIsHole(*result), &slowPath, &exit);
662     }
663     Bind(&slowPath);
664     {
665         result = CallRuntime(glue, RTSTUB_ID(StObjByIndex), {receiver, IntToTaggedInt(index), value});
666         Jump(&exit);
667     }
668     Bind(&exit);
669     auto ret = *result;
670     env->SubCfgExit();
671     return ret;
672 }
673 
LdObjByIndex(GateRef glue,GateRef receiver,GateRef index)674 GateRef AccessObjectStubBuilder::LdObjByIndex(GateRef glue, GateRef receiver, GateRef index)
675 {
676     auto env = GetEnvironment();
677     Label entry(env);
678     env->SubCfgEntry(&entry);
679     DEFVARIABLE(varAcc, VariableType::JS_ANY(), Hole());
680     Label fastPath(env);
681     Label slowPath(env);
682     Label exit(env);
683     Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
684     Bind(&fastPath);
685     {
686         varAcc = GetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), ProfileOperation());
687         Branch(TaggedIsHole(*varAcc), &slowPath, &exit);
688     }
689     Bind(&slowPath);
690     {
691         GateRef undefined = Undefined();
692         auto args = { receiver, IntToTaggedInt(index), TaggedFalse(), undefined };
693         varAcc = CallRuntime(glue, RTSTUB_ID(LdObjByIndex), args);
694         Jump(&exit);
695     }
696     Bind(&exit);
697     auto ret = *varAcc;
698     env->SubCfgExit();
699     return ret;
700 }
701 }  // namespace panda::ecmascript::kungfu
702