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(); |
} |
} |