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