8213845: ARM32: Interpreter doesn't call result handler after native calls
Reviewed-by: aph
--- 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);