| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 String::New(malformed_error.ToErrorCString())); | 406 String::New(malformed_error.ToErrorCString())); |
| 407 const String& no_name = String::Handle(String::NewSymbol("")); | 407 const String& no_name = String::Handle(String::NewSymbol("")); |
| 408 Exceptions::CreateAndThrowTypeError( | 408 Exceptions::CreateAndThrowTypeError( |
| 409 location, no_name, no_name, no_name, malformed_error_message); | 409 location, no_name, no_name, no_name, malformed_error_message); |
| 410 UNREACHABLE(); | 410 UNREACHABLE(); |
| 411 } | 411 } |
| 412 arguments.SetReturn(result); | 412 arguments.SetReturn(result); |
| 413 } | 413 } |
| 414 | 414 |
| 415 | 415 |
| 416 // Check that the type of the given instance is assignable to the given type. | 416 // Check that the type of the given instance is a subtype of the given type and |
| 417 // can therefore be assigned. |
| 417 // Arg0: index of the token of the assignment (source location). | 418 // Arg0: index of the token of the assignment (source location). |
| 418 // Arg1: instance being assigned. | 419 // Arg1: instance being assigned. |
| 419 // Arg2: type being assigned to. | 420 // Arg2: type being assigned to. |
| 420 // Arg3: type arguments of the instantiator of the type being assigned to. | 421 // Arg3: type arguments of the instantiator of the type being assigned to. |
| 421 // Arg4: name of instance being assigned to. | 422 // Arg4: name of variable being assigned to. |
| 422 // Return value: instance if assignable, otherwise throw a TypeError. | 423 // Return value: instance if a subtype, otherwise throw a TypeError. |
| 423 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) { | 424 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) { |
| 424 ASSERT(arguments.Count() == kTypeCheckRuntimeEntry.argument_count()); | 425 ASSERT(arguments.Count() == kTypeCheckRuntimeEntry.argument_count()); |
| 425 // TODO(regis): Get the token index from the PcDesc (via DartFrame). | 426 // TODO(regis): Get the token index from the PcDesc (via DartFrame). |
| 426 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); | 427 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); |
| 427 const Instance& src_instance = Instance::CheckedHandle(arguments.At(1)); | 428 const Instance& src_instance = Instance::CheckedHandle(arguments.At(1)); |
| 428 const AbstractType& dst_type = AbstractType::CheckedHandle(arguments.At(2)); | 429 const AbstractType& dst_type = AbstractType::CheckedHandle(arguments.At(2)); |
| 429 const AbstractTypeArguments& dst_type_instantiator = | 430 const AbstractTypeArguments& dst_type_instantiator = |
| 430 AbstractTypeArguments::CheckedHandle(arguments.At(3)); | 431 AbstractTypeArguments::CheckedHandle(arguments.At(3)); |
| 431 const String& dst_name = String::CheckedHandle(arguments.At(4)); | 432 const String& dst_name = String::CheckedHandle(arguments.At(4)); |
| 432 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. | 433 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. |
| 434 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. |
| 433 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. | 435 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. |
| 434 | 436 |
| 435 Error& malformed_error = Error::Handle(); | 437 Error& malformed_error = Error::Handle(); |
| 436 const bool is_assignable = src_instance.IsAssignableTo( | 438 const bool is_instance_of = src_instance.IsInstanceOf( |
| 437 dst_type, dst_type_instantiator, &malformed_error); | 439 dst_type, dst_type_instantiator, &malformed_error); |
| 438 | 440 |
| 439 if (FLAG_trace_type_checks) { | 441 if (FLAG_trace_type_checks) { |
| 440 const Type& src_type = Type::Handle(src_instance.GetType()); | 442 const Type& src_type = Type::Handle(src_instance.GetType()); |
| 441 if (dst_type.IsInstantiated()) { | 443 if (dst_type.IsInstantiated()) { |
| 442 OS::Print("TypeCheck: '%s' %s assignable to '%s' of '%s'.\n", | 444 OS::Print("TypeCheck: type '%s' %s a subtype of type '%s' of '%s'.\n", |
| 443 String::Handle(src_type.Name()).ToCString(), | 445 String::Handle(src_type.Name()).ToCString(), |
| 444 is_assignable ? "is" : "is not", | 446 is_instance_of ? "is" : "is not", |
| 445 String::Handle(dst_type.Name()).ToCString(), | 447 String::Handle(dst_type.Name()).ToCString(), |
| 446 dst_name.ToCString()); | 448 dst_name.ToCString()); |
| 447 } else { | 449 } else { |
| 448 // Instantiate dst_type before printing. | 450 // Instantiate dst_type before printing. |
| 449 const AbstractType& instantiated_dst_type = AbstractType::Handle( | 451 const AbstractType& instantiated_dst_type = AbstractType::Handle( |
| 450 dst_type.InstantiateFrom(dst_type_instantiator)); | 452 dst_type.InstantiateFrom(dst_type_instantiator)); |
| 451 OS::Print("TypeCheck: '%s' %s assignable to '%s' of '%s' " | 453 OS::Print("TypeCheck: type '%s' %s a subtype of type '%s' of '%s' " |
| 452 "instantiated from '%s'.\n", | 454 "instantiated from '%s'.\n", |
| 453 String::Handle(src_type.Name()).ToCString(), | 455 String::Handle(src_type.Name()).ToCString(), |
| 454 is_assignable ? "is" : "is not", | 456 is_instance_of ? "is" : "is not", |
| 455 String::Handle(instantiated_dst_type.Name()).ToCString(), | 457 String::Handle(instantiated_dst_type.Name()).ToCString(), |
| 456 dst_name.ToCString(), | 458 dst_name.ToCString(), |
| 457 String::Handle(dst_type.Name()).ToCString()); | 459 String::Handle(dst_type.Name()).ToCString()); |
| 458 } | 460 } |
| 459 DartFrameIterator iterator; | 461 DartFrameIterator iterator; |
| 460 DartFrame* caller_frame = iterator.NextFrame(); | 462 DartFrame* caller_frame = iterator.NextFrame(); |
| 461 ASSERT(caller_frame != NULL); | 463 ASSERT(caller_frame != NULL); |
| 462 const Function& function = Function::Handle( | 464 const Function& function = Function::Handle( |
| 463 caller_frame->LookupDartFunction()); | 465 caller_frame->LookupDartFunction()); |
| 464 OS::Print(" -> Function %s\n", function.ToFullyQualifiedCString()); | 466 OS::Print(" -> Function %s\n", function.ToFullyQualifiedCString()); |
| 465 } | 467 } |
| 466 if (!is_assignable) { | 468 if (!is_instance_of) { |
| 467 const Type& src_type = Type::Handle(src_instance.GetType()); | 469 const Type& src_type = Type::Handle(src_instance.GetType()); |
| 468 const String& src_type_name = String::Handle(src_type.Name()); | 470 const String& src_type_name = String::Handle(src_type.Name()); |
| 469 String& dst_type_name = String::Handle(); | 471 String& dst_type_name = String::Handle(); |
| 470 if (!dst_type.IsInstantiated()) { | 472 if (!dst_type.IsInstantiated()) { |
| 471 // Instantiate dst_type before reporting the error. | 473 // Instantiate dst_type before reporting the error. |
| 472 const AbstractType& instantiated_dst_type = AbstractType::Handle( | 474 const AbstractType& instantiated_dst_type = AbstractType::Handle( |
| 473 dst_type.InstantiateFrom(dst_type_instantiator)); | 475 dst_type.InstantiateFrom(dst_type_instantiator)); |
| 474 dst_type_name = instantiated_dst_type.Name(); | 476 dst_type_name = instantiated_dst_type.Name(); |
| 475 } else { | 477 } else { |
| 476 dst_type_name = dst_type.Name(); | 478 dst_type_name = dst_type.Name(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 const String& malformed_error = String::CheckedHandle(arguments.At(3)); | 529 const String& malformed_error = String::CheckedHandle(arguments.At(3)); |
| 528 const String& dst_type_name = String::Handle(String::NewSymbol("malformed")); | 530 const String& dst_type_name = String::Handle(String::NewSymbol("malformed")); |
| 529 const String& src_type_name = | 531 const String& src_type_name = |
| 530 String::Handle(Type::Handle(src_value.GetType()).Name()); | 532 String::Handle(Type::Handle(src_value.GetType()).Name()); |
| 531 Exceptions::CreateAndThrowTypeError(location, src_type_name, | 533 Exceptions::CreateAndThrowTypeError(location, src_type_name, |
| 532 dst_type_name, dst_name, malformed_error); | 534 dst_type_name, dst_name, malformed_error); |
| 533 UNREACHABLE(); | 535 UNREACHABLE(); |
| 534 } | 536 } |
| 535 | 537 |
| 536 | 538 |
| 539 // TODO(regis): Function rest arguments are not supported anymore, but they may |
| 540 // come back. |
| 537 // Check that the type of each element of the given array is assignable to the | 541 // Check that the type of each element of the given array is assignable to the |
| 538 // given type. | 542 // given type. |
| 539 // Arg0: index of the token of the rest argument declaration (source location). | 543 // Arg0: index of the token of the rest argument declaration (source location). |
| 540 // Arg1: rest argument array. | 544 // Arg1: rest argument array. |
| 541 // Arg2: element declaration type. | 545 // Arg2: element declaration type. |
| 542 // Arg3: type arguments of the instantiator of the element declaration type. | 546 // Arg3: type arguments of the instantiator of the element declaration type. |
| 543 // Arg4: name of object being assigned to, i.e. name of rest argument. | 547 // Arg4: name of object being assigned to, i.e. name of rest argument. |
| 544 // Return value: null if assignable, otherwise allocate and throw a TypeError. | 548 // Return value: null if assignable, otherwise allocate and throw a TypeError. |
| 545 DEFINE_RUNTIME_ENTRY(RestArgumentTypeCheck, 5) { | 549 DEFINE_RUNTIME_ENTRY(RestArgumentTypeCheck, 5) { |
| 546 ASSERT(arguments.Count() == | 550 ASSERT(arguments.Count() == |
| 547 kRestArgumentTypeCheckRuntimeEntry.argument_count()); | 551 kRestArgumentTypeCheckRuntimeEntry.argument_count()); |
| 548 // TODO(regis): Get the token index from the PcDesc (via DartFrame). | 552 // TODO(regis): Get the token index from the PcDesc (via DartFrame). |
| 549 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); | 553 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); |
| 550 const Array& rest_array = Array::CheckedHandle(arguments.At(1)); | 554 const Array& rest_array = Array::CheckedHandle(arguments.At(1)); |
| 551 const AbstractType& element_type = | 555 const AbstractType& element_type = |
| 552 AbstractType::CheckedHandle(arguments.At(2)); | 556 AbstractType::CheckedHandle(arguments.At(2)); |
| 553 const AbstractTypeArguments& element_type_instantiator = | 557 const AbstractTypeArguments& element_type_instantiator = |
| 554 AbstractTypeArguments::CheckedHandle(arguments.At(3)); | 558 AbstractTypeArguments::CheckedHandle(arguments.At(3)); |
| 555 const String& rest_name = String::CheckedHandle(arguments.At(4)); | 559 const String& rest_name = String::CheckedHandle(arguments.At(4)); |
| 556 ASSERT(!element_type.IsDynamicType()); // No need to check assignment. | 560 ASSERT(!element_type.IsDynamicType()); // No need to check assignment. |
| 561 ASSERT(!element_type.IsMalformed()); // Already checked in code generator. |
| 557 ASSERT(!rest_array.IsNull()); | 562 ASSERT(!rest_array.IsNull()); |
| 558 | 563 |
| 559 Instance& elem = Instance::Handle(); | 564 Instance& elem = Instance::Handle(); |
| 560 Error& malformed_error = Error::Handle(); | 565 Error& malformed_error = Error::Handle(); |
| 561 for (intptr_t i = 0; i < rest_array.Length(); i++) { | 566 for (intptr_t i = 0; i < rest_array.Length(); i++) { |
| 562 elem ^= rest_array.At(i); | 567 elem ^= rest_array.At(i); |
| 563 // The previous successful type check may have set malformed_error. | 568 // The previous successful type check may have set malformed_error. |
| 564 // Note that a returned malformed_error is ignored if a type check succeeds. | 569 // Note that a returned malformed_error is ignored if a type check succeeds. |
| 565 malformed_error = Error::null(); | 570 malformed_error = Error::null(); |
| 566 if (!elem.IsNull() && !elem.IsAssignableTo(element_type, | 571 if (!elem.IsNull() && !elem.IsInstanceOf(element_type, |
| 567 element_type_instantiator, | 572 element_type_instantiator, |
| 568 &malformed_error)) { | 573 &malformed_error)) { |
| 569 // Allocate and throw a new instance of TypeError. | 574 // Allocate and throw a new instance of TypeError. |
| 570 char buf[256]; | 575 char buf[256]; |
| 571 OS::SNPrint(buf, sizeof(buf), "%s[%d]", | 576 OS::SNPrint(buf, sizeof(buf), "%s[%d]", |
| 572 rest_name.ToCString(), static_cast<int>(i)); | 577 rest_name.ToCString(), static_cast<int>(i)); |
| 573 const String& src_type_name = | 578 const String& src_type_name = |
| 574 String::Handle(Type::Handle(elem.GetType()).Name()); | 579 String::Handle(Type::Handle(elem.GetType()).Name()); |
| 575 String& dst_type_name = String::Handle(); | 580 String& dst_type_name = String::Handle(); |
| 576 if (!element_type.IsInstantiated()) { | 581 if (!element_type.IsInstantiated()) { |
| 577 // Instantiate element_type before reporting the error. | 582 // Instantiate element_type before reporting the error. |
| 578 const AbstractType& instantiated_element_type = AbstractType::Handle( | 583 const AbstractType& instantiated_element_type = AbstractType::Handle( |
| (...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1428 } | 1433 } |
| 1429 } | 1434 } |
| 1430 } | 1435 } |
| 1431 // The cache is null terminated, therefore the loop above should never | 1436 // The cache is null terminated, therefore the loop above should never |
| 1432 // terminate by itself. | 1437 // terminate by itself. |
| 1433 UNREACHABLE(); | 1438 UNREACHABLE(); |
| 1434 return Code::null(); | 1439 return Code::null(); |
| 1435 } | 1440 } |
| 1436 | 1441 |
| 1437 } // namespace dart | 1442 } // namespace dart |
| OLD | NEW |