Chromium Code Reviews| 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(); |
| } |