6#include <QtCore/qjsondocument.h>
7#include <QtCore/qjsonobject.h>
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>
31#include <private/qv4baselinejit_p.h>
34#include <qtqml_tracepoints_p.h>
36#undef COUNT_INSTRUCTIONS
120#if QT_CONFIG(qml_debug)
121static int qt_v4BreakpointCount = 0;
122static bool qt_v4IsDebugging =
false;
123static bool qt_v4IsStepping =
false;
128 Breakpoint() : bpNumber(0), lineNumber(-1) {}
143static Breakpoint qt_v4LastStop;
145static void qt_v4TriggerBreakpoint(
const Breakpoint &bp,
QV4::Function *function)
174 if (command ==
"protocolVersion") {
179 if (version != ProtocolVersion) {
180 return -WrongProtocol;
183 if (command ==
"insertBreakpoint") {
185 bp.bpNumber = ++qt_v4BreakpointCount;
190 qt_v4Breakpoints.
append(bp);
191 qt_v4IsDebugging =
true;
195 if (command ==
"removeBreakpoint") {
198 if (qt_v4Breakpoints.
last().matches(
fullName, lineNumber)) {
200 qt_v4IsDebugging = !qt_v4Breakpoints.
isEmpty();
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();
209 return -NoSuchBreakpoint;
212 if (command ==
"prepareStep") {
213 qt_v4IsStepping =
true;
218 return -NoSuchCommand;
223 if (!qt_v4IsStepping && !qt_v4Breakpoints.
size())
226 const int lineNumber =
frame->lineNumber();
233 if (qt_v4IsStepping) {
234 if (qt_v4LastStop.lineNumber != lineNumber
235 || qt_v4LastStop.engineName != engineName) {
236 qt_v4IsStepping =
false;
239 bp.lineNumber = lineNumber;
240 bp.engineName = engineName;
241 qt_v4TriggerBreakpoint(bp, function);
246 for (
int i = qt_v4Breakpoints.
size(); --
i >= 0; ) {
247 const Breakpoint &bp = qt_v4Breakpoints.
at(
i);
248 if (bp.lineNumber != lineNumber)
250 if (bp.engineName != engineName)
253 qt_v4TriggerBreakpoint(bp, function);
261 debugger->maybeBreakAtInstruction();
262 if (qt_v4IsDebugging)
263 qt_v4CheckForBreak(
engine->currentStackFrame);
272#ifdef COUNT_INSTRUCTIONS
273static struct InstrCount {
275 fprintf(stderr,
"Counting instructions...\n");
280 fprintf(stderr,
"Instruction count:\n");
282 fprintf(stderr, "%llu : %s\n", hits[int(Instr::Type::I)], #I);
291#define MOTH_BEGIN_INSTR_COMMON(instr) \
293 INSTR_##instr(MOTH_DECODE)
295#ifdef COUNT_INSTRUCTIONS
296# define MOTH_BEGIN_INSTR(instr) \
297 MOTH_BEGIN_INSTR_COMMON(instr) \
298 instrCount.hit(Instr::Type::instr);
300# define MOTH_BEGIN_INSTR(instr) \
301 MOTH_BEGIN_INSTR_COMMON(instr)
304#ifdef MOTH_COMPUTED_GOTO
305#define MOTH_END_INSTR(instr) \
306 MOTH_DISPATCH_SINGLE() \
309#define MOTH_END_INSTR(instr) \
317 +
frame->jsFrame->argc()
318 +
frame->v4Function->compiledFunction->nRegisters);
324#define STACK_VALUE(temp) stackValue(stack, temp, frame)
327#ifdef CHECK_EXCEPTION
328#undef CHECK_EXCEPTION
330#define CHECK_EXCEPTION \
331 if (engine->hasException || engine->isInterrupted.loadRelaxed()) \
339 scope = scope->outer;
342 return static_cast<Heap::CallContext *
>(scope);
357 if (lhs.m()->internalClass->vtable->
isString)
371 return lhs.
int_32() == rhs;
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) \
383 if (Q_LIKELY(val.integerCompatible())) { \
387 if (val.isDouble()) \
388 d = val.doubleValue(); \
391 d = val.toNumberImpl(); \
394 i = QJSNumberCoercion::toInteger(d); \
401 if (
engine->checkStackLimits()) {
402 frame->setReturnValueUndefined();
410 function->executableCompilationUnit()->fileName(),
411 function->compiledFunction->location.line(),
412 function->compiledFunction->location.column());
415 const qsizetype numFunctionArguments =
function->aotCompiledFunction->argumentTypes.size();
419 const bool isValid =
frame->argc() >
i;
423 if (isValid && argumentType == frameType)
426 if (transformedArguments ==
nullptr) {
427 Q_ALLOCA_ASSIGN(
void *, transformedArguments, numFunctionArguments *
sizeof(
void *));
428 memcpy(transformedArguments,
frame->argv(),
frame->argc() *
sizeof(
void *));
431 if (argumentType.
sizeOf() == 0) {
432 transformedArguments[
i] =
nullptr;
436 void *frameVal = isValid ?
frame->argv()[
i] :
nullptr;
437 if (isValid && frameType == QMetaType::fromType<QVariant>()) {
441 if (variantType == argumentType) {
449 transformedArguments[
i] =
arg;
456 if (argumentType == QMetaType::fromType<QVariant>()) {
461 }
else if (argumentType == QMetaType::fromType<QJSPrimitiveValue>()) {
473 transformedArguments[
i] =
arg;
478 bool returnsQVariantWrapper =
false;
480 if (
frame->returnValue() && returnType != frameReturn) {
481 if (frameReturn == QMetaType::fromType<QVariant>()) {
482 void *returnValue =
frame->returnValue();
483 new (returnValue)
QVariant(returnType);
484 transformedResult =
static_cast<QVariant *
>(returnValue)->
data();
485 returnsQVariantWrapper =
true;
486 }
else if (returnType.
sizeOf() > 0) {
489 transformedResult =
frame;
495 QV4::Heap::QQmlContextWrapper *
wrapper =
static_cast<Heap::QmlContext *
>(
context)->qml();
503 function->aotCompiledFunction->functionPtr(
504 &aotContext, transformedResult ? transformedResult :
frame->returnValue(),
505 transformedArguments ? transformedArguments :
frame->argv());
507 if (transformedResult && !returnsQVariantWrapper) {
517 }
else if (returnType == QMetaType::fromType<QVariant>()) {
519 if (resultVariant->
metaType() == frameReturn) {
525 frameReturn,
frame->returnValue());
532 returnType.
destruct(transformedResult);
536 if (transformedArguments) {
537 for (
int i = 0;
i < numFunctionArguments; ++
i) {
538 void *
arg = transformedArguments[
i];
542 function->aotCompiledFunction->argumentTypes[
i].destruct(
arg);
554 function->executableCompilationUnit()->fileName(),
555 function->compiledFunction->location.line(),
556 function->compiledFunction->location.column());
560#if QT_CONFIG(qml_jit)
567 QV4::JIT::BaselineJIT(
function).generate();
615 acc =
Encode(
static_cast<int>(0));
651 acc =
function->compilationUnit->imports[
index]->asReturnedValue();
656 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
657 acc = cc->locals[
index].asReturnedValue();
663 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
669 acc = cc->locals[
index].asReturnedValue();
679 acc =
function->compilationUnit->runtimeStrings[stringId]->asReturnedValue();
765 .arg(
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->
nameIndex]->toQString())
820 frame->setYield(code);
821 frame->setYieldIsIterator(
false);
826 frame->setYield(code);
827 frame->setYieldIsIterator(
true);
833 if (
engine->hasException) {
837 engine->hasException =
false;
869 acc =
static_cast<const FunctionObject &
>(
func).call(stack + thisObject, stack + argv, argc);
881 Lookup *l =
function->executableCompilationUnit()->runtimeLookups + lookupIndex;
885 .arg(
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->
nameIndex]->toQString())
896 .arg(
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->
nameIndex]->toQString())
966 if (
frame->unwindLevel) {
967 --
frame->unwindLevel;
968 if (
frame->unwindLevel)
970 code =
frame->unwindLabel;
996 acc =
engine->hasException ?
engine->exceptionValue->asReturnedValue()
998 engine->hasException =
false;
1003 *
engine->exceptionValue = acc;
1004 engine->hasException =
true;
1138 acc =
ACC.toObject(
engine)->asReturnedValue();
1149 takeJump =
ACC.int_32();
1151 takeJump =
ACC.toBoolean();
1159 takeJump = !
ACC.int_32();
1161 takeJump = !
ACC.toBoolean();
1167 if (!
engine->hasException)
1189 if (
ACC.isIntOrBool()) {
1199 if (
ACC.isIntOrBool()) {
1200 acc =
Encode(
bool(
ACC.int_32() != lhs));
1236 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1249 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1262 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1275 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1318 if (
ACC.integerCompatible()) {
1319 acc =
Encode(!
static_cast<bool>(
ACC.int_32()));
1334 int a =
ACC.int_32();
1335 if (
a == 0 ||
a == std::numeric_limits<int>::min()) {
1336 acc =
Encode(-
static_cast<double>(
a));
1340 }
else if (
ACC.isDouble()) {
1341 acc ^= (1ull << 63);
1356 }
else if (
ACC.isDouble()) {
1367 }
else if (
ACC.isDouble()) {
1379 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1392 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1410 double exp =
ACC.toNumber();
1418 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1466 acc =
Encode(l >> (
a & 0x1f));
1472 acc =
Encode(l << (
a & 0x1f));
1517 engine->throwTypeError();
1527#if QT_CONFIG(qml_debug)
1538 if (!
frame->unwindHandler) {
1542 code =
frame->unwindHandler;
bool isInterrupted() const
The QJSPrimitiveValue class operates on primitive types in JavaScript semantics.
\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
QJsonValue value(const QString &key) const
Returns a QJsonValue representing the value for the key key.
QString toString() const
Converts the value to a QString and returns it.
qsizetype size() const noexcept
bool isEmpty() const noexcept
const_reference at(qsizetype i) const noexcept
void removeLast() noexcept
void append(parameter_type t)
bool inherits(const char *classname) const
Returns true if this object is an instance of a class that inherits className or a QObject subclass t...
\macro QT_RESTRICTED_CAST_FROM_ASCII
int toInt(bool *ok=nullptr, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QByteArray toUtf8() const &
static QV4::ReturnedValue interpret(JSTypesStackFrame *frame, ExecutionEngine *engine, const char *codeEntry)
static void exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
~QVariant()
Destroys the QVariant and the contained object.
QMetaType metaType() const
QList< QVariant > arguments
double jsExponentiate(double base, double exponent)
void write(EngineBase *engine, Heap::Base *base, ReturnedValue *slot, ReturnedValue value)
\qmltype Particle \inqmlmodule QtQuick.Particles
static QMLJS_READONLY ReturnedValue mul_int32(int a, int b)
static QMLJS_READONLY ReturnedValue add_int32(int a, int b)
static QMLJS_READONLY ReturnedValue sub_int32(int a, int b)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static bool matches(const QJsonObject &object, const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease, const QOpenGLConfig::Gpu &gpu)
GLenum GLuint GLint level
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLenum GLenum GLsizei void GLsizei void * column
QLatin1StringView QLatin1String
#define QStringLiteral(str)
static DebuggerProgram debugger
#define Q_TRACE_SCOPE(x,...)
#define Q_TRACE_POINT(provider, tracepoint,...)
unsigned long long quint64
#define Q_ALLOCA_VAR(type, name, size)
#define Q_ALLOCA_ASSIGN(type, name, size)
#define Q_ALLOCA_DECLARE(type, name)
#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 CHECK_EXCEPTION()
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)
Q_QML_EXPORT void qt_v4ResolvePendingBreakpointsHook()
Q_QML_EXPORT void qt_v4TriggeredBreakpointHook()
QQmlContextData * qmlContext
QV4::ExecutableCompilationUnit * compilationUnit
static constexpr int HeaderSize()
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
Heap::QmlContext * qmlContext() const
QString toQString() const
ReturnedValue(* globalGetter)(Lookup *l, ExecutionEngine *engine)
ReturnedValue(* qmlContextPropertyGetter)(Lookup *l, ExecutionEngine *engine, Value *thisObject)
ReturnedValue(* getter)(Lookup *l, ExecutionEngine *engine, const Value &object)
bool(* setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v)
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 &, 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
QV4_NEARLY_ALWAYS_INLINE constexpr int int_32() const
static bool toBooleanImpl(Value val)
static constexpr Value fromInt32(int i)
static constexpr Value undefinedValue()
static constexpr Value fromReturnedValue(ReturnedValue val)
QString toQStringNoThrow() const
static constexpr Value emptyValue()