| 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. |
| 156 if (Object::Handle(arguments.At(2)).IsSmi()) { |
| 157 ASSERT(Smi::CheckedHandle(arguments.At(2)).Value() == |
| 158 StubCode::kNoInstantiator); |
| 159 instance.SetTypeArguments(type_arguments); // May be null. |
| 178 return; | 160 return; |
| 179 } | 161 } |
| 180 ASSERT(type_arguments.Length() == cls.NumTypeArguments()); | 162 ASSERT(!type_arguments.IsInstantiated()); |
| 181 const AbstractTypeArguments& instantiator = | 163 const AbstractTypeArguments& instantiator = |
| 182 AbstractTypeArguments::CheckedHandle(arguments.At(2)); | 164 AbstractTypeArguments::CheckedHandle(arguments.At(2)); |
| 183 if (instantiator.IsNull()) { | 165 if (instantiator.IsNull()) { |
| 184 // Either the type argument vector is instantiated (use it), or the | 166 type_arguments = |
| 185 // instantiator is of a raw type and we cannot instantiate the type argument | 167 InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 186 // vector (leave it as null). | 168 } else if (instantiator.IsTypeArguments()) { |
| 187 if (type_arguments.IsInstantiated()) { | |
| 188 instance.SetTypeArguments(type_arguments); | |
| 189 } | |
| 190 return; | |
| 191 } | |
| 192 ASSERT(!type_arguments.IsInstantiated()); | |
| 193 // If possible, use the instantiator as the type argument vector. | |
| 194 if (instantiator.IsTypeArguments()) { | |
| 195 // Code inlined in the caller should have optimized the case where the | 169 // 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. | 170 // instantiator is a TypeArguments and can be used as type argument vector. |
| 197 ASSERT(!type_arguments.IsUninstantiatedIdentity() || | 171 ASSERT(!type_arguments.IsUninstantiatedIdentity() || |
| 198 (instantiator.Length() != type_arguments.Length())); | 172 (instantiator.Length() != type_arguments.Length())); |
| 199 type_arguments = | 173 type_arguments = |
| 200 InstantiatedTypeArguments::New(type_arguments, instantiator); | 174 InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 201 } else { | 175 } else { |
| 176 // If possible, use the instantiator as the type argument vector. |
| 202 if (type_arguments.IsUninstantiatedIdentity() && | 177 if (type_arguments.IsUninstantiatedIdentity() && |
| 203 (instantiator.Length() == type_arguments.Length())) { | 178 (instantiator.Length() == type_arguments.Length())) { |
| 204 type_arguments = instantiator.raw(); | 179 type_arguments = instantiator.raw(); |
| 205 } else { | 180 } else { |
| 206 type_arguments = | 181 type_arguments = |
| 207 InstantiatedTypeArguments::New(type_arguments, instantiator); | 182 InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 208 } | 183 } |
| 209 } | 184 } |
| 185 ASSERT(type_arguments.IsInstantiated()); |
| 210 instance.SetTypeArguments(type_arguments); | 186 instance.SetTypeArguments(type_arguments); |
| 211 } | 187 } |
| 212 | 188 |
| 213 | 189 |
| 214 // Instantiate type arguments. | 190 // Instantiate type arguments. |
| 215 // Arg0: uninstantiated type arguments. | 191 // Arg0: uninstantiated type arguments. |
| 216 // Arg1: instantiator type arguments. | 192 // Arg1: instantiator type arguments. |
| 217 // Return value: instantiated type arguments. | 193 // Return value: instantiated type arguments. |
| 218 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { | 194 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { |
| 219 ASSERT(arguments.Count() == | 195 ASSERT(arguments.Count() == |
| 220 kInstantiateTypeArgumentsRuntimeEntry.argument_count()); | 196 kInstantiateTypeArgumentsRuntimeEntry.argument_count()); |
| 221 AbstractTypeArguments& type_arguments = | 197 AbstractTypeArguments& type_arguments = |
| 222 AbstractTypeArguments::CheckedHandle(arguments.At(0)); | 198 AbstractTypeArguments::CheckedHandle(arguments.At(0)); |
| 223 const AbstractTypeArguments& instantiator = | 199 const AbstractTypeArguments& instantiator = |
| 224 AbstractTypeArguments::CheckedHandle(arguments.At(1)); | 200 AbstractTypeArguments::CheckedHandle(arguments.At(1)); |
| 225 ASSERT(!type_arguments.IsNull() && | 201 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); |
| 226 !type_arguments.IsInstantiated() && | |
| 227 !instantiator.IsNull()); | |
| 228 // Code inlined in the caller should have optimized the case where the | 202 // Code inlined in the caller should have optimized the case where the |
| 229 // instantiator can be used as type argument vector. | 203 // instantiator can be used as type argument vector. |
| 230 ASSERT(!type_arguments.IsUninstantiatedIdentity() || | 204 ASSERT(instantiator.IsNull() || |
| 205 !type_arguments.IsUninstantiatedIdentity() || |
| 231 !instantiator.IsTypeArguments() || | 206 !instantiator.IsTypeArguments() || |
| 232 (instantiator.Length() != type_arguments.Length())); | 207 (instantiator.Length() != type_arguments.Length())); |
| 233 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator); | 208 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator); |
| 209 ASSERT(type_arguments.IsInstantiated()); |
| 234 arguments.SetReturn(type_arguments); | 210 arguments.SetReturn(type_arguments); |
| 235 } | 211 } |
| 236 | 212 |
| 237 | 213 |
| 238 // Allocate a new closure. | 214 // Allocate a new closure. |
| 215 // The type argument vector of a closure is always the vector of type parameters |
| 216 // of its signature class, i.e. an uninstantiated identity vector. Therefore, |
| 217 // the instantiator type arguments can be used as the instantiated closure type |
| 218 // arguments and is passed here as the type arguments. |
| 239 // Arg0: local function. | 219 // Arg0: local function. |
| 240 // Arg1: type arguments of the closure. | 220 // Arg1: type arguments of the closure (i.e. instantiator). |
| 241 // Return value: newly allocated closure. | 221 // Return value: newly allocated closure. |
| 242 DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) { | 222 DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) { |
| 243 ASSERT(arguments.Count() == kAllocateClosureRuntimeEntry.argument_count()); | 223 ASSERT(arguments.Count() == kAllocateClosureRuntimeEntry.argument_count()); |
| 244 const Function& function = Function::CheckedHandle(arguments.At(0)); | 224 const Function& function = Function::CheckedHandle(arguments.At(0)); |
| 245 ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction()); | 225 ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction()); |
| 246 const AbstractTypeArguments& type_arguments = | 226 const AbstractTypeArguments& type_arguments = |
| 247 AbstractTypeArguments::CheckedHandle(arguments.At(1)); | 227 AbstractTypeArguments::CheckedHandle(arguments.At(1)); |
| 248 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); | 228 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); |
| 249 // The current context was saved in the Isolate structure when entering the | 229 // The current context was saved in the Isolate structure when entering the |
| 250 // runtime. | 230 // runtime. |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. | 391 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. |
| 412 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. | 392 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. |
| 413 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. | 393 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. |
| 414 | 394 |
| 415 Error& malformed_error = Error::Handle(); | 395 Error& malformed_error = Error::Handle(); |
| 416 const bool is_instance_of = src_instance.IsInstanceOf( | 396 const bool is_instance_of = src_instance.IsInstanceOf( |
| 417 dst_type, dst_type_instantiator, &malformed_error); | 397 dst_type, dst_type_instantiator, &malformed_error); |
| 418 | 398 |
| 419 if (FLAG_trace_type_checks) { | 399 if (FLAG_trace_type_checks) { |
| 420 const Type& src_type = Type::Handle(src_instance.GetType()); | 400 const Type& src_type = Type::Handle(src_instance.GetType()); |
| 401 ASSERT(src_type.IsInstantiated()); |
| 421 if (dst_type.IsInstantiated()) { | 402 if (dst_type.IsInstantiated()) { |
| 422 OS::Print("TypeCheck: type '%s' %s a subtype of type '%s' of '%s'.\n", | 403 OS::Print("TypeCheck: type '%s' %s a subtype of type '%s' of '%s'.\n", |
| 423 String::Handle(src_type.Name()).ToCString(), | 404 String::Handle(src_type.Name()).ToCString(), |
| 424 is_instance_of ? "is" : "is not", | 405 is_instance_of ? "is" : "is not", |
| 425 String::Handle(dst_type.Name()).ToCString(), | 406 String::Handle(dst_type.Name()).ToCString(), |
| 426 dst_name.ToCString()); | 407 dst_name.ToCString()); |
| 427 } else { | 408 } else { |
| 428 // Instantiate dst_type before printing. | 409 // Instantiate dst_type before printing. |
| 429 const AbstractType& instantiated_dst_type = AbstractType::Handle( | 410 const AbstractType& instantiated_dst_type = AbstractType::Handle( |
| 430 dst_type.InstantiateFrom(dst_type_instantiator)); | 411 dst_type.InstantiateFrom(dst_type_instantiator)); |
| (...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 } | 1394 } |
| 1414 } | 1395 } |
| 1415 } | 1396 } |
| 1416 // The cache is null terminated, therefore the loop above should never | 1397 // The cache is null terminated, therefore the loop above should never |
| 1417 // terminate by itself. | 1398 // terminate by itself. |
| 1418 UNREACHABLE(); | 1399 UNREACHABLE(); |
| 1419 return Code::null(); | 1400 return Code::null(); |
| 1420 } | 1401 } |
| 1421 | 1402 |
| 1422 } // namespace dart | 1403 } // namespace dart |
| OLD | NEW |