1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/*** 2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ASM: a very small and fast Java bytecode manipulation framework 3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright (c) 2000-2007 INRIA, France Telecom 4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * All rights reserved. 5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Redistribution and use in source and binary forms, with or without 7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * modification, are permitted provided that the following conditions 8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are met: 9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1. Redistributions of source code must retain the above copyright 10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * notice, this list of conditions and the following disclaimer. 11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2. Redistributions in binary form must reproduce the above copyright 12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * notice, this list of conditions and the following disclaimer in the 13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * documentation and/or other materials provided with the distribution. 14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 3. Neither the name of the copyright holders nor the names of its 15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * contributors may be used to endorse or promote products derived from 16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * this software without specific prior written permission. 17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THE POSSIBILITY OF SUCH DAMAGE. 29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.asm.tree.analysis; 31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.ArrayList; 33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.HashMap; 34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.List; 35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.Map; 36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Opcodes; 38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Type; 39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.AbstractInsnNode; 40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.IincInsnNode; 41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.InsnList; 42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.JumpInsnNode; 43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.LabelNode; 44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.LookupSwitchInsnNode; 45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.MethodNode; 46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.TableSwitchInsnNode; 47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.TryCatchBlockNode; 48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.tree.VarInsnNode; 49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/** 51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * A semantic bytecode analyzer. <i>This class does not fully check that JSR and 52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * RET instructions are valid.</i> 53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eric Bruneton 55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class Analyzer implements Opcodes { 57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private final Interpreter interpreter; 59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int n; 61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private InsnList insns; 63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private List[] handlers; 65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Frame[] frames; 67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Subroutine[] subroutines; 69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private boolean[] queued; 71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int[] queue; 73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int top; 75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Constructs a new {@link Analyzer}. 78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param interpreter the interpreter to be used to symbolically interpret 80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the bytecode instructions. 81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Analyzer(final Interpreter interpreter) { 83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.interpreter = interpreter; 84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Analyzes the given method. 88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param owner the internal name of the class to which the method belongs. 90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param m the method to be analyzed. 91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the symbolic state of the execution stack frame at each bytecode 92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction of the method. The size of the returned array is 93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * equal to the number of instructions (and labels) of the method. A 94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * given frame is <tt>null</tt> if and only if the corresponding 95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction cannot be reached (dead code). 96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @throws AnalyzerException if a problem occurs during the analysis. 97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Frame[] analyze(final String owner, final MethodNode m) 99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throws AnalyzerException 100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) { 102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frames = new Frame[0]; 103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return frames; 104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n = m.instructions.size(); 106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insns = m.instructions; 107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen handlers = new List[n]; 108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frames = new Frame[n]; 109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutines = new Subroutine[n]; 110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen queued = new boolean[n]; 111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen queue = new int[n]; 112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen top = 0; 113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes exception handlers for each instruction 115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < m.tryCatchBlocks.size(); ++i) { 116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TryCatchBlockNode tcb = (TryCatchBlockNode) m.tryCatchBlocks.get(i); 117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int begin = insns.indexOf(tcb.start); 118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int end = insns.indexOf(tcb.end); 119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int j = begin; j < end; ++j) { 120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List insnHandlers = handlers[j]; 121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnHandlers == null) { 122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insnHandlers = new ArrayList(); 123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen handlers[j] = insnHandlers; 124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insnHandlers.add(tcb); 126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes the subroutine for each instruction: 130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Subroutine main = new Subroutine(null, m.maxLocals, null); 131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List subroutineCalls = new ArrayList(); 132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Map subroutineHeads = new HashMap(); 133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(0, main, subroutineCalls); 134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (!subroutineCalls.isEmpty()) { 135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0); 136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Subroutine sub = (Subroutine) subroutineHeads.get(jsr.label); 137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (sub == null) { 138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen sub = new Subroutine(jsr.label, m.maxLocals, jsr); 139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutineHeads.put(jsr.label, sub); 140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls); 141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen sub.callers.add(jsr); 143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < n; ++i) { 146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (subroutines[i] != null && subroutines[i].start == null) { 147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutines[i] = null; 148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // initializes the data structures for the control flow analysis 152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame current = newFrame(m.maxLocals, m.maxStack); 153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame handler = newFrame(m.maxLocals, m.maxStack); 154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] args = Type.getArgumentTypes(m.desc); 155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int local = 0; 156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((m.access & ACC_STATIC) == 0) { 157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type ctype = Type.getObjectType(owner); 158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen current.setLocal(local++, interpreter.newValue(ctype)); 159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < args.length; ++i) { 161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen current.setLocal(local++, interpreter.newValue(args[i])); 162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (args[i].getSize() == 2) { 163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen current.setLocal(local++, interpreter.newValue(null)); 164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (local < m.maxLocals) { 167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen current.setLocal(local++, interpreter.newValue(null)); 168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(0, current, null); 170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // control flow analysis 172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (top > 0) { 173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int insn = queue[--top]; 174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame f = frames[insn]; 175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Subroutine subroutine = subroutines[insn]; 176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen queued[insn] = false; 177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen AbstractInsnNode insnNode = m.instructions.get(insn); 180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int insnOpcode = insnNode.getOpcode(); 181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int insnType = insnNode.getType(); 182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnType == AbstractInsnNode.LABEL 184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || insnType == AbstractInsnNode.LINE 185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || insnType == AbstractInsnNode.FRAME) 186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(insn + 1, f, subroutine); 188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, insn + 1); 189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen current.init(f).execute(insnNode, interpreter); 191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutine = subroutine == null ? null : subroutine.copy(); 192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnNode instanceof JumpInsnNode) { 194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen JumpInsnNode j = (JumpInsnNode) insnNode; 195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnOpcode != GOTO && insnOpcode != JSR) { 196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(insn + 1, current, subroutine); 197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, insn + 1); 198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int jump = insns.indexOf(j.label); 200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnOpcode == JSR) { 201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(jump, current, new Subroutine(j.label, 202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen m.maxLocals, 203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen j)); 204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(jump, current, subroutine); 206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, jump); 208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (insnNode instanceof LookupSwitchInsnNode) { 209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode; 210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int jump = insns.indexOf(lsi.dflt); 211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(jump, current, subroutine); 212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, jump); 213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int j = 0; j < lsi.labels.size(); ++j) { 214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen LabelNode label = (LabelNode) lsi.labels.get(j); 215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen jump = insns.indexOf(label); 216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(jump, current, subroutine); 217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, jump); 218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (insnNode instanceof TableSwitchInsnNode) { 220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode; 221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int jump = insns.indexOf(tsi.dflt); 222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(jump, current, subroutine); 223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, jump); 224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int j = 0; j < tsi.labels.size(); ++j) { 225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen LabelNode label = (LabelNode) tsi.labels.get(j); 226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen jump = insns.indexOf(label); 227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(jump, current, subroutine); 228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, jump); 229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (insnOpcode == RET) { 231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (subroutine == null) { 232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new AnalyzerException("RET instruction outside of a sub routine"); 233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < subroutine.callers.size(); ++i) { 235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Object caller = subroutine.callers.get(i); 236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int call = insns.indexOf((AbstractInsnNode) caller); 237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (frames[call] != null) { 238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(call + 1, 239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frames[call], 240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen current, 241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutines[call], 242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutine.access); 243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, call + 1); 244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (insnOpcode != ATHROW 247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen && (insnOpcode < IRETURN || insnOpcode > RETURN)) 248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (subroutine != null) { 250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnNode instanceof VarInsnNode) { 251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int var = ((VarInsnNode) insnNode).var; 252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutine.access[var] = true; 253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnOpcode == LLOAD || insnOpcode == DLOAD 254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || insnOpcode == LSTORE 255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || insnOpcode == DSTORE) 256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutine.access[var + 1] = true; 258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (insnNode instanceof IincInsnNode) { 260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int var = ((IincInsnNode) insnNode).var; 261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutine.access[var] = true; 262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(insn + 1, current, subroutine); 265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newControlFlowEdge(insn, insn + 1); 266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List insnHandlers = handlers[insn]; 270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnHandlers != null) { 271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < insnHandlers.size(); ++i) { 272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i); 273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type type; 274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (tcb.type == null) { 275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type = Type.getObjectType("java/lang/Throwable"); 276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type = Type.getObjectType(tcb.type); 278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int jump = insns.indexOf(tcb.handler); 280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (newControlFlowExceptionEdge(insn, jump)) { 281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen handler.init(f); 282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen handler.clearStack(); 283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen handler.push(interpreter.newValue(type)); 284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen merge(jump, handler, subroutine); 285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (AnalyzerException e) { 289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new AnalyzerException("Error at instruction " + insn 290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen + ": " + e.getMessage(), e); 291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Exception e) { 292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new AnalyzerException("Error at instruction " + insn 293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen + ": " + e.getMessage(), e); 294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return frames; 298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void findSubroutine(int insn, final Subroutine sub, final List calls) 301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throws AnalyzerException 302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (true) { 304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insn < 0 || insn >= n) { 305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new AnalyzerException("Execution can fall off end of the code"); 306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (subroutines[insn] != null) { 308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutines[insn] = sub.copy(); 311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen AbstractInsnNode node = insns.get(insn); 312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // calls findSubroutine recursively on normal successors 314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (node instanceof JumpInsnNode) { 315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (node.getOpcode() == JSR) { 316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // do not follow a JSR, it leads to another subroutine! 317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen calls.add(node); 318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen JumpInsnNode jnode = (JumpInsnNode) node; 320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(insns.indexOf(jnode.label), sub, calls); 321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (node instanceof TableSwitchInsnNode) { 323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node; 324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(insns.indexOf(tsnode.dflt), sub, calls); 325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = tsnode.labels.size() - 1; i >= 0; --i) { 326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen LabelNode l = (LabelNode) tsnode.labels.get(i); 327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(insns.indexOf(l), sub, calls); 328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (node instanceof LookupSwitchInsnNode) { 330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node; 331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(insns.indexOf(lsnode.dflt), sub, calls); 332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = lsnode.labels.size() - 1; i >= 0; --i) { 333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen LabelNode l = (LabelNode) lsnode.labels.get(i); 334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(insns.indexOf(l), sub, calls); 335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // calls findSubroutine recursively on exception handler successors 339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List insnHandlers = handlers[insn]; 340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insnHandlers != null) { 341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < insnHandlers.size(); ++i) { 342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i); 343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen findSubroutine(insns.indexOf(tcb.handler), sub, calls); 344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if insn does not falls through to the next instruction, return. 348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (node.getOpcode()) { 349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case GOTO: 350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case RET: 351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case TABLESWITCH: 352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case LOOKUPSWITCH: 353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case IRETURN: 354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case LRETURN: 355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case FRETURN: 356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case DRETURN: 357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ARETURN: 358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case RETURN: 359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ATHROW: 360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insn++; 363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns the symbolic stack frame for each instruction of the last 368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * recently analyzed method. 369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the symbolic state of the execution stack frame at each bytecode 371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction of the method. The size of the returned array is 372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * equal to the number of instructions (and labels) of the method. A 373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * given frame is <tt>null</tt> if the corresponding instruction 374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * cannot be reached, or if an error occured during the analysis of 375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the method. 376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Frame[] getFrames() { 378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return frames; 379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns the exception handlers for the given instruction. 383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param insn the index of an instruction of the last recently analyzed 385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method. 386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return a list of {@link TryCatchBlockNode} objects. 387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public List getHandlers(final int insn) { 389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return handlers[insn]; 390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Constructs a new frame with the given size. 394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param nLocals the maximum number of local variables of the frame. 396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param nStack the maximum stack size of the frame. 397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the created frame. 398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected Frame newFrame(final int nLocals, final int nStack) { 400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new Frame(nLocals, nStack); 401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Constructs a new frame that is identical to the given frame. 405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param src a frame. 407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the created frame. 408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected Frame newFrame(final Frame src) { 410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new Frame(src); 411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Creates a control flow graph edge. The default implementation of this 415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method does nothing. It can be overriden in order to construct the 416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * control flow graph of a method (this method is called by the 417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link #analyze analyze} method during its visit of the method's code). 418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param insn an instruction index. 420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param successor index of a successor instruction. 421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected void newControlFlowEdge(final int insn, final int successor) { 423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Creates a control flow graph edge corresponding to an exception handler. 427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The default implementation of this method does nothing. It can be 428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * overriden in order to construct the control flow graph of a method (this 429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method is called by the {@link #analyze analyze} method during its visit 430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of the method's code). 431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param insn an instruction index. 433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param successor index of a successor instruction. 434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return true if this edge must be considered in the data flow analysis 435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * performed by this analyzer, or false otherwise. The default 436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * implementation of this method always returns true. 437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected boolean newControlFlowExceptionEdge( 439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int insn, 440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int successor) 441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return true; 443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------- 446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void merge( 448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int insn, 449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Frame frame, 450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Subroutine subroutine) throws AnalyzerException 451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame oldFrame = frames[insn]; 453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Subroutine oldSubroutine = subroutines[insn]; 454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean changes; 455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (oldFrame == null) { 457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frames[insn] = newFrame(frame); 458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changes = true; 459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changes = oldFrame.merge(frame, interpreter); 461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (oldSubroutine == null) { 464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (subroutine != null) { 465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutines[insn] = subroutine.copy(); 466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changes = true; 467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (subroutine != null) { 470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changes |= oldSubroutine.merge(subroutine); 471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (changes && !queued[insn]) { 474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen queued[insn] = true; 475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen queue[top++] = insn; 476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void merge( 480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int insn, 481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Frame beforeJSR, 482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Frame afterRET, 483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Subroutine subroutineBeforeJSR, 484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final boolean[] access) throws AnalyzerException 485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame oldFrame = frames[insn]; 487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Subroutine oldSubroutine = subroutines[insn]; 488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean changes; 489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen afterRET.merge(beforeJSR, access); 491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (oldFrame == null) { 493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frames[insn] = newFrame(afterRET); 494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changes = true; 495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changes = oldFrame.merge(afterRET, access); 497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (oldSubroutine != null && subroutineBeforeJSR != null) { 500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changes |= oldSubroutine.merge(subroutineBeforeJSR); 501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (changes && !queued[insn]) { 503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen queued[insn] = true; 504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen queue[top++] = insn; 505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen} 508