http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Frame.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Frame.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Frame.java new file mode 100644 index 0000000..c7ff4fb --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Frame.java @@ -0,0 +1,729 @@ +/*** + * 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.tree.analysis; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tajo.org.objectweb.asm.Type; +import org.apache.tajo.org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.apache.tajo.org.objectweb.asm.Opcodes; +import org.apache.tajo.org.objectweb.asm.tree.AbstractInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.IincInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.MethodInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.VarInsnNode; + +/** + * A symbolic execution stack frame. A stack frame contains a set of local + * variable slots, and an operand stack. Warning: long and double values are + * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in + * the operand stack. + * + * @param <V> + * type of the Value used for the analysis. + * + * @author Eric Bruneton + */ +public class Frame<V extends Value> { + + /** + * The expected return type of the analyzed method, or <tt>null</tt> if the + * method returns void. + */ + private V returnValue; + + /** + * The local variables and operand stack of this frame. + */ + private V[] values; + + /** + * The number of local variables of this frame. + */ + private int locals; + + /** + * The number of elements in the operand stack. + */ + private int top; + + /** + * Constructs a new frame with the given size. + * + * @param nLocals + * the maximum number of local variables of the frame. + * @param nStack + * the maximum stack size of the frame. + */ + public Frame(final int nLocals, final int nStack) { + this.values = (V[]) new Value[nLocals + nStack]; + this.locals = nLocals; + } + + /** + * Constructs a new frame that is identical to the given frame. + * + * @param src + * a frame. + */ + public Frame(final Frame<? extends V> src) { + this(src.locals, src.values.length - src.locals); + init(src); + } + + /** + * Copies the state of the given frame into this frame. + * + * @param src + * a frame. + * @return this frame. + */ + public Frame<V> init(final Frame<? extends V> src) { + returnValue = src.returnValue; + System.arraycopy(src.values, 0, values, 0, values.length); + top = src.top; + return this; + } + + /** + * Sets the expected return type of the analyzed method. + * + * @param v + * the expected return type of the analyzed method, or + * <tt>null</tt> if the method returns void. + */ + public void setReturn(final V v) { + returnValue = v; + } + + /** + * Returns the maximum number of local variables of this frame. + * + * @return the maximum number of local variables of this frame. + */ + public int getLocals() { + return locals; + } + + /** + * Returns the value of the given local variable. + * + * @param i + * a local variable index. + * @return the value of the given local variable. + * @throws IndexOutOfBoundsException + * if the variable does not exist. + */ + public V getLocal(final int i) throws IndexOutOfBoundsException { + if (i >= locals) { + throw new IndexOutOfBoundsException( + "Trying to access an inexistant local variable"); + } + return values[i]; + } + + /** + * Sets the value of the given local variable. + * + * @param i + * a local variable index. + * @param value + * the new value of this local variable. + * @throws IndexOutOfBoundsException + * if the variable does not exist. + */ + public void setLocal(final int i, final V value) + throws IndexOutOfBoundsException { + if (i >= locals) { + throw new IndexOutOfBoundsException( + "Trying to access an inexistant local variable " + i); + } + values[i] = value; + } + + /** + * Returns the number of values in the operand stack of this frame. Long and + * double values are treated as single values. + * + * @return the number of values in the operand stack of this frame. + */ + public int getStackSize() { + return top; + } + + /** + * Returns the value of the given operand stack slot. + * + * @param i + * the index of an operand stack slot. + * @return the value of the given operand stack slot. + * @throws IndexOutOfBoundsException + * if the operand stack slot does not exist. + */ + public V getStack(final int i) throws IndexOutOfBoundsException { + return values[i + locals]; + } + + /** + * Clears the operand stack of this frame. + */ + public void clearStack() { + top = 0; + } + + /** + * Pops a value from the operand stack of this frame. + * + * @return the value that has been popped from the stack. + * @throws IndexOutOfBoundsException + * if the operand stack is empty. + */ + public V pop() throws IndexOutOfBoundsException { + if (top == 0) { + throw new IndexOutOfBoundsException( + "Cannot pop operand off an empty stack."); + } + return values[--top + locals]; + } + + /** + * Pushes a value into the operand stack of this frame. + * + * @param value + * the value that must be pushed into the stack. + * @throws IndexOutOfBoundsException + * if the operand stack is full. + */ + public void push(final V value) throws IndexOutOfBoundsException { + if (top + locals >= values.length) { + throw new IndexOutOfBoundsException( + "Insufficient maximum stack size."); + } + values[top++ + locals] = value; + } + + public void execute(final AbstractInsnNode insn, + final Interpreter<V> interpreter) throws AnalyzerException { + V value1, value2, value3, value4; + List<V> values; + int var; + + switch (insn.getOpcode()) { + case Opcodes.NOP: + break; + case Opcodes.ACONST_NULL: + 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.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + case Opcodes.LDC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.ILOAD: + case Opcodes.LLOAD: + case Opcodes.FLOAD: + case Opcodes.DLOAD: + case Opcodes.ALOAD: + push(interpreter.copyOperation(insn, + getLocal(((VarInsnNode) insn).var))); + break; + case Opcodes.IALOAD: + case Opcodes.LALOAD: + case Opcodes.FALOAD: + case Opcodes.DALOAD: + case Opcodes.AALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.ISTORE: + case Opcodes.LSTORE: + case Opcodes.FSTORE: + case Opcodes.DSTORE: + case Opcodes.ASTORE: + value1 = interpreter.copyOperation(insn, pop()); + var = ((VarInsnNode) insn).var; + setLocal(var, value1); + if (value1.getSize() == 2) { + setLocal(var + 1, interpreter.newValue(null)); + } + if (var > 0) { + Value local = getLocal(var - 1); + if (local != null && local.getSize() == 2) { + setLocal(var - 1, interpreter.newValue(null)); + } + } + break; + case Opcodes.IASTORE: + case Opcodes.LASTORE: + case Opcodes.FASTORE: + case Opcodes.DASTORE: + case Opcodes.AASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + value3 = pop(); + value2 = pop(); + value1 = pop(); + interpreter.ternaryOperation(insn, value1, value2, value3); + break; + case Opcodes.POP: + if (pop().getSize() == 2) { + throw new AnalyzerException(insn, "Illegal use of POP"); + } + break; + case Opcodes.POP2: + if (pop().getSize() == 1) { + if (pop().getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of POP2"); + } + } + break; + case Opcodes.DUP: + value1 = pop(); + if (value1.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP"); + } + push(value1); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.DUP_X1: + value1 = pop(); + value2 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP_X1"); + } + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + case Opcodes.DUP_X2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } else { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + } + } + throw new AnalyzerException(insn, "Illegal use of DUP_X2"); + case Opcodes.DUP2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + push(value2); + push(value1); + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; + } + } else { + push(value1); + push(interpreter.copyOperation(insn, value1)); + break; + } + throw new AnalyzerException(insn, "Illegal use of DUP2"); + case Opcodes.DUP2_X1: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } + } else { + value2 = pop(); + if (value2.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + } + } + throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); + case Opcodes.DUP2_X2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + value4 = pop(); + if (value4.getSize() == 1) { + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + push(value4); + push(value3); + push(value2); + push(value1); + break; + } + } else { + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } + } else { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } else { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + } + } + throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); + case Opcodes.SWAP: + value2 = pop(); + value1 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of SWAP"); + } + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.IADD: + case Opcodes.LADD: + case Opcodes.FADD: + case Opcodes.DADD: + case Opcodes.ISUB: + case Opcodes.LSUB: + case Opcodes.FSUB: + case Opcodes.DSUB: + case Opcodes.IMUL: + case Opcodes.LMUL: + case Opcodes.FMUL: + case Opcodes.DMUL: + case Opcodes.IDIV: + case Opcodes.LDIV: + case Opcodes.FDIV: + case Opcodes.DDIV: + case Opcodes.IREM: + case Opcodes.LREM: + case Opcodes.FREM: + case Opcodes.DREM: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.ISHL: + case Opcodes.LSHL: + case Opcodes.ISHR: + case Opcodes.LSHR: + case Opcodes.IUSHR: + case Opcodes.LUSHR: + case Opcodes.IAND: + case Opcodes.LAND: + case Opcodes.IOR: + case Opcodes.LOR: + case Opcodes.IXOR: + case Opcodes.LXOR: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.IINC: + var = ((IincInsnNode) insn).var; + setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); + break; + case Opcodes.I2L: + case Opcodes.I2F: + case Opcodes.I2D: + case Opcodes.L2I: + case Opcodes.L2F: + case Opcodes.L2D: + case Opcodes.F2I: + case Opcodes.F2L: + case Opcodes.F2D: + case Opcodes.D2I: + case Opcodes.D2L: + case Opcodes.D2F: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.LCMP: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + interpreter.unaryOperation(insn, pop()); + break; + 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: + value2 = pop(); + value1 = pop(); + interpreter.binaryOperation(insn, value1, value2); + break; + case Opcodes.GOTO: + break; + case Opcodes.JSR: + push(interpreter.newOperation(insn)); + break; + case Opcodes.RET: + break; + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.IRETURN: + case Opcodes.LRETURN: + case Opcodes.FRETURN: + case Opcodes.DRETURN: + case Opcodes.ARETURN: + value1 = pop(); + interpreter.unaryOperation(insn, value1); + interpreter.returnOperation(insn, value1, returnValue); + break; + case Opcodes.RETURN: + if (returnValue != null) { + throw new AnalyzerException(insn, "Incompatible return type"); + } + break; + case Opcodes.GETSTATIC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.PUTSTATIC: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.GETFIELD: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.PUTFIELD: + value2 = pop(); + value1 = pop(); + interpreter.binaryOperation(insn, value1, value2); + break; + case Opcodes.INVOKEVIRTUAL: + case Opcodes.INVOKESPECIAL: + case Opcodes.INVOKESTATIC: + case Opcodes.INVOKEINTERFACE: { + values = new ArrayList<V>(); + String desc = ((MethodInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { + values.add(0, pop()); + } + if (insn.getOpcode() != Opcodes.INVOKESTATIC) { + values.add(0, pop()); + } + if (Type.getReturnType(desc) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, values); + } else { + push(interpreter.naryOperation(insn, values)); + } + break; + } + case Opcodes.INVOKEDYNAMIC: { + values = new ArrayList<V>(); + String desc = ((InvokeDynamicInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { + values.add(0, pop()); + } + if (Type.getReturnType(desc) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, values); + } else { + push(interpreter.naryOperation(insn, values)); + } + break; + } + case Opcodes.NEW: + push(interpreter.newOperation(insn)); + break; + case Opcodes.NEWARRAY: + case Opcodes.ANEWARRAY: + case Opcodes.ARRAYLENGTH: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.ATHROW: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.CHECKCAST: + case Opcodes.INSTANCEOF: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.MULTIANEWARRAY: + values = new ArrayList<V>(); + for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) { + values.add(0, pop()); + } + push(interpreter.naryOperation(insn, values)); + break; + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + interpreter.unaryOperation(insn, pop()); + break; + default: + throw new RuntimeException("Illegal opcode " + insn.getOpcode()); + } + } + + /** + * Merges this frame with the given frame. + * + * @param frame + * a frame. + * @param interpreter + * the interpreter used to merge values. + * @return <tt>true</tt> if this frame has been changed as a result of the + * merge operation, or <tt>false</tt> otherwise. + * @throws AnalyzerException + * if the frames have incompatible sizes. + */ + public boolean merge(final Frame<? extends V> frame, + final Interpreter<V> interpreter) throws AnalyzerException { + if (top != frame.top) { + throw new AnalyzerException(null, "Incompatible stack heights"); + } + boolean changes = false; + for (int i = 0; i < locals + top; ++i) { + V v = interpreter.merge(values[i], frame.values[i]); + if (!v.equals(values[i])) { + values[i] = v; + changes = true; + } + } + return changes; + } + + /** + * Merges this frame with the given frame (case of a RET instruction). + * + * @param frame + * a frame + * @param access + * the local variables that have been accessed by the subroutine + * to which the RET instruction corresponds. + * @return <tt>true</tt> if this frame has been changed as a result of the + * merge operation, or <tt>false</tt> otherwise. + */ + public boolean merge(final Frame<? extends V> frame, final boolean[] access) { + boolean changes = false; + for (int i = 0; i < locals; ++i) { + if (!access[i] && !values[i].equals(frame.values[i])) { + values[i] = frame.values[i]; + changes = true; + } + } + return changes; + } + + /** + * Returns a string representation of this frame. + * + * @return a string representation of this frame. + */ + @Override + public String toString() { + StringBuffer b = new StringBuffer(); + for (int i = 0; i < getLocals(); ++i) { + b.append(getLocal(i)); + } + b.append(' '); + for (int i = 0; i < getStackSize(); ++i) { + b.append(getStack(i).toString()); + } + return b.toString(); + } +}
http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Interpreter.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Interpreter.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Interpreter.java new file mode 100644 index 0000000..5e90560 --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Interpreter.java @@ -0,0 +1,226 @@ +/*** + * 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.tree.analysis; + +import java.util.List; + +import org.apache.tajo.org.objectweb.asm.Type; +import org.apache.tajo.org.objectweb.asm.tree.AbstractInsnNode; + +/** + * A semantic bytecode interpreter. More precisely, this interpreter only + * manages the computation of values from other values: it does not manage the + * transfer of values to or from the stack, and to or from the local variables. + * This separation allows a generic bytecode {@link Analyzer} to work with + * various semantic interpreters, without needing to duplicate the code to + * simulate the transfer of values. + * + * @param <V> + * type of the Value used for the analysis. + * + * @author Eric Bruneton + */ +public abstract class Interpreter<V extends Value> { + + protected final int api; + + protected Interpreter(final int api) { + this.api = api; + } + + /** + * Creates a new value that represents the given type. + * + * Called for method parameters (including <code>this</code>), exception + * handler variable and with <code>null</code> type for variables reserved + * by long and double types. + * + * @param type + * a primitive or reference type, or <tt>null</tt> to represent + * an uninitialized value. + * @return a value that represents the given type. The size of the returned + * value must be equal to the size of the given type. + */ + public abstract V newValue(Type type); + + /** + * Interprets a bytecode instruction without arguments. This method is + * called for the following opcodes: + * + * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, + * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, + * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW + * + * @param insn + * the bytecode instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException + * if an error occured during the interpretation. + */ + public abstract V newOperation(AbstractInsnNode insn) + throws AnalyzerException; + + /** + * Interprets a bytecode instruction that moves a value on the stack or to + * or from local variables. This method is called for the following opcodes: + * + * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, + * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP + * + * @param insn + * the bytecode instruction to be interpreted. + * @param value + * the value that must be moved by the instruction. + * @return the result of the interpretation of the given instruction. The + * returned value must be <tt>equal</tt> to the given value. + * @throws AnalyzerException + * if an error occured during the interpretation. + */ + public abstract V copyOperation(AbstractInsnNode insn, V value) + throws AnalyzerException; + + /** + * Interprets a bytecode instruction with a single argument. This method is + * called for the following opcodes: + * + * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, + * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, + * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, + * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST, + * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL + * + * @param insn + * the bytecode instruction to be interpreted. + * @param value + * the argument of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException + * if an error occured during the interpretation. + */ + public abstract V unaryOperation(AbstractInsnNode insn, V value) + throws AnalyzerException; + + /** + * Interprets a bytecode instruction with two arguments. This method is + * called for the following opcodes: + * + * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD, + * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, + * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR, + * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL, + * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, + * IF_ACMPEQ, IF_ACMPNE, PUTFIELD + * + * @param insn + * the bytecode instruction to be interpreted. + * @param value1 + * the first argument of the instruction to be interpreted. + * @param value2 + * the second argument of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException + * if an error occured during the interpretation. + */ + public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2) + throws AnalyzerException; + + /** + * Interprets a bytecode instruction with three arguments. This method is + * called for the following opcodes: + * + * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE + * + * @param insn + * the bytecode instruction to be interpreted. + * @param value1 + * the first argument of the instruction to be interpreted. + * @param value2 + * the second argument of the instruction to be interpreted. + * @param value3 + * the third argument of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException + * if an error occured during the interpretation. + */ + public abstract V ternaryOperation(AbstractInsnNode insn, V value1, + V value2, V value3) throws AnalyzerException; + + /** + * Interprets a bytecode instruction with a variable number of arguments. + * This method is called for the following opcodes: + * + * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE, + * MULTIANEWARRAY and INVOKEDYNAMIC + * + * @param insn + * the bytecode instruction to be interpreted. + * @param values + * the arguments of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException + * if an error occured during the interpretation. + */ + public abstract V naryOperation(AbstractInsnNode insn, + List<? extends V> values) throws AnalyzerException; + + /** + * Interprets a bytecode return instruction. This method is called for the + * following opcodes: + * + * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN + * + * @param insn + * the bytecode instruction to be interpreted. + * @param value + * the argument of the instruction to be interpreted. + * @param expected + * the expected return type of the analyzed method. + * @throws AnalyzerException + * if an error occured during the interpretation. + */ + public abstract void returnOperation(AbstractInsnNode insn, V value, + V expected) throws AnalyzerException; + + /** + * Merges two values. The merge operation must return a value that + * represents both values (for instance, if the two values are two types, + * the merged value must be a common super type of the two types. If the two + * values are integer intervals, the merged value must be an interval that + * contains the previous ones. Likewise for other types of values). + * + * @param v + * a value. + * @param w + * another value. + * @return the merged value. If the merged value is equal to <tt>v</tt>, + * this method <i>must</i> return <tt>v</tt>. + */ + public abstract V merge(V v, V w); +} http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SimpleVerifier.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SimpleVerifier.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SimpleVerifier.java new file mode 100644 index 0000000..ac4971c --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SimpleVerifier.java @@ -0,0 +1,320 @@ +/*** + * 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.tree.analysis; + +import java.util.List; + +import org.apache.tajo.org.objectweb.asm.Type; + +/** + * An extended {@link BasicVerifier} that performs more precise verifications. + * This verifier computes exact class types, instead of using a single "object + * reference" type (as done in the {@link BasicVerifier}). + * + * @author Eric Bruneton + * @author Bing Ran + */ +public class SimpleVerifier extends BasicVerifier { + + /** + * The class that is verified. + */ + private final Type currentClass; + + /** + * The super class of the class that is verified. + */ + private final Type currentSuperClass; + + /** + * The interfaces implemented by the class that is verified. + */ + private final List<Type> currentClassInterfaces; + + /** + * If the class that is verified is an interface. + */ + private final boolean isInterface; + + /** + * The loader to use for referenced classes. + */ + private ClassLoader loader = getClass().getClassLoader(); + + /** + * Constructs a new {@link SimpleVerifier}. + */ + public SimpleVerifier() { + this(null, null, false); + } + + /** + * Constructs a new {@link SimpleVerifier} to verify a specific class. This + * class will not be loaded into the JVM since it may be incorrect. + * + * @param currentClass + * the class that is verified. + * @param currentSuperClass + * the super class of the class that is verified. + * @param isInterface + * if the class that is verified is an interface. + */ + public SimpleVerifier(final Type currentClass, + final Type currentSuperClass, final boolean isInterface) { + this(currentClass, currentSuperClass, null, isInterface); + } + + /** + * Constructs a new {@link SimpleVerifier} to verify a specific class. This + * class will not be loaded into the JVM since it may be incorrect. + * + * @param currentClass + * the class that is verified. + * @param currentSuperClass + * the super class of the class that is verified. + * @param currentClassInterfaces + * the interfaces implemented by the class that is verified. + * @param isInterface + * if the class that is verified is an interface. + */ + public SimpleVerifier(final Type currentClass, + final Type currentSuperClass, + final List<Type> currentClassInterfaces, final boolean isInterface) { + this(ASM4, currentClass, currentSuperClass, currentClassInterfaces, + isInterface); + } + + protected SimpleVerifier(final int api, final Type currentClass, + final Type currentSuperClass, + final List<Type> currentClassInterfaces, final boolean isInterface) { + super(api); + this.currentClass = currentClass; + this.currentSuperClass = currentSuperClass; + this.currentClassInterfaces = currentClassInterfaces; + this.isInterface = isInterface; + } + + /** + * Set the <code>ClassLoader</code> which will be used to load referenced + * classes. This is useful if you are verifying multiple interdependent + * classes. + * + * @param loader + * a <code>ClassLoader</code> to use + */ + public void setClassLoader(final ClassLoader loader) { + this.loader = loader; + } + + @Override + public BasicValue newValue(final Type type) { + if (type == null) { + return BasicValue.UNINITIALIZED_VALUE; + } + + boolean isArray = type.getSort() == Type.ARRAY; + if (isArray) { + switch (type.getElementType().getSort()) { + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + return new BasicValue(type); + } + } + + BasicValue v = super.newValue(type); + if (BasicValue.REFERENCE_VALUE.equals(v)) { + if (isArray) { + v = newValue(type.getElementType()); + String desc = v.getType().getDescriptor(); + for (int i = 0; i < type.getDimensions(); ++i) { + desc = '[' + desc; + } + v = new BasicValue(Type.getType(desc)); + } else { + v = new BasicValue(type); + } + } + return v; + } + + @Override + protected boolean isArrayValue(final BasicValue value) { + Type t = value.getType(); + return t != null + && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY); + } + + @Override + protected BasicValue getElementValue(final BasicValue objectArrayValue) + throws AnalyzerException { + Type arrayType = objectArrayValue.getType(); + if (arrayType != null) { + if (arrayType.getSort() == Type.ARRAY) { + return newValue(Type.getType(arrayType.getDescriptor() + .substring(1))); + } else if ("Lnull;".equals(arrayType.getDescriptor())) { + return objectArrayValue; + } + } + throw new Error("Internal error"); + } + + @Override + protected boolean isSubTypeOf(final BasicValue value, + final BasicValue expected) { + Type expectedType = expected.getType(); + Type type = value.getType(); + switch (expectedType.getSort()) { + case Type.INT: + case Type.FLOAT: + case Type.LONG: + case Type.DOUBLE: + return type.equals(expectedType); + case Type.ARRAY: + case Type.OBJECT: + if ("Lnull;".equals(type.getDescriptor())) { + return true; + } else if (type.getSort() == Type.OBJECT + || type.getSort() == Type.ARRAY) { + return isAssignableFrom(expectedType, type); + } else { + return false; + } + default: + throw new Error("Internal error"); + } + } + + @Override + public BasicValue merge(final BasicValue v, final BasicValue w) { + if (!v.equals(w)) { + Type t = v.getType(); + Type u = w.getType(); + if (t != null + && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) { + if (u != null + && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) { + if ("Lnull;".equals(t.getDescriptor())) { + return w; + } + if ("Lnull;".equals(u.getDescriptor())) { + return v; + } + if (isAssignableFrom(t, u)) { + return v; + } + if (isAssignableFrom(u, t)) { + return w; + } + // TODO case of array classes of the same dimension + // TODO should we look also for a common super interface? + // problem: there may be several possible common super + // interfaces + do { + if (t == null || isInterface(t)) { + return BasicValue.REFERENCE_VALUE; + } + t = getSuperClass(t); + if (isAssignableFrom(t, u)) { + return newValue(t); + } + } while (true); + } + } + return BasicValue.UNINITIALIZED_VALUE; + } + return v; + } + + protected boolean isInterface(final Type t) { + if (currentClass != null && t.equals(currentClass)) { + return isInterface; + } + return getClass(t).isInterface(); + } + + protected Type getSuperClass(final Type t) { + if (currentClass != null && t.equals(currentClass)) { + return currentSuperClass; + } + Class<?> c = getClass(t).getSuperclass(); + return c == null ? null : Type.getType(c); + } + + protected boolean isAssignableFrom(final Type t, final Type u) { + if (t.equals(u)) { + return true; + } + if (currentClass != null && t.equals(currentClass)) { + if (getSuperClass(u) == null) { + return false; + } else { + if (isInterface) { + return u.getSort() == Type.OBJECT + || u.getSort() == Type.ARRAY; + } + return isAssignableFrom(t, getSuperClass(u)); + } + } + if (currentClass != null && u.equals(currentClass)) { + if (isAssignableFrom(t, currentSuperClass)) { + return true; + } + if (currentClassInterfaces != null) { + for (int i = 0; i < currentClassInterfaces.size(); ++i) { + Type v = currentClassInterfaces.get(i); + if (isAssignableFrom(t, v)) { + return true; + } + } + } + return false; + } + Class<?> tc = getClass(t); + if (tc.isInterface()) { + tc = Object.class; + } + return tc.isAssignableFrom(getClass(u)); + } + + protected Class<?> getClass(final Type t) { + try { + if (t.getSort() == Type.ARRAY) { + return Class.forName(t.getDescriptor().replace('/', '.'), + false, loader); + } + return Class.forName(t.getClassName(), false, loader); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e.toString()); + } + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SmallSet.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SmallSet.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SmallSet.java new file mode 100644 index 0000000..cf92e28 --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SmallSet.java @@ -0,0 +1,134 @@ +/*** + * 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.tree.analysis; + +import java.util.AbstractSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * A set of at most two elements. + * + * @author Eric Bruneton + */ +class SmallSet<E> extends AbstractSet<E> implements Iterator<E> { + + // if e1 is null, e2 must be null; otherwise e2 must be different from e1 + + E e1, e2; + + static final <T> Set<T> emptySet() { + return new SmallSet<T>(null, null); + } + + SmallSet(final E e1, final E e2) { + this.e1 = e1; + this.e2 = e2; + } + + // ------------------------------------------------------------------------- + // Implementation of inherited abstract methods + // ------------------------------------------------------------------------- + + @Override + public Iterator<E> iterator() { + return new SmallSet<E>(e1, e2); + } + + @Override + public int size() { + return e1 == null ? 0 : (e2 == null ? 1 : 2); + } + + // ------------------------------------------------------------------------- + // Implementation of the Iterator interface + // ------------------------------------------------------------------------- + + public boolean hasNext() { + return e1 != null; + } + + public E next() { + if (e1 == null) { + throw new NoSuchElementException(); + } + E e = e1; + e1 = e2; + e2 = null; + return e; + } + + public void remove() { + } + + // ------------------------------------------------------------------------- + // Utility methods + // ------------------------------------------------------------------------- + + Set<E> union(final SmallSet<E> s) { + if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) { + return this; // if the two sets are equal, return this + } + if (s.e1 == null) { + return this; // if s is empty, return this + } + if (e1 == null) { + return s; // if this is empty, return s + } + if (s.e2 == null) { // s contains exactly one element + if (e2 == null) { + return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1 + } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this + return this; + } + } + if (e2 == null) { // this contains exactly one element + // if (s.e2 == null) { // cannot happen + // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1 + // } else + if (e1 == s.e1 || e1 == s.e2) { // this in included in s + return s; + } + } + // here we know that there are at least 3 distinct elements + HashSet<E> r = new HashSet<E>(4); + r.add(e1); + if (e2 != null) { + r.add(e2); + } + r.add(s.e1); + if (s.e2 != null) { + r.add(s.e2); + } + return r; + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceInterpreter.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceInterpreter.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceInterpreter.java new file mode 100644 index 0000000..4054dc6 --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceInterpreter.java @@ -0,0 +1,198 @@ +/*** + * 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.tree.analysis; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.tajo.org.objectweb.asm.Type; +import org.apache.tajo.org.objectweb.asm.Opcodes; +import org.apache.tajo.org.objectweb.asm.tree.AbstractInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.FieldInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.LdcInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.MethodInsnNode; + +/** + * An {@link Interpreter} for {@link SourceValue} values. + * + * @author Eric Bruneton + */ +public class SourceInterpreter extends Interpreter<SourceValue> implements + Opcodes { + + public SourceInterpreter() { + super(ASM4); + } + + protected SourceInterpreter(final int api) { + super(api); + } + + @Override + public SourceValue newValue(final Type type) { + if (type == Type.VOID_TYPE) { + return null; + } + return new SourceValue(type == null ? 1 : type.getSize()); + } + + @Override + public SourceValue newOperation(final AbstractInsnNode insn) { + int size; + switch (insn.getOpcode()) { + case LCONST_0: + case LCONST_1: + case DCONST_0: + case DCONST_1: + size = 2; + break; + case LDC: + Object cst = ((LdcInsnNode) insn).cst; + size = cst instanceof Long || cst instanceof Double ? 2 : 1; + break; + case GETSTATIC: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; + } + return new SourceValue(size, insn); + } + + @Override + public SourceValue copyOperation(final AbstractInsnNode insn, + final SourceValue value) { + return new SourceValue(value.getSize(), insn); + } + + @Override + public SourceValue unaryOperation(final AbstractInsnNode insn, + final SourceValue value) { + int size; + switch (insn.getOpcode()) { + case LNEG: + case DNEG: + case I2L: + case I2D: + case L2D: + case F2L: + case F2D: + case D2L: + size = 2; + break; + case GETFIELD: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; + } + return new SourceValue(size, insn); + } + + @Override + public SourceValue binaryOperation(final AbstractInsnNode insn, + final SourceValue value1, final SourceValue value2) { + int size; + switch (insn.getOpcode()) { + case LALOAD: + case DALOAD: + case LADD: + case DADD: + case LSUB: + case DSUB: + case LMUL: + case DMUL: + case LDIV: + case DDIV: + case LREM: + case DREM: + case LSHL: + case LSHR: + case LUSHR: + case LAND: + case LOR: + case LXOR: + size = 2; + break; + default: + size = 1; + } + return new SourceValue(size, insn); + } + + @Override + public SourceValue ternaryOperation(final AbstractInsnNode insn, + final SourceValue value1, final SourceValue value2, + final SourceValue value3) { + return new SourceValue(1, insn); + } + + @Override + public SourceValue naryOperation(final AbstractInsnNode insn, + final List<? extends SourceValue> values) { + int size; + int opcode = insn.getOpcode(); + if (opcode == MULTIANEWARRAY) { + size = 1; + } else { + String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc + : ((MethodInsnNode) insn).desc; + size = Type.getReturnType(desc).getSize(); + } + return new SourceValue(size, insn); + } + + @Override + public void returnOperation(final AbstractInsnNode insn, + final SourceValue value, final SourceValue expected) { + } + + @Override + public SourceValue merge(final SourceValue d, final SourceValue w) { + if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) { + Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns) + .union((SmallSet<AbstractInsnNode>) w.insns); + if (s == d.insns && d.size == w.size) { + return d; + } else { + return new SourceValue(Math.min(d.size, w.size), s); + } + } + if (d.size != w.size || !d.insns.containsAll(w.insns)) { + HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>(); + s.addAll(d.insns); + s.addAll(w.insns); + return new SourceValue(Math.min(d.size, w.size), s); + } + return d; + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceValue.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceValue.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceValue.java new file mode 100644 index 0000000..aa42478 --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/SourceValue.java @@ -0,0 +1,97 @@ +/*** + * 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.tree.analysis; + +import java.util.Set; + +import org.apache.tajo.org.objectweb.asm.tree.AbstractInsnNode; + +/** + * A {@link Value} that is represented by its type in a two types type system. + * This type system distinguishes the ONEWORD and TWOWORDS types. + * + * @author Eric Bruneton + */ +public class SourceValue implements Value { + + /** + * The size of this value. + */ + public final int size; + + /** + * The instructions that can produce this value. For example, for the Java + * code below, the instructions that can produce the value of <tt>i</tt> at + * line 5 are the txo ISTORE instructions at line 1 and 3: + * + * <pre> + * 1: i = 0; + * 2: if (...) { + * 3: i = 1; + * 4: } + * 5: return i; + * </pre> + * + * This field is a set of {@link org.apache.tajo.org.objectweb.asm.tree.AbstractInsnNode} objects. + */ + public final Set<AbstractInsnNode> insns; + + public SourceValue(final int size) { + this(size, SmallSet.<AbstractInsnNode> emptySet()); + } + + public SourceValue(final int size, final AbstractInsnNode insn) { + this.size = size; + this.insns = new SmallSet<AbstractInsnNode>(insn, null); + } + + public SourceValue(final int size, final Set<AbstractInsnNode> insns) { + this.size = size; + this.insns = insns; + } + + public int getSize() { + return size; + } + + @Override + public boolean equals(final Object value) { + if (!(value instanceof SourceValue)) { + return false; + } + SourceValue v = (SourceValue) value; + return size == v.size && insns.equals(v.insns); + } + + @Override + public int hashCode() { + return insns.hashCode(); + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Subroutine.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Subroutine.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Subroutine.java new file mode 100644 index 0000000..19cb36f --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Subroutine.java @@ -0,0 +1,90 @@ +/*** + * 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.tree.analysis; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tajo.org.objectweb.asm.tree.JumpInsnNode; +import org.apache.tajo.org.objectweb.asm.tree.LabelNode; + +/** + * A method subroutine (corresponds to a JSR instruction). + * + * @author Eric Bruneton + */ +class Subroutine { + + LabelNode start; + + boolean[] access; + + List<JumpInsnNode> callers; + + private Subroutine() { + } + + Subroutine(final LabelNode start, final int maxLocals, + final JumpInsnNode caller) { + this.start = start; + this.access = new boolean[maxLocals]; + this.callers = new ArrayList<JumpInsnNode>(); + callers.add(caller); + } + + public Subroutine copy() { + Subroutine result = new Subroutine(); + result.start = start; + result.access = new boolean[access.length]; + System.arraycopy(access, 0, result.access, 0, access.length); + result.callers = new ArrayList<JumpInsnNode>(callers); + return result; + } + + public boolean merge(final Subroutine subroutine) throws AnalyzerException { + boolean changes = false; + for (int i = 0; i < access.length; ++i) { + if (subroutine.access[i] && !access[i]) { + access[i] = true; + changes = true; + } + } + if (subroutine.start == start) { + for (int i = 0; i < subroutine.callers.size(); ++i) { + JumpInsnNode caller = subroutine.callers.get(i); + if (!callers.contains(caller)) { + callers.add(caller); + changes = true; + } + } + } + return changes; + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Value.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Value.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Value.java new file mode 100644 index 0000000..6a2887a --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Value.java @@ -0,0 +1,45 @@ +/*** + * 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.tree.analysis; + +/** + * An immutable symbolic value for semantic interpretation of bytecode. + * + * @author Eric Bruneton + */ +public interface Value { + + /** + * Returns the size of this value in words. + * + * @return either 1 or 2. + */ + int getSize(); +} http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/package.html ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/package.html b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/package.html new file mode 100644 index 0000000..57345a8 --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/package.html @@ -0,0 +1,85 @@ +<!--~ + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<html> +<!-- + * 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. +--> +<body> + +<p> +Provides a framework for static code analysis based on the asm.tree package. +</p> + +<p> +Basic usage: +</p> + +<pre> +ClassReader cr = new ClassReader(bytecode); +ClassNode cn = new ClassNode(); +cr.accept(cn, ClassReader.SKIP_DEBUG); + +List methods = cn.methods; +for (int i = 0; i < methods.size(); ++i) { + MethodNode method = (MethodNode) methods.get(i); + if (method.instructions.size() > 0) { + Analyzer a = new Analyzer(new BasicInterpreter()); + a.analyze(cn.name, method); + Frame[] frames = a.getFrames(); + // Elements of the frames arrray now contains info for each instruction + // from the analyzed method. BasicInterpreter creates BasicValue, that + // is using simplified type system that distinguishes the UNINITIALZED, + // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types. + ... + } +} +</pre> + +<p> +@since ASM 1.4.3 +</p> + +</body> +</html> http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/package.html ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/package.html b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/package.html new file mode 100644 index 0000000..733f2ff --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/package.html @@ -0,0 +1,210 @@ +<!--~ + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<html> +<!-- + * 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. +--> +<body> + +<p> +Provides an ASM visitor that constructs a tree representation of the +classes it visits. This class adapter can be useful to implement "complex" +class manipulation operations, i.e., operations that would be very hard to +implement without using a tree representation (such as optimizing the number +of local variables used by a method). +</p> + +<p> +However, this class adapter has a cost: it makes ASM bigger and slower. Indeed +it requires more than twenty new classes, and multiplies the time needed to +transform a class by almost two (it is almost two times faster to read, "modify" +and write a class with a ClassVisitor than with a ClassNode). This is why +this package is bundled in an optional <tt>asm-tree.jar</tt> library that +is separated from (but requires) the <tt>asm.jar</tt> library, which contains +the core ASM framework. This is also why <i><font color="red">it is recommended +not to use this class adapter when it is possible</font></i>. +</p> + +<p> +The root class is the ClassNode, that can be created from existing bytecode. For example: +</p> + +<pre> + ClassReader cr = new ClassReader(source); + ClassNode cn = new ClassNode(); + cr.accept(cn, true); +</pre> + +<p> +Now the content of ClassNode can be modified and then +serialized back into bytecode: +</p> + +<pre> + ClassWriter cw = new ClassWriter(true); + cn.accept(cw); +</pre> + +<p> +Using a simple ClassVisitor it is possible to create MethodNode instances per-method. +In this example MethodNode is acting as a buffer that is flushed out at visitEnd() call: +</p> + +<pre> + ClassReader cr = new ClassReader(source); + ClassWriter cw = new ClassWriter(); + ClassVisitor cv = new ClassVisitor(cw) { + public MethodVisitor visitMethod(int access, String name, + String desc, String signature, String[] exceptions) { + final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + MethodNode mn = new MethodNode(access, name, desc, signature, exceptions) { + public void visitEnd() { + // transform or analyze method code using tree API + accept(mv); + } + }; + } + }; + cr.accept(cv, true); +</pre> + +<p> +Several strategies can be used to construct method code from scratch. The first +option is to create a MethodNode, and then create XxxInsnNode instances and +add them to the instructions list: +</p> + +<pre> +MethodNode m = new MethodNode(...); +m.instructions.add(new VarInsnNode(ALOAD, 0)); +... +</pre> + +<p> +Alternatively, you can use the fact that MethodNode is a MethodVisitor, and use +that to create the XxxInsnNode and add them to the instructions list through +the standard MethodVisitor methods: +</p> + +<pre> +MethodNode m = new MethodNode(...); +m.visitVarInsn(ALOAD, 0); +... +</pre> + +<p> +If you cannot generate all the instructions in sequential order, i.e. if you +need to save some pointer in the instruction list and then insert instructions +at that place after other instructions have been generated, you can use InsnList +methods insert() and insertBefore() to insert instructions at a saved pointer. +</p> + +<pre> +MethodNode m = new MethodNode(...); +m.visitVarInsn(ALOAD, 0); +AbstractInsnNode ptr = m.instructions.getLast(); +m.visitVarInsn(ALOAD, 1); +// inserts an instruction between ALOAD 0 and ALOAD 1 +m.instructions.insert(ptr, new VarInsnNode(ALOAD, 0)); +... +</pre> + +<p> +If you need to insert instructions while iterating over an existing instruction +list, you can also use several strategies. The first one is to use a +ListIterator over the instruction list: +</p> + +<pre> +ListIterator it = m.instructions.iterator(); +while (it.hasNext()) { + AbstractInsnNode n = (AbstractInsnNode) it.next(); + if (...) { + it.add(new VarInsnNode(ALOAD, 0)); + } +} +</pre> + +<p> +It is also possible to convert an instruction list into an array and iterate trough +array elements: +</p> + +<pre> +AbstractInsnNode[] insns = m.instructions.toArray(); +for(int i = 0; i<insns.length; i++) { + AbstractInsnNode n = insns[i]; + if (...) { + m.instructions.insert(n, new VarInsnNode(ALOAD, 0)); + } +} +</pre> + +<p> +If you want to insert these instructions through the MethodVisitor methods, +you can use another instance of MethodNode as a MethodVisitor and then +insert instructions collected by that instance into the instruction list. +For example: +</p> + +<pre> +AbstractInsnNode[] insns = m.instructions.toArray(); +for(int i = 0; i<insns.length; i++) { + AbstractInsnNode n = insns[i]; + if (...) { + MethodNode mn = new MethodNode(); + mn.visitVarInsn(ALOAD, 0); + mn.visitVarInsn(ALOAD, 1); + m.instructions.insert(n, mn.instructions); + } +} +</pre> + +<p> +@since ASM 1.3.3 +</p> + +</body> +</html> http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/util/ASMifiable.java ---------------------------------------------------------------------- diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/util/ASMifiable.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/util/ASMifiable.java new file mode 100644 index 0000000..b2381c1 --- /dev/null +++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/util/ASMifiable.java @@ -0,0 +1,56 @@ +/** + * 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.util; + +import java.util.Map; + +import org.apache.tajo.org.objectweb.asm.Label; + +/** + * An {@link org.apache.tajo.org.objectweb.asm.Attribute Attribute} that can print the ASM code + * to create an equivalent attribute. + * + * @author Eugene Kuleshov + */ +public interface ASMifiable { + + /** + * Prints the ASM code to create an attribute equal to this attribute. + * + * @param buf + * a buffer used for printing Java code. + * @param varName + * name of the variable in a printed code used to store attribute + * instance. + * @param labelNames + * map of label instances to their names. + */ + void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames); +}
