mirror of
https://github.com/LegacyModdingMC/UniMix.git
synced 2026-11-13 00:47:52 +00:00
Transformer delegation list belongs in MixinEnvironment
This commit is contained in:
1 parent
333450f64c
commit
a85f2cd316
2 files changed
+122
-114
No files matched your search
@@ -27,15 +27,21 @@ package org.spongepowered.asm.mixin;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.helpers.Booleans;
|
||||
import org.spongepowered.asm.launch.MixinBootstrap;
|
||||
import org.spongepowered.asm.mixin.transformer.MixinTransformer;
|
||||
import org.spongepowered.asm.util.PrettyPrinter;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassNameTransformer;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.ITweaker;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
@@ -277,11 +283,22 @@ public class MixinEnvironment {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Known re-entrant transformers, other re-entrant transformers will
|
||||
* detected automatically
|
||||
*/
|
||||
private static final Set<String> excludeTransformers = Sets.<String>newHashSet(
|
||||
"net.minecraftforge.fml.common.asm.transformers.EventSubscriptionTransformer",
|
||||
"cpw.mods.fml.common.asm.transformers.EventSubscriptionTransformer",
|
||||
"net.minecraftforge.fml.common.asm.transformers.TerminalTransformer",
|
||||
"cpw.mods.fml.common.asm.transformers.TerminalTransformer"
|
||||
);
|
||||
|
||||
// Blackboard keys
|
||||
private static final String CONFIGS_KEY = "mixin.configs";
|
||||
private static final String TRANSFORMER_KEY = "mixin.transformer";
|
||||
|
||||
|
||||
/**
|
||||
* Current (active) environment phase, set to NOT_INITIALISED until the
|
||||
* phases have been populated
|
||||
@@ -298,6 +315,11 @@ public class MixinEnvironment {
|
||||
*/
|
||||
private static MixinEnvironment currentEnvironment;
|
||||
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
private final Logger logger = LogManager.getLogger("mixin");
|
||||
|
||||
/**
|
||||
* The phase for this environment
|
||||
*/
|
||||
@@ -318,6 +340,19 @@ public class MixinEnvironment {
|
||||
*/
|
||||
private Side side;
|
||||
|
||||
/**
|
||||
* Local transformer chain, this consists of all transformers present at the
|
||||
* init phase with the exclusion of the mixin transformer itself and known
|
||||
* re-entrant transformers. Detected re-entrant transformers will be
|
||||
* subsequently removed.
|
||||
*/
|
||||
private List<IClassTransformer> transformers;
|
||||
|
||||
/**
|
||||
* Class name transformer (if present)
|
||||
*/
|
||||
private IClassNameTransformer nameTransformer;
|
||||
|
||||
private MixinEnvironment(Phase phase) {
|
||||
this.phase = phase;
|
||||
this.configsKey = MixinEnvironment.CONFIGS_KEY + "." + this.phase.name.toLowerCase();
|
||||
@@ -473,7 +508,85 @@ public class MixinEnvironment {
|
||||
transformer.audit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns (and generates if necessary) the transformer delegation list for
|
||||
* this environment.
|
||||
*/
|
||||
public List<IClassTransformer> getTransformers() {
|
||||
if (this.transformers == null) {
|
||||
this.buildTransformerDelegationList();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(this.transformers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a transformer to the transformer exclusions list
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public void addTransformerExclusion(String name) {
|
||||
MixinEnvironment.excludeTransformers.add(name);
|
||||
|
||||
// Force rebuild of the list
|
||||
this.transformers = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a class name back to its obfuscated counterpart
|
||||
*
|
||||
* @param className
|
||||
* @return obfuscated name for the specified deobfuscated reference
|
||||
*/
|
||||
public String unmap(String className) {
|
||||
if (this.nameTransformer == null) {
|
||||
this.buildTransformerDelegationList();
|
||||
}
|
||||
|
||||
if (this.nameTransformer != null) {
|
||||
return this.nameTransformer.unmapClassName(className);
|
||||
}
|
||||
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the transformer list to apply to loaded mixin bytecode. Since
|
||||
* generating this list requires inspecting each transformer by name (to
|
||||
* cope with the new wrapper functionality added by FML) we generate the
|
||||
* list just once per environment and cache the result.
|
||||
*/
|
||||
private void buildTransformerDelegationList() {
|
||||
this.logger.debug("Rebuilding transformer delegation list:");
|
||||
this.transformers = new ArrayList<IClassTransformer>();
|
||||
for (IClassTransformer transformer : Launch.classLoader.getTransformers()) {
|
||||
String transformerName = transformer.getClass().getName();
|
||||
boolean include = true;
|
||||
for (String excludeClass : MixinEnvironment.excludeTransformers) {
|
||||
if (transformerName.contains(excludeClass)) {
|
||||
include = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (include && !transformerName.contains(MixinTransformer.class.getName())) {
|
||||
this.logger.debug(" Adding: {}", transformerName);
|
||||
this.transformers.add(transformer);
|
||||
} else {
|
||||
this.logger.debug(" Excluding: {}", transformerName);
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.debug("Transformer delegation list created with {} entries", this.transformers.size());
|
||||
|
||||
for (IClassTransformer transformer : Launch.classLoader.getTransformers()) {
|
||||
if (transformer instanceof IClassNameTransformer) {
|
||||
this.logger.debug("Found name transformer: {}", transformer.getClass().getName());
|
||||
this.nameTransformer = (IClassNameTransformer) transformer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
@@ -27,12 +27,7 @@ package org.spongepowered.asm.mixin.transformer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassNameTransformer;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
@@ -44,44 +39,13 @@ import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.transformer.MixinTransformer.ReEntranceState;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Base class for "info" objects which use ASM tree API to do stuff, with things
|
||||
*/
|
||||
abstract class TreeInfo {
|
||||
|
||||
/**
|
||||
* Known re-entrant transformers, other re-entrant transformers will
|
||||
* detected automatically
|
||||
*/
|
||||
private static final Set<String> excludeTransformers = Sets.<String>newHashSet(
|
||||
"net.minecraftforge.fml.common.asm.transformers.EventSubscriptionTransformer",
|
||||
"cpw.mods.fml.common.asm.transformers.EventSubscriptionTransformer",
|
||||
"net.minecraftforge.fml.common.asm.transformers.TerminalTransformer",
|
||||
"cpw.mods.fml.common.asm.transformers.TerminalTransformer"
|
||||
);
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("mixin");
|
||||
|
||||
/**
|
||||
* Local transformer chain, this consists of all transformers present at the
|
||||
* init phase with the exclusion of the mixin transformer itself and known
|
||||
* re-entrant transformers. Detected re-entrant transformers will be
|
||||
* subsequently removed.
|
||||
*/
|
||||
private static List<IClassTransformer> transformers;
|
||||
|
||||
/**
|
||||
* Class name transformer (if present)
|
||||
*/
|
||||
private static IClassNameTransformer nameTransformer;
|
||||
|
||||
/**
|
||||
* Current environment
|
||||
*/
|
||||
private static MixinEnvironment currentEnvironment;
|
||||
|
||||
/**
|
||||
* Re-entrance lock
|
||||
*/
|
||||
@@ -100,7 +64,7 @@ abstract class TreeInfo {
|
||||
* @param flags
|
||||
* @return ASM Tree view of the specified class
|
||||
*/
|
||||
static ClassNode getClassNode(byte[] classBytes, int flags) {
|
||||
protected static ClassNode getClassNode(byte[] classBytes, int flags) {
|
||||
ClassNode classNode = new ClassNode();
|
||||
ClassReader classReader = new ClassReader(classBytes);
|
||||
classReader.accept(classNode, flags);
|
||||
@@ -112,11 +76,9 @@ abstract class TreeInfo {
|
||||
* @param runTransformers
|
||||
* @return Transformed class bytecode for the specified class
|
||||
*/
|
||||
static byte[] loadClass(String className, boolean runTransformers) throws ClassNotFoundException, IOException {
|
||||
TreeInfo.checkEnvironment();
|
||||
|
||||
protected static byte[] loadClass(String className, boolean runTransformers) throws ClassNotFoundException, IOException {
|
||||
String transformedName = className.replace('/', '.');
|
||||
String name = TreeInfo.unmap(transformedName);
|
||||
String name = MixinEnvironment.getCurrentEnvironment().unmap(transformedName);
|
||||
byte[] classBytes = null;
|
||||
|
||||
if ((classBytes = TreeInfo.getClassBytes(name, transformedName)) == null) {
|
||||
@@ -167,11 +129,9 @@ abstract class TreeInfo {
|
||||
* except the excluded transformers
|
||||
*/
|
||||
private static byte[] applyTransformers(String name, String transformedName, byte[] basicClass) {
|
||||
final List<IClassTransformer> transformers = TreeInfo.transformers;
|
||||
|
||||
for (Iterator<IClassTransformer> iter = transformers.iterator(); iter.hasNext();) {
|
||||
IClassTransformer transformer = iter.next();
|
||||
|
||||
MixinEnvironment environment = MixinEnvironment.getCurrentEnvironment();
|
||||
|
||||
for (IClassTransformer transformer : environment.getTransformers()) {
|
||||
if (TreeInfo.lock != null) {
|
||||
// Clear the re-entrance semaphore
|
||||
TreeInfo.lock.clear();
|
||||
@@ -180,12 +140,8 @@ abstract class TreeInfo {
|
||||
basicClass = transformer.transform(name, transformedName, basicClass);
|
||||
|
||||
if (TreeInfo.lock != null && TreeInfo.lock.isSet()) {
|
||||
// If the re-entrance semaphore was raised during the last transformation then we can assume
|
||||
// that this transformer is re-entrant and remove it from our transformer chain.
|
||||
iter.remove();
|
||||
|
||||
// Also add it to the exclusion list so we can exclude it if the environment triggers a rebuild
|
||||
TreeInfo.excludeTransformers.add(transformer.getClass().getName());
|
||||
environment.addTransformerExclusion(transformer.getClass().getName());
|
||||
|
||||
TreeInfo.lock.clear();
|
||||
TreeInfo.logger.info("A re-entrant transformer '{}' was detected and will no longer process meta class data",
|
||||
@@ -195,65 +151,4 @@ abstract class TreeInfo {
|
||||
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a class name back to its obfuscated counterpart
|
||||
*
|
||||
* @param className
|
||||
* @return obfuscated name for the specified deobfuscated reference
|
||||
*/
|
||||
static String unmap(String className) {
|
||||
IClassNameTransformer nameTransformer = TreeInfo.nameTransformer;
|
||||
if (nameTransformer != null) {
|
||||
return nameTransformer.unmapClassName(className);
|
||||
}
|
||||
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the current environment has changed
|
||||
*/
|
||||
private static void checkEnvironment() {
|
||||
if (MixinEnvironment.getCurrentEnvironment() != TreeInfo.currentEnvironment) {
|
||||
TreeInfo.buildTransformerDelegationList();
|
||||
TreeInfo.currentEnvironment = MixinEnvironment.getCurrentEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the transformer list to apply to loaded mixin bytecode. Since
|
||||
* generating this list requires inspecting each transformer by name (to
|
||||
* cope with the new wrapper functionality added by FML) we generate the
|
||||
* list just once and cache the result.
|
||||
*/
|
||||
private static void buildTransformerDelegationList() {
|
||||
TreeInfo.logger.debug("Building transformer delegation list:");
|
||||
TreeInfo.transformers = new ArrayList<IClassTransformer>();
|
||||
for (IClassTransformer transformer : Launch.classLoader.getTransformers()) {
|
||||
String transformerName = transformer.getClass().getName();
|
||||
boolean include = true;
|
||||
for (String excludeClass : TreeInfo.excludeTransformers) {
|
||||
if (transformerName.contains(excludeClass)) {
|
||||
include = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (include && !transformerName.contains(MixinTransformer.class.getName())) {
|
||||
TreeInfo.logger.debug(" Adding: {}", transformerName);
|
||||
TreeInfo.transformers.add(transformer);
|
||||
} else {
|
||||
TreeInfo.logger.debug(" Excluding: {}", transformerName);
|
||||
}
|
||||
}
|
||||
|
||||
TreeInfo.logger.debug("Transformer delegation list created with {} entries", TreeInfo.transformers.size());
|
||||
|
||||
for (IClassTransformer transformer : Launch.classLoader.getTransformers()) {
|
||||
if (transformer instanceof IClassNameTransformer) {
|
||||
TreeInfo.logger.debug("Found name transformer: {}", transformer.getClass().getName());
|
||||
TreeInfo.nameTransformer = (IClassNameTransformer) transformer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user