0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-21 15:04:33 -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=BUILD.gn");
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
// probably more than what is needed, but missing an important
@ -147,7 +149,11 @@ fn build_binding() {
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.clang_args(["-x", "c++", "-std=c++20", "-Iv8/include"])
.clang_args(args)
.respect_cxx_access_specs(true)
.allowlist_item("RUST_.*")
.blocklist_item("v8::.*")
.blocklist_item("cppgc::.*")
.blocklist_item("std::.*")
.generate()
.expect("Unable to generate bindings");

View file

@ -1,4 +1,6 @@
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
#include "binding.hpp"
#include <algorithm>
#include <cassert>
#include <cstddef>
@ -1071,35 +1073,6 @@ v8__String__GetExternalStringResourceBase(const v8::String& self,
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
: public v8::String::ExternalOneByteStringResource {
public:
@ -1138,7 +1111,7 @@ class ExternalConstOneByteStringResource
const int _length;
};
const v8::String* v8__String__NewExternalOneByteConst(
const v8::String* v8__String__NewExternalOneByte(
v8::Isolate* isolate, v8::String::ExternalOneByteStringResource* 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)));
}
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(
v8::String::ExternalOneByteStringResource* self) {
return self->data();
@ -3787,31 +3753,23 @@ void v8__PropertyDescriptor__set_configurable(v8::PropertyDescriptor* self,
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"
// cppgc
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,
v8::CppHeapPointerTag 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,
RustTraceFn trace,
RustDestroyFn destroy) {
RustObj::RustTraceFn trace,
RustObj::RustDestroyFn destroy) {
return cppgc::MakeGarbageCollected<RustObj>(heap->GetAllocationHandle(),
cppgc::AdditionalBytes(size),
trace, destroy);
@ -3948,4 +3906,5 @@ RustObj* cppgc__WeakPersistent__Get(cppgc::WeakPersistent<RustObj>* self) {
return self->Get();
}
//
} // extern "C"

View file

@ -1,4 +1,5 @@
#include <v8-cppgc.h>
#include <v8-isolate.h>
#include <v8-message.h>
/**
@ -6,12 +7,53 @@
* and made available in `crate::binding` in rust.
*/
namespace {
extern "C" {
class RUST_ExternalOneByteString
: 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);
class RustObj;
~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_cppgc__Member_SIZE = sizeof(cppgc::Member<RustObj>);

View file

@ -1,4 +1,7 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
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,
) -> *mut ExternalStringResourceBase;
fn v8__String__NewExternalOneByteConst(
isolate: *mut Isolate,
onebyte_const: *const OneByteConst,
) -> *const String;
fn v8__String__NewExternalOneByteStatic(
isolate: *mut Isolate,
buffer: *const char,
@ -92,9 +87,7 @@ extern "C" {
fn v8__String__NewExternalOneByte(
isolate: *mut Isolate,
buffer: *mut char,
length: int,
free: extern "C" fn(*mut char, size_t),
resource: *mut ExternalOneByteStringResource,
) -> *const String;
fn v8__String__NewExternalTwoByteStatic(
@ -571,7 +564,11 @@ impl String {
) -> Option<Local<'s, String>> {
unsafe {
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()?;
unsafe {
scope.cast_local(|sd| {
v8__String__NewExternalOneByte(
sd.get_isolate_ptr(),
let ptr = crate::support::cpp_new::<
crate::binding::RUST_ExternalOneByteString,
>();
crate::binding::RUST_ExternalOneByteString_RUST_ExternalOneByteString(
ptr,
Box::into_raw(buffer).cast::<char>(),
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(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.
#[repr(transparent)]
#[derive(Debug)]