| 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) { | 78 if (!FLAG_lazy_dispatchers) { |
| 120 return Function::null(); | 79 return Function::null(); |
| 121 } | 80 } |
| 122 | 81 |
| 123 // Resolving a getter "get:#..." is a request to closurize an instance | 82 // Resolving a getter "get:#..." is a request to closurize an instance |
| 124 // property of the receiver object. It can be of the form: | 83 // property of the receiver object. It can be of the form: |
| 125 // - get:#id, which closurizes a method or getter id | 84 // - get:#id, which closurizes a method or getter id |
| 126 // - get:#set:id, which closurizes a setter id | 85 // - get:#set:id, which closurizes a setter id |
| 127 // - get:#operator, eg. get:#<<, which closurizes an operator method. | 86 // - get:#operator, eg. get:#<<, which closurizes an operator method. |
| 128 // If the property can be resolved, a method extractor function | 87 // If the property can be resolved, a method extractor function |
| 129 // "get:#..." is created and injected into the receiver's class. | 88 // "get:#..." is created and injected into the receiver's class. |
| 130 String& property_name = String::Handle(String::SubString(field_name, 1)); | 89 field_name = String::SubString(field_name, 1); |
| 131 ASSERT(!Field::IsGetterName(property_name)); | 90 ASSERT(!Field::IsGetterName(field_name)); |
| 132 | 91 |
| 133 String& property_getter_name = String::Handle(); | 92 String& property_getter_name = String::Handle(); |
| 134 if (!Field::IsSetterName(property_name)) { | 93 if (!Field::IsSetterName(field_name)) { |
| 135 // If this is not a setter, we need to look for both the regular | 94 // 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 | 95 // 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, | 96 // code will also try to resolve for example get:<< and will fail, |
| 138 // but that's harmless.) | 97 // but that's harmless.) |
| 139 property_getter_name = Field::GetterName(property_name); | 98 property_getter_name = Field::GetterName(field_name); |
| 140 } | 99 } |
| 141 | 100 |
| 142 Function& function = Function::Handle(); | 101 Function& function = Function::Handle(); |
| 143 while (!cls.IsNull()) { | 102 while (!cls.IsNull()) { |
| 144 function = cls.LookupDynamicFunction(property_name); | 103 function = cls.LookupDynamicFunction(field_name); |
| 145 if (!function.IsNull()) { | 104 if (!function.IsNull()) { |
| 146 return CreateMethodExtractor(function_name, function); | 105 return function.GetMethodExtractor(function_name); |
| 147 } | 106 } |
| 148 if (!property_getter_name.IsNull()) { | 107 if (!property_getter_name.IsNull()) { |
| 149 function = cls.LookupDynamicFunction(property_getter_name); | 108 function = cls.LookupDynamicFunction(property_getter_name); |
| 150 if (!function.IsNull()) { | 109 if (!function.IsNull()) { |
| 151 return CreateMethodExtractor(function_name, function); | 110 return function.GetMethodExtractor(function_name); |
| 152 } | 111 } |
| 153 } | 112 } |
| 154 cls = cls.SuperClass(); | 113 cls = cls.SuperClass(); |
| 155 } | 114 } |
| 156 return Function::null(); | 115 return Function::null(); |
| 157 } | 116 } |
| 158 } | 117 } |
| 159 | 118 |
| 160 // Now look for an instance function whose name matches function_name | 119 // Now look for an instance function whose name matches function_name |
| 161 // in the class. | 120 // in the class. |
| 162 Function& function = Function::Handle(); | 121 Function& function = Function::Handle(); |
| 163 while (!cls.IsNull()) { | 122 while (!cls.IsNull()) { |
| 164 function ^= cls.LookupDynamicFunction(function_name); | 123 function ^= cls.LookupDynamicFunction(function_name); |
| 165 if (!function.IsNull()) { | 124 if (!function.IsNull()) { |
| 166 return function.raw(); | 125 return function.raw(); |
| 167 } | 126 } |
| 168 // Getter invocation might actually be a method extraction. | 127 // Getter invocation might actually be a method extraction. |
| 169 if (FLAG_lazy_dispatchers) { | 128 if (FLAG_lazy_dispatchers) { |
| 170 if (is_getter && function.IsNull()) { | 129 if (is_getter && function.IsNull()) { |
| 171 function ^= cls.LookupDynamicFunction(field_name); | 130 function ^= cls.LookupDynamicFunction(field_name); |
| 172 if (!function.IsNull()) { | 131 if (!function.IsNull()) { |
| 173 // We were looking for the getter but found a method with the same | 132 // We were looking for the getter but found a method with the same |
| 174 // name. Create a method extractor and return it. | 133 // name. Create a method extractor and return it. |
| 175 function ^= CreateMethodExtractor(function_name, function); | 134 // The extractor does not exist yet, so using GetMethodExtractor is |
| 135 // not necessary here. |
| 136 function ^= function.CreateMethodExtractor(function_name); |
| 176 return function.raw(); | 137 return function.raw(); |
| 177 } | 138 } |
| 178 } | 139 } |
| 179 } | 140 } |
| 180 cls = cls.SuperClass(); | 141 cls = cls.SuperClass(); |
| 181 } | 142 } |
| 182 return function.raw(); | 143 return function.raw(); |
| 183 } | 144 } |
| 184 | 145 |
| 185 | 146 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 OS::Print("ResolveStaticAllowPrivate error '%s': %s.\n", | 253 OS::Print("ResolveStaticAllowPrivate error '%s': %s.\n", |
| 293 function_name.ToCString(), | 254 function_name.ToCString(), |
| 294 error_message.ToCString()); | 255 error_message.ToCString()); |
| 295 } | 256 } |
| 296 return Function::null(); | 257 return Function::null(); |
| 297 } | 258 } |
| 298 return function.raw(); | 259 return function.raw(); |
| 299 } | 260 } |
| 300 | 261 |
| 301 } // namespace dart | 262 } // namespace dart |
| OLD | NEW |