Version 3.7.9.
Removed exit-time destructors.
Stability and performance improvements on all platforms.
Review URL: http://codereview.chromium.org/8551006
git-svn-id: http://v8.googlecode.com/svn/trunk@10037 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/runtime.cc b/src/runtime.cc
index 62c38aa..c3918e6 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1794,11 +1794,14 @@
JSFunction::cast(constructor)->initial_map() == map) {
// If we still have the original map, set in-object properties directly.
regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
- // TODO(lrn): Consider skipping write barrier on booleans as well.
- // Both true and false should be in oldspace at all times.
- regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global);
- regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase);
- regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline);
+ // Both true and false are immovable immortal objects so no need for write
+ // barrier.
+ regexp->InObjectPropertyAtPut(
+ JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
+ regexp->InObjectPropertyAtPut(
+ JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
+ regexp->InObjectPropertyAtPut(
+ JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
Smi::FromInt(0),
SKIP_WRITE_BARRIER); // It's a Smi.
@@ -11213,48 +11216,28 @@
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?
@@ -11262,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());
@@ -11329,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.
@@ -11346,28 +11320,13 @@
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
@@ -11429,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);
};
@@ -11892,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.
- 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);
- }
+ if (current->IsFunctionContext() || current->IsGlobalContext()) {
+ return base;
}
- 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);
}
@@ -12085,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);