| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/compiler.h" |
| 9 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 11 #include "vm/exceptions.h" | 12 #include "vm/exceptions.h" |
| 12 #include "vm/flow_graph_builder.h" | 13 #include "vm/flow_graph_builder.h" |
| 13 #include "vm/flow_graph_compiler.h" | 14 #include "vm/flow_graph_compiler.h" |
| 14 #include "vm/flow_graph_range_analysis.h" | 15 #include "vm/flow_graph_range_analysis.h" |
| 15 #include "vm/hash_map.h" | 16 #include "vm/hash_map.h" |
| 16 #include "vm/il_printer.h" | 17 #include "vm/il_printer.h" |
| 17 #include "vm/intermediate_language.h" | 18 #include "vm/intermediate_language.h" |
| 18 #include "vm/object_store.h" | 19 #include "vm/object_store.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 #endif | 81 #endif |
| 81 } | 82 } |
| 82 | 83 |
| 83 | 84 |
| 84 // Optimize instance calls using ICData. | 85 // Optimize instance calls using ICData. |
| 85 void FlowGraphOptimizer::ApplyICData() { | 86 void FlowGraphOptimizer::ApplyICData() { |
| 86 VisitBlocks(); | 87 VisitBlocks(); |
| 87 } | 88 } |
| 88 | 89 |
| 89 | 90 |
| 91 void FlowGraphOptimizer::PopulateWithICData() { |
| 92 ASSERT(current_iterator_ == NULL); |
| 93 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 94 BlockEntryInstr* entry = block_order_[i]; |
| 95 ForwardInstructionIterator it(entry); |
| 96 for (; !it.Done(); it.Advance()) { |
| 97 Instruction* instr = it.Current(); |
| 98 if (instr->IsInstanceCall()) { |
| 99 InstanceCallInstr* call = instr->AsInstanceCall(); |
| 100 if (!call->HasICData()) { |
| 101 const Array& arguments_descriptor = |
| 102 Array::Handle(zone(), |
| 103 ArgumentsDescriptor::New(call->ArgumentCount(), |
| 104 call->argument_names())); |
| 105 const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New( |
| 106 function(), call->function_name(), |
| 107 arguments_descriptor, call->deopt_id(), |
| 108 call->checked_argument_count())); |
| 109 call->set_ic_data(&ic_data); |
| 110 } |
| 111 } |
| 112 } |
| 113 current_iterator_ = NULL; |
| 114 } |
| 115 } |
| 116 |
| 117 |
| 90 // Optimize instance calls using cid. This is called after optimizer | 118 // Optimize instance calls using cid. This is called after optimizer |
| 91 // converted instance calls to instructions. Any remaining | 119 // converted instance calls to instructions. Any remaining |
| 92 // instance calls are either megamorphic calls, cannot be optimized or | 120 // instance calls are either megamorphic calls, cannot be optimized or |
| 93 // have no runtime type feedback collected. | 121 // have no runtime type feedback collected. |
| 94 // Attempts to convert an instance call (IC call) using propagated class-ids, | 122 // Attempts to convert an instance call (IC call) using propagated class-ids, |
| 95 // e.g., receiver class id, guarded-cid, or by guessing cid-s. | 123 // e.g., receiver class id, guarded-cid, or by guessing cid-s. |
| 96 void FlowGraphOptimizer::ApplyClassIds() { | 124 void FlowGraphOptimizer::ApplyClassIds() { |
| 97 ASSERT(current_iterator_ == NULL); | 125 ASSERT(current_iterator_ == NULL); |
| 98 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 126 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 99 BlockEntryInstr* entry = block_order_[i]; | 127 BlockEntryInstr* entry = block_order_[i]; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); | 183 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); |
| 156 class_ids.Add(cid); | 184 class_ids.Add(cid); |
| 157 } | 185 } |
| 158 | 186 |
| 159 const Token::Kind op_kind = call->token_kind(); | 187 const Token::Kind op_kind = call->token_kind(); |
| 160 if (Token::IsRelationalOperator(op_kind) || | 188 if (Token::IsRelationalOperator(op_kind) || |
| 161 Token::IsEqualityOperator(op_kind) || | 189 Token::IsEqualityOperator(op_kind) || |
| 162 Token::IsBinaryOperator(op_kind)) { | 190 Token::IsBinaryOperator(op_kind)) { |
| 163 // Guess cid: if one of the inputs is a number assume that the other | 191 // Guess cid: if one of the inputs is a number assume that the other |
| 164 // is a number of same type. | 192 // is a number of same type. |
| 165 const intptr_t cid_0 = class_ids[0]; | 193 if (Compiler::guess_other_cid()) { |
| 166 const intptr_t cid_1 = class_ids[1]; | 194 const intptr_t cid_0 = class_ids[0]; |
| 167 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { | 195 const intptr_t cid_1 = class_ids[1]; |
| 168 class_ids[0] = cid_1; | 196 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { |
| 169 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { | 197 class_ids[0] = cid_1; |
| 170 class_ids[1] = cid_0; | 198 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { |
| 199 class_ids[1] = cid_0; |
| 200 } |
| 171 } | 201 } |
| 172 } | 202 } |
| 173 | 203 |
| 174 for (intptr_t i = 0; i < class_ids.length(); i++) { | 204 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 175 if (class_ids[i] == kDynamicCid) { | 205 if (class_ids[i] == kDynamicCid) { |
| 176 // Not all cid-s known. | 206 // Not all cid-s known. |
| 177 return false; | 207 return false; |
| 178 } | 208 } |
| 179 } | 209 } |
| 180 | 210 |
| (...skipping 2075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 const String& name = (kind == RawFunction::kMethodExtractor) | 2286 const String& name = (kind == RawFunction::kMethodExtractor) |
| 2257 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) | 2287 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) |
| 2258 : call->function_name(); | 2288 : call->function_name(); |
| 2259 return thread()->cha()->HasOverride(Class::Handle(Z, function.Owner()), | 2289 return thread()->cha()->HasOverride(Class::Handle(Z, function.Owner()), |
| 2260 name); | 2290 name); |
| 2261 } | 2291 } |
| 2262 return true; | 2292 return true; |
| 2263 } | 2293 } |
| 2264 | 2294 |
| 2265 | 2295 |
| 2266 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { | 2296 bool FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call, |
| 2297 bool allow_check) { |
| 2267 ASSERT(call->HasICData()); | 2298 ASSERT(call->HasICData()); |
| 2268 const ICData& ic_data = *call->ic_data(); | 2299 const ICData& ic_data = *call->ic_data(); |
| 2269 ASSERT(ic_data.HasOneTarget()); | 2300 ASSERT(ic_data.HasOneTarget()); |
| 2270 Function& target = Function::Handle(Z); | 2301 Function& target = Function::Handle(Z); |
| 2271 GrowableArray<intptr_t> class_ids; | 2302 GrowableArray<intptr_t> class_ids; |
| 2272 ic_data.GetCheckAt(0, &class_ids, &target); | 2303 ic_data.GetCheckAt(0, &class_ids, &target); |
| 2273 ASSERT(class_ids.length() == 1); | 2304 ASSERT(class_ids.length() == 1); |
| 2274 // Inline implicit instance getter. | 2305 // Inline implicit instance getter. |
| 2275 const String& field_name = | 2306 const String& field_name = |
| 2276 String::Handle(Z, Field::NameFromGetter(call->function_name())); | 2307 String::Handle(Z, Field::NameFromGetter(call->function_name())); |
| 2277 const Field& field = | 2308 const Field& field = |
| 2278 Field::ZoneHandle(Z, GetField(class_ids[0], field_name)); | 2309 Field::ZoneHandle(Z, GetField(class_ids[0], field_name)); |
| 2279 ASSERT(!field.IsNull()); | 2310 ASSERT(!field.IsNull()); |
| 2280 | 2311 |
| 2281 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) { | 2312 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) { |
| 2313 if (!allow_check) { |
| 2314 return false; |
| 2315 } |
| 2282 AddReceiverCheck(call); | 2316 AddReceiverCheck(call); |
| 2283 } | 2317 } |
| 2284 LoadFieldInstr* load = new(Z) LoadFieldInstr( | 2318 LoadFieldInstr* load = new(Z) LoadFieldInstr( |
| 2285 new(Z) Value(call->ArgumentAt(0)), | 2319 new(Z) Value(call->ArgumentAt(0)), |
| 2286 &field, | 2320 &field, |
| 2287 AbstractType::ZoneHandle(Z, field.type()), | 2321 AbstractType::ZoneHandle(Z, field.type()), |
| 2288 call->token_pos()); | 2322 call->token_pos()); |
| 2289 load->set_is_immutable(field.is_final()); | 2323 load->set_is_immutable(field.is_final()); |
| 2290 if (field.guarded_cid() != kIllegalCid) { | 2324 if (field.guarded_cid() != kIllegalCid) { |
| 2291 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 2325 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
| 2292 load->set_result_cid(field.guarded_cid()); | 2326 load->set_result_cid(field.guarded_cid()); |
| 2293 } | 2327 } |
| 2294 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 2328 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 2295 } | 2329 } |
| 2296 | 2330 |
| 2297 // Discard the environment from the original instruction because the load | 2331 // Discard the environment from the original instruction because the load |
| 2298 // can't deoptimize. | 2332 // can't deoptimize. |
| 2299 call->RemoveEnvironment(); | 2333 call->RemoveEnvironment(); |
| 2300 ReplaceCall(call, load); | 2334 ReplaceCall(call, load); |
| 2301 | 2335 |
| 2302 if (load->result_cid() != kDynamicCid) { | 2336 if (load->result_cid() != kDynamicCid) { |
| 2303 // Reset value types if guarded_cid was used. | 2337 // Reset value types if guarded_cid was used. |
| 2304 for (Value::Iterator it(load->input_use_list()); | 2338 for (Value::Iterator it(load->input_use_list()); |
| 2305 !it.Done(); | 2339 !it.Done(); |
| 2306 it.Advance()) { | 2340 it.Advance()) { |
| 2307 it.Current()->SetReachingType(NULL); | 2341 it.Current()->SetReachingType(NULL); |
| 2308 } | 2342 } |
| 2309 } | 2343 } |
| 2344 return true; |
| 2310 } | 2345 } |
| 2311 | 2346 |
| 2312 | 2347 |
| 2313 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 2348 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
| 2314 MethodRecognizer::Kind getter) { | 2349 MethodRecognizer::Kind getter) { |
| 2315 if (!ShouldInlineSimd()) { | 2350 if (!ShouldInlineSimd()) { |
| 2316 return false; | 2351 return false; |
| 2317 } | 2352 } |
| 2318 AddCheckClass(call->ArgumentAt(0), | 2353 AddCheckClass(call->ArgumentAt(0), |
| 2319 ICData::ZoneHandle( | 2354 ICData::ZoneHandle( |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2577 BinaryFloat64x2OpInstr* float64x2_bin_op = | 2612 BinaryFloat64x2OpInstr* float64x2_bin_op = |
| 2578 new(Z) BinaryFloat64x2OpInstr( | 2613 new(Z) BinaryFloat64x2OpInstr( |
| 2579 op_kind, new(Z) Value(left), new(Z) Value(right), | 2614 op_kind, new(Z) Value(left), new(Z) Value(right), |
| 2580 call->deopt_id()); | 2615 call->deopt_id()); |
| 2581 ReplaceCall(call, float64x2_bin_op); | 2616 ReplaceCall(call, float64x2_bin_op); |
| 2582 return true; | 2617 return true; |
| 2583 } | 2618 } |
| 2584 | 2619 |
| 2585 | 2620 |
| 2586 // Only unique implicit instance getters can be currently handled. | 2621 // Only unique implicit instance getters can be currently handled. |
| 2587 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 2622 // Returns false if 'allow_check' is false and a check is needed. |
| 2623 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call, |
| 2624 bool allow_check) { |
| 2588 ASSERT(call->HasICData()); | 2625 ASSERT(call->HasICData()); |
| 2589 const ICData& ic_data = *call->ic_data(); | 2626 const ICData& ic_data = *call->ic_data(); |
| 2590 if (ic_data.NumberOfUsedChecks() == 0) { | 2627 if (ic_data.NumberOfUsedChecks() == 0) { |
| 2591 // No type feedback collected. | 2628 // No type feedback collected. |
| 2592 return false; | 2629 return false; |
| 2593 } | 2630 } |
| 2594 | 2631 |
| 2595 if (!ic_data.HasOneTarget()) { | 2632 if (!ic_data.HasOneTarget()) { |
| 2596 // Polymorphic sites are inlined like normal methods by conventional | 2633 // Polymorphic sites are inlined like normal methods by conventional |
| 2597 // inlining in FlowGraphInliner. | 2634 // inlining in FlowGraphInliner. |
| 2598 return false; | 2635 return false; |
| 2599 } | 2636 } |
| 2600 | 2637 |
| 2601 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0)); | 2638 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0)); |
| 2602 if (target.kind() != RawFunction::kImplicitGetter) { | 2639 if (target.kind() != RawFunction::kImplicitGetter) { |
| 2603 // Non-implicit getters are inlined like normal methods by conventional | 2640 // Non-implicit getters are inlined like normal methods by conventional |
| 2604 // inlining in FlowGraphInliner. | 2641 // inlining in FlowGraphInliner. |
| 2605 return false; | 2642 return false; |
| 2606 } | 2643 } |
| 2607 InlineImplicitInstanceGetter(call); | 2644 return InlineImplicitInstanceGetter(call, allow_check); |
| 2608 return true; | |
| 2609 } | 2645 } |
| 2610 | 2646 |
| 2611 | 2647 |
| 2612 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( | 2648 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( |
| 2613 InstanceCallInstr* call) { | 2649 InstanceCallInstr* call) { |
| 2614 Function& target = Function::Handle(Z); | 2650 Function& target = Function::Handle(Z); |
| 2615 GrowableArray<intptr_t> class_ids; | 2651 GrowableArray<intptr_t> class_ids; |
| 2616 call->ic_data()->GetCheckAt(0, &class_ids, &target); | 2652 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2617 const intptr_t receiver_cid = class_ids[0]; | 2653 const intptr_t receiver_cid = class_ids[0]; |
| 2618 | 2654 |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3119 return true; | 3155 return true; |
| 3120 } | 3156 } |
| 3121 } | 3157 } |
| 3122 return false; | 3158 return false; |
| 3123 } | 3159 } |
| 3124 | 3160 |
| 3125 | 3161 |
| 3126 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( | 3162 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( |
| 3127 StaticCallInstr* call, | 3163 StaticCallInstr* call, |
| 3128 MethodRecognizer::Kind recognized_kind) { | 3164 MethodRecognizer::Kind recognized_kind) { |
| 3165 if (Compiler::always_optimize()) { |
| 3166 // Cannot handle unboxed instructions. |
| 3167 return false; |
| 3168 } |
| 3129 if (!ShouldInlineSimd()) { | 3169 if (!ShouldInlineSimd()) { |
| 3130 return false; | 3170 return false; |
| 3131 } | 3171 } |
| 3132 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { | 3172 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { |
| 3133 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr(); | 3173 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr(); |
| 3134 ReplaceCall(call, zero); | 3174 ReplaceCall(call, zero); |
| 3135 return true; | 3175 return true; |
| 3136 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { | 3176 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { |
| 3137 Float32x4SplatInstr* splat = | 3177 Float32x4SplatInstr* splat = |
| 3138 new(Z) Float32x4SplatInstr( | 3178 new(Z) Float32x4SplatInstr( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3162 ReplaceCall(call, cast); | 3202 ReplaceCall(call, cast); |
| 3163 return true; | 3203 return true; |
| 3164 } | 3204 } |
| 3165 return false; | 3205 return false; |
| 3166 } | 3206 } |
| 3167 | 3207 |
| 3168 | 3208 |
| 3169 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( | 3209 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( |
| 3170 StaticCallInstr* call, | 3210 StaticCallInstr* call, |
| 3171 MethodRecognizer::Kind recognized_kind) { | 3211 MethodRecognizer::Kind recognized_kind) { |
| 3212 if (Compiler::always_optimize()) { |
| 3213 // Cannot handle unboxed instructions. |
| 3214 return false; |
| 3215 } |
| 3172 if (!ShouldInlineSimd()) { | 3216 if (!ShouldInlineSimd()) { |
| 3173 return false; | 3217 return false; |
| 3174 } | 3218 } |
| 3175 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { | 3219 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { |
| 3176 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr(); | 3220 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr(); |
| 3177 ReplaceCall(call, zero); | 3221 ReplaceCall(call, zero); |
| 3178 return true; | 3222 return true; |
| 3179 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { | 3223 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { |
| 3180 Float64x2SplatInstr* splat = | 3224 Float64x2SplatInstr* splat = |
| 3181 new(Z) Float64x2SplatInstr( | 3225 new(Z) Float64x2SplatInstr( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3197 ReplaceCall(call, cast); | 3241 ReplaceCall(call, cast); |
| 3198 return true; | 3242 return true; |
| 3199 } | 3243 } |
| 3200 return false; | 3244 return false; |
| 3201 } | 3245 } |
| 3202 | 3246 |
| 3203 | 3247 |
| 3204 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( | 3248 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( |
| 3205 StaticCallInstr* call, | 3249 StaticCallInstr* call, |
| 3206 MethodRecognizer::Kind recognized_kind) { | 3250 MethodRecognizer::Kind recognized_kind) { |
| 3251 if (Compiler::always_optimize()) { |
| 3252 // Cannot handle unboxed instructions. |
| 3253 return false; |
| 3254 } |
| 3207 if (!ShouldInlineSimd()) { | 3255 if (!ShouldInlineSimd()) { |
| 3208 return false; | 3256 return false; |
| 3209 } | 3257 } |
| 3210 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { | 3258 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { |
| 3211 Int32x4BoolConstructorInstr* con = | 3259 Int32x4BoolConstructorInstr* con = |
| 3212 new(Z) Int32x4BoolConstructorInstr( | 3260 new(Z) Int32x4BoolConstructorInstr( |
| 3213 new(Z) Value(call->ArgumentAt(1)), | 3261 new(Z) Value(call->ArgumentAt(1)), |
| 3214 new(Z) Value(call->ArgumentAt(2)), | 3262 new(Z) Value(call->ArgumentAt(2)), |
| 3215 new(Z) Value(call->ArgumentAt(3)), | 3263 new(Z) Value(call->ArgumentAt(3)), |
| 3216 new(Z) Value(call->ArgumentAt(4)), | 3264 new(Z) Value(call->ArgumentAt(4)), |
| (...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4145 | 4193 |
| 4146 | 4194 |
| 4147 // Tries to optimize instance call by replacing it with a faster instruction | 4195 // Tries to optimize instance call by replacing it with a faster instruction |
| 4148 // (e.g, binary op, field load, ..). | 4196 // (e.g, binary op, field load, ..). |
| 4149 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 4197 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 4150 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { | 4198 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { |
| 4151 return; | 4199 return; |
| 4152 } | 4200 } |
| 4153 | 4201 |
| 4154 const Token::Kind op_kind = instr->token_kind(); | 4202 const Token::Kind op_kind = instr->token_kind(); |
| 4203 if (Compiler::always_optimize()) { |
| 4204 // TODO(srdjan): Investigate other attempts, as they are not allowed to |
| 4205 // deoptimize. |
| 4206 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, false)) { |
| 4207 return; |
| 4208 } |
| 4209 return; |
| 4210 } |
| 4211 |
| 4155 // Type test is special as it always gets converted into inlined code. | 4212 // Type test is special as it always gets converted into inlined code. |
| 4156 if (Token::IsTypeTestOperator(op_kind)) { | 4213 if (Token::IsTypeTestOperator(op_kind)) { |
| 4157 ReplaceWithInstanceOf(instr); | 4214 ReplaceWithInstanceOf(instr); |
| 4158 return; | 4215 return; |
| 4159 } | 4216 } |
| 4160 | 4217 |
| 4161 if (Token::IsTypeCastOperator(op_kind)) { | 4218 if (Token::IsTypeCastOperator(op_kind)) { |
| 4162 ReplaceWithTypeCast(instr); | 4219 ReplaceWithTypeCast(instr); |
| 4163 return; | 4220 return; |
| 4164 } | 4221 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4268 unary_kind = MathUnaryInstr::kSin; | 4325 unary_kind = MathUnaryInstr::kSin; |
| 4269 break; | 4326 break; |
| 4270 case MethodRecognizer::kMathCos: | 4327 case MethodRecognizer::kMathCos: |
| 4271 unary_kind = MathUnaryInstr::kCos; | 4328 unary_kind = MathUnaryInstr::kCos; |
| 4272 break; | 4329 break; |
| 4273 default: | 4330 default: |
| 4274 unary_kind = MathUnaryInstr::kIllegal; | 4331 unary_kind = MathUnaryInstr::kIllegal; |
| 4275 break; | 4332 break; |
| 4276 } | 4333 } |
| 4277 if (unary_kind != MathUnaryInstr::kIllegal) { | 4334 if (unary_kind != MathUnaryInstr::kIllegal) { |
| 4278 MathUnaryInstr* math_unary = | 4335 if (Compiler::always_optimize()) { |
| 4279 new(Z) MathUnaryInstr(unary_kind, | 4336 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well. |
| 4280 new(Z) Value(call->ArgumentAt(0)), | 4337 } else { |
| 4281 call->deopt_id()); | 4338 MathUnaryInstr* math_unary = |
| 4282 ReplaceCall(call, math_unary); | 4339 new(Z) MathUnaryInstr(unary_kind, |
| 4340 new(Z) Value(call->ArgumentAt(0)), |
| 4341 call->deopt_id()); |
| 4342 ReplaceCall(call, math_unary); |
| 4343 } |
| 4283 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || | 4344 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || |
| 4284 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || | 4345 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || |
| 4285 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) || | 4346 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) || |
| 4286 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) { | 4347 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) { |
| 4287 TryInlineFloat32x4Constructor(call, recognized_kind); | 4348 TryInlineFloat32x4Constructor(call, recognized_kind); |
| 4288 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) || | 4349 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) || |
| 4289 (recognized_kind == MethodRecognizer::kFloat64x2Zero) || | 4350 (recognized_kind == MethodRecognizer::kFloat64x2Zero) || |
| 4290 (recognized_kind == MethodRecognizer::kFloat64x2Splat) || | 4351 (recognized_kind == MethodRecognizer::kFloat64x2Splat) || |
| 4291 (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) { | 4352 (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) { |
| 4292 TryInlineFloat64x2Constructor(call, recognized_kind); | 4353 TryInlineFloat64x2Constructor(call, recognized_kind); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4333 call); | 4394 call); |
| 4334 AddCheckClass(min_max->right()->definition(), | 4395 AddCheckClass(min_max->right()->definition(), |
| 4335 unary_checks, | 4396 unary_checks, |
| 4336 call->deopt_id(), | 4397 call->deopt_id(), |
| 4337 call->env(), | 4398 call->env(), |
| 4338 call); | 4399 call); |
| 4339 ReplaceCall(call, min_max); | 4400 ReplaceCall(call, min_max); |
| 4340 } | 4401 } |
| 4341 } | 4402 } |
| 4342 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { | 4403 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { |
| 4404 if (Compiler::always_optimize()) { |
| 4405 // No UnboxDouble instructons allowed. |
| 4406 return; |
| 4407 } |
| 4343 // We know that first argument is double, the second is num. | 4408 // We know that first argument is double, the second is num. |
| 4344 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble | 4409 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble |
| 4345 // instructions contain type checks and conversions to double. | 4410 // instructions contain type checks and conversions to double. |
| 4346 ZoneGrowableArray<Value*>* args = | 4411 ZoneGrowableArray<Value*>* args = |
| 4347 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); | 4412 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
| 4348 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 4413 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
| 4349 args->Add(new(Z) Value(call->ArgumentAt(i))); | 4414 args->Add(new(Z) Value(call->ArgumentAt(i))); |
| 4350 } | 4415 } |
| 4351 InvokeMathCFunctionInstr* invoke = | 4416 InvokeMathCFunctionInstr* invoke = |
| 4352 new(Z) InvokeMathCFunctionInstr(args, | 4417 new(Z) InvokeMathCFunctionInstr(args, |
| (...skipping 4228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8581 | 8646 |
| 8582 // Insert materializations at environment uses. | 8647 // Insert materializations at environment uses. |
| 8583 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8648 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8584 CreateMaterializationAt( | 8649 CreateMaterializationAt( |
| 8585 exits_collector_.exits()[i], alloc, *slots); | 8650 exits_collector_.exits()[i], alloc, *slots); |
| 8586 } | 8651 } |
| 8587 } | 8652 } |
| 8588 | 8653 |
| 8589 | 8654 |
| 8590 } // namespace dart | 8655 } // namespace dart |
| OLD | NEW |