View Javadoc
1   /*
2    * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   *
23   */
24  
25  package sun.jvm.hotspot.runtime;
26  
27  import java.io.*;
28  import java.util.*;
29  
30  import sun.jvm.hotspot.debugger.*;
31  import sun.jvm.hotspot.interpreter.*;
32  import sun.jvm.hotspot.code.*;
33  import sun.jvm.hotspot.types.*;
34  import sun.jvm.hotspot.utilities.*;
35  
36  /** <P> A companion structure used for stack traversal. The
37      RegisterMap contains misc. information needed in order to do
38      correct stack traversal of stack frames.  Hence, it must always be
39      passed in as an argument to Frame.sender(RegisterMap). </P>
40  
41      <P> The use of RegisterMaps is slightly different in the
42      Serviceability Agent APIs than in the VM itself. In the VM, a
43      RegisterMap is created either for a particular thread or cloned
44      from another RegisterMap. In these APIs, a JavaThread is the
45      top-level factory for RegisterMaps, and RegisterMaps know how to
46      copy themselves (through either the clone() or copy()
47      methods). </P> */
48  
49  public abstract class RegisterMap implements Cloneable {
50    /** Location of registers */
51    protected Address[]  location;
52    // FIXME: don't know about LocationValidType
53    protected long[]     locationValid;
54    /** Should include argument_oop marked locations for compiler */
55    protected boolean    includeArgumentOops;
56    /** Reference to current thread */
57    protected JavaThread thread;
58    /** Tells if the register map needs to be updated when traversing the stack */
59    protected boolean    updateMap;
60    /** Location of a frame where the pc is not at a call (NULL if no frame exists) */
61    protected static int regCount;
62    protected static int locationValidTypeSize;
63    protected static int locationValidSize;
64  
65    static {
66      VM.registerVMInitializedObserver(new Observer() {
67          public void update(Observable o, Object data) {
68            initialize(VM.getVM().getTypeDataBase());
69          }
70        });
71    }
72  
73    private static void initialize(TypeDataBase db) {
74      regCount = db.lookupIntConstant("ConcreteRegisterImpl::number_of_registers").intValue();
75      // FIXME: don't know about LocationValidType. The LocationValidType is typedef'ed as julong
76      // so used julong to get the size of LocationValidType.
77      locationValidTypeSize = (int)db.lookupType("julong").getSize() * 8;
78      locationValidSize = (regCount + locationValidTypeSize - 1) / locationValidTypeSize;
79    }
80  
81    protected RegisterMap(JavaThread thread, boolean updateMap) {
82      this.thread    = thread;
83      this.updateMap = updateMap;
84      location      = new Address[regCount];
85      locationValid = new long[locationValidSize];
86      clear();
87    }
88  
89    /** Makes a copy of map into this */
90    protected RegisterMap(RegisterMap map) {
91      if (Assert.ASSERTS_ENABLED) {
92        Assert.that(map != null, "RegisterMap must be present");
93      }
94      this.thread              = map.getThread();
95      this.updateMap           = map.getUpdateMap();
96      this.includeArgumentOops = map.getIncludeArgumentOops();
97      location                 = new Address[map.location.length];
98      locationValid            = new long[map.locationValid.length];
99      initializeFromPD(map);
100     if (updateMap) {
101       for (int i = 0; i < locationValidSize; i++) {
102         long bits = (!getUpdateMap()) ? 0 : map.locationValid[i];
103         locationValid[i] = bits;
104         // for whichever bits are set, pull in the corresponding map->_location
105         int j = i*locationValidTypeSize;
106         while (bits != 0) {
107           if ((bits & 1) != 0) {
108             if (Assert.ASSERTS_ENABLED) {
109               Assert.that(0 <= j && j < regCount, "range check");
110             }
111             location[j] = map.location[j];
112           }
113           bits >>>= 1;
114           j += 1;
115         }
116       }
117     }
118   }
119 
120   public abstract Object clone();
121 
122   public RegisterMap copy() {
123     return (RegisterMap) clone();
124   }
125 
126   public void clear() {
127     setIncludeArgumentOops(true);
128     if (!VM.getVM().isCore()) {
129       if (updateMap) {
130         for (int i = 0; i < locationValid.length; i++) {
131           locationValid[i] = 0;
132         }
133         clearPD();
134       } else {
135         initializePD();
136       }
137     }
138   }
139 
140   public Address getLocation(VMReg reg) {
141     int i = reg.getValue();
142     int index = i / locationValidTypeSize;
143     if (Assert.ASSERTS_ENABLED) {
144       Assert.that(0 <= i && i < regCount, "sanity check");
145       Assert.that(0 <= index && index < locationValidSize, "sanity check");
146     }
147     if ((locationValid[index] & (1 << i % locationValidTypeSize)) != 0) {
148       return location[i];
149     } else {
150       return getLocationPD(reg);
151     }
152   }
153 
154   public void setLocation(VMReg reg, Address loc) {
155     int i = reg.getValue();
156     int index = i / locationValidTypeSize;
157     if (Assert.ASSERTS_ENABLED) {
158       Assert.that(0 <= i && i < regCount, "sanity check");
159       Assert.that(0 <= index && index < locationValidSize, "sanity check");
160       Assert.that(updateMap, "updating map that does not need updating");
161     }
162     location[i]          = loc;
163     locationValid[index] |= (1 << (i % locationValidTypeSize));
164   }
165 
166   public boolean getIncludeArgumentOops() {
167     return includeArgumentOops;
168   }
169 
170   public void setIncludeArgumentOops(boolean f) {
171     includeArgumentOops = f;
172   }
173 
174   public JavaThread getThread() {
175     return thread;
176   }
177 
178   public boolean getUpdateMap() {
179     return updateMap;
180   }
181 
182   public void print() {
183     printOn(System.out);
184   }
185 
186   public void printOn(PrintStream tty) {
187     tty.println("Register map");
188     for (int i = 0; i < location.length; i++) {
189       Address src = getLocation(new VMReg(i));
190       if (src != null) {
191         tty.print("  " + VMRegImpl.getRegisterName(i) +
192                   " [" + src + "] = ");
193         if (src.andWithMask(VM.getVM().getAddressSize() - 1) != null) {
194           tty.print("<misaligned>");
195         } else {
196           tty.print(src.getAddressAt(0));
197         }
198       }
199     }
200   }
201 
202   /** Platform-dependent clear() functionality */
203   protected abstract void clearPD();
204   /** Platform-dependent initialize() functionality */
205   protected abstract void initializePD();
206   /** Platform-dependent initializeFrom() functionality */
207   protected abstract void initializeFromPD(RegisterMap map);
208   /** Platform-dependent getLocation() functionality */
209   protected abstract Address getLocationPD(VMReg reg);
210 }