16FfiCallbackMetadata::FfiCallbackMetadata() {}
18void FfiCallbackMetadata::EnsureStubPageLocked() {
20 if (stub_page_ !=
nullptr) {
26 const Code& trampoline_code = StubCode::FfiCallbackTrampoline();
27 const uword code_start = trampoline_code.EntryPoint();
28 const uword code_end = code_start + trampoline_code.Size();
37 code_end - page_start);
39 offset_of_first_trampoline_in_page_ = code_start - page_start;
41#if defined(DART_TARGET_OS_FUCHSIA)
48 false,
"FfiCallbackMetadata::TrampolinePage");
49 Metadata* metadata =
reinterpret_cast<Metadata*
>(
52 AddToFreeListLocked(&metadata[
i]);
57FfiCallbackMetadata::~FfiCallbackMetadata() {
60 for (intptr_t
i = 0;
i < trampoline_pages_.length(); ++
i) {
61 delete trampoline_pages_[
i];
64#if defined(DART_TARGET_OS_FUCHSIA)
66 delete fuchsia_metadata_page_;
71 ASSERT(singleton_ ==
nullptr);
76 ASSERT(singleton_ !=
nullptr);
82 ASSERT(singleton_ !=
nullptr);
94VirtualMemory* FfiCallbackMetadata::AllocateTrampolinePage() {
95#if defined(DART_TARGET_OS_FUCHSIA)
101#if defined(DART_HOST_OS_MACOS) && !defined(DART_PRECOMPILED_RUNTIME)
106 const bool is_executable =
true;
108 const bool is_executable =
false;
113 false,
"FfiCallbackMetadata::TrampolinePage");
114 if (new_page ==
nullptr) {
123#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
124 if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
125 DisassembleToStdout formatter;
126 THR_Print(
"Code for duplicated stub 'FfiCallbackTrampoline' {\n");
127 const uword code_start =
128 new_page->start() + offset_of_first_trampoline_in_page_;
139void FfiCallbackMetadata::EnsureFreeListNotEmptyLocked() {
141 EnsureStubPageLocked();
143 if (free_list_head_ !=
nullptr) {
147 VirtualMemory* new_page = AllocateTrampolinePage();
148 if (new_page ==
nullptr) {
151 trampoline_pages_.Add(new_page);
162 reinterpret_cast<Metadata*
>(new_page->start() +
MetadataOffset());
163 for (intptr_t
i = 0;
i < trampolines_per_page; ++
i) {
164 AddToFreeListLocked(&metadata[
i]);
169 Isolate* target_isolate,
170 TrampolineType trampoline_type,
171 uword target_entry_point,
173 Metadata** list_head) {
174 MutexLocker locker(&lock_);
175 EnsureFreeListNotEmptyLocked();
176 ASSERT(free_list_head_ !=
nullptr);
177 Metadata* entry = free_list_head_;
179 if (free_list_head_ ==
nullptr) {
180 ASSERT(free_list_tail_ == entry);
181 free_list_tail_ =
nullptr;
183 Metadata* next_entry = *list_head;
184 if (next_entry !=
nullptr) {
185 ASSERT(next_entry->list_prev_ ==
nullptr);
186 next_entry->list_prev_ = entry;
188 *entry = Metadata(target_isolate, trampoline_type, target_entry_point,
189 context,
nullptr, next_entry);
194void FfiCallbackMetadata::AddToFreeListLocked(Metadata* entry) {
196 if (free_list_tail_ ==
nullptr) {
197 ASSERT(free_list_head_ ==
nullptr);
198 free_list_head_ = free_list_tail_ = entry;
200 ASSERT(free_list_head_ !=
nullptr && free_list_tail_ !=
nullptr);
203 free_list_tail_ = entry;
206 entry->target_isolate_ =
nullptr;
207 entry->free_list_next_ =
nullptr;
210void FfiCallbackMetadata::DeleteCallbackLocked(Metadata* entry) {
213 entry->context_ != 0) {
214 ASSERT(entry->target_isolate_ !=
nullptr);
215 auto* api_state = entry->target_isolate_->group()->api_state();
216 ASSERT(api_state !=
nullptr);
217 api_state->FreePersistentHandle(entry->closure_handle());
219 AddToFreeListLocked(entry);
224 for (
Metadata* entry = *list_head; entry !=
nullptr;) {
226 DeleteCallbackLocked(entry);
229 *list_head =
nullptr;
237 auto*
prev = entry->list_prev_;
238 auto*
next = entry->list_next_;
239 if (
prev !=
nullptr) {
242 ASSERT(*list_head == entry);
245 if (
next !=
nullptr) {
248 DeleteCallbackLocked(entry);
256 return code.EntryPoint();
259PersistentHandle* FfiCallbackMetadata::CreatePersistentHandle(
262 auto* api_state = isolate->group()->api_state();
263 ASSERT(api_state !=
nullptr);
264 auto* handle = api_state->AllocatePersistentHandle();
280 return CreateSyncFfiCallbackImpl(isolate, zone,
function,
nullptr,
285 return CreateSyncFfiCallbackImpl(isolate, zone,
function,
286 CreatePersistentHandle(isolate,
closure),
296 Metadata** list_head) {
299#if defined(TARGET_ARCH_IA32)
301 const intptr_t stack_return_delta =
305 if (stack_return_delta != 0) {
306 ASSERT(stack_return_delta == 4);
311 return CreateMetadataEntry(isolate, trampoline_type,
313 reinterpret_cast<uint64_t
>(
closure), list_head);
324 GetEntryPoint(zone, send_function),
325 static_cast<uint64_t
>(send_port), list_head);
332 const uword index = metadata - metadatas;
333#if defined(DART_TARGET_OS_FUCHSIA)
334 return StubCode::FfiCallbackTrampoline().EntryPoint() +
335 index * kNativeCallbackTrampolineSize;
337 return start + offset_of_first_trampoline_in_page_ +
338 index * kNativeCallbackTrampolineSize;
344#if defined(DART_TARGET_OS_FUCHSIA)
347 const uword page_start =
351 (trampoline - offset_of_first_trampoline_in_page_ - page_start) /
352 kNativeCallbackTrampolineSize;
356 return metadata_table + index;
361 (trampoline -
start - offset_of_first_trampoline_in_page_) /
362 kNativeCallbackTrampolineSize;
363 return &metadatas[index];
static float next(float f)
static float prev(float f)
#define ASSERT_LESS_OR_EQUAL(expected, actual)
static constexpr bool kUsesRet4
static void Disassemble(uword start, uword end, DisassemblyFormatter *formatter, const Code &code, const CodeComments *comments=nullptr)
static DART_NORETURN void ThrowOOM()
FfiCallbackKind GetFfiCallbackKind() const
bool IsOwnedByCurrentThread() const
static constexpr T RoundDown(T x, intptr_t alignment)
static VirtualMemory * AllocateAligned(intptr_t size, intptr_t alignment, bool is_executable, bool is_compressed, const char *name)
static intptr_t PageSize()
bool DuplicateRX(VirtualMemory *target)
static VirtualMemory * ForImagePage(void *pointer, uword size)
#define THR_Print(format,...)
Dart_NativeFunction function
static constexpr intptr_t kWordSize
Thread * DLRT_GetFfiCallbackMetadata(FfiCallbackMetadata::Trampoline trampoline, uword *out_entry_point, uword *out_trampoline_type)
@ kIsolateLocalClosureCallback
@ kIsolateLocalStaticCallback
void DLRT_ExitTemporaryIsolate()
std::function< void()> closure