Mercurial > hg > truffle
comparison src/share/vm/code/nmethod.hpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | d2a62e0f25eb |
children | 8966c2d65d96 137868b7aa6f |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
25 #ifndef SHARE_VM_CODE_NMETHOD_HPP | 25 #ifndef SHARE_VM_CODE_NMETHOD_HPP |
26 #define SHARE_VM_CODE_NMETHOD_HPP | 26 #define SHARE_VM_CODE_NMETHOD_HPP |
27 | 27 |
28 #include "code/codeBlob.hpp" | 28 #include "code/codeBlob.hpp" |
29 #include "code/pcDesc.hpp" | 29 #include "code/pcDesc.hpp" |
30 #include "oops/metadata.hpp" | |
30 | 31 |
31 // This class is used internally by nmethods, to cache | 32 // This class is used internally by nmethods, to cache |
32 // exception/pc/handler information. | 33 // exception/pc/handler information. |
33 | 34 |
34 class ExceptionCache : public CHeapObj<mtCode> { | 35 class ExceptionCache : public CHeapObj<mtCode> { |
35 friend class VMStructs; | 36 friend class VMStructs; |
36 private: | 37 private: |
37 enum { cache_size = 16 }; | 38 enum { cache_size = 16 }; |
38 klassOop _exception_type; | 39 Klass* _exception_type; |
39 address _pc[cache_size]; | 40 address _pc[cache_size]; |
40 address _handler[cache_size]; | 41 address _handler[cache_size]; |
41 int _count; | 42 int _count; |
42 ExceptionCache* _next; | 43 ExceptionCache* _next; |
43 | 44 |
50 | 51 |
51 public: | 52 public: |
52 | 53 |
53 ExceptionCache(Handle exception, address pc, address handler); | 54 ExceptionCache(Handle exception, address pc, address handler); |
54 | 55 |
55 klassOop exception_type() { return _exception_type; } | 56 Klass* exception_type() { return _exception_type; } |
56 klassOop* exception_type_addr() { return &_exception_type; } | |
57 ExceptionCache* next() { return _next; } | 57 ExceptionCache* next() { return _next; } |
58 void set_next(ExceptionCache *ec) { _next = ec; } | 58 void set_next(ExceptionCache *ec) { _next = ec; } |
59 | 59 |
60 address match(Handle exception, address pc); | 60 address match(Handle exception, address pc); |
61 bool match_exception_with_space(Handle exception) ; | 61 bool match_exception_with_space(Handle exception) ; |
110 friend class VMStructs; | 110 friend class VMStructs; |
111 friend class NMethodSweeper; | 111 friend class NMethodSweeper; |
112 friend class CodeCache; // scavengable oops | 112 friend class CodeCache; // scavengable oops |
113 private: | 113 private: |
114 // Shared fields for all nmethod's | 114 // Shared fields for all nmethod's |
115 methodOop _method; | 115 Method* _method; |
116 int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method | 116 int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method |
117 jmethodID _jmethod_id; // Cache of method()->jmethod_id() | 117 jmethodID _jmethod_id; // Cache of method()->jmethod_id() |
118 | 118 |
119 // To support simple linked-list chaining of nmethods: | 119 // To support simple linked-list chaining of nmethods: |
120 nmethod* _osr_link; // from instanceKlass::osr_nmethods_head | 120 nmethod* _osr_link; // from InstanceKlass::osr_nmethods_head |
121 nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods | 121 nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods |
122 nmethod* _saved_nmethod_link; // from CodeCache::speculatively_disconnect | 122 nmethod* _saved_nmethod_link; // from CodeCache::speculatively_disconnect |
123 | 123 |
124 static nmethod* volatile _oops_do_mark_nmethods; | 124 static nmethod* volatile _oops_do_mark_nmethods; |
125 nmethod* volatile _oops_do_mark_link; | 125 nmethod* volatile _oops_do_mark_link; |
146 int _trap_offset; | 146 int _trap_offset; |
147 #endif // def HAVE_DTRACE_H | 147 #endif // def HAVE_DTRACE_H |
148 int _consts_offset; | 148 int _consts_offset; |
149 int _stub_offset; | 149 int _stub_offset; |
150 int _oops_offset; // offset to where embedded oop table begins (inside data) | 150 int _oops_offset; // offset to where embedded oop table begins (inside data) |
151 int _metadata_offset; // embedded meta data table | |
151 int _scopes_data_offset; | 152 int _scopes_data_offset; |
152 int _scopes_pcs_offset; | 153 int _scopes_pcs_offset; |
153 int _dependencies_offset; | 154 int _dependencies_offset; |
154 int _handler_table_offset; | 155 int _handler_table_offset; |
155 int _nul_chk_table_offset; | 156 int _nul_chk_table_offset; |
224 ByteSize _native_basic_lock_sp_offset; | 225 ByteSize _native_basic_lock_sp_offset; |
225 | 226 |
226 friend class nmethodLocker; | 227 friend class nmethodLocker; |
227 | 228 |
228 // For native wrappers | 229 // For native wrappers |
229 nmethod(methodOop method, | 230 nmethod(Method* method, |
230 int nmethod_size, | 231 int nmethod_size, |
231 int compile_id, | 232 int compile_id, |
232 CodeOffsets* offsets, | 233 CodeOffsets* offsets, |
233 CodeBuffer *code_buffer, | 234 CodeBuffer *code_buffer, |
234 int frame_size, | 235 int frame_size, |
236 ByteSize basic_lock_sp_offset, /* synchronized natives only */ | 237 ByteSize basic_lock_sp_offset, /* synchronized natives only */ |
237 OopMapSet* oop_maps); | 238 OopMapSet* oop_maps); |
238 | 239 |
239 #ifdef HAVE_DTRACE_H | 240 #ifdef HAVE_DTRACE_H |
240 // For native wrappers | 241 // For native wrappers |
241 nmethod(methodOop method, | 242 nmethod(Method* method, |
242 int nmethod_size, | 243 int nmethod_size, |
243 CodeOffsets* offsets, | 244 CodeOffsets* offsets, |
244 CodeBuffer *code_buffer, | 245 CodeBuffer *code_buffer, |
245 int frame_size); | 246 int frame_size); |
246 #endif // def HAVE_DTRACE_H | 247 #endif // def HAVE_DTRACE_H |
247 | 248 |
248 // Creation support | 249 // Creation support |
249 nmethod(methodOop method, | 250 nmethod(Method* method, |
250 int nmethod_size, | 251 int nmethod_size, |
251 int compile_id, | 252 int compile_id, |
252 int entry_bci, | 253 int entry_bci, |
253 CodeOffsets* offsets, | 254 CodeOffsets* offsets, |
254 int orig_pc_offset, | 255 int orig_pc_offset, |
323 address trap_address() const { return insts_begin() + _trap_offset; } | 324 address trap_address() const { return insts_begin() + _trap_offset; } |
324 | 325 |
325 #endif // def HAVE_DTRACE_H | 326 #endif // def HAVE_DTRACE_H |
326 | 327 |
327 // accessors | 328 // accessors |
328 methodOop method() const { return _method; } | 329 Method* method() const { return _method; } |
329 AbstractCompiler* compiler() const { return _compiler; } | 330 AbstractCompiler* compiler() const { return _compiler; } |
330 | 331 |
331 // type info | 332 // type info |
332 bool is_nmethod() const { return true; } | 333 bool is_nmethod() const { return true; } |
333 bool is_java_method() const { return !method()->is_native(); } | 334 bool is_java_method() const { return !method()->is_native(); } |
348 address exception_begin () const { return header_begin() + _exception_offset ; } | 349 address exception_begin () const { return header_begin() + _exception_offset ; } |
349 address deopt_handler_begin () const { return header_begin() + _deoptimize_offset ; } | 350 address deopt_handler_begin () const { return header_begin() + _deoptimize_offset ; } |
350 address deopt_mh_handler_begin() const { return header_begin() + _deoptimize_mh_offset ; } | 351 address deopt_mh_handler_begin() const { return header_begin() + _deoptimize_mh_offset ; } |
351 address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (header_begin() + _unwind_handler_offset) : NULL; } | 352 address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (header_begin() + _unwind_handler_offset) : NULL; } |
352 oop* oops_begin () const { return (oop*) (header_begin() + _oops_offset) ; } | 353 oop* oops_begin () const { return (oop*) (header_begin() + _oops_offset) ; } |
353 oop* oops_end () const { return (oop*) (header_begin() + _scopes_data_offset) ; } | 354 oop* oops_end () const { return (oop*) (header_begin() + _metadata_offset) ; } |
355 | |
356 Metadata** metadata_begin () const { return (Metadata**) (header_begin() + _metadata_offset) ; } | |
357 Metadata** metadata_end () const { return (Metadata**) (header_begin() + _scopes_data_offset) ; } | |
354 | 358 |
355 address scopes_data_begin () const { return header_begin() + _scopes_data_offset ; } | 359 address scopes_data_begin () const { return header_begin() + _scopes_data_offset ; } |
356 address scopes_data_end () const { return header_begin() + _scopes_pcs_offset ; } | 360 address scopes_data_end () const { return header_begin() + _scopes_pcs_offset ; } |
357 PcDesc* scopes_pcs_begin () const { return (PcDesc*)(header_begin() + _scopes_pcs_offset ); } | 361 PcDesc* scopes_pcs_begin () const { return (PcDesc*)(header_begin() + _scopes_pcs_offset ); } |
358 PcDesc* scopes_pcs_end () const { return (PcDesc*)(header_begin() + _dependencies_offset) ; } | 362 PcDesc* scopes_pcs_end () const { return (PcDesc*)(header_begin() + _dependencies_offset) ; } |
366 // Sizes | 370 // Sizes |
367 int consts_size () const { return consts_end () - consts_begin (); } | 371 int consts_size () const { return consts_end () - consts_begin (); } |
368 int insts_size () const { return insts_end () - insts_begin (); } | 372 int insts_size () const { return insts_end () - insts_begin (); } |
369 int stub_size () const { return stub_end () - stub_begin (); } | 373 int stub_size () const { return stub_end () - stub_begin (); } |
370 int oops_size () const { return (address) oops_end () - (address) oops_begin (); } | 374 int oops_size () const { return (address) oops_end () - (address) oops_begin (); } |
375 int metadata_size () const { return (address) metadata_end () - (address) metadata_begin (); } | |
371 int scopes_data_size () const { return scopes_data_end () - scopes_data_begin (); } | 376 int scopes_data_size () const { return scopes_data_end () - scopes_data_begin (); } |
372 int scopes_pcs_size () const { return (intptr_t) scopes_pcs_end () - (intptr_t) scopes_pcs_begin (); } | 377 int scopes_pcs_size () const { return (intptr_t) scopes_pcs_end () - (intptr_t) scopes_pcs_begin (); } |
373 int dependencies_size () const { return dependencies_end () - dependencies_begin (); } | 378 int dependencies_size () const { return dependencies_end () - dependencies_begin (); } |
374 int handler_table_size() const { return handler_table_end() - handler_table_begin(); } | 379 int handler_table_size() const { return handler_table_end() - handler_table_begin(); } |
375 int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); } | 380 int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); } |
379 // Containment | 384 // Containment |
380 bool consts_contains (address addr) const { return consts_begin () <= addr && addr < consts_end (); } | 385 bool consts_contains (address addr) const { return consts_begin () <= addr && addr < consts_end (); } |
381 bool insts_contains (address addr) const { return insts_begin () <= addr && addr < insts_end (); } | 386 bool insts_contains (address addr) const { return insts_begin () <= addr && addr < insts_end (); } |
382 bool stub_contains (address addr) const { return stub_begin () <= addr && addr < stub_end (); } | 387 bool stub_contains (address addr) const { return stub_begin () <= addr && addr < stub_end (); } |
383 bool oops_contains (oop* addr) const { return oops_begin () <= addr && addr < oops_end (); } | 388 bool oops_contains (oop* addr) const { return oops_begin () <= addr && addr < oops_end (); } |
389 bool metadata_contains (Metadata** addr) const { return metadata_begin () <= addr && addr < metadata_end (); } | |
384 bool scopes_data_contains (address addr) const { return scopes_data_begin () <= addr && addr < scopes_data_end (); } | 390 bool scopes_data_contains (address addr) const { return scopes_data_begin () <= addr && addr < scopes_data_end (); } |
385 bool scopes_pcs_contains (PcDesc* addr) const { return scopes_pcs_begin () <= addr && addr < scopes_pcs_end (); } | 391 bool scopes_pcs_contains (PcDesc* addr) const { return scopes_pcs_begin () <= addr && addr < scopes_pcs_end (); } |
386 bool handler_table_contains(address addr) const { return handler_table_begin() <= addr && addr < handler_table_end(); } | 392 bool handler_table_contains(address addr) const { return handler_table_begin() <= addr && addr < handler_table_end(); } |
387 bool nul_chk_table_contains(address addr) const { return nul_chk_table_begin() <= addr && addr < nul_chk_table_end(); } | 393 bool nul_chk_table_contains(address addr) const { return nul_chk_table_begin() <= addr && addr < nul_chk_table_end(); } |
388 | 394 |
446 assert(index > 0 && index <= oops_size(), "must be a valid non-zero index"); | 452 assert(index > 0 && index <= oops_size(), "must be a valid non-zero index"); |
447 assert(!_oops_are_stale, "oops are stale"); | 453 assert(!_oops_are_stale, "oops are stale"); |
448 return &oops_begin()[index - 1]; | 454 return &oops_begin()[index - 1]; |
449 } | 455 } |
450 | 456 |
451 void copy_oops(GrowableArray<jobject>* oops); | 457 // Support for meta data in scopes and relocs: |
458 // Note: index 0 is reserved for null. | |
459 Metadata* metadata_at(int index) const { return index == 0 ? NULL: *metadata_addr_at(index); } | |
460 Metadata** metadata_addr_at(int index) const { // for GC | |
461 // relocation indexes are biased by 1 (because 0 is reserved) | |
462 assert(index > 0 && index <= metadata_size(), "must be a valid non-zero index"); | |
463 return &metadata_begin()[index - 1]; | |
464 } | |
465 | |
466 void copy_values(GrowableArray<jobject>* oops); | |
467 void copy_values(GrowableArray<Metadata*>* metadata); | |
452 | 468 |
453 // Relocation support | 469 // Relocation support |
454 private: | 470 private: |
455 void fix_oop_relocations(address begin, address end, bool initialize_immediates); | 471 void fix_oop_relocations(address begin, address end, bool initialize_immediates); |
456 inline void initialize_immediate_oop(oop* dest, jobject handle); | 472 inline void initialize_immediate_oop(oop* dest, jobject handle); |
514 void cleanup_inline_caches(); | 530 void cleanup_inline_caches(); |
515 bool inlinecache_check_contains(address addr) const { | 531 bool inlinecache_check_contains(address addr) const { |
516 return (addr >= code_begin() && addr < verified_entry_point()); | 532 return (addr >= code_begin() && addr < verified_entry_point()); |
517 } | 533 } |
518 | 534 |
535 // Check that all metadata is still alive | |
536 void verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive); | |
537 | |
519 // unlink and deallocate this nmethod | 538 // unlink and deallocate this nmethod |
520 // Only NMethodSweeper class is expected to use this. NMethodSweeper is not | 539 // Only NMethodSweeper class is expected to use this. NMethodSweeper is not |
521 // expected to use any other private methods/data in this class. | 540 // expected to use any other private methods/data in this class. |
522 | 541 |
523 protected: | 542 protected: |
531 | 550 |
532 // See comment at definition of _last_seen_on_stack | 551 // See comment at definition of _last_seen_on_stack |
533 void mark_as_seen_on_stack(); | 552 void mark_as_seen_on_stack(); |
534 bool can_not_entrant_be_converted(); | 553 bool can_not_entrant_be_converted(); |
535 | 554 |
536 // Evolution support. We make old (discarded) compiled methods point to new methodOops. | 555 // Evolution support. We make old (discarded) compiled methods point to new Method*s. |
537 void set_method(methodOop method) { _method = method; } | 556 void set_method(Method* method) { _method = method; } |
538 | 557 |
539 // GC support | 558 // GC support |
540 void do_unloading(BoolObjectClosure* is_alive, OopClosure* keep_alive, | 559 void do_unloading(BoolObjectClosure* is_alive, OopClosure* keep_alive, |
541 bool unloading_occurred); | 560 bool unloading_occurred); |
542 bool can_unload(BoolObjectClosure* is_alive, OopClosure* keep_alive, | 561 bool can_unload(BoolObjectClosure* is_alive, OopClosure* keep_alive, |
661 bool check_dependency_on(DepChange& changes); | 680 bool check_dependency_on(DepChange& changes); |
662 | 681 |
663 // Evolution support. Tells if this compiled method is dependent on any of | 682 // Evolution support. Tells if this compiled method is dependent on any of |
664 // methods m() of class dependee, such that if m() in dependee is replaced, | 683 // methods m() of class dependee, such that if m() in dependee is replaced, |
665 // this compiled method will have to be deoptimized. | 684 // this compiled method will have to be deoptimized. |
666 bool is_evol_dependent_on(klassOop dependee); | 685 bool is_evol_dependent_on(Klass* dependee); |
667 | 686 |
668 // Fast breakpoint support. Tells if this compiled method is | 687 // Fast breakpoint support. Tells if this compiled method is |
669 // dependent on the given method. Returns true if this nmethod | 688 // dependent on the given method. Returns true if this nmethod |
670 // corresponds to the given method as well. | 689 // corresponds to the given method as well. |
671 bool is_dependent_on_method(methodOop dependee); | 690 bool is_dependent_on_method(Method* dependee); |
672 | 691 |
673 // is it ok to patch at address? | 692 // is it ok to patch at address? |
674 bool is_patchable_at(address instr_address); | 693 bool is_patchable_at(address instr_address); |
675 | 694 |
676 // UseBiasedLocking support | 695 // UseBiasedLocking support |
684 // support for code generation | 703 // support for code generation |
685 static int verified_entry_point_offset() { return offset_of(nmethod, _verified_entry_point); } | 704 static int verified_entry_point_offset() { return offset_of(nmethod, _verified_entry_point); } |
686 static int osr_entry_point_offset() { return offset_of(nmethod, _osr_entry_point); } | 705 static int osr_entry_point_offset() { return offset_of(nmethod, _osr_entry_point); } |
687 static int entry_bci_offset() { return offset_of(nmethod, _entry_bci); } | 706 static int entry_bci_offset() { return offset_of(nmethod, _entry_bci); } |
688 | 707 |
708 // RedefineClasses support. Mark metadata in nmethods as on_stack so that | |
709 // redefine classes doesn't purge it. | |
710 static void mark_on_stack(nmethod* nm) { | |
711 nm->metadata_do(Metadata::mark_on_stack); | |
712 } | |
713 void metadata_do(void f(Metadata*)); | |
689 }; | 714 }; |
690 | 715 |
691 // Locks an nmethod so its code will not get removed and it will not | 716 // Locks an nmethod so its code will not get removed and it will not |
692 // be made into a zombie, even if it is a not_entrant method. After the | 717 // be made into a zombie, even if it is a not_entrant method. After the |
693 // nmethod becomes a zombie, if CompiledMethodUnload event processing | 718 // nmethod becomes a zombie, if CompiledMethodUnload event processing |