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

Side by Side Diff: runtime/vm/flow_graph_builder.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/ast_printer.h" 8 #include "vm/ast_printer.h"
9 #include "vm/bit_vector.h" 9 #include "vm/bit_vector.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 19 matching lines...) Expand all
30 #include "vm/zone.h" 30 #include "vm/zone.h"
31 31
32 namespace dart { 32 namespace dart {
33 33
34 DEFINE_FLAG(bool, eliminate_type_checks, true, 34 DEFINE_FLAG(bool, eliminate_type_checks, true,
35 "Eliminate type checks when allowed by static type analysis."); 35 "Eliminate type checks when allowed by static type analysis.");
36 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); 36 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
37 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); 37 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables.");
38 DEFINE_FLAG(bool, trace_type_check_elimination, false, 38 DEFINE_FLAG(bool, trace_type_check_elimination, false,
39 "Trace type check elimination at compile time."); 39 "Trace type check elimination at compile time.");
40 DEFINE_FLAG(bool, warn_on_javascript_compatibility, false,
41 "Warn on incompatibilities between vm and dart2js.");
40 DECLARE_FLAG(bool, enable_type_checks); 42 DECLARE_FLAG(bool, enable_type_checks);
43 DECLARE_FLAG(bool, warning_as_error);
44 DECLARE_FLAG(bool, silent_warnings);
41 45
42 46
43 // TODO(srdjan): Allow compiler to add constants as they are encountered in 47 // TODO(srdjan): Allow compiler to add constants as they are encountered in
44 // the compilation. 48 // the compilation.
45 const double kCommonDoubleConstants[] = 49 const double kCommonDoubleConstants[] =
46 {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 2.0, 4.0, 5.0, 50 {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 2.0, 4.0, 5.0,
47 10.0, 20.0, 30.0, 64.0, 255.0, NAN, 51 10.0, 20.0, 30.0, 64.0, 255.0, NAN,
48 // From dart:math 52 // From dart:math
49 2.718281828459045, 2.302585092994046, 0.6931471805599453, 53 2.718281828459045, 2.302585092994046, 0.6931471805599453,
50 1.4426950408889634, 0.4342944819032518, 3.1415926535897932, 54 1.4426950408889634, 0.4342944819032518, 3.1415926535897932,
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 true_successor_addresses_.AddArray(for_left.true_successor_addresses_); 953 true_successor_addresses_.AddArray(for_left.true_successor_addresses_);
950 true_successor_addresses_.AddArray(for_right.true_successor_addresses_); 954 true_successor_addresses_.AddArray(for_right.true_successor_addresses_);
951 } 955 }
952 CloseFragment(); 956 CloseFragment();
953 return; 957 return;
954 } 958 }
955 ValueGraphVisitor::VisitBinaryOpNode(node); 959 ValueGraphVisitor::VisitBinaryOpNode(node);
956 } 960 }
957 961
958 962
959 void EffectGraphVisitor::Bailout(const char* reason) { 963 void EffectGraphVisitor::Bailout(const char* reason) const {
960 owner()->Bailout(reason); 964 owner()->Bailout(reason);
961 } 965 }
962 966
963 967
964 void EffectGraphVisitor::InlineBailout(const char* reason) { 968 void EffectGraphVisitor::InlineBailout(const char* reason) const {
965 owner()->parsed_function()->function().set_is_inlinable(false); 969 owner()->parsed_function()->function().set_is_inlinable(false);
966 if (owner()->IsInlining()) owner()->Bailout(reason); 970 if (owner()->IsInlining()) owner()->Bailout(reason);
967 } 971 }
968 972
969 973
970 // <Statement> ::= Return { value: <Expression> 974 // <Statement> ::= Return { value: <Expression>
971 // inlined_finally_list: <InlinedFinally>* } 975 // inlined_finally_list: <InlinedFinally>* }
972 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { 976 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
973 ValueGraphVisitor for_value(owner()); 977 ValueGraphVisitor for_value(owner());
974 node->value()->Visit(&for_value); 978 node->value()->Visit(&for_value);
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 Value* value, 1400 Value* value,
1397 const AbstractType& dst_type, 1401 const AbstractType& dst_type,
1398 const String& dst_name) { 1402 const String& dst_name) {
1399 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { 1403 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) {
1400 return value; 1404 return value;
1401 } 1405 }
1402 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); 1406 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name));
1403 } 1407 }
1404 1408
1405 1409
1410 void FlowGraphBuilder::WarnOnJSIntegralNumTypeTest(
1411 AstNode* node, const AbstractType& type) const {
1412 if (is_optimizing()) {
1413 // Warnings for constants are issued when the graph is built for the first
1414 // time only, i.e. just before generating unoptimized code.
1415 // They should not be repeated when generating optimized code.
1416 return;
1417 }
1418 if (!(node->IsLiteralNode() && (type.IsIntType() || type.IsDoubleType()))) {
1419 return;
1420 }
1421 const Instance& instance = node->AsLiteralNode()->literal();
1422 if (type.IsIntType()) {
1423 if (instance.IsDouble()) {
1424 const Double& double_instance = Double::Cast(instance);
1425 double value = double_instance.value();
1426 if (floor(value) == value) {
1427 Warning(node->token_pos(),
1428 "javascript compatibility warning: integral value of type "
1429 "'double' is also considered to be of type 'int'");
1430 }
1431 }
1432 } else {
1433 ASSERT(type.IsDoubleType());
1434 if (instance.IsInteger()) {
1435 Warning(node->token_pos(),
1436 "javascript compatibility warning: integer value is also "
1437 "considered to be of type 'double'");
1438 }
1439 }
1440 }
1441
1442
1406 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { 1443 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
1407 ASSERT(Token::IsTypeTestOperator(node->kind())); 1444 ASSERT(Token::IsTypeTestOperator(node->kind()));
1408 const AbstractType& type = node->right()->AsTypeNode()->type(); 1445 const AbstractType& type = node->right()->AsTypeNode()->type();
1409 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); 1446 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
1410 const bool negate_result = (node->kind() == Token::kISNOT); 1447 const bool negate_result = (node->kind() == Token::kISNOT);
1411 // All objects are instances of type T if Object type is a subtype of type T. 1448 // All objects are instances of type T if Object type is a subtype of type T.
1412 const Type& object_type = Type::Handle(Type::ObjectType()); 1449 const Type& object_type = Type::Handle(Type::ObjectType());
1413 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) { 1450 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) {
1414 // Must evaluate left side. 1451 // Must evaluate left side.
1415 EffectGraphVisitor for_left_value(owner()); 1452 EffectGraphVisitor for_left_value(owner());
1416 node->left()->Visit(&for_left_value); 1453 node->left()->Visit(&for_left_value);
1417 Append(for_left_value); 1454 Append(for_left_value);
1418 ReturnDefinition(new ConstantInstr(Bool::Get(!negate_result))); 1455 ReturnDefinition(new ConstantInstr(Bool::Get(!negate_result)));
1419 return; 1456 return;
1420 } 1457 }
1458
1459 // Check for javascript compatibility.
1460 if (FLAG_warn_on_javascript_compatibility) {
1461 owner()->WarnOnJSIntegralNumTypeTest(node->left(), type);
1462 }
1463
1421 ValueGraphVisitor for_left_value(owner()); 1464 ValueGraphVisitor for_left_value(owner());
1422 node->left()->Visit(&for_left_value); 1465 node->left()->Visit(&for_left_value);
1423 Append(for_left_value); 1466 Append(for_left_value);
1424 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); 1467 PushArgumentInstr* push_left = PushArgument(for_left_value.value());
1425 PushArgumentInstr* push_instantiator = NULL; 1468 PushArgumentInstr* push_instantiator = NULL;
1426 PushArgumentInstr* push_type_args = NULL; 1469 PushArgumentInstr* push_type_args = NULL;
1427 if (type.IsInstantiated()) { 1470 if (type.IsInstantiated()) {
1428 push_instantiator = PushArgument(BuildNullValue()); 1471 push_instantiator = PushArgument(BuildNullValue());
1429 push_type_args = PushArgument(BuildNullValue()); 1472 push_type_args = PushArgument(BuildNullValue());
1430 } else { 1473 } else {
(...skipping 24 matching lines...) Expand all
1455 owner()->ic_data_array()); 1498 owner()->ic_data_array());
1456 ReturnDefinition(call); 1499 ReturnDefinition(call);
1457 } 1500 }
1458 1501
1459 1502
1460 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { 1503 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
1461 ASSERT(Token::IsTypeCastOperator(node->kind())); 1504 ASSERT(Token::IsTypeCastOperator(node->kind()));
1462 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); 1505 ASSERT(!node->right()->AsTypeNode()->type().IsNull());
1463 const AbstractType& type = node->right()->AsTypeNode()->type(); 1506 const AbstractType& type = node->right()->AsTypeNode()->type();
1464 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); 1507 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
1508
1509 // Check for javascript compatibility.
1510 if (FLAG_warn_on_javascript_compatibility) {
1511 owner()->WarnOnJSIntegralNumTypeTest(node->left(), type);
1512 }
1513
1465 ValueGraphVisitor for_value(owner()); 1514 ValueGraphVisitor for_value(owner());
1466 node->left()->Visit(&for_value); 1515 node->left()->Visit(&for_value);
1467 Append(for_value); 1516 Append(for_value);
1468 const String& dst_name = String::ZoneHandle( 1517 const String& dst_name = String::ZoneHandle(
1469 Symbols::New(Exceptions::kCastErrorDstName)); 1518 Symbols::New(Exceptions::kCastErrorDstName));
1470 if (CanSkipTypeCheck(node->token_pos(), 1519 if (CanSkipTypeCheck(node->token_pos(),
1471 for_value.value(), 1520 for_value.value(),
1472 type, 1521 type,
1473 dst_name)) { 1522 dst_name)) {
1474 ReturnValue(for_value.value()); 1523 ReturnValue(for_value.value());
(...skipping 2407 matching lines...) Expand 10 before | Expand all | Expand 10 after
3882 3931
3883 void FlowGraphBuilder::PruneUnreachable() { 3932 void FlowGraphBuilder::PruneUnreachable() {
3884 ASSERT(osr_id_ != Isolate::kNoDeoptId); 3933 ASSERT(osr_id_ != Isolate::kNoDeoptId);
3885 BitVector* block_marks = new BitVector(last_used_block_id_ + 1); 3934 BitVector* block_marks = new BitVector(last_used_block_id_ + 1);
3886 bool found = graph_entry_->PruneUnreachable(this, graph_entry_, NULL, osr_id_, 3935 bool found = graph_entry_->PruneUnreachable(this, graph_entry_, NULL, osr_id_,
3887 block_marks); 3936 block_marks);
3888 ASSERT(found); 3937 ASSERT(found);
3889 } 3938 }
3890 3939
3891 3940
3941 void FlowGraphBuilder::Warning(intptr_t token_pos,
3942 const char* format, ...) const {
3943 if (FLAG_silent_warnings) return;
3944 const Function& function = parsed_function_->function();
3945 va_list args;
3946 va_start(args, format);
3947 const Error& error = Error::Handle(
3948 LanguageError::NewFormattedV(Error::Handle(), // No previous error.
3949 Script::Handle(function.script()),
3950 token_pos, LanguageError::kWarning,
3951 Heap::kNew, format, args));
3952 va_end(args);
3953 if (FLAG_warning_as_error) {
3954 Isolate::Current()->long_jump_base()->Jump(1, error);
3955 UNREACHABLE();
3956 } else {
3957 OS::Print("%s", error.ToErrorCString());
3958 }
3959 }
3960
3961
3892 void FlowGraphBuilder::Bailout(const char* reason) const { 3962 void FlowGraphBuilder::Bailout(const char* reason) const {
3893 const Function& function = parsed_function_->function(); 3963 const Function& function = parsed_function_->function();
3894 const Error& error = Error::Handle( 3964 const Error& error = Error::Handle(
3895 LanguageError::NewFormatted(Error::Handle(), // No previous error. 3965 LanguageError::NewFormatted(Error::Handle(), // No previous error.
3896 Script::Handle(function.script()), 3966 Script::Handle(function.script()),
3897 function.token_pos(), 3967 function.token_pos(),
3898 LanguageError::kError, 3968 LanguageError::kBailout,
3899 Heap::kNew, 3969 Heap::kNew,
3900 "FlowGraphBuilder Bailout: %s %s", 3970 "FlowGraphBuilder Bailout: %s %s",
3901 String::Handle(function.name()).ToCString(), 3971 String::Handle(function.name()).ToCString(),
3902 reason)); 3972 reason));
3903 Isolate::Current()->long_jump_base()->Jump(1, error); 3973 Isolate::Current()->long_jump_base()->Jump(1, error);
3974 UNREACHABLE();
3904 } 3975 }
3905 3976
3906 } // namespace dart 3977 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698