-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add support for printing to JIT #4262
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
base: main
Are you sure you want to change the base?
Conversation
| let function = self.stack.pop().ok_or(JitCompileError::BadBytecode)?; | ||
|
|
||
| match (arg1.ty, function.ty) { | ||
| (JitType::Int, JitType::PrintFunction) => { |
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 generally haven't touched on the jit folder and have no real experience with cranelift. Is my understanding correct that what this PR allows is a subcase of the Python print, i.e: print(some_int_value)?
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.
Exactly. print with exactly one int argument works.
With thanks to https://zmedley.com/calling-rust.html for showing me how to do this.
|
Hey, I've been thinking about adding something similar recently (function calls), but had some different ideas. My initial idea would be to add a That would allows us to restore control back to the VM and call functions that way. This also means that we can load globals from the global list in the VM and return What do you think about that? (The obvious downside is that this is WAYYYY slower than a direct function call as you are doing here, although we can probably specialize later) |
| @@ -33,10 +34,19 @@ struct Jit { | |||
| module: JITModule, | |||
| } | |||
|
|
|||
| // TODO: print should return None | |||
| pub fn print_fun(a: i64) -> i64 { | |||
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 probably want to make this extern "C" so that its compatible with the calling convention that we selected in the signature that was sent to cranelift.
Right now it uses the Rust calling convention which is unstable. Although for a single argument / return function it's probably going to match and work out.
Edit: Also, maybe we should prefix these functions with something that indicates that they belong to the JIT Run Time instead of being user functions?
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.
Good catch. I think I might just put them in a different file/mod?
| @@ -165,6 +180,7 @@ pub enum JitType { | |||
| Int, | |||
| Float, | |||
| Bool, | |||
| PrintFunction, | |||
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.
Would it make sense to represent this as Function(enum JITFunction) or something along those lines?
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 think that would make sense when adding a second builtin function. See also #4263.
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.
Yeah, sounds good 👍
|
Definitely sounds like a good long term goal. I don't understand enough about how memory management in cranelift works to do this. Realistically most JITs also have both: 1. Fast native calls 2. Slower calls into the VM. |
Right, just wanted to know if you had any thoughts on how to expand from here! I think this is a good start on getting external function calls. If you need any help working on cranelift feel free to @ me, I'll try my best to help out. (Or ask in the wasmtime zulip!) |
|
Hey both! This sounds like something that could warrant an issue to hammer the details out. I have no familiarity with cranelift (yet!) but I'd follow your discussion to get a grip on things. It would be nice to see how other JITs tackle these things (built with or without cranelift) and what tradeoffs exist with each approach. |
|
Yeah we should definitely do that! I'm really only familiar with how Wasmtime works, but I don't mind looking into a few more JIT's and writing a summary. (If anyone has a favorite one that they would like me to look into, let me know!) |
| @@ -33,10 +34,19 @@ struct Jit { | |||
| module: JITModule, | |||
| } | |||
|
|
|||
| // TODO: print should return None | |||
| pub fn print_fun(a: i64) -> i64 { | |||
| println!("PRINT: {a}"); | |||
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 am confused here. would print(1) be compiled to print PRINT: {a} instead of {a}? Then it will not be compatible to pure python behavior.
I've opened #4271 which turned out way bigger than I thought it was going to be. Hopefully if we can pin that down we are then able to make a decision about this! |
|
I am sorry. I tried to rebase this PR but not easy because many things changed. |
With thanks to https://zmedley.com/calling-rust.html for showing me how to do this.