comparison src/share/vm/code/nmethod.hpp @ 1644:2a47bd84841f

6965184: possible races in make_not_entrant_or_zombie Reviewed-by: kvn
author never
date Thu, 08 Jul 2010 14:29:44 -0700
parents 38e8278318ca
children 126ea7725993
comparison
equal deleted inserted replaced
1635:a693e51ac197 1644:2a47bd84841f
76 PcDesc* last_pc_desc() { return _last_pc_desc; } 76 PcDesc* last_pc_desc() { return _last_pc_desc; }
77 }; 77 };
78 78
79 79
80 // nmethods (native methods) are the compiled code versions of Java methods. 80 // nmethods (native methods) are the compiled code versions of Java methods.
81 81 //
82 struct nmFlags { 82 // An nmethod contains:
83 friend class VMStructs;
84 unsigned int version:8; // version number (0 = first version)
85 unsigned int age:4; // age (in # of sweep steps)
86
87 unsigned int state:2; // {alive, zombie, unloaded)
88
89 unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
90 unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
91 unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
92 unsigned int markedForReclamation:1; // Used by NMethodSweeper
93
94 unsigned int has_unsafe_access:1; // May fault due to unsafe access.
95 unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes?
96
97 unsigned int speculatively_disconnected:1; // Marked for potential unload
98
99 void clear();
100 };
101
102
103 // A nmethod contains:
104 // - header (the nmethod structure) 83 // - header (the nmethod structure)
105 // [Relocation] 84 // [Relocation]
106 // - relocation information 85 // - relocation information
107 // - constant part (doubles, longs and floats used in nmethod) 86 // - constant part (doubles, longs and floats used in nmethod)
108 // - oop table 87 // - oop table
129 friend class VMStructs; 108 friend class VMStructs;
130 friend class NMethodSweeper; 109 friend class NMethodSweeper;
131 friend class CodeCache; // non-perm oops 110 friend class CodeCache; // non-perm oops
132 private: 111 private:
133 // Shared fields for all nmethod's 112 // Shared fields for all nmethod's
134 static int _zombie_instruction_size;
135
136 methodOop _method; 113 methodOop _method;
137 int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method 114 int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
138 jmethodID _jmethod_id; // Cache of method()->jmethod_id() 115 jmethodID _jmethod_id; // Cache of method()->jmethod_id()
139 116
140 // To support simple linked-list chaining of nmethods: 117 // To support simple linked-list chaining of nmethods:
144 121
145 static nmethod* volatile _oops_do_mark_nmethods; 122 static nmethod* volatile _oops_do_mark_nmethods;
146 nmethod* volatile _oops_do_mark_link; 123 nmethod* volatile _oops_do_mark_link;
147 124
148 AbstractCompiler* _compiler; // The compiler which compiled this nmethod 125 AbstractCompiler* _compiler; // The compiler which compiled this nmethod
126
127 // offsets for entry points
128 address _entry_point; // entry point with class check
129 address _verified_entry_point; // entry point without class check
130 address _osr_entry_point; // entry point for on stack replacement
149 131
150 // Offsets for different nmethod parts 132 // Offsets for different nmethod parts
151 int _exception_offset; 133 int _exception_offset;
152 // All deoptee's will resume execution at this location described by 134 // All deoptee's will resume execution at this location described by
153 // this offset. 135 // this offset.
173 155
174 // location in frame (offset for sp) that deopt can store the original 156 // location in frame (offset for sp) that deopt can store the original
175 // pc during a deopt. 157 // pc during a deopt.
176 int _orig_pc_offset; 158 int _orig_pc_offset;
177 159
178 int _compile_id; // which compilation made this nmethod 160 int _compile_id; // which compilation made this nmethod
179 int _comp_level; // compilation level 161 int _comp_level; // compilation level
180 162
181 // offsets for entry points 163 // protected by CodeCache_lock
182 address _entry_point; // entry point with class check 164 bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock)
183 address _verified_entry_point; // entry point without class check 165 bool _speculatively_disconnected; // Marked for potential unload
184 address _osr_entry_point; // entry point for on stack replacement 166
185 167 bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper)
186 nmFlags flags; // various flags to keep track of nmethod state 168 bool _marked_for_deoptimization; // Used for stack deoptimization
187 bool _markedForDeoptimization; // Used for stack deoptimization 169
170 // used by jvmti to track if an unload event has been posted for this nmethod.
171 bool _unload_reported;
172
173 // set during construction
174 unsigned int _has_unsafe_access:1; // May fault due to unsafe access.
175 unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?
176
177 // Protected by Patching_lock
178 unsigned char _state; // {alive, not_entrant, zombie, unloaded)
179
188 enum { alive = 0, 180 enum { alive = 0,
189 not_entrant = 1, // uncommon trap has happened but activations may still exist 181 not_entrant = 1, // uncommon trap has happened but activations may still exist
190 zombie = 2, 182 zombie = 2,
191 unloaded = 3 }; 183 unloaded = 3 };
192 184
193 // used by jvmti to track if an unload event has been posted for this nmethod.
194 bool _unload_reported;
195 185
196 jbyte _scavenge_root_state; 186 jbyte _scavenge_root_state;
197 187
198 NOT_PRODUCT(bool _has_debug_info; ) 188 NOT_PRODUCT(bool _has_debug_info; )
199 189
268 // Returns true if this thread changed the state of the nmethod or 258 // Returns true if this thread changed the state of the nmethod or
269 // false if another thread performed the transition. 259 // false if another thread performed the transition.
270 bool make_not_entrant_or_zombie(unsigned int state); 260 bool make_not_entrant_or_zombie(unsigned int state);
271 void inc_decompile_count(); 261 void inc_decompile_count();
272 262
273 // used to check that writes to nmFlags are done consistently.
274 static void check_safepoint() PRODUCT_RETURN;
275
276 // Used to manipulate the exception cache 263 // Used to manipulate the exception cache
277 void add_exception_cache_entry(ExceptionCache* new_entry); 264 void add_exception_cache_entry(ExceptionCache* new_entry);
278 ExceptionCache* exception_cache_entry_for_exception(Handle exception); 265 ExceptionCache* exception_cache_entry_for_exception(Handle exception);
279 266
280 // Inform external interfaces that a compiled method has been unloaded 267 // Inform external interfaces that a compiled method has been unloaded
281 inline void post_compiled_method_unload(); 268 void post_compiled_method_unload();
269
270 // Initailize fields to their default values
271 void init_defaults();
282 272
283 public: 273 public:
284 // create nmethod with entry_bci 274 // create nmethod with entry_bci
285 static nmethod* new_nmethod(methodHandle method, 275 static nmethod* new_nmethod(methodHandle method,
286 int compile_id, 276 int compile_id,
391 // entry points 381 // entry points
392 address entry_point() const { return _entry_point; } // normal entry point 382 address entry_point() const { return _entry_point; } // normal entry point
393 address verified_entry_point() const { return _verified_entry_point; } // if klass is correct 383 address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
394 384
395 // flag accessing and manipulation 385 // flag accessing and manipulation
396 bool is_in_use() const { return flags.state == alive; } 386 bool is_in_use() const { return _state == alive; }
397 bool is_alive() const { return flags.state == alive || flags.state == not_entrant; } 387 bool is_alive() const { return _state == alive || _state == not_entrant; }
398 bool is_not_entrant() const { return flags.state == not_entrant; } 388 bool is_not_entrant() const { return _state == not_entrant; }
399 bool is_zombie() const { return flags.state == zombie; } 389 bool is_zombie() const { return _state == zombie; }
400 bool is_unloaded() const { return flags.state == unloaded; } 390 bool is_unloaded() const { return _state == unloaded; }
401 391
402 // Make the nmethod non entrant. The nmethod will continue to be 392 // Make the nmethod non entrant. The nmethod will continue to be
403 // alive. It is used when an uncommon trap happens. Returns true 393 // alive. It is used when an uncommon trap happens. Returns true
404 // if this thread changed the state of the nmethod or false if 394 // if this thread changed the state of the nmethod or false if
405 // another thread performed the transition. 395 // another thread performed the transition.
408 398
409 // used by jvmti to track if the unload event has been reported 399 // used by jvmti to track if the unload event has been reported
410 bool unload_reported() { return _unload_reported; } 400 bool unload_reported() { return _unload_reported; }
411 void set_unload_reported() { _unload_reported = true; } 401 void set_unload_reported() { _unload_reported = true; }
412 402
413 bool is_marked_for_deoptimization() const { return _markedForDeoptimization; } 403 bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; }
414 void mark_for_deoptimization() { _markedForDeoptimization = true; } 404 void mark_for_deoptimization() { _marked_for_deoptimization = true; }
415 405
416 void make_unloaded(BoolObjectClosure* is_alive, oop cause); 406 void make_unloaded(BoolObjectClosure* is_alive, oop cause);
417 407
418 bool has_dependencies() { return dependencies_size() != 0; } 408 bool has_dependencies() { return dependencies_size() != 0; }
419 void flush_dependencies(BoolObjectClosure* is_alive); 409 void flush_dependencies(BoolObjectClosure* is_alive);
420 bool has_flushed_dependencies() { return flags.hasFlushedDependencies; } 410 bool has_flushed_dependencies() { return _has_flushed_dependencies; }
421 void set_has_flushed_dependencies() { 411 void set_has_flushed_dependencies() {
422 assert(!has_flushed_dependencies(), "should only happen once"); 412 assert(!has_flushed_dependencies(), "should only happen once");
423 flags.hasFlushedDependencies = 1; 413 _has_flushed_dependencies = 1;
424 } 414 }
425 415
426 bool is_marked_for_reclamation() const { return flags.markedForReclamation; } 416 bool is_marked_for_reclamation() const { return _marked_for_reclamation; }
427 void mark_for_reclamation() { flags.markedForReclamation = 1; } 417 void mark_for_reclamation() { _marked_for_reclamation = 1; }
428 void unmark_for_reclamation() { flags.markedForReclamation = 0; } 418
429 419 bool has_unsafe_access() const { return _has_unsafe_access; }
430 bool has_unsafe_access() const { return flags.has_unsafe_access; } 420 void set_has_unsafe_access(bool z) { _has_unsafe_access = z; }
431 void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; } 421
432 422 bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
433 bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; } 423 void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
434 void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; } 424
435 425 bool is_speculatively_disconnected() const { return _speculatively_disconnected; }
436 bool is_speculatively_disconnected() const { return flags.speculatively_disconnected; } 426 void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; }
437 void set_speculatively_disconnected(bool z) { flags.speculatively_disconnected = z; }
438 427
439 int comp_level() const { return _comp_level; } 428 int comp_level() const { return _comp_level; }
440
441 int version() const { return flags.version; }
442 void set_version(int v);
443 429
444 // Support for oops in scopes and relocs: 430 // Support for oops in scopes and relocs:
445 // Note: index 0 is reserved for null. 431 // Note: index 0 is reserved for null.
446 oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); } 432 oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
447 oop* oop_addr_at(int index) const { // for GC 433 oop* oop_addr_at(int index) const { // for GC