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