5 #ifndef V8_AST_SCOPES_H_ 6 #define V8_AST_SCOPES_H_ 8 #include "src/ast/ast.h" 9 #include "src/base/compiler-specific.h" 10 #include "src/base/hashmap.h" 11 #include "src/globals.h" 12 #include "src/objects.h" 13 #include "src/pointer-with-payload.h" 14 #include "src/zone/zone.h" 20 class AstValueFactory;
24 class PreParsedScopeDataBuilder;
25 class SloppyBlockFunctionStatement;
37 VariableKind kind = NORMAL_VARIABLE,
38 InitializationFlag initialization_flag = kCreatedInitialized,
39 MaybeAssignedFlag maybe_assigned_flag = kNotAssigned,
59 : scope_(scope), statement_(statement), next_(
nullptr), index_(index) {}
61 void set_next(
Delegate* next) { next_ = next; }
62 Delegate* next()
const {
return next_; }
63 Scope* scope()
const {
return scope_; }
64 int index()
const {
return index_; }
85 static constexpr
int value = 1;
101 class V8_EXPORT_PRIVATE
Scope :
public NON_EXPORTED_BASE(ZoneObject) {
111 scope_name_ = scope_name;
119 int num_parameters()
const;
129 : outer_scope_and_calls_eval_(
nullptr,
false),
138 if (!IsCleared() && outer_scope_and_calls_eval_.GetPayload()) {
143 void RestoreEvalFlag() {
144 outer_scope_and_calls_eval_->scope_calls_eval_ =
145 outer_scope_and_calls_eval_.GetPayload();
149 outer_scope_and_calls_eval_.SetPointer(
150 source.outer_scope_and_calls_eval_.GetPointer());
151 outer_scope_and_calls_eval_.SetPayload(
152 outer_scope_and_calls_eval_->scope_calls_eval_);
153 top_inner_scope_ = source.top_inner_scope_;
154 top_unresolved_ = source.top_unresolved_;
155 top_local_ = source.top_local_;
160 source.RestoreEvalFlag();
167 bool IsCleared()
const {
168 return outer_scope_and_calls_eval_.GetPointer() ==
nullptr;
173 outer_scope_and_calls_eval_.SetPointer(
nullptr);
175 outer_scope_and_calls_eval_.SetPayload(
false);
176 top_inner_scope_ =
nullptr;
187 Scope* top_inner_scope_;
196 enum class DeserializationMode { kIncludingVariables, kScopesOnly };
202 DeserializationMode deserialization_mode);
207 Scope* FinalizeBlockScope();
209 bool HasBeenRemoved()
const;
212 Scope* GetUnremovedScope();
217 void ReplaceOuterScope(
Scope* outer_scope);
219 Zone* zone()
const {
return zone_; }
221 void SetMustUsePreParsedScopeData() {
222 if (must_use_preparsed_scope_data_) {
225 must_use_preparsed_scope_data_ =
true;
227 outer_scope_->SetMustUsePreParsedScopeData();
231 bool must_use_preparsed_scope_data()
const {
232 return must_use_preparsed_scope_data_;
240 Variable* LookupLocal(
const AstRawString* name) {
241 DCHECK(scope_info_.is_null());
242 return variables_.Lookup(name);
245 Variable* LookupInScopeInfo(
const AstRawString* name, Scope* cache);
249 Variable* DeclareLocal(
const AstRawString* name, VariableMode mode,
250 InitializationFlag init_flag = kCreatedInitialized);
252 Variable* DeclareVariable(Declaration* declaration, VariableMode mode,
253 InitializationFlag init,
254 bool* sloppy_mode_block_scope_function_redefinition,
258 Variable* DeclareVariableName(
const AstRawString* name, VariableMode mode);
259 void DeclareCatchVariableName(
const AstRawString* name);
262 base::ThreadedList<Declaration>* declarations() {
return &decls_; }
264 base::ThreadedList<Variable>* locals() {
return &locals_; }
267 VariableProxy* NewUnresolved(AstNodeFactory* factory,
268 const AstRawString* name,
269 int start_pos = kNoSourcePosition,
270 VariableKind kind = NORMAL_VARIABLE) {
274 DCHECK(!already_resolved_);
275 DCHECK_EQ(factory->zone(), zone());
276 VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_pos);
277 AddUnresolved(proxy);
281 void AddUnresolved(VariableProxy* proxy);
286 bool RemoveUnresolved(VariableProxy* var);
295 void DeleteUnresolved(VariableProxy* var);
303 Variable* NewTemporary(
const AstRawString* name);
311 Declaration* CheckConflictingVarDeclarations();
318 Declaration* CheckLexDeclarationsConflictingWith(
319 const ZonePtrList<const AstRawString>& names);
326 void RecordEvalCall() {
327 scope_calls_eval_ =
true;
330 void RecordInnerScopeEvalCall() {
331 inner_scope_calls_eval_ =
true;
332 for (Scope* scope = outer_scope(); scope !=
nullptr;
333 scope = scope->outer_scope()) {
334 if (scope->inner_scope_calls_eval_) {
337 scope->inner_scope_calls_eval_ =
true;
342 void SetLanguageMode(LanguageMode language_mode) {
343 DCHECK(!is_module_scope() || is_strict(language_mode));
344 set_language_mode(language_mode);
356 void SetNonlinear() { scope_nonlinear_ =
true; }
384 int start_position()
const {
return start_position_; }
385 void set_start_position(
int statement_pos) {
386 start_position_ = statement_pos;
388 int end_position()
const {
return end_position_; }
389 void set_end_position(
int statement_pos) {
390 end_position_ = statement_pos;
394 bool is_hidden()
const {
return is_hidden_; }
395 void set_is_hidden() { is_hidden_ =
true; }
397 void ForceContextAllocationForParameters() {
398 DCHECK(!already_resolved_);
399 force_context_allocation_for_parameters_ =
true;
401 bool has_forced_context_allocation_for_parameters()
const {
402 return force_context_allocation_for_parameters_;
409 bool is_eval_scope()
const {
return scope_type_ == EVAL_SCOPE; }
410 bool is_function_scope()
const {
return scope_type_ == FUNCTION_SCOPE; }
411 bool is_module_scope()
const {
return scope_type_ == MODULE_SCOPE; }
412 bool is_script_scope()
const {
return scope_type_ == SCRIPT_SCOPE; }
413 bool is_catch_scope()
const {
return scope_type_ == CATCH_SCOPE; }
414 bool is_block_scope()
const {
return scope_type_ == BLOCK_SCOPE; }
415 bool is_with_scope()
const {
return scope_type_ == WITH_SCOPE; }
416 bool is_declaration_scope()
const {
return is_declaration_scope_; }
418 bool inner_scope_calls_eval()
const {
return inner_scope_calls_eval_; }
419 bool IsAsmModule()
const;
422 bool ContainsAsmModule()
const;
424 bool is_nonlinear()
const {
return scope_nonlinear_; }
427 bool NeedsContext()
const {
429 DCHECK_IMPLIES(is_catch_scope(), num_heap_slots() > 0);
430 DCHECK_IMPLIES(is_with_scope(), num_heap_slots() > 0);
431 return num_heap_slots() > 0;
438 ScopeType scope_type()
const {
return scope_type_; }
441 LanguageMode language_mode()
const {
442 return is_strict_ ? LanguageMode::kStrict : LanguageMode::kSloppy;
448 Scope* inner_scope()
const {
return inner_scope_; }
449 Scope* sibling()
const {
return sibling_; }
452 Scope* outer_scope()
const {
return outer_scope_; }
454 Variable* catch_variable()
const {
455 DCHECK(is_catch_scope());
456 DCHECK_EQ(1, num_var());
457 return static_cast<Variable*
>(variables_.Start()->value);
460 bool ShouldBanArguments();
466 int num_stack_slots()
const {
return num_stack_slots_; }
467 int num_heap_slots()
const {
return num_heap_slots_; }
469 int StackLocalCount()
const;
470 int ContextLocalCount()
const;
474 bool AllowsLazyParsingWithoutUnresolvedVariables(
const Scope* outer)
const;
477 int ContextChainLength(Scope* scope)
const;
481 int ContextChainLengthUntilOutermostSloppyEval()
const;
485 DeclarationScope* GetDeclarationScope();
492 DeclarationScope* GetClosureScope();
493 const DeclarationScope* GetClosureScope()
const;
497 DeclarationScope* GetReceiverScope();
500 Scope* GetOuterScopeWithContext();
503 Handle<ScopeInfo> scope_info()
const {
504 DCHECK(!scope_info_.is_null());
508 int num_var()
const {
return variables_.occupancy(); }
514 void Print(
int n = 0);
517 void CheckScopePositions();
524 bool HasSimpleParameters();
525 void set_is_debug_evaluate_scope() { is_debug_evaluate_scope_ =
true; }
526 bool is_debug_evaluate_scope()
const {
return is_debug_evaluate_scope_; }
528 bool RemoveInnerScope(Scope* inner_scope) {
529 DCHECK_NOT_NULL(inner_scope);
530 if (inner_scope == inner_scope_) {
531 inner_scope_ = inner_scope_->sibling_;
534 for (Scope* scope = inner_scope_; scope !=
nullptr;
535 scope = scope->sibling_) {
536 if (scope->sibling_ == inner_scope) {
537 scope->sibling_ = scope->sibling_->sibling_;
544 Variable* LookupInScopeOrScopeInfo(
const AstRawString* name) {
545 Variable* var = variables_.Lookup(name);
546 if (var !=
nullptr || scope_info_.is_null())
return var;
547 return LookupInScopeInfo(name,
this);
550 Variable* LookupForTesting(
const AstRawString* name) {
551 for (Scope* scope =
this; scope !=
nullptr; scope = scope->outer_scope()) {
552 Variable* var = scope->LookupInScopeOrScopeInfo(name);
553 if (var !=
nullptr)
return var;
558 static void*
const kDummyPreParserVariable;
559 static void*
const kDummyPreParserLexicalVariable;
562 explicit Scope(Zone* zone);
564 void set_language_mode(LanguageMode language_mode) {
565 is_strict_ = is_strict(language_mode);
570 Zone* zone,
const AstRawString* name, VariableMode mode,
571 VariableKind kind = NORMAL_VARIABLE,
572 InitializationFlag initialization_flag = kCreatedInitialized,
573 MaybeAssignedFlag maybe_assigned_flag = kNotAssigned) {
574 return variables_.Declare(zone,
this, name, mode, kind, initialization_flag,
575 maybe_assigned_flag, &locals_);
582 bool NeedsScopeInfo()
const;
584 Variable* NewTemporary(
const AstRawString* name,
585 MaybeAssignedFlag maybe_assigned);
589 void SavePreParsedScopeData();
603 VariableMap variables_;
606 base::ThreadedList<Variable> locals_;
609 UnresolvedList unresolved_list_;
611 base::ThreadedList<Declaration> decls_;
614 Handle<ScopeInfo> scope_info_;
617 const AstRawString* scope_name_;
621 bool already_resolved_;
624 bool needs_migration_;
632 int num_stack_slots_;
636 const ScopeType scope_type_;
641 STATIC_ASSERT(LanguageModeSize == 2);
645 bool scope_calls_eval_ : 1;
647 bool scope_nonlinear_ : 1;
650 bool is_debug_evaluate_scope_ : 1;
653 bool inner_scope_calls_eval_ : 1;
654 bool force_context_allocation_ : 1;
655 bool force_context_allocation_for_parameters_ : 1;
658 bool is_declaration_scope_ : 1;
660 bool must_use_preparsed_scope_data_ : 1;
664 Variable* NonLocal(
const AstRawString* name, VariableMode mode);
666 enum ScopeLookupMode {
676 template <ScopeLookupMode mode>
677 static Variable* Lookup(VariableProxy* proxy, Scope* scope,
678 Scope* outer_scope_end, Scope* entry_point =
nullptr,
679 bool force_context_allocation =
false);
680 static Variable* LookupWith(VariableProxy* proxy, Scope* scope,
681 Scope* outer_scope_end, Scope* entry_point,
682 bool force_context_allocation);
683 static Variable* LookupSloppyEval(VariableProxy* proxy, Scope* scope,
684 Scope* outer_scope_end, Scope* entry_point,
685 bool force_context_allocation);
686 void ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var);
687 V8_WARN_UNUSED_RESULT
bool ResolveVariable(ParseInfo* info,
688 VariableProxy* proxy);
689 V8_WARN_UNUSED_RESULT
bool ResolveVariablesRecursively(ParseInfo* info);
693 void AnalyzePartially(DeclarationScope* max_outer_scope,
694 AstNodeFactory* ast_node_factory,
695 UnresolvedList* new_unresolved_list);
696 void CollectNonLocals(DeclarationScope* max_outer_scope, Isolate* isolate,
697 ParseInfo* info, Handle<StringSet>* non_locals);
700 bool MustAllocate(Variable* var);
701 bool MustAllocateInContext(Variable* var);
704 void AllocateStackSlot(Variable* var);
705 void AllocateHeapSlot(Variable* var);
706 void AllocateNonParameterLocal(Variable* var);
707 void AllocateDeclaredGlobal(Variable* var);
708 void AllocateNonParameterLocalsAndDeclaredGlobals();
709 void AllocateVariablesRecursively();
711 void AllocateScopeInfosRecursively(Isolate* isolate,
712 MaybeHandle<ScopeInfo> outer_scope);
713 void AllocateDebuggerScopeInfos(Isolate* isolate,
714 MaybeHandle<ScopeInfo> outer_scope);
717 Scope(Zone* zone, ScopeType type, Handle<ScopeInfo> scope_info);
720 Scope(Zone* zone,
const AstRawString* catch_variable_name,
721 MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info);
723 void AddInnerScope(Scope* inner_scope) {
724 inner_scope->sibling_ = inner_scope_;
725 inner_scope_ = inner_scope;
726 inner_scope->outer_scope_ =
this;
731 friend class DeclarationScope;
732 friend class ScopeTestHelper;
738 FunctionKind function_kind = kNormalFunction);
746 FunctionKind function_kind()
const {
return function_kind_; }
748 bool is_arrow_scope()
const {
749 return is_function_scope() && IsArrowFunction(function_kind_);
753 void RecordSuperPropertyUsage() {
754 DCHECK(IsConciseMethod(function_kind()) ||
755 IsAccessorFunction(function_kind()) ||
756 IsClassConstructor(function_kind()));
757 scope_uses_super_property_ =
true;
761 bool NeedsHomeObject()
const {
762 return scope_uses_super_property_ ||
763 (inner_scope_calls_eval_ && (IsConciseMethod(function_kind()) ||
764 IsAccessorFunction(function_kind()) ||
765 IsClassConstructor(function_kind())));
768 bool calls_sloppy_eval()
const {
769 return scope_calls_eval_ && is_sloppy(language_mode());
772 bool was_lazily_parsed()
const {
return was_lazily_parsed_; }
775 DCHECK(is_module_scope());
776 Variable* var = variables_.Lookup(name);
777 DCHECK_NOT_NULL(var);
782 void set_is_being_lazily_parsed(
bool is_being_lazily_parsed) {
783 is_being_lazily_parsed_ = is_being_lazily_parsed;
785 bool is_being_lazily_parsed()
const {
return is_being_lazily_parsed_; }
787 void set_zone(
Zone* zone) {
789 needs_migration_ =
true;
794 bool ShouldEagerCompile()
const;
795 void set_should_eager_compile();
798 DCHECK(is_script_scope());
799 DCHECK(scope_info_.is_null());
800 scope_info_ = scope_info;
803 bool asm_module()
const {
return asm_module_; }
804 void set_asm_module();
806 bool should_ban_arguments()
const {
807 return IsClassMembersInitializerFunction(function_kind());
812 void DeclareDefaultFunctionVariables(
AstValueFactory* ast_value_factory);
823 Scope* cache =
nullptr);
833 bool is_optional,
bool is_rest,
840 bool declare_local,
bool add_parameter);
847 VariableKind variable_kind,
Scope* cache);
851 DCHECK(has_this_declaration());
852 DCHECK_NOT_NULL(receiver_);
859 bool has_this_declaration()
const {
860 return (is_function_scope() && !is_arrow_scope()) || is_module_scope();
864 Variable* new_target_var() {
return new_target_; }
868 Variable* function_var()
const {
return function_; }
873 Variable* generator_object_var()
const {
874 DCHECK(is_function_scope() || is_module_scope());
875 return GetRareVariable(RareVariable::kGeneratorObject);
880 Variable* parameter(
int index)
const {
881 DCHECK(is_function_scope() || is_module_scope());
882 return params_[index];
890 int num_parameters()
const {
891 return has_rest_ ? params_.length() - 1 : params_.length();
896 return has_rest_ ? params_[params_.length() - 1] :
nullptr;
899 bool has_simple_parameters()
const {
return has_simple_parameters_; }
906 void SetHasNonSimpleParameters() {
907 DCHECK(is_function_scope());
908 has_simple_parameters_ =
false;
912 CreateArgumentsType GetArgumentsType()
const {
913 DCHECK(is_function_scope());
914 DCHECK(!is_arrow_scope());
915 DCHECK_NOT_NULL(arguments_);
916 return is_sloppy(language_mode()) && has_simple_parameters()
917 ? CreateArgumentsType::kMappedArguments
918 : CreateArgumentsType::kUnmappedArguments;
924 DCHECK_IMPLIES(is_arrow_scope(), arguments_ ==
nullptr);
928 Variable* this_function_var()
const {
929 Variable* this_function = GetRareVariable(RareVariable::kThisFunction);
932 DCHECK(this_function ==
nullptr ||
933 (is_function_scope() && (IsClassConstructor(function_kind()) ||
934 IsConciseMethod(function_kind()) ||
935 IsAccessorFunction(function_kind()))));
936 return this_function;
944 void DeclareSloppyBlockFunction(
953 return sloppy_block_function_map_;
967 V8_WARN_UNUSED_RESULT
985 bool AllowsLazyCompilation()
const;
988 void ForceEagerCompilation() {
989 DCHECK_EQ(
this, GetClosureScope());
991 for (s =
this; !s->is_script_scope();
992 s = s->outer_scope()->GetClosureScope()) {
993 s->force_eager_compilation_ =
true;
995 s->force_eager_compilation_ =
true;
999 void PrintParameters();
1002 void AllocateLocals();
1003 void AllocateParameterLocals();
1004 void AllocateReceiver();
1006 void ResetAfterPreparsing(
AstValueFactory* ast_value_factory,
bool aborted);
1008 bool is_skipped_function()
const {
return is_skipped_function_; }
1009 void set_is_skipped_function(
bool is_skipped_function) {
1010 is_skipped_function_ = is_skipped_function;
1013 bool has_inferred_function_name()
const {
1014 return has_inferred_function_name_;
1016 void set_has_inferred_function_name(
bool value) {
1017 DCHECK(is_function_scope());
1018 has_inferred_function_name_ = value;
1024 void SavePreParsedScopeDataForDeclarationScope();
1026 void set_preparsed_scope_data_builder(
1028 preparsed_scope_data_builder_ = preparsed_scope_data_builder;
1032 return preparsed_scope_data_builder_;
1036 void AllocateParameter(
Variable* var,
int index);
1048 bool AllocateVariables(
ParseInfo* info);
1052 bool has_simple_parameters_ : 1;
1054 bool asm_module_ : 1;
1055 bool force_eager_compilation_ : 1;
1059 bool has_arguments_parameter_ : 1;
1061 bool scope_uses_super_property_ : 1;
1062 bool should_eager_compile_ : 1;
1064 bool was_lazily_parsed_ : 1;
1066 bool is_being_lazily_parsed_ : 1;
1068 bool is_skipped_function_ : 1;
1069 bool has_inferred_function_name_ : 1;
1072 const FunctionKind function_kind_;
1096 Variable* generator_object =
nullptr;
1099 enum class RareVariable {
1100 kThisFunction = offsetof(RareData, this_function),
1101 kGeneratorObject = offsetof(RareData, generator_object),
1104 V8_INLINE RareData* EnsureRareData() {
1105 if (rare_data_ ==
nullptr) {
1106 rare_data_ =
new (zone_) RareData;
1111 V8_INLINE
Variable* GetRareVariable(RareVariable
id)
const {
1112 if (rare_data_ ==
nullptr)
return nullptr;
1113 return *
reinterpret_cast<Variable**
>(
1114 reinterpret_cast<uint8_t*
>(rare_data_) + static_cast<ptrdiff_t>(
id));
1119 template <
typename Predicate>
1120 V8_INLINE
void NullifyRareVariableIf(RareVariable
id, Predicate predicate) {
1121 if (V8_LIKELY(rare_data_ ==
nullptr))
return;
1123 reinterpret_cast<uint8_t*
>(rare_data_) + static_cast<ptrdiff_t>(
id));
1124 if (*var && predicate(*var)) *var =
nullptr;
1127 RareData* rare_data_ =
nullptr;
1130 Scope::Snapshot::Snapshot(
Scope* scope)
1131 : outer_scope_and_calls_eval_(scope, scope->scope_calls_eval_),
1132 top_inner_scope_(scope->inner_scope_),
1133 top_unresolved_(scope->unresolved_list_.end()),
1134 top_local_(scope->GetClosureScope()->locals_.end()) {
1136 outer_scope_and_calls_eval_.GetPointer()->scope_calls_eval_ =
false;
1152 DCHECK_NOT_NULL(module_descriptor_);
1153 return module_descriptor_;
1158 void AllocateModuleVariables();
1167 #endif // V8_AST_SCOPES_H_