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

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