< prev index next >
src/hotspot/cpu/ppc/frame_ppc.cpp
Print this page
rev 51053 : JFR profiling for PPC64
* * *
PPC64: jfr profiling
@@ -47,18 +47,150 @@
}
#endif // ASSERT
bool frame::safe_for_sender(JavaThread *thread) {
bool safe = false;
- address cursp = (address)sp();
- address curfp = (address)fp();
- if ((cursp != NULL && curfp != NULL &&
- (cursp <= thread->stack_base() && cursp >= thread->stack_base() - thread->stack_size())) &&
- (curfp <= thread->stack_base() && curfp >= thread->stack_base() - thread->stack_size())) {
- safe = true;
+ address sp = (address)_sp;
+ address fp = (address)_fp;
+ address unextended_sp = (address)_unextended_sp;
+
+
+ // consider stack guards when trying to determine "safe" stack pointers
+ static size_t stack_guard_size = os::uses_stack_guard_pages() ?
+ JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size() : 0;
+ size_t usable_stack_size = thread->stack_size() - stack_guard_size;
+
+ // sp must be within the usable part of the stack (not in guards)
+ bool sp_safe = (sp < thread->stack_base()) &&
+ (sp >= thread->stack_base() - usable_stack_size);
+
+
+ if (!sp_safe) {
+ return false;
+ }
+
+ // unextended sp must be within the stack and above or equal sp
+ bool unextended_sp_safe = (unextended_sp < thread->stack_base()) && (unextended_sp >= sp);
+
+ if (!unextended_sp_safe) {
+ return false;
+ }
+
+ // an fp must be within the stack and above (but not equal) sp
+ bool fp_safe = (fp <= thread->stack_base()) && (fp > sp) && ((fp - sp) >= (ijava_state_size + top_ijava_frame_abi_size));
+
+ // We know sp/unextended_sp are safe only fp is questionable here
+
+ // If the current frame is known to the code cache then we can attempt to
+ // to construct the sender and do some validation of it. This goes a long way
+ // toward eliminating issues when we get in frame construction code
+
+ if (_cb != NULL ) {
+ // First check if frame is complete and tester is reliable
+ // Unfortunately we can only check frame complete for runtime stubs and nmethod
+ // other generic buffer blobs are more problematic so we just assume they are
+ // ok. adapter blobs never have a frame complete and are never ok.
+ if (!_cb->is_frame_complete_at(_pc)) {
+ if (_cb->is_compiled() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) {
+ return false;
+ }
+ }
+
+ // Could just be some random pointer within the codeBlob
+ if (!_cb->code_contains(_pc)) {
+ return false;
+ }
+
+ // Entry frame checks
+ if (is_entry_frame()) {
+ // an entry frame must have a valid fp.
+ return fp_safe && is_entry_frame_valid(thread);
+ }
+
+ if (is_interpreted_frame() && !fp_safe) {
+ return false;
+ }
+
+ abi_minframe* sender_abi = (abi_minframe*) fp;
+ intptr_t* sender_sp = (intptr_t*) fp;
+ address sender_pc = (address) sender_abi->lr;;
+
+ // We must always be able to find a recognizable pc
+ CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc);
+ if (sender_pc == NULL || sender_blob == NULL) {
+ return false;
+ }
+
+ // Could be a zombie method
+ if (sender_blob->is_zombie() || sender_blob->is_unloaded()) {
+ return false;
+ }
+
+ // It should be safe to construct the sender though it might not be valid
+
+ frame sender(sender_sp, sender_pc);
+
+ // Do we have a valid fp?
+ address sender_fp = (address) sender.fp();
+
+ // an fp must be within the stack and above (but not equal) current frame's _FP
+
+ bool sender_fp_safe = (sender_fp <= thread->stack_base()) && (sender_fp > fp);
+
+ if (!sender_fp_safe) {
+ return false;
+ }
+
+ // If the potential sender is the interpreter then we can do some more checking
+ if (Interpreter::contains(sender_pc)) {
+ return sender.is_interpreted_frame_valid(thread);
+ }
+
+ // Could just be some random pointer within the codeBlob
+ if (!sender.cb()->code_contains(sender_pc)) {
+ return false;
+ }
+
+ // We should never be able to see an adapter if the current frame is something from code cache
+ if (sender_blob->is_adapter_blob()) {
+ return false;
+ }
+
+ if (sender.is_entry_frame()) {
+ // Validate the JavaCallWrapper an entry frame must have
+
+ address jcw = (address)sender.entry_frame_call_wrapper();
+
+ bool jcw_safe = (jcw <= thread->stack_base()) && (jcw > sender_fp);
+ return jcw_safe;
}
- return safe;
+
+ // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size
+ // because you must allocate window space
+ if (sender_blob->frame_size() <= 0) {
+ return false;
+ }
+
+ // Could put some more validation for the potential non-interpreted sender
+ // frame we'd create by calling sender if I could think of any. Wait for next crash in forte...
+
+ // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb
+
+ // We've validated the potential sender that would be created
+
+ return true;
+
+ }
+
+ // Must be native-compiled frame. Since sender will try and use fp to find
+ // linkages it must be safe
+
+ if (!fp_safe) return false;
+
+ // could try and do some more potential verification of native frame if we could think of some...
+
+ return true;
}
bool frame::is_interpreted_frame() const {
return Interpreter::contains(pc());
}
< prev index next >