aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-04-06 10:20:08 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-02 14:17:51 +0000
commit922e6f42b4fa9b9fa87246c577c13bb945bd4bc4 (patch)
tree182cf430b7340c4f34c0cb350af1c15fd41b6648 /src
parent20d30b6b3a253eebedc927dbb91685bbec52cfee (diff)
Rework catch context handling
Remove the need for a specialized catch context, instead use a regular block context, that also captures the catched variable. This also removes the need to do lookups by name inside a catch expression. Change-Id: I8b037add7f423922e2a76b4c0da646ca7e25813a Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp2
-rw-r--r--src/qml/compiler/qv4codegen.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
-rw-r--r--src/qml/compiler/qv4compiler.cpp12
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp34
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h2
-rw-r--r--src/qml/compiler/qv4compilercontrolflow_p.h23
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp31
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions_p.h4
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp2
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/jit/qv4assembler.cpp7
-rw-r--r--src/qml/jit/qv4assembler_p.h2
-rw-r--r--src/qml/jit/qv4jit.cpp2
-rw-r--r--src/qml/jit/qv4jit_p.h2
-rw-r--r--src/qml/jsruntime/qv4context.cpp48
-rw-r--r--src/qml/jsruntime/qv4context_p.h27
-rw-r--r--src/qml/jsruntime/qv4engine.cpp1
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h1
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp11
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp2
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)