Rebuild scope chain from serialized scope info before parsing lazily.
We used to rebuild it in Scope::Analyze but this might lead to mismatch between scopes seen by parser during the first and the second parse of the function. BUG=v8:1230 Review URL: http://codereview.chromium.org/6646017 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7110 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5dcd32beda
commit
83616da7f5
@ -692,38 +692,40 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
|
||||
return result;
|
||||
}
|
||||
|
||||
FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
|
||||
FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
|
||||
CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
|
||||
HistogramTimerScope timer(&Counters::parse_lazy);
|
||||
Handle<String> source(String::cast(script_->source()));
|
||||
Counters::total_parse_size.Increment(source->length());
|
||||
|
||||
Handle<SharedFunctionInfo> shared_info = info->shared_info();
|
||||
// Initialize parser state.
|
||||
source->TryFlatten();
|
||||
if (source->IsExternalTwoByteString()) {
|
||||
ExternalTwoByteStringUC16CharacterStream stream(
|
||||
Handle<ExternalTwoByteString>::cast(source),
|
||||
info->start_position(),
|
||||
info->end_position());
|
||||
shared_info->start_position(),
|
||||
shared_info->end_position());
|
||||
FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
|
||||
return result;
|
||||
} else {
|
||||
GenericStringUC16CharacterStream stream(source,
|
||||
info->start_position(),
|
||||
info->end_position());
|
||||
shared_info->start_position(),
|
||||
shared_info->end_position());
|
||||
FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
||||
FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
|
||||
UC16CharacterStream* source,
|
||||
ZoneScope* zone_scope) {
|
||||
Handle<SharedFunctionInfo> shared_info = info->shared_info();
|
||||
scanner_.Initialize(source);
|
||||
ASSERT(target_stack_ == NULL);
|
||||
|
||||
Handle<String> name(String::cast(info->name()));
|
||||
Handle<String> name(String::cast(shared_info->name()));
|
||||
fni_ = new FuncNameInferrer();
|
||||
fni_->PushEnclosingName(name);
|
||||
|
||||
@ -735,18 +737,20 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
||||
{
|
||||
// Parse the function literal.
|
||||
Handle<String> no_name = Factory::empty_symbol();
|
||||
Scope* scope =
|
||||
NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
|
||||
Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
|
||||
if (!info->closure().is_null()) {
|
||||
scope = Scope::DeserializeScopeChain(info, scope);
|
||||
}
|
||||
LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
|
||||
scope);
|
||||
TemporaryScope temp_scope(&this->temp_scope_);
|
||||
|
||||
if (info->strict_mode()) {
|
||||
if (shared_info->strict_mode()) {
|
||||
top_scope_->EnableStrictMode();
|
||||
}
|
||||
|
||||
FunctionLiteralType type =
|
||||
info->is_expression() ? EXPRESSION : DECLARATION;
|
||||
shared_info->is_expression() ? EXPRESSION : DECLARATION;
|
||||
bool ok = true;
|
||||
result = ParseFunctionLiteral(name,
|
||||
false, // Strict mode name already checked.
|
||||
@ -764,7 +768,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
||||
zone_scope->DeleteOnExit();
|
||||
if (stack_overflow_) Top::StackOverflow();
|
||||
} else {
|
||||
Handle<String> inferred_name(info->inferred_name());
|
||||
Handle<String> inferred_name(shared_info->inferred_name());
|
||||
result->set_inferred_name(inferred_name);
|
||||
}
|
||||
return result;
|
||||
@ -5126,7 +5130,7 @@ bool ParserApi::Parse(CompilationInfo* info) {
|
||||
Handle<Script> script = info->script();
|
||||
if (info->is_lazy()) {
|
||||
Parser parser(script, true, NULL, NULL);
|
||||
result = parser.ParseLazy(info->shared_info());
|
||||
result = parser.ParseLazy(info);
|
||||
} else {
|
||||
bool allow_natives_syntax =
|
||||
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
|
||||
|
@ -426,7 +426,7 @@ class Parser {
|
||||
bool in_global_context,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
|
||||
FunctionLiteral* ParseLazy(CompilationInfo* info);
|
||||
|
||||
void ReportMessageAt(Scanner::Location loc,
|
||||
const char* message,
|
||||
@ -441,7 +441,7 @@ class Parser {
|
||||
// construct a hashable id, so if more than 2^17 are allowed, this
|
||||
// should be checked.
|
||||
static const int kMaxNumFunctionParameters = 32766;
|
||||
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info,
|
||||
FunctionLiteral* ParseLazy(CompilationInfo* info,
|
||||
UC16CharacterStream* source,
|
||||
ZoneScope* zone_scope);
|
||||
enum Mode {
|
||||
|
@ -148,13 +148,14 @@ Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info)
|
||||
unresolved_(16),
|
||||
decls_(4) {
|
||||
ASSERT(scope_info != NULL);
|
||||
SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info);
|
||||
SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
|
||||
ASSERT(resolved());
|
||||
InsertAfterScope(inner_scope);
|
||||
if (scope_info->HasHeapAllocatedLocals()) {
|
||||
num_heap_slots_ = scope_info_->NumberOfContextSlots();
|
||||
}
|
||||
|
||||
AddInnerScope(inner_scope);
|
||||
|
||||
// This scope's arguments shadow (if present) is context-allocated if an inner
|
||||
// scope accesses this one's parameters. Allocate the arguments_shadow_
|
||||
// variable if necessary.
|
||||
@ -175,29 +176,39 @@ Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info)
|
||||
}
|
||||
|
||||
|
||||
Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
|
||||
Scope* global_scope) {
|
||||
ASSERT(!info->closure().is_null());
|
||||
// If we have a serialized scope info, reuse it.
|
||||
Scope* innermost_scope = NULL;
|
||||
Scope* scope = NULL;
|
||||
|
||||
SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
JSFunction* current = *info->closure();
|
||||
do {
|
||||
current = current->context()->closure();
|
||||
SerializedScopeInfo* scope_info = current->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
scope = new Scope(scope, scope_info);
|
||||
if (innermost_scope == NULL) innermost_scope = scope;
|
||||
} else {
|
||||
ASSERT(current->context()->IsGlobalContext());
|
||||
}
|
||||
} while (!current->context()->IsGlobalContext());
|
||||
}
|
||||
|
||||
global_scope->AddInnerScope(scope);
|
||||
if (innermost_scope == NULL) innermost_scope = global_scope;
|
||||
|
||||
return innermost_scope;
|
||||
}
|
||||
|
||||
|
||||
bool Scope::Analyze(CompilationInfo* info) {
|
||||
ASSERT(info->function() != NULL);
|
||||
Scope* top = info->function()->scope();
|
||||
|
||||
// If we have a serialized scope info, reuse it.
|
||||
if (!info->closure().is_null()) {
|
||||
SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
Scope* scope = top;
|
||||
JSFunction* current = *info->closure();
|
||||
do {
|
||||
current = current->context()->closure();
|
||||
SerializedScopeInfo* scope_info = current->shared()->scope_info();
|
||||
if (scope_info != SerializedScopeInfo::Empty()) {
|
||||
scope = new Scope(scope, scope_info);
|
||||
} else {
|
||||
ASSERT(current->context()->IsGlobalContext());
|
||||
}
|
||||
} while (!current->context()->IsGlobalContext());
|
||||
}
|
||||
}
|
||||
|
||||
while (top->outer_scope() != NULL) top = top->outer_scope();
|
||||
top->AllocateVariables(info->calling_context());
|
||||
|
||||
|
18
src/scopes.h
18
src/scopes.h
@ -104,6 +104,9 @@ class Scope: public ZoneObject {
|
||||
// doesn't re-allocate variables repeatedly.
|
||||
static bool Analyze(CompilationInfo* info);
|
||||
|
||||
static Scope* DeserializeScopeChain(CompilationInfo* info,
|
||||
Scope* innermost_scope);
|
||||
|
||||
// The scope name is only used for printing/debugging.
|
||||
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
|
||||
|
||||
@ -318,14 +321,6 @@ class Scope: public ZoneObject {
|
||||
|
||||
explicit Scope(Type type);
|
||||
|
||||
void InsertAfterScope(Scope* scope) {
|
||||
inner_scopes_.Add(scope);
|
||||
outer_scope_ = scope->outer_scope_;
|
||||
outer_scope_->inner_scopes_.RemoveElement(scope);
|
||||
outer_scope_->inner_scopes_.Add(this);
|
||||
scope->outer_scope_ = this;
|
||||
}
|
||||
|
||||
// Scope tree.
|
||||
Scope* outer_scope_; // the immediately enclosing outer scope, or NULL
|
||||
ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes
|
||||
@ -419,6 +414,13 @@ class Scope: public ZoneObject {
|
||||
private:
|
||||
Scope(Scope* inner_scope, SerializedScopeInfo* scope_info);
|
||||
|
||||
void AddInnerScope(Scope* inner_scope) {
|
||||
if (inner_scope != NULL) {
|
||||
inner_scopes_.Add(inner_scope);
|
||||
inner_scope->outer_scope_ = this;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDefaults(Type type,
|
||||
Scope* outer_scope,
|
||||
SerializedScopeInfo* scope_info) {
|
||||
|
Loading…
Reference in New Issue
Block a user