| 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/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 DEFINE_FLAG(bool, use_cha_deopt, true, | 44 DEFINE_FLAG(bool, use_cha_deopt, true, |
| 45 "Use class hierarchy analysis even if it can cause deoptimization."); | 45 "Use class hierarchy analysis even if it can cause deoptimization."); |
| 46 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) | 46 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) |
| 47 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); | 47 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); |
| 48 #endif | 48 #endif |
| 49 | 49 |
| 50 DECLARE_FLAG(bool, precompilation); | 50 DECLARE_FLAG(bool, precompilation); |
| 51 DECLARE_FLAG(bool, polymorphic_with_deopt); | 51 DECLARE_FLAG(bool, polymorphic_with_deopt); |
| 52 DECLARE_FLAG(bool, trace_cha); | 52 DECLARE_FLAG(bool, trace_cha); |
| 53 DECLARE_FLAG(bool, trace_field_guards); | 53 DECLARE_FLAG(bool, trace_field_guards); |
| 54 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | |
| 55 | 54 |
| 56 // Quick access to the current isolate and zone. | 55 // Quick access to the current isolate and zone. |
| 57 #define I (isolate()) | 56 #define I (isolate()) |
| 58 #define Z (zone()) | 57 #define Z (zone()) |
| 59 | 58 |
| 60 static bool ShouldInlineSimd() { | 59 static bool ShouldInlineSimd() { |
| 61 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 60 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
| 62 } | 61 } |
| 63 | 62 |
| 64 | 63 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 } | 162 } |
| 164 | 163 |
| 165 | 164 |
| 166 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 165 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| 167 ASSERT(call->HasICData()); | 166 ASSERT(call->HasICData()); |
| 168 if (call->ic_data()->NumberOfUsedChecks() > 0) { | 167 if (call->ic_data()->NumberOfUsedChecks() > 0) { |
| 169 // This occurs when an instance call has too many checks, will be converted | 168 // This occurs when an instance call has too many checks, will be converted |
| 170 // to megamorphic call. | 169 // to megamorphic call. |
| 171 return false; | 170 return false; |
| 172 } | 171 } |
| 173 if (FLAG_warn_on_javascript_compatibility) { | |
| 174 // Do not make the instance call megamorphic if the callee needs to decode | |
| 175 // the calling code sequence to lookup the ic data and verify if a warning | |
| 176 // has already been issued or not. | |
| 177 if (call->ic_data()->MayCheckForJSWarning()) { | |
| 178 return false; | |
| 179 } | |
| 180 } | |
| 181 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); | 172 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); |
| 182 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); | 173 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); |
| 183 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { | 174 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { |
| 184 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); | 175 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); |
| 185 } | 176 } |
| 186 | 177 |
| 187 const Token::Kind op_kind = call->token_kind(); | 178 const Token::Kind op_kind = call->token_kind(); |
| 188 if (Token::IsRelationalOperator(op_kind) || | 179 if (Token::IsRelationalOperator(op_kind) || |
| 189 Token::IsEqualityOperator(op_kind) || | 180 Token::IsEqualityOperator(op_kind) || |
| 190 Token::IsBinaryOperator(op_kind)) { | 181 Token::IsBinaryOperator(op_kind)) { |
| (...skipping 3820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4011 negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition() | 4002 negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition() |
| 4012 ->AsConstant()->value()).value(); | 4003 ->AsConstant()->value()).value(); |
| 4013 } else { | 4004 } else { |
| 4014 type_args = call->ArgumentAt(1); | 4005 type_args = call->ArgumentAt(1); |
| 4015 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); | 4006 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); |
| 4016 negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition() | 4007 negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition() |
| 4017 ->AsConstant()->value()).value(); | 4008 ->AsConstant()->value()).value(); |
| 4018 } | 4009 } |
| 4019 const ICData& unary_checks = | 4010 const ICData& unary_checks = |
| 4020 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 4011 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 4021 if (FLAG_warn_on_javascript_compatibility && | |
| 4022 !unary_checks.IssuedJSWarning() && | |
| 4023 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | |
| 4024 // No warning was reported yet for this type check, either because it has | |
| 4025 // not been executed yet, or because no problematic combinations of instance | |
| 4026 // type and test type have been encountered so far. A warning may still be | |
| 4027 // reported, so do not replace the instance call. | |
| 4028 return; | |
| 4029 } | |
| 4030 if ((unary_checks.NumberOfChecks() > 0) && | 4012 if ((unary_checks.NumberOfChecks() > 0) && |
| 4031 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 4013 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { |
| 4032 ZoneGrowableArray<intptr_t>* results = | 4014 ZoneGrowableArray<intptr_t>* results = |
| 4033 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 4015 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
| 4034 Bool& as_bool = | 4016 Bool& as_bool = |
| 4035 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 4017 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
| 4036 if (as_bool.IsNull()) { | 4018 if (as_bool.IsNull()) { |
| 4037 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 4019 if (results->length() == unary_checks.NumberOfChecks() * 2) { |
| 4038 const bool can_deopt = TryExpandTestCidsResult(results, type); | 4020 const bool can_deopt = TryExpandTestCidsResult(results, type); |
| 4039 TestCidsInstr* test_cids = new(Z) TestCidsInstr( | 4021 TestCidsInstr* test_cids = new(Z) TestCidsInstr( |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4101 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 4083 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
| 4102 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 4084 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 4103 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 4085 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 4104 Definition* left = call->ArgumentAt(0); | 4086 Definition* left = call->ArgumentAt(0); |
| 4105 Definition* type_args = call->ArgumentAt(1); | 4087 Definition* type_args = call->ArgumentAt(1); |
| 4106 const AbstractType& type = | 4088 const AbstractType& type = |
| 4107 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); | 4089 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); |
| 4108 ASSERT(!type.IsMalformedOrMalbounded()); | 4090 ASSERT(!type.IsMalformedOrMalbounded()); |
| 4109 const ICData& unary_checks = | 4091 const ICData& unary_checks = |
| 4110 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 4092 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 4111 if (FLAG_warn_on_javascript_compatibility && | |
| 4112 !unary_checks.IssuedJSWarning() && | |
| 4113 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | |
| 4114 // No warning was reported yet for this type check, either because it has | |
| 4115 // not been executed yet, or because no problematic combinations of instance | |
| 4116 // type and test type have been encountered so far. A warning may still be | |
| 4117 // reported, so do not replace the instance call. | |
| 4118 return; | |
| 4119 } | |
| 4120 if ((unary_checks.NumberOfChecks() > 0) && | 4093 if ((unary_checks.NumberOfChecks() > 0) && |
| 4121 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 4094 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { |
| 4122 ZoneGrowableArray<intptr_t>* results = | 4095 ZoneGrowableArray<intptr_t>* results = |
| 4123 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 4096 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
| 4124 const Bool& as_bool = Bool::ZoneHandle(Z, | 4097 const Bool& as_bool = Bool::ZoneHandle(Z, |
| 4125 InstanceOfAsBool(unary_checks, type, results)); | 4098 InstanceOfAsBool(unary_checks, type, results)); |
| 4126 if (as_bool.raw() == Bool::True().raw()) { | 4099 if (as_bool.raw() == Bool::True().raw()) { |
| 4127 AddReceiverCheck(call); | 4100 AddReceiverCheck(call); |
| 4128 // Remove the original push arguments. | 4101 // Remove the original push arguments. |
| 4129 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 4102 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| (...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5022 // the code for this instruction, however, leaving the environment | 4995 // the code for this instruction, however, leaving the environment |
| 5023 // changes code. | 4996 // changes code. |
| 5024 current->RemoveEnvironment(); | 4997 current->RemoveEnvironment(); |
| 5025 } | 4998 } |
| 5026 } | 4999 } |
| 5027 } | 5000 } |
| 5028 } | 5001 } |
| 5029 | 5002 |
| 5030 | 5003 |
| 5031 } // namespace dart | 5004 } // namespace dart |
| OLD | NEW |