Commit 171e491f790ffcaa8d23e85821c56c077dc103b9
1 parent
104bd7e5
pass the current return value into ReturnEventInfo ctor where possible
Showing
3 changed files
with
39 additions
and
15 deletions
java/common/com/mumfrey/liteloader/transformers/event/Event.java
... | ... | @@ -345,18 +345,30 @@ public class Event implements Comparable<Event> |
345 | 345 | LiteLoaderLogger.debug("Event %s is spawning handler %s in class %s", this.name, handler.name, Event.getActiveProxyRef()); |
346 | 346 | |
347 | 347 | int ctorMAXS = 0, invokeMAXS = arguments.length + (doCaptureLocals ? locals.length - initialFrameSize : 0); |
348 | - int eventInfoVar = this.method.maxLocals++; | |
348 | + int marshallVar = this.method.maxLocals++; | |
349 | 349 | |
350 | 350 | InsnList insns = new InsnList(); |
351 | 351 | |
352 | + boolean pushReturnValue = false; | |
353 | + | |
354 | + // If this is a ReturnEventInfo AND we are right before a RETURN opcode (so we can expect the *original* return | |
355 | + // value to be on the stack, then we dup the return value into a local var so we can push it later when we invoke | |
356 | + // the ReturnEventInfo ctor | |
357 | + if (injectionPoint instanceof InsnNode && injectionPoint.getOpcode() >= Opcodes.IRETURN && injectionPoint.getOpcode() < Opcodes.RETURN) | |
358 | + { | |
359 | + pushReturnValue = true; | |
360 | + insns.add(new InsnNode(Opcodes.DUP)); | |
361 | + insns.add(new VarInsnNode(this.methodReturnType.getOpcode(Opcodes.ISTORE), marshallVar)); | |
362 | + } | |
363 | + | |
352 | 364 | // Instance the EventInfo for this event |
353 | 365 | insns.add(new TypeInsnNode(Opcodes.NEW, this.eventInfoClass)); ctorMAXS++; |
354 | 366 | insns.add(new InsnNode(Opcodes.DUP)); ctorMAXS++; invokeMAXS++; |
355 | - ctorMAXS += this.invokeEventInfoConstructor(insns, cancellable); | |
356 | - insns.add(new VarInsnNode(Opcodes.ASTORE, eventInfoVar)); | |
367 | + ctorMAXS += this.invokeEventInfoConstructor(insns, cancellable, pushReturnValue, marshallVar); | |
368 | + insns.add(new VarInsnNode(Opcodes.ASTORE, marshallVar)); | |
357 | 369 | |
358 | 370 | // Call the event handler method in the proxy |
359 | - insns.add(new VarInsnNode(Opcodes.ALOAD, eventInfoVar)); | |
371 | + insns.add(new VarInsnNode(Opcodes.ALOAD, marshallVar)); | |
360 | 372 | ByteCodeUtilities.loadArgs(arguments, insns, this.methodIsStatic ? 0 : 1); |
361 | 373 | if (doCaptureLocals) |
362 | 374 | { |
... | ... | @@ -367,7 +379,7 @@ public class Event implements Comparable<Event> |
367 | 379 | if (cancellable) |
368 | 380 | { |
369 | 381 | // Inject the if (e.isCancelled()) return e.getReturnValue(); |
370 | - this.injectCancellationCode(insns, injectionPoint, eventInfoVar); | |
382 | + this.injectCancellationCode(insns, injectionPoint, marshallVar); | |
371 | 383 | } |
372 | 384 | |
373 | 385 | // Inject our generated code into the method |
... | ... | @@ -390,14 +402,23 @@ public class Event implements Comparable<Event> |
390 | 402 | return eventDescriptor + ")V"; |
391 | 403 | } |
392 | 404 | |
393 | - protected int invokeEventInfoConstructor(InsnList insns, boolean cancellable) | |
405 | + protected int invokeEventInfoConstructor(InsnList insns, boolean cancellable, boolean pushReturnValue, int marshallVar) | |
394 | 406 | { |
395 | 407 | int ctorMAXS = 0; |
396 | 408 | |
397 | 409 | insns.add(new LdcInsnNode(this.name)); ctorMAXS++; |
398 | 410 | insns.add(this.methodIsStatic ? new InsnNode(Opcodes.ACONST_NULL) : new VarInsnNode(Opcodes.ALOAD, 0)); ctorMAXS++; |
399 | 411 | insns.add(new InsnNode(cancellable ? Opcodes.ICONST_1 : Opcodes.ICONST_0)); ctorMAXS++; |
400 | - insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, this.eventInfoClass, Obf.constructor.name, EventInfo.getConstructorDescriptor(), false)); | |
412 | + | |
413 | + if (pushReturnValue) | |
414 | + { | |
415 | + insns.add(new VarInsnNode(this.methodReturnType.getOpcode(Opcodes.ILOAD), marshallVar)); | |
416 | + insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, this.eventInfoClass, Obf.constructor.name, EventInfo.getConstructorDescriptor(this.methodReturnType), false)); | |
417 | + } | |
418 | + else | |
419 | + { | |
420 | + insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, this.eventInfoClass, Obf.constructor.name, EventInfo.getConstructorDescriptor(), false)); | |
421 | + } | |
401 | 422 | |
402 | 423 | return ctorMAXS; |
403 | 424 | } |
... | ... | @@ -412,18 +433,18 @@ public class Event implements Comparable<Event> |
412 | 433 | * |
413 | 434 | * @param insns |
414 | 435 | * @param injectionPoint |
415 | - * @param eventInfoVar | |
436 | + * @param marshallVar | |
416 | 437 | */ |
417 | - protected void injectCancellationCode(final InsnList insns, final AbstractInsnNode injectionPoint, int eventInfoVar) | |
438 | + protected void injectCancellationCode(final InsnList insns, final AbstractInsnNode injectionPoint, int marshallVar) | |
418 | 439 | { |
419 | - insns.add(new VarInsnNode(Opcodes.ALOAD, eventInfoVar)); | |
440 | + insns.add(new VarInsnNode(Opcodes.ALOAD, marshallVar)); | |
420 | 441 | insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, this.eventInfoClass, EventInfo.getIsCancelledMethodName(), EventInfo.getIsCancelledMethodSig(), false)); |
421 | 442 | |
422 | 443 | LabelNode notCancelled = new LabelNode(); |
423 | 444 | insns.add(new JumpInsnNode(Opcodes.IFEQ, notCancelled)); |
424 | 445 | |
425 | 446 | // If this is a void method, just injects a RETURN opcode, otherwise we need to get the return value from the EventInfo |
426 | - this.injectReturnCode(insns, injectionPoint, eventInfoVar); | |
447 | + this.injectReturnCode(insns, injectionPoint, marshallVar); | |
427 | 448 | |
428 | 449 | insns.add(notCancelled); |
429 | 450 | } | ... | ... |
java/common/com/mumfrey/liteloader/transformers/event/EventInfo.java
... | ... | @@ -108,10 +108,10 @@ public class EventInfo<S> implements Cancellable |
108 | 108 | |
109 | 109 | if (returnType.getSort() == Type.OBJECT) |
110 | 110 | { |
111 | - return String.format("(%s%s%sZ)V", EventInfo.STRING, EventInfo.OBJECT, EventInfo.OBJECT); | |
111 | + return String.format("(%s%sZ%s)V", EventInfo.STRING, EventInfo.OBJECT, EventInfo.OBJECT); | |
112 | 112 | } |
113 | 113 | |
114 | - return String.format("(%s%s%sZ)V", EventInfo.STRING, EventInfo.OBJECT, returnType.getDescriptor()); | |
114 | + return String.format("(%s%sZ%s)V", EventInfo.STRING, EventInfo.OBJECT, returnType.getDescriptor()); | |
115 | 115 | } |
116 | 116 | |
117 | 117 | public static String getConstructorDescriptor() | ... | ... |
java/common/com/mumfrey/liteloader/transformers/event/inject/BeforeInvoke.java
... | ... | @@ -223,9 +223,12 @@ public class BeforeInvoke extends InjectionPoint |
223 | 223 | if (this.methodOwners[i] != null) this.methodOwners[i] = this.methodOwners[i].replace('.', '/'); |
224 | 224 | } |
225 | 225 | |
226 | - for (int i = 0; i < this.methodSignatures.length; i++) | |
226 | + if (this.methodSignatures != null) | |
227 | 227 | { |
228 | - if (this.methodSignatures[i] != null) this.methodSignatures[i] = this.methodSignatures[i].replace('.', '/'); | |
228 | + for (int i = 0; i < this.methodSignatures.length; i++) | |
229 | + { | |
230 | + if (this.methodSignatures[i] != null) this.methodSignatures[i] = this.methodSignatures[i].replace('.', '/'); | |
231 | + } | |
229 | 232 | } |
230 | 233 | } |
231 | 234 | ... | ... |