List of usage examples for org.objectweb.asm.commons GeneratorAdapter GeneratorAdapter
public GeneratorAdapter(final MethodVisitor methodVisitor, final int access, final String name, final String descriptor)
From source file:ch.raffael.contracts.processor.cel.skeletons.SkeletonMethodVisitor.java
License:Apache License
public SkeletonMethodVisitor(MethodVisitor methodVisitor, int access, String name, String desc, String className) {/*from w w w .j a va2s . c om*/ super(ASM5, new GeneratorAdapter(methodVisitor, access, name, desc)); gen = (GeneratorAdapter) mv; }
From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java
License:Apache License
/** * Defines the org.apache.spark.deploy.yarn.Client class with rewriting of the createConfArchive method to * workaround the SPARK-13441 bug./*w w w .j ava2 s .com*/ */ private Class<?> defineClient(String name, InputStream createConfArchive) throws IOException, ClassNotFoundException { // We only need to rewrite if listing either HADOOP_CONF_DIR or YARN_CONF_DIR return null. boolean needRewrite = false; for (String env : ImmutableList.of("HADOOP_CONF_DIR", "YARN_CONF_DIR")) { String value = System.getenv(env); if (value != null) { File path = new File(value); if (path.isDirectory() && path.listFiles() == null) { needRewrite = true; break; } } } // If rewrite is not needed if (!needRewrite) { return findClass(name); } ClassReader cr = new ClassReader(createConfArchive); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cr.accept(new ClassVisitor(Opcodes.ASM5, cw) { @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); // Only rewrite the createConfArchive method if (!"createConfArchive".equals(name)) { return mv; } // Check if it's a recognizable return type. // Spark 1.5+ return type is File boolean isReturnFile = Type.getReturnType(desc).equals(Type.getType(File.class)); Type optionType = Type.getObjectType("scala/Option"); if (!isReturnFile) { // Spark 1.4 return type is Option<File> if (!Type.getReturnType(desc).equals(optionType)) { // Unknown type. Not going to modify the code. return mv; } } // Generate this for Spark 1.5+ // return SparkRuntimeUtils.createConfArchive(this.sparkConf, SPARK_CONF_FILE, // LOCALIZED_CONF_DIR, LOCALIZED_CONF_DIR_ZIP); // Generate this for Spark 1.4 // return Option.apply(SparkRuntimeUtils.createConfArchive(this.sparkConf, SPARK_CONF_FILE, // LOCALIZED_CONF_DIR, LOCALIZED_CONF_DIR_ZIP)); GeneratorAdapter mg = new GeneratorAdapter(mv, access, name, desc); // load this.sparkConf to the stack mg.loadThis(); mg.getField(Type.getObjectType("org/apache/spark/deploy/yarn/Client"), "sparkConf", SPARK_CONF_TYPE); // push three constants to the stack mg.visitLdcInsn(SPARK_CONF_FILE); mg.visitLdcInsn(LOCALIZED_CONF_DIR); mg.visitLdcInsn(LOCALIZED_CONF_DIR_ZIP); // call SparkRuntimeUtils.createConfArchive, return a File and leave it in stack Type stringType = Type.getType(String.class); mg.invokeStatic(SPARK_RUNTIME_UTILS_TYPE, new Method("createConfArchive", Type.getType(File.class), new Type[] { SPARK_CONF_TYPE, stringType, stringType, stringType })); if (isReturnFile) { // Spark 1.5+ return type is File, hence just return the File from the stack mg.returnValue(); mg.endMethod(); } else { // Spark 1.4 return type is Option<File> // return Option.apply(<file from stack>); // where the file is actually just popped from the stack mg.invokeStatic(optionType, new Method("apply", optionType, new Type[] { Type.getType(Object.class) })); mg.checkCast(optionType); mg.returnValue(); mg.endMethod(); } return null; } }, ClassReader.EXPAND_FRAMES); byte[] byteCode = cw.toByteArray(); return defineClass(name, byteCode, 0, byteCode.length); }
From source file:co.cask.cdap.explore.service.ExploreServiceUtils.java
License:Apache License
@VisibleForTesting static File rewriteHiveAuthFactory(File sourceJar, File targetJar) throws IOException { try (JarFile input = new JarFile(sourceJar); JarOutputStream output = new JarOutputStream(new FileOutputStream(targetJar))) { String hiveAuthFactoryPath = HIVE_AUTHFACTORY_CLASS_NAME.replace('.', '/') + ".class"; Enumeration<JarEntry> sourceEntries = input.entries(); while (sourceEntries.hasMoreElements()) { JarEntry entry = sourceEntries.nextElement(); output.putNextEntry(new JarEntry(entry.getName())); try (InputStream entryInputStream = input.getInputStream(entry)) { if (!hiveAuthFactoryPath.equals(entry.getName())) { ByteStreams.copy(entryInputStream, output); continue; }//from w ww. ja va 2 s .co m try { // Rewrite the bytecode of HiveAuthFactory.loginFromKeytab method to a no-op method ClassReader cr = new ClassReader(entryInputStream); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cr.accept(new ClassVisitor(Opcodes.ASM5, cw) { @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, String signature, String[] exceptions) { MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); if (!"loginFromKeytab".equals(name)) { return methodVisitor; } GeneratorAdapter adapter = new GeneratorAdapter(methodVisitor, access, name, desc); adapter.returnValue(); // VisitMaxs with 0 so that COMPUTE_MAXS from ClassWriter will compute the right values. adapter.visitMaxs(0, 0); return new MethodVisitor(Opcodes.ASM5) { }; } }, 0); output.write(cw.toByteArray()); } catch (Exception e) { throw new IOException("Unable to generate HiveAuthFactory class", e); } } } return targetJar; } }
From source file:com.alibaba.hotswap.processor.constructor.ConstructorVisitor.java
License:Open Source License
private void addEmptyUniformConstructor() { int access = Opcodes.ACC_PUBLIC + Opcodes.ACC_SYNTHETIC; String name = HotswapConstants.INIT; String desc = HotswapConstants.UNIFORM_CONSTRUCTOR_DESC; MethodVisitor hotswapInit = cv.visitMethod(access, name, desc, null, null); GeneratorAdapter hotswapInitAdapter = new GeneratorAdapter(hotswapInit, access, name, desc); hotswapInitAdapter.visitCode();/*from w w w . j ava2 s. com*/ hotswapInitAdapter.push(this.className); hotswapInitAdapter.loadArg(1); hotswapInitAdapter.invokeStatic(Type.getType(HotswapMethodUtil.class), Method.getMethod("Throwable noSuchMethodError(String, int)")); hotswapInitAdapter.throwException(); hotswapInitAdapter.endMethod(); }
From source file:com.alibaba.hotswap.processor.constructor.ConstructorVisitor.java
License:Open Source License
@SuppressWarnings({ "unchecked" })
private void addUniformConstructor(ClassMeta classMeta) {
int access = Opcodes.ACC_PUBLIC + Opcodes.ACC_SYNTHETIC;
String name = HotswapConstants.INIT;
String desc = HotswapConstants.UNIFORM_CONSTRUCTOR_DESC;
MethodVisitor hotswapInit = new ConstructorInvokeModifier(cv.visitMethod(access, name, desc, null, null),
access, name, desc);/*from w w w.ja v a2 s . co m*/
GeneratorAdapter hotswapInitAdapter = new GeneratorAdapter(hotswapInit, access, name, desc);
hotswapInitAdapter.visitCode();
TreeMap<MethodMeta, MethodNode> initMethodMap = new TreeMap<MethodMeta, MethodNode>(
new ConstructorIndexComparator());
for (MethodNode node : initNodes.values()) {
MethodMeta meta = new MethodMeta(node.access, node.name, node.desc, node.signature,
((String[]) node.exceptions.toArray(new String[node.exceptions.size()])));
meta.setIndex(HotswapMethodIndexHolder.getMethodIndex(className, node.name, node.desc));
classMeta.refreshInitMeta(meta, true);
initMethodMap.put(meta, node);
}
List<MethodMeta> keys = new ArrayList<MethodMeta>(initMethodMap.keySet());
List<MethodNode> values = new ArrayList<MethodNode>(initMethodMap.values());
Label defaultLabel = new Label();
int[] indexes = new int[keys.size()];
Label[] labels = new Label[keys.size()];
for (int i = 0; i < keys.size(); i++) {
indexes[i] = keys.get(i).getIndex();
labels[i] = new Label();
}
for (int i = 0; i < values.size(); i++) {
MethodNode node = values.get(i);
for (int j = 0; j < node.tryCatchBlocks.size(); j++) {
((TryCatchBlockNode) node.tryCatchBlocks.get(j)).accept(hotswapInitAdapter);
}
}
hotswapInitAdapter.loadArg(1);
hotswapInitAdapter.visitLookupSwitchInsn(defaultLabel, indexes, labels);
for (int i = 0; i < keys.size(); i++) {
MethodMeta methodMeta = keys.get(i);
hotswapInitAdapter.visitLabel(labels[i]);
MethodNode node = values.get(i);
storeArgs(hotswapInitAdapter, hotswapInit, methodMeta);
MethodVisitor methodVisitor = new ConstructorLVTAdjustModifier(hotswapInit, 3);
node.instructions.accept(methodVisitor);
for (int j = 0; j < (node.localVariables == null ? 0 : node.localVariables.size()); j++) {
((LocalVariableNode) node.localVariables.get(j)).accept(methodVisitor);
}
}
hotswapInitAdapter.mark(defaultLabel);
hotswapInitAdapter.push(this.className);
hotswapInitAdapter.loadArg(1);
hotswapInitAdapter.invokeStatic(Type.getType(HotswapMethodUtil.class),
Method.getMethod("Throwable noSuchMethodError(String, int)"));
hotswapInitAdapter.throwException();
hotswapInitAdapter.endMethod();
}
From source file:com.alibaba.hotswap.processor.front.compile.CompilerErrorVisitor.java
License:Open Source License
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); return new GeneratorAdapter(mv, access, name, desc) { private int status = 0; @Override/*from w ww .j ava2s . c om*/ public void visitCode() { super.visitCode(); status = 1; } @Override public void visitTypeInsn(int opcode, String type) { if (status == 1 && opcode == Opcodes.NEW) { status = 2; } else { status = 0; } super.visitTypeInsn(opcode, type); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (status == 4 && opcode == Opcodes.INVOKESPECIAL) { status = 5; } else { status = 0; } super.visitMethodInsn(opcode, owner, name, desc); } @Override public void visitLdcInsn(Object cst) { if (status == 3) { status = 4; } else { status = 0; } super.visitLdcInsn(cst); } @Override public void visitInsn(int opcode) { if (status == 2 && opcode == Opcodes.DUP) { status = 3; } else if (status == 5 && opcode == Opcodes.ATHROW) { status = 6; } else { status = 0; } super.visitInsn(opcode); } @Override public void visitEnd() { if (status == 6) { throw new HotswapException( "Class file is compiled from Java source file which has compile error"); } super.visitEnd(); } }; }
From source file:com.android.build.gradle.internal.incremental.ConstructorBuilder.java
License:Apache License
/** * Splits the constructor in two methods, the "set up" and the "body" parts (see above). *//*from w w w. ja v a 2s. c o m*/ @NonNull private static Constructor split(@NonNull String owner, @NonNull MethodNode method, @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine, @NonNull List<LocalVariable> variables, int localsAtLoadThis) { String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]); // Do not add the local array yet, as we treat it as a new variable. String newDesc = method.desc.replace(")V", ")Ljava/lang/Object;"); newDesc = newDesc.replace("(", "([L" + owner + ";"); Type[] argumentTypes = Type.getArgumentTypes(newDesc); // Store the non hotswappable part of the constructor List<AbstractInsnNode> fixed = Lists.newLinkedList(); AbstractInsnNode insn = method.instructions.getFirst(); while (insn != loadThis) { fixed.add(insn); insn = insn.getNext(); } fixed.add(loadThis); MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null, exceptions); GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc); int newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;")); mv.loadLocal(newArgument); ByteCodeUtils.restoreVariables(mv, variables.subList(0, localsAtLoadThis)); // Now insert the original method insn = loadThis.getNext(); while (insn != delegation) { insn.accept(mv); insn = insn.getNext(); } LabelNode labelBefore = new LabelNode(); labelBefore.accept(mv); // Create the args array with the local variables and the values to send to the delegated constructor Type[] returnTypes = Type.getArgumentTypes(delegation.desc); // The extra elements for the local variables and the qualified name of the constructor. mv.push(returnTypes.length + 2); mv.newArray(Type.getType(Object.class)); int args = mv.newLocal(Type.getType("[Ljava/lang/Object;")); mv.storeLocal(args); for (int i = returnTypes.length - 1; i >= 0; i--) { Type type = returnTypes[i]; mv.loadLocal(args); mv.swap(type, Type.getType(Object.class)); mv.push(i + 2); mv.swap(type, Type.INT_TYPE); mv.box(type); mv.arrayStore(Type.getType(Object.class)); } // Store the qualified name of the constructor in the second element of the array. mv.loadLocal(args); mv.push(1); mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called. mv.arrayStore(Type.getType(Object.class)); // Create the locals array and place it in the first element of the return array mv.loadLocal(args); mv.push(0); mv.push(argumentTypes.length + 1); mv.newArray(Type.getType(Object.class)); ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(Arrays.asList(argumentTypes)), 0); mv.dup(); mv.push(argumentTypes.length); ByteCodeUtils.newVariableArray(mv, variables); mv.arrayStore(Type.getType(Object.class)); mv.arrayStore(Type.getType(Object.class)); mv.loadLocal(args); mv.returnValue(); // Move the first variable up to be an argument initArgs.desc = initArgs.desc.replace(")", "[Ljava/lang/Object;)"); newDesc = method.desc.replace("(", "(L" + owner + ";"); MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null, exceptions); mv = new GeneratorAdapter(body, body.access, body.name, body.desc); newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;")); LabelNode labelAfter = new LabelNode(); labelAfter.accept(body); Set<LabelNode> bodyLabels = new HashSet<LabelNode>(); mv.loadLocal(newArgument); ByteCodeUtils.restoreVariables(mv, variables); insn = delegation.getNext(); while (insn != null) { if (insn instanceof LabelNode) { bodyLabels.add((LabelNode) insn); } insn.accept(mv); insn = insn.getNext(); } // manually transfer the exception table from the existing constructor to the new // "init$body" method. The labels were transferred just above so we can reuse them. //noinspection unchecked for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) { tryCatch.accept(mv); } //noinspection unchecked for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) { boolean startsInBody = bodyLabels.contains(variable.start); boolean endsInBody = bodyLabels.contains(variable.end); if (!startsInBody && !endsInBody) { if (variable.index != 0) { // '#0' on init$args is not 'this' variable.accept(initArgs); } } else if (startsInBody && endsInBody) { variable.accept(body); } else if (!startsInBody && endsInBody) { // The variable spans from the args to the end of the method, create two: if (variable.index != 0) { // '#0' on init$args is not 'this' LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature, variable.start, labelBefore, variable.index); var0.accept(initArgs); } LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature, labelAfter, variable.end, variable.index); var1.accept(body); } else { throw new IllegalStateException("Local variable starts after it ends."); } } // Move the first variable up to be an argument body.desc = body.desc.replace(")", "[Ljava/lang/Object;)"); return new Constructor(owner, fixed, loadThis, loadThisLine, initArgs, delegation, body, variables, localsAtLoadThis); }
From source file:com.android.build.gradle.internal.incremental.ConstructorDelegationDetector.java
License:Apache License
/** * Splits the constructor in two methods, the "set up" and the "body" parts (see above). *///from w ww .ja va2s. c o m @NonNull private static Constructor split(@NonNull String owner, @NonNull MethodNode method, @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine) { String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]); String newDesc = method.desc.replaceAll("\\((.*)\\)V", "([Ljava/lang/Object;$1)Ljava/lang/Object;"); MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null, exceptions); AbstractInsnNode insn = loadThis.getNext(); while (insn != delegation) { insn.accept(initArgs); insn = insn.getNext(); } LabelNode labelBefore = new LabelNode(); labelBefore.accept(initArgs); GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc); // Copy the arguments back to the argument array // The init_args part cannot access the "this" object and can have side effects on the // local variables. Because of this we use the first argument (which we want to keep // so all the other arguments remain unchanged) as a reference to the array where to // return the values of the modified local variables. Type[] types = Type.getArgumentTypes(initArgs.desc); int stack = 1; // Skip the first one which is a reference to the local array. for (int i = 1; i < types.length; i++) { Type type = types[i]; // This is not this, but the array of local arguments final values. mv.visitVarInsn(Opcodes.ALOAD, 0); mv.push(i); mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), stack); mv.box(type); mv.arrayStore(Type.getType(Object.class)); stack += type.getSize(); } // Create the args array with the values to send to the delegated constructor Type[] returnTypes = Type.getArgumentTypes(delegation.desc); // The extra element for the qualified name of the constructor. mv.push(returnTypes.length + 1); mv.newArray(Type.getType(Object.class)); int args = mv.newLocal(Type.getType("[Ljava/lang/Object;")); mv.storeLocal(args); for (int i = returnTypes.length - 1; i >= 0; i--) { Type type = returnTypes[i]; mv.loadLocal(args); mv.swap(type, Type.getType(Object.class)); mv.push(i + 1); mv.swap(type, Type.INT_TYPE); mv.box(type); mv.arrayStore(Type.getType(Object.class)); } // Store the qualified name of the constructor in the first element of the array. mv.loadLocal(args); mv.push(0); mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called. mv.arrayStore(Type.getType(Object.class)); mv.loadLocal(args); mv.returnValue(); newDesc = method.desc.replace("(", "(L" + owner + ";"); MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null, exceptions); LabelNode labelAfter = new LabelNode(); labelAfter.accept(body); Set<LabelNode> bodyLabels = new HashSet<LabelNode>(); insn = delegation.getNext(); while (insn != null) { if (insn instanceof LabelNode) { bodyLabels.add((LabelNode) insn); } insn.accept(body); insn = insn.getNext(); } // manually transfer the exception table from the existing constructor to the new // "init$body" method. The labels were transferred just above so we can reuse them. //noinspection unchecked for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) { tryCatch.accept(body); } //noinspection unchecked for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) { boolean startsInBody = bodyLabels.contains(variable.start); boolean endsInBody = bodyLabels.contains(variable.end); if (!startsInBody && !endsInBody) { if (variable.index != 0) { // '#0' on init$args is not 'this' variable.accept(initArgs); } } else if (startsInBody && endsInBody) { variable.accept(body); } else if (!startsInBody && endsInBody) { // The variable spans from the args to the end of the method, create two: if (variable.index != 0) { // '#0' on init$args is not 'this' LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature, variable.start, labelBefore, variable.index); var0.accept(initArgs); } LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature, labelAfter, variable.end, variable.index); var1.accept(body); } else { throw new IllegalStateException("Local variable starts after it ends."); } } return new Constructor(loadThis, loadThisLine, initArgs, delegation, body); }
From source file:com.android.build.gradle.internal2.incremental.ConstructorBuilder.java
License:Apache License
/** * Splits the constructor in two methods, the "set up" and the "body" parts (see above). *///w w w .j a v a2 s . c om @NonNull private static Constructor split(@NonNull String owner, @NonNull MethodNode method, @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine, @NonNull List<LocalVariable> variables, int localsAtLoadThis) { String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]); // Do not add the local array yet, as we treat it as a new variable. String newDesc = method.desc.replace(")V", ")Ljava/lang/Object;"); newDesc = newDesc.replace("(", "([L" + owner + ";"); Type[] argumentTypes = Type.getArgumentTypes(newDesc); // Store the non hotswappable part of the constructor List<AbstractInsnNode> fixed = Lists.newLinkedList(); AbstractInsnNode insn = method.instructions.getFirst(); while (insn != loadThis) { fixed.add(insn); insn = insn.getNext(); } fixed.add(loadThis); MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null, exceptions); GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc); int newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;")); mv.loadLocal(newArgument); ByteCodeUtils.restoreVariables(mv, variables.subList(0, localsAtLoadThis)); // Now insert the original method insn = loadThis.getNext(); while (insn != delegation) { insn.accept(mv); insn = insn.getNext(); } LabelNode labelBefore = new LabelNode(); labelBefore.accept(mv); // Create the args array with the local variables and the values to send to the delegated constructor Type[] returnTypes = Type.getArgumentTypes(delegation.desc); // The extra elements for the local variables and the qualified name of the constructor. mv.push(returnTypes.length + 2); mv.newArray(Type.getType(Object.class)); int args = mv.newLocal(Type.getType("[Ljava/lang/Object;")); mv.storeLocal(args); for (int i = returnTypes.length - 1; i >= 0; i--) { Type type = returnTypes[i]; mv.loadLocal(args); mv.swap(type, Type.getType(Object.class)); mv.push(i + 2); mv.swap(type, Type.INT_TYPE); mv.box(type); mv.arrayStore(Type.getType(Object.class)); } // Store the qualified name of the constructor in the second element of the array. mv.loadLocal(args); mv.push(1); mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called. mv.arrayStore(Type.getType(Object.class)); // Create the locals array and place it in the first element of the return array mv.loadLocal(args); mv.push(0); mv.push(argumentTypes.length + 1); mv.newArray(Type.getType(Object.class)); ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(Arrays.asList(argumentTypes)), 0); mv.dup(); mv.push(argumentTypes.length); ByteCodeUtils.newVariableArray(mv, variables); mv.arrayStore(Type.getType(Object.class)); mv.arrayStore(Type.getType(Object.class)); mv.loadLocal(args); mv.returnValue(); // Move the first variable up to be an argument initArgs.desc = initArgs.desc.replace(")", "[Ljava/lang/Object;)"); newDesc = method.desc.replace("(", "(L" + owner + ";"); MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null, exceptions); mv = new GeneratorAdapter(body, body.access, body.name, body.desc); newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;")); LabelNode labelAfter = new LabelNode(); labelAfter.accept(body); Set<LabelNode> bodyLabels = new HashSet<LabelNode>(); mv.loadLocal(newArgument); ByteCodeUtils.restoreVariables(mv, variables); insn = delegation.getNext(); while (insn != null) { if (insn instanceof LabelNode) { bodyLabels.add((LabelNode) insn); } insn.accept(mv); insn = insn.getNext(); } // manually transfer the exception table from the existing constructor to the new // "init$body" method. The labels were transferred just above so we can reuse them. //noinspection unchecked for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) { tryCatch.accept(mv); } //noinspection unchecked for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) { boolean startsInBody = bodyLabels.contains(variable.start); boolean endsInBody = bodyLabels.contains(variable.end); if (!startsInBody && !endsInBody) { if (variable.index != 0) { // '#0' on init$args is not 'this' variable.accept(initArgs); } } else if (startsInBody && endsInBody) { variable.accept(body); } else if (!startsInBody && endsInBody) { // The variable spans from the args to the end of the method, create two: if (variable.index != 0) { // '#0' on init$args is not 'this' LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature, variable.start, labelBefore, variable.index); var0.accept(initArgs); } LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature, labelAfter, variable.end, variable.index); var1.accept(body); } else { throw new IllegalStateException("Local variable starts after it ends."); } } // Move the first variable up to be an argument body.desc = body.desc.replace(")", "[Ljava/lang/Object;)"); return new Constructor(owner, method, fixed, loadThis, loadThisLine, initArgs, delegation, body, variables, localsAtLoadThis); }
From source file:com.google.template.soy.jbcsrc.CodeBuilder.java
License:Apache License
CodeBuilder(MethodVisitor mv, int access, String name, String desc) { super(Opcodes.ASM5, mv); this.adapter = new GeneratorAdapter(mv, access, name, desc); }