| Index: runtime/vm/compiler.cc
|
| ===================================================================
|
| --- runtime/vm/compiler.cc (revision 25620)
|
| +++ runtime/vm/compiler.cc (working copy)
|
| @@ -488,52 +488,75 @@
|
| }
|
| }
|
|
|
| - Assembler assembler;
|
| - FlowGraphCompiler graph_compiler(&assembler,
|
| - *flow_graph,
|
| - optimized);
|
| - {
|
| - TimerScope timer(FLAG_compiler_stats,
|
| - &CompilerStats::graphcompiler_timer,
|
| - isolate);
|
| - graph_compiler.CompileGraph();
|
| - }
|
| - {
|
| - TimerScope timer(FLAG_compiler_stats,
|
| - &CompilerStats::codefinalizer_timer,
|
| - isolate);
|
| - const Code& code = Code::Handle(
|
| - Code::FinalizeCode(function, &assembler, optimized));
|
| - code.set_is_optimized(optimized);
|
| - graph_compiler.FinalizePcDescriptors(code);
|
| - graph_compiler.FinalizeDeoptInfo(code);
|
| - graph_compiler.FinalizeStackmaps(code);
|
| - graph_compiler.FinalizeVarDescriptors(code);
|
| - graph_compiler.FinalizeExceptionHandlers(code);
|
| - graph_compiler.FinalizeComments(code);
|
| - graph_compiler.FinalizeStaticCallTargetsTable(code);
|
| + // First, try to assemble the function using only near branches. If that
|
| + // fails, we'll longjmp back here, set the needs_far_branches bit in the
|
| + // function and try again.
|
| + bool assembled = false;
|
| + while (!assembled) {
|
| + const intptr_t prev_deopt_id = isolate->deopt_id();
|
| + isolate->set_deopt_id(0);
|
| + LongJump* assembler_old_base = isolate->long_jump_base();
|
| + LongJump assembler_jump;
|
| + isolate->set_long_jump_base(&assembler_jump);
|
| + if (setjmp(*assembler_jump.Set()) == 0) {
|
| + Assembler assembler(flow_graph->use_far_branches());
|
| + FlowGraphCompiler graph_compiler(&assembler,
|
| + *flow_graph,
|
| + optimized);
|
| + {
|
| + TimerScope timer(FLAG_compiler_stats,
|
| + &CompilerStats::graphcompiler_timer,
|
| + isolate);
|
| + graph_compiler.CompileGraph();
|
| + assembled = true;
|
| + }
|
| + {
|
| + TimerScope timer(FLAG_compiler_stats,
|
| + &CompilerStats::codefinalizer_timer,
|
| + isolate);
|
| + const Code& code = Code::Handle(
|
| + Code::FinalizeCode(function, &assembler, optimized));
|
| + code.set_is_optimized(optimized);
|
| + graph_compiler.FinalizePcDescriptors(code);
|
| + graph_compiler.FinalizeDeoptInfo(code);
|
| + graph_compiler.FinalizeStackmaps(code);
|
| + graph_compiler.FinalizeVarDescriptors(code);
|
| + graph_compiler.FinalizeExceptionHandlers(code);
|
| + graph_compiler.FinalizeComments(code);
|
| + graph_compiler.FinalizeStaticCallTargetsTable(code);
|
|
|
| - if (optimized) {
|
| - if (osr_id == Isolate::kNoDeoptId) {
|
| - CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
|
| - if (FLAG_trace_compiler) {
|
| - OS::Print("--> patching entry %#"Px"\n",
|
| - Code::Handle(function.unoptimized_code()).EntryPoint());
|
| + if (optimized) {
|
| + if (osr_id == Isolate::kNoDeoptId) {
|
| + CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
|
| + if (FLAG_trace_compiler) {
|
| + OS::Print("--> patching entry %#"Px"\n",
|
| + Code::Handle(function.unoptimized_code()).EntryPoint());
|
| + }
|
| + }
|
| + function.SetCode(code);
|
| +
|
| + for (intptr_t i = 0; i < guarded_fields.length(); i++) {
|
| + const Field& field = *guarded_fields[i];
|
| + field.RegisterDependentCode(code);
|
| + }
|
| + } else {
|
| + function.set_unoptimized_code(code);
|
| + function.SetCode(code);
|
| + ASSERT(CodePatcher::CodeIsPatchable(code));
|
| }
|
| }
|
| - function.SetCode(code);
|
| + is_compiled = true;
|
| + } else {
|
| + isolate->object_store()->clear_sticky_error();
|
|
|
| - for (intptr_t i = 0; i < guarded_fields.length(); i++) {
|
| - const Field& field = *guarded_fields[i];
|
| - field.RegisterDependentCode(code);
|
| - }
|
| - } else {
|
| - function.set_unoptimized_code(code);
|
| - function.SetCode(code);
|
| - ASSERT(CodePatcher::CodeIsPatchable(code));
|
| + // If far branches were enabled, assembly should not fail again.
|
| + ASSERT(!flow_graph->use_far_branches());
|
| + flow_graph->set_use_far_branches(true);
|
| + is_compiled = false;
|
| }
|
| + isolate->set_long_jump_base(assembler_old_base);
|
| + isolate->set_deopt_id(prev_deopt_id);
|
| }
|
| - is_compiled = true;
|
| } else {
|
| // We bailed out.
|
| Error& bailout_error = Error::Handle(
|
|
|