-
Notifications
You must be signed in to change notification settings - Fork 96
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
feat: op2 codegen for object methods #682
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #682 +/- ##
==========================================
+ Coverage 81.14% 81.23% +0.09%
==========================================
Files 96 96
Lines 24347 24493 +146
==========================================
+ Hits 19756 19897 +141
- Misses 4591 4596 +5 ☔ View full report in Codecov by Sentry. |
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.
Let's do a small change to break the this
change out and then work through this.
@@ -503,7 +518,7 @@ pub(crate) fn generate_dispatch_fast( | |||
|
|||
#[allow(clippy::too_many_arguments)] | |||
extern "C" fn #fast_function( | |||
_: deno_core::v8::Local<deno_core::v8::Object>, |
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.
Let's split this one line change into its own PR + the test changes to reduce the PR size.
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.
it will be a warning (unused argument) if landed seperately
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.
No worries -- just add allow(unused)
for it. We can remove that at a later date.
@@ -323,6 +323,17 @@ pub(crate) fn initialize_deno_core_ops_bindings<'s>( | |||
} | |||
} | |||
|
|||
pub fn register_op_method( |
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.
We should try to create these once when the JsRuntime is created and then look them up.
@@ -183,8 +183,6 @@ impl InnerIsolateState { | |||
unsafe { | |||
ManuallyDrop::take(&mut self.main_realm).0.destroy(); | |||
} | |||
|
|||
debug_assert_eq!(Rc::strong_count(&self.state), 1); |
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.
This is definitely a smell here -- we're leaking OpCtxs.
@@ -439,6 +439,21 @@ pub(crate) fn generate_dispatch_fast( | |||
quote!() | |||
}; | |||
|
|||
let with_self = if generator_state.needs_self { | |||
gs_quote!(generator_state(self_ty) => { | |||
let self_: &#self_ty = deno_core::cppgc::try_unwrap_cppgc_object(this.into()).unwrap(); |
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.
👍 awesome
}; | ||
|
||
if *needs_self { | ||
let register = format_ident!("register_{name}"); |
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.
This shouldn't be necessary -- this code is effectively the same as if it were on the OpDecl
itself.
@@ -122,13 +124,14 @@ fn generate_op2( | |||
zip(signature.args.iter(), &func.sig.inputs).collect::<Vec<_>>(); | |||
|
|||
let mut args = vec![]; | |||
let mut needs_args = false; | |||
let mut needs_args = config.method.is_some(); |
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.
Aren't we using the receiver for self? This shouldn't change, right?
@@ -1345,6 +1349,7 @@ fn parse_type_path( | |||
} | |||
( OpState ) => Ok(CBare(TSpecial(Special::OpState))), | |||
( JsRuntimeState ) => Ok(CBare(TSpecial(Special::JsRuntimeState))), | |||
( OpCtx ) => Ok(CBare(TSpecial(Special::OpCtx))), |
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.
I don't think any of this OpCtx stuff will be necessary in the end
Ok, looked through this PR a few times and I think I know the right plan here. Ignore my previous comment about a
eg, this should work:
We don't currently support this style of op because we're using a struct, and structs can't be nested in
|
Switch op declaration from a `impl #name` to a `const fn #name`. Based on Matt's suggestion in denoland#682 [Playground link](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=2d7152d548b4a466779c401551b21b05) This patch wraps `const` around the existing `impl` codegen to unblock work on op2++
Switch op declaration from a `impl #name` to a `const fn #name`. This form for declaration can be used inside `impl` blocks. ```rust struct Foo {} impl Foo { #[op2(fast)] pub fn bar(#[state] state: &mut OpState) {} } // const DECL: OpDecl = Foo::bar(); ``` Based on Matt's suggestion in #682 [Playground link](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=2d7152d548b4a466779c401551b21b05) This patch wraps `const` around the existing `impl` codegen to unblock work on op2++
Refactor out codegen for `&self` from #682 ```rust struct State { name: &'static str, } impl State { #[op2(fast, method(State)] fn print(&self) { println!("{}", self.name); } } const STATE_DECL: [OpDecl; 1] = [ State::print() ]; ```
Awesome |
Introducing op2++ (a.k.a
op2
for object methods).op2++ is to op2 as C++ is to C.
This patch introduces a small extension on top of the existing op2 codegen infrastructure to enable writing cppgc object methods in Rust:
Notable changes:
&OpCtx
as argument, required for registration of methods.method(Type)
where Type is thetype
of the recieverself
. Due to the independent nature of op2 codegen we need to know the concrete type.Type::register_op
that can be called to register the method onto a Cppgc object.Future work could make these constructors transparent by processing
impl
s.