Skip to content

Commit

Permalink
Propagate local context through compounds via decoration, closes #532
Browse files Browse the repository at this point in the history
  • Loading branch information
Mumfrey committed Jun 25, 2024
1 parent d2105c6 commit 017eecf
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URI;
import java.util.List;

import javax.annotation.processing.Filer;
import javax.annotation.processing.FilerException;
import javax.tools.FileObject;
import javax.tools.JavaFileManager.Location;
import javax.tools.StandardLocation;

import org.spongepowered.asm.mixin.injection.selectors.ITargetSelectorRemappable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,33 @@ public enum SpecialNodeType {
* @return the special node or null if not available
*/
public abstract AbstractInsnNode getSpecialNode(SpecialNodeType type);


/**
* Get whether this list is decorated with the specified key
*
* @param key meta key
* @return true if the specified decoration exists
*/
public abstract boolean hasDecoration(String key);

/**
* Get the specified decoration
*
* @param key meta key
* @param <V> value type
* @return decoration value or null if absent
*/
public abstract <V> V getDecoration(String key);

/**
* Get the specified decoration or default value
*
* @param key meta key
* @param defaultValue default value to return
* @param <V> value type
* @return decoration value or default value if absent
*/
public abstract <V> V getDecoration(String key, V defaultValue);

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@
*/
package org.spongepowered.asm.mixin.injection.code;

import java.util.HashMap;
import java.util.Map;

import org.objectweb.asm.tree.AbstractInsnNode;
import org.spongepowered.asm.mixin.injection.struct.Constructor;
import org.spongepowered.asm.mixin.injection.struct.IChainedDecoration;
import org.spongepowered.asm.mixin.injection.struct.Target;
import org.spongepowered.asm.mixin.transformer.struct.Initialiser;
import org.spongepowered.asm.mixin.transformer.struct.Initialiser.InjectionMode;
Expand All @@ -40,7 +44,12 @@ public class InsnListEx extends InsnListReadOnly implements IInsnListEx {
/**
* The target method
*/
private final Target target;
protected final Target target;

/**
* Decorations on this insn list
*/
private Map<String, Object> decorations;

public InsnListEx(Target target) {
super(target.insns);
Expand Down Expand Up @@ -154,5 +163,88 @@ public AbstractInsnNode getSpecialNode(SpecialNodeType type) {
return null;
}
}

/**
* Decorate this insn list with arbitrary metadata for use by
* context-specific injection points
*
* @param key meta key
* @param value meta value
* @param <V> value type
* @return fluent
*/
@SuppressWarnings("unchecked")
public <V> InsnListEx decorate(String key, V value) {
if (this.decorations == null) {
this.decorations = new HashMap<String, Object>();
}
if (value instanceof IChainedDecoration<?> && this.decorations.containsKey(key)) {
Object previous = this.decorations.get(key);
if (previous.getClass().equals(value.getClass())) {
((IChainedDecoration<Object>)value).replace(previous);
}
}
this.decorations.put(key, value);
return this;
}

/**
* Strip a specific decoration from this list if the decoration exists
*
* @param key meta key
* @return fluent
*/
public InsnListEx undecorate(String key) {
if (this.decorations != null) {
this.decorations.remove(key);
}
return this;
}

/**
* Strip all decorations from this list
*
* @return fluent
*/
public InsnListEx undecorate() {
this.decorations = null;
return this;
}

/**
* Get whether this list is decorated with the specified key
*
* @param key meta key
* @return true if the specified decoration exists
*/
public boolean hasDecoration(String key) {
return this.decorations != null && this.decorations.get(key) != null;
}

/**
* Get the specified decoration
*
* @param key meta key
* @param <V> value type
* @return decoration value or null if absent
*/
@SuppressWarnings("unchecked")
public <V> V getDecoration(String key) {
return (V) (this.decorations == null ? null : this.decorations.get(key));
}

/**
* Get the specified decoration or default value
*
* @param key meta key
* @param defaultValue default value to return
* @param <V> value type
* @return decoration value or null if absent
*/
@SuppressWarnings("unchecked")
public <V> V getDecoration(String key, V defaultValue) {
V existing = (V) (this.decorations == null ? null : this.decorations.get(key));
return existing != null ? existing : defaultValue;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ protected void inject(Target target, InjectionNode node) {
protected void injectAtInvoke(Target target, InjectionNode node) {
MethodInsnNode methodNode = (MethodInsnNode)node.getCurrentTarget();
Type[] args = Type.getArgumentTypes(methodNode.desc);
ArgOffsets offsets = node.getDecoration(ArgOffsets.KEY);
ArgOffsets offsets = node.<ArgOffsets>getDecoration(ArgOffsets.KEY);
if (offsets != null) {
args = offsets.apply(args);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ protected void inject(Target target, InjectionNode node) {
protected void injectAtInvoke(Target target, InjectionNode node) {
MethodInsnNode targetMethod = (MethodInsnNode)node.getCurrentTarget();
Type[] args = Type.getArgumentTypes(targetMethod.desc);
ArgOffsets offsets = node.getDecoration(ArgOffsets.KEY);
ArgOffsets offsets = node.<ArgOffsets>getDecoration(ArgOffsets.KEY);
if (offsets != null) {
args = offsets.apply(args);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ protected void addTargetNode(InjectorTarget injectorTarget, List<InjectionNode>
}

if (node != null ) {
Meta other = node.getDecoration(Meta.KEY);
Meta other = node.<Meta>getDecoration(Meta.KEY);

if (other != null && other.getOwner() != this) {
if (other.priority >= this.meta.priority) {
Expand Down Expand Up @@ -359,7 +359,7 @@ protected void inject(Target target, InjectionNode node) {
}

protected boolean preInject(InjectionNode node) {
Meta other = node.getDecoration(Meta.KEY);
Meta other = node.<Meta>getDecoration(Meta.KEY);
if (other.getOwner() != this) {
Injector.logger.warn("{} conflict. Skipping {} with priority {}, already redirected by {} with priority {}",
this.annotationType, this.info, this.meta.priority, other.name, other.priority);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ int getOrdinal() {
}

/**
* Injection info
* Injection info
*/
final InjectionInfo info;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
import org.spongepowered.asm.mixin.injection.InjectionPoint;
import org.spongepowered.asm.mixin.injection.InjectionPoint.RestrictTargetLevel;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.code.IInsnListEx;
import org.spongepowered.asm.mixin.injection.code.Injector;
import org.spongepowered.asm.mixin.injection.code.InjectorTarget;
import org.spongepowered.asm.mixin.injection.code.InsnListEx;
import org.spongepowered.asm.mixin.injection.struct.InjectionInfo;
import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode;
import org.spongepowered.asm.mixin.injection.struct.InjectionPointData;
Expand All @@ -56,6 +58,9 @@
*/
public class ModifyVariableInjector extends Injector {

private static final String KEY_INFO = "mv.info";
private static final String KEY_TARGET = "mv.target";

/**
* Target context information
*/
Expand Down Expand Up @@ -86,13 +91,22 @@ abstract static class LocalVariableInjectionPoint extends InjectionPoint {

@Override
public boolean find(String desc, InsnList insns, Collection<AbstractInsnNode> nodes) {
if (insns instanceof IInsnListEx) {
IInsnListEx xinsns = (IInsnListEx)insns;
Target target = xinsns.<Target>getDecoration(ModifyVariableInjector.KEY_TARGET);
if (target != null) {
// Info is not actually used internally so we don't especially care if it's null
return this.find(xinsns.<InjectionInfo>getDecoration(ModifyVariableInjector.KEY_INFO), insns, nodes, target);
}
}

throw new InvalidInjectionException(this.mixin, this.getAtCode() + " injection point must be used in conjunction with @ModifyVariable");
}

abstract boolean find(InjectionInfo info, InsnList insns, Collection<AbstractInsnNode> nodes, Target target);

}

/**
* True to consider only method args
*/
Expand All @@ -109,11 +123,20 @@ public ModifyVariableInjector(InjectionInfo info, LocalVariableDiscriminator dis

@Override
protected boolean findTargetNodes(InjectorTarget target, InjectionPoint injectionPoint, Collection<AbstractInsnNode> nodes) {
if (injectionPoint instanceof LocalVariableInjectionPoint) {
return ((LocalVariableInjectionPoint)injectionPoint).find(this.info, target.getSlice(injectionPoint), nodes,
target.getTarget());
InsnListEx slice = (InsnListEx)target.getSlice(injectionPoint);
slice.decorate(ModifyVariableInjector.KEY_TARGET, target.getTarget());
slice.decorate(ModifyVariableInjector.KEY_INFO, this.info);

boolean found = injectionPoint instanceof LocalVariableInjectionPoint
? ((LocalVariableInjectionPoint)injectionPoint).find(this.info, slice, nodes, target.getTarget())
: injectionPoint.find(target.getDesc(), slice, nodes);

if (slice instanceof InsnListEx) {
slice.undecorate(ModifyVariableInjector.KEY_TARGET);
slice.undecorate(ModifyVariableInjector.KEY_INFO);
}
return injectionPoint.find(target.getDesc(), target.getSlice(injectionPoint), nodes);

return found;
}

/* (non-Javadoc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import java.util.Iterator;
import java.util.List;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
Expand Down

0 comments on commit 017eecf

Please sign in to comment.