1 | // Copyright (C) 2017 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qv4baselinejit_p.h" |
5 | #include "qv4baselineassembler_p.h" |
6 | #include <private/qv4lookup_p.h> |
7 | #include <private/qv4generatorobject_p.h> |
8 | |
9 | #if QT_CONFIG(qml_jit) |
10 | |
11 | QT_USE_NAMESPACE |
12 | using namespace QV4; |
13 | using namespace QV4::JIT; |
14 | using namespace QV4::Moth; |
15 | |
16 | BaselineJIT::BaselineJIT(Function *function) |
17 | : function(function) |
18 | , as(new BaselineAssembler(&(function->compilationUnit->constants->asValue<Value>()))) |
19 | {} |
20 | |
21 | BaselineJIT::~BaselineJIT() |
22 | {} |
23 | |
24 | void BaselineJIT::generate() |
25 | { |
26 | // qDebug()<<"jitting" << function->name()->toQString(); |
27 | const char *code = function->codeData; |
28 | uint len = function->compiledFunction->codeSize; |
29 | |
30 | for (unsigned i = 0, ei = function->compiledFunction->nLabelInfos; i != ei; ++i) |
31 | labels.insert(value: int(function->compiledFunction->labelInfoTable()[i])); |
32 | |
33 | as->generatePrologue(); |
34 | // Make sure the ACC register is initialized and not clobbered by the caller. |
35 | as->loadAccumulatorFromFrame(); |
36 | decode(code, len); |
37 | as->generateEpilogue(); |
38 | |
39 | as->link(function); |
40 | // qDebug()<<"done"; |
41 | } |
42 | |
43 | #define STORE_IP() as->storeInstructionPointer(nextInstructionOffset()) |
44 | #define STORE_ACC() as->saveAccumulatorInFrame() |
45 | #define LOAD_ACC() as->loadAccumulatorFromFrame() |
46 | #define BASELINEJIT_GENERATE_RUNTIME_CALL(function, destination) { \ |
47 | as->GENERATE_RUNTIME_CALL(function, destination); \ |
48 | if (Runtime::function::throws) \ |
49 | as->checkException(); \ |
50 | else {} } // this else prevents else statements after the macro from attaching to the if above |
51 | |
52 | void BaselineJIT::generate_Ret() |
53 | { |
54 | as->ret(); |
55 | } |
56 | |
57 | void BaselineJIT::generate_Debug() { Q_UNREACHABLE(); } |
58 | |
59 | void BaselineJIT::generate_LoadConst(int index) |
60 | { |
61 | as->loadConst(constIndex: index); |
62 | } |
63 | |
64 | void BaselineJIT::generate_LoadZero() |
65 | { |
66 | as->loadValue(value: Encode(int(0))); |
67 | } |
68 | |
69 | void BaselineJIT::generate_LoadTrue() |
70 | { |
71 | as->loadValue(value: Encode(true)); |
72 | } |
73 | |
74 | void BaselineJIT::generate_LoadFalse() |
75 | { |
76 | as->loadValue(value: Encode(false)); |
77 | } |
78 | |
79 | void BaselineJIT::generate_LoadNull() |
80 | { |
81 | as->loadValue(value: Encode::null()); |
82 | } |
83 | |
84 | void BaselineJIT::generate_LoadUndefined() |
85 | { |
86 | as->loadValue(value: Encode::undefined()); |
87 | } |
88 | |
89 | void BaselineJIT::generate_LoadInt(int value) |
90 | { |
91 | //### |
92 | as->loadValue(value: Encode(value)); |
93 | } |
94 | |
95 | void BaselineJIT::generate_MoveConst(int constIndex, int destTemp) |
96 | { |
97 | as->copyConst(constIndex, destReg: destTemp); |
98 | } |
99 | |
100 | void BaselineJIT::generate_LoadReg(int reg) |
101 | { |
102 | as->loadReg(reg); |
103 | } |
104 | |
105 | void BaselineJIT::generate_StoreReg(int reg) |
106 | { |
107 | as->storeReg(reg); |
108 | } |
109 | |
110 | void BaselineJIT::generate_MoveReg(int srcReg, int destReg) |
111 | { |
112 | // Don't clobber the accumulator. |
113 | as->moveReg(sourceReg: srcReg, destReg); |
114 | } |
115 | |
116 | void BaselineJIT::generate_LoadImport(int index) |
117 | { |
118 | as->loadImport(index); |
119 | } |
120 | |
121 | void BaselineJIT::generate_LoadLocal(int index) |
122 | { |
123 | as->loadLocal(index); |
124 | } |
125 | |
126 | void BaselineJIT::generate_StoreLocal(int index) |
127 | { |
128 | as->checkException(); |
129 | as->storeLocal(index); |
130 | } |
131 | |
132 | void BaselineJIT::generate_LoadScopedLocal(int scope, int index) |
133 | { |
134 | as->loadLocal(index, level: scope); |
135 | } |
136 | |
137 | void BaselineJIT::generate_StoreScopedLocal(int scope, int index) |
138 | { |
139 | as->checkException(); |
140 | as->storeLocal(index, level: scope); |
141 | } |
142 | |
143 | void BaselineJIT::generate_LoadRuntimeString(int stringId) |
144 | { |
145 | as->loadString(stringId); |
146 | } |
147 | |
148 | void BaselineJIT::generate_MoveRegExp(int regExpId, int destReg) |
149 | { |
150 | as->prepareCallWithArgCount(argc: 2); |
151 | as->passInt32AsArg(value: regExpId, arg: 1); |
152 | as->passEngineAsArg(arg: 0); |
153 | BASELINEJIT_GENERATE_RUNTIME_CALL(RegexpLiteral, CallResultDestination::InAccumulator); |
154 | as->storeReg(reg: destReg); |
155 | } |
156 | |
157 | void BaselineJIT::generate_LoadClosure(int value) |
158 | { |
159 | as->prepareCallWithArgCount(argc: 2); |
160 | as->passInt32AsArg(value, arg: 1); |
161 | as->passEngineAsArg(arg: 0); |
162 | BASELINEJIT_GENERATE_RUNTIME_CALL(Closure, CallResultDestination::InAccumulator); |
163 | } |
164 | |
165 | void BaselineJIT::generate_LoadName(int name) |
166 | { |
167 | STORE_IP(); |
168 | as->prepareCallWithArgCount(argc: 2); |
169 | as->passInt32AsArg(value: name, arg: 1); |
170 | as->passEngineAsArg(arg: 0); |
171 | BASELINEJIT_GENERATE_RUNTIME_CALL(LoadName, CallResultDestination::InAccumulator); |
172 | } |
173 | |
174 | void BaselineJIT::generate_LoadGlobalLookup(int index) |
175 | { |
176 | STORE_IP(); |
177 | as->prepareCallWithArgCount(argc: 3); |
178 | as->passInt32AsArg(value: index, arg: 2); |
179 | as->passFunctionAsArg(arg: 1); |
180 | as->passEngineAsArg(arg: 0); |
181 | BASELINEJIT_GENERATE_RUNTIME_CALL(LoadGlobalLookup, CallResultDestination::InAccumulator); |
182 | } |
183 | |
184 | void BaselineJIT::generate_LoadQmlContextPropertyLookup(int index) |
185 | { |
186 | STORE_IP(); |
187 | as->prepareCallWithArgCount(argc: 2); |
188 | as->passInt32AsArg(value: index, arg: 1); |
189 | as->passEngineAsArg(arg: 0); |
190 | BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlContextPropertyLookup, CallResultDestination::InAccumulator); |
191 | } |
192 | |
193 | void BaselineJIT::generate_StoreNameSloppy(int name) |
194 | { |
195 | STORE_IP(); |
196 | STORE_ACC(); |
197 | as->prepareCallWithArgCount(argc: 3); |
198 | as->passAccumulatorAsArg(arg: 2); |
199 | as->passInt32AsArg(value: name, arg: 1); |
200 | as->passEngineAsArg(arg: 0); |
201 | BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameSloppy, CallResultDestination::Ignore); |
202 | LOAD_ACC(); |
203 | } |
204 | |
205 | void BaselineJIT::generate_StoreNameStrict(int name) |
206 | { |
207 | STORE_IP(); |
208 | STORE_ACC(); |
209 | as->prepareCallWithArgCount(argc: 3); |
210 | as->passAccumulatorAsArg(arg: 2); |
211 | as->passInt32AsArg(value: name, arg: 1); |
212 | as->passEngineAsArg(arg: 0); |
213 | BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameStrict, CallResultDestination::Ignore); |
214 | LOAD_ACC(); |
215 | } |
216 | |
217 | void BaselineJIT::generate_LoadElement(int base) |
218 | { |
219 | STORE_IP(); |
220 | STORE_ACC(); |
221 | as->prepareCallWithArgCount(argc: 3); |
222 | as->passAccumulatorAsArg(arg: 2); |
223 | as->passJSSlotAsArg(reg: base, arg: 1); |
224 | as->passEngineAsArg(arg: 0); |
225 | BASELINEJIT_GENERATE_RUNTIME_CALL(LoadElement, CallResultDestination::InAccumulator); |
226 | } |
227 | |
228 | void BaselineJIT::generate_StoreElement(int base, int index) |
229 | { |
230 | STORE_IP(); |
231 | STORE_ACC(); |
232 | as->prepareCallWithArgCount(argc: 4); |
233 | as->passAccumulatorAsArg(arg: 3); |
234 | as->passJSSlotAsArg(reg: index, arg: 2); |
235 | as->passJSSlotAsArg(reg: base, arg: 1); |
236 | as->passEngineAsArg(arg: 0); |
237 | BASELINEJIT_GENERATE_RUNTIME_CALL(StoreElement, CallResultDestination::Ignore); |
238 | LOAD_ACC(); |
239 | } |
240 | |
241 | void BaselineJIT::generate_LoadProperty(int name) |
242 | { |
243 | STORE_IP(); |
244 | STORE_ACC(); |
245 | as->prepareCallWithArgCount(argc: 3); |
246 | as->passInt32AsArg(value: name, arg: 2); |
247 | as->passAccumulatorAsArg(arg: 1); |
248 | as->passEngineAsArg(arg: 0); |
249 | BASELINEJIT_GENERATE_RUNTIME_CALL(LoadProperty, CallResultDestination::InAccumulator); |
250 | } |
251 | |
252 | void BaselineJIT::generate_LoadOptionalProperty(int name, int offset) |
253 | { |
254 | labels.insert(value: as->jumpEqNull(offset: absoluteOffset(relativeOffset: offset))); |
255 | |
256 | generate_LoadProperty(name); |
257 | } |
258 | |
259 | void BaselineJIT::generate_GetLookup(int index) |
260 | { |
261 | STORE_IP(); |
262 | STORE_ACC(); |
263 | as->prepareCallWithArgCount(argc: 4); |
264 | as->passInt32AsArg(value: index, arg: 3); |
265 | as->passAccumulatorAsArg(arg: 2); |
266 | as->passFunctionAsArg(arg: 1); |
267 | as->passEngineAsArg(arg: 0); |
268 | BASELINEJIT_GENERATE_RUNTIME_CALL(GetLookup, CallResultDestination::InAccumulator); |
269 | } |
270 | |
271 | void BaselineJIT::generate_GetOptionalLookup(int index, int offset) |
272 | { |
273 | labels.insert(value: as->jumpEqNull(offset: absoluteOffset(relativeOffset: offset))); |
274 | |
275 | generate_GetLookup(index); |
276 | } |
277 | |
278 | void BaselineJIT::generate_StoreProperty(int name, int base) |
279 | { |
280 | STORE_IP(); |
281 | STORE_ACC(); |
282 | as->prepareCallWithArgCount(argc: 4); |
283 | as->passAccumulatorAsArg(arg: 3); |
284 | as->passInt32AsArg(value: name, arg: 2); |
285 | as->passJSSlotAsArg(reg: base, arg: 1); |
286 | as->passEngineAsArg(arg: 0); |
287 | BASELINEJIT_GENERATE_RUNTIME_CALL(StoreProperty, CallResultDestination::Ignore); |
288 | LOAD_ACC(); |
289 | } |
290 | |
291 | void BaselineJIT::generate_SetLookup(int index, int base) |
292 | { |
293 | STORE_IP(); |
294 | STORE_ACC(); |
295 | as->prepareCallWithArgCount(argc: 4); |
296 | as->passAccumulatorAsArg(arg: 3); |
297 | as->passInt32AsArg(value: index, arg: 2); |
298 | as->passJSSlotAsArg(reg: base, arg: 1); |
299 | as->passFunctionAsArg(arg: 0); |
300 | if (function->isStrict()) |
301 | BASELINEJIT_GENERATE_RUNTIME_CALL(SetLookupStrict, CallResultDestination::InAccumulator) |
302 | else |
303 | BASELINEJIT_GENERATE_RUNTIME_CALL(SetLookupSloppy, CallResultDestination::InAccumulator) |
304 | } |
305 | |
306 | void BaselineJIT::generate_LoadSuperProperty(int property) |
307 | { |
308 | STORE_IP(); |
309 | as->prepareCallWithArgCount(argc: 2); |
310 | as->passJSSlotAsArg(reg: property, arg: 1); |
311 | as->passEngineAsArg(arg: 0); |
312 | BASELINEJIT_GENERATE_RUNTIME_CALL(LoadSuperProperty, CallResultDestination::InAccumulator); |
313 | } |
314 | |
315 | void BaselineJIT::generate_StoreSuperProperty(int property) |
316 | { |
317 | STORE_IP(); |
318 | STORE_ACC(); |
319 | as->prepareCallWithArgCount(argc: 3); |
320 | as->passAccumulatorAsArg(arg: 2); |
321 | as->passJSSlotAsArg(reg: property, arg: 1); |
322 | as->passEngineAsArg(arg: 0); |
323 | BASELINEJIT_GENERATE_RUNTIME_CALL(StoreSuperProperty, CallResultDestination::Ignore); |
324 | LOAD_ACC(); |
325 | } |
326 | |
327 | void BaselineJIT::generate_Yield() |
328 | { |
329 | // ##### |
330 | Q_UNREACHABLE(); |
331 | } |
332 | |
333 | void BaselineJIT::generate_YieldStar() |
334 | { |
335 | // ##### |
336 | Q_UNREACHABLE(); |
337 | } |
338 | |
339 | void BaselineJIT::generate_Resume(int) |
340 | { |
341 | // ##### |
342 | Q_UNREACHABLE(); |
343 | } |
344 | |
345 | void BaselineJIT::generate_CallValue(int name, int argc, int argv) |
346 | { |
347 | STORE_IP(); |
348 | as->prepareCallWithArgCount(argc: 4); |
349 | as->passInt32AsArg(value: argc, arg: 3); |
350 | as->passJSSlotAsArg(reg: argv, arg: 2); |
351 | as->passJSSlotAsArg(reg: name, arg: 1); |
352 | as->passEngineAsArg(arg: 0); |
353 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallValue, CallResultDestination::InAccumulator); |
354 | } |
355 | |
356 | void BaselineJIT::generate_CallWithReceiver(int name, int thisObject, int argc, int argv) |
357 | { |
358 | STORE_IP(); |
359 | as->prepareCallWithArgCount(argc: 5); |
360 | as->passInt32AsArg(value: argc, arg: 4); |
361 | as->passJSSlotAsArg(reg: argv, arg: 3); |
362 | as->passJSSlotAsArg(reg: thisObject, arg: 2); |
363 | as->passJSSlotAsArg(reg: name, arg: 1); |
364 | as->passEngineAsArg(arg: 0); |
365 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallWithReceiver, CallResultDestination::InAccumulator); |
366 | } |
367 | |
368 | void BaselineJIT::generate_CallProperty(int name, int base, int argc, int argv) |
369 | { |
370 | STORE_IP(); |
371 | as->prepareCallWithArgCount(argc: 5); |
372 | as->passInt32AsArg(value: argc, arg: 4); |
373 | as->passJSSlotAsArg(reg: argv, arg: 3); |
374 | as->passInt32AsArg(value: name, arg: 2); |
375 | as->passJSSlotAsArg(reg: base, arg: 1); |
376 | as->passEngineAsArg(arg: 0); |
377 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallProperty, CallResultDestination::InAccumulator); |
378 | } |
379 | |
380 | void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) |
381 | { |
382 | STORE_IP(); |
383 | as->prepareCallWithArgCount(argc: 5); |
384 | as->passInt32AsArg(value: argc, arg: 4); |
385 | as->passJSSlotAsArg(reg: argv, arg: 3); |
386 | as->passInt32AsArg(value: lookupIndex, arg: 2); |
387 | as->passJSSlotAsArg(reg: base, arg: 1); |
388 | as->passEngineAsArg(arg: 0); |
389 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallPropertyLookup, CallResultDestination::InAccumulator); |
390 | } |
391 | |
392 | void BaselineJIT::generate_CallName(int name, int argc, int argv) |
393 | { |
394 | STORE_IP(); |
395 | as->prepareCallWithArgCount(argc: 4); |
396 | as->passInt32AsArg(value: argc, arg: 3); |
397 | as->passJSSlotAsArg(reg: argv, arg: 2); |
398 | as->passInt32AsArg(value: name, arg: 1); |
399 | as->passEngineAsArg(arg: 0); |
400 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallName, CallResultDestination::InAccumulator); |
401 | } |
402 | |
403 | void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv) |
404 | { |
405 | STORE_IP(); |
406 | as->prepareCallWithArgCount(argc: 3); |
407 | as->passInt32AsArg(value: argc, arg: 2); |
408 | as->passJSSlotAsArg(reg: argv, arg: 1); |
409 | as->passEngineAsArg(arg: 0); |
410 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallPossiblyDirectEval, CallResultDestination::InAccumulator); |
411 | } |
412 | |
413 | void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv) |
414 | { |
415 | STORE_IP(); |
416 | as->prepareCallWithArgCount(argc: 4); |
417 | as->passInt32AsArg(value: argc, arg: 3); |
418 | as->passJSSlotAsArg(reg: argv, arg: 2); |
419 | as->passInt32AsArg(value: index, arg: 1); |
420 | as->passEngineAsArg(arg: 0); |
421 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallGlobalLookup, CallResultDestination::InAccumulator); |
422 | } |
423 | |
424 | void BaselineJIT::generate_CallQmlContextPropertyLookup(int index, int argc, int argv) |
425 | { |
426 | STORE_IP(); |
427 | as->prepareCallWithArgCount(argc: 4); |
428 | as->passInt32AsArg(value: argc, arg: 3); |
429 | as->passJSSlotAsArg(reg: argv, arg: 2); |
430 | as->passInt32AsArg(value: index, arg: 1); |
431 | as->passEngineAsArg(arg: 0); |
432 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallQmlContextPropertyLookup, CallResultDestination::InAccumulator); |
433 | } |
434 | |
435 | void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, int argv) |
436 | { |
437 | STORE_IP(); |
438 | as->prepareCallWithArgCount(argc: 5); |
439 | as->passInt32AsArg(value: argc, arg: 4); |
440 | as->passJSSlotAsArg(reg: argv, arg: 3); |
441 | as->passJSSlotAsArg(reg: thisObject, arg: 2); |
442 | as->passJSSlotAsArg(reg: func, arg: 1); |
443 | as->passEngineAsArg(arg: 0); |
444 | BASELINEJIT_GENERATE_RUNTIME_CALL(CallWithSpread, CallResultDestination::InAccumulator); |
445 | } |
446 | |
447 | void BaselineJIT::generate_TailCall(int func, int thisObject, int argc, int argv) |
448 | { |
449 | STORE_IP(); |
450 | as->jsTailCall(func, thisObject, argc, argv); |
451 | } |
452 | |
453 | void BaselineJIT::generate_Construct(int func, int argc, int argv) |
454 | { |
455 | STORE_IP(); |
456 | STORE_ACC(); |
457 | as->prepareCallWithArgCount(argc: 5); |
458 | as->passInt32AsArg(value: argc, arg: 4); |
459 | as->passJSSlotAsArg(reg: argv, arg: 3); |
460 | as->passAccumulatorAsArg(arg: 2); |
461 | as->passJSSlotAsArg(reg: func, arg: 1); |
462 | as->passEngineAsArg(arg: 0); |
463 | BASELINEJIT_GENERATE_RUNTIME_CALL(Construct, CallResultDestination::InAccumulator); |
464 | } |
465 | |
466 | void BaselineJIT::generate_ConstructWithSpread(int func, int argc, int argv) |
467 | { |
468 | STORE_IP(); |
469 | STORE_ACC(); |
470 | as->prepareCallWithArgCount(argc: 5); |
471 | as->passInt32AsArg(value: argc, arg: 4); |
472 | as->passJSSlotAsArg(reg: argv, arg: 3); |
473 | as->passAccumulatorAsArg(arg: 2); |
474 | as->passJSSlotAsArg(reg: func, arg: 1); |
475 | as->passEngineAsArg(arg: 0); |
476 | BASELINEJIT_GENERATE_RUNTIME_CALL(ConstructWithSpread, CallResultDestination::InAccumulator); |
477 | } |
478 | |
479 | void BaselineJIT::generate_SetUnwindHandler(int offset) |
480 | { |
481 | if (offset) |
482 | labels.insert(value: as->setUnwindHandler(absoluteOffset(relativeOffset: offset))); |
483 | else |
484 | as->clearUnwindHandler(); |
485 | } |
486 | |
487 | void BaselineJIT::generate_UnwindDispatch() |
488 | { |
489 | as->unwindDispatch(); |
490 | } |
491 | |
492 | void BaselineJIT::generate_UnwindToLabel(int level, int offset) |
493 | { |
494 | labels.insert(value: as->unwindToLabel(level, offset: absoluteOffset(relativeOffset: offset))); |
495 | } |
496 | |
497 | void BaselineJIT::generate_DeadTemporalZoneCheck(int name) |
498 | { |
499 | as->deadTemporalZoneCheck(offsetForSavedIP: nextInstructionOffset(), variableName: name); |
500 | } |
501 | |
502 | void BaselineJIT::generate_ThrowException() |
503 | { |
504 | STORE_IP(); |
505 | STORE_ACC(); |
506 | as->prepareCallWithArgCount(argc: 2); |
507 | as->passAccumulatorAsArg(arg: 1); |
508 | as->passEngineAsArg(arg: 0); |
509 | BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowException, CallResultDestination::Ignore); |
510 | as->gotoCatchException(); |
511 | |
512 | // LOAD_ACC(); <- not needed here since it would be unreachable. |
513 | } |
514 | |
515 | void BaselineJIT::generate_GetException() { as->getException(); } |
516 | void BaselineJIT::generate_SetException() { as->setException(); } |
517 | |
518 | void BaselineJIT::generate_CreateCallContext() |
519 | { |
520 | STORE_ACC(); |
521 | as->prepareCallWithArgCount(argc: 1); |
522 | as->passCppFrameAsArg(arg: 0); |
523 | BASELINEJIT_GENERATE_RUNTIME_CALL(PushCallContext, CallResultDestination::Ignore); |
524 | LOAD_ACC(); |
525 | } |
526 | |
527 | void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); } |
528 | |
529 | void BaselineJIT::generate_PushWithContext() |
530 | { |
531 | STORE_IP(); |
532 | as->saveAccumulatorInFrame(); |
533 | as->prepareCallWithArgCount(argc: 2); |
534 | as->passJSSlotAsArg(reg: CallData::Accumulator, arg: 1); |
535 | as->passEngineAsArg(arg: 0); |
536 | BASELINEJIT_GENERATE_RUNTIME_CALL(PushWithContext, CallResultDestination::InAccumulator); |
537 | } |
538 | |
539 | void BaselineJIT::generate_PushBlockContext(int index) |
540 | { |
541 | as->saveAccumulatorInFrame(); |
542 | as->prepareCallWithArgCount(argc: 2); |
543 | as->passInt32AsArg(value: index, arg: 1); |
544 | as->passEngineAsArg(arg: 0); |
545 | BASELINEJIT_GENERATE_RUNTIME_CALL(PushBlockContext, CallResultDestination::Ignore); |
546 | as->loadAccumulatorFromFrame(); |
547 | } |
548 | |
549 | void BaselineJIT::generate_CloneBlockContext() |
550 | { |
551 | as->saveAccumulatorInFrame(); |
552 | as->prepareCallWithArgCount(argc: 1); |
553 | as->passEngineAsArg(arg: 0); |
554 | BASELINEJIT_GENERATE_RUNTIME_CALL(CloneBlockContext, CallResultDestination::Ignore); |
555 | as->loadAccumulatorFromFrame(); |
556 | } |
557 | |
558 | void BaselineJIT::generate_PushScriptContext(int index) |
559 | { |
560 | as->saveAccumulatorInFrame(); |
561 | as->prepareCallWithArgCount(argc: 2); |
562 | as->passInt32AsArg(value: index, arg: 1); |
563 | as->passEngineAsArg(arg: 0); |
564 | BASELINEJIT_GENERATE_RUNTIME_CALL(PushScriptContext, CallResultDestination::Ignore); |
565 | as->loadAccumulatorFromFrame(); |
566 | } |
567 | |
568 | void BaselineJIT::generate_PopScriptContext() |
569 | { |
570 | as->saveAccumulatorInFrame(); |
571 | as->prepareCallWithArgCount(argc: 1); |
572 | as->passEngineAsArg(arg: 0); |
573 | BASELINEJIT_GENERATE_RUNTIME_CALL(PopScriptContext, CallResultDestination::Ignore); |
574 | as->loadAccumulatorFromFrame(); |
575 | } |
576 | |
577 | void BaselineJIT::generate_PopContext() { as->popContext(); } |
578 | |
579 | void BaselineJIT::generate_GetIterator(int iterator) |
580 | { |
581 | as->saveAccumulatorInFrame(); |
582 | as->prepareCallWithArgCount(argc: 3); |
583 | as->passInt32AsArg(value: iterator, arg: 2); |
584 | as->passAccumulatorAsArg(arg: 1); |
585 | as->passEngineAsArg(arg: 0); |
586 | BASELINEJIT_GENERATE_RUNTIME_CALL(GetIterator, CallResultDestination::InAccumulator); |
587 | } |
588 | |
589 | void BaselineJIT::generate_IteratorNext(int value, int done) |
590 | { |
591 | as->saveAccumulatorInFrame(); |
592 | as->prepareCallWithArgCount(argc: 3); |
593 | as->passJSSlotAsArg(reg: value, arg: 2); |
594 | as->passAccumulatorAsArg(arg: 1); |
595 | as->passEngineAsArg(arg: 0); |
596 | BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorNext, CallResultDestination::InAccumulator); |
597 | as->storeReg(reg: done); |
598 | } |
599 | |
600 | void BaselineJIT::generate_IteratorNextForYieldStar(int iterator, int object) |
601 | { |
602 | as->saveAccumulatorInFrame(); |
603 | as->prepareCallWithArgCount(argc: 4); |
604 | as->passJSSlotAsArg(reg: object, arg: 3); |
605 | as->passJSSlotAsArg(reg: iterator, arg: 2); |
606 | as->passAccumulatorAsArg(arg: 1); |
607 | as->passEngineAsArg(arg: 0); |
608 | BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorNextForYieldStar, CallResultDestination::InAccumulator); |
609 | } |
610 | |
611 | void BaselineJIT::generate_IteratorClose(int done) |
612 | { |
613 | as->saveAccumulatorInFrame(); |
614 | as->prepareCallWithArgCount(argc: 3); |
615 | as->passJSSlotAsArg(reg: done, arg: 2); |
616 | as->passAccumulatorAsArg(arg: 1); |
617 | as->passEngineAsArg(arg: 0); |
618 | BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorClose, CallResultDestination::InAccumulator); |
619 | } |
620 | |
621 | void BaselineJIT::generate_DestructureRestElement() |
622 | { |
623 | as->saveAccumulatorInFrame(); |
624 | as->prepareCallWithArgCount(argc: 2); |
625 | as->passAccumulatorAsArg(arg: 1); |
626 | as->passEngineAsArg(arg: 0); |
627 | BASELINEJIT_GENERATE_RUNTIME_CALL(DestructureRestElement, CallResultDestination::InAccumulator); |
628 | } |
629 | |
630 | void BaselineJIT::generate_DeleteProperty(int base, int index) |
631 | { |
632 | STORE_IP(); |
633 | as->prepareCallWithArgCount(argc: 4); |
634 | as->passJSSlotAsArg(reg: index, arg: 3); |
635 | as->passJSSlotAsArg(reg: base, arg: 2); |
636 | as->passFunctionAsArg(arg: 1); |
637 | as->passEngineAsArg(arg: 0); |
638 | BASELINEJIT_GENERATE_RUNTIME_CALL(DeleteProperty, CallResultDestination::InAccumulator); |
639 | } |
640 | |
641 | void BaselineJIT::generate_DeleteName(int name) |
642 | { |
643 | STORE_IP(); |
644 | as->prepareCallWithArgCount(argc: 3); |
645 | as->passInt32AsArg(value: name, arg: 2); |
646 | as->passFunctionAsArg(arg: 1); |
647 | as->passEngineAsArg(arg: 0); |
648 | BASELINEJIT_GENERATE_RUNTIME_CALL(DeleteName, CallResultDestination::InAccumulator); |
649 | } |
650 | |
651 | void BaselineJIT::generate_TypeofName(int name) |
652 | { |
653 | as->prepareCallWithArgCount(argc: 2); |
654 | as->passInt32AsArg(value: name, arg: 1); |
655 | as->passEngineAsArg(arg: 0); |
656 | BASELINEJIT_GENERATE_RUNTIME_CALL(TypeofName, CallResultDestination::InAccumulator); |
657 | } |
658 | |
659 | void BaselineJIT::generate_TypeofValue() |
660 | { |
661 | STORE_ACC(); |
662 | as->prepareCallWithArgCount(argc: 2); |
663 | as->passAccumulatorAsArg(arg: 1); |
664 | as->passEngineAsArg(arg: 0); |
665 | BASELINEJIT_GENERATE_RUNTIME_CALL(TypeofValue, CallResultDestination::InAccumulator); |
666 | } |
667 | |
668 | void BaselineJIT::generate_DeclareVar(int varName, int isDeletable) |
669 | { |
670 | STORE_ACC(); |
671 | as->prepareCallWithArgCount(argc: 3); |
672 | as->passInt32AsArg(value: varName, arg: 2); |
673 | as->passInt32AsArg(value: isDeletable, arg: 1); |
674 | as->passEngineAsArg(arg: 0); |
675 | BASELINEJIT_GENERATE_RUNTIME_CALL(DeclareVar, CallResultDestination::Ignore); |
676 | LOAD_ACC(); |
677 | } |
678 | |
679 | void BaselineJIT::generate_DefineArray(int argc, int args) |
680 | { |
681 | as->prepareCallWithArgCount(argc: 3); |
682 | as->passInt32AsArg(value: argc, arg: 2); |
683 | as->passJSSlotAsArg(reg: args, arg: 1); |
684 | as->passEngineAsArg(arg: 0); |
685 | BASELINEJIT_GENERATE_RUNTIME_CALL(ArrayLiteral, CallResultDestination::InAccumulator); |
686 | } |
687 | |
688 | void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int argc, int args) |
689 | { |
690 | as->prepareCallWithArgCount(argc: 4); |
691 | as->passInt32AsArg(value: argc, arg: 3); |
692 | as->passJSSlotAsArg(reg: args, arg: 2); |
693 | as->passInt32AsArg(value: internalClassId, arg: 1); |
694 | as->passEngineAsArg(arg: 0); |
695 | BASELINEJIT_GENERATE_RUNTIME_CALL(ObjectLiteral, CallResultDestination::InAccumulator); |
696 | } |
697 | |
698 | void BaselineJIT::generate_CreateClass(int classIndex, int heritage, int computedNames) |
699 | { |
700 | as->prepareCallWithArgCount(argc: 4); |
701 | as->passJSSlotAsArg(reg: computedNames, arg: 3); |
702 | as->passJSSlotAsArg(reg: heritage, arg: 2); |
703 | as->passInt32AsArg(value: classIndex, arg: 1); |
704 | as->passEngineAsArg(arg: 0); |
705 | BASELINEJIT_GENERATE_RUNTIME_CALL(CreateClass, CallResultDestination::InAccumulator); |
706 | } |
707 | |
708 | void BaselineJIT::generate_CreateMappedArgumentsObject() |
709 | { |
710 | as->prepareCallWithArgCount(argc: 1); |
711 | as->passEngineAsArg(arg: 0); |
712 | BASELINEJIT_GENERATE_RUNTIME_CALL(CreateMappedArgumentsObject, |
713 | CallResultDestination::InAccumulator); |
714 | } |
715 | |
716 | void BaselineJIT::generate_CreateUnmappedArgumentsObject() |
717 | { |
718 | as->prepareCallWithArgCount(argc: 1); |
719 | as->passEngineAsArg(arg: 0); |
720 | BASELINEJIT_GENERATE_RUNTIME_CALL(CreateUnmappedArgumentsObject, |
721 | CallResultDestination::InAccumulator); |
722 | } |
723 | |
724 | void BaselineJIT::generate_CreateRestParameter(int argIndex) |
725 | { |
726 | as->prepareCallWithArgCount(argc: 2); |
727 | as->passInt32AsArg(value: argIndex, arg: 1); |
728 | as->passEngineAsArg(arg: 0); |
729 | BASELINEJIT_GENERATE_RUNTIME_CALL(CreateRestParameter, CallResultDestination::InAccumulator); |
730 | } |
731 | |
732 | void BaselineJIT::generate_ConvertThisToObject() |
733 | { |
734 | STORE_ACC(); |
735 | as->prepareCallWithArgCount(argc: 2); |
736 | as->passJSSlotAsArg(reg: CallData::This, arg: 1); |
737 | as->passEngineAsArg(arg: 0); |
738 | BASELINEJIT_GENERATE_RUNTIME_CALL(ConvertThisToObject, CallResultDestination::InAccumulator); |
739 | as->storeReg(reg: CallData::This); |
740 | LOAD_ACC(); |
741 | } |
742 | |
743 | void BaselineJIT::generate_LoadSuperConstructor() |
744 | { |
745 | as->prepareCallWithArgCount(argc: 2); |
746 | as->passJSSlotAsArg(reg: CallData::Function, arg: 1); |
747 | as->passEngineAsArg(arg: 0); |
748 | BASELINEJIT_GENERATE_RUNTIME_CALL(LoadSuperConstructor, CallResultDestination::InAccumulator); |
749 | } |
750 | |
751 | void BaselineJIT::generate_ToObject() |
752 | { |
753 | STORE_ACC(); |
754 | as->prepareCallWithArgCount(argc: 2); |
755 | as->passAccumulatorAsArg(arg: 1); |
756 | as->passEngineAsArg(arg: 0); |
757 | BASELINEJIT_GENERATE_RUNTIME_CALL(ToObject, CallResultDestination::InAccumulator); |
758 | |
759 | } |
760 | |
761 | void BaselineJIT::generate_Jump(int offset) |
762 | { |
763 | labels.insert(value: as->jump(offset: absoluteOffset(relativeOffset: offset))); |
764 | } |
765 | |
766 | void BaselineJIT::generate_JumpTrue(int offset) |
767 | { |
768 | labels.insert(value: as->jumpTrue(offset: absoluteOffset(relativeOffset: offset))); |
769 | } |
770 | |
771 | void BaselineJIT::generate_JumpFalse(int offset) |
772 | { |
773 | labels.insert(value: as->jumpFalse(offset: absoluteOffset(relativeOffset: offset))); |
774 | } |
775 | |
776 | void BaselineJIT::generate_JumpNoException(int offset) |
777 | { |
778 | labels.insert(value: as->jumpNoException(offset: absoluteOffset(relativeOffset: offset))); |
779 | } |
780 | |
781 | void BaselineJIT::generate_JumpNotUndefined(int offset) |
782 | { |
783 | labels.insert(value: as->jumpNotUndefined(offset: absoluteOffset(relativeOffset: offset))); |
784 | } |
785 | |
786 | void BaselineJIT::generate_CheckException() |
787 | { |
788 | as->checkException(); |
789 | } |
790 | |
791 | void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); } |
792 | void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); } |
793 | void BaselineJIT::generate_CmpEqInt(int lhs) { as->cmpeqInt(lhs); } |
794 | void BaselineJIT::generate_CmpNeInt(int lhs) { as->cmpneInt(lhs); } |
795 | void BaselineJIT::generate_CmpEq(int lhs) { as->cmpeq(lhs); } |
796 | void BaselineJIT::generate_CmpNe(int lhs) { as->cmpne(lhs); } |
797 | void BaselineJIT::generate_CmpGt(int lhs) { as->cmpgt(lhs); } |
798 | void BaselineJIT::generate_CmpGe(int lhs) { as->cmpge(lhs); } |
799 | void BaselineJIT::generate_CmpLt(int lhs) { as->cmplt(lhs); } |
800 | void BaselineJIT::generate_CmpLe(int lhs) { as->cmple(lhs); } |
801 | void BaselineJIT::generate_CmpStrictEqual(int lhs) { as->cmpStrictEqual(lhs); } |
802 | void BaselineJIT::generate_CmpStrictNotEqual(int lhs) { as->cmpStrictNotEqual(lhs); } |
803 | |
804 | void BaselineJIT::generate_CmpIn(int lhs) |
805 | { |
806 | STORE_IP(); |
807 | STORE_ACC(); |
808 | as->prepareCallWithArgCount(argc: 3); |
809 | as->passAccumulatorAsArg(arg: 2); |
810 | as->passJSSlotAsArg(reg: lhs, arg: 1); |
811 | as->passEngineAsArg(arg: 0); |
812 | BASELINEJIT_GENERATE_RUNTIME_CALL(In, CallResultDestination::InAccumulator); |
813 | } |
814 | |
815 | void BaselineJIT::generate_CmpInstanceOf(int lhs) |
816 | { |
817 | STORE_ACC(); |
818 | as->prepareCallWithArgCount(argc: 3); |
819 | as->passAccumulatorAsArg(arg: 2); |
820 | as->passJSSlotAsArg(reg: lhs, arg: 1); |
821 | as->passEngineAsArg(arg: 0); |
822 | BASELINEJIT_GENERATE_RUNTIME_CALL(Instanceof, CallResultDestination::InAccumulator); |
823 | } |
824 | |
825 | void BaselineJIT::generate_As(int lhs) |
826 | { |
827 | STORE_ACC(); |
828 | as->prepareCallWithArgCount(argc: 3); |
829 | as->passAccumulatorAsArg(arg: 2); |
830 | as->passJSSlotAsArg(reg: lhs, arg: 1); |
831 | as->passEngineAsArg(arg: 0); |
832 | BASELINEJIT_GENERATE_RUNTIME_CALL(As, CallResultDestination::InAccumulator); |
833 | } |
834 | |
835 | void BaselineJIT::generate_UNot() { as->unot(); } |
836 | void BaselineJIT::generate_UPlus() { as->toNumber(); } |
837 | void BaselineJIT::generate_UMinus() { as->uminus(); } |
838 | void BaselineJIT::generate_UCompl() { as->ucompl(); } |
839 | void BaselineJIT::generate_Increment() { as->inc(); } |
840 | void BaselineJIT::generate_Decrement() { as->dec(); } |
841 | void BaselineJIT::generate_Add(int lhs) { as->add(lhs); } |
842 | |
843 | void BaselineJIT::generate_BitAnd(int lhs) { as->bitAnd(lhs); } |
844 | void BaselineJIT::generate_BitOr(int lhs) { as->bitOr(lhs); } |
845 | void BaselineJIT::generate_BitXor(int lhs) { as->bitXor(lhs); } |
846 | void BaselineJIT::generate_UShr(int lhs) { as->ushr(lhs); } |
847 | void BaselineJIT::generate_Shr(int lhs) { as->shr(lhs); } |
848 | void BaselineJIT::generate_Shl(int lhs) { as->shl(lhs); } |
849 | |
850 | void BaselineJIT::generate_BitAndConst(int rhs) { as->bitAndConst(rhs); } |
851 | void BaselineJIT::generate_BitOrConst(int rhs) { as->bitOrConst(rhs); } |
852 | void BaselineJIT::generate_BitXorConst(int rhs) { as->bitXorConst(rhs); } |
853 | void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); } |
854 | void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); } |
855 | void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); } |
856 | |
857 | void BaselineJIT::generate_Exp(int lhs) { |
858 | STORE_IP(); |
859 | STORE_ACC(); |
860 | as->prepareCallWithArgCount(argc: 2); |
861 | as->passAccumulatorAsArg(arg: 1); |
862 | as->passJSSlotAsArg(reg: lhs, arg: 0); |
863 | BASELINEJIT_GENERATE_RUNTIME_CALL(Exp, CallResultDestination::InAccumulator); |
864 | } |
865 | void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); } |
866 | void BaselineJIT::generate_Div(int lhs) { as->div(lhs); } |
867 | void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); } |
868 | void BaselineJIT::generate_Sub(int lhs) { as->sub(lhs); } |
869 | |
870 | //void BaselineJIT::generate_BinopContext(int alu, int lhs) |
871 | //{ |
872 | // auto engine = function->internalClass->engine; |
873 | // void *op = engine->runtime.runtimeMethods[alu]; |
874 | // STORE_ACC(); |
875 | // as->passAccumulatorAsArg(2); |
876 | // as->passRegAsArg(lhs, 1); |
877 | // as->passEngineAsArg(0); |
878 | // as->callRuntime("binopContext", op, CallResultDestination::InAccumulator); |
879 | // as->checkException(); |
880 | //} |
881 | |
882 | void BaselineJIT::generate_InitializeBlockDeadTemporalZone(int firstReg, int count) |
883 | { |
884 | as->loadValue(value: Value::emptyValue().rawValue()); |
885 | for (int i = firstReg, end = firstReg + count; i < end; ++i) |
886 | as->storeReg(reg: i); |
887 | } |
888 | |
889 | void BaselineJIT::generate_ThrowOnNullOrUndefined() |
890 | { |
891 | STORE_ACC(); |
892 | as->prepareCallWithArgCount(argc: 2); |
893 | as->passAccumulatorAsArg(arg: 1); |
894 | as->passEngineAsArg(arg: 0); |
895 | BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowOnNullOrUndefined, CallResultDestination::Ignore); |
896 | LOAD_ACC(); |
897 | } |
898 | |
899 | void BaselineJIT::generate_GetTemplateObject(int index) |
900 | { |
901 | as->prepareCallWithArgCount(argc: 2); |
902 | as->passInt32AsArg(value: index, arg: 1); |
903 | as->passFunctionAsArg(arg: 0); |
904 | BASELINEJIT_GENERATE_RUNTIME_CALL(GetTemplateObject, CallResultDestination::InAccumulator); |
905 | } |
906 | |
907 | ByteCodeHandler::Verdict BaselineJIT::startInstruction(Instr::Type /*instr*/) |
908 | { |
909 | if (labels.contains(value: currentInstructionOffset())) |
910 | as->addLabel(offset: currentInstructionOffset()); |
911 | return ProcessInstruction; |
912 | } |
913 | |
914 | void BaselineJIT::endInstruction(Instr::Type instr) |
915 | { |
916 | Q_UNUSED(instr); |
917 | } |
918 | |
919 | #endif // QT_CONFIG(qml_jit) |
920 | |
921 | |