2323import net .bytebuddy .implementation .Implementation ;
2424import net .bytebuddy .jar .asm .ClassVisitor ;
2525import net .bytebuddy .jar .asm .Handle ;
26+ import net .bytebuddy .jar .asm .Label ;
2627import net .bytebuddy .jar .asm .MethodVisitor ;
2728import net .bytebuddy .jar .asm .Opcodes ;
2829import net .bytebuddy .jar .asm .Type ;
@@ -128,23 +129,43 @@ public MethodVisitor visitMethod(
128129 private static class CallSiteMethodVisitor extends MethodVisitor
129130 implements CallSiteAdvice .MethodHandler {
130131 protected final Advices advices ;
132+ protected int lastOpcode ;
133+ protected boolean newFollowedByDup ;
131134
132135 private CallSiteMethodVisitor (
133136 @ Nonnull final Advices advices , @ Nonnull final MethodVisitor delegated ) {
134137 super (ASM_API , delegated );
135138 this .advices = advices ;
136139 }
137140
141+ @ Override
142+ public void visitTypeInsn (int opcode , String type ) {
143+ lastOpcode = opcode ;
144+ if (opcode == Opcodes .NEW ) {
145+ newFollowedByDup = false ;
146+ }
147+ super .visitTypeInsn (opcode , type );
148+ }
149+
150+ @ Override
151+ public void visitInsn (final int opcode ) {
152+ if (opcode == Opcodes .DUP ) {
153+ newFollowedByDup = lastOpcode == Opcodes .NEW ;
154+ }
155+ lastOpcode = opcode ;
156+ super .visitInsn (opcode );
157+ }
158+
138159 @ Override
139160 public void visitMethodInsn (
140161 final int opcode ,
141162 final String owner ,
142163 final String name ,
143164 final String descriptor ,
144165 final boolean isInterface ) {
145-
166+ lastOpcode = opcode ;
146167 CallSiteAdvice advice = advices .findAdvice (owner , name , descriptor );
147- if (advice instanceof InvokeAdvice ) {
168+ if (applyInvokeAdvice ( advice , name , descriptor ) ) {
148169 invokeAdvice ((InvokeAdvice ) advice , opcode , owner , name , descriptor , isInterface );
149170 } else {
150171 mv .visitMethodInsn (opcode , owner , name , descriptor , isInterface );
@@ -167,6 +188,7 @@ public void visitInvokeDynamicInsn(
167188 final String descriptor ,
168189 final Handle bootstrapMethodHandle ,
169190 final Object ... bootstrapMethodArguments ) {
191+ lastOpcode = Opcodes .INVOKEDYNAMIC ;
170192 CallSiteAdvice advice = advices .findAdvice (bootstrapMethodHandle );
171193 if (advice instanceof InvokeDynamicAdvice ) {
172194 invokeDynamicAdvice (
@@ -303,6 +325,75 @@ private Type[] methodParamTypesWithThis(String owner, String methodDescriptor) {
303325 methodParameterTypesWithThis .length - 1 );
304326 return methodParameterTypesWithThis ;
305327 }
328+
329+ protected boolean applyInvokeAdvice (
330+ final CallSiteAdvice advice , final String methodName , final String methodDescriptor ) {
331+ if (!(advice instanceof InvokeAdvice )) {
332+ return false ;
333+ }
334+ if (!"<init>" .equals (methodName )) {
335+ return true ;
336+ }
337+ // TODO: do not ignore ctors where there is no DUP after NEW
338+ return newFollowedByDup ;
339+ }
340+
341+ // Keep track of the latest opcode to match a DUP with its previous NEW
342+ @ Override
343+ public void visitIntInsn (final int opcode , final int operand ) {
344+ lastOpcode = opcode ;
345+ super .visitIntInsn (opcode , operand );
346+ }
347+
348+ @ Override
349+ public void visitVarInsn (final int opcode , final int var ) {
350+ lastOpcode = opcode ;
351+ super .visitVarInsn (opcode , var );
352+ }
353+
354+ @ Override
355+ public void visitFieldInsn (
356+ final int opcode , final String owner , final String name , final String descriptor ) {
357+ lastOpcode = opcode ;
358+ super .visitFieldInsn (opcode , owner , name , descriptor );
359+ }
360+
361+ @ Override
362+ public void visitJumpInsn (final int opcode , final Label label ) {
363+ lastOpcode = opcode ;
364+ super .visitJumpInsn (opcode , label );
365+ }
366+
367+ @ Override
368+ public void visitLdcInsn (final Object value ) {
369+ lastOpcode = Opcodes .LDC ;
370+ super .visitLdcInsn (value );
371+ }
372+
373+ @ Override
374+ public void visitIincInsn (final int var , final int increment ) {
375+ lastOpcode = Opcodes .IINC ;
376+ super .visitIincInsn (var , increment );
377+ }
378+
379+ @ Override
380+ public void visitTableSwitchInsn (
381+ final int min , final int max , final Label dflt , final Label ... labels ) {
382+ lastOpcode = Opcodes .TABLESWITCH ;
383+ super .visitTableSwitchInsn (min , max , dflt , labels );
384+ }
385+
386+ @ Override
387+ public void visitLookupSwitchInsn (final Label dflt , final int [] keys , final Label [] labels ) {
388+ lastOpcode = Opcodes .LOOKUPSWITCH ;
389+ super .visitLookupSwitchInsn (dflt , keys , labels );
390+ }
391+
392+ @ Override
393+ public void visitMultiANewArrayInsn (final String descriptor , final int numDimensions ) {
394+ lastOpcode = Opcodes .MULTIANEWARRAY ;
395+ super .visitMultiANewArrayInsn (descriptor , numDimensions );
396+ }
306397 }
307398
308399 private static class CallSiteCtorMethodVisitor extends CallSiteMethodVisitor {
@@ -390,5 +481,14 @@ protected void invokeAdvice(
390481 super .invokeAdvice (advice , opcode , owner , name , descriptor , isInterface );
391482 }
392483 }
484+
485+ @ Override
486+ protected boolean applyInvokeAdvice (
487+ final CallSiteAdvice advice , final String methodName , final String descriptor ) {
488+ if (isSuperCall ) {
489+ return advice instanceof InvokeAdvice && "<init>" .equals (methodName );
490+ }
491+ return super .applyInvokeAdvice (advice , methodName , descriptor );
492+ }
393493 }
394494}
0 commit comments