| Index: runtime/vm/flow_graph_optimizer.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_optimizer.cc (revision 11146)
|
| +++ runtime/vm/flow_graph_optimizer.cc (working copy)
|
| @@ -34,15 +34,18 @@
|
| BindInstr* instr = it.Current()->AsBind();
|
| if (instr != NULL) {
|
| Definition* result = instr->computation()->TryReplace(instr);
|
| - if (result != NULL) {
|
| - // Replace uses and remove the current instructions via the iterator.
|
| - instr->ReplaceUsesWith(result);
|
| + if (result != instr) {
|
| + if (result != NULL) {
|
| + instr->ReplaceUsesWith(result);
|
| + if (FLAG_trace_optimization) {
|
| + OS::Print("Replacing v%d with v%d\n",
|
| + instr->ssa_temp_index(),
|
| + result->ssa_temp_index());
|
| + }
|
| + } else if (FLAG_trace_optimization) {
|
| + OS::Print("Removing v%d.\n", instr->ssa_temp_index());
|
| + }
|
| it.RemoveCurrentFromGraph();
|
| - if (FLAG_trace_optimization) {
|
| - OS::Print("Replacing v%d with v%d\n",
|
| - instr->ssa_temp_index(),
|
| - result->ssa_temp_index());
|
| - }
|
| }
|
| }
|
| }
|
| @@ -194,6 +197,19 @@
|
| }
|
|
|
|
|
| +// Insert a check computation before an instruction and set the environment
|
| +// of the check to the same as the instruction.
|
| +static void InsertCheckBefore(BindInstr* instr,
|
| + Computation* check,
|
| + Environment* env) {
|
| + BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check);
|
| + check_instr->InsertBefore(instr);
|
| + ASSERT(env != NULL);
|
| + // Attach an environment to the check instruction.
|
| + check_instr->set_env(env);
|
| +}
|
| +
|
| +
|
| static void AddCheckClass(BindInstr* instr,
|
| InstanceCallComp* comp,
|
| Value* value) {
|
| @@ -202,11 +218,10 @@
|
| 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.
|
| - // Attach the original environment to the check instruction.
|
| - check_instr->set_env(instr->env());
|
| - check_instr->InsertBefore(instr);
|
| + InsertCheckBefore(instr, check, instr->env());
|
| + // Detach environment from the original instruction because it can't
|
| + // deoptimize.
|
| + instr->set_env(NULL);
|
| }
|
|
|
|
|
| @@ -317,6 +332,14 @@
|
| ASSERT(operands_type == kSmiCid);
|
| Value* left = comp->ArgumentAt(0)->value();
|
| Value* right = comp->ArgumentAt(1)->value();
|
| + // Insert two smi checks and attach a copy of the original
|
| + // environment because the smi operation can still deoptimize.
|
| + InsertCheckBefore(instr,
|
| + new CheckSmiComp(left, comp),
|
| + instr->env()->Copy());
|
| + InsertCheckBefore(instr,
|
| + new CheckSmiComp(right, comp),
|
| + instr->env()->Copy());
|
| BinarySmiOpComp* bin_op = new BinarySmiOpComp(op_kind,
|
| comp,
|
| left,
|
| @@ -391,8 +414,8 @@
|
| String::Handle(Field::NameFromGetter(comp->function_name()));
|
| const Field& field = Field::Handle(GetField(class_ids[0], field_name));
|
| ASSERT(!field.IsNull());
|
| +
|
| AddCheckClass(instr, comp, comp->ArgumentAt(0)->value());
|
| - instr->set_env(NULL);
|
| LoadInstanceFieldComp* load =
|
| new LoadInstanceFieldComp(field,
|
| comp->ArgumentAt(0)->value(),
|
| @@ -573,7 +596,6 @@
|
| ASSERT(!field.IsNull());
|
|
|
| AddCheckClass(instr, comp, comp->ArgumentAt(0)->value());
|
| - instr->set_env(NULL);
|
| StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
|
| field,
|
| comp->ArgumentAt(0)->value(),
|
|
|