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