-
Notifications
You must be signed in to change notification settings - Fork 18
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
Support for deopts in promises #1177
base: master
Are you sure you want to change the base?
Conversation
Watch out for this annotation here which needs to be removed, or actually only put there if it is a non-promise: https://github.com/reactorlabs/rir/blob/master/rir/src/compiler/native/builtins.cpp#L2448 |
Oh, I just removed it.. maybe have two versions of deoptImpl then, one for promises and one for closures |
sorry I somehow completely missed that you did already. but yeah, it should help llvm with optimizations. maybe drop the attribute, but keep the unreachable for the cases where it is not a promise? that should be equally good as the no return annotation. |
79a10dd
to
f750863
Compare
Here are some stats for your PR:
Please find your performance results at https://rir-benchmarks.prl.fit.cvut.cz/diff?job_ids[]=2479130138&job_ids[]=2467128976&selection=all |
Because of an optimization where we replace the first checkpoint in an inlinee by the checkpoint at the callsite it is possible to take the outer deopt exit from within the inlinee. In case the inlinee needs its own context we need to pop it, otherwise the context offsets in MkEnv instructions in the deopt block would modify the wrong frame. ``` a = checkpoint -> [deopt with (mkenv ... context 1)] ... c = push_context .... assume ..., a -> we have to pop c ``` The other option would be to make the context field in MkEnvs a PIR variable and then set it to the correct value based on where we come from, however, this seems easier.
This adds support for deopting from promises that are the outermost frame when deopting. The mechanism is that if the outermost frame is a promise, we don't longjump to a context (since promises don't have contexts), but rather return the result. This is the only case when deopt returns, and we immediately return also from the promise code with the result, passing it to the place where the promise forcing occured.
Here are some stats for your PR:
Please find your performance results at https://rir-benchmarks.prl.fit.cvut.cz/diff?job_ids[]=2599407256&job_ids[]=2578982488&selection=all |
If there is a deoptimization in a promise (that is also the outermost frame, ie.,
forcing a promise that isn't inlined), we cannot longjump out of the optimized
execution, since the promise doesn't have its own context.
Thus we add a return instruction immediately after the deopt, which is only reached
if there was no longjump. In that case, we know that this is the evaluation of
a promise that deoptimized, and the result is left on the stack to be returned.
TODO: actually use speculation in promises (most passes don't run on promises as of now)