Chromium Code Reviews| Index: src/runtime.cc | 
| diff --git a/src/runtime.cc b/src/runtime.cc | 
| index 43d34510f4ac4ecce5be2f12d66b3bb33bf88956..3b9173e168547d26596d056645db07a2d64673bf 100644 | 
| --- a/src/runtime.cc | 
| +++ b/src/runtime.cc | 
| @@ -7883,7 +7883,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) { | 
| } | 
| -RUNTIME_FUNCTION(MaybeObject*, Runtime_NewContext) { | 
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) { | 
| NoHandleAllocation ha; | 
| ASSERT(args.length() == 1); | 
| @@ -7901,50 +7901,50 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewContext) { | 
| } | 
| -MUST_USE_RESULT static MaybeObject* PushContextHelper(Isolate* isolate, | 
| - Object* object, | 
| - bool is_catch_context) { | 
| - // Convert the object to a proper JavaScript object. | 
| - Object* js_object = object; | 
| - if (!js_object->IsJSObject()) { | 
| - MaybeObject* maybe_js_object = js_object->ToObject(); | 
| - if (!maybe_js_object->ToObject(&js_object)) { | 
| - if (!Failure::cast(maybe_js_object)->IsInternalError()) { | 
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) { | 
| + NoHandleAllocation ha; | 
| + ASSERT(args.length() == 1); | 
| + JSObject* extension_object; | 
| + if (args[0]->IsJSObject()) { | 
| + extension_object = JSObject::cast(args[0]); | 
| + } else { | 
| + // Convert the object to a proper JavaScript object. | 
| + MaybeObject* maybe_js_object = args[0]->ToObject(); | 
| + if (!maybe_js_object->To(&extension_object)) { | 
| + if (Failure::cast(maybe_js_object)->IsInternalError()) { | 
| + HandleScope scope(isolate); | 
| + Handle<Object> handle = args.at<Object>(0); | 
| + Handle<Object> result = | 
| + isolate->factory()->NewTypeError("with_expression", | 
| + HandleVector(&handle, 1)); | 
| + return isolate->Throw(*result); | 
| + } else { | 
| return maybe_js_object; | 
| } | 
| - HandleScope scope(isolate); | 
| - Handle<Object> handle(object, isolate); | 
| - Handle<Object> result = | 
| - isolate->factory()->NewTypeError("with_expression", | 
| - HandleVector(&handle, 1)); | 
| - return isolate->Throw(*result); | 
| } | 
| } | 
| - Object* result; | 
| - { MaybeObject* maybe_result = isolate->heap()->AllocateWithContext( | 
| - isolate->context(), JSObject::cast(js_object), is_catch_context); | 
| - if (!maybe_result->ToObject(&result)) return maybe_result; | 
| - } | 
| - | 
| - Context* context = Context::cast(result); | 
| + Context* context; | 
| + MaybeObject* maybe_context = | 
| + isolate->heap()->AllocateWithContext(isolate->context(), | 
| + extension_object); | 
| + if (!maybe_context->To(&context)) return maybe_context; | 
| isolate->set_context(context); | 
| - | 
| - return result; | 
| -} | 
| - | 
| - | 
| -RUNTIME_FUNCTION(MaybeObject*, Runtime_PushContext) { | 
| - NoHandleAllocation ha; | 
| - ASSERT(args.length() == 1); | 
| - return PushContextHelper(isolate, args[0], false); | 
| + return context; | 
| } | 
| RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) { | 
| NoHandleAllocation ha; | 
| ASSERT(args.length() == 1); | 
| - return PushContextHelper(isolate, args[0], true); | 
| + JSObject* extension_object = JSObject::cast(args[0]); | 
| + Context* context; | 
| + MaybeObject* maybe_context = | 
| + isolate->heap()->AllocateCatchContext(isolate->context(), | 
| + extension_object); | 
| + if (!maybe_context->To(&context)) return maybe_context; | 
| + isolate->set_context(context); | 
| + return context; | 
| } | 
| @@ -8607,9 +8607,8 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { | 
| // Stop search when eval is found or when the global context is | 
| // reached. | 
| if (attributes != ABSENT || context->IsGlobalContext()) break; | 
| - if (context->is_function_context()) { | 
| 
 
Kevin Millikin (Chromium)
2011/06/08 16:35:52
Global contexts could not reach this site.
 
 | 
| - context = Handle<Context>(Context::cast(context->closure()->context()), | 
| - isolate); | 
| + if (context->IsFunctionContext()) { | 
| + context = Handle<Context>(context->closure()->context(), isolate); | 
| } else { | 
| context = Handle<Context>(context->previous(), isolate); | 
| } | 
| @@ -9842,8 +9841,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { | 
| Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); | 
| ScopeInfo<> info(*scope_info); | 
| - // Get the context. | 
| - Handle<Context> context(Context::cast(it.frame()->context())); | 
| + // Get the nearest enclosing function context. | 
| + Handle<Context> context(Context::cast(it.frame()->context())->fcontext()); | 
| // Get the locals names and values into a temporary array. | 
| // | 
| @@ -9859,25 +9858,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { | 
| } | 
| // Fill in the values of the locals. | 
| - for (int i = 0; i < info.NumberOfLocals(); i++) { | 
| - if (is_optimized_frame) { | 
| - // If we are inspecting an optimized frame use undefined as the | 
| - // value for all locals. | 
| - // | 
| - // TODO(1140): We should be able to get the correct values | 
| - // for locals in optimized frames. | 
| + if (is_optimized_frame) { | 
| + // If we are inspecting an optimized frame use undefined as the | 
| + // value for all locals. | 
| + // | 
| + // TODO(1140): We should be able to get the correct values | 
| + // for locals in optimized frames. | 
| + for (int i = 0; i < info.NumberOfLocals(); i++) { | 
| locals->set(i * 2 + 1, isolate->heap()->undefined_value()); | 
| - } else if (i < info.number_of_stack_slots()) { | 
| + } | 
| + } else { | 
| + for (int i = 0; i < info.number_of_stack_slots(); i++) { | 
| // Get the value from the stack. | 
| locals->set(i * 2 + 1, it.frame()->GetExpression(i)); | 
| - } else { | 
| - // Traverse the context chain to the function context as all local | 
| - // variables stored in the context will be on the function context. | 
| + } | 
| + for (int i = info.number_of_stack_slots(); i < info.NumberOfLocals(); i++) { | 
| Handle<String> name = info.LocalName(i); | 
| - while (!context->is_function_context()) { | 
| - context = Handle<Context>(context->previous()); | 
| - } | 
| - ASSERT(context->is_function_context()); | 
| locals->set(i * 2 + 1, | 
| context->get(scope_info->ContextSlotIndex(*name, NULL))); | 
| } | 
| @@ -10139,7 +10135,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate, | 
| // context. | 
| static Handle<JSObject> MaterializeClosure(Isolate* isolate, | 
| Handle<Context> context) { | 
| - ASSERT(context->is_function_context()); | 
| 
 
Kevin Millikin (Chromium)
2011/06/08 16:35:52
It's a little convoluted, but MaterializeClosure i
 
 | 
| + ASSERT(context->IsFunctionContext()); | 
| Handle<SharedFunctionInfo> shared(context->closure()->shared()); | 
| Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); | 
| @@ -10238,7 +10234,7 @@ class ScopeIterator { | 
| int index = function_->shared()->scope_info()-> | 
| StackSlotIndex(isolate_->heap()->result_symbol()); | 
| at_local_ = index < 0; | 
| - } else if (context_->is_function_context()) { | 
| 
 
Kevin Millikin (Chromium)
2011/06/08 16:35:52
Global contexts could not reach this site.
 
 | 
| + } else if (context_->IsFunctionContext()) { | 
| at_local_ = true; | 
| } else if (context_->closure() != *function_) { | 
| // The context_ is a with block from the outer function. | 
| @@ -10272,8 +10268,8 @@ class ScopeIterator { | 
| } | 
| // Move to the next context. | 
| - if (context_->is_function_context()) { | 
| 
 
Kevin Millikin (Chromium)
2011/06/08 16:35:52
Also here.
 
 | 
| - context_ = Handle<Context>(Context::cast(context_->closure()->context())); | 
| + if (context_->IsFunctionContext()) { | 
| + context_ = Handle<Context>(context_->closure()->context()); | 
| } else { | 
| context_ = Handle<Context>(context_->previous()); | 
| } | 
| @@ -10281,7 +10277,7 @@ class ScopeIterator { | 
| // If passing the local scope indicate that the current scope is now the | 
| // local scope. | 
| if (!local_done_ && | 
| - (context_->IsGlobalContext() || (context_->is_function_context()))) { | 
| + (context_->IsGlobalContext() || (context_->IsFunctionContext()))) { | 
| 
 
Mads Ager (chromium)
2011/06/09 07:31:00
Can't we remove the IsGlobalContext here as well s
 
Kevin Millikin (Chromium)
2011/06/09 11:09:40
Not here, because this context_ is already the nex
 
Mads Ager (chromium)
2011/06/09 11:12:53
Oh, yeah. Thanks!
 
 | 
| at_local_ = true; | 
| } | 
| } | 
| @@ -10295,7 +10291,7 @@ class ScopeIterator { | 
| ASSERT(context_->global()->IsGlobalObject()); | 
| return ScopeTypeGlobal; | 
| } | 
| - if (context_->is_function_context()) { | 
| 
 
Kevin Millikin (Chromium)
2011/06/08 16:35:52
Also here.
 
 | 
| + if (context_->IsFunctionContext()) { | 
| return ScopeTypeClosure; | 
| } | 
| ASSERT(context_->has_extension()); | 
| @@ -10863,19 +10859,23 @@ 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> CopyWithContextChain(Handle<Context> context_chain, | 
| - Handle<Context> function_context) { | 
| - // At the bottom of the chain. Return the function context to link to. | 
| - if (context_chain->is_function_context()) { | 
| - return function_context; | 
| +static Handle<Context> CopyWithContextChain(Isolate* isolate, | 
| + Handle<Context> current, | 
| + Handle<Context> base) { | 
| + // At the end of the chain. Return the bast context to link to. | 
| 
 
Kevin Millikin (Chromium)
2011/06/08 16:35:52
bast ==> base.  Duh.
 
 | 
| + if (current->IsFunctionContext() || current->IsGlobalContext()) { | 
| + return base; | 
| } | 
| - // Recursively copy the with contexts. | 
| - Handle<Context> previous(context_chain->previous()); | 
| - Handle<JSObject> extension(JSObject::cast(context_chain->extension())); | 
| - Handle<Context> context = CopyWithContextChain(previous, function_context); | 
| - return context->GetIsolate()->factory()->NewWithContext( | 
| - context, extension, context_chain->IsCatchContext()); | 
| + // Recursively copy the with and catch contexts. | 
| + HandleScope scope(isolate); | 
| + Handle<Context> previous(current->previous()); | 
| + Handle<Context> new_previous = CopyWithContextChain(isolate, previous, base); | 
| + Handle<JSObject> extension(JSObject::cast(current->extension())); | 
| + Handle<Context> new_current = current->IsCatchContext() | 
| + ? isolate->factory()->NewCatchContext(new_previous, extension) | 
| + : isolate->factory()->NewWithContext(new_previous, extension); | 
| + return scope.CloseAndEscape(new_current); | 
| } | 
| @@ -11004,11 +11004,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { | 
| // Copy any with contexts present and chain them in front of this context. | 
| Handle<Context> frame_context(Context::cast(frame->context())); | 
| Handle<Context> function_context(frame_context->fcontext()); | 
| - context = CopyWithContextChain(frame_context, context); | 
| + context = CopyWithContextChain(isolate, frame_context, context); | 
| if (additional_context->IsJSObject()) { | 
| - context = isolate->factory()->NewWithContext(context, | 
| - Handle<JSObject>::cast(additional_context), false); | 
| + Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); | 
| + context = isolate->factory()->NewWithContext(context, extension); | 
| } | 
| // Wrap the evaluation statement in a new function compiled in the newly |