| 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/dart_entry.h" | 7 #include "vm/dart_entry.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 OS::Print("ResolveDynamic error '%s': %s.\n", | 52 OS::Print("ResolveDynamic error '%s': %s.\n", |
| 53 function_name.ToCString(), | 53 function_name.ToCString(), |
| 54 error_message.ToCString()); | 54 error_message.ToCString()); |
| 55 } | 55 } |
| 56 return Function::null(); | 56 return Function::null(); |
| 57 } | 57 } |
| 58 return function.raw(); | 58 return function.raw(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 // Method extractors are used to create implicit closures from methods. | |
| 63 // When an expression obj.M is evaluated for the first time and receiver obj | |
| 64 // does not have a getter called M but has a method called M then an extractor | |
| 65 // is created and injected as a getter (under the name get:M) into the class | |
| 66 // owning method M. | |
| 67 static RawFunction* CreateMethodExtractor(const String& getter_name, | |
| 68 const Function& method) { | |
| 69 ASSERT(FLAG_lazy_dispatchers); | |
| 70 const Function& closure_function = | |
| 71 Function::Handle(method.ImplicitClosureFunction()); | |
| 72 | |
| 73 const Class& owner = Class::Handle(closure_function.Owner()); | |
| 74 Function& extractor = Function::Handle( | |
| 75 Function::New(String::Handle(Symbols::New(getter_name)), | |
| 76 RawFunction::kMethodExtractor, | |
| 77 false, // Not static. | |
| 78 false, // Not const. | |
| 79 false, // Not abstract. | |
| 80 false, // Not external. | |
| 81 false, // Not native. | |
| 82 owner, | |
| 83 0)); // No token position. | |
| 84 | |
| 85 // Initialize signature: receiver is a single fixed parameter. | |
| 86 const intptr_t kNumParameters = 1; | |
| 87 extractor.set_num_fixed_parameters(kNumParameters); | |
| 88 extractor.SetNumOptionalParameters(0, 0); | |
| 89 extractor.set_parameter_types(Object::extractor_parameter_types()); | |
| 90 extractor.set_parameter_names(Object::extractor_parameter_names()); | |
| 91 extractor.set_result_type(Type::Handle(Type::DynamicType())); | |
| 92 | |
| 93 extractor.set_extracted_method_closure(closure_function); | |
| 94 extractor.set_is_debuggable(false); | |
| 95 extractor.set_is_visible(false); | |
| 96 | |
| 97 owner.AddFunction(extractor); | |
| 98 | |
| 99 return extractor.raw(); | |
| 100 } | |
| 101 | |
| 102 | |
| 103 RawFunction* Resolver::ResolveDynamicAnyArgs( | 62 RawFunction* Resolver::ResolveDynamicAnyArgs( |
| 104 const Class& receiver_class, | 63 const Class& receiver_class, |
| 105 const String& function_name) { | 64 const String& function_name) { |
| 106 Class& cls = Class::Handle(receiver_class.raw()); | 65 Class& cls = Class::Handle(receiver_class.raw()); |
| 107 if (FLAG_trace_resolving) { | 66 if (FLAG_trace_resolving) { |
| 108 OS::Print("ResolveDynamic '%s' for class %s\n", | 67 OS::Print("ResolveDynamic '%s' for class %s\n", |
| 109 function_name.ToCString(), | 68 function_name.ToCString(), |
| 110 String::Handle(cls.Name()).ToCString()); | 69 String::Handle(cls.Name()).ToCString()); |
| 111 } | 70 } |
| 112 | 71 |
| 113 const bool is_getter = Field::IsGetterName(function_name); | 72 const bool is_getter = Field::IsGetterName(function_name); |
| 114 String& field_name = String::Handle(); | 73 String& field_name = String::Handle(); |
| 115 if (is_getter) { | 74 if (is_getter) { |
| 116 field_name ^= Field::NameFromGetter(function_name); | 75 field_name ^= Field::NameFromGetter(function_name); |
| 117 | 76 |
| 118 if (field_name.CharAt(0) == '#') { | 77 if (field_name.CharAt(0) == '#') { |
| 119 if (!FLAG_lazy_dispatchers) { | |
| 120 return Function::null(); | |
| 121 } | |
| 122 | |
| 123 // Resolving a getter "get:#..." is a request to closurize an instance | 78 // Resolving a getter "get:#..." is a request to closurize an instance |
| 124 // property of the receiver object. It can be of the form: | 79 // property of the receiver object. It can be of the form: |
| 125 // - get:#id, which closurizes a method or getter id | 80 // - get:#id, which closurizes a method or getter id |
| 126 // - get:#set:id, which closurizes a setter id | 81 // - get:#set:id, which closurizes a setter id |
| 127 // - get:#operator, eg. get:#<<, which closurizes an operator method. | 82 // - get:#operator, eg. get:#<<, which closurizes an operator method. |
| 128 // If the property can be resolved, a method extractor function | 83 // If the property can be resolved, a method extractor function |
| 129 // "get:#..." is created and injected into the receiver's class. | 84 // "get:#..." is created and injected into the receiver's class. |
| 130 String& property_name = String::Handle(String::SubString(field_name, 1)); | 85 field_name = String::SubString(field_name, 1); |
| 131 ASSERT(!Field::IsGetterName(property_name)); | 86 ASSERT(!Field::IsGetterName(field_name)); |
| 132 | 87 |
| 133 String& property_getter_name = String::Handle(); | 88 String& property_getter_name = String::Handle(); |
| 134 if (!Field::IsSetterName(property_name)) { | 89 if (!Field::IsSetterName(field_name)) { |
| 135 // If this is not a setter, we need to look for both the regular | 90 // If this is not a setter, we need to look for both the regular |
| 136 // name and the getter name. (In the case of an operator, this | 91 // name and the getter name. (In the case of an operator, this |
| 137 // code will also try to resolve for example get:<< and will fail, | 92 // code will also try to resolve for example get:<< and will fail, |
| 138 // but that's harmless.) | 93 // but that's harmless.) |
| 139 property_getter_name = Field::GetterName(property_name); | 94 property_getter_name = Field::GetterName(field_name); |
| 140 } | 95 } |
| 141 | 96 |
| 142 Function& function = Function::Handle(); | 97 Function& function = Function::Handle(); |
| 143 while (!cls.IsNull()) { | 98 while (!cls.IsNull()) { |
| 144 function = cls.LookupDynamicFunction(property_name); | 99 function = cls.LookupDynamicFunction(field_name); |
| 145 if (!function.IsNull()) { | 100 if (!function.IsNull()) { |
| 146 return CreateMethodExtractor(function_name, function); | 101 return function.GetMethodExtractor(function_name); |
| 147 } | 102 } |
| 148 if (!property_getter_name.IsNull()) { | 103 if (!property_getter_name.IsNull()) { |
| 149 function = cls.LookupDynamicFunction(property_getter_name); | 104 function = cls.LookupDynamicFunction(property_getter_name); |
| 150 if (!function.IsNull()) { | 105 if (!function.IsNull()) { |
| 151 return CreateMethodExtractor(function_name, function); | 106 return function.GetMethodExtractor(function_name); |
| 152 } | 107 } |
| 153 } | 108 } |
| 154 cls = cls.SuperClass(); | 109 cls = cls.SuperClass(); |
| 155 } | 110 } |
| 156 return Function::null(); | 111 return Function::null(); |
| 157 } | 112 } |
| 158 } | 113 } |
| 159 | 114 |
| 160 // Now look for an instance function whose name matches function_name | 115 // Now look for an instance function whose name matches function_name |
| 161 // in the class. | 116 // in the class. |
| 162 Function& function = Function::Handle(); | 117 Function& function = Function::Handle(); |
| 163 while (!cls.IsNull()) { | 118 while (!cls.IsNull()) { |
| 164 function ^= cls.LookupDynamicFunction(function_name); | 119 function ^= cls.LookupDynamicFunction(function_name); |
| 165 if (!function.IsNull()) { | 120 if (!function.IsNull()) { |
| 166 return function.raw(); | 121 return function.raw(); |
| 167 } | 122 } |
| 168 // Getter invocation might actually be a method extraction. | 123 // Getter invocation might actually be a method extraction. |
| 169 if (FLAG_lazy_dispatchers) { | 124 if (FLAG_lazy_dispatchers) { |
| 170 if (is_getter && function.IsNull()) { | 125 if (is_getter && function.IsNull()) { |
| 171 function ^= cls.LookupDynamicFunction(field_name); | 126 function ^= cls.LookupDynamicFunction(field_name); |
| 172 if (!function.IsNull()) { | 127 if (!function.IsNull()) { |
| 173 // We were looking for the getter but found a method with the same | 128 // We were looking for the getter but found a method with the same |
| 174 // name. Create a method extractor and return it. | 129 // name. Create a method extractor and return it. |
| 175 function ^= CreateMethodExtractor(function_name, function); | 130 // The extractor does not exist yet, so using GetMethodExtractor is |
| 131 // not necessary here. |
| 132 function ^= function.CreateMethodExtractor(function_name); |
| 176 return function.raw(); | 133 return function.raw(); |
| 177 } | 134 } |
| 178 } | 135 } |
| 179 } | 136 } |
| 180 cls = cls.SuperClass(); | 137 cls = cls.SuperClass(); |
| 181 } | 138 } |
| 182 return function.raw(); | 139 return function.raw(); |
| 183 } | 140 } |
| 184 | 141 |
| 185 | 142 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 OS::Print("ResolveStaticAllowPrivate error '%s': %s.\n", | 249 OS::Print("ResolveStaticAllowPrivate error '%s': %s.\n", |
| 293 function_name.ToCString(), | 250 function_name.ToCString(), |
| 294 error_message.ToCString()); | 251 error_message.ToCString()); |
| 295 } | 252 } |
| 296 return Function::null(); | 253 return Function::null(); |
| 297 } | 254 } |
| 298 return function.raw(); | 255 return function.raw(); |
| 299 } | 256 } |
| 300 | 257 |
| 301 } // namespace dart | 258 } // namespace dart |
| OLD | NEW |