Cleanup: Get rid of calls to builtin_{push,pop}_catch_scope in the IR
authorSimon Hausmann <simon.hausmann@digia.com>
Wed, 6 Mar 2013 19:04:31 +0000 (20:04 +0100)
committerLars Knoll <lars.knoll@digia.com>
Wed, 6 Mar 2013 21:19:19 +0000 (22:19 +0100)
These calls aren't needed anymore and can easily be done on the run-time level
instead right before and after calling the catch block.

Change-Id: I445361688782d12269764578e83ebb21ae184190
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
13 files changed:
src/v4/moth/qv4instr_moth_p.h
src/v4/moth/qv4isel_moth.cpp
src/v4/moth/qv4isel_moth_p.h
src/v4/moth/qv4vme_moth.cpp
src/v4/qv4codegen.cpp
src/v4/qv4codegen_p.h
src/v4/qv4isel_llvm_p.h
src/v4/qv4isel_masm.cpp
src/v4/qv4isel_masm_p.h
src/v4/qv4isel_p.cpp
src/v4/qv4isel_p.h
src/v4/qv4jsir.cpp
src/v4/qv4jsir_p.h

index 7a9b59c..ec0fe27 100644 (file)
@@ -25,7 +25,6 @@
     F(CallBuiltinFinishTry, callBuiltinFinishTry) \
     F(CallBuiltinGetException, callBuiltinGetException) \
     F(CallBuiltinPushScope, callBuiltinPushScope) \
-    F(CallBuiltinPushCatchScope, callBuiltinPushCatchScope) \
     F(CallBuiltinPopScope, callBuiltinPopScope) \
     F(CallBuiltinForeachIteratorObject, callBuiltinForeachIteratorObject) \
     F(CallBuiltinForeachNextPropertyName, callBuiltinForeachNextPropertyName) \
@@ -214,6 +213,7 @@ union Instr
         MOTH_INSTR_HEADER
         ptrdiff_t tryOffset;
         ptrdiff_t catchOffset;
+        VM::String *exceptionVarName;
     };
     struct instr_callValue {
         MOTH_INSTR_HEADER
@@ -260,10 +260,6 @@ union Instr
         MOTH_INSTR_HEADER
         Param arg;
     };
-    struct instr_callBuiltinPushCatchScope {
-        MOTH_INSTR_HEADER
-        VM::String *varName;
-    };
     struct instr_callBuiltinPopScope {
         MOTH_INSTR_HEADER
     };
@@ -474,7 +470,6 @@ union Instr
     instr_callBuiltinFinishTry callBuiltinFinishTry;
     instr_callBuiltinGetException callBuiltinGetException;
     instr_callBuiltinPushScope callBuiltinPushScope;
-    instr_callBuiltinPushCatchScope callBuiltinPushCatchScope;
     instr_callBuiltinPopScope callBuiltinPopScope;
     instr_callBuiltinForeachIteratorObject callBuiltinForeachIteratorObject;
     instr_callBuiltinForeachNextPropertyName callBuiltinForeachNextPropertyName;
index 46a40d0..b45b4c0 100644 (file)
@@ -682,6 +682,7 @@ void InstructionSelection::visitTry(IR::Try *t)
     Instruction::EnterTry enterTry;
     enterTry.tryOffset = 0;
     enterTry.catchOffset = 0;
+    enterTry.exceptionVarName = identifier(t->exceptionVarName);
     ptrdiff_t enterTryLoc = addInstruction(enterTry);
 
     ptrdiff_t tryLoc = enterTryLoc + (((const char *)&enterTry.tryOffset) - ((const char *)&enterTry));
@@ -879,13 +880,6 @@ void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
     addInstruction(call);
 }
 
-void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionVarName)
-{
-    Instruction::CallBuiltinPushCatchScope call;
-    call.varName = identifier(exceptionVarName);
-    addInstruction(call);
-}
-
 void InstructionSelection::callBuiltinPopScope()
 {
     Instruction::CallBuiltinPopScope call;
index 04bb72d..39dc92d 100644 (file)
@@ -49,7 +49,6 @@ protected:
     virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result);
     virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
     virtual void callBuiltinPushWithScope(IR::Temp *arg);
