0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-22 15:07:00 -05:00

Use bindgen + raw api

This commit is contained in:
Nathan Whitaker 2024-06-27 18:34:11 -07:00
parent b085881ac4
commit 8ea00476b6
No known key found for this signature in database
6 changed files with 123 additions and 73 deletions

View file

@ -24,6 +24,8 @@ fn main() {
println!("cargo:rerun-if-changed=.gn"); println!("cargo:rerun-if-changed=.gn");
println!("cargo:rerun-if-changed=BUILD.gn"); println!("cargo:rerun-if-changed=BUILD.gn");
println!("cargo:rerun-if-changed=src/binding.cc"); println!("cargo:rerun-if-changed=src/binding.cc");
println!("cargo:rerun-if-changed=src/binding.hpp");
println!("cargo:rerun-if-changed=build.rs");
// These are all the environment variables that we check. This is // These are all the environment variables that we check. This is
// probably more than what is needed, but missing an important // probably more than what is needed, but missing an important
@ -147,7 +149,11 @@ fn build_binding() {
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.clang_args(["-x", "c++", "-std=c++20", "-Iv8/include"]) .clang_args(["-x", "c++", "-std=c++20", "-Iv8/include"])
.clang_args(args) .clang_args(args)
.respect_cxx_access_specs(true)
.allowlist_item("RUST_.*") .allowlist_item("RUST_.*")
.blocklist_item("v8::.*")
.blocklist_item("cppgc::.*")
.blocklist_item("std::.*")
.generate() .generate()
.expect("Unable to generate bindings"); .expect("Unable to generate bindings");

View file

@ -1,4 +1,6 @@
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license. // Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
#include "binding.hpp"
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
@ -1071,35 +1073,6 @@ v8__String__GetExternalStringResourceBase(const v8::String& self,
return self.GetExternalStringResourceBase(encoding_out); return self.GetExternalStringResourceBase(encoding_out);
} }
class ExternalOneByteString : public v8::String::ExternalOneByteStringResource {
public:
using RustDestroy = void (*)(char*, size_t);
ExternalOneByteString(char* data, int length, RustDestroy rustDestroy,
v8::Isolate* isolate)
: _data(data),
_length(length),
_rustDestroy(rustDestroy),
_isolate(isolate) {
_isolate->AdjustAmountOfExternalAllocatedMemory(
static_cast<int64_t>(_length));
}
~ExternalOneByteString() override {
(*_rustDestroy)(_data, _length);
_isolate->AdjustAmountOfExternalAllocatedMemory(
-static_cast<int64_t>(-_length));
}
const char* data() const override { return _data; }
size_t length() const override { return _length; }
private:
char* _data;
const int _length;
RustDestroy _rustDestroy;
v8::Isolate* _isolate;
};
class ExternalStaticOneByteStringResource class ExternalStaticOneByteStringResource
: public v8::String::ExternalOneByteStringResource { : public v8::String::ExternalOneByteStringResource {
public: public:
@ -1138,7 +1111,7 @@ class ExternalConstOneByteStringResource
const int _length; const int _length;
}; };
const v8::String* v8__String__NewExternalOneByteConst( const v8::String* v8__String__NewExternalOneByte(
v8::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) { v8::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
return maybe_local_to_ptr(v8::String::NewExternalOneByte(isolate, resource)); return maybe_local_to_ptr(v8::String::NewExternalOneByte(isolate, resource));
} }
@ -1150,13 +1123,6 @@ const v8::String* v8__String__NewExternalOneByteStatic(v8::Isolate* isolate,
isolate, new ExternalStaticOneByteStringResource(data, length))); isolate, new ExternalStaticOneByteStringResource(data, length)));
} }
const v8::String* v8__String__NewExternalOneByte(
v8::Isolate* isolate, char* data, int length,
ExternalOneByteString::RustDestroy rustDestroy) {
return maybe_local_to_ptr(v8::String::NewExternalOneByte(
isolate, new ExternalOneByteString(data, length, rustDestroy, isolate)));
}
const char* v8__ExternalOneByteStringResource__data( const char* v8__ExternalOneByteStringResource__data(
v8::String::ExternalOneByteStringResource* self) { v8::String::ExternalOneByteStringResource* self) {
return self->data(); return self->data();
@ -3787,31 +3753,23 @@ void v8__PropertyDescriptor__set_configurable(v8::PropertyDescriptor* self,
self->set_configurable(configurable); self->set_configurable(configurable);
} }
RUST_ExternalOneByteString::RUST_ExternalOneByteString(
char* data, int length,
RUST_ExternalOneByteString::RustDestroyFn rustDestroy, v8::Isolate* isolate)
: _data(data),
_length(length),
_rustDestroy(rustDestroy),
_isolate(isolate) {
_isolate->AdjustAmountOfExternalAllocatedMemory(
static_cast<int64_t>(_length));
}
} // extern "C" } // extern "C"
// cppgc // cppgc
extern "C" { extern "C" {
class RustObj;
using RustTraceFn = void (*)(const RustObj* obj, cppgc::Visitor*);
using RustDestroyFn = void (*)(const RustObj* obj);
class RustObj final : public cppgc::GarbageCollected<RustObj> {
public:
explicit RustObj(RustTraceFn trace, RustDestroyFn destroy)
: trace_(trace), destroy_(destroy) {}
~RustObj() { destroy_(this); }
void Trace(cppgc::Visitor* visitor) const { trace_(this, visitor); }
private:
RustTraceFn trace_;
RustDestroyFn destroy_;
};
RustObj* v8__Object__Unwrap(v8::Isolate* isolate, const v8::Object& wrapper, RustObj* v8__Object__Unwrap(v8::Isolate* isolate, const v8::Object& wrapper,
v8::CppHeapPointerTag tag) { v8::CppHeapPointerTag tag) {
v8::CppHeapPointerTagRange tag_range(tag, tag); v8::CppHeapPointerTagRange tag_range(tag, tag);
@ -3858,8 +3816,8 @@ void cppgc__heap__collect_garbage_for_testing(
} }
RustObj* cppgc__make_garbage_collectable(v8::CppHeap* heap, size_t size, RustObj* cppgc__make_garbage_collectable(v8::CppHeap* heap, size_t size,
RustTraceFn trace, RustObj::RustTraceFn trace,
RustDestroyFn destroy) { RustObj::RustDestroyFn destroy) {
return cppgc::MakeGarbageCollected<RustObj>(heap->GetAllocationHandle(), return cppgc::MakeGarbageCollected<RustObj>(heap->GetAllocationHandle(),
cppgc::AdditionalBytes(size), cppgc::AdditionalBytes(size),
trace, destroy); trace, destroy);
@ -3948,4 +3906,5 @@ RustObj* cppgc__WeakPersistent__Get(cppgc::WeakPersistent<RustObj>* self) {
return self->Get(); return self->Get();
} }
//
} // extern "C" } // extern "C"

View file

@ -1,4 +1,5 @@
#include <v8-cppgc.h> #include <v8-cppgc.h>
#include <v8-isolate.h>
#include <v8-message.h> #include <v8-message.h>
/** /**
@ -6,12 +7,53 @@
* and made available in `crate::binding` in rust. * and made available in `crate::binding` in rust.
*/ */
namespace { extern "C" {
class RUST_ExternalOneByteString
class RustObj; : public v8::String::ExternalOneByteStringResource {
public:
using RustDestroyFn = void (*)(char*, size_t);
// bindgen doesn't support generating bindings for inline
// constructors/functions
RUST_ExternalOneByteString(char* data, int length, RustDestroyFn rustDestroy,
v8::Isolate* isolate);
~RUST_ExternalOneByteString() {
(*_rustDestroy)(_data, _length);
_isolate->AdjustAmountOfExternalAllocatedMemory(
-static_cast<int64_t>(-_length));
} }
const char* data() const { return _data; }
size_t length() const { return static_cast<size_t>(_length); }
private:
char* const _data;
const size_t _length;
RustDestroyFn _rustDestroy;
v8::Isolate* _isolate;
};
class RustObj final : public cppgc::GarbageCollected<RustObj> {
public:
using RustTraceFn = void (*)(const RustObj* obj, cppgc::Visitor*);
using RustDestroyFn = void (*)(const RustObj* obj);
explicit RustObj(RustTraceFn trace, RustDestroyFn destroy)
: trace_(trace), destroy_(destroy) {}
~RustObj() { destroy_(this); }
void Trace(cppgc::Visitor* visitor) const { trace_(this, visitor); }
private:
RustTraceFn trace_;
RustDestroyFn destroy_;
};
}
// Allocate memory using C++'s `new` operator
void* RUST_new(size_t size) { return operator new(size); }
static size_t RUST_v8__ScriptOrigin_SIZE = sizeof(v8::ScriptOrigin); static size_t RUST_v8__ScriptOrigin_SIZE = sizeof(v8::ScriptOrigin);
static size_t RUST_cppgc__Member_SIZE = sizeof(cppgc::Member<RustObj>); static size_t RUST_cppgc__Member_SIZE = sizeof(cppgc::Member<RustObj>);

View file

@ -1,4 +1,7 @@
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(dead_code)]
include!(env!("RUSTY_V8_SRC_BINDING_PATH")); include!(env!("RUSTY_V8_SRC_BINDING_PATH"));
pub use crate::Isolate as v8_Isolate;

View file

@ -79,11 +79,6 @@ extern "C" {
encoding: *mut Encoding, encoding: *mut Encoding,
) -> *mut ExternalStringResourceBase; ) -> *mut ExternalStringResourceBase;
fn v8__String__NewExternalOneByteConst(
isolate: *mut Isolate,
onebyte_const: *const OneByteConst,
) -> *const String;
fn v8__String__NewExternalOneByteStatic( fn v8__String__NewExternalOneByteStatic(
isolate: *mut Isolate, isolate: *mut Isolate,
buffer: *const char, buffer: *const char,
@ -92,9 +87,7 @@ extern "C" {
fn v8__String__NewExternalOneByte( fn v8__String__NewExternalOneByte(
isolate: *mut Isolate, isolate: *mut Isolate,
buffer: *mut char, resource: *mut ExternalOneByteStringResource,
length: int,
free: extern "C" fn(*mut char, size_t),
) -> *const String; ) -> *const String;
fn v8__String__NewExternalTwoByteStatic( fn v8__String__NewExternalTwoByteStatic(
@ -571,7 +564,11 @@ impl String {
) -> Option<Local<'s, String>> { ) -> Option<Local<'s, String>> {
unsafe { unsafe {
scope.cast_local(|sd| { scope.cast_local(|sd| {
v8__String__NewExternalOneByteConst(sd.get_isolate_ptr(), onebyte_const) v8__String__NewExternalOneByte(
sd.get_isolate_ptr(),
onebyte_const as *const _ as *mut OneByteConst
as *mut ExternalOneByteStringResource,
)
}) })
} }
} }
@ -606,12 +603,51 @@ impl String {
let buffer_len = buffer.len().try_into().ok()?; let buffer_len = buffer.len().try_into().ok()?;
unsafe { unsafe {
scope.cast_local(|sd| { scope.cast_local(|sd| {
v8__String__NewExternalOneByte( let ptr = crate::support::cpp_new::<
sd.get_isolate_ptr(), crate::binding::RUST_ExternalOneByteString,
>();
crate::binding::RUST_ExternalOneByteString_RUST_ExternalOneByteString(
ptr,
Box::into_raw(buffer).cast::<char>(), Box::into_raw(buffer).cast::<char>(),
buffer_len, buffer_len,
free_rust_external_onebyte, Some(free_rust_external_onebyte),
) sd.get_isolate_ptr().cast(),
);
v8__String__NewExternalOneByte(sd.get_isolate_ptr(), ptr.cast())
})
}
}
/// Creates a `v8::String` from owned bytes, length, and a custom destructor.
/// The bytes must be Latin-1 or ASCII.
/// V8 will take ownership of the buffer and free it when the string is garbage collected.
///
/// SAFETY: `buffer` must be owned (valid for the lifetime of the string), and
/// `destructor` must be a valid function pointer that can free the buffer.
/// The destructor will be called with the buffer and length when the string is garbage collected.
#[inline(always)]
pub unsafe fn new_external_onebyte_raw<'s>(
scope: &mut HandleScope<'s, ()>,
buffer: *mut char,
buffer_len: usize,
destructor: extern "C" fn(*mut char, usize),
) -> Option<Local<'s, String>> {
let buffer_len = buffer_len.try_into().ok()?;
unsafe {
scope.cast_local(|sd| {
let ptr = crate::support::cpp_new::<
crate::binding::RUST_ExternalOneByteString,
>();
crate::binding::RUST_ExternalOneByteString_RUST_ExternalOneByteString(
ptr,
buffer.cast::<char>(),
buffer_len,
Some(destructor),
sd.get_isolate_ptr().cast(),
);
v8__String__NewExternalOneByte(sd.get_isolate_ptr(), ptr.cast())
}) })
} }
} }

View file

@ -41,6 +41,10 @@ pub use std::os::raw::c_long as long;
pub type Opaque = [u8; 0]; pub type Opaque = [u8; 0];
pub(crate) fn cpp_new<T>() -> *mut T {
unsafe { crate::binding::RUST_new(std::mem::size_of::<T>()).cast() }
}
/// Pointer to object allocated on the C++ heap. The pointer may be null. /// Pointer to object allocated on the C++ heap. The pointer may be null.
#[repr(transparent)] #[repr(transparent)]
#[derive(Debug)] #[derive(Debug)]