Flutter Engine
The Flutter Engine
dart_api_impl.h
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_DART_API_IMPL_H_
6#define RUNTIME_VM_DART_API_IMPL_H_
7
8#include <memory>
9
10#include "vm/allocation.h"
11#include "vm/heap/safepoint.h"
12#include "vm/native_arguments.h"
13#include "vm/object.h"
14#include "vm/timeline.h"
15
16namespace dart {
17
18class ApiLocalScope;
19class ApiState;
20class FinalizablePersistentHandle;
21class LocalHandle;
22class PersistentHandle;
23class ReusableObjectHandleScope;
24class ThreadRegistry;
25
26const char* CanonicalFunction(const char* func);
27
28#define CURRENT_FUNC CanonicalFunction(__FUNCTION__)
29
30// Checks that the current isolate group is not nullptr.
31#define CHECK_ISOLATE_GROUP(isolate_group) \
32 do { \
33 if ((isolate_group) == nullptr) { \
34 FATAL( \
35 "%s expects there to be a current isolate group. Did you " \
36 "forget to call Dart_CreateIsolateGroup or Dart_EnterIsolate?", \
37 CURRENT_FUNC); \
38 } \
39 } while (0)
40
41// Checks that the current isolate is not nullptr.
42#define CHECK_ISOLATE(isolate) \
43 do { \
44 if ((isolate) == nullptr) { \
45 FATAL( \
46 "%s expects there to be a current isolate. Did you " \
47 "forget to call Dart_CreateIsolateGroup or Dart_EnterIsolate?", \
48 CURRENT_FUNC); \
49 } \
50 } while (0)
51
52// Checks that the current isolate is nullptr.
53#define CHECK_NO_ISOLATE(isolate) \
54 do { \
55 if ((isolate) != nullptr) { \
56 FATAL( \
57 "%s expects there to be no current isolate. Did you " \
58 "forget to call Dart_ExitIsolate?", \
59 CURRENT_FUNC); \
60 } \
61 } while (0)
62
63// Checks that the current isolate is not nullptr and that it has an API scope.
64#define CHECK_API_SCOPE(thread) \
65 do { \
66 Thread* tmpT = (thread); \
67 Isolate* tmpI = tmpT == nullptr ? nullptr : tmpT->isolate(); \
68 CHECK_ISOLATE(tmpI); \
69 if (tmpT->api_top_scope() == nullptr) { \
70 FATAL( \
71 "%s expects to find a current scope. Did you forget to call " \
72 "Dart_EnterScope?", \
73 CURRENT_FUNC); \
74 } \
75 } while (0);
76
77#define DARTSCOPE(thread) \
78 Thread* T = (thread); \
79 CHECK_API_SCOPE(T); \
80 TransitionNativeToVM transition(T); \
81 HANDLESCOPE(T);
82
83#define RETURN_TYPE_ERROR(zone, dart_handle, type) \
84 do { \
85 const Object& tmp = \
86 Object::Handle(zone, Api::UnwrapHandle((dart_handle))); \
87 if (tmp.IsNull()) { \
88 return Api::NewArgumentError("%s expects argument '%s' to be non-null.", \
89 CURRENT_FUNC, #dart_handle); \
90 } else if (tmp.IsError()) { \
91 return dart_handle; \
92 } \
93 return Api::NewArgumentError("%s expects argument '%s' to be of type %s.", \
94 CURRENT_FUNC, #dart_handle, #type); \
95 } while (0)
96
97#define RETURN_NULL_ERROR(parameter) \
98 return Api::NewError("%s expects argument '%s' to be non-null.", \
99 CURRENT_FUNC, #parameter)
100
101#define CHECK_NULL(parameter) \
102 if (parameter == nullptr) { \
103 RETURN_NULL_ERROR(parameter); \
104 }
105
106#define CHECK_LENGTH(length, max_elements) \
107 do { \
108 intptr_t len = (length); \
109 intptr_t max = (max_elements); \
110 if (len < 0 || len > max) { \
111 return Api::NewError( \
112 "%s expects argument '%s' to be in the range [0..%" Pd "].", \
113 CURRENT_FUNC, #length, max); \
114 } \
115 } while (0)
116
117#ifdef SUPPORT_TIMELINE
118#define API_TIMELINE_DURATION(thread) \
119 TimelineBeginEndScope api_tbes(thread, Timeline::GetAPIStream(), CURRENT_FUNC)
120
121#define API_TIMELINE_BEGIN_END(thread) \
122 TimelineBeginEndScope api_tbes(thread, Timeline::GetAPIStream(), CURRENT_FUNC)
123
124#else
125#define API_TIMELINE_DURATION(thread) \
126 do { \
127 } while (false)
128#define API_TIMELINE_BEGIN_END(thread) \
129 do { \
130 } while (false)
131#endif // SUPPORT_TIMELINE
132
133class Api : AllStatic {
134 public:
135 // Create on the stack to provide a new throw-safe api scope.
136 class Scope : public ThreadStackResource {
137 public:
140 }
142
143 private:
144 DISALLOW_COPY_AND_ASSIGN(Scope);
145 };
146
147 // Creates a new local handle.
148 static Dart_Handle NewHandle(Thread* thread, ObjectPtr raw);
149
150 // Unwraps the raw object from the handle.
151 static ObjectPtr UnwrapHandle(Dart_Handle object);
152
153// Unwraps a raw Type from the handle. The handle will be null if
154// the object was not of the requested Type.
155#define DECLARE_UNWRAP(Type) \
156 static const Type& Unwrap##Type##Handle(Zone* zone, Dart_Handle object);
158#undef DECLARE_UNWRAP
159
160 // Unwraps the raw object from the handle using a reused handle.
161 static const String& UnwrapStringHandle(
162 const ReusableObjectHandleScope& reused,
163 Dart_Handle object);
164 static const Instance& UnwrapInstanceHandle(
165 const ReusableObjectHandleScope& reused,
166 Dart_Handle object);
167
168 // Returns an Error handle if isolate is in an inconsistent state
169 // or there was an error while finalizing classes.
170 // Returns a Success handle when no error condition exists.
171 static Dart_Handle CheckAndFinalizePendingClasses(Thread* thread);
172
173 // Casts the internal Isolate* type to the external Dart_Isolate type.
174 static Dart_Isolate CastIsolate(Isolate* isolate);
175
176 // Casts the internal IsolateGroup* type to the external Dart_IsolateGroup
177 // type.
178 static Dart_IsolateGroup CastIsolateGroup(IsolateGroup* isolate_group);
179
180 // Gets the handle used to designate successful return.
181 static Dart_Handle Success() { return Api::True(); }
182
183 // Returns true if the handle holds a Smi.
184 static bool IsSmi(Dart_Handle handle) {
185 // Important: we do not require current thread to be in VM state because
186 // we do not dereference the handle.
187 ObjectPtr raw = *(reinterpret_cast<ObjectPtr*>(handle));
188 return !raw->IsHeapObject();
189 }
190
191 // Returns the value of a Smi.
192 static intptr_t SmiValue(Dart_Handle handle) {
193 // Important: we do not require current thread to be in VM state because
194 // we do not dereference the handle.
195 ObjectPtr value = *(reinterpret_cast<ObjectPtr*>(handle));
196 return Smi::Value(static_cast<SmiPtr>(value));
197 }
198
199 // Returns true if the handle holds a Dart Instance.
200 static bool IsInstance(Dart_Handle handle) {
201 return !IsInternalOnlyClassId(ClassId(handle));
202 }
203
204 // Returns true if the handle is non-dangling.
205 static bool IsValid(Dart_Handle handle);
206
207 // Returns true if the handle holds an Error.
208 static bool IsError(Dart_Handle handle) {
209 return IsErrorClassId(ClassId(handle));
210 }
211
212 static intptr_t ClassId(Dart_Handle handle) {
213 ObjectPtr raw = UnwrapHandle(handle);
214 if (!raw->IsHeapObject()) {
215 return kSmiCid;
216 }
217 return raw->GetClassId();
218 }
219
220 // Generates a handle used to designate an error return.
221 static Dart_Handle NewError(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
222 static Dart_Handle NewArgumentError(const char* format, ...)
223 PRINTF_ATTRIBUTE(1, 2);
224
225 // Gets a handle to Null.
226 static Dart_Handle Null() { return null_handle_; }
227
228 // Gets a handle to True.
229 static Dart_Handle True() { return true_handle_; }
230
231 // Gets a handle to False.
232 static Dart_Handle False() { return false_handle_; }
233
234 // Gets a handle to EmptyString.
235 static Dart_Handle EmptyString() { return empty_string_handle_; }
236
237 // Gets the handle which holds the pre-created acquired error object.
238 static Dart_Handle NoCallbacksError() { return no_callbacks_error_handle_; }
239
240 // Gets the handle for unwind-is-in-progress error.
242 return unwind_in_progress_error_handle_;
243 }
244
245 static bool IsProtectedHandle(Dart_Handle object) {
246 if (object == nullptr) return false;
247 return (object == true_handle_) || (object == false_handle_) ||
248 (object == null_handle_) || (object == empty_string_handle_) ||
249 (object == no_callbacks_error_handle_) ||
250 (object == unwind_in_progress_error_handle_);
251 }
252
253 // Retrieves the top ApiLocalScope.
254 static ApiLocalScope* TopScope(Thread* thread);
255
256 // Performs initialization needed by the API.
257 static void Init();
258
259 // Allocates handles for objects in the VM isolate.
260 static void InitHandles();
261
262 // Cleanup
263 static void Cleanup();
264
265 // Helper function to get the peer value of an external string object.
267 int arg_index,
268 void** peer);
269
270 // Helper function to get the native field from a native receiver argument.
271 static bool GetNativeReceiver(NativeArguments* args, intptr_t* value);
272
273 // Helper function to get the boolean value of a Bool native argument.
275 int arg_index,
276 bool* value);
277
278 // Helper function to get the integer value of a Integer native argument.
280 int arg_index,
281 int64_t* value);
282
283 // Helper function to get the double value of a Double native argument.
285 int arg_index,
286 double* value);
287
288 // Helper function to get the native fields of an Instance native argument.
290 int arg_index,
291 int num_fields,
292 intptr_t* field_values);
293
294 // Helper function to set the return value of native functions.
296 args->SetReturnUnsafe(UnwrapHandle(retval));
297 }
298 static void SetSmiReturnValue(NativeArguments* args, intptr_t retval) {
299 args->SetReturnUnsafe(Smi::New(retval));
300 }
301 static void SetIntegerReturnValue(NativeArguments* args, int64_t retval) {
302 args->SetReturnUnsafe(Integer::New(retval));
303 }
304 static void SetDoubleReturnValue(NativeArguments* args, double retval) {
305 args->SetReturnUnsafe(Double::New(retval));
306 }
309
310 static StringPtr GetEnvironmentValue(Thread* thread, const String& name);
311
312 static bool IsFfiEnabled() { return FLAG_enable_ffi; }
313
314 private:
315 static Dart_Handle InitNewHandle(Thread* thread, ObjectPtr raw);
316
317 static StringPtr CallEnvironmentCallback(Thread* thread, const String& name);
318
319 // Thread local key used by the API. Currently holds the current
320 // ApiNativeScope if any.
321 static ThreadLocalKey api_native_key_;
322 static Dart_Handle true_handle_;
323 static Dart_Handle false_handle_;
324 static Dart_Handle null_handle_;
325 static Dart_Handle empty_string_handle_;
326 static Dart_Handle no_callbacks_error_handle_;
327 static Dart_Handle unwind_in_progress_error_handle_;
328
329 friend class ApiNativeScope;
330};
331
332// Start a scope in which no Dart API call backs are allowed.
333#define START_NO_CALLBACK_SCOPE(thread) thread->IncrementNoCallbackScopeDepth()
334
335// End a no Dart API call backs Scope.
336#define END_NO_CALLBACK_SCOPE(thread) \
337 do { \
338 thread->DecrementNoCallbackScopeDepth(); \
339 if (thread->no_callback_scope_depth() == 0) { \
340 thread->heap()->CheckExternalGC(thread); \
341 } \
342 } while (false)
343
344#define CHECK_CALLBACK_STATE(thread) \
345 if (thread->no_callback_scope_depth() != 0) { \
346 return reinterpret_cast<Dart_Handle>(Api::NoCallbacksError()); \
347 } \
348 if (thread->is_unwind_in_progress()) { \
349 return reinterpret_cast<Dart_Handle>(Api::UnwindInProgressError()); \
350 }
351
352#define ASSERT_CALLBACK_STATE(thread) \
353 ASSERT(thread->no_callback_scope_depth() == 0)
354
355class IsolateGroupSource;
356
357// Creates a new isolate from [source] (which should come from an existing
358// isolate).
359Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
360 const char* name,
361 char** error);
362
363} // namespace dart.
364
365#endif // RUNTIME_VM_DART_API_IMPL_H_
#define CLASS_LIST_FOR_HANDLES(V)
Definition: class_id.h:193
Scope(Thread *thread)
static Dart_Handle Success()
static void SetDoubleReturnValue(NativeArguments *args, double retval)
static bool IsInstance(Dart_Handle handle)
static Dart_Handle NewHandle(Thread *thread, ObjectPtr raw)
static void SetReturnValue(NativeArguments *args, Dart_Handle retval)
static Dart_Handle UnwindInProgressError()
static bool GetNativeFieldsOfArgument(NativeArguments *args, int arg_index, int num_fields, intptr_t *field_values)
static Dart_Isolate CastIsolate(Isolate *isolate)
static ApiLocalScope * TopScope(Thread *thread)
static ObjectPtr UnwrapHandle(Dart_Handle object)
static bool GetNativeBooleanArgument(NativeArguments *args, int arg_index, bool *value)
static StringPtr GetEnvironmentValue(Thread *thread, const String &name)
static Dart_Handle False()
static intptr_t ClassId(Dart_Handle handle)
static Dart_Handle static Dart_Handle NewArgumentError(const char *format,...) PRINTF_ATTRIBUTE(1
static Dart_IsolateGroup CastIsolateGroup(IsolateGroup *isolate_group)
static bool StringGetPeerHelper(NativeArguments *args, int arg_index, void **peer)
static void Init()
static Dart_Handle static Dart_Handle static Dart_Handle Null()
static void InitHandles()
static bool GetNativeDoubleArgument(NativeArguments *args, int arg_index, double *value)
static const Instance & UnwrapInstanceHandle(const ReusableObjectHandleScope &reused, Dart_Handle object)
static bool IsFfiEnabled()
static Dart_Handle EmptyString()
static bool IsProtectedHandle(Dart_Handle object)
static bool GetNativeIntegerArgument(NativeArguments *args, int arg_index, int64_t *value)
static const String & UnwrapStringHandle(const ReusableObjectHandleScope &reused, Dart_Handle object)
static void SetWeakHandleReturnValue(NativeArguments *args, Dart_WeakPersistentHandle retval)
static void SetSmiReturnValue(NativeArguments *args, intptr_t retval)
static Dart_Handle True()
static bool IsValid(Dart_Handle handle)
static intptr_t SmiValue(Dart_Handle handle)
static bool GetNativeReceiver(NativeArguments *args, intptr_t *value)
static bool IsSmi(Dart_Handle handle)
static Dart_Handle NoCallbacksError()
static void Cleanup()
static void SetIntegerReturnValue(NativeArguments *args, int64_t retval)
static bool IsError(Dart_Handle handle)
static Dart_Handle NewError(const char *format,...) PRINTF_ATTRIBUTE(1
static Dart_Handle CheckAndFinalizePendingClasses(Thread *thread)
static DoublePtr New(double d, Heap::Space space=Heap::kNew)
Definition: object.cc:23402
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
Definition: object.cc:22984
intptr_t GetClassId() const
Definition: raw_object.h:885
static SmiPtr New(intptr_t value)
Definition: object.h:10006
intptr_t Value() const
Definition: object.h:9990
void EnterApiScope()
Definition: thread.cc:1301
void ExitApiScope()
Definition: thread.cc:1314
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
struct _Dart_IsolateGroup * Dart_IsolateGroup
Definition: dart_api.h:89
struct _Dart_WeakPersistentHandle * Dart_WeakPersistentHandle
Definition: dart_api.h:260
#define DECLARE_UNWRAP(Type)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
uint32_t uint32_t * format
Definition: dart_vm.cc:33
const char *const name
const char * CanonicalFunction(const char *func)
bool IsErrorClassId(intptr_t index)
Definition: class_id.h:321
pthread_key_t ThreadLocalKey
bool IsInternalOnlyClassId(intptr_t index)
Definition: class_id.h:299
Isolate * CreateWithinExistingIsolateGroup(IsolateGroup *group, const char *name, char **error)
#define PRINTF_ATTRIBUTE(string_index, first_to_check)
Definition: globals.h:697