Index: runtime/vm/code_generator.cc |
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
index 0dd758140a55a5fbf8bf0f3b22e95517a5076111..58da738d483ba5dea7464ba281e45fb27bd658f9 100644 |
--- a/runtime/vm/code_generator.cc |
+++ b/runtime/vm/code_generator.cc |
@@ -1127,13 +1127,59 @@ DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) { |
} |
+static const char* CreateMethodExtractorName(const Function& closure_function) { |
srdjan
2013/01/16 22:08:56
ASSERT(closure_function.IsClosureFunction()) ... a
Vyacheslav Egorov (Google)
2013/01/17 12:46:38
This method died.
|
+ const char* kFormat = "[MethodExtractor:%s]"; |
+ const char* function_name = |
+ String::Handle(closure_function.name()).ToCString(); |
+ intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name) + 1; |
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
+ OS::SNPrint(chars, len, kFormat, function_name); |
+ return chars; |
+} |
+ |
+ |
+static RawFunction* GetMethodExtractor(const Function& closure_function) { |
srdjan
2013/01/16 22:08:56
Please add a brief comment what a method extractor
Vyacheslav Egorov (Google)
2013/01/17 12:46:38
Done.
|
+ Function& extractor = Function::Handle(closure_function.method_extractor()); |
+ if (extractor.IsNull()) { |
+ const char* name = CreateMethodExtractorName(closure_function); |
+ |
+ const Class& owner = Class::Handle(closure_function.Owner()); |
+ extractor ^= Function::New(String::Handle(Symbols::New(name)), |
+ RawFunction::kMethodExtractor, |
+ false, // Not static. |
+ false, // Not const. |
+ false, // Not abstract. |
+ false, // Not external. |
+ owner, |
+ 0); // No token position. |
+ // Initialize function's signature. |
+ const intptr_t kNumParameters = 1; |
+ extractor.set_num_fixed_parameters(kNumParameters); |
+ extractor.SetNumOptionalParameters(0, 0); |
+ extractor.set_parameter_types(Array::Handle(Array::New(kNumParameters, |
+ Heap::kOld))); |
+ extractor.set_parameter_names(Array::Handle(Array::New(kNumParameters, |
+ Heap::kOld))); |
+ extractor.SetParameterTypeAt(0, Type::Handle(Type::DynamicType())); |
+ extractor.SetParameterNameAt(0, Symbols::This()); |
+ extractor.set_result_type(Type::Handle(Type::DynamicType())); |
+ |
+ extractor.set_extracted_method_closure(closure_function); |
+ |
+ Compiler::CompileFunction(extractor); |
+ } |
+ return extractor.raw(); |
+} |
+ |
+ |
// An instance call could not be resolved by an IC miss handler. Check if |
// it was a getter call and if there is an instance function with the same |
// name. If so, create and return an implicit closure from the function. |
// Otherwise return null. |
static RawInstance* ResolveImplicitClosure(const Instance& receiver, |
const Class& receiver_class, |
- const String& target_name) { |
+ const String& target_name, |
+ const ICData& ic_data) { |
// 1. Check if was a getter call. |
if (!Field::IsGetterName(target_name)) return Instance::null(); |
@@ -1156,6 +1202,11 @@ static RawInstance* ResolveImplicitClosure(const Instance& receiver, |
AbstractTypeArguments::Handle(receiver.GetTypeArguments()); |
closure.SetTypeArguments(type_arguments); |
} |
+ |
+ ASSERT(ic_data.num_args_tested() == 1); |
+ ic_data.AddReceiverCheck( |
+ receiver_class.id(), |
+ Function::Handle(GetMethodExtractor(closure_function))); |
return closure.raw(); |
} |
@@ -1233,7 +1284,8 @@ DEFINE_RUNTIME_ENTRY(InstanceFunctionLookup, 4) { |
Instance& closure = Instance::Handle(ResolveImplicitClosure(receiver, |
receiver_class, |
- target_name)); |
+ target_name, |
+ ic_data)); |
if (!closure.IsNull()) { |
arguments.SetReturn(closure); |
return; |