| Index: src/scopes.cc
|
| diff --git a/src/scopes.cc b/src/scopes.cc
|
| index 74d0c2a2e258f4140fa7f0b344b4eadfa8172854..c20c85214f014b9ac033db8eee8820deb10af056 100644
|
| --- a/src/scopes.cc
|
| +++ b/src/scopes.cc
|
| @@ -256,11 +256,16 @@ void Scope::Initialize(bool inside_with) {
|
| // instead load them directly from the stack. Currently, the only
|
| // such parameter is 'this' which is passed on the stack when
|
| // invoking scripts
|
| - Variable* var =
|
| - variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
|
| - false, Variable::THIS);
|
| - var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
|
| - receiver_ = var;
|
| + if (is_catch_scope()) {
|
| + ASSERT(outer_scope() != NULL);
|
| + receiver_ = outer_scope()->receiver();
|
| + } else {
|
| + Variable* var =
|
| + variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
|
| + false, Variable::THIS);
|
| + var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
|
| + receiver_ = var;
|
| + }
|
|
|
| if (is_function_scope()) {
|
| // Declare 'arguments' variable which exists in all functions.
|
| @@ -514,6 +519,7 @@ static const char* Header(Scope::Type type) {
|
| case Scope::EVAL_SCOPE: return "eval";
|
| case Scope::FUNCTION_SCOPE: return "function";
|
| case Scope::GLOBAL_SCOPE: return "global";
|
| + case Scope::CATCH_SCOPE: return "catch";
|
| }
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -864,8 +870,10 @@ bool Scope::MustAllocate(Variable* var) {
|
| // visible name.
|
| if ((var->is_this() || var->name()->length() > 0) &&
|
| (var->is_accessed_from_inner_scope() ||
|
| - scope_calls_eval_ || inner_scope_calls_eval_ ||
|
| - scope_contains_with_)) {
|
| + scope_calls_eval_ ||
|
| + inner_scope_calls_eval_ ||
|
| + scope_contains_with_ ||
|
| + is_catch_scope())) {
|
| var->set_is_used(true);
|
| }
|
| // Global variables do not need to be allocated.
|
| @@ -874,16 +882,20 @@ bool Scope::MustAllocate(Variable* var) {
|
|
|
|
|
| bool Scope::MustAllocateInContext(Variable* var) {
|
| - // If var is accessed from an inner scope, or if there is a
|
| - // possibility that it might be accessed from the current or an inner
|
| - // scope (through an eval() call), it must be allocated in the
|
| - // context. Exception: temporary variables are not allocated in the
|
| + // If var is accessed from an inner scope, or if there is a possibility
|
| + // that it might be accessed from the current or an inner scope (through
|
| + // an eval() call or a runtime with lookup), it must be allocated in the
|
| // context.
|
| - return
|
| - var->mode() != Variable::TEMPORARY &&
|
| - (var->is_accessed_from_inner_scope() ||
|
| - scope_calls_eval_ || inner_scope_calls_eval_ ||
|
| - scope_contains_with_ || var->is_global());
|
| + //
|
| + // Exceptions: temporary variables are never allocated in a context;
|
| + // catch-bound variables are always allocated in a context.
|
| + if (var->mode() == Variable::TEMPORARY) return false;
|
| + if (is_catch_scope()) return true;
|
| + return var->is_accessed_from_inner_scope() ||
|
| + scope_calls_eval_ ||
|
| + inner_scope_calls_eval_ ||
|
| + scope_contains_with_ ||
|
| + var->is_global();
|
| }
|
|
|
|
|
|
|