Emit more debug info to the generated dispatcher classes
This commit is contained in:
parent
784b914a43
commit
e16179b797
|
|
@ -66,6 +66,7 @@ public class CapabilityProviderDispatcherGenerator {
|
||||||
private static final String LAZY_OPTIONAL_DESC = "Lnet/minecraftforge/common/util/LazyOptional;";
|
private static final String LAZY_OPTIONAL_DESC = "Lnet/minecraftforge/common/util/LazyOptional;";
|
||||||
private static final String DIRECTION_DESC = "Lnet/minecraft/core/Direction;";
|
private static final String DIRECTION_DESC = "Lnet/minecraft/core/Direction;";
|
||||||
private static final String MAP_DESC = "Ljava/util/Map;";
|
private static final String MAP_DESC = "Ljava/util/Map;";
|
||||||
|
private static final String MAP_SIGNATURE = "Ljava/util/Map<Lnet/minecraftforge/common/capabilities/Capability<*>;Lnet/minecraftforge/common/capabilities/ICapabilityProvider;>;";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or generates a constructor MethodHandle for the given capability provider types.
|
* Gets or generates a constructor MethodHandle for the given capability provider types.
|
||||||
|
|
@ -276,13 +277,20 @@ public class CapabilityProviderDispatcherGenerator {
|
||||||
// Generate final fields for each distinct provider
|
// Generate final fields for each distinct provider
|
||||||
LinkedHashMap<Integer, String> providerFields = collectProviderFields(dispatches);
|
LinkedHashMap<Integer, String> providerFields = collectProviderFields(dispatches);
|
||||||
for (var entry : providerFields.entrySet()) {
|
for (var entry : providerFields.entrySet()) {
|
||||||
cw.visitField(ACC_PRIVATE | ACC_FINAL, "provider" + entry.getKey(), entry.getValue(), null, null).visitEnd();
|
FieldVisitor fv = cw.visitField(ACC_PRIVATE | ACC_FINAL, "provider" + entry.getKey(), entry.getValue(), null, null);
|
||||||
|
if (entry.getValue().equals(ICAP_PROVIDER_DESC)) {
|
||||||
|
String originalName = providerTypes.get(entry.getKey()).getName();
|
||||||
|
AnnotationVisitor av = fv.visitAnnotation("Lorg/embeddedt/modernfix/forge/capability/OriginalType;", false);
|
||||||
|
av.visit("value", originalName);
|
||||||
|
av.visitEnd();
|
||||||
|
}
|
||||||
|
fv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate map fields for Hash dispatches
|
// Generate map fields for Hash dispatches
|
||||||
for (ProviderDispatch dispatch : dispatches) {
|
for (ProviderDispatch dispatch : dispatches) {
|
||||||
if (dispatch instanceof ProviderDispatch.Hash hash) {
|
if (dispatch instanceof ProviderDispatch.Hash hash) {
|
||||||
cw.visitField(ACC_PRIVATE | ACC_FINAL, "capMap" + hash.mapIndex(), MAP_DESC, null, null).visitEnd();
|
cw.visitField(ACC_PRIVATE | ACC_FINAL, "capMap" + hash.mapIndex(), MAP_DESC, MAP_SIGNATURE, null).visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -367,32 +375,36 @@ public class CapabilityProviderDispatcherGenerator {
|
||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
// Generate unrolled dispatch loop
|
Label methodStart = new Label();
|
||||||
// For each provider, call getCapability and check if present
|
Label methodEnd = new Label();
|
||||||
Label endLabel = new Label();
|
mv.visitLabel(methodStart);
|
||||||
|
|
||||||
String internalName = className.replace('.', '/');
|
String internalName = className.replace('.', '/');
|
||||||
String getCapDesc = "(" + CAPABILITY_DESC + DIRECTION_DESC + ")" + LAZY_OPTIONAL_DESC;
|
String getCapDesc = "(" + CAPABILITY_DESC + DIRECTION_DESC + ")" + LAZY_OPTIONAL_DESC;
|
||||||
|
|
||||||
|
// slot 3 = LazyOptional<T> result (all paths)
|
||||||
|
// slot 4 = ICapabilityProvider provider (Hash paths only)
|
||||||
|
boolean usesProviderLocal = dispatches.stream().anyMatch(d -> d instanceof ProviderDispatch.Hash);
|
||||||
|
|
||||||
for (ProviderDispatch dispatch : dispatches) {
|
for (ProviderDispatch dispatch : dispatches) {
|
||||||
Label nextLabel = new Label();
|
Label nextLabel = new Label();
|
||||||
|
|
||||||
if (dispatch instanceof ProviderDispatch.Hash hash) {
|
if (dispatch instanceof ProviderDispatch.Hash hash) {
|
||||||
// ICapabilityProvider p = (ICapabilityProvider) this.capMapN.get(cap);
|
// ICapabilityProvider provider = (ICapabilityProvider) this.capMapN.get(cap);
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, internalName, "capMap" + hash.mapIndex(), MAP_DESC);
|
mv.visitFieldInsn(GETFIELD, internalName, "capMap" + hash.mapIndex(), MAP_DESC);
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get",
|
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get",
|
||||||
"(Ljava/lang/Object;)Ljava/lang/Object;", true);
|
"(Ljava/lang/Object;)Ljava/lang/Object;", true);
|
||||||
mv.visitVarInsn(ASTORE, 3);
|
mv.visitTypeInsn(CHECKCAST, "net/minecraftforge/common/capabilities/ICapabilityProvider");
|
||||||
|
mv.visitVarInsn(ASTORE, 4);
|
||||||
|
|
||||||
// if (p == null) goto next
|
// if (provider == null) goto next
|
||||||
mv.visitVarInsn(ALOAD, 3);
|
mv.visitVarInsn(ALOAD, 4);
|
||||||
mv.visitJumpInsn(IFNULL, nextLabel);
|
mv.visitJumpInsn(IFNULL, nextLabel);
|
||||||
|
|
||||||
// result = ((ICapabilityProvider) p).getCapability(cap, side)
|
// LazyOptional<T> result = provider.getCapability(cap, side)
|
||||||
mv.visitVarInsn(ALOAD, 3);
|
mv.visitVarInsn(ALOAD, 4);
|
||||||
mv.visitTypeInsn(CHECKCAST, "net/minecraftforge/common/capabilities/ICapabilityProvider");
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
mv.visitVarInsn(ALOAD, 2);
|
||||||
mv.visitMethodInsn(INVOKEINTERFACE,
|
mv.visitMethodInsn(INVOKEINTERFACE,
|
||||||
|
|
@ -445,7 +457,6 @@ public class CapabilityProviderDispatcherGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no provider returned a capability, return empty
|
// If no provider returned a capability, return empty
|
||||||
mv.visitLabel(endLabel);
|
|
||||||
mv.visitMethodInsn(
|
mv.visitMethodInsn(
|
||||||
INVOKESTATIC,
|
INVOKESTATIC,
|
||||||
"net/minecraftforge/common/util/LazyOptional",
|
"net/minecraftforge/common/util/LazyOptional",
|
||||||
|
|
@ -455,6 +466,18 @@ public class CapabilityProviderDispatcherGenerator {
|
||||||
);
|
);
|
||||||
mv.visitInsn(ARETURN);
|
mv.visitInsn(ARETURN);
|
||||||
|
|
||||||
|
mv.visitLabel(methodEnd);
|
||||||
|
|
||||||
|
// Local variable table for clean decompilation
|
||||||
|
String capSig = CAPABILITY_DESC.replace(";", "<TT;>;");
|
||||||
|
String resultSig = LAZY_OPTIONAL_DESC.replace(";", "<TT;>;");
|
||||||
|
mv.visitLocalVariable("cap", CAPABILITY_DESC, capSig, methodStart, methodEnd, 1);
|
||||||
|
mv.visitLocalVariable("side", DIRECTION_DESC, null, methodStart, methodEnd, 2);
|
||||||
|
mv.visitLocalVariable("result", LAZY_OPTIONAL_DESC, resultSig, methodStart, methodEnd, 3);
|
||||||
|
if (usesProviderLocal) {
|
||||||
|
mv.visitLocalVariable("provider", ICAP_PROVIDER_DESC, null, methodStart, methodEnd, 4);
|
||||||
|
}
|
||||||
|
|
||||||
mv.visitMaxs(0, 0); // Computed by COMPUTE_MAXS
|
mv.visitMaxs(0, 0); // Computed by COMPUTE_MAXS
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.embeddedt.modernfix.forge.capability;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applied to generated provider fields whose declared type has been widened to
|
||||||
|
* {@link net.minecraftforge.common.capabilities.ICapabilityProvider} because the
|
||||||
|
* concrete class is non-public or hidden. The value records the original type name.
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
public @interface OriginalType {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user