diff options
23 files changed, 100 insertions, 123 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index 99d106d5f6..2d7141937f 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -103,8 +103,6 @@ int QV4DataCollector::encodeScopeType(QV4::Heap::ExecutionContext::ContextType s switch (scopeType) { case QV4::Heap::ExecutionContext::Type_GlobalContext: return 0; - case QV4::Heap::ExecutionContext::Type_CatchContext: - return 4; case QV4::Heap::ExecutionContext::Type_WithContext: return 2; case QV4::Heap::ExecutionContext::Type_CallContext: diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 463a1e8d27..794428b14d 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -2923,8 +2923,6 @@ bool Codegen::visit(TryStatement *ast) if (hasError) return true; - Q_ASSERT(_context->hasTry); - RegisterScope scope(this); if (ast->finallyExpression && ast->finallyExpression->statement) { diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 636b74e0fc..74f1ab81aa 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -541,7 +541,7 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) function->length = function->nFormals; // Hack to ensure an activation is created. - function->flags |= QV4::CompiledData::Function::HasCatchOrWith | QV4::CompiledData::Function::HasDirectEval; + function->flags |= QV4::CompiledData::Function::HasWith | QV4::CompiledData::Function::HasDirectEval; signalParameterNameTableOffset += function->nFormals * sizeof(quint32); } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 156fbc0149..668532fc41 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -231,7 +231,7 @@ struct Function UsesArgumentsObject = 0x4, IsArrowFunction = 0x8, IsGenerator = 0x20, - HasCatchOrWith = 0x10 + HasWith = 0x10 }; // Absolute offset into file where the code for this function is located. diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index d5b77f61cb..cca4c01be6 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -321,8 +321,8 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte function->flags |= CompiledData::Function::IsArrowFunction; if (irFunction->isGenerator) function->flags |= CompiledData::Function::IsGenerator; - if (irFunction->hasTry || irFunction->hasWith) - function->flags |= CompiledData::Function::HasCatchOrWith; + if (irFunction->hasWith) + function->flags |= CompiledData::Function::HasWith; function->nestedFunctionIndex = irFunction->returnsClosure ? quint32(module->functions.indexOf(irFunction->nestedContexts.first())) : std::numeric_limits<uint32_t>::max(); @@ -421,6 +421,14 @@ void QV4::Compiler::JSUnitGenerator::writeBlock(char *b, QV4::Compiler::Context quint32_le *locals = (quint32_le *)(b + block->localsOffset); for (int i = 0; i < irBlock->locals.size(); ++i) locals[i] = getStringId(irBlock->locals.at(i)); + + static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); + if (showCode) { + qDebug() << "=== Variables for block" << irBlock->blockIndex; + for (int i = 0; i < irBlock->locals.size(); ++i) + qDebug() << " " << i << ":" << locals[i]; + qDebug(); + } } QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, quint32_le *blockAndFunctionOffsets, uint *jsClassDataOffset) diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp index 4893a06af8..f340d62e52 100644 --- a/src/qml/compiler/qv4compilercontext.cpp +++ b/src/qml/compiler/qv4compilercontext.cpp @@ -84,15 +84,17 @@ bool Context::addLocalVar(const QString &name, Context::MemberType type, Variabl if (formals && formals->containsName(name)) return (scope == QQmlJS::AST::VariableScope::Var); } - MemberMap::iterator it = members.find(name); - if (it != members.end()) { - if (scope != QQmlJS::AST::VariableScope::Var || (*it).scope != QQmlJS::AST::VariableScope::Var) - return false; - if ((*it).type <= type) { - (*it).type = type; - (*it).function = function; + if (!isCatchBlock || name != catchedVariable) { + MemberMap::iterator it = members.find(name); + if (it != members.end()) { + if (scope != VariableScope::Var || (*it).scope != VariableScope::Var) + return false; + if ((*it).type <= type) { + (*it).type = type; + (*it).function = function; + } + return true; } - return true; } Member m; m.type = type; @@ -164,10 +166,18 @@ int Context::emitBlockHeader(Codegen *codegen) if (requiresExecutionContext || contextType == ContextType::Binding) { // we don't really need this for bindings, but we do for signal handlers, and we don't know if the code is a signal handler or not. if (contextType == ContextType::Block) { - Instruction::PushBlockContext blockContext; - blockContext.index = blockIndex; - blockContext.reg = contextReg = bytecodeGenerator->newRegister(); - bytecodeGenerator->addInstruction(blockContext); + if (isCatchBlock) { + Instruction::PushCatchContext catchContext; + catchContext.index = blockIndex; + catchContext.reg = contextReg = bytecodeGenerator->newRegister(); + catchContext.name = codegen->registerString(catchedVariable); + bytecodeGenerator->addInstruction(catchContext); + } else { + Instruction::PushBlockContext blockContext; + blockContext.index = blockIndex; + blockContext.reg = contextReg = bytecodeGenerator->newRegister(); + bytecodeGenerator->addInstruction(blockContext); + } } else { Instruction::CreateCallContext createContext; bytecodeGenerator->addInstruction(createContext); diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 189a623703..8c7da397a9 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -155,6 +155,8 @@ struct Context { mutable bool argumentsCanEscape = false; bool requiresExecutionContext = false; bool forceLookupByName = false; + bool isCatchBlock = false; + QString catchedVariable; enum UsesArgumentsObject { ArgumentsObjectUnknown, diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h index c02168c1b6..6f524bb366 100644 --- a/src/qml/compiler/qv4compilercontrolflow_p.h +++ b/src/qml/compiler/qv4compilercontrolflow_p.h @@ -409,32 +409,33 @@ struct ControlFlowCatch : public ControlFlowUnwind ~ControlFlowCatch() { // emit code for unwinding - - cg->_context->forceLookupByName = true; insideCatch = true; Codegen::RegisterScope scope(cg); // exceptions inside the try block go here exceptionLabel.link(); - Moth::StackSlot savedContextReg = Moth::StackSlot::createRegister(generator()->newRegister()); - Instruction::PushCatchContext pushCatch; - pushCatch.name = cg->registerString(catchExpression->name.toString()); - pushCatch.reg = savedContextReg; - generator()->addInstruction(pushCatch); + + cg->enterContext(catchExpression); + Context *block = cg->currentContext(); + cg->_module->blocks.append(block); + block->blockIndex = cg->_module->blocks.count() - 1; + + int savedContextReg = block->emitBlockHeader(cg); + // clear the unwind temp for exceptions, we want to resume normal code flow afterwards Reference::storeConstOnStack(cg, QV4::Encode::undefined(), controlFlowTemp); generator()->setExceptionHandler(&catchUnwindLabel); - cg->statement(catchExpression->statement); + cg->statementList(catchExpression->statement->statements); insideCatch = false; // exceptions inside catch and break/return statements go here catchUnwindLabel.link(); - Instruction::PopContext pop; - pop.reg = savedContextReg; - generator()->addInstruction(pop); + block->emitBlockFooter(cg, savedContextReg); + + cg->leaveContext(); // break/continue/return statements in try go here unwindLabel.link(); diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index 312f07e254..120c606f91 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -317,13 +317,6 @@ void ScanFunctions::endVisit(FunctionDeclaration *) leaveEnvironment(); } -bool ScanFunctions::visit(TryStatement *) -{ - // ### should limit to catch(), as try{} finally{} should be ok without - _context->hasTry = true; - return true; -} - bool ScanFunctions::visit(WithStatement *ast) { if (_context->isStrict) { @@ -406,6 +399,23 @@ void ScanFunctions::endVisit(Block *) leaveEnvironment(); } +bool ScanFunctions::visit(Catch *ast) +{ + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls); + enterEnvironment(ast, ContextType::Block); + _context->name = QLatin1String("CatchBlock"); + _context->isCatchBlock = true; + _context->catchedVariable = ast->name.toString(); + _context->addLocalVar(ast->name.toString(), Context::MemberType::VariableDefinition, VariableScope::Let); + Node::accept(ast->statement->statements, this); + return false; +} + +void ScanFunctions::endVisit(Catch *) +{ + leaveEnvironment(); +} + bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, bool enterName) { Context *outerContext = _context; @@ -513,7 +523,7 @@ void ScanFunctions::calcEscapingVariables() } } for (Context *c : qAsConst(m->contextMap)) { - bool allVarsEscape = c->hasWith || c->hasTry || c->hasDirectEval; + bool allVarsEscape = c->hasWith || c->hasDirectEval; if (allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty()) allVarsEscape = false; if (m->debugMode) @@ -528,6 +538,11 @@ void ScanFunctions::calcEscapingVariables() // ### Shouldn't be required, we could probably rather change the ContextType to FunctionCode for strict eval if (c->contextType == ContextType::Eval && c->isStrict) c->requiresExecutionContext = true; + if (c->contextType == ContextType::Block && c->isCatchBlock) { + c->requiresExecutionContext = true; + auto m = c->members.find(c->catchedVariable); + m->canEscape = true; + } if (!c->parent || c->usesArgumentsObject == Context::ArgumentsObjectUnknown) c->usesArgumentsObject = Context::ArgumentsObjectNotUsed; if (c->usesArgumentsObject == Context::ArgumentsObjectUsed) { diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h index d6969c56e8..013cb0d4e6 100644 --- a/src/qml/compiler/qv4compilerscanfunctions_p.h +++ b/src/qml/compiler/qv4compilerscanfunctions_p.h @@ -123,7 +123,6 @@ protected: bool visit(AST::FunctionDeclaration *ast) override; void endVisit(AST::FunctionDeclaration *) override; - bool visit(AST::TryStatement *ast) override; bool visit(AST::WithStatement *ast) override; bool visit(AST::DoWhileStatement *ast) override; @@ -136,6 +135,9 @@ protected: bool visit(AST::Block *ast) override; void endVisit(AST::Block *ast) override; + bool visit(AST::Catch *ast) override; + void endVisit(AST::Catch *ast) override; + protected: bool enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, bool enterName); diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 094611e974..bae8d9e64e 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -397,7 +397,7 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_END_INSTR(CreateCallContext) MOTH_BEGIN_INSTR(PushCatchContext) - d << dumpRegister(reg, nFormals) << ", " << name; + d << dumpRegister(reg, nFormals) << ", " << index << ", " << name; MOTH_END_INSTR(PushCatchContext) MOTH_BEGIN_INSTR(PushWithContext) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 2e1763d3be..15ab1b52dd 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -112,7 +112,7 @@ QT_BEGIN_NAMESPACE #define INSTR_GetException(op) INSTRUCTION(op, GetException, 0) #define INSTR_SetException(op) INSTRUCTION(op, SetException, 0) #define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0) -#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, name, reg) +#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 3, reg, index, name) #define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 1, reg) #define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 2, reg, index) #define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 1, reg) diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index 890d9d03a1..c73b3919ae 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -2222,11 +2222,12 @@ void Assembler::clearExceptionHandler() pasm()->storePtr(TrustedImmPtr(nullptr), pasm()->exceptionHandlerAddress()); } -void Assembler::pushCatchContext(int name, int reg) +void Assembler::pushCatchContext(int reg, int index, int name) { pasm()->copyReg(pasm()->contextAddress(), regAddr(reg)); - prepareCallWithArgCount(2); - passInt32AsArg(name, 1); + prepareCallWithArgCount(3); + passInt32AsArg(name, 2); + passInt32AsArg(index, 1); passRegAsArg(CallData::Context, 0); IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_createCatchContext, ResultInAccumulator); pasm()->storeAccumulator(pasm()->contextAddress()); diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index a98761c6ab..f9a74edc77 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -163,7 +163,7 @@ public: void setException(); void setExceptionHandler(int offset); void clearExceptionHandler(); - void pushCatchContext(int name, int reg); + void pushCatchContext(int reg, int index, int name); void popContext(int reg); // other stuff diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp index 4a2e2b959c..678a0c16db 100644 --- a/src/qml/jit/qv4jit.cpp +++ b/src/qml/jit/qv4jit.cpp @@ -604,7 +604,7 @@ void BaselineJIT::generate_CreateCallContext() as->storeHeapObject(CallData::Context); } -void BaselineJIT::generate_PushCatchContext(int name, int reg) { as->pushCatchContext(name, reg); } +void BaselineJIT::generate_PushCatchContext(int reg, int index, int name) { as->pushCatchContext(reg, index, name); } static void pushWithContextHelper(ExecutionEngine *engine, QV4::Value *stack, int reg) { diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h index 3e81807754..150f4b6aab 100644 --- a/src/qml/jit/qv4jit_p.h +++ b/src/qml/jit/qv4jit_p.h @@ -175,7 +175,7 @@ public: void generate_GetException() override; void generate_SetException() override; void generate_CreateCallContext() override; - void generate_PushCatchContext(int name, int reg) override; + void generate_PushCatchContext(int reg, int index, int name) override; void generate_PushWithContext(int reg) override; void generate_PushBlockContext(int reg, int index) override; void generate_PopContext(int reg) override; diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 39fdcf0227..bd2e0faebf 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -53,7 +53,6 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(ExecutionContext); DEFINE_MANAGED_VTABLE(CallContext); -DEFINE_MANAGED_VTABLE(CatchContext); Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int blockIndex) { @@ -119,11 +118,14 @@ Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with) return c; } -Heap::CatchContext *ExecutionContext::newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue) +Heap::ExecutionContext *ExecutionContext::newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName) { - Scope scope(this); - ScopedValue e(scope, exceptionValue); - return engine()->memoryManager->alloc<CatchContext>(d(), exceptionVarName, e); + Scope scope(frame->context()); + ScopedString name(scope, exceptionVarName); + ScopedValue val(scope, scope.engine->catchException(nullptr)); + ScopedContext ctx(scope, newBlockContext(frame, blockIndex)); + ctx->setProperty(name, val); + return ctx->d(); } void ExecutionContext::createMutableBinding(String *name, bool deletable) @@ -170,16 +172,6 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable) activation->__defineOwnProperty__(scope.engine, name, desc, attrs); } -void Heap::CatchContext::init(ExecutionContext *outerContext, String *exceptionVarName, - const Value &exceptionValue) -{ - Heap::ExecutionContext::init(Heap::ExecutionContext::Type_CatchContext); - outer.set(internalClass->engine, outerContext); - - this->exceptionVarName.set(internalClass->engine, exceptionVarName); - this->exceptionValue.set(internalClass->engine, exceptionValue); -} - bool ExecutionContext::deleteProperty(String *name) { name->makeIdentifier(); @@ -188,12 +180,6 @@ bool ExecutionContext::deleteProperty(String *name) Heap::ExecutionContext *ctx = d(); for (; ctx; ctx = ctx->outer) { switch (ctx->type) { - case Heap::ExecutionContext::Type_CatchContext: { - Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx); - if (c->exceptionVarName->isEqualTo(name->d())) - return false; - break; - } case Heap::ExecutionContext::Type_BlockContext: case Heap::ExecutionContext::Type_CallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx); @@ -232,14 +218,6 @@ ExecutionContext::Error ExecutionContext::setProperty(String *name, const Value for (; ctx; ctx = ctx->outer) { switch (ctx->type) { - case Heap::ExecutionContext::Type_CatchContext: { - Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx); - if (c->exceptionVarName->isEqualTo(name->d())) { - c->exceptionValue.set(v4, value); - return NoError; - } - break; - } case Heap::ExecutionContext::Type_WithContext: { Scope scope(v4); ScopedObject w(scope, ctx->activation); @@ -293,12 +271,6 @@ ReturnedValue ExecutionContext::getProperty(String *name) Heap::ExecutionContext *ctx = d(); for (; ctx; ctx = ctx->outer) { switch (ctx->type) { - case Heap::ExecutionContext::Type_CatchContext: { - Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx); - if (c->exceptionVarName->isEqualTo(name->d())) - return c->exceptionValue.asReturnedValue(); - break; - } case Heap::ExecutionContext::Type_BlockContext: case Heap::ExecutionContext::Type_CallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx); @@ -335,12 +307,6 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base) Heap::ExecutionContext *ctx = d(); for (; ctx; ctx = ctx->outer) { switch (ctx->type) { - case Heap::ExecutionContext::Type_CatchContext: { - Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx); - if (c->exceptionVarName->isEqualTo(name->d())) - return c->exceptionValue.asReturnedValue(); - break; - } case Heap::ExecutionContext::Type_BlockContext: case Heap::ExecutionContext::Type_CallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx); diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 5a9c85c941..cd99f162d2 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -107,11 +107,10 @@ DECLARE_HEAP_OBJECT(ExecutionContext, Base) { enum ContextType { Type_GlobalContext = 0x1, - Type_CatchContext = 0x2, - Type_WithContext = 0x3, - Type_QmlContext = 0x4, - Type_BlockContext = 0x5, - Type_CallContext = 0x6 + Type_WithContext = 0x2, + Type_QmlContext = 0x3, + Type_BlockContext = 0x4, + Type_CallContext = 0x5 }; void init(ContextType t) @@ -169,16 +168,6 @@ Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0); //Q_STATIC_ASSERT(sizeof(CallContext) == sizeof(ExecutionContext) + sizeof(CallContextData)); //#endif -#define CatchContextMembers(class, Member) \ - Member(class, Pointer, String *, exceptionVarName) \ - Member(class, HeapValue, HeapValue, exceptionValue) - -DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) { - DECLARE_MARKOBJECTS(CatchContext); - - void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue); -}; -Q_STATIC_ASSERT(std::is_trivial< CatchContext >::value); } @@ -195,7 +184,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex); static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame); Heap::ExecutionContext *newWithContext(Heap::Object *with); - Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue); + static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName); void createMutableBinding(String *name, bool deletable); @@ -228,12 +217,6 @@ struct Q_QML_EXPORT CallContext : public ExecutionContext } }; -struct CatchContext : public ExecutionContext -{ - V4_MANAGED(CatchContext, ExecutionContext) - V4_INTERNALCLASS(CatchContext) -}; - inline CallContext *ExecutionContext::asCallContext() { return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<CallContext *>(this) : nullptr; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 10030a14e4..3660ab3855 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -209,7 +209,6 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) classes[Class_SparseArrayData] = classes[Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable()); classes[Class_ExecutionContext] = classes[Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable()); classes[Class_CallContext] = classes[Class_Empty]->changeVTable(QV4::CallContext::staticVTable()); - classes[Class_CatchContext] = classes[Class_Empty]->changeVTable(QV4::CatchContext::staticVTable()); classes[Class_QmlContext] = classes[Class_Empty]->changeVTable(QV4::QmlContext::staticVTable()); jsStrings[String_Empty] = newIdentifier(QString()); diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h index b7f6b8d3cd..c01b9b1842 100644 --- a/src/qml/jsruntime/qv4enginebase_p.h +++ b/src/qml/jsruntime/qv4enginebase_p.h @@ -96,7 +96,6 @@ struct Q_QML_EXPORT EngineBase { Class_SparseArrayData, Class_ExecutionContext, Class_CallContext, - Class_CatchContext, Class_QmlContext, Class_Object, Class_ArrayObject, diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 95e4017344..40e08ededb 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1183,11 +1183,6 @@ QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameI return method_typeofValue(engine, prop); } -/* The next three methods are a bit tricky. They can't open up a Scope, as that - * would mess up the pushing of the context. - * - * Instead the push/pop pair acts as a non local scope. - */ ReturnedValue Runtime::method_createWithContext(ExecutionContext *parent, const Value &o) { Q_ASSERT(o.isObject()); @@ -1195,11 +1190,11 @@ ReturnedValue Runtime::method_createWithContext(ExecutionContext *parent, const return parent->newWithContext(obj.d())->asReturnedValue(); } -ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int exceptionVarNameIndex) +ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex) { ExecutionEngine *e = parent->engine(); - return parent->newCatchContext(e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex], - e->catchException(nullptr))->asReturnedValue(); + return parent->newCatchContext(e->currentStackFrame, blockIndex, + e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex])->asReturnedValue(); } ReturnedValue Runtime::method_createBlockContext(ExecutionContext *parent, int index) diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index 24bab70327..a1a7bd9ed0 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -125,7 +125,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> { /* exceptions & scopes */ \ F(void, throwException, (ExecutionEngine *engine, const Value &value)) \ F(ReturnedValue, createWithContext, (ExecutionContext *parent, const Value &o)) \ - F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int exceptionVarNameIndex)) \ + F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)) \ F(ReturnedValue, createBlockContext, (ExecutionContext *parent, int index)) \ \ /* closures */ \ diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index a515abd9de..4a7339ca3a 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -877,7 +877,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj MOTH_BEGIN_INSTR(PushCatchContext) STACK_VALUE(reg) = STACK_VALUE(CallData::Context); ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context); - STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, name); + STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, index, name); MOTH_END_INSTR(PushCatchContext) MOTH_BEGIN_INSTR(CreateCallContext) |