summaryrefslogtreecommitdiff
path: root/deps/v8/src/ast/scopes.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ast/scopes.cc')
-rw-r--r--deps/v8/src/ast/scopes.cc1081
1 files changed, 501 insertions, 580 deletions
diff --git a/deps/v8/src/ast/scopes.cc b/deps/v8/src/ast/scopes.cc
index e9fb195609..28869cd94a 100644
--- a/deps/v8/src/ast/scopes.cc
+++ b/deps/v8/src/ast/scopes.cc
@@ -8,29 +8,21 @@
#include "src/accessors.h"
#include "src/ast/ast.h"
-#include "src/ast/scopes-inl.h"
#include "src/base/optional.h"
#include "src/bootstrapper.h"
#include "src/counters.h"
-#include "src/messages.h"
+#include "src/message-template.h"
#include "src/objects-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/scope-info.h"
#include "src/parsing/parse-info.h"
-#include "src/parsing/preparsed-scope-data.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/preparse-data.h"
#include "src/zone/zone-list-inl.h"
namespace v8 {
namespace internal {
-namespace {
-bool IsLexical(Variable* variable) {
- if (variable == Scope::kDummyPreParserLexicalVariable) return true;
- if (variable == Scope::kDummyPreParserVariable) return false;
- return IsLexicalVariableMode(variable->mode());
-}
-} // namespace
-
// ----------------------------------------------------------------------------
// Implementation of LocalsMap
//
@@ -48,34 +40,20 @@ Variable* VariableMap::Declare(Zone* zone, Scope* scope,
VariableKind kind,
InitializationFlag initialization_flag,
MaybeAssignedFlag maybe_assigned_flag,
- bool* added) {
+ bool* was_added) {
// AstRawStrings are unambiguous, i.e., the same string is always represented
// by the same AstRawString*.
// FIXME(marja): fix the type of Lookup.
Entry* p =
ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
ZoneAllocationPolicy(zone));
- if (added) *added = p->value == nullptr;
- if (p->value == nullptr) {
- // The variable has not been declared yet -> insert it.
- DCHECK_EQ(name, p->key);
- p->value = new (zone) Variable(scope, name, mode, kind, initialization_flag,
- maybe_assigned_flag);
- }
- return reinterpret_cast<Variable*>(p->value);
-}
-
-Variable* VariableMap::DeclareName(Zone* zone, const AstRawString* name,
- VariableMode mode) {
- Entry* p =
- ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
- ZoneAllocationPolicy(zone));
- if (p->value == nullptr) {
+ *was_added = p->value == nullptr;
+ if (*was_added) {
// The variable has not been declared yet -> insert it.
DCHECK_EQ(name, p->key);
- p->value = mode == VariableMode::kVar
- ? Scope::kDummyPreParserVariable
- : Scope::kDummyPreParserLexicalVariable;
+ Variable* variable = new (zone) Variable(
+ scope, name, mode, kind, initialization_flag, maybe_assigned_flag);
+ p->value = variable;
}
return reinterpret_cast<Variable*>(p->value);
}
@@ -149,24 +127,6 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
outer_scope_->AddInnerScope(this);
}
-Scope::Snapshot::Snapshot(Scope* scope)
- : outer_scope_(scope),
- top_inner_scope_(scope->inner_scope_),
- top_unresolved_(scope->unresolved_list_.first()),
- top_local_(scope->GetClosureScope()->locals_.end()),
- top_decl_(scope->GetClosureScope()->decls_.end()),
- outer_scope_calls_eval_(scope->scope_calls_eval_) {
- // Reset in order to record eval calls during this Snapshot's lifetime.
- outer_scope_->scope_calls_eval_ = false;
-}
-
-Scope::Snapshot::~Snapshot() {
- // Restore previous calls_eval bit if needed.
- if (outer_scope_calls_eval_) {
- outer_scope_->scope_calls_eval_ = true;
- }
-}
-
DeclarationScope::DeclarationScope(Zone* zone,
AstValueFactory* ast_value_factory)
: Scope(zone), function_kind_(kNormalFunction), params_(4, zone) {
@@ -175,7 +135,7 @@ DeclarationScope::DeclarationScope(Zone* zone,
// Make sure that if we don't find the global 'this', it won't be declared as
// a regular dynamic global by predeclaring it with the right variable kind.
- DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE);
+ DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE, this);
}
DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
@@ -188,13 +148,6 @@ DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
SetDefaults();
}
-bool DeclarationScope::IsDeclaredParameter(const AstRawString* name) {
- // If IsSimpleParameterList is false, duplicate parameters are not allowed,
- // however `arguments` may be allowed if function is not strict code. Thus,
- // the assumptions explained above do not hold.
- return params_.Contains(variables_.Lookup(name));
-}
-
ModuleScope::ModuleScope(DeclarationScope* script_scope,
AstValueFactory* ast_value_factory)
: DeclarationScope(ast_value_factory->zone(), script_scope, MODULE_SCOPE,
@@ -267,7 +220,7 @@ Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
num_heap_slots_ = scope_info->ContextLength();
DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
// We don't really need to use the preparsed scope data; this is just to
- // shorten the recursion in SetMustUsePreParsedScopeData.
+ // shorten the recursion in SetMustUsePreparseData.
must_use_preparsed_scope_data_ = true;
}
@@ -294,22 +247,22 @@ Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
// Cache the catch variable, even though it's also available via the
// scope_info, as the parser expects that a catch scope always has the catch
// variable as first and only variable.
+ bool was_added;
Variable* variable =
Declare(zone, catch_variable_name, VariableMode::kVar, NORMAL_VARIABLE,
- kCreatedInitialized, maybe_assigned);
+ kCreatedInitialized, maybe_assigned, &was_added);
+ DCHECK(was_added);
AllocateHeapSlot(variable);
}
void DeclarationScope::SetDefaults() {
is_declaration_scope_ = true;
has_simple_parameters_ = true;
- asm_module_ = false;
+ is_asm_module_ = false;
force_eager_compilation_ = false;
has_arguments_parameter_ = false;
scope_uses_super_property_ = false;
has_rest_ = false;
- has_promise_ = false;
- has_generator_object_ = false;
sloppy_block_function_map_ = nullptr;
receiver_ = nullptr;
new_target_ = nullptr;
@@ -319,7 +272,7 @@ void DeclarationScope::SetDefaults() {
should_eager_compile_ = false;
was_lazily_parsed_ = false;
is_skipped_function_ = false;
- preparsed_scope_data_builder_ = nullptr;
+ preparse_data_builder_ = nullptr;
#ifdef DEBUG
DeclarationScope* outer_declaration_scope =
outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
@@ -374,12 +327,10 @@ void DeclarationScope::set_should_eager_compile() {
should_eager_compile_ = !was_lazily_parsed_;
}
-void DeclarationScope::set_asm_module() {
- asm_module_ = true;
-}
+void DeclarationScope::set_is_asm_module() { is_asm_module_ = true; }
bool Scope::IsAsmModule() const {
- return is_function_scope() && AsDeclarationScope()->asm_module();
+ return is_function_scope() && AsDeclarationScope()->is_asm_module();
}
bool Scope::ContainsAsmModule() const {
@@ -398,7 +349,7 @@ bool Scope::ContainsAsmModule() const {
}
Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
- ScopeInfo* scope_info,
+ ScopeInfo scope_info,
DeclarationScope* script_scope,
AstValueFactory* ast_value_factory,
DeserializationMode deserialization_mode) {
@@ -406,7 +357,7 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
Scope* current_scope = nullptr;
Scope* innermost_scope = nullptr;
Scope* outer_scope = nullptr;
- while (scope_info) {
+ while (!scope_info.is_null()) {
if (scope_info->scope_type() == WITH_SCOPE) {
// For scope analysis, debug-evaluate is equivalent to a with scope.
outer_scope =
@@ -429,8 +380,9 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
} else if (scope_info->scope_type() == FUNCTION_SCOPE) {
outer_scope = new (zone)
DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info, isolate));
- if (scope_info->IsAsmModule())
- outer_scope->AsDeclarationScope()->set_asm_module();
+ if (scope_info->IsAsmModule()) {
+ outer_scope->AsDeclarationScope()->set_is_asm_module();
+ }
} else if (scope_info->scope_type() == EVAL_SCOPE) {
outer_scope = new (zone)
DeclarationScope(zone, EVAL_SCOPE, handle(scope_info, isolate));
@@ -450,7 +402,7 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
DCHECK_EQ(scope_info->ContextLocalCount(), 1);
DCHECK_EQ(scope_info->ContextLocalMode(0), VariableMode::kVar);
DCHECK_EQ(scope_info->ContextLocalInitFlag(0), kCreatedInitialized);
- String* name = scope_info->ContextLocalName(0);
+ String name = scope_info->ContextLocalName(0);
MaybeAssignedFlag maybe_assigned =
scope_info->ContextLocalMaybeAssignedFlag(0);
outer_scope = new (zone)
@@ -466,7 +418,16 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
current_scope = outer_scope;
if (innermost_scope == nullptr) innermost_scope = current_scope;
scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
- : nullptr;
+ : ScopeInfo();
+ }
+
+ if (deserialization_mode == DeserializationMode::kIncludingVariables &&
+ script_scope->scope_info_.is_null()) {
+ Handle<ScriptContextTable> table(
+ isolate->native_context()->script_context_table(), isolate);
+ Handle<Context> first = ScriptContextTable::GetContext(isolate, table, 0);
+ Handle<ScopeInfo> scope_info(first->scope_info(), isolate);
+ script_scope->SetScriptScopeInfo(scope_info);
}
if (innermost_scope == nullptr) return script_scope;
@@ -519,7 +480,11 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
SloppyBlockFunctionMap* map = sloppy_block_function_map();
if (map == nullptr) return;
- const bool has_simple_parameters = HasSimpleParameters();
+ // In case of complex parameters the current scope is the body scope and the
+ // parameters are stored in the outer scope.
+ Scope* parameter_scope = HasSimpleParameters() ? this : outer_scope_;
+ DCHECK(parameter_scope->is_function_scope() || is_eval_scope() ||
+ is_script_scope());
// The declarations need to be added in the order they were seen,
// so accumulate declared names sorted by index.
@@ -534,21 +499,9 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
// or parameter,
// Check if there's a conflict with a parameter.
- // This depends on the fact that functions always have a scope solely to
- // hold complex parameters, and the names local to that scope are
- // precisely the names of the parameters. IsDeclaredParameter(name) does
- // not hold for names declared by complex parameters, nor are those
- // bindings necessarily declared lexically, so we have to check for them
- // explicitly. On the other hand, if there are not complex parameters,
- // it is sufficient to just check IsDeclaredParameter.
- if (!has_simple_parameters) {
- if (outer_scope_->LookupLocal(name) != nullptr) {
- continue;
- }
- } else {
- if (IsDeclaredParameter(name)) {
- continue;
- }
+ Variable* maybe_parameter = parameter_scope->LookupLocal(name);
+ if (maybe_parameter != nullptr && maybe_parameter->is_parameter()) {
+ continue;
}
bool declaration_queued = false;
@@ -575,8 +528,8 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
// example, that does not prevent hoisting of the function in
// `{ let e; try {} catch (e) { function e(){} } }`
do {
- var = query_scope->LookupLocal(name);
- if (var != nullptr && IsLexical(var)) {
+ var = query_scope->LookupInScopeOrScopeInfo(name);
+ if (var != nullptr && IsLexicalVariableMode(var->mode())) {
should_hoist = false;
break;
}
@@ -592,12 +545,12 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
if (factory) {
DCHECK(!is_being_lazily_parsed_);
+ int pos = delegate->position();
Assignment* assignment = factory->NewAssignment(
- Token::ASSIGN, NewUnresolved(factory, name),
- delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition);
+ Token::ASSIGN, NewUnresolved(factory, name, pos),
+ delegate->scope()->NewUnresolved(factory, name, pos), pos);
assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
- Statement* statement =
- factory->NewExpressionStatement(assignment, kNoSourcePosition);
+ Statement* statement = factory->NewExpressionStatement(assignment, pos);
delegate->set_statement(statement);
}
}
@@ -610,46 +563,20 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
if (factory) {
DCHECK(!is_being_lazily_parsed_);
VariableProxy* proxy = factory->NewVariableProxy(name, NORMAL_VARIABLE);
- auto declaration =
- factory->NewVariableDeclaration(proxy, kNoSourcePosition);
+ auto declaration = factory->NewVariableDeclaration(kNoSourcePosition);
+ bool was_added;
// Based on the preceding checks, it doesn't matter what we pass as
// sloppy_mode_block_scope_function_redefinition.
bool ok = true;
- DeclareVariable(declaration, VariableMode::kVar,
+ DeclareVariable(declaration, proxy, VariableMode::kVar, NORMAL_VARIABLE,
Variable::DefaultInitializationFlag(VariableMode::kVar),
- nullptr, &ok);
+ &was_added, nullptr, &ok);
DCHECK(ok);
} else {
DCHECK(is_being_lazily_parsed_);
- Variable* var = DeclareVariableName(name, VariableMode::kVar);
- if (var != kDummyPreParserVariable &&
- var != kDummyPreParserLexicalVariable) {
- DCHECK(FLAG_preparser_scope_analysis);
- var->set_maybe_assigned();
- }
- }
- }
-}
-
-void DeclarationScope::AttachOuterScopeInfo(ParseInfo* info, Isolate* isolate) {
- DCHECK(scope_info_.is_null());
- Handle<ScopeInfo> outer_scope_info;
- if (info->maybe_outer_scope_info().ToHandle(&outer_scope_info)) {
- // If we have a scope info we will potentially need to lookup variable names
- // on the scope info as internalized strings, so make sure ast_value_factory
- // is internalized.
- info->ast_value_factory()->Internalize(isolate);
- if (outer_scope()) {
- DeclarationScope* script_scope = new (info->zone())
- DeclarationScope(info->zone(), info->ast_value_factory());
- info->set_script_scope(script_scope);
- ReplaceOuterScope(Scope::DeserializeScopeChain(
- isolate, info->zone(), *outer_scope_info, script_scope,
- info->ast_value_factory(),
- Scope::DeserializationMode::kIncludingVariables));
- } else {
- DCHECK_EQ(outer_scope_info->scope_type(), SCRIPT_SCOPE);
- SetScriptScopeInfo(outer_scope_info);
+ bool was_added;
+ Variable* var = DeclareVariableName(name, VariableMode::kVar, &was_added);
+ var->set_maybe_assigned();
}
}
}
@@ -686,10 +613,9 @@ bool DeclarationScope::Analyze(ParseInfo* info) {
scope->set_should_eager_compile();
if (scope->must_use_preparsed_scope_data_) {
- DCHECK(FLAG_preparser_scope_analysis);
DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
allow_deref.emplace();
- info->consumed_preparsed_scope_data()->RestoreScopeAllocationData(scope);
+ info->consumed_preparse_data()->RestoreScopeAllocationData(scope);
}
if (!scope->AllocateVariables(info)) return false;
@@ -712,11 +638,14 @@ void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
DCHECK(has_this_declaration());
bool derived_constructor = IsDerivedConstructor(function_kind_);
+ bool was_added;
Variable* var =
Declare(zone(), ast_value_factory->this_string(),
derived_constructor ? VariableMode::kConst : VariableMode::kVar,
THIS_VARIABLE,
- derived_constructor ? kNeedsInitialization : kCreatedInitialized);
+ derived_constructor ? kNeedsInitialization : kCreatedInitialized,
+ kNotAssigned, &was_added);
+ DCHECK(was_added);
receiver_ = var;
}
@@ -724,14 +653,14 @@ void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
DCHECK(is_function_scope());
DCHECK(!is_arrow_scope());
- arguments_ = LookupLocal(ast_value_factory->arguments_string());
- if (arguments_ == nullptr) {
- // Declare 'arguments' variable which exists in all non arrow functions.
- // Note that it might never be accessed, in which case it won't be
- // allocated during variable allocation.
- arguments_ = Declare(zone(), ast_value_factory->arguments_string(),
- VariableMode::kVar);
- } else if (IsLexical(arguments_)) {
+ // Declare 'arguments' variable which exists in all non arrow functions. Note
+ // that it might never be accessed, in which case it won't be allocated during
+ // variable allocation.
+ bool was_added;
+ arguments_ =
+ Declare(zone(), ast_value_factory->arguments_string(), VariableMode::kVar,
+ NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
+ if (!was_added && IsLexicalVariableMode(arguments_->mode())) {
// Check if there's lexically declared variable named arguments to avoid
// redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
arguments_ = nullptr;
@@ -744,29 +673,35 @@ void DeclarationScope::DeclareDefaultFunctionVariables(
DCHECK(!is_arrow_scope());
DeclareThis(ast_value_factory);
+ bool was_added;
new_target_ = Declare(zone(), ast_value_factory->new_target_string(),
- VariableMode::kConst);
+ VariableMode::kConst, NORMAL_VARIABLE,
+ kCreatedInitialized, kNotAssigned, &was_added);
+ DCHECK(was_added);
if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
IsAccessorFunction(function_kind_)) {
- EnsureRareData()->this_function =
- Declare(zone(), ast_value_factory->this_function_string(),
- VariableMode::kConst);
+ EnsureRareData()->this_function = Declare(
+ zone(), ast_value_factory->this_function_string(), VariableMode::kConst,
+ NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
+ DCHECK(was_added);
}
}
-Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) {
+Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name,
+ Scope* cache) {
DCHECK(is_function_scope());
DCHECK_NULL(function_);
- DCHECK_NULL(variables_.Lookup(name));
+ if (cache == nullptr) cache = this;
+ DCHECK_NULL(cache->variables_.Lookup(name));
VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
: NORMAL_VARIABLE;
function_ = new (zone())
Variable(this, name, VariableMode::kConst, kind, kCreatedInitialized);
if (calls_sloppy_eval()) {
- NonLocal(name, VariableMode::kDynamic);
+ cache->NonLocal(name, VariableMode::kDynamic);
} else {
- variables_.Add(zone(), function_);
+ cache->variables_.Add(zone(), function_);
}
return function_;
}
@@ -779,40 +714,14 @@ Variable* DeclarationScope::DeclareGeneratorObjectVar(
Variable* result = EnsureRareData()->generator_object =
NewTemporary(name, kNotAssigned);
result->set_is_used();
- has_generator_object_ = true;
return result;
}
-Variable* DeclarationScope::DeclarePromiseVar(const AstRawString* name) {
- DCHECK(is_function_scope());
- DCHECK_NULL(promise_var());
- Variable* result = EnsureRareData()->promise = NewTemporary(name);
- result->set_is_used();
- has_promise_ = true;
- return result;
-}
-
-bool Scope::HasBeenRemoved() const {
- if (sibling() == this) {
- DCHECK_NULL(inner_scope_);
- DCHECK(is_block_scope());
- return true;
- }
- return false;
-}
-
-Scope* Scope::GetUnremovedScope() {
- Scope* scope = this;
- while (scope != nullptr && scope->HasBeenRemoved()) {
- scope = scope->outer_scope();
- }
- DCHECK_NOT_NULL(scope);
- return scope;
-}
-
Scope* Scope::FinalizeBlockScope() {
DCHECK(is_block_scope());
- DCHECK(!HasBeenRemoved());
+#ifdef DEBUG
+ DCHECK_NE(sibling_, this);
+#endif
if (variables_.occupancy() > 0 ||
(is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval())) {
@@ -852,8 +761,9 @@ Scope* Scope::FinalizeBlockScope() {
num_heap_slots_ = 0;
// Mark scope as removed by making it its own sibling.
+#ifdef DEBUG
sibling_ = this;
- DCHECK(HasBeenRemoved());
+#endif
return nullptr;
}
@@ -865,25 +775,13 @@ void DeclarationScope::AddLocal(Variable* var) {
locals_.Add(var);
}
-Variable* Scope::Declare(Zone* zone, const AstRawString* name,
- VariableMode mode, VariableKind kind,
- InitializationFlag initialization_flag,
- MaybeAssignedFlag maybe_assigned_flag) {
- bool added;
- Variable* var =
- variables_.Declare(zone, this, name, mode, kind, initialization_flag,
- maybe_assigned_flag, &added);
- if (added) locals_.Add(var);
- return var;
-}
-
-void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const {
- DCHECK_EQ(new_parent, outer_scope_->inner_scope_);
- DCHECK_EQ(new_parent->outer_scope_, outer_scope_);
+void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
+ DCHECK(!IsCleared());
+ DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_);
+ DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer());
DCHECK_EQ(new_parent, new_parent->GetClosureScope());
DCHECK_NULL(new_parent->inner_scope_);
DCHECK(new_parent->unresolved_list_.is_empty());
- DCHECK(new_parent->locals_.is_empty());
Scope* inner_scope = new_parent->sibling_;
if (inner_scope != top_inner_scope_) {
for (; inner_scope->sibling() != top_inner_scope_;
@@ -905,52 +803,33 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const {
new_parent->sibling_ = top_inner_scope_;
}
- if (outer_scope_->unresolved_list_.first() != top_unresolved_) {
- // If the marked VariableProxy (snapshoted) is not the first, we need to
- // find it and move all VariableProxys up to that point into the new_parent,
- // then we restore the snapshoted state by reinitializing the outer_scope
- // list.
- {
- auto iter = outer_scope_->unresolved_list_.begin();
- while (*iter != top_unresolved_) {
- ++iter;
- }
- outer_scope_->unresolved_list_.Rewind(iter);
- }
-
- new_parent->unresolved_list_ = std::move(outer_scope_->unresolved_list_);
- outer_scope_->unresolved_list_.ReinitializeHead(top_unresolved_);
- }
+ Scope* outer_scope_ = outer_scope_and_calls_eval_.GetPointer();
+ new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_,
+ top_unresolved_);
- // TODO(verwaest): This currently only moves do-expression declared variables
- // in default arguments that weren't already previously declared with the same
- // name in the closure-scope. See
- // test/mjsunit/harmony/default-parameter-do-expression.js.
+ // Move temporaries allocated for complex parameter initializers.
DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
-
- new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
- for (Variable* local : new_parent->locals_) {
- DCHECK(local->mode() == VariableMode::kTemporary ||
- local->mode() == VariableMode::kVar);
+ for (auto it = top_local_; it != outer_closure->locals()->end(); ++it) {
+ Variable* local = *it;
+ DCHECK_EQ(VariableMode::kTemporary, local->mode());
DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
DCHECK_NE(local->scope(), new_parent);
local->set_scope(new_parent);
- if (local->mode() == VariableMode::kVar) {
- outer_closure->variables_.Remove(local);
- new_parent->variables_.Add(new_parent->zone(), local);
- }
}
+ new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
outer_closure->locals_.Rewind(top_local_);
- outer_closure->decls_.Rewind(top_decl_);
// Move eval calls since Snapshot's creation into new_parent.
- if (outer_scope_->scope_calls_eval_) {
+ if (outer_scope_and_calls_eval_->scope_calls_eval_) {
new_parent->scope_calls_eval_ = true;
new_parent->inner_scope_calls_eval_ = true;
}
- // Reset the outer_scope's eval state. It will be restored to its
- // original value as necessary in the destructor of this class.
- outer_scope_->scope_calls_eval_ = false;
+
+ // We are in the arrow function case. The calls eval we may have recorded
+ // is intended for the inner scope and we should simply restore the
+ // original "calls eval" flag of the outer scope.
+ RestoreEvalFlag();
+ Clear();
}
void Scope::ReplaceOuterScope(Scope* outer) {
@@ -962,7 +841,10 @@ void Scope::ReplaceOuterScope(Scope* outer) {
outer_scope_ = outer;
}
-Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
+Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
+ DCHECK(!scope_info_.is_null());
+ DCHECK_NULL(cache->variables_.Lookup(name));
+
Handle<String> name_handle = name->string();
// The Scope is backed up by ScopeInfo. This means it cannot operate in a
// heap-independent mode, and all strings must be internalized immediately. So
@@ -992,10 +874,10 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
if (!found) {
index = scope_info_->FunctionContextSlotIndex(*name_handle);
if (index < 0) return nullptr; // Nowhere found.
- Variable* var = AsDeclarationScope()->DeclareFunctionVar(name);
+ Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache);
DCHECK_EQ(VariableMode::kConst, var->mode());
var->AllocateTo(VariableLocation::CONTEXT, index);
- return variables_.Lookup(name);
+ return cache->variables_.Lookup(name);
}
VariableKind kind = NORMAL_VARIABLE;
@@ -1006,23 +888,20 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
// TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and
// ARGUMENTS bindings as their corresponding VariableKind.
- Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag,
- maybe_assigned_flag);
+ bool was_added;
+ Variable* var =
+ cache->variables_.Declare(zone(), this, name, mode, kind, init_flag,
+ maybe_assigned_flag, &was_added);
+ DCHECK(was_added);
var->AllocateTo(location, index);
return var;
}
-Variable* Scope::Lookup(const AstRawString* name) {
- for (Scope* scope = this; scope != nullptr; scope = scope->outer_scope()) {
- Variable* var = scope->LookupLocal(name);
- if (var != nullptr) return var;
- }
- return nullptr;
-}
-
-Variable* DeclarationScope::DeclareParameter(
- const AstRawString* name, VariableMode mode, bool is_optional, bool is_rest,
- bool* is_duplicate, AstValueFactory* ast_value_factory, int position) {
+Variable* DeclarationScope::DeclareParameter(const AstRawString* name,
+ VariableMode mode,
+ bool is_optional, bool is_rest,
+ AstValueFactory* ast_value_factory,
+ int position) {
DCHECK(!already_resolved_);
DCHECK(is_function_scope() || is_module_scope());
DCHECK(!has_rest_);
@@ -1033,53 +912,37 @@ Variable* DeclarationScope::DeclareParameter(
if (mode == VariableMode::kTemporary) {
var = NewTemporary(name);
} else {
+ var = LookupLocal(name);
DCHECK_EQ(mode, VariableMode::kVar);
- var = Declare(zone(), name, mode);
- // TODO(wingo): Avoid O(n^2) check.
- if (is_duplicate != nullptr) {
- *is_duplicate = *is_duplicate || IsDeclaredParameter(name);
- }
+ DCHECK(var->is_parameter());
}
has_rest_ = is_rest;
var->set_initializer_position(position);
params_.Add(var, zone());
+ if (!is_rest) ++num_parameters_;
if (name == ast_value_factory->arguments_string()) {
has_arguments_parameter_ = true;
}
+ // Params are automatically marked as used to make sure that the debugger and
+ // function.arguments sees them.
+ // TODO(verwaest): Reevaluate whether we always need to do this, since
+ // strict-mode function.arguments does not make the arguments available.
+ var->set_is_used();
return var;
}
-Variable* DeclarationScope::DeclareParameterName(
- const AstRawString* name, bool is_rest, AstValueFactory* ast_value_factory,
- bool declare_as_local, bool add_parameter) {
+void DeclarationScope::RecordParameter(bool is_rest) {
DCHECK(!already_resolved_);
DCHECK(is_function_scope() || is_module_scope());
- DCHECK(!has_rest_ || is_rest);
DCHECK(is_being_lazily_parsed_);
+ DCHECK(!has_rest_);
has_rest_ = is_rest;
- if (name == ast_value_factory->arguments_string()) {
- has_arguments_parameter_ = true;
- }
- if (FLAG_preparser_scope_analysis) {
- Variable* var;
- if (declare_as_local) {
- var = Declare(zone(), name, VariableMode::kVar);
- } else {
- var = new (zone()) Variable(this, name, VariableMode::kTemporary,
- NORMAL_VARIABLE, kCreatedInitialized);
- }
- if (add_parameter) {
- params_.Add(var, zone());
- }
- return var;
- }
- DeclareVariableName(name, VariableMode::kVar);
- return nullptr;
+ if (!is_rest) ++num_parameters_;
}
Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
- InitializationFlag init_flag, VariableKind kind,
- MaybeAssignedFlag maybe_assigned_flag) {
+ VariableKind kind, bool* was_added,
+ InitializationFlag init_flag) {
DCHECK(!already_resolved_);
// This function handles VariableMode::kVar, VariableMode::kLet, and
// VariableMode::kConst modes. VariableMode::kDynamic variables are
@@ -1090,11 +953,14 @@ Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
mode == VariableMode::kVar || mode == VariableMode::kLet ||
mode == VariableMode::kConst);
DCHECK(!GetDeclarationScope()->was_lazily_parsed());
- return Declare(zone(), name, mode, kind, init_flag, maybe_assigned_flag);
+ return Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added);
}
+// TODO(leszeks): Avoid passing the proxy into here, passing the raw_name alone
+// instead.
Variable* Scope::DeclareVariable(
- Declaration* declaration, VariableMode mode, InitializationFlag init,
+ Declaration* declaration, VariableProxy* proxy, VariableMode mode,
+ VariableKind kind, InitializationFlag init, bool* was_added,
bool* sloppy_mode_block_scope_function_redefinition, bool* ok) {
DCHECK(IsDeclaredVariableMode(mode));
DCHECK(!already_resolved_);
@@ -1103,18 +969,16 @@ Variable* Scope::DeclareVariable(
if (mode == VariableMode::kVar && !is_declaration_scope()) {
return GetDeclarationScope()->DeclareVariable(
- declaration, mode, init, sloppy_mode_block_scope_function_redefinition,
- ok);
+ declaration, proxy, mode, kind, init, was_added,
+ sloppy_mode_block_scope_function_redefinition, ok);
}
DCHECK(!is_catch_scope());
DCHECK(!is_with_scope());
DCHECK(is_declaration_scope() ||
(IsLexicalVariableMode(mode) && is_block_scope()));
- VariableProxy* proxy = declaration->proxy();
DCHECK_NOT_NULL(proxy->raw_name());
const AstRawString* name = proxy->raw_name();
- bool is_function_declaration = declaration->IsFunctionDeclaration();
// Pessimistically assume that top-level variables will be assigned.
//
@@ -1127,71 +991,55 @@ Variable* Scope::DeclareVariable(
if (mode != VariableMode::kConst) proxy->set_is_assigned();
}
- Variable* var = nullptr;
- if (is_eval_scope() && is_sloppy(language_mode()) &&
- mode == VariableMode::kVar) {
- // In a var binding in a sloppy direct eval, pollute the enclosing scope
- // with this new binding by doing the following:
- // The proxy is bound to a lookup variable to force a dynamic declaration
- // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
- var = new (zone())
- Variable(this, name, mode, NORMAL_VARIABLE, init, kMaybeAssigned);
- var->AllocateTo(VariableLocation::LOOKUP, -1);
- } else {
- // Declare the variable in the declaration scope.
- var = LookupLocal(name);
- if (var == nullptr) {
+ Variable* var = LookupLocal(name);
+ // Declare the variable in the declaration scope.
+ *was_added = var == nullptr;
+ if (V8_LIKELY(*was_added)) {
+ if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) &&
+ mode == VariableMode::kVar)) {
+ // In a var binding in a sloppy direct eval, pollute the enclosing scope
+ // with this new binding by doing the following:
+ // The proxy is bound to a lookup variable to force a dynamic declaration
+ // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
+ DCHECK_EQ(NORMAL_VARIABLE, kind);
+ var = NonLocal(proxy->raw_name(), VariableMode::kDynamic);
+ } else {
// Declare the name.
- VariableKind kind = NORMAL_VARIABLE;
- if (is_function_declaration) {
- kind = FUNCTION_VARIABLE;
- }
- var = DeclareLocal(name, mode, init, kind, kNotAssigned);
- } else if (IsLexicalVariableMode(mode) ||
- IsLexicalVariableMode(var->mode())) {
- // Allow duplicate function decls for web compat, see bug 4693.
- bool duplicate_allowed = false;
- if (is_sloppy(language_mode()) && is_function_declaration &&
- var->is_function()) {
- DCHECK(IsLexicalVariableMode(mode) &&
- IsLexicalVariableMode(var->mode()));
- // If the duplication is allowed, then the var will show up
- // in the SloppyBlockFunctionMap and the new FunctionKind
- // will be a permitted duplicate.
- FunctionKind function_kind =
- declaration->AsFunctionDeclaration()->fun()->kind();
- SloppyBlockFunctionMap* map =
- GetDeclarationScope()->sloppy_block_function_map();
- duplicate_allowed = map != nullptr &&
- map->Lookup(const_cast<AstRawString*>(name),
- name->Hash()) != nullptr &&
- !IsAsyncFunction(function_kind) &&
- !IsGeneratorFunction(function_kind);
- }
- if (duplicate_allowed) {
- *sloppy_mode_block_scope_function_redefinition = true;
- } else {
- // The name was declared in this scope before; check for conflicting
- // re-declarations. We have a conflict if either of the declarations
- // is not a var (in script scope, we also have to ignore legacy const
- // for compatibility). There is similar code in runtime.cc in the
- // Declare functions. The function CheckConflictingVarDeclarations
- // checks for var and let bindings from different scopes whereas this
- // is a check for conflicting declarations within the same scope. This
- // check also covers the special case
- //
- // function () { let x; { var x; } }
- //
- // because the var declaration is hoisted to the function scope where
- // 'x' is already bound.
- DCHECK(IsDeclaredVariableMode(var->mode()));
- // In harmony we treat re-declarations as early errors. See
- // ES5 16 for a definition of early errors.
- *ok = false;
- return nullptr;
- }
- } else if (mode == VariableMode::kVar) {
- var->set_maybe_assigned();
+ var = DeclareLocal(name, mode, kind, was_added, init);
+ DCHECK(*was_added);
+ }
+ } else {
+ var->set_maybe_assigned();
+ if (V8_UNLIKELY(IsLexicalVariableMode(mode) ||
+ IsLexicalVariableMode(var->mode()))) {
+ // The name was declared in this scope before; check for conflicting
+ // re-declarations. We have a conflict if either of the declarations is
+ // not a var (in script scope, we also have to ignore legacy const for
+ // compatibility). There is similar code in runtime.cc in the Declare
+ // functions. The function CheckConflictingVarDeclarations checks for
+ // var and let bindings from different scopes whereas this is a check
+ // for conflicting declarations within the same scope. This check also
+ // covers the special case
+ //
+ // function () { let x; { var x; } }
+ //
+ // because the var declaration is hoisted to the function scope where
+ // 'x' is already bound.
+ //
+ // In harmony we treat re-declarations as early errors. See ES5 16 for a
+ // definition of early errors.
+ //
+ // Allow duplicate function decls for web compat, see bug 4693. If the
+ // duplication is allowed, then the var will show up in the
+ // SloppyBlockFunctionMap.
+ SloppyBlockFunctionMap* map =
+ GetDeclarationScope()->sloppy_block_function_map();
+ *ok =
+ map != nullptr && declaration->IsFunctionDeclaration() &&
+ declaration->AsFunctionDeclaration()
+ ->declares_sloppy_block_function() &&
+ map->Lookup(const_cast<AstRawString*>(name), name->Hash()) != nullptr;
+ *sloppy_mode_block_scope_function_redefinition = *ok;
}
}
DCHECK_NOT_NULL(var);
@@ -1206,18 +1054,21 @@ Variable* Scope::DeclareVariable(
// semantic issue, but it may be a performance issue since it may
// lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
decls_.Add(declaration);
+ declaration->set_var(var);
proxy->BindTo(var);
return var;
}
Variable* Scope::DeclareVariableName(const AstRawString* name,
- VariableMode mode) {
+ VariableMode mode, bool* was_added,
+ VariableKind kind) {
DCHECK(IsDeclaredVariableMode(mode));
DCHECK(!already_resolved_);
DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
if (mode == VariableMode::kVar && !is_declaration_scope()) {
- return GetDeclarationScope()->DeclareVariableName(name, mode);
+ return GetDeclarationScope()->DeclareVariableName(name, mode, was_added,
+ kind);
}
DCHECK(!is_with_scope());
DCHECK(!is_eval_scope());
@@ -1225,52 +1076,46 @@ Variable* Scope::DeclareVariableName(const AstRawString* name,
DCHECK(scope_info_.is_null());
// Declare the variable in the declaration scope.
- if (FLAG_preparser_scope_analysis) {
- Variable* var = LookupLocal(name);
- DCHECK_NE(var, kDummyPreParserLexicalVariable);
- DCHECK_NE(var, kDummyPreParserVariable);
- if (var == nullptr) {
- var = DeclareLocal(name, mode);
- } else if (IsLexicalVariableMode(mode) ||
- IsLexicalVariableMode(var->mode())) {
+ Variable* var = DeclareLocal(name, mode, kind, was_added);
+ if (!*was_added) {
+ if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())) {
// Duplicate functions are allowed in the sloppy mode, but if this is not
// a function declaration, it's an error. This is an error PreParser
- // hasn't previously detected. TODO(marja): Investigate whether we can now
- // start returning this error.
- } else if (mode == VariableMode::kVar) {
- var->set_maybe_assigned();
+ // hasn't previously detected.
+ return nullptr;
}
- var->set_is_used();
- return var;
- } else {
- return variables_.DeclareName(zone(), name, mode);
+ if (mode == VariableMode::kVar) var->set_maybe_assigned();
}
+ var->set_is_used();
+ return var;
}
-void Scope::DeclareCatchVariableName(const AstRawString* name) {
+Variable* Scope::DeclareCatchVariableName(const AstRawString* name) {
DCHECK(!already_resolved_);
- DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
DCHECK(is_catch_scope());
DCHECK(scope_info_.is_null());
- if (FLAG_preparser_scope_analysis) {
- Declare(zone(), name, VariableMode::kVar);
- } else {
- variables_.DeclareName(zone(), name, VariableMode::kVar);
- }
+ bool was_added;
+ Variable* result = Declare(zone(), name, VariableMode::kVar, NORMAL_VARIABLE,
+ kCreatedInitialized, kNotAssigned, &was_added);
+ DCHECK(was_added);
+ return result;
}
void Scope::AddUnresolved(VariableProxy* proxy) {
DCHECK(!already_resolved_);
DCHECK(!proxy->is_resolved());
- unresolved_list_.AddFront(proxy);
+ unresolved_list_.Add(proxy);
}
Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
- VariableKind kind) {
+ VariableKind kind,
+ Scope* cache) {
DCHECK(is_script_scope());
- return variables_.Declare(zone(), this, name, VariableMode::kDynamicGlobal,
- kind);
+ bool was_added;
+ return cache->variables_.Declare(
+ zone(), this, name, VariableMode::kDynamicGlobal, kind,
+ kCreatedInitialized, kNotAssigned, &was_added);
// TODO(neis): Mark variable as maybe-assigned?
}
@@ -1278,6 +1123,11 @@ bool Scope::RemoveUnresolved(VariableProxy* var) {
return unresolved_list_.Remove(var);
}
+void Scope::DeleteUnresolved(VariableProxy* var) {
+ DCHECK(unresolved_list_.Contains(var));
+ var->mark_removed_from_unresolved();
+}
+
Variable* Scope::NewTemporary(const AstRawString* name) {
return NewTemporary(name, kMaybeAssigned);
}
@@ -1294,53 +1144,46 @@ Variable* Scope::NewTemporary(const AstRawString* name,
Declaration* Scope::CheckConflictingVarDeclarations() {
for (Declaration* decl : decls_) {
- VariableMode mode = decl->proxy()->var()->mode();
-
// Lexical vs lexical conflicts within the same scope have already been
// captured in Parser::Declare. The only conflicts we still need to check
- // are lexical vs nested var, or any declarations within a declaration
- // block scope vs lexical declarations in its surrounding (function) scope.
- Scope* current = this;
+ // are lexical vs nested var.
+ Scope* current = nullptr;
if (decl->IsVariableDeclaration() &&
decl->AsVariableDeclaration()->AsNested() != nullptr) {
- DCHECK_EQ(mode, VariableMode::kVar);
current = decl->AsVariableDeclaration()->AsNested()->scope();
- } else if (IsLexicalVariableMode(mode)) {
- if (!is_block_scope()) continue;
- DCHECK(is_declaration_scope());
- DCHECK_EQ(outer_scope()->scope_type(), FUNCTION_SCOPE);
- current = outer_scope();
+ } else if (is_eval_scope() && is_sloppy(language_mode())) {
+ if (IsLexicalVariableMode(decl->var()->mode())) continue;
+ current = outer_scope_;
}
-
+ if (current == nullptr) continue;
+ DCHECK(decl->var()->mode() == VariableMode::kVar ||
+ decl->var()->mode() == VariableMode::kDynamic);
// Iterate through all scopes until and including the declaration scope.
while (true) {
// There is a conflict if there exists a non-VAR binding.
Variable* other_var =
- current->variables_.Lookup(decl->proxy()->raw_name());
+ current->LookupInScopeOrScopeInfo(decl->var()->raw_name());
if (other_var != nullptr && IsLexicalVariableMode(other_var->mode())) {
return decl;
}
- if (current->is_declaration_scope()) break;
+ if (current->is_declaration_scope() &&
+ !(current->is_eval_scope() && is_sloppy(current->language_mode()))) {
+ break;
+ }
current = current->outer_scope();
}
}
return nullptr;
}
-Declaration* Scope::CheckLexDeclarationsConflictingWith(
- const ZonePtrList<const AstRawString>& names) {
- DCHECK(is_block_scope());
- for (int i = 0; i < names.length(); ++i) {
- Variable* var = LookupLocal(names.at(i));
- if (var != nullptr) {
- // Conflict; find and return its declaration.
- DCHECK(IsLexicalVariableMode(var->mode()));
- const AstRawString* name = names.at(i);
- for (Declaration* decl : decls_) {
- if (decl->proxy()->raw_name() == name) return decl;
- }
- DCHECK(false);
- }
+const AstRawString* Scope::FindVariableDeclaredIn(Scope* scope,
+ VariableMode mode_limit) {
+ const VariableMap& variables = scope->variables_;
+ for (ZoneHashMap::Entry* p = variables.Start(); p != nullptr;
+ p = variables.Next(p)) {
+ const AstRawString* name = static_cast<const AstRawString*>(p->key);
+ Variable* var = LookupLocal(name);
+ if (var != nullptr && var->mode() <= mode_limit) return name;
}
return nullptr;
}
@@ -1467,14 +1310,82 @@ Scope* Scope::GetOuterScopeWithContext() {
return scope;
}
+void Scope::CollectNonLocals(DeclarationScope* max_outer_scope,
+ Isolate* isolate, ParseInfo* info,
+ Handle<StringSet>* non_locals) {
+ // Module variables must be allocated before variable resolution
+ // to ensure that UpdateNeedsHoleCheck() can detect import variables.
+ if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
+
+ // Lazy parsed declaration scopes are already partially analyzed. If there are
+ // unresolved references remaining, they just need to be resolved in outer
+ // scopes.
+ Scope* lookup =
+ is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()
+ ? outer_scope()
+ : this;
+
+ for (VariableProxy* proxy : unresolved_list_) {
+ DCHECK(!proxy->is_resolved());
+ Variable* var =
+ Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope());
+ if (var == nullptr) {
+ *non_locals = StringSet::Add(isolate, *non_locals, proxy->name());
+ } else {
+ // In this case we need to leave scopes in a way that they can be
+ // allocated. If we resolved variables from lazy parsed scopes, we need
+ // to context allocate the var.
+ ResolveTo(info, proxy, var);
+ if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
+ }
+ }
+
+ // Clear unresolved_list_ as it's in an inconsistent state.
+ unresolved_list_.Clear();
+
+ for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
+ scope->CollectNonLocals(max_outer_scope, isolate, info, non_locals);
+ }
+}
+
+void Scope::AnalyzePartially(DeclarationScope* max_outer_scope,
+ AstNodeFactory* ast_node_factory,
+ UnresolvedList* new_unresolved_list) {
+ DCHECK_IMPLIES(is_declaration_scope(),
+ !AsDeclarationScope()->was_lazily_parsed());
+
+ for (VariableProxy* proxy = unresolved_list_.first(); proxy != nullptr;
+ proxy = proxy->next_unresolved()) {
+ DCHECK(!proxy->is_resolved());
+ Variable* var =
+ Lookup<kParsedScope>(proxy, this, max_outer_scope->outer_scope());
+ if (var == nullptr) {
+ // Don't copy unresolved references to the script scope, unless it's a
+ // reference to a private name or method. In that case keep it so we
+ // can fail later.
+ if (!max_outer_scope->outer_scope()->is_script_scope() ||
+ proxy->IsPrivateName()) {
+ VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
+ new_unresolved_list->Add(copy);
+ }
+ } else {
+ var->set_is_used();
+ if (proxy->is_assigned()) var->set_maybe_assigned();
+ }
+ }
+
+ // Clear unresolved_list_ as it's in an inconsistent state.
+ unresolved_list_.Clear();
+
+ for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
+ scope->AnalyzePartially(max_outer_scope, ast_node_factory,
+ new_unresolved_list);
+ }
+}
+
Handle<StringSet> DeclarationScope::CollectNonLocals(
Isolate* isolate, ParseInfo* info, Handle<StringSet> non_locals) {
- ResolveScopesThenForEachVariable(this,
- [=, &non_locals](VariableProxy* proxy) {
- non_locals = StringSet::Add(
- isolate, non_locals, proxy->name());
- },
- info);
+ Scope::CollectNonLocals(this, isolate, info, &non_locals);
return non_locals;
}
@@ -1483,11 +1394,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
DCHECK(is_function_scope());
// Reset all non-trivial members.
- if (!aborted || !IsArrowFunction(function_kind_)) {
- // Do not remove parameters when lazy parsing an Arrow Function has failed,
- // as the formal parameters are not re-parsed.
- params_.Clear();
- }
+ params_.Clear();
decls_.Clear();
locals_.Clear();
inner_scope_ = nullptr;
@@ -1495,8 +1402,6 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
sloppy_block_function_map_ = nullptr;
rare_data_ = nullptr;
has_rest_ = false;
- has_promise_ = false;
- has_generator_object_ = false;
DCHECK_NE(zone_, ast_value_factory->zone());
zone_->ReleaseMemory();
@@ -1506,6 +1411,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
zone_ = ast_value_factory->zone();
variables_.Reset(ZoneAllocationPolicy(zone_));
if (!IsArrowFunction(function_kind_)) {
+ has_simple_parameters_ = true;
DeclareDefaultFunctionVariables(ast_value_factory);
}
} else {
@@ -1522,54 +1428,40 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
was_lazily_parsed_ = !aborted;
}
-void Scope::SavePreParsedScopeData() {
- DCHECK(FLAG_preparser_scope_analysis);
- if (PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(this)) {
- AsDeclarationScope()->SavePreParsedScopeDataForDeclarationScope();
+void Scope::SavePreparseData(Parser* parser) {
+ if (PreparseDataBuilder::ScopeIsSkippableFunctionScope(this)) {
+ AsDeclarationScope()->SavePreparseDataForDeclarationScope(parser);
}
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
- scope->SavePreParsedScopeData();
+ scope->SavePreparseData(parser);
}
}
-void DeclarationScope::SavePreParsedScopeDataForDeclarationScope() {
- if (preparsed_scope_data_builder_ != nullptr) {
- DCHECK(FLAG_preparser_scope_analysis);
- preparsed_scope_data_builder_->SaveScopeAllocationData(this);
- }
+void DeclarationScope::SavePreparseDataForDeclarationScope(Parser* parser) {
+ if (preparse_data_builder_ == nullptr) return;
+ preparse_data_builder_->SaveScopeAllocationData(this, parser);
}
-void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
+void DeclarationScope::AnalyzePartially(Parser* parser,
+ AstNodeFactory* ast_node_factory) {
DCHECK(!force_eager_compilation_);
- base::ThreadedList<VariableProxy> new_unresolved_list;
+ UnresolvedList new_unresolved_list;
if (!IsArrowFunction(function_kind_) &&
(!outer_scope_->is_script_scope() ||
- (FLAG_preparser_scope_analysis &&
- preparsed_scope_data_builder_ != nullptr &&
- preparsed_scope_data_builder_->ContainsInnerFunctions()))) {
+ (preparse_data_builder_ != nullptr &&
+ preparse_data_builder_->HasInnerFunctions()))) {
// Try to resolve unresolved variables for this Scope and migrate those
// which cannot be resolved inside. It doesn't make sense to try to resolve
// them in the outer Scopes here, because they are incomplete.
- ResolveScopesThenForEachVariable(
- this, [=, &new_unresolved_list](VariableProxy* proxy) {
- // Don't copy unresolved references to the script scope, unless it's a
- // reference to a private field. In that case keep it so we can fail
- // later.
- if (!outer_scope_->is_script_scope() || proxy->is_private_field()) {
- VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
- new_unresolved_list.AddFront(copy);
- }
- });
+ Scope::AnalyzePartially(this, ast_node_factory, &new_unresolved_list);
// Migrate function_ to the right Zone.
if (function_ != nullptr) {
function_ = ast_node_factory->CopyVariable(function_);
}
- if (FLAG_preparser_scope_analysis) {
- SavePreParsedScopeData();
- }
+ SavePreparseData(parser);
}
#ifdef DEBUG
@@ -1668,10 +1560,6 @@ void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
Variable* var = reinterpret_cast<Variable*>(p->value);
if (var == function_var) continue;
- if (var == Scope::kDummyPreParserVariable ||
- var == Scope::kDummyPreParserLexicalVariable) {
- continue;
- }
bool local = !IsDynamicVariableMode(var->mode());
if ((locals ? local : !local) &&
(var->is_used() || !var->IsUnallocated())) {
@@ -1691,10 +1579,11 @@ void DeclarationScope::PrintParameters() {
for (int i = 0; i < params_.length(); i++) {
if (i > 0) PrintF(", ");
const AstRawString* name = params_[i]->raw_name();
- if (name->IsEmpty())
+ if (name->IsEmpty()) {
PrintF(".%p", reinterpret_cast<void*>(params_[i]));
- else
+ } else {
PrintName(name);
+ }
}
PrintF(")");
}
@@ -1823,107 +1712,175 @@ void Scope::CheckZones() {
Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
// Declare a new non-local.
DCHECK(IsDynamicVariableMode(mode));
- Variable* var = variables_.Declare(zone(), nullptr, name, mode);
+ bool was_added;
+ Variable* var =
+ variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE,
+ kCreatedInitialized, kNotAssigned, &was_added);
// Allocate it by giving it a dynamic lookup.
var->AllocateTo(VariableLocation::LOOKUP, -1);
return var;
}
-Variable* Scope::LookupRecursive(ParseInfo* info, VariableProxy* proxy,
- Scope* outer_scope_end) {
- DCHECK_NE(outer_scope_end, this);
- // Short-cut: whenever we find a debug-evaluate scope, just look everything up
- // dynamically. Debug-evaluate doesn't properly create scope info for the
- // lookups it does. It may not have a valid 'this' declaration, and anything
- // accessed through debug-evaluate might invalidly resolve to stack-allocated
- // variables.
- // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for the
- // scopes in which it's evaluating.
- if (is_debug_evaluate_scope_)
- return NonLocal(proxy->raw_name(), VariableMode::kDynamic);
-
- // Try to find the variable in this scope.
- Variable* var = LookupLocal(proxy->raw_name());
-
- // We found a variable and we are done. (Even if there is an 'eval' in this
- // scope which introduces the same variable again, the resulting variable
- // remains the same.)
- if (var != nullptr) return var;
-
- if (outer_scope_ == outer_scope_end) {
- // We may just be trying to find all free variables. In that case, don't
- // declare them in the outer scope.
- if (!is_script_scope()) return nullptr;
-
- if (proxy->is_private_field()) {
- info->pending_error_handler()->ReportMessageAt(
- proxy->position(), proxy->position() + 1,
- MessageTemplate::kInvalidPrivateFieldAccess, proxy->raw_name(),
- kSyntaxError);
- return nullptr;
+// static
+template <Scope::ScopeLookupMode mode>
+Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
+ Scope* outer_scope_end, Scope* entry_point,
+ bool force_context_allocation) {
+ if (mode == kDeserializedScope) {
+ Variable* var = entry_point->variables_.Lookup(proxy->raw_name());
+ if (var != nullptr) return var;
+ }
+
+ while (true) {
+ DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_);
+ // Short-cut: whenever we find a debug-evaluate scope, just look everything
+ // up dynamically. Debug-evaluate doesn't properly create scope info for the
+ // lookups it does. It may not have a valid 'this' declaration, and anything
+ // accessed through debug-evaluate might invalidly resolve to
+ // stack-allocated variables.
+ // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for
+ // the scopes in which it's evaluating.
+ if (mode == kDeserializedScope &&
+ V8_UNLIKELY(scope->is_debug_evaluate_scope_)) {
+ return entry_point->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
}
- // No binding has been found. Declare a variable on the global object.
- return AsDeclarationScope()->DeclareDynamicGlobal(proxy->raw_name(),
- NORMAL_VARIABLE);
- }
+ // Try to find the variable in this scope.
+ Variable* var = mode == kParsedScope ? scope->LookupLocal(proxy->raw_name())
+ : scope->LookupInScopeInfo(
+ proxy->raw_name(), entry_point);
- DCHECK(!is_script_scope());
+ // We found a variable and we are done. (Even if there is an 'eval' in this
+ // scope which introduces the same variable again, the resulting variable
+ // remains the same.)
+ if (var != nullptr) {
+ if (mode == kParsedScope && force_context_allocation &&
+ !var->is_dynamic()) {
+ var->ForceContextAllocation();
+ }
+ return var;
+ }
- var = outer_scope_->LookupRecursive(info, proxy, outer_scope_end);
+ if (scope->outer_scope_ == outer_scope_end) break;
- // The variable could not be resolved statically.
- if (var == nullptr) return var;
+ DCHECK(!scope->is_script_scope());
+ if (V8_UNLIKELY(scope->is_with_scope())) {
+ return LookupWith(proxy, scope, outer_scope_end, entry_point,
+ force_context_allocation);
+ }
+ if (V8_UNLIKELY(scope->is_declaration_scope() &&
+ scope->AsDeclarationScope()->calls_sloppy_eval())) {
+ return LookupSloppyEval(proxy, scope, outer_scope_end, entry_point,
+ force_context_allocation);
+ }
- // TODO(marja): Separate LookupRecursive for preparsed scopes better.
- if (var == kDummyPreParserVariable || var == kDummyPreParserLexicalVariable) {
- DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
- DCHECK(FLAG_lazy_inner_functions);
- return var;
+ force_context_allocation |= scope->is_function_scope();
+ scope = scope->outer_scope_;
+ // TODO(verwaest): Separate through AnalyzePartially.
+ if (mode == kParsedScope && !scope->scope_info_.is_null()) {
+ return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end, scope);
+ }
}
- if (is_function_scope() && !var->is_dynamic()) {
- var->ForceContextAllocation();
- }
- // "this" can't be shadowed by "eval"-introduced bindings or by "with"
- // scopes.
- // TODO(wingo): There are other variables in this category; add them.
- if (var->is_this()) return var;
-
- if (is_with_scope()) {
- // The current scope is a with scope, so the variable binding can not be
- // statically resolved. However, note that it was necessary to do a lookup
- // in the outer scope anyway, because if a binding exists in an outer
- // scope, the associated variable has to be marked as potentially being
- // accessed from inside of an inner with scope (the property may not be in
- // the 'with' object).
- if (!var->is_dynamic() && var->IsUnallocated()) {
- DCHECK(!already_resolved_);
- var->set_is_used();
- var->ForceContextAllocation();
- if (proxy->is_assigned()) var->set_maybe_assigned();
- }
- return NonLocal(proxy->raw_name(), VariableMode::kDynamic);
+ // We may just be trying to find all free variables. In that case, don't
+ // declare them in the outer scope.
+ // TODO(marja): Separate Lookup for preparsed scopes better.
+ if (mode == kParsedScope && !scope->is_script_scope()) {
+ return nullptr;
}
+ if (V8_UNLIKELY(proxy->IsPrivateName())) return nullptr;
- if (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval()) {
- // A variable binding may have been found in an outer scope, but the current
- // scope makes a sloppy 'eval' call, so the found variable may not be the
- // correct one (the 'eval' may introduce a binding with the same name). In
- // that case, change the lookup result to reflect this situation. Only
- // scopes that can host var bindings (declaration scopes) need be considered
- // here (this excludes block and catch scopes), and variable lookups at
- // script scope are always dynamic.
- if (var->IsGlobalObjectProperty()) {
- return NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
- }
+ // No binding has been found. Declare a variable on the global object.
+ return scope->AsDeclarationScope()->DeclareDynamicGlobal(
+ proxy->raw_name(), NORMAL_VARIABLE,
+ mode == kDeserializedScope ? entry_point : scope);
+}
- if (var->is_dynamic()) return var;
+template Variable* Scope::Lookup<Scope::kParsedScope>(
+ VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
+ Scope* entry_point, bool force_context_allocation);
+template Variable* Scope::Lookup<Scope::kDeserializedScope>(
+ VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
+ Scope* entry_point, bool force_context_allocation);
- Variable* invalidated = var;
- var = NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
- var->set_local_if_not_shadowed(invalidated);
+namespace {
+bool CanBeShadowed(Scope* scope, Variable* var) {
+ if (var == nullptr) return false;
+
+ // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes.
+ // TODO(wingo): There are other variables in this category; add them.
+ return !var->is_this();
+}
+}; // namespace
+
+Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
+ Scope* outer_scope_end, Scope* entry_point,
+ bool force_context_allocation) {
+ DCHECK(scope->is_with_scope());
+
+ Variable* var =
+ scope->outer_scope_->scope_info_.is_null()
+ ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
+ nullptr, force_context_allocation)
+ : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
+ outer_scope_end, entry_point);
+
+ if (!CanBeShadowed(scope, var)) return var;
+
+ // The current scope is a with scope, so the variable binding can not be
+ // statically resolved. However, note that it was necessary to do a lookup
+ // in the outer scope anyway, because if a binding exists in an outer
+ // scope, the associated variable has to be marked as potentially being
+ // accessed from inside of an inner with scope (the property may not be in
+ // the 'with' object).
+ if (!var->is_dynamic() && var->IsUnallocated()) {
+ DCHECK(!scope->already_resolved_);
+ var->set_is_used();
+ var->ForceContextAllocation();
+ if (proxy->is_assigned()) var->set_maybe_assigned();
}
+ if (entry_point != nullptr) entry_point->variables_.Remove(var);
+ Scope* target = entry_point == nullptr ? scope : entry_point;
+ return target->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
+}
+
+Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
+ Scope* outer_scope_end, Scope* entry_point,
+ bool force_context_allocation) {
+ DCHECK(scope->is_declaration_scope() &&
+ scope->AsDeclarationScope()->calls_sloppy_eval());
+
+ // If we're compiling eval, it's possible that the outer scope is the first
+ // ScopeInfo-backed scope.
+ Scope* entry = entry_point == nullptr ? scope->outer_scope_ : entry_point;
+ Variable* var =
+ scope->outer_scope_->scope_info_.is_null()
+ ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
+ nullptr, force_context_allocation)
+ : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
+ outer_scope_end, entry);
+ if (!CanBeShadowed(scope, var)) return var;
+
+ // A variable binding may have been found in an outer scope, but the current
+ // scope makes a sloppy 'eval' call, so the found variable may not be the
+ // correct one (the 'eval' may introduce a binding with the same name). In
+ // that case, change the lookup result to reflect this situation. Only
+ // scopes that can host var bindings (declaration scopes) need be considered
+ // here (this excludes block and catch scopes), and variable lookups at
+ // script scope are always dynamic.
+ if (var->IsGlobalObjectProperty()) {
+ Scope* target = entry_point == nullptr ? scope : entry_point;
+ return target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
+ }
+
+ if (var->is_dynamic()) return var;
+
+ Variable* invalidated = var;
+ if (entry_point != nullptr) entry_point->variables_.Remove(invalidated);
+
+ Scope* target = entry_point == nullptr ? scope : entry_point;
+ var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
+ var->set_local_if_not_shadowed(invalidated);
return var;
}
@@ -1931,9 +1888,13 @@ Variable* Scope::LookupRecursive(ParseInfo* info, VariableProxy* proxy,
bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
DCHECK(info->script_scope()->is_script_scope());
DCHECK(!proxy->is_resolved());
- Variable* var = LookupRecursive(info, proxy, nullptr);
+ Variable* var = Lookup<kParsedScope>(proxy, this, nullptr);
if (var == nullptr) {
- DCHECK(proxy->is_private_field());
+ DCHECK(proxy->IsPrivateName());
+ info->pending_error_handler()->ReportMessageAt(
+ proxy->position(), proxy->position() + 1,
+ MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name(),
+ kSyntaxError);
return false;
}
ResolveTo(info, proxy, var);
@@ -2041,9 +2002,13 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
DCHECK_EQ(variables_.occupancy(), 0);
for (VariableProxy* proxy : unresolved_list_) {
- Variable* var = outer_scope()->LookupRecursive(info, proxy, nullptr);
+ Variable* var = Lookup<kParsedScope>(proxy, outer_scope(), nullptr);
if (var == nullptr) {
- DCHECK(proxy->is_private_field());
+ info->pending_error_handler()->ReportMessageAt(
+ proxy->position(), proxy->position() + 1,
+ MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name(),
+ kSyntaxError);
+ DCHECK(proxy->IsPrivateName());
return false;
}
if (!var->is_dynamic()) {
@@ -2068,9 +2033,6 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
}
bool Scope::MustAllocate(Variable* var) {
- if (var == kDummyPreParserLexicalVariable || var == kDummyPreParserVariable) {
- return true;
- }
DCHECK(var->location() != VariableLocation::MODULE);
// Give var a read/write use if there is a chance it might be accessed
// via an eval() call. This is only possible if the variable has a
@@ -2143,6 +2105,7 @@ void DeclarationScope::AllocateParameterLocals() {
// order is relevant!
for (int i = num_parameters() - 1; i >= 0; --i) {
Variable* var = params_[i];
+ DCHECK_NOT_NULL(var);
DCHECK(!has_rest_ || var != rest_parameter());
DCHECK_EQ(this, var->scope());
if (has_mapped_arguments) {
@@ -2178,24 +2141,6 @@ void DeclarationScope::AllocateReceiver() {
AllocateParameter(receiver(), -1);
}
-void DeclarationScope::AllocatePromise() {
- if (!has_promise_) return;
- DCHECK_NOT_NULL(promise_var());
- DCHECK_EQ(this, promise_var()->scope());
- AllocateStackSlot(promise_var());
- DCHECK_EQ(VariableLocation::LOCAL, promise_var()->location());
- DCHECK_EQ(kPromiseVarIndex, promise_var()->index());
-}
-
-void DeclarationScope::AllocateGeneratorObject() {
- if (!has_generator_object_) return;
- DCHECK_NOT_NULL(generator_object_var());
- DCHECK_EQ(this, generator_object_var()->scope());
- AllocateStackSlot(generator_object_var());
- DCHECK_EQ(VariableLocation::LOCAL, generator_object_var()->location());
- DCHECK_EQ(kGeneratorObjectVarIndex, generator_object_var()->index());
-}
-
void Scope::AllocateNonParameterLocal(Variable* var) {
DCHECK(var->scope() == this);
if (var->IsUnallocated() && MustAllocate(var)) {
@@ -2257,26 +2202,12 @@ void ModuleScope::AllocateModuleVariables() {
void Scope::AllocateVariablesRecursively() {
DCHECK(!already_resolved_);
- DCHECK_IMPLIES(!FLAG_preparser_scope_analysis, num_stack_slots_ == 0);
// Don't allocate variables of preparsed scopes.
if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
return;
}
- // Make sure to allocate the .promise (for async functions) or
- // .generator_object (for async generators) first, so that it
- // get's the required stack slot 0 in case it's needed. See
- // http://bit.ly/v8-zero-cost-async-stack-traces for details.
- if (is_function_scope()) {
- FunctionKind kind = GetClosureScope()->function_kind();
- if (IsAsyncGeneratorFunction(kind)) {
- AsDeclarationScope()->AllocateGeneratorObject();
- } else if (IsAsyncFunction(kind)) {
- AsDeclarationScope()->AllocatePromise();
- }
- }
-
// Allocate variables for inner scopes.
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
scope->AllocateVariablesRecursively();
@@ -2299,8 +2230,10 @@ void Scope::AllocateVariablesRecursively() {
// scope and for a function scope that makes an 'eval' call we need a context,
// even if no local variables were statically allocated in the scope.
// Likewise for modules and function scopes representing asm.js modules.
+ // Also force a context, if the scope is stricter than the outer scope.
bool must_have_context =
is_with_scope() || is_module_scope() || IsAsmModule() ||
+ ForceContextForLanguageMode() ||
(is_function_scope() && AsDeclarationScope()->calls_sloppy_eval()) ||
(is_block_scope() && is_declaration_scope() &&
AsDeclarationScope()->calls_sloppy_eval());
@@ -2365,14 +2298,6 @@ void DeclarationScope::AllocateScopeInfos(ParseInfo* info, Isolate* isolate) {
}
}
-int Scope::StackLocalCount() const {
- Variable* function =
- is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
- return num_stack_slots() -
- (function != nullptr && function->IsStackLocal() ? 1 : 0);
-}
-
-
int Scope::ContextLocalCount() const {
if (num_heap_slots() == 0) return 0;
Variable* function =
@@ -2383,9 +2308,5 @@ int Scope::ContextLocalCount() const {
(is_function_var_in_context ? 1 : 0);
}
-void* const Scope::kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
-void* const Scope::kDummyPreParserLexicalVariable =
- reinterpret_cast<void*>(0x2);
-
} // namespace internal
} // namespace v8