| Index: runtime/vm/flow_graph_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
|
| index 2b7eecc01579dd628e0973ae19db35e9fd6ac02c..2784d9696372aec32e278fe58d218496a6eff6da 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/flow_graph_optimizer.cc
|
| @@ -28,6 +28,8 @@ DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
|
| DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress");
|
| DEFINE_FLAG(bool, trace_constant_propagation, false,
|
| "Print constant propagation and useless code elimination.");
|
| +DEFINE_FLAG(bool, array_bounds_check_elimination, true,
|
| + "Eliminate redundant bounds checks.");
|
|
|
|
|
| void FlowGraphOptimizer::ApplyICData() {
|
| @@ -915,7 +917,8 @@ void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
|
|
|
| void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call,
|
| intptr_t length_offset,
|
| - bool is_immutable) {
|
| + bool is_immutable,
|
| + MethodRecognizer::Kind kind) {
|
| // Check receiver class.
|
| AddCheckClass(call, call->ArgumentAt(0)->value()->Copy());
|
|
|
| @@ -925,6 +928,7 @@ void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call,
|
| Type::ZoneHandle(Type::SmiType()),
|
| is_immutable);
|
| load->set_result_cid(kSmiCid);
|
| + load->set_recognized_kind(kind);
|
| call->ReplaceWith(load, current_iterator());
|
| RemovePushArguments(call);
|
| }
|
| @@ -947,6 +951,7 @@ void FlowGraphOptimizer::InlineGArrayCapacityGetter(InstanceCallInstr* call) {
|
| Array::length_offset(),
|
| Type::ZoneHandle(Type::SmiType()));
|
| length_load->set_result_cid(kSmiCid);
|
| + length_load->set_recognized_kind(MethodRecognizer::kObjectArrayLength);
|
|
|
| call->ReplaceWith(length_load, current_iterator());
|
| RemovePushArguments(call);
|
| @@ -1027,12 +1032,16 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
|
| switch (recognized_kind) {
|
| case MethodRecognizer::kObjectArrayLength:
|
| case MethodRecognizer::kImmutableArrayLength:
|
| - InlineArrayLengthGetter(call, Array::length_offset(), true);
|
| + InlineArrayLengthGetter(call,
|
| + Array::length_offset(),
|
| + true,
|
| + recognized_kind);
|
| break;
|
| case MethodRecognizer::kGrowableArrayLength:
|
| InlineArrayLengthGetter(call,
|
| GrowableObjectArray::length_offset(),
|
| - false);
|
| + false,
|
| + recognized_kind);
|
| break;
|
| default:
|
| UNREACHABLE();
|
| @@ -2100,11 +2109,17 @@ void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) {
|
| }
|
|
|
| for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
|
| - Definition* defn = it.Current()->AsDefinition();
|
| + Instruction* current = it.Current();
|
| +
|
| + Definition* defn = current->AsDefinition();
|
| if ((defn != NULL) &&
|
| (defn->ssa_temp_index() != -1) &&
|
| smi_definitions_->Contains(defn->ssa_temp_index())) {
|
| defn->InferRange();
|
| + } else if (FLAG_array_bounds_check_elimination &&
|
| + current->IsCheckArrayBound() &&
|
| + current->AsCheckArrayBound()->IsRedundant()) {
|
| + it.RemoveCurrentFromGraph();
|
| }
|
| }
|
|
|
|
|