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 return; \ | |
hausner
2015/08/04 18:21:53
I'd leave the return statement in the function bod
rmacnak
2015/08/04 23:11:24
Done.
| |
1066 | |
1067 #define CLOSURIZE(some_function) \ | |
1068 const Function& closure_function = \ | |
1069 Function::Handle(some_function.ImplicitClosureFunction()); \ | |
1070 const Object& result = \ | |
1071 Object::Handle(closure_function.ImplicitInstanceClosure(receiver)); \ | |
1072 arguments.SetReturn(result); \ | |
1073 return; \ | |
hausner
2015/08/04 18:21:53
Same here. I would leave the return statement in t
rmacnak
2015/08/04 23:11:25
Done.
| |
1074 | |
1057 const bool is_getter = Field::IsGetterName(target_name); | 1075 const bool is_getter = Field::IsGetterName(target_name); |
1058 if (is_getter) { | 1076 if (is_getter) { |
1059 // o.foo failed, closurize o.foo() if it exists | 1077 // o.foo (o.get:foo) failed, closurize o.foo() if it exists. Or, |
1060 const String& field_name = | 1078 // o#foo (o.get:#foo) failed, closurizee o.foo or o.foo(), whichever is |
1061 String::Handle(Field::NameFromGetter(target_name)); | 1079 // encountered first on the inheritance chain. Or, |
1080 // o#foo= (o.get:#set:foo) failed, closurize o.foo= if it exists. | |
1081 String& field_name = | |
1082 String::Handle(Field::NameFromGetter(target_name)); | |
1083 | |
1084 const bool is_extractor = field_name.CharAt(0) == '#'; | |
1085 if (is_extractor) { | |
1086 field_name = String::SubString(field_name, 1); | |
1087 ASSERT(!Field::IsGetterName(field_name)); | |
1088 field_name = Symbols::New(field_name); | |
1089 | |
1090 if (!Field::IsSetterName(field_name)) { | |
1091 const String& getter_name = | |
1092 String::Handle(Field::GetterName(field_name)); | |
1093 | |
1094 // Zigzagged lookup: closure either a regular method or a getter. | |
1095 while (!cls.IsNull()) { | |
1096 function ^= cls.LookupDynamicFunction(field_name); | |
1097 if (!function.IsNull()) { | |
1098 CLOSURIZE(function); | |
1099 } | |
1100 function ^= cls.LookupDynamicFunction(getter_name); | |
1101 if (!function.IsNull()) { | |
1102 CLOSURIZE(function); | |
1103 } | |
1104 cls = cls.SuperClass(); | |
1105 } | |
1106 NO_SUCH_METHOD(); | |
1107 } else { | |
1108 // Fall through for non-ziggaged lookup for o#foo=. | |
1109 } | |
1110 } | |
1111 | |
1062 while (!cls.IsNull()) { | 1112 while (!cls.IsNull()) { |
1063 function ^= cls.LookupDynamicFunction(field_name); | 1113 function ^= cls.LookupDynamicFunction(field_name); |
1064 if (!function.IsNull()) { | 1114 if (!function.IsNull()) { |
1065 const Function& closure_function = | 1115 CLOSURIZE(function); |
1066 Function::Handle(function.ImplicitClosureFunction()); | |
1067 const Object& result = | |
1068 Object::Handle(closure_function.ImplicitInstanceClosure(receiver)); | |
1069 arguments.SetReturn(result); | |
1070 return; | |
1071 } | 1116 } |
1072 cls = cls.SuperClass(); | 1117 cls = cls.SuperClass(); |
1073 } | 1118 } |
1119 | |
1120 // Fall through for noSuchMethod | |
1074 } else { | 1121 } else { |
1075 // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong | 1122 // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong |
1076 // number of arguments, or try (o.foo).call(...) | 1123 // number of arguments, or try (o.foo).call(...) |
1077 | 1124 |
1078 if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) { | 1125 if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) { |
1079 // Special case: closures are implemented with a call getter instead of a | 1126 // Special case: closures are implemented with a call getter instead of a |
1080 // call method and with lazy dispatchers the field-invocation-dispatcher | 1127 // call method and with lazy dispatchers the field-invocation-dispatcher |
1081 // would perform the closure call. | 1128 // would perform the closure call. |
1082 const Object& result = | 1129 const Object& result = |
1083 Object::Handle(DartEntry::InvokeClosure(orig_arguments, | 1130 Object::Handle(DartEntry::InvokeClosure(orig_arguments, |
(...skipping 26 matching lines...) Expand all Loading... | |
1110 Object::Handle(DartEntry::InvokeClosure(orig_arguments, | 1157 Object::Handle(DartEntry::InvokeClosure(orig_arguments, |
1111 orig_arguments_desc)); | 1158 orig_arguments_desc)); |
1112 CheckResultError(call_result); | 1159 CheckResultError(call_result); |
1113 arguments.SetReturn(call_result); | 1160 arguments.SetReturn(call_result); |
1114 return; | 1161 return; |
1115 } | 1162 } |
1116 cls = cls.SuperClass(); | 1163 cls = cls.SuperClass(); |
1117 } | 1164 } |
1118 } | 1165 } |
1119 | 1166 |
1120 // Handle noSuchMethod invocation. | 1167 NO_SUCH_METHOD(); |
1121 const Object& result = Object::Handle( | 1168 |
1122 DartEntry::InvokeNoSuchMethod(receiver, | 1169 #undef NO_SUCH_METHOD |
1123 target_name, | 1170 #undef CLOSURIZE |
1124 orig_arguments, | |
1125 orig_arguments_desc)); | |
1126 CheckResultError(result); | |
1127 arguments.SetReturn(result); | |
1128 } | 1171 } |
1129 | 1172 |
1130 | 1173 |
1131 | 1174 |
1132 // Invoke appropriate noSuchMethod function. | 1175 // Invoke appropriate noSuchMethod function. |
1133 // Arg0: receiver (closure object) | 1176 // Arg0: receiver (closure object) |
1134 // Arg1: arguments descriptor array. | 1177 // Arg1: arguments descriptor array. |
1135 // Arg2: arguments array. | 1178 // Arg2: arguments array. |
1136 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { | 1179 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { |
1137 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 1180 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(); | 1837 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1795 const TypedData& new_data = | 1838 const TypedData& new_data = |
1796 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1839 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1797 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1840 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1798 typed_data_cell.SetAt(0, new_data); | 1841 typed_data_cell.SetAt(0, new_data); |
1799 arguments.SetReturn(new_data); | 1842 arguments.SetReturn(new_data); |
1800 } | 1843 } |
1801 | 1844 |
1802 | 1845 |
1803 } // namespace dart | 1846 } // namespace dart |
OLD | NEW |