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 StrictEqualStubBuilder::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.StrictEqual(glue, x, y));
110 }
111
GenerateCircuit()112 void StrictNotEqualStubBuilder::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.StrictNotEqual(glue, x, y));
119 }
120
GenerateCircuit()121 void LessStubBuilder::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.Less(glue, x, y));
128 }
129
GenerateCircuit()130 void LessEqStubBuilder::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.LessEq(glue, x, y));
137 }
138
GenerateCircuit()139 void GreaterStubBuilder::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.Greater(glue, x, y));
146 }
147
GenerateCircuit()148 void GreaterEqStubBuilder::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.GreaterEq(glue, x, y));
155 }
156
GenerateCircuit()157 void ShlStubBuilder::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.Shl(glue, x, y));
164 }
165
GenerateCircuit()166 void ShrStubBuilder::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.Shr(glue, x, y));
173 }
174
GenerateCircuit()175 void AshrStubBuilder::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.Ashr(glue, x, y));
182 }
183
GenerateCircuit()184 void AndStubBuilder::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.And(glue, x, y));
191 }
192
GenerateCircuit()193 void OrStubBuilder::GenerateCircuit()
194 {
195 GateRef glue = PtrArgument(0);
196 GateRef x = TaggedArgument(1);
197 GateRef y = TaggedArgument(2); // 2: 3rd argument
198 OperationsStubBuilder operationBuilder(this);
199 Return(operationBuilder.Or(glue, x, y));
200 }
201
GenerateCircuit()202 void XorStubBuilder::GenerateCircuit()
203 {
204 GateRef glue = PtrArgument(0);
205 GateRef x = TaggedArgument(1);
206 GateRef y = TaggedArgument(2); // 2: 3rd argument
207 OperationsStubBuilder operationBuilder(this);
208 Return(operationBuilder.Xor(glue, x, y));
209 }
210
GenerateCircuit()211 void InstanceofStubBuilder::GenerateCircuit()
212 {
213 GateRef glue = PtrArgument(0);
214 GateRef object = TaggedArgument(1);
215 GateRef target = TaggedArgument(2); // 2: 3rd argument
216 GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
217 GateRef slotId = Int32Argument(4); // 4 : 5th pars
218 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
219 Return(InstanceOf(glue, object, target, profileTypeInfo, slotId, ProfileOperation()));
220 }
221
GenerateCircuit()222 void IncStubBuilder::GenerateCircuit()
223 {
224 GateRef glue = PtrArgument(0);
225 GateRef x = TaggedArgument(1);
226 OperationsStubBuilder operationBuilder(this);
227 Return(operationBuilder.Inc(glue, x));
228 }
229
GenerateCircuit()230 void DecStubBuilder::GenerateCircuit()
231 {
232 GateRef glue = PtrArgument(0);
233 GateRef x = TaggedArgument(1);
234 OperationsStubBuilder operationBuilder(this);
235 Return(operationBuilder.Dec(glue, x));
236 }
237
GenerateCircuit()238 void NegStubBuilder::GenerateCircuit()
239 {
240 GateRef glue = PtrArgument(0);
241 GateRef x = TaggedArgument(1);
242 OperationsStubBuilder operationBuilder(this);
243 Return(operationBuilder.Neg(glue, x));
244 }
245
GenerateCircuit()246 void NotStubBuilder::GenerateCircuit()
247 {
248 GateRef glue = PtrArgument(0);
249 GateRef x = TaggedArgument(1);
250 OperationsStubBuilder operationBuilder(this);
251 Return(operationBuilder.Not(glue, x));
252 }
253
GenerateCircuit()254 void ToBooleanStubBuilder::GenerateCircuit()
255 {
256 GateRef glue = PtrArgument(0);
257 (void)glue;
258 GateRef x = TaggedArgument(1);
259 Return(FastToBoolean(x));
260 }
261
GenerateCircuit()262 void NewLexicalEnvStubBuilder::GenerateCircuit()
263 {
264 auto env = GetEnvironment();
265 GateRef glue = PtrArgument(0);
266 GateRef parent = TaggedArgument(1);
267 GateRef numVars = Int32Argument(2); /* 2 : 3rd parameter is index */
268
269 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
270 NewObjectStubBuilder newBuilder(this);
271 newBuilder.SetParameters(glue, 0);
272 Label afterNew(env);
273 newBuilder.NewLexicalEnv(&result, &afterNew, numVars, parent);
274 Bind(&afterNew);
275 Return(*result);
276 }
277
GenerateCircuit()278 void GetUnmapedArgsStubBuilder::GenerateCircuit()
279 {
280 auto env = GetEnvironment();
281 GateRef glue = PtrArgument(0);
282 GateRef numArgs = Int32Argument(1);
283
284 DEFVARIABLE(argumentsList, VariableType::JS_ANY(), Hole());
285 DEFVARIABLE(argumentsObj, VariableType::JS_ANY(), Hole());
286 Label afterArgumentsList(env);
287 Label newArgumentsObj(env);
288 Label exit(env);
289
290 GateRef argv = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
291 GateRef args = PtrAdd(argv, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
292 GateRef actualArgc = Int32Sub(numArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
293 GateRef startIdx = Int32(0);
294 NewObjectStubBuilder newBuilder(this);
295 newBuilder.SetParameters(glue, 0);
296 newBuilder.NewArgumentsList(&argumentsList, &afterArgumentsList, args, startIdx, actualArgc);
297 Bind(&afterArgumentsList);
298 Branch(TaggedIsException(*argumentsList), &exit, &newArgumentsObj);
299 Bind(&newArgumentsObj);
300 newBuilder.NewArgumentsObj(&argumentsObj, &exit, *argumentsList, actualArgc);
301 Bind(&exit);
302 Return(*argumentsObj);
303 }
304
GenerateCircuit()305 void GetPropertyByIndexStubBuilder::GenerateCircuit()
306 {
307 GateRef glue = PtrArgument(0);
308 GateRef receiver = TaggedArgument(1);
309 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
310 Return(GetPropertyByIndex(glue, receiver, index, ProfileOperation()));
311 }
312
GenerateCircuit()313 void SetPropertyByIndexStubBuilder::GenerateCircuit()
314 {
315 GateRef glue = PtrArgument(0);
316 GateRef receiver = TaggedArgument(1);
317 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
318 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
319 Return(SetPropertyByIndex(glue, receiver, index, value, false, ProfileOperation()));
320 }
321
GenerateCircuit()322 void SetPropertyByIndexWithOwnStubBuilder::GenerateCircuit()
323 {
324 GateRef glue = PtrArgument(0);
325 GateRef receiver = TaggedArgument(1);
326 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
327 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
328 Return(SetPropertyByIndex(glue, receiver, index, value, true, ProfileOperation()));
329 }
330
GenerateCircuit()331 void GetPropertyByNameStubBuilder::GenerateCircuit()
332 {
333 GateRef glue = PtrArgument(0);
334 GateRef receiver = TaggedArgument(1);
335 GateRef id = Int64Argument(2); // 2 : 3rd para
336 GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
337 GateRef slotId = Int32Argument(4); // 4 : 5th para
338 AccessObjectStubBuilder builder(this, jsFunc);
339 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
340 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
341 Return(builder.LoadObjByName(glue, receiver, id, info, profileTypeInfo, slotId, ProfileOperation()));
342 }
343
GenerateCircuit()344 void DeprecatedGetPropertyByNameStubBuilder::GenerateCircuit()
345 {
346 GateRef glue = PtrArgument(0);
347 GateRef receiver = TaggedArgument(1);
348 GateRef key = TaggedPointerArgument(2); // 2 : 3rd para
349 AccessObjectStubBuilder builder(this);
350 Return(builder.DeprecatedLoadObjByName(glue, receiver, key));
351 }
352
GenerateCircuit()353 void SetPropertyByNameStubBuilder::GenerateCircuit()
354 {
355 GateRef glue = PtrArgument(0);
356 GateRef receiver = TaggedArgument(1);
357 GateRef id = Int64Argument(2); // 2 : 3rd para
358 GateRef value = TaggedPointerArgument(3); // 3 : 4th para
359 GateRef jsFunc = TaggedArgument(4); // 4 : 5th para
360 GateRef slotId = Int32Argument(5); // 5 : 6th para
361 AccessObjectStubBuilder builder(this, jsFunc);
362 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
363 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
364 Return(builder.StoreObjByName(glue, receiver, id, info, value, profileTypeInfo, slotId, ProfileOperation()));
365 }
366
GenerateCircuit()367 void DeprecatedSetPropertyByNameStubBuilder::GenerateCircuit()
368 {
369 GateRef glue = PtrArgument(0);
370 GateRef receiver = TaggedArgument(1);
371 GateRef key = TaggedArgument(2); // 2 : 3rd para
372 GateRef value = TaggedArgument(3); // 3 : 4th para
373 Return(SetPropertyByName(glue, receiver, key, value, false));
374 }
375
GenerateCircuit()376 void SetPropertyByNameWithOwnStubBuilder::GenerateCircuit()
377 {
378 GateRef glue = PtrArgument(0);
379 GateRef receiver = TaggedArgument(1);
380 GateRef key = TaggedArgument(2); // 2 : 3rd para
381 GateRef value = TaggedArgument(3); // 3 : 4th para
382 Return(SetPropertyByName(glue, receiver, key, value, true));
383 }
384
GenerateCircuit()385 void GetPropertyByValueStubBuilder::GenerateCircuit()
386 {
387 GateRef glue = PtrArgument(0);
388 GateRef receiver = TaggedArgument(1);
389 GateRef key = TaggedArgument(2); // 2 : 3rd para
390 GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
391 GateRef slotId = Int32Argument(4); // 4 : 5th para
392 AccessObjectStubBuilder builder(this);
393 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
394 Return(builder.LoadObjByValue(glue, receiver, key, profileTypeInfo, slotId));
395 }
396
GenerateCircuit()397 void DeprecatedGetPropertyByValueStubBuilder::GenerateCircuit()
398 {
399 GateRef glue = PtrArgument(0);
400 GateRef receiver = TaggedArgument(1);
401 GateRef key = TaggedArgument(2); // 2 : 3rd para
402 Return(GetPropertyByValue(glue, receiver, key, ProfileOperation()));
403 }
404
GenerateCircuit()405 void SetPropertyByValueStubBuilder::GenerateCircuit()
406 {
407 GateRef glue = PtrArgument(0);
408 GateRef receiver = TaggedArgument(1);
409 GateRef key = TaggedArgument(2); // 2 : 3rd para
410 GateRef value = TaggedArgument(3); // 3 : 4th para
411 GateRef jsFunc = TaggedArgument(4); // 4 : 5th para
412 GateRef slotId = Int32Argument(5); // 5 : 6th para
413 AccessObjectStubBuilder builder(this);
414 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
415 Return(builder.StoreObjByValue(glue, receiver, key, value, profileTypeInfo, slotId));
416 }
417
GenerateCircuit()418 void DeprecatedSetPropertyByValueStubBuilder::GenerateCircuit()
419 {
420 GateRef glue = PtrArgument(0);
421 GateRef receiver = TaggedArgument(1);
422 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is key */
423 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
424 Return(SetPropertyByValue(glue, receiver, key, value, false));
425 }
426
GenerateCircuit()427 void SetPropertyByValueWithOwnStubBuilder::GenerateCircuit()
428 {
429 GateRef glue = PtrArgument(0);
430 GateRef receiver = TaggedArgument(1);
431 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is key */
432 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
433 Return(SetPropertyByValue(glue, receiver, key, value, true));
434 }
435
GenerateCircuit()436 void TryLdGlobalByNameStubBuilder::GenerateCircuit()
437 {
438 GateRef glue = PtrArgument(0);
439 GateRef id = Int64Argument(1);
440 GateRef jsFunc = TaggedArgument(2); // 2 : 3th para
441 GateRef slotId = Int32Argument(3); // 3 : 4th para
442 AccessObjectStubBuilder builder(this, jsFunc);
443 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
444 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
445 Return(builder.TryLoadGlobalByName(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
446 }
447
GenerateCircuit()448 void TryStGlobalByNameStubBuilder::GenerateCircuit()
449 {
450 GateRef glue = PtrArgument(0);
451 GateRef id = Int64Argument(1);
452 GateRef value = TaggedArgument(2); // 2 : 3rd para
453 GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
454 GateRef slotId = Int32Argument(4); // 4: 5th para
455 AccessObjectStubBuilder builder(this, jsFunc);
456 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
457 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
458 Return(builder.TryStoreGlobalByName(glue, id, info, value, profileTypeInfo, slotId, ProfileOperation()));
459 }
460
GenerateCircuit()461 void LdGlobalVarStubBuilder::GenerateCircuit()
462 {
463 GateRef glue = PtrArgument(0);
464 GateRef id = Int64Argument(1);
465 GateRef jsFunc = TaggedArgument(2); // 2 : 3th para
466 GateRef slotId = Int32Argument(3); // 3 : 4th para
467 AccessObjectStubBuilder builder(this, jsFunc);
468 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
469 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
470 Return(builder.LoadGlobalVar(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
471 }
472
GenerateCircuit()473 void StGlobalVarStubBuilder::GenerateCircuit()
474 {
475 GateRef glue = PtrArgument(0);
476 GateRef id = Int64Argument(1);
477 GateRef value = TaggedArgument(2); // 2 : 3rd para
478 GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
479 GateRef slotId = Int32Argument(4); // 4: 5th para
480 AccessObjectStubBuilder builder(this, jsFunc);
481 StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
482 GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
483 Return(builder.StoreGlobalVar(glue, id, info, value, profileTypeInfo, slotId));
484 }
485
GenerateCircuit()486 void TryLoadICByNameStubBuilder::GenerateCircuit()
487 {
488 auto env = GetEnvironment();
489 GateRef glue = PtrArgument(0);
490 GateRef receiver = TaggedArgument(1);
491 GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
492 GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
493
494 Label receiverIsHeapObject(env);
495 Label receiverNotHeapObject(env);
496 Label hclassEqualFirstValue(env);
497 Label hclassNotEqualFirstValue(env);
498 Label cachedHandlerNotHole(env);
499 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
500 Bind(&receiverIsHeapObject);
501 {
502 GateRef hclass = LoadHClass(receiver);
503 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
504 &hclassEqualFirstValue,
505 &hclassNotEqualFirstValue);
506 Bind(&hclassEqualFirstValue);
507 {
508 Return(LoadICWithHandler(glue, receiver, receiver, secondValue, ProfileOperation()));
509 }
510 Bind(&hclassNotEqualFirstValue);
511 {
512 GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
513 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
514 Bind(&cachedHandlerNotHole);
515 {
516 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
517 }
518 }
519 }
520 Bind(&receiverNotHeapObject);
521 {
522 Return(Hole());
523 }
524 }
525
GenerateCircuit()526 void TryLoadICByValueStubBuilder::GenerateCircuit()
527 {
528 auto env = GetEnvironment();
529 GateRef glue = PtrArgument(0);
530 GateRef receiver = TaggedArgument(1);
531 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
532 GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
533 GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
534
535 Label receiverIsHeapObject(env);
536 Label receiverNotHeapObject(env);
537 Label hclassEqualFirstValue(env);
538 Label hclassNotEqualFirstValue(env);
539 Label firstValueEqualKey(env);
540 Label cachedHandlerNotHole(env);
541 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
542 Bind(&receiverIsHeapObject);
543 {
544 GateRef hclass = LoadHClass(receiver);
545 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
546 &hclassEqualFirstValue,
547 &hclassNotEqualFirstValue);
548 Bind(&hclassEqualFirstValue);
549 Return(LoadElement(glue, receiver, key, ProfileOperation()));
550 Bind(&hclassNotEqualFirstValue);
551 {
552 Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
553 Bind(&firstValueEqualKey);
554 {
555 auto cachedHandler = CheckPolyHClass(secondValue, hclass);
556 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
557 Bind(&cachedHandlerNotHole);
558 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
559 }
560 }
561 }
562 Bind(&receiverNotHeapObject);
563 Return(Hole());
564 }
565
GenerateCircuit()566 void TryStoreICByNameStubBuilder::GenerateCircuit()
567 {
568 auto env = GetEnvironment();
569 GateRef glue = PtrArgument(0);
570 GateRef receiver = TaggedArgument(1);
571 GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
572 GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
573 GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */
574 Label receiverIsHeapObject(env);
575 Label receiverNotHeapObject(env);
576 Label hclassEqualFirstValue(env);
577 Label hclassNotEqualFirstValue(env);
578 Label cachedHandlerNotHole(env);
579 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
580 Bind(&receiverIsHeapObject);
581 {
582 GateRef hclass = LoadHClass(receiver);
583 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
584 &hclassEqualFirstValue,
585 &hclassNotEqualFirstValue);
586 Bind(&hclassEqualFirstValue);
587 {
588 Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue));
589 }
590 Bind(&hclassNotEqualFirstValue);
591 {
592 GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
593 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
594 Bind(&cachedHandlerNotHole);
595 {
596 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
597 }
598 }
599 }
600 Bind(&receiverNotHeapObject);
601 Return(Hole());
602 }
603
GenerateCircuit()604 void TryStoreICByValueStubBuilder::GenerateCircuit()
605 {
606 auto env = GetEnvironment();
607 GateRef glue = PtrArgument(0);
608 GateRef receiver = TaggedArgument(1);
609 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
610 GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
611 GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
612 GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */
613 Label receiverIsHeapObject(env);
614 Label receiverNotHeapObject(env);
615 Label hclassEqualFirstValue(env);
616 Label hclassNotEqualFirstValue(env);
617 Label firstValueEqualKey(env);
618 Label cachedHandlerNotHole(env);
619 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
620 Bind(&receiverIsHeapObject);
621 {
622 GateRef hclass = LoadHClass(receiver);
623 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
624 &hclassEqualFirstValue,
625 &hclassNotEqualFirstValue);
626 Bind(&hclassEqualFirstValue);
627 Return(ICStoreElement(glue, receiver, key, value, secondValue, ProfileOperation()));
628 Bind(&hclassNotEqualFirstValue);
629 {
630 Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
631 Bind(&firstValueEqualKey);
632 {
633 GateRef cachedHandler = CheckPolyHClass(secondValue, hclass);
634 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
635 Bind(&cachedHandlerNotHole);
636 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
637 }
638 }
639 }
640 Bind(&receiverNotHeapObject);
641 Return(Hole());
642 }
643
GenerateCircuit()644 void SetValueWithBarrierStubBuilder::GenerateCircuit()
645 {
646 GateRef glue = PtrArgument(0);
647 GateRef obj = TaggedArgument(1);
648 GateRef offset = PtrArgument(2); // 2 : 3rd para
649 GateRef value = TaggedArgument(3); // 3 : 4th para
650 SetValueWithBarrier(glue, obj, offset, value);
651 Return();
652 }
653
GenerateCircuit()654 void NewThisObjectCheckedStubBuilder::GenerateCircuit()
655 {
656 GateRef glue = PtrArgument(0);
657 GateRef ctor = TaggedArgument(1);
658 NewObjectStubBuilder newBuilder(this);
659 Return(newBuilder.NewThisObjectChecked(glue, ctor));
660 }
661
GenerateCircuit()662 void ConstructorCheckStubBuilder::GenerateCircuit()
663 {
664 GateRef glue = PtrArgument(0);
665 GateRef ctor = TaggedArgument(1);
666 GateRef value = TaggedArgument(2); // 2 : 3rd para
667 GateRef thisObj = TaggedArgument(3); // 3 : 4th para
668 Return(ConstructorCheck(glue, ctor, value, thisObj));
669 }
670
GenerateCircuit()671 void CreateEmptyArrayStubBuilder::GenerateCircuit()
672 {
673 GateRef glue = PtrArgument(0);
674 NewObjectStubBuilder newBuilder(this);
675 Return(newBuilder.CreateEmptyArray(glue, ProfileOperation()));
676 }
677
GenerateCircuit()678 void CreateArrayWithBufferStubBuilder::GenerateCircuit()
679 {
680 GateRef glue = PtrArgument(0);
681 GateRef index = Int32Argument(1);
682 GateRef jsFunc = TaggedArgument(2); // 2 : 3rd para
683 NewObjectStubBuilder newBuilder(this);
684 Return(newBuilder.CreateArrayWithBuffer(glue, index, jsFunc, ProfileOperation()));
685 }
686
GenerateCircuit()687 void NewJSObjectStubBuilder::GenerateCircuit()
688 {
689 GateRef glue = PtrArgument(0);
690 GateRef hclass = TaggedArgument(1);
691 NewObjectStubBuilder newBuilder(this);
692 Return(newBuilder.NewJSObject(glue, hclass));
693 }
694
GenerateCircuit()695 void JsBoundCallInternalStubBuilder::GenerateCircuit()
696 {
697 auto env = GetEnvironment();
698 Label exit(env);
699 Label fastCall(env);
700 Label notFastCall(env);
701 Label methodIsFastCall(env);
702 Label fastCallBridge(env);
703 Label slowCall(env);
704 Label slowCallBridge(env);
705
706 GateRef glue = PtrArgument(0);
707 GateRef argc = Int64Argument(1);
708 GateRef func = TaggedPointerArgument(2); // callTarget
709 GateRef argv = PtrArgument(3);
710 GateRef thisValue = TaggedPointerArgument(4); // this
711 GateRef newTarget = TaggedPointerArgument(5); // new target
712 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
713 GateRef method = GetMethodFromFunction(func);
714 GateRef callfield = Load(VariableType::INT64(), method, IntPtr(Method::CALL_FIELD_OFFSET));
715 GateRef expectedNum = Int64And(Int64LSR(callfield, Int64(MethodLiteral::NumArgsBits::START_BIT)),
716 Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
717 GateRef expectedArgc = Int64Add(expectedNum, Int64(NUM_MANDATORY_JSFUNC_ARGS));
718 GateRef actualArgc = Int64Sub(argc, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
719 GateRef hClass = LoadHClass(func);
720 GateRef bitfield = Load(VariableType::INT32(), hClass, Int32(JSHClass::BIT_FIELD_OFFSET));
721 Branch(CanFastCallWithBitField(bitfield), &methodIsFastCall, ¬FastCall);
722 Bind(&methodIsFastCall);
723 {
724 Branch(Int64LessThanOrEqual(expectedArgc, argc), &fastCall, &fastCallBridge);
725 Bind(&fastCall);
726 {
727 result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgV),
728 { glue, func, thisValue, actualArgc, argv });
729 Jump(&exit);
730 }
731 Bind(&fastCallBridge);
732 {
733 result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgVAndPushUndefined),
734 { glue, func, thisValue, actualArgc, argv, expectedNum });
735 Jump(&exit);
736 }
737 }
738 Bind(¬FastCall);
739 {
740 Branch(Int64LessThanOrEqual(expectedArgc, argc), &slowCall, &slowCallBridge);
741 Bind(&slowCall);
742 {
743 result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgV),
744 { glue, actualArgc, func, newTarget, thisValue, argv });
745 Jump(&exit);
746 }
747 Bind(&slowCallBridge);
748 {
749 result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgVAndPushUndefined),
750 { glue, actualArgc, func, newTarget, thisValue, argv });
751 Jump(&exit);
752 }
753 }
754 Bind(&exit);
755 Return(*result);
756 }
757
GenerateCircuit()758 void JsProxyCallInternalStubBuilder::GenerateCircuit()
759 {
760 auto env = GetEnvironment();
761 Label exit(env);
762 Label isNull(env);
763 Label notNull(env);
764 Label isUndefined(env);
765 Label isNotUndefined(env);
766
767 GateRef glue = PtrArgument(0);
768 GateRef argc = Int64Argument(1);
769 GateRef proxy = TaggedPointerArgument(2); // callTarget
770 GateRef argv = PtrArgument(3);
771 GateRef newTarget = Load(VariableType::JS_POINTER(), argv, IntPtr(sizeof(JSTaggedValue)));
772 GateRef thisTarget = Load(VariableType::JS_POINTER(), argv, IntPtr(2 * sizeof(JSTaggedValue)));
773
774 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
775
776 GateRef handler = GetHandlerFromJSProxy(proxy);
777 Branch(TaggedIsNull(handler), &isNull, ¬Null);
778 Bind(&isNull);
779 {
780 ThrowTypeAndReturn(glue, GET_MESSAGE_STRING_ID(NonCallable), Exception());
781 }
782 Bind(¬Null);
783 {
784 GateRef target = GetTargetFromJSProxy(proxy);
785 GateRef gConstPointer = Load(VariableType::JS_ANY(), glue,
786 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit())));
787
788 GateRef keyOffset = PtrAdd(gConstPointer,
789 PtrMul(IntPtr(static_cast<int64_t>(ConstantIndex::APPLY_STRING_INDEX)),
790 IntPtr(sizeof(JSTaggedValue))));
791 GateRef key = Load(VariableType::JS_ANY(), keyOffset);
792 GateRef method = CallRuntime(glue, RTSTUB_ID(JSObjectGetMethod), {handler, key});
793 ReturnExceptionIfAbruptCompletion(glue);
794
795 Branch(TaggedIsUndefined(method), &isUndefined, &isNotUndefined);
796 Bind(&isUndefined);
797 {
798 Label isHeapObject(env);
799 Label slowPath(env);
800 Label isJsFcuntion(env);
801 Label notCallConstructor(env);
802 Label fastCall(env);
803 Label notFastCall(env);
804 Label slowCall(env);
805 Branch(TaggedIsHeapObject(target), &isHeapObject, &slowPath);
806 Bind(&isHeapObject);
807 {
808 GateRef hClass = LoadHClass(target);
809 GateRef bitfield = Load(VariableType::INT32(), hClass, Int32(JSHClass::BIT_FIELD_OFFSET));
810 Branch(IsClassConstructorFromBitField(bitfield), &slowPath, ¬CallConstructor);
811 Bind(¬CallConstructor);
812 GateRef actualArgc = Int64Sub(argc, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
813 GateRef actualArgv = PtrAdd(argv, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * sizeof(JSTaggedValue)));
814 Branch(CanFastCallWithBitField(bitfield), &fastCall, ¬FastCall);
815 Bind(&fastCall);
816 {
817 result = CallNGCRuntime(glue, RTSTUB_ID(JSFastCallWithArgV),
818 { glue, target, thisTarget, actualArgc, actualArgv });
819 Jump(&exit);
820 }
821 Bind(¬FastCall);
822 {
823 Branch(IsOptimizedWithBitField(bitfield), &slowCall, &slowPath);
824 Bind(&slowCall);
825 {
826 result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgV),
827 { glue, actualArgc, target, newTarget, thisTarget, actualArgv });
828 Jump(&exit);
829 }
830 }
831 }
832 Bind(&slowPath);
833 {
834 result = CallNGCRuntime(glue, RTSTUB_ID(JSProxyCallInternalWithArgV), {glue, target});
835 Jump(&exit);
836 }
837 }
838 Bind(&isNotUndefined);
839 {
840 Label isHeapObject1(env);
841 Label slowPath1(env);
842 Label isJsFcuntion1(env);
843 Label notCallConstructor1(env);
844 Label fastCall1(env);
845 Label notFastCall1(env);
846 Label slowCall1(env);
847 const int JSPROXY_NUM_ARGS = 3;
848 GateRef arrHandle = CallRuntime(glue, RTSTUB_ID(CreateArrayFromList), argc, argv);
849 // 2: this offset
850 GateRef numArgs = Int64(JSPROXY_NUM_ARGS + NUM_MANDATORY_JSFUNC_ARGS);
851
852 Branch(TaggedIsHeapObject(method), &isHeapObject1, &slowPath1);
853 Bind(&isHeapObject1);
854 {
855 GateRef hClass = LoadHClass(method);
856 GateRef bitfield = Load(VariableType::INT32(), hClass, Int32(JSHClass::BIT_FIELD_OFFSET));
857 Branch(IsClassConstructor(method), &slowPath1, ¬CallConstructor1);
858 Bind(¬CallConstructor1);
859 GateRef meth = GetMethodFromFunction(method);
860 GateRef code = GetAotCodeAddr(meth);
861 Branch(CanFastCallWithBitField(bitfield), &fastCall1, ¬FastCall1);
862 Bind(&fastCall1);
863 {
864 result = FastCallOptimized(glue, code,
865 { glue, method, handler, target, thisTarget, arrHandle });
866 Jump(&exit);
867 }
868 Bind(¬FastCall1);
869 {
870 Branch(IsOptimizedWithBitField(bitfield), &slowCall1, &slowPath1);
871 Bind(&slowCall1);
872 {
873 result = CallOptimized(glue, code,
874 { glue, numArgs, method, Undefined(), handler, target, thisTarget, arrHandle });
875 Jump(&exit);
876 }
877 }
878 }
879 Bind(&slowPath1);
880 {
881 result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
882 { glue, numArgs, method, Undefined(), handler, target, thisTarget, arrHandle });
883 Jump(&exit);
884 }
885 }
886 }
887 Bind(&exit);
888 Return(*result);
889 }
890
891 CallSignature CommonStubCSigns::callSigns_[CommonStubCSigns::NUM_OF_STUBS];
892
Initialize()893 void CommonStubCSigns::Initialize()
894 {
895 #define INIT_SIGNATURES(name) \
896 name##CallSignature::Initialize(&callSigns_[name]); \
897 callSigns_[name].SetID(name); \
898 callSigns_[name].SetName(std::string("COStub_") + #name); \
899 callSigns_[name].SetConstructor( \
900 [](void* env) { \
901 return static_cast<void*>( \
902 new name##StubBuilder(&callSigns_[name], static_cast<Environment*>(env))); \
903 });
904
905 COMMON_STUB_ID_LIST(INIT_SIGNATURES)
906 #undef INIT_SIGNATURES
907 }
908
GetCSigns(std::vector<const CallSignature * > & outCSigns)909 void CommonStubCSigns::GetCSigns(std::vector<const CallSignature*>& outCSigns)
910 {
911 for (size_t i = 0; i < NUM_OF_STUBS; i++) {
912 outCSigns.push_back(&callSigns_[i]);
913 }
914 }
915 } // namespace panda::ecmascript::kungfu
916