summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/analysis/index
diff options
context:
space:
mode:
authorGravatar gegy10002019-05-10 22:21:11 +0200
committerGravatar gegy10002019-05-10 22:21:11 +0200
commit75f383a1956eb19fc838ea647a7e7b24552324cf (patch)
treed0aa11a90110b60404f40a5f7f39704598491585 /src/main/java/cuchaz/enigma/analysis/index
parentUse our procyon to fix compiler issues (#128) (diff)
downloadenigma-fork-75f383a1956eb19fc838ea647a7e7b24552324cf.tar.gz
enigma-fork-75f383a1956eb19fc838ea647a7e7b24552324cf.tar.xz
enigma-fork-75f383a1956eb19fc838ea647a7e7b24552324cf.zip
Don't remap specialized methods to their bridge partner in bytecode
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis/index')
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java62
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java12
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java24
3 files changed, 33 insertions, 65 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
index 649ce25..8a9b459 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
@@ -17,8 +17,8 @@ public class BridgeMethodIndex implements JarIndexer {
17 private final InheritanceIndex inheritanceIndex; 17 private final InheritanceIndex inheritanceIndex;
18 private final ReferenceIndex referenceIndex; 18 private final ReferenceIndex referenceIndex;
19 19
20 private final Set<MethodEntry> bridgeMethods = Sets.newHashSet(); 20 private final Set<MethodEntry> bridgeToSpecialized = Sets.newHashSet();
21 private final Map<MethodEntry, MethodEntry> accessedToBridge = Maps.newHashMap(); 21 private final Map<MethodEntry, MethodEntry> specializedToBridge = Maps.newHashMap();
22 22
23 public BridgeMethodIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex) { 23 public BridgeMethodIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex) {
24 this.entryIndex = entryIndex; 24 this.entryIndex = entryIndex;
@@ -42,34 +42,34 @@ public class BridgeMethodIndex implements JarIndexer {
42 42
43 @Override 43 @Override
44 public void processIndex(JarIndex index) { 44 public void processIndex(JarIndex index) {
45 Map<MethodEntry, MethodEntry> copiedAccessToBridge = new HashMap<>(accessedToBridge); 45 Map<MethodEntry, MethodEntry> copiedAccessToBridge = new HashMap<>(specializedToBridge);
46 46
47 for (Map.Entry<MethodEntry, MethodEntry> entry : copiedAccessToBridge.entrySet()) { 47 for (Map.Entry<MethodEntry, MethodEntry> entry : copiedAccessToBridge.entrySet()) {
48 MethodEntry accessedEntry = entry.getKey(); 48 MethodEntry specializedEntry = entry.getKey();
49 MethodEntry bridgeEntry = entry.getValue(); 49 MethodEntry bridgeEntry = entry.getValue();
50 if (bridgeEntry.getName().equals(accessedEntry.getName())) { 50 if (bridgeEntry.getName().equals(specializedEntry.getName())) {
51 continue; 51 continue;
52 } 52 }
53 53
54 MethodEntry renamedAccessedEntry = accessedEntry.withName(bridgeEntry.getName()); 54 MethodEntry renamedSpecializedEntry = specializedEntry.withName(bridgeEntry.getName());
55 bridgeMethods.add(renamedAccessedEntry); 55 bridgeToSpecialized.add(renamedSpecializedEntry);
56 accessedToBridge.put(renamedAccessedEntry, accessedToBridge.get(accessedEntry)); 56 specializedToBridge.put(renamedSpecializedEntry, specializedToBridge.get(specializedEntry));
57 } 57 }
58 } 58 }
59 59
60 private void indexSyntheticMethod(MethodDefEntry syntheticMethod, AccessFlags access) { 60 private void indexSyntheticMethod(MethodDefEntry syntheticMethod, AccessFlags access) {
61 MethodEntry accessedMethod = findAccessMethod(syntheticMethod); 61 MethodEntry specializedMethod = findSpecializedMethod(syntheticMethod);
62 if (accessedMethod == null) { 62 if (specializedMethod == null) {
63 return; 63 return;
64 } 64 }
65 65
66 if (access.isBridge() || isPotentialBridge(syntheticMethod, accessedMethod)) { 66 if (access.isBridge() || isPotentialBridge(syntheticMethod, specializedMethod)) {
67 bridgeMethods.add(syntheticMethod); 67 bridgeToSpecialized.add(syntheticMethod);
68 accessedToBridge.put(accessedMethod, syntheticMethod); 68 specializedToBridge.put(specializedMethod, syntheticMethod);
69 } 69 }
70 } 70 }
71 71
72 private MethodEntry findAccessMethod(MethodEntry method) { 72 private MethodEntry findSpecializedMethod(MethodEntry method) {
73 // we want to find all compiler-added methods that directly call another with no processing 73 // we want to find all compiler-added methods that directly call another with no processing
74 74
75 // get all the methods that we call 75 // get all the methods that we call
@@ -83,7 +83,7 @@ public class BridgeMethodIndex implements JarIndexer {
83 return referencedMethods.stream().findFirst().orElse(null); 83 return referencedMethods.stream().findFirst().orElse(null);
84 } 84 }
85 85
86 private boolean isPotentialBridge(MethodDefEntry bridgeMethod, MethodEntry accessedMethod) { 86 private boolean isPotentialBridge(MethodDefEntry bridgeMethod, MethodEntry specializedMethod) {
87 // Bridge methods only exist for inheritance purposes, if we're private, final, or static, we cannot be inherited 87 // Bridge methods only exist for inheritance purposes, if we're private, final, or static, we cannot be inherited
88 AccessFlags bridgeAccess = bridgeMethod.getAccess(); 88 AccessFlags bridgeAccess = bridgeMethod.getAccess();
89 if (bridgeAccess.isPrivate() || bridgeAccess.isFinal() || bridgeAccess.isStatic()) { 89 if (bridgeAccess.isPrivate() || bridgeAccess.isFinal() || bridgeAccess.isStatic()) {
@@ -91,35 +91,35 @@ public class BridgeMethodIndex implements JarIndexer {
91 } 91 }
92 92
93 MethodDescriptor bridgeDesc = bridgeMethod.getDesc(); 93 MethodDescriptor bridgeDesc = bridgeMethod.getDesc();
94 MethodDescriptor accessedDesc = accessedMethod.getDesc(); 94 MethodDescriptor specializedDesc = specializedMethod.getDesc();
95 List<TypeDescriptor> bridgeArguments = bridgeDesc.getArgumentDescs(); 95 List<TypeDescriptor> bridgeArguments = bridgeDesc.getArgumentDescs();
96 List<TypeDescriptor> accessedArguments = accessedDesc.getArgumentDescs(); 96 List<TypeDescriptor> specializedArguments = specializedDesc.getArgumentDescs();
97 97
98 // A bridge method will always have the same number of arguments 98 // A bridge method will always have the same number of arguments
99 if (bridgeArguments.size() != accessedArguments.size()) { 99 if (bridgeArguments.size() != specializedArguments.size()) {
100 return false; 100 return false;
101 } 101 }
102 102
103 // Check that all argument types are bridge-compatible 103 // Check that all argument types are bridge-compatible
104 for (int i = 0; i < bridgeArguments.size(); i++) { 104 for (int i = 0; i < bridgeArguments.size(); i++) {
105 if (!areTypesBridgeCompatible(bridgeArguments.get(i), accessedArguments.get(i))) { 105 if (!areTypesBridgeCompatible(bridgeArguments.get(i), specializedArguments.get(i))) {
106 return false; 106 return false;
107 } 107 }
108 } 108 }
109 109
110 // Check that the return type is bridge-compatible 110 // Check that the return type is bridge-compatible
111 return areTypesBridgeCompatible(bridgeDesc.getReturnDesc(), accessedDesc.getReturnDesc()); 111 return areTypesBridgeCompatible(bridgeDesc.getReturnDesc(), specializedDesc.getReturnDesc());
112 } 112 }
113 113
114 private boolean areTypesBridgeCompatible(TypeDescriptor bridgeDesc, TypeDescriptor accessedDesc) { 114 private boolean areTypesBridgeCompatible(TypeDescriptor bridgeDesc, TypeDescriptor specializedDesc) {
115 if (bridgeDesc.equals(accessedDesc)) { 115 if (bridgeDesc.equals(specializedDesc)) {
116 return true; 116 return true;
117 } 117 }
118 118
119 // Either the descs will be equal, or they are both types and different through a generic 119 // Either the descs will be equal, or they are both types and different through a generic
120 if (bridgeDesc.isType() && accessedDesc.isType()) { 120 if (bridgeDesc.isType() && specializedDesc.isType()) {
121 ClassEntry bridgeType = bridgeDesc.getTypeEntry(); 121 ClassEntry bridgeType = bridgeDesc.getTypeEntry();
122 ClassEntry accessedType = accessedDesc.getTypeEntry(); 122 ClassEntry accessedType = specializedDesc.getTypeEntry();
123 123
124 // If the given types are completely unrelated to each other, this can't be bridge compatible 124 // If the given types are completely unrelated to each other, this can't be bridge compatible
125 InheritanceIndex.Relation relation = inheritanceIndex.computeClassRelation(accessedType, bridgeType); 125 InheritanceIndex.Relation relation = inheritanceIndex.computeClassRelation(accessedType, bridgeType);
@@ -130,19 +130,19 @@ public class BridgeMethodIndex implements JarIndexer {
130 } 130 }
131 131
132 public boolean isBridgeMethod(MethodEntry entry) { 132 public boolean isBridgeMethod(MethodEntry entry) {
133 return bridgeMethods.contains(entry); 133 return bridgeToSpecialized.contains(entry);
134 } 134 }
135 135
136 public boolean isAccessedByBridge(MethodEntry entry) { 136 public boolean isSpecializedMethod(MethodEntry entry) {
137 return accessedToBridge.containsKey(entry); 137 return specializedToBridge.containsKey(entry);
138 } 138 }
139 139
140 @Nullable 140 @Nullable
141 public MethodEntry getBridgeFromAccessed(MethodEntry entry) { 141 public MethodEntry getBridgeFromSpecialized(MethodEntry specialized) {
142 return accessedToBridge.get(entry); 142 return specializedToBridge.get(specialized);
143 } 143 }
144 144
145 public Map<MethodEntry, MethodEntry> getAccessedToBridge() { 145 public Map<MethodEntry, MethodEntry> getSpecializedToBridge() {
146 return Collections.unmodifiableMap(accessedToBridge); 146 return Collections.unmodifiableMap(specializedToBridge);
147 } 147 }
148} 148}
diff --git a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
index 645110a..773eaf1 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
@@ -28,18 +28,6 @@ public class EntryIndex implements JarIndexer {
28 fields.put(fieldEntry, fieldEntry.getAccess()); 28 fields.put(fieldEntry, fieldEntry.getAccess());
29 } 29 }
30 30
31 @Override
32 public void processIndex(JarIndex index) {
33 Map<MethodEntry, MethodEntry> accessedToBridge = index.getBridgeMethodIndex().getAccessedToBridge();
34 for (Map.Entry<MethodEntry, MethodEntry> entry : accessedToBridge.entrySet()) {
35 MethodEntry accessedEntry = entry.getKey();
36 MethodEntry bridgeEntry = entry.getValue();
37
38 MethodEntry renamedAccessedEntry = accessedEntry.withName(bridgeEntry.getName());
39 methods.put(renamedAccessedEntry, methods.remove(accessedEntry));
40 }
41 }
42
43 public boolean hasClass(ClassEntry entry) { 31 public boolean hasClass(ClassEntry entry) {
44 return classes.containsKey(entry); 32 return classes.containsKey(entry);
45 } 33 }
diff --git a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java
index ee28b3e..2b63c5d 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java
@@ -8,7 +8,6 @@ import cuchaz.enigma.translation.representation.entry.*;
8 8
9import java.util.Collection; 9import java.util.Collection;
10import java.util.Map; 10import java.util.Map;
11import java.util.Optional;
12 11
13public class ReferenceIndex implements JarIndexer { 12public class ReferenceIndex implements JarIndexer {
14 private Multimap<MethodEntry, MethodEntry> methodReferences = HashMultimap.create(); 13 private Multimap<MethodEntry, MethodEntry> methodReferences = HashMultimap.create();
@@ -58,30 +57,11 @@ public class ReferenceIndex implements JarIndexer {
58 } 57 }
59 58
60 private <E extends Entry<?>> E remap(JarIndex index, E entry) { 59 private <E extends Entry<?>> E remap(JarIndex index, E entry) {
61 E resolvedEntry = index.getEntryResolver().resolveFirstEntry(entry, ResolutionStrategy.RESOLVE_CLOSEST); 60 return index.getEntryResolver().resolveFirstEntry(entry, ResolutionStrategy.RESOLVE_CLOSEST);
62
63 Optional<E> remappedBridge = getRemappedBridge(index, resolvedEntry);
64 return remappedBridge.orElse(resolvedEntry);
65 } 61 }
66 62
67 private <E extends Entry<?>, C extends Entry<?>> EntryReference<E, C> remap(JarIndex index, EntryReference<E, C> reference) { 63 private <E extends Entry<?>, C extends Entry<?>> EntryReference<E, C> remap(JarIndex index, EntryReference<E, C> reference) {
68 EntryReference<E, C> resolvedReference = index.getEntryResolver().resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); 64 return index.getEntryResolver().resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST);
69
70 getRemappedBridge(index, resolvedReference.entry).ifPresent(e -> resolvedReference.entry = e);
71 getRemappedBridge(index, resolvedReference.context).ifPresent(e -> resolvedReference.context = e);
72
73 return resolvedReference;
74 }
75
76 @SuppressWarnings("unchecked")
77 private <E extends Entry<?>> Optional<E> getRemappedBridge(JarIndex index, E entry) {
78 if (entry instanceof MethodEntry) {
79 MethodEntry bridgeEntry = index.getBridgeMethodIndex().getBridgeFromAccessed((MethodEntry) entry);
80 if (bridgeEntry != null) {
81 return Optional.of((E) entry.withName(bridgeEntry.getName()));
82 }
83 }
84 return Optional.empty();
85 } 65 }
86 66
87 public Collection<MethodEntry> getMethodsReferencedBy(MethodEntry entry) { 67 public Collection<MethodEntry> getMethodsReferencedBy(MethodEntry entry) {