001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package org.ejb3unit.asm.tree.analysis;
030:
031: import java.util.HashSet;
032: import java.util.List;
033: import java.util.Set;
034:
035: import org.ejb3unit.asm.Opcodes;
036: import org.ejb3unit.asm.Type;
037: import org.ejb3unit.asm.tree.AbstractInsnNode;
038: import org.ejb3unit.asm.tree.FieldInsnNode;
039: import org.ejb3unit.asm.tree.LdcInsnNode;
040: import org.ejb3unit.asm.tree.MethodInsnNode;
041:
042: /**
043: * An {@link Interpreter} for {@link SourceValue} values.
044: *
045: * @author Eric Bruneton
046: */
047: public class SourceInterpreter implements Opcodes, Interpreter {
048:
049: public Value newValue(final Type type) {
050: return new SourceValue(type == null ? 1 : type.getSize());
051: }
052:
053: public Value newOperation(final AbstractInsnNode insn) {
054: int size;
055: switch (insn.getOpcode()) {
056: case LCONST_0:
057: case LCONST_1:
058: case DCONST_0:
059: case DCONST_1:
060: size = 2;
061: break;
062: case LDC:
063: Object cst = ((LdcInsnNode) insn).cst;
064: size = cst instanceof Long || cst instanceof Double ? 2 : 1;
065: break;
066: case GETSTATIC:
067: size = Type.getType(((FieldInsnNode) insn).desc).getSize();
068: break;
069: default:
070: size = 1;
071: }
072: return new SourceValue(size, insn);
073: }
074:
075: public Value copyOperation(final AbstractInsnNode insn,
076: final Value value) {
077: return new SourceValue(value.getSize(), insn);
078: }
079:
080: public Value unaryOperation(final AbstractInsnNode insn,
081: final Value value) {
082: int size;
083: switch (insn.getOpcode()) {
084: case LNEG:
085: case DNEG:
086: case I2L:
087: case I2D:
088: case L2D:
089: case F2L:
090: case F2D:
091: case D2L:
092: size = 2;
093: break;
094: case GETFIELD:
095: size = Type.getType(((FieldInsnNode) insn).desc).getSize();
096: break;
097: default:
098: size = 1;
099: }
100: return new SourceValue(size, insn);
101: }
102:
103: public Value binaryOperation(final AbstractInsnNode insn,
104: final Value value1, final Value value2) {
105: int size;
106: switch (insn.getOpcode()) {
107: case LALOAD:
108: case DALOAD:
109: case LADD:
110: case DADD:
111: case LSUB:
112: case DSUB:
113: case LMUL:
114: case DMUL:
115: case LDIV:
116: case DDIV:
117: case LREM:
118: case DREM:
119: case LSHL:
120: case LSHR:
121: case LUSHR:
122: case LAND:
123: case LOR:
124: case LXOR:
125: size = 2;
126: break;
127: default:
128: size = 1;
129: }
130: return new SourceValue(size, insn);
131: }
132:
133: public Value ternaryOperation(final AbstractInsnNode insn,
134: final Value value1, final Value value2, final Value value3) {
135: return new SourceValue(1, insn);
136: }
137:
138: public Value naryOperation(final AbstractInsnNode insn,
139: final List values) {
140: int size;
141: if (insn.getOpcode() == MULTIANEWARRAY) {
142: size = 1;
143: } else {
144: size = Type.getReturnType(((MethodInsnNode) insn).desc)
145: .getSize();
146: }
147: return new SourceValue(size, insn);
148: }
149:
150: public Value merge(final Value v, final Value w) {
151: SourceValue dv = (SourceValue) v;
152: SourceValue dw = (SourceValue) w;
153: if (dv.insns instanceof SmallSet
154: && dw.insns instanceof SmallSet) {
155: Set s = ((SmallSet) dv.insns).union((SmallSet) dw.insns);
156: if (s == dv.insns && dv.size == dw.size) {
157: return v;
158: } else {
159: return new SourceValue(Math.min(dv.size, dw.size), s);
160: }
161: }
162: if (dv.size != dw.size || !dv.insns.containsAll(dw.insns)) {
163: Set s = new HashSet();
164: s.addAll(dv.insns);
165: s.addAll(dw.insns);
166: return new SourceValue(Math.min(dv.size, dw.size), s);
167: }
168: return v;
169: }
170: }
|