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