Save This Page
Home » cglib-src-2.2 » net.sf.cglib.core » [javadoc | source]
    1   /***
    2    * ASM: a very small and fast Java bytecode manipulation framework
    3    * Copyright (c) 2000-2005 INRIA, France Telecom
    4    * All rights reserved.
    5    *
    6    * Redistribution and use in source and binary forms, with or without
    7    * modification, are permitted provided that the following conditions
    8    * are met:
    9    * 1. Redistributions of source code must retain the above copyright
   10    *    notice, this list of conditions and the following disclaimer.
   11    * 2. Redistributions in binary form must reproduce the above copyright
   12    *    notice, this list of conditions and the following disclaimer in the
   13    *    documentation and/or other materials provided with the distribution.
   14    * 3. Neither the name of the copyright holders nor the names of its
   15    *    contributors may be used to endorse or promote products derived from
   16    *    this software without specific prior written permission.
   17    *
   18    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   19    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21    * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   22    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   23    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   28    * THE POSSIBILITY OF SUCH DAMAGE.
   29    */
   30   package net.sf.cglib.core;
   31   
   32   import org.objectweb.asm.Label;
   33   import org.objectweb.asm.MethodAdapter;
   34   import org.objectweb.asm.MethodVisitor;
   35   import org.objectweb.asm.Opcodes;
   36   import org.objectweb.asm.Type;
   37   
   38   /**
   39    * A {@link MethodAdapter} that renumbers local variables in their order of
   40    * appearance. This adapter allows one to easily add new local variables to a
   41    * method.
   42    * 
   43    * @author Chris Nokleberg
   44    * @author Eric Bruneton
   45    */
   46   public class LocalVariablesSorter extends MethodAdapter {
   47   
   48       /**
   49        * Mapping from old to new local variable indexes. A local variable at index
   50        * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
   51        * index i of size 2 is remapped to 'mapping[2*i+1]'.
   52        */
   53       private static class State
   54       {
   55           int[] mapping = new int[40];        
   56           int nextLocal;
   57       }
   58   
   59       protected final int firstLocal;
   60       private final State state;
   61   
   62       public LocalVariablesSorter(
   63           final int access,
   64           final String desc,
   65           final MethodVisitor mv)
   66       {
   67           super(mv);
   68           state = new State();
   69           Type[] args = Type.getArgumentTypes(desc);
   70           state.nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1;
   71           for (int i = 0; i < args.length; i++) {
   72               state.nextLocal += args[i].getSize();
   73           }
   74           firstLocal = state.nextLocal;
   75       }
   76   
   77       public LocalVariablesSorter(LocalVariablesSorter lvs) {
   78           super(lvs.mv);
   79           state = lvs.state;
   80           firstLocal = lvs.firstLocal;
   81       }
   82   
   83       public void visitVarInsn(final int opcode, final int var) {
   84           int size;
   85           switch (opcode) {
   86               case Opcodes.LLOAD:
   87               case Opcodes.LSTORE:
   88               case Opcodes.DLOAD:
   89               case Opcodes.DSTORE:
   90                   size = 2;
   91                   break;
   92               default:
   93                   size = 1;
   94           }
   95           mv.visitVarInsn(opcode, remap(var, size));
   96       }
   97   
   98       public void visitIincInsn(final int var, final int increment) {
   99           mv.visitIincInsn(remap(var, 1), increment);
  100       }
  101   
  102       public void visitMaxs(final int maxStack, final int maxLocals) {
  103           mv.visitMaxs(maxStack, state.nextLocal);
  104       }
  105   
  106       public void visitLocalVariable(
  107           final String name,
  108           final String desc,
  109           final String signature,
  110           final Label start,
  111           final Label end,
  112           final int index)
  113       {
  114           mv.visitLocalVariable(name, desc, signature, start, end, remap(index));
  115       }
  116   
  117       // -------------
  118   
  119       protected int newLocal(final int size) {
  120           int var = state.nextLocal;
  121           state.nextLocal += size;
  122           return var;
  123       }
  124   
  125       private int remap(final int var, final int size) {
  126           if (var < firstLocal) {
  127               return var;
  128           }
  129           int key = 2 * var + size - 1;
  130           int length = state.mapping.length;
  131           if (key >= length) {
  132               int[] newMapping = new int[Math.max(2 * length, key + 1)];
  133               System.arraycopy(state.mapping, 0, newMapping, 0, length);
  134               state.mapping = newMapping;
  135           }
  136           int value = state.mapping[key];
  137           if (value == 0) {
  138               value = state.nextLocal + 1;
  139               state.mapping[key] = value;
  140               state.nextLocal += size;
  141           }
  142           return value - 1;
  143       }
  144   
  145       private int remap(final int var) {
  146           if (var < firstLocal) {
  147               return var;
  148           }
  149           int key = 2 * var;
  150           int value = key < state.mapping.length ? state.mapping[key] : 0;
  151           if (value == 0) {
  152               value = key + 1 < state.mapping.length ? state.mapping[key + 1] : 0;
  153           }
  154           if (value == 0) {
  155               throw new IllegalStateException("Unknown local variable " + var);
  156           }
  157           return value - 1;
  158       }
  159   }

Save This Page
Home » cglib-src-2.2 » net.sf.cglib.core » [javadoc | source]