• 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);
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, callback, True());
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);
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(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);
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(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);
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, callback, True());
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, ProfileOperation(), True());
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);
205     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, callback);
206     builder.StoreICByName(&result, &tryFastPath, &tryPreDump, &exit);
207     Bind(&tryFastPath);
208     {
209         GateRef propKey = ResolvePropKey(glue, prop, info);
210         result = SetPropertyByName(glue, receiver, propKey, value, false, True(), callback);
211         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
212     }
213     Bind(&tryPreDump);
214     {
215         callback.TryPreDump();
216         Jump(&slowPath);
217     }
218     Bind(&slowPath);
219     {
220         GateRef propKey = ResolvePropKey(glue, prop, info);
221         result = CallRuntime(
222             glue, RTSTUB_ID(StoreICByName), {profileTypeInfo, receiver, propKey, value, IntToTaggedInt(slotId)});
223         Jump(&exit);
224     }
225 
226     Bind(&exit);
227     auto ret = *result;
228     env->SubCfgExit();
229     return ret;
230 }
231 
StorePrivatePropertyByName(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)232 GateRef AccessObjectStubBuilder::StorePrivatePropertyByName(GateRef glue,
233                                                             GateRef receiver,
234                                                             GateRef key,
235                                                             GateRef value,
236                                                             GateRef profileTypeInfo,
237                                                             GateRef slotId,
238                                                             ProfileOperation callback)
239 {
240     auto env = GetEnvironment();
241     Label entry(env);
242     env->SubCfgEntry(&entry);
243     Label exit(env);
244     Label tryFastPath(env);
245     Label slowPath(env);
246     Label tryPreDump(env);
247 
248     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
249     ICStubBuilder builder(this);
250     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, callback);
251     builder.StoreICByName(&result, &tryFastPath, &tryPreDump, &exit);
252     Bind(&tryFastPath);
253     {
254         result = SetPropertyByName(glue, receiver, key, value, false, True(), callback);
255         Branch(TaggedIsHole(*result), &slowPath, &exit);
256     }
257     Bind(&tryPreDump);
258     {
259         callback.TryPreDump();
260         Jump(&slowPath);
261     }
262     Bind(&slowPath);
263     {
264         result = CallRuntime(
265             glue, RTSTUB_ID(StoreICByName), {profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId)});
266         Jump(&exit);
267     }
268 
269     Bind(&exit);
270     auto ret = *result;
271     env->SubCfgExit();
272     return ret;
273 }
274 
ResolvePropKey(GateRef glue,GateRef prop,const StringIdInfo & info)275 GateRef AccessObjectStubBuilder::ResolvePropKey(GateRef glue, GateRef prop, const StringIdInfo &info)
276 {
277     if (jsFunc_ != Circuit::NullGate()) {
278         GateRef constpool = GetConstPoolFromFunction(jsFunc_);
279         return GetStringFromConstPool(glue, constpool, ChangeIntPtrToInt32(prop));
280     }
281     if (!info.IsValid()) {
282         return prop;
283     }
284     ASSERT(info.IsValid());
285     InterpreterToolsStubBuilder builder(GetCallSignature(), GetEnvironment());
286     GateRef stringId = builder.GetStringId(info);
287     return GetStringFromConstPool(glue, info.GetConstantPool(), stringId);
288 }
289 
LoadObjByValue(GateRef glue,GateRef receiver,GateRef key,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)290 GateRef AccessObjectStubBuilder::LoadObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo,
291                                                 GateRef slotId, ProfileOperation callback)
292 {
293     auto env = GetEnvironment();
294     Label entry(env);
295     env->SubCfgEntry(&entry);
296     Label exit(env);
297     Label tryFastPath(env);
298     Label slowPath(env);
299     Label tryPreDump(env);
300 
301     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
302     GateRef value = 0;
303     ICStubBuilder builder(this);
304     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key);
305     builder.LoadICByValue(&result, &tryFastPath, &tryPreDump, &exit, callback);
306     Bind(&tryFastPath);
307     {
308         result = GetPropertyByValue(glue, receiver, key, callback);
309         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
310     }
311     Bind(&tryPreDump);
312     {
313         callback.TryPreDump();
314         Jump(&slowPath);
315     }
316     Bind(&slowPath);
317     {
318         result = CallRuntime(glue, RTSTUB_ID(LoadICByValue), {profileTypeInfo, receiver, key, IntToTaggedInt(slotId)});
319         Jump(&exit);
320     }
321     Bind(&exit);
322     auto ret = *result;
323     env->SubCfgExit();
324     return ret;
325 }
326 
327 // Used for deprecated bytecodes which will not support ic
DeprecatedLoadObjByValue(GateRef glue,GateRef receiver,GateRef key)328 GateRef AccessObjectStubBuilder::DeprecatedLoadObjByValue(GateRef glue, GateRef receiver, GateRef key)
329 {
330     auto env = GetEnvironment();
331     Label entry(env);
332     env->SubCfgEntry(&entry);
333     Label exit(env);
334     Label fastPath(env);
335     Label slowPath(env);
336 
337     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
338     BRANCH(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
339     Bind(&fastPath);
340     {
341         result = GetPropertyByValue(glue, receiver, key, ProfileOperation());
342         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
343     }
344     Bind(&slowPath);
345     {
346         result = CallRuntime(glue, RTSTUB_ID(LoadICByValue),
347             { Undefined(), receiver, key, IntToTaggedInt(Int32(0xFF)) });  // 0xFF: invalied slot id
348         Jump(&exit);
349     }
350     Bind(&exit);
351     auto ret = *result;
352     env->SubCfgExit();
353     return ret;
354 }
355 
StoreOwnByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)356 GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value,
357                                                  GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
358 {
359     auto env = GetEnvironment();
360     Label entry(env);
361     env->SubCfgEntry(&entry);
362     Label exit(env);
363     Label tryFastPath(env);
364     Label slowPath(env);
365     Label tryPreDump(env);
366 
367     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
368     ICStubBuilder builder(this);
369     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, IntToTaggedPtr(index), callback);
370     builder.StoreICByValue(&result, &tryFastPath, &tryPreDump, &exit);
371     Bind(&tryFastPath);
372     {
373         Label isHeapObject(env);
374         BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
375         Bind(&isHeapObject);
376         Label notClassConstructor(env);
377         BRANCH(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
378         Bind(&notClassConstructor);
379         Label notClassPrototype(env);
380         BRANCH(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
381         Bind(&notClassPrototype);
382         result = SetPropertyByIndex(glue, receiver, index, value, true);
383         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
384     }
385     Bind(&tryPreDump);
386     {
387         callback.TryPreDump();
388         Jump(&slowPath);
389     }
390     Bind(&slowPath);
391     {
392         result = CallRuntime(glue,
393                              RTSTUB_ID(StoreOwnICByValue),
394                              {profileTypeInfo, receiver, IntToTaggedInt(index), value, IntToTaggedInt(slotId)});
395         Jump(&exit);
396     }
397     Bind(&exit);
398     auto ret = *result;
399     env->SubCfgExit();
400     return ret;
401 }
402 
StoreObjByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)403 GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value,
404                                                  GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
405 {
406     auto env = GetEnvironment();
407     Label entry(env);
408     env->SubCfgEntry(&entry);
409     Label exit(env);
410     Label tryFastPath(env);
411     Label slowPath(env);
412     Label tryPreDump(env);
413 
414     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
415     ICStubBuilder builder(this);
416     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key, callback);
417     builder.StoreICByValue(&result, &tryFastPath, &tryPreDump, &exit);
418     Bind(&tryFastPath);
419     {
420         result = SetPropertyByValue(glue, receiver, key, value, false, callback);
421         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
422     }
423     Bind(&tryPreDump);
424     {
425         callback.TryPreDump();
426         Jump(&slowPath);
427     }
428     Bind(&slowPath);
429     {
430         result = CallRuntime(
431             glue, RTSTUB_ID(StoreICByValue), {profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId)});
432         Jump(&exit);
433     }
434     Bind(&exit);
435     auto ret = *result;
436     env->SubCfgExit();
437     return ret;
438 }
439 
TryLoadGlobalByName(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)440 GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
441                                                      GateRef profileTypeInfo, GateRef slotId,
442                                                      ProfileOperation callback)
443 {
444     auto env = GetEnvironment();
445     Label entry(env);
446     env->SubCfgEntry(&entry);
447     Label exit(env);
448     Label tryFastPath(env);
449     Label slowPath(env);
450 
451     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
452     GateRef receiver = 0;
453     GateRef value = 0;
454     ICStubBuilder builder(this);
455     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
456     builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
457     Bind(&tryFastPath);
458     {
459         GateRef propKey = ResolvePropKey(glue, prop, info);
460         GateRef record = LdGlobalRecord(glue, propKey);
461         Label foundInRecord(env);
462         Label notFoundInRecord(env);
463         BRANCH(TaggedIsUndefined(record), &notFoundInRecord, &foundInRecord);
464         Bind(&foundInRecord);
465         {
466             result = Load(VariableType::JS_ANY(), record, IntPtr(PropertyBox::VALUE_OFFSET));
467             Jump(&exit);
468         }
469         Bind(&notFoundInRecord);
470         {
471             GateRef globalObject = GetGlobalObject(glue);
472             result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
473             BRANCH(TaggedIsHole(*result), &slowPath, &exit);
474         }
475     }
476     Bind(&slowPath);
477     {
478         GateRef propKey = ResolvePropKey(glue, prop, info);
479         result = CallRuntime(glue, RTSTUB_ID(TryLdGlobalICByName),
480                              { profileTypeInfo, propKey, IntToTaggedInt(slotId) });
481         Jump(&exit);
482     }
483 
484     Bind(&exit);
485     auto ret = *result;
486     env->SubCfgExit();
487     return ret;
488 }
489 
TryStoreGlobalByName(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)490 GateRef AccessObjectStubBuilder::TryStoreGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
491                                                       GateRef value, GateRef profileTypeInfo, GateRef slotId,
492                                                       ProfileOperation callback)
493 {
494     auto env = GetEnvironment();
495     Label entry(env);
496     env->SubCfgEntry(&entry);
497     Label exit(env);
498     Label tryFastPath(env);
499     Label slowPath(env);
500 
501     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
502     GateRef receiver = 0;
503     ICStubBuilder builder(this);
504     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
505     builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
506     Bind(&tryFastPath);
507     {
508         GateRef propKey = ResolvePropKey(glue, prop, info);
509         GateRef record = LdGlobalRecord(glue, propKey);
510         Label foundInRecord(env);
511         Label notFoundInRecord(env);
512         BRANCH(TaggedIsUndefined(record), &notFoundInRecord, &foundInRecord);
513         Bind(&foundInRecord);
514         {
515             result = CallRuntime(glue, RTSTUB_ID(TryUpdateGlobalRecord), { propKey, value });
516             Jump(&exit);
517         }
518         Bind(&notFoundInRecord);
519         {
520             GateRef globalObject = GetGlobalObject(glue);
521             result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
522             Label isFoundInGlobal(env);
523             Label notFoundInGlobal(env);
524             BRANCH(TaggedIsHole(*result), &notFoundInGlobal, &isFoundInGlobal);
525             Bind(&isFoundInGlobal);
526             {
527                 result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value });
528                 Jump(&exit);
529             }
530             Bind(&notFoundInGlobal);
531             {
532                 result = CallRuntime(glue, RTSTUB_ID(ThrowReferenceError), { propKey });
533                 Jump(&exit);
534             }
535         }
536     }
537     Bind(&slowPath);
538     {
539         GateRef propKey = ResolvePropKey(glue, prop, info);
540         GateRef globalObject = GetGlobalObject(glue);
541         result = CallRuntime(glue, RTSTUB_ID(StoreMiss),
542                              { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId),
543                                IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalTryStoreIC))) });
544         Jump(&exit);
545     }
546 
547     Bind(&exit);
548     auto ret = *result;
549     env->SubCfgExit();
550     return ret;
551 }
552 
LoadGlobalVar(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)553 GateRef AccessObjectStubBuilder::LoadGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
554                                                GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
555 {
556     auto env = GetEnvironment();
557     Label entry(env);
558     env->SubCfgEntry(&entry);
559     Label exit(env);
560     Label tryFastPath(env);
561     Label slowPath(env);
562 
563     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
564     GateRef receiver = 0;
565     GateRef value = 0;
566     ICStubBuilder builder(this);
567     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
568     builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
569     Bind(&tryFastPath);
570     {
571         GateRef globalObject = GetGlobalObject(glue);
572         GateRef propKey = ResolvePropKey(glue, prop, info);
573         result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
574         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
575     }
576     Bind(&slowPath);
577     {
578         GateRef globalObject = GetGlobalObject(glue);
579         GateRef propKey = ResolvePropKey(glue, prop, info);
580         result = CallRuntime(glue, RTSTUB_ID(LdGlobalICVar),
581                              { globalObject, propKey, profileTypeInfo, IntToTaggedInt(slotId) });
582         Jump(&exit);
583     }
584 
585     Bind(&exit);
586     auto ret = *result;
587     env->SubCfgExit();
588     return ret;
589 }
590 
StoreGlobalVar(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId)591 GateRef AccessObjectStubBuilder::StoreGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
592                                                 GateRef value, GateRef profileTypeInfo, GateRef slotId)
593 {
594     auto env = GetEnvironment();
595     Label entry(env);
596     env->SubCfgEntry(&entry);
597     Label exit(env);
598     Label tryFastPath(env);
599     Label slowPath(env);
600 
601     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
602     GateRef receiver = 0;
603     ICStubBuilder builder(this);
604     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
605     builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
606     Bind(&tryFastPath);
607     {
608         GateRef propKey = ResolvePropKey(glue, prop, info);
609         // IR later
610         result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value });
611         Jump(&exit);
612     }
613     Bind(&slowPath);
614     {
615         GateRef propKey = ResolvePropKey(glue, prop, info);
616         GateRef globalObject = GetGlobalObject(glue);
617         result = CallRuntime(glue, RTSTUB_ID(StoreMiss),
618                              { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId),
619                                IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalStoreIC))) });
620         Jump(&exit);
621     }
622 
623     Bind(&exit);
624     auto ret = *result;
625     env->SubCfgExit();
626     return ret;
627 }
628 
StOwnByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)629 GateRef AccessObjectStubBuilder::StOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
630 {
631     auto env = GetEnvironment();
632     Label entry(env);
633     env->SubCfgEntry(&entry);
634     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
635     Label isHeapObject(env);
636     Label slowPath(env);
637     Label exit(env);
638     BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
639     Bind(&isHeapObject);
640     Label notClassConstructor(env);
641     BRANCH(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
642     Bind(&notClassConstructor);
643     Label notClassPrototype(env);
644     BRANCH(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
645     Bind(&notClassPrototype);
646     {
647         result = SetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), value, true);
648         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
649     }
650     Bind(&slowPath);
651     {
652         result = CallRuntime(glue, RTSTUB_ID(StOwnByIndex), {receiver, IntToTaggedInt(index), value });
653         Jump(&exit);
654     }
655     Bind(&exit);
656     auto ret = *result;
657     env->SubCfgExit();
658     return ret;
659 }
660 
StOwnByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value)661 GateRef AccessObjectStubBuilder::StOwnByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value)
662 {
663     auto env = GetEnvironment();
664     Label entry(env);
665     env->SubCfgEntry(&entry);
666     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
667     Label isHeapObject(env);
668     Label slowPath(env);
669     Label exit(env);
670     BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
671     Bind(&isHeapObject);
672     Label notClassConstructor(env);
673     BRANCH(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
674     Bind(&notClassConstructor);
675     Label notClassPrototype(env);
676     BRANCH(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
677     Bind(&notClassPrototype);
678     {
679         result = SetPropertyByValue(glue, receiver, key, value, true);
680         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
681     }
682     Bind(&slowPath);
683     {
684         result = CallRuntime(glue, RTSTUB_ID(StOwnByValue), { receiver, key, value });
685         Jump(&exit);
686     }
687     Bind(&exit);
688     auto ret = *result;
689     env->SubCfgExit();
690     return ret;
691 }
692 
StOwnByName(GateRef glue,GateRef receiver,GateRef key,GateRef value)693 GateRef AccessObjectStubBuilder::StOwnByName(GateRef glue, GateRef receiver, GateRef key, GateRef value)
694 {
695     auto env = GetEnvironment();
696     Label entry(env);
697     env->SubCfgEntry(&entry);
698     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
699     Label isJSObject(env);
700     Label slowPath(env);
701     Label exit(env);
702     BRANCH(IsJSObject(receiver), &isJSObject, &slowPath);
703     Bind(&isJSObject);
704     Label notClassConstructor(env);
705     BRANCH(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
706     Bind(&notClassConstructor);
707     Label notClassPrototype(env);
708     BRANCH(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
709     Bind(&notClassPrototype);
710     {
711         result = SetPropertyByName(glue, receiver, key, value, true, True());
712         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
713     }
714     Bind(&slowPath);
715     {
716         result = CallRuntime(glue, RTSTUB_ID(StOwnByName), { receiver, key, value });
717         Jump(&exit);
718     }
719     Bind(&exit);
720     auto ret = *result;
721     env->SubCfgExit();
722     return ret;
723 }
724 
StOwnByValueWithNameSet(GateRef glue,GateRef receiver,GateRef key,GateRef value)725 GateRef AccessObjectStubBuilder::StOwnByValueWithNameSet(GateRef glue, GateRef receiver, GateRef key, GateRef value)
726 {
727     auto env = GetEnvironment();
728     Label entry(env);
729     env->SubCfgEntry(&entry);
730     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
731     Label isHeapObject(env);
732     Label slowPath(env);
733     Label notClassConstructor(env);
734     Label notClassPrototype(env);
735     Label notHole(env);
736     Label exit(env);
737     BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
738     Bind(&isHeapObject);
739     {
740         BRANCH(IsClassConstructor(receiver), &slowPath, &notClassConstructor);
741         Bind(&notClassConstructor);
742         {
743             BRANCH(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
744             Bind(&notClassPrototype);
745             {
746                 result = SetPropertyByValue(glue, receiver, key, value, true, ProfileOperation(), true);
747                 BRANCH(TaggedIsHole(*result), &slowPath, &notHole);
748                 Bind(&notHole);
749                 {
750                     Label notexception(env);
751                     BRANCH(TaggedIsException(*result), &exit, &notexception);
752                     Bind(&notexception);
753                     CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), { value, key });
754                     Jump(&exit);
755                 }
756             }
757         }
758     }
759     Bind(&slowPath);
760     {
761         result = CallRuntime(glue, RTSTUB_ID(StOwnByValueWithNameSet), { receiver, key, value });
762         Jump(&exit);
763     }
764     Bind(&exit);
765     auto ret = *result;
766     env->SubCfgExit();
767     return ret;
768 }
769 
StOwnByNameWithNameSet(GateRef glue,GateRef receiver,GateRef key,GateRef value)770 GateRef AccessObjectStubBuilder::StOwnByNameWithNameSet(GateRef glue, GateRef receiver, GateRef key, GateRef value)
771 {
772     auto env = GetEnvironment();
773     Label entry(env);
774     env->SubCfgEntry(&entry);
775     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
776     Label isJSObject(env);
777     Label notJSObject(env);
778     Label notClassConstructor(env);
779     Label notClassPrototype(env);
780     Label notHole(env);
781     Label exit(env);
782     BRANCH(IsJSObject(receiver), &isJSObject, &notJSObject);
783     Bind(&isJSObject);
784     {
785         BRANCH(IsClassConstructor(receiver), &notJSObject, &notClassConstructor);
786         Bind(&notClassConstructor);
787         {
788             BRANCH(IsClassPrototype(receiver), &notJSObject, &notClassPrototype);
789             Bind(&notClassPrototype);
790             {
791                 result = SetPropertyByName(glue, receiver, key, value, true, True(), ProfileOperation(), false, true);
792                 BRANCH(TaggedIsHole(*result), &notJSObject, &notHole);
793                 Bind(&notHole);
794                 {
795                     Label notException(env);
796                     BRANCH(TaggedIsException(*result), &exit, &notException);
797                     Bind(&notException);
798                     CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), {value, key});
799                     Jump(&exit);
800                 }
801             }
802         }
803     }
804     Bind(&notJSObject);
805     {
806         result = CallRuntime(glue, RTSTUB_ID(StOwnByNameWithNameSet), { receiver, key, value });
807         Jump(&exit);
808     }
809     Bind(&exit);
810     auto ret = *result;
811     env->SubCfgExit();
812     return ret;
813 }
814 
StObjByIndex(GateRef glue,GateRef receiver,GateRef index,GateRef value)815 GateRef AccessObjectStubBuilder::StObjByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value)
816 {
817     auto env = GetEnvironment();
818     Label entry(env);
819     env->SubCfgEntry(&entry);
820     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
821     Label exit(env);
822     Label fastPath(env);
823     Label slowPath(env);
824     BRANCH(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
825     Bind(&fastPath);
826     {
827         result = SetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), value, false);
828         BRANCH(TaggedIsHole(*result), &slowPath, &exit);
829     }
830     Bind(&slowPath);
831     {
832         result = CallRuntime(glue, RTSTUB_ID(StObjByIndex), {receiver, IntToTaggedInt(index), value});
833         Jump(&exit);
834     }
835     Bind(&exit);
836     auto ret = *result;
837     env->SubCfgExit();
838     return ret;
839 }
840 
LdObjByIndex(GateRef glue,GateRef receiver,GateRef index)841 GateRef AccessObjectStubBuilder::LdObjByIndex(GateRef glue, GateRef receiver, GateRef index)
842 {
843     auto env = GetEnvironment();
844     Label entry(env);
845     env->SubCfgEntry(&entry);
846     DEFVARIABLE(varAcc, VariableType::JS_ANY(), Hole());
847     Label fastPath(env);
848     Label slowPath(env);
849     Label exit(env);
850     BRANCH(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
851     Bind(&fastPath);
852     {
853         varAcc = GetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), ProfileOperation());
854         BRANCH(TaggedIsHole(*varAcc), &slowPath, &exit);
855     }
856     Bind(&slowPath);
857     {
858         GateRef undefined = Undefined();
859         auto args = { receiver, IntToTaggedInt(index), TaggedFalse(), undefined };
860         varAcc = CallRuntime(glue, RTSTUB_ID(LdObjByIndex), args);
861         Jump(&exit);
862     }
863     Bind(&exit);
864     auto ret = *varAcc;
865     env->SubCfgExit();
866     return ret;
867 }
868 }  // namespace panda::ecmascript::kungfu
869