-    virtual void callBuiltinPushCatchScope(const QString &exceptionVarName);
     virtual void callBuiltinPopScope();
     virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
     virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter);
index e47dae2..401752f 100644 (file)
@@ -267,9 +267,11 @@ VM::Value VME::run(QQmlJS::VM::ExecutionContext *context, const uchar *&code,
         } catch (VM::Exception &ex) {
             ex.accept(context);
             try {
+                VM::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(instr.exceptionVarName, context);
                 const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
-                run(context, catchCode, stack, stackSize);
+                run(catchContext, catchCode, stack, stackSize);
                 code = catchCode;
+                context = __qmljs_builtin_pop_scope(catchContext);
             } catch (VM::Exception &ex) {
                 ex.accept(context);
                 const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
@@ -291,10 +293,6 @@ VM::Value VME::run(QQmlJS::VM::ExecutionContext *context, const uchar *&code,
         context = __qmljs_builtin_push_with_scope(VALUE(instr.arg), context);
     MOTH_END_INSTR(CallBuiltinPushScope)
 
-    MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
-         context = __qmljs_builtin_push_catch_scope(instr.varName, context);
-    MOTH_END_INSTR(CallBuiltinPushCatchScope)
-
     MOTH_BEGIN_INSTR(CallBuiltinPopScope)
         context = __qmljs_builtin_pop_scope(context);
     MOTH_END_INSTR(CallBuiltinPopScope)
index 8946041..76f5b90 100644 (file)
@@ -2475,7 +2475,7 @@ bool Codegen::visit(TryStatement *ast)
     ScopeAndFinally tcf(_scopeAndFinally, ast->finallyExpression, finishTryArgs);
     _scopeAndFinally = &tcf;
 
-    _block->TRY(tryBody, catchBody);
+    _block->TRY(tryBody, catchBody, ast->catchExpression ? ast->catchExpression->name.toString() : QString());
 
     _block = tryBody;
     statement(ast->statement);
@@ -2494,21 +2494,15 @@ bool Codegen::visit(TryStatement *ast)
     move(_block->TEMP(hasException), _block->CONST(IR::BoolType, true));
 
     if (ast->catchExpression) {
-        IR::ExprList *catchScopeArgs = _function->New<IR::ExprList>();
-        catchScopeArgs->init(_block->NAME(ast->catchExpression->name.toString(), ast->catchExpression->identifierToken.startLine, ast->catchExpression->identifierToken.startColumn));
-        _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_push_catch_scope, 0, 0), catchScopeArgs));
-
         ++_function->insideWithOrCatch;
         {
-            ScopeAndFinally scope(_scopeAndFinally);
+            ScopeAndFinally scope(_scopeAndFinally, ScopeAndFinally::CatchScope);
             _scopeAndFinally = &scope;
             statement(ast->catchExpression->statement);
             _scopeAndFinally = scope.parent;
         }
         --_function->insideWithOrCatch;
-
         move(_block->TEMP(hasException), _block->CONST(IR::BoolType, false));
-        _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0)));
     }
     _block->JUMP(finallyBody);
 
@@ -2543,16 +2537,22 @@ void Codegen::unwindException(Codegen::ScopeAndFinally *outest)
     ScopeAndFinally *scopeAndFinally = _scopeAndFinally;
     qSwap(_scopeAndFinally, scopeAndFinally);
     while (_scopeAndFinally != outest) {
-        if (_scopeAndFinally->popScope) {
+        switch (_scopeAndFinally->type) {
+        case ScopeAndFinally::WithScope:
             _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0)));
+            // fall through
+        case ScopeAndFinally::CatchScope:
             _scopeAndFinally = _scopeAndFinally->parent;
             --_function->insideWithOrCatch;
-        } else {
+            break;
+        case ScopeAndFinally::TryScope: {
             _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_finish_try, 0, 0), _scopeAndFinally->finishTryArgs));
             ScopeAndFinally *tc = _scopeAndFinally;
             _scopeAndFinally = tc->parent;
             if (tc->finally && tc->finally->statement)
                 statement(tc->finally->statement);
