OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler.h" | 5 #include "src/compiler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "src/asmjs/asm-js.h" | 10 #include "src/asmjs/asm-js.h" |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 } | 298 } |
299 | 299 |
300 // It's very important that recompiles do not alter the structure of the type | 300 // It's very important that recompiles do not alter the structure of the type |
301 // feedback vector. Verify that the structure fits the function literal. | 301 // feedback vector. Verify that the structure fits the function literal. |
302 CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom( | 302 CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom( |
303 info->literal()->feedback_vector_spec())); | 303 info->literal()->feedback_vector_spec())); |
304 } | 304 } |
305 | 305 |
306 bool UseTurboFan(Handle<SharedFunctionInfo> shared) { | 306 bool UseTurboFan(Handle<SharedFunctionInfo> shared) { |
307 bool optimization_disabled = shared->optimization_disabled(); | 307 bool optimization_disabled = shared->optimization_disabled(); |
308 bool dont_crankshaft = shared->dont_crankshaft(); | 308 bool must_use_ignition_turbo = shared->must_use_ignition_turbo(); |
309 | 309 |
310 // Check the enabling conditions for Turbofan. | 310 // Check the enabling conditions for Turbofan. |
311 // 1. "use asm" code. | 311 // 1. "use asm" code. |
312 bool is_turbofanable_asm = | 312 bool is_turbofanable_asm = |
313 FLAG_turbo_asm && shared->asm_function() && !optimization_disabled; | 313 FLAG_turbo_asm && shared->asm_function() && !optimization_disabled; |
314 | 314 |
315 // 2. Fallback for features unsupported by Crankshaft. | 315 // 2. Fallback for features unsupported by Crankshaft. |
316 bool is_unsupported_by_crankshaft_but_turbofanable = | 316 bool is_unsupported_by_crankshaft_but_turbofanable = |
317 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && | 317 must_use_ignition_turbo && strcmp(FLAG_turbo_filter, "~~") == 0 && |
318 !optimization_disabled; | 318 !optimization_disabled; |
319 | 319 |
320 // 3. Explicitly enabled by the command-line filter. | 320 // 3. Explicitly enabled by the command-line filter. |
321 bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter); | 321 bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter); |
322 | 322 |
323 return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable || | 323 return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable || |
324 passes_turbo_filter; | 324 passes_turbo_filter; |
325 } | 325 } |
326 | 326 |
327 bool ShouldUseIgnition(CompilationInfo* info) { | 327 bool ShouldUseIgnition(CompilationInfo* info) { |
328 DCHECK(info->has_shared_info()); | 328 DCHECK(info->has_shared_info()); |
329 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
330 | |
331 // Code which can't be supported by the old pipeline should use Ignition. | |
332 if (shared->must_use_ignition_turbo()) return true; | |
329 | 333 |
330 // Resumable functions are not supported by {FullCodeGenerator}, suspended | 334 // Resumable functions are not supported by {FullCodeGenerator}, suspended |
331 // activations stored as {JSGeneratorObject} on the heap always assume the | 335 // activations stored as {JSGeneratorObject} on the heap always assume the |
332 // underlying code to be based on the bytecode array. | 336 // underlying code to be based on the bytecode array. |
333 // TODO(mstarzinger): Once we want to deprecate even more support from the | 337 DCHECK(!IsResumableFunction(shared->kind())); |
334 // {FullCodeGenerator}, we will compute an appropriate bit in {AstNumbering} | |
335 // and turn this predicate into a DCHECK instead. | |
336 if (IsResumableFunction(info->shared_info()->kind())) { | |
337 return true; | |
338 } | |
339 | 338 |
340 // Skip Ignition for asm.js functions. | 339 // Skip Ignition for asm.js functions. |
341 if (info->shared_info()->asm_function()) { | 340 if (shared->asm_function()) return false; |
341 | |
342 // Skip Ignition for asm wasm code. | |
343 if (FLAG_validate_asm && shared->HasAsmWasmData()) { | |
342 return false; | 344 return false; |
343 } | 345 } |
344 | 346 |
345 // When requesting debug code as a replacement for existing code, we provide | 347 // When requesting debug code as a replacement for existing code, we provide |
346 // the same kind as the existing code (to prevent implicit tier-change). | 348 // the same kind as the existing code (to prevent implicit tier-change). |
347 if (info->is_debug() && info->shared_info()->is_compiled()) { | 349 if (info->is_debug() && shared->is_compiled()) { |
348 return !info->shared_info()->HasBaselineCode(); | 350 return !shared->HasBaselineCode(); |
349 } | 351 } |
350 | 352 |
351 // Code destined for TurboFan should be compiled with Ignition first. | 353 // Code destined for TurboFan should be compiled with Ignition first. |
352 if (UseTurboFan(info->shared_info())) return true; | 354 if (UseTurboFan(shared)) return true; |
353 | 355 |
354 // Only use Ignition for any other function if FLAG_ignition is true. | 356 // Only use Ignition for any other function if FLAG_ignition is true. |
355 if (!FLAG_ignition) return false; | 357 if (!FLAG_ignition) return false; |
356 | 358 |
357 // Checks whether top level functions should be passed by the filter. | 359 // Checks whether top level functions should be passed by the filter. |
358 if (info->shared_info()->is_toplevel()) { | 360 if (shared->is_toplevel()) { |
359 Vector<const char> filter = CStrVector(FLAG_ignition_filter); | 361 Vector<const char> filter = CStrVector(FLAG_ignition_filter); |
360 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | 362 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); |
361 } | 363 } |
362 | 364 |
363 // Finally respect the filter. | 365 // Finally respect the filter. |
364 return info->shared_info()->PassesFilter(FLAG_ignition_filter); | 366 return shared->PassesFilter(FLAG_ignition_filter); |
365 } | 367 } |
366 | 368 |
367 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { | 369 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { |
368 // Function should have been parsed and analyzed before creating a compilation | 370 // Function should have been parsed and analyzed before creating a compilation |
369 // job. | 371 // job. |
370 DCHECK_NOT_NULL(info->literal()); | 372 DCHECK_NOT_NULL(info->literal()); |
371 DCHECK_NOT_NULL(info->scope()); | 373 DCHECK_NOT_NULL(info->scope()); |
372 | 374 |
373 EnsureFeedbackMetadata(info); | 375 EnsureFeedbackMetadata(info); |
374 if (ShouldUseIgnition(info)) { | 376 if (ShouldUseIgnition(info)) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 parse_info->literal())) { | 522 parse_info->literal())) { |
521 return false; | 523 return false; |
522 } | 524 } |
523 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); | 525 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); |
524 if (!shared_info.is_null()) { | 526 if (!shared_info.is_null()) { |
525 FunctionLiteral* lit = parse_info->literal(); | 527 FunctionLiteral* lit = parse_info->literal(); |
526 shared_info->set_ast_node_count(lit->ast_node_count()); | 528 shared_info->set_ast_node_count(lit->ast_node_count()); |
527 if (lit->dont_optimize_reason() != kNoReason) { | 529 if (lit->dont_optimize_reason() != kNoReason) { |
528 shared_info->DisableOptimization(lit->dont_optimize_reason()); | 530 shared_info->DisableOptimization(lit->dont_optimize_reason()); |
529 } | 531 } |
530 if (lit->flags() & AstProperties::kDontCrankshaft) { | 532 if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { |
531 shared_info->set_dont_crankshaft(true); | 533 shared_info->set_must_use_ignition_turbo(true); |
532 } | 534 } |
533 } | 535 } |
534 return true; | 536 return true; |
535 } | 537 } |
536 | 538 |
537 bool GetOptimizedCodeNow(CompilationJob* job) { | 539 bool GetOptimizedCodeNow(CompilationJob* job) { |
538 CompilationInfo* info = job->info(); | 540 CompilationInfo* info = job->info(); |
539 Isolate* isolate = info->isolate(); | 541 Isolate* isolate = info->isolate(); |
540 | 542 |
541 // Parsing is not required when optimizing from existing bytecode. | 543 // Parsing is not required when optimizing from existing bytecode. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
643 function->ShortPrint(); | 645 function->ShortPrint(); |
644 if (!osr_ast_id.IsNone()) { | 646 if (!osr_ast_id.IsNone()) { |
645 PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); | 647 PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); |
646 } | 648 } |
647 PrintF("]\n"); | 649 PrintF("]\n"); |
648 } | 650 } |
649 return cached_code; | 651 return cached_code; |
650 } | 652 } |
651 | 653 |
652 // Reset profiler ticks, function is no longer considered hot. | 654 // Reset profiler ticks, function is no longer considered hot. |
655 DCHECK(shared->is_compiled()); | |
653 if (shared->HasBaselineCode()) { | 656 if (shared->HasBaselineCode()) { |
654 shared->code()->set_profiler_ticks(0); | 657 shared->code()->set_profiler_ticks(0); |
655 } else if (shared->HasBytecodeArray()) { | 658 } else if (shared->HasBytecodeArray()) { |
656 shared->set_profiler_ticks(0); | 659 shared->set_profiler_ticks(0); |
657 } | 660 } |
658 | 661 |
659 VMState<COMPILER> state(isolate); | 662 VMState<COMPILER> state(isolate); |
660 DCHECK(!isolate->has_pending_exception()); | 663 DCHECK(!isolate->has_pending_exception()); |
661 PostponeInterruptsScope postpone(isolate); | 664 PostponeInterruptsScope postpone(isolate); |
662 bool use_turbofan = UseTurboFan(shared) || ignition_osr; | 665 bool use_turbofan = UseTurboFan(shared) || ignition_osr; |
(...skipping 19 matching lines...) Expand all Loading... | |
682 return MaybeHandle<Code>(); | 685 return MaybeHandle<Code>(); |
683 } | 686 } |
684 | 687 |
685 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); | 688 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); |
686 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode); | 689 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode); |
687 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode"); | 690 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode"); |
688 | 691 |
689 // TurboFan can optimize directly from existing bytecode. | 692 // TurboFan can optimize directly from existing bytecode. |
690 if (use_turbofan && ShouldUseIgnition(info)) { | 693 if (use_turbofan && ShouldUseIgnition(info)) { |
691 if (info->is_osr() && !ignition_osr) return MaybeHandle<Code>(); | 694 if (info->is_osr() && !ignition_osr) return MaybeHandle<Code>(); |
692 if (!Compiler::EnsureBytecode(info)) { | 695 DCHECK(shared->HasBytecodeArray()); |
693 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | |
694 return MaybeHandle<Code>(); | |
695 } | |
696 info->MarkAsOptimizeFromBytecode(); | 696 info->MarkAsOptimizeFromBytecode(); |
697 } | 697 } |
698 | 698 |
699 // Verify that OSR compilations are delegated to the correct graph builder. | 699 // Verify that OSR compilations are delegated to the correct graph builder. |
700 // Depending on the underlying frame the semantics of the {BailoutId} differ | 700 // Depending on the underlying frame the semantics of the {BailoutId} differ |
701 // and the various graph builders hard-code a certain semantic: | 701 // and the various graph builders hard-code a certain semantic: |
702 // - Interpreter : The BailoutId represents a bytecode offset. | 702 // - Interpreter : The BailoutId represents a bytecode offset. |
703 // - FullCodegen : The BailoutId represents the id of an AST node. | 703 // - FullCodegen : The BailoutId represents the id of an AST node. |
704 DCHECK_IMPLIES(info->is_osr() && ignition_osr, | 704 DCHECK_IMPLIES(info->is_osr() && ignition_osr, |
705 info->is_optimizing_from_bytecode()); | 705 info->is_optimizing_from_bytecode()); |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1187 | 1187 |
1188 // Restore the original function info list in order to remain side-effect | 1188 // Restore the original function info list in order to remain side-effect |
1189 // free as much as possible, since some code expects the old shared function | 1189 // free as much as possible, since some code expects the old shared function |
1190 // infos to stick around. | 1190 // infos to stick around. |
1191 script->set_shared_function_infos(*old_function_infos); | 1191 script->set_shared_function_infos(*old_function_infos); |
1192 | 1192 |
1193 return infos; | 1193 return infos; |
1194 } | 1194 } |
1195 | 1195 |
1196 bool Compiler::EnsureBytecode(CompilationInfo* info) { | 1196 bool Compiler::EnsureBytecode(CompilationInfo* info) { |
1197 if (!ShouldUseIgnition(info)) return false; | 1197 if (!info->shared_info()->is_compiled()) { |
1198 if (!info->shared_info()->HasBytecodeArray()) { | |
1199 Handle<Code> original_code(info->shared_info()->code()); | |
1200 if (GetUnoptimizedCode(info).is_null()) return false; | 1198 if (GetUnoptimizedCode(info).is_null()) return false; |
1201 if (info->shared_info()->HasAsmWasmData()) return false; | 1199 if (info->shared_info()->HasAsmWasmData()) return false; |
1202 DCHECK(info->shared_info()->is_compiled()); | 1200 DCHECK(info->shared_info()->is_compiled()); |
1203 if (original_code->kind() == Code::FUNCTION) { | |
1204 // Generating bytecode will install the {InterpreterEntryTrampoline} as | |
1205 // shared code on the function. To avoid an implicit tier down we restore | |
1206 // original baseline code in case it existed beforehand. | |
1207 info->shared_info()->ReplaceCode(*original_code); | |
1208 } | |
1209 } | 1201 } |
1210 DCHECK(info->shared_info()->HasBytecodeArray()); | 1202 DCHECK_EQ(ShouldUseIgnition(info), info->shared_info()->HasBytecodeArray()); |
1211 return true; | 1203 return info->shared_info()->HasBytecodeArray(); |
1212 } | 1204 } |
1213 | 1205 |
1214 // TODO(turbofan): In the future, unoptimized code with deopt support could | 1206 // TODO(turbofan): In the future, unoptimized code with deopt support could |
1215 // be generated lazily once deopt is triggered. | 1207 // be generated lazily once deopt is triggered. |
1216 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { | 1208 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
1217 DCHECK_NOT_NULL(info->literal()); | 1209 DCHECK_NOT_NULL(info->literal()); |
1218 DCHECK_NOT_NULL(info->scope()); | 1210 DCHECK_NOT_NULL(info->scope()); |
1219 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1211 Handle<SharedFunctionInfo> shared = info->shared_info(); |
1220 if (!shared->has_deoptimization_support()) { | 1212 if (!shared->has_deoptimization_support()) { |
1221 Zone zone(info->isolate()->allocator(), ZONE_NAME); | 1213 Zone zone(info->isolate()->allocator(), ZONE_NAME); |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1707 return true; | 1699 return true; |
1708 } | 1700 } |
1709 return false; | 1701 return false; |
1710 } | 1702 } |
1711 } | 1703 } |
1712 | 1704 |
1713 void Compiler::PostInstantiation(Handle<JSFunction> function, | 1705 void Compiler::PostInstantiation(Handle<JSFunction> function, |
1714 PretenureFlag pretenure) { | 1706 PretenureFlag pretenure) { |
1715 Handle<SharedFunctionInfo> shared(function->shared()); | 1707 Handle<SharedFunctionInfo> shared(function->shared()); |
1716 | 1708 |
1717 if (FLAG_always_opt && shared->allows_lazy_compilation()) { | 1709 if (FLAG_always_opt && shared->allows_lazy_compilation() && |
1710 function->shared()->is_compiled()) { | |
rmcilroy
2016/11/22 14:03:44
With this change we only mark for optimization if
Michael Starzinger
2016/11/22 14:53:50
Acknowledged. I thought about this for a little bi
rmcilroy
2016/11/22 17:24:02
Acknowledged.
| |
1718 function->MarkForOptimization(); | 1711 function->MarkForOptimization(); |
1719 } | 1712 } |
1720 | 1713 |
1721 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( | 1714 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( |
1722 function->context()->native_context(), BailoutId::None()); | 1715 function->context()->native_context(), BailoutId::None()); |
1723 if (cached.code != nullptr) { | 1716 if (cached.code != nullptr) { |
1724 // Caching of optimized code enabled and optimized code found. | 1717 // Caching of optimized code enabled and optimized code found. |
1725 DCHECK(!cached.code->marked_for_deoptimization()); | 1718 DCHECK(!cached.code->marked_for_deoptimization()); |
1726 DCHECK(function->shared()->is_compiled()); | 1719 DCHECK(function->shared()->is_compiled()); |
1727 function->ReplaceCode(cached.code); | 1720 function->ReplaceCode(cached.code); |
1728 } | 1721 } |
1729 | 1722 |
1730 if (cached.literals != nullptr) { | 1723 if (cached.literals != nullptr) { |
1731 DCHECK(shared->is_compiled()); | 1724 DCHECK(shared->is_compiled()); |
1732 function->set_literals(cached.literals); | 1725 function->set_literals(cached.literals); |
1733 } else if (shared->is_compiled()) { | 1726 } else if (shared->is_compiled()) { |
1734 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1727 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1735 JSFunction::EnsureLiterals(function); | 1728 JSFunction::EnsureLiterals(function); |
1736 } | 1729 } |
1737 } | 1730 } |
1738 | 1731 |
1739 } // namespace internal | 1732 } // namespace internal |
1740 } // namespace v8 | 1733 } // namespace v8 |
OLD | NEW |