001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 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 */ 030package io.ebean.enhance.asm.tree.analysis; 031 032import io.ebean.enhance.asm.Opcodes; 033import io.ebean.enhance.asm.Type; 034import io.ebean.enhance.asm.tree.AbstractInsnNode; 035import io.ebean.enhance.asm.tree.FieldInsnNode; 036import io.ebean.enhance.asm.tree.InvokeDynamicInsnNode; 037import io.ebean.enhance.asm.tree.LdcInsnNode; 038import io.ebean.enhance.asm.tree.MethodInsnNode; 039 040import java.util.HashSet; 041import java.util.List; 042import java.util.Set; 043 044/** 045 * An {@link Interpreter} for {@link SourceValue} values. 046 * 047 * @author Eric Bruneton 048 */ 049public class SourceInterpreter extends Interpreter<SourceValue> implements 050 Opcodes { 051 052 public SourceInterpreter() { 053 super(ASM6); 054 } 055 056 protected SourceInterpreter(final int api) { 057 super(api); 058 } 059 060 @Override 061 public SourceValue newValue(final Type type) { 062 if (type == Type.VOID_TYPE) { 063 return null; 064 } 065 return new SourceValue(type == null ? 1 : type.getSize()); 066 } 067 068 @Override 069 public SourceValue newOperation(final AbstractInsnNode insn) { 070 int size; 071 switch (insn.getOpcode()) { 072 case LCONST_0: 073 case LCONST_1: 074 case DCONST_0: 075 case DCONST_1: 076 size = 2; 077 break; 078 case LDC: 079 Object cst = ((LdcInsnNode) insn).cst; 080 size = cst instanceof Long || cst instanceof Double ? 2 : 1; 081 break; 082 case GETSTATIC: 083 size = Type.getType(((FieldInsnNode) insn).desc).getSize(); 084 break; 085 default: 086 size = 1; 087 } 088 return new SourceValue(size, insn); 089 } 090 091 @Override 092 public SourceValue copyOperation(final AbstractInsnNode insn, 093 final SourceValue value) { 094 return new SourceValue(value.getSize(), insn); 095 } 096 097 @Override 098 public SourceValue unaryOperation(final AbstractInsnNode insn, 099 final SourceValue value) { 100 int size; 101 switch (insn.getOpcode()) { 102 case LNEG: 103 case DNEG: 104 case I2L: 105 case I2D: 106 case L2D: 107 case F2L: 108 case F2D: 109 case D2L: 110 size = 2; 111 break; 112 case GETFIELD: 113 size = Type.getType(((FieldInsnNode) insn).desc).getSize(); 114 break; 115 default: 116 size = 1; 117 } 118 return new SourceValue(size, insn); 119 } 120 121 @Override 122 public SourceValue binaryOperation(final AbstractInsnNode insn, 123 final SourceValue value1, final SourceValue value2) { 124 int size; 125 switch (insn.getOpcode()) { 126 case LALOAD: 127 case DALOAD: 128 case LADD: 129 case DADD: 130 case LSUB: 131 case DSUB: 132 case LMUL: 133 case DMUL: 134 case LDIV: 135 case DDIV: 136 case LREM: 137 case DREM: 138 case LSHL: 139 case LSHR: 140 case LUSHR: 141 case LAND: 142 case LOR: 143 case LXOR: 144 size = 2; 145 break; 146 default: 147 size = 1; 148 } 149 return new SourceValue(size, insn); 150 } 151 152 @Override 153 public SourceValue ternaryOperation(final AbstractInsnNode insn, 154 final SourceValue value1, final SourceValue value2, 155 final SourceValue value3) { 156 return new SourceValue(1, insn); 157 } 158 159 @Override 160 public SourceValue naryOperation(final AbstractInsnNode insn, 161 final List<? extends SourceValue> values) { 162 int size; 163 int opcode = insn.getOpcode(); 164 if (opcode == MULTIANEWARRAY) { 165 size = 1; 166 } else { 167 String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc 168 : ((MethodInsnNode) insn).desc; 169 size = Type.getReturnType(desc).getSize(); 170 } 171 return new SourceValue(size, insn); 172 } 173 174 @Override 175 public void returnOperation(final AbstractInsnNode insn, 176 final SourceValue value, final SourceValue expected) { 177 } 178 179 @Override 180 public SourceValue merge(final SourceValue d, final SourceValue w) { 181 if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) { 182 Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns) 183 .union((SmallSet<AbstractInsnNode>) w.insns); 184 if (s == d.insns && d.size == w.size) { 185 return d; 186 } else { 187 return new SourceValue(Math.min(d.size, w.size), s); 188 } 189 } 190 if (d.size != w.size || !d.insns.containsAll(w.insns)) { 191 HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>(); 192 s.addAll(d.insns); 193 s.addAll(w.insns); 194 return new SourceValue(Math.min(d.size, w.size), s); 195 } 196 return d; 197 } 198}