From 9a6e90be3820dff296de9f90923ca59010989ecd Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Tue, 22 Oct 2019 14:52:43 -0700 Subject: [PATCH] Add Task --- build.rs | 1 + src/main.rs | 54 ++++++++++-- src/support.rs | 57 +++++------- src/v8/inspector/channel.cpp | 13 ++- src/v8/inspector/channel.rs | 11 +-- src/v8/inspector/client.cpp | 11 +-- src/v8/inspector/client.rs | 11 +-- src/v8/mod.rs | 1 + src/v8/platform/mod.rs | 3 + src/v8/platform/task.cpp | 32 +++++++ src/v8/platform/task.rs | 164 +++++++++++++++++++++++++++++++++++ 11 files changed, 283 insertions(+), 75 deletions(-) create mode 100644 src/v8/platform/mod.rs create mode 100644 src/v8/platform/task.cpp create mode 100644 src/v8/platform/task.rs diff --git a/build.rs b/build.rs index 17db9844..bc62a75d 100644 --- a/build.rs +++ b/build.rs @@ -7,6 +7,7 @@ fn main() { .debug(true) .file("src/v8/inspector/channel.cpp") .file("src/v8/inspector/client.cpp") + .file("src/v8/platform/task.cpp") .file("src/v8/string_buffer.cpp") .compile("v8-bindings"); diff --git a/src/main.rs b/src/main.rs index 5db7dd2d..62e10490 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,15 +7,16 @@ mod v8; mod example { use crate::support::UniquePtr; use crate::v8::inspector::channel::*; + use crate::v8::platform::task::*; use crate::v8::*; - pub struct Example { + pub struct TestChannel { a: i32, channel_base: ChannelBase, b: i32, } - impl ChannelImpl for Example { + impl ChannelImpl for TestChannel { fn base(&self) -> &ChannelBase { &self.channel_base } @@ -37,7 +38,7 @@ mod example { fn flushProtocolNotifications(&mut self) {} } - impl Example { + impl TestChannel { pub fn new() -> Self { Self { channel_base: ChannelBase::new::(), @@ -46,16 +47,59 @@ mod example { } } } + + pub struct TestTask { + a: i32, + base: TaskBase, + b: i32, + } + + impl TaskImpl for TestTask { + fn base(&self) -> &TaskBase { + &self.base + } + fn base_mut(&mut self) -> &mut TaskBase { + &mut self.base + } + fn Run(&mut self) -> () { + println!("TestTask::Run {} {}", self.a, self.b); + } + } + + impl TestTask { + pub fn new() -> Self { + Self { + base: TaskBase::new::(), + a: 2, + b: 3, + } + } + } + + impl Drop for TestTask { + fn drop(&mut self) { + println!("TestTask::drop()"); + } + } } -fn main() { +fn main1() { use crate::v8::inspector::channel::*; use crate::v8::*; use example::*; - let mut ex = Example::new(); + let mut ex = TestChannel::new(); let chan = ex.as_channel_mut(); let message = b"hello"; let message = StringView::from(&message[..]); let message = StringBuffer::create(&message); chan.sendResponse(3, message); } + +fn main() { + use crate::v8::platform::task::*; + use example::*; + let mut v = TestTask::new(); + v.Run(); + let b = Box::new(v); + b.into_unique_ptr(); +} diff --git a/src/support.rs b/src/support.rs index 4bae789a..7d3e661b 100644 --- a/src/support.rs +++ b/src/support.rs @@ -1,6 +1,8 @@ use std::marker::PhantomData; use std::mem::size_of; -use std::ops::{Deref, DerefMut}; +use std::mem::transmute; +use std::ops::Deref; +use std::ops::DerefMut; pub use std::os::raw::c_int as int; @@ -20,6 +22,23 @@ pub struct UniquePtr(Option<&'static mut T>) where T: Delete; +impl UniquePtr +where + T: Delete, +{ + pub fn null() -> Self { + Self(None) + } + + pub fn new(r: &'static mut T) -> Self { + Self(Some(r)) + } + + pub unsafe fn from_raw(p: *mut T) -> Self { + transmute(p) + } +} + impl Deref for UniquePtr where T: Delete, @@ -48,42 +67,6 @@ where } } -/// Reference to object allocated on the C++ heap, similar to UniquePtr, -/// but guaranteed to never contain a nullptr. -#[repr(transparent)] -pub struct UniqueRef(&'static mut T) -where - T: Delete; - -impl Deref for UniqueRef -where - T: Delete, -{ - type Target = T; - fn deref(&self) -> &Self::Target { - self.0 - } -} - -impl DerefMut for UniqueRef -where - T: Delete, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - self.0 - } -} - -impl Drop for UniqueRef -where - T: Delete, -{ - fn drop(&mut self) { - let ptr: &'static mut T = unsafe { std::mem::transmute_copy(self.0) }; - ptr.delete(); - } -} - #[derive(Copy, Clone, Debug)] #[repr(transparent)] pub struct CxxVTable(pub *const Opaque); diff --git a/src/v8/inspector/channel.cpp b/src/v8/inspector/channel.cpp index bd1b5cf7..7ea373bf 100644 --- a/src/v8/inspector/channel.cpp +++ b/src/v8/inspector/channel.cpp @@ -19,28 +19,25 @@ void v8_inspector__V8Inspector__Channel__BASE__flushProtocolNotifications( struct v8_inspector__V8Inspector__Channel__BASE : public V8Inspector::Channel { using V8Inspector::Channel::Channel; - inline void sendResponse(int callId, - std::unique_ptr message) override { + void sendResponse(int callId, + std::unique_ptr message) override { v8_inspector__V8Inspector__Channel__BASE__sendResponse(*this, callId, message.release()); } - inline void sendNotification(std::unique_ptr message) override { + void sendNotification(std::unique_ptr message) override { v8_inspector__V8Inspector__Channel__BASE__sendNotification( *this, message.release()); } - inline void flushProtocolNotifications() override { + void flushProtocolNotifications() override { v8_inspector__V8Inspector__Channel__BASE__flushProtocolNotifications(*this); } }; extern "C" { -void v8_inspector__V8Inspector__Channel__BASE__CTOR( +void v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT( uninit_t& buf) { construct_in_place(buf); } -void v8_inspector__V8Inspector__Channel__DTOR(V8Inspector::Channel& self) { - self.~Channel(); -} void v8_inspector__V8Inspector__Channel__sendResponse( V8Inspector::Channel& self, diff --git a/src/v8/inspector/channel.rs b/src/v8/inspector/channel.rs index 2df051b0..831d623d 100644 --- a/src/v8/inspector/channel.rs +++ b/src/v8/inspector/channel.rs @@ -16,10 +16,9 @@ use crate::v8::StringBuffer; // }; extern "C" { - fn v8_inspector__V8Inspector__Channel__BASE__CTOR( + fn v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT( buf: &mut std::mem::MaybeUninit, ) -> (); - fn v8_inspector__V8Inspector__Channel__DTOR(this: &mut Channel) -> (); fn v8_inspector__V8Inspector__Channel__sendResponse( this: &mut Channel, @@ -86,12 +85,6 @@ impl Channel { } } -impl Drop for Channel { - fn drop(&mut self) { - unsafe { v8_inspector__V8Inspector__Channel__DTOR(self) } - } -} - pub trait AsChannel { fn as_channel(&self) -> &Channel; fn as_channel_mut(&mut self) -> &mut Channel; @@ -141,7 +134,7 @@ impl ChannelBase { fn construct_cxx_base() -> Channel { unsafe { let mut buf = std::mem::MaybeUninit::::uninit(); - v8_inspector__V8Inspector__Channel__BASE__CTOR(&mut buf); + v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(&mut buf); buf.assume_init() } } diff --git a/src/v8/inspector/client.cpp b/src/v8/inspector/client.cpp index 7480ddff..738da3f1 100644 --- a/src/v8/inspector/client.cpp +++ b/src/v8/inspector/client.cpp @@ -18,27 +18,24 @@ void v8_inspector__V8InspectorClient__BASE__runIfWaitingForDebugger( struct v8_inspector__V8InspectorClient__BASE : public V8InspectorClient { using V8InspectorClient::V8InspectorClient; - inline void runMessageLoopOnPause(int contextGroupId) override { + void runMessageLoopOnPause(int contextGroupId) override { v8_inspector__V8InspectorClient__BASE__runMessageLoopOnPause( *this, contextGroupId); } - inline void quitMessageLoopOnPause() override { + void quitMessageLoopOnPause() override { v8_inspector__V8InspectorClient__BASE__quitMessageLoopOnPause(*this); } - inline void runIfWaitingForDebugger(int contextGroupId) override { + void runIfWaitingForDebugger(int contextGroupId) override { v8_inspector__V8InspectorClient__BASE__runIfWaitingForDebugger( *this, contextGroupId); } }; extern "C" { -void v8_inspector__V8InspectorClient__BASE__CTOR( +void v8_inspector__V8InspectorClient__BASE__CONSTRUCT( uninit_t& buf) { construct_in_place(buf); } -void v8_inspector__V8InspectorClient__DTOR(V8InspectorClient& self) { - self.~V8InspectorClient(); -} void v8_inspector__V8InspectorClient__runMessageLoopOnPause( V8InspectorClient& self, diff --git a/src/v8/inspector/client.rs b/src/v8/inspector/client.rs index d5168761..1113f4d6 100644 --- a/src/v8/inspector/client.rs +++ b/src/v8/inspector/client.rs @@ -67,10 +67,9 @@ use crate::support::RustVTable; // }; extern "C" { - fn v8_inspector__V8InspectorClient__BASE__CTOR( + fn v8_inspector__V8InspectorClient__BASE__CONSTRUCT( buf: &mut std::mem::MaybeUninit, ) -> (); - fn v8_inspector__V8InspectorClient__DTOR(this: &mut Client) -> (); fn v8_inspector__V8InspectorClient__runMessageLoopOnPause( this: &mut Client, @@ -135,12 +134,6 @@ impl Client { } } -impl Drop for Client { - fn drop(&mut self) { - unsafe { v8_inspector__V8InspectorClient__DTOR(self) } - } -} - pub trait AsClient { fn as_client(&self) -> &Client; fn as_client_mut(&mut self) -> &mut Client; @@ -187,7 +180,7 @@ impl ClientBase { fn construct_cxx_base() -> Client { unsafe { let mut buf = std::mem::MaybeUninit::::uninit(); - v8_inspector__V8InspectorClient__BASE__CTOR(&mut buf); + v8_inspector__V8InspectorClient__BASE__CONSTRUCT(&mut buf); buf.assume_init() } } diff --git a/src/v8/mod.rs b/src/v8/mod.rs index d04e4373..6a9237fb 100644 --- a/src/v8/mod.rs +++ b/src/v8/mod.rs @@ -1,4 +1,5 @@ pub mod inspector; +pub mod platform; pub mod string_buffer; pub mod string_view; diff --git a/src/v8/platform/mod.rs b/src/v8/platform/mod.rs new file mode 100644 index 00000000..71550415 --- /dev/null +++ b/src/v8/platform/mod.rs @@ -0,0 +1,3 @@ +pub mod task; + +pub use task::Task; diff --git a/src/v8/platform/task.cpp b/src/v8/platform/task.cpp new file mode 100644 index 00000000..92049deb --- /dev/null +++ b/src/v8/platform/task.cpp @@ -0,0 +1,32 @@ +#include "../../../v8/include/v8-platform.h" +#include "../../support.h" + +#include + +using namespace v8; +using namespace support; + +extern "C" { +void v8__Task__BASE__DELETE(Task& self); +void v8__Task__BASE__Run(Task& self); +} // extern "C" + +struct v8__Task__BASE : public Task { + using Task::Task; + void operator delete(void* ptr) noexcept { + v8__Task__BASE__DELETE(*reinterpret_cast(ptr)); + } + void Run() override { v8__Task__BASE__Run(*this); } +}; + +extern "C" { +void v8__Task__BASE__CONSTRUCT(uninit_t& buf) { + construct_in_place(buf); +} +void v8__Task__DELETE(Task& self) { + delete &self; +} +void v8__Task__Run(Task& self) { + self.Run(); +} +} // extern "C" diff --git a/src/v8/platform/task.rs b/src/v8/platform/task.rs new file mode 100644 index 00000000..c9b05392 --- /dev/null +++ b/src/v8/platform/task.rs @@ -0,0 +1,164 @@ +use std::mem::drop; +use std::mem::forget; + +use crate::support::CxxVTable; +use crate::support::Delete; +use crate::support::FieldOffset; +use crate::support::Opaque; +use crate::support::RustVTable; +use crate::support::UniquePtr; + +// class Task { +// public: +// virtual ~Task() = default; +// virtual void Run() = 0; +// }; + +extern "C" { + fn v8__Task__BASE__CONSTRUCT(buf: &mut std::mem::MaybeUninit) -> (); + fn v8__Task__DELETE(this: &'static mut Task) -> (); + fn v8__Task__Run(this: &mut Task) -> (); +} + +#[no_mangle] +pub unsafe extern "C" fn v8__Task__BASE__DELETE(this: &mut Task) -> () { + println!("v8__Task__BASE__DELETE"); + drop(TaskBase::dispatch_box(this)) +} + +#[no_mangle] +pub unsafe extern "C" fn v8__Task__BASE__Run(this: &mut Task) -> () { + TaskBase::dispatch_mut(this).Run() +} + +#[repr(C)] +pub struct Task { + _cxx_vtable: CxxVTable, +} + +impl Task { + pub fn Run(&mut self) -> () { + unsafe { v8__Task__Run(self) } + } +} + +impl Delete for Task { + fn delete(&'static mut self) { + println!("Task::delete()"); + unsafe { v8__Task__DELETE(self) } + } +} + +pub trait AsTask { + fn as_task(&self) -> &Task; + fn as_task_mut(&mut self) -> &mut Task; + + // TODO: this should be a trait in itself. + fn into_unique_ptr(mut self: Box) -> UniquePtr + where + Self: 'static, + { + let task = self.as_task_mut() as *mut Task; + forget(self); + unsafe { UniquePtr::from_raw(task) } + } +} + +impl AsTask for Task { + fn as_task(&self) -> &Task { + self + } + fn as_task_mut(&mut self) -> &mut Task { + self + } +} + +impl AsTask for T +where + T: TaskImpl, +{ + fn as_task(&self) -> &Task { + &self.base().cxx_base + } + fn as_task_mut(&mut self) -> &mut Task { + &mut self.base_mut().cxx_base + } +} + +pub trait TaskImpl: AsTask { + fn base(&self) -> &TaskBase; + fn base_mut(&mut self) -> &mut TaskBase; + fn Run(&mut self) -> (); +} + +pub struct TaskBase { + cxx_base: Task, + offset_within_embedder: FieldOffset, + rust_vtable: RustVTable<&'static dyn TaskImpl>, +} + +impl TaskBase { + fn construct_cxx_base() -> Task { + unsafe { + let mut buf = std::mem::MaybeUninit::::uninit(); + v8__Task__BASE__CONSTRUCT(&mut buf); + buf.assume_init() + } + } + + fn get_cxx_base_offset() -> FieldOffset { + let buf = std::mem::MaybeUninit::::uninit(); + FieldOffset::from_ptrs(buf.as_ptr(), unsafe { &(*buf.as_ptr()).cxx_base }) + } + + fn get_offset_within_embedder() -> FieldOffset + where + T: TaskImpl, + { + let buf = std::mem::MaybeUninit::::uninit(); + let embedder_ptr: *const T = buf.as_ptr(); + let self_ptr: *const Self = unsafe { (*embedder_ptr).base() }; + FieldOffset::from_ptrs(embedder_ptr, self_ptr) + } + + fn get_rust_vtable() -> RustVTable<&'static dyn TaskImpl> + where + T: TaskImpl, + { + let buf = std::mem::MaybeUninit::::uninit(); + let embedder_ptr = buf.as_ptr(); + let trait_object: *const dyn TaskImpl = embedder_ptr; + let (data_ptr, vtable): (*const T, RustVTable<_>) = + unsafe { std::mem::transmute(trait_object) }; + assert_eq!(data_ptr, embedder_ptr); + vtable + } + + pub fn new() -> Self + where + T: TaskImpl, + { + Self { + cxx_base: Self::construct_cxx_base(), + offset_within_embedder: Self::get_offset_within_embedder::(), + rust_vtable: Self::get_rust_vtable::(), + } + } + + pub unsafe fn dispatch(task: &Task) -> &dyn TaskImpl { + let this = Self::get_cxx_base_offset().to_embedder::(task); + let embedder = this.offset_within_embedder.to_embedder::(this); + std::mem::transmute((embedder, this.rust_vtable)) + } + + pub unsafe fn dispatch_mut(task: &mut Task) -> &mut dyn TaskImpl { + let this = Self::get_cxx_base_offset().to_embedder_mut::(task); + let vtable = this.rust_vtable; + let embedder = this.offset_within_embedder.to_embedder_mut::(this); + std::mem::transmute((embedder, vtable)) + } + + pub unsafe fn dispatch_box(task: &mut Task) -> Box { + std::mem::transmute(Self::dispatch_mut(task)) + } +}