1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/parsing/parse-info.h" 6 7 #include "src/ast/ast-source-ranges.h" 8 #include "src/ast/ast-value-factory.h" 9 #include "src/ast/ast.h" 10 #include "src/base/template-utils.h" 11 #include "src/heap/heap-inl.h" 12 #include "src/objects-inl.h" 13 #include "src/objects/scope-info.h" 14 #include "src/zone/zone.h" 15 16 namespace v8 { 17 namespace internal { 18 19 ParseInfo::ParseInfo(Isolate* isolate, AccountingAllocator* zone_allocator) 20 : zone_(base::make_unique<Zone>(zone_allocator, ZONE_NAME)), 21 flags_(0), 22 extension_(nullptr), 23 script_scope_(nullptr), 24 unicode_cache_(nullptr), 25 stack_limit_(0), 26 hash_seed_(0), 27 function_kind_(FunctionKind::kNormalFunction), 28 script_id_(-1), 29 start_position_(0), 30 end_position_(0), 31 parameters_end_pos_(kNoSourcePosition), 32 function_literal_id_(FunctionLiteral::kIdTypeInvalid), 33 max_function_literal_id_(FunctionLiteral::kIdTypeInvalid), 34 character_stream_(nullptr), 35 ast_value_factory_(nullptr), 36 ast_string_constants_(nullptr), 37 function_name_(nullptr), 38 runtime_call_stats_(nullptr), 39 source_range_map_(nullptr), 40 literal_(nullptr) { 41 set_hash_seed(isolate->heap()->HashSeed()); 42 set_stack_limit(isolate->stack_guard()->real_climit()); 43 set_unicode_cache(isolate->unicode_cache()); 44 set_runtime_call_stats(isolate->counters()->runtime_call_stats()); 45 set_logger(isolate->logger()); 46 set_ast_string_constants(isolate->ast_string_constants()); 47 if (isolate->is_block_code_coverage()) set_block_coverage_enabled(); 48 if (isolate->is_collecting_type_profile()) set_collect_type_profile(); 49 } 50 51 ParseInfo::ParseInfo(Isolate* isolate) 52 : ParseInfo(isolate, isolate->allocator()) { 53 script_id_ = isolate->heap()->NextScriptId(); 54 LOG(isolate, ScriptEvent(Logger::ScriptEventType::kReserveId, script_id_)); 55 } 56 57 ParseInfo::ParseInfo(Isolate* isolate, Handle<SharedFunctionInfo> shared) 58 : ParseInfo(isolate, isolate->allocator()) { 59 // Do not support re-parsing top-level function of a wrapped script. 60 // TODO(yangguo): consider whether we need a top-level function in a 61 // wrapped script at all. 62 DCHECK_IMPLIES(is_toplevel(), !Script::cast(shared->script())->is_wrapped()); 63 64 set_toplevel(shared->is_toplevel()); 65 set_wrapped_as_function(shared->is_wrapped()); 66 set_allow_lazy_parsing(FLAG_lazy_inner_functions); 67 set_is_named_expression(shared->is_named_expression()); 68 set_start_position(shared->StartPosition()); 69 set_end_position(shared->EndPosition()); 70 function_literal_id_ = shared->FunctionLiteralId(isolate); 71 set_language_mode(shared->language_mode()); 72 set_function_kind(shared->kind()); 73 set_declaration(shared->is_declaration()); 74 set_requires_instance_fields_initializer( 75 shared->requires_instance_fields_initializer()); 76 set_asm_wasm_broken(shared->is_asm_wasm_broken()); 77 78 Handle<Script> script(Script::cast(shared->script()), isolate); 79 set_script(script); 80 81 if (shared->HasOuterScopeInfo()) { 82 set_outer_scope_info(handle(shared->GetOuterScopeInfo(), isolate)); 83 } 84 85 // CollectTypeProfile uses its own feedback slots. If we have existing 86 // FeedbackMetadata, we can only collect type profile if the feedback vector 87 // has the appropriate slots. 88 set_collect_type_profile( 89 isolate->is_collecting_type_profile() && 90 (shared->HasFeedbackMetadata() 91 ? shared->feedback_metadata()->HasTypeProfileSlot() 92 : script->IsUserJavaScript())); 93 } 94 95 ParseInfo::ParseInfo(Isolate* isolate, Handle<Script> script) 96 : ParseInfo(isolate, isolate->allocator()) { 97 SetScriptForToplevelCompile(isolate, script); 98 set_collect_type_profile(isolate->is_collecting_type_profile() && 99 script->IsUserJavaScript()); 100 } 101 102 ParseInfo::~ParseInfo() {} 103 104 DeclarationScope* ParseInfo::scope() const { return literal()->scope(); } 105 106 void ParseInfo::EmitBackgroundParseStatisticsOnBackgroundThread() { 107 // If runtime call stats was enabled by tracing, emit a trace event at the 108 // end of background parsing on the background thread. 109 if (runtime_call_stats_ && 110 (FLAG_runtime_stats & 111 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) { 112 auto value = v8::tracing::TracedValue::Create(); 113 runtime_call_stats_->Dump(value.get()); 114 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats"), 115 "V8.RuntimeStats", TRACE_EVENT_SCOPE_THREAD, 116 "runtime-call-stats", std::move(value)); 117 } 118 } 119 120 void ParseInfo::UpdateBackgroundParseStatisticsOnMainThread(Isolate* isolate) { 121 // Copy over the counters from the background thread to the main counters on 122 // the isolate. 123 RuntimeCallStats* main_call_stats = isolate->counters()->runtime_call_stats(); 124 if (FLAG_runtime_stats == 125 v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE) { 126 DCHECK_NE(main_call_stats, runtime_call_stats()); 127 DCHECK_NOT_NULL(main_call_stats); 128 DCHECK_NOT_NULL(runtime_call_stats()); 129 main_call_stats->Add(runtime_call_stats()); 130 } 131 set_runtime_call_stats(main_call_stats); 132 } 133 134 Handle<Script> ParseInfo::CreateScript(Isolate* isolate, Handle<String> source, 135 ScriptOriginOptions origin_options, 136 NativesFlag natives) { 137 // Create a script object describing the script to be compiled. 138 Handle<Script> script; 139 if (script_id_ == -1) { 140 script = isolate->factory()->NewScript(source); 141 } else { 142 script = isolate->factory()->NewScriptWithId(source, script_id_); 143 } 144 if (isolate->NeedsSourcePositionsForProfiling()) { 145 Script::InitLineEnds(script); 146 } 147 switch (natives) { 148 case NATIVES_CODE: 149 script->set_type(Script::TYPE_NATIVE); 150 break; 151 case EXTENSION_CODE: 152 script->set_type(Script::TYPE_EXTENSION); 153 break; 154 case INSPECTOR_CODE: 155 script->set_type(Script::TYPE_INSPECTOR); 156 break; 157 case NOT_NATIVES_CODE: 158 break; 159 } 160 script->set_origin_options(origin_options); 161 162 SetScriptForToplevelCompile(isolate, script); 163 return script; 164 } 165 166 AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() { 167 if (!ast_value_factory_.get()) { 168 ast_value_factory_.reset( 169 new AstValueFactory(zone(), ast_string_constants(), hash_seed())); 170 } 171 return ast_value_factory(); 172 } 173 174 void ParseInfo::AllocateSourceRangeMap() { 175 DCHECK(block_coverage_enabled()); 176 set_source_range_map(new (zone()) SourceRangeMap(zone())); 177 } 178 179 void ParseInfo::ResetCharacterStream() { character_stream_.reset(); } 180 181 void ParseInfo::set_character_stream( 182 std::unique_ptr<Utf16CharacterStream> character_stream) { 183 DCHECK_NULL(character_stream_); 184 character_stream_.swap(character_stream); 185 } 186 187 void ParseInfo::SetScriptForToplevelCompile(Isolate* isolate, 188 Handle<Script> script) { 189 set_script(script); 190 set_allow_lazy_parsing(); 191 set_toplevel(); 192 set_collect_type_profile(isolate->is_collecting_type_profile() && 193 script->IsUserJavaScript()); 194 set_wrapped_as_function(script->is_wrapped()); 195 } 196 197 void ParseInfo::set_script(Handle<Script> script) { 198 script_ = script; 199 DCHECK(script_id_ == -1 || script_id_ == script->id()); 200 script_id_ = script->id(); 201 202 set_native(script->type() == Script::TYPE_NATIVE); 203 set_eval(script->compilation_type() == Script::COMPILATION_TYPE_EVAL); 204 set_module(script->origin_options().IsModule()); 205 DCHECK(!(is_eval() && is_module())); 206 207 if (block_coverage_enabled() && script->IsUserJavaScript()) { 208 AllocateSourceRangeMap(); 209 } 210 } 211 212 } // namespace internal 213 } // namespace v8 214