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