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) {}
142static QVector<Breakpoint> qt_v4Breakpoints;
143static Breakpoint qt_v4LastStop;
145static void qt_v4TriggerBreakpoint(
const Breakpoint &bp,
QV4::Function *function)
174 if (command ==
"protocolVersion") {
178 int version = ob.value(
QLatin1String(
"version")).toString().toInt();
179 if (version != ProtocolVersion) {
180 return -WrongProtocol;
183 if (command ==
"insertBreakpoint") {
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;
195 if (command ==
"removeBreakpoint") {
196 int lineNumber = ob.value(
QLatin1String(
"lineNumber")).toString().toInt();
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();
228 QString engineName = function->sourceFile();
230 if (engineName.isEmpty())
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);
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);
347 return function->compilationUnit->constants[
index].asValue<
QV4::Value>();
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); \
402 : aotCompiledFunction(aotCompiledFunction)
416 if (
engine->checkStackLimits()) {
417 frame->setReturnValueUndefined();
423 Q_ASSERT(function->aotCompiledCode);
425 function->executableCompilationUnit()->fileName(),
426 function->compiledFunction->location.line(),
427 function->compiledFunction->location.column());
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;
444 aotContext.engine =
engine->jsEngine();
445 aotContext.compilationUnit = function->executableCompilationUnit();
446 function->aotCompiledCode(&aotContext, argv);
457 function->executableCompilationUnit()->fileName(),
458 function->compiledFunction->location.line(),
459 function->compiledFunction->location.column());
463#if QT_CONFIG(qml_jit)
464 if (debugger ==
nullptr) {
468 if (function->codeRef ==
nullptr) {
469 if (
engine->canJIT(function))
470 QV4::JIT::BaselineJIT(function).generate();
472 ++function->interpreterCallCount;
483 if (function->jittedCode !=
nullptr && debugger ==
nullptr) {
518 acc =
Encode(
static_cast<int>(0));
554 acc = function->compilationUnit->imports[
index]->asReturnedValue();
559 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
560 acc = cc->locals[
index].asReturnedValue();
566 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
572 acc = cc->locals[
index].asReturnedValue();
582 acc = function->compilationUnit->runtimeStrings[stringId]->asReturnedValue();
601 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups +
index;
608 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups +
index;
664 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups +
index;
668 .arg(
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->
nameIndex]->toQString())
682 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups +
index;
702 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups +
index;
722 frame->setYield(code);
723 frame->setYieldIsIterator(
false);
728 frame->setYield(code);
729 frame->setYieldIsIterator(
true);
735 if (
engine->hasException) {
739 engine->hasException =
false;
772 acc =
static_cast<const FunctionObject &
>(
func).call(stack + thisObject, stack + argv, argc);
784 Lookup *l = function->executableCompilationUnit()->runtimeLookups + lookupIndex;
788 .arg(
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->
nameIndex]->toQString())
800 acc = handler->
call(stack +
base, stack + argv, argc);
803 .arg(
engine->currentStackFrame->v4Function->compilationUnit
804 ->runtimeStrings[l->
nameIndex]->toQString())
873 if (
frame->unwindLevel) {
874 --
frame->unwindLevel;
875 if (
frame->unwindLevel)
877 code =
frame->unwindLabel;
903 acc =
engine->hasException ?
engine->exceptionValue->asReturnedValue()
905 engine->hasException =
false;
910 *
engine->exceptionValue = acc;
911 engine->hasException =
true;
1044 acc =
ACC.toObject(
engine)->asReturnedValue();
1055 takeJump =
ACC.int_32();
1057 takeJump =
ACC.toBoolean();
1065 takeJump = !
ACC.int_32();
1067 takeJump = !
ACC.toBoolean();
1073 if (!
engine->hasException)
1095 if (
ACC.isIntOrBool()) {
1105 if (
ACC.isIntOrBool()) {
1106 acc =
Encode(
bool(
ACC.int_32() != lhs));
1142 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1155 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1168 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1181 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1224 if (
ACC.integerCompatible()) {
1225 acc =
Encode(!
static_cast<bool>(
ACC.int_32()));
1240 int a =
ACC.int_32();
1241 if (
a == 0 ||
a == std::numeric_limits<int>::min()) {
1242 acc =
Encode(-
static_cast<double>(
a));
1246 }
else if (
ACC.isDouble()) {
1247 acc ^= (1ull << 63);
1262 }
else if (
ACC.isDouble()) {
1273 }
else if (
ACC.isDouble()) {
1285 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1298 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1316 double exp =
ACC.toNumber();
1324 }
else if (
left.isNumber() &&
ACC.isNumber()) {
1372 acc =
Encode(l >> (
a & 0x1f));
1378 acc =
Encode(l << (
a & 0x1f));
1423 engine->throwTypeError();
1433#if QT_CONFIG(qml_debug)
1444 if (!
frame->unwindHandler) {
1448 code =
frame->unwindHandler;
bool isInterrupted() const
QString toString() const
Returns the string value of this QJSValue, as defined in \l{ECMA-262} section 9.8,...
\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
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
QByteArray toUtf8() const &
void leavingFunction(const ReturnedValue &)
void maybeBreakAtInstruction()
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)
static QMLJS_READONLY ReturnedValue add_int32(int a, int b)
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)
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)
GLenum GLuint GLint level
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLuint GLsizei const GLchar * message
GLenum GLuint GLintptr offset
GLenum GLenum GLsizei void GLsizei void * column
QLatin1StringView QLatin1String
#define QStringLiteral(str)
#define Q_TRACE_SCOPE(x,...)
#define Q_TRACE_POINT(provider, tracepoint,...)
unsigned long long quint64
#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()
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
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 &)
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()
static Q_ALWAYS_INLINE void write(EngineBase *engine, Heap::Base *base, ReturnedValue *slot, ReturnedValue value)