Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4vme_moth.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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 "qv4vme_moth_p.h"
5
6#include <QtCore/qjsondocument.h>
7#include <QtCore/qjsonobject.h>
8
9#include <private/qv4alloca_p.h>
10#include <private/qv4instr_moth_p.h>
11#include <private/qv4value_p.h>
12#include <private/qv4debugging_p.h>
13#include <private/qv4function_p.h>
14#include <private/qv4functionobject_p.h>
15#include <private/qv4math_p.h>
16#include <private/qv4scopedvalue_p.h>
17#include <private/qv4lookup_p.h>
18#include <private/qv4regexp_p.h>
19#include <private/qv4regexpobject_p.h>
20#include <private/qv4string_p.h>
21#include <private/qv4profiling_p.h>
22#include <private/qv4jscall_p.h>
23#include <private/qv4generatorobject_p.h>
24#include <private/qv4alloca_p.h>
25#include <private/qqmljavascriptexpression_p.h>
26#include <private/qv4qmlcontext_p.h>
27#include <QtQml/private/qv4runtime_p.h>
28#include <iostream>
29
30#if QT_CONFIG(qml_jit)
31#include <private/qv4baselinejit_p.h>
32#endif
33
34#include <qtqml_tracepoints_p.h>
35
36#undef COUNT_INSTRUCTIONS
37
38Q_TRACE_POINT(qtqml, QQmlV4_function_call_entry, const QV4::ExecutionEngine *engine, const QString &function, const QString &fileName, int line, int column)
39Q_TRACE_POINT(qtqml, QQmlV4_function_call_exit)
40
42
43extern "C" {
44
45// This is the interface to Qt Creator's (new) QML debugger.
46
57{
58}
59
69{
70}
71
115Q_QML_EXPORT int qt_v4DebuggerHook(const char *json);
116
117
118} // extern "C"
119
120#if QT_CONFIG(qml_debug)
121static int qt_v4BreakpointCount = 0;
122static bool qt_v4IsDebugging = false;
123static bool qt_v4IsStepping = false;
124
125class Breakpoint
126{
127public:
128 Breakpoint() : bpNumber(0), lineNumber(-1) {}
129
130 bool matches(const QString &file, int line) const
131 {
132 return fullName == file && lineNumber == line;
133 }
134
135 int bpNumber;
136 int lineNumber;
137 QString fullName; // e.g. /opt/project/main.qml
138 QString engineName; // e.g. qrc:/main.qml
139 QString condition; // optional
140};
141
142static QVector<Breakpoint> qt_v4Breakpoints;
143static Breakpoint qt_v4LastStop;
144
145static void qt_v4TriggerBreakpoint(const Breakpoint &bp, QV4::Function *function)
146{
147 qt_v4LastStop = bp;
148
149 // Set up some auxiliary data for informational purpose.
150 // This is not part of the protocol.
151 QV4::Heap::String *functionName = function->name();
152 QByteArray functionNameUtf8;
153 if (functionName)
154 functionNameUtf8 = functionName->toQString().toUtf8();
155
156 qt_v4TriggeredBreakpointHook(); // Trigger Breakpoint.
157}
158
159int qt_v4DebuggerHook(const char *json)
160{
161 const int ProtocolVersion = 1;
162
163 enum {
164 Success = 0,
165 WrongProtocol,
166 NoSuchCommand,
167 NoSuchBreakpoint
168 };
169
171 QJsonObject ob = doc.object();
172 QByteArray command = ob.value(QLatin1String("command")).toString().toUtf8();
173
174 if (command == "protocolVersion") {
175 return ProtocolVersion; // Version number.
176 }
177
178 int version = ob.value(QLatin1String("version")).toString().toInt();
179 if (version != ProtocolVersion) {
180 return -WrongProtocol;
181 }
182
183 if (command == "insertBreakpoint") {
184 Breakpoint bp;
185 bp.bpNumber = ++qt_v4BreakpointCount;
186 bp.lineNumber = ob.value(QLatin1String("lineNumber")).toString().toInt();
187 bp.engineName = ob.value(QLatin1String("engineName")).toString();
188 bp.fullName = ob.value(QLatin1String("fullName")).toString();
189 bp.condition = ob.value(QLatin1String("condition")).toString();
190 qt_v4Breakpoints.append(bp);
191 qt_v4IsDebugging = true;
192 return bp.bpNumber;
193 }
194
195 if (command == "removeBreakpoint") {
196 int lineNumber = ob.value(QLatin1String("lineNumber")).toString().toInt();
197 QString fullName = ob.value(QLatin1String("fullName")).toString();
198 if (qt_v4Breakpoints.last().matches(fullName, lineNumber)) {
199 qt_v4Breakpoints.removeLast();
200 qt_v4IsDebugging = !qt_v4Breakpoints.isEmpty();
201 return Success;
202 }
203 for (int i = 0; i + 1 < qt_v4Breakpoints.size(); ++i) {
204 if (qt_v4Breakpoints.at(i).matches(fullName, lineNumber)) {
205 qt_v4Breakpoints[i] = qt_v4Breakpoints.takeLast();
206 return Success; // Ok.
207 }
208 }
209 return -NoSuchBreakpoint; // Failure
210 }
211
212 if (command == "prepareStep") {
213 qt_v4IsStepping = true;
214 return Success; // Ok.
215 }
216
217
218 return -NoSuchCommand; // Failure.
219}
220
221Q_NEVER_INLINE static void qt_v4CheckForBreak(QV4::CppStackFrame *frame)
222{
223 if (!qt_v4IsStepping && !qt_v4Breakpoints.size())
224 return;
225
226 const int lineNumber = frame->lineNumber();
227 QV4::Function *function = frame->v4Function;
228 QString engineName = function->sourceFile();
229
230 if (engineName.isEmpty())
231 return;
232
233 if (qt_v4IsStepping) {
234 if (qt_v4LastStop.lineNumber != lineNumber
235 || qt_v4LastStop.engineName != engineName) {
236 qt_v4IsStepping = false;
237 Breakpoint bp;
238 bp.bpNumber = 0;
239 bp.lineNumber = lineNumber;
240 bp.engineName = engineName;
241 qt_v4TriggerBreakpoint(bp, function);
242 return;
243 }
244 }
245
246 for (int i = qt_v4Breakpoints.size(); --i >= 0; ) {
247 const Breakpoint &bp = qt_v4Breakpoints.at(i);
248 if (bp.lineNumber != lineNumber)
249 continue;
250 if (bp.engineName != engineName)
251 continue;
252
253 qt_v4TriggerBreakpoint(bp, function);
254 }
255}
256
257Q_NEVER_INLINE static void debug_slowPath(QV4::ExecutionEngine *engine)
258{
259 QV4::Debugging::Debugger *debugger = engine->debugger();
260 if (debugger && debugger->pauseAtNextOpportunity())
261 debugger->maybeBreakAtInstruction();
262 if (qt_v4IsDebugging)
263 qt_v4CheckForBreak(engine->currentStackFrame);
264}
265
266#endif // QT_CONFIG(qml_debug)
267// End of debugger interface
268
269using namespace QV4;
270using namespace QV4::Moth;
271
272#ifdef COUNT_INSTRUCTIONS
273static struct InstrCount {
274 InstrCount() {
275 fprintf(stderr, "Counting instructions...\n");
276 for (int i = 0; i < MOTH_NUM_INSTRUCTIONS(); ++i)
277 hits[i] = 0;
278 }
279 ~InstrCount() {
280 fprintf(stderr, "Instruction count:\n");
281#define BLAH(I) \
282 fprintf(stderr, "%llu : %s\n", hits[int(Instr::Type::I)], #I);
284 #undef BLAH
285 }
287 void hit(Instr::Type i) { hits[int(i)]++; }
288} instrCount;
289#endif // COUNT_INSTRUCTIONS
290
291#define MOTH_BEGIN_INSTR_COMMON(instr) \
292 { \
293 INSTR_##instr(MOTH_DECODE)
294
295#ifdef COUNT_INSTRUCTIONS
296# define MOTH_BEGIN_INSTR(instr) \
297 MOTH_BEGIN_INSTR_COMMON(instr) \
298 instrCount.hit(Instr::Type::instr);
299#else // !COUNT_INSTRUCTIONS
300# define MOTH_BEGIN_INSTR(instr) \
301 MOTH_BEGIN_INSTR_COMMON(instr)
302#endif // COUNT_INSTRUCTIONS
303
304#ifdef MOTH_COMPUTED_GOTO
305#define MOTH_END_INSTR(instr) \
306 MOTH_DISPATCH_SINGLE() \
307 }
308#else // !MOTH_COMPUTED_GOTO
309#define MOTH_END_INSTR(instr) \
310 continue; \
311 }
312#endif
313
314static inline QV4::Value &stackValue(QV4::Value *stack, size_t slot, const JSTypesStackFrame *frame)
315{
317 + frame->jsFrame->argc()
318 + frame->v4Function->compiledFunction->nRegisters);
320
321 return stack[slot];
322}
323
324#define STACK_VALUE(temp) stackValue(stack, temp, frame)
325
326// qv4scopedvalue_p.h also defines a CHECK_EXCEPTION macro
327#ifdef CHECK_EXCEPTION
328#undef CHECK_EXCEPTION
329#endif
330#define CHECK_EXCEPTION \
331 if (engine->hasException || engine->isInterrupted.loadRelaxed()) \
332 goto handleUnwind
333
334static inline Heap::CallContext *getScope(QV4::Value *stack, int level)
335{
336 Heap::ExecutionContext *scope = static_cast<ExecutionContext &>(stack[CallData::Context]).d();
337 while (level > 0) {
338 --level;
339 scope = scope->outer;
340 }
341 Q_ASSERT(scope);
342 return static_cast<Heap::CallContext *>(scope);
343}
344
345static inline const QV4::Value &constant(Function *function, int index)
346{
347 return function->compilationUnit->constants[index].asValue<QV4::Value>();
348}
349
350static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
351{
352 redo:
353 if (lhs.isUndefined())
354 return false;
355 if (lhs.isManagedOrUndefined()) {
356 // LHS: Managed
357 if (lhs.m()->internalClass->vtable->isString)
358 return RuntimeHelpers::stringToNumber(static_cast<String &>(lhs).toQString()) == rhs;
359 accumulator = lhs;
361 goto redo;
362 }
363
364 switch (lhs.quickType()) {
366 Q_UNREACHABLE();
368 return false;
371 return lhs.int_32() == rhs;
372 default: // double
373 return lhs.doubleValue() == rhs;
374 }
375}
376
377#define STORE_IP() frame->instructionPointer = int(code - function->codeData);
378#define STORE_ACC() accumulator = acc;
379#define ACC Value::fromReturnedValue(acc)
380#define VALUE_TO_INT(i, val) \
381 int i; \
382 do { \
383 if (Q_LIKELY(val.integerCompatible())) { \
384 i = val.int_32(); \
385 } else { \
386 double d; \
387 if (val.isDouble()) \
388 d = val.doubleValue(); \
389 else { \
390 STORE_ACC(); \
391 d = val.toNumberImpl(); \
392 CHECK_EXCEPTION; \
393 } \
394 i = QJSNumberCoercion::toInteger(d); \
395 } \
396 } while (false)
397
399{
400public:
402 : aotCompiledFunction(aotCompiledFunction)
403 {}
404
405 int parameterCount() const { return aotCompiledFunction->types.size() - 1; }
406 QMetaType returnMetaType() const { return aotCompiledFunction->types[0]; }
407 QMetaType parameterMetaType(int i) const { return aotCompiledFunction->types[i + 1]; }
408
409private:
410 const Function::AOTCompiledFunction *aotCompiledFunction = nullptr;
411};
412
414{
416 if (engine->checkStackLimits()) {
417 frame->setReturnValueUndefined();
418 return;
419 }
420 ExecutionEngineCallDepthRecorder executionEngineCallDepthRecorder(engine);
421
422 Function *function = frame->v4Function;
423 Q_ASSERT(function->aotCompiledCode);
424 Q_TRACE_SCOPE(QQmlV4_function_call, engine, function->name()->toQString(),
425 function->executableCompilationUnit()->fileName(),
426 function->compiledFunction->location.line(),
427 function->compiledFunction->location.column());
428 Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
429
430 const AOTCompiledMetaMethod method(&function->aotCompiledFunction);
432 engine, &method, frame->returnAndArgValues(),
433 frame->returnAndArgTypes(), frame->argc(),
434 [frame, engine, function](void **argv, int argc) {
435 Q_UNUSED(argc);
436
437 QQmlPrivate::AOTCompiledContext aotContext;
438 if (auto context = QV4::ExecutionEngine::qmlContext(frame->context()->d())) {
439 QV4::Heap::QQmlContextWrapper *wrapper = static_cast<Heap::QmlContext *>(context)->qml();
440 aotContext.qmlScopeObject = wrapper->scopeObject;
441 aotContext.qmlContext = wrapper->context;
442 }
443
444 aotContext.engine = engine->jsEngine();
445 aotContext.compilationUnit = function->executableCompilationUnit();
446 function->aotCompiledCode(&aotContext, argv);
447 });
448}
449
451{
454
455 Function *function = frame->v4Function;
456 Q_TRACE_SCOPE(QQmlV4_function_call, engine, function->name()->toQString(),
457 function->executableCompilationUnit()->fileName(),
458 function->compiledFunction->location.line(),
459 function->compiledFunction->location.column());
460 Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
461 QV4::Debugging::Debugger *debugger = engine->debugger();
462
463#if QT_CONFIG(qml_jit)
464 if (debugger == nullptr) {
465 // Check for codeRef here. In rare cases the JIT compilation may fail, which leaves us
466 // with a (useless) codeRef, but no jittedCode. In that case, don't try to JIT again every
467 // time we execute the function, but just interpret instead.
468 if (function->codeRef == nullptr) {
469 if (engine->canJIT(function))
470 QV4::JIT::BaselineJIT(function).generate();
471 else
472 ++function->interpreterCallCount;
473 }
474 }
475#endif // QT_CONFIG(qml_jit)
476
477 // interpreter
478 if (debugger)
479 debugger->enteringFunction();
480
482 Q_ASSERT(function->kind != Function::AotCompiled);
483 if (function->jittedCode != nullptr && debugger == nullptr) {
484 result = function->jittedCode(frame, engine);
485 } else {
486 // interpreter
487 result = interpret(frame, engine, function->codeData);
488 }
489
490 if (debugger)
491 debugger->leavingFunction(result);
492
493 return result;
494}
495
497{
498 QV4::Function *function = frame->v4Function;
499 QV4::Value &accumulator = frame->jsFrame->accumulator.asValue<Value>();
500 QV4::ReturnedValue acc = accumulator.asReturnedValue();
501 Value *stack = reinterpret_cast<Value *>(frame->jsFrame);
502
504
505 for (;;) {
507 Q_UNREACHABLE(); // only reached when the dispatch doesn't jump somewhere
508
509 MOTH_BEGIN_INSTR(LoadConst)
510 acc = constant(function, index).asReturnedValue();
511 MOTH_END_INSTR(LoadConst)
512
513 MOTH_BEGIN_INSTR(LoadNull)
514 acc = Encode::null();
515 MOTH_END_INSTR(LoadNull)
516
517 MOTH_BEGIN_INSTR(LoadZero)
518 acc = Encode(static_cast<int>(0));
519 MOTH_END_INSTR(LoadZero)
520
521 MOTH_BEGIN_INSTR(LoadTrue)
522 acc = Encode(true);
523 MOTH_END_INSTR(LoadTrue)
524
525 MOTH_BEGIN_INSTR(LoadFalse)
526 acc = Encode(false);
527 MOTH_END_INSTR(LoadFalse)
528
529 MOTH_BEGIN_INSTR(LoadUndefined)
530 acc = Encode::undefined();
531 MOTH_END_INSTR(LoadUndefined)
532
533 MOTH_BEGIN_INSTR(LoadInt)
534 acc = Encode(value);
535 MOTH_END_INSTR(LoadInt)
536
537 MOTH_BEGIN_INSTR(MoveConst)
538 STACK_VALUE(destTemp) = constant(function, constIndex);
539 MOTH_END_INSTR(MoveConst)
540
541 MOTH_BEGIN_INSTR(LoadReg)
542 acc = STACK_VALUE(reg).asReturnedValue();
543 MOTH_END_INSTR(LoadReg)
544
545 MOTH_BEGIN_INSTR(StoreReg)
546 STACK_VALUE(reg) = acc;
547 MOTH_END_INSTR(StoreReg)
548
549 MOTH_BEGIN_INSTR(MoveReg)
550 STACK_VALUE(destReg) = STACK_VALUE(srcReg);
551 MOTH_END_INSTR(MoveReg)
552
553 MOTH_BEGIN_INSTR(LoadImport)
554 acc = function->compilationUnit->imports[index]->asReturnedValue();
555 MOTH_END_INSTR(LoadImport)
556
557 MOTH_BEGIN_INSTR(LoadLocal)
558 auto cc = static_cast<Heap::CallContext *>(STACK_VALUE(CallData::Context).m());
559 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
560 acc = cc->locals[index].asReturnedValue();
561 MOTH_END_INSTR(LoadLocal)
562
563 MOTH_BEGIN_INSTR(StoreLocal)
565 auto cc = static_cast<Heap::CallContext *>(STACK_VALUE(CallData::Context).m());
566 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
567 QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
568 MOTH_END_INSTR(StoreLocal)
569
570 MOTH_BEGIN_INSTR(LoadScopedLocal)
571 auto cc = getScope(stack, scope);
572 acc = cc->locals[index].asReturnedValue();
573 MOTH_END_INSTR(LoadScopedLocal)
574
575 MOTH_BEGIN_INSTR(StoreScopedLocal)
577 auto cc = getScope(stack, scope);
578 QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
579 MOTH_END_INSTR(StoreScopedLocal)
580
581 MOTH_BEGIN_INSTR(LoadRuntimeString)
582 acc = function->compilationUnit->runtimeStrings[stringId]->asReturnedValue();
583 MOTH_END_INSTR(LoadRuntimeString)
584
585 MOTH_BEGIN_INSTR(MoveRegExp)
586 STACK_VALUE(destReg) = Runtime::RegexpLiteral::call(engine, regExpId);
587 MOTH_END_INSTR(MoveRegExp)
588
589 MOTH_BEGIN_INSTR(LoadClosure)
591 MOTH_END_INSTR(LoadClosure)
592
593 MOTH_BEGIN_INSTR(LoadName)
594 STORE_IP();
597 MOTH_END_INSTR(LoadName)
598
599 MOTH_BEGIN_INSTR(LoadGlobalLookup)
600 STORE_IP();
601 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
602 acc = l->globalGetter(l, engine);
604 MOTH_END_INSTR(LoadGlobalLookup)
605
606 MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup)
607 STORE_IP();
608 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
609 acc = l->qmlContextPropertyGetter(l, engine, nullptr);
611 MOTH_END_INSTR(LoadQmlContextPropertyLookup)
612
613 MOTH_BEGIN_INSTR(StoreNameStrict)
614 STORE_IP();
615 STORE_ACC();
618 MOTH_END_INSTR(StoreNameStrict)
619
620 MOTH_BEGIN_INSTR(StoreNameSloppy)
621 STORE_IP();
622 STORE_ACC();
625 MOTH_END_INSTR(StoreNameSloppy)
626
627 MOTH_BEGIN_INSTR(LoadElement)
628 STORE_IP();
629 STORE_ACC();
632 MOTH_END_INSTR(LoadElement)
633
634 MOTH_BEGIN_INSTR(StoreElement)
635 STORE_IP();
636 STORE_ACC();
639 MOTH_END_INSTR(StoreElement)
640
641 MOTH_BEGIN_INSTR(LoadProperty)
642 STORE_IP();
643 STORE_ACC();
644 acc = Runtime::LoadProperty::call(engine, accumulator, name);
646 MOTH_END_INSTR(LoadProperty)
647
648 MOTH_BEGIN_INSTR(LoadOptionalProperty)
649 STORE_IP();
650 STORE_ACC();
651 if (accumulator.isNullOrUndefined()) {
652 acc = Encode::undefined();
653 code += offset;
654 } else {
655 acc = Runtime::LoadProperty::call(engine, accumulator, name);
656 }
658 MOTH_END_INSTR(LoadOptionalProperty)
659
660 MOTH_BEGIN_INSTR(GetLookup)
661 STORE_IP();
662 STORE_ACC();
663
664 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
665
666 if (accumulator.isNullOrUndefined()) {
667 QString message = QStringLiteral("Cannot read property '%1' of %2")
668 .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString())
669 .arg(accumulator.toQStringNoThrow());
670 acc = engine->throwTypeError(message);
671 goto handleUnwind;
672 }
673
674 acc = l->getter(l, engine, accumulator);
676 MOTH_END_INSTR(GetLookup)
677
678 MOTH_BEGIN_INSTR(GetOptionalLookup)
679 STORE_IP();
680 STORE_ACC();
681
682 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
683
684 if (accumulator.isNullOrUndefined()) {
685 code += offset;
686 } else {
687 acc = l->getter(l, engine, accumulator);
688 }
690 MOTH_END_INSTR(GetOptionalLookup)
691
692 MOTH_BEGIN_INSTR(StoreProperty)
693 STORE_IP();
694 STORE_ACC();
697 MOTH_END_INSTR(StoreProperty)
698
699 MOTH_BEGIN_INSTR(SetLookup)
700 STORE_IP();
701 STORE_ACC();
702 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
703 if (!l->setter(l, engine, STACK_VALUE(base), accumulator) && function->isStrict())
704 engine->throwTypeError();
706 MOTH_END_INSTR(SetLookup)
707
708 MOTH_BEGIN_INSTR(LoadSuperProperty)
709 STORE_IP();
712 MOTH_END_INSTR(LoadSuperProperty)
713
714 MOTH_BEGIN_INSTR(StoreSuperProperty)
715 STORE_IP();
716 STORE_ACC();
719 MOTH_END_INSTR(StoreSuperProperty)
720
721 MOTH_BEGIN_INSTR(Yield)
722 frame->setYield(code);
723 frame->setYieldIsIterator(false);
724 return acc;
725 MOTH_END_INSTR(Yield)
726
727 MOTH_BEGIN_INSTR(YieldStar)
728 frame->setYield(code);
729 frame->setYieldIsIterator(true);
730 return acc;
731 MOTH_END_INSTR(YieldStar)
732
733 MOTH_BEGIN_INSTR(Resume)
734 // check exception, in case the generator was called with throw() or return()
735 if (engine->hasException) {
736 // an empty value indicates that the generator was called with return()
737 if (engine->exceptionValue->asReturnedValue() != Value::emptyValue().asReturnedValue())
738 goto handleUnwind;
739 engine->hasException = false;
740 *engine->exceptionValue = Value::undefinedValue();
741 } else {
742 code += offset;
743 }
744 MOTH_END_INSTR(Resume)
745
746 MOTH_BEGIN_INSTR(IteratorNextForYieldStar)
747 STORE_ACC();
748 acc = Runtime::IteratorNextForYieldStar::call(engine, accumulator, STACK_VALUE(iterator), &STACK_VALUE(object));
749 if (ACC.toBoolean())
750 code += offset;
751 MOTH_END_INSTR(IteratorNextForYieldStar)
752
753 MOTH_BEGIN_INSTR(CallValue)
754 STORE_IP();
756 if (Q_UNLIKELY(!func.isFunctionObject())) {
757 acc = engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
758 goto handleUnwind;
759 }
761 acc = static_cast<const FunctionObject &>(func).call(&undef, stack + argv, argc);
763 MOTH_END_INSTR(CallValue)
764
765 MOTH_BEGIN_INSTR(CallWithReceiver)
766 STORE_IP();
768 if (Q_UNLIKELY(!func.isFunctionObject())) {
769 acc = engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
770 goto handleUnwind;
771 }
772 acc = static_cast<const FunctionObject &>(func).call(stack + thisObject, stack + argv, argc);
774 MOTH_END_INSTR(CallWithReceiver)
775
776 MOTH_BEGIN_INSTR(CallProperty)
777 STORE_IP();
778 acc = Runtime::CallProperty::call(engine, STACK_VALUE(base), name, stack + argv, argc);
780 MOTH_END_INSTR(CallProperty)
781
782 MOTH_BEGIN_INSTR(CallPropertyLookup)
783 STORE_IP();
784 Lookup *l = function->executableCompilationUnit()->runtimeLookups + lookupIndex;
785
786 if (STACK_VALUE(base).isNullOrUndefined()) {
787 QString message = QStringLiteral("Cannot call method '%1' of %2")
788 .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString())
789 .arg(STACK_VALUE(base).toQStringNoThrow());
790 acc = engine->throwTypeError(message);
791 goto handleUnwind;
792 }
793
794 // ok to have the value on the stack here
796
797 if (Q_LIKELY(f.isFunctionObject())) {
798 acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
799 } else if (QmlSignalHandler *handler = f.as<QmlSignalHandler>()) {
800 acc = handler->call(stack + base, stack + argv, argc);
801 } else {
802 const QString message = QStringLiteral("Property '%1' of object %2 is not a function")
803 .arg(engine->currentStackFrame->v4Function->compilationUnit
804 ->runtimeStrings[l->nameIndex]->toQString())
805 .arg(STACK_VALUE(base).toQStringNoThrow());
806 acc = engine->throwTypeError(message);
807 goto handleUnwind;
808 }
809
811 MOTH_END_INSTR(CallPropertyLookup)
812
813 MOTH_BEGIN_INSTR(CallName)
814 STORE_IP();
815 acc = Runtime::CallName::call(engine, name, stack + argv, argc);
817 MOTH_END_INSTR(CallName)
818
819 MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
820 STORE_IP();
821 acc = Runtime::CallPossiblyDirectEval::call(engine, stack + argv, argc);
823 MOTH_END_INSTR(CallPossiblyDirectEval)
824
825 MOTH_BEGIN_INSTR(CallGlobalLookup)
826 STORE_IP();
827 acc = Runtime::CallGlobalLookup::call(engine, index, stack + argv, argc);
829 MOTH_END_INSTR(CallGlobalLookup)
830
831 MOTH_BEGIN_INSTR(CallQmlContextPropertyLookup)
832 STORE_IP();
833 acc = Runtime::CallQmlContextPropertyLookup::call(engine, index, stack + argv, argc);
835 MOTH_END_INSTR(CallQmlContextPropertyLookup)
836
837 MOTH_BEGIN_INSTR(CallWithSpread)
838 STORE_IP();
839 acc = Runtime::CallWithSpread::call(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc);
841 MOTH_END_INSTR(CallWithSpread)
842
843 MOTH_BEGIN_INSTR(TailCall)
844 STORE_IP();
845 *engine->jsAlloca(1) = Primitive::fromInt32(argc);
846 *engine->jsAlloca(1) = Primitive::fromInt32(argv);
847 *engine->jsAlloca(1) = STACK_VALUE(thisObject);
848 *engine->jsAlloca(1) = STACK_VALUE(func);
851 MOTH_END_INSTR(TailCall)
852
854 STORE_IP();
855 STORE_ACC();
856 acc = Runtime::Construct::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
859
860 MOTH_BEGIN_INSTR(ConstructWithSpread)
861 STORE_IP();
862 STORE_ACC();
863 acc = Runtime::ConstructWithSpread::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
865 MOTH_END_INSTR(ConstructWithSpread)
866
867 MOTH_BEGIN_INSTR(SetUnwindHandler)
868 frame->unwindHandler = offset ? code + offset : nullptr;
869 MOTH_END_INSTR(SetUnwindHandler)
870
871 MOTH_BEGIN_INSTR(UnwindDispatch)
873 if (frame->unwindLevel) {
874 --frame->unwindLevel;
875 if (frame->unwindLevel)
876 goto handleUnwind;
877 code = frame->unwindLabel;
878 }
879 MOTH_END_INSTR(UnwindDispatch)
880
881 MOTH_BEGIN_INSTR(UnwindToLabel)
882 frame->unwindLevel = level;
883 frame->unwindLabel = code + offset;
884 goto handleUnwind;
885 MOTH_END_INSTR(UnwindToLabel)
886
887 MOTH_BEGIN_INSTR(DeadTemporalZoneCheck)
888 if (ACC.isEmpty()) {
889 STORE_IP();
891 goto handleUnwind;
892 }
893 MOTH_END_INSTR(DeadTemporalZoneCheck)
894
895 MOTH_BEGIN_INSTR(ThrowException)
896 STORE_IP();
897 STORE_ACC();
899 goto handleUnwind;
900 MOTH_END_INSTR(ThrowException)
901
902 MOTH_BEGIN_INSTR(GetException)
903 acc = engine->hasException ? engine->exceptionValue->asReturnedValue()
904 : Value::emptyValue().asReturnedValue();
905 engine->hasException = false;
906 MOTH_END_INSTR(HasException)
907
908 MOTH_BEGIN_INSTR(SetException)
909 if (acc != Value::emptyValue().asReturnedValue()) {
910 *engine->exceptionValue = acc;
911 engine->hasException = true;
912 }
913 MOTH_END_INSTR(SetException)
914
915 MOTH_BEGIN_INSTR(PushCatchContext)
917 MOTH_END_INSTR(PushCatchContext)
918
919 MOTH_BEGIN_INSTR(CreateCallContext)
921 MOTH_END_INSTR(CreateCallContext)
922
923 MOTH_BEGIN_INSTR(PushWithContext)
924 STORE_IP();
925 STORE_ACC();
928 MOTH_END_INSTR(PushWithContext)
929
930 MOTH_BEGIN_INSTR(PushBlockContext)
931 STORE_ACC();
933 MOTH_END_INSTR(PushBlockContext)
934
935 MOTH_BEGIN_INSTR(CloneBlockContext)
936 STORE_ACC();
938 MOTH_END_INSTR(CloneBlockContext)
939
940 MOTH_BEGIN_INSTR(PushScriptContext)
942 MOTH_END_INSTR(PushScriptContext)
943
944 MOTH_BEGIN_INSTR(PopScriptContext)
946 MOTH_END_INSTR(PopScriptContext)
947
948 MOTH_BEGIN_INSTR(PopContext)
949 ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
950 STACK_VALUE(CallData::Context) = c->d()->outer;
951 MOTH_END_INSTR(PopContext)
952
953 MOTH_BEGIN_INSTR(GetIterator)
954 STORE_IP();
955 STORE_ACC();
956 acc = Runtime::GetIterator::call(engine, accumulator, iterator);
958 MOTH_END_INSTR(GetIterator)
959
960 MOTH_BEGIN_INSTR(IteratorNext)
961 STORE_IP();
962 STORE_ACC();
964 if (ACC.toBoolean())
965 code += offset;
966 MOTH_END_INSTR(IteratorNext)
967
968 MOTH_BEGIN_INSTR(IteratorClose)
969 STORE_IP();
970 STORE_ACC();
971 acc = Runtime::IteratorClose::call(engine, accumulator);
972 MOTH_END_INSTR(IteratorClose)
973
974 MOTH_BEGIN_INSTR(DestructureRestElement)
975 STORE_IP();
976 STORE_ACC();
979 MOTH_END_INSTR(DestructureRestElement)
980
981 MOTH_BEGIN_INSTR(DeleteProperty)
984 MOTH_END_INSTR(DeleteProperty)
985
986 MOTH_BEGIN_INSTR(DeleteName)
987 acc = Runtime::DeleteName::call(engine, function, name);
989 MOTH_END_INSTR(DeleteName)
990
991 MOTH_BEGIN_INSTR(TypeofName)
993 MOTH_END_INSTR(TypeofName)
994
995 MOTH_BEGIN_INSTR(TypeofValue)
996 STORE_ACC();
997 acc = Runtime::TypeofValue::call(engine, accumulator);
998 MOTH_END_INSTR(TypeofValue)
999
1000 MOTH_BEGIN_INSTR(DeclareVar)
1001 Runtime::DeclareVar::call(engine, isDeletable, varName);
1002 MOTH_END_INSTR(DeclareVar)
1003
1004 MOTH_BEGIN_INSTR(DefineArray)
1005 QV4::Value *arguments = stack + args;
1007 MOTH_END_INSTR(DefineArray)
1008
1009 MOTH_BEGIN_INSTR(DefineObjectLiteral)
1010 QV4::Value *arguments = stack + args;
1011 acc = Runtime::ObjectLiteral::call(engine, internalClassId, arguments, argc);
1012 MOTH_END_INSTR(DefineObjectLiteral)
1013
1014 MOTH_BEGIN_INSTR(CreateClass)
1015 acc = Runtime::CreateClass::call(engine, classIndex, STACK_VALUE(heritage), stack + computedNames);
1016 MOTH_END_INSTR(CreateClass)
1017
1018 MOTH_BEGIN_INSTR(CreateMappedArgumentsObject)
1020 MOTH_END_INSTR(CreateMappedArgumentsObject)
1021
1022 MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
1024 MOTH_END_INSTR(CreateUnmappedArgumentsObject)
1025
1026 MOTH_BEGIN_INSTR(CreateRestParameter)
1028 MOTH_END_INSTR(CreateRestParameter)
1029
1030 MOTH_BEGIN_INSTR(ConvertThisToObject)
1031 STORE_ACC();
1035 MOTH_END_INSTR(ConvertThisToObject)
1036
1037 MOTH_BEGIN_INSTR(LoadSuperConstructor)
1040 MOTH_END_INSTR(LoadSuperConstructor)
1041
1042 MOTH_BEGIN_INSTR(ToObject)
1043 STORE_ACC();
1044 acc = ACC.toObject(engine)->asReturnedValue();
1046 MOTH_END_INSTR(ToObject)
1047
1048 MOTH_BEGIN_INSTR(Jump)
1049 code += offset;
1050 MOTH_END_INSTR(Jump)
1051
1052 MOTH_BEGIN_INSTR(JumpTrue)
1053 bool takeJump;
1054 if (Q_LIKELY(ACC.integerCompatible()))
1055 takeJump = ACC.int_32();
1056 else
1057 takeJump = ACC.toBoolean();
1058 if (takeJump)
1059 code += offset;
1060 MOTH_END_INSTR(JumpTrue)
1061
1062 MOTH_BEGIN_INSTR(JumpFalse)
1063 bool takeJump;
1064 if (Q_LIKELY(ACC.integerCompatible()))
1065 takeJump = !ACC.int_32();
1066 else
1067 takeJump = !ACC.toBoolean();
1068 if (takeJump)
1069 code += offset;
1070 MOTH_END_INSTR(JumpFalse)
1071
1072 MOTH_BEGIN_INSTR(JumpNoException)
1073 if (!engine->hasException)
1074 code += offset;
1075 MOTH_END_INSTR(JumpNoException)
1076
1077 MOTH_BEGIN_INSTR(JumpNotUndefined)
1078 if (Q_LIKELY(acc != QV4::Encode::undefined()))
1079 code += offset;
1080 MOTH_END_INSTR(JumpNotUndefined)
1081
1082 MOTH_BEGIN_INSTR(CheckException)
1084 MOTH_END_INSTR(CheckException)
1085
1086 MOTH_BEGIN_INSTR(CmpEqNull)
1087 acc = Encode(ACC.isNullOrUndefined());
1088 MOTH_END_INSTR(CmpEqNull)
1089
1090 MOTH_BEGIN_INSTR(CmpNeNull)
1091 acc = Encode(!ACC.isNullOrUndefined());
1092 MOTH_END_INSTR(CmpNeNull)
1093
1094 MOTH_BEGIN_INSTR(CmpEqInt)
1095 if (ACC.isIntOrBool()) {
1096 acc = Encode(ACC.int_32() == lhs);
1097 } else {
1098 STORE_ACC();
1099 acc = Encode(compareEqualInt(accumulator, ACC, lhs));
1101 }
1102 MOTH_END_INSTR(CmpEqInt)
1103
1104 MOTH_BEGIN_INSTR(CmpNeInt)
1105 if (ACC.isIntOrBool()) {
1106 acc = Encode(bool(ACC.int_32() != lhs));
1107 } else {
1108 STORE_ACC();
1109 acc = Encode(!compareEqualInt(accumulator, ACC, lhs));
1111 }
1112 MOTH_END_INSTR(CmpNeInt)
1113
1114 MOTH_BEGIN_INSTR(CmpEq)
1115 const Value left = STACK_VALUE(lhs);
1116 if (Q_LIKELY(left.asReturnedValue() == ACC.asReturnedValue())) {
1117 acc = Encode(!ACC.isNaN());
1118 } else if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
1119 acc = Encode(left.int_32() == ACC.int_32());
1120 } else {
1121 STORE_ACC();
1122 acc = Encode(bool(Runtime::CompareEqual::call(left, accumulator)));
1124 }
1125 MOTH_END_INSTR(CmpEq)
1126
1127 MOTH_BEGIN_INSTR(CmpNe)
1128 const Value left = STACK_VALUE(lhs);
1129 if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
1130 acc = Encode(bool(left.int_32() != ACC.int_32()));
1131 } else {
1132 STORE_ACC();
1133 acc = Encode(bool(!Runtime::CompareEqual::call(left, accumulator)));
1135 }
1136 MOTH_END_INSTR(CmpNe)
1137
1138 MOTH_BEGIN_INSTR(CmpGt)
1139 const Value left = STACK_VALUE(lhs);
1140 if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
1141 acc = Encode(left.int_32() > ACC.int_32());
1142 } else if (left.isNumber() && ACC.isNumber()) {
1143 acc = Encode(left.asDouble() > ACC.asDouble());
1144 } else {
1145 STORE_ACC();
1146 acc = Encode(bool(Runtime::CompareGreaterThan::call(left, accumulator)));
1148 }
1149 MOTH_END_INSTR(CmpGt)
1150
1151 MOTH_BEGIN_INSTR(CmpGe)
1152 const Value left = STACK_VALUE(lhs);
1153 if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
1154 acc = Encode(left.int_32() >= ACC.int_32());
1155 } else if (left.isNumber() && ACC.isNumber()) {
1156 acc = Encode(left.asDouble() >= ACC.asDouble());
1157 } else {
1158 STORE_ACC();
1159 acc = Encode(bool(Runtime::CompareGreaterEqual::call(left, accumulator)));
1161 }
1162 MOTH_END_INSTR(CmpGe)
1163
1164 MOTH_BEGIN_INSTR(CmpLt)
1165 const Value left = STACK_VALUE(lhs);
1166 if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
1167 acc = Encode(left.int_32() < ACC.int_32());
1168 } else if (left.isNumber() && ACC.isNumber()) {
1169 acc = Encode(left.asDouble() < ACC.asDouble());
1170 } else {
1171 STORE_ACC();
1172 acc = Encode(bool(Runtime::CompareLessThan::call(left, accumulator)));
1174 }
1175 MOTH_END_INSTR(CmpLt)
1176
1177 MOTH_BEGIN_INSTR(CmpLe)
1178 const Value left = STACK_VALUE(lhs);
1179 if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
1180 acc = Encode(left.int_32() <= ACC.int_32());
1181 } else if (left.isNumber() && ACC.isNumber()) {
1182 acc = Encode(left.asDouble() <= ACC.asDouble());
1183 } else {
1184 STORE_ACC();
1185 acc = Encode(bool(Runtime::CompareLessEqual::call(left, accumulator)));
1187 }
1188 MOTH_END_INSTR(CmpLe)
1189
1190 MOTH_BEGIN_INSTR(CmpStrictEqual)
1191 if (STACK_VALUE(lhs).rawValue() == ACC.rawValue() && !ACC.isNaN()) {
1192 acc = Encode(true);
1193 } else {
1194 STORE_ACC();
1195 acc = Runtime::StrictEqual::call(STACK_VALUE(lhs), accumulator);
1197 }
1198 MOTH_END_INSTR(CmpStrictEqual)
1199
1200 MOTH_BEGIN_INSTR(CmpStrictNotEqual)
1201 if (STACK_VALUE(lhs).rawValue() != ACC.rawValue() || ACC.isNaN()) {
1202 STORE_ACC();
1203 acc = Runtime::StrictNotEqual::call(STACK_VALUE(lhs), accumulator);
1205 } else {
1206 acc = Encode(false);
1207 }
1208 MOTH_END_INSTR(CmpStrictNotEqual)
1209
1210 MOTH_BEGIN_INSTR(CmpIn)
1211 STORE_IP();
1212 STORE_ACC();
1213 acc = Runtime::In::call(engine, STACK_VALUE(lhs), accumulator);
1215 MOTH_END_INSTR(CmpIn)
1216
1217 MOTH_BEGIN_INSTR(CmpInstanceOf)
1218 STORE_ACC();
1221 MOTH_END_INSTR(CmpInstanceOf)
1222
1223 MOTH_BEGIN_INSTR(UNot)
1224 if (ACC.integerCompatible()) {
1225 acc = Encode(!static_cast<bool>(ACC.int_32()));
1226 } else {
1228 }
1229 MOTH_END_INSTR(UNot)
1230
1231 MOTH_BEGIN_INSTR(UPlus)
1232 if (Q_UNLIKELY(!ACC.isNumber())) {
1233 acc = Encode(ACC.toNumberImpl());
1235 }
1236 MOTH_END_INSTR(UPlus)
1237
1238 MOTH_BEGIN_INSTR(UMinus)
1239 if (Q_LIKELY(ACC.integerCompatible())) {
1240 int a = ACC.int_32();
1241 if (a == 0 || a == std::numeric_limits<int>::min()) {
1242 acc = Encode(-static_cast<double>(a));
1243 } else {
1244 acc = sub_int32(0, ACC.int_32());
1245 }
1246 } else if (ACC.isDouble()) {
1247 acc ^= (1ull << 63); // simply flip sign bit
1248 } else {
1249 acc = Encode(-ACC.toNumberImpl());
1251 }
1252 MOTH_END_INSTR(UMinus)
1253
1254 MOTH_BEGIN_INSTR(UCompl)
1255 VALUE_TO_INT(a, ACC);
1256 acc = Encode(~a);
1257 MOTH_END_INSTR(UCompl)
1258
1259 MOTH_BEGIN_INSTR(Increment)
1260 if (Q_LIKELY(ACC.integerCompatible())) {
1261 acc = add_int32(ACC.int_32(), 1);
1262 } else if (ACC.isDouble()) {
1263 acc = QV4::Encode(ACC.doubleValue() + 1.);
1264 } else {
1265 acc = Encode(ACC.toNumberImpl() + 1.);
1267 }
1268 MOTH_END_INSTR(Increment)
1269
1270 MOTH_BEGIN_INSTR(Decrement)
1271 if (Q_LIKELY(ACC.integerCompatible())) {
1272 acc = sub_int32(ACC.int_32(), 1);
1273 } else if (ACC.isDouble()) {
1274 acc = QV4::Encode(ACC.doubleValue() - 1.);
1275 } else {
1276 acc = Encode(ACC.toNumberImpl() - 1.);
1278 }
1279 MOTH_END_INSTR(Decrement)
1280
1281 MOTH_BEGIN_INSTR(Add)
1282 const Value left = STACK_VALUE(lhs);
1284 acc = add_int32(left.int_32(), ACC.int_32());
1285 } else if (left.isNumber() && ACC.isNumber()) {
1286 acc = Encode(left.asDouble() + ACC.asDouble());
1287 } else {
1288 STORE_ACC();
1289 acc = Runtime::Add::call(engine, left, accumulator);
1291 }
1292 MOTH_END_INSTR(Add)
1293
1294 MOTH_BEGIN_INSTR(Sub)
1295 const Value left = STACK_VALUE(lhs);
1297 acc = sub_int32(left.int_32(), ACC.int_32());
1298 } else if (left.isNumber() && ACC.isNumber()) {
1299 acc = Encode(left.asDouble() - ACC.asDouble());
1300 } else {
1301 STORE_ACC();
1302 acc = Runtime::Sub::call(left, accumulator);
1304 }
1305 MOTH_END_INSTR(Sub)
1306
1308 const Value left = STACK_VALUE(lhs);
1309 STORE_ACC();
1310 acc = Runtime::As::call(engine, left, accumulator);
1311 MOTH_END_INSTR(As)
1312
1313 MOTH_BEGIN_INSTR(Exp)
1314 const Value left = STACK_VALUE(lhs);
1315 double base = left.toNumber();
1316 double exp = ACC.toNumber();
1318 MOTH_END_INSTR(Exp)
1319
1320 MOTH_BEGIN_INSTR(Mul)
1321 const Value left = STACK_VALUE(lhs);
1323 acc = mul_int32(left.int_32(), ACC.int_32());
1324 } else if (left.isNumber() && ACC.isNumber()) {
1325 acc = Encode(left.asDouble() * ACC.asDouble());
1326 } else {
1327 STORE_ACC();
1328 acc = Runtime::Mul::call(left, accumulator);
1330 }
1331 MOTH_END_INSTR(Mul)
1332
1333 MOTH_BEGIN_INSTR(Div)
1334 STORE_ACC();
1335 acc = Runtime::Div::call(STACK_VALUE(lhs), accumulator);
1337 MOTH_END_INSTR(Div)
1338
1339 MOTH_BEGIN_INSTR(Mod)
1340 STORE_ACC();
1341 acc = Runtime::Mod::call(STACK_VALUE(lhs), accumulator);
1343 MOTH_END_INSTR(Mod)
1344
1345 MOTH_BEGIN_INSTR(BitAnd)
1346 VALUE_TO_INT(l, STACK_VALUE(lhs));
1347 VALUE_TO_INT(a, ACC);
1348 acc = Encode(l & a);
1349 MOTH_END_INSTR(BitAnd)
1350
1351 MOTH_BEGIN_INSTR(BitOr)
1352 VALUE_TO_INT(l, STACK_VALUE(lhs));
1353 VALUE_TO_INT(a, ACC);
1354 acc = Encode(l | a);
1355 MOTH_END_INSTR(BitOr)
1356
1357 MOTH_BEGIN_INSTR(BitXor)
1358 VALUE_TO_INT(l, STACK_VALUE(lhs));
1359 VALUE_TO_INT(a, ACC);
1360 acc = Encode(l ^ a);
1361 MOTH_END_INSTR(BitXor)
1362
1363 MOTH_BEGIN_INSTR(UShr)
1364 VALUE_TO_INT(l, STACK_VALUE(lhs));
1365 VALUE_TO_INT(a, ACC);
1366 acc = Encode(static_cast<uint>(l) >> uint(a & 0x1f));
1367 MOTH_END_INSTR(UShr)
1368
1369 MOTH_BEGIN_INSTR(Shr)
1370 VALUE_TO_INT(l, STACK_VALUE(lhs));
1371 VALUE_TO_INT(a, ACC);
1372 acc = Encode(l >> (a & 0x1f));
1373 MOTH_END_INSTR(Shr)
1374
1375 MOTH_BEGIN_INSTR(Shl)
1376 VALUE_TO_INT(l, STACK_VALUE(lhs));
1377 VALUE_TO_INT(a, ACC);
1378 acc = Encode(l << (a & 0x1f));
1379 MOTH_END_INSTR(Shl)
1380
1381 MOTH_BEGIN_INSTR(BitAndConst)
1382 VALUE_TO_INT(a, ACC);
1383 acc = Encode(a & rhs);
1385 MOTH_END_INSTR(BitAndConst)
1386
1387 MOTH_BEGIN_INSTR(BitOrConst)
1388 VALUE_TO_INT(a, ACC);
1389 acc = Encode(a | rhs);
1390 MOTH_END_INSTR(BitOrConst)
1391
1392 MOTH_BEGIN_INSTR(BitXorConst)
1393 VALUE_TO_INT(a, ACC);
1394 acc = Encode(a ^ rhs);
1395 MOTH_END_INSTR(BitXorConst)
1396
1397 MOTH_BEGIN_INSTR(UShrConst)
1398 acc = Encode(ACC.toUInt32() >> uint(rhs));
1399 MOTH_END_INSTR(UShrConst)
1400
1401 MOTH_BEGIN_INSTR(ShrConst)
1402 VALUE_TO_INT(a, ACC);
1403 acc = Encode(a >> rhs);
1404 MOTH_END_INSTR(ShrConst)
1405
1406 MOTH_BEGIN_INSTR(ShlConst)
1407 VALUE_TO_INT(a, ACC);
1408 acc = Encode(a << rhs);
1409 MOTH_END_INSTR(ShlConst)
1410
1411 MOTH_BEGIN_INSTR(Ret)
1412 return acc;
1413 MOTH_END_INSTR(Ret)
1414
1415 MOTH_BEGIN_INSTR(InitializeBlockDeadTemporalZone)
1416 acc = Encode(Value::emptyValue());
1417 for (int i = firstReg, end = firstReg + count; i < end; ++i)
1418 STACK_VALUE(i) = acc;
1419 MOTH_END_INSTR(InitializeBlockDeadTemporalZone)
1420
1421 MOTH_BEGIN_INSTR(ThrowOnNullOrUndefined)
1422 if (Value::fromReturnedValue(acc).isNullOrUndefined()) {
1423 engine->throwTypeError();
1424 goto handleUnwind;
1425 }
1426 MOTH_END_INSTR(ThrowOnNullOrUndefined)
1427
1428 MOTH_BEGIN_INSTR(GetTemplateObject)
1429 acc = Runtime::GetTemplateObject::call(function, index);
1430 MOTH_END_INSTR(GetTemplateObject)
1431
1433#if QT_CONFIG(qml_debug)
1434 STORE_IP();
1435 debug_slowPath(engine);
1436#endif // QT_CONFIG(qml_debug)
1438
1439 handleUnwind:
1440 // We do start the exception handler in case of isInterrupted. The exception handler will
1441 // immediately abort, due to the same isInterrupted. We don't skip the exception handler
1442 // because the current behavior is easier to implement in the JIT.
1443 Q_ASSERT(engine->hasException || engine->isInterrupted.loadRelaxed() || frame->unwindLevel);
1444 if (!frame->unwindHandler) {
1445 acc = Encode::undefined();
1446 return acc;
1447 }
1448 code = frame->unwindHandler;
1449 }
1450}
\inmodule QtCore
Definition qbytearray.h:57
bool isInterrupted() const
QString toString() const
Returns the string value of this QJSValue, as defined in \l{ECMA-262} section 9.8,...
Definition qjsvalue.cpp:494
\inmodule QtCore\reentrant
QJsonObject object() const
Returns the QJsonObject contained in the document.
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore
Definition qmetatype.h:341
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QString & removeLast()
Definition qstring.h:558
QByteArray toUtf8() const &
Definition qstring.h:634
void leavingFunction(const ReturnedValue &)
bool pauseAtNextOpportunity() const
static QV4::ReturnedValue interpret(JSTypesStackFrame *frame, ExecutionEngine *engine, const char *codeEntry)
static void exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
QList< QVariant > arguments
double jsExponentiate(double base, double exponent)
static QMLJS_READONLY ReturnedValue mul_int32(int a, int b)
Definition qv4math_p.h:50
@ PREFERREDTYPE_HINT
static QMLJS_READONLY ReturnedValue add_int32(int a, int b)
Definition qv4math_p.h:34
quint64 ReturnedValue
ReturnedValue coerceAndCall(ExecutionEngine *engine, const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction, const Value *argv, int argc, Callable call)
static QMLJS_READONLY ReturnedValue sub_int32(int a, int b)
Definition qv4math_p.h:42
#define Q_UNLIKELY(x)
#define Q_NEVER_INLINE
#define Q_LIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static bool matches(const QJsonObject &object, const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease, const QOpenGLConfig::Gpu &gpu)
Definition qopengl.cpp:270
GLenum GLuint GLint level
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLenum condition
GLuint GLuint end
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLint left
GLuint GLsizei const GLchar * message
GLenum GLuint GLintptr offset
GLuint name
GLenum GLenum GLsizei void GLsizei void * column
GLenum func
Definition qopenglext.h:663
const GLubyte * c
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int void * arg
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
@ Success
Definition main.cpp:3325
#define Q_UNUSED(x)
#define Q_TRACE_SCOPE(x,...)
Definition qtrace_p.h:146
#define Q_TRACE_POINT(provider, tracepoint,...)
Definition qtrace_p.h:232
unsigned long long quint64
Definition qtypes.h:61
unsigned int uint
Definition qtypes.h:34
static const uint base
Definition qurlidna.cpp:20
#define CHECK_STACK_LIMITS(v4)
#define MOTH_BEGIN_INSTR(instr)
#define MOTH_END_INSTR(instr)
#define MOTH_NUM_INSTRUCTIONS()
#define FOR_EACH_MOTH_INSTR(F)
#define MOTH_JUMP_TABLE
#define MOTH_DISPATCH()
#define CHECK_EXCEPTION()
#define ACC
Q_QML_EXPORT int qt_v4DebuggerHook(const char *json)
#define STACK_VALUE(temp)
static const QV4::Value & constant(Function *function, int index)
#define VALUE_TO_INT(i, val)
@ ShowWhenDeoptimiationHappens
static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
static QV4::Value & stackValue(QV4::Value *stack, size_t slot, const JSTypesStackFrame *frame)
static Heap::CallContext * getScope(QV4::Value *stack, int level)
#define STORE_ACC()
#define STORE_IP()
Q_QML_EXPORT void qt_v4ResolvePendingBreakpointsHook()
Q_QML_EXPORT void qt_v4TriggeredBreakpointHook()
const char property[13]
Definition qwizard.cpp:101
QFile file
[0]
QFrame frame
[0]
QJSValueList args
QJSValue fullName
QJSEngine engine
[0]
AOTCompiledMetaMethod(const Function::AOTCompiledFunction *aotCompiledFunction)
QMetaType returnMetaType() const
QMetaType parameterMetaType(int i) const
static constexpr int HeaderSize()
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const
QString toQString() const
Definition qv4string_p.h:92
ReturnedValue(* globalGetter)(Lookup *l, ExecutionEngine *engine)
Definition qv4lookup_p.h:41
ReturnedValue(* qmlContextPropertyGetter)(Lookup *l, ExecutionEngine *engine, Value *thisObject)
Definition qv4lookup_p.h:42
ReturnedValue(* getter)(Lookup *l, ExecutionEngine *engine, const Value &object)
Definition qv4lookup_p.h:40
bool(* setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v)
Definition qv4lookup_p.h:43
static ReturnedValue objectDefaultValue(const Object *object, int typeHint)
static double stringToNumber(const QString &s)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, Value[], uint)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, uint, Value[], int)
static ReturnedValue call(ExecutionEngine *, int, Value[], int)
static ReturnedValue call(ExecutionEngine *, Value[], int)
static ReturnedValue call(ExecutionEngine *, const Value &, int, Value[], int)
static ReturnedValue call(ExecutionEngine *, uint, Value[], int)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int)
static void call(ExecutionEngine *)
static ReturnedValue call(ExecutionEngine *, int)
static Bool call(const Value &, const Value &)
static Bool call(const Value &, const Value &)
static Bool call(const Value &, const Value &)
static Bool call(const Value &, const Value &)
static Bool call(const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int)
static ReturnedValue call(ExecutionEngine *, const Value &)
static ReturnedValue call(ExecutionEngine *, int, const Value &, Value[])
static ReturnedValue call(ExecutionEngine *)
static ReturnedValue call(ExecutionEngine *, int)
static ReturnedValue call(ExecutionEngine *)
static void call(ExecutionEngine *, Bool, int)
static ReturnedValue call(ExecutionEngine *, Function *, int)
static ReturnedValue call(ExecutionEngine *, Function *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &)
static ReturnedValue call(const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &, int)
static ReturnedValue call(Function *, int)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value *)
static ReturnedValue call(ExecutionEngine *, const Value &, Value *)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, int)
static ReturnedValue call(ExecutionEngine *, const Value &, int)
static ReturnedValue call(ExecutionEngine *, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &)
static ReturnedValue call(const Value &, const Value &)
static ReturnedValue call(const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, int, Value[], int)
static void call(ExecutionEngine *)
static void call(ExecutionEngine *, int)
static void call(JSTypesStackFrame *)
static void call(ExecutionEngine *, int, int)
static void call(ExecutionEngine *, int)
static ReturnedValue call(ExecutionEngine *, const Value &)
static ReturnedValue call(ExecutionEngine *, int)
static void call(ExecutionEngine *, const Value &, const Value &, const Value &)
static void call(ExecutionEngine *, int, const Value &)
static void call(ExecutionEngine *, int, const Value &)
static void call(ExecutionEngine *, const Value &, int, const Value &)
static void call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(const Value &, const Value &)
static ReturnedValue call(const Value &, const Value &)
static ReturnedValue call(const Value &, const Value &)
static ReturnedValue call(JSTypesStackFrame *, ExecutionEngine *engine)
static void call(ExecutionEngine *, const Value &)
static void call(ExecutionEngine *, int)
static ReturnedValue call(ExecutionEngine *, int)
static ReturnedValue call(ExecutionEngine *, const Value &)
quint64 quickType() const
bool isManagedOrUndefined() const
constexpr ReturnedValue asReturnedValue() const
QV4_NEARLY_ALWAYS_INLINE double doubleValue() const
bool integerCompatible() const
bool isNullOrUndefined() const
bool isUndefined() const
QV4_NEARLY_ALWAYS_INLINE constexpr int int_32() const
static bool toBooleanImpl(Value val)
Definition qv4value.cpp:42
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
bool isString() const
Definition qv4value_p.h:284
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
static constexpr Value fromReturnedValue(ReturnedValue val)
Definition qv4value_p.h:165
const T * as() const
Definition qv4value_p.h:132
QString toQStringNoThrow() const
Definition qv4value.cpp:122
static constexpr Value emptyValue()
Definition qv4value_p.h:179
static Q_ALWAYS_INLINE void write(EngineBase *engine, Heap::Base *base, ReturnedValue *slot, ReturnedValue value)