Index: runtime/vm/flow_graph_builder.cc |
=================================================================== |
--- runtime/vm/flow_graph_builder.cc (revision 23243) |
+++ runtime/vm/flow_graph_builder.cc (working copy) |
@@ -57,7 +57,8 @@ |
context_level_(0), |
last_used_try_index_(CatchClauseNode::kInvalidTryIndex), |
try_index_(CatchClauseNode::kInvalidTryIndex), |
- graph_entry_(NULL) { } |
+ graph_entry_(NULL), |
+ args_pushed_(0) { } |
void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { |
@@ -356,6 +357,7 @@ |
DeallocateTempIndex(definition->InputCount()); |
definition->set_use_kind(Definition::kValue); |
definition->set_temp_index(AllocateTempIndex()); |
+ owner_->add_args_pushed(-definition->ArgumentCount()); |
if (is_empty()) { |
entry_ = definition; |
} else { |
@@ -370,6 +372,7 @@ |
ASSERT(is_open()); |
DeallocateTempIndex(definition->InputCount()); |
definition->set_use_kind(Definition::kEffect); |
+ owner_->add_args_pushed(-definition->ArgumentCount()); |
if (is_empty()) { |
entry_ = definition; |
} else { |
@@ -384,6 +387,7 @@ |
ASSERT(instruction->IsPushArgument() || !instruction->IsDefinition()); |
ASSERT(!instruction->IsBlockEntry()); |
DeallocateTempIndex(instruction->InputCount()); |
+ owner_->add_args_pushed(-instruction->ArgumentCount()); |
if (is_empty()) { |
entry_ = exit_ = instruction; |
} else { |
@@ -503,6 +507,7 @@ |
PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { |
+ owner_->add_args_pushed(1); |
PushArgumentInstr* result = new PushArgumentInstr(value); |
AddInstruction(result); |
return result; |
@@ -1824,6 +1829,93 @@ |
} |
+intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { |
+ return kFirstLocalSlotFromFp |
+ - owner()->num_stack_locals() |
+ - owner()->num_copied_params() |
+ - owner()->args_pushed() |
+ - temp_index() + 1; |
+} |
+ |
+ |
+class TempLocalScope : public ValueObject { |
+ public: |
+ TempLocalScope(EffectGraphVisitor* visitor, Value* value) |
+ : visitor_(visitor) { |
+ ASSERT(value->definition()->temp_index() == visitor->temp_index() - 1); |
+ intptr_t index = visitor->GetCurrentTempLocalIndex(); |
+ char name[64]; |
+ OS::SNPrint(name, 64, ":tmp_local%"Pd, index); |
+ var_ = new LocalVariable(0, String::ZoneHandle(Symbols::New(name)), |
+ Type::ZoneHandle(Type::DynamicType())); |
+ var_->set_index(index); |
+ visitor->Do(new PushTempInstr(value)); |
+ visitor->AllocateTempIndex(); |
+ } |
+ |
+ LocalVariable* var() const { return var_; } |
+ |
+ ~TempLocalScope() { |
+ Value* result = visitor_->Bind(new LoadLocalInstr(*var_)); |
+ visitor_->DeallocateTempIndex(1); |
+ visitor_->ReturnDefinition(new DropTempsInstr(1, result)); |
+ } |
+ |
+ private: |
+ EffectGraphVisitor* visitor_; |
+ Value* value_; |
+ LocalVariable* var_; |
+}; |
+ |
+ |
+void EffectGraphVisitor::BuildLetTempExpressions(LetNode* node) { |
+ intptr_t num_temps = node->num_temps(); |
+ for (intptr_t i = 0; i < num_temps; ++i) { |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->InitializerAt(i)->Visit(&for_value); |
+ Append(for_value); |
+ Value* temp_val = for_value.value(); |
+ node->TempAt(i)->set_index(GetCurrentTempLocalIndex()); |
+ Do(new PushTempInstr(temp_val)); |
+ AllocateTempIndex(); |
+ } |
+} |
+ |
+ |
+void EffectGraphVisitor::VisitLetNode(LetNode* node) { |
+ BuildLetTempExpressions(node); |
+ intptr_t num_temps = node->num_temps(); |
+ |
+ // TODO(fschneider): Generate better code for effect context by visiting the |
+ // body for effect. Currently, the value of the body expression is |
+ // materialized and then dropped. This also requires changing DropTempsInstr |
+ // to have zero or one inputs. |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->body()->Visit(&for_value); |
+ Append(for_value); |
+ Value* result_value = for_value.value(); |
+ DeallocateTempIndex(num_temps); |
+ Do(new DropTempsInstr(num_temps, result_value)); |
+} |
+ |
+ |
+void ValueGraphVisitor::VisitLetNode(LetNode* node) { |
+ BuildLetTempExpressions(node); |
+ |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->body()->Visit(&for_value); |
+ Append(for_value); |
+ Value* result_value = for_value.value(); |
+ intptr_t num_temps = node->num_temps(); |
+ if (num_temps > 0) { |
+ DeallocateTempIndex(num_temps); |
+ ReturnDefinition(new DropTempsInstr(num_temps, result_value)); |
+ } else { |
+ ReturnValue(result_value); |
+ } |
+} |
+ |
+ |
void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { |
const AbstractTypeArguments& type_args = |
AbstractTypeArguments::ZoneHandle(node->type().arguments()); |
@@ -1834,31 +1926,28 @@ |
node->type(), |
element_type); |
Value* array_val = Bind(create); |
- Definition* store = BuildStoreTemp(node->temp_local(), array_val); |
- Do(store); |
- const intptr_t class_id = create->Type()->ToCid(); |
- const intptr_t deopt_id = Isolate::kNoDeoptId; |
- for (int i = 0; i < node->length(); ++i) { |
- Value* array = Bind( |
- new LoadLocalInstr(node->temp_local())); |
- Value* index = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(i)))); |
- ValueGraphVisitor for_value(owner(), temp_index()); |
- node->ElementAt(i)->Visit(&for_value); |
- Append(for_value); |
- // No store barrier needed for constants. |
- const StoreBarrierType emit_store_barrier = |
- for_value.value()->BindsToConstant() |
- ? kNoStoreBarrier |
- : kEmitStoreBarrier; |
- intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id); |
- StoreIndexedInstr* store = new StoreIndexedInstr( |
- array, index, for_value.value(), |
- emit_store_barrier, index_scale, class_id, deopt_id); |
- Do(store); |
+ { TempLocalScope tmp(this, array_val); |
+ const intptr_t class_id = create->Type()->ToCid(); |
+ const intptr_t deopt_id = Isolate::kNoDeoptId; |
+ for (int i = 0; i < node->length(); ++i) { |
+ Value* array = Bind(new LoadLocalInstr(*tmp.var())); |
+ Value* index = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(i)))); |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->ElementAt(i)->Visit(&for_value); |
+ Append(for_value); |
+ // No store barrier needed for constants. |
+ const StoreBarrierType emit_store_barrier = |
+ for_value.value()->BindsToConstant() |
+ ? kNoStoreBarrier |
+ : kEmitStoreBarrier; |
+ intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id); |
+ StoreIndexedInstr* store = new StoreIndexedInstr( |
+ array, index, for_value.value(), |
+ emit_store_barrier, index_scale, class_id, deopt_id); |
+ Do(store); |
+ } |
} |
- |
- ReturnDefinition(new LoadLocalInstr(node->temp_local())); |
} |
@@ -2332,7 +2421,6 @@ |
// The type arguments are uninstantiated. We use expression_temp_var to save |
// the instantiator type arguments because they have two uses. |
ASSERT(owner()->parsed_function().expression_temp_var() != NULL); |
- const LocalVariable& temp = *owner()->parsed_function().expression_temp_var(); |
const Class& instantiator_class = Class::Handle( |
owner()->parsed_function().function().Owner()); |
Value* type_arguments_val = BuildInstantiatorTypeArguments( |
@@ -2347,7 +2435,7 @@ |
const intptr_t len = node->type_arguments().Length(); |
if (node->type_arguments().IsRawInstantiatedRaw(len)) { |
type_arguments_val = |
- Bind(BuildStoreTemp(temp, type_arguments_val)); |
+ Bind(BuildStoreExprTemp(type_arguments_val)); |
type_arguments_val = Bind( |
new ExtractConstructorTypeArgumentsInstr( |
node->token_pos(), |
@@ -2355,7 +2443,7 @@ |
instantiator_class, |
type_arguments_val)); |
} else { |
- Do(BuildStoreTemp(temp, type_arguments_val)); |
+ Do(BuildStoreExprTemp(type_arguments_val)); |
type_arguments_val = Bind(new ConstantInstr(node->type_arguments())); |
} |
} |
@@ -2363,7 +2451,7 @@ |
Value* instantiator_val = NULL; |
if (!use_instantiator_type_args) { |
- instantiator_val = Bind(BuildLoadLocal(temp)); |
+ instantiator_val = Bind(BuildLoadExprTemp()); |
const intptr_t len = node->type_arguments().Length(); |
if (node->type_arguments().IsRawInstantiatedRaw(len)) { |
instantiator_val = |
@@ -2395,15 +2483,11 @@ |
// tn <- LoadLocal(temp) |
Value* allocate = BuildObjectAllocation(node); |
- Value* allocated_value = Bind(BuildStoreTemp( |
- node->allocated_object_var(), |
- allocate)); |
- PushArgumentInstr* push_allocated_value = PushArgument(allocated_value); |
- BuildConstructorCall(node, push_allocated_value); |
- Definition* load_allocated = BuildLoadLocal( |
- node->allocated_object_var()); |
- allocated_value = Bind(load_allocated); |
- ReturnValue(allocated_value); |
+ { TempLocalScope tmp(this, allocate); |
+ Value* allocated_tmp = Bind(new LoadLocalInstr(*tmp.var())); |
+ PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp); |
+ BuildConstructorCall(node, push_allocated_value); |
+ } |
} |
@@ -3270,8 +3354,7 @@ |
// including the receiver. |
ArrayNode* args_array = new ArrayNode( |
args_pos, |
- Type::ZoneHandle(Type::ArrayType()), |
- *owner()->parsed_function().array_literal_var()); |
+ Type::ZoneHandle(Type::ArrayType())); |
for (intptr_t i = 0; i < method_arguments->length(); i++) { |
args_array->AddElement(method_arguments->NodeAt(i)); |
} |