Flutter Engine
The Flutter Engine
native_api_impl.cc
Go to the documentation of this file.
1// Copyright (c) 2013, 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 <functional>
6
8
9#include "platform/assert.h"
10#include "platform/utils.h"
11#include "vm/dart_api_impl.h"
12#include "vm/dart_api_message.h"
13#include "vm/dart_api_state.h"
14#include "vm/message.h"
15#include "vm/message_snapshot.h"
17#include "vm/port.h"
18#include "vm/service_isolate.h"
19
20namespace dart {
21
22// --- Message sending/receiving from native code ---
23
25 public:
26 explicit IsolateLeaveScope(Isolate* current_isolate)
27 : saved_isolate_(current_isolate) {
28 if (current_isolate != nullptr) {
29 ASSERT(current_isolate == Isolate::Current());
31 }
32 }
34 if (saved_isolate_ != nullptr) {
35 Dart_Isolate I = reinterpret_cast<Dart_Isolate>(saved_isolate_);
37 }
38 }
39
40 private:
41 Isolate* saved_isolate_;
42
43 DISALLOW_COPY_AND_ASSIGN(IsolateLeaveScope);
44};
45
48 std::unique_ptr<Message> msg = WriteApiMessage(
49 zone.GetZone(), message, port_id, Message::kNormalPriority);
50
51 if (msg == nullptr) {
52 return false;
53 }
54
55 // Post the message at the given port.
56 return PortMap::PostMessage(std::move(msg));
57}
58
60 return PostCObjectHelper(port_id, message);
61}
62
64 if (Smi::IsValid(message)) {
67 }
68 Dart_CObject cobj;
70 cobj.value.as_int64 = message;
71 return PostCObjectHelper(port_id, &cobj);
72}
73
76 bool handle_concurrently) {
77 if (name == nullptr) {
78 name = "<UnnamedNativePort>";
79 }
80 if (handler == nullptr) {
81 OS::PrintErr("%s expects argument 'handler' to be non-null.\n",
83 return ILLEGAL_PORT;
84 }
86 return ILLEGAL_PORT;
87 }
88 // Start the native port without a current isolate.
90
92 Dart_Port port_id = PortMap::CreatePort(nmh);
93 if (port_id != ILLEGAL_PORT) {
94 if (!nmh->Run(Dart::thread_pool(), nullptr, nullptr, 0)) {
95 PortMap::ClosePort(port_id);
96 nmh->RequestDeletion();
97 port_id = ILLEGAL_PORT;
98 }
99 }
101 return port_id;
102}
103
105 // Close the native port without a current isolate.
107
108 MessageHandler* handler = nullptr;
109 const bool was_closed = PortMap::ClosePort(native_port_id, &handler);
110 if (was_closed) {
111 handler->RequestDeletion();
112 }
113 return was_closed;
114}
115
116DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json,
117 intptr_t request_json_length,
118 uint8_t** response_json,
119 intptr_t* response_json_length,
120 char** error) {
121#if !defined(PRODUCT)
122 Isolate* isolate = Isolate::Current();
123 ASSERT(isolate == nullptr || !isolate->is_service_isolate());
124 IsolateLeaveScope saver(isolate);
125
126 if (!Dart::IsInitialized()) {
127 *error = ::dart::Utils::StrDup("VM Service is not active.");
128 return false;
129 }
130
131 // We only allow one isolate reload at a time. If this turns out to be on the
132 // critical path, we can change it to have a global datastructure which is
133 // mapping the reply ports to receive buffers.
134 static Monitor* vm_service_calls_monitor = new Monitor();
135 MonitorLocker _(vm_service_calls_monitor);
136
137 static Monitor* vm_service_call_monitor = new Monitor();
138 static uint8_t* result_bytes = nullptr;
139 static intptr_t result_length = 0;
140
141 ASSERT(result_bytes == nullptr);
142 ASSERT(result_length == 0);
143
144 struct Utils {
145 static void HandleResponse(Dart_Port dest_port_id, Dart_CObject* message) {
146 MonitorLocker monitor(vm_service_call_monitor);
147
149 RELEASE_ASSERT(message->value.as_typed_data.type ==
151 result_length = message->value.as_typed_data.length;
152 result_bytes = reinterpret_cast<uint8_t*>(malloc(result_length));
153 memmove(result_bytes, message->value.as_typed_data.values, result_length);
154
155 monitor.Notify();
156 }
157 };
158
159 auto port =
160 ::Dart_NewNativePort("service-rpc", &Utils::HandleResponse, false);
161 if (port == ILLEGAL_PORT) {
162 if (error != nullptr) {
163 *error = ::dart::Utils::StrDup("Was unable to create native port.");
164 }
165 return false;
166 }
167
168 // Before sending the message we'll lock the monitor, which the receiver
169 // will later on notify once the answer has been received.
170 MonitorLocker monitor(vm_service_call_monitor);
171
172 if (ServiceIsolate::SendServiceRpc(request_json, request_json_length, port,
173 error)) {
174 // We posted successfully and expect the vm-service to send the reply, so
175 // we will wait for it now. Since the service isolate could have shutdown
176 // after we sent the message we make sure to wake up periodically and
177 // check to see if the service isolate has shutdown.
178 do {
179 auto wait_result = monitor.Wait(1000); /* milliseconds */
180 if (wait_result == Monitor::kNotified) {
181 break;
182 }
184 // Service Isolate has shutdown while we were waiting for a reply,
185 // We will not get a reply anymore, cleanup and return an error.
187 return false;
188 }
189 } while (true);
190
191 // The caller takes ownership of the data.
192 *response_json = result_bytes;
193 *response_json_length = result_length;
194
195 // Reset global data, which can be used by the next call (after the mutex
196 // has been released).
197 result_bytes = nullptr;
198 result_length = 0;
199
200 // After the data has been received, we will not get any more messages on
201 // this port and can safely close it now.
203
204 return true;
205 } else {
206 // We couldn't post the message and will not receive any reply. Therefore we
207 // clean up the port and return an error.
209 return false;
210 }
211#else // !defined(PRODUCT)
212 if (error != nullptr) {
213 *error = Utils::StrDup("VM Service is not supported in PRODUCT mode.");
214 }
215 return false;
216#endif // !defined(PRODUCT)
217}
218
219// --- Verification tools ---
220
222#if defined(DART_PRECOMPILED_RUNTIME)
223 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
224#else
228 if (Api::IsError(result)) {
229 return result;
230 }
232 const Error& error = Error::Handle(T->zone(), Library::CompileAll());
233 if (!error.IsNull()) {
234 return Api::NewHandle(T, error.ptr());
235 }
236 return Api::Success();
237#endif // defined(DART_PRECOMPILED_RUNTIME)
238}
239
241#if defined(DART_PRECOMPILED_RUNTIME)
242 return Api::NewError("%s: All classes are already finalized in AOT runtime.",
244#else
248 if (Api::IsError(result)) {
249 return result;
250 }
253 if (!error.IsNull()) {
254 return Api::NewHandle(T, error.ptr());
255 }
256 return Api::Success();
257#endif // defined(DART_PRECOMPILED_RUNTIME)
258}
259
263};
264
265DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg) {
266 if (strcmp(command, "gc-on-nth-allocation") == 0) {
267 Thread* const thread = Thread::Current();
268 Isolate* isolate = (thread == nullptr) ? nullptr : thread->isolate();
269 CHECK_ISOLATE(isolate);
270 TransitionNativeToVM _(thread);
271 intptr_t argument = reinterpret_cast<intptr_t>(arg);
272 ASSERT(argument > 0);
274 return nullptr;
275
276 } else if (strcmp(command, "gc-now") == 0) {
277 ASSERT(arg == nullptr); // Don't pass an argument to this command.
278 Thread* const thread = Thread::Current();
279 Isolate* isolate = (thread == nullptr) ? nullptr : thread->isolate();
280 CHECK_ISOLATE(isolate);
281 TransitionNativeToVM _(thread);
283 return nullptr;
284
285 } else if (strcmp(command, "is-thread-in-generated") == 0) {
286 if (Thread::Current()->execution_state() == Thread::kThreadInGenerated) {
287 return reinterpret_cast<void*>(1);
288 }
289 return nullptr;
290
291 } else if (strcmp(command, "is-mutator-in-native") == 0) {
292 Isolate* const isolate = reinterpret_cast<Isolate*>(arg);
293 CHECK_ISOLATE(isolate);
296 return arg;
297 } else {
298 return nullptr;
299 }
300
301 } else if (strcmp(command, "run-in-safepoint-and-rw-code") == 0) {
302 const RunInSafepointAndRWCodeArgs* const args =
303 reinterpret_cast<RunInSafepointAndRWCodeArgs*>(arg);
304 Isolate* const isolate = args->isolate;
305 CHECK_ISOLATE(isolate);
306 auto isolate_group = isolate->group();
307 const bool kBypassSafepoint = false;
309 kBypassSafepoint);
310 Thread* const thread = Thread::Current();
311 {
312 GcSafepointOperationScope scope(thread);
313 isolate_group->heap()->WriteProtectCode(/*read_only=*/false);
314 (*args->callback)();
315 isolate_group->heap()->WriteProtectCode(/*read_only=*/true);
316 }
317 Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
318 return nullptr;
319
320 } else {
321 UNREACHABLE();
322 }
323}
324
325} // namespace dart
#define UNREACHABLE()
Definition: assert.h:248
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
static Dart_Handle Success()
static Dart_Handle NewHandle(Thread *thread, ObjectPtr raw)
static bool IsError(Dart_Handle handle)
static Dart_Handle NewError(const char *format,...) PRINTF_ATTRIBUTE(1
static Dart_Handle CheckAndFinalizePendingClasses(Thread *thread)
static ThreadPool * thread_pool()
Definition: dart.h:73
static bool IsInitialized()
Definition: dart.cc:799
static bool SetActiveApiCall()
Definition: dart.cc:803
static void ResetActiveApiCall()
Definition: dart.cc:807
void CollectOnNthAllocation(intptr_t num_allocations)
Definition: heap.cc:720
void CollectAllGarbage(GCReason reason=GCReason::kFull, bool compact=false)
Definition: heap.cc:573
Heap * heap() const
Definition: isolate.h:296
static IsolateGroup * Current()
Definition: isolate.h:539
IsolateLeaveScope(Isolate *current_isolate)
static Isolate * Current()
Definition: isolate.h:986
IsolateGroup * group() const
Definition: isolate.h:1037
Thread * mutator_thread() const
Definition: isolate.cc:1920
static ErrorPtr FinalizeAllClasses()
Definition: object.cc:15270
static ErrorPtr CompileAll(bool ignore_error=false)
Definition: object.cc:15228
bool Run(ThreadPool *pool, StartCallback start_callback, EndCallback end_callback, CallbackData data)
static std::unique_ptr< Message > New(Args &&... args)
Definition: message.h:72
@ kNormalPriority
Definition: message.h:28
Monitor::WaitResult Wait(int64_t millis=Monitor::kNoTimeout)
Definition: lockers.h:172
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static Object & Handle()
Definition: object.h:407
static bool PostMessage(std::unique_ptr< Message > message, bool before_events=false)
Definition: port.cc:152
static bool ClosePort(Dart_Port id, MessageHandler **message_handler=nullptr)
Definition: port.cc:90
static Dart_Port CreatePort(MessageHandler *handler)
Definition: port.cc:55
static bool SendServiceRpc(uint8_t *request_json, intptr_t request_json_length, Dart_Port reply_port, char **error)
static SmiPtr New(intptr_t value)
Definition: object.h:10006
static bool IsValid(int64_t value)
Definition: object.h:10026
NO_SANITIZE_THREAD ExecutionState execution_state_cross_thread_for_testing() const
Definition: thread.h:1045
@ kUnknownTask
Definition: thread.h:346
static Thread * Current()
Definition: thread.h:362
static void ExitIsolateGroupAsHelper(bool bypass_safepoint)
Definition: thread.cc:499
Isolate * isolate() const
Definition: thread.h:534
@ kThreadInNative
Definition: thread.h:1036
@ kThreadInGenerated
Definition: thread.h:1035
static bool EnterIsolateGroupAsHelper(IsolateGroup *isolate_group, TaskKind kind, bool bypass_safepoint)
Definition: thread.cc:481
static char * StrDup(const char *s)
#define ILLEGAL_PORT
Definition: dart_api.h:1535
int64_t Dart_Port
Definition: dart_api.h:1525
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
@ Dart_TypedData_kUint8
Definition: dart_api.h:2615
#define API_TIMELINE_DURATION(thread)
#define CHECK_ISOLATE(isolate)
Definition: dart_api_impl.h:42
#define DARTSCOPE(thread)
Definition: dart_api_impl.h:77
#define CHECK_CALLBACK_STATE(thread)
#define CURRENT_FUNC
Definition: dart_api_impl.h:28
void(* Dart_NativeMessageHandler)(Dart_Port dest_port_id, Dart_CObject *message)
@ Dart_CObject_kInt64
@ Dart_CObject_kTypedData
#define ASSERT(E)
#define DART_EXPORT
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
Dart_NativeFunction function
Definition: fuchsia.cc:51
Win32Message message
void HandleResponse(bool handled, void *user_data)
Definition: dart_vm.cc:33
const char *const name
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
void * malloc(size_t size)
Definition: allocation.cc:19
DART_EXPORT void * Dart_ExecuteInternalCommand(const char *command, void *arg)
static void HandleResponse(Dart_Port dest_port_id, Dart_CObject *message)
static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject *message)
DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t *request_json, intptr_t request_json_length, uint8_t **response_json, intptr_t *response_json_length, char **error)
DART_EXPORT void Dart_ExitIsolate()
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id)
DART_EXPORT Dart_Handle Dart_CompileAll()
DART_EXPORT Dart_Handle Dart_FinalizeAllClasses()
std::unique_ptr< Message > WriteApiMessage(Zone *zone, Dart_CObject *obj, Dart_Port dest_port, Message::Priority priority)
DART_EXPORT Dart_Port Dart_NewNativePort(const char *name, Dart_NativeMessageHandler handler, bool handle_concurrently)
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject *message)
DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service port
Definition: switches.h:87
list command
Definition: valgrind.py:24
#define T
Definition: precompiler.cc:65
Definition: SkMD5.cpp:134
union _Dart_CObject::@86 value
Dart_CObject_Type type
std::function< void()> * callback