+            break;
+        }
         }
     }
     qSwap(_scopeAndFinally, scopeAndFinally);
index 283e282..1825396 100644 (file)
@@ -215,14 +215,20 @@ protected:
     };
 
     struct ScopeAndFinally {
+        enum ScopeType {
+            WithScope,
+            TryScope,
+            CatchScope
+        };
+
         ScopeAndFinally *parent;
         AST::Finally *finally;
         IR::ExprList *finishTryArgs;
-        bool popScope;
+        ScopeType type;
 
-        ScopeAndFinally(ScopeAndFinally *parent) : parent(parent), finally(0), finishTryArgs(0), popScope(true) {}
+        ScopeAndFinally(ScopeAndFinally *parent, ScopeType t = WithScope) : parent(parent), finally(0), finishTryArgs(0), type(t) {}
         ScopeAndFinally(ScopeAndFinally *parent, AST::Finally *finally, IR::ExprList *finishTryArgs)
-        : parent(parent), finally(finally), finishTryArgs(finishTryArgs), popScope(false)
+        : parent(parent), finally(finally), finishTryArgs(finishTryArgs), type(TryScope)
         {}
     };
 
index 0f34547..cf9aaed 100644 (file)
@@ -94,7 +94,6 @@ public: // methods from InstructionSelection:
     virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result);
     virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
     virtual void callBuiltinPushWithScope(IR::Temp *arg);
-    virtual void callBuiltinPushCatchScope(const QString &exceptionVarName){}
     virtual void callBuiltinPopScope();
     virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
     virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter);
index 69e6d21..28a5c7b 100644 (file)
@@ -677,7 +677,8 @@ void InstructionSelection::callBuiltinThrow(IR::Temp *arg)
 }
 
 typedef void *(*MiddleOfFunctionEntryPoint(ExecutionContext *, void *localsPtr));
-static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunctionEntryPoint tryBody, MiddleOfFunctionEntryPoint catchBody)
+static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunctionEntryPoint tryBody, MiddleOfFunctionEntryPoint catchBody,
+                        VM::String *exceptionVarName)
 {
     void *addressToContinueAt = 0;
     try {
@@ -685,7 +686,9 @@ static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunc
     } catch (Exception& ex) {
         ex.accept(context);
         try {
-            addressToContinueAt = catchBody(context, localsPtr);
+            ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, context);
+            addressToContinueAt = catchBody(catchContext, localsPtr);
+            context = __qmljs_builtin_pop_scope(catchContext);
         } catch (Exception& ex) {
             ex.accept(context);
             addressToContinueAt = catchBody(context, localsPtr);
@@ -706,7 +709,8 @@ void InstructionSelection::visitTry(IR::Try *t)
     _reentryBlocks.insert(t->catchBlock);
 
     generateFunctionCall(Assembler::ReturnValueRegister, tryWrapper, Assembler::ContextRegister, Assembler::LocalsRegister,
-                         Assembler::ReentryBlock(t->tryBlock), Assembler::ReentryBlock(t->catchBlock));
+                         Assembler::ReentryBlock(t->tryBlock), Assembler::ReentryBlock(t->catchBlock),
+                         identifier(t->exceptionVarName));
     _as->jump(Assembler::ReturnValueRegister);
 }
 
@@ -740,11 +744,6 @@ void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
     generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_push_with_scope, Assembler::Reference(arg), Assembler::ContextRegister);
 }
 
-void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionVarName)
-{
-    generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_push_catch_scope, identifier(exceptionVarName), Assembler::ContextRegister);
-}
-
 void InstructionSelection::callBuiltinPopScope()
 {
     generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_pop_scope, Assembler::ContextRegister);
index 92b30ab..8143020 100644 (file)
@@ -792,7 +792,6 @@ protected:
     virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result);
     virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
     virtual void callBuiltinPushWithScope(IR::Temp *arg);
-    virtual void callBuiltinPushCatchScope(const QString &exceptionVarName);
     virtual void callBuiltinPopScope();
     virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
     virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter);
