1 /*
2 * Copyright (c) 2021 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
16 #include "ecmascript/compiler/common_stubs.h"
17
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/compiler/access_object_stub_builder.h"
20 #include "ecmascript/compiler/interpreter_stub.h"
21 #include "ecmascript/compiler/llvm_ir_builder.h"
22 #include "ecmascript/compiler/new_object_stub_builder.h"
23 #include "ecmascript/compiler/operations_stub_builder.h"
24 #include "ecmascript/compiler/stub_builder-inl.h"
25 #include "ecmascript/compiler/variable_type.h"
26 #include "ecmascript/js_array.h"
27 #include "ecmascript/message_string.h"
28 #include "ecmascript/tagged_hash_table.h"
29
30 namespace panda::ecmascript::kungfu {
31 using namespace panda::ecmascript;
32
GenerateCircuit()33 void AddStubBuilder::GenerateCircuit()
34 {
35 GateRef glue = PtrArgument(0);
36 GateRef x = TaggedArgument(1);
37 GateRef y = TaggedArgument(2);
38 OperationsStubBuilder operationBuilder(this);
39 Return(operationBuilder.Add(glue, x, y));
40 }
41
GenerateCircuit()42 void SubStubBuilder::GenerateCircuit()
43 {
44 GateRef glue = PtrArgument(0);
45 GateRef x = TaggedArgument(1);
46 GateRef y = TaggedArgument(2);
47 OperationsStubBuilder operationBuilder(this);
48 Return(operationBuilder.Sub(glue, x, y));
49 }
50
GenerateCircuit()51 void MulStubBuilder::GenerateCircuit()
52 {
53 GateRef glue = PtrArgument(0);
54 GateRef x = TaggedArgument(1);
55 GateRef y = TaggedArgument(2);
56 OperationsStubBuilder operationBuilder(this);
57 Return(operationBuilder.Mul(glue, x, y));
58 }
59
GenerateCircuit()60 void DivStubBuilder::GenerateCircuit()
61 {
62 GateRef glue = PtrArgument(0);
63 GateRef x = TaggedArgument(1);
64 GateRef y = TaggedArgument(2);
65 OperationsStubBuilder operationBuilder(this);
66 Return(operationBuilder.Div(glue, x, y));
67 }
68
GenerateCircuit()69 void ModStubBuilder::GenerateCircuit()
70 {
71 GateRef glue = PtrArgument(0);
72 GateRef x = TaggedArgument(1);
73 GateRef y = TaggedArgument(2); // 2: 3rd argument
74 OperationsStubBuilder operationBuilder(this);
75 Return(operationBuilder.Mod(glue, x, y));
76 }
77
GenerateCircuit()78 void TypeOfStubBuilder::GenerateCircuit()
79 {
80 GateRef glue = PtrArgument(0);
81 GateRef obj = TaggedArgument(1);
82 Return(FastTypeOf(glue, obj));
83 }
84
GenerateCircuit()85 void EqualStubBuilder::GenerateCircuit()
86 {
87 GateRef glue = PtrArgument(0);
88 GateRef x = TaggedArgument(1);
89 GateRef y = TaggedArgument(2); // 2: 3rd argument
90 OperationsStubBuilder operationBuilder(this);
91 Return(operationBuilder.Equal(glue, x, y));
92 }
93
GenerateCircuit()94 void NotEqualStubBuilder::GenerateCircuit()
95 {
96 GateRef glue = PtrArgument(0);
97 GateRef x = TaggedArgument(1);
98 GateRef y = TaggedArgument(2); // 2: 3rd argument
99 OperationsStubBuilder operationBuilder(this);
100 Return(operationBuilder.NotEqual(glue, x, y));
101 }
102
GenerateCircuit()103 void LessStubBuilder::GenerateCircuit()
104 {
105 GateRef glue = PtrArgument(0);
106 GateRef x = TaggedArgument(1);
107 GateRef y = TaggedArgument(2); // 2: 3rd argument
108 OperationsStubBuilder operationBuilder(this);
109 Return(operationBuilder.Less(glue, x, y));
110 }
111
GenerateCircuit()112 void LessEqStubBuilder::GenerateCircuit()
113 {
114 GateRef glue = PtrArgument(0);
115 GateRef x = TaggedArgument(1);
116 GateRef y = TaggedArgument(2); // 2: 3rd argument
117 OperationsStubBuilder operationBuilder(this);
118 Return(operationBuilder.LessEq(glue, x, y));
119 }
120
GenerateCircuit()121 void GreaterStubBuilder::GenerateCircuit()
122 {
123 GateRef glue = PtrArgument(0);
124 GateRef x = TaggedArgument(1);
125 GateRef y = TaggedArgument(2); // 2: 3rd argument
126 OperationsStubBuilder operationBuilder(this);
127 Return(operationBuilder.Greater(glue, x, y));
128 }
129
GenerateCircuit()130 void GreaterEqStubBuilder::GenerateCircuit()
131 {
132 GateRef glue = PtrArgument(0);
133 GateRef x = TaggedArgument(1);
134 GateRef y = TaggedArgument(2); // 2: 3rd argument
135 OperationsStubBuilder operationBuilder(this);
136 Return(operationBuilder.GreaterEq(glue, x, y));
137 }
138
GenerateCircuit()139 void ShlStubBuilder::GenerateCircuit()
140 {
141 GateRef glue = PtrArgument(0);
142 GateRef x = TaggedArgument(1);
143 GateRef y = TaggedArgument(2); // 2: 3rd argument
144 OperationsStubBuilder operationBuilder(this);
145 Return(operationBuilder.Shl(glue, x, y));
146 }
147
GenerateCircuit()148 void ShrStubBuilder::GenerateCircuit()
149 {
150 GateRef glue = PtrArgument(0);
151 GateRef x = TaggedArgument(1);
152 GateRef y = TaggedArgument(2); // 2: 3rd argument
153 OperationsStubBuilder operationBuilder(this);
154 Return(operationBuilder.Shr(glue, x, y));
155 }
156
GenerateCircuit()157 void AshrStubBuilder::GenerateCircuit()
158 {
159 GateRef glue = PtrArgument(0);
160 GateRef x = TaggedArgument(1);
161 GateRef y = TaggedArgument(2); // 2: 3rd argument
162 OperationsStubBuilder operationBuilder(this);
163 Return(operationBuilder.Ashr(glue, x, y));
164 }
165
GenerateCircuit()166 void AndStubBuilder::GenerateCircuit()
167 {
168 GateRef glue = PtrArgument(0);
169 GateRef x = TaggedArgument(1);
170 GateRef y = TaggedArgument(2); // 2: 3rd argument
171 OperationsStubBuilder operationBuilder(this);
172 Return(operationBuilder.And(glue, x, y));
173 }
174
GenerateCircuit()175 void OrStubBuilder::GenerateCircuit()
176 {
177 GateRef glue = PtrArgument(0);
178 GateRef x = TaggedArgument(1);
179 GateRef y = TaggedArgument(2); // 2: 3rd argument
180 OperationsStubBuilder operationBuilder(this);
181 Return(operationBuilder.Or(glue, x, y));
182 }
183
GenerateCircuit()184 void XorStubBuilder::GenerateCircuit()
185 {
186 GateRef glue = PtrArgument(0);
187 GateRef x = TaggedArgument(1);
188 GateRef y = TaggedArgument(2); // 2: 3rd argument
189 OperationsStubBuilder operationBuilder(this);
190 Return(operationBuilder.Xor(glue, x, y));
191 }
192
GenerateCircuit()193 void InstanceofStubBuilder::GenerateCircuit()
194 {
195 GateRef glue = PtrArgument(0);
196 GateRef x = TaggedArgument(1);
197 GateRef y = TaggedArgument(2); // 2: 3rd argument
198 Return(InstanceOf(glue, x, y));
199 }
200
GenerateCircuit()201 void IncStubBuilder::GenerateCircuit()
202 {
203 GateRef glue = PtrArgument(0);
204 GateRef x = TaggedArgument(1);
205 OperationsStubBuilder operationBuilder(this);
206 Return(operationBuilder.Inc(glue, x));
207 }
208
GenerateCircuit()209 void DecStubBuilder::GenerateCircuit()
210 {
211 GateRef glue = PtrArgument(0);
212 GateRef x = TaggedArgument(1);
213 OperationsStubBuilder operationBuilder(this);
214 Return(operationBuilder.Dec(glue, x));
215 }
216
GenerateCircuit()217 void NegStubBuilder::GenerateCircuit()
218 {
219 GateRef glue = PtrArgument(0);
220 GateRef x = TaggedArgument(1);
221 OperationsStubBuilder operationBuilder(this);
222 Return(operationBuilder.Neg(glue, x));
223 }
224
GenerateCircuit()225 void NotStubBuilder::GenerateCircuit()
226 {
227 GateRef glue = PtrArgument(0);
228 GateRef x = TaggedArgument(1);
229 OperationsStubBuilder operationBuilder(this);
230 Return(operationBuilder.Not(glue, x));
231 }
232
GenerateCircuit()233 void ToBooleanStubBuilder::GenerateCircuit()
234 {
235 GateRef glue = PtrArgument(0);
236 (void)glue;
237 GateRef x = TaggedArgument(1);
238 Return(FastToBoolean(x));
239 }
240
GenerateCircuit()241 void NewLexicalEnvStubBuilder::GenerateCircuit()
242 {
243 auto env = GetEnvironment();
244 GateRef glue = PtrArgument(0);
245 GateRef parent = TaggedArgument(1);
246 GateRef numVars = Int32Argument(2); /* 2 : 3rd parameter is index */
247
248 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
249 NewObjectStubBuilder newBuilder(this);
250 newBuilder.SetParameters(glue, 0);
251 Label afterNew(env);
252 newBuilder.NewLexicalEnv(&result, &afterNew, numVars, parent);
253 Bind(&afterNew);
254 Return(*result);
255 }
256
GenerateCircuit()257 void GetUnmapedArgsStubBuilder::GenerateCircuit()
258 {
259 auto env = GetEnvironment();
260 GateRef glue = PtrArgument(0);
261 GateRef numArgs = Int32Argument(1);
262
263 DEFVARIABLE(argumentsList, VariableType::JS_ANY(), Hole());
264 DEFVARIABLE(argumentsObj, VariableType::JS_ANY(), Hole());
265 Label afterArgumentsList(env);
266 Label newArgumentsObj(env);
267 Label exit(env);
268
269 GateRef argv = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
270 GateRef args = PtrAdd(argv, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
271 GateRef actualArgc = Int32Sub(numArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
272 GateRef startIdx = Int32(0);
273 NewObjectStubBuilder newBuilder(this);
274 newBuilder.SetParameters(glue, 0);
275 newBuilder.NewArgumentsList(&argumentsList, &afterArgumentsList, args, startIdx, actualArgc);
276 Bind(&afterArgumentsList);
277 Branch(TaggedIsException(*argumentsList), &exit, &newArgumentsObj);
278 Bind(&newArgumentsObj);
279 newBuilder.NewArgumentsObj(&argumentsObj, &exit, *argumentsList, actualArgc);
280 Bind(&exit);
281 Return(*argumentsObj);
282 }
283
GenerateCircuit()284 void GetPropertyByIndexStubBuilder::GenerateCircuit()
285 {
286 GateRef glue = PtrArgument(0);
287 GateRef receiver = TaggedArgument(1);
288 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
289 Return(GetPropertyByIndex(glue, receiver, index));
290 }
291
GenerateCircuit()292 void SetPropertyByIndexStubBuilder::GenerateCircuit()
293 {
294 GateRef glue = PtrArgument(0);
295 GateRef receiver = TaggedArgument(1);
296 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
297 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
298 Return(SetPropertyByIndex(glue, receiver, index, value, false));
299 }
300
GenerateCircuit()301 void SetPropertyByIndexWithOwnStubBuilder::GenerateCircuit()
302 {
303 GateRef glue = PtrArgument(0);
304 GateRef receiver = TaggedArgument(1);
305 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
306 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
307 Return(SetPropertyByIndex(glue, receiver, index, value, true));
308 }
309
GenerateCircuit()310 void GetPropertyByNameStubBuilder::GenerateCircuit()
311 {
312 GateRef glue = PtrArgument(0);
313 GateRef receiver = TaggedArgument(1);
314 GateRef prop = TaggedPointerArgument(2); // 2 : 3rd para
315 GateRef profileTypeInfo = TaggedPointerArgument(3); // 3 : 4th para
316 GateRef slotId = Int32Argument(4); // 4 : 5th para
317 AccessObjectStubBuilder builder(this);
318 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
319 Return(builder.LoadObjByName(glue, receiver, prop, info, profileTypeInfo, slotId));
320 }
321
GenerateCircuit()322 void DeprecatedGetPropertyByNameStubBuilder::GenerateCircuit()
323 {
324 GateRef glue = PtrArgument(0);
325 GateRef receiver = TaggedArgument(1);
326 GateRef key = TaggedPointerArgument(2); // 2 : 3rd para
327 AccessObjectStubBuilder builder(this);
328 Return(builder.DeprecatedLoadObjByName(glue, receiver, key));
329 }
330
GenerateCircuit()331 void SetPropertyByNameStubBuilder::GenerateCircuit()
332 {
333 GateRef glue = PtrArgument(0);
334 GateRef receiver = TaggedArgument(1);
335 GateRef prop = TaggedArgument(2); // 2 : 3rd para
336 GateRef value = TaggedPointerArgument(3); // 3 : 4th para
337 GateRef profileTypeInfo = TaggedPointerArgument(4); // 4 : 5th para
338 GateRef slotId = Int32Argument(5); // 5 : 6th para
339 AccessObjectStubBuilder builder(this);
340 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
341 Return(builder.StoreObjByName(glue, receiver, prop, info, value, profileTypeInfo, slotId));
342 }
343
GenerateCircuit()344 void DeprecatedSetPropertyByNameStubBuilder::GenerateCircuit()
345 {
346 GateRef glue = PtrArgument(0);
347 GateRef receiver = TaggedArgument(1);
348 GateRef key = TaggedArgument(2); // 2 : 3rd para
349 GateRef value = TaggedArgument(3); // 3 : 4th para
350 Return(SetPropertyByName(glue, receiver, key, value, false));
351 }
352
GenerateCircuit()353 void SetPropertyByNameWithOwnStubBuilder::GenerateCircuit()
354 {
355 GateRef glue = PtrArgument(0);
356 GateRef receiver = TaggedArgument(1);
357 GateRef key = TaggedArgument(2); // 2 : 3rd para
358 GateRef value = TaggedArgument(3); // 3 : 4th para
359 Return(SetPropertyByName(glue, receiver, key, value, true));
360 }
361
GenerateCircuit()362 void GetPropertyByValueStubBuilder::GenerateCircuit()
363 {
364 GateRef glue = PtrArgument(0);
365 GateRef receiver = TaggedArgument(1);
366 GateRef key = TaggedArgument(2); // 2 : 3rd para
367 GateRef profileTypeInfo = TaggedPointerArgument(3); // 3 : 4th para
368 GateRef slotId = Int32Argument(4); // 4 : 5th para
369 AccessObjectStubBuilder builder(this);
370 Return(builder.LoadObjByValue(glue, receiver, key, profileTypeInfo, slotId));
371 }
372
GenerateCircuit()373 void DeprecatedGetPropertyByValueStubBuilder::GenerateCircuit()
374 {
375 GateRef glue = PtrArgument(0);
376 GateRef receiver = TaggedArgument(1);
377 GateRef key = TaggedArgument(2); // 2 : 3rd para
378 Return(GetPropertyByValue(glue, receiver, key));
379 }
380
GenerateCircuit()381 void SetPropertyByValueStubBuilder::GenerateCircuit()
382 {
383 GateRef glue = PtrArgument(0);
384 GateRef receiver = TaggedArgument(1);
385 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is key */
386 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
387 GateRef profileTypeInfo = TaggedPointerArgument(4); /* 4 : 5th parameter is profileTypeInfo */
388 GateRef slotId = Int32Argument(5); /* 5 : 6th parameter is slotId */
389 AccessObjectStubBuilder builder(this);
390 Return(builder.StoreObjByValue(glue, receiver, key, value, profileTypeInfo, slotId));
391 }
392
GenerateCircuit()393 void DeprecatedSetPropertyByValueStubBuilder::GenerateCircuit()
394 {
395 GateRef glue = PtrArgument(0);
396 GateRef receiver = TaggedArgument(1);
397 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is key */
398 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
399 Return(SetPropertyByValue(glue, receiver, key, value, false));
400 }
401
GenerateCircuit()402 void SetPropertyByValueWithOwnStubBuilder::GenerateCircuit()
403 {
404 GateRef glue = PtrArgument(0);
405 GateRef receiver = TaggedArgument(1);
406 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is key */
407 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
408 Return(SetPropertyByValue(glue, receiver, key, value, true));
409 }
410
GenerateCircuit()411 void TryLdGlobalByNameStubBuilder::GenerateCircuit()
412 {
413 GateRef glue = PtrArgument(0);
414 GateRef prop = TaggedPointerArgument(1);
415 GateRef profileTypeInfo = TaggedPointerArgument(2); // 2 : 3rd para
416 GateRef slotId = Int32Argument(3); // 3 : 4th para
417 AccessObjectStubBuilder builder(this);
418 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
419 Return(builder.TryLoadGlobalByName(glue, prop, info, profileTypeInfo, slotId));
420 }
421
GenerateCircuit()422 void TryStGlobalByNameStubBuilder::GenerateCircuit()
423 {
424 GateRef glue = PtrArgument(0);
425 GateRef prop = TaggedPointerArgument(1);
426 GateRef value = TaggedArgument(2); // 2 : 3rd para
427 GateRef profileTypeInfo = TaggedPointerArgument(3); // 3 : 4th para
428 GateRef slotId = Int32Argument(4); // 4: 5th para
429 AccessObjectStubBuilder builder(this);
430 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
431 Return(builder.TryStoreGlobalByName(glue, prop, info, value, profileTypeInfo, slotId));
432 }
433
GenerateCircuit()434 void LdGlobalVarStubBuilder::GenerateCircuit()
435 {
436 GateRef glue = PtrArgument(0);
437 GateRef prop = TaggedPointerArgument(1);
438 GateRef profileTypeInfo = TaggedPointerArgument(2); // 2 : 3rd para
439 GateRef slotId = Int32Argument(3); // 3 : 4th para
440 AccessObjectStubBuilder builder(this);
441 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
442 Return(builder.LoadGlobalVar(glue, prop, info, profileTypeInfo, slotId));
443 }
444
GenerateCircuit()445 void StGlobalVarStubBuilder::GenerateCircuit()
446 {
447 GateRef glue = PtrArgument(0);
448 GateRef prop = TaggedPointerArgument(1);
449 GateRef value = TaggedArgument(2); // 2 : 3rd para
450 GateRef profileTypeInfo = TaggedPointerArgument(3); // 3 : 4th para
451 GateRef slotId = Int32Argument(4); // 4: 5th para
452 AccessObjectStubBuilder builder(this);
453 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
454 Return(builder.StoreGlobalVar(glue, prop, info, value, profileTypeInfo, slotId));
455 }
456
GenerateCircuit()457 void TryLoadICByNameStubBuilder::GenerateCircuit()
458 {
459 auto env = GetEnvironment();
460 GateRef glue = PtrArgument(0);
461 GateRef receiver = TaggedArgument(1);
462 GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
463 GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
464
465 Label receiverIsHeapObject(env);
466 Label receiverNotHeapObject(env);
467 Label hclassEqualFirstValue(env);
468 Label hclassNotEqualFirstValue(env);
469 Label cachedHandlerNotHole(env);
470 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
471 Bind(&receiverIsHeapObject);
472 {
473 GateRef hclass = LoadHClass(receiver);
474 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
475 &hclassEqualFirstValue,
476 &hclassNotEqualFirstValue);
477 Bind(&hclassEqualFirstValue);
478 {
479 Return(LoadICWithHandler(glue, receiver, receiver, secondValue));
480 }
481 Bind(&hclassNotEqualFirstValue);
482 {
483 GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
484 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
485 Bind(&cachedHandlerNotHole);
486 {
487 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
488 }
489 }
490 }
491 Bind(&receiverNotHeapObject);
492 {
493 Return(Hole());
494 }
495 }
496
GenerateCircuit()497 void TryLoadICByValueStubBuilder::GenerateCircuit()
498 {
499 auto env = GetEnvironment();
500 GateRef glue = PtrArgument(0);
501 GateRef receiver = TaggedArgument(1);
502 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
503 GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
504 GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
505
506 Label receiverIsHeapObject(env);
507 Label receiverNotHeapObject(env);
508 Label hclassEqualFirstValue(env);
509 Label hclassNotEqualFirstValue(env);
510 Label firstValueEqualKey(env);
511 Label cachedHandlerNotHole(env);
512 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
513 Bind(&receiverIsHeapObject);
514 {
515 GateRef hclass = LoadHClass(receiver);
516 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
517 &hclassEqualFirstValue,
518 &hclassNotEqualFirstValue);
519 Bind(&hclassEqualFirstValue);
520 Return(LoadElement(receiver, key));
521 Bind(&hclassNotEqualFirstValue);
522 {
523 Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
524 Bind(&firstValueEqualKey);
525 {
526 auto cachedHandler = CheckPolyHClass(secondValue, hclass);
527 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
528 Bind(&cachedHandlerNotHole);
529 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
530 }
531 }
532 }
533 Bind(&receiverNotHeapObject);
534 Return(Hole());
535 }
536
GenerateCircuit()537 void TryStoreICByNameStubBuilder::GenerateCircuit()
538 {
539 auto env = GetEnvironment();
540 GateRef glue = PtrArgument(0);
541 GateRef receiver = TaggedArgument(1);
542 GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
543 GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
544 GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */
545 Label receiverIsHeapObject(env);
546 Label receiverNotHeapObject(env);
547 Label hclassEqualFirstValue(env);
548 Label hclassNotEqualFirstValue(env);
549 Label cachedHandlerNotHole(env);
550 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
551 Bind(&receiverIsHeapObject);
552 {
553 GateRef hclass = LoadHClass(receiver);
554 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
555 &hclassEqualFirstValue,
556 &hclassNotEqualFirstValue);
557 Bind(&hclassEqualFirstValue);
558 {
559 Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue));
560 }
561 Bind(&hclassNotEqualFirstValue);
562 {
563 GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
564 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
565 Bind(&cachedHandlerNotHole);
566 {
567 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
568 }
569 }
570 }
571 Bind(&receiverNotHeapObject);
572 Return(Hole());
573 }
574
GenerateCircuit()575 void TryStoreICByValueStubBuilder::GenerateCircuit()
576 {
577 auto env = GetEnvironment();
578 GateRef glue = PtrArgument(0);
579 GateRef receiver = TaggedArgument(1);
580 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
581 GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
582 GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
583 GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */
584 Label receiverIsHeapObject(env);
585 Label receiverNotHeapObject(env);
586 Label hclassEqualFirstValue(env);
587 Label hclassNotEqualFirstValue(env);
588 Label firstValueEqualKey(env);
589 Label cachedHandlerNotHole(env);
590 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
591 Bind(&receiverIsHeapObject);
592 {
593 GateRef hclass = LoadHClass(receiver);
594 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
595 &hclassEqualFirstValue,
596 &hclassNotEqualFirstValue);
597 Bind(&hclassEqualFirstValue);
598 Return(ICStoreElement(glue, receiver, key, value, secondValue));
599 Bind(&hclassNotEqualFirstValue);
600 {
601 Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
602 Bind(&firstValueEqualKey);
603 {
604 GateRef cachedHandler = CheckPolyHClass(secondValue, hclass);
605 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
606 Bind(&cachedHandlerNotHole);
607 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
608 }
609 }
610 }
611 Bind(&receiverNotHeapObject);
612 Return(Hole());
613 }
614
GenerateCircuit()615 void SetValueWithBarrierStubBuilder::GenerateCircuit()
616 {
617 GateRef glue = PtrArgument(0);
618 GateRef obj = TaggedArgument(1);
619 GateRef offset = PtrArgument(2); // 2 : 3rd para
620 GateRef value = TaggedArgument(3); // 3 : 4th para
621 SetValueWithBarrier(glue, obj, offset, value);
622 Return();
623 }
624
GenerateCircuit()625 void NewThisObjectCheckedStubBuilder::GenerateCircuit()
626 {
627 GateRef glue = PtrArgument(0);
628 GateRef ctor = TaggedArgument(1);
629 NewObjectStubBuilder newBuilder(this);
630 Return(newBuilder.NewThisObjectChecked(glue, ctor));
631 }
632
GenerateCircuit()633 void ConstructorCheckStubBuilder::GenerateCircuit()
634 {
635 GateRef glue = PtrArgument(0);
636 GateRef ctor = TaggedArgument(1);
637 GateRef value = TaggedArgument(2); // 2 : 3rd para
638 GateRef thisObj = TaggedArgument(3); // 3 : 4th para
639 Return(ConstructorCheck(glue, ctor, value, thisObj));
640 }
641
GenerateCircuit()642 void JsProxyCallInternalStubBuilder::GenerateCircuit()
643 {
644 auto env = GetEnvironment();
645 Label exit(env);
646 Label isNull(env);
647 Label notNull(env);
648 Label isUndefined(env);
649 Label isNotUndefined(env);
650
651 GateRef glue = PtrArgument(0);
652 GateRef argc = Int64Argument(1);
653 GateRef proxy = TaggedPointerArgument(2); // callTarget
654 GateRef argv = PtrArgument(3);
655
656 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
657
658 GateRef handler = GetHandlerFromJSProxy(proxy);
659 Branch(TaggedIsNull(handler), &isNull, ¬Null);
660 Bind(&isNull);
661 {
662 ThrowTypeAndReturn(glue, GET_MESSAGE_STRING_ID(NonCallable), Exception());
663 }
664 Bind(¬Null);
665 {
666 GateRef target = GetTargetFromJSProxy(proxy);
667 GateRef globalConstOffset = IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit()));
668 GateRef keyOffset = PtrAdd(globalConstOffset,
669 PtrMul(IntPtr(static_cast<int64_t>(ConstantIndex::APPLY_STRING_INDEX)),
670 IntPtr(sizeof(JSTaggedValue))));
671 GateRef key = Load(VariableType::JS_ANY(), glue, keyOffset);
672 GateRef method = CallRuntime(glue, RTSTUB_ID(JSObjectGetMethod), {handler, key});
673 ReturnExceptionIfAbruptCompletion(glue);
674
675 Branch(TaggedIsUndefined(method), &isUndefined, &isNotUndefined);
676 Bind(&isUndefined);
677 {
678 result = CallNGCRuntime(glue, RTSTUB_ID(JSProxyCallInternalWithArgV), {glue, argc, target, argv});
679 Return(*result);
680 }
681 Bind(&isNotUndefined);
682 {
683 const int JSPROXY_NUM_ARGS = 3;
684 GateRef arrHandle = CallRuntime(glue, RTSTUB_ID(CreateArrayFromList), argc, argv);
685 // 2: this offset
686 GateRef thisArg = Load(VariableType::JS_POINTER(), argv, IntPtr(2 * sizeof(JSTaggedValue)));
687 GateRef numArgs = Int64(JSPROXY_NUM_ARGS + NUM_MANDATORY_JSFUNC_ARGS);
688 GateRef lexEnv = Load(VariableType::JS_POINTER(), method, IntPtr(JSFunction::LEXICAL_ENV_OFFSET));
689 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
690 {glue, lexEnv, numArgs, method, Undefined(), handler, target, thisArg, arrHandle});
691 Jump(&exit);
692 }
693 }
694 Bind(&exit);
695 Return(*result);
696 }
697
698 CallSignature CommonStubCSigns::callSigns_[CommonStubCSigns::NUM_OF_STUBS];
699
Initialize()700 void CommonStubCSigns::Initialize()
701 {
702 #define INIT_SIGNATURES(name) \
703 name##CallSignature::Initialize(&callSigns_[name]); \
704 callSigns_[name].SetID(name); \
705 callSigns_[name].SetName(std::string("COStub_") + #name); \
706 callSigns_[name].SetConstructor( \
707 [](void* env) { \
708 return static_cast<void*>( \
709 new name##StubBuilder(&callSigns_[name], static_cast<Environment*>(env))); \
710 });
711
712 COMMON_STUB_ID_LIST(INIT_SIGNATURES)
713 #undef INIT_SIGNATURES
714 }
715
GetCSigns(std::vector<const CallSignature * > & outCSigns)716 void CommonStubCSigns::GetCSigns(std::vector<const CallSignature*>& outCSigns)
717 {
718 for (size_t i = 0; i < NUM_OF_STUBS; i++) {
719 outCSigns.push_back(&callSigns_[i]);
720 }
721 }
722 } // namespace panda::ecmascript::kungfu
723