Skip to content

Commit

Permalink
Remove param transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
Matyrobbrt committed Jan 25, 2024
1 parent f2dc31c commit 469839c
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ default void extractWrapOperation(final MethodContext methodContext, final Metho
// Assume that people are only calling `call` on the operation object
if (!(
AdapterUtil.getIntConstValue(methodNode.instructions.get(loadInsnIndex + 1)).isPresent() &&
methodNode.instructions.get(loadInsnIndex + 2) instanceof TypeInsnNode n && n.getOpcode() == Opcodes.ANEWARRAY
methodNode.instructions.get(loadInsnIndex + 2) instanceof TypeInsnNode n && n.getOpcode() == Opcodes.ANEWARRAY
)) {
return;
}
Expand Down Expand Up @@ -203,10 +203,24 @@ public void removeParameter(int index) {
methodNode.instructions.set(methodNode.instructions.get(methodNode.instructions.indexOf(objects[j - 1].get(0)) - 1), AdapterUtil.getIntConstInsn(j - 1));
}
}
methodNode.instructions.remove(methodNode.instructions.get(methodNode.instructions.indexOf(toRemove.get(0)) - 1));
methodNode.instructions.remove(methodNode.instructions.get(methodNode.instructions.indexOf(toRemove.get(toRemove.size() - 1)) + 1));
methodNode.instructions.remove(methodNode.instructions.get(methodNode.instructions.indexOf(toRemove.get(toRemove.size() - 1)) + 2));

final AbstractInsnNode dup = methodNode.instructions.get(methodNode.instructions.indexOf(toRemove.get(toRemove.size() - 1)) + 2);
List.of(
methodNode.instructions.get(methodNode.instructions.indexOf(toRemove.get(0)) - 1),
methodNode.instructions.get(methodNode.instructions.indexOf(toRemove.get(toRemove.size() - 1)) + 1)
).forEach(methodNode.instructions::remove);
toRemove.forEach(methodNode.instructions::remove);
if (dup.getOpcode() == Opcodes.DUP) {
methodNode.instructions.remove(dup);
}

if (position > 0 && !objects[position - 1].isEmpty()) {
// Make sure that the last one doesn't have a DUP
final int lastOfPrevious = methodNode.instructions.indexOf(objects[position - 1].get(objects[position - 1].size() - 1));
if (methodNode.instructions.get(lastOfPrevious + 2).getOpcode() == Opcodes.DUP) {
methodNode.instructions.remove(methodNode.instructions.get(lastOfPrevious + 2));
}
}
});

