2013-06-14 23:47:40 +00:00
|
|
|
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "include/dart_native_api.h"
|
|
|
|
|
|
|
|
#include "platform/assert.h"
|
|
|
|
#include "vm/dart_api_impl.h"
|
|
|
|
#include "vm/dart_api_message.h"
|
|
|
|
#include "vm/dart_api_state.h"
|
|
|
|
#include "vm/message.h"
|
|
|
|
#include "vm/native_message_handler.h"
|
|
|
|
#include "vm/port.h"
|
2018-07-25 12:06:55 +00:00
|
|
|
#include "vm/service_isolate.h"
|
2013-06-14 23:47:40 +00:00
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
|
|
|
// --- Message sending/receiving from native code ---
|
|
|
|
|
2015-11-19 21:45:10 +00:00
|
|
|
class IsolateSaver {
|
|
|
|
public:
|
|
|
|
explicit IsolateSaver(Isolate* current_isolate)
|
|
|
|
: saved_isolate_(current_isolate) {
|
|
|
|
if (current_isolate != NULL) {
|
|
|
|
ASSERT(current_isolate == Isolate::Current());
|
2016-02-01 18:57:34 +00:00
|
|
|
Dart_ExitIsolate();
|
2015-11-19 21:45:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
~IsolateSaver() {
|
|
|
|
if (saved_isolate_ != NULL) {
|
2016-02-01 18:57:34 +00:00
|
|
|
Dart_Isolate I = reinterpret_cast<Dart_Isolate>(saved_isolate_);
|
|
|
|
Dart_EnterIsolate(I);
|
2015-11-19 21:45:10 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-08 21:54:47 +00:00
|
|
|
|
2015-11-19 21:45:10 +00:00
|
|
|
private:
|
|
|
|
Isolate* saved_isolate_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(IsolateSaver);
|
|
|
|
};
|
|
|
|
|
2015-12-12 03:45:17 +00:00
|
|
|
static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject* message) {
|
2018-02-14 00:28:01 +00:00
|
|
|
ApiMessageWriter writer;
|
|
|
|
Message* msg =
|
|
|
|
writer.WriteCMessage(message, port_id, Message::kNormalPriority);
|
2013-06-14 23:47:40 +00:00
|
|
|
|
2018-02-14 00:28:01 +00:00
|
|
|
if (msg == NULL) {
|
|
|
|
return false;
|
2017-01-11 19:12:40 +00:00
|
|
|
}
|
2013-06-14 23:47:40 +00:00
|
|
|
|
|
|
|
// Post the message at the given port.
|
2018-02-14 00:28:01 +00:00
|
|
|
return PortMap::PostMessage(msg);
|
2013-06-14 23:47:40 +00:00
|
|
|
}
|
|
|
|
|
2015-12-12 03:45:17 +00:00
|
|
|
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message) {
|
|
|
|
return PostCObjectHelper(port_id, message);
|
|
|
|
}
|
|
|
|
|
2015-12-12 00:07:16 +00:00
|
|
|
DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message) {
|
|
|
|
if (Smi::IsValid(message)) {
|
2016-11-08 21:54:47 +00:00
|
|
|
return PortMap::PostMessage(
|
|
|
|
new Message(port_id, Smi::New(message), Message::kNormalPriority));
|
2015-12-12 00:07:16 +00:00
|
|
|
}
|
|
|
|
Dart_CObject cobj;
|
|
|
|
cobj.type = Dart_CObject_kInt64;
|
|
|
|
cobj.value.as_int64 = message;
|
2015-12-12 03:45:17 +00:00
|
|
|
return PostCObjectHelper(port_id, &cobj);
|
2015-12-12 00:07:16 +00:00
|
|
|
}
|
|
|
|
|
2013-06-14 23:47:40 +00:00
|
|
|
DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
|
|
|
|
Dart_NativeMessageHandler handler,
|
2017-01-31 09:30:15 +00:00
|
|
|
bool handle_concurrently) {
|
2013-06-14 23:47:40 +00:00
|
|
|
if (name == NULL) {
|
|
|
|
name = "<UnnamedNativePort>";
|
|
|
|
}
|
|
|
|
if (handler == NULL) {
|
|
|
|
OS::PrintErr("%s expects argument 'handler' to be non-null.\n",
|
|
|
|
CURRENT_FUNC);
|
2015-05-19 18:41:42 +00:00
|
|
|
return ILLEGAL_PORT;
|
2013-06-14 23:47:40 +00:00
|
|
|
}
|
|
|
|
// Start the native port without a current isolate.
|
|
|
|
IsolateSaver saver(Isolate::Current());
|
|
|
|
|
2017-01-31 09:30:15 +00:00
|
|
|
NativeMessageHandler* nmh = new NativeMessageHandler(name, handler);
|
2013-06-14 23:47:40 +00:00
|
|
|
Dart_Port port_id = PortMap::CreatePort(nmh);
|
2016-08-04 22:34:24 +00:00
|
|
|
PortMap::SetPortState(port_id, PortMap::kLivePort);
|
2013-06-14 23:47:40 +00:00
|
|
|
nmh->Run(Dart::thread_pool(), NULL, NULL, 0);
|
|
|
|
return port_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id) {
|
|
|
|
// Close the native port without a current isolate.
|
|
|
|
IsolateSaver saver(Isolate::Current());
|
|
|
|
|
|
|
|
// TODO(turnidge): Check that the port is native before trying to close.
|
|
|
|
return PortMap::ClosePort(native_port_id);
|
|
|
|
}
|
|
|
|
|
2018-07-25 12:06:55 +00:00
|
|
|
static Monitor* vm_service_calls_monitor = new Monitor();
|
|
|
|
|
|
|
|
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) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate == nullptr || !isolate->is_service_isolate());
|
|
|
|
IsolateSaver saver(isolate);
|
|
|
|
|
|
|
|
// We only allow one isolate reload at a time. If this turns out to be on the
|
|
|
|
// critical path, we can change it to have a global datastructure which is
|
|
|
|
// mapping the reply ports to receive buffers.
|
|
|
|
MonitorLocker _(vm_service_calls_monitor);
|
|
|
|
|
|
|
|
static Monitor* vm_service_call_monitor = new Monitor();
|
|
|
|
static uint8_t* result_bytes = nullptr;
|
|
|
|
static intptr_t result_length = 0;
|
|
|
|
|
|
|
|
ASSERT(result_bytes == nullptr);
|
|
|
|
ASSERT(result_length == 0);
|
|
|
|
|
|
|
|
struct Utils {
|
|
|
|
static void HandleResponse(Dart_Port dest_port_id, Dart_CObject* message) {
|
|
|
|
MonitorLocker monitor(vm_service_call_monitor);
|
|
|
|
|
|
|
|
RELEASE_ASSERT(message->type == Dart_CObject_kTypedData);
|
|
|
|
RELEASE_ASSERT(message->value.as_typed_data.type ==
|
|
|
|
Dart_TypedData_kUint8);
|
|
|
|
result_length = message->value.as_typed_data.length;
|
|
|
|
result_bytes = reinterpret_cast<uint8_t*>(malloc(result_length));
|
|
|
|
memmove(result_bytes, message->value.as_typed_data.values, result_length);
|
|
|
|
|
|
|
|
monitor.Notify();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-07-25 12:34:59 +00:00
|
|
|
auto port =
|
|
|
|
::Dart_NewNativePort("service-rpc", &Utils::HandleResponse, false);
|
2018-07-25 12:06:55 +00:00
|
|
|
if (port == ILLEGAL_PORT) {
|
|
|
|
return Api::NewError("Was unable to create native port.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Before sending the message we'll lock the monitor, which the receiver
|
|
|
|
// will later on notify once the answer has been received.
|
|
|
|
MonitorLocker monitor(vm_service_call_monitor);
|
|
|
|
|
|
|
|
if (ServiceIsolate::SendServiceRpc(request_json, request_json_length, port)) {
|
|
|
|
// We posted successfully and expect the vm-service to send the reply, so
|
|
|
|
// we will wait for it now.
|
|
|
|
auto wait_result = monitor.Wait();
|
|
|
|
ASSERT(wait_result == Monitor::kNotified);
|
|
|
|
|
|
|
|
// The caller takes ownership of the data.
|
|
|
|
*response_json = result_bytes;
|
|
|
|
*response_json_length = result_length;
|
|
|
|
|
|
|
|
// Reset global data, which can be used by the next call (after the mutex
|
|
|
|
// has been released).
|
|
|
|
result_bytes = nullptr;
|
|
|
|
result_length = 0;
|
|
|
|
|
|
|
|
// After the data has been received, we will not get any more messages on
|
|
|
|
// this port and can safely close it now.
|
|
|
|
Dart_CloseNativePort(port);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
// We couldn't post the message and will not receive any reply. Therefore we
|
|
|
|
// clean up the port and return an error.
|
|
|
|
Dart_CloseNativePort(port);
|
|
|
|
|
|
|
|
if (error != nullptr) {
|
|
|
|
*error = strdup("Was unable to post message to isolate.");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-14 23:47:40 +00:00
|
|
|
// --- Verification tools ---
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_CompileAll() {
|
2017-12-07 17:49:39 +00:00
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
|
|
|
|
#else
|
2015-09-02 00:18:55 +00:00
|
|
|
DARTSCOPE(Thread::Current());
|
2018-02-23 01:31:38 +00:00
|
|
|
API_TIMELINE_DURATION(T);
|
2015-11-25 19:07:22 +00:00
|
|
|
Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
|
2013-06-14 23:47:40 +00:00
|
|
|
if (::Dart_IsError(result)) {
|
|
|
|
return result;
|
|
|
|
}
|
2015-10-13 21:29:43 +00:00
|
|
|
CHECK_CALLBACK_STATE(T);
|
2017-12-07 17:49:39 +00:00
|
|
|
const Error& error = Error::Handle(T->zone(), Library::CompileAll());
|
|
|
|
if (!error.IsNull()) {
|
|
|
|
return Api::NewHandle(T, error.raw());
|
2016-09-23 22:20:39 +00:00
|
|
|
}
|
2017-12-07 17:49:39 +00:00
|
|
|
return Api::Success();
|
|
|
|
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
2016-09-23 22:20:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ParseAll() {
|
2017-12-07 17:49:39 +00:00
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
|
|
|
|
#else
|
2016-09-23 22:20:39 +00:00
|
|
|
DARTSCOPE(Thread::Current());
|
2018-02-23 01:31:38 +00:00
|
|
|
API_TIMELINE_DURATION(T);
|
2016-09-23 22:20:39 +00:00
|
|
|
Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
|
|
|
|
if (::Dart_IsError(result)) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
CHECK_CALLBACK_STATE(T);
|
2017-12-07 17:49:39 +00:00
|
|
|
const Error& error = Error::Handle(T->zone(), Library::ParseAll(T));
|
|
|
|
if (!error.IsNull()) {
|
|
|
|
return Api::NewHandle(T, error.raw());
|
|
|
|
}
|
|
|
|
return Api::Success();
|
|
|
|
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
2016-09-23 22:20:39 +00:00
|
|
|
}
|
|
|
|
|
2013-06-14 23:47:40 +00:00
|
|
|
} // namespace dart
|