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 |