1/*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2007 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30package org.mockito.asm.tree.analysis; 31 32import java.util.HashSet; 33import java.util.List; 34import java.util.Set; 35 36import org.mockito.asm.Opcodes; 37import org.mockito.asm.Type; 38import org.mockito.asm.tree.AbstractInsnNode; 39import org.mockito.asm.tree.FieldInsnNode; 40import org.mockito.asm.tree.LdcInsnNode; 41import org.mockito.asm.tree.MethodInsnNode; 42 43/** 44 * An {@link Interpreter} for {@link SourceValue} values. 45 * 46 * @author Eric Bruneton 47 */ 48public class SourceInterpreter implements Opcodes, Interpreter { 49 50 public Value newValue(final Type type) { 51 return new SourceValue(type == null ? 1 : type.getSize()); 52 } 53 54 public Value newOperation(final AbstractInsnNode insn) { 55 int size; 56 switch (insn.getOpcode()) { 57 case LCONST_0: 58 case LCONST_1: 59 case DCONST_0: 60 case DCONST_1: 61 size = 2; 62 break; 63 case LDC: 64 Object cst = ((LdcInsnNode) insn).cst; 65 size = cst instanceof Long || cst instanceof Double ? 2 : 1; 66 break; 67 case GETSTATIC: 68 size = Type.getType(((FieldInsnNode) insn).desc).getSize(); 69 break; 70 default: 71 size = 1; 72 } 73 return new SourceValue(size, insn); 74 } 75 76 public Value copyOperation(final AbstractInsnNode insn, final Value value) { 77 return new SourceValue(value.getSize(), insn); 78 } 79 80 public Value unaryOperation(final AbstractInsnNode insn, final Value value) 81 { 82 int size; 83 switch (insn.getOpcode()) { 84 case LNEG: 85 case DNEG: 86 case I2L: 87 case I2D: 88 case L2D: 89 case F2L: 90 case F2D: 91 case D2L: 92 size = 2; 93 break; 94 case GETFIELD: 95 size = Type.getType(((FieldInsnNode) insn).desc).getSize(); 96 break; 97 default: 98 size = 1; 99 } 100 return new SourceValue(size, insn); 101 } 102 103 public Value binaryOperation( 104 final AbstractInsnNode insn, 105 final Value value1, 106 final Value value2) 107 { 108 int size; 109 switch (insn.getOpcode()) { 110 case LALOAD: 111 case DALOAD: 112 case LADD: 113 case DADD: 114 case LSUB: 115 case DSUB: 116 case LMUL: 117 case DMUL: 118 case LDIV: 119 case DDIV: 120 case LREM: 121 case DREM: 122 case LSHL: 123 case LSHR: 124 case LUSHR: 125 case LAND: 126 case LOR: 127 case LXOR: 128 size = 2; 129 break; 130 default: 131 size = 1; 132 } 133 return new SourceValue(size, insn); 134 } 135 136 public Value ternaryOperation( 137 final AbstractInsnNode insn, 138 final Value value1, 139 final Value value2, 140 final Value value3) 141 { 142 return new SourceValue(1, insn); 143 } 144 145 public Value naryOperation(final AbstractInsnNode insn, final List values) { 146 int size; 147 if (insn.getOpcode() == MULTIANEWARRAY) { 148 size = 1; 149 } else { 150 size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize(); 151 } 152 return new SourceValue(size, insn); 153 } 154 155 public Value merge(final Value v, final Value w) { 156 SourceValue dv = (SourceValue) v; 157 SourceValue dw = (SourceValue) w; 158 if (dv.insns instanceof SmallSet && dw.insns instanceof SmallSet) { 159 Set s = ((SmallSet) dv.insns).union((SmallSet) dw.insns); 160 if (s == dv.insns && dv.size == dw.size) { 161 return v; 162 } else { 163 return new SourceValue(Math.min(dv.size, dw.size), s); 164 } 165 } 166 if (dv.size != dw.size || !dv.insns.containsAll(dw.insns)) { 167 Set s = new HashSet(); 168 s.addAll(dv.insns); 169 s.addAll(dw.insns); 170 return new SourceValue(Math.min(dv.size, dw.size), s); 171 } 172 return v; 173 } 174} 175