View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.javaflow.bytecode.transformation.bcel.analyser;
18  
19  import org.apache.bcel.generic.Type;
20  import org.apache.bcel.verifier.exc.AssertionViolatedException;
21  
22  import java.util.Arrays;
23  
24  /**
25   * This class implements an array of local variables used for symbolic JVM
26   * simulation.
27   * 
28   * WARNING! These classes are a fork of the bcel verifier.
29   *
30   * @version $Id: LocalVariables.java 480487 2006-11-29 08:54:42Z bayard $
31   * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
32   */
33  public class LocalVariables{
34      /** The Type[] containing the local variable slots. */
35      private Type[] locals;
36  
37      /**
38       * Creates a new LocalVariables object.
39       */
40      public LocalVariables(int maxLocals){
41          locals = new Type[maxLocals];
42          Arrays.fill(locals,Type.UNKNOWN);
43      }
44  
45      /**
46       * Returns a deep copy of this object; i.e. the clone
47       * operates on a new local variable array.
48       * However, the Type objects in the array are shared.
49       */
50      protected Object clone(){
51          LocalVariables lvs = new LocalVariables(locals.length);
52          System.arraycopy(this.locals, 0, lvs.locals, 0, locals.length);
53          return lvs;
54      }
55  
56      /**
57       * Returns the type of the local variable slot i.
58       */
59      public Type get(int i){
60          return locals[i];
61      }
62  
63      /**
64       * Returns a (correctly typed) clone of this object.
65       * This is equivalent to ((LocalVariables) this.clone()).
66       */
67      public LocalVariables getClone(){
68          return (LocalVariables) this.clone();
69      }
70  
71      /**
72       * Returns the number of local variable slots this
73       * LocalVariables instance has.
74       */
75      public int maxLocals(){
76          return locals.length;
77      }
78  
79      /**
80       * Sets a new Type for the given local variable slot.
81       */
82      public void set(int i, Type type){
83          if (type == Type.BYTE || type == Type.SHORT || type == Type.BOOLEAN || type == Type.CHAR){
84              throw new AssertionViolatedException("LocalVariables do not know about '"+type+"'. Use Type.INT instead.");
85          }
86          locals[i] = type;
87      }
88  
89      /*
90        * Fulfills the general contract of Object.equals().
91        */
92      public boolean equals(Object o){
93          if (!(o instanceof LocalVariables)) return false;
94          LocalVariables lv = (LocalVariables) o;
95          return Arrays.equals(this.locals, lv.locals);
96      }
97  
98      /**
99       * Merges two local variables sets as described in the Java Virtual Machine Specification,
100      * Second Edition, section 4.9.2, page 146.
101      */
102     public void merge(LocalVariables that){
103 
104         if (this.locals.length != that.locals.length){
105             throw new AssertionViolatedException("Merging LocalVariables of different size?!? From different methods or what?!?");
106         }
107 
108         for (int i=0; i<locals.length; i++) {
109             this.locals[i] = Frame.merge(this.locals[i], that.locals[i], false);
110         }
111     }
112 
113 
114     /**
115      * Returns a String representation of this object.
116      */
117     public String toString(){
118         String s = "";
119         for (int i=0; i<locals.length; i++){
120             s += Integer.toString(i)+": "+locals[i]+"\n";
121         }
122         return s;
123     }
124 
125     /**
126      * Replaces all occurences of u in this local variables set
127      * with an "initialized" ObjectType.
128      */
129     public void initializeObject(UninitializedObjectType u){
130         for (int i=0; i<locals.length; i++){
131             if (locals[i] == u){
132                 locals[i] = u.getInitialized();
133             }
134         }
135     }
136 }