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

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

Issue 347873002: Ensure that a javascript compatibility warning results in a (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 6 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 23 matching lines...) Expand all
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 40
41 DECLARE_FLAG(bool, enable_debugger); 41 DECLARE_FLAG(bool, enable_debugger);
42 DECLARE_FLAG(bool, enable_type_checks); 42 DECLARE_FLAG(bool, enable_type_checks);
43 DECLARE_FLAG(int, optimization_counter_threshold); 43 DECLARE_FLAG(int, optimization_counter_threshold);
44 DECLARE_FLAG(bool, silent_warnings);
45 DECLARE_FLAG(bool, warn_on_javascript_compatibility); 44 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
46 DECLARE_FLAG(bool, warning_as_error);
47 45
48 // Quick access to the locally defined isolate() method. 46 // Quick access to the locally defined isolate() method.
49 #define I (isolate()) 47 #define I (isolate())
50 48
51 // TODO(srdjan): Allow compiler to add constants as they are encountered in 49 // TODO(srdjan): Allow compiler to add constants as they are encountered in
52 // the compilation. 50 // the compilation.
53 const double kCommonDoubleConstants[] = 51 const double kCommonDoubleConstants[] =
54 {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 2.0, 4.0, 5.0, 52 {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 2.0, 4.0, 5.0,
55 10.0, 20.0, 30.0, 64.0, 255.0, NAN, 53 10.0, 20.0, 30.0, 64.0, 255.0, NAN,
56 // From dart:math 54 // From dart:math
(...skipping 1352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1409 Value* value, 1407 Value* value,
1410 const AbstractType& dst_type, 1408 const AbstractType& dst_type,
1411 const String& dst_name) { 1409 const String& dst_name) {
1412 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { 1410 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) {
1413 return value; 1411 return value;
1414 } 1412 }
1415 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); 1413 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name));
1416 } 1414 }
1417 1415
1418 1416
1419 void FlowGraphBuilder::WarnOnJSIntegralNumTypeTest( 1417 bool FlowGraphBuilder::WarnOnJSIntegralNumTypeTest(
1420 AstNode* node, const AbstractType& type) const { 1418 AstNode* node, const AbstractType& type) const {
1421 if (is_optimizing()) {
1422 // Warnings for constants are issued when the graph is built for the first
1423 // time only, i.e. just before generating unoptimized code.
1424 // They should not be repeated when generating optimized code.
1425 return;
1426 }
1427 if (!(node->IsLiteralNode() && (type.IsIntType() || type.IsDoubleType()))) { 1419 if (!(node->IsLiteralNode() && (type.IsIntType() || type.IsDoubleType()))) {
1428 return; 1420 return false;
1429 } 1421 }
1430 const Instance& instance = node->AsLiteralNode()->literal(); 1422 const Instance& instance = node->AsLiteralNode()->literal();
1431 if (type.IsIntType()) { 1423 if (type.IsIntType()) {
1432 if (instance.IsDouble()) { 1424 if (instance.IsDouble()) {
1433 const Double& double_instance = Double::Cast(instance); 1425 const Double& double_instance = Double::Cast(instance);
1434 double value = double_instance.value(); 1426 double value = double_instance.value();
1435 if (floor(value) == value) { 1427 if (floor(value) == value) {
1436 JSWarning(node->token_pos(), 1428 return true;
1437 "integral value of type 'double' is also considered "
1438 "to be of type 'int'");
1439 } 1429 }
1440 } 1430 }
1441 } else { 1431 } else {
1442 ASSERT(type.IsDoubleType()); 1432 ASSERT(type.IsDoubleType());
1443 if (instance.IsInteger()) { 1433 if (instance.IsInteger()) {
1444 JSWarning(node->token_pos(), 1434 return true;
1445 "integer value is also considered to be of type 'double'");
1446 } 1435 }
1447 } 1436 }
1437 return false;
1448 } 1438 }
1449 1439
1450 1440
1451 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { 1441 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
1452 ASSERT(Token::IsTypeTestOperator(node->kind())); 1442 ASSERT(Token::IsTypeTestOperator(node->kind()));
1453 const AbstractType& type = node->right()->AsTypeNode()->type(); 1443 const AbstractType& type = node->right()->AsTypeNode()->type();
1454 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); 1444 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
1455 const bool negate_result = (node->kind() == Token::kISNOT); 1445 const bool negate_result = (node->kind() == Token::kISNOT);
1456 // All objects are instances of type T if Object type is a subtype of type T. 1446 // All objects are instances of type T if Object type is a subtype of type T.
1457 const Type& object_type = Type::Handle(I, Type::ObjectType()); 1447 const Type& object_type = Type::Handle(I, Type::ObjectType());
1458 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) { 1448 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) {
1459 // Must evaluate left side. 1449 // Must evaluate left side.
1460 EffectGraphVisitor for_left_value(owner()); 1450 EffectGraphVisitor for_left_value(owner());
1461 node->left()->Visit(&for_left_value); 1451 node->left()->Visit(&for_left_value);
1462 Append(for_left_value); 1452 Append(for_left_value);
1463 ReturnDefinition(new ConstantInstr(Bool::Get(!negate_result))); 1453 ReturnDefinition(new ConstantInstr(Bool::Get(!negate_result)));
1464 return; 1454 return;
1465 } 1455 }
1466
1467 // Check for javascript compatibility.
1468 if (FLAG_warn_on_javascript_compatibility) {
1469 owner()->WarnOnJSIntegralNumTypeTest(node->left(), type);
1470 }
1471
1472 ValueGraphVisitor for_left_value(owner()); 1456 ValueGraphVisitor for_left_value(owner());
1473 node->left()->Visit(&for_left_value); 1457 node->left()->Visit(&for_left_value);
1474 Append(for_left_value); 1458 Append(for_left_value);
1475 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); 1459 PushArgumentInstr* push_left = PushArgument(for_left_value.value());
1476 PushArgumentInstr* push_instantiator = NULL; 1460 PushArgumentInstr* push_instantiator = NULL;
1477 PushArgumentInstr* push_type_args = NULL; 1461 PushArgumentInstr* push_type_args = NULL;
1478 if (type.IsInstantiated()) { 1462 if (type.IsInstantiated()) {
1479 push_instantiator = PushArgument(BuildNullValue()); 1463 push_instantiator = PushArgument(BuildNullValue());
1480 push_type_args = PushArgument(BuildNullValue()); 1464 push_type_args = PushArgument(BuildNullValue());
1481 } else { 1465 } else {
(...skipping 24 matching lines...) Expand all
1506 owner()->ic_data_array()); 1490 owner()->ic_data_array());
1507 ReturnDefinition(call); 1491 ReturnDefinition(call);
1508 } 1492 }
1509 1493
1510 1494
1511 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { 1495 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
1512 ASSERT(Token::IsTypeCastOperator(node->kind())); 1496 ASSERT(Token::IsTypeCastOperator(node->kind()));
1513 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); 1497 ASSERT(!node->right()->AsTypeNode()->type().IsNull());
1514 const AbstractType& type = node->right()->AsTypeNode()->type(); 1498 const AbstractType& type = node->right()->AsTypeNode()->type();
1515 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); 1499 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
1516
1517 // Check for javascript compatibility.
1518 if (FLAG_warn_on_javascript_compatibility) {
1519 owner()->WarnOnJSIntegralNumTypeTest(node->left(), type);
1520 }
1521
1522 ValueGraphVisitor for_value(owner()); 1500 ValueGraphVisitor for_value(owner());
1523 node->left()->Visit(&for_value); 1501 node->left()->Visit(&for_value);
1524 Append(for_value); 1502 Append(for_value);
1525 const String& dst_name = String::ZoneHandle( 1503 const String& dst_name = String::ZoneHandle(
1526 I, Symbols::New(Exceptions::kCastErrorDstName)); 1504 I, Symbols::New(Exceptions::kCastErrorDstName));
1527 if (CanSkipTypeCheck(node->token_pos(), 1505 if (CanSkipTypeCheck(node->token_pos(),
1528 for_value.value(), 1506 for_value.value(),
1529 type, 1507 type,
1530 dst_name)) { 1508 dst_name)) {
1531 ReturnValue(for_value.value()); 1509 // Check for javascript compatibility.
1532 return; 1510 // Do not skip type check if javascript compatibility warning is required.
1511 if (!FLAG_warn_on_javascript_compatibility ||
1512 !owner()->WarnOnJSIntegralNumTypeTest(node->left(), type)) {
1513 ReturnValue(for_value.value());
1514 return;
1515 }
1533 } 1516 }
1534 PushArgumentInstr* push_left = PushArgument(for_value.value()); 1517 PushArgumentInstr* push_left = PushArgument(for_value.value());
1535 PushArgumentInstr* push_instantiator = NULL; 1518 PushArgumentInstr* push_instantiator = NULL;
1536 PushArgumentInstr* push_type_args = NULL; 1519 PushArgumentInstr* push_type_args = NULL;
1537 if (type.IsInstantiated()) { 1520 if (type.IsInstantiated()) {
1538 push_instantiator = PushArgument(BuildNullValue()); 1521 push_instantiator = PushArgument(BuildNullValue());
1539 push_type_args = PushArgument(BuildNullValue()); 1522 push_type_args = PushArgument(BuildNullValue());
1540 } else { 1523 } else {
1541 BuildTypecheckPushArguments(node->token_pos(), 1524 BuildTypecheckPushArguments(node->token_pos(),
1542 &push_instantiator, 1525 &push_instantiator,
(...skipping 2410 matching lines...) Expand 10 before | Expand all | Expand 10 after
3953 3936
3954 void FlowGraphBuilder::PruneUnreachable() { 3937 void FlowGraphBuilder::PruneUnreachable() {
3955 ASSERT(osr_id_ != Isolate::kNoDeoptId); 3938 ASSERT(osr_id_ != Isolate::kNoDeoptId);
3956 BitVector* block_marks = new BitVector(last_used_block_id_ + 1); 3939 BitVector* block_marks = new BitVector(last_used_block_id_ + 1);
3957 bool found = graph_entry_->PruneUnreachable(this, graph_entry_, NULL, osr_id_, 3940 bool found = graph_entry_->PruneUnreachable(this, graph_entry_, NULL, osr_id_,
3958 block_marks); 3941 block_marks);
3959 ASSERT(found); 3942 ASSERT(found);
3960 } 3943 }
3961 3944
3962 3945
3963 void FlowGraphBuilder::JSWarning(intptr_t token_pos, const char* msg) const {
3964 const Script& script = Script::Handle(parsed_function_->function().script());
3965 if (FLAG_warning_as_error) {
3966 // Report::kJSWarning would result in a JavascriptCompatibilityError, but we
3967 // want a compile-time error.
3968 // TODO(regis): Should we change the expection and make the tests work with
3969 // a JavascriptCompatibilityError?
3970 Report::MessageF(Report::kWarning, script, token_pos, "%s", msg);
3971 UNREACHABLE();
3972 }
3973 Report::MessageF(Report::kJSWarning, script, token_pos, "%s", msg);
3974 }
3975
3976
3977 void FlowGraphBuilder::Bailout(const char* reason) const { 3946 void FlowGraphBuilder::Bailout(const char* reason) const {
3978 const Function& function = parsed_function_->function(); 3947 const Function& function = parsed_function_->function();
3979 Report::MessageF(Report::kBailout, 3948 Report::MessageF(Report::kBailout,
3980 Script::Handle(function.script()), 3949 Script::Handle(function.script()),
3981 function.token_pos(), 3950 function.token_pos(),
3982 "FlowGraphBuilder Bailout: %s %s", 3951 "FlowGraphBuilder Bailout: %s %s",
3983 String::Handle(function.name()).ToCString(), 3952 String::Handle(function.name()).ToCString(),
3984 reason); 3953 reason);
3985 UNREACHABLE(); 3954 UNREACHABLE();
3986 } 3955 }
3987 3956
3988 } // namespace dart 3957 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | tests/standalone/javascript_compatibility_errors_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698