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
11QT_USE_NAMESPACE
12using namespace QV4;
13using namespace QV4::JIT;
14using namespace QV4::Moth;
15
16BaselineJIT::BaselineJIT(Function *function)
17 : function(function)
18 , as(new BaselineAssembler(&(function->compilationUnit->constants->asValue<Value>())))
19{}
20
21BaselineJIT::~BaselineJIT()
22{}
23
24void 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
52void BaselineJIT::generate_Ret()
53{
54 as->ret();
55}
56
57void BaselineJIT::generate_Debug() { Q_UNREACHABLE(); }
58
59void BaselineJIT::generate_LoadConst(int index)
60{
61 as->loadConst(constIndex: index);
62}
63
64void BaselineJIT::generate_LoadZero()
65{
66 as->loadValue(value: Encode(int(0)));
67}
68
69void BaselineJIT::generate_LoadTrue()
70{
71 as->loadValue(value: Encode(true));
72}
73
74void BaselineJIT::generate_LoadFalse()
75{
76 as->loadValue(value: Encode(false));
77}
78
79void BaselineJIT::generate_LoadNull()
80{
81 as->loadValue(value: Encode::null());
82}
83
84void BaselineJIT::generate_LoadUndefined()
85{
86 as->loadValue(value: Encode::undefined());
87}
88
89void BaselineJIT::generate_LoadInt(int value)
90{
91 //###
92 as->loadValue(value: Encode(value));
93}
94
95void BaselineJIT::generate_MoveConst(int constIndex, int destTemp)
96{
97 as->copyConst(constIndex, destReg: destTemp);
98}
99
100void BaselineJIT::generate_LoadReg(int reg)
101{
102 as->loadReg(reg);
103}
104
105void BaselineJIT::generate_StoreReg(int reg)
106{
107 as->storeReg(reg);
108}
109
110void BaselineJIT::generate_MoveReg(int srcReg, int destReg)
111{
112 // Don't clobber the accumulator.
113 as->moveReg(sourceReg: srcReg, destReg);
114}
115
116void BaselineJIT::generate_LoadImport(int index)
117{
118 as->loadImport(index);
119}
120
121void BaselineJIT::generate_LoadLocal(int index)
122{
123 as->loadLocal(index);
124}
125
126void BaselineJIT::generate_StoreLocal(int index)
127{
128 as->checkException();
129 as->storeLocal(index);
130}
131
132void BaselineJIT::generate_LoadScopedLocal(int scope, int index)
133{
134 as->loadLocal(index, level: scope);
135}
136
137void BaselineJIT::generate_StoreScopedLocal(int scope, int index)
138{
139 as->checkException();
140 as->storeLocal(index, level: scope);
141}
142
143void BaselineJIT::generate_LoadRuntimeString(int stringId)
144{
145 as->loadString(stringId);
146}
147
148void 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
157void 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
165void 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
174void 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
184void 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
193void 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
205void 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
217void 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
228void 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
241void 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
252void 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
259void 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
271void 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
278void 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
291void 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
306void 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
315void 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
327void BaselineJIT::generate_Yield()
328{
329 // #####
330 Q_UNREACHABLE();
331}
332
333void BaselineJIT::generate_YieldStar()
334{
335 // #####
336 Q_UNREACHABLE();
337}
338
339void BaselineJIT::generate_Resume(int)
340{
341 // #####
342 Q_UNREACHABLE();
343}
344
345void 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
356void 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
368void 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
380void 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
392void 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
403void 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
413void 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
424void 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
435void 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
447void BaselineJIT::generate_TailCall(int func, int thisObject, int argc, int argv)
448{
449 STORE_IP();
450 as->jsTailCall(func, thisObject, argc, argv);
451}
452
453void 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
466void 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
479void 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
487void BaselineJIT::generate_UnwindDispatch()
488{
489 as->unwindDispatch();
490}
491
492void BaselineJIT::generate_UnwindToLabel(int level, int offset)
493{
494 labels.insert(value: as->unwindToLabel(level, offset: absoluteOffset(relativeOffset: offset)));
495}
496
497void BaselineJIT::generate_DeadTemporalZoneCheck(int name)
498{
499 as->deadTemporalZoneCheck(offsetForSavedIP: nextInstructionOffset(), variableName: name);
500}
501
502void 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
515void BaselineJIT::generate_GetException() { as->getException(); }
516void BaselineJIT::generate_SetException() { as->setException(); }
517
518void 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
527void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); }
528
529void 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
539void 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
549void 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
558void 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
568void 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
577void BaselineJIT::generate_PopContext() { as->popContext(); }
578
579void 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
589void 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
600void 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
611void 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
621void 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
630void 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
641void 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
651void 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
659void 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
668void 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
679void 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
688void 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
698void 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
708void 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
716void 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
724void 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
732void 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
743void 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
751void 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
761void BaselineJIT::generate_Jump(int offset)
762{
763 labels.insert(value: as->jump(offset: absoluteOffset(relativeOffset: offset)));
764}
765
766void BaselineJIT::generate_JumpTrue(int offset)
767{
768 labels.insert(value: as->jumpTrue(offset: absoluteOffset(relativeOffset: offset)));
769}
770
771void BaselineJIT::generate_JumpFalse(int offset)
772{
773 labels.insert(value: as->jumpFalse(offset: absoluteOffset(relativeOffset: offset)));
774}
775
776void BaselineJIT::generate_JumpNoException(int offset)
777{
778 labels.insert(value: as->jumpNoException(offset: absoluteOffset(relativeOffset: offset)));
779}
780
781void BaselineJIT::generate_JumpNotUndefined(int offset)
782{
783 labels.insert(value: as->jumpNotUndefined(offset: absoluteOffset(relativeOffset: offset)));
784}
785
786void BaselineJIT::generate_CheckException()
787{
788 as->checkException();
789}
790
791void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); }
792void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); }
793void BaselineJIT::generate_CmpEqInt(int lhs) { as->cmpeqInt(lhs); }
794void BaselineJIT::generate_CmpNeInt(int lhs) { as->cmpneInt(lhs); }
795void BaselineJIT::generate_CmpEq(int lhs) { as->cmpeq(lhs); }
796void BaselineJIT::generate_CmpNe(int lhs) { as->cmpne(lhs); }
797void BaselineJIT::generate_CmpGt(int lhs) { as->cmpgt(lhs); }
798void BaselineJIT::generate_CmpGe(int lhs) { as->cmpge(lhs); }
799void BaselineJIT::generate_CmpLt(int lhs) { as->cmplt(lhs); }
800void BaselineJIT::generate_CmpLe(int lhs) { as->cmple(lhs); }
801void BaselineJIT::generate_CmpStrictEqual(int lhs) { as->cmpStrictEqual(lhs); }
802void BaselineJIT::generate_CmpStrictNotEqual(int lhs) { as->cmpStrictNotEqual(lhs); }
803
804void 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
815void 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
825void 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
835void BaselineJIT::generate_UNot() { as->unot(); }
836void BaselineJIT::generate_UPlus() { as->toNumber(); }
837void BaselineJIT::generate_UMinus() { as->uminus(); }
838void BaselineJIT::generate_UCompl() { as->ucompl(); }
839void BaselineJIT::generate_Increment() { as->inc(); }
840void BaselineJIT::generate_Decrement() { as->dec(); }
841void BaselineJIT::generate_Add(int lhs) { as->add(lhs); }
842
843void BaselineJIT::generate_BitAnd(int lhs) { as->bitAnd(lhs); }
844void BaselineJIT::generate_BitOr(int lhs) { as->bitOr(lhs); }
845void BaselineJIT::generate_BitXor(int lhs) { as->bitXor(lhs); }
846void BaselineJIT::generate_UShr(int lhs) { as->ushr(lhs); }
847void BaselineJIT::generate_Shr(int lhs) { as->shr(lhs); }
848void BaselineJIT::generate_Shl(int lhs) { as->shl(lhs); }
849
850void BaselineJIT::generate_BitAndConst(int rhs) { as->bitAndConst(rhs); }
851void BaselineJIT::generate_BitOrConst(int rhs) { as->bitOrConst(rhs); }
852void BaselineJIT::generate_BitXorConst(int rhs) { as->bitXorConst(rhs); }
853void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); }
854void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); }
855void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); }
856
857void 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}
865void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); }
866void BaselineJIT::generate_Div(int lhs) { as->div(lhs); }
867void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); }
868void 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
882void 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
889void 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
899void 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
907ByteCodeHandler::Verdict BaselineJIT::startInstruction(Instr::Type /*instr*/)
908{
909 if (labels.contains(value: currentInstructionOffset()))
910 as->addLabel(offset: currentInstructionOffset());
911 return ProcessInstruction;
912}
913
914void BaselineJIT::endInstruction(Instr::Type instr)
915{
916 Q_UNUSED(instr);
917}
918
919#endif // QT_CONFIG(qml_jit)
920
921

source code of qtdeclarative/src/qml/jit/qv4baselinejit.cpp