Index: runtime/vm/flow_graph_compiler.cc |
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc |
index c5530297bc67d1b60f13d295ee1f189202c1a4fd..e1c8a0113e9743421e959d5441295684503e5f4a 100644 |
--- a/runtime/vm/flow_graph_compiler.cc |
+++ b/runtime/vm/flow_graph_compiler.cc |
@@ -196,7 +196,6 @@ FlowGraphCompiler::FlowGraphCompiler( |
pc_descriptors_list_(NULL), |
stackmap_table_builder_(NULL), |
code_source_map_builder_(NULL), |
- catch_entry_state_maps_builder_(NULL), |
block_info_(block_order_.length()), |
deopt_infos_(), |
static_calls_target_table_(), |
@@ -268,7 +267,6 @@ bool FlowGraphCompiler::IsPotentialUnboxedField(const Field& field) { |
void FlowGraphCompiler::InitCompiler() { |
pc_descriptors_list_ = new (zone()) DescriptorList(64); |
exception_handlers_list_ = new (zone()) ExceptionHandlerList(); |
- catch_entry_state_maps_builder_ = new (zone()) CatchEntryStateMapBuilder(); |
block_info_.Clear(); |
// Conservative detection of leaf routines used to remove the stack check |
// on function entry. |
@@ -414,91 +412,6 @@ void FlowGraphCompiler::CompactBlocks() { |
} |
-void FlowGraphCompiler::EmitCatchEntryState(Environment* env, |
- intptr_t try_index) { |
-#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
- env = env ? env : pending_deoptimization_env_; |
- try_index = try_index != CatchClauseNode::kInvalidTryIndex |
- ? try_index |
- : CurrentTryIndex(); |
- if (is_optimizing() && env != NULL && |
- (try_index != CatchClauseNode::kInvalidTryIndex)) { |
- env = env->Outermost(); |
- CatchBlockEntryInstr* catch_block = |
- flow_graph().graph_entry()->GetCatchEntry(try_index); |
- const GrowableArray<Definition*>* idefs = |
- catch_block->initial_definitions(); |
- catch_entry_state_maps_builder_->NewMapping(assembler()->CodeSize()); |
- // Parameters first. |
- intptr_t i = 0; |
- const intptr_t num_non_copied_params = flow_graph().num_non_copied_params(); |
- for (; i < num_non_copied_params; ++i) { |
- // Don't sync captured parameters. They are not in the environment. |
- if (flow_graph().captured_parameters()->Contains(i)) continue; |
- if ((*idefs)[i]->IsConstant()) continue; // Common constants. |
- Location src = env->LocationAt(i); |
- intptr_t dest_index = i - num_non_copied_params; |
- if (!src.IsStackSlot()) { |
- ASSERT(src.IsConstant()); |
- // Skip dead locations. |
- if (src.constant().raw() == Symbols::OptimizedOut().raw()) { |
- continue; |
- } |
- intptr_t id = |
- assembler()->object_pool_wrapper().FindObject(src.constant()); |
- catch_entry_state_maps_builder_->AppendConstant(id, dest_index); |
- continue; |
- } |
- if (src.stack_index() != dest_index) { |
- catch_entry_state_maps_builder_->AppendMove(src.stack_index(), |
- dest_index); |
- } |
- } |
- |
- // Process locals. Skip exception_var and stacktrace_var. |
- intptr_t local_base = kFirstLocalSlotFromFp + num_non_copied_params; |
- intptr_t ex_idx = local_base - catch_block->exception_var().index(); |
- intptr_t st_idx = local_base - catch_block->stacktrace_var().index(); |
- for (; i < flow_graph().variable_count(); ++i) { |
- // Don't sync captured parameters. They are not in the environment. |
- if (flow_graph().captured_parameters()->Contains(i)) continue; |
- if (i == ex_idx || i == st_idx) continue; |
- if ((*idefs)[i]->IsConstant()) continue; // Common constants. |
- Location src = env->LocationAt(i); |
- if (src.IsInvalid()) continue; |
- intptr_t dest_index = i - num_non_copied_params; |
- if (!src.IsStackSlot()) { |
- ASSERT(src.IsConstant()); |
- // Skip dead locations. |
- if (src.constant().raw() == Symbols::OptimizedOut().raw()) { |
- continue; |
- } |
- intptr_t id = |
- assembler()->object_pool_wrapper().FindObject(src.constant()); |
- catch_entry_state_maps_builder_->AppendConstant(id, dest_index); |
- continue; |
- } |
- if (src.stack_index() != dest_index) { |
- catch_entry_state_maps_builder_->AppendMove(src.stack_index(), |
- dest_index); |
- } |
- } |
- catch_entry_state_maps_builder_->EndMapping(); |
- } |
-#endif // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
-} |
- |
- |
-void FlowGraphCompiler::EmitCallsiteMetaData(TokenPosition token_pos, |
- intptr_t deopt_id, |
- RawPcDescriptors::Kind kind, |
- LocationSummary* locs) { |
- AddCurrentDescriptor(kind, deopt_id, token_pos); |
- RecordSafepoint(locs); |
- EmitCatchEntryState(); |
-} |
- |
- |
void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { |
if (!is_optimizing()) { |
if (instr->CanBecomeDeoptimizationTarget() && !instr->IsGoto()) { |
@@ -509,6 +422,10 @@ void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { |
instr->token_pos()); |
} |
AllocateRegistersLocally(instr); |
+ } else if (instr->MayThrow() && |
+ (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) { |
+ // Optimized try-block: Sync locals to fixed stack locations. |
+ EmitTrySync(instr, CurrentTryIndex()); |
} |
} |
@@ -627,6 +544,69 @@ void FlowGraphCompiler::Bailout(const char* reason) { |
} |
+void FlowGraphCompiler::EmitTrySync(Instruction* instr, intptr_t try_index) { |
+ ASSERT(is_optimizing()); |
+ Environment* env = instr->env()->Outermost(); |
+ CatchBlockEntryInstr* catch_block = |
+ flow_graph().graph_entry()->GetCatchEntry(try_index); |
+ const GrowableArray<Definition*>* idefs = catch_block->initial_definitions(); |
+ |
+ // Construct a ParallelMove instruction for parameters and locals. Skip the |
+ // special locals exception_var and stacktrace_var since they will be filled |
+ // when an exception is thrown. Constant locations are known to be the same |
+ // at all instructions that may throw, and do not need to be materialized. |
+ |
+ // Parameters first. |
+ intptr_t i = 0; |
+ const intptr_t num_non_copied_params = flow_graph().num_non_copied_params(); |
+ ParallelMoveInstr* move_instr = new (zone()) ParallelMoveInstr(); |
+ for (; i < num_non_copied_params; ++i) { |
+ // Don't sync captured parameters. They are not in the environment. |
+ if (flow_graph().captured_parameters()->Contains(i)) continue; |
+ if ((*idefs)[i]->IsConstant()) continue; // Common constants |
+ Location src = env->LocationAt(i); |
+#if defined(TARGET_ARCH_DBC) |
+ intptr_t dest_index = kNumberOfCpuRegisters - 1 - i; |
+ Location dest = Location::RegisterLocation(dest_index); |
+ // Update safepoint bitmap to indicate that the target location |
+ // now contains a pointer. With DBC parameters are copied into |
+ // the locals area. |
+ instr->locs()->SetStackBit(dest_index); |
+#else |
+ intptr_t dest_index = i - num_non_copied_params; |
+ Location dest = Location::StackSlot(dest_index); |
+#endif |
+ move_instr->AddMove(dest, src); |
+ } |
+ |
+ // Process locals. Skip exception_var and stacktrace_var. |
+ intptr_t local_base = kFirstLocalSlotFromFp + num_non_copied_params; |
+ intptr_t ex_idx = local_base - catch_block->exception_var().index(); |
+ intptr_t st_idx = local_base - catch_block->stacktrace_var().index(); |
+ for (; i < flow_graph().variable_count(); ++i) { |
+ // Don't sync captured parameters. They are not in the environment. |
+ if (flow_graph().captured_parameters()->Contains(i)) continue; |
+ if (i == ex_idx || i == st_idx) continue; |
+ if ((*idefs)[i]->IsConstant()) continue; |
+ Location src = env->LocationAt(i); |
+ ASSERT(!src.IsFpuRegister()); |
+ ASSERT(!src.IsDoubleStackSlot()); |
+#if defined(TARGET_ARCH_DBC) |
+ intptr_t dest_index = kNumberOfCpuRegisters - 1 - i; |
+ Location dest = Location::RegisterLocation(dest_index); |
+#else |
+ intptr_t dest_index = i - num_non_copied_params; |
+ Location dest = Location::StackSlot(dest_index); |
+#endif |
+ move_instr->AddMove(dest, src); |
+ // Update safepoint bitmap to indicate that the target location |
+ // now contains a pointer. |
+ instr->locs()->SetStackBit(dest_index); |
+ } |
+ parallel_move_resolver()->EmitNativeCode(move_instr); |
+} |
+ |
+ |
intptr_t FlowGraphCompiler::StackSize() const { |
if (is_optimizing_) { |
return flow_graph_.graph_entry()->spill_slot_count(); |
@@ -1035,15 +1015,6 @@ void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { |
code.set_var_descriptors(var_descs); |
} |
-void FlowGraphCompiler::FinalizeCatchEntryStateMap(const Code& code) { |
-#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) |
- TypedData& maps = TypedData::Handle( |
- catch_entry_state_maps_builder_->FinalizeCatchEntryStateMap()); |
- code.set_catch_entry_state_maps(maps); |
-#else |
- code.set_variables(Smi::Handle(Smi::New(flow_graph().variable_count()))); |
-#endif |
-} |
void FlowGraphCompiler::FinalizeStaticCallTargetsTable(const Code& code) { |
ASSERT(code.static_calls_target_table() == Array::null()); |
@@ -1071,7 +1042,6 @@ void FlowGraphCompiler::FinalizeStaticCallTargetsTable(const Code& code) { |
} |
- |
void FlowGraphCompiler::FinalizeCodeSourceMap(const Code& code) { |
const Array& inlined_id_array = |
Array::Handle(zone(), code_source_map_builder_->InliningIdToFunction()); |
@@ -1153,23 +1123,6 @@ bool FlowGraphCompiler::TryIntrinsify() { |
// DBC is very different from other architectures in how it performs instance |
// and static calls because it does not use stubs. |
#if !defined(TARGET_ARCH_DBC) |
-void FlowGraphCompiler::GenerateCallWithDeopt(TokenPosition token_pos, |
- intptr_t deopt_id, |
- const StubEntry& stub_entry, |
- RawPcDescriptors::Kind kind, |
- LocationSummary* locs) { |
- GenerateCall(token_pos, stub_entry, kind, locs); |
- const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); |
- if (is_optimizing()) { |
- AddDeoptIndexAtCall(deopt_id_after); |
- } else { |
- // Add deoptimization continuation point after the call and before the |
- // arguments are removed. |
- AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
- } |
-} |
- |
- |
void FlowGraphCompiler::GenerateInstanceCall(intptr_t deopt_id, |
TokenPosition token_pos, |
intptr_t argument_count, |