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, ¬ClassConstructor);
428 Bind(¬ClassConstructor);
429 Label notClassPrototype(env);
430 BRANCH(IsClassPrototype(glue, receiver), &slowPath, ¬ClassPrototype);
431 Bind(¬ClassPrototype);
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), ¬FoundInRecord, &foundInRecord);
510 Bind(&foundInRecord);
511 {
512 result = Load(VariableType::JS_ANY(), glue, record, IntPtr(PropertyBox::VALUE_OFFSET));
513 Jump(&exit);
514 }
515 Bind(¬FoundInRecord);
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), ¬FoundInRecord, &foundInRecord);
560 Bind(&foundInRecord);
561 {
562 result = CallRuntimeWithGlobalEnv(glue, globalEnv, RTSTUB_ID(TryUpdateGlobalRecord), { propKey, value });
563 Jump(&exit);
564 }
565 Bind(¬FoundInRecord);
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), ¬FoundInGlobal, &isFoundInGlobal);
572 Bind(&isFoundInGlobal);
573 {
574 result = CallRuntimeWithGlobalEnv(glue, globalEnv, RTSTUB_ID(StGlobalVar), { propKey, value });
575 Jump(&exit);
576 }
577 Bind(¬FoundInGlobal);
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, ¬ClassConstructor);
691 Bind(¬ClassConstructor);
692 Label notClassPrototype(env);
693 BRANCH(IsClassPrototype(glue, receiver), &slowPath, ¬ClassPrototype);
694 Bind(¬ClassPrototype);
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, ¬ClassConstructor);
723 Bind(¬ClassConstructor);
724 Label notClassPrototype(env);
725 BRANCH(IsClassPrototype(glue, receiver), &slowPath, ¬ClassPrototype);
726 Bind(¬ClassPrototype);
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, ¬ClassConstructor);
755 Bind(¬ClassConstructor);
756 Label notClassPrototype(env);
757 BRANCH(IsClassPrototype(glue, receiver), &slowPath, ¬ClassPrototype);
758 Bind(¬ClassPrototype);
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, ¬ClassConstructor);
790 Bind(¬ClassConstructor);
791 {
792 BRANCH(IsClassPrototype(glue, receiver), &slowPath, ¬ClassPrototype);
793 Bind(¬ClassPrototype);
794 {
795 result = SetPropertyByValue(glue, receiver, key, value, true, ProfileOperation(), true);
796 BRANCH(TaggedIsHole(*result), &slowPath, ¬Hole);
797 Bind(¬Hole);
798 {
799 Label notexception(env);
800 BRANCH(TaggedIsException(*result), &exit, ¬exception);
801 Bind(¬exception);
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, ¬JSObject);
832 Bind(&isJSObject);
833 {
834 BRANCH(IsClassConstructor(glue, receiver), ¬JSObject, ¬ClassConstructor);
835 Bind(¬ClassConstructor);
836 {
837 BRANCH(IsClassPrototype(glue, receiver), ¬JSObject, ¬ClassPrototype);
838 Bind(¬ClassPrototype);
839 {
840 result = SetPropertyByName(glue, receiver, key, value, true, True(), ProfileOperation(), false, true);
841 BRANCH(TaggedIsHole(*result), ¬JSObject, ¬Hole);
842 Bind(¬Hole);
843 {
844 Label notException(env);
845 BRANCH(TaggedIsException(*result), &exit, ¬Exception);
846 Bind(¬Exception);
847 CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), {value, key});
848 Jump(&exit);
849 }
850 }
851 }
852 }
853 Bind(¬JSObject);
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