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/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 ASSERT(arguments.ArgCount() == | 174 ASSERT(arguments.ArgCount() == |
175 kAllocateObjectWithBoundsCheckRuntimeEntry.argument_count()); | 175 kAllocateObjectWithBoundsCheckRuntimeEntry.argument_count()); |
176 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); | 176 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); |
177 const Instance& instance = Instance::Handle(Instance::New(cls)); | 177 const Instance& instance = Instance::Handle(Instance::New(cls)); |
178 arguments.SetReturn(instance); | 178 arguments.SetReturn(instance); |
179 ASSERT(cls.HasTypeArguments()); | 179 ASSERT(cls.HasTypeArguments()); |
180 AbstractTypeArguments& type_arguments = | 180 AbstractTypeArguments& type_arguments = |
181 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); | 181 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); |
182 ASSERT(type_arguments.IsNull() || | 182 ASSERT(type_arguments.IsNull() || |
183 (type_arguments.Length() == cls.NumTypeArguments())); | 183 (type_arguments.Length() == cls.NumTypeArguments())); |
184 AbstractTypeArguments& bounds_instantiator = AbstractTypeArguments::Handle(); | |
185 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) { | 184 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) { |
186 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() == | 185 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() == |
187 StubCode::kNoInstantiator); | 186 StubCode::kNoInstantiator); |
188 } else { | 187 } else { |
189 ASSERT(!type_arguments.IsInstantiated()); | 188 ASSERT(!type_arguments.IsInstantiated()); |
190 const AbstractTypeArguments& instantiator = | 189 const AbstractTypeArguments& instantiator = |
191 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2)); | 190 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2)); |
192 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); | 191 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); |
| 192 Error& malformed_error = Error::Handle(); |
193 if (instantiator.IsNull()) { | 193 if (instantiator.IsNull()) { |
194 type_arguments = | 194 type_arguments = type_arguments.InstantiateFrom(instantiator, |
195 InstantiatedTypeArguments::New(type_arguments, instantiator); | 195 &malformed_error); |
196 } else if (instantiator.IsTypeArguments()) { | 196 } else if (instantiator.IsTypeArguments()) { |
197 // Code inlined in the caller should have optimized the case where the | 197 // Code inlined in the caller should have optimized the case where the |
198 // instantiator is a TypeArguments and can be used as type argument | 198 // instantiator is a TypeArguments and can be used as type argument |
199 // vector. | 199 // vector. |
200 ASSERT(!type_arguments.IsUninstantiatedIdentity() || | 200 ASSERT(!type_arguments.IsUninstantiatedIdentity() || |
201 (instantiator.Length() != type_arguments.Length())); | 201 (instantiator.Length() != type_arguments.Length())); |
202 type_arguments = | 202 type_arguments = type_arguments.InstantiateFrom(instantiator, |
203 InstantiatedTypeArguments::New(type_arguments, instantiator); | 203 &malformed_error); |
204 } else { | 204 } else { |
205 // If possible, use the instantiator as the type argument vector. | 205 // If possible, use the instantiator as the type argument vector. |
206 if (type_arguments.IsUninstantiatedIdentity() && | 206 if (type_arguments.IsUninstantiatedIdentity() && |
207 (instantiator.Length() == type_arguments.Length())) { | 207 (instantiator.Length() == type_arguments.Length())) { |
208 type_arguments = instantiator.raw(); | 208 type_arguments = instantiator.raw(); |
209 } else { | 209 } else { |
210 type_arguments = | 210 type_arguments = type_arguments.InstantiateFrom(instantiator, |
211 InstantiatedTypeArguments::New(type_arguments, instantiator); | 211 &malformed_error); |
212 } | 212 } |
213 } | 213 } |
214 bounds_instantiator = instantiator.raw(); | 214 if (!malformed_error.IsNull()) { |
215 } | |
216 if (!type_arguments.IsNull()) { | |
217 ASSERT(type_arguments.IsInstantiated()); | |
218 Error& malformed_error = Error::Handle(); | |
219 if (!type_arguments.IsWithinBoundsOf(cls, | |
220 bounds_instantiator, | |
221 &malformed_error)) { | |
222 ASSERT(!malformed_error.IsNull()); | |
223 // Throw a dynamic type error. | 215 // Throw a dynamic type error. |
224 const intptr_t location = GetCallerLocation(); | 216 const intptr_t location = GetCallerLocation(); |
225 String& malformed_error_message = String::Handle( | 217 String& malformed_error_message = String::Handle( |
226 String::New(malformed_error.ToErrorCString())); | 218 String::New(malformed_error.ToErrorCString())); |
227 Exceptions::CreateAndThrowTypeError( | 219 Exceptions::CreateAndThrowTypeError( |
228 location, Symbols::Empty(), Symbols::Empty(), | 220 location, Symbols::Empty(), Symbols::Empty(), |
229 Symbols::Empty(), malformed_error_message); | 221 Symbols::Empty(), malformed_error_message); |
230 UNREACHABLE(); | 222 UNREACHABLE(); |
231 } | 223 } |
232 } | 224 } |
| 225 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); |
233 instance.SetTypeArguments(type_arguments); | 226 instance.SetTypeArguments(type_arguments); |
234 } | 227 } |
235 | 228 |
236 | 229 |
237 // Instantiate type arguments. | 230 // Instantiate type arguments. |
238 // Arg0: uninstantiated type arguments. | 231 // Arg0: uninstantiated type arguments. |
239 // Arg1: instantiator type arguments. | 232 // Arg1: instantiator type arguments. |
240 // Return value: instantiated type arguments. | 233 // Return value: instantiated type arguments. |
241 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { | 234 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { |
242 ASSERT(arguments.ArgCount() == | 235 ASSERT(arguments.ArgCount() == |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 OS::PrintErr("%s: '%s' %"Pd" %s '%s' %"Pd" (pc: %#"Px").\n", | 359 OS::PrintErr("%s: '%s' %"Pd" %s '%s' %"Pd" (pc: %#"Px").\n", |
367 message, | 360 message, |
368 String::Handle(instance_type.Name()).ToCString(), | 361 String::Handle(instance_type.Name()).ToCString(), |
369 Class::Handle(instance_type.type_class()).id(), | 362 Class::Handle(instance_type.type_class()).id(), |
370 (result.raw() == Bool::True().raw()) ? "is" : "is !", | 363 (result.raw() == Bool::True().raw()) ? "is" : "is !", |
371 String::Handle(type.Name()).ToCString(), | 364 String::Handle(type.Name()).ToCString(), |
372 Class::Handle(type.type_class()).id(), | 365 Class::Handle(type.type_class()).id(), |
373 caller_frame->pc()); | 366 caller_frame->pc()); |
374 } else { | 367 } else { |
375 // Instantiate type before printing. | 368 // Instantiate type before printing. |
376 const AbstractType& instantiated_type = | 369 Error& malformed_error = Error::Handle(); |
377 AbstractType::Handle(type.InstantiateFrom(instantiator_type_arguments)); | 370 const AbstractType& instantiated_type = AbstractType::Handle( |
| 371 type.InstantiateFrom(instantiator_type_arguments, &malformed_error)); |
378 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#"Px").\n", | 372 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#"Px").\n", |
379 message, | 373 message, |
380 String::Handle(instance_type.Name()).ToCString(), | 374 String::Handle(instance_type.Name()).ToCString(), |
381 (result.raw() == Bool::True().raw()) ? "is" : "is !", | 375 (result.raw() == Bool::True().raw()) ? "is" : "is !", |
382 String::Handle(instantiated_type.Name()).ToCString(), | 376 String::Handle(instantiated_type.Name()).ToCString(), |
383 String::Handle(type.Name()).ToCString(), | 377 String::Handle(type.Name()).ToCString(), |
384 caller_frame->pc()); | 378 caller_frame->pc()); |
| 379 if (!malformed_error.IsNull()) { |
| 380 OS::Print(" malformed error: %s\n", malformed_error.ToErrorCString()); |
| 381 } |
385 } | 382 } |
386 const Function& function = Function::Handle( | 383 const Function& function = Function::Handle( |
387 caller_frame->LookupDartFunction()); | 384 caller_frame->LookupDartFunction()); |
388 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); | 385 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); |
389 } | 386 } |
390 | 387 |
391 | 388 |
392 // Converts InstantiatedTypeArguments to TypeArguments and stores it | 389 // Converts InstantiatedTypeArguments to TypeArguments and stores it |
393 // into the instance. The assembly code can handle only type arguments of | 390 // into the instance. The assembly code can handle only type arguments of |
394 // class TypeArguments. Because of the overhead, do it only when needed. | 391 // class TypeArguments. Because of the overhead, do it only when needed. |
(...skipping 11 matching lines...) Expand all Loading... |
406 bool replaced = false; | 403 bool replaced = false; |
407 if (type_arguments.IsInstantiatedTypeArguments()) { | 404 if (type_arguments.IsInstantiatedTypeArguments()) { |
408 AbstractTypeArguments& uninstantiated = AbstractTypeArguments::Handle(); | 405 AbstractTypeArguments& uninstantiated = AbstractTypeArguments::Handle(); |
409 AbstractTypeArguments& instantiator = AbstractTypeArguments::Handle(); | 406 AbstractTypeArguments& instantiator = AbstractTypeArguments::Handle(); |
410 do { | 407 do { |
411 const InstantiatedTypeArguments& instantiated_type_arguments = | 408 const InstantiatedTypeArguments& instantiated_type_arguments = |
412 InstantiatedTypeArguments::Cast(type_arguments); | 409 InstantiatedTypeArguments::Cast(type_arguments); |
413 uninstantiated = | 410 uninstantiated = |
414 instantiated_type_arguments.uninstantiated_type_arguments(); | 411 instantiated_type_arguments.uninstantiated_type_arguments(); |
415 instantiator = instantiated_type_arguments.instantiator_type_arguments(); | 412 instantiator = instantiated_type_arguments.instantiator_type_arguments(); |
416 type_arguments = uninstantiated.InstantiateFrom(instantiator); | 413 Error& malformed_error = Error::Handle(); |
| 414 type_arguments = uninstantiated.InstantiateFrom(instantiator, |
| 415 &malformed_error); |
| 416 ASSERT(malformed_error.IsNull()); // Malformed types are not optimized. |
417 } while (type_arguments.IsInstantiatedTypeArguments()); | 417 } while (type_arguments.IsInstantiatedTypeArguments()); |
418 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle(); | 418 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle(); |
419 new_type_arguments = type_arguments.Canonicalize(); | 419 new_type_arguments = type_arguments.Canonicalize(); |
420 instance.SetTypeArguments(new_type_arguments); | 420 instance.SetTypeArguments(new_type_arguments); |
421 replaced = true; | 421 replaced = true; |
422 } else if (!type_arguments.IsCanonical()) { | 422 } else if (!type_arguments.IsCanonical()) { |
423 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle(); | 423 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle(); |
424 new_type_arguments = type_arguments.Canonicalize(); | 424 new_type_arguments = type_arguments.Canonicalize(); |
425 instance.SetTypeArguments(new_type_arguments); | 425 instance.SetTypeArguments(new_type_arguments); |
426 replaced = true; | 426 replaced = true; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 } | 509 } |
510 if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) { | 510 if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) { |
511 new_cache.AddCheck(instance_class.id(), | 511 new_cache.AddCheck(instance_class.id(), |
512 instance_type_arguments, | 512 instance_type_arguments, |
513 instantiator_type_arguments, | 513 instantiator_type_arguments, |
514 result); | 514 result); |
515 } | 515 } |
516 if (FLAG_trace_type_checks) { | 516 if (FLAG_trace_type_checks) { |
517 AbstractType& test_type = AbstractType::Handle(type.raw()); | 517 AbstractType& test_type = AbstractType::Handle(type.raw()); |
518 if (!test_type.IsInstantiated()) { | 518 if (!test_type.IsInstantiated()) { |
519 test_type = type.InstantiateFrom(instantiator_type_arguments); | 519 Error& malformed_error = Error::Handle(); |
| 520 test_type = type.InstantiateFrom(instantiator_type_arguments, |
| 521 &malformed_error); |
| 522 ASSERT(malformed_error.IsNull()); // Malformed types are not optimized. |
520 } | 523 } |
521 OS::PrintErr(" Updated test cache %p ix: %"Pd" with (%"Pd", %p, %p, %s)\n" | 524 OS::PrintErr(" Updated test cache %p ix: %"Pd" with (%"Pd", %p, %p, %s)\n" |
522 " [%p %s %"Pd", %p %s]\n" | 525 " [%p %s %"Pd", %p %s]\n" |
523 " [%p %s %"Pd", %p %s] %s\n", | 526 " [%p %s %"Pd", %p %s] %s\n", |
524 new_cache.raw(), | 527 new_cache.raw(), |
525 len, | 528 len, |
526 instance_class.id(), | 529 instance_class.id(), |
527 | 530 |
528 instance_type_arguments.raw(), | 531 instance_type_arguments.raw(), |
529 instantiator_type_arguments.raw(), | 532 instantiator_type_arguments.raw(), |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 } | 627 } |
625 if (!is_instance_of) { | 628 if (!is_instance_of) { |
626 // Throw a dynamic type error. | 629 // Throw a dynamic type error. |
627 const intptr_t location = GetCallerLocation(); | 630 const intptr_t location = GetCallerLocation(); |
628 const AbstractType& src_type = AbstractType::Handle(src_instance.GetType()); | 631 const AbstractType& src_type = AbstractType::Handle(src_instance.GetType()); |
629 const String& src_type_name = String::Handle(src_type.UserVisibleName()); | 632 const String& src_type_name = String::Handle(src_type.UserVisibleName()); |
630 String& dst_type_name = String::Handle(); | 633 String& dst_type_name = String::Handle(); |
631 if (!dst_type.IsInstantiated()) { | 634 if (!dst_type.IsInstantiated()) { |
632 // Instantiate dst_type before reporting the error. | 635 // Instantiate dst_type before reporting the error. |
633 const AbstractType& instantiated_dst_type = AbstractType::Handle( | 636 const AbstractType& instantiated_dst_type = AbstractType::Handle( |
634 dst_type.InstantiateFrom(instantiator_type_arguments)); | 637 dst_type.InstantiateFrom(instantiator_type_arguments, NULL)); |
| 638 // Note that instantiated_dst_type may be malformed. |
635 dst_type_name = instantiated_dst_type.UserVisibleName(); | 639 dst_type_name = instantiated_dst_type.UserVisibleName(); |
636 } else { | 640 } else { |
637 dst_type_name = dst_type.UserVisibleName(); | 641 dst_type_name = dst_type.UserVisibleName(); |
638 } | 642 } |
639 String& malformed_error_message = String::Handle(); | 643 String& malformed_error_message = String::Handle(); |
640 if (!malformed_error.IsNull()) { | 644 if (!malformed_error.IsNull()) { |
641 ASSERT(FLAG_enable_type_checks); | 645 ASSERT(FLAG_enable_type_checks); |
642 malformed_error_message = String::New(malformed_error.ToErrorCString()); | 646 malformed_error_message = String::New(malformed_error.ToErrorCString()); |
643 } | 647 } |
644 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, | 648 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, |
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1723 if (right < 0) { | 1727 if (right < 0) { |
1724 remainder -= right; | 1728 remainder -= right; |
1725 } else { | 1729 } else { |
1726 remainder += right; | 1730 remainder += right; |
1727 } | 1731 } |
1728 } | 1732 } |
1729 return remainder; | 1733 return remainder; |
1730 } | 1734 } |
1731 | 1735 |
1732 } // namespace dart | 1736 } // namespace dart |
OLD | NEW |