[ffi/isolate_group] Move IsolateGroupBound callbacks from isolate to isolate group.

This allows creation of isolategroup-bound callbacks when isolate is not available. For example, to support proposed Isolate::onEvent/Isolate::handleEvent api https://github.com/dart-lang/language/blob/main/working/333%20-%20shared%20memory%20multithreading/shared_native_memory.md#additional-isolate-apis.

BUG=https://github.com/dart-lang/sdk/issues/63291
TEST=isolate_group_bound_callback_test

CoreLibraryReviewExempt: vm ffi-specific comments changes
Change-Id: I9a757a39ba8e152db64f59a66d337ca672103277
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/499661
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
This commit is contained in:
Alexander Aprelev
2026-05-05 08:37:06 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent b10062cbbf
commit 00cda4d60f
7 changed files with 82 additions and 52 deletions
+8 -1
View File
@@ -52,7 +52,8 @@ DEFINE_NATIVE_ENTRY(Ffi_createNativeCallableIsolateGroupBound, 1, 2) {
Function::CheckedHandle(zone, arguments->NativeArg0());
const auto& target = Closure::CheckedHandle(zone, arguments->NativeArgAt(1));
return Pointer::New(
isolate->CreateIsolateGroupBoundFfiCallback(zone, trampoline, target));
thread->isolate_group()->CreateIsolateGroupBoundFfiCallback(
zone, trampoline, target));
}
DEFINE_NATIVE_ENTRY(Ffi_deleteNativeCallable, 1, 1) {
@@ -61,6 +62,12 @@ DEFINE_NATIVE_ENTRY(Ffi_deleteNativeCallable, 1, 1) {
return Object::null();
}
DEFINE_NATIVE_ENTRY(Ffi_deleteIsolateGroupNativeCallable, 1, 1) {
const auto& pointer = Pointer::CheckedHandle(zone, arguments->NativeArg0());
thread->isolate_group()->DeleteFfiCallback(pointer.NativeAddress());
return Object::null();
}
DEFINE_NATIVE_ENTRY(Ffi_updateNativeCallableKeepIsolateAliveCounter, 1, 1) {
const int64_t delta =
Integer::CheckedHandle(zone, arguments->NativeArg0()).Value();
+1
View File
@@ -302,6 +302,7 @@ namespace dart {
V(Ffi_createNativeCallableIsolateLocal, 3) \
V(Ffi_createNativeCallableIsolateGroupBound, 2) \
V(Ffi_deleteNativeCallable, 1) \
V(Ffi_deleteIsolateGroupNativeCallable, 1) \
V(Ffi_updateNativeCallableKeepIsolateAliveCounter, 1) \
V(Ffi_dl_open, 1) \
V(Ffi_dl_close, 1) \
+17 -6
View File
@@ -2705,6 +2705,13 @@ void Isolate::LowLevelCleanup(Isolate* isolate) {
FinalizeWeakPersistentHandlesVisitor visitor(isolate_group);
isolate_group->api_state()->VisitWeakHandlesUnlocked(&visitor);
// Clean up any synchronous FFI callbacks registered with this
// isolate group. Skip if this isolate group never registered any.
if (isolate_group->ffi_callback_list_head_ != nullptr) {
FfiCallbackMetadata::Instance()->DeleteAllCallbacks(
&isolate_group->ffi_callback_list_head_);
}
Thread::ExitIsolateGroupAsHelper(/*bypass_safepoint=*/false);
}
@@ -3817,16 +3824,20 @@ FfiCallbackMetadata::Trampoline Isolate::CreateIsolateLocalFfiCallback(
&ffi_callback_list_head_);
}
// TODO(aam): Should this be in IsolateGroup?
FfiCallbackMetadata::Trampoline Isolate::CreateIsolateGroupBoundFfiCallback(
Zone* zone,
const Function& trampoline,
const Closure& target) {
FfiCallbackMetadata::Trampoline
IsolateGroup::CreateIsolateGroupBoundFfiCallback(Zone* zone,
const Function& trampoline,
const Closure& target) {
return FfiCallbackMetadata::Instance()->CreateLocalFfiCallback(
/*isolate=*/nullptr, group(), zone, trampoline, target,
/*isolate=*/nullptr, this, zone, trampoline, target,
&ffi_callback_list_head_);
}
void IsolateGroup::DeleteFfiCallback(FfiCallbackMetadata::Trampoline callback) {
FfiCallbackMetadata::Instance()->DeleteCallback(callback,
&ffi_callback_list_head_);
}
bool Isolate::HasLivePorts() {
ASSERT(0 <= open_ports_ && 0 <= open_ports_keepalive_ &&
open_ports_keepalive_ <= open_ports_);
+8 -4
View File
@@ -846,6 +846,12 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
return thread_locals_count_.fetch_add(1u, std::memory_order_relaxed);
}
FfiCallbackMetadata::Trampoline CreateIsolateGroupBoundFfiCallback(
Zone* zone,
const Function& trampoline,
const Closure& target);
void DeleteFfiCallback(FfiCallbackMetadata::Trampoline callback);
private:
friend class Dart; // For `object_store_ = ` in Dart::Init
friend class Heap;
@@ -1008,6 +1014,8 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
std::atomic<intptr_t> thread_locals_count_ = 0;
std::unique_ptr<Roots> roots_;
FfiCallbackMetadata::MetadataEntry* ffi_callback_list_head_ = nullptr;
};
// When an isolate sends-and-exits this class represent things that it passed
@@ -1338,10 +1346,6 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
const Function& trampoline,
const Closure& target,
bool keep_isolate_alive);
FfiCallbackMetadata::Trampoline CreateIsolateGroupBoundFfiCallback(
Zone* zone,
const Function& trampoline,
const Closure& target);
void DeleteFfiCallback(FfiCallbackMetadata::Trampoline callback);
void UpdateNativeCallableKeepIsolateAliveCounter(intptr_t delta);
bool HasOpenNativeCallables();