|
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 |
@@ -277,14 +277,46 @@ private void runApplicatorPass(ApplicatorPass pass, List<MixinTargetContext> mix |
277 | 277 | this.applyFields(mixin); |
278 | 278 | activity.next("Apply Methods"); |
279 | 279 | this.applyMethods(mixin); |
280 | | - activity.next("Apply Initialisers"); |
281 | | - this.applyInitialisers(mixin); |
282 | 280 | }); |
283 | 281 | break; |
284 | 282 | case INJECT_PREPARE: |
285 | 283 | this.processMixins(mixinContexts, (activity, mixin) -> { |
286 | | - activity.next("Prepare Injections"); |
287 | | - this.prepareInjections(mixin); |
| 284 | + if (FabricUtil.getCompatibility(mixin) >= FabricUtil.COMPATIBILITY_0_17_1) { |
| 285 | + activity.next("Prepare Injections"); |
| 286 | + this.prepareInjections(mixin); |
| 287 | + } |
| 288 | + }); |
| 289 | + break; |
| 290 | + case INITIALISER_APPLY_LEGACY: |
| 291 | + this.processMixins(mixinContexts, (activity, mixin) -> { |
| 292 | + if (FabricUtil.getCompatibility(mixin) < FabricUtil.COMPATIBILITY_0_17_1) { |
| 293 | + activity.next("Apply Legacy Initialisers"); |
| 294 | + this.applyInitialisers(mixin); |
| 295 | + MethodNode clinit = Bytecode.findMethod(mixin.getClassNode(), Constants.CLINIT, "()V"); |
| 296 | + if (clinit != null) { |
| 297 | + activity.next("Apply Legacy CLINIT"); |
| 298 | + this.appendInsns(mixin, clinit); |
| 299 | + } |
| 300 | + } |
| 301 | + }); |
| 302 | + break; |
| 303 | + case INJECT_PREPARE_LEGACY: |
| 304 | + this.processMixins(mixinContexts, (activity, mixin) -> { |
| 305 | + if (FabricUtil.getCompatibility(mixin) < FabricUtil.COMPATIBILITY_0_17_1) { |
| 306 | + activity.next("Prepare Legacy Injections"); |
| 307 | + this.prepareInjections(mixin); |
| 308 | + } |
| 309 | + }); |
| 310 | + break; |
| 311 | + case INITIALISER_APPLY: |
| 312 | + Supplier<Clinit> targetClinit = Suppliers.memoize(this::prepareOrCreateClinit); |
| 313 | + this.processMixins(mixinContexts, (activity, mixin) -> { |
| 314 | + if (FabricUtil.getCompatibility(mixin) >= FabricUtil.COMPATIBILITY_0_17_1) { |
| 315 | + activity.next("Apply Initialisers"); |
| 316 | + this.applyInitialisers(mixin); |
| 317 | + activity.next("Apply CLINIT"); |
| 318 | + this.applyClinit(mixin, targetClinit); |
| 319 | + } |
288 | 320 | }); |
289 | 321 | break; |
290 | 322 | case ACCESSOR: |
@@ -467,11 +499,6 @@ protected void applyNormalMethod(MixinTargetContext mixin, MethodNode mixinMetho |
467 | 499 | this.checkMethodVisibility(mixin, mixinMethod); |
468 | 500 | this.checkMethodConstraints(mixin, mixinMethod); |
469 | 501 | 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 | 502 | } |
476 | 503 | } |
477 | 504 |
|
@@ -723,6 +750,26 @@ protected void applyInitialisers(MixinTargetContext mixin) { |
723 | 750 | } |
724 | 751 | } |
725 | 752 |
|
| 753 | + private Clinit prepareOrCreateClinit() { |
| 754 | + MethodNode clinit = Bytecode.findMethod(this.targetClass, Constants.CLINIT, "()V"); |
| 755 | + if (clinit != null) { |
| 756 | + return Clinit.prepare(this.context.getTargetMethod(clinit)); |
| 757 | + } |
| 758 | + clinit = new MethodNode(ASM.API_VERSION, Opcodes.ACC_STATIC, Constants.CLINIT, "()V", null, null); |
| 759 | + InsnNode finalReturn = new InsnNode(Opcodes.RETURN); |
| 760 | + clinit.instructions.add(finalReturn); |
| 761 | + this.targetClass.methods.add(clinit); |
| 762 | + return new Clinit(clinit, finalReturn); |
| 763 | + } |
| 764 | + |
| 765 | + protected void applyClinit(MixinTargetContext mixin, Supplier<Clinit> clinit) { |
| 766 | + MethodNode mixinClinit = Bytecode.findMethod(mixin.getClassNode(), Constants.CLINIT, "()V"); |
| 767 | + if (mixinClinit == null) { |
| 768 | + return; |
| 769 | + } |
| 770 | + clinit.get().append(mixinClinit); |
| 771 | + } |
| 772 | + |
726 | 773 | /** |
727 | 774 | * Scan for injector methods and injection points |
728 | 775 | * |
|
0 commit comments