|
28 | 28 | import java.util.*; |
29 | 29 | import java.util.Map.Entry; |
30 | 30 | import java.util.function.BiConsumer; |
| 31 | +import java.util.function.Supplier; |
31 | 32 |
|
| 33 | +import com.google.common.base.Suppliers; |
32 | 34 | import org.spongepowered.asm.logging.ILogger; |
33 | | -import org.objectweb.asm.Label; |
34 | 35 | import org.objectweb.asm.Opcodes; |
35 | 36 | import org.objectweb.asm.Type; |
36 | 37 | import org.objectweb.asm.signature.SignatureReader; |
37 | 38 | import org.objectweb.asm.signature.SignatureVisitor; |
38 | 39 | import org.objectweb.asm.tree.*; |
39 | | -import org.spongepowered.asm.mixin.Final; |
40 | | -import org.spongepowered.asm.mixin.Intrinsic; |
41 | | -import org.spongepowered.asm.mixin.MixinEnvironment; |
| 40 | +import org.spongepowered.asm.mixin.*; |
42 | 41 | import org.spongepowered.asm.mixin.MixinEnvironment.Option; |
43 | | -import org.spongepowered.asm.mixin.Overwrite; |
44 | 42 | import org.spongepowered.asm.mixin.extensibility.IActivityContext.IActivity; |
45 | 43 | import org.spongepowered.asm.mixin.gen.Accessor; |
46 | 44 | import org.spongepowered.asm.mixin.gen.Invoker; |
|
51 | 49 | import org.spongepowered.asm.mixin.injection.ModifyVariable; |
52 | 50 | import org.spongepowered.asm.mixin.injection.Redirect; |
53 | 51 | import org.spongepowered.asm.mixin.injection.struct.Constructor; |
| 52 | +import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode; |
| 53 | +import org.spongepowered.asm.mixin.injection.struct.Target; |
54 | 54 | import org.spongepowered.asm.mixin.throwables.MixinError; |
55 | 55 | import org.spongepowered.asm.mixin.transformer.ClassInfo.Field; |
56 | 56 | import org.spongepowered.asm.mixin.transformer.ext.extensions.ExtensionClassExporter; |
57 | 57 | import org.spongepowered.asm.mixin.transformer.meta.MixinMerged; |
58 | 58 | import org.spongepowered.asm.mixin.transformer.meta.MixinRenamed; |
| 59 | +import org.spongepowered.asm.mixin.transformer.struct.Clinit; |
59 | 60 | import org.spongepowered.asm.mixin.transformer.struct.Initialiser; |
60 | 61 | import org.spongepowered.asm.mixin.transformer.throwables.InvalidMixinException; |
61 | 62 | import org.spongepowered.asm.mixin.transformer.throwables.MixinApplicatorException; |
62 | 63 | import org.spongepowered.asm.service.IMixinAuditTrail; |
63 | 64 | import org.spongepowered.asm.service.MixinService; |
64 | 65 | import org.spongepowered.asm.util.Annotations; |
65 | 66 | import org.spongepowered.asm.util.Bytecode; |
66 | | -import org.spongepowered.asm.util.Bytecode.DelegateInitialiser; |
67 | 67 | import org.spongepowered.asm.util.Constants; |
68 | 68 | import org.spongepowered.asm.util.ConstraintParser; |
69 | 69 | import org.spongepowered.asm.util.ConstraintParser.Constraint; |
| 70 | +import org.spongepowered.asm.util.asm.ASM; |
70 | 71 | import org.spongepowered.asm.util.perf.Profiler; |
71 | 72 | import org.spongepowered.asm.util.perf.Profiler.Section; |
72 | 73 | import org.spongepowered.asm.util.throwables.ConstraintViolationException; |
73 | 74 | import org.spongepowered.asm.util.throwables.InvalidConstraintException; |
74 | 75 |
|
75 | 76 | import com.google.common.collect.ImmutableList; |
76 | | -import com.google.common.collect.ImmutableSet; |
77 | 77 |
|
78 | 78 | /** |
79 | 79 | * Applies mixins to a target class |
@@ -103,12 +103,24 @@ enum ApplicatorPass { |
103 | 103 | */ |
104 | 104 | MAIN, |
105 | 105 |
|
| 106 | + /** |
| 107 | + * Enumerate injectors and scan for injection points |
| 108 | + */ |
106 | 109 | INJECT_PREPARE, |
107 | 110 |
|
| 111 | + /** |
| 112 | + * Apply instance field initialisers and {@code <clinit>} methods in legacy mixins (compat level < 0.17.1) |
| 113 | + */ |
108 | 114 | INITIALISER_APPLY_LEGACY, |
109 | 115 |
|
| 116 | + /** |
| 117 | + * Enumerate injectors and scan for injection points in legacy mixins (compat level < 0.17.1) |
| 118 | + */ |
110 | 119 | INJECT_PREPARE_LEGACY, |
111 | 120 |
|
| 121 | + /** |
| 122 | + * Apply instance field initialisers and {@code <clinit>} methods |
| 123 | + */ |
112 | 124 | INITIALISER_APPLY, |
113 | 125 |
|
114 | 126 | /** |
@@ -277,14 +289,43 @@ private void runApplicatorPass(ApplicatorPass pass, List<MixinTargetContext> mix |
277 | 289 | this.applyFields(mixin); |
278 | 290 | activity.next("Apply Methods"); |
279 | 291 | this.applyMethods(mixin); |
280 | | - activity.next("Apply Initialisers"); |
281 | | - this.applyInitialisers(mixin); |
282 | 292 | }); |
283 | 293 | break; |
284 | 294 | case INJECT_PREPARE: |
285 | 295 | this.processMixins(mixinContexts, (activity, mixin) -> { |
286 | | - activity.next("Prepare Injections"); |
287 | | - this.prepareInjections(mixin); |
| 296 | + if (FabricUtil.getCompatibility(mixin) >= FabricUtil.COMPATIBILITY_0_17_1) { |
| 297 | + activity.next("Prepare Injections"); |
| 298 | + this.prepareInjections(mixin); |
| 299 | + } |
| 300 | + }); |
| 301 | + break; |
| 302 | + case INITIALISER_APPLY_LEGACY: |
| 303 | + this.processMixins(mixinContexts, (activity, mixin) -> { |
| 304 | + if (FabricUtil.getCompatibility(mixin) < FabricUtil.COMPATIBILITY_0_17_1) { |
| 305 | + activity.next("Apply Legacy Initialisers"); |
| 306 | + this.applyInitialisers(mixin); |
| 307 | + activity.next("Apply Legacy CLINIT"); |
| 308 | + this.applyClinitLegacy(mixin); |
| 309 | + } |
| 310 | + }); |
| 311 | + break; |
| 312 | + case INJECT_PREPARE_LEGACY: |
| 313 | + this.processMixins(mixinContexts, (activity, mixin) -> { |
| 314 | + if (FabricUtil.getCompatibility(mixin) < FabricUtil.COMPATIBILITY_0_17_1) { |
| 315 | + activity.next("Prepare Legacy Injections"); |
| 316 | + this.prepareInjections(mixin); |
| 317 | + } |
| 318 | + }); |
| 319 | + break; |
| 320 | + case INITIALISER_APPLY: |
| 321 | + Supplier<Clinit> targetClinit = Suppliers.memoize(this::prepareOrCreateClinit); |
| 322 | + this.processMixins(mixinContexts, (activity, mixin) -> { |
| 323 | + if (FabricUtil.getCompatibility(mixin) >= FabricUtil.COMPATIBILITY_0_17_1) { |
| 324 | + activity.next("Apply Initialisers"); |
| 325 | + this.applyInitialisers(mixin); |
| 326 | + activity.next("Apply CLINIT"); |
| 327 | + this.applyClinit(mixin, targetClinit); |
| 328 | + } |
288 | 329 | }); |
289 | 330 | break; |
290 | 331 | case ACCESSOR: |
@@ -467,11 +508,6 @@ protected void applyNormalMethod(MixinTargetContext mixin, MethodNode mixinMetho |
467 | 508 | this.checkMethodVisibility(mixin, mixinMethod); |
468 | 509 | this.checkMethodConstraints(mixin, mixinMethod); |
469 | 510 | this.mergeMethod(mixin, mixinMethod); |
470 | | - } else if (Constants.CLINIT.equals(mixinMethod.name)) { |
471 | | - // Class initialiser insns get appended |
472 | | - IActivity activity = this.activities.begin("Merge CLINIT insns"); |
473 | | - this.appendInsns(mixin, mixinMethod); |
474 | | - activity.end(); |
475 | 511 | } |
476 | 512 | } |
477 | 513 |
|
@@ -723,6 +759,33 @@ protected void applyInitialisers(MixinTargetContext mixin) { |
723 | 759 | } |
724 | 760 | } |
725 | 761 |
|
| 762 | + protected void applyClinitLegacy(MixinTargetContext mixin) { |
| 763 | + MethodNode clinit = Bytecode.findMethod(mixin.getClassNode(), Constants.CLINIT, "()V"); |
| 764 | + if (clinit != null) { |
| 765 | + this.appendInsns(mixin, clinit); |
| 766 | + } |
| 767 | + } |
| 768 | + |
| 769 | + private Clinit prepareOrCreateClinit() { |
| 770 | + MethodNode clinit = Bytecode.findMethod(this.targetClass, Constants.CLINIT, "()V"); |
| 771 | + if (clinit != null) { |
| 772 | + return Clinit.prepare(this.context.getTargetMethod(clinit)); |
| 773 | + } |
| 774 | + clinit = new MethodNode(ASM.API_VERSION, Opcodes.ACC_STATIC, Constants.CLINIT, "()V", null, null); |
| 775 | + InsnNode finalReturn = new InsnNode(Opcodes.RETURN); |
| 776 | + clinit.instructions.add(finalReturn); |
| 777 | + this.targetClass.methods.add(clinit); |
| 778 | + return new Clinit(clinit, finalReturn); |
| 779 | + } |
| 780 | + |
| 781 | + protected void applyClinit(MixinTargetContext mixin, Supplier<Clinit> clinit) { |
| 782 | + MethodNode mixinClinit = Bytecode.findMethod(mixin.getClassNode(), Constants.CLINIT, "()V"); |
| 783 | + if (mixinClinit == null) { |
| 784 | + return; |
| 785 | + } |
| 786 | + clinit.get().append(mixinClinit); |
| 787 | + } |
| 788 | + |
726 | 789 | /** |
727 | 790 | * Scan for injector methods and injection points |
728 | 791 | * |
|
0 commit comments