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