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 |