-
Notifications
You must be signed in to change notification settings - Fork 110
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
Reuse runtime when compiling source code to bytecode #781
Conversation
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.
The code changes LGTM. However, I think I'm a bit conflicted by the open questions and assumption around the change.
If a plugin were to change any JS runtime configurations and if any of those configurations were to effect QuickJS bytecode emission
Do we have any evidence of which configurations of the ones that we allow might affect compilation to bytecode? Naively, I assumed that most of those features wouldn't change compilation and only affect the runtime behavior. But maybe that assumption is not correct.
An unfortunate result of this change is the a fresh instance would need to be used after invoking compile_src if invoke were called were called with a JS function.
It's probably unlikely that anyone is relying on this; however, if we end up settling on this approach, it might be worth considering adding some documentation around it, which I suspect will require a bit more of investigation to get to the bottom of the root cause.
I have evidence when changing the Given a JS program that looks like this: function foo() {
"use math"
1234 % 32
} With
With
These are slightly different. The 164th, 209th, and 210th characters are different.
Adding documentation around the limitation makes sense. I could spend more time looking into the root cause but alternatively, we could also just say it's not supported right now and if someone complains, we can look more into exactly what's going on at that point. |
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.
Thanks for investigating this and for your patience here. I think it might make sense to include the results of your findings as part of a comment in the code.
Adding documentation around the limitation makes sense. I could spend more time looking into the root cause but alternatively, we could also just say it's not supported right now and if someone complains, we can look more into exactly what's going on at that point.
The part that I struggle the most with is the "fresh instance" part of the workaround, however, I do agree that monitoring and digging deeper when/if more issues arise is probably best.
@@ -43,8 +43,7 @@ pub extern "C" fn init() { | |||
/// * `js_src_ptr` must reference a valid array of unsigned bytes of `js_src_len` length | |||
#[export_name = "compile_src"] | |||
pub unsafe extern "C" fn compile_src(js_src_ptr: *const u8, js_src_len: usize) -> *const u32 { | |||
// Use fresh runtime to avoid depending on Wizened runtime | |||
let runtime = runtime::new(Config::default()).unwrap(); | |||
let runtime = unsafe { RUNTIME.get().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.
Could you add some docs that include your comment?
The current constraint is that |
I experimented a bit with how we're loading the bytecode and I think I have a solution that will both solve the problem about not being able to re-use the instance/runtime and also reduce the instruction count when calling an exported function. I'll make that PR separately and then rebase this PR on top of that one. |
Description of the change
Re-use the runtime when compiling JS code to QuickJS bytecode. Also update the dylib test code to refresh the instance to work around the module being evaluated twice.
An unfortunate result of this change is the a fresh instance would need to be used after invoking
compile_src
ifinvoke
were called were called with a JS function. I don't think anyone would be relying on this behaviour. I'm also not entirely why we're seeing this behaviour. If I updateinvoke
to not callexecution::run_bytecode
, everything runs as expected if a fresh instance isn't created. However, if a fresh instance is used (as in the common use case), then QuickJS indicates the module has not been declared and traps.Why am I making this change?
Part of #768. If a plugin were to change any JS runtime configurations and if any of those configurations were to effect QuickJS bytecode emission, we would want to use that runtime configuration when compiling the QuickJS bytecode. Without this change, a default runtime configuration would be used instead which may not be intended.
An alternative approach is to persist the configuration generated in
wizer.initialize
and use that configuration when initializing the runtime incompile_src
. This approach will not continue to work if we were to add the ability to further customize the runtime inwizer.initialize
(which is planned).I also looked into if there was a way to "de-register" a JS module from a QuickJS context but couldn't find a way to do it. Hypothetically I could re-register an empty module with the same name after compiling the bytecode which may have a similar effect.
Checklist
javy-cli
andjavy-core
do not require updating CHANGELOG files.