| Index: src/runtime.cc | 
| diff --git a/src/runtime.cc b/src/runtime.cc | 
| index 3e9c6c695456d0e66bdbf015ed9445aa92935f3c..c3918e634c0f060c49870744f6d4eb2def7a7d5c 100644 | 
| --- a/src/runtime.cc | 
| +++ b/src/runtime.cc | 
| @@ -11216,48 +11216,28 @@ class ScopeIterator { | 
| inlined_frame_index_(inlined_frame_index), | 
| function_(JSFunction::cast(frame->function())), | 
| context_(Context::cast(frame->context())), | 
| -      nested_scope_chain_(4) { | 
| +      local_done_(false), | 
| +      at_local_(false) { | 
|  | 
| -    // Catch the case when the debugger stops in an internal function. | 
| -    Handle<SharedFunctionInfo> shared_info(function_->shared()); | 
| -    if (shared_info->script() == isolate->heap()->undefined_value()) { | 
| -      while (context_->closure() == *function_) { | 
| -        context_ = Handle<Context>(context_->previous(), isolate_); | 
| -      } | 
| -      return; | 
| -    } | 
| - | 
| -    // Check whether we are in global code or function code. If there is a stack | 
| -    // slot for .result then this function has been created for evaluating | 
| -    // global code and it is not a real function. | 
| +    // Check whether the first scope is actually a local scope. | 
| +    // If there is a stack slot for .result then this local scope has been | 
| +    // created for evaluating top level code and it is not a real local scope. | 
| // Checking for the existence of .result seems fragile, but the scope info | 
| // saved with the code object does not otherwise have that information. | 
| -    int index = shared_info->scope_info()-> | 
| +    int index = function_->shared()->scope_info()-> | 
| StackSlotIndex(isolate_->heap()->result_symbol()); | 
| - | 
| -    // Reparse the code and analyze the scopes. | 
| -    ZoneScope zone_scope(isolate, DELETE_ON_EXIT); | 
| -    Handle<Script> script(Script::cast(shared_info->script())); | 
| -    Scope* scope; | 
| if (index >= 0) { | 
| -      // Global code | 
| -      CompilationInfo info(script); | 
| -      info.MarkAsGlobal(); | 
| -      CHECK(ParserApi::Parse(&info)); | 
| -      CHECK(Scope::Analyze(&info)); | 
| -      scope = info.function()->scope(); | 
| -    } else { | 
| -      // Function code | 
| -      CompilationInfo info(shared_info); | 
| -      CHECK(ParserApi::Parse(&info)); | 
| -      CHECK(Scope::Analyze(&info)); | 
| -      scope = info.function()->scope(); | 
| +      local_done_ = true; | 
| +    } else if (context_->IsGlobalContext() || | 
| +               context_->IsFunctionContext()) { | 
| +      at_local_ = true; | 
| +    } else if (context_->closure() != *function_) { | 
| +      // The context_ is a block or with or catch block from the outer function. | 
| +      ASSERT(context_->IsWithContext() || | 
| +             context_->IsCatchContext() || | 
| +             context_->IsBlockContext()); | 
| +      at_local_ = true; | 
| } | 
| - | 
| -    // Retrieve the scope chain for the current position. | 
| -    int statement_position = | 
| -        shared_info->code()->SourceStatementPosition(frame_->pc()); | 
| -    scope->GetNestedScopeChain(&nested_scope_chain_, statement_position); | 
| } | 
|  | 
| // More scopes? | 
| @@ -11265,48 +11245,40 @@ class ScopeIterator { | 
|  | 
| // Move to the next scope. | 
| void Next() { | 
| -    ScopeType scope_type = Type(); | 
| -    if (scope_type == ScopeTypeGlobal) { | 
| -      // The global scope is always the last in the chain. | 
| -      ASSERT(context_->IsGlobalContext()); | 
| +    // If at a local scope mark the local scope as passed. | 
| +    if (at_local_) { | 
| +      at_local_ = false; | 
| +      local_done_ = true; | 
| + | 
| +      // If the current context is not associated with the local scope the | 
| +      // current context is the next real scope, so don't move to the next | 
| +      // context in this case. | 
| +      if (context_->closure() != *function_) { | 
| +        return; | 
| +      } | 
| +    } | 
| + | 
| +    // The global scope is always the last in the chain. | 
| +    if (context_->IsGlobalContext()) { | 
| context_ = Handle<Context>(); | 
| return; | 
| } | 
| -    if (nested_scope_chain_.is_empty()) { | 
| -      context_ = Handle<Context>(context_->previous(), isolate_); | 
| -    } else { | 
| -      if (nested_scope_chain_.last()->HasContext()) { | 
| -        context_ = Handle<Context>(context_->previous(), isolate_); | 
| -      } | 
| -      nested_scope_chain_.RemoveLast(); | 
| + | 
| +    // Move to the next context. | 
| +    context_ = Handle<Context>(context_->previous(), isolate_); | 
| + | 
| +    // If passing the local scope indicate that the current scope is now the | 
| +    // local scope. | 
| +    if (!local_done_ && | 
| +        (context_->IsGlobalContext() || context_->IsFunctionContext())) { | 
| +      at_local_ = true; | 
| } | 
| } | 
|  | 
| // Return the type of the current scope. | 
| ScopeType Type() { | 
| -    if (!nested_scope_chain_.is_empty()) { | 
| -      Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); | 
| -      switch (scope_info->Type()) { | 
| -        case FUNCTION_SCOPE: | 
| -          ASSERT(context_->IsFunctionContext() || | 
| -                 !scope_info->HasContext()); | 
| -          return ScopeTypeLocal; | 
| -        case GLOBAL_SCOPE: | 
| -          ASSERT(context_->IsGlobalContext()); | 
| -          return ScopeTypeGlobal; | 
| -        case WITH_SCOPE: | 
| -          ASSERT(context_->IsWithContext()); | 
| -          return ScopeTypeWith; | 
| -        case CATCH_SCOPE: | 
| -          ASSERT(context_->IsCatchContext()); | 
| -          return ScopeTypeCatch; | 
| -        case BLOCK_SCOPE: | 
| -          ASSERT(!scope_info->HasContext() || | 
| -                 context_->IsBlockContext()); | 
| -          return ScopeTypeBlock; | 
| -        case EVAL_SCOPE: | 
| -          UNREACHABLE(); | 
| -      } | 
| +    if (at_local_) { | 
| +      return ScopeTypeLocal; | 
| } | 
| if (context_->IsGlobalContext()) { | 
| ASSERT(context_->global()->IsGlobalObject()); | 
| @@ -11332,7 +11304,6 @@ class ScopeIterator { | 
| return Handle<JSObject>(CurrentContext()->global()); | 
| case ScopeIterator::ScopeTypeLocal: | 
| // Materialize the content of the local scope into a JSObject. | 
| -        ASSERT(nested_scope_chain_.length() == 1); | 
| return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_); | 
| case ScopeIterator::ScopeTypeWith: | 
| // Return the with object. | 
| @@ -11349,28 +11320,13 @@ class ScopeIterator { | 
| return Handle<JSObject>(); | 
| } | 
|  | 
| -  Handle<ScopeInfo> CurrentScopeInfo() { | 
| -    if (!nested_scope_chain_.is_empty()) { | 
| -      return nested_scope_chain_.last(); | 
| -    } else if (context_->IsBlockContext()) { | 
| -      return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension())); | 
| -    } else if (context_->IsFunctionContext()) { | 
| -      return Handle<ScopeInfo>(context_->closure()->shared()->scope_info()); | 
| -    } | 
| -    return Handle<ScopeInfo>::null(); | 
| -  } | 
| - | 
| // Return the context for this scope. For the local context there might not | 
| // be an actual context. | 
| Handle<Context> CurrentContext() { | 
| -    if (Type() == ScopeTypeGlobal || | 
| -        nested_scope_chain_.is_empty()) { | 
| -      return context_; | 
| -    } else if (nested_scope_chain_.last()->HasContext()) { | 
| -      return context_; | 
| -    } else { | 
| +    if (at_local_ && context_->closure() != *function_) { | 
| return Handle<Context>(); | 
| } | 
| +    return context_; | 
| } | 
|  | 
| #ifdef DEBUG | 
| @@ -11432,7 +11388,8 @@ class ScopeIterator { | 
| int inlined_frame_index_; | 
| Handle<JSFunction> function_; | 
| Handle<Context> context_; | 
| -  List<Handle<ScopeInfo> > nested_scope_chain_; | 
| +  bool local_done_; | 
| +  bool at_local_; | 
|  | 
| DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); | 
| }; | 
| @@ -11895,65 +11852,45 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) { | 
|  | 
| // Creates a copy of the with context chain. The copy of the context chain is | 
| // is linked to the function context supplied. | 
| -static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate, | 
| -                                                   Handle<JSFunction> function, | 
| -                                                   Handle<Context> base, | 
| -                                                   JavaScriptFrame* frame, | 
| -                                                   int inlined_frame_index) { | 
| -  HandleScope scope(isolate); | 
| -  List<Handle<ScopeInfo> > scope_chain; | 
| -  List<Handle<Context> > context_chain; | 
| - | 
| -  ScopeIterator it(isolate, frame, inlined_frame_index); | 
| -  for (; it.Type() != ScopeIterator::ScopeTypeGlobal && | 
| -         it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) { | 
| -    ASSERT(!it.Done()); | 
| -    scope_chain.Add(it.CurrentScopeInfo()); | 
| -    context_chain.Add(it.CurrentContext()); | 
| +static Handle<Context> CopyWithContextChain(Isolate* isolate, | 
| +                                            Handle<JSFunction> function, | 
| +                                            Handle<Context> current, | 
| +                                            Handle<Context> base) { | 
| +  // At the end of the chain. Return the base context to link to. | 
| +  if (current->IsFunctionContext() || current->IsGlobalContext()) { | 
| +    return base; | 
| } | 
|  | 
| -  // At the end of the chain. Return the base context to link to. | 
| -  Handle<Context> context = base; | 
| - | 
| -  // Iteratively copy and or materialize the nested contexts. | 
| -  while (!scope_chain.is_empty()) { | 
| -    Handle<ScopeInfo> scope_info = scope_chain.RemoveLast(); | 
| -    Handle<Context> current = context_chain.RemoveLast(); | 
| -    ASSERT(!(scope_info->HasContext() & current.is_null())); | 
| - | 
| -    if (scope_info->Type() == CATCH_SCOPE) { | 
| -      Handle<String> name(String::cast(current->extension())); | 
| -      Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX)); | 
| -      context = | 
| -          isolate->factory()->NewCatchContext(function, | 
| -                                              context, | 
| -                                              name, | 
| -                                              thrown_object); | 
| -    } else if (scope_info->Type() == BLOCK_SCOPE) { | 
| -      // Materialize the contents of the block scope into a JSObject. | 
| -      Handle<JSObject> block_scope_object = | 
| -          MaterializeBlockScope(isolate, current); | 
| -      if (block_scope_object.is_null()) { | 
| -        return Handle<Context>::null(); | 
| -      } | 
| -      // Allocate a new function context for the debug evaluation and set the | 
| -      // extension object. | 
| -      Handle<Context> new_context = | 
| -          isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, | 
| -                                                 function); | 
| -      new_context->set_extension(*block_scope_object); | 
| -      new_context->set_previous(*context); | 
| -      context = new_context; | 
| -    } else { | 
| -      ASSERT(scope_info->Type() == WITH_SCOPE); | 
| -      ASSERT(current->IsWithContext()); | 
| -      Handle<JSObject> extension(JSObject::cast(current->extension())); | 
| -      context = | 
| -          isolate->factory()->NewWithContext(function, context, extension); | 
| +  // Recursively copy the with and catch contexts. | 
| +  HandleScope scope(isolate); | 
| +  Handle<Context> previous(current->previous()); | 
| +  Handle<Context> new_previous = | 
| +      CopyWithContextChain(isolate, function, previous, base); | 
| +  Handle<Context> new_current; | 
| +  if (current->IsCatchContext()) { | 
| +    Handle<String> name(String::cast(current->extension())); | 
| +    Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX)); | 
| +    new_current = | 
| +        isolate->factory()->NewCatchContext(function, | 
| +                                            new_previous, | 
| +                                            name, | 
| +                                            thrown_object); | 
| +  } else if (current->IsBlockContext()) { | 
| +    Handle<ScopeInfo> scope_info(ScopeInfo::cast(current->extension())); | 
| +    new_current = | 
| +        isolate->factory()->NewBlockContext(function, new_previous, scope_info); | 
| +    // Copy context slots. | 
| +    int num_context_slots = scope_info->ContextLength(); | 
| +    for (int i = Context::MIN_CONTEXT_SLOTS; i < num_context_slots; ++i) { | 
| +      new_current->set(i, current->get(i)); | 
| } | 
| +  } else { | 
| +    ASSERT(current->IsWithContext()); | 
| +    Handle<JSObject> extension(JSObject::cast(current->extension())); | 
| +    new_current = | 
| +        isolate->factory()->NewWithContext(function, new_previous, extension); | 
| } | 
| - | 
| -  return scope.CloseAndEscape(context); | 
| +  return scope.CloseAndEscape(new_current); | 
| } | 
|  | 
|  | 
| @@ -12088,11 +12025,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { | 
| if (scope_info->HasContext()) { | 
| function_context = Handle<Context>(frame_context->declaration_context()); | 
| } | 
| -  context = CopyNestedScopeContextChain(isolate, | 
| -                                        go_between, | 
| -                                        context, | 
| -                                        frame, | 
| -                                        inlined_frame_index); | 
| +  context = CopyWithContextChain(isolate, go_between, frame_context, context); | 
|  | 
| if (additional_context->IsJSObject()) { | 
| Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); | 
|  |