Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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
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
262 std::function<void()>* callback;
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:709
void CollectAllGarbage(GCReason reason=GCReason::kFull, bool compact=false)
Definition heap.cc:562
Heap * heap() const
Definition isolate.h:295
static IsolateGroup * Current()
Definition isolate.h:534
IsolateLeaveScope(Isolate *current_isolate)
static Isolate * Current()
Definition isolate.h:939
IsolateGroup * group() const
Definition isolate.h:990
Thread * mutator_thread() const
Definition isolate.cc:1884
static ErrorPtr FinalizeAllClasses()
Definition object.cc:15317
static ErrorPtr CompileAll(bool ignore_error=false)
Definition object.cc:15275
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:9985
static bool IsValid(int64_t value)
Definition object.h:10005
NO_SANITIZE_THREAD ExecutionState execution_state_cross_thread_for_testing() const
Definition thread.h:1032
static Thread * Current()
Definition thread.h:361
static void ExitIsolateGroupAsHelper(bool bypass_safepoint)
Definition thread.cc:494
Isolate * isolate() const
Definition thread.h:533
@ kThreadInNative
Definition thread.h:1023
@ kThreadInGenerated
Definition thread.h:1022
static bool EnterIsolateGroupAsHelper(IsolateGroup *isolate_group, TaskKind kind, bool bypass_safepoint)
Definition thread.cc:476
static char * StrDup(const char *s)
#define ILLEGAL_PORT
Definition dart_api.h:1530
int64_t Dart_Port
Definition dart_api.h:1524
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:2606
#define API_TIMELINE_DURATION(thread)
#define CHECK_ISOLATE(isolate)
#define DARTSCOPE(thread)
#define CHECK_CALLBACK_STATE(thread)
#define CURRENT_FUNC
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
Win32Message message
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)
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
#define T
Definition SkMD5.cpp:134
union _Dart_CObject::@86 value
Dart_CObject_Type type
std::function< void()> * callback