Commit 65aa596f authored by jochen's avatar jochen Committed by Commit bot

Only pass the outer scope info with ParseInfo

We don't need the context anymore for parsing, the scope info chain is
enough.

BUG=v8:5215
R=marja@chromium.org,jgruber@chromium.org,mstarzinger@chromium.org

Review-Url: https://codereview.chromium.org/2342443004
Cr-Commit-Position: refs/heads/master@{#39457}
parent 6b7430fa
......@@ -2221,7 +2221,6 @@ MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
}
source->info->set_script(script);
source->info->set_context(isolate->native_context());
{
// Create a canonical handle scope if compiling ignition bytecode. This is
......
......@@ -308,7 +308,7 @@ bool Scope::IsAsmFunction() const {
}
Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
Context* context,
ScopeInfo* scope_info,
DeclarationScope* script_scope,
AstValueFactory* ast_value_factory,
DeserializationMode deserialization_mode) {
......@@ -316,93 +316,68 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
Scope* current_scope = nullptr;
Scope* innermost_scope = nullptr;
Scope* outer_scope = nullptr;
while (!context->IsNativeContext()) {
if (context->IsWithContext() || context->IsDebugEvaluateContext()) {
while (scope_info) {
if (scope_info->scope_type() == WITH_SCOPE) {
// For scope analysis, debug-evaluate is equivalent to a with scope.
outer_scope = new (zone)
Scope(zone, WITH_SCOPE, Handle<ScopeInfo>(context->scope_info()));
outer_scope = new (zone) Scope(zone, WITH_SCOPE, handle(scope_info));
// TODO(yangguo): Remove once debug-evaluate properly keeps track of the
// function scope in which we are evaluating.
if (context->IsDebugEvaluateContext()) {
if (scope_info->IsDebugEvaluateScope()) {
outer_scope->set_is_debug_evaluate_scope();
}
} else if (context->IsScriptContext()) {
// If we reach a script context, it's the outermost context with scope
// info. The next context will be the native context. Install the scope
// info of this script context onto the existing script scope to avoid
// nesting script scopes.
Handle<ScopeInfo> scope_info(context->scope_info(), isolate);
} else if (scope_info->scope_type() == SCRIPT_SCOPE) {
// If we reach a script scope, it's the outermost scope. Install the
// scope info of this script context onto the existing script scope to
// avoid nesting script scopes.
if (deserialization_mode == DeserializationMode::kIncludingVariables) {
script_scope->SetScriptScopeInfo(scope_info);
script_scope->SetScriptScopeInfo(handle(scope_info));
}
DCHECK(context->previous()->IsNativeContext());
DCHECK(!scope_info->HasOuterScopeInfo());
break;
} else if (context->IsFunctionContext()) {
Handle<ScopeInfo> scope_info(context->scope_info(), isolate);
} else if (scope_info->scope_type() == FUNCTION_SCOPE ||
scope_info->scope_type() == EVAL_SCOPE) {
// TODO(neis): For an eval scope, we currently create an ordinary function
// context. This is wrong and needs to be fixed.
// https://bugs.chromium.org/p/v8/issues/detail?id=5295
DCHECK(scope_info->scope_type() == FUNCTION_SCOPE ||
scope_info->scope_type() == EVAL_SCOPE);
outer_scope =
new (zone) DeclarationScope(zone, FUNCTION_SCOPE, scope_info);
new (zone) DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info));
if (scope_info->IsAsmFunction())
outer_scope->AsDeclarationScope()->set_asm_function();
if (scope_info->IsAsmModule())
outer_scope->AsDeclarationScope()->set_asm_module();
} else if (context->IsBlockContext()) {
Handle<ScopeInfo> scope_info(context->scope_info(), isolate);
DCHECK_EQ(scope_info->scope_type(), BLOCK_SCOPE);
} else if (scope_info->scope_type() == BLOCK_SCOPE) {
if (scope_info->is_declaration_scope()) {
outer_scope =
new (zone) DeclarationScope(zone, BLOCK_SCOPE, scope_info);
new (zone) DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info));
} else {
outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, scope_info);
outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info));
}
} else if (context->IsModuleContext()) {
ScopeInfo* scope_info = context->scope_info();
DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE);
outer_scope = new (zone) ModuleScope(
isolate, Handle<ScopeInfo>(scope_info), ast_value_factory);
} else if (scope_info->scope_type() == MODULE_SCOPE) {
outer_scope = new (zone)
ModuleScope(isolate, handle(scope_info), ast_value_factory);
} else {
DCHECK(context->IsCatchContext());
String* name = context->catch_name();
DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE);
DCHECK_EQ(scope_info->LocalCount(), 1);
String* name = scope_info->LocalName(0);
outer_scope = new (zone)
Scope(zone, ast_value_factory->GetString(handle(name, isolate)),
Handle<ScopeInfo>(context->scope_info()));
handle(scope_info));
}
if (deserialization_mode == DeserializationMode::kScopesOnly) {
outer_scope->scope_info_ = Handle<ScopeInfo>::null();
}
if (current_scope != nullptr) {
outer_scope->AddInnerScope(current_scope);
DCHECK_IMPLIES(
deserialization_mode == DeserializationMode::kIncludingVariables,
current_scope->scope_info_->HasOuterScopeInfo());
DCHECK_IMPLIES(
deserialization_mode == DeserializationMode::kIncludingVariables,
outer_scope->scope_info_->Equals(
current_scope->scope_info_->OuterScopeInfo()));
}
current_scope = outer_scope;
if (innermost_scope == nullptr) innermost_scope = current_scope;
context = context->previous();
scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
: nullptr;
}
if (innermost_scope == nullptr) return script_scope;
script_scope->AddInnerScope(current_scope);
#if DEBUG
if (deserialization_mode == DeserializationMode::kIncludingVariables) {
if (script_scope->scope_info_.is_null()) {
DCHECK(!current_scope->scope_info_->HasOuterScopeInfo());
} else {
DCHECK(!script_scope->scope_info_->HasOuterScopeInfo());
DCHECK(script_scope->scope_info_->Equals(
current_scope->scope_info_->OuterScopeInfo()));
}
}
#endif
return innermost_scope;
}
......@@ -527,20 +502,19 @@ void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) {
DCHECK(info->literal() != NULL);
DeclarationScope* scope = info->literal()->scope();
if (!info->context().is_null() && !info->context()->IsNativeContext()) {
Handle<ScopeInfo> outer_scope_info;
if (info->maybe_outer_scope_info().ToHandle(&outer_scope_info)) {
if (scope->outer_scope()) {
DeclarationScope* script_scope = new (info->zone())
DeclarationScope(info->zone(), info->ast_value_factory());
info->set_script_scope(script_scope);
scope->ReplaceOuterScope(Scope::DeserializeScopeChain(
info->isolate(), info->zone(), *info->context(), script_scope,
info->isolate(), info->zone(), *outer_scope_info, script_scope,
info->ast_value_factory(),
Scope::DeserializationMode::kIncludingVariables));
} else {
DCHECK(info->context()->IsScriptContext());
Handle<ScopeInfo> scope_info(info->context()->scope_info(),
info->isolate());
scope->SetScriptScopeInfo(scope_info);
DCHECK_EQ(outer_scope_info->scope_type(), SCRIPT_SCOPE);
scope->SetScriptScopeInfo(outer_scope_info);
}
}
......
......@@ -101,7 +101,7 @@ class Scope: public ZoneObject {
enum class DeserializationMode { kIncludingVariables, kScopesOnly };
static Scope* DeserializeScopeChain(Isolate* isolate, Zone* zone,
Context* context,
ScopeInfo* scope_info,
DeclarationScope* script_scope,
AstValueFactory* ast_value_factory,
DeserializationMode deserialization_mode);
......
......@@ -51,7 +51,7 @@ BackgroundParsingTask::BackgroundParsingTask(
// thread.
source_->parser.reset(new Parser(source_->info.get()));
source_->parser->DeserializeScopeChain(source_->info.get(),
MaybeHandle<Context>());
MaybeHandle<ScopeInfo>());
}
......
......@@ -83,8 +83,12 @@ void CompilerDispatcherJob::PrepareToParseOnMainThread() {
parse_info_->set_language_mode(shared->language_mode());
parser_.reset(new Parser(parse_info_.get()));
parser_->DeserializeScopeChain(parse_info_.get(),
handle(function_->context(), isolate_));
parser_->DeserializeScopeChain(
parse_info_.get(),
function_->context()->IsNativeContext()
? MaybeHandle<ScopeInfo>()
: MaybeHandle<ScopeInfo>(function_->context()->scope_info(),
isolate_));
Handle<String> name(String::cast(shared->name()));
parse_info_->set_function_name(
......@@ -141,7 +145,10 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
Handle<Script> script(Script::cast(shared->script()), isolate_);
parse_info_->set_script(script);
parse_info_->set_context(handle(function_->context(), isolate_));
if (!function_->context()->IsNativeContext()) {
parse_info_->set_outer_scope_info(
handle(function_->context()->scope_info(), isolate_));
}
parse_info_->set_shared_info(handle(function_->shared(), isolate_));
{
......
......@@ -1482,7 +1482,9 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
if (context->IsNativeContext()) parse_info.set_global();
parse_info.set_language_mode(language_mode);
parse_info.set_parse_restriction(restriction);
parse_info.set_context(context);
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info()));
}
shared_info = CompileToplevel(&info);
......@@ -1655,7 +1657,9 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
}
parse_info.set_compile_options(compile_options);
parse_info.set_extension(extension);
parse_info.set_context(context);
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info()));
}
if (FLAG_serialize_toplevel &&
compile_options == ScriptCompiler::kProduceCodeCache) {
info.PrepareForSerializing();
......
......@@ -99,7 +99,9 @@ ScopeIterator::ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector,
} else {
DCHECK(scope_info->scope_type() == EVAL_SCOPE);
info->set_eval();
info->set_context(Handle<Context>(function->context()));
if (!function->context()->IsNativeContext()) {
info->set_outer_scope_info(handle(function->context()->scope_info()));
}
// Language mode may be inherited from the eval caller.
// Retrieve it from shared function info.
info->set_language_mode(shared_info->language_mode());
......
......@@ -206,6 +206,10 @@ class MaybeHandle final {
USE(a);
}
template <typename S>
V8_INLINE MaybeHandle(S* object, Isolate* isolate)
: MaybeHandle(handle(object, isolate)) {}
V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); }
V8_INLINE void Check() const { CHECK_NOT_NULL(location_); }
......
......@@ -33,7 +33,9 @@ ParseInfo::ParseInfo(Zone* zone)
ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function)
: ParseInfo(zone, Handle<SharedFunctionInfo>(function->shared())) {
set_context(Handle<Context>(function->context()));
if (!function->context()->IsNativeContext()) {
set_outer_scope_info(handle(function->context()->scope_info()));
}
}
ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared)
......
......@@ -159,11 +159,15 @@ class ParseInfo {
Isolate* isolate() const { return isolate_; }
Handle<SharedFunctionInfo> shared_info() const { return shared_; }
Handle<Script> script() const { return script_; }
Handle<Context> context() const { return context_; }
MaybeHandle<ScopeInfo> maybe_outer_scope_info() const {
return maybe_outer_scope_info_;
}
void clear_script() { script_ = Handle<Script>::null(); }
void set_isolate(Isolate* isolate) { isolate_ = isolate; }
void set_shared_info(Handle<SharedFunctionInfo> shared) { shared_ = shared; }
void set_context(Handle<Context> context) { context_ = context; }
void set_outer_scope_info(Handle<ScopeInfo> outer_scope_info) {
maybe_outer_scope_info_ = outer_scope_info;
}
void set_script(Handle<Script> script) { script_ = script; }
//--------------------------------------------------------------------------
......@@ -178,7 +182,10 @@ class ParseInfo {
void ReopenHandlesInNewHandleScope() {
shared_ = Handle<SharedFunctionInfo>(*shared_);
script_ = Handle<Script>(*script_);
context_ = Handle<Context>(*context_);
Handle<ScopeInfo> outer_scope_info;
if (maybe_outer_scope_info_.ToHandle(&outer_scope_info)) {
maybe_outer_scope_info_ = Handle<ScopeInfo>(*outer_scope_info);
}
}
#ifdef DEBUG
......@@ -224,7 +231,7 @@ class ParseInfo {
Isolate* isolate_;
Handle<SharedFunctionInfo> shared_;
Handle<Script> script_;
Handle<Context> context_;
MaybeHandle<ScopeInfo> maybe_outer_scope_info_;
//----------- Inputs+Outputs of parsing and scope analysis -----------------
ScriptData** cached_data_; // used if available, populated if requested.
......
......@@ -603,19 +603,19 @@ Parser::Parser(ParseInfo* info)
}
}
void Parser::DeserializeScopeChain(ParseInfo* info,
MaybeHandle<Context> maybe_context) {
void Parser::DeserializeScopeChain(
ParseInfo* info, MaybeHandle<ScopeInfo> maybe_outer_scope_info) {
DCHECK(ThreadId::Current().Equals(info->isolate()->thread_id()));
// TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
// context, which will have the "this" binding for script scopes.
DeclarationScope* script_scope = NewScriptScope();
info->set_script_scope(script_scope);
Scope* scope = script_scope;
Handle<Context> context;
if (maybe_context.ToHandle(&context) && !context->IsNativeContext()) {
Handle<ScopeInfo> outer_scope_info;
if (maybe_outer_scope_info.ToHandle(&outer_scope_info)) {
scope = Scope::DeserializeScopeChain(
info->isolate(), zone(), *context, script_scope, ast_value_factory(),
Scope::DeserializationMode::kScopesOnly);
info->isolate(), zone(), *outer_scope_info, script_scope,
ast_value_factory(), Scope::DeserializationMode::kScopesOnly);
DCHECK(!info->is_module() || scope->is_module_scope());
}
original_scope_ = scope;
......@@ -649,7 +649,7 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
cached_parse_data_->Initialize();
}
DeserializeScopeChain(info, info->context());
DeserializeScopeChain(info, info->maybe_outer_scope_info());
source = String::Flatten(source);
FunctionLiteral* result;
......@@ -814,7 +814,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
timer.Start();
}
Handle<SharedFunctionInfo> shared_info = info->shared_info();
DeserializeScopeChain(info, info->context());
DeserializeScopeChain(info, info->maybe_outer_scope_info());
// Initialize parser state.
source = String::Flatten(source);
......@@ -4052,7 +4052,7 @@ void Parser::ParseOnBackground(ParseInfo* info) {
info->source_stream_encoding()));
stream_ptr = stream.get();
}
DCHECK(info->context().is_null() || info->context()->IsNativeContext());
DCHECK(info->maybe_outer_scope_info().is_null());
DCHECK(original_scope_);
......
......@@ -186,14 +186,14 @@ class Parser : public ParserBase<Parser> {
// Deserialize the scope chain prior to parsing in which the script is going
// to be executed. If the script is a top-level script, or the scope chain
// consists of only a native context, maybe_context should be an empty
// handle.
// consists of only a native context, maybe_outer_scope_info should be an
// empty handle.
//
// This only deserializes the scope chain, but doesn't connect the scopes to
// their corresponding scope infos. Therefore, looking up variables in the
// deserialized scopes is not possible.
void DeserializeScopeChain(ParseInfo* info,
MaybeHandle<Context> maybe_context);
MaybeHandle<ScopeInfo> maybe_outer_scope_info);
// Handle errors detected during parsing, move statistics to Isolate,
// internalize strings (move them to the heap).
......
......@@ -3404,7 +3404,7 @@ TEST(SerializationOfMaybeAssignmentFlag) {
i::DeclarationScope* script_scope =
new (&zone) i::DeclarationScope(&zone, &avf);
i::Scope* s = i::Scope::DeserializeScopeChain(
isolate, &zone, context, script_scope, &avf,
isolate, &zone, context->scope_info(), script_scope, &avf,
i::Scope::DeserializationMode::kIncludingVariables);
CHECK(s != script_scope);
CHECK(name != NULL);
......@@ -3452,7 +3452,7 @@ TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
i::DeclarationScope* script_scope =
new (&zone) i::DeclarationScope(&zone, &avf);
i::Scope* s = i::Scope::DeserializeScopeChain(
isolate, &zone, context, script_scope, &avf,
isolate, &zone, context->scope_info(), script_scope, &avf,
i::Scope::DeserializationMode::kIncludingVariables);
CHECK(s != script_scope);
const i::AstRawString* name_x = avf.GetOneByteString("x");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment