| 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/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| 11 #include "vm/exceptions.h" |
| 11 #include "vm/flow_graph_builder.h" | 12 #include "vm/flow_graph_builder.h" |
| 12 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/hash_map.h" | 14 #include "vm/hash_map.h" |
| 14 #include "vm/il_printer.h" | 15 #include "vm/il_printer.h" |
| 15 #include "vm/intermediate_language.h" | 16 #include "vm/intermediate_language.h" |
| 16 #include "vm/object_store.h" | 17 #include "vm/object_store.h" |
| 17 #include "vm/parser.h" | 18 #include "vm/parser.h" |
| 18 #include "vm/resolver.h" | 19 #include "vm/resolver.h" |
| 19 #include "vm/scopes.h" | 20 #include "vm/scopes.h" |
| 20 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 40 "Print live sets for load optimization pass."); | 41 "Print live sets for load optimization pass."); |
| 41 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); | 42 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
| 42 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); | 43 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); |
| 43 DEFINE_FLAG(bool, truncating_left_shift, true, | 44 DEFINE_FLAG(bool, truncating_left_shift, true, |
| 44 "Optimize left shift to truncate if possible"); | 45 "Optimize left shift to truncate if possible"); |
| 45 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); | 46 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
| 46 DECLARE_FLAG(bool, eliminate_type_checks); | 47 DECLARE_FLAG(bool, eliminate_type_checks); |
| 47 DECLARE_FLAG(bool, enable_type_checks); | 48 DECLARE_FLAG(bool, enable_type_checks); |
| 48 DECLARE_FLAG(bool, source_lines); | 49 DECLARE_FLAG(bool, source_lines); |
| 49 DECLARE_FLAG(bool, trace_type_check_elimination); | 50 DECLARE_FLAG(bool, trace_type_check_elimination); |
| 51 DECLARE_FLAG(bool, warn_on_javascript_incompatibility); |
| 50 | 52 |
| 51 static bool ShouldInlineSimd() { | 53 static bool ShouldInlineSimd() { |
| 52 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 54 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
| 53 } | 55 } |
| 54 | 56 |
| 55 | 57 |
| 56 // Optimize instance calls using ICData. | 58 // Optimize instance calls using ICData. |
| 57 void FlowGraphOptimizer::ApplyICData() { | 59 void FlowGraphOptimizer::ApplyICData() { |
| 58 VisitBlocks(); | 60 VisitBlocks(); |
| 59 } | 61 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 | 105 |
| 104 | 106 |
| 105 // Attempt to build ICData for call using propagated class-ids. | 107 // Attempt to build ICData for call using propagated class-ids. |
| 106 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 108 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| 107 ASSERT(call->HasICData()); | 109 ASSERT(call->HasICData()); |
| 108 if (call->ic_data()->NumberOfChecks() > 0) { | 110 if (call->ic_data()->NumberOfChecks() > 0) { |
| 109 // This occurs when an instance call has too many checks, will be converted | 111 // This occurs when an instance call has too many checks, will be converted |
| 110 // to megamorphic call. | 112 // to megamorphic call. |
| 111 return false; | 113 return false; |
| 112 } | 114 } |
| 115 if (FLAG_warn_on_javascript_incompatibility && |
| 116 Exceptions::MayIssueJSWarning(*call->ic_data(), true)) { |
| 117 return false; |
| 118 } |
| 113 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); | 119 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); |
| 114 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); | 120 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); |
| 115 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { | 121 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { |
| 116 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); | 122 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); |
| 117 class_ids.Add(cid); | 123 class_ids.Add(cid); |
| 118 } | 124 } |
| 119 | 125 |
| 120 const Token::Kind op_kind = call->token_kind(); | 126 const Token::Kind op_kind = call->token_kind(); |
| 121 if (Token::IsRelationalOperator(op_kind) || | 127 if (Token::IsRelationalOperator(op_kind) || |
| 122 Token::IsEqualityOperator(op_kind) || | 128 Token::IsEqualityOperator(op_kind) || |
| (...skipping 3742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3865 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 3871 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| 3866 Definition* left = call->ArgumentAt(0); | 3872 Definition* left = call->ArgumentAt(0); |
| 3867 Definition* instantiator = call->ArgumentAt(1); | 3873 Definition* instantiator = call->ArgumentAt(1); |
| 3868 Definition* type_args = call->ArgumentAt(2); | 3874 Definition* type_args = call->ArgumentAt(2); |
| 3869 const AbstractType& type = | 3875 const AbstractType& type = |
| 3870 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 3876 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
| 3871 const bool negate = Bool::Cast( | 3877 const bool negate = Bool::Cast( |
| 3872 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); | 3878 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); |
| 3873 const ICData& unary_checks = | 3879 const ICData& unary_checks = |
| 3874 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); | 3880 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); |
| 3881 if (FLAG_warn_on_javascript_incompatibility && |
| 3882 !unary_checks.IssuedJSWarning() && |
| 3883 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
| 3884 // No warning was reported yet for this type check, either because it has |
| 3885 // not been executed yet, or because no problematic combinations of instance |
| 3886 // type and test type have been encountered so far. A warning may still be |
| 3887 // reported, so do not replace the instance call. |
| 3888 return; |
| 3889 } |
| 3875 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 3890 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
| 3876 ZoneGrowableArray<intptr_t>* results = | 3891 ZoneGrowableArray<intptr_t>* results = |
| 3877 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 3892 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
| 3878 Bool& as_bool = | 3893 Bool& as_bool = |
| 3879 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); | 3894 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); |
| 3880 if (as_bool.IsNull()) { | 3895 if (as_bool.IsNull()) { |
| 3881 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 3896 if (results->length() == unary_checks.NumberOfChecks() * 2) { |
| 3882 const bool can_deopt = TryExpandTestCidsResult(results, type); | 3897 const bool can_deopt = TryExpandTestCidsResult(results, type); |
| 3883 TestCidsInstr* test_cids = new TestCidsInstr( | 3898 TestCidsInstr* test_cids = new TestCidsInstr( |
| 3884 call->token_pos(), | 3899 call->token_pos(), |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3946 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 3961 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 3947 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 3962 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 3948 Definition* left = call->ArgumentAt(0); | 3963 Definition* left = call->ArgumentAt(0); |
| 3949 Definition* instantiator = call->ArgumentAt(1); | 3964 Definition* instantiator = call->ArgumentAt(1); |
| 3950 Definition* type_args = call->ArgumentAt(2); | 3965 Definition* type_args = call->ArgumentAt(2); |
| 3951 const AbstractType& type = | 3966 const AbstractType& type = |
| 3952 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 3967 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
| 3953 ASSERT(!type.IsMalformedOrMalbounded()); | 3968 ASSERT(!type.IsMalformedOrMalbounded()); |
| 3954 const ICData& unary_checks = | 3969 const ICData& unary_checks = |
| 3955 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); | 3970 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); |
| 3971 if (FLAG_warn_on_javascript_incompatibility && |
| 3972 !unary_checks.IssuedJSWarning() && |
| 3973 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
| 3974 // No warning was reported yet for this type check, either because it has |
| 3975 // not been executed yet, or because no problematic combinations of instance |
| 3976 // type and test type have been encountered so far. A warning may still be |
| 3977 // reported, so do not replace the instance call. |
| 3978 return; |
| 3979 } |
| 3956 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 3980 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
| 3957 ZoneGrowableArray<intptr_t>* results = | 3981 ZoneGrowableArray<intptr_t>* results = |
| 3958 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 3982 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
| 3959 const Bool& as_bool = | 3983 const Bool& as_bool = |
| 3960 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); | 3984 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); |
| 3961 if (as_bool.raw() == Bool::True().raw()) { | 3985 if (as_bool.raw() == Bool::True().raw()) { |
| 3962 AddReceiverCheck(call); | 3986 AddReceiverCheck(call); |
| 3963 // Remove the original push arguments. | 3987 // Remove the original push arguments. |
| 3964 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 3988 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 3965 PushArgumentInstr* push = call->PushArgumentAt(i); | 3989 PushArgumentInstr* push = call->PushArgumentAt(i); |
| (...skipping 5552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9518 } | 9542 } |
| 9519 | 9543 |
| 9520 // Insert materializations at environment uses. | 9544 // Insert materializations at environment uses. |
| 9521 for (intptr_t i = 0; i < exits.length(); i++) { | 9545 for (intptr_t i = 0; i < exits.length(); i++) { |
| 9522 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9546 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
| 9523 } | 9547 } |
| 9524 } | 9548 } |
| 9525 | 9549 |
| 9526 | 9550 |
| 9527 } // namespace dart | 9551 } // namespace dart |
| OLD | NEW |