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.objectweb.asm.tree.analysis;
030:
031: import java.util.HashSet;
032: import java.util.List;
033: import java.util.Set;
034:
035: import org.objectweb.asm.Opcodes;
036: import org.objectweb.asm.Type;
037: import org.objectweb.asm.tree.AbstractInsnNode;
038: import org.objectweb.asm.tree.FieldInsnNode;
039: import org.objectweb.asm.tree.LdcInsnNode;
040: import org.objectweb.asm.tree.MethodInsnNode;
041:
042: /**
043: * An {@link Interpreter} for {@link SourceValue} values.
044: *
045: * @author Eric Bruneton
046: */
047: @SuppressWarnings("unchecked")
048: public class SourceInterpreter implements Opcodes, Interpreter {
049:
050: public Value newValue(final Type type) {
051: return new SourceValue(type == null ? 1 : type.getSize());
052: }
053:
054: public Value newOperation(final AbstractInsnNode insn) {
055: int size;
056: switch (insn.getOpcode()) {
057: case LCONST_0:
058: case LCONST_1:
059: case DCONST_0:
060: case DCONST_1:
061: size = 2;
062: break;
063: case LDC:
064: Object cst = ((LdcInsnNode) insn).cst;
065: size = cst instanceof Long || cst instanceof Double ? 2 : 1;
066: break;
067: case GETSTATIC:
068: size = Type.getType(((FieldInsnNode) insn).desc).getSize();
069: break;
070: default:
071: size = 1;
072: }
073: return new SourceValue(size, insn);
074: }
075:
076: public Value copyOperation(final AbstractInsnNode insn,
077: final Value value) {
078: return new SourceValue(value.getSize(), insn);
079: }
080:
081: public Value unaryOperation(final AbstractInsnNode insn,
082: final Value value) {
083: int size;
084: switch (insn.getOpcode()) {
085: case LNEG:
086: case DNEG:
087: case I2L:
088: case I2D:
089: case L2D:
090: case F2L:
091: case F2D:
092: case D2L:
093: size = 2;
094: break;
095: case GETFIELD:
096: size = Type.getType(((FieldInsnNode) insn).desc).getSize();
097: break;
098: default:
099: size = 1;
100: }
101: return new SourceValue(size, insn);
102: }
103:
104: public Value binaryOperation(final AbstractInsnNode insn,
105: final Value value1, final Value value2) {
106: int size;
107: switch (insn.getOpcode()) {
108: case LALOAD:
109: case DALOAD:
110: case LADD:
111: case DADD:
112: case LSUB:
113: case DSUB:
114: case LMUL:
115: case DMUL:
116: case LDIV:
117: case DDIV:
118: case LREM:
119: case DREM:
120: case LSHL:
121: case LSHR:
122: case LUSHR:
123: case LAND:
124: case LOR:
125: case LXOR:
126: size = 2;
127: break;
128: default:
129: size = 1;
130: }
131: return new SourceValue(size, insn);
132: }
133:
134: public Value ternaryOperation(final AbstractInsnNode insn,
135: final Value value1, final Value value2, final Value value3) {
136: return new SourceValue(1, insn);
137: }
138:
139: public Value naryOperation(final AbstractInsnNode insn,
140: final List values) {
141: int size;
142: if (insn.getOpcode() == MULTIANEWARRAY) {
143: size = 1;
144: } else {
145: size = Type.getReturnType(((MethodInsnNode) insn).desc)
146: .getSize();
147: }
148: return new SourceValue(size, insn);
149: }
150:
151: public Value merge(final Value v, final Value w) {
152: SourceValue dv = (SourceValue) v;
153: SourceValue dw = (SourceValue) w;
154: if (dv.insns instanceof SmallSet
155: && dw.insns instanceof SmallSet) {
156: Set s = ((SmallSet) dv.insns).union((SmallSet) dw.insns);
157: if (s == dv.insns && dv.size == dw.size) {
158: return v;
159: } else {
160: return new SourceValue(Math.min(dv.size, dw.size), s);
161: }
162: }
163: if (dv.size != dw.size || !dv.insns.containsAll(dw.insns)) {
164: Set s = new HashSet();
165: s.addAll(dv.insns);
166: s.addAll(dw.insns);
167: return new SourceValue(Math.min(dv.size, dw.size), s);
168: }
169: return v;
170: }
171: }
|