// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_PARSING_PARSE_INFO_H_ #define V8_PARSING_PARSE_INFO_H_ #include <memory> #include "src/base/bit-field.h" #include "src/base/export-template.h" #include "src/base/logging.h" #include "src/common/globals.h" #include "src/handles/handles.h" #include "src/objects/function-kind.h" #include "src/objects/function-syntax-kind.h" #include "src/objects/script.h" #include "src/parsing/pending-compilation-error-handler.h" #include "src/parsing/preparse-data.h" namespace v8 { class Extension; namespace internal { class AccountingAllocator; class AstRawString; class AstStringConstants; class AstValueFactory; class LazyCompileDispatcher; class DeclarationScope; class FunctionLiteral; class RuntimeCallStats; class V8FileLogger; class SourceRangeMap; class Utf16CharacterStream; class Zone; // The flags for a parse + unoptimized compile operation. #define FLAG_FIELDS(V, _) \ V(is_toplevel, bool, 1, _) \ V(is_eager, bool, 1, _) \ V(is_eval, bool, 1, _) \ V(is_reparse, bool, 1, _) \ V(outer_language_mode, LanguageMode, 1, _) \ V(parse_restriction, ParseRestriction, 1, _) \ V(is_module, bool, 1, _) \ V(allow_lazy_parsing, bool, 1, _) \ V(is_lazy_compile, bool, 1, _) \ V(collect_type_profile, bool, 1, _) \ V(coverage_enabled, bool, 1, _) \ V(block_coverage_enabled, bool, 1, _) \ V(is_asm_wasm_broken, bool, 1, _) \ V(class_scope_has_private_brand, bool, 1, _) \ V(private_name_lookup_skips_outer_class, bool, 1, _) \ V(requires_instance_members_initializer, bool, 1, _) \ V(has_static_private_methods_or_accessors, bool, 1, _) \ V(might_always_turbofan, bool, 1, _) \ V(allow_natives_syntax, bool, 1, _) \ V(allow_lazy_compile, bool, 1, _) \ V(post_parallel_compile_tasks_for_eager_toplevel, bool, 1, _) \ V(post_parallel_compile_tasks_for_lazy, bool, 1, _) \ V(collect_source_positions, bool, 1, _) \ V(is_repl_mode, bool, 1, _) class V8_EXPORT_PRIVATE UnoptimizedCompileFlags { public: // Set-up flags for a toplevel compilation. static UnoptimizedCompileFlags ForToplevelCompile(Isolate* isolate, bool is_user_javascript, LanguageMode language_mode, REPLMode repl_mode, ScriptType type, bool lazy); // Set-up flags for a compiling a particular function (either a lazy compile // or a recompile). static UnoptimizedCompileFlags ForFunctionCompile(Isolate* isolate, SharedFunctionInfo shared); // Set-up flags for a full compilation of a given script. static UnoptimizedCompileFlags ForScriptCompile(Isolate* isolate, Script script); // Set-up flags for a parallel toplevel function compilation, based on the // flags of an existing toplevel compilation. static UnoptimizedCompileFlags ForToplevelFunction( const UnoptimizedCompileFlags toplevel_flags, const FunctionLiteral* literal); // Create flags for a test. static UnoptimizedCompileFlags ForTest(Isolate* isolate); #define FLAG_GET_SET(NAME, TYPE, SIZE, _) \ TYPE NAME() const { return BitFields::NAME::decode(flags_); } \ UnoptimizedCompileFlags& set_##NAME(TYPE value) { \ flags_ = BitFields::NAME::update(flags_, value); \ return *this; \ } FLAG_FIELDS(FLAG_GET_SET, _) int script_id() const { return script_id_; } UnoptimizedCompileFlags& set_script_id(int value) { script_id_ = value; return *this; } FunctionKind function_kind() const { return function_kind_; } UnoptimizedCompileFlags& set_function_kind(FunctionKind value) { function_kind_ = value; return *this; } FunctionSyntaxKind function_syntax_kind() const { return function_syntax_kind_; } UnoptimizedCompileFlags& set_function_syntax_kind(FunctionSyntaxKind value) { function_syntax_kind_ = value; return *this; } ParsingWhileDebugging parsing_while_debugging() const { return parsing_while_debugging_; } UnoptimizedCompileFlags& set_parsing_while_debugging( ParsingWhileDebugging value) { parsing_while_debugging_ = value; return *this; } private: struct BitFields { DEFINE_BIT_FIELDS(FLAG_FIELDS) }; UnoptimizedCompileFlags(Isolate* isolate, int script_id); // Set function info flags based on those in either FunctionLiteral or // SharedFunctionInfo |function| template <typename T> void SetFlagsFromFunction(T function); void SetFlagsForToplevelCompile(bool is_collecting_type_profile, bool is_user_javascript, LanguageMode language_mode, REPLMode repl_mode, ScriptType type, bool lazy); void SetFlagsForFunctionFromScript(Script script); uint32_t flags_; int script_id_; FunctionKind function_kind_; FunctionSyntaxKind function_syntax_kind_; ParsingWhileDebugging parsing_while_debugging_; }; #undef FLAG_FIELDS class ParseInfo; // The mutable state for a parse + unoptimized compile operation. class V8_EXPORT_PRIVATE UnoptimizedCompileState { public: const PendingCompilationErrorHandler* pending_error_handler() const { return &pending_error_handler_; } PendingCompilationErrorHandler* pending_error_handler() { return &pending_error_handler_; } private: PendingCompilationErrorHandler pending_error_handler_; }; // A container for ParseInfo fields that are reusable across multiple parses and // unoptimized compiles. // // Note that this is different from UnoptimizedCompileState, which has mutable // state for a single compilation that is not reusable across multiple // compilations. class V8_EXPORT_PRIVATE ReusableUnoptimizedCompileState { public: explicit ReusableUnoptimizedCompileState(Isolate* isolate); explicit ReusableUnoptimizedCompileState(LocalIsolate* isolate); ~ReusableUnoptimizedCompileState(); // The AstRawString Zone stores the AstRawStrings in the AstValueFactory that // can be reused across parses, and thereforce should stay alive between // parses that reuse this reusable state and its AstValueFactory. Zone* ast_raw_string_zone() { return &ast_raw_string_zone_; } // The single parse Zone stores the data of a single parse, and can be cleared // when that parse completes. // // This is in "reusable" state despite being wiped per-parse, because it // allows us to reuse the Zone itself, and e.g. keep the same single parse // Zone pointer in the AstValueFactory. Zone* single_parse_zone() { return &single_parse_zone_; } void NotifySingleParseCompleted() { single_parse_zone_.Reset(); } AstValueFactory* ast_value_factory() const { return ast_value_factory_.get(); } uint64_t hash_seed() const { return hash_seed_; } AccountingAllocator* allocator() const { return allocator_; } const AstStringConstants* ast_string_constants() const { return ast_string_constants_; } // TODO(cbruni): Switch this back to the main logger. V8FileLogger* v8_file_logger() const { return v8_file_logger_; } LazyCompileDispatcher* dispatcher() const { return dispatcher_; } private: uint64_t hash_seed_; AccountingAllocator* allocator_; V8FileLogger* v8_file_logger_; LazyCompileDispatcher* dispatcher_; const AstStringConstants* ast_string_constants_; Zone ast_raw_string_zone_; Zone single_parse_zone_; std::unique_ptr<AstValueFactory> ast_value_factory_; }; // A container for the inputs, configuration options, and outputs of parsing. class V8_EXPORT_PRIVATE ParseInfo { public: ParseInfo(Isolate* isolate, const UnoptimizedCompileFlags flags, UnoptimizedCompileState* state, ReusableUnoptimizedCompileState* reusable_state); ParseInfo(LocalIsolate* isolate, const UnoptimizedCompileFlags flags, UnoptimizedCompileState* state, ReusableUnoptimizedCompileState* reusable_state, uintptr_t stack_limit); ~ParseInfo(); template <typename IsolateT> EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Handle<Script> CreateScript(IsolateT* isolate, Handle<String> source, MaybeHandle<FixedArray> maybe_wrapped_arguments, ScriptOriginOptions origin_options, NativesFlag natives = NOT_NATIVES_CODE); Zone* zone() const { return reusable_state_->single_parse_zone(); } const UnoptimizedCompileFlags& flags() const { return flags_; } // Getters for reusable state. uint64_t hash_seed() const { return reusable_state_->hash_seed(); } AccountingAllocator* allocator() const { return reusable_state_->allocator(); } const AstStringConstants* ast_string_constants() const { return reusable_state_->ast_string_constants(); } V8FileLogger* v8_file_logger() const { return reusable_state_->v8_file_logger(); } LazyCompileDispatcher* dispatcher() const { return reusable_state_->dispatcher(); } const UnoptimizedCompileState* state() const { return state_; } // Getters for state. PendingCompilationErrorHandler* pending_error_handler() { return state_->pending_error_handler(); } // Accessors for per-thread state. uintptr_t stack_limit() const { return stack_limit_; } RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; } // Accessor methods for output flags. bool allow_eval_cache() const { return allow_eval_cache_; } void set_allow_eval_cache(bool value) { allow_eval_cache_ = value; } #if V8_ENABLE_WEBASSEMBLY bool contains_asm_module() const { return contains_asm_module_; } void set_contains_asm_module(bool value) { contains_asm_module_ = value; } #endif // V8_ENABLE_WEBASSEMBLY LanguageMode language_mode() const { return language_mode_; } void set_language_mode(LanguageMode value) { language_mode_ = value; } Utf16CharacterStream* character_stream() const { return character_stream_.get(); } void set_character_stream( std::unique_ptr<Utf16CharacterStream> character_stream); void ResetCharacterStream(); v8::Extension* extension() const { return extension_; } void set_extension(v8::Extension* extension) { extension_ = extension; } void set_consumed_preparse_data(std::unique_ptr<ConsumedPreparseData> data) { consumed_preparse_data_.swap(data); } ConsumedPreparseData* consumed_preparse_data() { return consumed_preparse_data_.get(); } DeclarationScope* script_scope() const { return script_scope_; } void set_script_scope(DeclarationScope* script_scope) { script_scope_ = script_scope; } AstValueFactory* ast_value_factory() const { return reusable_state_->ast_value_factory(); } const AstRawString* function_name() const { return function_name_; } void set_function_name(const AstRawString* function_name) { function_name_ = function_name; } FunctionLiteral* literal() const { return literal_; } void set_literal(FunctionLiteral* literal) { literal_ = literal; } DeclarationScope* scope() const; int parameters_end_pos() const { return parameters_end_pos_; } void set_parameters_end_pos(int parameters_end_pos) { parameters_end_pos_ = parameters_end_pos; } bool is_wrapped_as_function() const { return flags().function_syntax_kind() == FunctionSyntaxKind::kWrapped; } int max_function_literal_id() const { return max_function_literal_id_; } void set_max_function_literal_id(int max_function_literal_id) { max_function_literal_id_ = max_function_literal_id; } void AllocateSourceRangeMap(); SourceRangeMap* source_range_map() const { return source_range_map_; } void set_source_range_map(SourceRangeMap* source_range_map) { source_range_map_ = source_range_map; } void CheckFlagsForFunctionFromScript(Script script); private: ParseInfo(const UnoptimizedCompileFlags flags, UnoptimizedCompileState* state, ReusableUnoptimizedCompileState* reusable_state, uintptr_t stack_limit, RuntimeCallStats* runtime_call_stats); void CheckFlagsForToplevelCompileFromScript(Script script, bool is_collecting_type_profile); //------------- Inputs to parsing and scope analysis ----------------------- const UnoptimizedCompileFlags flags_; UnoptimizedCompileState* state_; ReusableUnoptimizedCompileState* reusable_state_; v8::Extension* extension_; DeclarationScope* script_scope_; uintptr_t stack_limit_; int parameters_end_pos_; int max_function_literal_id_; //----------- Inputs+Outputs of parsing and scope analysis ----------------- std::unique_ptr<Utf16CharacterStream> character_stream_; std::unique_ptr<ConsumedPreparseData> consumed_preparse_data_; const AstRawString* function_name_; RuntimeCallStats* runtime_call_stats_; SourceRangeMap* source_range_map_; // Used when block coverage is enabled. //----------- Output of parsing and scope analysis ------------------------ FunctionLiteral* literal_; bool allow_eval_cache_ : 1; #if V8_ENABLE_WEBASSEMBLY bool contains_asm_module_ : 1; #endif // V8_ENABLE_WEBASSEMBLY LanguageMode language_mode_ : 1; }; } // namespace internal } // namespace v8 #endif // V8_PARSING_PARSE_INFO_H_