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/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); | 331 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); |
332 } | 332 } |
333 | 333 |
334 | 334 |
335 // This updates the type test cache, an array containing 4-value elements | 335 // This updates the type test cache, an array containing 4-value elements |
336 // (instance class, instance type arguments, instantiator type arguments and | 336 // (instance class, instance type arguments, instantiator type arguments and |
337 // test_result). It can be applied to classes with type arguments in which | 337 // test_result). It can be applied to classes with type arguments in which |
338 // case it contains just the result of the class subtype test, not including | 338 // case it contains just the result of the class subtype test, not including |
339 // the evaluation of type arguments. | 339 // the evaluation of type arguments. |
340 // This operation is currently very slow (lookup of code is not efficient yet). | 340 // This operation is currently very slow (lookup of code is not efficient yet). |
341 // 'instantiator' can be null, in which case inst_targ | |
342 static void UpdateTypeTestCache( | 341 static void UpdateTypeTestCache( |
343 const Instance& instance, | 342 const Instance& instance, |
344 const AbstractType& type, | 343 const AbstractType& type, |
345 const Instance& instantiator, | |
346 const TypeArguments& instantiator_type_arguments, | 344 const TypeArguments& instantiator_type_arguments, |
347 const Bool& result, | 345 const Bool& result, |
348 const SubtypeTestCache& new_cache) { | 346 const SubtypeTestCache& new_cache) { |
349 // Since the test is expensive, don't do it unless necessary. | 347 // Since the test is expensive, don't do it unless necessary. |
350 // The list of disallowed cases will decrease as they are implemented in | 348 // The list of disallowed cases will decrease as they are implemented in |
351 // inlined assembly. | 349 // inlined assembly. |
352 if (new_cache.IsNull()) { | 350 if (new_cache.IsNull()) { |
353 if (FLAG_trace_type_checks) { | 351 if (FLAG_trace_type_checks) { |
354 OS::Print("UpdateTypeTestCache: cache is null\n"); | 352 OS::Print("UpdateTypeTestCache: cache is null\n"); |
355 } | 353 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 instantiator_type_arguments.raw(), | 438 instantiator_type_arguments.raw(), |
441 instantiator_type_arguments.ToCString()); | 439 instantiator_type_arguments.ToCString()); |
442 } | 440 } |
443 } | 441 } |
444 | 442 |
445 | 443 |
446 // Check that the given instance is an instance of the given type. | 444 // Check that the given instance is an instance of the given type. |
447 // Tested instance may not be null, because the null test is inlined. | 445 // Tested instance may not be null, because the null test is inlined. |
448 // Arg0: instance being checked. | 446 // Arg0: instance being checked. |
449 // Arg1: type. | 447 // Arg1: type. |
450 // Arg2: instantiator (or null). | 448 // Arg2: type arguments of the instantiator of the type. |
451 // Arg3: type arguments of the instantiator of the type. | 449 // Arg3: SubtypeTestCache. |
452 // Arg4: SubtypeTestCache. | |
453 // Return value: true or false, or may throw a type error in checked mode. | 450 // Return value: true or false, or may throw a type error in checked mode. |
454 DEFINE_RUNTIME_ENTRY(Instanceof, 5) { | 451 DEFINE_RUNTIME_ENTRY(Instanceof, 4) { |
455 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); | 452 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); |
456 const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1)); | 453 const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1)); |
457 const Instance& instantiator = Instance::CheckedHandle(arguments.ArgAt(2)); | |
458 const TypeArguments& instantiator_type_arguments = | 454 const TypeArguments& instantiator_type_arguments = |
459 TypeArguments::CheckedHandle(arguments.ArgAt(3)); | 455 TypeArguments::CheckedHandle(arguments.ArgAt(2)); |
460 const SubtypeTestCache& cache = | 456 const SubtypeTestCache& cache = |
461 SubtypeTestCache::CheckedHandle(arguments.ArgAt(4)); | 457 SubtypeTestCache::CheckedHandle(arguments.ArgAt(3)); |
462 ASSERT(type.IsFinalized()); | 458 ASSERT(type.IsFinalized()); |
463 ASSERT(!type.IsDynamicType()); // No need to check assignment. | 459 ASSERT(!type.IsDynamicType()); // No need to check assignment. |
464 ASSERT(!type.IsMalformed()); // Already checked in code generator. | 460 ASSERT(!type.IsMalformed()); // Already checked in code generator. |
465 ASSERT(!type.IsMalbounded()); // Already checked in code generator. | 461 ASSERT(!type.IsMalbounded()); // Already checked in code generator. |
466 Error& bound_error = Error::Handle(); | 462 Error& bound_error = Error::Handle(); |
467 const Bool& result = | 463 const Bool& result = |
468 Bool::Get(instance.IsInstanceOf(type, | 464 Bool::Get(instance.IsInstanceOf(type, |
469 instantiator_type_arguments, | 465 instantiator_type_arguments, |
470 &bound_error)); | 466 &bound_error)); |
471 if (FLAG_trace_type_checks) { | 467 if (FLAG_trace_type_checks) { |
472 PrintTypeCheck("InstanceOf", | 468 PrintTypeCheck("InstanceOf", |
473 instance, type, instantiator_type_arguments, result); | 469 instance, type, instantiator_type_arguments, result); |
474 } | 470 } |
475 if (!result.value() && !bound_error.IsNull()) { | 471 if (!result.value() && !bound_error.IsNull()) { |
476 // Throw a dynamic type error only if the instanceof test fails. | 472 // Throw a dynamic type error only if the instanceof test fails. |
477 const intptr_t location = GetCallerLocation(); | 473 const intptr_t location = GetCallerLocation(); |
478 String& bound_error_message = String::Handle( | 474 String& bound_error_message = String::Handle( |
479 String::New(bound_error.ToErrorCString())); | 475 String::New(bound_error.ToErrorCString())); |
480 Exceptions::CreateAndThrowTypeError( | 476 Exceptions::CreateAndThrowTypeError( |
481 location, Symbols::Empty(), Symbols::Empty(), | 477 location, Symbols::Empty(), Symbols::Empty(), |
482 Symbols::Empty(), bound_error_message); | 478 Symbols::Empty(), bound_error_message); |
483 UNREACHABLE(); | 479 UNREACHABLE(); |
484 } | 480 } |
485 UpdateTypeTestCache(instance, type, instantiator, | 481 UpdateTypeTestCache( |
486 instantiator_type_arguments, result, cache); | 482 instance, type, instantiator_type_arguments, result, cache); |
487 arguments.SetReturn(result); | 483 arguments.SetReturn(result); |
488 } | 484 } |
489 | 485 |
490 | 486 |
491 // Check that the type of the given instance is a subtype of the given type and | 487 // Check that the type of the given instance is a subtype of the given type and |
492 // can therefore be assigned. | 488 // can therefore be assigned. |
493 // Arg0: instance being assigned. | 489 // Arg0: instance being assigned. |
494 // Arg1: type being assigned to. | 490 // Arg1: type being assigned to. |
495 // Arg2: instantiator (or null). | 491 // Arg2: type arguments of the instantiator of the type being assigned to. |
496 // Arg3: type arguments of the instantiator of the type being assigned to. | 492 // Arg3: name of variable being assigned to. |
497 // Arg4: name of variable being assigned to. | 493 // Arg4: SubtypeTestCache. |
498 // Arg5: SubtypeTestCache. | |
499 // Return value: instance if a subtype, otherwise throw a TypeError. | 494 // Return value: instance if a subtype, otherwise throw a TypeError. |
500 DEFINE_RUNTIME_ENTRY(TypeCheck, 6) { | 495 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) { |
501 const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0)); | 496 const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0)); |
502 const AbstractType& dst_type = | 497 const AbstractType& dst_type = |
503 AbstractType::CheckedHandle(arguments.ArgAt(1)); | 498 AbstractType::CheckedHandle(arguments.ArgAt(1)); |
504 const Instance& dst_instantiator = | |
505 Instance::CheckedHandle(arguments.ArgAt(2)); | |
506 const TypeArguments& instantiator_type_arguments = | 499 const TypeArguments& instantiator_type_arguments = |
507 TypeArguments::CheckedHandle(arguments.ArgAt(3)); | 500 TypeArguments::CheckedHandle(arguments.ArgAt(2)); |
508 const String& dst_name = String::CheckedHandle(arguments.ArgAt(4)); | 501 const String& dst_name = String::CheckedHandle(arguments.ArgAt(3)); |
509 const SubtypeTestCache& cache = | 502 const SubtypeTestCache& cache = |
510 SubtypeTestCache::CheckedHandle(arguments.ArgAt(5)); | 503 SubtypeTestCache::CheckedHandle(arguments.ArgAt(4)); |
511 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. | 504 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. |
512 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. | 505 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. |
513 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. | 506 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. |
514 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. | 507 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. |
515 | 508 |
516 Error& bound_error = Error::Handle(); | 509 Error& bound_error = Error::Handle(); |
517 const bool is_instance_of = src_instance.IsInstanceOf( | 510 const bool is_instance_of = src_instance.IsInstanceOf( |
518 dst_type, instantiator_type_arguments, &bound_error); | 511 dst_type, instantiator_type_arguments, &bound_error); |
519 | 512 |
520 if (FLAG_trace_type_checks) { | 513 if (FLAG_trace_type_checks) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 lib_name = dst_type_lib.name(); | 551 lib_name = dst_type_lib.name(); |
559 if (lib_name.Length() != 0) { | 552 if (lib_name.Length() != 0) { |
560 lib_name = String::Concat(lib_name, Symbols::Dot()); | 553 lib_name = String::Concat(lib_name, Symbols::Dot()); |
561 dst_type_name = String::Concat(lib_name, dst_type_name); | 554 dst_type_name = String::Concat(lib_name, dst_type_name); |
562 } | 555 } |
563 } | 556 } |
564 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, | 557 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, |
565 dst_name, bound_error_message); | 558 dst_name, bound_error_message); |
566 UNREACHABLE(); | 559 UNREACHABLE(); |
567 } | 560 } |
568 UpdateTypeTestCache(src_instance, dst_type, | 561 UpdateTypeTestCache( |
569 dst_instantiator, instantiator_type_arguments, | 562 src_instance, dst_type, instantiator_type_arguments, Bool::True(), cache); |
570 Bool::True(), cache); | |
571 arguments.SetReturn(src_instance); | 563 arguments.SetReturn(src_instance); |
572 } | 564 } |
573 | 565 |
574 | 566 |
575 // Report that the type of the given object is not bool in conditional context. | 567 // Report that the type of the given object is not bool in conditional context. |
576 // Throw assertion error if the object is null. (cf. Boolean Conversion | 568 // Throw assertion error if the object is null. (cf. Boolean Conversion |
577 // in language Spec.) | 569 // in language Spec.) |
578 // Arg0: bad object. | 570 // Arg0: bad object. |
579 // Return value: none, throws TypeError or AssertionError. | 571 // Return value: none, throws TypeError or AssertionError. |
580 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { | 572 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { |
(...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1882 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1874 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1883 const TypedData& new_data = | 1875 const TypedData& new_data = |
1884 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1876 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1885 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1877 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1886 typed_data_cell.SetAt(0, new_data); | 1878 typed_data_cell.SetAt(0, new_data); |
1887 arguments.SetReturn(new_data); | 1879 arguments.SetReturn(new_data); |
1888 } | 1880 } |
1889 | 1881 |
1890 | 1882 |
1891 } // namespace dart | 1883 } // namespace dart |
OLD | NEW |