43 }; |
43 }; |
44 }; |
44 }; |
45 |
45 |
46 // CodeBlob - superclass for all entries in the CodeCache. |
46 // CodeBlob - superclass for all entries in the CodeCache. |
47 // |
47 // |
48 // Suptypes are: |
48 // Subtypes are: |
49 // nmethod : Compiled Java methods (include method that calls to native code) |
49 // CompiledMethod : Compiled Java methods (include method that calls to native code) |
50 // RuntimeStub : Call to VM runtime methods |
50 // nmethod : JIT Compiled Java methods |
51 // DeoptimizationBlob : Used for deoptimizatation |
51 // RuntimeBlob : Non-compiled method code; generated glue code |
52 // ExceptionBlob : Used for stack unrolling |
52 // RuntimeStub : Call to VM runtime methods |
53 // SafepointBlob : Used to handle illegal instruction exceptions |
53 // DeoptimizationBlob : Used for deoptimization |
|
54 // ExceptionBlob : Used for stack unrolling |
|
55 // SafepointBlob : Used to handle illegal instruction exceptions |
54 // |
56 // |
55 // |
57 // |
56 // Layout: |
58 // Layout: |
57 // - header |
59 // - header |
58 // - relocation |
60 // - relocation |
59 // - content space |
61 // - content space |
60 // - instruction space |
62 // - instruction space |
61 // - data space |
63 // - data space |
62 class DeoptimizationBlob; |
64 |
|
65 |
|
66 class CodeBlobLayout; |
63 |
67 |
64 class CodeBlob VALUE_OBJ_CLASS_SPEC { |
68 class CodeBlob VALUE_OBJ_CLASS_SPEC { |
65 |
|
66 friend class VMStructs; |
69 friend class VMStructs; |
67 friend class JVMCIVMStructs; |
70 friend class JVMCIVMStructs; |
68 friend class CodeCacheDumper; |
71 friend class CodeCacheDumper; |
69 |
72 |
70 private: |
73 protected: |
71 const char* _name; |
74 const char* _name; |
72 int _size; // total size of CodeBlob in bytes |
75 int _size; // total size of CodeBlob in bytes |
73 int _header_size; // size of header (depends on subclass) |
76 int _header_size; // size of header (depends on subclass) |
74 int _relocation_size; // size of relocation |
|
75 int _content_offset; // offset to where content region begins (this includes consts, insts, stubs) |
|
76 int _code_offset; // offset to where instructions region begins (this includes insts, stubs) |
|
77 int _frame_complete_offset; // instruction offsets in [0.._frame_complete_offset) have |
77 int _frame_complete_offset; // instruction offsets in [0.._frame_complete_offset) have |
78 // not finished setting up their frame. Beware of pc's in |
78 // not finished setting up their frame. Beware of pc's in |
79 // that range. There is a similar range(s) on returns |
79 // that range. There is a similar range(s) on returns |
80 // which we don't detect. |
80 // which we don't detect. |
81 int _data_offset; // offset to where data region begins |
81 int _data_offset; // offset to where data region begins |
82 int _frame_size; // size of stack frame |
82 int _frame_size; // size of stack frame |
|
83 |
|
84 address _code_begin; |
|
85 address _code_end; |
|
86 address _content_begin; // address to where content region begins (this includes consts, insts, stubs) |
|
87 // address _content_end - not required, for all CodeBlobs _code_end == _content_end for now |
|
88 address _data_end; |
|
89 address _relocation_begin; |
|
90 address _relocation_end; |
|
91 |
83 ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob |
92 ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob |
84 CodeStrings _strings; |
93 bool _caller_must_gc_arguments; |
85 |
94 CodeStrings _strings; |
86 public: |
95 |
|
96 CodeBlob(const char* name, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments); |
|
97 CodeBlob(const char* name, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments); |
|
98 public: |
87 // Returns the space needed for CodeBlob |
99 // Returns the space needed for CodeBlob |
88 static unsigned int allocation_size(CodeBuffer* cb, int header_size); |
100 static unsigned int allocation_size(CodeBuffer* cb, int header_size); |
89 static unsigned int align_code_offset(int offset); |
101 static unsigned int align_code_offset(int offset); |
90 |
102 |
91 // Creation |
|
92 // a) simple CodeBlob |
|
93 // frame_complete is the offset from the beginning of the instructions |
|
94 // to where the frame setup (from stackwalk viewpoint) is complete. |
|
95 CodeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size); |
|
96 |
|
97 // b) full CodeBlob |
|
98 CodeBlob( |
|
99 const char* name, |
|
100 CodeBuffer* cb, |
|
101 int header_size, |
|
102 int size, |
|
103 int frame_complete, |
|
104 int frame_size, |
|
105 OopMapSet* oop_maps |
|
106 ); |
|
107 |
|
108 // Deletion |
103 // Deletion |
109 void flush(); |
104 virtual void flush(); |
110 |
105 |
111 // Typing |
106 // Typing |
112 virtual bool is_buffer_blob() const { return false; } |
107 virtual bool is_buffer_blob() const { return false; } |
113 virtual bool is_nmethod() const { return false; } |
108 virtual bool is_nmethod() const { return false; } |
114 virtual bool is_runtime_stub() const { return false; } |
109 virtual bool is_runtime_stub() const { return false; } |
115 virtual bool is_deoptimization_stub() const { return false; } |
110 virtual bool is_deoptimization_stub() const { return false; } |
116 virtual bool is_uncommon_trap_stub() const { return false; } |
111 virtual bool is_uncommon_trap_stub() const { return false; } |
117 virtual bool is_exception_stub() const { return false; } |
112 virtual bool is_exception_stub() const { return false; } |
118 virtual bool is_safepoint_stub() const { return false; } |
113 virtual bool is_safepoint_stub() const { return false; } |
119 virtual bool is_adapter_blob() const { return false; } |
114 virtual bool is_adapter_blob() const { return false; } |
120 virtual bool is_method_handles_adapter_blob() const { return false; } |
115 virtual bool is_method_handles_adapter_blob() const { return false; } |
|
116 virtual bool is_compiled() const { return false; } |
121 |
117 |
122 virtual bool is_compiled_by_c2() const { return false; } |
118 virtual bool is_compiled_by_c2() const { return false; } |
123 virtual bool is_compiled_by_c1() const { return false; } |
119 virtual bool is_compiled_by_c1() const { return false; } |
124 virtual bool is_compiled_by_jvmci() const { return false; } |
120 virtual bool is_compiled_by_jvmci() const { return false; } |
125 |
121 |
126 // Casting |
122 // Casting |
127 nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; } |
123 nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; } |
|
124 nmethod* as_nmethod() { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; } |
|
125 CompiledMethod* as_compiled_method_or_null() { return is_compiled() ? (CompiledMethod*) this : NULL; } |
|
126 CompiledMethod* as_compiled_method() { assert(is_compiled(), "must be compiled"); return (CompiledMethod*) this; } |
128 |
127 |
129 // Boundaries |
128 // Boundaries |
130 address header_begin() const { return (address) this; } |
129 address header_begin() const { return (address) this; } |
131 address header_end() const { return ((address) this) + _header_size; }; |
130 relocInfo* relocation_begin() const { return (relocInfo*) _relocation_begin; }; |
132 relocInfo* relocation_begin() const { return (relocInfo*) header_end(); }; |
131 relocInfo* relocation_end() const { return (relocInfo*) _relocation_end; } |
133 relocInfo* relocation_end() const { return (relocInfo*)(header_end() + _relocation_size); } |
132 address content_begin() const { return _content_begin; } |
134 address content_begin() const { return (address) header_begin() + _content_offset; } |
133 address content_end() const { return _code_end; } // _code_end == _content_end is true for all types of blobs for now, it is also checked in the constructor |
135 address content_end() const { return (address) header_begin() + _data_offset; } |
134 address code_begin() const { return _code_begin; } |
136 address code_begin() const { return (address) header_begin() + _code_offset; } |
135 address code_end() const { return _code_end; } |
137 address code_end() const { return (address) header_begin() + _data_offset; } |
136 address data_end() const { return _data_end; } |
138 address data_begin() const { return (address) header_begin() + _data_offset; } |
|
139 address data_end() const { return (address) header_begin() + _size; } |
|
140 |
|
141 // Offsets |
|
142 int relocation_offset() const { return _header_size; } |
|
143 int content_offset() const { return _content_offset; } |
|
144 int code_offset() const { return _code_offset; } |
|
145 int data_offset() const { return _data_offset; } |
|
146 |
137 |
147 // Sizes |
138 // Sizes |
148 int size() const { return _size; } |
139 int size() const { return _size; } |
149 int header_size() const { return _header_size; } |
140 int header_size() const { return _header_size; } |
150 int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); } |
141 int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); } |
151 int content_size() const { return content_end() - content_begin(); } |
142 int content_size() const { return content_end() - content_begin(); } |
152 int code_size() const { return code_end() - code_begin(); } |
143 int code_size() const { return code_end() - code_begin(); } |
153 int data_size() const { return data_end() - data_begin(); } |
|
154 |
144 |
155 // Containment |
145 // Containment |
156 bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); } |
146 bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); } |
157 bool relocation_contains(relocInfo* addr) const{ return relocation_begin() <= addr && addr < relocation_end(); } |
|
158 bool content_contains(address addr) const { return content_begin() <= addr && addr < content_end(); } |
|
159 bool code_contains(address addr) const { return code_begin() <= addr && addr < code_end(); } |
147 bool code_contains(address addr) const { return code_begin() <= addr && addr < code_end(); } |
160 bool data_contains(address addr) const { return data_begin() <= addr && addr < data_end(); } |
148 bool contains(address addr) const { return content_begin() <= addr && addr < content_end(); } |
161 bool contains(address addr) const { return content_contains(addr); } |
149 bool is_frame_complete_at(address addr) const { return code_contains(addr) && addr >= code_begin() + _frame_complete_offset; } |
162 bool is_frame_complete_at(address addr) const { return code_contains(addr) && |
|
163 addr >= code_begin() + _frame_complete_offset; } |
|
164 |
150 |
165 // CodeCache support: really only used by the nmethods, but in order to get |
151 // CodeCache support: really only used by the nmethods, but in order to get |
166 // asserts and certain bookkeeping to work in the CodeCache they are defined |
152 // asserts and certain bookkeeping to work in the CodeCache they are defined |
167 // virtual here. |
153 // virtual here. |
168 virtual bool is_zombie() const { return false; } |
154 virtual bool is_zombie() const { return false; } |
176 |
162 |
177 // OopMap for frame |
163 // OopMap for frame |
178 ImmutableOopMapSet* oop_maps() const { return _oop_maps; } |
164 ImmutableOopMapSet* oop_maps() const { return _oop_maps; } |
179 void set_oop_maps(OopMapSet* p); |
165 void set_oop_maps(OopMapSet* p); |
180 const ImmutableOopMap* oop_map_for_return_address(address return_address); |
166 const ImmutableOopMap* oop_map_for_return_address(address return_address); |
181 virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { ShouldNotReachHere(); } |
167 virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) = 0; |
182 |
168 |
183 // Frame support |
169 // Frame support |
184 int frame_size() const { return _frame_size; } |
170 int frame_size() const { return _frame_size; } |
185 void set_frame_size(int size) { _frame_size = size; } |
171 void set_frame_size(int size) { _frame_size = size; } |
186 |
172 |
187 // Returns true, if the next frame is responsible for GC'ing oops passed as arguments |
173 // Returns true, if the next frame is responsible for GC'ing oops passed as arguments |
188 virtual bool caller_must_gc_arguments(JavaThread* thread) const { return false; } |
174 bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; } |
189 |
175 |
190 // Naming |
176 // Naming |
191 const char* name() const { return _name; } |
177 const char* name() const { return _name; } |
192 void set_name(const char* name) { _name = name; } |
178 void set_name(const char* name) { _name = name; } |
193 |
179 |
194 // Debugging |
180 // Debugging |
195 virtual void verify(); |
181 virtual void verify() = 0; |
196 void print() const { print_on(tty); } |
182 virtual void print() const { print_on(tty); }; |
197 virtual void print_on(outputStream* st) const; |
183 virtual void print_on(outputStream* st) const; |
198 virtual void print_value_on(outputStream* st) const; |
184 virtual void print_value_on(outputStream* st) const; |
199 void print_code(); |
185 void print_code(); |
200 |
|
201 // Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService. |
|
202 static void trace_new_stub(CodeBlob* blob, const char* name1, const char* name2 = ""); |
|
203 |
186 |
204 // Print the comment associated with offset on stream, if there is one |
187 // Print the comment associated with offset on stream, if there is one |
205 virtual void print_block_comment(outputStream* stream, address block_begin) const { |
188 virtual void print_block_comment(outputStream* stream, address block_begin) const { |
206 intptr_t offset = (intptr_t)(block_begin - code_begin()); |
189 intptr_t offset = (intptr_t)(block_begin - code_begin()); |
207 _strings.print_block_comment(stream, offset); |
190 _strings.print_block_comment(stream, offset); |
219 static ByteSize oop_maps_field_offset() { |
202 static ByteSize oop_maps_field_offset() { |
220 return byte_offset_of(CodeBlob, _oop_maps); |
203 return byte_offset_of(CodeBlob, _oop_maps); |
221 } |
204 } |
222 }; |
205 }; |
223 |
206 |
|
207 class CodeBlobLayout : public StackObj { |
|
208 private: |
|
209 int _size; |
|
210 int _header_size; |
|
211 int _relocation_size; |
|
212 int _content_offset; |
|
213 int _code_offset; |
|
214 int _data_offset; |
|
215 address _code_begin; |
|
216 address _code_end; |
|
217 address _content_begin; |
|
218 address _content_end; |
|
219 address _data_end; |
|
220 address _relocation_begin; |
|
221 address _relocation_end; |
|
222 |
|
223 public: |
|
224 CodeBlobLayout(address code_begin, address code_end, address content_begin, address content_end, address data_end, address relocation_begin, address relocation_end) : |
|
225 _size(0), |
|
226 _header_size(0), |
|
227 _relocation_size(0), |
|
228 _content_offset(0), |
|
229 _code_offset(0), |
|
230 _data_offset(0), |
|
231 _content_begin(content_begin), |
|
232 _content_end(content_end), |
|
233 _code_begin(code_begin), |
|
234 _code_end(code_end), |
|
235 _data_end(data_end), |
|
236 _relocation_begin(relocation_begin), |
|
237 _relocation_end(relocation_end) |
|
238 { |
|
239 } |
|
240 |
|
241 CodeBlobLayout(const address start, int size, int header_size, int relocation_size, int data_offset) : |
|
242 _size(size), |
|
243 _header_size(header_size), |
|
244 _relocation_size(relocation_size), |
|
245 _content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)), |
|
246 _code_offset(_content_offset), |
|
247 _data_offset(data_offset) |
|
248 { |
|
249 assert(_relocation_size == round_to(_relocation_size, oopSize), "unaligned size"); |
|
250 |
|
251 _code_begin = (address) start + _code_offset; |
|
252 _code_end = (address) start + _data_offset; |
|
253 |
|
254 _content_begin = (address) start + _content_offset; |
|
255 _content_end = (address) start + _data_offset; |
|
256 |
|
257 _data_end = (address) start + _size; |
|
258 _relocation_begin = (address) start + _header_size; |
|
259 _relocation_end = _relocation_begin + _relocation_size; |
|
260 } |
|
261 |
|
262 CodeBlobLayout(const address start, int size, int header_size, const CodeBuffer* cb) : |
|
263 _size(size), |
|
264 _header_size(header_size), |
|
265 _relocation_size(round_to(cb->total_relocation_size(), oopSize)), |
|
266 _content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)), |
|
267 _code_offset(_content_offset + cb->total_offset_of(cb->insts())), |
|
268 _data_offset(_content_offset + round_to(cb->total_content_size(), oopSize)) |
|
269 { |
|
270 assert(_relocation_size == round_to(_relocation_size, oopSize), "unaligned size"); |
|
271 |
|
272 _code_begin = (address) start + _code_offset; |
|
273 _code_end = (address) start + _data_offset; |
|
274 |
|
275 _content_begin = (address) start + _content_offset; |
|
276 _content_end = (address) start + _data_offset; |
|
277 |
|
278 _data_end = (address) start + _size; |
|
279 _relocation_begin = (address) start + _header_size; |
|
280 _relocation_end = _relocation_begin + _relocation_size; |
|
281 } |
|
282 |
|
283 int size() const { return _size; } |
|
284 int header_size() const { return _header_size; } |
|
285 int relocation_size() const { return _relocation_size; } |
|
286 int content_offset() const { return _content_offset; } |
|
287 int code_offset() const { return _code_offset; } |
|
288 int data_offset() const { return _data_offset; } |
|
289 address code_begin() const { return _code_begin; } |
|
290 address code_end() const { return _code_end; } |
|
291 address data_end() const { return _data_end; } |
|
292 address relocation_begin() const { return _relocation_begin; } |
|
293 address relocation_end() const { return _relocation_end; } |
|
294 address content_begin() const { return _content_begin; } |
|
295 address content_end() const { return _content_end; } |
|
296 }; |
|
297 |
|
298 |
|
299 class RuntimeBlob : public CodeBlob { |
|
300 friend class VMStructs; |
|
301 public: |
|
302 |
|
303 // Creation |
|
304 // a) simple CodeBlob |
|
305 // frame_complete is the offset from the beginning of the instructions |
|
306 // to where the frame setup (from stackwalk viewpoint) is complete. |
|
307 RuntimeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size); |
|
308 |
|
309 // b) full CodeBlob |
|
310 RuntimeBlob( |
|
311 const char* name, |
|
312 CodeBuffer* cb, |
|
313 int header_size, |
|
314 int size, |
|
315 int frame_complete, |
|
316 int frame_size, |
|
317 OopMapSet* oop_maps, |
|
318 bool caller_must_gc_arguments = false |
|
319 ); |
|
320 |
|
321 // GC support |
|
322 virtual bool is_alive() const = 0; |
|
323 |
|
324 void verify(); |
|
325 |
|
326 // OopMap for frame |
|
327 virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { ShouldNotReachHere(); } |
|
328 |
|
329 // Debugging |
|
330 void print() const { print_on(tty); } |
|
331 virtual void print_on(outputStream* st) const { CodeBlob::print_on(st); } |
|
332 virtual void print_value_on(outputStream* st) const { CodeBlob::print_value_on(st); } |
|
333 |
|
334 // Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService. |
|
335 static void trace_new_stub(RuntimeBlob* blob, const char* name1, const char* name2 = ""); |
|
336 }; |
|
337 |
224 class WhiteBox; |
338 class WhiteBox; |
225 //---------------------------------------------------------------------------------------------------- |
339 //---------------------------------------------------------------------------------------------------- |
226 // BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc. |
340 // BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc. |
227 |
341 |
228 class BufferBlob: public CodeBlob { |
342 class BufferBlob: public RuntimeBlob { |
229 friend class VMStructs; |
343 friend class VMStructs; |
230 friend class AdapterBlob; |
344 friend class AdapterBlob; |
231 friend class MethodHandlesAdapterBlob; |
345 friend class MethodHandlesAdapterBlob; |
232 friend class WhiteBox; |
346 friend class WhiteBox; |
233 |
347 |