[vm, ffi] Emit the FFI callback stub as a raw blob and place it in the Fuchsia package.

Any blob in the package can be loaded as an executable VMO.

TEST=child CL
Bug: https://dartbug.com/52579
Change-Id: I61f7a84453da4da4733c5a70d4d19f0a6652581b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/496661
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
Ryan Macnak
2026-04-20 11:31:19 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 877ded1a38
commit e860a9b0fa
8 changed files with 81 additions and 2 deletions
+8
View File
@@ -444,6 +444,7 @@ if (is_fuchsia) {
manifest = "runtime/bin/${binary}_test_component.cml"
data_deps = [
"runtime/bin:${binary}",
"runtime/bin:ffi_callback_stub_bin",
"runtime/bin:ffi_test_dynamic_library",
"runtime/bin:ffi_test_functions",
]
@@ -464,6 +465,13 @@ if (is_fuchsia) {
},
]
}
resources += [
{
path = get_label_info("runtime/bin:ffi_callback_stub_bin",
"target_gen_dir") + "/ffi_callback_stub.bin"
dest = "lib/ffi_callback_stub.bin"
},
]
foreach(file, resource_files) {
resources += [
{
+1
View File
@@ -708,6 +708,7 @@ trace to find the place to insert the appropriate support.
'--isolate_snapshot_data',
'--isolate_snapshot_instructions',
'--elf',
'--ffi_callback_stub',
]):
self.outputs.append(self.rebase(self.optarg))
elif self.get_option([
+14
View File
@@ -650,6 +650,20 @@ gen_snapshot_action("generate_snapshot_bin") {
]
}
gen_snapshot_action("ffi_callback_stub_bin") {
deps = [ "../vm:vm_platform_stripped" ]
platform_dill = "$root_out_dir/vm_platform_stripped.dill"
inputs = [ platform_dill ]
outputs = [ "$target_gen_dir/ffi_callback_stub.bin" ]
args = [
"--deterministic",
"--snapshot_kind=ffi-callback-stub",
"--ffi_callback_stub=" +
rebase_path("$target_gen_dir/ffi_callback_stub.bin", root_build_dir),
rebase_path(platform_dill, root_build_dir),
]
}
# Generates an assembly file defining a given symbol with the bytes from a
# binary file. Places the symbol in a text section if 'executable' is true,
# otherwise places the symbol in a read-only data section.
+10
View File
@@ -459,6 +459,8 @@ typedef Dart_Handle (*Dart_CreateAppAOTSnapshotAndRelocatableObjectType)(
typedef Dart_Handle (*Dart_CreateVMAOTSnapshotAsAssemblyType)(
Dart_StreamingWriteCallback,
void*);
typedef Dart_Handle (*Dart_WriteCallbackStubType)(Dart_StreamingWriteCallback,
void*);
typedef Dart_Handle (*Dart_SortClassesType)();
typedef Dart_Handle (*Dart_CreateAppJITSnapshotAsBlobsType)(uint8_t**,
intptr_t*,
@@ -772,6 +774,7 @@ static Dart_CreateAppAOTSnapshotAndRelocatableObjectType
Dart_CreateAppAOTSnapshotAndRelocatableObjectFn = NULL;
static Dart_CreateVMAOTSnapshotAsAssemblyType
Dart_CreateVMAOTSnapshotAsAssemblyFn = NULL;
static Dart_WriteCallbackStubType Dart_WriteCallbackStubFn = NULL;
static Dart_SortClassesType Dart_SortClassesFn = NULL;
static Dart_CreateAppJITSnapshotAsBlobsType Dart_CreateAppJITSnapshotAsBlobsFn =
NULL;
@@ -1368,6 +1371,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
Dart_CreateVMAOTSnapshotAsAssemblyFn =
(Dart_CreateVMAOTSnapshotAsAssemblyType)GetProcAddress(
process, "Dart_CreateVMAOTSnapshotAsAssembly");
Dart_WriteCallbackStubFn = (Dart_WriteCallbackStubType)GetProcAddress(
process, "Dart_WriteCallbackStub");
Dart_SortClassesFn =
(Dart_SortClassesType)GetProcAddress(process, "Dart_SortClasses");
Dart_CreateAppJITSnapshotAsBlobsFn =
@@ -2701,6 +2706,11 @@ Dart_Handle Dart_CreateVMAOTSnapshotAsAssembly(
return Dart_CreateVMAOTSnapshotAsAssemblyFn(callback, callback_data);
}
Dart_Handle Dart_WriteCallbackStub(Dart_StreamingWriteCallback callback,
void* callback_data) {
return Dart_WriteCallbackStubFn(callback, callback_data);
}
Dart_Handle Dart_SortClasses() {
return Dart_SortClassesFn();
}
+22 -2
View File
@@ -80,6 +80,7 @@ enum SnapshotKind {
kAppAOTElf,
kAppAOTMachODylib,
kVMAOTAssembly,
kFfiCallbackStub,
};
static SnapshotKind snapshot_kind = kCore;
@@ -93,6 +94,7 @@ static const char* const kSnapshotKindNames[] = {
"app-aot-elf",
"app-aot-macho-dylib",
"vm-aot-assembly",
"ffi-callback-stub",
nullptr,
// clang-format on
};
@@ -114,7 +116,8 @@ static const char* const kSnapshotKindNames[] = {
V(macho_object, macho_object_filename) \
V(loading_unit_manifest, loading_unit_manifest_filename) \
V(save_debugging_info, debugging_info_filename) \
V(save_obfuscation_map, obfuscation_map_filename)
V(save_obfuscation_map, obfuscation_map_filename) \
V(ffi_callback_stub, ffi_callback_stub_filename)
#define BOOL_OPTIONS_LIST(V) \
V(compile_all, compile_all) \
@@ -142,7 +145,8 @@ DEFINE_CB_OPTION(ProcessEnvironmentOption);
static bool IsSnapshottingForPrecompilation() {
return (snapshot_kind == kAppAOTAssembly) || (snapshot_kind == kAppAOTElf) ||
(snapshot_kind == kAppAOTMachODylib) ||
(snapshot_kind == kVMAOTAssembly);
(snapshot_kind == kVMAOTAssembly) ||
(snapshot_kind == kFfiCallbackStub);
}
// clang-format off
@@ -308,6 +312,14 @@ static int ParseArguments(int argc,
#endif
break;
}
case kFfiCallbackStub:
if (ffi_callback_stub_filename == nullptr) {
Syslog::PrintErr(
"Building the FFI callback stub blob requires specifying "
"an output file for --ffi_callback_stub.\n\n");
return -1;
}
break;
}
if (!obfuscate && obfuscation_map_filename != nullptr) {
@@ -637,6 +649,13 @@ static void CreateAndWritePrecompiledSnapshot() {
CHECK_RESULT(result);
return;
}
if (snapshot_kind == kFfiCallbackStub) {
File* file = OpenFile(ffi_callback_stub_filename);
RefCntReleaseScope<File> rs(file);
Dart_Handle result = Dart_WriteCallbackStub(StreamingWriteCallback, file);
CHECK_RESULT(result);
return;
}
Dart_AotBinaryFormat format;
const char* kind_str = nullptr;
@@ -834,6 +853,7 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) {
case kAppAOTElf:
case kAppAOTMachODylib:
case kVMAOTAssembly:
case kFfiCallbackStub:
CreateAndWritePrecompiledSnapshot();
break;
default:
+3
View File
@@ -4239,6 +4239,9 @@ Dart_CreateAppAOTSnapshotAndRelocatableObject(
DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle
Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
void* callback_data);
DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle
Dart_WriteCallbackStub(Dart_StreamingWriteCallback callback,
void* callback_data);
/**
* Sorts the class-ids in depth first traversal order of the inheritance
@@ -366,6 +366,7 @@ main() {
"Dart_TypeToNullableType",
"Dart_TypeVoid",
"Dart_VersionString",
"Dart_WriteCallbackStub",
"Dart_WriteHeapSnapshot",
"Dart_WriteProfileToTimeline",
if (isAOTRuntime) ...[
+22
View File
@@ -6911,6 +6911,28 @@ Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
#endif
}
DART_EXPORT Dart_Handle
Dart_WriteCallbackStub(Dart_StreamingWriteCallback callback,
void* callback_data) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_NULL(callback);
callback(callback_data,
reinterpret_cast<uint8_t*>(
StubCode::FfiCallbackTrampoline().EntryPoint()),
StubCode::FfiCallbackTrampoline().Size());
return Api::Success();
#endif
}
DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
void* callback_data,