# HG changeset patch # User bulasevich # Date 1616426559 -3600 # Mon Mar 22 16:22:39 2021 +0100 # Node ID 1effd12c479af44e3d3e36d9d1152a355a114603 # Parent a6e68314ec2258d867568104b146fbc0655951ed 8213845: ARM32: Interpreter doesn't call result handler after native calls Summary: Fix mapping of native jboolean result to 0..1 on ARM32 Reviewed-by: aph, phh Contributed-by: christoph.goettschkes@microdoc.com diff --git a/src/hotspot/cpu/arm/interpreterRT_arm.cpp b/src/hotspot/cpu/arm/interpreterRT_arm.cpp --- a/src/hotspot/cpu/arm/interpreterRT_arm.cpp +++ b/src/hotspot/cpu/arm/interpreterRT_arm.cpp @@ -86,11 +86,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; @@ -281,14 +282,7 @@ address result_handler = Interpreter::result_handler(result_type); -#ifdef AARCH64 - __ mov_slow(R0, (address)result_handler); -#else - // 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); -#endif __ ret(); } diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -1229,6 +1229,15 @@ bind(done); } +void MacroAssembler::c2bool(Register x) { + tst(x, 0xff); // Only look at the lowest byte +#ifdef AARCH64 + cset(x, ne); +#else + mov(x, 1, ne); +#endif +} + void MacroAssembler::null_check(Register reg, Register tmp, int offset) { if (needs_explicit_null_check(offset)) { #ifdef AARCH64 diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp --- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp @@ -1054,6 +1054,8 @@ #endif } + // C 'boolean' to Java boolean: x == 0 ? 0 : 1 + void c2bool(Register x); // klass oop manipulations if compressed diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -1657,6 +1657,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; diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -351,16 +351,12 @@ } address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type) { -#ifdef AARCH64 address entry = __ pc(); switch (type) { - case T_BOOLEAN: - __ tst(R0, 0xff); - __ cset(R0, ne); - break; - case T_CHAR : __ zero_extend(R0, R0, 16); break; - case T_BYTE : __ sign_extend(R0, R0, 8); break; - case T_SHORT : __ sign_extend(R0, R0, 16); break; + case T_BOOLEAN: __ c2bool(R0); break; + case T_CHAR : AARCH64_ONLY(__ zero_extend(R0, R0, 16);) break; + case T_BYTE : AARCH64_ONLY(__ sign_extend(R0, R0, 8);) break; + case T_SHORT : AARCH64_ONLY(__ sign_extend(R0, R0, 16);) break; case T_INT : // fall through case T_LONG : // fall through case T_VOID : // fall through @@ -372,19 +368,10 @@ // and verify it __ verify_oop(R0); break; - default : ShouldNotReachHere(); + default : __ should_not_reach_here(); break; } __ ret(); return entry; -#else - // 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 - - // 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; -#endif // AARCH64 } address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, address runtime_entry) { @@ -1216,14 +1203,9 @@ // Unbox oop result, e.g. JNIHandles::resolve result if it's an oop. { Label Lnot_oop; -#ifdef AARCH64 __ mov_slow(Rtemp, AbstractInterpreter::result_handler(T_OBJECT)); __ cmp(Rresult_handler, Rtemp); __ b(Lnot_oop, ne); -#else // !AARCH64 - // For ARM32, Rresult_handler is -1 for oop result, 0 otherwise. - __ cbz(Rresult_handler, Lnot_oop); -#endif // !AARCH64 Register value = AARCH64_ONLY(Rsaved_result) NOT_AARCH64(Rsaved_result_lo); __ resolve_jobject(value, // value Rtemp, // tmp1 @@ -1296,25 +1278,14 @@ __ blr(Rresult_handler); #else - __ cmp(Rresult_handler, 0); - __ ldr(R0, Address(FP, frame::interpreter_frame_oop_temp_offset * wordSize), ne); - __ mov(R0, Rsaved_result_lo, eq); + __ mov(R0, Rsaved_result_lo); __ mov(R1, Rsaved_result_hi); #ifdef __ABI_HARD__ // reload native FP result __ 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); #endif // AARCH64 // Restore FP/LR, sender_sp and return