8145137: Incorrect call signature can be used in nmethod::preserve_callee_argument_oops
authorvlivanov
Fri, 11 Dec 2015 15:03:11 +0300
changeset 35108 ccb4e1f2a6cf
parent 35107 ebed5fa5b08a
child 35109 92535200db7d
child 35119 7af8d9f08a25
8145137: Incorrect call signature can be used in nmethod::preserve_callee_argument_oops Reviewed-by: roland, jrose
hotspot/src/share/vm/code/nmethod.cpp
hotspot/src/share/vm/code/nmethod.hpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Dec 10 14:51:54 2015 +0300
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Fri Dec 11 15:03:11 2015 +0300
@@ -2332,11 +2332,22 @@
 void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) {
 #ifndef SHARK
   if (method() != NULL && !method()->is_native()) {
-    SimpleScopeDesc ssd(this, fr.pc());
+    address pc = fr.pc();
+    SimpleScopeDesc ssd(this, pc);
     Bytecode_invoke call(ssd.method(), ssd.bci());
     bool has_receiver = call.has_receiver();
     bool has_appendix = call.has_appendix();
     Symbol* signature = call.signature();
+
+    // The method attached by JIT-compilers should be used, if present.
+    // Bytecode can be inaccurate in such case.
+    Method* callee = attached_method_before_pc(pc);
+    if (callee != NULL) {
+      has_receiver = !(callee->access_flags().is_static());
+      has_appendix = false;
+      signature = callee->signature();
+    }
+
     fr.oops_compiled_arguments_do(signature, has_receiver, has_appendix, reg_map, f);
   }
 #endif // !SHARK
@@ -3526,3 +3537,11 @@
   return NULL; // not found
 }
 
+Method* nmethod::attached_method_before_pc(address pc) {
+  if (NativeCall::is_call_before(pc)) {
+    NativeCall* ncall = nativeCall_before(pc);
+    return attached_method(ncall->instruction_address());
+  }
+  return NULL; // not a call
+}
+
--- a/hotspot/src/share/vm/code/nmethod.hpp	Thu Dec 10 14:51:54 2015 +0300
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Fri Dec 11 15:03:11 2015 +0300
@@ -512,6 +512,7 @@
   void copy_values(GrowableArray<Metadata*>* metadata);
 
   Method* attached_method(address call_pc);
+  Method* attached_method_before_pc(address pc);
 
   // Relocation support
 private:
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Dec 10 14:51:54 2015 +0300
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Fri Dec 11 15:03:11 2015 +0300
@@ -1078,10 +1078,7 @@
   address pc = vfst.frame_pc();
   { // Get call instruction under lock because another thread may be busy patching it.
     MutexLockerEx ml_patch(Patching_lock, Mutex::_no_safepoint_check_flag);
-    if (NativeCall::is_call_before(pc)) {
-      NativeCall* ncall = nativeCall_before(pc);
-      return caller_nm->attached_method(ncall->instruction_address());
-    }
+    return caller_nm->attached_method_before_pc(pc);
   }
   return NULL;
 }
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java	Thu Dec 10 14:51:54 2015 +0300
+++ b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java	Fri Dec 11 15:03:11 2015 +0300
@@ -74,23 +74,23 @@
     }
 
     static class T implements I {
-        @DontInline public        Class<?> f1() { if (doDeopt) WB.deoptimize(); return T.class; }
-        @DontInline public static Class<?> f2() { if (doDeopt) WB.deoptimize(); return T.class; }
-        @DontInline private       Class<?> f4() { if (doDeopt) WB.deoptimize(); return T.class; }
+        @DontInline public        Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
+        @DontInline public static Class<?> f2() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
+        @DontInline private       Class<?> f4() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
     }
 
     static class P1 extends T {
-        @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimize(); return P1.class; }
-        @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimize(); return P1.class; }
+        @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P1.class; }
+        @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P1.class; }
     }
 
     static class P2 extends T {
-        @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimize(); return P2.class; }
-        @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimize(); return P2.class; }
+        @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P2.class; }
+        @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P2.class; }
     }
 
     static interface I {
-        @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimize(); return I.class; }
+        @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return I.class; }
     }
 
     @DontInline