| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
| 6 | 6 |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); | 577 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); |
| 578 if (super_type.IsBeingFinalized()) { | 578 if (super_type.IsBeingFinalized()) { |
| 579 // This type references itself via its type arguments. This is legal, but | 579 // This type references itself via its type arguments. This is legal, but |
| 580 // we must avoid endless recursion. We therefore map the innermost | 580 // we must avoid endless recursion. We therefore map the innermost |
| 581 // super type to dynamic. | 581 // super type to dynamic. |
| 582 // Note that a direct self-reference via the super class chain is illegal | 582 // Note that a direct self-reference via the super class chain is illegal |
| 583 // and reported as an error earlier. | 583 // and reported as an error earlier. |
| 584 // Such legal self-references occur with F-bounded quantification. | 584 // Such legal self-references occur with F-bounded quantification. |
| 585 // Example 1: class Derived extends Base<Derived>. | 585 // Example 1: class Derived extends Base<Derived>. |
| 586 // The type 'Derived' forms a cycle by pointing to itself via its | 586 // The type 'Derived' forms a cycle by pointing to itself via its |
| 587 // flattened type argument vector: Derived[Base[Derived[Base[...]]]] | 587 // flattened type argument vector: Derived[Derived[...]] |
| 588 // We break the cycle as follows: Derived[Base[Derived[dynamic]]] | 588 // We break the cycle as follows: Derived[Derived[dynamic]] |
| 589 // Example 2: class Derived extends Base<Middle<Derived>> results in | 589 // Example 2: class Derived extends Base<Middle<Derived>> results in |
| 590 // Derived[Base[Middle[Derived[dynamic]]]] | 590 // Derived[Middle[Derived[dynamic]]] |
| 591 // Example 3: class Derived<T> extends Base<Derived<T>> results in | 591 // Example 3: class Derived<T> extends Base<Derived<T>> results in |
| 592 // Derived[Base[Derived[dynamic]], T]. | 592 // Derived[Derived[dynamic], T]. |
| 593 ASSERT(super_type_args.IsNull()); // Same as a vector of dynamic. | 593 ASSERT(super_type_args.IsNull()); // Same as a vector of dynamic. |
| 594 } else { | 594 } else { |
| 595 super_type ^= FinalizeType(cls, super_type, finalization); | 595 super_type ^= FinalizeType(cls, super_type, finalization); |
| 596 cls.set_super_type(super_type); | 596 cls.set_super_type(super_type); |
| 597 super_type_args = super_type.arguments(); | 597 super_type_args = super_type.arguments(); |
| 598 } | 598 } |
| 599 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 599 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
| 600 const intptr_t offset = super_class.NumTypeArguments(); | 600 const intptr_t offset = super_class.NumTypeArguments(); |
| 601 const intptr_t super_offset = offset - num_super_type_params; | 601 const intptr_t super_offset = offset - num_super_type_params; |
| 602 ASSERT(offset == (cls.NumTypeArguments() - cls.NumOwnTypeArguments())); | 602 ASSERT(offset == (cls.NumTypeArguments() - cls.NumOwnTypeArguments())); |
| (...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2120 if (!test2.IsNull()) { | 2120 if (!test2.IsNull()) { |
| 2121 test2 = test2.SuperClass(); | 2121 test2 = test2.SuperClass(); |
| 2122 } | 2122 } |
| 2123 } | 2123 } |
| 2124 // No cycles. | 2124 // No cycles. |
| 2125 return true; | 2125 return true; |
| 2126 } | 2126 } |
| 2127 | 2127 |
| 2128 | 2128 |
| 2129 // Helper function called by IsAliasCycleFree. | 2129 // Helper function called by IsAliasCycleFree. |
| 2130 bool ClassFinalizer::IsParameterTypeCycleFree( | 2130 bool ClassFinalizer::IsTypeCycleFree( |
| 2131 const Class& cls, | 2131 const Class& cls, |
| 2132 const AbstractType& type, | 2132 const AbstractType& type, |
| 2133 GrowableArray<intptr_t>* visited) { | 2133 GrowableArray<intptr_t>* visited) { |
| 2134 ASSERT(visited != NULL); | 2134 ASSERT(visited != NULL); |
| 2135 ResolveType(cls, type, kCanonicalize); | 2135 ResolveType(cls, type, kCanonicalize); |
| 2136 if (type.IsType() && !type.IsMalformed()) { | 2136 if (type.IsType() && !type.IsMalformed()) { |
| 2137 const Class& type_class = Class::Handle(type.type_class()); | 2137 const Class& type_class = Class::Handle(type.type_class()); |
| 2138 if (!type_class.is_type_finalized() && | 2138 if (!type_class.is_type_finalized() && |
| 2139 type_class.IsSignatureClass() && | 2139 type_class.IsSignatureClass() && |
| 2140 !IsAliasCycleFree(type_class, visited)) { | 2140 !IsAliasCycleFree(type_class, visited)) { |
| 2141 return false; | 2141 return false; |
| 2142 } | 2142 } |
| 2143 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( | 2143 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( |
| 2144 type.arguments()); | 2144 type.arguments()); |
| 2145 if (!type_args.IsNull()) { | 2145 if (!type_args.IsNull()) { |
| 2146 AbstractType& type_arg = AbstractType::Handle(); | 2146 AbstractType& type_arg = AbstractType::Handle(); |
| 2147 for (intptr_t i = 0; i < type_args.Length(); i++) { | 2147 for (intptr_t i = 0; i < type_args.Length(); i++) { |
| 2148 type_arg = type_args.TypeAt(i); | 2148 type_arg = type_args.TypeAt(i); |
| 2149 if (!IsParameterTypeCycleFree(cls, type_arg, visited)) { | 2149 if (!IsTypeCycleFree(cls, type_arg, visited)) { |
| 2150 return false; | 2150 return false; |
| 2151 } | 2151 } |
| 2152 } | 2152 } |
| 2153 } | 2153 } |
| 2154 } | 2154 } |
| 2155 return true; | 2155 return true; |
| 2156 } | 2156 } |
| 2157 | 2157 |
| 2158 | 2158 |
| 2159 // Returns false if the function type alias illegally refers to itself. | 2159 // Returns false if the function type alias illegally refers to itself. |
| 2160 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, | 2160 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, |
| 2161 GrowableArray<intptr_t>* visited) { | 2161 GrowableArray<intptr_t>* visited) { |
| 2162 ASSERT(cls.IsSignatureClass()); | 2162 ASSERT(cls.IsSignatureClass()); |
| 2163 ASSERT(!cls.is_type_finalized()); | 2163 ASSERT(!cls.is_type_finalized()); |
| 2164 ASSERT(visited != NULL); | 2164 ASSERT(visited != NULL); |
| 2165 const intptr_t cls_index = cls.id(); | 2165 const intptr_t cls_index = cls.id(); |
| 2166 for (intptr_t i = 0; i < visited->length(); i++) { | 2166 for (intptr_t i = 0; i < visited->length(); i++) { |
| 2167 if ((*visited)[i] == cls_index) { | 2167 if ((*visited)[i] == cls_index) { |
| 2168 // We have already visited alias 'cls'. We found a cycle. | 2168 // We have already visited alias 'cls'. We found a cycle. |
| 2169 return false; | 2169 return false; |
| 2170 } | 2170 } |
| 2171 } | 2171 } |
| 2172 | 2172 |
| 2173 // Visit the result type and parameter types of this signature type. | 2173 // Visit the bounds, result type, and parameter types of this signature type. |
| 2174 visited->Add(cls.id()); | 2174 visited->Add(cls.id()); |
| 2175 AbstractType& type = AbstractType::Handle(); |
| 2176 |
| 2177 // Check the bounds of this signature type. |
| 2178 const intptr_t num_type_params = cls.NumTypeParameters(); |
| 2179 TypeParameter& type_param = TypeParameter::Handle(); |
| 2180 const AbstractTypeArguments& type_params = |
| 2181 AbstractTypeArguments::Handle(cls.type_parameters()); |
| 2182 ASSERT((type_params.IsNull() && (num_type_params == 0)) || |
| 2183 (type_params.Length() == num_type_params)); |
| 2184 for (intptr_t i = 0; i < num_type_params; i++) { |
| 2185 type_param ^= type_params.TypeAt(i); |
| 2186 type = type_param.bound(); |
| 2187 if (!IsTypeCycleFree(cls, type, visited)) { |
| 2188 return false; |
| 2189 } |
| 2190 } |
| 2191 // Check the result type of the function of this signature type. |
| 2175 const Function& function = Function::Handle(cls.signature_function()); | 2192 const Function& function = Function::Handle(cls.signature_function()); |
| 2176 // Check class of result type. | 2193 type = function.result_type(); |
| 2177 AbstractType& type = AbstractType::Handle(function.result_type()); | 2194 if (!IsTypeCycleFree(cls, type, visited)) { |
| 2178 if (!IsParameterTypeCycleFree(cls, type, visited)) { | |
| 2179 return false; | 2195 return false; |
| 2180 } | 2196 } |
| 2181 // Check classes of formal parameter types. | 2197 // Check the formal parameter types of the function of this signature type. |
| 2182 const intptr_t num_parameters = function.NumParameters(); | 2198 const intptr_t num_parameters = function.NumParameters(); |
| 2183 for (intptr_t i = 0; i < num_parameters; i++) { | 2199 for (intptr_t i = 0; i < num_parameters; i++) { |
| 2184 type = function.ParameterTypeAt(i); | 2200 type = function.ParameterTypeAt(i); |
| 2185 if (!IsParameterTypeCycleFree(cls, type, visited)) { | 2201 if (!IsTypeCycleFree(cls, type, visited)) { |
| 2186 return false; | 2202 return false; |
| 2187 } | 2203 } |
| 2188 } | 2204 } |
| 2189 visited->RemoveLast(); | 2205 visited->RemoveLast(); |
| 2190 return true; | 2206 return true; |
| 2191 } | 2207 } |
| 2192 | 2208 |
| 2193 | 2209 |
| 2194 // Returns false if the mixin illegally refers to itself. | 2210 // Returns false if the mixin illegally refers to itself. |
| 2195 bool ClassFinalizer::IsMixinCycleFree(const Class& cls, | 2211 bool ClassFinalizer::IsMixinCycleFree(const Class& cls, |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2746 expected_name ^= String::New("_offset"); | 2762 expected_name ^= String::New("_offset"); |
| 2747 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2763 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 2748 field ^= fields_array.At(2); | 2764 field ^= fields_array.At(2); |
| 2749 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2765 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 2750 name ^= field.name(); | 2766 name ^= field.name(); |
| 2751 ASSERT(name.Equals("length")); | 2767 ASSERT(name.Equals("length")); |
| 2752 #endif | 2768 #endif |
| 2753 } | 2769 } |
| 2754 | 2770 |
| 2755 } // namespace dart | 2771 } // namespace dart |
| OLD | NEW |