| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 DEFINE_FLAG(bool, use_cha_deopt, true, | 45 DEFINE_FLAG(bool, use_cha_deopt, true, |
| 46 "Use class hierarchy analysis even if it can cause deoptimization."); | 46 "Use class hierarchy analysis even if it can cause deoptimization."); |
| 47 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) | 47 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) |
| 48 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); | 48 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); |
| 49 #endif | 49 #endif |
| 50 | 50 |
| 51 DECLARE_FLAG(bool, precompilation); | 51 DECLARE_FLAG(bool, precompilation); |
| 52 DECLARE_FLAG(bool, polymorphic_with_deopt); | 52 DECLARE_FLAG(bool, polymorphic_with_deopt); |
| 53 DECLARE_FLAG(bool, trace_cha); | 53 DECLARE_FLAG(bool, trace_cha); |
| 54 DECLARE_FLAG(bool, trace_field_guards); | 54 DECLARE_FLAG(bool, trace_field_guards); |
| 55 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | |
| 56 | 55 |
| 57 // Quick access to the current isolate and zone. | 56 // Quick access to the current isolate and zone. |
| 58 #define I (isolate()) | 57 #define I (isolate()) |
| 59 #define Z (zone()) | 58 #define Z (zone()) |
| 60 | 59 |
| 61 static bool ShouldInlineSimd() { | 60 static bool ShouldInlineSimd() { |
| 62 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 61 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
| 63 } | 62 } |
| 64 | 63 |
| 65 | 64 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 } | 156 } |
| 158 | 157 |
| 159 | 158 |
| 160 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 159 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| 161 ASSERT(call->HasICData()); | 160 ASSERT(call->HasICData()); |
| 162 if (call->ic_data()->NumberOfUsedChecks() > 0) { | 161 if (call->ic_data()->NumberOfUsedChecks() > 0) { |
| 163 // This occurs when an instance call has too many checks, will be converted | 162 // This occurs when an instance call has too many checks, will be converted |
| 164 // to megamorphic call. | 163 // to megamorphic call. |
| 165 return false; | 164 return false; |
| 166 } | 165 } |
| 167 if (FLAG_warn_on_javascript_compatibility) { | |
| 168 // Do not make the instance call megamorphic if the callee needs to decode | |
| 169 // the calling code sequence to lookup the ic data and verify if a warning | |
| 170 // has already been issued or not. | |
| 171 if (call->ic_data()->MayCheckForJSWarning()) { | |
| 172 return false; | |
| 173 } | |
| 174 } | |
| 175 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); | 166 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); |
| 176 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); | 167 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); |
| 177 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { | 168 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { |
| 178 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); | 169 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); |
| 179 } | 170 } |
| 180 | 171 |
| 181 const Token::Kind op_kind = call->token_kind(); | 172 const Token::Kind op_kind = call->token_kind(); |
| 182 if (Token::IsRelationalOperator(op_kind) || | 173 if (Token::IsRelationalOperator(op_kind) || |
| 183 Token::IsEqualityOperator(op_kind) || | 174 Token::IsEqualityOperator(op_kind) || |
| 184 Token::IsBinaryOperator(op_kind)) { | 175 Token::IsBinaryOperator(op_kind)) { |
| (...skipping 2788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2973 negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition() | 2964 negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition() |
| 2974 ->AsConstant()->value()).value(); | 2965 ->AsConstant()->value()).value(); |
| 2975 } else { | 2966 } else { |
| 2976 type_args = call->ArgumentAt(1); | 2967 type_args = call->ArgumentAt(1); |
| 2977 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); | 2968 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); |
| 2978 negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition() | 2969 negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition() |
| 2979 ->AsConstant()->value()).value(); | 2970 ->AsConstant()->value()).value(); |
| 2980 } | 2971 } |
| 2981 const ICData& unary_checks = | 2972 const ICData& unary_checks = |
| 2982 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 2973 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 2983 if (FLAG_warn_on_javascript_compatibility && | |
| 2984 !unary_checks.IssuedJSWarning() && | |
| 2985 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | |
| 2986 // No warning was reported yet for this type check, either because it has | |
| 2987 // not been executed yet, or because no problematic combinations of instance | |
| 2988 // type and test type have been encountered so far. A warning may still be | |
| 2989 // reported, so do not replace the instance call. | |
| 2990 return; | |
| 2991 } | |
| 2992 if ((unary_checks.NumberOfChecks() > 0) && | 2974 if ((unary_checks.NumberOfChecks() > 0) && |
| 2993 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 2975 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { |
| 2994 ZoneGrowableArray<intptr_t>* results = | 2976 ZoneGrowableArray<intptr_t>* results = |
| 2995 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 2977 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
| 2996 Bool& as_bool = | 2978 Bool& as_bool = |
| 2997 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 2979 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
| 2998 if (as_bool.IsNull()) { | 2980 if (as_bool.IsNull()) { |
| 2999 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 2981 if (results->length() == unary_checks.NumberOfChecks() * 2) { |
| 3000 const bool can_deopt = TryExpandTestCidsResult(results, type); | 2982 const bool can_deopt = TryExpandTestCidsResult(results, type); |
| 3001 TestCidsInstr* test_cids = new(Z) TestCidsInstr( | 2983 TestCidsInstr* test_cids = new(Z) TestCidsInstr( |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3063 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 3045 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
| 3064 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 3046 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 3065 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 3047 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 3066 Definition* left = call->ArgumentAt(0); | 3048 Definition* left = call->ArgumentAt(0); |
| 3067 Definition* type_args = call->ArgumentAt(1); | 3049 Definition* type_args = call->ArgumentAt(1); |
| 3068 const AbstractType& type = | 3050 const AbstractType& type = |
| 3069 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); | 3051 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); |
| 3070 ASSERT(!type.IsMalformedOrMalbounded()); | 3052 ASSERT(!type.IsMalformedOrMalbounded()); |
| 3071 const ICData& unary_checks = | 3053 const ICData& unary_checks = |
| 3072 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 3054 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 3073 if (FLAG_warn_on_javascript_compatibility && | |
| 3074 !unary_checks.IssuedJSWarning() && | |
| 3075 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | |
| 3076 // No warning was reported yet for this type check, either because it has | |
| 3077 // not been executed yet, or because no problematic combinations of instance | |
| 3078 // type and test type have been encountered so far. A warning may still be | |
| 3079 // reported, so do not replace the instance call. | |
| 3080 return; | |
| 3081 } | |
| 3082 if ((unary_checks.NumberOfChecks() > 0) && | 3055 if ((unary_checks.NumberOfChecks() > 0) && |
| 3083 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 3056 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { |
| 3084 ZoneGrowableArray<intptr_t>* results = | 3057 ZoneGrowableArray<intptr_t>* results = |
| 3085 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 3058 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
| 3086 const Bool& as_bool = Bool::ZoneHandle(Z, | 3059 const Bool& as_bool = Bool::ZoneHandle(Z, |
| 3087 InstanceOfAsBool(unary_checks, type, results)); | 3060 InstanceOfAsBool(unary_checks, type, results)); |
| 3088 if (as_bool.raw() == Bool::True().raw()) { | 3061 if (as_bool.raw() == Bool::True().raw()) { |
| 3089 AddReceiverCheck(call); | 3062 AddReceiverCheck(call); |
| 3090 // Remove the original push arguments. | 3063 // Remove the original push arguments. |
| 3091 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 3064 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| (...skipping 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3982 // the code for this instruction, however, leaving the environment | 3955 // the code for this instruction, however, leaving the environment |
| 3983 // changes code. | 3956 // changes code. |
| 3984 current->RemoveEnvironment(); | 3957 current->RemoveEnvironment(); |
| 3985 } | 3958 } |
| 3986 } | 3959 } |
| 3987 } | 3960 } |
| 3988 } | 3961 } |
| 3989 | 3962 |
| 3990 | 3963 |
| 3991 } // namespace dart | 3964 } // namespace dart |
| OLD | NEW |