Chromium Code Reviews| Index: runtime/vm/flow_graph.cc |
| =================================================================== |
| --- runtime/vm/flow_graph.cc (revision 41279) |
| +++ runtime/vm/flow_graph.cc (working copy) |
| @@ -8,6 +8,7 @@ |
| #include "vm/flow_graph_builder.h" |
| #include "vm/intermediate_language.h" |
| #include "vm/growable_array.h" |
| +#include "vm/object_store.h" |
| #include "vm/report.h" |
| namespace dart { |
| @@ -36,6 +37,8 @@ |
| optimized_block_order_(), |
| constant_null_(NULL), |
| constant_dead_(NULL), |
| + constant_empty_context_(NULL), |
| + current_context_(NULL), |
| block_effects_(NULL), |
| licm_allowed_(true), |
| loop_headers_(NULL), |
| @@ -465,10 +468,13 @@ |
| // Returns true if the value set by the given store reaches any load from the |
| // same local variable. |
| bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) { |
| + if (store->local().index() == flow_graph_->CurrentContextVar()->index()) { |
|
Vyacheslav Egorov (Google)
2014/10/28 13:44:57
is it possible just to do
store->local().Equals(f
Florian Schneider
2014/10/28 19:04:31
Done.
|
| + return true; |
| + } |
| + |
| if (store->is_dead()) { |
| return false; |
| } |
| - |
| if (store->is_last()) { |
| const intptr_t index = store->local().BitIndexIn(num_non_copied_params_); |
| return GetLiveOutSet(block)->Contains(index); |
| @@ -480,6 +486,9 @@ |
| // Returns true if the given load is the last for the local and the value |
| // of the local will not flow into another one. |
| bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) { |
| + if (load->local().index() == flow_graph_->CurrentContextVar()->index()) { |
|
Vyacheslav Egorov (Google)
2014/10/28 13:44:57
ditto
Florian Schneider
2014/10/28 19:04:30
Done.
|
| + return false; |
| + } |
| const intptr_t index = load->local().BitIndexIn(num_non_copied_params_); |
| return load->is_last() && !GetLiveOutSet(block)->Contains(index); |
| } |
| @@ -722,6 +731,7 @@ |
| // Insert phis for each variable in turn. |
| GrowableArray<BlockEntryInstr*> worklist; |
| for (intptr_t var_index = 0; var_index < variable_count(); ++var_index) { |
| + bool always_live = var_index == CurrentContextEnvIndex(); |
|
Vyacheslav Egorov (Google)
2014/10/28 13:44:57
const bool is_always_alive
Florian Schneider
2014/10/28 19:04:30
Done.
|
| // Add to the worklist each block containing an assignment. |
| for (intptr_t block_index = 0; block_index < block_count; ++block_index) { |
| if (assigned_vars[block_index]->Contains(var_index)) { |
| @@ -740,7 +750,9 @@ |
| if (has_already[index] < var_index) { |
| BlockEntryInstr* block = preorder[index]; |
| ASSERT(block->IsJoinEntry()); |
| - block->AsJoinEntry()->InsertPhi(var_index, variable_count()); |
| + block->AsJoinEntry()->InsertPhi(var_index, |
|
Vyacheslav Egorov (Google)
2014/10/28 13:44:57
You can also make InsertPhi return the phi it crea
Florian Schneider
2014/10/28 19:04:31
Done.
|
| + variable_count(), |
| + always_live); |
| has_already[index] = var_index; |
| if (work[index] < var_index) { |
| work[index] = var_index; |
| @@ -764,6 +776,8 @@ |
| // Add global constants to the initial definitions. |
| constant_null_ = GetConstant(Object::ZoneHandle()); |
| constant_dead_ = GetConstant(Symbols::OptimizedOut()); |
| + constant_empty_context_ = GetConstant(Context::Handle( |
| + isolate()->object_store()->empty_context())); |
| // Add parameters to the initial definitions and renaming environment. |
| if (inlining_parameters != NULL) { |
| @@ -791,7 +805,18 @@ |
| // the locals have already been handled as parameters. |
| if (!IsCompiledForOsr()) { |
| for (intptr_t i = parameter_count(); i < variable_count(); ++i) { |
| - env.Add(constant_null()); |
| + if (i == CurrentContextEnvIndex()) { |
| + if (parsed_function().function().IsClosureFunction()) { |
| + CurrentContextInstr* context = new CurrentContextInstr(); |
| + context->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| + AddToInitialDefinitions(context); |
| + env.Add(context); |
| + } else { |
| + env.Add(constant_empty_context()); |
| + } |
| + } else { |
| + env.Add(constant_null()); |
| + } |
| } |
| } |
| @@ -812,12 +837,6 @@ |
| *env, |
| num_non_copied_params_, |
| &parsed_function_); |
| - // TODO(fschneider): Add predicates CanEagerlyDeoptimize and |
| - // CanLazilyDeoptimize to instructions to generally deal with instructions |
| - // that have pushed arguments and input operands. |
| - // Right now, closure calls are the only instructions that have both. They |
| - // also don't have an eager deoptimziation point, so the environment attached |
| - // here is only used for after the call. |
| if (instr->IsClosureCall()) { |
| deopt_env = deopt_env->DeepCopy(isolate(), |
| deopt_env->Length() - instr->InputCount()); |
| @@ -872,7 +891,7 @@ |
| // slots with null. |
| BitVector* live_in = variable_liveness->GetLiveInSet(block_entry); |
| for (intptr_t i = 0; i < variable_count(); i++) { |
| - if (!live_in->Contains(i)) { |
| + if (!live_in->Contains(i) && (i != CurrentContextEnvIndex())) { |
|
Vyacheslav Egorov (Google)
2014/10/28 13:44:57
Should not we instead ensure that live_in->Contain
Florian Schneider
2014/10/28 19:04:31
Yes, I can change the VariableLiveness accordingly
|
| (*env)[i] = constant_dead(); |
| } |
| } |