1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm.commons; 60 61 import jdk.internal.org.objectweb.asm.Handle; 62 import jdk.internal.org.objectweb.asm.Label; 63 import jdk.internal.org.objectweb.asm.MethodVisitor; 64 import jdk.internal.org.objectweb.asm.Opcodes; 65 66 /** 67 * A {@link MethodVisitor} that can be used to approximate method size. 68 * 69 * @author Eugene Kuleshov 70 */ 71 public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { 72 73 private int minSize; 74 75 private int maxSize; 76 CodeSizeEvaluator(final MethodVisitor mv)77 public CodeSizeEvaluator(final MethodVisitor mv) { 78 this(Opcodes.ASM6, mv); 79 } 80 CodeSizeEvaluator(final int api, final MethodVisitor mv)81 protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { 82 super(api, mv); 83 } 84 getMinSize()85 public int getMinSize() { 86 return this.minSize; 87 } 88 getMaxSize()89 public int getMaxSize() { 90 return this.maxSize; 91 } 92 93 @Override visitInsn(final int opcode)94 public void visitInsn(final int opcode) { 95 minSize += 1; 96 maxSize += 1; 97 if (mv != null) { 98 mv.visitInsn(opcode); 99 } 100 } 101 102 @Override visitIntInsn(final int opcode, final int operand)103 public void visitIntInsn(final int opcode, final int operand) { 104 if (opcode == SIPUSH) { 105 minSize += 3; 106 maxSize += 3; 107 } else { 108 minSize += 2; 109 maxSize += 2; 110 } 111 if (mv != null) { 112 mv.visitIntInsn(opcode, operand); 113 } 114 } 115 116 @Override visitVarInsn(final int opcode, final int var)117 public void visitVarInsn(final int opcode, final int var) { 118 if (var < 4 && opcode != RET) { 119 minSize += 1; 120 maxSize += 1; 121 } else if (var >= 256) { 122 minSize += 4; 123 maxSize += 4; 124 } else { 125 minSize += 2; 126 maxSize += 2; 127 } 128 if (mv != null) { 129 mv.visitVarInsn(opcode, var); 130 } 131 } 132 133 @Override visitTypeInsn(final int opcode, final String type)134 public void visitTypeInsn(final int opcode, final String type) { 135 minSize += 3; 136 maxSize += 3; 137 if (mv != null) { 138 mv.visitTypeInsn(opcode, type); 139 } 140 } 141 142 @Override visitFieldInsn(final int opcode, final String owner, final String name, final String desc)143 public void visitFieldInsn(final int opcode, final String owner, 144 final String name, final String desc) { 145 minSize += 3; 146 maxSize += 3; 147 if (mv != null) { 148 mv.visitFieldInsn(opcode, owner, name, desc); 149 } 150 } 151 152 @Deprecated 153 @Override visitMethodInsn(final int opcode, final String owner, final String name, final String desc)154 public void visitMethodInsn(final int opcode, final String owner, 155 final String name, final String desc) { 156 if (api >= Opcodes.ASM5) { 157 super.visitMethodInsn(opcode, owner, name, desc); 158 return; 159 } 160 doVisitMethodInsn(opcode, owner, name, desc, 161 opcode == Opcodes.INVOKEINTERFACE); 162 } 163 164 @Override visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf)165 public void visitMethodInsn(final int opcode, final String owner, 166 final String name, final String desc, final boolean itf) { 167 if (api < Opcodes.ASM5) { 168 super.visitMethodInsn(opcode, owner, name, desc, itf); 169 return; 170 } 171 doVisitMethodInsn(opcode, owner, name, desc, itf); 172 } 173 doVisitMethodInsn(int opcode, final String owner, final String name, final String desc, final boolean itf)174 private void doVisitMethodInsn(int opcode, final String owner, 175 final String name, final String desc, final boolean itf) { 176 if (opcode == INVOKEINTERFACE) { 177 minSize += 5; 178 maxSize += 5; 179 } else { 180 minSize += 3; 181 maxSize += 3; 182 } 183 if (mv != null) { 184 mv.visitMethodInsn(opcode, owner, name, desc, itf); 185 } 186 } 187 188 @Override visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs)189 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, 190 Object... bsmArgs) { 191 minSize += 5; 192 maxSize += 5; 193 if (mv != null) { 194 mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); 195 } 196 } 197 198 @Override visitJumpInsn(final int opcode, final Label label)199 public void visitJumpInsn(final int opcode, final Label label) { 200 minSize += 3; 201 if (opcode == GOTO || opcode == JSR) { 202 maxSize += 5; 203 } else { 204 maxSize += 8; 205 } 206 if (mv != null) { 207 mv.visitJumpInsn(opcode, label); 208 } 209 } 210 211 @Override visitLdcInsn(final Object cst)212 public void visitLdcInsn(final Object cst) { 213 if (cst instanceof Long || cst instanceof Double) { 214 minSize += 3; 215 maxSize += 3; 216 } else { 217 minSize += 2; 218 maxSize += 3; 219 } 220 if (mv != null) { 221 mv.visitLdcInsn(cst); 222 } 223 } 224 225 @Override visitIincInsn(final int var, final int increment)226 public void visitIincInsn(final int var, final int increment) { 227 if (var > 255 || increment > 127 || increment < -128) { 228 minSize += 6; 229 maxSize += 6; 230 } else { 231 minSize += 3; 232 maxSize += 3; 233 } 234 if (mv != null) { 235 mv.visitIincInsn(var, increment); 236 } 237 } 238 239 @Override visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels)240 public void visitTableSwitchInsn(final int min, final int max, 241 final Label dflt, final Label... labels) { 242 minSize += 13 + labels.length * 4; 243 maxSize += 16 + labels.length * 4; 244 if (mv != null) { 245 mv.visitTableSwitchInsn(min, max, dflt, labels); 246 } 247 } 248 249 @Override visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels)250 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 251 final Label[] labels) { 252 minSize += 9 + keys.length * 8; 253 maxSize += 12 + keys.length * 8; 254 if (mv != null) { 255 mv.visitLookupSwitchInsn(dflt, keys, labels); 256 } 257 } 258 259 @Override visitMultiANewArrayInsn(final String desc, final int dims)260 public void visitMultiANewArrayInsn(final String desc, final int dims) { 261 minSize += 4; 262 maxSize += 4; 263 if (mv != null) { 264 mv.visitMultiANewArrayInsn(desc, dims); 265 } 266 } 267 } 268