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

Breaking or Continuing a loop with mixins? #55

Closed
thomas15v opened this issue Jun 28, 2015 · 6 comments
Closed

Breaking or Continuing a loop with mixins? #55

thomas15v opened this issue Jun 28, 2015 · 6 comments

Comments

@thomas15v
Copy link

I am going to explain it with an example.

public void dostuff(){
    for (int i = 0; i < 200; i++){
        doOtherstuff(i);
    }
}

Lets say I want a mixin like this:

//inject might be incorrect
@Inject(method = "dostuff()V", at = @At(value = "INVOKE", target = "Exampleclass.doOtherstuff(I)V", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILSOFT, cancellable = true)
private void continueLoop(CallbackInfo callbackInfo, int i){
    if (i == 50) {
        continue; // Doesn't work because we aren't in a loop
        callbackInfo.cancel(); //will stop the loop and return. does not continue to work on number 51
    }
}
@Mumfrey
Copy link
Member

Mumfrey commented Jun 28, 2015

This is pretty much impossible.

@Mumfrey
Copy link
Member

Mumfrey commented Jun 28, 2015

However there are other things which are planned which you could probably leverage to do something like that.

@Lunaphied
Copy link

Why is this impossible?

@Mumfrey
Copy link
Member

Mumfrey commented Jun 29, 2015

Because there's no such thing as a loop or the concept of continue in bytecode, the compiler converts it all to jumps. Working out where a loop is is incredibly difficult, working out the semantics of a continue at an arbitrary point in the bytecode would be much harder.

Okay, "impossible" is probably over-stating somewhat, but "incredibly hard, bordering on impossible" would be closer.

@thomas15v
Copy link
Author

Wouldn't it be possible to make something like this:

callbackInfo.goto("L1");

Than this also could be helpfully to overwrite pieces of code in a method. Like you inject and than jump over the code you don't want to use anymore.

@Mumfrey
Copy link
Member

Mumfrey commented Jun 29, 2015

No, injectors already are a little too close to needing to understand bytecode for my liking, but there's no way around it. With rerouters, understanding bytecode is actually required but the code generated is still safe. There is no way I am going to allow the mixin author to control the bytecode, see this old reply, that is not what mixin is about.

Mixin isn't just a library for "making ASM hackery easy", that is not what it is about. It is a way of defining deterministic transformations to target classes which can be generated and injected into the target class in such a way that the output bytecode falls in to one of two guarantees:

  • The bytecode will be sane OR
  • The bytecode will not be injected

This is why there are so many checks and balances in Mixin and why any type of hackery is not happening.

Rerouters are by the far the hackiest feature, and are not going to be released until I'm satisfied that the LVT inflection upon which they rely is stable to my satisfaction. Even then, their scope is limited such that the code they inject will always be sane.

This has always been the case, people get so fixated on doing things with mixins that they forget that you can do whatever you want to with a transformer. But I am not prepared to ever let the end user have any direct control over the bytecode which is injected. Literally the only exception to this currently is the BY argument in @At annotations, and that only exists because that functionality was ported directly from liteloader and I didn't think to remove it at the time.

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

No branches or pull requests

3 participants