Skip to content
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

Update to wasmtime v19 #322

Merged
merged 6 commits into from
May 10, 2024
Merged

Update to wasmtime v19 #322

merged 6 commits into from
May 10, 2024

Conversation

saulecabrera
Copy link
Member

@saulecabrera saulecabrera commented May 5, 2024

This commit reworks the bindings to support wasmtime v19 which introduces significant changes regarding reference types, namely ValType adds support for typed function refereces and GC. It's important to note that given that these features are not enabled by default, these proposals are not visible in wasmtime-rb's API surface. It's reasonable to add support for them once the implementation in Wasmtime proper is enabled by default, however, this commit paves the road in a couple of places to support the Ref type.

Full changelog: https://github.com/bytecodealliance/wasmtime/blob/main/RELEASES.md#1900

@@ -122,22 +127,42 @@ impl ToExtern for Value {
}

pub trait ToSym {
fn to_sym(self) -> Symbol;
fn as_sym(&self) -> Result<Symbol, Error>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ValType is no longer Copy, which is the main motivation for this change. I also suspect that once APIs for typed function reference and GC are introduced it's likely that we will have to rework the relationship between ValType and its Ruby representation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your rationale for the naming change?

#to_sym is the normal name for converting to a Symbol, so I think the name could stay the same even if it can now raise.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name change was mostly to reflect owned -> borrow in the signature, but then I realized that I misinterpreted this table https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv

Reverted!

@@ -10,9 +10,6 @@ struct Param {
index: u32,
ty: ValType,
}
// Keep `Param` small so copying it to the stack is cheap, typically anything
// less than 3usize is good
assert_eq_size!(Param, [u64; 2]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ValType is not Copy anymore, so I don't think this assert is useful anymore, but let me know if there's anything that I'm missing here cc @ianks

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may still have a small performance impact (we can benchmark it) but if that's the case we can come back to optimize it, it doesn't sound like a big deal?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a big deal to be honest, but we can always come back later if this ends up being an issue.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the new size of it? Can we assert on the new size instead to avoid accidentally bloating it?

@saulecabrera
Copy link
Member Author

macos-latest, 3.1 is reporting a dynamic linking error

dyld[10102]: missing symbol called

I'm not entirely sure what's going on, however, the symptoms look very similar to oxidize-rb/rb-sys#157

@@ -122,22 +127,42 @@ impl ToExtern for Value {
}

pub trait ToSym {
fn to_sym(self) -> Symbol;
fn as_sym(&self) -> Result<Symbol, Error>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your rationale for the naming change?

#to_sym is the normal name for converting to a Symbol, so I think the name could stay the same even if it can now raise.

Comment on lines +67 to +92
if ty.matches(&ValType::EXTERNREF) {
let extern_ref_value = match self.is_nil() {
true => None,
false => Some(ExternRef::new(ExternRefValue::from(*self))),
};

return Ok(Val::ExternRef(extern_ref_value));
}

if ty.matches(&ValType::FUNCREF) {
let func_ref_value = match self.is_nil() {
true => None,
false => Some(*<&Func>::try_convert(*self)?.inner()),
};
return Ok(Val::FuncRef(func_ref_value));
}

match ty {
ValType::I32 => Ok(i32::try_convert(*self)?.into()),
ValType::I64 => Ok(i64::try_convert(*self)?.into()),
ValType::F32 => Ok(f32::try_convert(*self)?.into()),
ValType::F64 => Ok(f64::try_convert(*self)?.into()),
ValType::ExternRef => {
let extern_ref_value = match self.is_nil() {
true => None,
false => Some(ExternRef::new(ExternRefValue::from(*self))),
};

Ok(Val::ExternRef(extern_ref_value))
}
ValType::FuncRef => {
let func_ref_value = match self.is_nil() {
true => None,
false => Some(*<&Func>::try_convert(*self)?.inner()),
};
Ok(Val::FuncRef(func_ref_value))
}
ValType::V128 => err!("converting from Ruby to v128 not supported"),
// TODO: to be filled in once typed function references and/or GC
// are enabled by default.
t => err!("unsupported type: {t:?}"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit / suggestion: I think it reads nicely when the RefType is a nested match:

impl ToWasmVal for Value {
    fn to_wasm_val(&self, ty: ValType) -> Result<Val, Error> {
        match ty {
            ValType::I32 => Ok(i32::try_convert(*self)?.into()),
            ValType::I64 => Ok(i64::try_convert(*self)?.into()),
            ValType::F32 => Ok(f32::try_convert(*self)?.into()),
            ValType::F64 => Ok(f64::try_convert(*self)?.into()),
            ValType::V128 => err!("converting from Ruby to v128 not supported"),
            ValType::Ref(ty) => {
                if ty.matches(&RefType::EXTERNREF) {
                    let extern_ref_value = match self.is_nil() {
                        true => None,
                        false => Some(ExternRef::new(ExternRefValue::from(*self))),
                    };

                    Ok(Val::ExternRef(extern_ref_value))
                } else if ty.matches(&RefType::FUNCREF) {
                    let func_ref_value = match self.is_nil() {
                        true => None,
                        false => Some(*<&Func>::try_convert(*self)?.inner()),
                    };

                    Ok(Val::FuncRef(func_ref_value))
                } else {
                    // TODO: to be filled in once typed function references and/or GC
                    // are enabled by default.
                    err!("unsupported type: {ty:?}")
                }
            }
        }
    }
}

Same below. Use this version if you like it too, or disregard if you don't!

ext/src/ruby_api/func.rs Outdated Show resolved Hide resolved
@@ -10,9 +10,6 @@ struct Param {
index: u32,
ty: ValType,
}
// Keep `Param` small so copying it to the stack is cheap, typically anything
// less than 3usize is good
assert_eq_size!(Param, [u64; 2]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may still have a small performance impact (we can benchmark it) but if that's the case we can come back to optimize it, it doesn't sound like a big deal?

@ianks
Copy link
Collaborator

ianks commented May 9, 2024

You can disable the rust-crate example on ruby 3.1, no idea what's going on there and why it's now failing 🤔

This commit reworks the bindings to support `wasmtime` 19 which introduces significant changes regarding reference types, namely `ValType` adds support for typed function refereces and GC. It's important to note that given that these features are not enabled by default, these proposals are not visible in `wasmtime-rb`'s API surface. It's reasonable to add support for them once the implementation in Wasmtime proper is enabled by default, however, this commit paves the road in a couple of places to support the `Ref` type.
Errors in cross store args/returns have changed, this commit updates the test expectations to match those changes and also fixes a multiple dynamic borros bug.
Updates the gem's version
@saulecabrera saulecabrera merged commit ffd785c into main May 10, 2024
23 checks passed
@saulecabrera saulecabrera deleted the update-to-wasmtime-v19 branch May 10, 2024 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants