1/*
2 * Copyright (c) 2015, 2016, 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 */
23package sun.jvm.hotspot.code;
24
25import sun.jvm.hotspot.compiler.ImmutableOopMap;
26import sun.jvm.hotspot.compiler.ImmutableOopMapSet;
27import sun.jvm.hotspot.debugger.Address;
28import sun.jvm.hotspot.runtime.VM;
29import sun.jvm.hotspot.runtime.VMObject;
30import sun.jvm.hotspot.types.AddressField;
31import sun.jvm.hotspot.types.CIntegerField;
32import sun.jvm.hotspot.types.Type;
33import sun.jvm.hotspot.types.TypeDataBase;
34import sun.jvm.hotspot.utilities.Assert;
35import sun.jvm.hotspot.utilities.CStringUtilities;
36
37import java.io.PrintStream;
38import java.util.Observable;
39import java.util.Observer;
40
41public class CodeBlob extends VMObject {
42  private static AddressField nameField;
43  private static CIntegerField sizeField;
44  private static CIntegerField headerSizeField;
45  private static AddressField  contentBeginField;
46  private static AddressField  codeBeginField;
47  private static AddressField  codeEndField;
48  private static AddressField  dataEndField;
49  private static CIntegerField frameCompleteOffsetField;
50  private static CIntegerField dataOffsetField;
51  private static CIntegerField frameSizeField;
52  private static AddressField  oopMapsField;
53
54  public CodeBlob(Address addr) {
55    super(addr);
56  }
57
58  protected static       int     matcherInterpreterFramePointerReg;
59
60  private static void initialize(TypeDataBase db) {
61    Type type = db.lookupType("CodeBlob");
62
63    nameField                = type.getAddressField("_name");
64    sizeField                = type.getCIntegerField("_size");
65    headerSizeField          = type.getCIntegerField("_header_size");
66    frameCompleteOffsetField = type.getCIntegerField("_frame_complete_offset");
67    contentBeginField        = type.getAddressField("_content_begin");
68    codeBeginField           = type.getAddressField("_code_begin");
69    codeEndField             = type.getAddressField("_code_end");
70    dataEndField             = type.getAddressField("_data_end");
71    dataOffsetField          = type.getCIntegerField("_data_offset");
72    frameSizeField           = type.getCIntegerField("_frame_size");
73    oopMapsField             = type.getAddressField("_oop_maps");
74
75    if (VM.getVM().isServerCompiler()) {
76      matcherInterpreterFramePointerReg =
77          db.lookupIntConstant("Matcher::interpreter_frame_pointer_reg").intValue();
78    }
79  }
80
81  static {
82    VM.registerVMInitializedObserver(new Observer() {
83      public void update(Observable o, Object data) {
84        initialize(VM.getVM().getTypeDataBase());
85      }
86    });
87  }
88
89  public Address headerBegin() { return getAddress(); }
90
91  public Address headerEnd() { return getAddress().addOffsetTo(getHeaderSize()); }
92
93  public Address contentBegin() { return contentBeginField.getValue(addr); }
94
95  public Address contentEnd() { return headerBegin().addOffsetTo(getDataOffset()); }
96
97  public Address codeBegin() { return codeBeginField.getValue(addr); }
98
99  public Address codeEnd() { return codeEndField.getValue(addr); }
100
101  public Address dataBegin() { return headerBegin().addOffsetTo(getDataOffset()); }
102
103  public Address dataEnd() { return dataEndField.getValue(addr); }
104
105  public long getFrameCompleteOffset() { return frameCompleteOffsetField.getValue(addr); }
106
107  public int getDataOffset()       { return (int) dataOffsetField.getValue(addr); }
108
109  // Sizes
110  public int getSize()             { return (int) sizeField.getValue(addr); }
111
112  public int getHeaderSize()       { return (int) headerSizeField.getValue(addr); }
113
114  public long getFrameSizeWords() {
115    return (int) frameSizeField.getValue(addr);
116  }
117
118  public String getName() {
119    return CStringUtilities.getString(nameField.getValue(addr));
120  }
121
122  /** OopMap for frame; can return null if none available */
123
124  public ImmutableOopMapSet getOopMaps() {
125    Address value = oopMapsField.getValue(addr);
126    if (value == null) {
127      return null;
128    }
129    return new ImmutableOopMapSet(value);
130  }
131
132
133  // Typing
134  public boolean isBufferBlob()         { return false; }
135
136  public boolean isAOT()                { return false; }
137
138  public boolean isCompiled()           { return false; }
139
140  public boolean isNMethod()            { return false; }
141
142  public boolean isRuntimeStub()        { return false; }
143
144  public boolean isDeoptimizationStub() { return false; }
145
146  public boolean isUncommonTrapStub()   { return false; }
147
148  public boolean isExceptionStub()      { return false; }
149
150  public boolean isSafepointStub()      { return false; }
151
152  public boolean isAdapterBlob()        { return false; }
153
154  // Fine grain nmethod support: isNmethod() == isJavaMethod() || isNativeMethod() || isOSRMethod()
155  public boolean isJavaMethod()         { return false; }
156
157  public boolean isNativeMethod()       { return false; }
158
159  /** On-Stack Replacement method */
160  public boolean isOSRMethod()          { return false; }
161
162  public NMethod asNMethodOrNull() {
163    if (isNMethod()) return (NMethod)this;
164    return null;
165  }
166
167  // FIXME: add getRelocationSize()
168  public int getContentSize()      { return (int) contentEnd().minus(contentBegin()); }
169
170  public int getCodeSize()         { return (int) codeEnd()   .minus(codeBegin());    }
171
172  public int getDataSize()         { return (int) dataEnd()   .minus(dataBegin());    }
173
174  // Containment
175  public boolean blobContains(Address addr)    { return headerBegin() .lessThanOrEqual(addr) && dataEnd()   .greaterThan(addr); }
176
177  // FIXME: add relocationContains
178  public boolean contentContains(Address addr) { return contentBegin().lessThanOrEqual(addr) && contentEnd().greaterThan(addr); }
179
180  public boolean codeContains(Address addr)    { return codeBegin()   .lessThanOrEqual(addr) && codeEnd()   .greaterThan(addr); }
181
182  public boolean dataContains(Address addr)    { return dataBegin()   .lessThanOrEqual(addr) && dataEnd()   .greaterThan(addr); }
183
184  public boolean contains(Address addr)        { return contentContains(addr);                                                  }
185
186  public boolean isFrameCompleteAt(Address a)  { return codeContains(a) && a.minus(codeBegin()) >= getFrameCompleteOffset(); }
187
188  // Reclamation support (really only used by the nmethods, but in order to get asserts to work
189  // in the CodeCache they are defined virtual here)
190  public boolean isZombie()             { return false; }
191
192  public boolean isLockedByVM()         { return false; }
193
194  public ImmutableOopMap getOopMapForReturnAddress(Address returnAddress, boolean debugging) {
195    Address pc = returnAddress;
196    if (Assert.ASSERTS_ENABLED) {
197      Assert.that(getOopMaps() != null, "nope");
198    }
199    return getOopMaps().findMapAtOffset(pc.minus(codeBegin()), debugging);
200  }
201
202  /** NOTE: this returns a size in BYTES in this system! */
203  public long getFrameSize() {
204    return VM.getVM().getAddressSize() * getFrameSizeWords();
205  }
206
207  // Returns true, if the next frame is responsible for GC'ing oops passed as arguments
208  public boolean callerMustGCArguments() { return false; }
209
210  public void print() {
211    printOn(System.out);
212  }
213
214  public void printOn(PrintStream tty) {
215    tty.print(getName());
216    printComponentsOn(tty);
217  }
218
219  protected void printComponentsOn(PrintStream tty) {
220    tty.println(" content: [" + contentBegin() + ", " + contentEnd() + "), " +
221                " code: [" + codeBegin() + ", " + codeEnd() + "), " +
222                " data: [" + dataBegin() + ", " + dataEnd() + "), " +
223                " frame size: " + getFrameSize());
224  }
225}
226