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

Unified Diff: runtime/vm/object.cc

Issue 23190035: Distinguish between malformed and malbounded types (fix issues 12552 and 12554). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 26566)
+++ runtime/vm/object.cc (working copy)
@@ -61,6 +61,7 @@
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, trace_deoptimization);
DECLARE_FLAG(bool, trace_deoptimization_verbose);
+DECLARE_FLAG(bool, error_on_malformed_type);
DECLARE_FLAG(bool, error_on_bad_override);
static const char* kGetterPrefix = "get:";
@@ -1751,7 +1752,7 @@
TypeParameter& type_param = reused_handles.TypeParameterHandle();
String& type_param_name = reused_handles.StringHandle();
if (!type_params.IsNull()) {
- intptr_t num_type_params = type_params.Length();
+ const intptr_t num_type_params = type_params.Length();
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
type_param_name = type_param.name();
@@ -3034,7 +3035,7 @@
intptr_t AbstractTypeArguments::Hash() const {
if (IsNull()) return 0;
uword result = 0;
- intptr_t num_types = Length();
+ const intptr_t num_types = Length();
AbstractType& type = AbstractType::Handle();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
@@ -3080,7 +3081,7 @@
if (other.IsNull()) {
return false;
}
- intptr_t num_types = Length();
+ const intptr_t num_types = Length();
if (num_types != other.Length()) {
return false;
}
@@ -3209,7 +3210,7 @@
bool TypeArguments::IsResolved() const {
AbstractType& type = AbstractType::Handle();
- intptr_t num_types = Length();
+ const intptr_t num_types = Length();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
if (!type.IsResolved()) {
@@ -3222,7 +3223,7 @@
bool TypeArguments::IsInstantiated() const {
AbstractType& type = AbstractType::Handle();
- intptr_t num_types = Length();
+ const intptr_t num_types = Length();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
ASSERT(!type.IsNull());
@@ -3320,7 +3321,7 @@
bool TypeArguments::IsBounded() const {
AbstractType& type = AbstractType::Handle();
- intptr_t num_types = Length();
+ const intptr_t num_types = Length();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
if (type.IsBoundedType()) {
@@ -4766,7 +4767,7 @@
if (!type_parameters.IsNull()) {
const String& function_class_name = String::Handle(function_class.Name());
pieces.Add(function_class_name);
- intptr_t num_type_parameters = type_parameters.Length();
+ const intptr_t num_type_parameters = type_parameters.Length();
pieces.Add(Symbols::LAngleBracket());
TypeParameter& type_parameter = TypeParameter::Handle();
AbstractType& bound = AbstractType::Handle();
@@ -8330,7 +8331,7 @@
GetHandlerInfo(i, &info);
handled_types = GetHandledTypes(i);
ASSERT(!handled_types.IsNull());
- intptr_t num_types = handled_types.Length();
+ const intptr_t num_types = handled_types.Length();
len += OS::SNPrint(NULL, 0, kFormat,
i,
info.handler_pc,
@@ -8349,7 +8350,7 @@
for (intptr_t i = 0; i < Length(); i++) {
GetHandlerInfo(i, &info);
handled_types = GetHandledTypes(i);
- intptr_t num_types = handled_types.Length();
+ const intptr_t num_types = handled_types.Length();
num_chars += OS::SNPrint((buffer + num_chars),
(len - num_chars),
kFormat,
@@ -10228,12 +10229,14 @@
}
+// TODO(regis): Rename malformed_error to bound_error.
bool Instance::IsInstanceOf(const AbstractType& other,
const AbstractTypeArguments& other_instantiator,
Error* malformed_error) const {
ASSERT(other.IsFinalized());
ASSERT(!other.IsDynamicType());
ASSERT(!other.IsMalformed());
+ ASSERT(!other.IsMalbounded(NULL));
if (other.IsVoidType()) {
return false;
}
@@ -10460,6 +10463,13 @@
}
+bool AbstractType::IsMalbounded(Error* error) const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
RawError* AbstractType::malformed_error() const {
// AbstractType is an abstract class.
UNREACHABLE();
@@ -10857,6 +10867,30 @@
}
+bool Type::IsMalbounded(Error* bound_error) const {
+ if (!FLAG_enable_type_checks && !FLAG_error_on_malformed_type) {
+ return false;
+ }
+ ASSERT(IsFinalized());
+ ASSERT(!IsMalformed()); // Must be checked first.
+ AbstractTypeArguments& type_arguments =
+ AbstractTypeArguments::Handle(arguments());
+ if (type_arguments.IsNull()) {
hausner 2013/08/23 16:55:23 You could avoid this handle allocation by comparin
regis 2013/08/26 17:44:57 Done.
+ return false;
+ }
+ const intptr_t num_type_args = type_arguments.Length();
+ AbstractType& type_arg = AbstractType::Handle();
+ for (intptr_t i = 0; i < num_type_args; i++) {
+ type_arg = type_arguments.TypeAt(i);
+ ASSERT(!type_arg.IsNull());
+ if (type_arg.IsMalbounded(bound_error)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
void Type::set_malformed_error(const Error& value) const {
StorePointer(&raw_ptr()->malformed_error_, value.raw());
}
@@ -11230,10 +11264,14 @@
instantiator_type_arguments.TypeAt(index()));
if (type_arg.IsBoundedType()) {
const BoundedType& bounded_type = BoundedType::Cast(type_arg);
- ASSERT(!bounded_type.IsInstantiated());
- ASSERT(AbstractType::Handle(bounded_type.bound()).IsInstantiated());
- type_arg = bounded_type.InstantiateFrom(AbstractTypeArguments::Handle(),
- malformed_error);
+ // Bounds checking of a type is postponed to run time if the type is still
+ // uninstantiated at compile time, or if the bound and the type are mutually
+ // recursive. In the latter case, the type may already be instantiated.
+ if (!bounded_type.IsInstantiated()) {
+ ASSERT(AbstractType::Handle(bounded_type.bound()).IsInstantiated());
+ type_arg = bounded_type.InstantiateFrom(AbstractTypeArguments::Handle(),
+ malformed_error);
+ }
}
return type_arg.raw();
}
@@ -11350,13 +11388,28 @@
bool BoundedType::IsMalformed() const {
- return FLAG_enable_type_checks && AbstractType::Handle(bound()).IsMalformed();
+ return AbstractType::Handle(type()).IsMalformed();
}
+bool BoundedType::IsMalbounded(Error* bound_error) const {
+ if (!FLAG_enable_type_checks && !FLAG_error_on_malformed_type) {
+ return false;
+ }
+ const AbstractType& upper_bound = AbstractType::Handle(bound());
+ if (upper_bound.IsMalformed()) {
+ if (bound_error != NULL) {
+ *bound_error = upper_bound.malformed_error();
+ ASSERT(!bound_error->IsNull());
+ }
+ return true;
+ }
+ return false;
+}
+
+
RawError* BoundedType::malformed_error() const {
- ASSERT(FLAG_enable_type_checks);
- return AbstractType::Handle(bound()).malformed_error();
+ return AbstractType::Handle(type()).malformed_error();
}
« runtime/vm/object.h ('K') | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698