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 | |
47 | QT_USE_NAMESPACE |
48 | using namespace QV4; |
49 | using namespace QV4::JIT; |
50 | using namespace QV4::Moth; |
51 | |
52 | BaselineJIT::BaselineJIT(Function *function) |
53 | : function(function) |
54 | , as(new BaselineAssembler(&(function->compilationUnit->constants->asValue<Value>()))) |
55 | {} |
56 | |
57 | BaselineJIT::~BaselineJIT() |
58 | {} |
59 | |
60 | void 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 | |
88 | void BaselineJIT::generate_Ret() |
89 | { |
90 | as->ret(); |
91 | } |
92 | |
93 | void BaselineJIT::generate_Debug() { Q_UNREACHABLE(); } |
94 | |
95 | void BaselineJIT::generate_LoadConst(int index) |
96 | { |
97 | as->loadConst(constIndex: index); |
98 | } |
99 | |
100 | void BaselineJIT::generate_LoadZero() |
101 | { |
102 | as->loadValue(value: Encode(int(0))); |
103 | } |
104 | |
105 | void BaselineJIT::generate_LoadTrue() |
106 | { |
107 | as->loadValue(value: Encode(true)); |
108 | } |
109 | |
110 | void BaselineJIT::generate_LoadFalse() |
111 | { |
112 | as->loadValue(value: Encode(false)); |
113 | } |
114 | |
115 | void BaselineJIT::generate_LoadNull() |
116 | { |
117 | as->loadValue(value: Encode::null()); |
118 | } |
119 | |
120 | void BaselineJIT::generate_LoadUndefined() |
121 | { |
122 | as->loadValue(value: Encode::undefined()); |
123 | } |
124 | |
125 | void BaselineJIT::generate_LoadInt(int value) |
126 | { |
127 | //### |
128 | as->loadValue(value: Encode(value)); |
129 | } |
130 | |
131 | void BaselineJIT::generate_MoveConst(int constIndex, int destTemp) |
132 | { |
133 | as->copyConst(constIndex, destReg: destTemp); |
134 | } |
135 | |
136 | void BaselineJIT::generate_LoadReg(int reg) |
137 | { |
138 | as->loadReg(reg); |
139 | } |
140 | |
141 | void BaselineJIT::generate_StoreReg(int reg) |
142 | { |
143 | as->storeReg(reg); |
144 | } |
145 | |
146 | void BaselineJIT::generate_MoveReg(int srcReg, int destReg) |
147 | { |
148 | // Don't clobber the accumulator. |
149 | as->moveReg(sourceReg: srcReg, destReg); |
150 | } |
151 | |
152 | void BaselineJIT::generate_LoadImport(int index) |
153 | { |
154 | as->loadImport(index); |
155 | } |
156 | |
157 | void BaselineJIT::generate_LoadLocal(int index) |
158 | { |
159 | as->loadLocal(index); |
160 | } |
161 | |
162 | void BaselineJIT::generate_StoreLocal(int index) |
163 | { |
164 | as->checkException(); |
165 | as->storeLocal(index); |
166 | } |
167 | |
168 | void BaselineJIT::generate_LoadScopedLocal(int scope, int index) |
169 | { |
170 | as->loadLocal(index, level: scope); |
171 | } |
172 | |
173 | void BaselineJIT::generate_StoreScopedLocal(int scope, int index) |
174 | { |
175 | as->checkException(); |
176 | as->storeLocal(index, level: scope); |
177 | } |
178 | |
179 | void BaselineJIT::generate_LoadRuntimeString(int stringId) |
180 | { |
181 | as->loadString(stringId); |
182 | } |
183 | |
184 | void 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 | |
193 | void 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 | |
201 | void 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 | |
210 | void 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 | |
219 | void 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 | |
227 | void 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 | |
239 | void 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 | |
251 | void 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 | |
262 | void 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 | |
275 | void 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 | |
286 | void 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 | |
298 | void 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 | |
311 | void 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 | |
326 | void 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 | |
335 | void 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 | |
347 | void BaselineJIT::generate_Yield() |
348 | { |
349 | // ##### |
350 | Q_UNREACHABLE(); |
351 | } |
352 | |
353 | void BaselineJIT::generate_YieldStar() |
354 | { |
355 | // ##### |
356 | Q_UNREACHABLE(); |
357 | } |
358 | |
359 | void BaselineJIT::generate_Resume(int) |
360 | { |
361 | // ##### |
362 | Q_UNREACHABLE(); |
363 | } |
364 | |
365 | void 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 | |
376 | void 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 | |
388 | void 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 | |
400 | void 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 | |
412 | void 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 | |
424 | void 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 | |
435 | void 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 | |
445 | void 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 | |
456 | void 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 | |
467 | void 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 | |
479 | void BaselineJIT::generate_TailCall(int func, int thisObject, int argc, int argv) |
480 | { |
481 | STORE_IP(); |
482 | as->jsTailCall(func, thisObject, argc, argv); |
483 | } |
484 | |
485 | void 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 | |
498 | void 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 | |
511 | void 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 | |
519 | void BaselineJIT::generate_UnwindDispatch() |
520 | { |
521 | as->unwindDispatch(); |
522 | } |
523 | |
524 | void BaselineJIT::generate_UnwindToLabel(int level, int offset) |
525 | { |
526 | labels.insert(value: as->unwindToLabel(level, offset: absoluteOffset(relativeOffset: offset))); |
527 | } |
528 | |
529 | void BaselineJIT::generate_DeadTemporalZoneCheck(int name) |
530 | { |
531 | as->deadTemporalZoneCheck(offsetForSavedIP: nextInstructionOffset(), variableName: name); |
532 | } |
533 | |
534 | void 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 | |
545 | void BaselineJIT::generate_GetException() { as->getException(); } |
546 | void BaselineJIT::generate_SetException() { as->setException(); } |
547 | |
548 | void BaselineJIT::generate_CreateCallContext() |
549 | { |
550 | as->prepareCallWithArgCount(argc: 1); |
551 | as->passCppFrameAsArg(arg: 0); |
552 | BASELINEJIT_GENERATE_RUNTIME_CALL(PushCallContext, CallResultDestination::Ignore); |
553 | } |
554 | |
555 | void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); } |
556 | |
557 | void 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 | |
567 | void 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 | |
577 | void 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 | |
586 | void 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 | |
596 | void 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 | |
605 | void BaselineJIT::generate_PopContext() { as->popContext(); } |
606 | |
607 | void 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 | |
617 | void 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 | |
628 | void 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 | |
639 | void 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 | |
649 | void 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 | |
658 | void 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 | |
669 | void 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 | |
679 | void 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 | |
687 | void 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 | |
696 | void 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 | |
707 | void 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 | |
716 | void 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 | |
726 | void 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 | |
736 | void 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 | |
744 | void 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 | |
752 | void 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 | |
760 | void 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 | |
771 | void 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 | |
779 | void 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 | |
789 | void BaselineJIT::generate_Jump(int offset) |
790 | { |
791 | labels.insert(value: as->jump(offset: absoluteOffset(relativeOffset: offset))); |
792 | } |
793 | |
794 | void BaselineJIT::generate_JumpTrue(int offset) |
795 | { |
796 | labels.insert(value: as->jumpTrue(offset: absoluteOffset(relativeOffset: offset))); |
797 | } |
798 | |
799 | void BaselineJIT::generate_JumpFalse(int offset) |
800 | { |
801 | labels.insert(value: as->jumpFalse(offset: absoluteOffset(relativeOffset: offset))); |
802 | } |
803 | |
804 | void BaselineJIT::generate_JumpNoException(int offset) |
805 | { |
806 | labels.insert(value: as->jumpNoException(offset: absoluteOffset(relativeOffset: offset))); |
807 | } |
808 | |
809 | void BaselineJIT::generate_JumpNotUndefined(int offset) |
810 | { |
811 | labels.insert(value: as->jumpNotUndefined(offset: absoluteOffset(relativeOffset: offset))); |
812 | } |
813 | |
814 | void BaselineJIT::generate_CheckException() |
815 | { |
816 | as->checkException(); |
817 | } |
818 | |
819 | void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); } |
820 | void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); } |
821 | void BaselineJIT::generate_CmpEqInt(int lhs) { as->cmpeqInt(lhs); } |
822 | void BaselineJIT::generate_CmpNeInt(int lhs) { as->cmpneInt(lhs); } |
823 | void BaselineJIT::generate_CmpEq(int lhs) { as->cmpeq(lhs); } |
824 | void BaselineJIT::generate_CmpNe(int lhs) { as->cmpne(lhs); } |
825 | void BaselineJIT::generate_CmpGt(int lhs) { as->cmpgt(lhs); } |
826 | void BaselineJIT::generate_CmpGe(int lhs) { as->cmpge(lhs); } |
827 | void BaselineJIT::generate_CmpLt(int lhs) { as->cmplt(lhs); } |
828 | void BaselineJIT::generate_CmpLe(int lhs) { as->cmple(lhs); } |
829 | void BaselineJIT::generate_CmpStrictEqual(int lhs) { as->cmpStrictEqual(lhs); } |
830 | void BaselineJIT::generate_CmpStrictNotEqual(int lhs) { as->cmpStrictNotEqual(lhs); } |
831 | |
832 | void 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 | |
842 | void 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 | |
852 | void BaselineJIT::generate_UNot() { as->unot(); } |
853 | void BaselineJIT::generate_UPlus() { as->toNumber(); } |
854 | void BaselineJIT::generate_UMinus() { as->uminus(); } |
855 | void BaselineJIT::generate_UCompl() { as->ucompl(); } |
856 | void BaselineJIT::generate_Increment() { as->inc(); } |
857 | void BaselineJIT::generate_Decrement() { as->dec(); } |
858 | void BaselineJIT::generate_Add(int lhs) { as->add(lhs); } |
859 | |
860 | void BaselineJIT::generate_BitAnd(int lhs) { as->bitAnd(lhs); } |
861 | void BaselineJIT::generate_BitOr(int lhs) { as->bitOr(lhs); } |
862 | void BaselineJIT::generate_BitXor(int lhs) { as->bitXor(lhs); } |
863 | void BaselineJIT::generate_UShr(int lhs) { as->ushr(lhs); } |
864 | void BaselineJIT::generate_Shr(int lhs) { as->shr(lhs); } |
865 | void BaselineJIT::generate_Shl(int lhs) { as->shl(lhs); } |
866 | |
867 | void BaselineJIT::generate_BitAndConst(int rhs) { as->bitAndConst(rhs); } |
868 | void BaselineJIT::generate_BitOrConst(int rhs) { as->bitOrConst(rhs); } |
869 | void BaselineJIT::generate_BitXorConst(int rhs) { as->bitXorConst(rhs); } |
870 | void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); } |
871 | void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); } |
872 | void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); } |
873 | |
874 | void 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 | } |
882 | void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); } |
883 | void BaselineJIT::generate_Div(int lhs) { as->div(lhs); } |
884 | void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); } |
885 | void 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 | |
899 | void 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 | |
906 | void 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 | |
916 | void 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 | |
924 | ByteCodeHandler::Verdict BaselineJIT::startInstruction(Instr::Type /*instr*/) |
925 | { |
926 | if (labels.contains(value: currentInstructionOffset())) |
927 | as->addLabel(offset: currentInstructionOffset()); |
928 | return ProcessInstruction; |
929 | } |
930 | |
931 | void BaselineJIT::endInstruction(Instr::Type instr) |
932 | { |
933 | Q_UNUSED(instr); |
934 | } |
935 | |
936 | #endif // QT_CONFIG(qml_jit) |
937 | |
938 | |