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
25package sun.jvm.hotspot.runtime;
26
27import java.io.*;
28import java.util.*;
29
30import sun.jvm.hotspot.debugger.*;
31import sun.jvm.hotspot.interpreter.*;
32import sun.jvm.hotspot.code.*;
33import sun.jvm.hotspot.types.*;
34import 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
49public 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}
211