// Continue from the new position of the call
Expand All @@ -230,7 +244,9 @@ default Codec<? extends ParameterTransformer> codec() {

interface WrapOpModification {
void insertParameter(int index, Consumer<InsnList> adapter);

void replaceParameter(int index, Consumer<InsnList> adapter);

void removeParameter(int index);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dev.su5ed.sinytra.adapter.patch.transformer.param;

import com.mojang.serialization.Codec;
import dev.su5ed.sinytra.adapter.patch.api.MethodContext;
import dev.su5ed.sinytra.adapter.patch.api.Patch;
import dev.su5ed.sinytra.adapter.patch.api.PatchContext;
import dev.su5ed.sinytra.adapter.patch.util.AdapterUtil;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;

import java.util.List;

public record RemoveParameterTransformer(int index) implements ParameterTransformer {
public static final Codec<RemoveParameterTransformer> CODEC = Codec.intRange(0, 255)
.fieldOf("index").xmap(RemoveParameterTransformer::new, RemoveParameterTransformer::index)
.codec();

@Override
public Patch.Result apply(ClassNode classNode, MethodNode methodNode, MethodContext methodContext, PatchContext context, List<Type> parameters, int offset) {
final int target = this.index() + offset;
final int lvtIndex = ParameterTransformer.calculateLVTIndex(parameters, !methodContext.isStatic(methodNode), target);

// Remove the use of the param in a wrapop first to avoid the new LVT messing with the outcome of that
extractWrapOperation(methodContext, methodNode, parameters, op -> op.removeParameter(target));

withLVTSnapshot(methodNode, () -> {
LocalVariableNode lvn = methodNode.localVariables.stream()
.filter(v -> v.index == lvtIndex)
.findFirst()
.orElse(null);
if (lvn != null) {
methodNode.localVariables.remove(lvn);
AdapterUtil.replaceLVT(methodNode, idx -> idx == lvtIndex ? -1 : idx);
}
});

methodNode.parameters.remove(target);
parameters.remove(target);

return Patch.Result.COMPUTE_FRAMES;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dev.su5ed.sinytra.adapter.patch.api.MethodContext;
Expand All @@ -25,6 +27,7 @@ public record TransformParameters(List<ParameterTransformer> transformers, boole
.put("inject_parameter", InjectParameterTransform.CODEC)
.put("swap_parameters", SwapParametersTransformer.CODEC)
.put("substitute_parameters", SubstituteParameterTransformer.CODEC)
.put("remove_parameter", RemoveParameterTransformer.CODEC)
.build();

public static final Codec<TransformParameters> CODEC = RecordCodecBuilder.create(in -> in.group(
Expand Down Expand Up @@ -62,6 +65,7 @@ public Codec<? extends MethodTransform> codec() {
return CODEC;
}

@CanIgnoreReturnValue
public static class Builder {
private final List<ParameterTransformer> transformers = new ArrayList<>();
private boolean offset = false;
Expand All @@ -87,11 +91,16 @@ public Builder inline(int target, Consumer<InstructionAdapter> adapter) {
return this.transform(new InlineParameterTransformer(target, adapter));
}

public Builder remove(int index) {
return this.transform(new RemoveParameterTransformer(index));
}

public Builder withOffset() {
this.offset = true;
return this;
}

@CheckReturnValue
public TransformParameters build() {
return new TransformParameters(transformers, offset);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package dev.su5ed.sinytra.adapter.patch.test.mixin;

import dev.su5ed.sinytra.adapter.patch.api.MixinConstants;
import dev.su5ed.sinytra.adapter.patch.api.Patch;
import org.junit.jupiter.api.Test;

public class ParameterRemoveTest extends MixinPatchTest {
@Test
void testSimpleRemove() throws Exception {
assertSameCode(
"org/sinytra/adapter/test/mixins/ParameterRemoveMixin",
"testSimpleRemove",
Patch.builder()
.targetInjectionPoint("")
.targetMethod("testSimple")
.targetMixinType(MixinConstants.INJECT)
.transformParams(params -> params.remove(2))
);
}

@Test
void testWrapOpRemove() throws Exception {
assertSameCode(
"org/sinytra/adapter/test/mixins/ParameterRemoveMixin",
"testWrapOpRemove",
Patch.builder()
.targetMethod("testWrapOp")
.transformParams(params -> params.remove(2))
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.sinytra.adapter.test.classes;

import java.util.concurrent.atomic.AtomicBoolean;

public class ParameterRemove {
public static void testSimple(int p1, char p2) {

}

public static void testWrapOp(SObj sObj, AtomicBoolean p1) {

}

public record SObj() {
public void call(AtomicBoolean value) {

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
@Mixin(ParameterInline.class)
public class ParameterInlineMixin {
@Inject(method = "simple(ILjava/lang/String;ILjava/lang/String;)V", at = @At("HEAD"))
private void testSimpleInline(int p1, String p2, int p3, String p4) {
private static void testSimpleInline(int p1, String p2, int p3, String p4) {
System.out.println(p4);
}

private void testSimpleInlineExpected(int p1, String p2, int p3) {
private static void testSimpleInlineExpected(int p1, String p2, int p3) {
System.out.println("inlined");
}

@Inject(method = "big(IDI)V", at = @At("HEAD"))
private void testBigInline(int p1, double p2, double p3, int p4) {
private static void testBigInline(int p1, double p2, double p3, int p4) {
System.out.println(p3 * p2);
System.out.println("p4: " + p4);
}

private void testBigInlineExpected(int p1, double p2, int p4) {
private static void testBigInlineExpected(int p1, double p2, int p4) {
System.out.println(43d * p2);
System.out.println("p4: " + p4);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.sinytra.adapter.test.mixins;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import org.sinytra.adapter.test.classes.ParameterRemove;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;

import java.util.concurrent.atomic.AtomicBoolean;

@Mixin(ParameterRemove.class)
public class ParameterRemoveMixin {
@Inject(method = "testSimple(IC)V", at = @At("HEAD"))
private static void testSimpleRemove(int p1, char p2, boolean p3) {
System.out.println("Hi: " + p2 / p1);
}

private static void testSimpleRemoveExpected(int p1, char p2) {
System.out.println("Hi: " + p2 / p1);
}

@WrapOperation(method = "testWrapOp(Lorg/sinytra/adapter/test/classes/ParameterRemove$SObj;Ljava/util/concurrent/atomic/AtomicBoolean;)V", at = @At(value = "INVOKE", target = "Lorg/sinytra/adapter/test/classes/ParameterRemove$SObj;call(Ljava/util/concurrent/atomic/AtomicBoolean;)V"))
private static void testWrapOpRemove(ParameterRemove.SObj obj, AtomicBoolean p1, int p2, Operation<Void> operation) {
System.out.println(operation.call(obj, p1, p2));
}

private static void testWrapOpRemoveExpected(ParameterRemove.SObj obj, AtomicBoolean p1, Operation<Void> operation) {
System.out.println(operation.call(obj, p1));
}
}

0 comments on commit 469839c

Please sign in to comment.