• 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/rt_call_signature.h"
19 #include "ecmascript/compiler/stub_builder-inl.h"
20 #include "ecmascript/ic/profile_type_info.h"
21 
22 namespace panda::ecmascript::kungfu {
LoadObjByName(GateRef glue,GateRef receiver,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId)23 GateRef AccessObjectStubBuilder::LoadObjByName(GateRef glue, GateRef receiver, GateRef prop, const StringIdInfo &info,
24                                                GateRef profileTypeInfo, GateRef slotId)
25 {
26     auto env = GetEnvironment();
27     Label entry(env);
28     env->SubCfgEntry(&entry);
29     Label exit(env);
30     Label tryFastPath(env);
31     Label slowPath(env);
32 
33     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
34     GateRef value = 0;
35     ICStubBuilder builder(this);
36     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
37     builder.LoadICByName(&result, &tryFastPath, &slowPath, &exit);
38     Bind(&tryFastPath);
39     {
40         GateRef propKey = ResolvePropKey(glue, prop, info);
41         result = GetPropertyByName(glue, receiver, propKey);
42         Branch(TaggedIsHole(*result), &slowPath, &exit);
43     }
44     Bind(&slowPath);
45     {
46         GateRef propKey = ResolvePropKey(glue, prop, info);
47         result = CallRuntime(glue, RTSTUB_ID(LoadICByName),
48                              { profileTypeInfo, receiver, propKey, IntToTaggedInt(slotId) });
49         Jump(&exit);
50     }
51     Bind(&exit);
52     auto ret = *result;
53     env->SubCfgExit();
54     return ret;
55 }
56 
57 // Used for deprecated bytecodes which will not support ic
DeprecatedLoadObjByName(GateRef glue,GateRef receiver,GateRef propKey)58 GateRef AccessObjectStubBuilder::DeprecatedLoadObjByName(GateRef glue, GateRef receiver, GateRef propKey)
59 {
60     auto env = GetEnvironment();
61     Label entry(env);
62     env->SubCfgEntry(&entry);
63     Label exit(env);
64     Label fastPath(env);
65     Label slowPath(env);
66 
67     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
68     Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
69     Bind(&fastPath);
70     {
71         result = GetPropertyByName(glue, receiver, propKey);
72         Branch(TaggedIsHole(*result), &slowPath, &exit);
73     }
74     Bind(&slowPath);
75     {
76         result = CallRuntime(glue, RTSTUB_ID(LoadICByName),
77             { Undefined(), receiver, propKey, IntToTaggedInt(Int32(0xFF)) });  // 0xFF: invalid slot id
78         Jump(&exit);
79     }
80     Bind(&exit);
81     auto ret = *result;
82     env->SubCfgExit();
83     return ret;
84 }
85 
StoreObjByName(GateRef glue,GateRef receiver,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId)86 GateRef AccessObjectStubBuilder::StoreObjByName(GateRef glue, GateRef receiver, GateRef prop, const StringIdInfo &info,
87                                                 GateRef value, GateRef profileTypeInfo, GateRef slotId)
88 {
89     auto env = GetEnvironment();
90     Label entry(env);
91     env->SubCfgEntry(&entry);
92     Label exit(env);
93     Label tryFastPath(env);
94     Label slowPath(env);
95 
96     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
97     ICStubBuilder builder(this);
98     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
99     builder.StoreICByName(&result, &tryFastPath, &slowPath, &exit);
100     Bind(&tryFastPath);
101     {
102         GateRef propKey = ResolvePropKey(glue, prop, info);
103         result = SetPropertyByName(glue, receiver, propKey, value, false);
104         Branch(TaggedIsHole(*result), &slowPath, &exit);
105     }
106     Bind(&slowPath);
107     {
108         GateRef propKey = ResolvePropKey(glue, prop, info);
109         result = CallRuntime(glue, RTSTUB_ID(StoreICByName),
110             { profileTypeInfo, receiver, propKey, value, IntToTaggedInt(slotId) });
111         Jump(&exit);
112     }
113 
114     Bind(&exit);
115     auto ret = *result;
116     env->SubCfgExit();
117     return ret;
118 }
119 
ResolvePropKey(GateRef glue,GateRef prop,const StringIdInfo & info)120 GateRef AccessObjectStubBuilder::ResolvePropKey(GateRef glue, GateRef prop, const StringIdInfo &info)
121 {
122     if (prop != 0) {
123         return prop;
124     }
125     ASSERT(info.IsValid());
126     InterpreterToolsStubBuilder builder(GetCallSignature(), GetEnvironment());
127     GateRef stringId = builder.GetStringId(info);
128     return GetStringFromConstPool(glue, info.constpool, stringId);
129 }
130 
LoadObjByValue(GateRef glue,GateRef receiver,GateRef key,GateRef profileTypeInfo,GateRef slotId)131 GateRef AccessObjectStubBuilder::LoadObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo,
132                                                 GateRef slotId)
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 
141     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
142     GateRef value = 0;
143     ICStubBuilder builder(this);
144     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key);
145     builder.LoadICByValue(&result, &tryFastPath, &slowPath, &exit);
146     Bind(&tryFastPath);
147     {
148         result = GetPropertyByValue(glue, receiver, key);
149         Branch(TaggedIsHole(*result), &slowPath, &exit);
150     }
151     Bind(&slowPath);
152     {
153         result = CallRuntime(glue, RTSTUB_ID(LoadICByValue),
154             { profileTypeInfo, receiver, key, IntToTaggedInt(slotId) });
155         Jump(&exit);
156     }
157     Bind(&exit);
158     auto ret = *result;
159     env->SubCfgExit();
160     return ret;
161 }
162 
163 // Used for deprecated bytecodes which will not support ic
DeprecatedLoadObjByValue(GateRef glue,GateRef receiver,GateRef key)164 GateRef AccessObjectStubBuilder::DeprecatedLoadObjByValue(GateRef glue, GateRef receiver, GateRef key)
165 {
166     auto env = GetEnvironment();
167     Label entry(env);
168     env->SubCfgEntry(&entry);
169     Label exit(env);
170     Label fastPath(env);
171     Label slowPath(env);
172 
173     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
174     Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
175     Bind(&fastPath);
176     {
177         result = GetPropertyByValue(glue, receiver, key);
178         Branch(TaggedIsHole(*result), &slowPath, &exit);
179     }
180     Bind(&slowPath);
181     {
182         result = CallRuntime(glue, RTSTUB_ID(LoadICByValue),
183             { Undefined(), receiver, key, IntToTaggedInt(Int32(0xFF)) });  // 0xFF: invalied slot id
184         Jump(&exit);
185     }
186     Bind(&exit);
187     auto ret = *result;
188     env->SubCfgExit();
189     return ret;
190 }
191 
StoreObjByValue(GateRef glue,GateRef receiver,GateRef key,GateRef value,GateRef profileTypeInfo,GateRef slotId)192 GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value,
193                                                  GateRef profileTypeInfo, GateRef slotId)
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 
202     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
203     ICStubBuilder builder(this);
204     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key);
205     builder.StoreICByValue(&result, &tryFastPath, &slowPath, &exit);
206     Bind(&tryFastPath);
207     {
208         result = SetPropertyByValue(glue, receiver, key, value, false);
209         Branch(TaggedIsHole(*result), &slowPath, &exit);
210     }
211     Bind(&slowPath);
212     {
213         result = CallRuntime(glue, RTSTUB_ID(StoreICByValue),
214             { profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId) });
215         Jump(&exit);
216     }
217     Bind(&exit);
218     auto ret = *result;
219     env->SubCfgExit();
220     return ret;
221 }
222 
TryLoadGlobalByName(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId)223 GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
224                                                      GateRef profileTypeInfo, GateRef slotId)
225 {
226     auto env = GetEnvironment();
227     Label entry(env);
228     env->SubCfgEntry(&entry);
229     Label exit(env);
230     Label tryFastPath(env);
231     Label slowPath(env);
232 
233     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
234     GateRef receiver = 0;
235     GateRef value = 0;
236     ICStubBuilder builder(this);
237     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
238     builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
239     Bind(&tryFastPath);
240     {
241         GateRef propKey = ResolvePropKey(glue, prop, info);
242         GateRef record = LdGlobalRecord(glue, propKey);
243         Label foundInRecord(env);
244         Label notFoundInRecord(env);
245         Branch(TaggedIsUndefined(record), &notFoundInRecord, &foundInRecord);
246         Bind(&foundInRecord);
247         {
248             result = Load(VariableType::JS_ANY(), record, IntPtr(PropertyBox::VALUE_OFFSET));
249             Jump(&exit);
250         }
251         Bind(&notFoundInRecord);
252         {
253             GateRef globalObject = GetGlobalObject(glue);
254             result = GetGlobalOwnProperty(glue, globalObject, propKey);
255             Branch(TaggedIsHole(*result), &slowPath, &exit);
256         }
257     }
258     Bind(&slowPath);
259     {
260         GateRef propKey = ResolvePropKey(glue, prop, info);
261         result = CallRuntime(glue, RTSTUB_ID(TryLdGlobalICByName),
262                              { profileTypeInfo, propKey, IntToTaggedInt(slotId) });
263         Jump(&exit);
264     }
265 
266     Bind(&exit);
267     auto ret = *result;
268     env->SubCfgExit();
269     return ret;
270 }
271 
TryStoreGlobalByName(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId)272 GateRef AccessObjectStubBuilder::TryStoreGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
273                                                       GateRef value, GateRef profileTypeInfo, GateRef slotId)
274 {
275     auto env = GetEnvironment();
276     Label entry(env);
277     env->SubCfgEntry(&entry);
278     Label exit(env);
279     Label tryFastPath(env);
280     Label slowPath(env);
281 
282     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
283     GateRef receiver = 0;
284     ICStubBuilder builder(this);
285     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
286     builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
287     Bind(&tryFastPath);
288     {
289         GateRef propKey = ResolvePropKey(glue, prop, info);
290         GateRef record = LdGlobalRecord(glue, propKey);
291         Label foundInRecord(env);
292         Label notFoundInRecord(env);
293         Branch(TaggedIsUndefined(record), &notFoundInRecord, &foundInRecord);
294         Bind(&foundInRecord);
295         {
296             result = CallRuntime(glue, RTSTUB_ID(TryUpdateGlobalRecord), { propKey, value });
297             Jump(&exit);
298         }
299         Bind(&notFoundInRecord);
300         {
301             GateRef globalObject = GetGlobalObject(glue);
302             result = GetGlobalOwnProperty(glue, globalObject, propKey);
303             Label isFoundInGlobal(env);
304             Label notFoundInGlobal(env);
305             Branch(TaggedIsHole(*result), &notFoundInGlobal, &isFoundInGlobal);
306             Bind(&isFoundInGlobal);
307             {
308                 result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value });
309                 Jump(&exit);
310             }
311             Bind(&notFoundInGlobal);
312             {
313                 result = CallRuntime(glue, RTSTUB_ID(ThrowReferenceError), { propKey });
314                 Jump(&exit);
315             }
316         }
317     }
318     Bind(&slowPath);
319     {
320         GateRef propKey = ResolvePropKey(glue, prop, info);
321         GateRef globalObject = GetGlobalObject(glue);
322         result = CallRuntime(glue, RTSTUB_ID(StoreMiss),
323                              { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId),
324                                IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalTryStoreIC))) });
325         Jump(&exit);
326     }
327 
328     Bind(&exit);
329     auto ret = *result;
330     env->SubCfgExit();
331     return ret;
332 }
333 
LoadGlobalVar(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef profileTypeInfo,GateRef slotId)334 GateRef AccessObjectStubBuilder::LoadGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
335                                                GateRef profileTypeInfo, GateRef slotId)
336 {
337     auto env = GetEnvironment();
338     Label entry(env);
339     env->SubCfgEntry(&entry);
340     Label exit(env);
341     Label tryFastPath(env);
342     Label slowPath(env);
343 
344     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
345     GateRef receiver = 0;
346     GateRef value = 0;
347     ICStubBuilder builder(this);
348     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
349     builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
350     Bind(&tryFastPath);
351     {
352         GateRef globalObject = GetGlobalObject(glue);
353         GateRef propKey = ResolvePropKey(glue, prop, info);
354         result = GetGlobalOwnProperty(glue, globalObject, propKey);
355         Branch(TaggedIsHole(*result), &slowPath, &exit);
356     }
357     Bind(&slowPath);
358     {
359         GateRef globalObject = GetGlobalObject(glue);
360         GateRef propKey = ResolvePropKey(glue, prop, info);
361         result = CallRuntime(glue, RTSTUB_ID(LdGlobalICVar),
362                              { globalObject, propKey, profileTypeInfo, IntToTaggedInt(slotId) });
363         Jump(&exit);
364     }
365 
366     Bind(&exit);
367     auto ret = *result;
368     env->SubCfgExit();
369     return ret;
370 }
371 
StoreGlobalVar(GateRef glue,GateRef prop,const StringIdInfo & info,GateRef value,GateRef profileTypeInfo,GateRef slotId)372 GateRef AccessObjectStubBuilder::StoreGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
373                                                 GateRef value, GateRef profileTypeInfo, GateRef slotId)
374 {
375     auto env = GetEnvironment();
376     Label entry(env);
377     env->SubCfgEntry(&entry);
378     Label exit(env);
379     Label tryFastPath(env);
380     Label slowPath(env);
381 
382     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
383     GateRef receiver = 0;
384     ICStubBuilder builder(this);
385     builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
386     builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit);
387     Bind(&tryFastPath);
388     {
389         GateRef propKey = ResolvePropKey(glue, prop, info);
390         // IR later
391         result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value });
392         Jump(&exit);
393     }
394     Bind(&slowPath);
395     {
396         GateRef propKey = ResolvePropKey(glue, prop, info);
397         GateRef globalObject = GetGlobalObject(glue);
398         result = CallRuntime(glue, RTSTUB_ID(StoreMiss),
399                              { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId),
400                                IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalStoreIC))) });
401         Jump(&exit);
402     }
403 
404     Bind(&exit);
405     auto ret = *result;
406     env->SubCfgExit();
407     return ret;
408 }
409 }  // namespace panda::ecmascript::kungfu