Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(901)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 260713008: Add support for javascript incompatibility warnings. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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_compatibility);
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
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_compatibility) {
116 // Do not make the instance call megamorphic if the callee needs to decode
117 // the calling code sequence to lookup the ic data and verify if a warning
118 // has already been issued or not.
119 // TryCreateICData is only invoked if the ic_data target has not been called
120 // yet, so no warning can possibly have been issued.
121 ASSERT(!call->ic_data()->IssuedJSWarning());
122 if (call->ic_data()->MayCheckForJSWarning()) {
123 return false;
124 }
125 }
113 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); 126 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
114 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); 127 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount());
115 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { 128 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
116 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); 129 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid();
117 class_ids.Add(cid); 130 class_ids.Add(cid);
118 } 131 }
119 132
120 const Token::Kind op_kind = call->token_kind(); 133 const Token::Kind op_kind = call->token_kind();
121 if (Token::IsRelationalOperator(op_kind) || 134 if (Token::IsRelationalOperator(op_kind) ||
122 Token::IsEqualityOperator(op_kind) || 135 Token::IsEqualityOperator(op_kind) ||
(...skipping 3742 matching lines...) Expand 10 before | Expand all | Expand 10 after
3865 ASSERT(Token::IsTypeTestOperator(call->token_kind())); 3878 ASSERT(Token::IsTypeTestOperator(call->token_kind()));
3866 Definition* left = call->ArgumentAt(0); 3879 Definition* left = call->ArgumentAt(0);
3867 Definition* instantiator = call->ArgumentAt(1); 3880 Definition* instantiator = call->ArgumentAt(1);
3868 Definition* type_args = call->ArgumentAt(2); 3881 Definition* type_args = call->ArgumentAt(2);
3869 const AbstractType& type = 3882 const AbstractType& type =
3870 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); 3883 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
3871 const bool negate = Bool::Cast( 3884 const bool negate = Bool::Cast(
3872 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); 3885 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value();
3873 const ICData& unary_checks = 3886 const ICData& unary_checks =
3874 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); 3887 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks());
3888 if (FLAG_warn_on_javascript_compatibility &&
3889 !unary_checks.IssuedJSWarning() &&
3890 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
3891 // No warning was reported yet for this type check, either because it has
3892 // not been executed yet, or because no problematic combinations of instance
3893 // type and test type have been encountered so far. A warning may still be
3894 // reported, so do not replace the instance call.
3895 return;
3896 }
3875 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 3897 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
3876 ZoneGrowableArray<intptr_t>* results = 3898 ZoneGrowableArray<intptr_t>* results =
3877 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); 3899 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
3878 Bool& as_bool = 3900 Bool& as_bool =
3879 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); 3901 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results));
3880 if (as_bool.IsNull()) { 3902 if (as_bool.IsNull()) {
3881 if (results->length() == unary_checks.NumberOfChecks() * 2) { 3903 if (results->length() == unary_checks.NumberOfChecks() * 2) {
3882 const bool can_deopt = TryExpandTestCidsResult(results, type); 3904 const bool can_deopt = TryExpandTestCidsResult(results, type);
3883 TestCidsInstr* test_cids = new TestCidsInstr( 3905 TestCidsInstr* test_cids = new TestCidsInstr(
3884 call->token_pos(), 3906 call->token_pos(),
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3946 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { 3968 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
3947 ASSERT(Token::IsTypeCastOperator(call->token_kind())); 3969 ASSERT(Token::IsTypeCastOperator(call->token_kind()));
3948 Definition* left = call->ArgumentAt(0); 3970 Definition* left = call->ArgumentAt(0);
3949 Definition* instantiator = call->ArgumentAt(1); 3971 Definition* instantiator = call->ArgumentAt(1);
3950 Definition* type_args = call->ArgumentAt(2); 3972 Definition* type_args = call->ArgumentAt(2);
3951 const AbstractType& type = 3973 const AbstractType& type =
3952 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); 3974 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
3953 ASSERT(!type.IsMalformedOrMalbounded()); 3975 ASSERT(!type.IsMalformedOrMalbounded());
3954 const ICData& unary_checks = 3976 const ICData& unary_checks =
3955 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); 3977 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks());
3978 if (FLAG_warn_on_javascript_compatibility &&
3979 !unary_checks.IssuedJSWarning() &&
3980 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
3981 // No warning was reported yet for this type check, either because it has
3982 // not been executed yet, or because no problematic combinations of instance
3983 // type and test type have been encountered so far. A warning may still be
3984 // reported, so do not replace the instance call.
3985 return;
3986 }
3956 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 3987 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
3957 ZoneGrowableArray<intptr_t>* results = 3988 ZoneGrowableArray<intptr_t>* results =
3958 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); 3989 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
3959 const Bool& as_bool = 3990 const Bool& as_bool =
3960 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); 3991 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results));
3961 if (as_bool.raw() == Bool::True().raw()) { 3992 if (as_bool.raw() == Bool::True().raw()) {
3962 AddReceiverCheck(call); 3993 AddReceiverCheck(call);
3963 // Remove the original push arguments. 3994 // Remove the original push arguments.
3964 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 3995 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
3965 PushArgumentInstr* push = call->PushArgumentAt(i); 3996 PushArgumentInstr* push = call->PushArgumentAt(i);
(...skipping 5552 matching lines...) Expand 10 before | Expand all | Expand 10 after
9518 } 9549 }
9519 9550
9520 // Insert materializations at environment uses. 9551 // Insert materializations at environment uses.
9521 for (intptr_t i = 0; i < exits.length(); i++) { 9552 for (intptr_t i = 0; i < exits.length(); i++) {
9522 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); 9553 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots);
9523 } 9554 }
9524 } 9555 }
9525 9556
9526 9557
9527 } // namespace dart 9558 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698