| 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" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/debugger.h" | 12 #include "vm/debugger.h" |
| 13 #include "vm/exceptions.h" | 13 #include "vm/exceptions.h" |
| 14 #include "vm/ic_data.h" | |
| 15 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 16 #include "vm/resolver.h" | 15 #include "vm/resolver.h" |
| 17 #include "vm/runtime_entry.h" | 16 #include "vm/runtime_entry.h" |
| 18 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
| 19 #include "vm/verifier.h" | 18 #include "vm/verifier.h" |
| 20 | 19 |
| 21 namespace dart { | 20 namespace dart { |
| 22 | 21 |
| 23 DEFINE_FLAG(bool, inline_cache, true, "enable inline caches"); | 22 DEFINE_FLAG(bool, inline_cache, true, "enable inline caches"); |
| 24 DEFINE_FLAG(bool, trace_deopt, false, "Trace deoptimization"); | 23 DEFINE_FLAG(bool, trace_deopt, false, "Trace deoptimization"); |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 // Special handling so that we do not pollute the inline cache with null | 520 // Special handling so that we do not pollute the inline cache with null |
| 522 // classes. | 521 // classes. |
| 523 if (FLAG_trace_ic) { | 522 if (FLAG_trace_ic) { |
| 524 OS::Print("InlineCacheMissHandler Null receiver target %s\n", | 523 OS::Print("InlineCacheMissHandler Null receiver target %s\n", |
| 525 target_function.ToCString()); | 524 target_function.ToCString()); |
| 526 } | 525 } |
| 527 return target_function.raw(); | 526 return target_function.raw(); |
| 528 } | 527 } |
| 529 DartFrameIterator iterator; | 528 DartFrameIterator iterator; |
| 530 DartFrame* caller_frame = iterator.NextFrame(); | 529 DartFrame* caller_frame = iterator.NextFrame(); |
| 531 ICData ic_data(Array::Handle( | 530 ICData& ic_data = ICData::Handle( |
| 532 CodePatcher::GetInstanceCallIcDataAt(caller_frame->pc()))); | 531 CodePatcher::GetInstanceCallIcDataAt(caller_frame->pc())); |
| 533 | |
| 534 #if defined(DEBUG) | 532 #if defined(DEBUG) |
| 535 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 533 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 536 GrowableArray<const Class*> classes; | 534 GrowableArray<const Class*> classes; |
| 537 Function& target = Function::Handle(); | 535 Function& target = Function::Handle(); |
| 538 ic_data.GetCheckAt(i, &classes, &target); | 536 ic_data.GetCheckAt(i, &classes, &target); |
| 539 bool matches = true; | 537 bool matches = true; |
| 540 for (intptr_t k = 0; k < classes.length(); k++) { | 538 for (intptr_t k = 0; k < classes.length(); k++) { |
| 541 if (classes[k]->raw() != args[k]->clazz()) { | 539 if (classes[k]->raw() != args[k]->clazz()) { |
| 542 matches = false; | 540 matches = false; |
| 543 break; | 541 break; |
| 544 } | 542 } |
| 545 } | 543 } |
| 546 // Do not add an entry twice! | 544 // Do not add an entry twice! |
| 547 ASSERT(!matches); | 545 ASSERT(!matches); |
| 548 } | 546 } |
| 549 #endif // DEBUG | 547 #endif // DEBUG |
| 550 | 548 |
| 551 GrowableArray<const Class*> classes; | 549 GrowableArray<const Class*> classes; |
| 552 ASSERT(ic_data.NumberOfArgumentsChecked() == args.length()); | 550 ASSERT(ic_data.num_args_tested() == args.length()); |
| 553 for (intptr_t i = 0; i < args.length(); i++) { | 551 for (intptr_t i = 0; i < args.length(); i++) { |
| 554 classes.Add(&Class::ZoneHandle(args[i]->clazz())); | 552 classes.Add(&Class::ZoneHandle(args[i]->clazz())); |
| 555 } | 553 } |
| 556 ic_data.AddCheck(classes, target_function); | 554 ic_data.AddCheck(classes, target_function); |
| 557 CodePatcher::SetInstanceCallIcDataAt(caller_frame->pc(), | |
| 558 Array::ZoneHandle(ic_data.data())); | |
| 559 if (FLAG_trace_ic) { | 555 if (FLAG_trace_ic) { |
| 560 OS::Print("InlineCacheMissHandler %d call at 0x%x' adding <%s> -> <%s>\n", | 556 OS::Print("InlineCacheMissHandler %d call at 0x%x' adding <%s> -> <%s>\n", |
| 561 args.length(), | 557 args.length(), |
| 562 caller_frame->pc(), | 558 caller_frame->pc(), |
| 563 Class::Handle(receiver.clazz()).ToCString(), | 559 Class::Handle(receiver.clazz()).ToCString(), |
| 564 target_function.ToCString()); | 560 target_function.ToCString()); |
| 565 } | 561 } |
| 566 return target_function.raw(); | 562 return target_function.raw(); |
| 567 } | 563 } |
| 568 | 564 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 } | 620 } |
| 625 cls = cls.SuperClass(); | 621 cls = cls.SuperClass(); |
| 626 } | 622 } |
| 627 return function.raw(); | 623 return function.raw(); |
| 628 } | 624 } |
| 629 | 625 |
| 630 | 626 |
| 631 // Resolve an implicit closure by checking if an instance function | 627 // Resolve an implicit closure by checking if an instance function |
| 632 // of the same name exists and creating a closure object of the function. | 628 // of the same name exists and creating a closure object of the function. |
| 633 // Arg0: receiver object. | 629 // Arg0: receiver object. |
| 634 // Arg1: ic-data array. | 630 // Arg1: ic-data. |
| 635 // Returns: Closure object or NULL (instance function not found). | 631 // Returns: Closure object or NULL (instance function not found). |
| 636 // This is called by the megamorphic stub when it is unable to resolve an | 632 // This is called by the megamorphic stub when it is unable to resolve an |
| 637 // instance method. This is done just before the call to noSuchMethod. | 633 // instance method. This is done just before the call to noSuchMethod. |
| 638 DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureFunction, 2) { | 634 DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureFunction, 2) { |
| 639 ASSERT(arguments.Count() == | 635 ASSERT(arguments.Count() == |
| 640 kResolveImplicitClosureFunctionRuntimeEntry.argument_count()); | 636 kResolveImplicitClosureFunctionRuntimeEntry.argument_count()); |
| 641 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); | 637 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); |
| 642 const Array& ic_data_array = Array::CheckedHandle(arguments.At(1)); | 638 const ICData& ic_data = ICData::CheckedHandle(arguments.At(1)); |
| 643 ICData ic_data(ic_data_array); | 639 const String& original_function_name = String::Handle(ic_data.target_name()); |
| 644 const String& original_function_name = String::Handle(ic_data.FunctionName()); | |
| 645 const String& getter_prefix = String::Handle(String::New("get:")); | 640 const String& getter_prefix = String::Handle(String::New("get:")); |
| 646 Closure& closure = Closure::Handle(); | 641 Closure& closure = Closure::Handle(); |
| 647 if (!original_function_name.StartsWith(getter_prefix)) { | 642 if (!original_function_name.StartsWith(getter_prefix)) { |
| 648 // This is not a getter so can't be the case where we are trying to | 643 // This is not a getter so can't be the case where we are trying to |
| 649 // create an implicit closure of an instance function. | 644 // create an implicit closure of an instance function. |
| 650 arguments.SetReturn(closure); | 645 arguments.SetReturn(closure); |
| 651 return; | 646 return; |
| 652 } | 647 } |
| 653 Class& receiver_class = Class::Handle(); | 648 Class& receiver_class = Class::Handle(); |
| 654 receiver_class ^= receiver.clazz(); | 649 receiver_class ^= receiver.clazz(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 683 // value from getter is a closure. | 678 // value from getter is a closure. |
| 684 // Arg0: receiver object. | 679 // Arg0: receiver object. |
| 685 // Arg1: ic-data array. | 680 // Arg1: ic-data array. |
| 686 // Returns: Closure object or NULL (closure not found). | 681 // Returns: Closure object or NULL (closure not found). |
| 687 // This is called by the megamorphic stub when it is unable to resolve an | 682 // This is called by the megamorphic stub when it is unable to resolve an |
| 688 // instance method. This is done just before the call to noSuchMethod. | 683 // instance method. This is done just before the call to noSuchMethod. |
| 689 DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureThroughGetter, 2) { | 684 DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureThroughGetter, 2) { |
| 690 ASSERT(arguments.Count() == | 685 ASSERT(arguments.Count() == |
| 691 kResolveImplicitClosureThroughGetterRuntimeEntry.argument_count()); | 686 kResolveImplicitClosureThroughGetterRuntimeEntry.argument_count()); |
| 692 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); | 687 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); |
| 693 const Array& ic_data_array = Array::CheckedHandle(arguments.At(1)); | 688 const ICData& ic_data = ICData::CheckedHandle(arguments.At(1)); |
| 694 ICData ic_data(ic_data_array); | 689 const String& original_function_name = String::Handle(ic_data.target_name()); |
| 695 const String& original_function_name = String::Handle(ic_data.FunctionName()); | |
| 696 const int kNumArguments = 1; | 690 const int kNumArguments = 1; |
| 697 const int kNumNamedArguments = 0; | 691 const int kNumNamedArguments = 0; |
| 698 const String& getter_function_name = | 692 const String& getter_function_name = |
| 699 String::Handle(Field::GetterName(original_function_name)); | 693 String::Handle(Field::GetterName(original_function_name)); |
| 700 Function& function = Function::ZoneHandle( | 694 Function& function = Function::ZoneHandle( |
| 701 Resolver::ResolveDynamic(receiver, | 695 Resolver::ResolveDynamic(receiver, |
| 702 getter_function_name, | 696 getter_function_name, |
| 703 kNumArguments, | 697 kNumArguments, |
| 704 kNumNamedArguments)); | 698 kNumNamedArguments)); |
| 705 Code& code = Code::Handle(); | 699 Code& code = Code::Handle(); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 | 807 |
| 814 // Invoke appropriate noSuchMethod function. | 808 // Invoke appropriate noSuchMethod function. |
| 815 // Arg0: receiver. | 809 // Arg0: receiver. |
| 816 // Arg1: ic-data array. | 810 // Arg1: ic-data array. |
| 817 // Arg2: original arguments descriptor array. | 811 // Arg2: original arguments descriptor array. |
| 818 // Arg3: original arguments array. | 812 // Arg3: original arguments array. |
| 819 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { | 813 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { |
| 820 ASSERT(arguments.Count() == | 814 ASSERT(arguments.Count() == |
| 821 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); | 815 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); |
| 822 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); | 816 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); |
| 823 const Array& ic_data_array = Array::CheckedHandle(arguments.At(1)); | 817 const ICData& ic_data = ICData::CheckedHandle(arguments.At(1)); |
| 824 ICData ic_data(ic_data_array); | 818 const String& original_function_name = String::Handle(ic_data.target_name()); |
| 825 const String& original_function_name = String::Handle(ic_data.FunctionName()); | |
| 826 ASSERT(!Array::CheckedHandle(arguments.At(2)).IsNull()); | 819 ASSERT(!Array::CheckedHandle(arguments.At(2)).IsNull()); |
| 827 const Array& orig_arguments = Array::CheckedHandle(arguments.At(3)); | 820 const Array& orig_arguments = Array::CheckedHandle(arguments.At(3)); |
| 828 // TODO(regis): The signature of the "noSuchMethod" method has to change from | 821 // TODO(regis): The signature of the "noSuchMethod" method has to change from |
| 829 // noSuchMethod(String name, Array arguments) to something like | 822 // noSuchMethod(String name, Array arguments) to something like |
| 830 // noSuchMethod(InvocationMirror call). | 823 // noSuchMethod(InvocationMirror call). |
| 831 const int kNumArguments = 3; | 824 const int kNumArguments = 3; |
| 832 const int kNumNamedArguments = 0; | 825 const int kNumNamedArguments = 0; |
| 833 const Array& kNoArgumentNames = Array::Handle(); | 826 const Array& kNoArgumentNames = Array::Handle(); |
| 834 const String& function_name = | 827 const String& function_name = |
| 835 String::Handle(String::NewSymbol("noSuchMethod")); | 828 String::Handle(String::NewSymbol("noSuchMethod")); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1125 } | 1118 } |
| 1126 } | 1119 } |
| 1127 } | 1120 } |
| 1128 // The cache is null terminated, therefore the loop above should never | 1121 // The cache is null terminated, therefore the loop above should never |
| 1129 // terminate by itself. | 1122 // terminate by itself. |
| 1130 UNREACHABLE(); | 1123 UNREACHABLE(); |
| 1131 return Code::null(); | 1124 return Code::null(); |
| 1132 } | 1125 } |
| 1133 | 1126 |
| 1134 } // namespace dart | 1127 } // namespace dart |
| OLD | NEW |