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 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 | 717 |
718 // An instance call of the form o.f(...) could not be resolved. Check if | 718 // An instance call of the form o.f(...) could not be resolved. Check if |
719 // there is a getter with the same name. If so, invoke it. If the value is | 719 // there is a getter with the same name. If so, invoke it. If the value is |
720 // a closure, invoke it with the given arguments. If the value is a | 720 // a closure, invoke it with the given arguments. If the value is a |
721 // non-closure, attempt to invoke "call" on it. | 721 // non-closure, attempt to invoke "call" on it. |
722 static bool ResolveCallThroughGetter(const Instance& receiver, | 722 static bool ResolveCallThroughGetter(const Instance& receiver, |
723 const Class& receiver_class, | 723 const Class& receiver_class, |
724 const String& target_name, | 724 const String& target_name, |
725 const Array& arguments_descriptor, | 725 const Array& arguments_descriptor, |
726 Function* result) { | 726 Function* result) { |
| 727 ASSERT(FLAG_lazy_dispatchers); |
727 // 1. Check if there is a getter with the same name. | 728 // 1. Check if there is a getter with the same name. |
728 const String& getter_name = String::Handle(Field::GetterName(target_name)); | 729 const String& getter_name = String::Handle(Field::GetterName(target_name)); |
729 const int kNumArguments = 1; | 730 const int kNumArguments = 1; |
730 ArgumentsDescriptor args_desc( | 731 ArgumentsDescriptor args_desc( |
731 Array::Handle(ArgumentsDescriptor::New(kNumArguments))); | 732 Array::Handle(ArgumentsDescriptor::New(kNumArguments))); |
732 const Function& getter = Function::Handle( | 733 const Function& getter = Function::Handle( |
733 Resolver::ResolveDynamicForReceiverClass(receiver_class, | 734 Resolver::ResolveDynamicForReceiverClass(receiver_class, |
734 getter_name, | 735 getter_name, |
735 args_desc)); | 736 args_desc)); |
736 if (getter.IsNull() || getter.IsMethodExtractor()) { | 737 if (getter.IsNull() || getter.IsMethodExtractor()) { |
(...skipping 20 matching lines...) Expand all Loading... |
757 } | 758 } |
758 *result = target_function.raw(); | 759 *result = target_function.raw(); |
759 return true; | 760 return true; |
760 } | 761 } |
761 | 762 |
762 | 763 |
763 // Handle other invocations (implicit closures, noSuchMethod). | 764 // Handle other invocations (implicit closures, noSuchMethod). |
764 RawFunction* InlineCacheMissHelper( | 765 RawFunction* InlineCacheMissHelper( |
765 const Instance& receiver, | 766 const Instance& receiver, |
766 const ICData& ic_data) { | 767 const ICData& ic_data) { |
| 768 if (!FLAG_lazy_dispatchers) { |
| 769 return Function::null(); // We'll handle it in the runtime. |
| 770 } |
| 771 |
767 const Array& args_descriptor = Array::Handle(ic_data.arguments_descriptor()); | 772 const Array& args_descriptor = Array::Handle(ic_data.arguments_descriptor()); |
768 | 773 |
769 const Class& receiver_class = Class::Handle(receiver.clazz()); | 774 const Class& receiver_class = Class::Handle(receiver.clazz()); |
770 const String& target_name = String::Handle(ic_data.target_name()); | 775 const String& target_name = String::Handle(ic_data.target_name()); |
771 | 776 |
772 Function& result = Function::Handle(); | 777 Function& result = Function::Handle(); |
773 if (!ResolveCallThroughGetter(receiver, | 778 if (!ResolveCallThroughGetter(receiver, |
774 receiver_class, | 779 receiver_class, |
775 target_name, | 780 target_name, |
776 args_descriptor, | 781 args_descriptor, |
777 &result)) { | 782 &result)) { |
778 if (!FLAG_lazy_dispatchers) { | |
779 return result.raw(); // Return null. | |
780 } | |
781 ArgumentsDescriptor desc(args_descriptor); | 783 ArgumentsDescriptor desc(args_descriptor); |
782 const Function& target_function = | 784 const Function& target_function = |
783 Function::Handle(receiver_class.GetInvocationDispatcher( | 785 Function::Handle(receiver_class.GetInvocationDispatcher( |
784 target_name, | 786 target_name, |
785 args_descriptor, | 787 args_descriptor, |
786 RawFunction::kNoSuchMethodDispatcher)); | 788 RawFunction::kNoSuchMethodDispatcher)); |
787 if (FLAG_trace_ic) { | 789 if (FLAG_trace_ic) { |
788 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n", | 790 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n", |
789 Class::Handle(receiver.clazz()).ToCString(), | 791 Class::Handle(receiver.clazz()).ToCString(), |
790 receiver.GetClassId(), | 792 receiver.GetClassId(), |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 // Arg1: IC data | 1037 // Arg1: IC data |
1036 // Arg2: arguments descriptor array | 1038 // Arg2: arguments descriptor array |
1037 // Arg3: arguments array | 1039 // Arg3: arguments array |
1038 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { | 1040 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { |
1039 ASSERT(!FLAG_lazy_dispatchers); | 1041 ASSERT(!FLAG_lazy_dispatchers); |
1040 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 1042 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
1041 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | 1043 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
1042 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); | 1044 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); |
1043 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); | 1045 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); |
1044 const String& target_name = String::Handle(ic_data.target_name()); | 1046 const String& target_name = String::Handle(ic_data.target_name()); |
| 1047 |
| 1048 Class& cls = Class::Handle(receiver.clazz()); |
| 1049 Function& function = Function::Handle(); |
| 1050 |
| 1051 // Dart distinguishes getters and regular methods and allows their calls |
| 1052 // to mix with conversions, and its selectors are independent of arity. So do |
| 1053 // a zigzagged lookup to see if this call failed because of an arity mismatch, |
| 1054 // need for conversion, or there really is no such method. |
| 1055 |
| 1056 const bool is_getter = Field::IsGetterName(target_name); |
| 1057 if (is_getter) { |
| 1058 // o.foo failed, closurize o.foo() if it exists |
| 1059 const String& field_name = |
| 1060 String::Handle(Field::NameFromGetter(target_name)); |
| 1061 while (!cls.IsNull()) { |
| 1062 function ^= cls.LookupDynamicFunction(field_name); |
| 1063 if (!function.IsNull()) { |
| 1064 const Function& closure_function = |
| 1065 Function::Handle(function.ImplicitClosureFunction()); |
| 1066 const Object& result = |
| 1067 Object::Handle(closure_function.ImplicitInstanceClosure(receiver)); |
| 1068 arguments.SetReturn(result); |
| 1069 return; |
| 1070 } |
| 1071 cls = cls.SuperClass(); |
| 1072 } |
| 1073 } else { |
| 1074 // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong |
| 1075 // number of arguments, or try (o.foo).call(...) |
| 1076 |
| 1077 if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) { |
| 1078 // Special case: closures are implemented with a call getter instead of a |
| 1079 // call method and with lazy dispatchers the field-invocation-dispatcher |
| 1080 // would perform the closure call. |
| 1081 const Object& result = |
| 1082 Object::Handle(DartEntry::InvokeClosure(orig_arguments, |
| 1083 orig_arguments_desc)); |
| 1084 CheckResultError(result); |
| 1085 arguments.SetReturn(result); |
| 1086 return; |
| 1087 } |
| 1088 |
| 1089 const String& getter_name = String::Handle(Field::GetterName(target_name)); |
| 1090 while (!cls.IsNull()) { |
| 1091 function ^= cls.LookupDynamicFunction(target_name); |
| 1092 if (!function.IsNull()) { |
| 1093 ArgumentsDescriptor args_desc(orig_arguments_desc); |
| 1094 ASSERT(!function.AreValidArguments(args_desc, NULL)); |
| 1095 break; // mismatch, invoke noSuchMethod |
| 1096 } |
| 1097 function ^= cls.LookupDynamicFunction(getter_name); |
| 1098 if (!function.IsNull()) { |
| 1099 const Array& getter_arguments = Array::Handle(Array::New(1)); |
| 1100 getter_arguments.SetAt(0, receiver); |
| 1101 const Object& getter_result = |
| 1102 Object::Handle(DartEntry::InvokeFunction(function, |
| 1103 getter_arguments)); |
| 1104 CheckResultError(getter_result); |
| 1105 ASSERT(getter_result.IsNull() || getter_result.IsInstance()); |
| 1106 |
| 1107 orig_arguments.SetAt(0, getter_result); |
| 1108 const Object& call_result = |
| 1109 Object::Handle(DartEntry::InvokeClosure(orig_arguments, |
| 1110 orig_arguments_desc)); |
| 1111 CheckResultError(call_result); |
| 1112 arguments.SetReturn(call_result); |
| 1113 return; |
| 1114 } |
| 1115 cls = cls.SuperClass(); |
| 1116 } |
| 1117 } |
| 1118 |
1045 // Handle noSuchMethod invocation. | 1119 // Handle noSuchMethod invocation. |
1046 const Object& result = Object::Handle( | 1120 const Object& result = Object::Handle( |
1047 DartEntry::InvokeNoSuchMethod(receiver, | 1121 DartEntry::InvokeNoSuchMethod(receiver, |
1048 target_name, | 1122 target_name, |
1049 orig_arguments, | 1123 orig_arguments, |
1050 orig_arguments_desc)); | 1124 orig_arguments_desc)); |
1051 CheckResultError(result); | 1125 CheckResultError(result); |
1052 arguments.SetReturn(result); | 1126 arguments.SetReturn(result); |
1053 } | 1127 } |
1054 | 1128 |
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1716 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1790 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1717 const TypedData& new_data = | 1791 const TypedData& new_data = |
1718 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1792 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1719 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1793 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1720 typed_data_cell.SetAt(0, new_data); | 1794 typed_data_cell.SetAt(0, new_data); |
1721 arguments.SetReturn(new_data); | 1795 arguments.SetReturn(new_data); |
1722 } | 1796 } |
1723 | 1797 |
1724 | 1798 |
1725 } // namespace dart | 1799 } // namespace dart |
OLD | NEW |