http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/AnalyzerAdapter.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/AnalyzerAdapter.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/AnalyzerAdapter.java new file mode 100644 index 0000000..ef8ef4d --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/AnalyzerAdapter.java @@ -0,0 +1,920 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.apache.tajo.org.objectweb.asm.commons; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tajo.org.objectweb.asm.Label; +import org.apache.tajo.org.objectweb.asm.Type; +import org.apache.tajo.org.objectweb.asm.Handle; +import org.apache.tajo.org.objectweb.asm.MethodVisitor; +import org.apache.tajo.org.objectweb.asm.Opcodes; + +/** + * A {@link MethodVisitor} that keeps track of stack map frame changes between + * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This + * adapter must be used with the + * {@link org.apache.tajo.org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each + * visit<i>X</i> instruction delegates to the next visitor in the chain, if any, + * and then simulates the effect of this instruction on the stack map frame, + * represented by {@link #locals} and {@link #stack}. The next visitor in the + * chain can get the state of the stack map frame <i>before</i> each instruction + * by reading the value of these fields in its visit<i>X</i> methods (this + * requires a reference to the AnalyzerAdapter that is before it in the chain). + * If this adapter is used with a class that does not contain stack map table + * attributes (i.e., pre Java 6 classes) then this adapter may not be able to + * compute the stack map frame for each instruction. In this case no exception + * is thrown but the {@link #locals} and {@link #stack} fields will be null for + * these instructions. + * + * @author Eric Bruneton + */ +public class AnalyzerAdapter extends MethodVisitor { + + /** + * <code>List</code> of the local variable slots for current execution + * frame. Primitive types are represented by {@link Opcodes#TOP}, + * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by + * two elements, the second one being TOP). Reference types are represented + * by String objects (representing internal names), and uninitialized types + * by Label objects (this label designates the NEW instruction that created + * this uninitialized value). This field is <tt>null</tt> for unreachable + * instructions. + */ + public List<Object> locals; + + /** + * <code>List</code> of the operand stack slots for current execution frame. + * Primitive types are represented by {@link Opcodes#TOP}, + * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by + * two elements, the second one being TOP). Reference types are represented + * by String objects (representing internal names), and uninitialized types + * by Label objects (this label designates the NEW instruction that created + * this uninitialized value). This field is <tt>null</tt> for unreachable + * instructions. + */ + public List<Object> stack; + + /** + * The labels that designate the next instruction to be visited. May be + * <tt>null</tt>. + */ + private List<Label> labels; + + /** + * Information about uninitialized types in the current execution frame. + * This map associates internal names to Label objects. Each label + * designates a NEW instruction that created the currently uninitialized + * types, and the associated internal name represents the NEW operand, i.e. + * the final, initialized type value. + */ + public Map<Object, Object> uninitializedTypes; + + /** + * The maximum stack size of this method. + */ + private int maxStack; + + /** + * The maximum number of local variables of this method. + */ + private int maxLocals; + + /** + * The owner's class name. + */ + private String owner; + + /** + * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this + * constructor</i>. Instead, they must use the + * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)} + * version. + * + * @param owner + * the owner's class name. + * @param access + * the method's access flags (see {@link Opcodes}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link org.apache.tajo.org.objectweb.asm.Type Type}). + * @param mv + * the method visitor to which this adapter delegates calls. May + * be <tt>null</tt>. + */ + public AnalyzerAdapter(final String owner, final int access, + final String name, final String desc, final MethodVisitor mv) { + this(Opcodes.ASM4, owner, access, name, desc, mv); + } + + /** + * Creates a new {@link AnalyzerAdapter}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4}. + * @param owner + * the owner's class name. + * @param access + * the method's access flags (see {@link Opcodes}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link org.apache.tajo.org.objectweb.asm.Type Type}). + * @param mv + * the method visitor to which this adapter delegates calls. May + * be <tt>null</tt>. + */ + protected AnalyzerAdapter(final int api, final String owner, + final int access, final String name, final String desc, + final MethodVisitor mv) { + super(api, mv); + this.owner = owner; + locals = new ArrayList<Object>(); + stack = new ArrayList<Object>(); + uninitializedTypes = new HashMap<Object, Object>(); + + if ((access & Opcodes.ACC_STATIC) == 0) { + if ("<init>".equals(name)) { + locals.add(Opcodes.UNINITIALIZED_THIS); + } else { + locals.add(owner); + } + } + Type[] types = Type.getArgumentTypes(desc); + for (int i = 0; i < types.length; ++i) { + Type type = types[i]; + switch (type.getSort()) { + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + locals.add(Opcodes.INTEGER); + break; + case Type.FLOAT: + locals.add(Opcodes.FLOAT); + break; + case Type.LONG: + locals.add(Opcodes.LONG); + locals.add(Opcodes.TOP); + break; + case Type.DOUBLE: + locals.add(Opcodes.DOUBLE); + locals.add(Opcodes.TOP); + break; + case Type.ARRAY: + locals.add(types[i].getDescriptor()); + break; + // case Type.OBJECT: + default: + locals.add(types[i].getInternalName()); + } + } + } + + @Override + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { + if (type != Opcodes.F_NEW) { // uncompressed frame + throw new IllegalStateException( + "ClassReader.accept() should be called with EXPAND_FRAMES flag"); + } + + if (mv != null) { + mv.visitFrame(type, nLocal, local, nStack, stack); + } + + if (this.locals != null) { + this.locals.clear(); + this.stack.clear(); + } else { + this.locals = new ArrayList<Object>(); + this.stack = new ArrayList<Object>(); + } + visitFrameTypes(nLocal, local, this.locals); + visitFrameTypes(nStack, stack, this.stack); + maxStack = Math.max(maxStack, this.stack.size()); + } + + private static void visitFrameTypes(final int n, final Object[] types, + final List<Object> result) { + for (int i = 0; i < n; ++i) { + Object type = types[i]; + result.add(type); + if (type == Opcodes.LONG || type == Opcodes.DOUBLE) { + result.add(Opcodes.TOP); + } + } + } + + @Override + public void visitInsn(final int opcode) { + if (mv != null) { + mv.visitInsn(opcode); + } + execute(opcode, 0, null); + if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) + || opcode == Opcodes.ATHROW) { + this.locals = null; + this.stack = null; + } + } + + @Override + public void visitIntInsn(final int opcode, final int operand) { + if (mv != null) { + mv.visitIntInsn(opcode, operand); + } + execute(opcode, operand, null); + } + + @Override + public void visitVarInsn(final int opcode, final int var) { + if (mv != null) { + mv.visitVarInsn(opcode, var); + } + execute(opcode, var, null); + } + + @Override + public void visitTypeInsn(final int opcode, final String type) { + if (opcode == Opcodes.NEW) { + if (labels == null) { + Label l = new Label(); + labels = new ArrayList<Label>(3); + labels.add(l); + if (mv != null) { + mv.visitLabel(l); + } + } + for (int i = 0; i < labels.size(); ++i) { + uninitializedTypes.put(labels.get(i), type); + } + } + if (mv != null) { + mv.visitTypeInsn(opcode, type); + } + execute(opcode, 0, type); + } + + @Override + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { + if (mv != null) { + mv.visitFieldInsn(opcode, owner, name, desc); + } + execute(opcode, 0, desc); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { + if (mv != null) { + mv.visitMethodInsn(opcode, owner, name, desc); + } + if (this.locals == null) { + labels = null; + return; + } + pop(desc); + if (opcode != Opcodes.INVOKESTATIC) { + Object t = pop(); + if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') { + Object u; + if (t == Opcodes.UNINITIALIZED_THIS) { + u = this.owner; + } else { + u = uninitializedTypes.get(t); + } + for (int i = 0; i < locals.size(); ++i) { + if (locals.get(i) == t) { + locals.set(i, u); + } + } + for (int i = 0; i < stack.size(); ++i) { + if (stack.get(i) == t) { + stack.set(i, u); + } + } + } + } + pushDesc(desc); + labels = null; + } + + @Override + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { + if (mv != null) { + mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + } + if (this.locals == null) { + labels = null; + return; + } + pop(desc); + pushDesc(desc); + labels = null; + } + + @Override + public void visitJumpInsn(final int opcode, final Label label) { + if (mv != null) { + mv.visitJumpInsn(opcode, label); + } + execute(opcode, 0, null); + if (opcode == Opcodes.GOTO) { + this.locals = null; + this.stack = null; + } + } + + @Override + public void visitLabel(final Label label) { + if (mv != null) { + mv.visitLabel(label); + } + if (labels == null) { + labels = new ArrayList<Label>(3); + } + labels.add(label); + } + + @Override + public void visitLdcInsn(final Object cst) { + if (mv != null) { + mv.visitLdcInsn(cst); + } + if (this.locals == null) { + labels = null; + return; + } + if (cst instanceof Integer) { + push(Opcodes.INTEGER); + } else if (cst instanceof Long) { + push(Opcodes.LONG); + push(Opcodes.TOP); + } else if (cst instanceof Float) { + push(Opcodes.FLOAT); + } else if (cst instanceof Double) { + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + } else if (cst instanceof String) { + push("java/lang/String"); + } else if (cst instanceof Type) { + int sort = ((Type) cst).getSort(); + if (sort == Type.OBJECT || sort == Type.ARRAY) { + push("java/lang/Class"); + } else if (sort == Type.METHOD) { + push("java/lang/invoke/MethodType"); + } else { + throw new IllegalArgumentException(); + } + } else if (cst instanceof Handle) { + push("java/lang/invoke/MethodHandle"); + } else { + throw new IllegalArgumentException(); + } + labels = null; + } + + @Override + public void visitIincInsn(final int var, final int increment) { + if (mv != null) { + mv.visitIincInsn(var, increment); + } + execute(Opcodes.IINC, var, null); + } + + @Override + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { + if (mv != null) { + mv.visitTableSwitchInsn(min, max, dflt, labels); + } + execute(Opcodes.TABLESWITCH, 0, null); + this.locals = null; + this.stack = null; + } + + @Override + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { + if (mv != null) { + mv.visitLookupSwitchInsn(dflt, keys, labels); + } + execute(Opcodes.LOOKUPSWITCH, 0, null); + this.locals = null; + this.stack = null; + } + + @Override + public void visitMultiANewArrayInsn(final String desc, final int dims) { + if (mv != null) { + mv.visitMultiANewArrayInsn(desc, dims); + } + execute(Opcodes.MULTIANEWARRAY, dims, desc); + } + + @Override + public void visitMaxs(final int maxStack, final int maxLocals) { + if (mv != null) { + this.maxStack = Math.max(this.maxStack, maxStack); + this.maxLocals = Math.max(this.maxLocals, maxLocals); + mv.visitMaxs(this.maxStack, this.maxLocals); + } + } + + // ------------------------------------------------------------------------ + + private Object get(final int local) { + maxLocals = Math.max(maxLocals, local); + return local < locals.size() ? locals.get(local) : Opcodes.TOP; + } + + private void set(final int local, final Object type) { + maxLocals = Math.max(maxLocals, local); + while (local >= locals.size()) { + locals.add(Opcodes.TOP); + } + locals.set(local, type); + } + + private void push(final Object type) { + stack.add(type); + maxStack = Math.max(maxStack, stack.size()); + } + + private void pushDesc(final String desc) { + int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; + switch (desc.charAt(index)) { + case 'V': + return; + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + push(Opcodes.INTEGER); + return; + case 'F': + push(Opcodes.FLOAT); + return; + case 'J': + push(Opcodes.LONG); + push(Opcodes.TOP); + return; + case 'D': + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + return; + case '[': + if (index == 0) { + push(desc); + } else { + push(desc.substring(index, desc.length())); + } + break; + // case 'L': + default: + if (index == 0) { + push(desc.substring(1, desc.length() - 1)); + } else { + push(desc.substring(index + 1, desc.length() - 1)); + } + } + } + + private Object pop() { + return stack.remove(stack.size() - 1); + } + + private void pop(final int n) { + int size = stack.size(); + int end = size - n; + for (int i = size - 1; i >= end; --i) { + stack.remove(i); + } + } + + private void pop(final String desc) { + char c = desc.charAt(0); + if (c == '(') { + int n = 0; + Type[] types = Type.getArgumentTypes(desc); + for (int i = 0; i < types.length; ++i) { + n += types[i].getSize(); + } + pop(n); + } else if (c == 'J' || c == 'D') { + pop(2); + } else { + pop(1); + } + } + + private void execute(final int opcode, final int iarg, final String sarg) { + if (this.locals == null) { + labels = null; + return; + } + Object t1, t2, t3, t4; + switch (opcode) { + case Opcodes.NOP: + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + case Opcodes.GOTO: + case Opcodes.RETURN: + break; + case Opcodes.ACONST_NULL: + push(Opcodes.NULL); + break; + case Opcodes.ICONST_M1: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + push(Opcodes.INTEGER); + break; + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + push(Opcodes.FLOAT); + break; + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.ILOAD: + case Opcodes.FLOAD: + case Opcodes.ALOAD: + push(get(iarg)); + break; + case Opcodes.LLOAD: + case Opcodes.DLOAD: + push(get(iarg)); + push(Opcodes.TOP); + break; + case Opcodes.IALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + pop(2); + push(Opcodes.INTEGER); + break; + case Opcodes.LALOAD: + case Opcodes.D2L: + pop(2); + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.FALOAD: + pop(2); + push(Opcodes.FLOAT); + break; + case Opcodes.DALOAD: + case Opcodes.L2D: + pop(2); + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.AALOAD: + pop(1); + t1 = pop(); + if (t1 instanceof String) { + pushDesc(((String) t1).substring(1)); + } else { + push("java/lang/Object"); + } + break; + case Opcodes.ISTORE: + case Opcodes.FSTORE: + case Opcodes.ASTORE: + t1 = pop(); + set(iarg, t1); + if (iarg > 0) { + t2 = get(iarg - 1); + if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { + set(iarg - 1, Opcodes.TOP); + } + } + break; + case Opcodes.LSTORE: + case Opcodes.DSTORE: + pop(1); + t1 = pop(); + set(iarg, t1); + set(iarg + 1, Opcodes.TOP); + if (iarg > 0) { + t2 = get(iarg - 1); + if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { + set(iarg - 1, Opcodes.TOP); + } + } + break; + case Opcodes.IASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + case Opcodes.FASTORE: + case Opcodes.AASTORE: + pop(3); + break; + case Opcodes.LASTORE: + case Opcodes.DASTORE: + pop(4); + break; + case Opcodes.POP: + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + case Opcodes.IRETURN: + case Opcodes.FRETURN: + case Opcodes.ARETURN: + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + case Opcodes.ATHROW: + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + pop(1); + break; + case Opcodes.POP2: + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPNE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ACMPEQ: + case Opcodes.IF_ACMPNE: + case Opcodes.LRETURN: + case Opcodes.DRETURN: + pop(2); + break; + case Opcodes.DUP: + t1 = pop(); + push(t1); + push(t1); + break; + case Opcodes.DUP_X1: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2: + t1 = pop(); + t2 = pop(); + push(t2); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X1: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t2); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + t4 = pop(); + push(t2); + push(t1); + push(t4); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.SWAP: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + break; + case Opcodes.IADD: + case Opcodes.ISUB: + case Opcodes.IMUL: + case Opcodes.IDIV: + case Opcodes.IREM: + case Opcodes.IAND: + case Opcodes.IOR: + case Opcodes.IXOR: + case Opcodes.ISHL: + case Opcodes.ISHR: + case Opcodes.IUSHR: + case Opcodes.L2I: + case Opcodes.D2I: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + pop(2); + push(Opcodes.INTEGER); + break; + case Opcodes.LADD: + case Opcodes.LSUB: + case Opcodes.LMUL: + case Opcodes.LDIV: + case Opcodes.LREM: + case Opcodes.LAND: + case Opcodes.LOR: + case Opcodes.LXOR: + pop(4); + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.FADD: + case Opcodes.FSUB: + case Opcodes.FMUL: + case Opcodes.FDIV: + case Opcodes.FREM: + case Opcodes.L2F: + case Opcodes.D2F: + pop(2); + push(Opcodes.FLOAT); + break; + case Opcodes.DADD: + case Opcodes.DSUB: + case Opcodes.DMUL: + case Opcodes.DDIV: + case Opcodes.DREM: + pop(4); + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.LSHL: + case Opcodes.LSHR: + case Opcodes.LUSHR: + pop(3); + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.IINC: + set(iarg, Opcodes.INTEGER); + break; + case Opcodes.I2L: + case Opcodes.F2L: + pop(1); + push(Opcodes.LONG); + push(Opcodes.TOP); + break; + case Opcodes.I2F: + pop(1); + push(Opcodes.FLOAT); + break; + case Opcodes.I2D: + case Opcodes.F2D: + pop(1); + push(Opcodes.DOUBLE); + push(Opcodes.TOP); + break; + case Opcodes.F2I: + case Opcodes.ARRAYLENGTH: + case Opcodes.INSTANCEOF: + pop(1); + push(Opcodes.INTEGER); + break; + case Opcodes.LCMP: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + pop(4); + push(Opcodes.INTEGER); + break; + case Opcodes.JSR: + case Opcodes.RET: + throw new RuntimeException("JSR/RET are not supported"); + case Opcodes.GETSTATIC: + pushDesc(sarg); + break; + case Opcodes.PUTSTATIC: + pop(sarg); + break; + case Opcodes.GETFIELD: + pop(1); + pushDesc(sarg); + break; + case Opcodes.PUTFIELD: + pop(sarg); + pop(); + break; + case Opcodes.NEW: + push(labels.get(0)); + break; + case Opcodes.NEWARRAY: + pop(); + switch (iarg) { + case Opcodes.T_BOOLEAN: + pushDesc("[Z"); + break; + case Opcodes.T_CHAR: + pushDesc("[C"); + break; + case Opcodes.T_BYTE: + pushDesc("[B"); + break; + case Opcodes.T_SHORT: + pushDesc("[S"); + break; + case Opcodes.T_INT: + pushDesc("[I"); + break; + case Opcodes.T_FLOAT: + pushDesc("[F"); + break; + case Opcodes.T_DOUBLE: + pushDesc("[D"); + break; + // case Opcodes.T_LONG: + default: + pushDesc("[J"); + break; + } + break; + case Opcodes.ANEWARRAY: + pop(); + pushDesc("[" + Type.getObjectType(sarg)); + break; + case Opcodes.CHECKCAST: + pop(); + pushDesc(Type.getObjectType(sarg).getDescriptor()); + break; + // case Opcodes.MULTIANEWARRAY: + default: + pop(iarg); + pushDesc(sarg); + break; + } + labels = null; + } +}
http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/CodeSizeEvaluator.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/CodeSizeEvaluator.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/CodeSizeEvaluator.java new file mode 100644 index 0000000..5664b29 --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/commons/CodeSizeEvaluator.java @@ -0,0 +1,217 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.apache.tajo.org.objectweb.asm.commons; + +import org.apache.tajo.org.objectweb.asm.Handle; +import org.apache.tajo.org.objectweb.asm.Label; +import org.apache.tajo.org.objectweb.asm.MethodVisitor; +import org.apache.tajo.org.objectweb.asm.Opcodes; + +/** + * A {@link MethodVisitor} that can be used to approximate method size. + * + * @author Eugene Kuleshov + */ +public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { + + private int minSize; + + private int maxSize; + + public CodeSizeEvaluator(final MethodVisitor mv) { + this(Opcodes.ASM4, mv); + } + + protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { + super(api, mv); + } + + public int getMinSize() { + return this.minSize; + } + + public int getMaxSize() { + return this.maxSize; + } + + @Override + public void visitInsn(final int opcode) { + minSize += 1; + maxSize += 1; + if (mv != null) { + mv.visitInsn(opcode); + } + } + + @Override + public void visitIntInsn(final int opcode, final int operand) { + if (opcode == SIPUSH) { + minSize += 3; + maxSize += 3; + } else { + minSize += 2; + maxSize += 2; + } + if (mv != null) { + mv.visitIntInsn(opcode, operand); + } + } + + @Override + public void visitVarInsn(final int opcode, final int var) { + if (var < 4 && opcode != RET) { + minSize += 1; + maxSize += 1; + } else if (var >= 256) { + minSize += 4; + maxSize += 4; + } else { + minSize += 2; + maxSize += 2; + } + if (mv != null) { + mv.visitVarInsn(opcode, var); + } + } + + @Override + public void visitTypeInsn(final int opcode, final String type) { + minSize += 3; + maxSize += 3; + if (mv != null) { + mv.visitTypeInsn(opcode, type); + } + } + + @Override + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { + minSize += 3; + maxSize += 3; + if (mv != null) { + mv.visitFieldInsn(opcode, owner, name, desc); + } + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { + if (opcode == INVOKEINTERFACE) { + minSize += 5; + maxSize += 5; + } else { + minSize += 3; + maxSize += 3; + } + if (mv != null) { + mv.visitMethodInsn(opcode, owner, name, desc); + } + } + + @Override + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { + minSize += 5; + maxSize += 5; + if (mv != null) { + mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + } + } + + @Override + public void visitJumpInsn(final int opcode, final Label label) { + minSize += 3; + if (opcode == GOTO || opcode == JSR) { + maxSize += 5; + } else { + maxSize += 8; + } + if (mv != null) { + mv.visitJumpInsn(opcode, label); + } + } + + @Override + public void visitLdcInsn(final Object cst) { + if (cst instanceof Long || cst instanceof Double) { + minSize += 3; + maxSize += 3; + } else { + minSize += 2; + maxSize += 3; + } + if (mv != null) { + mv.visitLdcInsn(cst); + } + } + + @Override + public void visitIincInsn(final int var, final int increment) { + if (var > 255 || increment > 127 || increment < -128) { + minSize += 6; + maxSize += 6; + } else { + minSize += 3; + maxSize += 3; + } + if (mv != null) { + mv.visitIincInsn(var, increment); + } + } + + @Override + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { + minSize += 13 + labels.length * 4; + maxSize += 16 + labels.length * 4; + if (mv != null) { + mv.visitTableSwitchInsn(min, max, dflt, labels); + } + } + + @Override + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { + minSize += 9 + keys.length * 8; + maxSize += 12 + keys.length * 8; + if (mv != null) { + mv.visitLookupSwitchInsn(dflt, keys, labels); + } + } + + @Override + public void visitMultiANewArrayInsn(final String desc, final int dims) { + minSize += 4; + maxSize += 4; + if (mv != null) { + mv.visitMultiANewArrayInsn(desc, dims); + } + } +}
