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