| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/code_generator.h" | 5 #include "vm/code_generator.h" |
| 6 | 6 |
| 7 #include "vm/code_index_table.h" | 7 #include "vm/code_index_table.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 const Function& function = Function::CheckedHandle(arguments.At(0)); | 107 const Function& function = Function::CheckedHandle(arguments.At(0)); |
| 108 const String& function_name = String::Handle(function.name()); | 108 const String& function_name = String::Handle(function.name()); |
| 109 const String& class_name = | 109 const String& class_name = |
| 110 String::Handle(Class::Handle(function.owner()).Name()); | 110 String::Handle(Class::Handle(function.owner()).Name()); |
| 111 OS::Print("< Exiting '%s.%s'\n", | 111 OS::Print("< Exiting '%s.%s'\n", |
| 112 class_name.ToCString(), function_name.ToCString()); | 112 class_name.ToCString(), function_name.ToCString()); |
| 113 } | 113 } |
| 114 | 114 |
| 115 | 115 |
| 116 // Allocation of a fixed length array of given element type. | 116 // Allocation of a fixed length array of given element type. |
| 117 // TODO(regis): This runtime entry is never called for allocating a List of a |
| 118 // generic type, which does not seem correct. Verify that generic user Lists are |
| 119 // properly supported. |
| 117 // Arg0: array length. | 120 // Arg0: array length. |
| 118 // Arg1: array element type. | 121 // Arg1: array element type. |
| 119 // Arg2: type arguments of the instantiator. | |
| 120 // Return value: newly allocated array of length arg0. | 122 // Return value: newly allocated array of length arg0. |
| 121 DEFINE_RUNTIME_ENTRY(AllocateArray, 3) { | 123 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) { |
| 122 ASSERT(arguments.Count() == kAllocateArrayRuntimeEntry.argument_count()); | 124 ASSERT(arguments.Count() == kAllocateArrayRuntimeEntry.argument_count()); |
| 123 const Smi& length = Smi::CheckedHandle(arguments.At(0)); | 125 const Smi& length = Smi::CheckedHandle(arguments.At(0)); |
| 124 const Array& array = Array::Handle(Array::New(length.Value())); | 126 const Array& array = Array::Handle(Array::New(length.Value())); |
| 125 arguments.SetReturn(array); | 127 arguments.SetReturn(array); |
| 126 AbstractTypeArguments& element_type = | 128 AbstractTypeArguments& element_type = |
| 127 AbstractTypeArguments::CheckedHandle(arguments.At(1)); | 129 AbstractTypeArguments::CheckedHandle(arguments.At(1)); |
| 128 if (element_type.IsNull()) { | 130 // An Array is raw or takes only one type argument. |
| 129 // No instantiator required for a raw type. | 131 ASSERT(element_type.IsNull() || (element_type.Length() == 1)); |
| 130 ASSERT(AbstractTypeArguments::CheckedHandle(arguments.At(2)).IsNull()); | 132 array.SetTypeArguments(element_type); // May be null. |
| 131 return; | |
| 132 } | |
| 133 // An Array takes only one type argument. | |
| 134 ASSERT(element_type.Length() == 1); | |
| 135 const AbstractTypeArguments& instantiator = | |
| 136 AbstractTypeArguments::CheckedHandle(arguments.At(2)); | |
| 137 if (instantiator.IsNull()) { | |
| 138 // Either the type element is instantiated (use it), or the instantiator is | |
| 139 // of a raw type and we cannot instantiate the element type (leave as null). | |
| 140 if (element_type.IsInstantiated()) { | |
| 141 array.SetTypeArguments(element_type); | |
| 142 } | |
| 143 return; | |
| 144 } | |
| 145 ASSERT(!element_type.IsInstantiated()); | |
| 146 // If possible, use the instantiator as the type argument vector. | |
| 147 if (element_type.IsUninstantiatedIdentity() && (instantiator.Length() == 1)) { | |
| 148 // No need to check that the instantiator is a TypeArguments, since the | |
| 149 // virtual call to Length() handles other cases that are harder to inline. | |
| 150 element_type = instantiator.raw(); | |
| 151 } else { | |
| 152 element_type = InstantiatedTypeArguments::New(element_type, instantiator); | |
| 153 } | |
| 154 array.SetTypeArguments(element_type); | |
| 155 } | 133 } |
| 156 | 134 |
| 157 | 135 |
| 158 // Allocate a new object. | 136 // Allocate a new object. |
| 159 // Arg0: class of the object that needs to be allocated. | 137 // Arg0: class of the object that needs to be allocated. |
| 160 // Arg1: type arguments of the object that needs to be allocated. | 138 // Arg1: type arguments of the object that needs to be allocated. |
| 161 // Arg2: type arguments of the instantiator. | 139 // Arg2: type arguments of the instantiator or kNoInstantiator. |
| 162 // Return value: newly allocated object. | 140 // Return value: newly allocated object. |
| 163 DEFINE_RUNTIME_ENTRY(AllocateObject, 3) { | 141 DEFINE_RUNTIME_ENTRY(AllocateObject, 3) { |
| 164 ASSERT(arguments.Count() == kAllocateObjectRuntimeEntry.argument_count()); | 142 ASSERT(arguments.Count() == kAllocateObjectRuntimeEntry.argument_count()); |
| 165 const Class& cls = Class::CheckedHandle(arguments.At(0)); | 143 const Class& cls = Class::CheckedHandle(arguments.At(0)); |
| 166 const Instance& instance = Instance::Handle(Instance::New(cls)); | 144 const Instance& instance = Instance::Handle(Instance::New(cls)); |
| 167 arguments.SetReturn(instance); | 145 arguments.SetReturn(instance); |
| 168 if (!cls.HasTypeArguments()) { | 146 if (!cls.HasTypeArguments()) { |
| 169 // No type arguments required for a non-parameterized type. | 147 // No type arguments required for a non-parameterized type. |
| 170 ASSERT(Instance::CheckedHandle(arguments.At(1)).IsNull()); | 148 ASSERT(Instance::CheckedHandle(arguments.At(1)).IsNull()); |
| 171 return; | 149 return; |
| 172 } | 150 } |
| 173 AbstractTypeArguments& type_arguments = | 151 AbstractTypeArguments& type_arguments = |
| 174 AbstractTypeArguments::CheckedHandle(arguments.At(1)); | 152 AbstractTypeArguments::CheckedHandle(arguments.At(1)); |
| 175 if (type_arguments.IsNull()) { | 153 ASSERT(type_arguments.IsNull() || |
| 176 // No instantiator is required for a raw type. | 154 (type_arguments.Length() == cls.NumTypeArguments())); |
| 177 ASSERT(Instance::CheckedHandle(arguments.At(2)).IsNull()); | 155 // If no instantiator is provided, set the type arguments and return. |
| 178 return; | 156 if (Object::Handle(arguments.At(2)).IsSmi()) { |
| 179 } | 157 ASSERT(Smi::CheckedHandle(arguments.At(2)).Value() == |
| 180 ASSERT(type_arguments.Length() == cls.NumTypeArguments()); | 158 StubCode::kNoInstantiator); |
| 181 const AbstractTypeArguments& instantiator = | 159 instance.SetTypeArguments(type_arguments); // May be null. |
| 182 AbstractTypeArguments::CheckedHandle(arguments.At(2)); | |
| 183 if (instantiator.IsNull()) { | |
| 184 // Either the type argument vector is instantiated (use it), or the | |
| 185 // instantiator is of a raw type and we cannot instantiate the type argument | |
| 186 // vector (leave it as null). | |
| 187 if (type_arguments.IsInstantiated()) { | |
| 188 instance.SetTypeArguments(type_arguments); | |
| 189 } | |
| 190 return; | 160 return; |
| 191 } | 161 } |
| 192 ASSERT(!type_arguments.IsInstantiated()); | 162 ASSERT(!type_arguments.IsInstantiated()); |
| 193 // If possible, use the instantiator as the type argument vector. | 163 const AbstractTypeArguments& instantiator = |
| 194 if (instantiator.IsTypeArguments()) { | 164 AbstractTypeArguments::CheckedHandle(arguments.At(2)); |
| 165 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); |
| 166 if (instantiator.IsNull()) { |
| 167 type_arguments = |
| 168 InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 169 } else if (instantiator.IsTypeArguments()) { |
| 195 // Code inlined in the caller should have optimized the case where the | 170 // Code inlined in the caller should have optimized the case where the |
| 196 // instantiator is a TypeArguments and can be used as type argument vector. | 171 // instantiator is a TypeArguments and can be used as type argument vector. |
| 197 ASSERT(!type_arguments.IsUninstantiatedIdentity() || | 172 ASSERT(!type_arguments.IsUninstantiatedIdentity() || |
| 198 (instantiator.Length() != type_arguments.Length())); | 173 (instantiator.Length() != type_arguments.Length())); |
| 199 type_arguments = | 174 type_arguments = |
| 200 InstantiatedTypeArguments::New(type_arguments, instantiator); | 175 InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 201 } else { | 176 } else { |
| 177 // If possible, use the instantiator as the type argument vector. |
| 202 if (type_arguments.IsUninstantiatedIdentity() && | 178 if (type_arguments.IsUninstantiatedIdentity() && |
| 203 (instantiator.Length() == type_arguments.Length())) { | 179 (instantiator.Length() == type_arguments.Length())) { |
| 204 type_arguments = instantiator.raw(); | 180 type_arguments = instantiator.raw(); |
| 205 } else { | 181 } else { |
| 206 type_arguments = | 182 type_arguments = |
| 207 InstantiatedTypeArguments::New(type_arguments, instantiator); | 183 InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 208 } | 184 } |
| 209 } | 185 } |
| 186 ASSERT(type_arguments.IsInstantiated()); |
| 210 instance.SetTypeArguments(type_arguments); | 187 instance.SetTypeArguments(type_arguments); |
| 211 } | 188 } |
| 212 | 189 |
| 213 | 190 |
| 214 // Instantiate type arguments. | 191 // Instantiate type arguments. |
| 215 // Arg0: uninstantiated type arguments. | 192 // Arg0: uninstantiated type arguments. |
| 216 // Arg1: instantiator type arguments. | 193 // Arg1: instantiator type arguments. |
| 217 // Return value: instantiated type arguments. | 194 // Return value: instantiated type arguments. |
| 218 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { | 195 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { |
| 219 ASSERT(arguments.Count() == | 196 ASSERT(arguments.Count() == |
| 220 kInstantiateTypeArgumentsRuntimeEntry.argument_count()); | 197 kInstantiateTypeArgumentsRuntimeEntry.argument_count()); |
| 221 AbstractTypeArguments& type_arguments = | 198 AbstractTypeArguments& type_arguments = |
| 222 AbstractTypeArguments::CheckedHandle(arguments.At(0)); | 199 AbstractTypeArguments::CheckedHandle(arguments.At(0)); |
| 223 const AbstractTypeArguments& instantiator = | 200 const AbstractTypeArguments& instantiator = |
| 224 AbstractTypeArguments::CheckedHandle(arguments.At(1)); | 201 AbstractTypeArguments::CheckedHandle(arguments.At(1)); |
| 225 ASSERT(!type_arguments.IsNull() && | 202 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); |
| 226 !type_arguments.IsInstantiated() && | 203 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); |
| 227 !instantiator.IsNull()); | |
| 228 // Code inlined in the caller should have optimized the case where the | 204 // Code inlined in the caller should have optimized the case where the |
| 229 // instantiator can be used as type argument vector. | 205 // instantiator can be used as type argument vector. |
| 230 ASSERT(!type_arguments.IsUninstantiatedIdentity() || | 206 ASSERT(instantiator.IsNull() || |
| 207 !type_arguments.IsUninstantiatedIdentity() || |
| 231 !instantiator.IsTypeArguments() || | 208 !instantiator.IsTypeArguments() || |
| 232 (instantiator.Length() != type_arguments.Length())); | 209 (instantiator.Length() != type_arguments.Length())); |
| 233 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator); | 210 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 211 ASSERT(type_arguments.IsInstantiated()); |
| 234 arguments.SetReturn(type_arguments); | 212 arguments.SetReturn(type_arguments); |
| 235 } | 213 } |
| 236 | 214 |
| 237 | 215 |
| 238 // Allocate a new closure. | 216 // Allocate a new closure. |
| 217 // The type argument vector of a closure is always the vector of type parameters |
| 218 // of its signature class, i.e. an uninstantiated identity vector. Therefore, |
| 219 // the instantiator type arguments can be used as the instantiated closure type |
| 220 // arguments and is passed here as the type arguments. |
| 239 // Arg0: local function. | 221 // Arg0: local function. |
| 240 // Arg1: type arguments of the closure. | 222 // Arg1: type arguments of the closure (i.e. instantiator). |
| 241 // Return value: newly allocated closure. | 223 // Return value: newly allocated closure. |
| 242 DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) { | 224 DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) { |
| 243 ASSERT(arguments.Count() == kAllocateClosureRuntimeEntry.argument_count()); | 225 ASSERT(arguments.Count() == kAllocateClosureRuntimeEntry.argument_count()); |
| 244 const Function& function = Function::CheckedHandle(arguments.At(0)); | 226 const Function& function = Function::CheckedHandle(arguments.At(0)); |
| 245 ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction()); | 227 ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction()); |
| 246 const AbstractTypeArguments& type_arguments = | 228 const AbstractTypeArguments& type_arguments = |
| 247 AbstractTypeArguments::CheckedHandle(arguments.At(1)); | 229 AbstractTypeArguments::CheckedHandle(arguments.At(1)); |
| 248 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); | 230 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); |
| 249 // The current context was saved in the Isolate structure when entering the | 231 // The current context was saved in the Isolate structure when entering the |
| 250 // runtime. | 232 // runtime. |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. | 393 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. |
| 412 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. | 394 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. |
| 413 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. | 395 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. |
| 414 | 396 |
| 415 Error& malformed_error = Error::Handle(); | 397 Error& malformed_error = Error::Handle(); |
| 416 const bool is_instance_of = src_instance.IsInstanceOf( | 398 const bool is_instance_of = src_instance.IsInstanceOf( |
| 417 dst_type, dst_type_instantiator, &malformed_error); | 399 dst_type, dst_type_instantiator, &malformed_error); |
| 418 | 400 |
| 419 if (FLAG_trace_type_checks) { | 401 if (FLAG_trace_type_checks) { |
| 420 const Type& src_type = Type::Handle(src_instance.GetType()); | 402 const Type& src_type = Type::Handle(src_instance.GetType()); |
| 403 ASSERT(src_type.IsInstantiated()); |
| 421 if (dst_type.IsInstantiated()) { | 404 if (dst_type.IsInstantiated()) { |
| 422 OS::Print("TypeCheck: type '%s' %s a subtype of type '%s' of '%s'.\n", | 405 OS::Print("TypeCheck: type '%s' %s a subtype of type '%s' of '%s'.\n", |
| 423 String::Handle(src_type.Name()).ToCString(), | 406 String::Handle(src_type.Name()).ToCString(), |
| 424 is_instance_of ? "is" : "is not", | 407 is_instance_of ? "is" : "is not", |
| 425 String::Handle(dst_type.Name()).ToCString(), | 408 String::Handle(dst_type.Name()).ToCString(), |
| 426 dst_name.ToCString()); | 409 dst_name.ToCString()); |
| 427 } else { | 410 } else { |
| 428 // Instantiate dst_type before printing. | 411 // Instantiate dst_type before printing. |
| 429 const AbstractType& instantiated_dst_type = AbstractType::Handle( | 412 const AbstractType& instantiated_dst_type = AbstractType::Handle( |
| 430 dst_type.InstantiateFrom(dst_type_instantiator)); | 413 dst_type.InstantiateFrom(dst_type_instantiator)); |
| (...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 } | 1396 } |
| 1414 } | 1397 } |
| 1415 } | 1398 } |
| 1416 // The cache is null terminated, therefore the loop above should never | 1399 // The cache is null terminated, therefore the loop above should never |
| 1417 // terminate by itself. | 1400 // terminate by itself. |
| 1418 UNREACHABLE(); | 1401 UNREACHABLE(); |
| 1419 return Code::null(); | 1402 return Code::null(); |
| 1420 } | 1403 } |
| 1421 | 1404 |
| 1422 } // namespace dart | 1405 } // namespace dart |
| OLD | NEW |