-
-
Notifications
You must be signed in to change notification settings - Fork 38.6k
ffi: support function calls from pointers #66458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0fac5bc
52a5f52
f464a31
3da31d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ | |
| #include <string> | ||
| #include <thread> | ||
| #include <unordered_map> | ||
| #include <unordered_set> | ||
| #include <vector> | ||
|
|
||
| // libffi only accelerates reusable call plans on x86-64 System V. Other | ||
|
|
@@ -29,12 +30,18 @@ struct FFIFunction; | |
|
|
||
| struct FFIFunction { | ||
| FFIFunction() = default; | ||
| ~FFIFunction() { | ||
| if (auto registry = pointer_registry.lock()) { | ||
| registry->erase(this); | ||
| } | ||
| } | ||
| FFIFunction(const FFIFunction&) = delete; | ||
| FFIFunction& operator=(const FFIFunction&) = delete; | ||
| FFIFunction(FFIFunction&&) = delete; | ||
| FFIFunction& operator=(FFIFunction&&) = delete; | ||
|
|
||
| bool closed = false; | ||
| std::weak_ptr<std::unordered_set<FFIFunction*>> pointer_registry; | ||
|
|
||
| void* ptr = nullptr; | ||
| ffi_cif cif = {}; | ||
|
|
@@ -133,6 +140,7 @@ class DynamicLibrary : public BaseObject { | |
|
|
||
| static void GetPath(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| static void GetFunction(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| static void ToFunction(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| static void GetFunctions(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| static void GetSymbol(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| static void GetSymbols(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
|
|
@@ -156,11 +164,17 @@ class DynamicLibrary : public BaseObject { | |
| }; | ||
| v8::Maybe<PreparedFunction> PrepareFunction(Environment* env, | ||
| const std::string& name, | ||
| v8::Local<v8::Object> signature); | ||
| v8::Local<v8::Object> signature, | ||
| void* ptr = nullptr); | ||
| v8::MaybeLocal<v8::Function> CreateFunction( | ||
| Environment* env, | ||
| const std::string& name, | ||
| const std::shared_ptr<FFIFunction>& fn); | ||
| v8::MaybeLocal<v8::Function> BuildFunction( | ||
| Environment* env, | ||
| const std::string& name, | ||
| const std::shared_ptr<FFIFunction>& fn, | ||
| bool optimize); | ||
| static void CleanupFunctionInfo( | ||
| const v8::WeakCallbackInfo<FFIFunctionInfo>& data); | ||
| bool is_closed() const; | ||
|
|
@@ -175,6 +189,7 @@ class DynamicLibrary : public BaseObject { | |
| // which keeps the map from rooting the library through the wrapper's | ||
| // FFIFunctionInfo. | ||
| std::unordered_map<std::string, v8::Global<v8::Function>> function_wrappers_; | ||
| std::shared_ptr<std::unordered_set<FFIFunction*>> pointer_functions_; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a particular reason for having this behind a
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The library owns the registry, while each FFIFunction holds a weak_ptr to it. |
||
| std::unordered_map<void*, std::unique_ptr<FFICallback>> callbacks_; | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't we also want to call this whenever the JS function gets garbage-collected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is already handled by FFIFunction's destructor: it locks pointer_registry and calls erase(this) if the registry still exists.
GC of the callable's FFIFunctionInfo releases the FFIFunction.
The explicit erase here handles construction failure.