Make @ModifyExpressionValue support FIELD opcode = PUTFIELD, PUTSTATIC
I have this code here :
if (bool) {
this.someField = someEpression;
} else {
this.someField = someOtherExpression;
}
I would like to be able to make one handler to changes the code to :
if (bool) {
this.someField = this.injectHandler(someEpression);
} else {
this.someField = this.injectHandler(someOtherExpression);
}
Would this involve dealing with potential dups, or ignoring them?
You can already do that with either @WrapOperation or @ModifyExpressionValue + @Expression (this.someField = @(?)). Do neither of those fulfil your goal?
If I was using ASM I would do the following:
Original bytecode:
// some instructions that leave a variable on the stack of same type as the field
// <--- inject here
// PUTFIELD owner, field name, field type
Edited bytecode:
// some instructions that leave a variable on the stack of same type as the field
// ALOAD 0
// INVOKEVIRTUAL owner, method name, signature = (Lfieldtype;)Lfieldtype;
// PUTFIELD owner, field name, field type
Doing such an operation is non destructive, it can chain and it doesn't allocate any objects. It really is one of the simpliest operations to do with ASM.
I don't know if I am missing something but this doesn't seem to be possible to do with mixins, using @WrapOperation is destructive, it makes a mess in the bytecode and (it allocates objects?).
And I could figure out your suggestion of using @ModifyExpressionValue + @Expression
WrapOperation can chain, and the assumption is that the jit will take care of the lambdas
@ModifyExpressionValue + @Expression is effectively
// some instructions that leave a variable on the stack of same type as the field
// <--- inject here
// PUTFIELD owner, field name, field type
the same as that
using
@WrapOperationis destructive, it makes a mess in the bytecode and (it allocates objects?).
But @ModifyExpressionValue is exactly what you want, so just use that.
using
@WrapOperationis destructive, it makes a mess in the bytecode and (it allocates objects?).But
@ModifyExpressionValueis exactly what you want, so just use that.
Doesn't work for PUT
@ModifyExpressionValue+@Expressionis effectively// some instructions that leave a variable on the stack of same type as the field // <--- inject here // PUTFIELD owner, field name, field type the same as that
What is this @Expression thing, I can't find it in my IDE, it's not on the wiki either
It is in the wiki. It's in the RCs.
Doesn't work for PUT
You are not modifying PUT, you are modifying someEpression or someOtherExpression in your original example.
@ModifyExpressionValue+@Expressionis effectively// some instructions that leave a variable on the stack of same type as the field // <--- inject here // PUTFIELD owner, field name, field type the same as that
how much stuff does it injects tho
it injects a call to your handler method, that takes the value on the stack, and returns a value of the same type.
in fabric mixin, it can even be just
//value on stack
INVOKESTATIC yourMethod
// newValue on stack
but what does the code in the @Mixin class looks like when using @Expression ? The expression stuff look overcomplicated when all I want is to inject 2 bytecodes. Would it make sense to add a new mixin injector that does this @ModifyFieldAllocation or whatever name you prefer.
I would be an injector that is non destructive, it can chain, it doesn't allocated any object, pretty straight forward stuff
@Definition(id = "someField", field = "LSomeClass;someField:LFieldType;")
@Expression("this.someField = @(?)")
@ModifyExpressionValue(method = "containingMethod", at = @At("MIXINEXTRAS:EXPRESSION"))
private FieldType modifyFieldAssignment(FieldType originalValue) {
return newValue;
}
Do you have the MinecraftDev plugin for IntelliJ? It can autocomplete all of this stuff.
Do you have the MinecraftDev plugin for IntelliJ? It can autocomplete all of this stuff.
ok how about this:
@ModifyFieldAllocation(method = "containingMethod", field = "LSomeClass;someField:LFieldType;")
private FieldType modifyFieldAssignment(FieldType originalValue) {
return newValue;
}
isn't it much more convinient
the theoretical @ModifyInput will also be able to do this, but I don't think it's too cumbersome to require targeting via expressions, especially with mcdcv
Anyways I think that @ModifyExpressionValue should just work out of the box with PUTFIELD to modify the value that is allocated to the field, that would be great and much more convinient than using the @Expression stuff.
If you do not agree it's whatever.
This will be covered by the hypothetical @ModifyInput, I don't want @ModifyExpressionValue to work like this.