Skip to content

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

evilpie
Copy link
Contributor

@evilpie evilpie commented Nov 5, 2022

With thanks to https://zmedley.com/calling-rust.html for showing me how to do this.

let function = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;

match (arg1.ty, function.ty) {
(JitType::Int, JitType::PrintFunction) => {
Copy link
Member

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)?

Copy link
Contributor Author

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.
@afonso360
Copy link
Contributor

afonso360 commented Nov 7, 2022

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 vmctx arg that we pass through all JIT functions. Right now that could be a pointer to the VirtualMachine instance (although we can change that in the future!).

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 PyRef references back to the JIT'ed code that we can use later.

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 {
Copy link
Contributor

@afonso360 afonso360 Nov 8, 2022

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?

Copy link
Contributor Author

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,
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, sounds good 👍

@evilpie
Copy link
Contributor Author

evilpie commented Nov 8, 2022

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.

@afonso360
Copy link
Contributor

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!)

@DimitrisJim
Copy link
Member

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.

@afonso360
Copy link
Contributor

afonso360 commented Nov 8, 2022

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}");
Copy link
Member

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.

@afonso360
Copy link
Contributor

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.

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!

@youknowone
Copy link
Member

I am sorry. I tried to rebase this PR but not easy because many things changed.

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.

4 participants