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/resolver.h" | 5 #include "vm/resolver.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
9 #include "vm/object.h" | 9 #include "vm/object.h" |
10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| 11 #include "vm/symbols.h" |
11 | 12 |
12 namespace dart { | 13 namespace dart { |
13 | 14 |
14 DEFINE_FLAG(bool, trace_resolving, false, "Trace resolving."); | 15 DEFINE_FLAG(bool, trace_resolving, false, "Trace resolving."); |
15 | 16 |
16 | 17 |
17 // The actual names of named arguments are not checked by the dynamic resolver, | 18 // The actual names of named arguments are not checked by the dynamic resolver, |
18 // but by the method entry code. It is important that the dynamic resolver | 19 // but by the method entry code. It is important that the dynamic resolver |
19 // checks that no named arguments are passed to a method that does not accept | 20 // checks that no named arguments are passed to a method that does not accept |
20 // them, since the entry code of such a method does not check for named | 21 // them, since the entry code of such a method does not check for named |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 OS::Print("ResolveDynamic error '%s': %s.\n", | 65 OS::Print("ResolveDynamic error '%s': %s.\n", |
65 function_name.ToCString(), | 66 function_name.ToCString(), |
66 error_message.ToCString()); | 67 error_message.ToCString()); |
67 } | 68 } |
68 return Function::null(); | 69 return Function::null(); |
69 } | 70 } |
70 return function.raw(); | 71 return function.raw(); |
71 } | 72 } |
72 | 73 |
73 | 74 |
| 75 // Method extractors are used to create implicit closures from methods. |
| 76 // When an expression obj.M is evaluated for the first time and receiver obj |
| 77 // does not have a getter called M but has a method called M then an extractor |
| 78 // is created and injected as a getter (under the name get:M) into the class |
| 79 // ownining method M. |
| 80 static RawFunction* CreateMethodExtractor(const String& getter_name, |
| 81 const Function& method) { |
| 82 const Function& closure_function = |
| 83 Function::Handle(method.ImplicitClosureFunction()); |
| 84 |
| 85 const Class& owner = Class::Handle(closure_function.Owner()); |
| 86 Function& extractor = Function::Handle( |
| 87 Function::New(String::Handle(Symbols::New(getter_name)), |
| 88 RawFunction::kMethodExtractor, |
| 89 false, // Not static. |
| 90 false, // Not const. |
| 91 false, // Not abstract. |
| 92 false, // Not external. |
| 93 owner, |
| 94 0)); // No token position. |
| 95 |
| 96 // Initialize signature: receiver is a single fixed parameter. |
| 97 const intptr_t kNumParameters = 1; |
| 98 extractor.set_num_fixed_parameters(kNumParameters); |
| 99 extractor.SetNumOptionalParameters(0, 0); |
| 100 extractor.set_parameter_types(Array::Handle(Array::New(kNumParameters, |
| 101 Heap::kOld))); |
| 102 extractor.set_parameter_names(Array::Handle(Array::New(kNumParameters, |
| 103 Heap::kOld))); |
| 104 extractor.SetParameterTypeAt(0, Type::Handle(Type::DynamicType())); |
| 105 extractor.SetParameterNameAt(0, Symbols::This()); |
| 106 extractor.set_result_type(Type::Handle(Type::DynamicType())); |
| 107 |
| 108 extractor.set_extracted_method_closure(closure_function); |
| 109 |
| 110 owner.AddFunction(extractor); |
| 111 |
| 112 return extractor.raw(); |
| 113 } |
| 114 |
| 115 |
74 RawFunction* Resolver::ResolveDynamicAnyArgs( | 116 RawFunction* Resolver::ResolveDynamicAnyArgs( |
75 const Class& receiver_class, | 117 const Class& receiver_class, |
76 const String& function_name) { | 118 const String& function_name) { |
77 Class& cls = Class::Handle(receiver_class.raw()); | 119 Class& cls = Class::Handle(receiver_class.raw()); |
78 if (FLAG_trace_resolving) { | 120 if (FLAG_trace_resolving) { |
79 OS::Print("ResolveDynamic '%s' for class %s\n", | 121 OS::Print("ResolveDynamic '%s' for class %s\n", |
80 function_name.ToCString(), | 122 function_name.ToCString(), |
81 String::Handle(cls.Name()).ToCString()); | 123 String::Handle(cls.Name()).ToCString()); |
82 } | 124 } |
| 125 |
| 126 const bool is_getter = Field::IsGetterName(function_name); |
| 127 String& field_name = String::Handle(); |
| 128 if (is_getter) { |
| 129 field_name ^= Field::NameFromGetter(function_name); |
| 130 } |
| 131 |
83 // Now look for an instance function whose name matches function_name | 132 // Now look for an instance function whose name matches function_name |
84 // in the class. | 133 // in the class. |
85 Function& function = | 134 Function& function = Function::Handle(); |
86 Function::Handle(cls.LookupDynamicFunction(function_name)); | 135 while (function.IsNull() && !cls.IsNull()) { |
87 while (function.IsNull()) { | 136 function ^= cls.LookupDynamicFunction(function_name); |
| 137 |
| 138 // Getter invocation might actually be a method extraction. |
| 139 if (is_getter && function.IsNull()) { |
| 140 function ^= cls.LookupDynamicFunction(field_name); |
| 141 if (!function.IsNull()) { |
| 142 // We were looking for the getter but found a method with the same name. |
| 143 // Create a method extractor and return it. |
| 144 function ^= CreateMethodExtractor(function_name, function); |
| 145 } |
| 146 } |
| 147 |
88 cls = cls.SuperClass(); | 148 cls = cls.SuperClass(); |
89 if (cls.IsNull()) break; | |
90 function = cls.LookupDynamicFunction(function_name); | |
91 } | 149 } |
92 return function.raw(); | 150 return function.raw(); |
93 } | 151 } |
94 | 152 |
95 | 153 |
96 RawFunction* Resolver::ResolveStatic(const Library& library, | 154 RawFunction* Resolver::ResolveStatic(const Library& library, |
97 const String& class_name, | 155 const String& class_name, |
98 const String& function_name, | 156 const String& function_name, |
99 int num_arguments, | 157 int num_arguments, |
100 const Array& argument_names, | 158 const Array& argument_names, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 OS::Print("ResolveStatic error '%s': %s.\n", | 250 OS::Print("ResolveStatic error '%s': %s.\n", |
193 function_name.ToCString(), | 251 function_name.ToCString(), |
194 error_message.ToCString()); | 252 error_message.ToCString()); |
195 } | 253 } |
196 return Function::null(); | 254 return Function::null(); |
197 } | 255 } |
198 return function.raw(); | 256 return function.raw(); |
199 } | 257 } |
200 | 258 |
201 } // namespace dart | 259 } // namespace dart |
OLD | NEW |