diff options
Diffstat (limited to 'src/ast/scopes.h')
-rw-r--r-- | src/ast/scopes.h | 202 |
1 files changed, 153 insertions, 49 deletions
diff --git a/src/ast/scopes.h b/src/ast/scopes.h index c7d88aca..119d77c5 100644 --- a/src/ast/scopes.h +++ b/src/ast/scopes.h @@ -19,7 +19,9 @@ class AstValueFactory; class AstRawString; class Declaration; class ParseInfo; +class PreParsedScopeData; class SloppyBlockFunctionStatement; +class Statement; class StringSet; class VariableProxy; @@ -28,11 +30,17 @@ class VariableMap: public ZoneHashMap { public: explicit VariableMap(Zone* zone); - Variable* Declare(Zone* zone, Scope* scope, const AstRawString* name, - VariableMode mode, VariableKind kind, - InitializationFlag initialization_flag, - MaybeAssignedFlag maybe_assigned_flag = kNotAssigned, - bool* added = nullptr); + Variable* Declare( + Zone* zone, Scope* scope, const AstRawString* name, VariableMode mode, + VariableKind kind = NORMAL_VARIABLE, + InitializationFlag initialization_flag = kCreatedInitialized, + MaybeAssignedFlag maybe_assigned_flag = kNotAssigned, + bool* added = nullptr); + + // Records that "name" exists (if not recorded yet) but doesn't create a + // Variable. Useful for preparsing. + Variable* DeclareName(Zone* zone, const AstRawString* name, + VariableMode mode); Variable* Lookup(const AstRawString* name); void Remove(Variable* var); @@ -43,9 +51,24 @@ class VariableMap: public ZoneHashMap { // Sloppy block-scoped function declarations to var-bind class SloppyBlockFunctionMap : public ZoneHashMap { public: + class Delegate : public ZoneObject { + public: + explicit Delegate(Scope* scope, + SloppyBlockFunctionStatement* statement = nullptr) + : scope_(scope), statement_(statement), next_(nullptr) {} + void set_statement(Statement* statement); + void set_next(Delegate* next) { next_ = next; } + Delegate* next() const { return next_; } + Scope* scope() const { return scope_; } + + private: + Scope* scope_; + SloppyBlockFunctionStatement* statement_; + Delegate* next_; + }; + explicit SloppyBlockFunctionMap(Zone* zone); - void Declare(Zone* zone, const AstRawString* name, - SloppyBlockFunctionStatement* statement); + void Declare(Zone* zone, const AstRawString* name, Delegate* delegate); }; enum class AnalyzeMode { kRegular, kDebugger }; @@ -148,7 +171,8 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { // Declare a local variable in this scope. If the variable has been // declared before, the previously declared variable is returned. Variable* DeclareLocal(const AstRawString* name, VariableMode mode, - InitializationFlag init_flag, VariableKind kind, + InitializationFlag init_flag = kCreatedInitialized, + VariableKind kind = NORMAL_VARIABLE, MaybeAssignedFlag maybe_assigned_flag = kNotAssigned); Variable* DeclareVariable(Declaration* declaration, VariableMode mode, @@ -157,6 +181,9 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { bool* sloppy_mode_block_scope_function_redefinition, bool* ok); + // The return value is meaningful only if FLAG_preparser_scope_analysis is on. + Variable* DeclareVariableName(const AstRawString* name, VariableMode mode); + // Declarations list. ThreadedList<Declaration>* declarations() { return &decls_; } @@ -177,7 +204,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { // allocated globally as a "ghost" variable. RemoveUnresolved removes // such a variable again if it was added; otherwise this is a no-op. bool RemoveUnresolved(VariableProxy* var); - bool RemoveUnresolved(const AstRawString* name); // Creates a new temporary variable in this scope's TemporaryScope. The // name is only used for printing and cannot be used to find the variable. @@ -207,14 +233,11 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { // Scope-specific info. // Inform the scope and outer scopes that the corresponding code contains an - // eval call. We don't record eval calls from innner scopes in the outer most - // script scope, as we only see those when parsing eagerly. If we recorded the - // calls then, the outer most script scope would look different depending on - // whether we parsed eagerly or not which is undesirable. + // eval call. void RecordEvalCall() { scope_calls_eval_ = true; inner_scope_calls_eval_ = true; - for (Scope* scope = outer_scope(); scope && !scope->is_script_scope(); + for (Scope* scope = outer_scope(); scope != nullptr; scope = scope->outer_scope()) { scope->inner_scope_calls_eval_ = true; } @@ -303,6 +326,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { bool calls_sloppy_eval() const { return scope_calls_eval_ && is_sloppy(language_mode()); } + bool inner_scope_calls_eval() const { return inner_scope_calls_eval_; } bool IsAsmModule() const; bool IsAsmFunction() const; // Does this scope have the potential to execute declarations non-linearly? @@ -387,7 +411,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { Scope* GetOuterScopeWithContext(); // Analyze() must have been called once to create the ScopeInfo. - Handle<ScopeInfo> scope_info() { + Handle<ScopeInfo> scope_info() const { DCHECK(!scope_info_.is_null()); return scope_info_; } @@ -423,6 +447,22 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { void set_is_debug_evaluate_scope() { is_debug_evaluate_scope_ = true; } bool is_debug_evaluate_scope() const { return is_debug_evaluate_scope_; } + bool RemoveInnerScope(Scope* inner_scope) { + DCHECK_NOT_NULL(inner_scope); + if (inner_scope == inner_scope_) { + inner_scope_ = inner_scope_->sibling_; + return true; + } + for (Scope* scope = inner_scope_; scope != nullptr; + scope = scope->sibling_) { + if (scope->sibling_ == inner_scope) { + scope->sibling_ = scope->sibling_->sibling_; + return true; + } + } + return false; + } + protected: explicit Scope(Zone* zone); @@ -431,10 +471,11 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { } private: - Variable* Declare(Zone* zone, Scope* scope, const AstRawString* name, - VariableMode mode, VariableKind kind, - InitializationFlag initialization_flag, - MaybeAssignedFlag maybe_assigned_flag = kNotAssigned); + Variable* Declare( + Zone* zone, const AstRawString* name, VariableMode mode, + VariableKind kind = NORMAL_VARIABLE, + InitializationFlag initialization_flag = kCreatedInitialized, + MaybeAssignedFlag maybe_assigned_flag = kNotAssigned); // This method should only be invoked on scopes created during parsing (i.e., // not deserialized from a context). Also, since NeedsContext() is only @@ -442,6 +483,8 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { // should also be invoked after resolution. bool NeedsScopeInfo() const; + Variable* NewTemporary(const AstRawString* name, + MaybeAssignedFlag maybe_assigned); Zone* zone_; // Scope tree. @@ -527,7 +570,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { // list along the way, so full resolution cannot be done afterwards. // If a ParseInfo* is passed, non-free variables will be resolved. VariableProxy* FetchFreeVariables(DeclarationScope* max_outer_scope, - bool try_to_resolve = true, ParseInfo* info = nullptr, VariableProxy* stack = nullptr); @@ -548,6 +590,8 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { void AllocateDebuggerScopeInfos(Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope); + void CollectVariableData(PreParsedScopeData* data); + // Construct a scope based on the scope info. Scope(Zone* zone, ScopeType type, Handle<ScopeInfo> scope_info); @@ -556,33 +600,18 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { Handle<ScopeInfo> scope_info); void AddInnerScope(Scope* inner_scope) { - DCHECK_EQ(!needs_migration_, inner_scope->zone() == zone()); inner_scope->sibling_ = inner_scope_; inner_scope_ = inner_scope; inner_scope->outer_scope_ = this; } - void RemoveInnerScope(Scope* inner_scope) { - DCHECK_NOT_NULL(inner_scope); - if (inner_scope == inner_scope_) { - inner_scope_ = inner_scope_->sibling_; - return; - } - for (Scope* scope = inner_scope_; scope != nullptr; - scope = scope->sibling_) { - if (scope->sibling_ == inner_scope) { - scope->sibling_ = scope->sibling_->sibling_; - return; - } - } - } - void SetDefaults(); friend class DeclarationScope; + friend class ScopeTestHelper; }; -class DeclarationScope : public Scope { +class V8_EXPORT_PRIVATE DeclarationScope : public Scope { public: DeclarationScope(Zone* zone, Scope* outer_scope, ScopeType scope_type, FunctionKind function_kind = kNormalFunction); @@ -616,7 +645,15 @@ class DeclarationScope : public Scope { IsClassConstructor(function_kind()))); } - bool is_lazily_parsed() const { return is_lazily_parsed_; } + bool was_lazily_parsed() const { return was_lazily_parsed_; } + +#ifdef DEBUG + void set_is_being_lazily_parsed(bool is_being_lazily_parsed) { + is_being_lazily_parsed_ = is_being_lazily_parsed; + } + bool is_being_lazily_parsed() const { return is_being_lazily_parsed_; } +#endif + bool ShouldEagerCompile() const; void set_should_eager_compile(); @@ -629,7 +666,7 @@ class DeclarationScope : public Scope { bool asm_module() const { return asm_module_; } void set_asm_module(); bool asm_function() const { return asm_function_; } - void set_asm_function() { asm_module_ = true; } + void set_asm_function() { asm_function_ = true; } void DeclareThis(AstValueFactory* ast_value_factory); void DeclareArguments(AstValueFactory* ast_value_factory); @@ -645,6 +682,11 @@ class DeclarationScope : public Scope { // calls sloppy eval. Variable* DeclareFunctionVar(const AstRawString* name); + // Declare some special internal variables which must be accessible to + // Ignition without ScopeInfo. + Variable* DeclareGeneratorObjectVar(const AstRawString* name); + Variable* DeclarePromiseVar(const AstRawString* name); + // Declare a parameter in this scope. When there are duplicated // parameters the rightmost one 'wins'. However, the implementation // expects all parameters to be declared and from left to right. @@ -652,6 +694,11 @@ class DeclarationScope : public Scope { bool is_optional, bool is_rest, bool* is_duplicate, AstValueFactory* ast_value_factory); + // Declares that a parameter with the name exists. Creates a Variable and + // returns it if FLAG_preparser_scope_analysis is on. + Variable* DeclareParameterName(const AstRawString* name, bool is_rest, + AstValueFactory* ast_value_factory); + // Declare an implicit global variable in this scope which must be a // script scope. The variable was introduced (possibly from an inner // scope) by a reference to an unresolved variable with no intervening @@ -683,6 +730,17 @@ class DeclarationScope : public Scope { return function_; } + Variable* generator_object_var() const { + DCHECK(is_function_scope() || is_module_scope()); + return GetRareVariable(RareVariable::kGeneratorObject); + } + + Variable* promise_var() const { + DCHECK(is_function_scope()); + DCHECK(IsAsyncFunction(function_kind_)); + return GetRareVariable(RareVariable::kPromise); + } + // Parameters. The left-most parameter has index 0. // Only valid for function and module scopes. Variable* parameter(int index) const { @@ -723,12 +781,14 @@ class DeclarationScope : public Scope { } Variable* this_function_var() const { + Variable* this_function = GetRareVariable(RareVariable::kThisFunction); + // This is only used in derived constructors atm. - DCHECK(this_function_ == nullptr || + DCHECK(this_function == nullptr || (is_function_scope() && (IsClassConstructor(function_kind()) || IsConciseMethod(function_kind()) || IsAccessorFunction(function_kind())))); - return this_function_; + return this_function; } // Adds a local variable in this scope's locals list. This is for adjusting @@ -736,10 +796,9 @@ class DeclarationScope : public Scope { // initializers. void AddLocal(Variable* var); - void DeclareSloppyBlockFunction(const AstRawString* name, - SloppyBlockFunctionStatement* statement) { - sloppy_block_function_map_.Declare(zone(), name, statement); - } + void DeclareSloppyBlockFunction( + const AstRawString* name, Scope* scope, + SloppyBlockFunctionStatement* statement = nullptr); // Go through sloppy_block_function_map_ and hoist those (into this scope) // which should be hoisted. @@ -759,7 +818,8 @@ class DeclarationScope : public Scope { // records variables which cannot be resolved inside the Scope (we don't yet // know what they will resolve to since the outer Scopes are incomplete) and // migrates them into migrate_to. - void AnalyzePartially(AstNodeFactory* ast_node_factory); + void AnalyzePartially(AstNodeFactory* ast_node_factory, + PreParsedScopeData* preparsed_scope_data); Handle<StringSet> CollectNonLocals(ParseInfo* info, Handle<StringSet> non_locals); @@ -819,7 +879,11 @@ class DeclarationScope : public Scope { // This scope uses "super" property ('super.foo'). bool scope_uses_super_property_ : 1; bool should_eager_compile_ : 1; - bool is_lazily_parsed_ : 1; + // Set to true after we have finished lazy parsing the scope. + bool was_lazily_parsed_ : 1; +#if DEBUG + bool is_being_lazily_parsed_ : 1; +#endif // Parameter list in source order. ZoneList<Variable*> params_; @@ -833,8 +897,48 @@ class DeclarationScope : public Scope { Variable* new_target_; // Convenience variable; function scopes only. Variable* arguments_; - // Convenience variable; Subclass constructor only - Variable* this_function_; + + struct RareData : public ZoneObject { + // Convenience variable; Subclass constructor only + Variable* this_function = nullptr; + + // Generator object, if any; generator function scopes and module scopes + // only. + Variable* generator_object = nullptr; + // Promise, if any; async function scopes only. + Variable* promise = nullptr; + }; + + enum class RareVariable { + kThisFunction = offsetof(RareData, this_function), + kGeneratorObject = offsetof(RareData, generator_object), + kPromise = offsetof(RareData, promise) + }; + + V8_INLINE RareData* EnsureRareData() { + if (rare_data_ == nullptr) { + rare_data_ = new (zone_) RareData; + } + return rare_data_; + } + + V8_INLINE Variable* GetRareVariable(RareVariable id) const { + if (rare_data_ == nullptr) return nullptr; + return *reinterpret_cast<Variable**>( + reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id)); + } + + // Set `var` to null if it's non-null and Predicate (Variable*) -> bool + // returns true. + template <typename Predicate> + V8_INLINE void NullifyRareVariableIf(RareVariable id, Predicate predicate) { + if (V8_LIKELY(rare_data_ == nullptr)) return; + Variable** var = reinterpret_cast<Variable**>( + reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id)); + if (*var && predicate(*var)) *var = nullptr; + } + + RareData* rare_data_ = nullptr; }; class ModuleScope final : public DeclarationScope { |