| 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 |