| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 #include "vm/bootstrap_natives.h" |
| 6 |
| 7 #include "vm/compiler.h" |
| 8 #include "vm/dart_entry.h" |
| 9 #include "vm/exceptions.h" |
| 10 #include "vm/native_entry.h" |
| 11 #include "vm/object_store.h" |
| 12 #include "vm/resolver.h" |
| 13 #include "vm/symbols.h" |
| 14 |
| 15 namespace dart { |
| 16 |
| 17 // TODO(regis): Factorize this static helper copied from code_generator.cc. |
| 18 static RawObject* InvokeNoSuchMethod(const Instance& receiver, |
| 19 const String& target_name, |
| 20 const Array& arguments_descriptor, |
| 21 const Array& arguments) { |
| 22 // Allocate an InvocationMirror object. |
| 23 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 24 const String& invocation_mirror_name = |
| 25 String::Handle(Symbols::InvocationMirror()); |
| 26 Class& invocation_mirror_class = |
| 27 Class::Handle(core_lib.LookupClassAllowPrivate(invocation_mirror_name)); |
| 28 ASSERT(!invocation_mirror_class.IsNull()); |
| 29 const String& allocation_function_name = |
| 30 String::Handle(Symbols::AllocateInvocationMirror()); |
| 31 const Function& allocation_function = Function::Handle( |
| 32 Resolver::ResolveStaticByName(invocation_mirror_class, |
| 33 allocation_function_name, |
| 34 Resolver::kIsQualified)); |
| 35 ASSERT(!allocation_function.IsNull()); |
| 36 GrowableArray<const Object*> allocation_arguments(3); |
| 37 allocation_arguments.Add(&target_name); |
| 38 allocation_arguments.Add(&arguments_descriptor); |
| 39 allocation_arguments.Add(&arguments); |
| 40 const Array& kNoArgumentNames = Array::Handle(); |
| 41 const Object& invocation_mirror = |
| 42 Object::Handle(DartEntry::InvokeStatic(allocation_function, |
| 43 allocation_arguments, |
| 44 kNoArgumentNames)); |
| 45 |
| 46 const String& function_name = String::Handle(Symbols::NoSuchMethod()); |
| 47 const int kNumArguments = 2; |
| 48 const int kNumNamedArguments = 0; |
| 49 const Function& function = Function::Handle( |
| 50 Resolver::ResolveDynamic(receiver, |
| 51 function_name, |
| 52 kNumArguments, |
| 53 kNumNamedArguments)); |
| 54 ASSERT(!function.IsNull()); |
| 55 GrowableArray<const Object*> invoke_arguments(1); |
| 56 invoke_arguments.Add(&invocation_mirror); |
| 57 const Object& result = |
| 58 Object::Handle(DartEntry::InvokeDynamic(receiver, |
| 59 function, |
| 60 invoke_arguments, |
| 61 kNoArgumentNames)); |
| 62 if (result.IsError()) { |
| 63 Exceptions::PropagateError(Error::Cast(result)); |
| 64 } |
| 65 return result.raw(); |
| 66 } |
| 67 |
| 68 |
| 69 DEFINE_NATIVE_ENTRY(InvocationMirror_invoke, 4) { |
| 70 const Instance& receiver = Instance::CheckedHandle(arguments->NativeArgAt(0)); |
| 71 const String& fun_name = String::CheckedHandle(arguments->NativeArgAt(1)); |
| 72 const Array& fun_args_desc = Array::CheckedHandle(arguments->NativeArgAt(2)); |
| 73 const Array& fun_arguments = Array::CheckedHandle(arguments->NativeArgAt(3)); |
| 74 |
| 75 // Allocate a fixed-length array duplicating the original function arguments |
| 76 // and replace the receiver. |
| 77 const int num_arguments = fun_arguments.Length(); |
| 78 const Array& invoke_arguments = Array::Handle(Array::New(num_arguments)); |
| 79 invoke_arguments.SetAt(0, receiver); |
| 80 Object& arg = Object::Handle(); |
| 81 for (int i = 1; i < num_arguments; i++) { |
| 82 arg = fun_arguments.At(i); |
| 83 invoke_arguments.SetAt(i, arg); |
| 84 } |
| 85 // Resolve dynamic function given by name. |
| 86 const ArgumentsDescriptor args_desc(fun_args_desc); |
| 87 const Function& function = Function::Handle( |
| 88 Resolver::ResolveDynamic(receiver, |
| 89 fun_name, |
| 90 args_desc.Count(), |
| 91 args_desc.NamedCount())); |
| 92 if (function.IsNull()) { |
| 93 return InvokeNoSuchMethod(receiver, |
| 94 fun_name, |
| 95 fun_args_desc, |
| 96 invoke_arguments); |
| 97 } |
| 98 // TODO(regis): Simply call DartEntry::InvokeDynamic once it is modified to |
| 99 // take an arguments descriptor array and an arguments array. |
| 100 // Get the entrypoint corresponding to the instance function. This will |
| 101 // result in a compilation of the function if it is not already compiled. |
| 102 ASSERT(!function.IsNull()); |
| 103 if (!function.HasCode()) { |
| 104 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 105 if (!error.IsNull()) { |
| 106 Exceptions::PropagateError(error); |
| 107 } |
| 108 } |
| 109 // Set up arguments as GrowableArray. |
| 110 GrowableArray<const Object*> args(num_arguments); |
| 111 for (int i = 0; i < num_arguments; i++) { |
| 112 args.Add(&Object::ZoneHandle(invoke_arguments.At(i))); |
| 113 } |
| 114 // Now call the invoke stub which will invoke the function. |
| 115 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( |
| 116 StubCode::InvokeDartCodeEntryPoint()); |
| 117 const Code& code = Code::Handle(function.CurrentCode()); |
| 118 ASSERT(!code.IsNull()); |
| 119 const Context& context = Context::ZoneHandle( |
| 120 Isolate::Current()->object_store()->empty_context()); |
| 121 const Object& result = Object::Handle( |
| 122 entrypoint(code.EntryPoint(), fun_args_desc, args.data(), context)); |
| 123 if (result.IsError()) { |
| 124 Exceptions::PropagateError(Error::Cast(result)); |
| 125 } |
| 126 return result.raw(); |
| 127 } |
| 128 |
| 129 } // namespace dart |
| OLD | NEW |