1// Copyright (c) 2019, 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 "include/dart_api.h"
6#include "include/dart_api_dl.h"
7#include "include/dart_native_api.h"
8#include "include/dart_version.h"
9#include "include/internal/dart_api_dl_impl.h"
10#include "platform/globals.h"
11#include "vm/bootstrap_natives.h"
12#include "vm/class_finalizer.h"
13#include "vm/class_id.h"
14#include "vm/compiler/ffi/native_type.h"
15#include "vm/exceptions.h"
16#include "vm/ffi_callback_metadata.h"
17#include "vm/flags.h"
18#include "vm/heap/gc_shared.h"
19#include "vm/log.h"
20#include "vm/native_arguments.h"
21#include "vm/native_entry.h"
22#include "vm/object.h"
23#include "vm/object_store.h"
24#include "vm/symbols.h"
25
26#if !defined(DART_PRECOMPILED_RUNTIME)
27#include "vm/compiler/assembler/assembler.h"
28#include "vm/compiler/ffi/call.h"
29#include "vm/compiler/ffi/callback.h"
30#include "vm/compiler/ffi/marshaller.h"
31#include "vm/compiler/jit/compiler.h"
32#endif // !defined(DART_PRECOMPILED_RUNTIME)
33
34namespace dart {
35
36// Static invocations to this method are translated directly in streaming FGB.
37DEFINE_NATIVE_ENTRY(Ffi_asFunctionInternal, 2, 2) {
38 UNREACHABLE();
39}
40
41DEFINE_NATIVE_ENTRY(Ffi_pointerFromFunction, 1, 1) {
42 const auto& function = Function::CheckedHandle(zone, ptr: arguments->NativeArg0());
43 return Pointer::New(native_address: isolate->CreateSyncFfiCallback(zone, function));
44}
45
46DEFINE_NATIVE_ENTRY(Ffi_pointerAsyncFromFunction, 1, 2) {
47 const auto& function = Function::CheckedHandle(zone, ptr: arguments->NativeArg0());
48 const auto& port =
49 ReceivePort::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
50 return Pointer::New(
51 native_address: isolate->CreateAsyncFfiCallback(zone, send_function: function, send_port: port.Id()));
52}
53
54DEFINE_NATIVE_ENTRY(Ffi_deleteAsyncFunctionPointer, 1, 1) {
55 const auto& pointer = Pointer::CheckedHandle(zone, ptr: arguments->NativeArg0());
56 isolate->DeleteFfiCallback(callback: pointer.NativeAddress());
57 return Object::null();
58}
59
60DEFINE_NATIVE_ENTRY(DartNativeApiFunctionPointer, 0, 1) {
61 GET_NON_NULL_NATIVE_ARGUMENT(String, name_dart, arguments->NativeArgAt(0));
62 const char* name = name_dart.ToCString();
63
64#define RETURN_FUNCTION_ADDRESS(function_name, R, A) \
65 if (strcmp(name, #function_name) == 0) { \
66 return Integer::New(reinterpret_cast<intptr_t>(function_name)); \
67 }
68 DART_NATIVE_API_DL_SYMBOLS(RETURN_FUNCTION_ADDRESS)
69#undef RETURN_FUNCTION_ADDRESS
70
71 const String& error = String::Handle(
72 ptr: String::NewFormatted(format: "Unknown dart_native_api.h symbol: %s.", name));
73 Exceptions::ThrowArgumentError(arg: error);
74}
75
76DEFINE_NATIVE_ENTRY(DartApiDLMajorVersion, 0, 0) {
77 return Integer::New(DART_API_DL_MAJOR_VERSION);
78}
79
80DEFINE_NATIVE_ENTRY(DartApiDLMinorVersion, 0, 0) {
81 return Integer::New(DART_API_DL_MINOR_VERSION);
82}
83
84static const DartApiEntry dart_api_entries[] = {
85#define ENTRY(name, R, A) \
86 DartApiEntry{#name, reinterpret_cast<void (*)()>(name)},
87 DART_API_ALL_DL_SYMBOLS(ENTRY)
88#undef ENTRY
89 DartApiEntry{.name: nullptr, .function: nullptr}};
90
91static const DartApi dart_api_data = {
92 DART_API_DL_MAJOR_VERSION, DART_API_DL_MINOR_VERSION, .functions: dart_api_entries};
93
94DEFINE_NATIVE_ENTRY(DartApiDLInitializeData, 0, 0) {
95 return Integer::New(value: reinterpret_cast<intptr_t>(&dart_api_data));
96}
97
98DEFINE_FFI_NATIVE_ENTRY(FinalizerEntry_SetExternalSize,
99 void,
100 (Dart_Handle entry_handle, intptr_t external_size)) {
101 Thread* const thread = Thread::Current();
102 TransitionNativeToVM transition(thread);
103 Zone* const zone = thread->zone();
104 const auto& entry_object =
105 Object::Handle(zone, ptr: Api::UnwrapHandle(object: entry_handle));
106 const auto& entry = FinalizerEntry::Cast(obj: entry_object);
107
108 Heap::Space space;
109 intptr_t external_size_diff;
110 {
111 NoSafepointScope no_safepoint;
112 space = SpaceForExternal(raw_entry: entry.ptr());
113 const intptr_t external_size_old = entry.external_size();
114 if (FLAG_trace_finalizers) {
115 THR_Print("Setting external size from %" Pd " to %" Pd
116 " bytes in %s space\n",
117 external_size_old, external_size, space == 0 ? "new" : "old");
118 }
119 external_size_diff = external_size - external_size_old;
120 if (external_size_diff == 0) {
121 return;
122 }
123 entry.set_external_size(external_size);
124 }
125 // The next call cannot be in safepoint.
126 if (external_size_diff > 0) {
127 if (!thread->isolate_group()->heap()->AllocatedExternal(size: external_size_diff,
128 space)) {
129 Exceptions::ThrowOOM();
130 }
131 } else {
132 thread->isolate_group()->heap()->FreedExternal(size: -external_size_diff, space);
133 }
134};
135
136namespace {
137struct AsTypedListFinalizerData {
138 void (*callback)(void*);
139 void* token;
140};
141} // namespace
142
143DEFINE_FFI_NATIVE_ENTRY(Pointer_asTypedListFinalizerAllocateData, void*, ()) {
144 auto* result = malloc(size: sizeof(AsTypedListFinalizerData));
145 // Initialized with FFI stores.
146 MSAN_UNPOISON(result, sizeof(AsTypedListFinalizerData));
147 return result;
148};
149
150void AsTypedListFinalizerCallback(void* peer) {
151 const auto* data = reinterpret_cast<AsTypedListFinalizerData*>(peer);
152 data->callback(data->token);
153 free(ptr: peer);
154}
155
156DEFINE_FFI_NATIVE_ENTRY(Pointer_asTypedListFinalizerCallbackPointer,
157 void*,
158 ()) {
159 return reinterpret_cast<void*>(&AsTypedListFinalizerCallback);
160};
161
162} // namespace dart
163

source code of flutter_engine/third_party/dart/runtime/lib/ffi.cc