Chromium Code Reviews| 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_patcher.h" | 7 #include "vm/code_patcher.h" |
| 8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
| 9 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 372 cloned_ctx.SetAt(i, Instance::Handle(ctx.At(i))); | 372 cloned_ctx.SetAt(i, Instance::Handle(ctx.At(i))); |
| 373 } | 373 } |
| 374 arguments.SetReturn(cloned_ctx); | 374 arguments.SetReturn(cloned_ctx); |
| 375 } | 375 } |
| 376 | 376 |
| 377 | 377 |
| 378 // Helper routine for tracing a type check. | 378 // Helper routine for tracing a type check. |
| 379 static void PrintTypeCheck(const char* message, | 379 static void PrintTypeCheck(const char* message, |
| 380 const Instance& instance, | 380 const Instance& instance, |
| 381 const AbstractType&type, | 381 const AbstractType&type, |
| 382 const AbstractTypeArguments& type_instantiator, | 382 const AbstractTypeArguments& instantiator_targs, |
|
regis
2012/05/04 21:53:39
"targs" sounds like "targets".
I have always tried
srdjan
2012/05/04 23:01:58
Using instantiator_type_arguments.
| |
| 383 const Bool& result) { | 383 const Bool& result) { |
| 384 DartFrameIterator iterator; | |
| 385 StackFrame* caller_frame = iterator.NextFrame(); | |
| 386 ASSERT(caller_frame != NULL); | |
| 387 | |
| 384 const Type& instance_type = Type::Handle(instance.GetType()); | 388 const Type& instance_type = Type::Handle(instance.GetType()); |
| 385 ASSERT(instance_type.IsInstantiated()); | 389 ASSERT(instance_type.IsInstantiated()); |
| 386 if (type.IsInstantiated()) { | 390 if (type.IsInstantiated()) { |
| 387 OS::Print("%s: '%s' %s '%s'.\n", | 391 OS::Print("%s: '%s' %s '%s' (pc: 0x%x).\n", |
| 388 message, | 392 message, |
| 389 String::Handle(instance_type.Name()).ToCString(), | 393 String::Handle(instance_type.Name()).ToCString(), |
| 390 (result.raw() == Bool::True()) ? "is" : "is !", | 394 (result.raw() == Bool::True()) ? "is" : "is !", |
| 391 String::Handle(type.Name()).ToCString()); | 395 String::Handle(type.Name()).ToCString(), |
| 396 caller_frame->pc()); | |
| 392 } else { | 397 } else { |
| 393 // Instantiate type before printing. | 398 // Instantiate type before printing. |
| 394 const AbstractType& instantiated_type = | 399 const AbstractType& instantiated_type = |
| 395 AbstractType::Handle(type.InstantiateFrom(type_instantiator)); | 400 AbstractType::Handle(type.InstantiateFrom(instantiator_targs)); |
| 396 OS::Print("%s: '%s' %s '%s' instantiated from '%s'.\n", | 401 OS::Print("%s: '%s' %s '%s' instantiated from '%s' (pc: 0x%x).\n", |
| 397 message, | 402 message, |
| 398 String::Handle(instance_type.Name()).ToCString(), | 403 String::Handle(instance_type.Name()).ToCString(), |
| 399 (result.raw() == Bool::True()) ? "is" : "is !", | 404 (result.raw() == Bool::True()) ? "is" : "is !", |
| 400 String::Handle(instantiated_type.Name()).ToCString(), | 405 String::Handle(instantiated_type.Name()).ToCString(), |
| 401 String::Handle(type.Name()).ToCString()); | 406 String::Handle(type.Name()).ToCString(), |
| 407 caller_frame->pc()); | |
| 402 } | 408 } |
| 403 DartFrameIterator iterator; | |
| 404 StackFrame* caller_frame = iterator.NextFrame(); | |
| 405 ASSERT(caller_frame != NULL); | |
| 406 const Function& function = Function::Handle( | 409 const Function& function = Function::Handle( |
| 407 caller_frame->LookupDartFunction()); | 410 caller_frame->LookupDartFunction()); |
| 408 OS::Print(" -> Function %s\n", function.ToFullyQualifiedCString()); | 411 OS::Print(" -> Function %s\n", function.ToFullyQualifiedCString()); |
| 409 } | 412 } |
| 410 | 413 |
| 411 | 414 |
| 412 // Converts InstantiatedTypeArguments to TypeArguments and stores it | 415 // Converts InstantiatedTypeArguments to TypeArguments and stores it |
| 413 // into the instance. The assembly code can handle only type arguments of | 416 // into the instance. The assembly code can handle only type arguments of |
| 414 // class TypeArguments. Because of the overhead, do it only when needed. | 417 // class TypeArguments. Because of the overhead, do it only when needed. |
| 415 static void OptimizeTypeArguments(const Instance& instance) { | 418 // Return false if the optimization was aborted. |
| 419 // Set type_arguments_replaced to true if they have changed. | |
| 420 static bool OptimizeTypeArguments(const Instance& instance, | |
| 421 bool* type_arguments_replaced) { | |
| 422 *type_arguments_replaced = false; | |
| 416 const Class& type_class = Class::ZoneHandle(instance.clazz()); | 423 const Class& type_class = Class::ZoneHandle(instance.clazz()); |
| 417 if (type_class.HasTypeArguments()) { | 424 if (!type_class.HasTypeArguments()) { |
| 418 const AbstractTypeArguments& type_arguments = | 425 return true; |
| 419 AbstractTypeArguments::Handle(instance.GetTypeArguments()); | 426 } |
| 420 if (!type_arguments.IsNull() && | 427 const AbstractTypeArguments& type_arguments = |
| 421 type_arguments.IsInstantiatedTypeArguments()) { | 428 AbstractTypeArguments::Handle(instance.GetTypeArguments()); |
| 422 TypeArguments& new_type_arguments = | 429 if (type_arguments.IsNull()) { |
| 423 TypeArguments::Handle(TypeArguments::New(type_arguments.Length())); | 430 return true; |
| 424 for (int i = 0; i < type_arguments.Length(); i++) { | 431 } |
| 425 const AbstractType& type_at = | 432 if (type_arguments.IsInstantiatedTypeArguments()) { |
| 426 AbstractType::Handle(type_arguments.TypeAt(i)); | 433 TypeArguments& new_type_arguments = |
|
regis
2012/05/04 21:53:39
I think you can simply call new_type_arguments = t
srdjan
2012/05/04 23:01:58
Thanks, very nice!
| |
| 427 if (type_at.IsInstantiatedType()) { | 434 TypeArguments::Handle(TypeArguments::New(type_arguments.Length())); |
| 428 // TODO(srdjan): cannot canonicalize TypeArguments that contain | 435 for (int i = 0; i < type_arguments.Length(); i++) { |
| 429 // InstantiatedType. | 436 const AbstractType& type_at = |
| 430 return; | 437 AbstractType::Handle(type_arguments.TypeAt(i)); |
| 431 } else if (!type_at.IsType()) { | 438 if (type_at.IsInstantiatedType()) { |
| 432 // type_at cannot be TypeParameter at runtime. | 439 // TODO(srdjan): cannot canonicalize TypeArguments that contain |
| 433 UNREACHABLE(); | 440 // InstantiatedType. |
| 434 } | 441 return false; |
| 435 new_type_arguments.SetTypeAt(i, type_at); | 442 } else if (!type_at.IsType()) { |
| 443 // type_at cannot be TypeParameter at runtime. | |
| 444 UNREACHABLE(); | |
| 436 } | 445 } |
| 437 new_type_arguments ^= new_type_arguments.Canonicalize(); | 446 new_type_arguments.SetTypeAt(i, type_at); |
| 438 instance.SetTypeArguments(new_type_arguments); | |
| 439 } | 447 } |
| 448 new_type_arguments ^= new_type_arguments.Canonicalize(); | |
| 449 instance.SetTypeArguments(new_type_arguments); | |
| 450 *type_arguments_replaced = true; | |
| 451 } else if (!type_arguments.IsCanonical()) { | |
| 452 AbstractTypeArguments& new_type_arguments = | |
| 453 AbstractTypeArguments::Handle(); | |
| 454 new_type_arguments ^= type_arguments.Canonicalize(); | |
| 455 instance.SetTypeArguments(new_type_arguments); | |
| 456 *type_arguments_replaced = true; | |
| 440 } | 457 } |
| 458 ASSERT(AbstractTypeArguments::Handle( | |
| 459 instance.GetTypeArguments()).IsTypeArguments()); | |
| 460 return true; | |
| 441 } | 461 } |
| 442 | 462 |
| 443 | 463 |
| 444 // This updates the type test cache, an array containing 4-value elements | 464 // This updates the type test cache, an array containing 4-value elements |
| 445 // (instance class, instance type arguments, instantiator type arguments and | 465 // (instance class, instance type arguments, instantiator type arguments and |
| 446 // test_result). It can be applied to classes with type arguments in which | 466 // test_result). It can be applied to classes with type arguments in which |
| 447 // case it contains just the result of the class subtype test, not including | 467 // case it contains just the result of the class subtype test, not including |
| 448 // the evaluation of type arguments. | 468 // the evaluation of type arguments. |
| 449 // This operation is currently very slow (lookup of code is not efficient yet). | 469 // This operation is currently very slow (lookup of code is not efficient yet). |
| 450 static void UpdateTypeTestCache(intptr_t node_id, | 470 // 'instantiator' can be null, in which case inst_targ |
| 451 const Instance& instance, | 471 static void UpdateTypeTestCache( |
| 452 const AbstractType& type, | 472 intptr_t node_id, |
| 453 const AbstractTypeArguments& type_instantiator, | 473 const Instance& instance, |
| 454 const Bool& result, | 474 const AbstractType& type, |
| 455 const SubtypeTestCache& new_cache) { | 475 const Instance& instantiator, |
| 476 const AbstractTypeArguments& instantiator_type_arguments, | |
| 477 const Bool& result, | |
| 478 const SubtypeTestCache& new_cache) { | |
| 456 // Since the test is expensive, don't do it unless necessary. | 479 // Since the test is expensive, don't do it unless necessary. |
| 457 // The list of disallowed cases will decrease as they are implemented in | 480 // The list of disallowed cases will decrease as they are implemented in |
| 458 // inlined assembly. | 481 // inlined assembly. |
| 459 if (new_cache.IsNull()) return; | 482 if (new_cache.IsNull()) return; |
| 483 // Instantiator type arguments may be canonicalized later. | |
| 484 AbstractTypeArguments& instantiator_targs = | |
|
regis
2012/05/04 21:53:39
instantiator_type_arguments?
srdjan
2012/05/04 23:01:58
Done.
| |
| 485 AbstractTypeArguments::Handle(instantiator_type_arguments.raw()); | |
| 460 AbstractTypeArguments& instance_type_arguments = | 486 AbstractTypeArguments& instance_type_arguments = |
| 461 AbstractTypeArguments::Handle(); | 487 AbstractTypeArguments::Handle(); |
| 462 const Class& instance_class = Class::Handle(instance.clazz()); | 488 const Class& instance_class = Class::Handle(instance.clazz()); |
| 463 AbstractTypeArguments& original_instance_type_arguments = | 489 |
| 464 AbstractTypeArguments::Handle(); | 490 // Canonicalize type arguments. |
| 491 bool type_arguments_replaced = false; | |
| 465 if (instance_class.HasTypeArguments()) { | 492 if (instance_class.HasTypeArguments()) { |
| 466 // Canonicalize type arguments. | 493 // Canonicalize type arguments. |
| 467 original_instance_type_arguments = instance.GetTypeArguments(); | 494 if (!OptimizeTypeArguments(instance, &type_arguments_replaced)) { |
| 468 OptimizeTypeArguments(instance); | 495 if (FLAG_trace_type_checks) { |
| 496 PrintTypeCheck("WARNING: Cannot canonicalize instance type arguments", | |
| 497 instance, type, instantiator_targs, result); | |
| 498 } | |
| 499 return; | |
| 500 } | |
| 469 instance_type_arguments = instance.GetTypeArguments(); | 501 instance_type_arguments = instance.GetTypeArguments(); |
| 470 } | 502 } |
| 503 if (!instantiator.IsNull()) { | |
| 504 bool replaced = false; | |
| 505 if (!OptimizeTypeArguments(instantiator, &replaced)) { | |
| 506 if (FLAG_trace_type_checks) { | |
| 507 PrintTypeCheck("WARNING: Cannot canonicalize instantiator " | |
| 508 "type arguments", | |
| 509 instance, type, instantiator_targs, result); | |
| 510 } | |
| 511 return; | |
| 512 } | |
| 513 if (replaced) { | |
| 514 type_arguments_replaced = true; | |
| 515 } | |
| 516 instantiator_targs ^= instantiator.GetTypeArguments(); | |
| 517 } | |
| 471 | 518 |
| 472 Class& last_instance_class = Class::Handle(); | 519 Class& last_instance_class = Class::Handle(); |
| 473 AbstractTypeArguments& last_instance_type_arguments = | 520 AbstractTypeArguments& last_instance_type_arguments = |
| 474 AbstractTypeArguments::Handle(); | 521 AbstractTypeArguments::Handle(); |
| 475 AbstractTypeArguments& last_instantiator_type_arguments = | 522 AbstractTypeArguments& last_instantiator_type_arguments = |
| 476 AbstractTypeArguments::Handle(); | 523 AbstractTypeArguments::Handle(); |
| 477 Bool& last_result = Bool::Handle(); | 524 Bool& last_result = Bool::Handle(); |
| 478 intptr_t len = new_cache.NumberOfChecks(); | 525 intptr_t len = new_cache.NumberOfChecks(); |
| 479 for (intptr_t i = 0; i < len; ++i) { | 526 for (intptr_t i = 0; i < len; ++i) { |
| 480 new_cache.GetCheck( | 527 new_cache.GetCheck( |
| 481 i, | 528 i, |
| 482 &last_instance_class, | 529 &last_instance_class, |
| 483 &last_instance_type_arguments, | 530 &last_instance_type_arguments, |
| 484 &last_instantiator_type_arguments, | 531 &last_instantiator_type_arguments, |
| 485 &last_result); | 532 &last_result); |
| 486 if ((last_instance_class.raw() == instance_class.raw()) && | 533 if ((last_instance_class.raw() == instance_class.raw()) && |
| 487 (last_instance_type_arguments.raw() == | 534 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) && |
| 488 instance_type_arguments.raw())) { | 535 (last_instantiator_type_arguments.raw() == instantiator_targs.raw())) { |
| 489 if (FLAG_trace_type_checks) { | 536 if (FLAG_trace_type_checks) { |
| 490 if (original_instance_type_arguments.raw() == | 537 OS::Print("%d ", i); |
| 491 instance_type_arguments.raw()) { | 538 PrintTypeCheck("WARNING duplicate cache entry", instance, type, |
| 492 PrintTypeCheck("WARNING duplicate cache entry", instance, type, | 539 instantiator_targs, result); |
| 493 type_instantiator, result); | |
| 494 } | |
| 495 } | 540 } |
| 496 // A duplicate entry found, likely because the instance type arguments | 541 // Can occur if we have canonicalized arguments. |
| 497 // were not cacnonicalized before. | 542 ASSERT(type_arguments_replaced); |
| 498 return; | 543 return; |
| 499 } | 544 } |
| 500 } | 545 } |
| 501 new_cache.AddCheck(instance_class, | 546 new_cache.AddCheck(instance_class, |
| 502 instance_type_arguments, | 547 instance_type_arguments, |
| 503 AbstractTypeArguments::Handle(), | 548 instantiator_targs, |
| 504 result); | 549 result); |
| 505 if (FLAG_trace_type_checks) { | 550 if (FLAG_trace_type_checks) { |
| 506 OS::Print(" Updated test cache 0x%x ix:%d:\n" | 551 OS::Print(" Updated test cache 0x%x ix:%d:\n" |
| 507 " [0x%x %s, 0x%x %s]\n" | 552 " [0x%x %s, 0x%x %s]\n" |
| 508 " [0x%x %s] %s\n", | 553 " [0x%x %s, 0x%x %s] %s\n", |
| 509 new_cache.raw(), | 554 new_cache.raw(), |
| 510 len, | 555 len, |
| 511 instance_class.raw(), | 556 instance_class.raw(), |
| 512 instance_class.ToCString(), | 557 instance_class.ToCString(), |
| 513 instance_type_arguments.raw(), | 558 instance_type_arguments.raw(), |
| 514 instance_type_arguments.ToCString(), | 559 instance_type_arguments.ToCString(), |
| 515 type.type_class(), | 560 type.type_class(), |
| 516 Class::Handle(type.type_class()).ToCString(), | 561 Class::Handle(type.type_class()).ToCString(), |
| 562 instantiator_targs.raw(), | |
| 563 instantiator_targs.ToCString(), | |
| 517 result.ToCString()); | 564 result.ToCString()); |
| 518 } | 565 } |
| 519 } | 566 } |
| 520 | 567 |
| 521 | 568 |
| 522 // Check that the given instance is an instance of the given type. | 569 // Check that the given instance is an instance of the given type. |
| 523 // Tested instance may not be null, because the null test is inlined. | 570 // Tested instance may not be null, because the null test is inlined. |
| 524 // Arg0: index of the token of the instanceof test (source location). | 571 // Arg0: index of the token of the instanceof test (source location). |
| 525 // Arg1: node id of the instanceof node. | 572 // Arg1: node id of the instanceof node. |
| 526 // Arg2: instance being checked. | 573 // Arg2: instance being checked. |
| 527 // Arg3: type. | 574 // Arg3: type. |
| 528 // Arg4: type arguments of the instantiator of the type. | 575 // Arg4: instantiator (or null). |
| 529 // Arg5: SubtypeTestCache. | 576 // Arg5: type arguments of the instantiator of the type. |
| 577 // Arg6: SubtypeTestCache. | |
| 530 // Return value: true or false, or may throw a type error in checked mode. | 578 // Return value: true or false, or may throw a type error in checked mode. |
| 531 DEFINE_RUNTIME_ENTRY(Instanceof, 6) { | 579 DEFINE_RUNTIME_ENTRY(Instanceof, 7) { |
| 532 ASSERT(arguments.Count() == kInstanceofRuntimeEntry.argument_count()); | 580 ASSERT(arguments.Count() == kInstanceofRuntimeEntry.argument_count()); |
| 533 // TODO(regis): Get the token index from the PcDesc (via DartFrame). | 581 // TODO(regis): Get the token index from the PcDesc (via DartFrame). |
| 534 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); | 582 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); |
| 535 intptr_t node_id = Smi::CheckedHandle(arguments.At(1)).Value(); | 583 intptr_t node_id = Smi::CheckedHandle(arguments.At(1)).Value(); |
| 536 const Instance& instance = Instance::CheckedHandle(arguments.At(2)); | 584 const Instance& instance = Instance::CheckedHandle(arguments.At(2)); |
| 537 const AbstractType& type = AbstractType::CheckedHandle(arguments.At(3)); | 585 const AbstractType& type = AbstractType::CheckedHandle(arguments.At(3)); |
| 538 const AbstractTypeArguments& type_instantiator = | 586 const Instance& instantiator = Instance::CheckedHandle(arguments.At(4)); |
| 539 AbstractTypeArguments::CheckedHandle(arguments.At(4)); | 587 const AbstractTypeArguments& instantiator_targs = |
|
regis
2012/05/04 21:53:39
instantiator_type_arguments?
srdjan
2012/05/04 23:01:58
Done.
| |
| 588 AbstractTypeArguments::CheckedHandle(arguments.At(5)); | |
| 540 const SubtypeTestCache& cache = | 589 const SubtypeTestCache& cache = |
| 541 SubtypeTestCache::CheckedHandle(arguments.At(5)); | 590 SubtypeTestCache::CheckedHandle(arguments.At(6)); |
| 542 ASSERT(type.IsFinalized()); | 591 ASSERT(type.IsFinalized()); |
| 543 Error& malformed_error = Error::Handle(); | 592 Error& malformed_error = Error::Handle(); |
| 544 const Bool& result = Bool::Handle( | 593 const Bool& result = Bool::Handle( |
| 545 instance.IsInstanceOf(type, type_instantiator, &malformed_error) ? | 594 instance.IsInstanceOf(type, instantiator_targs, &malformed_error) ? |
| 546 Bool::True() : Bool::False()); | 595 Bool::True() : Bool::False()); |
| 547 if (FLAG_trace_type_checks) { | 596 if (FLAG_trace_type_checks) { |
| 548 PrintTypeCheck("InstanceOf", instance, type, type_instantiator, result); | 597 PrintTypeCheck("InstanceOf", instance, type, instantiator_targs, result); |
| 549 } | 598 } |
| 550 if (!result.value() && !malformed_error.IsNull()) { | 599 if (!result.value() && !malformed_error.IsNull()) { |
| 551 // Throw a dynamic type error only if the instanceof test fails. | 600 // Throw a dynamic type error only if the instanceof test fails. |
| 552 String& malformed_error_message = String::Handle( | 601 String& malformed_error_message = String::Handle( |
| 553 String::New(malformed_error.ToErrorCString())); | 602 String::New(malformed_error.ToErrorCString())); |
| 554 const String& no_name = String::Handle(String::NewSymbol("")); | 603 const String& no_name = String::Handle(String::NewSymbol("")); |
| 555 Exceptions::CreateAndThrowTypeError( | 604 Exceptions::CreateAndThrowTypeError( |
| 556 location, no_name, no_name, no_name, malformed_error_message); | 605 location, no_name, no_name, no_name, malformed_error_message); |
| 557 UNREACHABLE(); | 606 UNREACHABLE(); |
| 558 } | 607 } |
| 559 UpdateTypeTestCache( | 608 UpdateTypeTestCache( |
| 560 node_id, instance, type, type_instantiator, result, cache); | 609 node_id, instance, type, instantiator, instantiator_targs, result, cache); |
| 561 arguments.SetReturn(result); | 610 arguments.SetReturn(result); |
| 562 } | 611 } |
| 563 | 612 |
| 564 | 613 |
| 565 // For error reporting simplify type name, e.g, all integer types (Smi, Mint, | 614 // For error reporting simplify type name, e.g, all integer types (Smi, Mint, |
| 566 // Bigint) a re reported as 'int'. | 615 // Bigint) a re reported as 'int'. |
| 567 static RawString* GetSimpleTypeName(const Instance& value) { | 616 static RawString* GetSimpleTypeName(const Instance& value) { |
| 568 if (value.IsInteger()) { | 617 if (value.IsInteger()) { |
| 569 return String::NewSymbol("int"); | 618 return String::NewSymbol("int"); |
| 570 } else { | 619 } else { |
| 571 return Type::Handle(value.GetType()).Name(); | 620 return Type::Handle(value.GetType()).Name(); |
| 572 } | 621 } |
| 573 } | 622 } |
| 574 | 623 |
| 575 | 624 |
| 576 // Check that the type of the given instance is a subtype of the given type and | 625 // Check that the type of the given instance is a subtype of the given type and |
| 577 // can therefore be assigned. | 626 // can therefore be assigned. |
| 578 // Arg0: index of the token of the assignment (source location). | 627 // Arg0: index of the token of the assignment (source location). |
| 579 // Arg1: node-id of the assignemnt. | 628 // Arg1: node-id of the assignment. |
| 580 // Arg2: instance being assigned. | 629 // Arg2: instance being assigned. |
| 581 // Arg3: type being assigned to. | 630 // Arg3: type being assigned to. |
| 582 // Arg4: type arguments of the instantiator of the type being assigned to. | 631 // Arg4: instantiator (or null). |
| 583 // Arg5: name of variable being assigned to. | 632 // Arg5: type arguments of the instantiator of the type being assigned to. |
| 584 // Arg6: SubtypeTestCache. | 633 // Arg6: name of variable being assigned to. |
| 634 // Arg7: SubtypeTestCache. | |
| 585 // Return value: instance if a subtype, otherwise throw a TypeError. | 635 // Return value: instance if a subtype, otherwise throw a TypeError. |
| 586 DEFINE_RUNTIME_ENTRY(TypeCheck, 7) { | 636 DEFINE_RUNTIME_ENTRY(TypeCheck, 8) { |
| 587 ASSERT(arguments.Count() == kTypeCheckRuntimeEntry.argument_count()); | 637 ASSERT(arguments.Count() == kTypeCheckRuntimeEntry.argument_count()); |
| 588 // TODO(regis): Get the token index from the PcDesc (via DartFrame). | 638 // TODO(regis): Get the token index from the PcDesc (via DartFrame). |
| 589 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); | 639 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); |
| 590 intptr_t node_id = Smi::CheckedHandle(arguments.At(1)).Value(); | 640 intptr_t node_id = Smi::CheckedHandle(arguments.At(1)).Value(); |
| 591 const Instance& src_instance = Instance::CheckedHandle(arguments.At(2)); | 641 const Instance& src_instance = Instance::CheckedHandle(arguments.At(2)); |
| 592 const AbstractType& dst_type = AbstractType::CheckedHandle(arguments.At(3)); | 642 const AbstractType& dst_type = AbstractType::CheckedHandle(arguments.At(3)); |
| 593 const AbstractTypeArguments& dst_type_instantiator = | 643 const Instance& dst_instantiator = Instance::CheckedHandle(arguments.At(4)); |
| 594 AbstractTypeArguments::CheckedHandle(arguments.At(4)); | 644 const AbstractTypeArguments& dst_instantiator_targs = |
|
regis
2012/05/04 21:53:39
instantiator_type_arguments?
You can drop dst_
srdjan
2012/05/04 23:01:58
Done.
| |
| 595 const String& dst_name = String::CheckedHandle(arguments.At(5)); | 645 AbstractTypeArguments::CheckedHandle(arguments.At(5)); |
| 646 const String& dst_name = String::CheckedHandle(arguments.At(6)); | |
| 596 const SubtypeTestCache& cache = | 647 const SubtypeTestCache& cache = |
| 597 SubtypeTestCache::CheckedHandle(arguments.At(6)); | 648 SubtypeTestCache::CheckedHandle(arguments.At(7)); |
| 598 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. | 649 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. |
| 599 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. | 650 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. |
| 600 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. | 651 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. |
| 601 | 652 |
| 602 Error& malformed_error = Error::Handle(); | 653 Error& malformed_error = Error::Handle(); |
| 603 const bool is_instance_of = src_instance.IsInstanceOf( | 654 const bool is_instance_of = src_instance.IsInstanceOf( |
| 604 dst_type, dst_type_instantiator, &malformed_error); | 655 dst_type, dst_instantiator_targs, &malformed_error); |
| 605 | 656 |
| 606 if (FLAG_trace_type_checks) { | 657 if (FLAG_trace_type_checks) { |
| 607 PrintTypeCheck("TypeCheck", src_instance, dst_type, dst_type_instantiator, | 658 PrintTypeCheck("TypeCheck", src_instance, dst_type, dst_instantiator_targs, |
| 608 Bool::Handle(is_instance_of ? Bool::True() : Bool::False())); | 659 Bool::Handle(is_instance_of ? Bool::True() : Bool::False())); |
| 609 } | 660 } |
| 610 if (!is_instance_of) { | 661 if (!is_instance_of) { |
| 611 String& src_type_name = String::Handle(GetSimpleTypeName(src_instance)); | 662 String& src_type_name = String::Handle(GetSimpleTypeName(src_instance)); |
| 612 String& dst_type_name = String::Handle(); | 663 String& dst_type_name = String::Handle(); |
| 613 if (!dst_type.IsInstantiated()) { | 664 if (!dst_type.IsInstantiated()) { |
| 614 // Instantiate dst_type before reporting the error. | 665 // Instantiate dst_type before reporting the error. |
| 615 const AbstractType& instantiated_dst_type = AbstractType::Handle( | 666 const AbstractType& instantiated_dst_type = AbstractType::Handle( |
| 616 dst_type.InstantiateFrom(dst_type_instantiator)); | 667 dst_type.InstantiateFrom(dst_instantiator_targs)); |
| 617 dst_type_name = instantiated_dst_type.Name(); | 668 dst_type_name = instantiated_dst_type.Name(); |
| 618 } else { | 669 } else { |
| 619 dst_type_name = dst_type.Name(); | 670 dst_type_name = dst_type.Name(); |
| 620 } | 671 } |
| 621 String& malformed_error_message = String::Handle(); | 672 String& malformed_error_message = String::Handle(); |
| 622 if (!malformed_error.IsNull()) { | 673 if (!malformed_error.IsNull()) { |
| 623 ASSERT(FLAG_enable_type_checks); | 674 ASSERT(FLAG_enable_type_checks); |
| 624 malformed_error_message = String::New(malformed_error.ToErrorCString()); | 675 malformed_error_message = String::New(malformed_error.ToErrorCString()); |
| 625 } | 676 } |
| 626 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, | 677 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, |
| 627 dst_name, malformed_error_message); | 678 dst_name, malformed_error_message); |
| 628 UNREACHABLE(); | 679 UNREACHABLE(); |
| 629 } | 680 } |
| 630 UpdateTypeTestCache(node_id, src_instance, dst_type, dst_type_instantiator, | 681 UpdateTypeTestCache(node_id, src_instance, dst_type, |
| 631 Bool::ZoneHandle(Bool::True()), cache); | 682 dst_instantiator, dst_instantiator_targs, |
| 683 Bool::ZoneHandle(Bool::True()), cache); | |
| 632 arguments.SetReturn(src_instance); | 684 arguments.SetReturn(src_instance); |
| 633 } | 685 } |
| 634 | 686 |
| 635 | 687 |
| 636 // Report that the type of the given object is not bool in conditional context. | 688 // Report that the type of the given object is not bool in conditional context. |
| 637 // Arg0: index of the token of the assignment (source location). | 689 // Arg0: index of the token of the assignment (source location). |
| 638 // Arg1: bad object. | 690 // Arg1: bad object. |
| 639 // Return value: none, throws a TypeError. | 691 // Return value: none, throws a TypeError. |
| 640 DEFINE_RUNTIME_ENTRY(ConditionTypeError, 2) { | 692 DEFINE_RUNTIME_ENTRY(ConditionTypeError, 2) { |
| 641 ASSERT(arguments.Count() == | 693 ASSERT(arguments.Count() == |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1480 } | 1532 } |
| 1481 } | 1533 } |
| 1482 } | 1534 } |
| 1483 // The cache is null terminated, therefore the loop above should never | 1535 // The cache is null terminated, therefore the loop above should never |
| 1484 // terminate by itself. | 1536 // terminate by itself. |
| 1485 UNREACHABLE(); | 1537 UNREACHABLE(); |
| 1486 return Code::null(); | 1538 return Code::null(); |
| 1487 } | 1539 } |
| 1488 | 1540 |
| 1489 } // namespace dart | 1541 } // namespace dart |
| OLD | NEW |