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