Revision: 10033
Author: [email protected]
Date: Mon Nov 21 00:44:02 2011
Log: Partially revert r9734 due to crashes in dev and canary channel.
This reverts the changes to the ScopeIterator from r9734 to the
previous implementation. The other changes in the commit to Parser,
Scope and (Serialized)ScopeInfo are retained.
BUG=104522,v8:1824,v8:1826
Review URL: http://codereview.chromium.org/8547007
http://code.google.com/p/v8/source/detail?r=10033
Modified:
/branches/bleeding_edge/src/runtime.cc
=======================================
--- /branches/bleeding_edge/src/runtime.cc Fri Nov 18 06:09:41 2011
+++ /branches/bleeding_edge/src/runtime.cc Mon Nov 21 00:44:02 2011
@@ -11216,48 +11216,28 @@
inlined_frame_index_(inlined_frame_index),
function_(JSFunction::cast(frame->function())),
context_(Context::cast(frame->context())),
- nested_scope_chain_(4) {
-
- // 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.
+ local_done_(false),
+ at_local_(false) {
+
+ // 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();
- }
-
- // Retrieve the scope chain for the current position.
- int statement_position =
- shared_info->code()->SourceStatementPosition(frame_->pc());
- scope->GetNestedScopeChain(&nested_scope_chain_, statement_position);
+ 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;
+ }
}
// More scopes?
@@ -11265,48 +11245,40 @@
// 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 @@
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.
@@ -11348,29 +11319,14 @@
UNREACHABLE();
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 @@
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 @@
// 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);
- }
- }
-
- return scope.CloseAndEscape(context);
+ // 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(new_current);
}
@@ -12088,11 +12025,7 @@
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);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev