22
33import java .util .ArrayList ;
44import java .util .Comparator ;
5+ import java .util .HashMap ;
56import java .util .HashSet ;
67import java .util .List ;
8+ import java .util .Map ;
79import java .util .Set ;
810
911import org .objectweb .asm .Type ;
@@ -77,20 +79,26 @@ public void modify(org.objectweb.asm.tree.ClassNode classNode) {
7779 continue ;
7880 }
7981
82+ boolean inline = RANDOM .nextBoolean ();
8083 String implName = nextUniqueName (used , method .desc );
8184 used .add (methodKey (implName , method .desc ));
8285
83- MethodNode impl = new MethodNode ();
84- impl .access = toImplAccess (method .access );
85- impl .name = implName ;
86- impl .desc = method .desc ;
87- impl .signature = method .signature ;
88- impl .exceptions = method .exceptions ;
89- impl .instructions = method .instructions ;
90- impl .tryCatchBlocks = method .tryCatchBlocks ;
91- impl .localVariables = method .localVariables ;
92- impl .maxLocals = method .maxLocals ;
93- impl .maxStack = method .maxStack ;
86+ InsnList originalInsn = method .instructions ;
87+
88+ if (!inline ) {
89+ MethodNode impl = new MethodNode ();
90+ impl .access = toImplAccess (method .access );
91+ impl .name = implName ;
92+ impl .desc = method .desc ;
93+ impl .signature = method .signature ;
94+ impl .exceptions = method .exceptions ;
95+ impl .instructions = originalInsn ;
96+ impl .tryCatchBlocks = method .tryCatchBlocks ;
97+ impl .localVariables = method .localVariables ;
98+ impl .maxLocals = method .maxLocals ;
99+ impl .maxStack = method .maxStack ;
100+ classNode .methods .add (impl );
101+ }
94102
95103 method .instructions = new InsnList ();
96104 method .tryCatchBlocks = new ArrayList <>();
@@ -107,14 +115,12 @@ public void modify(org.objectweb.asm.tree.ClassNode classNode) {
107115
108116 Type returnType = Type .getReturnType (method .desc );
109117 Type [] argTypes = Type .getArgumentTypes (method .desc );
110- DispatchEntry entry = new DispatchEntry (key , implName , method .desc , returnType , argTypes , isStatic );
118+ DispatchEntry entry = new DispatchEntry (key , implName , method .desc , returnType , argTypes , isStatic , inline , originalInsn );
111119 if (isStatic ) {
112120 staticEntries .add (entry );
113121 } else {
114122 instanceEntries .add (entry );
115123 }
116-
117- classNode .methods .add (impl );
118124 }
119125
120126 if (!instanceEntries .isEmpty ()) {
@@ -152,20 +158,26 @@ private static MethodNode createDispatch(String name, boolean isStatic, List<Dis
152158 DispatchEntry entry = sorted .get (i );
153159 insn .add (labels [i ]);
154160
155- if (!entry .isStatic ) {
156- insn .add (new VarInsnNode (ALOAD , 0 ));
157- }
158- for (int argIndex = 0 ; argIndex < entry .argTypes .length ; argIndex ++) {
159- Type argType = entry .argTypes [argIndex ];
160- insn .add (new VarInsnNode (ALOAD , argsIndex ));
161- insn .add (pushInt (argIndex ));
162- insn .add (new InsnNode (AALOAD ));
163- addUnbox (insn , argType );
161+ if (entry .inline ) {
162+ InsnList inlinedCode = cloneInsnList (entry .insnList );
163+ remapVarsForInline (inlinedCode , entry .argTypes , entry .isStatic , argsIndex );
164+ insn .add (inlinedCode );
165+ } else {
166+ if (!entry .isStatic ) {
167+ insn .add (new VarInsnNode (ALOAD , 0 ));
168+ }
169+ for (int argIndex = 0 ; argIndex < entry .argTypes .length ; argIndex ++) {
170+ Type argType = entry .argTypes [argIndex ];
171+ insn .add (new VarInsnNode (ALOAD , argsIndex ));
172+ insn .add (pushInt (argIndex ));
173+ insn .add (new InsnNode (AALOAD ));
174+ addUnbox (insn , argType );
175+ }
176+
177+ int invokeOp = entry .isStatic ? INVOKESTATIC : INVOKESPECIAL ;
178+ insn .add (new MethodInsnNode (invokeOp , owner , entry .implName , entry .desc , false ));
179+ addBoxOrNullReturn (insn , entry .returnType );
164180 }
165-
166- int invokeOp = entry .isStatic ? INVOKESTATIC : INVOKESPECIAL ;
167- insn .add (new MethodInsnNode (invokeOp , owner , entry .implName , entry .desc , false ));
168- addBoxOrNullReturn (insn , entry .returnType );
169181 }
170182
171183 insn .add (defaultLabel );
@@ -341,22 +353,73 @@ private static int nextUniqueKey(Set<Integer> used) {
341353 return key ;
342354 }
343355
356+ private static InsnList cloneInsnList (InsnList original ) {
357+ InsnList clone = new InsnList ();
358+ Map <LabelNode , LabelNode > labelMap = new HashMap <>();
359+
360+ for (AbstractInsnNode insn : original ) {
361+ if (insn instanceof LabelNode ) {
362+ LabelNode oldLabel = (LabelNode ) insn ;
363+ LabelNode newLabel = new LabelNode ();
364+ labelMap .put (oldLabel , newLabel );
365+ }
366+ }
367+
368+ for (AbstractInsnNode insn : original ) {
369+ clone .add (insn .clone (labelMap ));
370+ }
371+
372+ return clone ;
373+ }
374+
375+ private static void remapVarsForInline (InsnList insn , Type [] argTypes , boolean isStatic , int argsArrayIndex ) {
376+ int originalVarBase = isStatic ? 0 : 1 ;
377+
378+ for (AbstractInsnNode node : insn ) {
379+ if (node instanceof VarInsnNode ) {
380+ VarInsnNode varNode = (VarInsnNode ) node ;
381+ int originalIndex = varNode .var ;
382+
383+ if (!isStatic && originalIndex == 0 ) {
384+ continue ;
385+ }
386+
387+ int argIndex = originalIndex - originalVarBase ;
388+ if (argIndex >= 0 && argIndex < argTypes .length ) {
389+ Type argType = argTypes [argIndex ];
390+ InsnList replacement = new InsnList ();
391+ replacement .add (new VarInsnNode (ALOAD , argsArrayIndex ));
392+ replacement .add (pushInt (argIndex ));
393+ replacement .add (new InsnNode (AALOAD ));
394+ addUnbox (replacement , argType );
395+
396+ insn .insert (node , replacement );
397+ insn .remove (node );
398+ }
399+ }
400+ }
401+ }
402+
344403 private static final class DispatchEntry {
345404 private final int key ;
346405 private final String implName ;
347406 private final String desc ;
348407 private final Type returnType ;
349408 private final Type [] argTypes ;
350409 private final boolean isStatic ;
410+ private final boolean inline ;
411+ private final InsnList insnList ;
351412
352413 private DispatchEntry (int key , String implName , String desc , Type returnType , Type [] argTypes ,
353- boolean isStatic ) {
414+ boolean isStatic , boolean inline , InsnList insnList ) {
354415 this .key = key ;
355416 this .implName = implName ;
356417 this .desc = desc ;
357418 this .returnType = returnType ;
358419 this .argTypes = argTypes ;
359420 this .isStatic = isStatic ;
421+ this .inline = inline ;
422+ this .insnList = insnList ;
360423 }
361424 }
362425}
0 commit comments