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
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_DART_ENTRY_H_
6#define RUNTIME_VM_DART_ENTRY_H_
7
8#include "vm/allocation.h"
9#include "vm/growable_array.h"
10#include "vm/object.h"
11#include "vm/raw_object.h"
12
13namespace dart {
14
15// Forward declarations.
16class Array;
17class Closure;
18class Function;
19class Instance;
20class Integer;
21class Library;
22class Object;
23class String;
24
25// An arguments descriptor array consists of the type argument vector length (0
26// if none); total argument count (not counting type argument vector); total
27// arguments size (not counting type argument vector); the positional argument
28// count; a sequence of (name, position) pairs, sorted by name, for each named
29// optional argument; and a terminating null to simplify iterating in generated
30// code.
31class ArgumentsDescriptor : public ValueObject {
32 public:
33 explicit ArgumentsDescriptor(const Array& array);
34
35 // Accessors.
36 intptr_t TypeArgsLen() const; // 0 if no type argument vector is passed.
37 intptr_t FirstArgIndex() const { return TypeArgsLen() > 0 ? 1 : 0; }
38 intptr_t CountWithTypeArgs() const { return FirstArgIndex() + Count(); }
39 intptr_t Count() const; // Excluding type arguments vector.
40 intptr_t Size() const; // Excluding type arguments vector.
41 intptr_t SizeWithTypeArgs() const { return FirstArgIndex() + Size(); }
42 intptr_t PositionalCount() const; // Excluding type arguments vector.
43 intptr_t NamedCount() const { return Count() - PositionalCount(); }
44 StringPtr NameAt(intptr_t i) const;
45 intptr_t PositionAt(intptr_t i) const;
46 bool MatchesNameAt(intptr_t i, const String& other) const;
47 // Returns array of argument names in the arguments order.
48 ArrayPtr GetArgumentNames() const;
49 void PrintTo(BaseTextBuffer* buffer) const;
50 const char* ToCString() const;
51
52 // Generated code support.
53 static intptr_t type_args_len_offset() {
54 return Array::element_offset(kTypeArgsLenIndex);
55 }
56
57 static intptr_t count_offset() { return Array::element_offset(kCountIndex); }
58
59 static intptr_t size_offset() { return Array::element_offset(kSizeIndex); }
60
61 static intptr_t positional_count_offset() {
62 return Array::element_offset(kPositionalCountIndex);
63 }
64
65 static intptr_t first_named_entry_offset() {
66 return Array::element_offset(kFirstNamedEntryIndex);
67 }
68
69 static intptr_t name_offset() { return kNameOffset * kWordSize; }
70 static intptr_t position_offset() { return kPositionOffset * kWordSize; }
71 static intptr_t named_entry_size() { return kNamedEntrySize * kWordSize; }
72
73 // Constructs an argument descriptor where all arguments are boxed and
74 // therefore number of parameters equals parameter size.
75 //
76 // Right now this is for example the case for all closure functions.
77 // Functions marked as entry-points may also be created by NewUnboxed because
78 // we rely that TFA will mark the arguments as nullable for such cases.
79 static ArrayPtr NewBoxed(intptr_t type_args_len,
80 intptr_t num_arguments,
81 const Array& optional_arguments_names,
82 Heap::Space space = Heap::kOld) {
83 return New(type_args_len, num_arguments, num_arguments,
84 optional_arguments_names, space);
85 }
86
87 // Allocate and return an arguments descriptor. The first
88 // (num_arguments - optional_arguments_names.Length()) arguments are
89 // positional and the remaining ones are named optional arguments.
90 // The presence of a type argument vector as first argument (not counted in
91 // num_arguments) is indicated by a non-zero type_args_len.
92 static ArrayPtr New(intptr_t type_args_len,
93 intptr_t num_arguments,
94 intptr_t size_arguments,
95 const Array& optional_arguments_names,
96 Heap::Space space = Heap::kOld);
97
98 // Constructs an argument descriptor where all arguments are boxed and
99 // therefore number of parameters equals parameter size.
100 //
101 // Right now this is for example the case for all closure functions.
102 static ArrayPtr NewBoxed(intptr_t type_args_len,
103 intptr_t num_arguments,
104 Heap::Space space = Heap::kOld) {
105 return New(type_args_len, num_arguments, num_arguments, space);
106 }
107
108 // Allocate and return an arguments descriptor that has no optional
109 // arguments. All arguments are positional. The presence of a type argument
110 // vector as first argument (not counted in num_arguments) is indicated
111 // by a non-zero type_args_len.
112 static ArrayPtr New(intptr_t type_args_len,
113 intptr_t num_arguments,
114 intptr_t size_arguments,
115 Heap::Space space = Heap::kOld);
116
117 // Initialize the preallocated fixed length arguments descriptors cache.
118 static void Init();
119
120 // Clear the preallocated fixed length arguments descriptors cache.
121 static void Cleanup();
122
123 enum { kCachedDescriptorCount = 32 };
124
125 private:
126 // Absolute indices into the array.
127 // Keep these in sync with the constants in invocation_mirror_patch.dart.
128 enum {
129 kTypeArgsLenIndex,
130 kCountIndex,
131 kSizeIndex,
132 kPositionalCountIndex,
133 kFirstNamedEntryIndex,
134 };
135
136 private:
137 // Relative indexes into each named argument entry.
138 enum {
139 kNameOffset,
140 // The least significant bit of the entry in 'kPositionOffset' (second
141 // least-significant after Smi-encoding) holds the strong-mode checking bit
142 // for the named argument.
143 kPositionOffset,
144 kNamedEntrySize,
145 };
146
147 public:
148 static intptr_t LengthFor(intptr_t num_named_arguments) {
149 // Add 1 for the terminating null.
150 return kFirstNamedEntryIndex + (kNamedEntrySize * num_named_arguments) + 1;
151 }
152
153 static ArrayPtr NewNonCached(intptr_t type_args_len,
154 intptr_t num_arguments,
155 intptr_t size_arguments,
156 bool canonicalize,
157 Heap::Space space);
158
159 // Used by Simulator to parse argument descriptors.
160 static intptr_t name_index(intptr_t index) {
161 return kFirstNamedEntryIndex + (index * kNamedEntrySize) + kNameOffset;
162 }
163
164 static intptr_t position_index(intptr_t index) {
165 return kFirstNamedEntryIndex + (index * kNamedEntrySize) + kPositionOffset;
166 }
167
168 const Array& array_;
169
170 // A cache of VM heap allocated arguments descriptors.
171 static ArrayPtr cached_args_descriptors_[kCachedDescriptorCount];
172
173 friend class SnapshotReader;
174 friend class SnapshotWriter;
175 friend class Serializer;
176 friend class Deserializer;
177 friend class Interpreter;
178 friend class InterpreterHelpers;
179 friend class Simulator;
180 friend class SimulatorHelpers;
181 DISALLOW_COPY_AND_ASSIGN(ArgumentsDescriptor);
182};
183
184// DartEntry abstracts functionality needed to resolve dart functions
185// and invoke them from C++.
186class DartEntry : public AllStatic {
187 public:
188 // Invokes the specified instance function or static function.
189 // The first argument of an instance function is the receiver.
190 // On success, returns a RawInstance. On failure, a RawError.
191 // This is used when there is no type argument vector and
192 // no named arguments in the call.
193 static ObjectPtr InvokeFunction(const Function& function,
194 const Array& arguments);
195
196 // Invokes the specified code as if it was a Dart function.
197 // On success, returns a RawInstance. On failure, a RawError.
198 static ObjectPtr InvokeCode(const Code& code,
199 const Array& arguments_descriptor,
200 const Array& arguments,
201 Thread* thread);
202
203 // Invokes the specified instance, static, or closure function.
204 // On success, returns a RawInstance. On failure, a RawError.
205 static ObjectPtr InvokeFunction(
206 const Function& function,
207 const Array& arguments,
208 const Array& arguments_descriptor,
209 uword current_sp = OSThread::GetCurrentStackPointer());
210
211 // Resolves the first argument to a callable compatible with the arguments.
212 //
213 // If no errors occur, the first argument is changed to be either the resolved
214 // callable or, if Function::null() is returned, an appropriate target for
215 // invoking noSuchMethod.
216 //
217 // On success, returns a RawFunction. On failure, a RawError.
218 static ObjectPtr ResolveCallable(const Array& arguments,
219 const Array& arguments_descriptor);
220
221 // Invokes the function returned by ResolveCallable.
222 //
223 // On success, returns a RawInstance. On failure, a RawError.
224 static ObjectPtr InvokeCallable(const Function& callable_function,
225 const Array& arguments,
226 const Array& arguments_descriptor);
227
228 // Invokes the closure object given as the first argument.
229 // On success, returns a RawInstance. On failure, a RawError.
230 // This is used when there is no type argument vector and
231 // no named arguments in the call.
232 static ObjectPtr InvokeClosure(const Array& arguments);
233
234 // Invokes the closure object given as the first argument.
235 // On success, returns a RawInstance. On failure, a RawError.
236 static ObjectPtr InvokeClosure(const Array& arguments,
237 const Array& arguments_descriptor);
238
239 // Invokes the noSuchMethod instance function on the receiver.
240 // On success, returns a RawInstance. On failure, a RawError.
241 static ObjectPtr InvokeNoSuchMethod(const Instance& receiver,
242 const String& target_name,
243 const Array& arguments,
244 const Array& arguments_descriptor);
245};
246
247// Utility functions to call from VM into Dart bootstrap libraries.
248// Each may return an exception object.
249class DartLibraryCalls : public AllStatic {
250 public:
251 // On success, returns a RawInstance. On failure, a RawError.
252 static ObjectPtr InstanceCreate(const Library& library,
253 const String& exception_name,
254 const String& constructor_name,
255 const Array& arguments);
256
257 // On success, returns a RawInstance. On failure, a RawError.
258 static ObjectPtr ToString(const Instance& receiver);
259
260 // On success, returns a RawInstance. On failure, a RawError.
261 static ObjectPtr HashCode(const Instance& receiver);
262
263 // On success, returns a RawInstance. On failure, a RawError.
264 static ObjectPtr Equals(const Instance& left, const Instance& right);
265
266 // On success, returns a RawInstance. On failure, a RawError.
267 static ObjectPtr IdentityHashCode(const Instance& object);
268
269 // Returns the handler if one has been registered for this port id.
270 static ObjectPtr LookupHandler(Dart_Port port_id);
271
272 // Returns null on success, a RawError on failure.
273 static ObjectPtr HandleMessage(const Object& handler,
274 const Instance& dart_message);
275
276 // Returns null on success, a RawError on failure.
277 static ObjectPtr DrainMicrotaskQueue();
278
279 // Ensures that the isolate's _pendingImmediateCallback is set to
280 // _startMicrotaskLoop from dart:async.
281 // Returns null on success, a RawError on failure.
282 static ObjectPtr EnsureScheduleImmediate();
283
284 // map[key] = value;
285 //
286 // Returns null on success, a RawError on failure.
287 static ObjectPtr MapSetAt(const Instance& map,
288 const Instance& key,
289 const Instance& value);
290};
291
292} // namespace dart
293
294#endif // RUNTIME_VM_DART_ENTRY_H_
295