Index: runtime/vm/flow_graph_builder.cc |
=================================================================== |
--- runtime/vm/flow_graph_builder.cc (revision 36000) |
+++ runtime/vm/flow_graph_builder.cc (working copy) |
@@ -37,7 +37,11 @@ |
DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); |
DEFINE_FLAG(bool, trace_type_check_elimination, false, |
"Trace type check elimination at compile time."); |
+DEFINE_FLAG(bool, warn_on_javascript_compatibility, false, |
+ "Warn on incompatibilities between vm and dart2js."); |
DECLARE_FLAG(bool, enable_type_checks); |
+DECLARE_FLAG(bool, warning_as_error); |
+DECLARE_FLAG(bool, silent_warnings); |
// TODO(srdjan): Allow compiler to add constants as they are encountered in |
@@ -956,12 +960,12 @@ |
} |
-void EffectGraphVisitor::Bailout(const char* reason) { |
+void EffectGraphVisitor::Bailout(const char* reason) const { |
owner()->Bailout(reason); |
} |
-void EffectGraphVisitor::InlineBailout(const char* reason) { |
+void EffectGraphVisitor::InlineBailout(const char* reason) const { |
owner()->parsed_function()->function().set_is_inlinable(false); |
if (owner()->IsInlining()) owner()->Bailout(reason); |
} |
@@ -1403,6 +1407,39 @@ |
} |
+void FlowGraphBuilder::WarnOnJSIntegralNumTypeTest( |
+ AstNode* node, const AbstractType& type) const { |
+ if (is_optimizing()) { |
+ // Warnings for constants are issued when the graph is built for the first |
+ // time only, i.e. just before generating unoptimized code. |
+ // They should not be repeated when generating optimized code. |
+ return; |
+ } |
+ if (!(node->IsLiteralNode() && (type.IsIntType() || type.IsDoubleType()))) { |
+ return; |
+ } |
+ const Instance& instance = node->AsLiteralNode()->literal(); |
+ if (type.IsIntType()) { |
+ if (instance.IsDouble()) { |
+ const Double& double_instance = Double::Cast(instance); |
+ double value = double_instance.value(); |
+ if (floor(value) == value) { |
+ Warning(node->token_pos(), |
+ "javascript compatibility warning: integral value of type " |
+ "'double' is also considered to be of type 'int'"); |
+ } |
+ } |
+ } else { |
+ ASSERT(type.IsDoubleType()); |
+ if (instance.IsInteger()) { |
+ Warning(node->token_pos(), |
+ "javascript compatibility warning: integer value is also " |
+ "considered to be of type 'double'"); |
+ } |
+ } |
+} |
+ |
+ |
void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { |
ASSERT(Token::IsTypeTestOperator(node->kind())); |
const AbstractType& type = node->right()->AsTypeNode()->type(); |
@@ -1418,6 +1455,12 @@ |
ReturnDefinition(new ConstantInstr(Bool::Get(!negate_result))); |
return; |
} |
+ |
+ // Check for javascript compatibility. |
+ if (FLAG_warn_on_javascript_compatibility) { |
+ owner()->WarnOnJSIntegralNumTypeTest(node->left(), type); |
+ } |
+ |
ValueGraphVisitor for_left_value(owner()); |
node->left()->Visit(&for_left_value); |
Append(for_left_value); |
@@ -1462,6 +1505,12 @@ |
ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
const AbstractType& type = node->right()->AsTypeNode()->type(); |
ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); |
+ |
+ // Check for javascript compatibility. |
+ if (FLAG_warn_on_javascript_compatibility) { |
+ owner()->WarnOnJSIntegralNumTypeTest(node->left(), type); |
+ } |
+ |
ValueGraphVisitor for_value(owner()); |
node->left()->Visit(&for_value); |
Append(for_value); |
@@ -3889,18 +3938,40 @@ |
} |
+void FlowGraphBuilder::Warning(intptr_t token_pos, |
+ const char* format, ...) const { |
+ if (FLAG_silent_warnings) return; |
+ const Function& function = parsed_function_->function(); |
+ va_list args; |
+ va_start(args, format); |
+ const Error& error = Error::Handle( |
+ LanguageError::NewFormattedV(Error::Handle(), // No previous error. |
+ Script::Handle(function.script()), |
+ token_pos, LanguageError::kWarning, |
+ Heap::kNew, format, args)); |
+ va_end(args); |
+ if (FLAG_warning_as_error) { |
+ Isolate::Current()->long_jump_base()->Jump(1, error); |
+ UNREACHABLE(); |
+ } else { |
+ OS::Print("%s", error.ToErrorCString()); |
+ } |
+} |
+ |
+ |
void FlowGraphBuilder::Bailout(const char* reason) const { |
const Function& function = parsed_function_->function(); |
const Error& error = Error::Handle( |
LanguageError::NewFormatted(Error::Handle(), // No previous error. |
Script::Handle(function.script()), |
function.token_pos(), |
- LanguageError::kError, |
+ LanguageError::kBailout, |
Heap::kNew, |
"FlowGraphBuilder Bailout: %s %s", |
String::Handle(function.name()).ToCString(), |
reason)); |
Isolate::Current()->long_jump_base()->Jump(1, error); |
+ UNREACHABLE(); |
} |
} // namespace dart |