| Index: runtime/vm/flow_graph_optimizer.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_optimizer.cc (revision 10885)
|
| +++ runtime/vm/flow_graph_optimizer.cc (working copy)
|
| @@ -5,6 +5,7 @@
|
| #include "vm/flow_graph_optimizer.h"
|
|
|
| #include "vm/flow_graph_builder.h"
|
| +#include "vm/hash_map.h"
|
| #include "vm/il_printer.h"
|
| #include "vm/object_store.h"
|
| #include "vm/parser.h"
|
| @@ -81,9 +82,9 @@
|
|
|
|
|
| static bool ClassIdIsOneOf(intptr_t class_id,
|
| - GrowableArray<intptr_t>* class_ids) {
|
| - for (intptr_t i = 0; i < class_ids->length(); i++) {
|
| - if ((*class_ids)[i] == class_id) {
|
| + const GrowableArray<intptr_t>& class_ids) {
|
| + for (intptr_t i = 0; i < class_ids.length(); i++) {
|
| + if (class_ids[i] == class_id) {
|
| return true;
|
| }
|
| }
|
| @@ -93,8 +94,8 @@
|
|
|
| static bool ICDataHasOnlyReceiverArgumentClassIds(
|
| const ICData& ic_data,
|
| - GrowableArray<intptr_t>* receiver_class_ids,
|
| - GrowableArray<intptr_t>* argument_class_ids) {
|
| + const GrowableArray<intptr_t>& receiver_class_ids,
|
| + const GrowableArray<intptr_t>& argument_class_ids) {
|
| if (ic_data.num_args_tested() != 2) return false;
|
|
|
| Function& target = Function::Handle();
|
| @@ -125,10 +126,10 @@
|
| // Returns false if the ICData contains anything other than the 4 combinations
|
| // of Mint and Smi for the receiver and argument classes.
|
| static bool HasTwoMintOrSmi(const ICData& ic_data) {
|
| - GrowableArray<intptr_t> class_ids;
|
| + GrowableArray<intptr_t> class_ids(2);
|
| class_ids.Add(kSmiCid);
|
| class_ids.Add(kMintCid);
|
| - return ICDataHasOnlyReceiverArgumentClassIds(ic_data, &class_ids, &class_ids);
|
| + return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids);
|
| }
|
|
|
|
|
| @@ -363,9 +364,35 @@
|
| String::Handle(Field::NameFromGetter(comp->function_name()));
|
| const Field& field = Field::Handle(GetField(class_ids[0], field_name));
|
| ASSERT(!field.IsNull());
|
| - LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
|
| - field, comp->ArgumentAt(0)->value(), comp);
|
| - load->set_ic_data(comp->ic_data());
|
| +
|
| + LoadInstanceFieldComp* load;
|
| + if (!use_ssa_) {
|
| + load = new LoadInstanceFieldComp(field,
|
| + comp->ArgumentAt(0)->value(),
|
| + comp,
|
| + true); // Can deoptimize.
|
| + // TODO(fschneider): Remove the boolean parameter can_deoptimize once
|
| + // the non-SSA optimizer is removed.
|
| + load->set_ic_data(comp->ic_data());
|
| + } else {
|
| + // TODO(fschneider): Avoid generating redundant checks by checking the
|
| + // result-cid of the value.
|
| + CheckClassComp* check =
|
| + new CheckClassComp(comp->ArgumentAt(0)->value(), comp);
|
| + const ICData& unary_checks =
|
| + ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
|
| + check->set_ic_data(&unary_checks);
|
| + BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check);
|
| + ASSERT(instr->env() != NULL); // Always the case with SSA.
|
| + check_instr->set_env(
|
| + new Environment(instr->env()->values(),
|
| + instr->env()->fixed_parameter_count()));
|
| + check_instr->InsertBefore(instr);
|
| + load = new LoadInstanceFieldComp(field,
|
| + comp->ArgumentAt(0)->value(),
|
| + NULL,
|
| + false); // Can not deoptimize.
|
| + }
|
| instr->set_computation(load);
|
| RemovePushArguments(comp);
|
| return true;
|
| @@ -489,7 +516,7 @@
|
| const intptr_t kMaxChecks = 4;
|
| if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) {
|
| PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
|
| - ICData& unary_checks =
|
| + const ICData& unary_checks =
|
| ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
|
| call->set_ic_data(&unary_checks);
|
| instr->set_computation(call);
|
| @@ -868,4 +895,31 @@
|
| }
|
| }
|
|
|
| +
|
| +void LocalCSE::Optimize() {
|
| + for (intptr_t i = 0; i < blocks_.length(); ++i) {
|
| + BlockEntryInstr* entry = blocks_[i];
|
| + DirectChainedHashMap<BindInstr*> map;
|
| + ASSERT(map.IsEmpty());
|
| + for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
|
| + BindInstr* instr = it.Current()->AsBind();
|
| + if (instr == NULL || instr->computation()->HasSideEffect()) continue;
|
| + BindInstr* result = map.Lookup(instr);
|
| + if (result == NULL) {
|
| + map.Insert(instr);
|
| + continue;
|
| + }
|
| + // Replace current with lookup result.
|
| + instr->ReplaceUsesWith(result);
|
| + it.RemoveCurrentFromGraph();
|
| + if (FLAG_trace_optimization) {
|
| + OS::Print("Replacing v%d with v%d\n",
|
| + instr->ssa_temp_index(),
|
| + result->ssa_temp_index());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| } // namespace dart
|
|
|