diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 5 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 130 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 31 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 28 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 65 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 144 |
10 files changed, 166 insertions, 243 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index 1fa1852d80..c9b7c4ae7e 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -75,11 +75,6 @@ QByteArray BytecodeGenerator::finalize() { QByteArray code; - Instruction::InitStackFrame init; - init.instructionType = Instr::InitStackFrame; - init.value = regCount; - code.append(reinterpret_cast<const char *>(&init), InstrMeta<Instr::InitStackFrame>::Size); - // content QVector<int> instructionOffsets; instructionOffsets.reserve(instructions.size()); diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index bfb1ada6e4..81b64f96da 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -195,6 +195,7 @@ public: int newRegister(); int newRegisterArray(int n); + int registerCount() const { return regCount; } QByteArray finalize(); diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index d3cfdbb7fc..82270ee086 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -619,7 +619,7 @@ bool Codegen::visit(ArrayLiteral *ast) Instruction::CallBuiltinDefineArray call; call.argc = argc; - call.args = Moth::StackSlot::create(args); + call.args = Moth::StackSlot::createRegister(args); bytecodeGenerator->addInstruction(call); _expr.setResult(Reference::fromAccumulator(this)); @@ -1089,7 +1089,7 @@ Moth::StackSlot Codegen::pushArgs(ArgumentList *args) ++argc; } - return Moth::StackSlot::create(calldata); + return Moth::StackSlot::createRegister(calldata); } bool Codegen::visit(ConditionalExpression *ast) @@ -1133,11 +1133,11 @@ bool Codegen::visit(DeleteExpression *ast) switch (expr.type) { case Reference::StackSlot: - if (!expr.stackSlotIsLocal) + if (!expr.stackSlotIsLocalOrArgument) break; // fall through - case Reference::Local: - case Reference::Argument: + case Reference::ScopedArgument: + case Reference::ScopedLocal: // Trying to delete a function argument might throw. if (_context->isStrict) { throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode.")); @@ -1219,7 +1219,7 @@ bool Codegen::visit(FunctionExpression *ast) Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs) { - uint scope = 0; + int scope = 0; Context *c = _context; while (c->parent) { @@ -1228,7 +1228,8 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs) Context::Member m = c->findMember(name); if (m.type != Context::UndefinedMember) { - Reference r = m.canEscape ? Reference::fromLocal(this, m.index, scope) : Reference::fromStackSlot(this, m.index, true /*isLocal*/); + Reference r = m.canEscape ? Reference::fromScopedLocal(this, m.index, scope) + : Reference::fromStackSlot(this, m.index, true /*isLocal*/); if (name == QLatin1String("arguments") || name == QLatin1String("eval")) { r.isArgOrEval = true; if (isLhs && c->isStrict) @@ -1238,8 +1239,14 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs) return r; } const int argIdx = c->findArgument(name); - if (argIdx != -1) - return Reference::fromArgument(this, argIdx, scope); + if (argIdx != -1) { + if (c->argumentsCanEscape || c->usesArgumentsObject == Context::ArgumentsObjectUsed) { + return Reference::fromScopedArgument(this, argIdx, scope); + } else { + Q_ASSERT(scope == 0); + return Reference::fromArgument(this, argIdx); + } + } if (!c->isStrict && c->hasDirectEval) goto loadByName; @@ -1487,7 +1494,7 @@ bool Codegen::visit(ObjectLiteral *ast) call.internalClassId = classId; call.arrayValueCount = arrayKeyWithValue.size(); call.arrayGetterSetterCountAndFlags = arrayGetterSetterCountAndFlags; - call.args = Moth::StackSlot::create(args); + call.args = Moth::StackSlot::createRegister(args); bytecodeGenerator->addInstruction(call); _expr.setResult(Reference::fromAccumulator(this)); @@ -1770,7 +1777,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, Reference::fromName(this, member.function->name.toString()).storeConsumeAccumulator(); } else { Q_ASSERT(member.index >= 0); - Reference local = member.canEscape ? Reference::fromLocal(this, member.index, 0) : Reference::fromStackSlot(this, member.index, true); + Reference local = member.canEscape ? Reference::fromScopedLocal(this, member.index, 0) + : Reference::fromStackSlot(this, member.index, true); local.storeConsumeAccumulator(); } } @@ -1800,9 +1808,11 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, } _context->code = bytecodeGenerator->finalize(); + _context->registerCount = bytecodeGenerator->registerCount(); static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); if (showCode) { - qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict; + qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict + << "register count" << _context->registerCount; QV4::Moth::dumpBytecode(_context->code); qDebug(); } @@ -2442,7 +2452,7 @@ bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, if (str == QLatin1String("eval") || str == QLatin1String("arguments")) { isArgOrEval = true; } - } else if (r.type == Reference::Local || r.type == Reference::StackSlot) { + } else if (r.type == Reference::ScopedLocal || r.isRegister()) { isArgOrEval = r.isArgOrEval; } if (isArgOrEval) @@ -2544,7 +2554,7 @@ bool Codegen::RValue::operator==(const RValue &other) const } } -Codegen::RValue Codegen::RValue::storeInTemp() const +Codegen::RValue Codegen::RValue::storeOnStack() const { switch (type) { case Accumulator: @@ -2574,8 +2584,8 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other) case StackSlot: theStackSlot = other.theStackSlot; break; - case Local: - case Argument: + case ScopedLocal: + case ScopedArgument: index = other.index; scope = other.scope; break; @@ -2611,7 +2621,7 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other) isArgOrEval = other.isArgOrEval; codegen = other.codegen; isReadonly = other.isReadonly; - stackSlotIsLocal = other.stackSlotIsLocal; + stackSlotIsLocalOrArgument = other.stackSlotIsLocalOrArgument; global = other.global; return *this; } @@ -2626,8 +2636,8 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const break; case StackSlot: return theStackSlot == other.theStackSlot; - case Local: - case Argument: + case ScopedLocal: + case ScopedArgument: return index == other.index && scope == other.scope; case Name: return unqualifiedNameIndex == other.unqualifiedNameIndex; @@ -2675,14 +2685,14 @@ Codegen::Reference Codegen::Reference::asLValue() const case Member: if (!propertyBase.isStackSlot()) { Reference r = *this; - r.propertyBase = propertyBase.storeInTemp(); + r.propertyBase = propertyBase.storeOnStack(); return r; } return *this; case Subscript: if (!elementSubscript.isStackSlot()) { Reference r = *this; - r.elementSubscript = elementSubscript.storeInTemp(); + r.elementSubscript = elementSubscript.storeOnStack(); return r; } return *this; @@ -2750,8 +2760,8 @@ bool Codegen::Reference::storeWipesAccumulator() const Q_UNREACHABLE(); return false; case StackSlot: - case Local: - case Argument: + case ScopedLocal: + case ScopedArgument: return false; case Name: case Member: @@ -2772,30 +2782,20 @@ void Codegen::Reference::storeAccumulator() const codegen->bytecodeGenerator->addInstruction(store); return; } - case Local: - if (scope == 0) { - Instruction::StoreLocal store; - store.index = index; - codegen->bytecodeGenerator->addInstruction(store); - } else { - Instruction::StoreScopedLocal store; - store.index = index; - store.scope = scope; - codegen->bytecodeGenerator->addInstruction(store); - } + case ScopedLocal: { + Instruction::StoreScopedLocal store; + store.index = index; + store.scope = scope; + codegen->bytecodeGenerator->addInstruction(store); return; - case Argument: - if (scope == 0) { - Instruction::StoreArg store; - store.index = index; - codegen->bytecodeGenerator->addInstruction(store); - } else { - Instruction::StoreScopedArg store; - store.index = index; - store.scope = scope; - codegen->bytecodeGenerator->addInstruction(store); - } + } + case ScopedArgument: { + Instruction::StoreScopedArgument store; + store.index = index; + store.scope = scope; + codegen->bytecodeGenerator->addInstruction(store); return; + } case Name: { Instruction::StoreName store; store.name = unqualifiedNameIndex; @@ -2859,30 +2859,20 @@ void Codegen::Reference::loadInAccumulator() const load.reg = stackSlot(); codegen->bytecodeGenerator->addInstruction(load); } return; - case Local: - if (scope == 0) { - Instruction::LoadLocal load; - load.index = index; - codegen->bytecodeGenerator->addInstruction(load); - } else { - Instruction::LoadScopedLocal load; - load.index = index; - load.scope = scope; - codegen->bytecodeGenerator->addInstruction(load); - } + case ScopedLocal: { + Instruction::LoadScopedLocal load; + load.index = index; + load.scope = scope; + codegen->bytecodeGenerator->addInstruction(load); return; - case Argument: - if (scope == 0) { - Instruction::LoadArg load; - load.index = index; - codegen->bytecodeGenerator->addInstruction(load); - } else { - Instruction::LoadScopedArg load; - load.index = index; - load.scope = scope; - codegen->bytecodeGenerator->addInstruction(load); - } + } + case ScopedArgument: { + Instruction::LoadScopedArgument load; + load.index = index; + load.scope = scope; + codegen->bytecodeGenerator->addInstruction(load); return; + } case Name: if (codegen->useFastLookups && global) { Instruction::GetGlobalLookup load; @@ -2902,7 +2892,7 @@ void Codegen::Reference::loadInAccumulator() const codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::GetLookup load; - load.base = propertyBase.storeInTemp().stackSlot(); + load.base = propertyBase.storeOnStack().stackSlot(); load.index = codegen->registerGetterLookup(propertyNameIndex); codegen->bytecodeGenerator->addInstruction(load); } @@ -2913,7 +2903,7 @@ void Codegen::Reference::loadInAccumulator() const codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadProperty load; - load.base = propertyBase.storeInTemp().stackSlot(); + load.base = propertyBase.storeOnStack().stackSlot(); load.name = propertyNameIndex; codegen->bytecodeGenerator->addInstruction(load); } @@ -2932,7 +2922,7 @@ void Codegen::Reference::loadInAccumulator() const } else { Instruction::LoadElement load; load.base = elementBase; - load.index = elementSubscript.storeInTemp().stackSlot(); + load.index = elementSubscript.storeOnStack().stackSlot(); codegen->bytecodeGenerator->addInstruction(load); } } return; diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 2a482196ca..56bed33c19 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -155,15 +155,15 @@ public: return constant; } - Q_REQUIRED_RESULT RValue storeInTemp() const; + Q_REQUIRED_RESULT RValue storeOnStack() const; }; struct Reference { enum Type { Invalid, Accumulator, StackSlot, - Local, - Argument, + ScopedLocal, + ScopedArgument, Name, Member, Subscript, @@ -202,6 +202,9 @@ public: bool isConst() const { return type == Const; } bool isAccumulator() const { return type == Accumulator; } bool isStackSlot() const { return type == StackSlot; } + bool isRegister() const { + return isStackSlot() && theStackSlot.isRegister(); + } static Reference fromAccumulator(Codegen *cg) { return Reference(cg, Accumulator); @@ -210,18 +213,24 @@ public: Reference r(cg, StackSlot); if (tempIndex == -1) tempIndex = cg->bytecodeGenerator->newRegister(); - r.theStackSlot = Moth::StackSlot::create(tempIndex); - r.stackSlotIsLocal = isLocal; + r.theStackSlot = Moth::StackSlot::createRegister(tempIndex); + r.stackSlotIsLocalOrArgument = isLocal; + return r; + } + static Reference fromArgument(Codegen *cg, int index) { + Reference r(cg, StackSlot); + r.theStackSlot = Moth::StackSlot::createArgument(index); + r.stackSlotIsLocalOrArgument = true; return r; } - static Reference fromLocal(Codegen *cg, uint index, uint scope) { - Reference r(cg, Local); + static Reference fromScopedLocal(Codegen *cg, int index, int scope) { + Reference r(cg, ScopedLocal); r.index = index; r.scope = scope; return r; } - static Reference fromArgument(Codegen *cg, uint index, uint scope) { - Reference r(cg, Argument); + static Reference fromScopedArgument(Codegen *cg, int index, int scope) { + Reference r(cg, ScopedArgument); r.index = index; r.scope = scope; return r; @@ -298,7 +307,7 @@ public: Moth::StackSlot theStackSlot; QV4::ReturnedValue constant; int unqualifiedNameIndex; - struct { // Argument/Local + struct { // Scoped arguments/Local int index; int scope; }; @@ -320,7 +329,7 @@ public: }; mutable bool isArgOrEval = false; bool isReadonly = false; - bool stackSlotIsLocal = false; + bool stackSlotIsLocalOrArgument = false; bool global = false; Codegen *codegen; diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 5f83c1bd19..9ffd2b2b1d 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -223,6 +223,7 @@ struct Function LEUInt32 nLocals; LEUInt32 localsOffset; LEUInt32 nInnerFunctions; + LEUInt32 nRegisters; Location location; // Qml Extensions Begin diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 8c15be5477..3d42dff662 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -336,6 +336,8 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte function->nInnerFunctions = irFunction->nestedContexts.size(); + function->nRegisters = irFunction->registerCount; + function->nDependingIdObjects = 0; function->nDependingContextProperties = 0; function->nDependingScopeProperties = 0; diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index f3481f0251..0a204d8c24 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -103,7 +103,7 @@ struct Context { QString name; int line = 0; int column = 0; - + int registerCount = 0; int functionIndex = -1; enum MemberType { diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index e2bd3c73b9..9f5413bcf2 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -142,22 +142,6 @@ void dumpBytecode(const char *code, int len) d << instr.destTemp << ", C" << instr.constIndex; MOTH_END_INSTR(MoveConst) - MOTH_BEGIN_INSTR(LoadLocal) - d << "$" << instr.index; - MOTH_END_INSTR(LoadLocal) - - MOTH_BEGIN_INSTR(StoreLocal) - d << "$" << instr.index; - MOTH_END_INSTR(StoreLocal) - - MOTH_BEGIN_INSTR(LoadArg) - d << "#" << instr.index; - MOTH_END_INSTR(LoadArg) - - MOTH_BEGIN_INSTR(StoreArg) - d << "#" << instr.index; - MOTH_END_INSTR(StoreArg) - MOTH_BEGIN_INSTR(LoadScopedLocal) d << "$" << instr.index << "@" << instr.scope; MOTH_END_INSTR(LoadScopedLocal) @@ -166,13 +150,13 @@ void dumpBytecode(const char *code, int len) d << ", " << "$" << instr.index << "@" << instr.scope; MOTH_END_INSTR(StoreScopedLocal) - MOTH_BEGIN_INSTR(LoadScopedArg) + MOTH_BEGIN_INSTR(LoadScopedArgument) d << "#" << instr.index << "@" << instr.scope; - MOTH_END_INSTR(LoadScopedArg) + MOTH_END_INSTR(LoadScopedArgument) - MOTH_BEGIN_INSTR(StoreScopedArg) + MOTH_BEGIN_INSTR(StoreScopedArgument) d << "#" << instr.index << "@" << instr.scope; - MOTH_END_INSTR(StoreScopedArg) + MOTH_END_INSTR(StoreScopedArgument) MOTH_BEGIN_INSTR(LoadRuntimeString) d << instr.stringId; @@ -262,10 +246,6 @@ void dumpBytecode(const char *code, int len) d << instr.base << "[" << instr.index << "]"; MOTH_END_INSTR(LoadIdObject) - MOTH_BEGIN_INSTR(InitStackFrame) - d << instr.value; - MOTH_END_INSTR(InitStackFrame) - MOTH_BEGIN_INSTR(CallValue) d << instr.dest << "(" << instr.callData << ")"; MOTH_END_INSTR(CallValue) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index c22be0c0fe..19d521dbe3 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -76,14 +76,10 @@ QT_BEGIN_NAMESPACE F(LoadReg, loadReg) \ F(StoreReg, storeReg) \ F(MoveReg, moveReg) \ - F(LoadLocal, loadLocal) \ - F(StoreLocal, storeLocal) \ - F(LoadArg, loadArg) \ - F(StoreArg, storeArg) \ F(LoadScopedLocal, loadScopedLocal) \ F(StoreScopedLocal, storeScopedLocal) \ - F(LoadScopedArg, loadScopedArg) \ - F(StoreScopedArg, storeScopedArg) \ + F(LoadScopedArgument, loadScopedArgument) \ + F(StoreScopedArgument, storeScopedArgument) \ F(LoadRuntimeString, loadRuntimeString) \ F(LoadRegExp, loadRegExp) \ F(LoadClosure, loadClosure) \ @@ -106,7 +102,6 @@ QT_BEGIN_NAMESPACE F(LoadScopeObjectProperty, loadScopeObjectProperty) \ F(LoadContextObjectProperty, loadContextObjectProperty) \ F(LoadIdObject, loadIdObject) \ - F(InitStackFrame, initStackFrame) \ F(CallValue, callValue) \ F(CallProperty, callProperty) \ F(CallPropertyLookup, callPropertyLookup) \ @@ -190,12 +185,33 @@ class StackSlot { int index; public: - static StackSlot create(int index) { + static StackSlot createRegister(int index) { + Q_ASSERT(index >= 0); StackSlot t; t.index = index; return t; } + static StackSlot createArgument(int index) { + Q_ASSERT(index >= 0); + StackSlot t; + t.index = -index - 1; + return t; + } + + bool isRegister() const { return index >= 0; } + bool isArgument() const { return index < 0; } + +// int tempIndex() const { +// Q_ASSERT(isTemp()); +// return index; +// } + +// int argIndex() const { +// Q_ASSERT(isArg()); +// return -index - 1; +// } + int stackSlot() const { return index; } }; @@ -258,22 +274,6 @@ union Instr StackSlot srcReg; StackSlot destReg; }; - struct instr_loadLocal { - MOTH_INSTR_HEADER - int index; - }; - struct instr_storeLocal { - MOTH_INSTR_HEADER - int index; - }; - struct instr_loadArg { - MOTH_INSTR_HEADER - int index; - }; - struct instr_storeArg { - MOTH_INSTR_HEADER - int index; - }; struct instr_loadScopedLocal { MOTH_INSTR_HEADER int scope; @@ -284,12 +284,12 @@ union Instr int scope; int index; }; - struct instr_loadScopedArg { + struct instr_loadScopedArgument { MOTH_INSTR_HEADER int scope; int index; }; - struct instr_storeScopedArg { + struct instr_storeScopedArgument { MOTH_INSTR_HEADER int scope; int index; @@ -399,10 +399,6 @@ union Instr StackSlot base; StackSlot index; }; - struct instr_initStackFrame { - MOTH_INSTR_HEADER - int value; - }; struct instr_callValue { MOTH_INSTR_HEADER StackSlot callData; @@ -682,14 +678,10 @@ union Instr instr_loadReg loadReg; instr_storeReg storeReg; instr_moveReg moveReg; - instr_loadLocal loadLocal; - instr_storeLocal storeLocal; - instr_loadArg loadArg; - instr_storeArg storeArg; instr_loadScopedLocal loadScopedLocal; instr_storeScopedLocal storeScopedLocal; - instr_loadScopedArg loadScopedArg; - instr_storeScopedArg storeScopedArg; + instr_loadScopedArgument loadScopedArgument; + instr_storeScopedArgument storeScopedArgument; instr_loadRuntimeString loadRuntimeString; instr_loadRegExp loadRegExp; instr_loadClosure loadClosure; @@ -712,7 +704,6 @@ union Instr instr_setLookup setLookup; instr_storeScopeObjectProperty storeScopeObjectProperty; instr_storeContextObjectProperty storeContextObjectProperty; - instr_initStackFrame initStackFrame; instr_callValue callValue; instr_callProperty callProperty; instr_callPropertyLookup callPropertyLookup; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 4ccd133d73..348751f0cb 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -393,25 +393,46 @@ static inline QV4::Heap::ExecutionContext *getScope(QV4::Heap::ExecutionContext return scope; } -static inline void storeLocal(ExecutionEngine *engine, QV4::Heap::ExecutionContext *scope, - QV4::Value *slot, QV4::Value value) +static inline ReturnedValue loadScopedLocal(ExecutionEngine *engine, int index, int scope) { - Q_ASSERT(scope->type == QV4::Heap::ExecutionContext::Type_CallContext); + auto ctxt = getScope(engine->current, scope); + Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext); + auto cc = static_cast<Heap::CallContext *>(ctxt); + return cc->locals[index].asReturnedValue(); +} + +static inline void storeScopedLocal(ExecutionEngine *engine, int index, int scope, + const QV4::Value &value) +{ + auto ctxt = getScope(engine->current, scope); + Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext); + auto cc = static_cast<Heap::CallContext *>(ctxt); + if (Q_UNLIKELY(engine->writeBarrierActive)) - QV4::WriteBarrier::write(engine, scope, slot, value); + QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, value); else - *slot = value; + *(cc->locals.values + index) = value; } -static inline void storeArg(ExecutionEngine *engine, QV4::Heap::ExecutionContext *scope, - QV4::Value *slot, QV4::Value value) +static inline ReturnedValue loadScopedArg(ExecutionEngine *engine, int index, int scope) { - Q_ASSERT(scope->type == QV4::Heap::ExecutionContext::Type_SimpleCallContext - || scope->type == QV4::Heap::ExecutionContext::Type_CallContext); + auto ctxt = getScope(engine->current, scope); + Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext); + auto cc = static_cast<Heap::CallContext *>(ctxt); + return cc->callData->args[index].asReturnedValue(); +} + +static inline void storeScopedArg(ExecutionEngine *engine, int index, int scope, + const QV4::Value &value) +{ + auto ctxt = getScope(engine->current, scope); + Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext); + auto cc = static_cast<Heap::CallContext *>(ctxt); + if (Q_UNLIKELY(engine->writeBarrierActive)) - QV4::WriteBarrier::write(engine, scope, slot, value); + QV4::WriteBarrier::write(engine, cc, cc->callData->args + index, value); else - *slot = value; + *(cc->callData->args + index) = value; } static inline const QV4::Value &constant(Function *function, int index) @@ -421,10 +442,6 @@ static inline const QV4::Value &constant(Function *function, int index) QV4::ReturnedValue VME::exec(Function *function) { -#ifdef DO_TRACE_INSTR - qDebug("Starting VME with context=%p and code=%p", context, code); -#endif // DO_TRACE_INSTR - qt_v4ResolvePendingBreakpointsHook(); #ifdef MOTH_THREADED_INTERPRETER @@ -436,38 +453,20 @@ QV4::ReturnedValue VME::exec(Function *function) #endif ExecutionEngine *engine = function->internalClass->engine; - - // Arguments/locals are used a *lot*, and pre-fetching them removes a whole bunch of triple - // (or quadruple) indirect loads. - QV4::Value *arguments = nullptr; - QV4::Value *locals = nullptr; - QV4::Value *argumentsScope1 = nullptr; - QV4::Value *localsScope1 = nullptr; - QV4::Heap::ExecutionContext *functionScope = nullptr; - QV4::Heap::ExecutionContext *functionScope1 = nullptr; - { // setup args/locals/etc - functionScope = engine->current; - arguments = functionScope->callData->args; - if (functionScope->type == QV4::Heap::ExecutionContext::Type_CallContext) - locals = static_cast<QV4::Heap::CallContext *>(functionScope)->locals.values; - - functionScope1 = functionScope->outer; - if (functionScope1) { - argumentsScope1 = functionScope1->callData->args; - if (functionScope1->type == QV4::Heap::ExecutionContext::Type_CallContext) - localsScope1 = static_cast<QV4::Heap::CallContext *>(functionScope1)->locals.values; - } - } - QV4::Value accumulator = Primitive::undefinedValue(); - QV4::Value *stack = 0; - unsigned stackSize = 0; - + QV4::Value *stack = nullptr; const uchar *exceptionHandler = 0; QV4::Scope scope(engine); - engine->current->lineNumber = -1; + { + int nFormals = function->nFormals; + stack = scope.alloc(function->compiledFunction->nRegisters + nFormals) + nFormals; + auto cc = engine->current; + for (int i = 0, ei = std::min<int>(cc->callData->argc, nFormals); i != ei; ++i) + stack[-i-1] = cc->callData->args[i]; + } + engine->current->lineNumber = -1; if (QV4::Debugging::Debugger *debugger = engine->debugger()) debugger->enteringFunction(); @@ -501,58 +500,23 @@ QV4::ReturnedValue VME::exec(Function *function) STACK_VALUE(instr.destReg) = STACK_VALUE(instr.srcReg); MOTH_END_INSTR(MoveReg) - MOTH_BEGIN_INSTR(LoadLocal) - accumulator = locals[instr.index]; - MOTH_END_INSTR(LoadLocal) - - MOTH_BEGIN_INSTR(StoreLocal) - CHECK_EXCEPTION; - storeLocal(engine, functionScope, locals + instr.index, accumulator); - MOTH_END_INSTR(StoreLocal) - - MOTH_BEGIN_INSTR(LoadArg) - accumulator = arguments[instr.index]; - MOTH_END_INSTR(LoadArg) - - MOTH_BEGIN_INSTR(StoreArg) - CHECK_EXCEPTION; - storeArg(engine, functionScope, arguments + instr.index, accumulator); - MOTH_END_INSTR(StoreArg) - MOTH_BEGIN_INSTR(LoadScopedLocal) - if (Q_LIKELY(instr.scope == 1)) - accumulator = localsScope1[instr.index]; - else - accumulator = static_cast<QV4::Heap::CallContext *>(getScope(functionScope, instr.scope))->locals[instr.index]; + accumulator = loadScopedLocal(engine, instr.index, instr.scope); MOTH_END_INSTR(LoadScopedLocal) MOTH_BEGIN_INSTR(StoreScopedLocal) CHECK_EXCEPTION; - if (Q_LIKELY(instr.scope == 1)) { - storeLocal(engine, functionScope1, localsScope1 + instr.index, accumulator); - } else { - QV4::Heap::ExecutionContext *scope = getScope(functionScope, instr.scope); - QV4::Heap::CallContext *cc = static_cast<QV4::Heap::CallContext *>(scope); - storeLocal(engine, cc, cc->locals.values + instr.index, accumulator); - } + storeScopedLocal(engine, instr.index, instr.scope, accumulator); MOTH_END_INSTR(StoreScopedLocal) - MOTH_BEGIN_INSTR(LoadScopedArg) - if (Q_LIKELY(instr.scope == 1)) - accumulator = argumentsScope1[instr.index]; - else - accumulator = getScope(functionScope, instr.scope)->callData->args[instr.index]; - MOTH_END_INSTR(LoadScopedArg); + MOTH_BEGIN_INSTR(LoadScopedArgument) + accumulator = loadScopedArg(engine, instr.index, instr.scope); + MOTH_END_INSTR(LoadScopedArgument) - MOTH_BEGIN_INSTR(StoreScopedArg) + MOTH_BEGIN_INSTR(StoreScopedArgument) CHECK_EXCEPTION; - if (Q_LIKELY(instr.scope == 1)) { - storeArg(engine, functionScope1, argumentsScope1 + instr.index, accumulator); - } else { - QV4::Heap::ExecutionContext *scope = getScope(functionScope, instr.scope); - storeLocal(engine, scope, scope->callData->args + instr.index, accumulator); - } - MOTH_END_INSTR(StoreScopedArg) + storeScopedArg(engine, instr.index, instr.scope, accumulator); + MOTH_END_INSTR(StoreScopedArgument) MOTH_BEGIN_INSTR(LoadRuntimeString) accumulator = function->compilationUnit->runtimeStrings[instr.stringId]; @@ -655,11 +619,6 @@ QV4::ReturnedValue VME::exec(Function *function) STORE_ACCUMULATOR(Runtime::method_getQmlIdObject(engine, STACK_VALUE(instr.base), instr.index)); MOTH_END_INSTR(LoadIdObject) - MOTH_BEGIN_INSTR(InitStackFrame) - stackSize = unsigned(instr.value); - stack = scope.alloc(instr.value); - MOTH_END_INSTR(InitStackFrame) - MOTH_BEGIN_INSTR(CallValue) QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot()); STORE_ACCUMULATOR(Runtime::method_callValue(engine, STACK_VALUE(instr.dest), callData)); @@ -763,7 +722,6 @@ QV4::ReturnedValue VME::exec(Function *function) MOTH_END_INSTR(CallBuiltinDeclareVar) MOTH_BEGIN_INSTR(CallBuiltinDefineArray) - Q_ASSERT(instr.args.stackSlot() + instr.argc <= stackSize); QV4::Value *args = stack + instr.args.stackSlot(); STORE_ACCUMULATOR(Runtime::method_arrayLiteral(engine, args, instr.argc)); MOTH_END_INSTR(CallBuiltinDefineArray) @@ -789,7 +747,6 @@ QV4::ReturnedValue VME::exec(Function *function) MOTH_END_INSTR(CreateValue) MOTH_BEGIN_INSTR(CreateProperty) - Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot()); callData->tag = quint32(Value::ValueTypeInternal::Integer); callData->argc = instr.argc; @@ -798,7 +755,6 @@ QV4::ReturnedValue VME::exec(Function *function) MOTH_END_INSTR(CreateProperty) MOTH_BEGIN_INSTR(ConstructPropertyLookup) - Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot()); callData->tag = quint32(Value::ValueTypeInternal::Integer); callData->argc = instr.argc; @@ -807,7 +763,6 @@ QV4::ReturnedValue VME::exec(Function *function) MOTH_END_INSTR(ConstructPropertyLookup) MOTH_BEGIN_INSTR(CreateActivationProperty) - Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot()); callData->tag = quint32(Value::ValueTypeInternal::Integer); callData->argc = instr.argc; @@ -816,7 +771,6 @@ QV4::ReturnedValue VME::exec(Function *function) MOTH_END_INSTR(CreateActivationProperty) MOTH_BEGIN_INSTR(ConstructGlobalLookup) - Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot()); callData->tag = quint32(Value::ValueTypeInternal::Integer); callData->argc = instr.argc; |