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); | 378 TimerScope timer(FLAG_compiler_stats, &CSTAT_TIMER(codegen_timer)); |
379 bool is_compiled = false; | 379 bool is_compiled = false; |
380 Thread* const thread = Thread::Current(); | 380 Thread* const thread = Thread::Current(); |
381 Zone* const zone = thread->zone(); | 381 Zone* const zone = thread->zone(); |
382 Isolate* const isolate = thread->isolate(); | 382 Isolate* const isolate = thread->isolate(); |
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 |
(...skipping 10 matching lines...) Expand all Loading... |
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 TimerScope timer(FLAG_compiler_stats, |
409 &CompilerStats::graphbuilder_timer, | 409 &CSTAT_TIMER(graphbuilder_timer), |
410 isolate); | 410 isolate); |
411 ZoneGrowableArray<const ICData*>* ic_data_array = | 411 ZoneGrowableArray<const ICData*>* ic_data_array = |
412 new(zone) ZoneGrowableArray<const ICData*>(); | 412 new(zone) ZoneGrowableArray<const ICData*>(); |
413 if (optimized) { | 413 if (optimized) { |
414 ASSERT(function.HasCode()); | 414 ASSERT(function.HasCode()); |
415 // Extract type feedback before the graph is built, as the graph | 415 // Extract type feedback before the graph is built, as the graph |
416 // builder uses it to attach it to nodes. | 416 // builder uses it to attach it to nodes. |
417 ASSERT(function.deoptimization_counter() < | 417 ASSERT(function.deoptimization_counter() < |
418 FLAG_deoptimization_counter_threshold); | 418 FLAG_deoptimization_counter_threshold); |
419 function.RestoreICDataMap(ic_data_array); | 419 function.RestoreICDataMap(ic_data_array); |
(...skipping 28 matching lines...) Expand all Loading... |
448 | 448 |
449 BlockScheduler block_scheduler(flow_graph); | 449 BlockScheduler block_scheduler(flow_graph); |
450 const bool reorder_blocks = | 450 const bool reorder_blocks = |
451 FlowGraph::ShouldReorderBlocks(function, optimized); | 451 FlowGraph::ShouldReorderBlocks(function, optimized); |
452 if (reorder_blocks) { | 452 if (reorder_blocks) { |
453 block_scheduler.AssignEdgeWeights(); | 453 block_scheduler.AssignEdgeWeights(); |
454 } | 454 } |
455 | 455 |
456 if (optimized) { | 456 if (optimized) { |
457 TimerScope timer(FLAG_compiler_stats, | 457 TimerScope timer(FLAG_compiler_stats, |
458 &CompilerStats::ssa_timer, | 458 &CSTAT_TIMER(ssa_timer), |
459 isolate); | 459 isolate); |
460 // Transform to SSA (virtual register 0 and no inlining arguments). | 460 // Transform to SSA (virtual register 0 and no inlining arguments). |
461 flow_graph->ComputeSSA(0, NULL); | 461 flow_graph->ComputeSSA(0, NULL); |
462 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 462 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
463 if (print_flow_graph) { | 463 if (print_flow_graph) { |
464 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 464 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
465 } | 465 } |
466 } | 466 } |
467 | 467 |
468 // Maps inline_id_to_function[inline_id] -> function. Top scope | 468 // Maps inline_id_to_function[inline_id] -> function. Top scope |
469 // function has inline_id 0. The map is populated by the inliner. | 469 // function has inline_id 0. The map is populated by the inliner. |
470 GrowableArray<const Function*> inline_id_to_function; | 470 GrowableArray<const Function*> inline_id_to_function; |
471 // For a given inlining-id(index) specifies the caller's inlining-id. | 471 // For a given inlining-id(index) specifies the caller's inlining-id. |
472 GrowableArray<intptr_t> caller_inline_id; | 472 GrowableArray<intptr_t> caller_inline_id; |
473 // Collect all instance fields that are loaded in the graph and | 473 // Collect all instance fields that are loaded in the graph and |
474 // have non-generic type feedback attached to them that can | 474 // have non-generic type feedback attached to them that can |
475 // potentially affect optimizations. | 475 // potentially affect optimizations. |
476 if (optimized) { | 476 if (optimized) { |
477 inline_id_to_function.Add(&function); | 477 inline_id_to_function.Add(&function); |
478 // Top scope function has no caller (-1). | 478 // Top scope function has no caller (-1). |
479 caller_inline_id.Add(-1); | 479 caller_inline_id.Add(-1); |
480 TimerScope timer(FLAG_compiler_stats, | 480 TimerScope timer(FLAG_compiler_stats, |
481 &CompilerStats::graphoptimizer_timer, | 481 &CSTAT_TIMER(graphoptimizer_timer), |
482 isolate); | 482 isolate); |
483 | 483 |
484 FlowGraphOptimizer optimizer(flow_graph); | 484 FlowGraphOptimizer optimizer(flow_graph); |
485 optimizer.ApplyICData(); | 485 optimizer.ApplyICData(); |
486 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 486 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
487 | 487 |
488 // Optimize (a << b) & c patterns, merge operations. | 488 // Optimize (a << b) & c patterns, merge operations. |
489 // Run early in order to have more opportunity to optimize left shifts. | 489 // Run early in order to have more opportunity to optimize left shifts. |
490 optimizer.TryOptimizePatterns(); | 490 optimizer.TryOptimizePatterns(); |
491 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 491 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
492 | 492 |
493 FlowGraphInliner::SetInliningId(flow_graph, 0); | 493 FlowGraphInliner::SetInliningId(flow_graph, 0); |
494 | 494 |
495 // Inlining (mutates the flow graph) | 495 // Inlining (mutates the flow graph) |
496 if (FLAG_use_inlining) { | 496 if (FLAG_use_inlining) { |
497 TimerScope timer(FLAG_compiler_stats, | 497 TimerScope timer(FLAG_compiler_stats, |
498 &CompilerStats::graphinliner_timer); | 498 &CSTAT_TIMER(graphinliner_timer)); |
499 // Propagate types to create more inlining opportunities. | 499 // Propagate types to create more inlining opportunities. |
500 FlowGraphTypePropagator::Propagate(flow_graph); | 500 FlowGraphTypePropagator::Propagate(flow_graph); |
501 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 501 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
502 | 502 |
503 // Use propagated class-ids to create more inlining opportunities. | 503 // Use propagated class-ids to create more inlining opportunities. |
504 optimizer.ApplyClassIds(); | 504 optimizer.ApplyClassIds(); |
505 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 505 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
506 | 506 |
507 FlowGraphInliner inliner(flow_graph, | 507 FlowGraphInliner inliner(flow_graph, |
508 &inline_id_to_function, | 508 &inline_id_to_function, |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 } | 703 } |
704 | 704 |
705 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); | 705 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
706 Assembler assembler(use_far_branches); | 706 Assembler assembler(use_far_branches); |
707 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 707 FlowGraphCompiler graph_compiler(&assembler, flow_graph, |
708 *parsed_function, optimized, | 708 *parsed_function, optimized, |
709 inline_id_to_function, | 709 inline_id_to_function, |
710 caller_inline_id); | 710 caller_inline_id); |
711 { | 711 { |
712 TimerScope timer(FLAG_compiler_stats, | 712 TimerScope timer(FLAG_compiler_stats, |
713 &CompilerStats::graphcompiler_timer, | 713 &CSTAT_TIMER(graphcompiler_timer), |
714 isolate); | 714 isolate); |
715 graph_compiler.CompileGraph(); | 715 graph_compiler.CompileGraph(); |
716 pipeline->FinalizeCompilation(); | 716 pipeline->FinalizeCompilation(); |
717 } | 717 } |
718 { | 718 { |
719 TimerScope timer(FLAG_compiler_stats, | 719 TimerScope timer(FLAG_compiler_stats, |
720 &CompilerStats::codefinalizer_timer, | 720 &CSTAT_TIMER(codefinalizer_timer), |
721 isolate); | 721 isolate); |
722 // CreateDeoptInfo uses the object pool and needs to be done before | 722 // CreateDeoptInfo uses the object pool and needs to be done before |
723 // FinalizeCode. | 723 // FinalizeCode. |
724 const Array& deopt_info_array = Array::Handle( | 724 const Array& deopt_info_array = |
725 graph_compiler.CreateDeoptInfo(&assembler)); | 725 Array::Handle(isolate, graph_compiler.CreateDeoptInfo(&assembler)); |
| 726 INC_STAT(isolate, total_code_size, |
| 727 deopt_info_array.Length() * sizeof(uword)); |
726 const Code& code = Code::Handle( | 728 const Code& code = Code::Handle( |
727 Code::FinalizeCode(function, &assembler, optimized)); | 729 Code::FinalizeCode(function, &assembler, optimized)); |
728 code.set_is_optimized(optimized); | 730 code.set_is_optimized(optimized); |
729 code.set_inlined_intervals(graph_compiler.inlined_code_intervals()); | 731 |
730 code.set_inlined_id_to_function( | 732 const Array& intervals = graph_compiler.inlined_code_intervals(); |
731 Array::Handle(graph_compiler.InliningIdToFunction())); | 733 INC_STAT(isolate, total_code_size, |
| 734 intervals.Length() * sizeof(uword)); |
| 735 code.set_inlined_intervals(intervals); |
| 736 |
| 737 const Array& inlined_id_array = |
| 738 Array::Handle(isolate, graph_compiler.InliningIdToFunction()); |
| 739 INC_STAT(isolate, total_code_size, |
| 740 inlined_id_array.Length() * sizeof(uword)); |
| 741 code.set_inlined_id_to_function(inlined_id_array); |
| 742 |
732 graph_compiler.FinalizePcDescriptors(code); | 743 graph_compiler.FinalizePcDescriptors(code); |
733 code.set_deopt_info_array(deopt_info_array); | 744 code.set_deopt_info_array(deopt_info_array); |
| 745 |
734 graph_compiler.FinalizeStackmaps(code); | 746 graph_compiler.FinalizeStackmaps(code); |
735 graph_compiler.FinalizeVarDescriptors(code); | 747 graph_compiler.FinalizeVarDescriptors(code); |
736 graph_compiler.FinalizeExceptionHandlers(code); | 748 graph_compiler.FinalizeExceptionHandlers(code); |
737 graph_compiler.FinalizeStaticCallTargetsTable(code); | 749 graph_compiler.FinalizeStaticCallTargetsTable(code); |
738 | 750 |
739 if (optimized) { | 751 if (optimized) { |
740 if (osr_id == Isolate::kNoDeoptId) { | 752 if (osr_id == Isolate::kNoDeoptId) { |
741 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); | 753 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); |
742 if (FLAG_trace_compiler || FLAG_trace_patching) { | 754 if (FLAG_trace_compiler || FLAG_trace_patching) { |
743 if (FLAG_trace_compiler) { | 755 if (FLAG_trace_compiler) { |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1305 const Object& result = | 1317 const Object& result = |
1306 PassiveObject::Handle(isolate->object_store()->sticky_error()); | 1318 PassiveObject::Handle(isolate->object_store()->sticky_error()); |
1307 isolate->object_store()->clear_sticky_error(); | 1319 isolate->object_store()->clear_sticky_error(); |
1308 return result.raw(); | 1320 return result.raw(); |
1309 } | 1321 } |
1310 UNREACHABLE(); | 1322 UNREACHABLE(); |
1311 return Object::null(); | 1323 return Object::null(); |
1312 } | 1324 } |
1313 | 1325 |
1314 } // namespace dart | 1326 } // namespace dart |
OLD | NEW |