OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/compiler.h" | 5 #include "vm/compiler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 | 8 |
9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
10 #include "vm/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 368 |
369 // Return false if bailed out. | 369 // Return false if bailed out. |
370 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, | 370 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
371 ParsedFunction* parsed_function, | 371 ParsedFunction* parsed_function, |
372 bool optimized, | 372 bool optimized, |
373 intptr_t osr_id) { | 373 intptr_t osr_id) { |
374 const Function& function = parsed_function->function(); | 374 const Function& function = parsed_function->function(); |
375 if (optimized && !function.IsOptimizable()) { | 375 if (optimized && !function.IsOptimizable()) { |
376 return false; | 376 return false; |
377 } | 377 } |
378 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | |
379 bool is_compiled = false; | 378 bool is_compiled = false; |
380 Thread* const thread = Thread::Current(); | 379 Thread* const thread = Thread::Current(); |
381 Zone* const zone = thread->zone(); | 380 Zone* const zone = thread->zone(); |
382 Isolate* const isolate = thread->isolate(); | 381 Isolate* const isolate = thread->isolate(); |
| 382 CSTAT_TIMER_SCOPE(isolate, codegen_timer); |
383 HANDLESCOPE(isolate); | 383 HANDLESCOPE(isolate); |
384 | 384 |
385 // We may reattempt compilation if the function needs to be assembled using | 385 // We may reattempt compilation if the function needs to be assembled using |
386 // far branches on ARM and MIPS. In the else branch of the setjmp call, | 386 // far branches on ARM and MIPS. In the else branch of the setjmp call, |
387 // done is set to false, and use_far_branches is set to true if there is a | 387 // done is set to false, and use_far_branches is set to true if there is a |
388 // longjmp from the ARM or MIPS assemblers. In all other paths through this | 388 // longjmp from the ARM or MIPS assemblers. In all other paths through this |
389 // while loop, done is set to true. use_far_branches is always false on ia32 | 389 // while loop, done is set to true. use_far_branches is always false on ia32 |
390 // and x64. | 390 // and x64. |
391 bool done = false; | 391 bool done = false; |
392 // volatile because the variable may be clobbered by a longjmp. | 392 // volatile because the variable may be clobbered by a longjmp. |
393 volatile bool use_far_branches = false; | 393 volatile bool use_far_branches = false; |
394 while (!done) { | 394 while (!done) { |
395 const intptr_t prev_deopt_id = isolate->deopt_id(); | 395 const intptr_t prev_deopt_id = isolate->deopt_id(); |
396 isolate->set_deopt_id(0); | 396 isolate->set_deopt_id(0); |
397 LongJumpScope jump; | 397 LongJumpScope jump; |
398 if (setjmp(*jump.Set()) == 0) { | 398 if (setjmp(*jump.Set()) == 0) { |
399 FlowGraph* flow_graph = NULL; | 399 FlowGraph* flow_graph = NULL; |
400 | 400 |
401 // Class hierarchy analysis is registered with the isolate in the | 401 // Class hierarchy analysis is registered with the isolate in the |
402 // constructor and unregisters itself upon destruction. | 402 // constructor and unregisters itself upon destruction. |
403 CHA cha(thread); | 403 CHA cha(thread); |
404 | 404 |
405 // TimerScope needs an isolate to be properly terminated in case of a | 405 // TimerScope needs an isolate to be properly terminated in case of a |
406 // LongJump. | 406 // LongJump. |
407 { | 407 { |
408 TimerScope timer(FLAG_compiler_stats, | 408 CSTAT_TIMER_SCOPE(isolate, graphbuilder_timer); |
409 &CompilerStats::graphbuilder_timer, | |
410 isolate); | |
411 ZoneGrowableArray<const ICData*>* ic_data_array = | 409 ZoneGrowableArray<const ICData*>* ic_data_array = |
412 new(zone) ZoneGrowableArray<const ICData*>(); | 410 new(zone) ZoneGrowableArray<const ICData*>(); |
413 if (optimized) { | 411 if (optimized) { |
414 ASSERT(function.HasCode()); | 412 ASSERT(function.HasCode()); |
415 // Extract type feedback before the graph is built, as the graph | 413 // Extract type feedback before the graph is built, as the graph |
416 // builder uses it to attach it to nodes. | 414 // builder uses it to attach it to nodes. |
417 ASSERT(function.deoptimization_counter() < | 415 ASSERT(function.deoptimization_counter() < |
418 FLAG_deoptimization_counter_threshold); | 416 FLAG_deoptimization_counter_threshold); |
419 function.RestoreICDataMap(ic_data_array); | 417 function.RestoreICDataMap(ic_data_array); |
420 if (FLAG_print_ic_data_map) { | 418 if (FLAG_print_ic_data_map) { |
(...skipping 26 matching lines...) Expand all Loading... |
447 } | 445 } |
448 | 446 |
449 BlockScheduler block_scheduler(flow_graph); | 447 BlockScheduler block_scheduler(flow_graph); |
450 const bool reorder_blocks = | 448 const bool reorder_blocks = |
451 FlowGraph::ShouldReorderBlocks(function, optimized); | 449 FlowGraph::ShouldReorderBlocks(function, optimized); |
452 if (reorder_blocks) { | 450 if (reorder_blocks) { |
453 block_scheduler.AssignEdgeWeights(); | 451 block_scheduler.AssignEdgeWeights(); |
454 } | 452 } |
455 | 453 |
456 if (optimized) { | 454 if (optimized) { |
457 TimerScope timer(FLAG_compiler_stats, | 455 CSTAT_TIMER_SCOPE(isolate, ssa_timer); |
458 &CompilerStats::ssa_timer, | |
459 isolate); | |
460 // Transform to SSA (virtual register 0 and no inlining arguments). | 456 // Transform to SSA (virtual register 0 and no inlining arguments). |
461 flow_graph->ComputeSSA(0, NULL); | 457 flow_graph->ComputeSSA(0, NULL); |
462 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 458 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
463 if (print_flow_graph) { | 459 if (print_flow_graph) { |
464 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 460 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
465 } | 461 } |
466 } | 462 } |
467 | 463 |
468 // Maps inline_id_to_function[inline_id] -> function. Top scope | 464 // Maps inline_id_to_function[inline_id] -> function. Top scope |
469 // function has inline_id 0. The map is populated by the inliner. | 465 // function has inline_id 0. The map is populated by the inliner. |
470 GrowableArray<const Function*> inline_id_to_function; | 466 GrowableArray<const Function*> inline_id_to_function; |
471 // For a given inlining-id(index) specifies the caller's inlining-id. | 467 // For a given inlining-id(index) specifies the caller's inlining-id. |
472 GrowableArray<intptr_t> caller_inline_id; | 468 GrowableArray<intptr_t> caller_inline_id; |
473 // Collect all instance fields that are loaded in the graph and | 469 // Collect all instance fields that are loaded in the graph and |
474 // have non-generic type feedback attached to them that can | 470 // have non-generic type feedback attached to them that can |
475 // potentially affect optimizations. | 471 // potentially affect optimizations. |
476 if (optimized) { | 472 if (optimized) { |
477 inline_id_to_function.Add(&function); | 473 inline_id_to_function.Add(&function); |
478 // Top scope function has no caller (-1). | 474 // Top scope function has no caller (-1). |
479 caller_inline_id.Add(-1); | 475 caller_inline_id.Add(-1); |
480 TimerScope timer(FLAG_compiler_stats, | 476 CSTAT_TIMER_SCOPE(isolate, graphoptimizer_timer); |
481 &CompilerStats::graphoptimizer_timer, | |
482 isolate); | |
483 | 477 |
484 FlowGraphOptimizer optimizer(flow_graph); | 478 FlowGraphOptimizer optimizer(flow_graph); |
485 optimizer.ApplyICData(); | 479 optimizer.ApplyICData(); |
486 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 480 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
487 | 481 |
488 // Optimize (a << b) & c patterns, merge operations. | 482 // Optimize (a << b) & c patterns, merge operations. |
489 // Run early in order to have more opportunity to optimize left shifts. | 483 // Run early in order to have more opportunity to optimize left shifts. |
490 optimizer.TryOptimizePatterns(); | 484 optimizer.TryOptimizePatterns(); |
491 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 485 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
492 | 486 |
493 FlowGraphInliner::SetInliningId(flow_graph, 0); | 487 FlowGraphInliner::SetInliningId(flow_graph, 0); |
494 | 488 |
495 // Inlining (mutates the flow graph) | 489 // Inlining (mutates the flow graph) |
496 if (FLAG_use_inlining) { | 490 if (FLAG_use_inlining) { |
497 TimerScope timer(FLAG_compiler_stats, | 491 CSTAT_TIMER_SCOPE(isolate, graphinliner_timer); |
498 &CompilerStats::graphinliner_timer); | |
499 // Propagate types to create more inlining opportunities. | 492 // Propagate types to create more inlining opportunities. |
500 FlowGraphTypePropagator::Propagate(flow_graph); | 493 FlowGraphTypePropagator::Propagate(flow_graph); |
501 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 494 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
502 | 495 |
503 // Use propagated class-ids to create more inlining opportunities. | 496 // Use propagated class-ids to create more inlining opportunities. |
504 optimizer.ApplyClassIds(); | 497 optimizer.ApplyClassIds(); |
505 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 498 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
506 | 499 |
507 FlowGraphInliner inliner(flow_graph, | 500 FlowGraphInliner inliner(flow_graph, |
508 &inline_id_to_function, | 501 &inline_id_to_function, |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 } | 695 } |
703 } | 696 } |
704 | 697 |
705 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); | 698 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
706 Assembler assembler(use_far_branches); | 699 Assembler assembler(use_far_branches); |
707 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 700 FlowGraphCompiler graph_compiler(&assembler, flow_graph, |
708 *parsed_function, optimized, | 701 *parsed_function, optimized, |
709 inline_id_to_function, | 702 inline_id_to_function, |
710 caller_inline_id); | 703 caller_inline_id); |
711 { | 704 { |
712 TimerScope timer(FLAG_compiler_stats, | 705 CSTAT_TIMER_SCOPE(isolate, graphcompiler_timer); |
713 &CompilerStats::graphcompiler_timer, | |
714 isolate); | |
715 graph_compiler.CompileGraph(); | 706 graph_compiler.CompileGraph(); |
716 pipeline->FinalizeCompilation(); | 707 pipeline->FinalizeCompilation(); |
717 } | 708 } |
718 { | 709 { |
719 TimerScope timer(FLAG_compiler_stats, | 710 CSTAT_TIMER_SCOPE(isolate, codefinalizer_timer); |
720 &CompilerStats::codefinalizer_timer, | |
721 isolate); | |
722 // CreateDeoptInfo uses the object pool and needs to be done before | 711 // CreateDeoptInfo uses the object pool and needs to be done before |
723 // FinalizeCode. | 712 // FinalizeCode. |
724 const Array& deopt_info_array = Array::Handle( | 713 const Array& deopt_info_array = |
725 graph_compiler.CreateDeoptInfo(&assembler)); | 714 Array::Handle(isolate, graph_compiler.CreateDeoptInfo(&assembler)); |
| 715 INC_STAT(isolate, total_code_size, |
| 716 deopt_info_array.Length() * sizeof(uword)); |
726 const Code& code = Code::Handle( | 717 const Code& code = Code::Handle( |
727 Code::FinalizeCode(function, &assembler, optimized)); | 718 Code::FinalizeCode(function, &assembler, optimized)); |
728 code.set_is_optimized(optimized); | 719 code.set_is_optimized(optimized); |
729 code.set_inlined_intervals(graph_compiler.inlined_code_intervals()); | 720 |
730 code.set_inlined_id_to_function( | 721 const Array& intervals = graph_compiler.inlined_code_intervals(); |
731 Array::Handle(graph_compiler.InliningIdToFunction())); | 722 INC_STAT(isolate, total_code_size, |
| 723 intervals.Length() * sizeof(uword)); |
| 724 code.set_inlined_intervals(intervals); |
| 725 |
| 726 const Array& inlined_id_array = |
| 727 Array::Handle(isolate, graph_compiler.InliningIdToFunction()); |
| 728 INC_STAT(isolate, total_code_size, |
| 729 inlined_id_array.Length() * sizeof(uword)); |
| 730 code.set_inlined_id_to_function(inlined_id_array); |
| 731 |
732 graph_compiler.FinalizePcDescriptors(code); | 732 graph_compiler.FinalizePcDescriptors(code); |
733 code.set_deopt_info_array(deopt_info_array); | 733 code.set_deopt_info_array(deopt_info_array); |
| 734 |
734 graph_compiler.FinalizeStackmaps(code); | 735 graph_compiler.FinalizeStackmaps(code); |
735 graph_compiler.FinalizeVarDescriptors(code); | 736 graph_compiler.FinalizeVarDescriptors(code); |
736 graph_compiler.FinalizeExceptionHandlers(code); | 737 graph_compiler.FinalizeExceptionHandlers(code); |
737 graph_compiler.FinalizeStaticCallTargetsTable(code); | 738 graph_compiler.FinalizeStaticCallTargetsTable(code); |
738 | 739 |
739 if (optimized) { | 740 if (optimized) { |
740 if (osr_id == Isolate::kNoDeoptId) { | 741 if (osr_id == Isolate::kNoDeoptId) { |
741 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); | 742 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); |
742 if (FLAG_trace_compiler || FLAG_trace_patching) { | 743 if (FLAG_trace_compiler || FLAG_trace_patching) { |
743 if (FLAG_trace_compiler) { | 744 if (FLAG_trace_compiler) { |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1305 const Object& result = | 1306 const Object& result = |
1306 PassiveObject::Handle(isolate->object_store()->sticky_error()); | 1307 PassiveObject::Handle(isolate->object_store()->sticky_error()); |
1307 isolate->object_store()->clear_sticky_error(); | 1308 isolate->object_store()->clear_sticky_error(); |
1308 return result.raw(); | 1309 return result.raw(); |
1309 } | 1310 } |
1310 UNREACHABLE(); | 1311 UNREACHABLE(); |
1311 return Object::null(); | 1312 return Object::null(); |
1312 } | 1313 } |
1313 | 1314 |
1314 } // namespace dart | 1315 } // namespace dart |
OLD | NEW |