| 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 |