Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
dart::CompileParsedFunctionHelper Class Reference
Inheritance diagram for dart::CompileParsedFunctionHelper:
dart::ValueObject

Public Member Functions

 CompileParsedFunctionHelper (ParsedFunction *parsed_function, bool optimized, intptr_t osr_id)
 
CodePtr Compile (CompilationPipeline *pipeline)
 
- Public Member Functions inherited from dart::ValueObject
 ValueObject ()
 
 ~ValueObject ()
 

Detailed Description

Definition at line 303 of file compiler.cc.

Constructor & Destructor Documentation

◆ CompileParsedFunctionHelper()

dart::CompileParsedFunctionHelper::CompileParsedFunctionHelper ( ParsedFunction parsed_function,
bool  optimized,
intptr_t  osr_id 
)
inline

Definition at line 305 of file compiler.cc.

308 : parsed_function_(parsed_function),
309 optimized_(optimized),
310 osr_id_(osr_id),
311 thread_(Thread::Current()) {}
static Thread * Current()
Definition: thread.h:362

Member Function Documentation

◆ Compile()

CodePtr dart::CompileParsedFunctionHelper::Compile ( CompilationPipeline pipeline)

Definition at line 487 of file compiler.cc.

487 {
488 ASSERT(!FLAG_precompiled_mode);
489 const Function& function = parsed_function()->function();
490 if (optimized() && !function.IsOptimizable()) {
491 return Code::null();
492 }
493 Zone* const zone = thread()->zone();
494 HANDLESCOPE(thread());
495 EnterCompilerScope cs(thread());
496
497 // We may reattempt compilation if the function needs to be assembled using
498 // far branches on ARM. In the else branch of the setjmp call, done is set to
499 // false, and use_far_branches is set to true if there is a longjmp from the
500 // ARM assembler. In all other paths through this while loop, done is set to
501 // true. use_far_branches is always false on ia32 and x64.
502 volatile bool done = false;
503 // volatile because the variable may be clobbered by a longjmp.
504 volatile intptr_t far_branch_level = 0;
505
506 // In the JIT case we allow speculative inlining and have no need for a
507 // suppression, since we don't restart optimization.
508 SpeculativeInliningPolicy speculative_policy(/*enable_suppression=*/false);
509
510 Code* volatile result = &Code::ZoneHandle(zone);
511 while (!done) {
512 *result = Code::null();
513 LongJumpScope jump;
514 if (setjmp(*jump.Set()) == 0) {
515 FlowGraph* flow_graph = nullptr;
516 ZoneGrowableArray<const ICData*>* ic_data_array = nullptr;
517
518 CompilerState compiler_state(thread(), /*is_aot=*/false, optimized(),
520 compiler_state.set_function(function);
521
522 {
523 // Extract type feedback before the graph is built, as the graph
524 // builder uses it to attach it to nodes.
525 ic_data_array = new (zone) ZoneGrowableArray<const ICData*>();
526
527 // Clone ICData for background compilation so that it does not
528 // change while compiling.
529 const bool clone_ic_data = Compiler::IsBackgroundCompilation();
530 function.RestoreICDataMap(ic_data_array, clone_ic_data);
531
532 if (optimized()) {
533 ASSERT(function.ic_data_array() != Array::null() ||
534 function.ForceOptimize());
535 }
536
537 if (FLAG_print_ic_data_map) {
538 for (intptr_t i = 0; i < ic_data_array->length(); i++) {
539 if ((*ic_data_array)[i] != nullptr) {
540 THR_Print("%" Pd " ", i);
541 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]);
542 }
543 }
544 }
545
546 TIMELINE_DURATION(thread(), CompilerVerbose, "BuildFlowGraph");
547 flow_graph = pipeline->BuildFlowGraph(
548 zone, parsed_function(), ic_data_array, osr_id(), optimized());
549 }
550
551 const bool print_flow_graph =
552 (FLAG_print_flow_graph ||
553 (optimized() && FLAG_print_flow_graph_optimized)) &&
555
556 if (print_flow_graph && !optimized()) {
557 FlowGraphPrinter::PrintGraph("Unoptimized Compilation", flow_graph);
558 }
559
560 if (flow_graph->should_reorder_blocks()) {
561 TIMELINE_DURATION(thread(), CompilerVerbose,
562 "BlockScheduler::AssignEdgeWeights");
564 }
565
566 CompilerPassState pass_state(thread(), flow_graph, &speculative_policy);
567
568 if (optimized()) {
569 TIMELINE_DURATION(thread(), CompilerVerbose, "OptimizationPasses");
570
571 JitCallSpecializer call_specializer(flow_graph, &speculative_policy);
572 pass_state.call_specializer = &call_specializer;
573
574 flow_graph = CompilerPass::RunPipeline(CompilerPass::kJIT, &pass_state);
575 }
576
577 ASSERT(pass_state.inline_id_to_function.length() ==
578 pass_state.caller_inline_id.length());
579 compiler::ObjectPoolBuilder object_pool_builder;
580 compiler::Assembler assembler(&object_pool_builder, far_branch_level);
581 FlowGraphCompiler graph_compiler(
582 &assembler, flow_graph, *parsed_function(), optimized(),
583 &speculative_policy, pass_state.inline_id_to_function,
584 pass_state.inline_id_to_token_pos, pass_state.caller_inline_id,
585 ic_data_array);
586 pass_state.graph_compiler = &graph_compiler;
587 CompilerPass::GenerateCode(&pass_state);
588
589 {
590 TIMELINE_DURATION(thread(), CompilerVerbose, "FinalizeCompilation");
591
592 auto install_code_fun = [&]() {
593 *result =
594 FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
595#if !defined(PRODUCT)
596 // Isolate debuggers need to be notified of compiled function right
597 // away as code is installed because there might be latent breakpoints
598 // in compiled function, which have to be activated before functions
599 // code is executed. Otherwise concurrently running isolates might
600 // execute code before its patched and miss a need to pause at a
601 // breakpoint.
602 if (!result->IsNull()) {
603 if (!function.HasOptimizedCode()) {
605 function);
606 }
607 }
608#endif
609 };
610
611 // Grab write program_lock outside of potential safepoint, that lock
612 // can't be waited for inside the safepoint.
613 // Initially read lock was added to guard direct_subclasses field
614 // access.
615 // Read lock was upgraded to write lock to guard dependent code updates.
616 SafepointWriteRwLocker ml(thread(),
617 thread()->isolate_group()->program_lock());
618 // We have to ensure no mutators are running, because:
619 //
620 // a) We allocate an instructions object, which might cause us to
621 // temporarily flip page protections (RX -> RW -> RX).
622 //
623 // b) We have to ensure the code generated does not violate
624 // assumptions (e.g. CHA, field guards), the validation has to
625 // happen while mutator is stopped.
626 //
627 // b) We update the [Function] object with a new [Code] which
628 // requires updating several pointers: We have to ensure all of
629 // those writes are observed atomically.
630 //
632 install_code_fun, /*use_force_growth=*/true);
633 }
634 if (!result->IsNull()) {
635 // Must be called outside of safepoint.
637
638 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
640 } else if (FLAG_disassemble_optimized && optimized() &&
643 }
644 }
645 // Exit the loop and the function with the correct result value.
646 done = true;
647 } else {
648 // We bailed out or we encountered an error.
649 const Error& error = Error::Handle(thread()->StealStickyError());
650
651 if (error.ptr() == Object::branch_offset_error().ptr()) {
652 // Compilation failed due to an out of range branch offset in the
653 // assembler. We try again (done = false) with far branches enabled.
654 done = false;
655 RELEASE_ASSERT(far_branch_level < 2);
656 far_branch_level++;
657 } else if (error.ptr() == Object::speculative_inlining_error().ptr()) {
658 // Can only happen with precompilation.
659 UNREACHABLE();
660 } else {
661 // If the error isn't due to an out of range branch offset, we don't
662 // try again (done = true).
663 if (FLAG_trace_bailout) {
664 THR_Print("%s\n", error.ToErrorCString());
665 }
666 if (!Compiler::IsBackgroundCompilation() && error.IsLanguageError() &&
667 (LanguageError::Cast(error).kind() == Report::kBailout)) {
668 // If is is not a background compilation, discard the error if it was
669 // not a real error, but just a bailout. If we're it a background
670 // compilation this will be dealt with in the caller.
671 } else {
672 // Otherwise, continue propagating unless we will try again.
673 thread()->set_sticky_error(error);
674 }
675 done = true;
676 }
677 }
678 }
679 return result->ptr();
680}
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition: DM.cpp:263
#define UNREACHABLE()
Definition: assert.h:248
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
static void AssignEdgeWeights(FlowGraph *flow_graph)
static void NotifyCodeObservers(const Code &code, bool optimized)
Definition: object.cc:18141
static void GenerateCode(CompilerPassState *state)
static DART_WARN_UNUSED_RESULT FlowGraph * RunPipeline(PipelineMode mode, CompilerPassState *state, bool compute_ssa=true)
static bool ShouldTrace()
static bool IsBackgroundCompilation()
Definition: compiler.cc:298
static void DisassembleCode(const Function &function, const Code &code, bool optimized)
static void PrintGraph(const char *phase, FlowGraph *flow_graph)
Definition: il_printer.cc:1706
static bool ShouldPrint(const Function &function, uint8_t **compiler_pass_filter=nullptr)
Definition: il_printer.cc:1715
static void PrintICData(const ICData &ic_data, intptr_t num_checks_to_print=kPrintAll)
Definition: il_printer.cc:1710
void NotifyCompilation(const Function &func)
Definition: debugger.cc:2977
GroupDebugger * debugger() const
Definition: isolate.h:315
void RunWithStoppedMutators(T single_current_mutator, S otherwise, bool use_force_growth_in_otherwise=false)
Definition: isolate.h:611
static ObjectPtr null()
Definition: object.h:433
static Object & Handle()
Definition: object.h:407
static Object & ZoneHandle()
Definition: object.h:419
const Function & function() const
Definition: parser.h:73
@ kBailout
Definition: report.h:26
Zone * zone() const
Definition: thread_state.h:37
void set_sticky_error(const Error &value)
Definition: thread.cc:236
IsolateGroup * isolate_group() const
Definition: thread.h:541
#define THR_Print(format,...)
Definition: log.h:20
#define ASSERT(E)
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
Dart_NativeFunction function
Definition: fuchsia.cc:51
#define HANDLESCOPE(thread)
Definition: handles.h:321
#define Pd
Definition: globals.h:408
#define TIMELINE_DURATION(thread, stream, name)
Definition: timeline.h:39

The documentation for this class was generated from the following file: