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 |