Skip to content

Commit 0a088c2

Browse files
committed
use interfaces from metadata instead of ClassNode in MixinPluginTransformer
1 parent c34d409 commit 0a088c2

4 files changed

Lines changed: 70 additions & 11 deletions

File tree

gradlew

100644100755
File mode changed.

src/main/java/com/falsepattern/lib/internal/asm/transformers/MixinPluginTransformer.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package com.falsepattern.lib.internal.asm.transformers;
2424

2525
import com.falsepattern.lib.internal.Tags;
26+
import com.falsepattern.lib.turboasm.ClassHeaderMetadata;
2627
import com.falsepattern.lib.turboasm.ClassNodeHandle;
2728
import com.falsepattern.lib.turboasm.TurboClassTransformer;
2829
import lombok.val;
@@ -75,17 +76,11 @@ public boolean shouldTransformClass(@NotNull String className, @NotNull ClassNod
7576
if (!classNode.isPresent())
7677
return false;
7778

78-
if (classNode.isOriginal()) {
79-
val meta = classNode.getOriginalMetadata();
80-
if (meta != null && meta.interfacesCount == 0)
81-
return false;
82-
}
83-
84-
val cn = classNode.getNode();
85-
if (cn == null)
79+
ClassHeaderMetadata metadata = classNode.getOriginalMetadata();
80+
if (metadata == null)
8681
return false;
8782

88-
for (String i : cn.interfaces) {
83+
for (String i : metadata.binaryInterfaceNames()) {
8984
if (IMIXINPLUGIN_INTERNAL.equals(i) || IMIXINCONFIGPLUGIN_INTERNAL.equals(i)) {
9085
return true;
9186
}

src/main/java/com/falsepattern/lib/turboasm/ClassHeaderMetadata.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import java.io.ByteArrayInputStream;
3131
import java.io.DataInputStream;
3232
import java.io.IOException;
33+
import java.util.ArrayList;
34+
import java.util.Collections;
35+
import java.util.List;
3336

3437
/**
3538
* Utilities for quickly processing class files without fully parsing them.
@@ -49,8 +52,11 @@ public final class ClassHeaderMetadata implements FastClassAccessor {
4952
public final int thisClassIndex;
5053
public final int superClassIndex;
5154
public final int interfacesCount;
55+
public final int @NotNull [] interfaceIndices;
5256
public final @NotNull String binaryThisName;
5357
public final @Nullable String binarySuperName;
58+
/** List is unmodifiable */
59+
public final @NotNull List<@NotNull String> binaryInterfaceNames;
5460

5561
/**
5662
* Attempts to parse a class header.
@@ -88,6 +94,9 @@ public ClassHeaderMetadata(byte @NotNull [] bytes) {
8894
this.thisClassIndex = u16(bytes, cpOff + Offsets.pastCpThisClassU16);
8995
this.superClassIndex = u16(bytes, cpOff + Offsets.pastCpSuperClassU16);
9096
this.interfacesCount = u16(bytes, cpOff + Offsets.pastCpInterfacesCountU16);
97+
this.interfaceIndices = new int[this.interfacesCount];
98+
List<String> interfaceNames = new ArrayList<>(this.interfacesCount);
99+
91100
// Parse this&super names
92101
if (constantPoolEntryTypes[thisClassIndex - 1] != ConstantPoolEntryTypes.Class) {
93102
throw new IllegalArgumentException("This class index is not a class ref");
@@ -110,6 +119,25 @@ public ClassHeaderMetadata(byte @NotNull [] bytes) {
110119
}
111120
this.binarySuperName = modifiedUtf8(bytes, constantPoolEntryOffsets[superNameIndex - 1] + 1);
112121
}
122+
123+
// Parse interface names
124+
for (int i = 0; i < this.interfacesCount; i++) {
125+
final int interfaceOffset = cpOff + Offsets.pastCpInterfacesList + i * 2;
126+
final int interfaceIndex = u16(bytes, interfaceOffset);
127+
if (constantPoolEntryTypes[interfaceIndex - 1] != ConstantPoolEntryTypes.Class) {
128+
throw new IllegalArgumentException("Interface " + i + " index is not a class ref");
129+
}
130+
final int interfaceNameIndex = u16(bytes, constantPoolEntryOffsets[interfaceIndex - 1] + 1);
131+
if (constantPoolEntryTypes[interfaceNameIndex - 1] != ConstantPoolEntryTypes.Utf8) {
132+
throw new IllegalArgumentException("Interface " + i + " index does not point to a UTF8 entry");
133+
}
134+
final String binaryInterfaceName =
135+
modifiedUtf8(bytes, constantPoolEntryOffsets[interfaceNameIndex - 1] + 1);
136+
137+
this.interfaceIndices[i] = interfaceIndex;
138+
interfaceNames.add(binaryInterfaceName);
139+
}
140+
this.binaryInterfaceNames = Collections.unmodifiableList(interfaceNames);
113141
}
114142

115143
/** Helpers to read big-endian values from class files. */
@@ -189,6 +217,8 @@ private Offsets() {}
189217
public static final int pastCpSuperClassU16 = pastCpThisClassU16 + 2;
190218
/** The value of the interfaces_count item gives the number of direct superinterfaces of this class or interface type */
191219
public static final int pastCpInterfacesCountU16 = pastCpSuperClassU16 + 2;
220+
221+
public static final int pastCpInterfacesList = pastCpInterfacesCountU16 + 2;
192222
}
193223

194224
public enum ConstantPoolEntryTypes {
@@ -354,4 +384,9 @@ public boolean isEnum() {
354384
public @Nullable String binarySuperName() {
355385
return binarySuperName;
356386
}
357-
}
387+
388+
@Override
389+
public @NotNull List<@NotNull String> binaryInterfaceNames() {
390+
return binaryInterfaceNames;
391+
}
392+
}

src/main/java/com/falsepattern/lib/turboasm/FastClassAccessor.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
import org.objectweb.asm.tree.ClassNode;
2929

3030
import java.lang.reflect.Modifier;
31+
import java.util.ArrayList;
32+
import java.util.Collections;
33+
import java.util.List;
3134

3235
/** An accessor to metadata about a class that is quickly accessible without fully parsing one. */
3336
public interface FastClassAccessor {
@@ -51,6 +54,9 @@ public interface FastClassAccessor {
5154
/** Binary (slash-separated packages) name of the super-class, null for the Object class */
5255
@Nullable
5356
String binarySuperName();
57+
/** Binary (slash-separated packages) names of the implemented interfaces, list is unmodifiable */
58+
@NotNull
59+
List<@NotNull String> binaryInterfaceNames();
5460

5561
static OfLoaded ofLoaded(Class<?> loadedClass) {
5662
return new OfLoaded(loadedClass);
@@ -111,10 +117,18 @@ public boolean isEnum() {
111117
public @Nullable String binarySuperName() {
112118
return handle.superName;
113119
}
120+
121+
@Override
122+
public @NotNull List<@NotNull String> binaryInterfaceNames() {
123+
return handle.interfaces == null
124+
? Collections.emptyList()
125+
: Collections.unmodifiableList(handle.interfaces);
126+
}
114127
}
115128

116129
final class OfLoaded implements FastClassAccessor {
117130
public final Class<?> handle;
131+
private @Nullable List<@NotNull String> interfacesCache = null;
118132

119133
private OfLoaded(Class<?> handle) {
120134
this.handle = handle;
@@ -165,5 +179,20 @@ public boolean isEnum() {
165179
final Class<?> superclass = handle.getSuperclass();
166180
return superclass == null ? null : superclass.getName().replace('.', '/');
167181
}
182+
183+
@Override
184+
public @NotNull List<@NotNull String> binaryInterfaceNames() {
185+
if (interfacesCache != null) {
186+
return interfacesCache;
187+
}
188+
189+
Class<?>[] interfaces = handle.getInterfaces();
190+
List<String> binaryInterfaceNames = new ArrayList<>(interfaces.length);
191+
for (Class<?> iface : interfaces) {
192+
binaryInterfaceNames.add(iface.getName().replace('.', '/'));
193+
}
194+
interfacesCache = Collections.unmodifiableList(binaryInterfaceNames);
195+
return interfacesCache;
196+
}
168197
}
169-
}
198+
}

0 commit comments

Comments
 (0)