| 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/dart_entry.h" | 5 #include "vm/dart_entry.h" |
| 6 | 6 |
| 7 #include "vm/code_generator.h" | 7 #include "vm/code_generator.h" |
| 8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
| 9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
| 10 #include "vm/resolver.h" | 10 #include "vm/resolver.h" |
| 11 #include "vm/stub_code.h" | 11 #include "vm/stub_code.h" |
| 12 #include "vm/symbols.h" | 12 #include "vm/symbols.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 RawObject* DartEntry::InvokeDynamic(const Function& function, | 16 RawObject* DartEntry::InvokeDynamic(const Function& function, |
| 17 const Array& arguments) { | 17 const Array& arguments) { |
| 18 const Array& arg_desc = | 18 const Array& arg_desc = |
| 19 Array::Handle(ArgumentsDescriptor::New(arguments.Length())); | 19 Array::Handle(ArgumentsDescriptor::New(arguments.Length())); |
| 20 return InvokeDynamic(function, arguments, arg_desc); | 20 return InvokeDynamic(function, arguments, arg_desc); |
| 21 } | 21 } |
| 22 | 22 |
| 23 | 23 |
| 24 RawObject* DartEntry::InvokeDynamic(const Function& function, | 24 RawObject* DartEntry::InvokeDynamic(const Function& function, |
| 25 const Array& arguments, | 25 const Array& arguments, |
| 26 const Array& arg_descriptor) { | 26 const Array& arguments_descriptor) { |
| 27 // Get the entrypoint corresponding to the function specified, this | 27 // Get the entrypoint corresponding to the function specified, this |
| 28 // will result in a compilation of the function if it is not already | 28 // will result in a compilation of the function if it is not already |
| 29 // compiled. | 29 // compiled. |
| 30 if (!function.HasCode()) { | 30 if (!function.HasCode()) { |
| 31 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 31 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 32 if (!error.IsNull()) { | 32 if (!error.IsNull()) { |
| 33 return error.raw(); | 33 return error.raw(); |
| 34 } | 34 } |
| 35 } | 35 } |
| 36 | 36 |
| 37 // Now Call the invoke stub which will invoke the dart function. | 37 // Now Call the invoke stub which will invoke the dart function. |
| 38 invokestub entrypoint = reinterpret_cast<invokestub>( | 38 invokestub entrypoint = reinterpret_cast<invokestub>( |
| 39 StubCode::InvokeDartCodeEntryPoint()); | 39 StubCode::InvokeDartCodeEntryPoint()); |
| 40 const Context& context = | 40 const Context& context = |
| 41 Context::ZoneHandle(Isolate::Current()->object_store()->empty_context()); | 41 Context::ZoneHandle(Isolate::Current()->object_store()->empty_context()); |
| 42 ASSERT(context.isolate() == Isolate::Current()); | 42 ASSERT(context.isolate() == Isolate::Current()); |
| 43 const Code& code = Code::Handle(function.CurrentCode()); | 43 const Code& code = Code::Handle(function.CurrentCode()); |
| 44 ASSERT(!code.IsNull()); | 44 ASSERT(!code.IsNull()); |
| 45 return entrypoint(code.EntryPoint(), arg_descriptor, arguments, context); | 45 return entrypoint(code.EntryPoint(), |
| 46 arguments_descriptor, |
| 47 arguments, |
| 48 context); |
| 46 } | 49 } |
| 47 | 50 |
| 48 | 51 |
| 49 RawObject* DartEntry::InvokeStatic(const Function& function, | 52 RawObject* DartEntry::InvokeStatic(const Function& function, |
| 50 const Array& arguments) { | 53 const Array& arguments) { |
| 51 const Array& arg_desc = | 54 const Array& arguments_descriptor = |
| 52 Array::Handle(ArgumentsDescriptor::New(arguments.Length())); | 55 Array::Handle(ArgumentsDescriptor::New(arguments.Length())); |
| 53 return InvokeStatic(function, arguments, arg_desc); | 56 return InvokeStatic(function, arguments, arguments_descriptor); |
| 54 } | 57 } |
| 55 | 58 |
| 56 | 59 |
| 57 RawObject* DartEntry::InvokeStatic(const Function& function, | 60 RawObject* DartEntry::InvokeStatic(const Function& function, |
| 58 const Array& arguments, | 61 const Array& arguments, |
| 59 const Array& arg_descriptor) { | 62 const Array& arguments_descriptor) { |
| 60 // Get the entrypoint corresponding to the function specified, this | 63 // Get the entrypoint corresponding to the function specified, this |
| 61 // will result in a compilation of the function if it is not already | 64 // will result in a compilation of the function if it is not already |
| 62 // compiled. | 65 // compiled. |
| 63 ASSERT(!function.IsNull()); | 66 ASSERT(!function.IsNull()); |
| 64 if (!function.HasCode()) { | 67 if (!function.HasCode()) { |
| 65 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 68 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 66 if (!error.IsNull()) { | 69 if (!error.IsNull()) { |
| 67 return error.raw(); | 70 return error.raw(); |
| 68 } | 71 } |
| 69 } | 72 } |
| 70 // Now Call the invoke stub which will invoke the dart function. | 73 // Now Call the invoke stub which will invoke the dart function. |
| 71 invokestub entrypoint = reinterpret_cast<invokestub>( | 74 invokestub entrypoint = reinterpret_cast<invokestub>( |
| 72 StubCode::InvokeDartCodeEntryPoint()); | 75 StubCode::InvokeDartCodeEntryPoint()); |
| 73 const Context& context = | 76 const Context& context = |
| 74 Context::ZoneHandle(Isolate::Current()->object_store()->empty_context()); | 77 Context::ZoneHandle(Isolate::Current()->object_store()->empty_context()); |
| 75 ASSERT(context.isolate() == Isolate::Current()); | 78 ASSERT(context.isolate() == Isolate::Current()); |
| 76 const Code& code = Code::Handle(function.CurrentCode()); | 79 const Code& code = Code::Handle(function.CurrentCode()); |
| 77 ASSERT(!code.IsNull()); | 80 ASSERT(!code.IsNull()); |
| 78 return entrypoint(code.EntryPoint(), arg_descriptor, arguments, context); | 81 return entrypoint(code.EntryPoint(), |
| 82 arguments_descriptor, |
| 83 arguments, |
| 84 context); |
| 79 } | 85 } |
| 80 | 86 |
| 81 | 87 |
| 82 RawObject* DartEntry::InvokeClosure(const Instance& closure, | 88 RawObject* DartEntry::InvokeClosure(const Instance& closure, |
| 83 const Array& arguments) { | 89 const Array& arguments) { |
| 84 const Array& arg_desc = | 90 const Array& arguments_descriptor = |
| 85 Array::Handle(ArgumentsDescriptor::New(arguments.Length())); | 91 Array::Handle(ArgumentsDescriptor::New(arguments.Length())); |
| 86 return InvokeClosure(closure, arguments, arg_desc); | 92 return InvokeClosure(closure, arguments, arguments_descriptor); |
| 87 } | 93 } |
| 88 | 94 |
| 89 | 95 |
| 90 RawObject* DartEntry::InvokeClosure(const Instance& instance, | 96 RawObject* DartEntry::InvokeClosure(const Instance& instance, |
| 91 const Array& arguments, | 97 const Array& arguments, |
| 92 const Array& arg_descriptor) { | 98 const Array& arguments_descriptor) { |
| 93 ASSERT(instance.raw() == arguments.At(0)); | 99 ASSERT(instance.raw() == arguments.At(0)); |
| 94 // Get the entrypoint corresponding to the closure function or to the call | 100 // Get the entrypoint corresponding to the closure function or to the call |
| 95 // method of the instance. This will result in a compilation of the function | 101 // method of the instance. This will result in a compilation of the function |
| 96 // if it is not already compiled. | 102 // if it is not already compiled. |
| 97 Function& function = Function::Handle(); | 103 Function& function = Function::Handle(); |
| 98 Context& context = Context::Handle(); | 104 Context& context = Context::Handle(); |
| 99 if (!instance.IsCallable(&function, &context)) { | 105 if (instance.IsCallable(&function, &context)) { |
| 100 // Set up arguments to include the receiver as the first argument. | 106 // Only invoke the function if its arguments are compatible. |
| 101 const String& call_symbol = String::Handle(Symbols::Call()); | 107 const ArgumentsDescriptor args_desc(arguments_descriptor); |
| 102 const Object& null_object = Object::Handle(); | 108 if (function.AreValidArgumentCounts(args_desc.Count(), |
| 103 const Array& dart_arguments = Array::Handle(Array::New(4)); | 109 args_desc.NamedCount(), |
| 104 dart_arguments.SetAt(0, instance); | 110 NULL)) { |
| 105 dart_arguments.SetAt(1, call_symbol); | 111 if (!function.HasCode()) { |
| 106 dart_arguments.SetAt(2, arguments); // Includes instance. | 112 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 107 dart_arguments.SetAt(3, null_object); // TODO(regis): Provide names. | 113 if (!error.IsNull()) { |
| 108 // If a function "call" with different arguments exists, it will have been | 114 return error.raw(); |
| 109 // invoked above, so no need to handle this case here. | 115 } |
| 110 Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); | 116 } |
| 111 UNREACHABLE(); | 117 // Now call the invoke stub which will invoke the closure function or |
| 112 return Object::null(); | 118 // 'call' function. |
| 113 } | 119 // The closure or non-closure object (receiver) is passed as implicit |
| 114 ASSERT(!function.IsNull()); | 120 // first argument. It is already included in the arguments array. |
| 115 if (!function.HasCode()) { | 121 invokestub entrypoint = reinterpret_cast<invokestub>( |
| 116 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 122 StubCode::InvokeDartCodeEntryPoint()); |
| 117 if (!error.IsNull()) { | 123 ASSERT(context.isolate() == Isolate::Current()); |
| 118 return error.raw(); | 124 const Code& code = Code::Handle(function.CurrentCode()); |
| 125 ASSERT(!code.IsNull()); |
| 126 return entrypoint(code.EntryPoint(), |
| 127 arguments_descriptor, |
| 128 arguments, |
| 129 context); |
| 119 } | 130 } |
| 120 } | 131 } |
| 121 // Now call the invoke stub which will invoke the closure. | 132 // There is no compatible 'call' method, so invoke noSuchMethod. |
| 122 invokestub entrypoint = reinterpret_cast<invokestub>( | 133 return InvokeNoSuchMethod(instance, |
| 123 StubCode::InvokeDartCodeEntryPoint()); | 134 String::Handle(Symbols::Call()), |
| 124 ASSERT(context.isolate() == Isolate::Current()); | 135 arguments, |
| 125 const Code& code = Code::Handle(function.CurrentCode()); | 136 arguments_descriptor); |
| 126 ASSERT(!code.IsNull()); | 137 } |
| 127 return entrypoint(code.EntryPoint(), arg_descriptor, arguments, context); | 138 |
| 139 |
| 140 RawObject* DartEntry::InvokeNoSuchMethod(const Instance& receiver, |
| 141 const String& target_name, |
| 142 const Array& arguments, |
| 143 const Array& arguments_descriptor) { |
| 144 ASSERT(receiver.raw() == arguments.At(0)); |
| 145 // Allocate an InvocationMirror object. |
| 146 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 147 const String& invocation_mirror_name = |
| 148 String::Handle(Symbols::InvocationMirror()); |
| 149 Class& invocation_mirror_class = |
| 150 Class::Handle(core_lib.LookupClassAllowPrivate(invocation_mirror_name)); |
| 151 ASSERT(!invocation_mirror_class.IsNull()); |
| 152 const String& allocation_function_name = |
| 153 String::Handle(Symbols::AllocateInvocationMirror()); |
| 154 const Function& allocation_function = Function::Handle( |
| 155 Resolver::ResolveStaticByName(invocation_mirror_class, |
| 156 allocation_function_name, |
| 157 Resolver::kIsQualified)); |
| 158 ASSERT(!allocation_function.IsNull()); |
| 159 const int kNumAllocationArgs = 3; |
| 160 const Array& allocation_args = Array::Handle(Array::New(kNumAllocationArgs)); |
| 161 allocation_args.SetAt(0, target_name); |
| 162 allocation_args.SetAt(1, arguments_descriptor); |
| 163 allocation_args.SetAt(2, arguments); |
| 164 const Object& invocation_mirror = Object::Handle( |
| 165 InvokeStatic(allocation_function, allocation_args)); |
| 166 |
| 167 // Now use the invocation mirror object and invoke NoSuchMethod. |
| 168 const String& function_name = String::Handle(Symbols::NoSuchMethod()); |
| 169 const int kNumArguments = 2; |
| 170 const int kNumNamedArguments = 0; |
| 171 const Function& function = Function::Handle( |
| 172 Resolver::ResolveDynamic(receiver, |
| 173 function_name, |
| 174 kNumArguments, |
| 175 kNumNamedArguments)); |
| 176 ASSERT(!function.IsNull()); |
| 177 const Array& args = Array::Handle(Array::New(kNumArguments)); |
| 178 args.SetAt(0, receiver); |
| 179 args.SetAt(1, invocation_mirror); |
| 180 return InvokeDynamic(function, args); |
| 128 } | 181 } |
| 129 | 182 |
| 130 | 183 |
| 131 ArgumentsDescriptor::ArgumentsDescriptor(const Array& array) | 184 ArgumentsDescriptor::ArgumentsDescriptor(const Array& array) |
| 132 : array_(array) { | 185 : array_(array) { |
| 133 } | 186 } |
| 134 | 187 |
| 135 | 188 |
| 136 intptr_t ArgumentsDescriptor::Count() const { | 189 intptr_t ArgumentsDescriptor::Count() const { |
| 137 return Smi::CheckedHandle(array_.At(kCountIndex)).Value(); | 190 return Smi::CheckedHandle(array_.At(kCountIndex)).Value(); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 const String& func_name = String::Handle(Field::GetterName(field_name)); | 449 const String& func_name = String::Handle(Field::GetterName(field_name)); |
| 397 const Function& func = Function::Handle(cls.LookupDynamicFunction(func_name)); | 450 const Function& func = Function::Handle(cls.LookupDynamicFunction(func_name)); |
| 398 ASSERT(!func.IsNull()); | 451 ASSERT(!func.IsNull()); |
| 399 const Array& args = Array::Handle(Array::New(1)); | 452 const Array& args = Array::Handle(Array::New(1)); |
| 400 args.SetAt(0, port); | 453 args.SetAt(0, port); |
| 401 return DartEntry::InvokeDynamic(func, args); | 454 return DartEntry::InvokeDynamic(func, args); |
| 402 } | 455 } |
| 403 | 456 |
| 404 | 457 |
| 405 } // namespace dart | 458 } // namespace dart |
| OLD | NEW |