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.commons; 031 032import io.ebean.enhance.asm.Handle; 033import io.ebean.enhance.asm.Label; 034import io.ebean.enhance.asm.MethodVisitor; 035import io.ebean.enhance.asm.Opcodes; 036 037/** 038 * A {@link MethodVisitor} that can be used to approximate method size. 039 * 040 * @author Eugene Kuleshov 041 */ 042public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { 043 044 private int minSize; 045 046 private int maxSize; 047 048 public CodeSizeEvaluator(final MethodVisitor mv) { 049 this(Opcodes.ASM6, mv); 050 } 051 052 protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { 053 super(api, mv); 054 } 055 056 public int getMinSize() { 057 return this.minSize; 058 } 059 060 public int getMaxSize() { 061 return this.maxSize; 062 } 063 064 @Override 065 public void visitInsn(final int opcode) { 066 minSize += 1; 067 maxSize += 1; 068 if (mv != null) { 069 mv.visitInsn(opcode); 070 } 071 } 072 073 @Override 074 public void visitIntInsn(final int opcode, final int operand) { 075 if (opcode == SIPUSH) { 076 minSize += 3; 077 maxSize += 3; 078 } else { 079 minSize += 2; 080 maxSize += 2; 081 } 082 if (mv != null) { 083 mv.visitIntInsn(opcode, operand); 084 } 085 } 086 087 @Override 088 public void visitVarInsn(final int opcode, final int var) { 089 if (var < 4 && opcode != RET) { 090 minSize += 1; 091 maxSize += 1; 092 } else if (var >= 256) { 093 minSize += 4; 094 maxSize += 4; 095 } else { 096 minSize += 2; 097 maxSize += 2; 098 } 099 if (mv != null) { 100 mv.visitVarInsn(opcode, var); 101 } 102 } 103 104 @Override 105 public void visitTypeInsn(final int opcode, final String type) { 106 minSize += 3; 107 maxSize += 3; 108 if (mv != null) { 109 mv.visitTypeInsn(opcode, type); 110 } 111 } 112 113 @Override 114 public void visitFieldInsn(final int opcode, final String owner, 115 final String name, final String desc) { 116 minSize += 3; 117 maxSize += 3; 118 if (mv != null) { 119 mv.visitFieldInsn(opcode, owner, name, desc); 120 } 121 } 122 123 @Deprecated 124 @Override 125 public void visitMethodInsn(final int opcode, final String owner, 126 final String name, final String desc) { 127 if (api >= Opcodes.ASM5) { 128 super.visitMethodInsn(opcode, owner, name, desc); 129 return; 130 } 131 doVisitMethodInsn(opcode, owner, name, desc, 132 opcode == Opcodes.INVOKEINTERFACE); 133 } 134 135 @Override 136 public void visitMethodInsn(final int opcode, final String owner, 137 final String name, final String desc, final boolean itf) { 138 if (api < Opcodes.ASM5) { 139 super.visitMethodInsn(opcode, owner, name, desc, itf); 140 return; 141 } 142 doVisitMethodInsn(opcode, owner, name, desc, itf); 143 } 144 145 private void doVisitMethodInsn(int opcode, final String owner, 146 final String name, final String desc, final boolean itf) { 147 if (opcode == INVOKEINTERFACE) { 148 minSize += 5; 149 maxSize += 5; 150 } else { 151 minSize += 3; 152 maxSize += 3; 153 } 154 if (mv != null) { 155 mv.visitMethodInsn(opcode, owner, name, desc, itf); 156 } 157 } 158 159 @Override 160 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, 161 Object... bsmArgs) { 162 minSize += 5; 163 maxSize += 5; 164 if (mv != null) { 165 mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); 166 } 167 } 168 169 @Override 170 public void visitJumpInsn(final int opcode, final Label label) { 171 minSize += 3; 172 if (opcode == GOTO || opcode == JSR) { 173 maxSize += 5; 174 } else { 175 maxSize += 8; 176 } 177 if (mv != null) { 178 mv.visitJumpInsn(opcode, label); 179 } 180 } 181 182 @Override 183 public void visitLdcInsn(final Object cst) { 184 if (cst instanceof Long || cst instanceof Double) { 185 minSize += 3; 186 maxSize += 3; 187 } else { 188 minSize += 2; 189 maxSize += 3; 190 } 191 if (mv != null) { 192 mv.visitLdcInsn(cst); 193 } 194 } 195 196 @Override 197 public void visitIincInsn(final int var, final int increment) { 198 if (var > 255 || increment > 127 || increment < -128) { 199 minSize += 6; 200 maxSize += 6; 201 } else { 202 minSize += 3; 203 maxSize += 3; 204 } 205 if (mv != null) { 206 mv.visitIincInsn(var, increment); 207 } 208 } 209 210 @Override 211 public void visitTableSwitchInsn(final int min, final int max, 212 final Label dflt, final Label... labels) { 213 minSize += 13 + labels.length * 4; 214 maxSize += 16 + labels.length * 4; 215 if (mv != null) { 216 mv.visitTableSwitchInsn(min, max, dflt, labels); 217 } 218 } 219 220 @Override 221 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 222 final Label[] labels) { 223 minSize += 9 + keys.length * 8; 224 maxSize += 12 + keys.length * 8; 225 if (mv != null) { 226 mv.visitLookupSwitchInsn(dflt, keys, labels); 227 } 228 } 229 230 @Override 231 public void visitMultiANewArrayInsn(final String desc, final int dims) { 232 minSize += 4; 233 maxSize += 4; 234 if (mv != null) { 235 mv.visitMultiANewArrayInsn(desc, dims); 236 } 237 } 238}