// 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 <map> #include <memory> #include <vector> #include "include/v8.h" #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 CompilerDispatcher; class DeclarationScope; class FunctionLiteral; class RuntimeCallStats; class Logger; 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(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(requires_instance_members_initializer, bool, 1, _) \ V(has_static_private_methods_or_accessors, bool, 1, _) \ V(might_always_opt, bool, 1, _) \ V(allow_natives_syntax, bool, 1, _) \ V(allow_lazy_compile, bool, 1, _) \ V(collect_source_positions, bool, 1, _) \ V(allow_harmony_top_level_await, 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; } 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_; }; #undef FLAG_FIELDS class ParseInfo; // The mutable state for a parse + unoptimized compile operation. class V8_EXPORT_PRIVATE UnoptimizedCompileState { public: explicit UnoptimizedCompileState(Isolate*); UnoptimizedCompileState(const UnoptimizedCompileState& other) V8_NOEXCEPT; class ParallelTasks { public: explicit ParallelTasks(CompilerDispatcher* compiler_dispatcher) : dispatcher_(compiler_dispatcher) { DCHECK_NOT_NULL(dispatcher_); } void Enqueue(ParseInfo* outer_parse_info, const AstRawString* function_name, FunctionLiteral* literal); using EnqueuedJobsIterator = std::forward_list<std::pair<FunctionLiteral*, uintptr_t>>::iterator; EnqueuedJobsIterator begin() { return enqueued_jobs_.begin(); } EnqueuedJobsIterator end() { return enqueued_jobs_.end(); } CompilerDispatcher* dispatcher() { return dispatcher_; } private: CompilerDispatcher* dispatcher_; std::forward_list<std::pair<FunctionLiteral*, uintptr_t>> enqueued_jobs_; }; uint64_t hash_seed() const { return hash_seed_; } AccountingAllocator* allocator() const { return allocator_; } const AstStringConstants* ast_string_constants() const { return ast_string_constants_; } Logger* logger() const { return logger_; } PendingCompilationErrorHandler* pending_error_handler() { return &pending_error_handler_; } const PendingCompilationErrorHandler* pending_error_handler() const { return &pending_error_handler_; } ParallelTasks* parallel_tasks() const { return parallel_tasks_.get(); } private: uint64_t hash_seed_; AccountingAllocator* allocator_; const AstStringConstants* ast_string_constants_; PendingCompilationErrorHandler pending_error_handler_; Logger* logger_; std::unique_ptr<ParallelTasks> parallel_tasks_; }; // 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); // Creates a new parse info based on parent top-level |outer_parse_info| for // function |literal|. static std::unique_ptr<ParseInfo> ForToplevelFunction( const UnoptimizedCompileFlags flags, UnoptimizedCompileState* compile_state, const FunctionLiteral* literal, const AstRawString* function_name); ~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); // Either returns the ast-value-factory associcated with this ParseInfo, or // creates and returns a new factory if none exists. AstValueFactory* GetOrCreateAstValueFactory(); Zone* zone() const { return zone_.get(); } const UnoptimizedCompileFlags& flags() const { return flags_; } // Getters for state. uint64_t hash_seed() const { return state_->hash_seed(); } AccountingAllocator* allocator() const { return state_->allocator(); } const AstStringConstants* ast_string_constants() const { return state_->ast_string_constants(); } Logger* logger() const { return state_->logger(); } PendingCompilationErrorHandler* pending_error_handler() { return state_->pending_error_handler(); } UnoptimizedCompileState::ParallelTasks* parallel_tasks() const { return state_->parallel_tasks(); } const UnoptimizedCompileState* state() const { return state_; } // Accessors for per-thread state. uintptr_t stack_limit() const { return stack_limit_; } RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; } void SetPerThreadState(uintptr_t stack_limit, RuntimeCallStats* runtime_call_stats) { stack_limit_ = stack_limit; runtime_call_stats_ = 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 { DCHECK(ast_value_factory_.get()); return ast_value_factory_.get(); } 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); void CheckFlagsForToplevelCompileFromScript(Script script, bool is_collecting_type_profile); //------------- Inputs to parsing and scope analysis ----------------------- const UnoptimizedCompileFlags flags_; UnoptimizedCompileState* state_; std::unique_ptr<Zone> zone_; 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_; std::unique_ptr<AstValueFactory> ast_value_factory_; 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_