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 |