src/cpu/x86/vm/c1_Runtime1_x86.cpp

Print this page
rev 3150 : 7148486: At a method handle call returning with an exception may call the runtime with misaligned stack (x64)
Summary: stack must be realigned when calling the runtime for exception propagation at a call.
Reviewed-by:

@@ -45,10 +45,16 @@
   // setup registers
   const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); // is callee-saved register (Visual C++ calling conventions)
   assert(!(oop_result1->is_valid() || oop_result2->is_valid()) || oop_result1 != oop_result2, "registers must be different");
   assert(oop_result1 != thread && oop_result2 != thread, "registers must be different");
   assert(args_size >= 0, "illegal args_size");
+  bool align_stack = false;
+#ifdef _LP64
+  // At a method handle call, the stack may not be properly aligned
+  // when returning with an exception.
+  align_stack = (stub_id() == Runtime1::handle_exception_from_callee_id);
+#endif
 
 #ifdef _LP64
   mov(c_rarg0, thread);
   set_num_rt_args(0); // Nothing on stack
 #else

@@ -57,15 +63,25 @@
   // push java thread (becomes first argument of C function)
   get_thread(thread);
   push(thread);
 #endif // _LP64
 
+  int call_offset;
+  if (!align_stack) {
   set_last_Java_frame(thread, noreg, rbp, NULL);
+  } else {
+    address the_pc = pc();
+    call_offset = offset();
+    set_last_Java_frame(thread, noreg, rbp, the_pc);
+    andptr(rsp, -(StackAlignmentInBytes));    // Align stack
+  }
 
   // do the call
   call(RuntimeAddress(entry));
-  int call_offset = offset();
+  if (!align_stack) {
+    call_offset = offset();
+  }
   // verify callee-saved register
 #ifdef ASSERT
   guarantee(thread != rax, "change this code");
   push(rax);
   { Label L;

@@ -76,11 +92,11 @@
     stop("StubAssembler::call_RT: rdi not callee saved?");
     bind(L);
   }
   pop(rax);
 #endif
-  reset_last_Java_frame(thread, true, false);
+  reset_last_Java_frame(thread, true, align_stack);
 
   // discard thread and arguments
   NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord));
 
   // check for pending exceptions