hotspot/src/cpu/x86/vm/frame_x86.cpp
changeset 4564 55dfb20908d0
parent 3261 c7d5aae8d3f7
child 4748 3fa8d8a7c0ea
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp	Mon Jan 04 07:04:46 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp	Mon Jan 04 18:38:08 2010 +0100
@@ -330,6 +330,14 @@
   // This is the sp before any possible extension (adapter/locals).
   intptr_t* unextended_sp = interpreter_frame_sender_sp();
 
+  address sender_pc = this->sender_pc();
+  CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
+  assert(sender_cb, "sanity");
+  nmethod* sender_nm = sender_cb->as_nmethod_or_null();
+  if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
+    unextended_sp = (intptr_t*) at(link_offset);
+  }
+
   // The interpreter and compiler(s) always save EBP/RBP in a known
   // location on entry. We must record where that location is
   // so this if EBP/RBP was live on callout from c2 we can find
@@ -352,7 +360,7 @@
 #endif // AMD64
   }
 #endif /* COMPILER2 */
-  return frame(sp, unextended_sp, link(), sender_pc());
+  return frame(sp, unextended_sp, link(), sender_pc);
 }
 
 
@@ -375,6 +383,18 @@
 
   intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset);
 
+  intptr_t* unextended_sp = sender_sp;
+  // If we are returning to a compiled method handle call site,
+  // the saved_fp will in fact be a saved value of the unextended SP.
+  // The simplest way to tell whether we are returning to such a call
+  // site is as follows:
+  CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
+  assert(sender_cb, "sanity");
+  nmethod* sender_nm = sender_cb->as_nmethod_or_null();
+  if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
+    unextended_sp = saved_fp;
+  }
+
   if (map->update_map()) {
     // Tell GC to use argument oopmaps for some runtime stubs that need it.
     // For C1, the runtime stub might not have oop maps, so set this flag
@@ -399,7 +419,7 @@
   }
 
   assert(sender_sp != sp(), "must have changed");
-  return frame(sender_sp, saved_fp, sender_pc);
+  return frame(sender_sp, unextended_sp, saved_fp, sender_pc);
 }
 
 frame frame::sender(RegisterMap* map) const {