tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hyun...@apache.org
Subject [07/25] TAJO-906: Runtime code generation for evaluating expression trees.
Date Sat, 23 Aug 2014 17:37:56 GMT
http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TableSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TableSwitchInsnNode.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TableSwitchInsnNode.java
new file mode 100644
index 0000000..a597c29
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TableSwitchInsnNode.java
@@ -0,0 +1,113 @@
+/***
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+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 node that represents a TABLESWITCH instruction.
+ * 
+ * @author Eric Bruneton
+ */
+public class TableSwitchInsnNode extends AbstractInsnNode {
+
+    /**
+     * The minimum key value.
+     */
+    public int min;
+
+    /**
+     * The maximum key value.
+     */
+    public int max;
+
+    /**
+     * Beginning of the default handler block.
+     */
+    public LabelNode dflt;
+
+    /**
+     * Beginnings of the handler blocks. This list is a list of
+     * {@link LabelNode} objects.
+     */
+    public List<LabelNode> labels;
+
+    /**
+     * Constructs a new {@link TableSwitchInsnNode}.
+     * 
+     * @param min
+     *            the minimum key value.
+     * @param max
+     *            the maximum key value.
+     * @param dflt
+     *            beginning of the default handler block.
+     * @param labels
+     *            beginnings of the handler blocks. <tt>labels[i]</tt> is the
+     *            beginning of the handler block for the <tt>min + i</tt> key.
+     */
+    public TableSwitchInsnNode(final int min, final int max,
+            final LabelNode dflt, final LabelNode... labels) {
+        super(Opcodes.TABLESWITCH);
+        this.min = min;
+        this.max = max;
+        this.dflt = dflt;
+        this.labels = new ArrayList<LabelNode>();
+        if (labels != null) {
+            this.labels.addAll(Arrays.asList(labels));
+        }
+    }
+
+    @Override
+    public int getType() {
+        return TABLESWITCH_INSN;
+    }
+
+    @Override
+    public void accept(final MethodVisitor mv) {
+        Label[] labels = new Label[this.labels.size()];
+        for (int i = 0; i < labels.length; ++i) {
+            labels[i] = this.labels.get(i).getLabel();
+        }
+        mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
+    }
+
+    @Override
+    public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+        return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
+                this.labels, labels));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TryCatchBlockNode.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TryCatchBlockNode.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TryCatchBlockNode.java
new file mode 100644
index 0000000..f04c3dc
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TryCatchBlockNode.java
@@ -0,0 +1,94 @@
+/***
+ * 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;
+
+import org.apache.tajo.org.objectweb.asm.MethodVisitor;
+
+/**
+ * A node that represents a try catch block.
+ * 
+ * @author Eric Bruneton
+ */
+public class TryCatchBlockNode {
+
+    /**
+     * Beginning of the exception handler's scope (inclusive).
+     */
+    public LabelNode start;
+
+    /**
+     * End of the exception handler's scope (exclusive).
+     */
+    public LabelNode end;
+
+    /**
+     * Beginning of the exception handler's code.
+     */
+    public LabelNode handler;
+
+    /**
+     * Internal name of the type of exceptions handled by the handler. May be
+     * <tt>null</tt> to catch any exceptions (for "finally" blocks).
+     */
+    public String type;
+
+    /**
+     * Constructs a new {@link TryCatchBlockNode}.
+     * 
+     * @param start
+     *            beginning of the exception handler's scope (inclusive).
+     * @param end
+     *            end of the exception handler's scope (exclusive).
+     * @param handler
+     *            beginning of the exception handler's code.
+     * @param type
+     *            internal name of the type of exceptions handled by the
+     *            handler, or <tt>null</tt> to catch any exceptions (for
+     *            "finally" blocks).
+     */
+    public TryCatchBlockNode(final LabelNode start, final LabelNode end,
+            final LabelNode handler, final String type) {
+        this.start = start;
+        this.end = end;
+        this.handler = handler;
+        this.type = type;
+    }
+
+    /**
+     * Makes the given visitor visit this try catch block.
+     * 
+     * @param mv
+     *            a method visitor.
+     */
+    public void accept(final MethodVisitor mv) {
+        mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
+                handler == null ? null : handler.getLabel(), type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TypeInsnNode.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TypeInsnNode.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TypeInsnNode.java
new file mode 100644
index 0000000..e6df331
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/TypeInsnNode.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;
+
+import java.util.Map;
+
+import org.apache.tajo.org.objectweb.asm.MethodVisitor;
+
+/**
+ * A node that represents a type instruction. A type instruction is an
+ * instruction that takes a type descriptor as parameter.
+ * 
+ * @author Eric Bruneton
+ */
+public class TypeInsnNode extends AbstractInsnNode {
+
+    /**
+     * The operand of this instruction. This operand is an internal name (see
+     * {@link org.apache.tajo.org.objectweb.asm.Type}).
+     */
+    public String desc;
+
+    /**
+     * Constructs a new {@link TypeInsnNode}.
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+     * @param desc
+     *            the operand of the instruction to be constructed. This operand
+     *            is an internal name (see {@link org.apache.tajo.org.objectweb.asm.Type}).
+     */
+    public TypeInsnNode(final int opcode, final String desc) {
+        super(opcode);
+        this.desc = desc;
+    }
+
+    /**
+     * Sets the opcode of this instruction.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be NEW,
+     *            ANEWARRAY, CHECKCAST or INSTANCEOF.
+     */
+    public void setOpcode(final int opcode) {
+        this.opcode = opcode;
+    }
+
+    @Override
+    public int getType() {
+        return TYPE_INSN;
+    }
+
+    @Override
+    public void accept(final MethodVisitor mv) {
+        mv.visitTypeInsn(opcode, desc);
+    }
+
+    @Override
+    public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+        return new TypeInsnNode(opcode, desc);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/VarInsnNode.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/VarInsnNode.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/VarInsnNode.java
new file mode 100644
index 0000000..afd0d14
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/VarInsnNode.java
@@ -0,0 +1,93 @@
+/***
+ * 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;
+
+import java.util.Map;
+
+import org.apache.tajo.org.objectweb.asm.MethodVisitor;
+
+/**
+ * A node that represents a local variable instruction. A local variable
+ * instruction is an instruction that loads or stores the value of a local
+ * variable.
+ * 
+ * @author Eric Bruneton
+ */
+public class VarInsnNode extends AbstractInsnNode {
+
+    /**
+     * The operand of this instruction. This operand is the index of a local
+     * variable.
+     */
+    public int var;
+
+    /**
+     * Constructs a new {@link VarInsnNode}.
+     * 
+     * @param opcode
+     *            the opcode of the local variable instruction to be
+     *            constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+     *            ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+     * @param var
+     *            the operand of the instruction to be constructed. This operand
+     *            is the index of a local variable.
+     */
+    public VarInsnNode(final int opcode, final int var) {
+        super(opcode);
+        this.var = var;
+    }
+
+    /**
+     * Sets the opcode of this instruction.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be ILOAD, LLOAD,
+     *            FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or
+     *            RET.
+     */
+    public void setOpcode(final int opcode) {
+        this.opcode = opcode;
+    }
+
+    @Override
+    public int getType() {
+        return VAR_INSN;
+    }
+
+    @Override
+    public void accept(final MethodVisitor mv) {
+        mv.visitVarInsn(opcode, var);
+    }
+
+    @Override
+    public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+        return new VarInsnNode(opcode, var);
+    }
+}

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/Analyzer.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Analyzer.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Analyzer.java
new file mode 100644
index 0000000..1095dd0
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/Analyzer.java
@@ -0,0 +1,549 @@
+/***
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.IincInsnNode;
+import org.apache.tajo.org.objectweb.asm.tree.InsnList;
+import org.apache.tajo.org.objectweb.asm.tree.JumpInsnNode;
+import org.apache.tajo.org.objectweb.asm.tree.LabelNode;
+import org.apache.tajo.org.objectweb.asm.tree.LookupSwitchInsnNode;
+import org.apache.tajo.org.objectweb.asm.tree.MethodNode;
+import org.apache.tajo.org.objectweb.asm.tree.TableSwitchInsnNode;
+import org.apache.tajo.org.objectweb.asm.tree.TryCatchBlockNode;
+import org.apache.tajo.org.objectweb.asm.tree.VarInsnNode;
+
+/**
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
+ * RET instructions are valid.</i>
+ * 
+ * @param <V>
+ *            type of the Value used for the analysis.
+ * 
+ * @author Eric Bruneton
+ */
+public class Analyzer<V extends Value> implements Opcodes {
+
+    private final Interpreter<V> interpreter;
+
+    private int n;
+
+    private InsnList insns;
+
+    private List<TryCatchBlockNode>[] handlers;
+
+    private Frame<V>[] frames;
+
+    private Subroutine[] subroutines;
+
+    private boolean[] queued;
+
+    private int[] queue;
+
+    private int top;
+
+    /**
+     * Constructs a new {@link Analyzer}.
+     * 
+     * @param interpreter
+     *            the interpreter to be used to symbolically interpret the
+     *            bytecode instructions.
+     */
+    public Analyzer(final Interpreter<V> interpreter) {
+        this.interpreter = interpreter;
+    }
+
+    /**
+     * Analyzes the given method.
+     * 
+     * @param owner
+     *            the internal name of the class to which the method belongs.
+     * @param m
+     *            the method to be analyzed.
+     * @return the symbolic state of the execution stack frame at each bytecode
+     *         instruction of the method. The size of the returned array is
+     *         equal to the number of instructions (and labels) of the method. A
+     *         given frame is <tt>null</tt> if and only if the corresponding
+     *         instruction cannot be reached (dead code).
+     * @throws AnalyzerException
+     *             if a problem occurs during the analysis.
+     */
+    public Frame<V>[] analyze(final String owner, final MethodNode m)
+            throws AnalyzerException {
+        if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+            frames = (Frame<V>[]) new Frame<?>[0];
+            return frames;
+        }
+        n = m.instructions.size();
+        insns = m.instructions;
+        handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
+        frames = (Frame<V>[]) new Frame<?>[n];
+        subroutines = new Subroutine[n];
+        queued = new boolean[n];
+        queue = new int[n];
+        top = 0;
+
+        // computes exception handlers for each instruction
+        for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+            TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
+            int begin = insns.indexOf(tcb.start);
+            int end = insns.indexOf(tcb.end);
+            for (int j = begin; j < end; ++j) {
+                List<TryCatchBlockNode> insnHandlers = handlers[j];
+                if (insnHandlers == null) {
+                    insnHandlers = new ArrayList<TryCatchBlockNode>();
+                    handlers[j] = insnHandlers;
+                }
+                insnHandlers.add(tcb);
+            }
+        }
+
+        // computes the subroutine for each instruction:
+        Subroutine main = new Subroutine(null, m.maxLocals, null);
+        List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
+        Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
+        findSubroutine(0, main, subroutineCalls);
+        while (!subroutineCalls.isEmpty()) {
+            JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
+            Subroutine sub = subroutineHeads.get(jsr.label);
+            if (sub == null) {
+                sub = new Subroutine(jsr.label, m.maxLocals, jsr);
+                subroutineHeads.put(jsr.label, sub);
+                findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+            } else {
+                sub.callers.add(jsr);
+            }
+        }
+        for (int i = 0; i < n; ++i) {
+            if (subroutines[i] != null && subroutines[i].start == null) {
+                subroutines[i] = null;
+            }
+        }
+
+        // initializes the data structures for the control flow analysis
+        Frame<V> current = newFrame(m.maxLocals, m.maxStack);
+        Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
+        current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
+        Type[] args = Type.getArgumentTypes(m.desc);
+        int local = 0;
+        if ((m.access & ACC_STATIC) == 0) {
+            Type ctype = Type.getObjectType(owner);
+            current.setLocal(local++, interpreter.newValue(ctype));
+        }
+        for (int i = 0; i < args.length; ++i) {
+            current.setLocal(local++, interpreter.newValue(args[i]));
+            if (args[i].getSize() == 2) {
+                current.setLocal(local++, interpreter.newValue(null));
+            }
+        }
+        while (local < m.maxLocals) {
+            current.setLocal(local++, interpreter.newValue(null));
+        }
+        merge(0, current, null);
+
+        init(owner, m);
+
+        // control flow analysis
+        while (top > 0) {
+            int insn = queue[--top];
+            Frame<V> f = frames[insn];
+            Subroutine subroutine = subroutines[insn];
+            queued[insn] = false;
+
+            AbstractInsnNode insnNode = null;
+            try {
+                insnNode = m.instructions.get(insn);
+                int insnOpcode = insnNode.getOpcode();
+                int insnType = insnNode.getType();
+
+                if (insnType == AbstractInsnNode.LABEL
+                        || insnType == AbstractInsnNode.LINE
+                        || insnType == AbstractInsnNode.FRAME) {
+                    merge(insn + 1, f, subroutine);
+                    newControlFlowEdge(insn, insn + 1);
+                } else {
+                    current.init(f).execute(insnNode, interpreter);
+                    subroutine = subroutine == null ? null : subroutine.copy();
+
+                    if (insnNode instanceof JumpInsnNode) {
+                        JumpInsnNode j = (JumpInsnNode) insnNode;
+                        if (insnOpcode != GOTO && insnOpcode != JSR) {
+                            merge(insn + 1, current, subroutine);
+                            newControlFlowEdge(insn, insn + 1);
+                        }
+                        int jump = insns.indexOf(j.label);
+                        if (insnOpcode == JSR) {
+                            merge(jump, current, new Subroutine(j.label,
+                                    m.maxLocals, j));
+                        } else {
+                            merge(jump, current, subroutine);
+                        }
+                        newControlFlowEdge(insn, jump);
+                    } else if (insnNode instanceof LookupSwitchInsnNode) {
+                        LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+                        int jump = insns.indexOf(lsi.dflt);
+                        merge(jump, current, subroutine);
+                        newControlFlowEdge(insn, jump);
+                        for (int j = 0; j < lsi.labels.size(); ++j) {
+                            LabelNode label = lsi.labels.get(j);
+                            jump = insns.indexOf(label);
+                            merge(jump, current, subroutine);
+                            newControlFlowEdge(insn, jump);
+                        }
+                    } else if (insnNode instanceof TableSwitchInsnNode) {
+                        TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+                        int jump = insns.indexOf(tsi.dflt);
+                        merge(jump, current, subroutine);
+                        newControlFlowEdge(insn, jump);
+                        for (int j = 0; j < tsi.labels.size(); ++j) {
+                            LabelNode label = tsi.labels.get(j);
+                            jump = insns.indexOf(label);
+                            merge(jump, current, subroutine);
+                            newControlFlowEdge(insn, jump);
+                        }
+                    } else if (insnOpcode == RET) {
+                        if (subroutine == null) {
+                            throw new AnalyzerException(insnNode,
+                                    "RET instruction outside of a sub routine");
+                        }
+                        for (int i = 0; i < subroutine.callers.size(); ++i) {
+                            JumpInsnNode caller = subroutine.callers.get(i);
+                            int call = insns.indexOf(caller);
+                            if (frames[call] != null) {
+                                merge(call + 1, frames[call], current,
+                                        subroutines[call], subroutine.access);
+                                newControlFlowEdge(insn, call + 1);
+                            }
+                        }
+                    } else if (insnOpcode != ATHROW
+                            && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
+                        if (subroutine != null) {
+                            if (insnNode instanceof VarInsnNode) {
+                                int var = ((VarInsnNode) insnNode).var;
+                                subroutine.access[var] = true;
+                                if (insnOpcode == LLOAD || insnOpcode == DLOAD
+                                        || insnOpcode == LSTORE
+                                        || insnOpcode == DSTORE) {
+                                    subroutine.access[var + 1] = true;
+                                }
+                            } else if (insnNode instanceof IincInsnNode) {
+                                int var = ((IincInsnNode) insnNode).var;
+                                subroutine.access[var] = true;
+                            }
+                        }
+                        merge(insn + 1, current, subroutine);
+                        newControlFlowEdge(insn, insn + 1);
+                    }
+                }
+
+                List<TryCatchBlockNode> insnHandlers = handlers[insn];
+                if (insnHandlers != null) {
+                    for (int i = 0; i < insnHandlers.size(); ++i) {
+                        TryCatchBlockNode tcb = insnHandlers.get(i);
+                        Type type;
+                        if (tcb.type == null) {
+                            type = Type.getObjectType("java/lang/Throwable");
+                        } else {
+                            type = Type.getObjectType(tcb.type);
+                        }
+                        int jump = insns.indexOf(tcb.handler);
+                        if (newControlFlowExceptionEdge(insn, tcb)) {
+                            handler.init(f);
+                            handler.clearStack();
+                            handler.push(interpreter.newValue(type));
+                            merge(jump, handler, subroutine);
+                        }
+                    }
+                }
+            } catch (AnalyzerException e) {
+                throw new AnalyzerException(e.node, "Error at instruction "
+                        + insn + ": " + e.getMessage(), e);
+            } catch (Exception e) {
+                throw new AnalyzerException(insnNode, "Error at instruction "
+                        + insn + ": " + e.getMessage(), e);
+            }
+        }
+
+        return frames;
+    }
+
+    private void findSubroutine(int insn, final Subroutine sub,
+            final List<AbstractInsnNode> calls) throws AnalyzerException {
+        while (true) {
+            if (insn < 0 || insn >= n) {
+                throw new AnalyzerException(null,
+                        "Execution can fall off end of the code");
+            }
+            if (subroutines[insn] != null) {
+                return;
+            }
+            subroutines[insn] = sub.copy();
+            AbstractInsnNode node = insns.get(insn);
+
+            // calls findSubroutine recursively on normal successors
+            if (node instanceof JumpInsnNode) {
+                if (node.getOpcode() == JSR) {
+                    // do not follow a JSR, it leads to another subroutine!
+                    calls.add(node);
+                } else {
+                    JumpInsnNode jnode = (JumpInsnNode) node;
+                    findSubroutine(insns.indexOf(jnode.label), sub, calls);
+                }
+            } else if (node instanceof TableSwitchInsnNode) {
+                TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+                findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
+                for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+                    LabelNode l = tsnode.labels.get(i);
+                    findSubroutine(insns.indexOf(l), sub, calls);
+                }
+            } else if (node instanceof LookupSwitchInsnNode) {
+                LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+                findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
+                for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+                    LabelNode l = lsnode.labels.get(i);
+                    findSubroutine(insns.indexOf(l), sub, calls);
+                }
+            }
+
+            // calls findSubroutine recursively on exception handler successors
+            List<TryCatchBlockNode> insnHandlers = handlers[insn];
+            if (insnHandlers != null) {
+                for (int i = 0; i < insnHandlers.size(); ++i) {
+                    TryCatchBlockNode tcb = insnHandlers.get(i);
+                    findSubroutine(insns.indexOf(tcb.handler), sub, calls);
+                }
+            }
+
+            // if insn does not falls through to the next instruction, return.
+            switch (node.getOpcode()) {
+            case GOTO:
+            case RET:
+            case TABLESWITCH:
+            case LOOKUPSWITCH:
+            case IRETURN:
+            case LRETURN:
+            case FRETURN:
+            case DRETURN:
+            case ARETURN:
+            case RETURN:
+            case ATHROW:
+                return;
+            }
+            insn++;
+        }
+    }
+
+    /**
+     * Returns the symbolic stack frame for each instruction of the last
+     * recently analyzed method.
+     * 
+     * @return the symbolic state of the execution stack frame at each bytecode
+     *         instruction of the method. The size of the returned array is
+     *         equal to the number of instructions (and labels) of the method. A
+     *         given frame is <tt>null</tt> if the corresponding instruction
+     *         cannot be reached, or if an error occured during the analysis of
+     *         the method.
+     */
+    public Frame<V>[] getFrames() {
+        return frames;
+    }
+
+    /**
+     * Returns the exception handlers for the given instruction.
+     * 
+     * @param insn
+     *            the index of an instruction of the last recently analyzed
+     *            method.
+     * @return a list of {@link TryCatchBlockNode} objects.
+     */
+    public List<TryCatchBlockNode> getHandlers(final int insn) {
+        return handlers[insn];
+    }
+
+    /**
+     * Initializes this analyzer. This method is called just before the
+     * execution of control flow analysis loop in #analyze. The default
+     * implementation of this method does nothing.
+     * 
+     * @param owner
+     *            the internal name of the class to which the method belongs.
+     * @param m
+     *            the method to be analyzed.
+     * @throws AnalyzerException
+     *             if a problem occurs.
+     */
+    protected void init(String owner, MethodNode m) throws AnalyzerException {
+    }
+
+    /**
+     * 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.
+     * @return the created frame.
+     */
+    protected Frame<V> newFrame(final int nLocals, final int nStack) {
+        return new Frame<V>(nLocals, nStack);
+    }
+
+    /**
+     * Constructs a new frame that is identical to the given frame.
+     * 
+     * @param src
+     *            a frame.
+     * @return the created frame.
+     */
+    protected Frame<V> newFrame(final Frame<? extends V> src) {
+        return new Frame<V>(src);
+    }
+
+    /**
+     * Creates a control flow graph edge. The default implementation of this
+     * method does nothing. It can be overriden in order to construct the
+     * control flow graph of a method (this method is called by the
+     * {@link #analyze analyze} method during its visit of the method's code).
+     * 
+     * @param insn
+     *            an instruction index.
+     * @param successor
+     *            index of a successor instruction.
+     */
+    protected void newControlFlowEdge(final int insn, final int successor) {
+    }
+
+    /**
+     * Creates a control flow graph edge corresponding to an exception handler.
+     * The default implementation of this method does nothing. It can be
+     * overridden in order to construct the control flow graph of a method (this
+     * method is called by the {@link #analyze analyze} method during its visit
+     * of the method's code).
+     * 
+     * @param insn
+     *            an instruction index.
+     * @param successor
+     *            index of a successor instruction.
+     * @return true if this edge must be considered in the data flow analysis
+     *         performed by this analyzer, or false otherwise. The default
+     *         implementation of this method always returns true.
+     */
+    protected boolean newControlFlowExceptionEdge(final int insn,
+            final int successor) {
+        return true;
+    }
+
+    /**
+     * Creates a control flow graph edge corresponding to an exception handler.
+     * The default implementation of this method delegates to
+     * {@link #newControlFlowExceptionEdge(int, int)
+     * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to
+     * construct the control flow graph of a method (this method is called by
+     * the {@link #analyze analyze} method during its visit of the method's
+     * code).
+     * 
+     * @param insn
+     *            an instruction index.
+     * @param tcb
+     *            TryCatchBlockNode corresponding to this edge.
+     * @return true if this edge must be considered in the data flow analysis
+     *         performed by this analyzer, or false otherwise. The default
+     *         implementation of this method delegates to
+     *         {@link #newControlFlowExceptionEdge(int, int)
+     *         newControlFlowExceptionEdge(int, int)}.
+     */
+    protected boolean newControlFlowExceptionEdge(final int insn,
+            final TryCatchBlockNode tcb) {
+        return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+    }
+
+    // -------------------------------------------------------------------------
+
+    private void merge(final int insn, final Frame<V> frame,
+            final Subroutine subroutine) throws AnalyzerException {
+        Frame<V> oldFrame = frames[insn];
+        Subroutine oldSubroutine = subroutines[insn];
+        boolean changes;
+
+        if (oldFrame == null) {
+            frames[insn] = newFrame(frame);
+            changes = true;
+        } else {
+            changes = oldFrame.merge(frame, interpreter);
+        }
+
+        if (oldSubroutine == null) {
+            if (subroutine != null) {
+                subroutines[insn] = subroutine.copy();
+                changes = true;
+            }
+        } else {
+            if (subroutine != null) {
+                changes |= oldSubroutine.merge(subroutine);
+            }
+        }
+        if (changes && !queued[insn]) {
+            queued[insn] = true;
+            queue[top++] = insn;
+        }
+    }
+
+    private void merge(final int insn, final Frame<V> beforeJSR,
+            final Frame<V> afterRET, final Subroutine subroutineBeforeJSR,
+            final boolean[] access) throws AnalyzerException {
+        Frame<V> oldFrame = frames[insn];
+        Subroutine oldSubroutine = subroutines[insn];
+        boolean changes;
+
+        afterRET.merge(beforeJSR, access);
+
+        if (oldFrame == null) {
+            frames[insn] = newFrame(afterRET);
+            changes = true;
+        } else {
+            changes = oldFrame.merge(afterRET, interpreter);
+        }
+
+        if (oldSubroutine != null && subroutineBeforeJSR != null) {
+            changes |= oldSubroutine.merge(subroutineBeforeJSR);
+        }
+        if (changes && !queued[insn]) {
+            queued[insn] = true;
+            queue[top++] = insn;
+        }
+    }
+}

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/AnalyzerException.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/AnalyzerException.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/AnalyzerException.java
new file mode 100644
index 0000000..bf760e7
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/AnalyzerException.java
@@ -0,0 +1,61 @@
+/***
+ * 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 org.apache.tajo.org.objectweb.asm.tree.AbstractInsnNode;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ * 
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+    public final AbstractInsnNode node;
+
+    public AnalyzerException(final AbstractInsnNode node, final String msg) {
+        super(msg);
+        this.node = node;
+    }
+
+    public AnalyzerException(final AbstractInsnNode node, final String msg,
+            final Throwable exception) {
+        super(msg, exception);
+        this.node = node;
+    }
+
+    public AnalyzerException(final AbstractInsnNode node, final String msg,
+            final Object expected, final Value encountered) {
+        super((msg == null ? "Expected " : msg + ": expected ") + expected
+                + ", but found " + encountered);
+        this.node = node;
+    }
+}

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/BasicInterpreter.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicInterpreter.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicInterpreter.java
new file mode 100644
index 0000000..07c5900
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicInterpreter.java
@@ -0,0 +1,358 @@
+/***
+ * 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.IntInsnNode;
+import org.apache.tajo.org.objectweb.asm.tree.LdcInsnNode;
+import org.apache.tajo.org.objectweb.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tajo.org.objectweb.asm.tree.TypeInsnNode;
+import org.apache.tajo.org.objectweb.asm.Handle;
+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.MethodInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter extends Interpreter<BasicValue> implements
+        Opcodes {
+
+    public BasicInterpreter() {
+        super(ASM4);
+    }
+
+    protected BasicInterpreter(final int api) {
+        super(api);
+    }
+
+    @Override
+    public BasicValue newValue(final Type type) {
+        if (type == null) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        switch (type.getSort()) {
+        case Type.VOID:
+            return null;
+        case Type.BOOLEAN:
+        case Type.CHAR:
+        case Type.BYTE:
+        case Type.SHORT:
+        case Type.INT:
+            return BasicValue.INT_VALUE;
+        case Type.FLOAT:
+            return BasicValue.FLOAT_VALUE;
+        case Type.LONG:
+            return BasicValue.LONG_VALUE;
+        case Type.DOUBLE:
+            return BasicValue.DOUBLE_VALUE;
+        case Type.ARRAY:
+        case Type.OBJECT:
+            return BasicValue.REFERENCE_VALUE;
+        default:
+            throw new Error("Internal error");
+        }
+    }
+
+    @Override
+    public BasicValue newOperation(final AbstractInsnNode insn)
+            throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case ACONST_NULL:
+            return newValue(Type.getObjectType("null"));
+        case ICONST_M1:
+        case ICONST_0:
+        case ICONST_1:
+        case ICONST_2:
+        case ICONST_3:
+        case ICONST_4:
+        case ICONST_5:
+            return BasicValue.INT_VALUE;
+        case LCONST_0:
+        case LCONST_1:
+            return BasicValue.LONG_VALUE;
+        case FCONST_0:
+        case FCONST_1:
+        case FCONST_2:
+            return BasicValue.FLOAT_VALUE;
+        case DCONST_0:
+        case DCONST_1:
+            return BasicValue.DOUBLE_VALUE;
+        case BIPUSH:
+        case SIPUSH:
+            return BasicValue.INT_VALUE;
+        case LDC:
+            Object cst = ((LdcInsnNode) insn).cst;
+            if (cst instanceof Integer) {
+                return BasicValue.INT_VALUE;
+            } else if (cst instanceof Float) {
+                return BasicValue.FLOAT_VALUE;
+            } else if (cst instanceof Long) {
+                return BasicValue.LONG_VALUE;
+            } else if (cst instanceof Double) {
+                return BasicValue.DOUBLE_VALUE;
+            } else if (cst instanceof String) {
+                return newValue(Type.getObjectType("java/lang/String"));
+            } else if (cst instanceof Type) {
+                int sort = ((Type) cst).getSort();
+                if (sort == Type.OBJECT || sort == Type.ARRAY) {
+                    return newValue(Type.getObjectType("java/lang/Class"));
+                } else if (sort == Type.METHOD) {
+                    return newValue(Type
+                            .getObjectType("java/lang/invoke/MethodType"));
+                } else {
+                    throw new IllegalArgumentException("Illegal LDC constant "
+                            + cst);
+                }
+            } else if (cst instanceof Handle) {
+                return newValue(Type
+                        .getObjectType("java/lang/invoke/MethodHandle"));
+            } else {
+                throw new IllegalArgumentException("Illegal LDC constant "
+                        + cst);
+            }
+        case JSR:
+            return BasicValue.RETURNADDRESS_VALUE;
+        case GETSTATIC:
+            return newValue(Type.getType(((FieldInsnNode) insn).desc));
+        case NEW:
+            return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue copyOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        return value;
+    }
+
+    @Override
+    public BasicValue unaryOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case INEG:
+        case IINC:
+        case L2I:
+        case F2I:
+        case D2I:
+        case I2B:
+        case I2C:
+        case I2S:
+            return BasicValue.INT_VALUE;
+        case FNEG:
+        case I2F:
+        case L2F:
+        case D2F:
+            return BasicValue.FLOAT_VALUE;
+        case LNEG:
+        case I2L:
+        case F2L:
+        case D2L:
+            return BasicValue.LONG_VALUE;
+        case DNEG:
+        case I2D:
+        case L2D:
+        case F2D:
+            return BasicValue.DOUBLE_VALUE;
+        case IFEQ:
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case TABLESWITCH:
+        case LOOKUPSWITCH:
+        case IRETURN:
+        case LRETURN:
+        case FRETURN:
+        case DRETURN:
+        case ARETURN:
+        case PUTSTATIC:
+            return null;
+        case GETFIELD:
+            return newValue(Type.getType(((FieldInsnNode) insn).desc));
+        case NEWARRAY:
+            switch (((IntInsnNode) insn).operand) {
+            case T_BOOLEAN:
+                return newValue(Type.getType("[Z"));
+            case T_CHAR:
+                return newValue(Type.getType("[C"));
+            case T_BYTE:
+                return newValue(Type.getType("[B"));
+            case T_SHORT:
+                return newValue(Type.getType("[S"));
+            case T_INT:
+                return newValue(Type.getType("[I"));
+            case T_FLOAT:
+                return newValue(Type.getType("[F"));
+            case T_DOUBLE:
+                return newValue(Type.getType("[D"));
+            case T_LONG:
+                return newValue(Type.getType("[J"));
+            default:
+                throw new AnalyzerException(insn, "Invalid array type");
+            }
+        case ANEWARRAY:
+            String desc = ((TypeInsnNode) insn).desc;
+            return newValue(Type.getType("[" + Type.getObjectType(desc)));
+        case ARRAYLENGTH:
+            return BasicValue.INT_VALUE;
+        case ATHROW:
+            return null;
+        case CHECKCAST:
+            desc = ((TypeInsnNode) insn).desc;
+            return newValue(Type.getObjectType(desc));
+        case INSTANCEOF:
+            return BasicValue.INT_VALUE;
+        case MONITORENTER:
+        case MONITOREXIT:
+        case IFNULL:
+        case IFNONNULL:
+            return null;
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue binaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2)
+            throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case IALOAD:
+        case BALOAD:
+        case CALOAD:
+        case SALOAD:
+        case IADD:
+        case ISUB:
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+        case IAND:
+        case IOR:
+        case IXOR:
+            return BasicValue.INT_VALUE;
+        case FALOAD:
+        case FADD:
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+            return BasicValue.FLOAT_VALUE;
+        case LALOAD:
+        case LADD:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+        case LAND:
+        case LOR:
+        case LXOR:
+            return BasicValue.LONG_VALUE;
+        case DALOAD:
+        case DADD:
+        case DSUB:
+        case DMUL:
+        case DDIV:
+        case DREM:
+            return BasicValue.DOUBLE_VALUE;
+        case AALOAD:
+            return BasicValue.REFERENCE_VALUE;
+        case LCMP:
+        case FCMPL:
+        case FCMPG:
+        case DCMPL:
+        case DCMPG:
+            return BasicValue.INT_VALUE;
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+        case PUTFIELD:
+            return null;
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue ternaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2,
+            final BasicValue value3) throws AnalyzerException {
+        return null;
+    }
+
+    @Override
+    public BasicValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends BasicValue> values) throws AnalyzerException {
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+        } else if (opcode == INVOKEDYNAMIC) {
+            return newValue(Type
+                    .getReturnType(((InvokeDynamicInsnNode) insn).desc));
+        } else {
+            return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+        }
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final BasicValue value, final BasicValue expected)
+            throws AnalyzerException {
+    }
+
+    @Override
+    public BasicValue merge(final BasicValue v, final BasicValue w) {
+        if (!v.equals(w)) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        return v;
+    }
+}

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/BasicValue.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicValue.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicValue.java
new file mode 100644
index 0000000..5782563
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicValue.java
@@ -0,0 +1,111 @@
+/***
+ * 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 org.apache.tajo.org.objectweb.asm.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type system.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ * 
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+    public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
+
+    public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+    public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+    public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+    public static final BasicValue DOUBLE_VALUE = new BasicValue(
+            Type.DOUBLE_TYPE);
+
+    public static final BasicValue REFERENCE_VALUE = new BasicValue(
+            Type.getObjectType("java/lang/Object"));
+
+    public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(
+            Type.VOID_TYPE);
+
+    private final Type type;
+
+    public BasicValue(final Type type) {
+        this.type = type;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public int getSize() {
+        return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+    }
+
+    public boolean isReference() {
+        return type != null
+                && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+    }
+
+    @Override
+    public boolean equals(final Object value) {
+        if (value == this) {
+            return true;
+        } else if (value instanceof BasicValue) {
+            if (type == null) {
+                return ((BasicValue) value).type == null;
+            } else {
+                return type.equals(((BasicValue) value).type);
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return type == null ? 0 : type.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        if (this == UNINITIALIZED_VALUE) {
+            return ".";
+        } else if (this == RETURNADDRESS_VALUE) {
+            return "A";
+        } else if (this == REFERENCE_VALUE) {
+            return "R";
+        } else {
+            return type.getDescriptor();
+        }
+    }
+}

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/BasicVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicVerifier.java b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicVerifier.java
new file mode 100644
index 0000000..9ad66c3
--- /dev/null
+++ b/tajo-thirdparty/asm/src/main/java/org/apache/tajo/org/objectweb/asm/tree/analysis/BasicVerifier.java
@@ -0,0 +1,433 @@
+/***
+ * 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;
+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.MethodInsnNode;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+    public BasicVerifier() {
+        super(ASM4);
+    }
+
+    protected BasicVerifier(final int api) {
+        super(api);
+    }
+
+    @Override
+    public BasicValue copyOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        Value expected;
+        switch (insn.getOpcode()) {
+        case ILOAD:
+        case ISTORE:
+            expected = BasicValue.INT_VALUE;
+            break;
+        case FLOAD:
+        case FSTORE:
+            expected = BasicValue.FLOAT_VALUE;
+            break;
+        case LLOAD:
+        case LSTORE:
+            expected = BasicValue.LONG_VALUE;
+            break;
+        case DLOAD:
+        case DSTORE:
+            expected = BasicValue.DOUBLE_VALUE;
+            break;
+        case ALOAD:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return value;
+        case ASTORE:
+            if (!value.isReference()
+                    && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
+                throw new AnalyzerException(insn, null,
+                        "an object reference or a return address", value);
+            }
+            return value;
+        default:
+            return value;
+        }
+        if (!expected.equals(value)) {
+            throw new AnalyzerException(insn, null, expected, value);
+        }
+        return value;
+    }
+
+    @Override
+    public BasicValue unaryOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        BasicValue expected;
+        switch (insn.getOpcode()) {
+        case INEG:
+        case IINC:
+        case I2F:
+        case I2L:
+        case I2D:
+        case I2B:
+        case I2C:
+        case I2S:
+        case IFEQ:
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case TABLESWITCH:
+        case LOOKUPSWITCH:
+        case IRETURN:
+        case NEWARRAY:
+        case ANEWARRAY:
+            expected = BasicValue.INT_VALUE;
+            break;
+        case FNEG:
+        case F2I:
+        case F2L:
+        case F2D:
+        case FRETURN:
+            expected = BasicValue.FLOAT_VALUE;
+            break;
+        case LNEG:
+        case L2I:
+        case L2F:
+        case L2D:
+        case LRETURN:
+            expected = BasicValue.LONG_VALUE;
+            break;
+        case DNEG:
+        case D2I:
+        case D2F:
+        case D2L:
+        case DRETURN:
+            expected = BasicValue.DOUBLE_VALUE;
+            break;
+        case GETFIELD:
+            expected = newValue(Type
+                    .getObjectType(((FieldInsnNode) insn).owner));
+            break;
+        case CHECKCAST:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case ARRAYLENGTH:
+            if (!isArrayValue(value)) {
+                throw new AnalyzerException(insn, null, "an array reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case ARETURN:
+        case ATHROW:
+        case INSTANCEOF:
+        case MONITORENTER:
+        case MONITOREXIT:
+        case IFNULL:
+        case IFNONNULL:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case PUTSTATIC:
+            expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value, expected)) {
+            throw new AnalyzerException(insn, null, expected, value);
+        }
+        return super.unaryOperation(insn, value);
+    }
+
+    @Override
+    public BasicValue binaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2)
+            throws AnalyzerException {
+        BasicValue expected1;
+        BasicValue expected2;
+        switch (insn.getOpcode()) {
+        case IALOAD:
+            expected1 = newValue(Type.getType("[I"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case BALOAD:
+            if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+                expected1 = newValue(Type.getType("[Z"));
+            } else {
+                expected1 = newValue(Type.getType("[B"));
+            }
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case CALOAD:
+            expected1 = newValue(Type.getType("[C"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case SALOAD:
+            expected1 = newValue(Type.getType("[S"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case LALOAD:
+            expected1 = newValue(Type.getType("[J"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case FALOAD:
+            expected1 = newValue(Type.getType("[F"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case DALOAD:
+            expected1 = newValue(Type.getType("[D"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case AALOAD:
+            expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case IADD:
+        case ISUB:
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+        case IAND:
+        case IOR:
+        case IXOR:
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+            expected1 = BasicValue.INT_VALUE;
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case FADD:
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+        case FCMPL:
+        case FCMPG:
+            expected1 = BasicValue.FLOAT_VALUE;
+            expected2 = BasicValue.FLOAT_VALUE;
+            break;
+        case LADD:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LAND:
+        case LOR:
+        case LXOR:
+        case LCMP:
+            expected1 = BasicValue.LONG_VALUE;
+            expected2 = BasicValue.LONG_VALUE;
+            break;
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+            expected1 = BasicValue.LONG_VALUE;
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case DADD:
+        case DSUB:
+        case DMUL:
+        case DDIV:
+        case DREM:
+        case DCMPL:
+        case DCMPG:
+            expected1 = BasicValue.DOUBLE_VALUE;
+            expected2 = BasicValue.DOUBLE_VALUE;
+            break;
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+            expected1 = BasicValue.REFERENCE_VALUE;
+            expected2 = BasicValue.REFERENCE_VALUE;
+            break;
+        case PUTFIELD:
+            FieldInsnNode fin = (FieldInsnNode) insn;
+            expected1 = newValue(Type.getObjectType(fin.owner));
+            expected2 = newValue(Type.getType(fin.desc));
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value1, expected1)) {
+            throw new AnalyzerException(insn, "First argument", expected1,
+                    value1);
+        } else if (!isSubTypeOf(value2, expected2)) {
+            throw new AnalyzerException(insn, "Second argument", expected2,
+                    value2);
+        }
+        if (insn.getOpcode() == AALOAD) {
+            return getElementValue(value1);
+        } else {
+            return super.binaryOperation(insn, value1, value2);
+        }
+    }
+
+    @Override
+    public BasicValue ternaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2,
+            final BasicValue value3) throws AnalyzerException {
+        BasicValue expected1;
+        BasicValue expected3;
+        switch (insn.getOpcode()) {
+        case IASTORE:
+            expected1 = newValue(Type.getType("[I"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case BASTORE:
+            if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+                expected1 = newValue(Type.getType("[Z"));
+            } else {
+                expected1 = newValue(Type.getType("[B"));
+            }
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case CASTORE:
+            expected1 = newValue(Type.getType("[C"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case SASTORE:
+            expected1 = newValue(Type.getType("[S"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case LASTORE:
+            expected1 = newValue(Type.getType("[J"));
+            expected3 = BasicValue.LONG_VALUE;
+            break;
+        case FASTORE:
+            expected1 = newValue(Type.getType("[F"));
+            expected3 = BasicValue.FLOAT_VALUE;
+            break;
+        case DASTORE:
+            expected1 = newValue(Type.getType("[D"));
+            expected3 = BasicValue.DOUBLE_VALUE;
+            break;
+        case AASTORE:
+            expected1 = value1;
+            expected3 = BasicValue.REFERENCE_VALUE;
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value1, expected1)) {
+            throw new AnalyzerException(insn, "First argument", "a "
+                    + expected1 + " array reference", value1);
+        } else if (!BasicValue.INT_VALUE.equals(value2)) {
+            throw new AnalyzerException(insn, "Second argument",
+                    BasicValue.INT_VALUE, value2);
+        } else if (!isSubTypeOf(value3, expected3)) {
+            throw new AnalyzerException(insn, "Third argument", expected3,
+                    value3);
+        }
+        return null;
+    }
+
+    @Override
+    public BasicValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends BasicValue> values) throws AnalyzerException {
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            for (int i = 0; i < values.size(); ++i) {
+                if (!BasicValue.INT_VALUE.equals(values.get(i))) {
+                    throw new AnalyzerException(insn, null,
+                            BasicValue.INT_VALUE, values.get(i));
+                }
+            }
+        } else {
+            int i = 0;
+            int j = 0;
+            if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
+                Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+                if (!isSubTypeOf(values.get(i++), newValue(owner))) {
+                    throw new AnalyzerException(insn, "Method owner",
+                            newValue(owner), values.get(0));
+                }
+            }
+            String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+                    : ((MethodInsnNode) insn).desc;
+            Type[] args = Type.getArgumentTypes(desc);
+            while (i < values.size()) {
+                BasicValue expected = newValue(args[j++]);
+                BasicValue encountered = values.get(i++);
+                if (!isSubTypeOf(encountered, expected)) {
+                    throw new AnalyzerException(insn, "Argument " + j,
+                            expected, encountered);
+                }
+            }
+        }
+        return super.naryOperation(insn, values);
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final BasicValue value, final BasicValue expected)
+            throws AnalyzerException {
+        if (!isSubTypeOf(value, expected)) {
+            throw new AnalyzerException(insn, "Incompatible return type",
+                    expected, value);
+        }
+    }
+
+    protected boolean isArrayValue(final BasicValue value) {
+        return value.isReference();
+    }
+
+    protected BasicValue getElementValue(final BasicValue objectArrayValue)
+            throws AnalyzerException {
+        return BasicValue.REFERENCE_VALUE;
+    }
+
+    protected boolean isSubTypeOf(final BasicValue value,
+            final BasicValue expected) {
+        return value.equals(expected);
+    }
+}


Mime
View raw message