1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/*** 2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ASM: a very small and fast Java bytecode manipulation framework 3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright (c) 2000-2007 INRIA, France Telecom 4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * All rights reserved. 5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Redistribution and use in source and binary forms, with or without 7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * modification, are permitted provided that the following conditions 8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are met: 9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1. Redistributions of source code must retain the above copyright 10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * notice, this list of conditions and the following disclaimer. 11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2. Redistributions in binary form must reproduce the above copyright 12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * notice, this list of conditions and the following disclaimer in the 13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * documentation and/or other materials provided with the distribution. 14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 3. Neither the name of the copyright holders nor the names of its 15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * contributors may be used to endorse or promote products derived from 16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * this software without specific prior written permission. 17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THE POSSIBILITY OF SUCH DAMAGE. 29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.asm; 31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/** 33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * A {@link MethodVisitor} that generates methods in bytecode form. Each visit 34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method of this class appends the bytecode corresponding to the visited 35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction to a byte vector, in the order these methods are called. 36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eric Bruneton 38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eugene Kuleshov 39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass MethodWriter implements MethodVisitor { 41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Pseudo access flag used to denote constructors. 44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int ACC_CONSTRUCTOR = 262144; 46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Frame has exactly the same locals as the previous stack map frame and 49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * number of stack items is zero. 50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int SAME_FRAME = 0; // to 63 (0-3f) 52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Frame has exactly the same locals as the previous stack map frame and 55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * number of stack items is 1 56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f) 58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Reserved for future use 61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int RESERVED = 128; 63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Frame has exactly the same locals as the previous stack map frame and 66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * number of stack items is 1. Offset is bigger then 63; 67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7 69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Frame where current locals are the same as the locals in the previous 72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * frame, except that the k last locals are absent. The value of k is given 73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * by the formula 251-frame_type. 74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int CHOP_FRAME = 248; // to 250 (f8-fA) 76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Frame has exactly the same locals as the previous stack map frame and 79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * number of stack items is zero. Offset is bigger then 63; 80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int SAME_FRAME_EXTENDED = 251; // fb 82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Frame where current locals are the same as the locals in the previous 85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * frame, except that k additional locals are defined. The value of k is 86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * given by the formula frame_type-251. 87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int APPEND_FRAME = 252; // to 254 // fc-fe 89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Full frame 92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int FULL_FRAME = 255; // ff 94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates that the stack map frames must be recomputed from scratch. In 97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * this case the maximum stack size and number of local variables is also 98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * recomputed from scratch. 99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #compute 101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final int FRAMES = 0; 103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates that the maximum stack size and number of local variables must 106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * be automatically computed. 107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #compute 109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final int MAXS = 1; 111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates that nothing must be automatically computed. 114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #compute 116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final int NOTHING = 2; 118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Next method writer (see {@link ClassWriter#firstMethod firstMethod}). 121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen MethodWriter next; 123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The class writer to which this method must be added. 126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ClassWriter cw; 128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Access flags of this method. 131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int access; 133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The index of the constant pool item that contains the name of this 136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method. 137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private final int name; 139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The index of the constant pool item that contains the descriptor of this 142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method. 143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private final int desc; 145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The descriptor of this method. 148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private final String descriptor; 150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The signature of this method. 153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String signature; 155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * If not zero, indicates that the code of this method must be copied from 158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the ClassReader associated to this writer in <code>cw.cr</code>. More 159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * precisely, this field gives the index of the first byte to copied from 160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <code>cw.cr.b</code>. 161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int classReaderOffset; 163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * If not zero, indicates that the code of this method must be copied from 166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the ClassReader associated to this writer in <code>cw.cr</code>. More 167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * precisely, this field gives the number of bytes to copied from 168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <code>cw.cr.b</code>. 169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int classReaderLength; 171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Number of exceptions that can be thrown by this method. 174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int exceptionCount; 176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The exceptions that can be thrown by this method. More precisely, this 179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * array contains the indexes of the constant pool items that contain the 180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * internal names of these exception classes. 181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] exceptions; 183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The annotation default attribute of this method. May be <tt>null</tt>. 186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private ByteVector annd; 188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The runtime visible annotations of this method. May be <tt>null</tt>. 191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private AnnotationWriter anns; 193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The runtime invisible annotations of this method. May be <tt>null</tt>. 196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private AnnotationWriter ianns; 198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The runtime visible parameter annotations of this method. May be 201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>null</tt>. 202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private AnnotationWriter[] panns; 204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The runtime invisible parameter annotations of this method. May be 207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>null</tt>. 208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private AnnotationWriter[] ipanns; 210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The number of synthetic parameters of this method. 213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int synthetics; 215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The non standard attributes of the method. 218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Attribute attrs; 220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The bytecode of this method. 223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private ByteVector code = new ByteVector(); 225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Maximum stack size of this method. 228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int maxStack; 230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Maximum number of local variables for this method. 233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int maxLocals; 235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Number of stack map frames in the StackMapTable attribute. 238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int frameCount; 240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The StackMapTable attribute. 243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private ByteVector stackMap; 245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The offset of the last frame that was written in the StackMapTable 248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * attribute. 249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int previousFrameOffset; 251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The last frame that was written in the StackMapTable attribute. 254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #frame 256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int[] previousFrame; 258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Index of the next element to be added in {@link #frame}. 261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int frameIndex; 263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The current stack map frame. The first element contains the offset of the 266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction to which the frame corresponds, the second element is the 267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * number of locals and the third one is the number of stack elements. The 268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * local variables start at index 3 and are followed by the operand stack 269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] = 270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * nStack, frame[3] = nLocal. All types are encoded as integers, with the 271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * same format as the one used in {@link Label}, but limited to BASE types. 272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int[] frame; 274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Number of elements in the exception handler list. 277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int handlerCount; 279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The first element in the exception handler list. 282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Handler firstHandler; 284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The last element in the exception handler list. 287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Handler lastHandler; 289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Number of entries in the LocalVariableTable attribute. 292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int localVarCount; 294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The LocalVariableTable attribute. 297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private ByteVector localVar; 299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Number of entries in the LocalVariableTypeTable attribute. 302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int localVarTypeCount; 304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The LocalVariableTypeTable attribute. 307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private ByteVector localVarType; 309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Number of entries in the LineNumberTable attribute. 312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int lineNumberCount; 314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The LineNumberTable attribute. 317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private ByteVector lineNumber; 319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The non standard attributes of the method's code. 322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Attribute cattrs; 324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if some jump instructions are too small and need to be resized. 327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private boolean resize; 329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The number of subroutines in this method. 332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int subroutines; 334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Fields for the control flow graph analysis algorithm (used to compute the 339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * maximum stack size). A control flow graph contains one node per "basic 340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * block", and one edge per "jump" from one basic block to another. Each 341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * node (i.e., each basic block) is represented by the Label object that 342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * corresponds to the first instruction of this basic block. Each node also 343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * stores the list of its successors in the graph, as a linked list of Edge 344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * objects. 345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates what must be automatically computed. 349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #FRAMES 351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #MAXS 352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #NOTHING 353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private final int compute; 355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * A list of labels. This list is the list of basic blocks in the method, 358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * i.e. a list of Label objects linked to each other by their 359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link Label#successor} field, in the order they are visited by 360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link MethodVisitor#visitLabel}, and starting with the first basic block. 361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Label labels; 363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The previous basic block. 366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Label previousBlock; 368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The current basic block. 371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Label currentBlock; 373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The (relative) stack size after the last visited instruction. This size 376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * is relative to the beginning of the current basic block, i.e., the true 377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * stack size after the last visited instruction is equal to the 378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link Label#inputStackTop beginStackSize} of the current basic block 379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * plus <tt>stackSize</tt>. 380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int stackSize; 382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The (relative) maximum stack size after the last visited instruction. 385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This size is relative to the beginning of the current basic block, i.e., 386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the true maximum stack size after the last visited instruction is equal 387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * to the {@link Label#inputStackTop beginStackSize} of the current basic 388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * block plus <tt>stackSize</tt>. 389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int maxStackSize; 391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Constructor 394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Constructs a new {@link MethodWriter}. 398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param cw the class writer in which the method must be added. 400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param access the method's access flags (see {@link Opcodes}). 401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param name the method's name. 402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param desc the method's descriptor (see {@link Type}). 403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param signature the method's signature. May be <tt>null</tt>. 404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param exceptions the internal names of the method's exceptions. May be 405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>null</tt>. 406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param computeMaxs <tt>true</tt> if the maximum stack size and number 407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of local variables must be automatically computed. 408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param computeFrames <tt>true</tt> if the stack map tables must be 409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * recomputed from scratch. 410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen MethodWriter( 412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ClassWriter cw, 413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int access, 414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String name, 415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String desc, 416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String signature, 417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String[] exceptions, 418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final boolean computeMaxs, 419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final boolean computeFrames) 420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (cw.firstMethod == null) { 422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.firstMethod = this; 423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.lastMethod.next = this; 425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.lastMethod = this; 427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.cw = cw; 428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.access = access; 429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.name = cw.newUTF8(name); 430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.desc = cw.newUTF8(desc); 431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.descriptor = desc; 432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.SIGNATURES) { 433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.signature = signature; 434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (exceptions != null && exceptions.length > 0) { 436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen exceptionCount = exceptions.length; 437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.exceptions = new int[exceptionCount]; 438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < exceptionCount; ++i) { 439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.exceptions[i] = cw.newClass(exceptions[i]); 440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); 443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (computeMaxs || computeFrames) { 444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (computeFrames && "<init>".equals(name)) { 445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.access |= ACC_CONSTRUCTOR; 446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates maxLocals 448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size = getArgumentsAndReturnSizes(descriptor) >> 2; 449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((access & Opcodes.ACC_STATIC) != 0) { 450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen --size; 451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxLocals = size; 453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // creates and visits the label for the first basic block 454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen labels = new Label(); 455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen labels.status |= Label.PUSHED; 456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitLabel(labels); 457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Implementation of the MethodVisitor interface 462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public AnnotationVisitor visitAnnotationDefault() { 465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!ClassReader.ANNOTATIONS) { 466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return null; 467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen annd = new ByteVector(); 469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new AnnotationWriter(cw, false, annd, null, 0); 470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public AnnotationVisitor visitAnnotation( 473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String desc, 474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final boolean visible) 475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!ClassReader.ANNOTATIONS) { 477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return null; 478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ByteVector bv = new ByteVector(); 480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // write type, and reserve space for values count 481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen bv.putShort(cw.newUTF8(desc)).putShort(0); 482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); 483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (visible) { 484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen aw.next = anns; 485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen anns = aw; 486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen aw.next = ianns; 488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ianns = aw; 489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return aw; 491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public AnnotationVisitor visitParameterAnnotation( 494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int parameter, 495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String desc, 496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final boolean visible) 497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!ClassReader.ANNOTATIONS) { 499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return null; 500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ByteVector bv = new ByteVector(); 502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ("Ljava/lang/Synthetic;".equals(desc)) { 503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // workaround for a bug in javac with synthetic parameters 504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // see ClassReader.readParameterAnnotations 505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen synthetics = Math.max(synthetics, parameter + 1); 506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new AnnotationWriter(cw, false, bv, null, 0); 507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // write type, and reserve space for values count 509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen bv.putShort(cw.newUTF8(desc)).putShort(0); 510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); 511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (visible) { 512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (panns == null) { 513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; 514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen aw.next = panns[parameter]; 516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen panns[parameter] = aw; 517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ipanns == null) { 519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; 520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen aw.next = ipanns[parameter]; 522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ipanns[parameter] = aw; 523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return aw; 525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitAttribute(final Attribute attr) { 528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (attr.isCodeAttribute()) { 529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attr.next = cattrs; 530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cattrs = attr; 531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attr.next = attrs; 533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attrs = attr; 534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitCode() { 538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitFrame( 541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int type, 542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int nLocal, 543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Object[] local, 544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int nStack, 545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Object[] stack) 546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!ClassReader.FRAMES || compute == FRAMES) { 548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (type == Opcodes.F_NEW) { 552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen startFrame(code.length, nLocal, nStack); 553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < nLocal; ++i) { 554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (local[i] instanceof String) { 555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = Frame.OBJECT 556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | cw.addType((String) local[i]); 557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (local[i] instanceof Integer) { 558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = ((Integer) local[i]).intValue(); 559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = Frame.UNINITIALIZED 561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | cw.addUninitializedType("", 562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ((Label) local[i]).position); 563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < nStack; ++i) { 566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (stack[i] instanceof String) { 567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = Frame.OBJECT 568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | cw.addType((String) stack[i]); 569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (stack[i] instanceof Integer) { 570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = ((Integer) stack[i]).intValue(); 571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = Frame.UNINITIALIZED 573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | cw.addUninitializedType("", 574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ((Label) stack[i]).position); 575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen endFrame(); 578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int delta; 580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (stackMap == null) { 581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap = new ByteVector(); 582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen delta = code.length; 583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen delta = code.length - previousFrameOffset - 1; 585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (type) { 588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.F_FULL: 589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(FULL_FRAME) 590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(delta) 591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(nLocal); 592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < nLocal; ++i) { 593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameType(local[i]); 594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putShort(nStack); 596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < nStack; ++i) { 597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameType(stack[i]); 598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.F_APPEND: 601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_FRAME_EXTENDED + nLocal) 602674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(delta); 603674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < nLocal; ++i) { 604674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameType(local[i]); 605674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 606674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 607674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.F_CHOP: 608674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_FRAME_EXTENDED - nLocal) 609674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(delta); 610674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 611674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.F_SAME: 612674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (delta < 64) { 613674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(delta); 614674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 615674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); 616674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 617674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 618674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.F_SAME1: 619674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (delta < 64) { 620674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); 621674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 622674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) 623674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(delta); 624674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 625674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameType(stack[0]); 626674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 627674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 628674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 629674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousFrameOffset = code.length; 630674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++frameCount; 631674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 632674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 633674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 634674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitInsn(final int opcode) { 635674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 636674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(opcode); 637674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // update currentBlock 638674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 639674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 640674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 641674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(opcode, 0, null, null); 642674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 643674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current and max stack sizes 644674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size = stackSize + Frame.SIZE[opcode]; 645674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (size > maxStackSize) { 646674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = size; 647674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 648674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = size; 649674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 650674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if opcode == ATHROW or xRETURN, ends current block (no successor) 651674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) 652674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || opcode == Opcodes.ATHROW) 653674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 654674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen noSuccessor(); 655674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 656674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 657674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 658674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 659674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitIntInsn(final int opcode, final int operand) { 660674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 661674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 662674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 663674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(opcode, operand, null, null); 664674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (opcode != Opcodes.NEWARRAY) { 665674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current and max stack sizes only for NEWARRAY 666674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // (stack size variation = 0 for BIPUSH or SIPUSH) 667674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size = stackSize + 1; 668674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (size > maxStackSize) { 669674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = size; 670674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 671674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = size; 672674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 673674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 674674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 675674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.SIPUSH) { 676674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(opcode, operand); 677674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { // BIPUSH or NEWARRAY 678674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put11(opcode, operand); 679674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 680674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 681674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 682674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitVarInsn(final int opcode, final int var) { 683674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 684674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 685674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 686674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(opcode, var, null, null); 687674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 688674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current and max stack sizes 689674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.RET) { 690674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // no stack change, but end of current block (no successor) 691674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.status |= Label.RET; 692674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // save 'stackSize' here for future use 693674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // (see {@link #findSubroutineSuccessors}) 694674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.inputStackTop = stackSize; 695674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen noSuccessor(); 696674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { // xLOAD or xSTORE 697674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size = stackSize + Frame.SIZE[opcode]; 698674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (size > maxStackSize) { 699674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = size; 700674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 701674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = size; 702674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 703674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 704674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 705674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute != NOTHING) { 706674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates max locals 707674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int n; 708674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD 709674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) 710674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 711674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n = var + 2; 712674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 713674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n = var + 1; 714674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 715674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (n > maxLocals) { 716674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxLocals = n; 717674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 718674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 719674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 720674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (var < 4 && opcode != Opcodes.RET) { 721674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int opt; 722674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode < Opcodes.ISTORE) { 723674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* ILOAD_0 */ 724674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; 725674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 726674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* ISTORE_0 */ 727674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; 728674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 729674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(opt); 730674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (var >= 256) { 731674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(196 /* WIDE */).put12(opcode, var); 732674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 733674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put11(opcode, var); 734674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 735674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) { 736674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitLabel(new Label()); 737674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 738674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 739674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 740674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitTypeInsn(final int opcode, final String type) { 741674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Item i = cw.newClassItem(type); 742674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 743674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 744674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 745674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(opcode, code.length, cw, i); 746674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (opcode == Opcodes.NEW) { 747674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current and max stack sizes only if opcode == NEW 748674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF) 749674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size = stackSize + 1; 750674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (size > maxStackSize) { 751674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = size; 752674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 753674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = size; 754674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 755674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 756674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 757674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(opcode, i.index); 758674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 759674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 760674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitFieldInsn( 761674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int opcode, 762674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String owner, 763674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String name, 764674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String desc) 765674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 766674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Item i = cw.newFieldItem(owner, name, desc); 767674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 768674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 769674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 770674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(opcode, 0, cw, i); 771674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 772674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size; 773674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes the stack size variation 774674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen char c = desc.charAt(0); 775674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (opcode) { 776674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.GETSTATIC: 777674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); 778674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 779674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.PUTSTATIC: 780674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); 781674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 782674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Opcodes.GETFIELD: 783674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); 784674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 785674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // case Constants.PUTFIELD: 786674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 787674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); 788674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 789674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 790674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current and max stack sizes 791674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (size > maxStackSize) { 792674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = size; 793674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 794674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = size; 795674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 796674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 797674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 798674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(opcode, i.index); 799674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 800674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 801674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitMethodInsn( 802674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int opcode, 803674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String owner, 804674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String name, 805674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String desc) 806674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 807674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean itf = opcode == Opcodes.INVOKEINTERFACE; 808674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Item i = cw.newMethodItem(owner, name, desc, itf); 809674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int argSize = i.intVal; 810674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 811674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 812674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 813674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(opcode, 0, cw, i); 814674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 815674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 816674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * computes the stack size variation. In order not to recompute 817674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * several times this variation for the same Item, we use the 818674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * intVal field of this item to store this variation, once it 819674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * has been computed. More precisely this intVal field stores 820674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the sizes of the arguments and of the return value 821674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * corresponding to desc. 822674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 823674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (argSize == 0) { 824674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // the above sizes have not been computed yet, 825674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // so we compute them... 826674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen argSize = getArgumentsAndReturnSizes(desc); 827674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ... and we save them in order 828674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // not to recompute them in the future 829674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen i.intVal = argSize; 830674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 831674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size; 832674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.INVOKESTATIC) { 833674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; 834674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 835674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize - (argSize >> 2) + (argSize & 0x03); 836674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 837674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current and max stack sizes 838674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (size > maxStackSize) { 839674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = size; 840674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 841674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = size; 842674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 843674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 844674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 845674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (itf) { 846674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (argSize == 0) { 847674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen argSize = getArgumentsAndReturnSizes(desc); 848674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen i.intVal = argSize; 849674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 850674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); 851674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 852674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(opcode, i.index); 853674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 854674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 855674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 856674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitJumpInsn(final int opcode, final Label label) { 857674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label nextInsn = null; 858674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 859674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 860674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 861674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(opcode, 0, null, null); 862674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // 'label' is the target of a jump instruction 863674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.getFirst().status |= Label.TARGET; 864674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds 'label' as a successor of this basic block 865674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(Edge.NORMAL, label); 866674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode != Opcodes.GOTO) { 867674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // creates a Label for the next basic block 868674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen nextInsn = new Label(); 869674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 870674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 871674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.JSR) { 872674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((label.status & Label.SUBROUTINE) == 0) { 873674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.status |= Label.SUBROUTINE; 874674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++subroutines; 875674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 876674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.status |= Label.JSR; 877674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(stackSize + 1, label); 878674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // creates a Label for the next basic block 879674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen nextInsn = new Label(); 880674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 881674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * note that, by construction in this method, a JSR block 882674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * has at least two successors in the control flow graph: 883674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the first one leads the next instruction after the JSR, 884674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * while the second one leads to the JSR target. 885674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 886674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 887674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current stack size (max stack size unchanged 888674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // because stack size variation always negative in this 889674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // case) 890674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize += Frame.SIZE[opcode]; 891674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(stackSize, label); 892674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 893674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 894674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 895674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 896674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((label.status & Label.RESOLVED) != 0 897674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen && label.position - code.length < Short.MIN_VALUE) 898674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 899674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 900674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * case of a backward jump with an offset < -32768. In this case we 901674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx 902674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the 903674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'> 904674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * designates the instruction just after the GOTO_W. 905674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 906674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.GOTO) { 907674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(200); // GOTO_W 908674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (opcode == Opcodes.JSR) { 909674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(201); // JSR_W 910674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 911674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if the IF instruction is transformed into IFNOT GOTO_W the 912674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // next instruction becomes the target of the IFNOT instruction 913674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (nextInsn != null) { 914674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen nextInsn.status |= Label.TARGET; 915674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 916674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(opcode <= 166 917674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ? ((opcode + 1) ^ 1) - 1 918674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen : opcode ^ 1); 919674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putShort(8); // jump offset 920674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(200); // GOTO_W 921674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 922674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.put(this, code, code.length - 1, true); 923674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 924674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 925674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * case of a backward jump with an offset >= -32768, or of a forward 926674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * jump with, of course, an unknown offset. In these cases we store 927674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the offset in 2 bytes (which will be increased in 928674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * resizeInstructions, if needed). 929674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 930674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(opcode); 931674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.put(this, code, code.length - 1, false); 932674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 933674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 934674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (nextInsn != null) { 935674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if the jump instruction is not a GOTO, the next instruction 936674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // is also a successor of this instruction. Calling visitLabel 937674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the label of this next instruction as a successor of the 938674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // current block, and starts a new basic block 939674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitLabel(nextInsn); 940674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 941674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.GOTO) { 942674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen noSuccessor(); 943674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 944674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 945674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 946674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 947674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitLabel(final Label label) { 948674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // resolves previous forward references to label, if any 949674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen resize |= label.resolve(this, code.length, code.data); 950674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates currentBlock 951674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((label.status & Label.DEBUG) != 0) { 952674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 953674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 954674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 955674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 956674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (label.position == currentBlock.position) { 957674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // successive labels, do not start a new basic block 958674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.status |= (label.status & Label.TARGET); 959674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.frame = currentBlock.frame; 960674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 961674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 962674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ends current block (with one new successor) 963674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(Edge.NORMAL, label); 964674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 965674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // begins a new current block 966674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock = label; 967674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (label.frame == null) { 968674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.frame = new Frame(); 969674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.frame.owner = label; 970674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 971674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the basic block list 972674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (previousBlock != null) { 973674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (label.position == previousBlock.position) { 974674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousBlock.status |= (label.status & Label.TARGET); 975674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.frame = previousBlock.frame; 976674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock = previousBlock; 977674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 978674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 979674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousBlock.successor = label; 980674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 981674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousBlock = label; 982674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (compute == MAXS) { 983674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 984674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ends current block (with one new successor) 985674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.outputStackMax = maxStackSize; 986674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(stackSize, label); 987674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 988674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // begins a new current block 989674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock = label; 990674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // resets the relative current and max stack sizes 991674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = 0; 992674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = 0; 993674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the basic block list 994674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (previousBlock != null) { 995674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousBlock.successor = label; 996674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 997674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousBlock = label; 998674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 999674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1000674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1001674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitLdcInsn(final Object cst) { 1002674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Item i = cw.newConstItem(cst); 1003674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 1004674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 1005674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 1006674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(Opcodes.LDC, 0, cw, i); 1007674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1008674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size; 1009674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes the stack size variation 1010674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) 1011674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1012674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize + 2; 1013674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1014674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size = stackSize + 1; 1015674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1016674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current and max stack sizes 1017674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (size > maxStackSize) { 1018674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStackSize = size; 1019674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1020674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize = size; 1021674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1022674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1023674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 1024674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int index = i.index; 1025674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 1026674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(20 /* LDC2_W */, index); 1027674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (index >= 256) { 1028674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(19 /* LDC_W */, index); 1029674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1030674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put11(Opcodes.LDC, index); 1031674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1032674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1033674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1034674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitIincInsn(final int var, final int increment) { 1035674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 1036674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 1037674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(Opcodes.IINC, var, null, null); 1038674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1039674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1040674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute != NOTHING) { 1041674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates max locals 1042674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int n = var + 1; 1043674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (n > maxLocals) { 1044674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxLocals = n; 1045674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1046674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1047674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 1048674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((var > 255) || (increment > 127) || (increment < -128)) { 1049674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(196 /* WIDE */) 1050674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .put12(Opcodes.IINC, var) 1051674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(increment); 1052674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1053674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(Opcodes.IINC).put11(var, increment); 1054674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1055674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1056674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1057674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitTableSwitchInsn( 1058674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int min, 1059674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int max, 1060674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label dflt, 1061674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label[] labels) 1062674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1063674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 1064674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int source = code.length; 1065674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(Opcodes.TABLESWITCH); 1066674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.length += (4 - code.length % 4) % 4; 1067674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen dflt.put(this, code, source, true); 1068674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putInt(min).putInt(max); 1069674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < labels.length; ++i) { 1070674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen labels[i].put(this, code, source, true); 1071674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1072674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates currentBlock 1073674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitSwitchInsn(dflt, labels); 1074674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1075674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1076674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitLookupSwitchInsn( 1077674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label dflt, 1078674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int[] keys, 1079674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label[] labels) 1080674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1081674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 1082674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int source = code.length; 1083674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putByte(Opcodes.LOOKUPSWITCH); 1084674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.length += (4 - code.length % 4) % 4; 1085674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen dflt.put(this, code, source, true); 1086674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putInt(labels.length); 1087674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < labels.length; ++i) { 1088674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.putInt(keys[i]); 1089674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen labels[i].put(this, code, source, true); 1090674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1091674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates currentBlock 1092674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitSwitchInsn(dflt, labels); 1093674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1094674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1095674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void visitSwitchInsn(final Label dflt, final Label[] labels) { 1096674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 1097674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 1098674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 1099674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null); 1100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds current block successors 1101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(Edge.NORMAL, dflt); 1102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen dflt.getFirst().status |= Label.TARGET; 1103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < labels.length; ++i) { 1104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(Edge.NORMAL, labels[i]); 1105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen labels[i].getFirst().status |= Label.TARGET; 1106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current stack size (max stack size unchanged) 1109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen --stackSize; 1110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds current block successors 1111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(stackSize, dflt); 1112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < labels.length; ++i) { 1113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addSuccessor(stackSize, labels[i]); 1114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ends current block 1117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen noSuccessor(); 1118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitMultiANewArrayInsn(final String desc, final int dims) { 1122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Item i = cw.newClassItem(desc); 1123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Label currentBlock = this.currentBlock; 1124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (currentBlock != null) { 1125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 1126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); 1127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates current stack size (max stack size unchanged because 1129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // stack size variation always negative or null) 1130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackSize += 1 - dims; 1131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds the instruction to the bytecode of the method 1134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); 1135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitTryCatchBlock( 1138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label start, 1139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end, 1140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label handler, 1141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String type) 1142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++handlerCount; 1144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Handler h = new Handler(); 1145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h.start = start; 1146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h.end = end; 1147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h.handler = handler; 1148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h.desc = type; 1149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h.type = type != null ? cw.newClass(type) : 0; 1150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (lastHandler == null) { 1151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen firstHandler = h; 1152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen lastHandler.next = h; 1154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen lastHandler = h; 1156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitLocalVariable( 1159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String name, 1160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String desc, 1161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String signature, 1162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label start, 1163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end, 1164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int index) 1165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (signature != null) { 1167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVarType == null) { 1168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen localVarType = new ByteVector(); 1169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++localVarTypeCount; 1171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen localVarType.putShort(start.position) 1172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(end.position - start.position) 1173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(cw.newUTF8(name)) 1174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(cw.newUTF8(signature)) 1175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(index); 1176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVar == null) { 1178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen localVar = new ByteVector(); 1179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++localVarCount; 1181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen localVar.putShort(start.position) 1182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(end.position - start.position) 1183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(cw.newUTF8(name)) 1184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(cw.newUTF8(desc)) 1185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(index); 1186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute != NOTHING) { 1187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates max locals 1188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen char c = desc.charAt(0); 1189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int n = index + (c == 'J' || c == 'D' ? 2 : 1); 1190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (n > maxLocals) { 1191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxLocals = n; 1192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitLineNumber(final int line, final Label start) { 1197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (lineNumber == null) { 1198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen lineNumber = new ByteVector(); 1199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++lineNumberCount; 1201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen lineNumber.putShort(start.position); 1202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen lineNumber.putShort(line); 1203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitMaxs(final int maxStack, final int maxLocals) { 1206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.FRAMES && compute == FRAMES) { 1207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // completes the control flow graph with exception handler blocks 1208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Handler handler = firstHandler; 1209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (handler != null) { 1210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = handler.start.getFirst(); 1211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label h = handler.handler.getFirst(); 1212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label e = handler.end.getFirst(); 1213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes the kind of the edges to 'h' 1214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String t = handler.desc == null 1215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ? "java/lang/Throwable" 1216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen : handler.desc; 1217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int kind = Frame.OBJECT | cw.addType(t); 1218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // h is an exception handler 1219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h.status |= Label.TARGET; 1220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds 'h' as a successor of labels between 'start' and 'end' 1221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (l != e) { 1222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // creates an edge to 'h' 1223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge b = new Edge(); 1224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.info = kind; 1225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.successor = h; 1226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds it to the successors of 'l' 1227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.next = l.successors; 1228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.successors = b; 1229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // goes to the next label 1230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = l.successor; 1231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen handler = handler.next; 1233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // creates and visits the first (implicit) frame 1236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame f = labels.frame; 1237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] args = Type.getArgumentTypes(descriptor); 1238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen f.initInputFrame(cw, access, args, this.maxLocals); 1239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitFrame(f); 1240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 1242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * fix point algorithm: mark the first basic block as 'changed' 1243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * (i.e. put it in the 'changed' list) and, while there are changed 1244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * basic blocks, choose one, mark it as unchanged, and update its 1245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * successors (which can be changed in the process). 1246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int max = 0; 1248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label changed = labels; 1249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (changed != null) { 1250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // removes a basic block from the list of changed basic blocks 1251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = changed; 1252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changed = changed.next; 1253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.next = null; 1254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen f = l.frame; 1255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // a reacheable jump target must be stored in the stack map 1256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.TARGET) != 0) { 1257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.status |= Label.STORE; 1258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // all visited labels are reacheable, by definition 1260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.status |= Label.REACHABLE; 1261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the (absolute) maximum stack size 1262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int blockMax = f.inputStack.length + l.outputStackMax; 1263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (blockMax > max) { 1264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen max = blockMax; 1265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the successors of the current basic block 1267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge e = l.successors; 1268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (e != null) { 1269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label n = e.successor.getFirst(); 1270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean change = f.merge(cw, n.frame, e.info); 1271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (change && n.next == null) { 1272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if n has changed and is not already in the 'changed' 1273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // list, adds it to this list 1274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n.next = changed; 1275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen changed = n; 1276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e = e.next; 1278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.maxStack = max; 1281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // visits all the frames that must be stored in the stack map 1283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = labels; 1284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (l != null) { 1285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen f = l.frame; 1286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.STORE) != 0) { 1287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitFrame(f); 1288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.REACHABLE) == 0) { 1290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // finds start and end of dead basic block 1291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label k = l.successor; 1292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int start = l.position; 1293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int end = (k == null ? code.length : k.position) - 1; 1294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if non empty basic block 1295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (end >= start) { 1296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // replaces instructions with NOP ... NOP ATHROW 1297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = start; i < end; ++i) { 1298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.data[i] = Opcodes.NOP; 1299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.data[end] = (byte) Opcodes.ATHROW; 1301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // emits a frame for this unreachable block 1302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen startFrame(start, 0, 1); 1303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = Frame.OBJECT 1304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | cw.addType("java/lang/Throwable"); 1305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen endFrame(); 1306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = l.successor; 1309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (compute == MAXS) { 1311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // completes the control flow graph with exception handler blocks 1312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Handler handler = firstHandler; 1313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (handler != null) { 1314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = handler.start; 1315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label h = handler.handler; 1316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label e = handler.end; 1317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds 'h' as a successor of labels between 'start' and 'end' 1318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (l != e) { 1319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // creates an edge to 'h' 1320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge b = new Edge(); 1321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.info = Edge.EXCEPTION; 1322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.successor = h; 1323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds it to the successors of 'l' 1324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.JSR) == 0) { 1325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.next = l.successors; 1326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.successors = b; 1327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if l is a JSR block, adds b after the first two edges 1329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // to preserve the hypothesis about JSR block successors 1330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // order (see {@link #visitJumpInsn}) 1331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.next = l.successors.next.next; 1332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.successors.next.next = b; 1333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // goes to the next label 1335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = l.successor; 1336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen handler = handler.next; 1338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (subroutines > 0) { 1341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // completes the control flow graph with the RET successors 1342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 1343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * first step: finds the subroutines. This step determines, for 1344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * each basic block, to which subroutine(s) it belongs. 1345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // finds the basic blocks that belong to the "main" subroutine 1347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int id = 0; 1348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen labels.visitSubroutine(null, 1, subroutines); 1349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // finds the basic blocks that belong to the real subroutines 1350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = labels; 1351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (l != null) { 1352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.JSR) != 0) { 1353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // the subroutine is defined by l's TARGET, not by l 1354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label subroutine = l.successors.next.successor; 1355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if this subroutine has not been visited yet... 1356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((subroutine.status & Label.VISITED) == 0) { 1357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ...assigns it a new id and finds its basic blocks 1358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen id += 1; 1359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutine.visitSubroutine(null, (id / 32L) << 32 1360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | (1L << (id % 32)), subroutines); 1361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = l.successor; 1364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // second step: finds the successors of RET blocks 1366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = labels; 1367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (l != null) { 1368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.JSR) != 0) { 1369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label L = labels; 1370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (L != null) { 1371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen L.status &= ~Label.VISITED; 1372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen L = L.successor; 1373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // the subroutine is defined by l's TARGET, not by l 1375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label subroutine = l.successors.next.successor; 1376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen subroutine.visitSubroutine(l, 0, subroutines); 1377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = l.successor; 1379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 1383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * control flow analysis algorithm: while the block stack is not 1384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * empty, pop a block from this stack, update the max stack size, 1385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * compute the true (non relative) begin stack size of the 1386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * successors of this block, and push these successors onto the 1387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * stack (unless they have already been pushed onto the stack). 1388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Note: by hypothesis, the {@link Label#inputStackTop} of the 1389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * blocks in the block stack are the true (non relative) beginning 1390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * stack sizes of these blocks. 1391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int max = 0; 1393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label stack = labels; 1394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (stack != null) { 1395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // pops a block from the stack 1396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = stack; 1397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stack = stack.next; 1398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes the true (non relative) max stack size of this block 1399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int start = l.inputStackTop; 1400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int blockMax = start + l.outputStackMax; 1401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the global max stack size 1402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (blockMax > max) { 1403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen max = blockMax; 1404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // analyzes the successors of the block 1406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge b = l.successors; 1407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.JSR) != 0) { 1408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ignores the first edge of JSR blocks (virtual successor) 1409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b = b.next; 1410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (b != null) { 1412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = b.successor; 1413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if this successor has not already been pushed... 1414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.PUSHED) == 0) { 1415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes its true beginning stack size... 1416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start 1417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen + b.info; 1418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ...and pushes it onto the stack 1419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.status |= Label.PUSHED; 1420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.next = stack; 1421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stack = l; 1422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b = b.next; 1424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.maxStack = max; 1427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.maxStack = maxStack; 1429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.maxLocals = maxLocals; 1430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void visitEnd() { 1434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 1437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Utility methods: control flow analysis algorithm 1438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 1439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Computes the size of the arguments and of the return value of a method. 1442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param desc the descriptor of a method. 1444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the size of the arguments of the method (plus one for the 1445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * implicit this argument), argSize, and the size of its return 1446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * value, retSize, packed into a single int i = 1447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal 1448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). 1449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static int getArgumentsAndReturnSizes(final String desc) { 1451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int n = 1; 1452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int c = 1; 1453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (true) { 1454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen char car = desc.charAt(c++); 1455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (car == ')') { 1456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen car = desc.charAt(c); 1457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return n << 2 1458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 1459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (car == 'L') { 1460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (desc.charAt(c++) != ';') { 1461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n += 1; 1463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (car == '[') { 1464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while ((car = desc.charAt(c)) == '[') { 1465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++c; 1466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (car == 'D' || car == 'J') { 1468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n -= 1; 1469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (car == 'D' || car == 'J') { 1471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n += 2; 1472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen n += 1; 1474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Adds a successor to the {@link #currentBlock currentBlock} block. 1480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param info information about the control flow edge to be added. 1482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param successor the successor block to be added to the current block. 1483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void addSuccessor(final int info, final Label successor) { 1485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // creates and initializes an Edge object... 1486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge b = new Edge(); 1487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.info = info; 1488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.successor = successor; 1489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ...and adds it to the successor list of the currentBlock block 1490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b.next = currentBlock.successors; 1491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.successors = b; 1492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Ends the current basic block. This method must be used in the case where 1496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the current basic block does not have any successor. 1497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void noSuccessor() { 1499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 1500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = new Label(); 1501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.frame = new Frame(); 1502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.frame.owner = l; 1503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l.resolve(this, code.length, code.data); 1504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousBlock.successor = l; 1505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousBlock = l; 1506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock.outputStackMax = maxStackSize; 1508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen currentBlock = null; 1510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 1513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Utility methods: stack map frames 1514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 1515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Visits a frame that has been computed from scratch. 1518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param f the frame that must be visited. 1520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void visitFrame(final Frame f) { 1522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int i, t; 1523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int nTop = 0; 1524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int nLocal = 0; 1525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int nStack = 0; 1526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] locals = f.inputLocals; 1527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] stacks = f.inputStack; 1528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes the number of locals (ignores TOP types that are just after 1529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // a LONG or a DOUBLE, and all trailing TOP types) 1530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (i = 0; i < locals.length; ++i) { 1531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen t = locals[i]; 1532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (t == Frame.TOP) { 1533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++nTop; 1534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen nLocal += nTop + 1; 1536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen nTop = 0; 1537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (t == Frame.LONG || t == Frame.DOUBLE) { 1539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++i; 1540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // computes the stack size (ignores TOP types that are just after 1543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // a LONG or a DOUBLE) 1544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (i = 0; i < stacks.length; ++i) { 1545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen t = stacks[i]; 1546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++nStack; 1547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (t == Frame.LONG || t == Frame.DOUBLE) { 1548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++i; 1549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // visits the frame and its content 1552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen startFrame(f.owner.position, nLocal, nStack); 1553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (i = 0; nLocal > 0; ++i, --nLocal) { 1554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen t = locals[i]; 1555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = t; 1556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (t == Frame.LONG || t == Frame.DOUBLE) { 1557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++i; 1558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (i = 0; i < stacks.length; ++i) { 1561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen t = stacks[i]; 1562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[frameIndex++] = t; 1563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (t == Frame.LONG || t == Frame.DOUBLE) { 1564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++i; 1565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen endFrame(); 1568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Starts the visit of a stack map frame. 1572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param offset the offset of the instruction to which the frame 1574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * corresponds. 1575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param nLocal the number of local variables in the frame. 1576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param nStack the number of stack elements in the frame. 1577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void startFrame(final int offset, final int nLocal, final int nStack) 1579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int n = 3 + nLocal + nStack; 1581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (frame == null || frame.length < n) { 1582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame = new int[n]; 1583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[0] = offset; 1585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[1] = nLocal; 1586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame[2] = nStack; 1587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frameIndex = 3; 1588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Checks if the visit of the current frame {@link #frame} is finished, and 1592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * if yes, write it in the StackMapTable attribute. 1593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void endFrame() { 1595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (previousFrame != null) { // do not write the first frame 1596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (stackMap == null) { 1597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap = new ByteVector(); 1598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrame(); 1600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++frameCount; 1601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1602674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousFrame = frame; 1603674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame = null; 1604674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1605674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1606674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1607674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Compress and writes the current frame {@link #frame} in the StackMapTable 1608674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * attribute. 1609674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1610674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void writeFrame() { 1611674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int clocalsSize = frame[1]; 1612674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int cstackSize = frame[2]; 1613674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((cw.version & 0xFFFF) < Opcodes.V1_6) { 1614674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putShort(frame[0]).putShort(clocalsSize); 1615674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameTypes(3, 3 + clocalsSize); 1616674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putShort(cstackSize); 1617674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); 1618674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 1619674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1620674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int localsSize = previousFrame[1]; 1621674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int type = FULL_FRAME; 1622674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int k = 0; 1623674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int delta; 1624674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (frameCount == 0) { 1625674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen delta = frame[0]; 1626674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1627674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen delta = frame[0] - previousFrame[0] - 1; 1628674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1629674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (cstackSize == 0) { 1630674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen k = clocalsSize - localsSize; 1631674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (k) { 1632674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case -3: 1633674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case -2: 1634674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case -1: 1635674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type = CHOP_FRAME; 1636674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen localsSize = clocalsSize; 1637674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1638674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 0: 1639674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; 1640674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1641674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 1: 1642674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 2: 1643674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 3: 1644674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type = APPEND_FRAME; 1645674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1646674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1647674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (clocalsSize == localsSize && cstackSize == 1) { 1648674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type = delta < 63 1649674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ? SAME_LOCALS_1_STACK_ITEM_FRAME 1650674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; 1651674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1652674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (type != FULL_FRAME) { 1653674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // verify if locals are the same 1654674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int l = 3; 1655674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int j = 0; j < localsSize; j++) { 1656674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (frame[l] != previousFrame[l]) { 1657674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type = FULL_FRAME; 1658674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1659674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1660674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l++; 1661674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1662674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1663674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (type) { 1664674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case SAME_FRAME: 1665674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(delta); 1666674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1667674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case SAME_LOCALS_1_STACK_ITEM_FRAME: 1668674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); 1669674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); 1670674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1671674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: 1672674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) 1673674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(delta); 1674674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); 1675674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1676674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case SAME_FRAME_EXTENDED: 1677674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); 1678674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1679674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case CHOP_FRAME: 1680674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); 1681674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1682674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case APPEND_FRAME: 1683674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); 1684674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameTypes(3 + localsSize, 3 + clocalsSize); 1685674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1686674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // case FULL_FRAME: 1687674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 1688674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(FULL_FRAME) 1689674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(delta) 1690674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(clocalsSize); 1691674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameTypes(3, 3 + clocalsSize); 1692674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putShort(cstackSize); 1693674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); 1694674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1695674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1696674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1697674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1698674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Writes some types of the current frame {@link #frame} into the 1699674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * StackMapTableAttribute. This method converts types from the format used 1700674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * in {@link Label} to the format used in StackMapTable attributes. In 1701674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * particular, it converts type table indexes to constant pool indexes. 1702674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1703674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param start index of the first type in {@link #frame} to write. 1704674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param end index of last type in {@link #frame} to write (exclusive). 1705674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1706674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void writeFrameTypes(final int start, final int end) { 1707674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = start; i < end; ++i) { 1708674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int t = frame[i]; 1709674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int d = t & Frame.DIM; 1710674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (d == 0) { 1711674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int v = t & Frame.BASE_VALUE; 1712674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (t & Frame.BASE_KIND) { 1713674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Frame.OBJECT: 1714674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(7) 1715674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(cw.newClass(cw.typeTable[v].strVal1)); 1716674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1717674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Frame.UNINITIALIZED: 1718674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(8).putShort(cw.typeTable[v].intVal); 1719674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1720674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 1721674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(v); 1722674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1723674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1724674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen StringBuffer buf = new StringBuffer(); 1725674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen d >>= 28; 1726674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (d-- > 0) { 1727674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('['); 1728674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1729674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((t & Frame.BASE_KIND) == Frame.OBJECT) { 1730674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('L'); 1731674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); 1732674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append(';'); 1733674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1734674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (t & 0xF) { 1735674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 1: 1736674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('I'); 1737674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1738674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 2: 1739674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('F'); 1740674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1741674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 3: 1742674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('D'); 1743674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1744674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 9: 1745674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('Z'); 1746674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1747674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 10: 1748674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('B'); 1749674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1750674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 11: 1751674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('C'); 1752674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1753674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 12: 1754674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('S'); 1755674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 1756674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 1757674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buf.append('J'); 1758674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1759674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1760674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(7).putShort(cw.newClass(buf.toString())); 1761674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1762674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1763674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1764674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1765674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void writeFrameType(final Object type) { 1766674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (type instanceof String) { 1767674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(7).putShort(cw.newClass((String) type)); 1768674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (type instanceof Integer) { 1769674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(((Integer) type).intValue()); 1770674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1771674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap.putByte(8).putShort(((Label) type).position); 1772674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1773674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1774674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1775674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 1776674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Utility methods: dump bytecode array 1777674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 1778674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1779674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1780674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns the size of the bytecode of this method. 1781674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1782674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the size of the bytecode of this method. 1783674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1784674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int getSize() { 1785674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (classReaderOffset != 0) { 1786674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return 6 + classReaderLength; 1787674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1788674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (resize) { 1789674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // replaces the temporary jump opcodes introduced by Label.resolve. 1790674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.RESIZE) { 1791674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen resizeInstructions(); 1792674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 1793674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new RuntimeException("Method code too large!"); 1794674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1795674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1796674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size = 8; 1797674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (code.length > 0) { 1798674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("Code"); 1799674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 18 + code.length + 8 * handlerCount; 1800674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVar != null) { 1801674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("LocalVariableTable"); 1802674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + localVar.length; 1803674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1804674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVarType != null) { 1805674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("LocalVariableTypeTable"); 1806674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + localVarType.length; 1807674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1808674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (lineNumber != null) { 1809674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("LineNumberTable"); 1810674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + lineNumber.length; 1811674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1812674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (stackMap != null) { 1813674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; 1814674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8(zip ? "StackMapTable" : "StackMap"); 1815674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + stackMap.length; 1816674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1817674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (cattrs != null) { 1818674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += cattrs.getSize(cw, 1819674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.data, 1820674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.length, 1821674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStack, 1822674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxLocals); 1823674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1824674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1825674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (exceptionCount > 0) { 1826674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("Exceptions"); 1827674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + 2 * exceptionCount; 1828674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1829674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((access & Opcodes.ACC_SYNTHETIC) != 0 1830674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen && (cw.version & 0xffff) < Opcodes.V1_5) 1831674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1832674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("Synthetic"); 1833674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 6; 1834674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1835674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1836674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("Deprecated"); 1837674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 6; 1838674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1839674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.SIGNATURES && signature != null) { 1840674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("Signature"); 1841674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8(signature); 1842674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8; 1843674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1844674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && annd != null) { 1845674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("AnnotationDefault"); 1846674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 6 + annd.length; 1847674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1848674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && anns != null) { 1849674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("RuntimeVisibleAnnotations"); 1850674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + anns.getSize(); 1851674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1852674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && ianns != null) { 1853674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("RuntimeInvisibleAnnotations"); 1854674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + ianns.getSize(); 1855674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1856674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && panns != null) { 1857674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("RuntimeVisibleParameterAnnotations"); 1858674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 7 + 2 * (panns.length - synthetics); 1859674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = panns.length - 1; i >= synthetics; --i) { 1860674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += panns[i] == null ? 0 : panns[i].getSize(); 1861674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1862674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1863674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && ipanns != null) { 1864674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.newUTF8("RuntimeInvisibleParameterAnnotations"); 1865674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 7 + 2 * (ipanns.length - synthetics); 1866674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = ipanns.length - 1; i >= synthetics; --i) { 1867674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += ipanns[i] == null ? 0 : ipanns[i].getSize(); 1868674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1869674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1870674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (attrs != null) { 1871674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += attrs.getSize(cw, null, 0, -1, -1); 1872674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1873674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return size; 1874674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1875674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1876674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 1877674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Puts the bytecode of this method in the given byte vector. 1878674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1879674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param out the byte vector into which the bytecode of this method must be 1880674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * copied. 1881674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 1882674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final void put(final ByteVector out) { 1883674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(access).putShort(name).putShort(desc); 1884674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (classReaderOffset != 0) { 1885674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); 1886674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 1887674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1888674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int attributeCount = 0; 1889674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (code.length > 0) { 1890674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1891674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1892674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (exceptionCount > 0) { 1893674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1894674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1895674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((access & Opcodes.ACC_SYNTHETIC) != 0 1896674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen && (cw.version & 0xffff) < Opcodes.V1_5) 1897674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 1898674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1899674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1900674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1901674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1902674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1903674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.SIGNATURES && signature != null) { 1904674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1905674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1906674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && annd != null) { 1907674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1908674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1909674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && anns != null) { 1910674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1911674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1912674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && ianns != null) { 1913674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1914674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1915674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && panns != null) { 1916674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1917674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1918674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && ipanns != null) { 1919674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1920674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1921674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (attrs != null) { 1922674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attributeCount += attrs.getCount(); 1923674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1924674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(attributeCount); 1925674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (code.length > 0) { 1926674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int size = 12 + code.length + 8 * handlerCount; 1927674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVar != null) { 1928674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + localVar.length; 1929674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1930674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVarType != null) { 1931674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + localVarType.length; 1932674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1933674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (lineNumber != null) { 1934674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + lineNumber.length; 1935674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1936674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (stackMap != null) { 1937674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += 8 + stackMap.length; 1938674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1939674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (cattrs != null) { 1940674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen size += cattrs.getSize(cw, 1941674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.data, 1942674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code.length, 1943674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxStack, 1944674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen maxLocals); 1945674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1946674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("Code")).putInt(size); 1947674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(maxStack).putShort(maxLocals); 1948674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(code.length).putByteArray(code.data, 0, code.length); 1949674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(handlerCount); 1950674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (handlerCount > 0) { 1951674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Handler h = firstHandler; 1952674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (h != null) { 1953674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(h.start.position) 1954674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(h.end.position) 1955674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(h.handler.position) 1956674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(h.type); 1957674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h = h.next; 1958674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1959674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1960674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attributeCount = 0; 1961674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVar != null) { 1962674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1963674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1964674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVarType != null) { 1965674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1966674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1967674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (lineNumber != null) { 1968674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1969674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1970674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (stackMap != null) { 1971674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ++attributeCount; 1972674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1973674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (cattrs != null) { 1974674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attributeCount += cattrs.getCount(); 1975674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1976674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(attributeCount); 1977674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVar != null) { 1978674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("LocalVariableTable")); 1979674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(localVar.length + 2).putShort(localVarCount); 1980674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putByteArray(localVar.data, 0, localVar.length); 1981674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1982674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (localVarType != null) { 1983674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("LocalVariableTypeTable")); 1984674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(localVarType.length + 2).putShort(localVarTypeCount); 1985674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putByteArray(localVarType.data, 0, localVarType.length); 1986674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1987674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (lineNumber != null) { 1988674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("LineNumberTable")); 1989674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(lineNumber.length + 2).putShort(lineNumberCount); 1990674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putByteArray(lineNumber.data, 0, lineNumber.length); 1991674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1992674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (stackMap != null) { 1993674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; 1994674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap")); 1995674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(stackMap.length + 2).putShort(frameCount); 1996674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putByteArray(stackMap.data, 0, stackMap.length); 1997674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1998674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (cattrs != null) { 1999674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); 2000674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2001674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2002674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (exceptionCount > 0) { 2003674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("Exceptions")) 2004674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putInt(2 * exceptionCount + 2); 2005674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(exceptionCount); 2006674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < exceptionCount; ++i) { 2007674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(exceptions[i]); 2008674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2009674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2010674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((access & Opcodes.ACC_SYNTHETIC) != 0 2011674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen && (cw.version & 0xffff) < Opcodes.V1_5) 2012674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 2013674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("Synthetic")).putInt(0); 2014674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2015674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((access & Opcodes.ACC_DEPRECATED) != 0) { 2016674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("Deprecated")).putInt(0); 2017674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2018674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.SIGNATURES && signature != null) { 2019674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("Signature")) 2020674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putInt(2) 2021674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen .putShort(cw.newUTF8(signature)); 2022674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2023674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && annd != null) { 2024674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("AnnotationDefault")); 2025674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(annd.length); 2026674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putByteArray(annd.data, 0, annd.length); 2027674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2028674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && anns != null) { 2029674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); 2030674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen anns.put(out); 2031674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2032674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && ianns != null) { 2033674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); 2034674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ianns.put(out); 2035674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2036674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && panns != null) { 2037674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); 2038674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen AnnotationWriter.put(panns, synthetics, out); 2039674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2040674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (ClassReader.ANNOTATIONS && ipanns != null) { 2041674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); 2042674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen AnnotationWriter.put(ipanns, synthetics, out); 2043674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2044674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (attrs != null) { 2045674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attrs.put(cw, null, 0, -1, -1, out); 2046674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2047674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2048674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2049674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 2050674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W) 2051674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 2052674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2053674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 2054674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Resizes and replaces the temporary instructions inserted by 2055674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link Label#resolve} for wide forward jumps, while keeping jump offsets 2056674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * and instruction addresses consistent. This may require to resize other 2057674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * existing instructions, or even to introduce new instructions: for 2058674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * example, increasing the size of an instruction by 2 at the middle of a 2059674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method can increases the offset of an IFEQ instruction from 32766 to 2060674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W 2061674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 32765. This, in turn, may require to increase the size of another jump 2062674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction, and so on... All these operations are handled automatically 2063674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * by this method. <p> <i>This method must be called after all the method 2064674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * that is being built has been visited</i>. In particular, the 2065674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link Label Label} objects used to construct the method are no longer 2066674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * valid after this method has been called. 2067674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2068674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void resizeInstructions() { 2069674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen byte[] b = code.data; // bytecode of the method 2070674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int u, v, label; // indexes in b 2071674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int i, j; // loop indexes 2072674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 2073674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1st step: As explained above, resizing an instruction may require to 2074674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * resize another one, which may require to resize yet another one, and 2075674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * so on. The first step of the algorithm consists in finding all the 2076674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instructions that need to be resized, without modifying the code. 2077674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This is done by the following "fix point" algorithm: 2078674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2079674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Parse the code to find the jump instructions whose offset will need 2080674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * more than 2 bytes to be stored (the future offset is computed from 2081674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the current offset and from the number of bytes that will be inserted 2082674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * or removed between the source and target instructions). For each such 2083674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction, adds an entry in (a copy of) the indexes and sizes 2084674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * arrays (if this has not already been done in a previous iteration!). 2085674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2086674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * If at least one entry has been added during the previous step, go 2087674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * back to the beginning, otherwise stop. 2088674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2089674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * In fact the real algorithm is complicated by the fact that the size 2090674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of TABLESWITCH and LOOKUPSWITCH instructions depends on their 2091674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * position in the bytecode (because of padding). In order to ensure the 2092674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * convergence of the algorithm, the number of bytes to be added or 2093674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * removed from these instructions is over estimated during the previous 2094674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * loop, and computed exactly only after the loop is finished (this 2095674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * requires another pass to parse the bytecode of the method). 2096674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2097674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] allIndexes = new int[0]; // copy of indexes 2098674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] allSizes = new int[0]; // copy of sizes 2099674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean[] resize; // instructions to be resized 2100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int newOffset; // future offset of a jump instruction 2101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen resize = new boolean[code.length]; 2103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done 2105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int state = 3; 2106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen do { 2107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (state == 3) { 2108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen state = 2; 2109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = 0; 2111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (u < b.length) { 2112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int opcode = b[u] & 0xFF; // opcode of current instruction 2113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int insert = 0; // bytes to be added after this instruction 2114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (ClassWriter.TYPE[opcode]) { 2116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.NOARG_INSN: 2117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.IMPLVAR_INSN: 2118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 1; 2119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LABEL_INSN: 2121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode > 201) { 2122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // converts temporary opcodes 202 to 217, 218 and 2123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // 219 to IFEQ ... JSR (inclusive), IFNULL and 2124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // IFNONNULL 2125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen opcode = opcode < 218 ? opcode - 49 : opcode - 20; 2126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = u + readUnsignedShort(b, u + 1); 2127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = u + readShort(b, u + 1); 2129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, u, label); 2131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (newOffset < Short.MIN_VALUE 2132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || newOffset > Short.MAX_VALUE) 2133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 2134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!resize[u]) { 2135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.GOTO 2136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen || opcode == Opcodes.JSR) 2137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 2138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // two additional bytes will be required to 2139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // replace this GOTO or JSR instruction with 2140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // a GOTO_W or a JSR_W 2141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insert = 2; 2142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // five additional bytes will be required to 2144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // replace this IFxxx <l> instruction with 2145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx 2146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // is the "opposite" opcode of IFxxx (i.e., 2147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // IFNE for IFEQ) and where <l'> designates 2148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // the instruction just after the GOTO_W. 2149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insert = 5; 2150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen resize[u] = true; 2152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 3; 2155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LABELW_INSN: 2157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 5; 2158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.TABL_INSN: 2160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (state == 1) { 2161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // true number of bytes to be added (or removed) 2162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // from this instruction = (future number of padding 2163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // bytes - current number of padding byte) - 2164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // previously over estimated variation = 2165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // = ((3 - newOffset%4) - (3 - u%4)) - u%4 2166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // = (-newOffset%4 + u%4) - u%4 2167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // = -(newOffset & 3) 2168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, 0, u); 2169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insert = -(newOffset & 3); 2170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (!resize[u]) { 2171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // over estimation of the number of bytes to be 2172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // added to this instruction = 3 - current number 2173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 2174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insert = u & 3; 2175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen resize[u] = true; 2176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // skips instruction 2178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = u + 4 - (u & 3); 2179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; 2180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LOOK_INSN: 2182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (state == 1) { 2183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // like TABL_INSN 2184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, 0, u); 2185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insert = -(newOffset & 3); 2186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (!resize[u]) { 2187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // like TABL_INSN 2188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen insert = u & 3; 2189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen resize[u] = true; 2190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // skips instruction 2192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = u + 4 - (u & 3); 2193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 8 * readInt(b, u + 4) + 8; 2194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.WIDE_INSN: 2196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen opcode = b[u + 1] & 0xFF; 2197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.IINC) { 2198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 6; 2199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.VAR_INSN: 2204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.SBYTE_INSN: 2205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LDC_INSN: 2206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 2; 2207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.SHORT_INSN: 2209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LDCW_INSN: 2210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.FIELDORMETH_INSN: 2211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.TYPE_INSN: 2212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.IINC_INSN: 2213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 3; 2214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.ITFMETH_INSN: 2216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 5; 2217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // case ClassWriter.MANA_INSN: 2219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 2220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insert != 0) { 2224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds a new (u, insert) entry in the allIndexes and 2225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // allSizes arrays 2226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] newIndexes = new int[allIndexes.length + 1]; 2227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] newSizes = new int[allSizes.length + 1]; 2228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen System.arraycopy(allIndexes, 2229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 0, 2230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newIndexes, 2231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 0, 2232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen allIndexes.length); 2233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); 2234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newIndexes[allIndexes.length] = u; 2235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newSizes[allSizes.length] = insert; 2236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen allIndexes = newIndexes; 2237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen allSizes = newSizes; 2238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (insert > 0) { 2239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen state = 3; 2240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (state < 3) { 2244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen --state; 2245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } while (state != 0); 2247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // 2nd step: 2249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // copies the bytecode of the method into a new bytevector, updates the 2250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // offsets, and inserts (or removes) bytes as requested. 2251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ByteVector newCode = new ByteVector(code.length); 2253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = 0; 2255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (u < code.length) { 2256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int opcode = b[u] & 0xFF; 2257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (ClassWriter.TYPE[opcode]) { 2258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.NOARG_INSN: 2259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.IMPLVAR_INSN: 2260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(opcode); 2261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 1; 2262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LABEL_INSN: 2264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode > 201) { 2265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // changes temporary opcodes 202 to 217 (inclusive), 218 2266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // and 219 to IFEQ ... JSR (inclusive), IFNULL and 2267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // IFNONNULL 2268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen opcode = opcode < 218 ? opcode - 49 : opcode - 20; 2269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = u + readUnsignedShort(b, u + 1); 2270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = u + readShort(b, u + 1); 2272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, u, label); 2274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (resize[u]) { 2275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx 2276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is 2277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) 2278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // and where <l'> designates the instruction just after 2279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // the GOTO_W. 2280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.GOTO) { 2281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(200); // GOTO_W 2282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (opcode == Opcodes.JSR) { 2283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(201); // JSR_W 2284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(opcode <= 166 2286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ? ((opcode + 1) ^ 1) - 1 2287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen : opcode ^ 1); 2288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putShort(8); // jump offset 2289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(200); // GOTO_W 2290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // newOffset now computed from start of GOTO_W 2291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset -= 3; 2292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(newOffset); 2294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(opcode); 2296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putShort(newOffset); 2297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 3; 2299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LABELW_INSN: 2301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = u + readInt(b, u + 1); 2302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, u, label); 2303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(opcode); 2304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(newOffset); 2305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 5; 2306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.TABL_INSN: 2308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // skips 0 to 3 padding bytes 2309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen v = u; 2310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = u + 4 - (v & 3); 2311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // reads and copies instruction 2312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(Opcodes.TABLESWITCH); 2313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.length += (4 - newCode.length % 4) % 4; 2314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = v + readInt(b, u); 2315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, v, label); 2317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(newOffset); 2318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen j = readInt(b, u); 2319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(j); 2321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen j = readInt(b, u) - j + 1; 2322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(readInt(b, u - 4)); 2324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (; j > 0; --j) { 2325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = v + readInt(b, u); 2326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, v, label); 2328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(newOffset); 2329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LOOK_INSN: 2332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // skips 0 to 3 padding bytes 2333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen v = u; 2334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = u + 4 - (v & 3); 2335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // reads and copies instruction 2336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByte(Opcodes.LOOKUPSWITCH); 2337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.length += (4 - newCode.length % 4) % 4; 2338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = v + readInt(b, u); 2339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, v, label); 2341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(newOffset); 2342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen j = readInt(b, u); 2343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(j); 2345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (; j > 0; --j) { 2346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(readInt(b, u)); 2347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = v + readInt(b, u); 2349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, v, label); 2351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putInt(newOffset); 2352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.WIDE_INSN: 2355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen opcode = b[u + 1] & 0xFF; 2356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode == Opcodes.IINC) { 2357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByteArray(b, u, 6); 2358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 6; 2359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByteArray(b, u, 4); 2361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.VAR_INSN: 2365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.SBYTE_INSN: 2366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LDC_INSN: 2367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByteArray(b, u, 2); 2368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 2; 2369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.SHORT_INSN: 2371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.LDCW_INSN: 2372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.FIELDORMETH_INSN: 2373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.TYPE_INSN: 2374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.IINC_INSN: 2375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByteArray(b, u, 3); 2376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 3; 2377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case ClassWriter.ITFMETH_INSN: 2379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByteArray(b, u, 5); 2380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 5; 2381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // case MANA_INSN: 2383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 2384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newCode.putByteArray(b, u, 4); 2385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 2387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // recomputes the stack map frames 2391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (frameCount > 0) { 2392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (compute == FRAMES) { 2393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frameCount = 0; 2394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stackMap = null; 2395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen previousFrame = null; 2396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen frame = null; 2397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame f = new Frame(); 2398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen f.owner = labels; 2399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] args = Type.getArgumentTypes(descriptor); 2400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen f.initInputFrame(cw, access, args, maxLocals); 2401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitFrame(f); 2402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label l = labels; 2403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (l != null) { 2404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 2405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * here we need the original label position. getNewOffset 2406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * must therefore never have been called for this label. 2407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = l.position - 3; 2409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) 2410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 2411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getNewOffset(allIndexes, allSizes, l); 2412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // TODO update offsets in UNINITIALIZED values 2413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen visitFrame(l.frame); 2414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen l = l.successor; 2416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 2418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 2419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Resizing an existing stack map frame table is really hard. 2420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Not only the table must be parsed to update the offets, but 2421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * new frames may be needed for jump instructions that were 2422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * inserted by this method. And updating the offsets or 2423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * inserting frames can change the format of the following 2424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * frames, in case of packed frames. In practice the whole table 2425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * must be recomputed. For this the frames are marked as 2426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * potentially invalid. This will cause the whole class to be 2427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * reread and rewritten with the COMPUTE_FRAMES option (see the 2428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ClassWriter.toByteArray method). This is not very efficient 2429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * but is much easier and requires much less code than any other 2430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method I can think of. 2431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cw.invalidFrames = true; 2433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the exception handler block labels 2436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Handler h = firstHandler; 2437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (h != null) { 2438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getNewOffset(allIndexes, allSizes, h.start); 2439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getNewOffset(allIndexes, allSizes, h.end); 2440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getNewOffset(allIndexes, allSizes, h.handler); 2441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen h = h.next; 2442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the instructions addresses in the 2444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // local var and line number tables 2445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (i = 0; i < 2; ++i) { 2446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ByteVector bv = i == 0 ? localVar : localVarType; 2447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (bv != null) { 2448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b = bv.data; 2449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = 0; 2450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (u < bv.length) { 2451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label = readUnsignedShort(b, u); 2452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, 0, label); 2453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeShort(b, u, newOffset); 2454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label += readUnsignedShort(b, u + 2); 2455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen newOffset = getNewOffset(allIndexes, allSizes, 0, label) 2456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen - newOffset; 2457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeShort(b, u + 2, newOffset); 2458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 10; 2459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (lineNumber != null) { 2463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b = lineNumber.data; 2464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u = 0; 2465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (u < lineNumber.length) { 2466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen writeShort(b, u, getNewOffset(allIndexes, 2467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen allSizes, 2468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 0, 2469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen readUnsignedShort(b, u))); 2470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen u += 4; 2471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // updates the labels of the other attributes 2474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Attribute attr = cattrs; 2475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (attr != null) { 2476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label[] labels = attr.getLabels(); 2477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (labels != null) { 2478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (i = labels.length - 1; i >= 0; --i) { 2479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getNewOffset(allIndexes, allSizes, labels[i]); 2480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen attr = attr.next; 2483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // replaces old bytecodes with new ones 2486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen code = newCode; 2487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 2490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Reads an unsigned short value in the given byte array. 2491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param b a byte array. 2493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param index the start index of the value to be read. 2494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the read value. 2495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static int readUnsignedShort(final byte[] b, final int index) { 2497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 2498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 2501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Reads a signed short value in the given byte array. 2502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param b a byte array. 2504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param index the start index of the value to be read. 2505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the read value. 2506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static short readShort(final byte[] b, final int index) { 2508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 2509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 2512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Reads a signed int value in the given byte array. 2513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param b a byte array. 2515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param index the start index of the value to be read. 2516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the read value. 2517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static int readInt(final byte[] b, final int index) { 2519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) 2520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); 2521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 2524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Writes a short value in the given byte array. 2525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param b a byte array. 2527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param index where the first byte of the short value must be written. 2528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param s the value to be written in the given byte array. 2529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static void writeShort(final byte[] b, final int index, final int s) { 2531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b[index] = (byte) (s >>> 8); 2532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen b[index + 1] = (byte) s; 2533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 2536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Computes the future value of a bytecode offset. <p> Note: it is possible 2537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * to have several entries for the same instruction in the <tt>indexes</tt> 2538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b') 2539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are equivalent to a single entry (index=a,size=b+b'). 2540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param indexes current positions of the instructions to be resized. Each 2542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction must be designated by the index of its <i>last</i> 2543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * byte, plus one (or, in other words, by the index of the <i>first</i> 2544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * byte of the <i>next</i> instruction). 2545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param sizes the number of bytes to be <i>added</i> to the above 2546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instructions. More precisely, for each i < <tt>len</tt>, 2547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>sizes</tt>[i] bytes will be added at the end of the 2548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction designated by <tt>indexes</tt>[i] or, if 2549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>| 2550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * bytes of the instruction will be removed (the instruction size 2551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <i>must not</i> become negative or null). 2552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param begin index of the first byte of the source instruction. 2553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param end index of the first byte of the target instruction. 2554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the future value of the given bytecode offset. 2555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static int getNewOffset( 2557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int[] indexes, 2558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int[] sizes, 2559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int begin, 2560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int end) 2561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 2562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int offset = end - begin; 2563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < indexes.length; ++i) { 2564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (begin < indexes[i] && indexes[i] <= end) { 2565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // forward jump 2566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen offset += sizes[i]; 2567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (end < indexes[i] && indexes[i] <= begin) { 2568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // backward jump 2569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen offset -= sizes[i]; 2570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return offset; 2573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 2575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 2576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Updates the offset of the given label. 2577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param indexes current positions of the instructions to be resized. Each 2579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction must be designated by the index of its <i>last</i> 2580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * byte, plus one (or, in other words, by the index of the <i>first</i> 2581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * byte of the <i>next</i> instruction). 2582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param sizes the number of bytes to be <i>added</i> to the above 2583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instructions. More precisely, for each i < <tt>len</tt>, 2584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>sizes</tt>[i] bytes will be added at the end of the 2585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction designated by <tt>indexes</tt>[i] or, if 2586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>| 2587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * bytes of the instruction will be removed (the instruction size 2588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <i>must not</i> become negative or null). 2589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param label the label whose offset must be updated. 2590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 2591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static void getNewOffset( 2592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int[] indexes, 2593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int[] sizes, 2594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label label) 2595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 2596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((label.status & Label.RESIZED) == 0) { 2597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.position = getNewOffset(indexes, sizes, 0, label.position); 2598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen label.status |= Label.RESIZED; 2599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 2601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen} 2602