diff options
author | Ali Ijaz Sheikh <ofrobots@google.com> | 2015-08-23 06:09:40 -0700 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2015-09-06 21:38:01 +1000 |
commit | 9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch) | |
tree | 4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/src/compiler.cc | |
parent | 46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff) | |
download | node-new-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.gz |
deps: upgrade V8 to 4.5.103.24
Upgrade to the latest branch-head for V8 4.5. For the full commit log see
https://github.com/v8/v8-git-mirror/commits/4.5.103.24
PR-URL: https://github.com/nodejs/node/pull/2509
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/compiler.cc')
-rw-r--r-- | deps/v8/src/compiler.cc | 263 |
1 files changed, 172 insertions, 91 deletions
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index 165bf4f2e4..0f3ebe0e67 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -114,18 +114,19 @@ CompilationInfo::CompilationInfo(ParseInfo* parse_info) if (isolate_->debug()->is_active()) MarkAsDebug(); if (FLAG_context_specialization) MarkAsContextSpecializing(); - if (FLAG_turbo_builtin_inlining) MarkAsBuiltinInliningEnabled(); - if (FLAG_turbo_deoptimization) MarkAsDeoptimizationEnabled(); if (FLAG_turbo_inlining) MarkAsInliningEnabled(); if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled(); if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); if (FLAG_turbo_types) MarkAsTypingEnabled(); - if (has_shared_info() && shared_info()->is_compiled()) { - // We should initialize the CompilationInfo feedback vector from the - // passed in shared info, rather than creating a new one. - feedback_vector_ = Handle<TypeFeedbackVector>( - shared_info()->feedback_vector(), parse_info->isolate()); + if (has_shared_info()) { + if (shared_info()->is_compiled()) { + // We should initialize the CompilationInfo feedback vector from the + // passed in shared info, rather than creating a new one. + feedback_vector_ = Handle<TypeFeedbackVector>( + shared_info()->feedback_vector(), parse_info->isolate()); + } + if (shared_info()->never_compiled()) MarkAsFirstCompile(); } } @@ -155,7 +156,8 @@ CompilationInfo::CompilationInfo(ParseInfo* parse_info, CodeStub* code_stub, opt_count_(has_shared_info() ? shared_info()->opt_count() : 0), parameter_count_(0), optimization_id_(-1), - osr_expr_stack_height_(0) {} + osr_expr_stack_height_(0), + function_type_(nullptr) {} CompilationInfo::~CompilationInfo() { @@ -175,6 +177,14 @@ int CompilationInfo::num_parameters() const { } +int CompilationInfo::num_parameters_including_this() const { + return num_parameters() + (is_this_defined() ? 1 : 0); +} + + +bool CompilationInfo::is_this_defined() const { return !IsStub(); } + + int CompilationInfo::num_heap_slots() const { return has_scope() ? scope()->num_heap_slots() : 0; } @@ -215,8 +225,7 @@ bool CompilationInfo::is_simple_parameter_list() { bool CompilationInfo::MayUseThis() const { - return scope()->uses_this() || scope()->inner_uses_this() || - scope()->calls_sloppy_eval(); + return scope()->has_this_declaration() && scope()->receiver()->is_used(); } @@ -273,6 +282,14 @@ void CompilationInfo::LogDeoptCallPosition(int pc_offset, int inlining_id) { } +Handle<Code> CompilationInfo::GenerateCodeStub() { + // Run a "mini pipeline", extracted from compiler.cc. + CHECK(Parser::ParseStatic(parse_info())); + CHECK(Compiler::Analyze(parse_info())); + return compiler::Pipeline(this).GenerateCode(); +} + + class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { public: explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) @@ -359,9 +376,12 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { } DCHECK(info()->shared_info()->has_deoptimization_support()); + DCHECK(!info()->is_first_compile()); // Check the enabling conditions for TurboFan. + bool dont_crankshaft = info()->shared_info()->dont_crankshaft(); if (((FLAG_turbo_asm && info()->shared_info()->asm_function()) || + (dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0) || info()->closure()->PassesFilter(FLAG_turbo_filter)) && (FLAG_turbo_osr || !info()->is_osr())) { // Use TurboFan for the compilation. @@ -374,11 +394,16 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { } if (info()->shared_info()->asm_function()) { + if (info()->osr_frame()) info()->MarkAsFrameSpecializing(); info()->MarkAsContextSpecializing(); } else if (FLAG_turbo_type_feedback) { info()->MarkAsTypeFeedbackEnabled(); info()->EnsureFeedbackVector(); } + if (!info()->shared_info()->asm_function() || + FLAG_turbo_asm_deoptimization) { + info()->MarkAsDeoptimizationEnabled(); + } Timer t(this, &time_taken_to_create_graph_); compiler::Pipeline pipeline(info()); @@ -388,7 +413,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { } } - if (!isolate()->use_crankshaft()) { + if (!isolate()->use_crankshaft() || dont_crankshaft) { // Crankshaft is entirely disabled. return SetLastStatus(FAILED); } @@ -488,7 +513,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { // TODO(turbofan): Currently everything is done in the first phase. if (!info()->code().is_null()) { info()->dependencies()->Commit(info()->code()); - if (FLAG_turbo_deoptimization) { + if (info()->is_deoptimization_enabled()) { info()->parse_info()->context()->native_context()->AddOptimizedCode( *info()->code()); } @@ -660,7 +685,6 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( // Update the code and feedback vector for the shared function info. shared->ReplaceCode(*info->code()); - if (shared->optimization_disabled()) info->code()->set_optimizable(false); shared->set_feedback_vector(*info->feedback_vector()); return info->code(); @@ -669,26 +693,16 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap( Handle<JSFunction> function, BailoutId osr_ast_id) { - if (FLAG_cache_optimized_code) { - Handle<SharedFunctionInfo> shared(function->shared()); - // Bound functions are not cached. - if (shared->bound()) return MaybeHandle<Code>(); - DisallowHeapAllocation no_gc; - int index = shared->SearchOptimizedCodeMap( - function->context()->native_context(), osr_ast_id); - if (index > 0) { - if (FLAG_trace_opt) { - PrintF("[found optimized code for "); - function->ShortPrint(); - if (!osr_ast_id.IsNone()) { - PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); - } - PrintF("]\n"); - } - FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index); - if (literals != NULL) function->set_literals(literals); - return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index)); - } + Handle<SharedFunctionInfo> shared(function->shared()); + DisallowHeapAllocation no_gc; + CodeAndLiterals cached = shared->SearchOptimizedCodeMap( + function->context()->native_context(), osr_ast_id); + if (cached.code != nullptr) { + // Caching of optimized code enabled and optimized code found. + if (cached.literals != nullptr) function->set_literals(cached.literals); + DCHECK(!cached.code->marked_for_deoptimization()); + DCHECK(function->shared()->is_compiled()); + return Handle<Code>(cached.code); } return MaybeHandle<Code>(); } @@ -699,19 +713,33 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. // Context specialization folds-in the context, so no sharing can occur. - if (code->is_turbofanned() && info->is_context_specializing()) return; + if (info->is_context_specializing()) return; + // Frame specialization implies context specialization. + DCHECK(!info->is_frame_specializing()); - // Cache optimized code. + // Do not cache bound functions. + Handle<JSFunction> function = info->closure(); + if (function->shared()->bound()) return; + + // Cache optimized context-specific code. if (FLAG_cache_optimized_code) { - Handle<JSFunction> function = info->closure(); Handle<SharedFunctionInfo> shared(function->shared()); - // Do not cache bound functions. - if (shared->bound()) return; Handle<FixedArray> literals(function->literals()); Handle<Context> native_context(function->context()->native_context()); SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, literals, info->osr_ast_id()); } + + // Do not cache context-independent code compiled for OSR. + if (code->is_turbofanned() && info->is_osr()) return; + + // Cache optimized context-independent code. + if (FLAG_turbo_cache_shared_code && code->is_turbofanned()) { + DCHECK(!info->is_context_specializing()); + DCHECK(info->osr_ast_id().IsNone()); + Handle<SharedFunctionInfo> shared(function->shared()); + SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code); + } } @@ -725,7 +753,7 @@ static bool Renumber(ParseInfo* parse_info) { FunctionLiteral* lit = parse_info->function(); shared_info->set_ast_node_count(lit->ast_node_count()); MaybeDisableOptimization(shared_info, lit->dont_optimize_reason()); - shared_info->set_dont_cache(lit->flags()->Contains(kDontCache)); + shared_info->set_dont_crankshaft(lit->flags()->Contains(kDontCrankshaft)); } return true; } @@ -835,7 +863,7 @@ MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) { // If the debugger is active, do not compile with turbofan unless we can // deopt from turbofan code. if (FLAG_turbo_asm && function->shared()->asm_function() && - (FLAG_turbo_deoptimization || !isolate->debug()->is_active()) && + (FLAG_turbo_asm_deoptimization || !isolate->debug()->is_active()) && !FLAG_turbo_osr) { CompilationInfoWithZone info(function); @@ -932,6 +960,8 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { shared->EnableDeoptimizationSupport(*unoptimized.code()); shared->set_feedback_vector(*unoptimized.feedback_vector()); + info->MarkAsCompiled(); + // The scope info might not have been set if a lazily compiled // function is inlined before being called for the first time. if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { @@ -994,6 +1024,8 @@ void Compiler::CompileForLiveEdit(Handle<Script> script) { PostponeInterruptsScope postpone(info.isolate()); VMState<COMPILER> state(info.isolate()); + // Get rid of old list of shared function infos. + info.MarkAsFirstCompile(); info.parse_info()->set_global(); if (!Parser::ParseStatic(info.parse_info())) return; @@ -1054,6 +1086,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { } } + info->MarkAsFirstCompile(); + FunctionLiteral* lit = info->function(); LiveEditFunctionTracker live_edit_tracker(isolate, lit); @@ -1080,7 +1114,7 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position()); SharedFunctionInfo::InitFromFunctionLiteral(result, lit); - result->set_script(*script); + SharedFunctionInfo::SetScript(result, script); result->set_is_toplevel(true); Handle<String> script_name = script->name()->IsString() @@ -1153,10 +1187,8 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( // If caller is strict mode, the result must be in strict mode as well. DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode())); - if (!shared_info->dont_cache()) { - compilation_cache->PutEval(source, outer_info, context, shared_info, - scope_position); - } + compilation_cache->PutEval(source, outer_info, context, shared_info, + scope_position); } } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) { shared_info->ResetForNewContext(isolate->heap()->global_ic_age()); @@ -1169,9 +1201,9 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( Handle<SharedFunctionInfo> Compiler::CompileScript( Handle<String> source, Handle<Object> script_name, int line_offset, - int column_offset, bool is_embedder_debug_script, - bool is_shared_cross_origin, Handle<Object> source_map_url, - Handle<Context> context, v8::Extension* extension, ScriptData** cached_data, + int column_offset, ScriptOriginOptions resource_options, + Handle<Object> source_map_url, Handle<Context> context, + v8::Extension* extension, ScriptData** cached_data, ScriptCompiler::CompileOptions compile_options, NativesFlag natives, bool is_module) { Isolate* isolate = source->GetIsolate(); @@ -1206,9 +1238,8 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( if (extension == NULL) { // First check per-isolate compilation cache. maybe_result = compilation_cache->LookupScript( - source, script_name, line_offset, column_offset, - is_embedder_debug_script, is_shared_cross_origin, context, - language_mode); + source, script_name, line_offset, column_offset, resource_options, + context, language_mode); if (maybe_result.is_null() && FLAG_serialize_toplevel && compile_options == ScriptCompiler::kConsumeCodeCache && !isolate->debug()->is_loaded()) { @@ -1218,7 +1249,6 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( if (CodeSerializer::Deserialize(isolate, *cached_data, source) .ToHandle(&result)) { // Promote to per-isolate compilation cache. - DCHECK(!result->dont_cache()); compilation_cache->PutScript(source, context, language_mode, result); return result; } @@ -1245,8 +1275,7 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( script->set_line_offset(Smi::FromInt(line_offset)); script->set_column_offset(Smi::FromInt(column_offset)); } - script->set_is_shared_cross_origin(is_shared_cross_origin); - script->set_is_embedder_debug_script(is_embedder_debug_script); + script->set_origin_options(resource_options); if (!source_map_url.is_null()) { script->set_source_mapping_url(*source_map_url); } @@ -1274,7 +1303,7 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( parse_info.set_language_mode( static_cast<LanguageMode>(info.language_mode() | language_mode)); result = CompileToplevel(&info); - if (extension == NULL && !result.is_null() && !result->dont_cache()) { + if (extension == NULL && !result.is_null()) { compilation_cache->PutScript(source, context, language_mode, result); if (FLAG_serialize_toplevel && compile_options == ScriptCompiler::kProduceCodeCache) { @@ -1315,10 +1344,29 @@ Handle<SharedFunctionInfo> Compiler::CompileStreamedScript( } -Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo( +Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( FunctionLiteral* literal, Handle<Script> script, CompilationInfo* outer_info) { // Precondition: code has been parsed and scopes have been analyzed. + Isolate* isolate = outer_info->isolate(); + MaybeHandle<SharedFunctionInfo> maybe_existing; + if (outer_info->is_first_compile()) { + // On the first compile, there are no existing shared function info for + // inner functions yet, so do not try to find them. All bets are off for + // live edit though. + DCHECK(script->FindSharedFunctionInfo(literal).is_null() || + isolate->debug()->live_edit_enabled()); + } else { + maybe_existing = script->FindSharedFunctionInfo(literal); + } + // We found an existing shared function info. If it's already compiled, + // don't worry about compiling it, and simply return it. If it's not yet + // compiled, continue to decide whether to eagerly compile. + Handle<SharedFunctionInfo> existing; + if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) { + return existing; + } + Zone zone; ParseInfo parse_info(&zone, script); CompilationInfo info(&parse_info); @@ -1326,9 +1374,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo( parse_info.set_scope(literal->scope()); parse_info.set_language_mode(literal->scope()->language_mode()); if (outer_info->will_serialize()) info.PrepareForSerializing(); + if (outer_info->is_first_compile()) info.MarkAsFirstCompile(); - Isolate* isolate = info.isolate(); - Factory* factory = isolate->factory(); LiveEditFunctionTracker live_edit_tracker(isolate, literal); // Determine if the function can be lazily compiled. This is necessary to // allow some of our builtin JS files to be lazily compiled. These @@ -1351,9 +1398,11 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo( DCHECK(allow_lazy); } + bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile(); + // Generate code Handle<ScopeInfo> scope_info; - if (FLAG_lazy && allow_lazy && !literal->should_eager_compile()) { + if (lazy) { Handle<Code> code = isolate->builtins()->CompileLazy(); info.SetCode(code); // There's no need in theory for a lazy-compiled function to have a type @@ -1379,57 +1428,82 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo( return Handle<SharedFunctionInfo>::null(); } - // Create a shared function info object. - Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo( - literal->name(), literal->materialized_literal_count(), literal->kind(), - info.code(), scope_info, info.feedback_vector()); - - SharedFunctionInfo::InitFromFunctionLiteral(result, literal); - result->set_script(*script); - result->set_is_toplevel(false); + if (maybe_existing.is_null()) { + // Create a shared function info object. + Handle<SharedFunctionInfo> result = + isolate->factory()->NewSharedFunctionInfo( + literal->name(), literal->materialized_literal_count(), + literal->kind(), info.code(), scope_info, info.feedback_vector()); + + SharedFunctionInfo::InitFromFunctionLiteral(result, literal); + SharedFunctionInfo::SetScript(result, script); + result->set_is_toplevel(false); + // If the outer function has been compiled before, we cannot be sure that + // shared function info for this function literal has been created for the + // first time. It may have already been compiled previously. + result->set_never_compiled(outer_info->is_first_compile() && lazy); + + if (literal->scope()->new_target_var() != nullptr) { + Handle<Code> stub(isolate->builtins()->JSConstructStubNewTarget()); + result->set_construct_stub(*stub); + } - RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); - result->set_allows_lazy_compilation(literal->AllowsLazyCompilation()); - result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx); + RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); + result->set_allows_lazy_compilation(literal->AllowsLazyCompilation()); + result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx); - // Set the expected number of properties for instances and return - // the resulting function. - SetExpectedNofPropertiesFromEstimate(result, - literal->expected_property_count()); - live_edit_tracker.RecordFunctionInfo(result, literal, info.zone()); - return result; + // Set the expected number of properties for instances and return + // the resulting function. + SetExpectedNofPropertiesFromEstimate(result, + literal->expected_property_count()); + live_edit_tracker.RecordFunctionInfo(result, literal, info.zone()); + return result; + } else if (!lazy) { + // We have additional data from compilation now. + DCHECK(!existing->is_compiled()); + existing->ReplaceCode(*info.code()); + existing->set_scope_info(*scope_info); + existing->set_feedback_vector(*info.feedback_vector()); + } + return existing; } MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, Handle<Code> current_code, ConcurrencyMode mode, - BailoutId osr_ast_id) { + BailoutId osr_ast_id, + JavaScriptFrame* osr_frame) { Handle<Code> cached_code; if (GetCodeFromOptimizedCodeMap( function, osr_ast_id).ToHandle(&cached_code)) { + if (FLAG_trace_opt) { + PrintF("[found optimized code for "); + function->ShortPrint(); + if (!osr_ast_id.IsNone()) { + PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); + } + PrintF("]\n"); + } return cached_code; } - SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function)); - Isolate* isolate = info->isolate(); + Isolate* isolate = function->GetIsolate(); DCHECK(AllowCompilation::IsAllowed(isolate)); - VMState<COMPILER> state(isolate); - DCHECK(!isolate->has_pending_exception()); - PostponeInterruptsScope postpone(isolate); - Handle<SharedFunctionInfo> shared = info->shared_info(); - if (shared->code()->kind() != Code::FUNCTION || - ScopeInfo::Empty(isolate) == shared->scope_info()) { + Handle<SharedFunctionInfo> shared(function->shared(), isolate); + if (!shared->is_compiled() || + shared->scope_info() == ScopeInfo::Empty(isolate)) { // The function was never compiled. Compile it unoptimized first. // TODO(titzer): reuse the AST and scope info from this compile. - CompilationInfoWithZone nested(function); - nested.EnableDeoptimizationSupport(); - if (!GetUnoptimizedCodeCommon(&nested).ToHandle(¤t_code)) { + CompilationInfoWithZone unoptimized(function); + unoptimized.EnableDeoptimizationSupport(); + if (!GetUnoptimizedCodeCommon(&unoptimized).ToHandle(¤t_code)) { return MaybeHandle<Code>(); } shared->ReplaceCode(*current_code); } + current_code->set_profiler_ticks(0); // TODO(mstarzinger): We cannot properly deserialize a scope chain containing @@ -1444,6 +1518,11 @@ MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, return MaybeHandle<Code>(); } + SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function)); + VMState<COMPILER> state(isolate); + DCHECK(!isolate->has_pending_exception()); + PostponeInterruptsScope postpone(isolate); + info->SetOptimizing(osr_ast_id, current_code); if (mode == CONCURRENT) { @@ -1452,6 +1531,7 @@ MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, return isolate->builtins()->InOptimizationQueue(); } } else { + info->set_osr_frame(osr_frame); if (GetOptimizedCodeNow(info.get())) return info->code(); } @@ -1487,8 +1567,8 @@ Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) { job->RetryOptimization(kDebuggerHasBreakPoints); } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) { RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared); - if (info->shared_info()->SearchOptimizedCodeMap( - info->context()->native_context(), info->osr_ast_id()) == -1) { + if (shared->SearchOptimizedCodeMap(info->context()->native_context(), + info->osr_ast_id()).code == nullptr) { InsertCodeIntoOptimizedCodeMap(info.get()); } if (FLAG_trace_opt) { @@ -1556,4 +1636,5 @@ void CompilationInfo::PrintAstForTesting() { PrettyPrinter(isolate(), zone()).PrintProgram(function())); } #endif -} } // namespace v8::internal +} // namespace internal +} // namespace v8 |