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 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 const String& target_name = String::Handle(ic_data.target_name()); | 1047 const String& target_name = String::Handle(ic_data.target_name()); |
1048 | 1048 |
1049 Class& cls = Class::Handle(receiver.clazz()); | 1049 Class& cls = Class::Handle(receiver.clazz()); |
1050 Function& function = Function::Handle(); | 1050 Function& function = Function::Handle(); |
1051 | 1051 |
1052 // Dart distinguishes getters and regular methods and allows their calls | 1052 // Dart distinguishes getters and regular methods and allows their calls |
1053 // to mix with conversions, and its selectors are independent of arity. So do | 1053 // to mix with conversions, and its selectors are independent of arity. So do |
1054 // a zigzagged lookup to see if this call failed because of an arity mismatch, | 1054 // a zigzagged lookup to see if this call failed because of an arity mismatch, |
1055 // need for conversion, or there really is no such method. | 1055 // need for conversion, or there really is no such method. |
1056 | 1056 |
| 1057 #define NO_SUCH_METHOD() \ |
| 1058 const Object& result = Object::Handle( \ |
| 1059 DartEntry::InvokeNoSuchMethod(receiver, \ |
| 1060 target_name, \ |
| 1061 orig_arguments, \ |
| 1062 orig_arguments_desc)); \ |
| 1063 CheckResultError(result); \ |
| 1064 arguments.SetReturn(result); \ |
| 1065 |
| 1066 #define CLOSURIZE(some_function) \ |
| 1067 const Function& closure_function = \ |
| 1068 Function::Handle(some_function.ImplicitClosureFunction()); \ |
| 1069 const Object& result = \ |
| 1070 Object::Handle(closure_function.ImplicitInstanceClosure(receiver)); \ |
| 1071 arguments.SetReturn(result); \ |
| 1072 |
1057 const bool is_getter = Field::IsGetterName(target_name); | 1073 const bool is_getter = Field::IsGetterName(target_name); |
1058 if (is_getter) { | 1074 if (is_getter) { |
1059 // o.foo failed, closurize o.foo() if it exists | 1075 // o.foo (o.get:foo) failed, closurize o.foo() if it exists. Or, |
1060 const String& field_name = | 1076 // o#foo (o.get:#foo) failed, closurizee o.foo or o.foo(), whichever is |
1061 String::Handle(Field::NameFromGetter(target_name)); | 1077 // encountered first on the inheritance chain. Or, |
| 1078 // o#foo= (o.get:#set:foo) failed, closurize o.foo= if it exists. |
| 1079 String& field_name = |
| 1080 String::Handle(Field::NameFromGetter(target_name)); |
| 1081 |
| 1082 const bool is_extractor = field_name.CharAt(0) == '#'; |
| 1083 if (is_extractor) { |
| 1084 field_name = String::SubString(field_name, 1); |
| 1085 ASSERT(!Field::IsGetterName(field_name)); |
| 1086 field_name = Symbols::New(field_name); |
| 1087 |
| 1088 if (!Field::IsSetterName(field_name)) { |
| 1089 const String& getter_name = |
| 1090 String::Handle(Field::GetterName(field_name)); |
| 1091 |
| 1092 // Zigzagged lookup: closure either a regular method or a getter. |
| 1093 while (!cls.IsNull()) { |
| 1094 function ^= cls.LookupDynamicFunction(field_name); |
| 1095 if (!function.IsNull()) { |
| 1096 CLOSURIZE(function); |
| 1097 return; |
| 1098 } |
| 1099 function ^= cls.LookupDynamicFunction(getter_name); |
| 1100 if (!function.IsNull()) { |
| 1101 CLOSURIZE(function); |
| 1102 return; |
| 1103 } |
| 1104 cls = cls.SuperClass(); |
| 1105 } |
| 1106 NO_SUCH_METHOD(); |
| 1107 return; |
| 1108 } else { |
| 1109 // Fall through for non-ziggaged lookup for o#foo=. |
| 1110 } |
| 1111 } |
| 1112 |
1062 while (!cls.IsNull()) { | 1113 while (!cls.IsNull()) { |
1063 function ^= cls.LookupDynamicFunction(field_name); | 1114 function ^= cls.LookupDynamicFunction(field_name); |
1064 if (!function.IsNull()) { | 1115 if (!function.IsNull()) { |
1065 const Function& closure_function = | 1116 CLOSURIZE(function); |
1066 Function::Handle(function.ImplicitClosureFunction()); | |
1067 const Object& result = | |
1068 Object::Handle(closure_function.ImplicitInstanceClosure(receiver)); | |
1069 arguments.SetReturn(result); | |
1070 return; | 1117 return; |
1071 } | 1118 } |
1072 cls = cls.SuperClass(); | 1119 cls = cls.SuperClass(); |
1073 } | 1120 } |
| 1121 |
| 1122 // Fall through for noSuchMethod |
1074 } else { | 1123 } else { |
1075 // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong | 1124 // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong |
1076 // number of arguments, or try (o.foo).call(...) | 1125 // number of arguments, or try (o.foo).call(...) |
1077 | 1126 |
1078 if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) { | 1127 if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) { |
1079 // Special case: closures are implemented with a call getter instead of a | 1128 // Special case: closures are implemented with a call getter instead of a |
1080 // call method and with lazy dispatchers the field-invocation-dispatcher | 1129 // call method and with lazy dispatchers the field-invocation-dispatcher |
1081 // would perform the closure call. | 1130 // would perform the closure call. |
1082 const Object& result = | 1131 const Object& result = |
1083 Object::Handle(DartEntry::InvokeClosure(orig_arguments, | 1132 Object::Handle(DartEntry::InvokeClosure(orig_arguments, |
(...skipping 26 matching lines...) Expand all Loading... |
1110 Object::Handle(DartEntry::InvokeClosure(orig_arguments, | 1159 Object::Handle(DartEntry::InvokeClosure(orig_arguments, |
1111 orig_arguments_desc)); | 1160 orig_arguments_desc)); |
1112 CheckResultError(call_result); | 1161 CheckResultError(call_result); |
1113 arguments.SetReturn(call_result); | 1162 arguments.SetReturn(call_result); |
1114 return; | 1163 return; |
1115 } | 1164 } |
1116 cls = cls.SuperClass(); | 1165 cls = cls.SuperClass(); |
1117 } | 1166 } |
1118 } | 1167 } |
1119 | 1168 |
1120 // Handle noSuchMethod invocation. | 1169 NO_SUCH_METHOD(); |
1121 const Object& result = Object::Handle( | 1170 |
1122 DartEntry::InvokeNoSuchMethod(receiver, | 1171 #undef NO_SUCH_METHOD |
1123 target_name, | 1172 #undef CLOSURIZE |
1124 orig_arguments, | |
1125 orig_arguments_desc)); | |
1126 CheckResultError(result); | |
1127 arguments.SetReturn(result); | |
1128 } | 1173 } |
1129 | 1174 |
1130 | 1175 |
1131 | 1176 |
1132 // Invoke appropriate noSuchMethod function. | 1177 // Invoke appropriate noSuchMethod function. |
1133 // Arg0: receiver (closure object) | 1178 // Arg0: receiver (closure object) |
1134 // Arg1: arguments descriptor array. | 1179 // Arg1: arguments descriptor array. |
1135 // Arg2: arguments array. | 1180 // Arg2: arguments array. |
1136 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { | 1181 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { |
1137 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 1182 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1839 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1795 const TypedData& new_data = | 1840 const TypedData& new_data = |
1796 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1841 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1797 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1842 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1798 typed_data_cell.SetAt(0, new_data); | 1843 typed_data_cell.SetAt(0, new_data); |
1799 arguments.SetReturn(new_data); | 1844 arguments.SetReturn(new_data); |
1800 } | 1845 } |
1801 | 1846 |
1802 | 1847 |
1803 } // namespace dart | 1848 } // namespace dart |
OLD | NEW |