index 85758df..1651555 100644 (file)
@@ -335,12 +335,6 @@ void InstructionSelection::callBuiltin(IR::Call *call, IR::Temp *result)
         callBuiltinPushWithScope(arg);
     } return;
 
-    case IR::Name::builtin_push_catch_scope: {
-        IR::Name *arg = call->args->expr->asName();
-        assert(arg != 0);
-        callBuiltinPushCatchScope(*arg->id);
-    } return;
-
     case IR::Name::builtin_pop_scope:
         callBuiltinPopScope();
         return;
index 9226f06..ae99bf6 100644 (file)
@@ -108,7 +108,6 @@ public: // to implement by subclasses:
     virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) = 0;
     virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) = 0;
     virtual void callBuiltinPushWithScope(IR::Temp *arg) = 0;
-    virtual void callBuiltinPushCatchScope(const QString &exceptionVarName) = 0;
     virtual void callBuiltinPopScope() = 0;
     virtual void callBuiltinDeclareVar(bool deletable, const QString &name) = 0;
     virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter) = 0;
index c4953a8..b5de42e 100644 (file)
@@ -366,8 +366,6 @@ static const char *builtin_to_string(Name::Builtin b)
         return "builtin_foreach_next_property_name";
     case IR::Name::builtin_push_with_scope:
         return "builtin_push_with_scope";
-    case IR::Name::builtin_push_catch_scope:
-        return "builtin_push_catch_scope";
     case IR::Name::builtin_pop_scope:
         return "builtin_pop_scope";
     case IR::Name::builtin_declare_vars:
@@ -526,7 +524,7 @@ void Ret::dump(QTextStream &out, Mode)
 
 void Try::dump(QTextStream &out, Stmt::Mode mode)
 {
-    out << "try L" << tryBlock->index << "; catch L" << catchBlock->index << ';';
+    out << "try L" << tryBlock->index << "; catch exception as " << exceptionVarName << " and go to L" << catchBlock->index << ';';
 }
 
 Function *Module::newFunction(const QString &name, Function *outer)
@@ -793,13 +791,13 @@ Stmt *BasicBlock::RET(Temp *expr)
     return s;
 }
 
-Stmt *BasicBlock::TRY(BasicBlock *tryBlock, BasicBlock *catchBlock)
+Stmt *BasicBlock::TRY(BasicBlock *tryBlock, BasicBlock *catchBlock, const QString &exceptionVarName)
 {
     if (isTerminated())
         return 0;
 
     Try *t = function->New<Try>();
-    t->init(tryBlock, catchBlock);
+    t->init(tryBlock, catchBlock, exceptionVarName);
     statements.append(t);
 
     assert(! out.contains(tryBlock));
index 570b0db..e4d8e1e 100644 (file)
@@ -296,7 +296,6 @@ struct Name: Expr {
         builtin_foreach_iterator_object,
         builtin_foreach_next_property_name,
         builtin_push_with_scope,
-        builtin_push_catch_scope,
         builtin_pop_scope,
         builtin_declare_vars,
         builtin_define_property,
@@ -608,11 +607,13 @@ struct Ret: Stmt {
 struct Try: Stmt {
     BasicBlock *tryBlock;
     BasicBlock *catchBlock;
+    QString exceptionVarName;
 
-    void init(BasicBlock *tryBlock, BasicBlock *catchBlock)
+    void init(BasicBlock *tryBlock, BasicBlock *catchBlock, const QString &exceptionVarName)
     {
         this->tryBlock = tryBlock;
         this->catchBlock = catchBlock;
+        this->exceptionVarName = exceptionVarName;
     }
 
     virtual Stmt *asTerminator() { return this; }
@@ -749,7 +750,7 @@ struct BasicBlock {
     Stmt *JUMP(BasicBlock *target);
     Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse);
     Stmt *RET(Temp *expr);
-    Stmt *TRY(BasicBlock *tryBlock, BasicBlock *catchBlock);
+    Stmt *TRY(BasicBlock *tryBlock, BasicBlock *catchBlock, const QString &exceptionVarName);
 
     void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);
 };