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

Unified Diff: runtime/vm/object.cc

Issue 10979058: - Implement first class types in the VM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 12980)
+++ runtime/vm/object.cc (working copy)
@@ -73,8 +73,6 @@
RawClass* Object::void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::unresolved_class_class_ =
reinterpret_cast<RawClass*>(RAW_NULL);
-RawClass* Object::type_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
-RawClass* Object::type_parameter_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::instantiated_type_arguments_class_ =
reinterpret_cast<RawClass*>(RAW_NULL);
@@ -318,12 +316,6 @@
cls.set_is_finalized();
void_class_ = cls.raw();
- cls = Class::New<Type>();
- type_class_ = cls.raw();
-
- cls = Class::New<TypeParameter>();
- type_parameter_class_ = cls.raw();
-
cls = Class::New<TypeArguments>();
type_arguments_class_ = cls.raw();
@@ -443,8 +435,6 @@
SET_CLASS_NAME(dynamic, Dynamic);
SET_CLASS_NAME(void, Void);
SET_CLASS_NAME(unresolved_class, UnresolvedClass);
- SET_CLASS_NAME(type, Type);
- SET_CLASS_NAME(type_parameter, TypeParameter);
SET_CLASS_NAME(type_arguments, TypeArguments);
SET_CLASS_NAME(instantiated_type_arguments, InstantiatedTypeArguments);
SET_CLASS_NAME(patch_class, PatchClass);
@@ -548,6 +538,13 @@
array = Array::New(4);
object_store->set_canonical_type_arguments(array);
+ // Setup type class early in the process.
+ cls = Class::New<Type>();
+ object_store->set_type_class(cls);
+
+ cls = Class::New<TypeParameter>();
+ object_store->set_type_parameter_class(cls);
+
// Pre-allocate the OneByteString class needed by the symbol table.
cls = Class::New<OneByteString>();
object_store->set_one_byte_string_class(cls);
@@ -668,6 +665,16 @@
type = Type::NewNonParameterizedType(cls);
object_store->set_object_type(type);
+ cls = object_store->type_class();
+ name = Symbols::Type();
+ RegisterPrivateClass(cls, name, core_lib);
+ pending_classes.Add(cls, Heap::kOld);
+
+ cls = object_store->type_parameter_class();
+ name = Symbols::TypeParameter();
+ RegisterPrivateClass(cls, name, core_lib);
+ pending_classes.Add(cls, Heap::kOld);
+
cls = Class::New<Integer>();
object_store->set_integer_implementation_class(cls);
name = Symbols::IntegerImplementation();
@@ -997,6 +1004,12 @@
cls = Class::New<Instance>(kInstanceCid);
object_store->set_object_class(cls);
+ cls = Class::New<Type>();
+ object_store->set_type_class(cls);
+
+ cls = Class::New<TypeParameter>();
+ object_store->set_type_parameter_class(cls);
+
cls = Class::New<Array>();
object_store->set_array_class(cls);
@@ -2427,825 +2440,6 @@
}
-bool AbstractType::IsResolved() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-bool AbstractType::HasResolvedTypeClass() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-RawClass* AbstractType::type_class() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return Class::null();
-}
-
-
-RawUnresolvedClass* AbstractType::unresolved_class() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return UnresolvedClass::null();
-}
-
-
-RawAbstractTypeArguments* AbstractType::arguments() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return NULL;
-}
-
-
-intptr_t AbstractType::token_pos() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return -1;
-}
-
-
-bool AbstractType::IsInstantiated() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-bool AbstractType::IsFinalized() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-bool AbstractType::IsBeingFinalized() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-bool AbstractType::IsMalformed() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-RawError* AbstractType::malformed_error() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return Error::null();
-}
-
-
-void AbstractType::set_malformed_error(const Error& value) const {
- // AbstractType is an abstract class.
- UNREACHABLE();
-}
-
-
-bool AbstractType::Equals(const AbstractType& other) const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-bool AbstractType::IsIdentical(const AbstractType& other,
- bool check_type_parameter_bound) const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return false;
-}
-
-
-RawAbstractType* AbstractType::InstantiateFrom(
- const AbstractTypeArguments& instantiator_type_arguments) const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return NULL;
-}
-
-
-RawAbstractType* AbstractType::Canonicalize() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return NULL;
-}
-
-
-RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
- if (IsTypeParameter()) {
- return TypeParameter::Cast(*this).name();
- }
- // If the type is still being finalized, we may be reporting an error about
- // a malformed type, so proceed with caution.
- const AbstractTypeArguments& args =
- AbstractTypeArguments::Handle(arguments());
- const intptr_t num_args = args.IsNull() ? 0 : args.Length();
- String& class_name = String::Handle();
- intptr_t first_type_param_index;
- intptr_t num_type_params; // Number of type parameters to print.
- if (HasResolvedTypeClass()) {
- const Class& cls = Class::Handle(type_class());
- num_type_params = cls.NumTypeParameters(); // Do not print the full vector.
- if (name_visibility == kInternalName) {
- class_name = cls.Name();
- } else {
- ASSERT(name_visibility == kUserVisibleName);
- // Map internal types to their corresponding public interfaces.
- class_name = cls.UserVisibleName();
- }
- if (num_type_params > num_args) {
- first_type_param_index = 0;
- if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
- // Most probably a malformed type. Do not fill up with "Dynamic",
- // but use actual vector.
- num_type_params = num_args;
- } else {
- ASSERT(num_args == 0); // Type is raw.
- // No need to fill up with "Dynamic".
- num_type_params = 0;
- }
- } else {
- first_type_param_index = num_args - num_type_params;
- }
- if (cls.IsSignatureClass()) {
- // We may be reporting an error about a malformed function type. In that
- // case, avoid instantiating the signature, since it may lead to cycles.
- if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
- return class_name.raw();
- }
- // In order to avoid cycles, print the name of a typedef (non-canonical
- // signature class) as a regular, possibly parameterized, class.
- if (cls.IsCanonicalSignatureClass()) {
- const Function& signature_function = Function::Handle(
- cls.signature_function());
- // Signature classes have no super type.
- ASSERT(first_type_param_index == 0);
- return signature_function.InstantiatedSignatureFrom(args,
- name_visibility);
- }
- }
- } else {
- const UnresolvedClass& cls = UnresolvedClass::Handle(unresolved_class());
- class_name = cls.Name();
- num_type_params = num_args;
- first_type_param_index = 0;
- }
- String& type_name = String::Handle();
- if (num_type_params == 0) {
- type_name = class_name.raw();
- } else {
- const String& args_name = String::Handle(
- args.SubvectorName(first_type_param_index,
- num_type_params,
- name_visibility));
- type_name = String::Concat(class_name, args_name);
- }
- // The name is only used for type checking and debugging purposes.
- // Unless profiling data shows otherwise, it is not worth caching the name in
- // the type.
- return Symbols::New(type_name);
-}
-
-
-RawString* AbstractType::ClassName() const {
- if (HasResolvedTypeClass()) {
- return Class::Handle(type_class()).Name();
- } else {
- return UnresolvedClass::Handle(unresolved_class()).Name();
- }
-}
-
-
-bool AbstractType::IsBoolType() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::BoolType()).type_class());
-}
-
-
-bool AbstractType::IsIntType() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::IntType()).type_class());
-}
-
-
-bool AbstractType::IsDoubleType() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::Double()).type_class());
-}
-
-
-bool AbstractType::IsNumberType() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::Number()).type_class());
-}
-
-
-bool AbstractType::IsStringInterface() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::StringInterface()).type_class());
-}
-
-
-bool AbstractType::IsFunctionType() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::Function()).type_class());
-}
-
-
-bool AbstractType::IsListInterface() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::ListInterface()).type_class());
-}
-
-
-bool AbstractType::TypeTest(TypeTestKind test_kind,
- const AbstractType& other,
- Error* malformed_error) const {
- ASSERT(IsFinalized());
- ASSERT(other.IsFinalized());
- // In case the type checked in a type test is malformed, the code generator
- // may compile a throw instead of a run time call performing the type check.
- // However, in checked mode, a function type may include malformed result type
- // and/or malformed parameter types, which will then be encountered here at
- // run time.
- if (IsMalformed()) {
- ASSERT(FLAG_enable_type_checks);
- if ((malformed_error != NULL) && malformed_error->IsNull()) {
- *malformed_error = this->malformed_error();
- }
- return false;
- }
- if (other.IsMalformed()) {
- ASSERT(FLAG_enable_type_checks);
- if ((malformed_error != NULL) && malformed_error->IsNull()) {
- *malformed_error = other.malformed_error();
- }
- return false;
- }
- // AbstractType parameters cannot be handled by Class::TypeTest().
- // When comparing two uninstantiated function types, one returning type
- // parameter K, the other returning type parameter V, we cannot assume that K
- // is a subtype of V, or vice versa. We only return true if K == V, i.e. if
- // they have the same index (both are finalized, so their indices are
- // comparable).
- // The same rule applies When checking the upper bound of a still
- // uninstantiated type at compile time. Returning false will defer the test
- // to run time. But there are cases where it can be decided at compile time.
- // For example, with class A<K, V extends K>, new A<T, T> called from within
- // a class B<T> will never require a run time bounds check, even it T is
- // uninstantiated at compile time.
- if (IsTypeParameter()) {
- const TypeParameter& type_param = TypeParameter::Cast(*this);
- if (other.IsTypeParameter()) {
- const TypeParameter& other_type_param = TypeParameter::Cast(other);
- return type_param.index() == other_type_param.index();
- } else if (FLAG_enable_type_checks) {
- // In checked mode, if the upper bound of this type is more specific than
- // the other type, then this type is more specific than the other type.
- const AbstractType& type_param_bound =
- AbstractType::Handle(type_param.bound());
- if (type_param_bound.IsMoreSpecificThan(other, malformed_error)) {
- return true;
- }
- }
- return false;
- }
- if (other.IsTypeParameter()) {
- return false;
- }
- const Class& cls = Class::Handle(type_class());
- return cls.TypeTest(test_kind,
- AbstractTypeArguments::Handle(arguments()),
- Class::Handle(other.type_class()),
- AbstractTypeArguments::Handle(other.arguments()),
- malformed_error);
-}
-
-
-const char* AbstractType::ToCString() const {
- // AbstractType is an abstract class.
- UNREACHABLE();
- return "AbstractType";
-}
-
-
-RawType* Type::NullType() {
- return Isolate::Current()->object_store()->null_type();
-}
-
-
-RawType* Type::DynamicType() {
- return Isolate::Current()->object_store()->dynamic_type();
-}
-
-
-RawType* Type::VoidType() {
- return Isolate::Current()->object_store()->void_type();
-}
-
-
-RawType* Type::ObjectType() {
- return Isolate::Current()->object_store()->object_type();
-}
-
-
-RawType* Type::BoolType() {
- return Isolate::Current()->object_store()->bool_type();
-}
-
-
-RawType* Type::IntType() {
- return Isolate::Current()->object_store()->int_type();
-}
-
-
-RawType* Type::SmiType() {
- return Isolate::Current()->object_store()->smi_type();
-}
-
-
-RawType* Type::MintType() {
- return Isolate::Current()->object_store()->mint_type();
-}
-
-
-RawType* Type::Double() {
- return Isolate::Current()->object_store()->double_type();
-}
-
-
-RawType* Type::Number() {
- return Isolate::Current()->object_store()->number_type();
-}
-
-
-RawType* Type::StringInterface() {
- return Isolate::Current()->object_store()->string_interface();
-}
-
-
-RawType* Type::Function() {
- return Isolate::Current()->object_store()->function_type();
-}
-
-
-RawType* Type::ListInterface() {
- return Isolate::Current()->object_store()->list_interface();
-}
-
-
-RawType* Type::NewNonParameterizedType(
- const Class& type_class) {
- ASSERT(!type_class.HasTypeArguments());
- const TypeArguments& no_type_arguments = TypeArguments::Handle();
- Type& type = Type::Handle();
- type ^= Type::New(Object::Handle(type_class.raw()),
- no_type_arguments,
- Scanner::kDummyTokenIndex);
- type.set_is_finalized_instantiated();
- type ^= type.Canonicalize();
- return type.raw();
-}
-
-
-void Type::set_is_finalized_instantiated() const {
- ASSERT(!IsFinalized());
- set_type_state(RawType::kFinalizedInstantiated);
-}
-
-
-void Type::set_is_finalized_uninstantiated() const {
- ASSERT(!IsFinalized());
- set_type_state(RawType::kFinalizedUninstantiated);
-}
-
-
-void Type::set_is_being_finalized() const {
- ASSERT(!IsFinalized() && !IsBeingFinalized());
- set_type_state(RawType::kBeingFinalized);
-}
-
-
-bool Type::IsMalformed() const {
- return raw_ptr()->malformed_error_ != Error::null();
-}
-
-
-void Type::set_malformed_error(const Error& value) const {
- StorePointer(&raw_ptr()->malformed_error_, value.raw());
-}
-
-
-RawError* Type::malformed_error() const {
- ASSERT(IsMalformed());
- return raw_ptr()->malformed_error_;
-}
-
-
-bool Type::IsResolved() const {
- if (IsFinalized()) {
- return true;
- }
- if (!HasResolvedTypeClass()) {
- return false;
- }
- const AbstractTypeArguments& args =
- AbstractTypeArguments::Handle(arguments());
- return args.IsNull() || args.IsResolved();
-}
-
-
-bool Type::HasResolvedTypeClass() const {
- const Object& type_class = Object::Handle(raw_ptr()->type_class_);
- return !type_class.IsNull() && type_class.IsClass();
-}
-
-
-RawClass* Type::type_class() const {
- ASSERT(HasResolvedTypeClass());
- Class& type_class = Class::Handle();
- type_class ^= raw_ptr()->type_class_;
- return type_class.raw();
-}
-
-
-RawUnresolvedClass* Type::unresolved_class() const {
- ASSERT(!HasResolvedTypeClass());
- UnresolvedClass& unresolved_class = UnresolvedClass::Handle();
- unresolved_class ^= raw_ptr()->type_class_;
- ASSERT(!unresolved_class.IsNull());
- return unresolved_class.raw();
-}
-
-
-RawString* Type::TypeClassName() const {
- if (HasResolvedTypeClass()) {
- const Class& cls = Class::Handle(type_class());
- return cls.Name();
- } else {
- const UnresolvedClass& cls = UnresolvedClass::Handle(unresolved_class());
- return cls.Name();
- }
-}
-
-
-RawAbstractTypeArguments* Type::arguments() const {
- return raw_ptr()->arguments_;
-}
-
-
-bool Type::IsInstantiated() const {
- if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) {
- return true;
- }
- if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) {
- return false;
- }
- const AbstractTypeArguments& args =
- AbstractTypeArguments::Handle(arguments());
- return args.IsNull() || args.IsInstantiated();
-}
-
-
-RawAbstractType* Type::InstantiateFrom(
- const AbstractTypeArguments& instantiator_type_arguments) const {
- ASSERT(IsFinalized());
- ASSERT(!IsInstantiated());
- AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::Handle(arguments());
- type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments);
- const Class& cls = Class::Handle(type_class());
- ASSERT(cls.is_finalized());
- Type& instantiated_type = Type::Handle(
- Type::New(cls, type_arguments, token_pos()));
- ASSERT(type_arguments.IsNull() ||
- (type_arguments.Length() == cls.NumTypeArguments()));
- instantiated_type.set_is_finalized_instantiated();
- return instantiated_type.raw();
-}
-
-
-bool Type::Equals(const AbstractType& other) const {
- ASSERT(IsFinalized() && other.IsFinalized());
- if (raw() == other.raw()) {
- return true;
- }
- if (IsMalformed() || !other.IsType() || other.IsMalformed()) {
- return false;
- }
- if (type_class() != other.type_class()) {
- return false;
- }
- return AbstractTypeArguments::AreEqual(
- AbstractTypeArguments::Handle(arguments()),
- AbstractTypeArguments::Handle(other.arguments()));
-}
-
-
-bool Type::IsIdentical(const AbstractType& other,
- bool check_type_parameter_bounds) const {
- if (raw() == other.raw()) {
- return true;
- }
- if (!other.IsType()) {
- return false;
- }
- // Both type classes may not be resolved yet.
- String& name = String::Handle(TypeClassName());
- String& other_name = String::Handle(Type::Cast(other).TypeClassName());
- if (!name.Equals(other_name)) {
- return false;
- }
- return AbstractTypeArguments::AreIdentical(
- AbstractTypeArguments::Handle(arguments()),
- AbstractTypeArguments::Handle(other.arguments()),
- false); // Bounds are only checked at the top level.
-}
-
-
-RawAbstractType* Type::Canonicalize() const {
- ASSERT(IsFinalized());
- if (IsCanonical() || IsMalformed()) {
- ASSERT(IsMalformed() || AbstractTypeArguments::Handle(arguments()).IsOld());
- return this->raw();
- }
- const Class& cls = Class::Handle(type_class());
- Array& canonical_types = Array::Handle(cls.canonical_types());
- if (canonical_types.IsNull()) {
- // Types defined in the VM isolate are canonicalized via the object store.
- return this->raw();
- }
- const intptr_t canonical_types_len = canonical_types.Length();
- // Linear search to see whether this type is already present in the
- // list of canonicalized types.
- // TODO(asiva): Try to re-factor this lookup code to make sharing
- // easy between the 4 versions of this loop.
- Type& type = Type::Handle();
- intptr_t index = 0;
- while (index < canonical_types_len) {
- type ^= canonical_types.At(index);
- if (type.IsNull()) {
- break;
- }
- if (!type.IsFinalized()) {
- ASSERT((index == 0) && cls.IsSignatureClass());
- index++;
- continue;
- }
- if (this->Equals(type)) {
- return type.raw();
- }
- index++;
- }
- // Canonicalize the type arguments.
- AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(arguments());
- type_args = type_args.Canonicalize();
- set_arguments(type_args);
- // The type needs to be added to the list. Grow the list if it is full.
- if (index == canonical_types_len) {
- const intptr_t kLengthIncrement = 2; // Raw and parameterized.
- const intptr_t new_length = canonical_types.Length() + kLengthIncrement;
- const Array& new_canonical_types =
- Array::Handle(Array::Grow(canonical_types, new_length, Heap::kOld));
- cls.set_canonical_types(new_canonical_types);
- new_canonical_types.SetAt(index, *this);
- } else {
- canonical_types.SetAt(index, *this);
- }
- ASSERT(IsOld());
- SetCanonical();
- return this->raw();
-}
-
-
-void Type::set_type_class(const Object& value) const {
- ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
- StorePointer(&raw_ptr()->type_class_, value.raw());
-}
-
-
-void Type::set_arguments(const AbstractTypeArguments& value) const {
- StorePointer(&raw_ptr()->arguments_, value.raw());
-}
-
-
-RawType* Type::New(Heap::Space space) {
- ASSERT(Object::type_class() != Class::null());
- RawObject* raw = Object::Allocate(Type::kClassId,
- Type::InstanceSize(),
- space);
- return reinterpret_cast<RawType*>(raw);
-}
-
-
-RawType* Type::New(const Object& clazz,
- const AbstractTypeArguments& arguments,
- intptr_t token_pos,
- Heap::Space space) {
- const Type& result = Type::Handle(Type::New(space));
- result.set_type_class(clazz);
- result.set_arguments(arguments);
- result.set_token_pos(token_pos);
- result.raw_ptr()->type_state_ = RawType::kAllocated;
- return result.raw();
-}
-
-
-void Type::set_token_pos(intptr_t token_pos) const {
- ASSERT(token_pos >= 0);
- raw_ptr()->token_pos_ = token_pos;
-}
-
-
-void Type::set_type_state(int8_t state) const {
- ASSERT((state == RawType::kAllocated) ||
- (state == RawType::kBeingFinalized) ||
- (state == RawType::kFinalizedInstantiated) ||
- (state == RawType::kFinalizedUninstantiated));
- raw_ptr()->type_state_ = state;
-}
-
-
-const char* Type::ToCString() const {
- if (IsResolved()) {
- const AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::Handle(arguments());
- if (type_arguments.IsNull()) {
- const char* format = "Type: class '%s'";
- const char* class_name =
- String::Handle(Class::Handle(type_class()).Name()).ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, class_name) + 1;
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, class_name);
- return chars;
- } else {
- const char* format = "Type: class '%s', args:[%s]";
- const char* class_name =
- String::Handle(Class::Handle(type_class()).Name()).ToCString();
- const char* args_cstr =
- AbstractTypeArguments::Handle(arguments()).ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, class_name, args_cstr) + 1;
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, class_name, args_cstr);
- return chars;
- }
- } else {
- return "Unresolved Type";
- }
-}
-
-
-void TypeParameter::set_is_finalized() const {
- ASSERT(!IsFinalized());
- set_type_state(RawTypeParameter::kFinalizedUninstantiated);
-}
-
-
-bool TypeParameter::Equals(const AbstractType& other) const {
- if (raw() == other.raw()) {
- return true;
- }
- if (!other.IsTypeParameter()) {
- return false;
- }
- const TypeParameter& other_type_param = TypeParameter::Cast(other);
- if (IsFinalized() != other_type_param.IsFinalized()) {
- return false;
- }
- if (parameterized_class() != other_type_param.parameterized_class()) {
- return false;
- }
- if (index() != other_type_param.index()) {
- return false;
- }
- const String& type_param_name = String::Handle(name());
- const String& other_type_param_name = String::Handle(other_type_param.name());
- return type_param_name.Equals(other_type_param_name);
-}
-
-
-bool TypeParameter::IsIdentical(const AbstractType& other,
- bool check_type_parameter_bound) const {
- if (raw() == other.raw()) {
- return true;
- }
- if (!other.IsTypeParameter()) {
- return false;
- }
- const TypeParameter& other_type_param = TypeParameter::Cast(other);
- // IsIdentical may be called on type parameters belonging to different
- // classes, e.g. to an interface and to its default factory class.
- // Therefore, both type parameters may have different parameterized classes
- // and different indices. Compare the type parameter names only, and their
- // bounds if requested.
- String& type_param_name = String::Handle(name());
- String& other_type_param_name = String::Handle(other_type_param.name());
- if (!type_param_name.Equals(other_type_param_name)) {
- return false;
- }
- if (check_type_parameter_bound) {
- AbstractType& this_bound = AbstractType::Handle(bound());
- AbstractType& other_bound = AbstractType::Handle(other_type_param.bound());
- // Bounds are only checked at the top level.
- const bool check_type_parameter_bounds = false;
- if (!this_bound.IsIdentical(other_bound, check_type_parameter_bounds)) {
- return false;
- }
- }
- return true;
-}
-
-
-void TypeParameter::set_parameterized_class(const Class& value) const {
- // Set value may be null.
- StorePointer(&raw_ptr()->parameterized_class_, value.raw());
-}
-
-
-void TypeParameter::set_index(intptr_t value) const {
- ASSERT(value >= 0);
- raw_ptr()->index_ = value;
-}
-
-
-void TypeParameter::set_name(const String& value) const {
- ASSERT(value.IsSymbol());
- StorePointer(&raw_ptr()->name_, value.raw());
-}
-
-
-void TypeParameter::set_bound(const AbstractType& value) const {
- StorePointer(&raw_ptr()->bound_, value.raw());
-}
-
-RawAbstractType* TypeParameter::InstantiateFrom(
- const AbstractTypeArguments& instantiator_type_arguments) const {
- ASSERT(IsFinalized());
- if (instantiator_type_arguments.IsNull()) {
- return Type::DynamicType();
- }
- return instantiator_type_arguments.TypeAt(index());
-}
-
-
-RawTypeParameter* TypeParameter::New() {
- ASSERT(Object::type_parameter_class() != Class::null());
- RawObject* raw = Object::Allocate(TypeParameter::kClassId,
- TypeParameter::InstanceSize(),
- Heap::kOld);
- return reinterpret_cast<RawTypeParameter*>(raw);
-}
-
-
-RawTypeParameter* TypeParameter::New(const Class& parameterized_class,
- intptr_t index,
- const String& name,
- const AbstractType& bound,
- intptr_t token_pos) {
- const TypeParameter& result = TypeParameter::Handle(TypeParameter::New());
- result.set_parameterized_class(parameterized_class);
- result.set_index(index);
- result.set_name(name);
- result.set_bound(bound);
- result.set_token_pos(token_pos);
- result.raw_ptr()->type_state_ = RawTypeParameter::kAllocated;
- return result.raw();
-}
-
-
-void TypeParameter::set_token_pos(intptr_t token_pos) const {
- ASSERT(token_pos >= 0);
- raw_ptr()->token_pos_ = token_pos;
-}
-
-
-void TypeParameter::set_type_state(int8_t state) const {
- ASSERT((state == RawTypeParameter::kAllocated) ||
- (state == RawTypeParameter::kBeingFinalized) ||
- (state == RawTypeParameter::kFinalizedUninstantiated));
- raw_ptr()->type_state_ = state;
-}
-
-
-const char* TypeParameter::ToCString() const {
- const char* format = "TypeParameter: name %s; index: %d";
- const char* name_cstr = String::Handle(Name()).ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, name_cstr, index()) + 1;
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, name_cstr, index());
- return chars;
-}
-
-
intptr_t AbstractTypeArguments::Length() const {
// AbstractTypeArguments is an abstract class.
UNREACHABLE();
@@ -8933,6 +8127,829 @@
}
+bool AbstractType::IsResolved() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+bool AbstractType::HasResolvedTypeClass() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+RawClass* AbstractType::type_class() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return Class::null();
+}
+
+
+RawUnresolvedClass* AbstractType::unresolved_class() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return UnresolvedClass::null();
+}
+
+
+RawAbstractTypeArguments* AbstractType::arguments() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return NULL;
+}
+
+
+intptr_t AbstractType::token_pos() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return -1;
+}
+
+
+bool AbstractType::IsInstantiated() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+bool AbstractType::IsFinalized() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+bool AbstractType::IsBeingFinalized() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+bool AbstractType::IsMalformed() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+RawError* AbstractType::malformed_error() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return Error::null();
+}
+
+
+void AbstractType::set_malformed_error(const Error& value) const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+}
+
+
+bool AbstractType::Equals(const Instance& other) const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+bool AbstractType::IsIdentical(const AbstractType& other,
+ bool check_type_parameter_bound) const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return false;
+}
+
+
+RawAbstractType* AbstractType::InstantiateFrom(
+ const AbstractTypeArguments& instantiator_type_arguments) const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return NULL;
+}
+
+
+RawAbstractType* AbstractType::Canonicalize() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return NULL;
+}
+
+
+RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
+ if (IsTypeParameter()) {
+ return TypeParameter::Cast(*this).name();
+ }
+ // If the type is still being finalized, we may be reporting an error about
+ // a malformed type, so proceed with caution.
+ const AbstractTypeArguments& args =
+ AbstractTypeArguments::Handle(arguments());
+ const intptr_t num_args = args.IsNull() ? 0 : args.Length();
+ String& class_name = String::Handle();
+ intptr_t first_type_param_index;
+ intptr_t num_type_params; // Number of type parameters to print.
+ if (HasResolvedTypeClass()) {
+ const Class& cls = Class::Handle(type_class());
+ num_type_params = cls.NumTypeParameters(); // Do not print the full vector.
+ if (name_visibility == kInternalName) {
+ class_name = cls.Name();
+ } else {
+ ASSERT(name_visibility == kUserVisibleName);
+ // Map internal types to their corresponding public interfaces.
+ class_name = cls.UserVisibleName();
+ }
+ if (num_type_params > num_args) {
+ first_type_param_index = 0;
+ if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
+ // Most probably a malformed type. Do not fill up with "Dynamic",
+ // but use actual vector.
+ num_type_params = num_args;
+ } else {
+ ASSERT(num_args == 0); // Type is raw.
+ // No need to fill up with "Dynamic".
+ num_type_params = 0;
+ }
+ } else {
+ first_type_param_index = num_args - num_type_params;
+ }
+ if (cls.IsSignatureClass()) {
+ // We may be reporting an error about a malformed function type. In that
+ // case, avoid instantiating the signature, since it may lead to cycles.
+ if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
+ return class_name.raw();
+ }
+ // In order to avoid cycles, print the name of a typedef (non-canonical
+ // signature class) as a regular, possibly parameterized, class.
+ if (cls.IsCanonicalSignatureClass()) {
+ const Function& signature_function = Function::Handle(
+ cls.signature_function());
+ // Signature classes have no super type.
+ ASSERT(first_type_param_index == 0);
+ return signature_function.InstantiatedSignatureFrom(args,
+ name_visibility);
+ }
+ }
+ } else {
+ const UnresolvedClass& cls = UnresolvedClass::Handle(unresolved_class());
+ class_name = cls.Name();
+ num_type_params = num_args;
+ first_type_param_index = 0;
+ }
+ String& type_name = String::Handle();
+ if (num_type_params == 0) {
+ type_name = class_name.raw();
+ } else {
+ const String& args_name = String::Handle(
+ args.SubvectorName(first_type_param_index,
+ num_type_params,
+ name_visibility));
+ type_name = String::Concat(class_name, args_name);
+ }
+ // The name is only used for type checking and debugging purposes.
+ // Unless profiling data shows otherwise, it is not worth caching the name in
+ // the type.
+ return Symbols::New(type_name);
+}
+
+
+RawString* AbstractType::ClassName() const {
+ if (HasResolvedTypeClass()) {
+ return Class::Handle(type_class()).Name();
+ } else {
+ return UnresolvedClass::Handle(unresolved_class()).Name();
+ }
+}
+
+
+bool AbstractType::IsBoolType() const {
+ return HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::BoolType()).type_class());
+}
+
+
+bool AbstractType::IsIntType() const {
+ return HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::IntType()).type_class());
+}
+
+
+bool AbstractType::IsDoubleType() const {
+ return HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::Double()).type_class());
+}
+
+
+bool AbstractType::IsNumberType() const {
+ return HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::Number()).type_class());
+}
+
+
+bool AbstractType::IsStringInterface() const {
+ return HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::StringInterface()).type_class());
+}
+
+
+bool AbstractType::IsFunctionType() const {
+ return HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::Function()).type_class());
+}
+
+
+bool AbstractType::IsListInterface() const {
+ return HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::ListInterface()).type_class());
+}
+
+
+bool AbstractType::TypeTest(TypeTestKind test_kind,
+ const AbstractType& other,
+ Error* malformed_error) const {
+ ASSERT(IsFinalized());
+ ASSERT(other.IsFinalized());
+ // In case the type checked in a type test is malformed, the code generator
+ // may compile a throw instead of a run time call performing the type check.
+ // However, in checked mode, a function type may include malformed result type
+ // and/or malformed parameter types, which will then be encountered here at
+ // run time.
+ if (IsMalformed()) {
+ ASSERT(FLAG_enable_type_checks);
+ if ((malformed_error != NULL) && malformed_error->IsNull()) {
+ *malformed_error = this->malformed_error();
+ }
+ return false;
+ }
+ if (other.IsMalformed()) {
+ ASSERT(FLAG_enable_type_checks);
+ if ((malformed_error != NULL) && malformed_error->IsNull()) {
+ *malformed_error = other.malformed_error();
+ }
+ return false;
+ }
+ // AbstractType parameters cannot be handled by Class::TypeTest().
+ // When comparing two uninstantiated function types, one returning type
+ // parameter K, the other returning type parameter V, we cannot assume that K
+ // is a subtype of V, or vice versa. We only return true if K == V, i.e. if
+ // they have the same index (both are finalized, so their indices are
+ // comparable).
+ // The same rule applies When checking the upper bound of a still
+ // uninstantiated type at compile time. Returning false will defer the test
+ // to run time. But there are cases where it can be decided at compile time.
+ // For example, with class A<K, V extends K>, new A<T, T> called from within
+ // a class B<T> will never require a run time bounds check, even it T is
+ // uninstantiated at compile time.
+ if (IsTypeParameter()) {
+ const TypeParameter& type_param = TypeParameter::Cast(*this);
+ if (other.IsTypeParameter()) {
+ const TypeParameter& other_type_param = TypeParameter::Cast(other);
+ return type_param.index() == other_type_param.index();
+ } else if (FLAG_enable_type_checks) {
+ // In checked mode, if the upper bound of this type is more specific than
+ // the other type, then this type is more specific than the other type.
+ const AbstractType& type_param_bound =
+ AbstractType::Handle(type_param.bound());
+ if (type_param_bound.IsMoreSpecificThan(other, malformed_error)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (other.IsTypeParameter()) {
+ return false;
+ }
+ const Class& cls = Class::Handle(type_class());
+ return cls.TypeTest(test_kind,
+ AbstractTypeArguments::Handle(arguments()),
+ Class::Handle(other.type_class()),
+ AbstractTypeArguments::Handle(other.arguments()),
+ malformed_error);
+}
+
+
+const char* AbstractType::ToCString() const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+ return "AbstractType";
+}
+
+
+RawType* Type::NullType() {
+ return Isolate::Current()->object_store()->null_type();
+}
+
+
+RawType* Type::DynamicType() {
+ return Isolate::Current()->object_store()->dynamic_type();
+}
+
+
+RawType* Type::VoidType() {
+ return Isolate::Current()->object_store()->void_type();
+}
+
+
+RawType* Type::ObjectType() {
+ return Isolate::Current()->object_store()->object_type();
+}
+
+
+RawType* Type::BoolType() {
+ return Isolate::Current()->object_store()->bool_type();
+}
+
+
+RawType* Type::IntType() {
+ return Isolate::Current()->object_store()->int_type();
+}
+
+
+RawType* Type::SmiType() {
+ return Isolate::Current()->object_store()->smi_type();
+}
+
+
+RawType* Type::MintType() {
+ return Isolate::Current()->object_store()->mint_type();
+}
+
+
+RawType* Type::Double() {
+ return Isolate::Current()->object_store()->double_type();
+}
+
+
+RawType* Type::Number() {
+ return Isolate::Current()->object_store()->number_type();
+}
+
+
+RawType* Type::StringInterface() {
+ return Isolate::Current()->object_store()->string_interface();
+}
+
+
+RawType* Type::Function() {
+ return Isolate::Current()->object_store()->function_type();
+}
+
+
+RawType* Type::ListInterface() {
+ return Isolate::Current()->object_store()->list_interface();
+}
+
+
+RawType* Type::NewNonParameterizedType(const Class& type_class) {
+ ASSERT(!type_class.HasTypeArguments());
+ const TypeArguments& no_type_arguments = TypeArguments::Handle();
+ Type& type = Type::Handle();
+ type ^= Type::New(Object::Handle(type_class.raw()),
+ no_type_arguments,
+ Scanner::kDummyTokenIndex);
+ type.set_is_finalized_instantiated();
+ type ^= type.Canonicalize();
+ return type.raw();
+}
+
+
+void Type::set_is_finalized_instantiated() const {
+ ASSERT(!IsFinalized());
+ set_type_state(RawType::kFinalizedInstantiated);
+}
+
+
+void Type::set_is_finalized_uninstantiated() const {
+ ASSERT(!IsFinalized());
+ set_type_state(RawType::kFinalizedUninstantiated);
+}
+
+
+void Type::set_is_being_finalized() const {
+ ASSERT(!IsFinalized() && !IsBeingFinalized());
+ set_type_state(RawType::kBeingFinalized);
+}
+
+
+bool Type::IsMalformed() const {
+ return raw_ptr()->malformed_error_ != Error::null();
+}
+
+
+void Type::set_malformed_error(const Error& value) const {
+ StorePointer(&raw_ptr()->malformed_error_, value.raw());
+}
+
+
+RawError* Type::malformed_error() const {
+ ASSERT(IsMalformed());
+ return raw_ptr()->malformed_error_;
+}
+
+
+bool Type::IsResolved() const {
+ if (IsFinalized()) {
+ return true;
+ }
+ if (!HasResolvedTypeClass()) {
+ return false;
+ }
+ const AbstractTypeArguments& args =
+ AbstractTypeArguments::Handle(arguments());
+ return args.IsNull() || args.IsResolved();
+}
+
+
+bool Type::HasResolvedTypeClass() const {
+ const Object& type_class = Object::Handle(raw_ptr()->type_class_);
+ return !type_class.IsNull() && type_class.IsClass();
+}
+
+
+RawClass* Type::type_class() const {
+ ASSERT(HasResolvedTypeClass());
+ Class& type_class = Class::Handle();
+ type_class ^= raw_ptr()->type_class_;
+ return type_class.raw();
+}
+
+
+RawUnresolvedClass* Type::unresolved_class() const {
+ ASSERT(!HasResolvedTypeClass());
+ UnresolvedClass& unresolved_class = UnresolvedClass::Handle();
+ unresolved_class ^= raw_ptr()->type_class_;
+ ASSERT(!unresolved_class.IsNull());
+ return unresolved_class.raw();
+}
+
+
+RawString* Type::TypeClassName() const {
+ if (HasResolvedTypeClass()) {
+ const Class& cls = Class::Handle(type_class());
+ return cls.Name();
+ } else {
+ const UnresolvedClass& cls = UnresolvedClass::Handle(unresolved_class());
+ return cls.Name();
+ }
+}
+
+
+RawAbstractTypeArguments* Type::arguments() const {
+ return raw_ptr()->arguments_;
+}
+
+
+bool Type::IsInstantiated() const {
+ if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) {
+ return true;
+ }
+ if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) {
+ return false;
+ }
+ const AbstractTypeArguments& args =
+ AbstractTypeArguments::Handle(arguments());
+ return args.IsNull() || args.IsInstantiated();
+}
+
+
+RawAbstractType* Type::InstantiateFrom(
+ const AbstractTypeArguments& instantiator_type_arguments) const {
+ ASSERT(IsFinalized());
+ ASSERT(!IsInstantiated());
+ AbstractTypeArguments& type_arguments =
+ AbstractTypeArguments::Handle(arguments());
+ type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments);
+ const Class& cls = Class::Handle(type_class());
+ ASSERT(cls.is_finalized());
+ Type& instantiated_type = Type::Handle(
+ Type::New(cls, type_arguments, token_pos()));
+ ASSERT(type_arguments.IsNull() ||
+ (type_arguments.Length() == cls.NumTypeArguments()));
+ instantiated_type.set_is_finalized_instantiated();
+ return instantiated_type.raw();
+}
+
+
+bool Type::Equals(const Instance& other) const {
+ if (raw() == other.raw()) {
+ return true;
+ }
+ if (!other.IsType()) {
+ return false;
+ }
+ const AbstractType& other_type = AbstractType::Cast(other);
+ ASSERT(IsFinalized() && other_type.IsFinalized());
+ if (IsMalformed() || other_type.IsMalformed()) {
+ return false;
+ }
+ if (type_class() != other_type.type_class()) {
+ return false;
+ }
+ return AbstractTypeArguments::AreEqual(
+ AbstractTypeArguments::Handle(arguments()),
+ AbstractTypeArguments::Handle(other_type.arguments()));
+}
+
+
+bool Type::IsIdentical(const AbstractType& other,
+ bool check_type_parameter_bounds) const {
+ if (raw() == other.raw()) {
+ return true;
+ }
+ if (!other.IsType()) {
+ return false;
+ }
+ // Both type classes may not be resolved yet.
+ String& name = String::Handle(TypeClassName());
+ String& other_name = String::Handle(Type::Cast(other).TypeClassName());
+ if (!name.Equals(other_name)) {
+ return false;
+ }
+ return AbstractTypeArguments::AreIdentical(
+ AbstractTypeArguments::Handle(arguments()),
+ AbstractTypeArguments::Handle(other.arguments()),
+ false); // Bounds are only checked at the top level.
+}
+
+
+RawAbstractType* Type::Canonicalize() const {
+ ASSERT(IsFinalized());
+ if (IsCanonical() || IsMalformed()) {
+ ASSERT(IsMalformed() || AbstractTypeArguments::Handle(arguments()).IsOld());
+ return this->raw();
+ }
+ const Class& cls = Class::Handle(type_class());
+ Array& canonical_types = Array::Handle(cls.canonical_types());
+ if (canonical_types.IsNull()) {
+ // Types defined in the VM isolate are canonicalized via the object store.
+ return this->raw();
+ }
+ const intptr_t canonical_types_len = canonical_types.Length();
+ // Linear search to see whether this type is already present in the
+ // list of canonicalized types.
+ // TODO(asiva): Try to re-factor this lookup code to make sharing
+ // easy between the 4 versions of this loop.
+ Type& type = Type::Handle();
+ intptr_t index = 0;
+ while (index < canonical_types_len) {
+ type ^= canonical_types.At(index);
+ if (type.IsNull()) {
+ break;
+ }
+ if (!type.IsFinalized()) {
+ ASSERT((index == 0) && cls.IsSignatureClass());
+ index++;
+ continue;
+ }
+ if (this->Equals(type)) {
+ return type.raw();
+ }
+ index++;
+ }
+ // Canonicalize the type arguments.
+ AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(arguments());
+ type_args = type_args.Canonicalize();
+ set_arguments(type_args);
+ // The type needs to be added to the list. Grow the list if it is full.
+ if (index == canonical_types_len) {
+ const intptr_t kLengthIncrement = 2; // Raw and parameterized.
+ const intptr_t new_length = canonical_types.Length() + kLengthIncrement;
+ const Array& new_canonical_types =
+ Array::Handle(Array::Grow(canonical_types, new_length, Heap::kOld));
+ cls.set_canonical_types(new_canonical_types);
+ new_canonical_types.SetAt(index, *this);
+ } else {
+ canonical_types.SetAt(index, *this);
+ }
+ ASSERT(IsOld());
+ SetCanonical();
+ return this->raw();
+}
+
+
+void Type::set_type_class(const Object& value) const {
+ ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
+ StorePointer(&raw_ptr()->type_class_, value.raw());
+}
+
+
+void Type::set_arguments(const AbstractTypeArguments& value) const {
+ StorePointer(&raw_ptr()->arguments_, value.raw());
+}
+
+
+RawType* Type::New(Heap::Space space) {
+ ASSERT(Isolate::Current()->object_store()->type_class() != Class::null());
+ RawObject* raw = Object::Allocate(Type::kClassId,
+ Type::InstanceSize(),
+ space);
+ return reinterpret_cast<RawType*>(raw);
+}
+
+
+RawType* Type::New(const Object& clazz,
+ const AbstractTypeArguments& arguments,
+ intptr_t token_pos,
+ Heap::Space space) {
+ const Type& result = Type::Handle(Type::New(space));
+ result.set_type_class(clazz);
+ result.set_arguments(arguments);
+ result.set_token_pos(token_pos);
+ result.raw_ptr()->type_state_ = RawType::kAllocated;
+ return result.raw();
+}
+
+
+void Type::set_token_pos(intptr_t token_pos) const {
+ ASSERT(token_pos >= 0);
+ raw_ptr()->token_pos_ = token_pos;
+}
+
+
+void Type::set_type_state(int8_t state) const {
+ ASSERT((state == RawType::kAllocated) ||
+ (state == RawType::kBeingFinalized) ||
+ (state == RawType::kFinalizedInstantiated) ||
+ (state == RawType::kFinalizedUninstantiated));
+ raw_ptr()->type_state_ = state;
+}
+
+
+const char* Type::ToCString() const {
+ if (IsResolved()) {
+ const AbstractTypeArguments& type_arguments =
+ AbstractTypeArguments::Handle(arguments());
+ if (type_arguments.IsNull()) {
+ const char* format = "Type: class '%s'";
+ const char* class_name =
+ String::Handle(Class::Handle(type_class()).Name()).ToCString();
+ intptr_t len = OS::SNPrint(NULL, 0, format, class_name) + 1;
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+ OS::SNPrint(chars, len, format, class_name);
+ return chars;
+ } else {
+ const char* format = "Type: class '%s', args:[%s]";
+ const char* class_name =
+ String::Handle(Class::Handle(type_class()).Name()).ToCString();
+ const char* args_cstr =
+ AbstractTypeArguments::Handle(arguments()).ToCString();
+ intptr_t len = OS::SNPrint(NULL, 0, format, class_name, args_cstr) + 1;
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+ OS::SNPrint(chars, len, format, class_name, args_cstr);
+ return chars;
+ }
+ } else {
+ return "Unresolved Type";
+ }
+}
+
+
+void TypeParameter::set_is_finalized() const {
+ ASSERT(!IsFinalized());
+ set_type_state(RawTypeParameter::kFinalizedUninstantiated);
+}
+
+
+bool TypeParameter::Equals(const Instance& other) const {
+ if (raw() == other.raw()) {
+ return true;
+ }
+ if (!other.IsTypeParameter()) {
+ return false;
+ }
+ const TypeParameter& other_type_param = TypeParameter::Cast(other);
+ if (IsFinalized() != other_type_param.IsFinalized()) {
+ return false;
+ }
+ if (parameterized_class() != other_type_param.parameterized_class()) {
+ return false;
+ }
+ if (index() != other_type_param.index()) {
+ return false;
+ }
+ const String& type_param_name = String::Handle(name());
+ const String& other_type_param_name = String::Handle(other_type_param.name());
+ return type_param_name.Equals(other_type_param_name);
+}
+
+
+bool TypeParameter::IsIdentical(const AbstractType& other,
+ bool check_type_parameter_bound) const {
+ if (raw() == other.raw()) {
+ return true;
+ }
+ if (!other.IsTypeParameter()) {
+ return false;
+ }
+ const TypeParameter& other_type_param = TypeParameter::Cast(other);
+ // IsIdentical may be called on type parameters belonging to different
+ // classes, e.g. to an interface and to its default factory class.
+ // Therefore, both type parameters may have different parameterized classes
+ // and different indices. Compare the type parameter names only, and their
+ // bounds if requested.
+ String& type_param_name = String::Handle(name());
+ String& other_type_param_name = String::Handle(other_type_param.name());
+ if (!type_param_name.Equals(other_type_param_name)) {
+ return false;
+ }
+ if (check_type_parameter_bound) {
+ AbstractType& this_bound = AbstractType::Handle(bound());
+ AbstractType& other_bound = AbstractType::Handle(other_type_param.bound());
+ // Bounds are only checked at the top level.
+ const bool check_type_parameter_bounds = false;
+ if (!this_bound.IsIdentical(other_bound, check_type_parameter_bounds)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+void TypeParameter::set_parameterized_class(const Class& value) const {
+ // Set value may be null.
+ StorePointer(&raw_ptr()->parameterized_class_, value.raw());
+}
+
+
+void TypeParameter::set_index(intptr_t value) const {
+ ASSERT(value >= 0);
+ raw_ptr()->index_ = value;
+}
+
+
+void TypeParameter::set_name(const String& value) const {
+ ASSERT(value.IsSymbol());
+ StorePointer(&raw_ptr()->name_, value.raw());
+}
+
+
+void TypeParameter::set_bound(const AbstractType& value) const {
+ StorePointer(&raw_ptr()->bound_, value.raw());
+}
+
+RawAbstractType* TypeParameter::InstantiateFrom(
+ const AbstractTypeArguments& instantiator_type_arguments) const {
+ ASSERT(IsFinalized());
+ if (instantiator_type_arguments.IsNull()) {
+ return Type::DynamicType();
+ }
+ return instantiator_type_arguments.TypeAt(index());
+}
+
+
+RawTypeParameter* TypeParameter::New() {
+ ASSERT(Isolate::Current()->object_store()->type_parameter_class() !=
+ Class::null());
+ RawObject* raw = Object::Allocate(TypeParameter::kClassId,
+ TypeParameter::InstanceSize(),
+ Heap::kOld);
+ return reinterpret_cast<RawTypeParameter*>(raw);
+}
+
+
+RawTypeParameter* TypeParameter::New(const Class& parameterized_class,
+ intptr_t index,
+ const String& name,
+ const AbstractType& bound,
+ intptr_t token_pos) {
+ const TypeParameter& result = TypeParameter::Handle(TypeParameter::New());
+ result.set_parameterized_class(parameterized_class);
+ result.set_index(index);
+ result.set_name(name);
+ result.set_bound(bound);
+ result.set_token_pos(token_pos);
+ result.raw_ptr()->type_state_ = RawTypeParameter::kAllocated;
+ return result.raw();
+}
+
+
+void TypeParameter::set_token_pos(intptr_t token_pos) const {
+ ASSERT(token_pos >= 0);
+ raw_ptr()->token_pos_ = token_pos;
+}
+
+
+void TypeParameter::set_type_state(int8_t state) const {
+ ASSERT((state == RawTypeParameter::kAllocated) ||
+ (state == RawTypeParameter::kBeingFinalized) ||
+ (state == RawTypeParameter::kFinalizedUninstantiated));
+ raw_ptr()->type_state_ = state;
+}
+
+
+const char* TypeParameter::ToCString() const {
+ const char* format = "TypeParameter: name %s; index: %d";
+ const char* name_cstr = String::Handle(Name()).ToCString();
+ intptr_t len = OS::SNPrint(NULL, 0, format, name_cstr, index()) + 1;
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+ OS::SNPrint(chars, len, format, name_cstr, index());
+ return chars;
+}
+
+
const char* Number::ToCString() const {
// Number is an interface. No instances of Number should exist.
UNREACHABLE();
« runtime/lib/object.cc ('K') | « runtime/vm/object.h ('k') | runtime/vm/object_store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698