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, ¬ClassConstructor);
378 Bind(¬ClassConstructor);
379 Label notClassPrototype(env);
380 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
381 Bind(¬ClassPrototype);
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), ¬FoundInRecord, &foundInRecord);
464 Bind(&foundInRecord);
465 {
466 result = Load(VariableType::JS_ANY(), record, IntPtr(PropertyBox::VALUE_OFFSET));
467 Jump(&exit);
468 }
469 Bind(¬FoundInRecord);
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), ¬FoundInRecord, &foundInRecord);
513 Bind(&foundInRecord);
514 {
515 result = CallRuntime(glue, RTSTUB_ID(TryUpdateGlobalRecord), { propKey, value });
516 Jump(&exit);
517 }
518 Bind(¬FoundInRecord);
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), ¬FoundInGlobal, &isFoundInGlobal);
525 Bind(&isFoundInGlobal);
526 {
527 result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value });
528 Jump(&exit);
529 }
530 Bind(¬FoundInGlobal);
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, ¬ClassConstructor);
642 Bind(¬ClassConstructor);
643 Label notClassPrototype(env);
644 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
645 Bind(¬ClassPrototype);
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, ¬ClassConstructor);
674 Bind(¬ClassConstructor);
675 Label notClassPrototype(env);
676 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
677 Bind(¬ClassPrototype);
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, ¬ClassConstructor);
706 Bind(¬ClassConstructor);
707 Label notClassPrototype(env);
708 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
709 Bind(¬ClassPrototype);
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, ¬ClassConstructor);
741 Bind(¬ClassConstructor);
742 {
743 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
744 Bind(¬ClassPrototype);
745 {
746 result = SetPropertyByValue(glue, receiver, key, value, true, ProfileOperation(), true);
747 BRANCH(TaggedIsHole(*result), &slowPath, ¬Hole);
748 Bind(¬Hole);
749 {
750 Label notexception(env);
751 BRANCH(TaggedIsException(*result), &exit, ¬exception);
752 Bind(¬exception);
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, ¬JSObject);
783 Bind(&isJSObject);
784 {
785 BRANCH(IsClassConstructor(receiver), ¬JSObject, ¬ClassConstructor);
786 Bind(¬ClassConstructor);
787 {
788 BRANCH(IsClassPrototype(receiver), ¬JSObject, ¬ClassPrototype);
789 Bind(¬ClassPrototype);
790 {
791 result = SetPropertyByName(glue, receiver, key, value, true, True(), ProfileOperation(), false, true);
792 BRANCH(TaggedIsHole(*result), ¬JSObject, ¬Hole);
793 Bind(¬Hole);
794 {
795 Label notException(env);
796 BRANCH(TaggedIsException(*result), &exit, ¬Exception);
797 Bind(¬Exception);
798 CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), {value, key});
799 Jump(&exit);
800 }
801 }
802 }
803 }
804 Bind(¬JSObject);
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