Mercurial > hg > truffle
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 |