aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/JSFFIFunction.h
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-06-22 23:21:48 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-06-22 23:21:48 -0700
commit729d445b6885f69dd2c6355f38707bd42851c791 (patch)
treef87a7c408929ea3f57bbb7ace380cf869da83c0e /src/bun.js/bindings/JSFFIFunction.h
parent25f820c6bf1d8ec6d444ef579cc036b8c0607b75 (diff)
downloadbun-jarred/rename.tar.gz
bun-jarred/rename.tar.zst
bun-jarred/rename.zip
change the directory structurejarred/rename
Diffstat (limited to 'src/bun.js/bindings/JSFFIFunction.h')
-rw-r--r--src/bun.js/bindings/JSFFIFunction.h88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/bun.js/bindings/JSFFIFunction.h b/src/bun.js/bindings/JSFFIFunction.h
new file mode 100644
index 000000000..e30beb5ea
--- /dev/null
+++ b/src/bun.js/bindings/JSFFIFunction.h
@@ -0,0 +1,88 @@
+#pragma once
+
+namespace Zig {
+class GlobalObject;
+}
+
+#include "root.h"
+#include "JavaScriptCore/JSFunction.h"
+#include "JavaScriptCore/VM.h"
+
+#include "headers-handwritten.h"
+#include "BunClientData.h"
+#include "JavaScriptCore/CallFrame.h"
+
+namespace JSC {
+class JSGlobalObject;
+}
+
+namespace Zig {
+
+using namespace JSC;
+
+using FFIFunction = JSC::EncodedJSValue (*)(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame);
+
+/**
+ * Call a C function with low overhead, modeled after JSC::JSNativeStdFunction
+ *
+ * The C function is expected to know how to get the arguments out of the JSC::CallFrame and
+ * return a JSC::EncodedJSValue. To do that, the argumentOffset is inlined at compile-time
+ * into Bun's binary and again inlined into the C function.
+ *
+ * This is used by functions compiled with TinyCC
+ *
+ * It was about 20% faster than using the JavaScriptCore C API for functions with 1 argument
+ *
+ * There is no wrapper function. It does zero bounds checking on the arguments.
+ * It does not check for exceptions. It does not check for return value.
+ * It is the caller's responsibility to not buffer overflow the arguments
+ * For all those reasons, this shouldn't be used directly.
+ */
+class JSFFIFunction final : public JSC::JSFunction {
+public:
+ using Base = JSFunction;
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ static constexpr bool needsDestruction = false;
+ static void destroy(JSCell* cell)
+ {
+ static_cast<JSFFIFunction*>(cell)->JSFFIFunction::~JSFFIFunction();
+ }
+
+ template<typename, SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSFFIFunction, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForFFIFunction.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForFFIFunction = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForFFIFunction.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForFFIFunction = WTFMove(space); });
+ }
+
+ DECLARE_EXPORT_INFO;
+
+ JS_EXPORT_PRIVATE static JSFFIFunction* create(VM&, Zig::GlobalObject*, unsigned length, const String& name, FFIFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ ASSERT(globalObject);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
+ }
+
+ const FFIFunction function() { return m_function; }
+
+ void* dataPtr;
+
+private:
+ JSFFIFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*, FFIFunction&&);
+ void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name);
+ DECLARE_VISIT_CHILDREN;
+
+ FFIFunction m_function;
+};
+
+} // namespace JSC
+
+extern "C" Zig::JSFFIFunction* Bun__CreateFFIFunction(Zig::GlobalObject* globalObject, const ZigString* symbolName, unsigned argCount, Zig::FFIFunction functionPointer);