8213845: ARM32: Interpreter doesn't call result handler after native calls
authorbulasevich
Fri, 23 Nov 2018 19:45:38 +0300
changeset 52676 2d795829f39f
parent 52675 7d3cde494494
child 52677 30a02b4e6c06
8213845: ARM32: Interpreter doesn't call result handler after native calls Reviewed-by: aph
src/hotspot/cpu/arm/interpreterRT_arm.cpp
src/hotspot/cpu/arm/macroAssembler_arm.cpp
src/hotspot/cpu/arm/macroAssembler_arm.hpp
src/hotspot/cpu/arm/sharedRuntime_arm.cpp
src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp
--- a/src/hotspot/cpu/arm/interpreterRT_arm.cpp	Thu Nov 22 17:25:47 2018 +0100
+++ b/src/hotspot/cpu/arm/interpreterRT_arm.cpp	Fri Nov 23 19:45:38 2018 +0300
@@ -82,11 +82,12 @@
   // For ARM, the fast signature handler only needs to know whether
   // the return value must be unboxed. T_OBJECT and T_ARRAY need not
   // be distinguished from each other and all other return values
-  // behave like integers with respect to the handler.
+  // behave like integers with respect to the handler except T_BOOLEAN
+  // which must be mapped to the range 0..1.
   bool unbox = (ret_type == T_OBJECT) || (ret_type == T_ARRAY);
   if (unbox) {
     ret_type = T_OBJECT;
-  } else {
+  } else if (ret_type != T_BOOLEAN) {
     ret_type = T_INT;
   }
   result |= ((uint64_t) ret_type) << shift;
@@ -226,9 +227,6 @@
 
   address result_handler = Interpreter::result_handler(result_type);
 
-  // Check that result handlers are not real handler on ARM (0 or -1).
-  // This ensures the signature handlers do not need symbolic information.
-  assert((result_handler == NULL)||(result_handler==(address)0xffffffff),"");
   __ mov_slow(R0, (intptr_t)result_handler);
 
   __ ret();
--- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp	Thu Nov 22 17:25:47 2018 +0100
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp	Fri Nov 23 19:45:38 2018 +0300
@@ -941,6 +941,12 @@
   bind(done);
 }
 
+void MacroAssembler::c2bool(Register x)
+{
+  tst(x, 0xff);   // Only look at the lowest byte
+  mov(x, 1, ne);
+}
+
 void MacroAssembler::null_check(Register reg, Register tmp, int offset) {
   if (needs_explicit_null_check(offset)) {
     assert_different_registers(reg, tmp);
--- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp	Thu Nov 22 17:25:47 2018 +0100
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp	Fri Nov 23 19:45:38 2018 +0300
@@ -853,6 +853,8 @@
     sub(dst, r1, AsmOperand(r2, lsl, shift));
   }
 
+  // C 'boolean' to Java boolean: x == 0 ? 0 : 1
+  void c2bool(Register x);
 
     // klass oop manipulations if compressed
 
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp	Thu Nov 22 17:25:47 2018 +0100
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp	Fri Nov 23 19:45:38 2018 +0300
@@ -1211,6 +1211,11 @@
     __ restore_default_fp_mode();
   }
 
+  // Ensure a Boolean result is mapped to 0..1
+  if (ret_type == T_BOOLEAN) {
+    __ c2bool(R0);
+  }
+
   // Do a safepoint check while thread is in transition state
   InlinedAddress safepoint_state(SafepointSynchronize::address_of_state());
   Label call_safepoint_runtime, return_to_java;
--- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp	Thu Nov 22 17:25:47 2018 +0100
+++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp	Fri Nov 23 19:45:38 2018 +0300
@@ -316,13 +316,27 @@
 }
 
 address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type) {
-  // Result handlers are not used on 32-bit ARM
-  // since the returned value is already in appropriate format.
-  __ should_not_reach_here();  // to avoid empty code block
+  address entry = __ pc();
 
-  // The result handler non-zero indicates an object is returned and this is
-  // used in the native entry code.
-  return type == T_OBJECT ? (address)(-1) : NULL;
+  switch (type) {
+  case T_CHAR    : /* Nothing to do */  break;
+  case T_BYTE    : /* Nothing to do */  break;
+  case T_SHORT   : /* Nothing to do */  break;
+  case T_INT     : /* Nothing to do */  break;
+  case T_LONG    : /* Nothing to do */  break;
+  case T_VOID    : /* Nothing to do */  break;
+  case T_DOUBLE  : /* Nothing to do */  break;
+  case T_FLOAT   : /* Nothing to do */  break;
+  case T_BOOLEAN : __ c2bool(R0);       break;
+  case T_OBJECT  :
+    __ ldr(R0, Address(FP, frame::interpreter_frame_oop_temp_offset * wordSize));
+    __ verify_oop(R0);
+    break;
+  default        : __ should_not_reach_here(); break;
+  }
+
+  __ ret();
+  return entry;
 }
 
 address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, address runtime_entry) {
@@ -985,8 +999,9 @@
   // Unbox oop result, e.g. JNIHandles::resolve result if it's an oop.
   {
     Label Lnot_oop;
-    // For ARM32, Rresult_handler is -1 for oop result, 0 otherwise.
-    __ cbz(Rresult_handler, Lnot_oop);
+    __ mov_slow(Rtemp, AbstractInterpreter::result_handler(T_OBJECT));
+    __ cmp(Rtemp, Rresult_handler);
+    __ b(Lnot_oop, ne);
     Register value = Rsaved_result_lo;
     __ resolve_jobject(value,   // value
                        Rtemp,   // tmp1
@@ -1028,10 +1043,9 @@
   //       not properly paired (was bug - gri 11/22/99).
   __ notify_method_exit(vtos, InterpreterMacroAssembler::NotifyJVMTI, true, Rsaved_result_lo, Rsaved_result_hi, saved_result_fp);
 
-  // Restore the result. Oop result is restored from the stack.
-  __ cmp(Rresult_handler, 0);
-  __ ldr(R0, Address(FP, frame::interpreter_frame_oop_temp_offset * wordSize), ne);
-  __ mov(R0, Rsaved_result_lo, eq);
+  // Restore the result. Oop result is restored from the stack by the
+  // result handler.
+  __ mov(R0, Rsaved_result_lo);
   __ mov(R1, Rsaved_result_hi);
 
 #ifdef __ABI_HARD__
@@ -1039,15 +1053,7 @@
   __ fcpyd(D0, D8);
 #endif // __ABI_HARD__
 
-#ifdef ASSERT
-  if (VerifyOops) {
-    Label L;
-    __ cmp(Rresult_handler, 0);
-    __ b(L, eq);
-    __ verify_oop(R0);
-    __ bind(L);
-  }
-#endif // ASSERT
+  __ blx(Rresult_handler);
 
   // Restore FP/LR, sender_sp and return
   __ mov(Rtemp, FP);