# HG changeset patch # User bulasevich # Date 1542991538 -10800 # Node ID 2d795829f39fbb50f2493658dc492a4d2e036aec # Parent 7d3cde4944947b6a704d3356a2656ff4a5c5e0ef 8213845: ARM32: Interpreter doesn't call result handler after native calls Reviewed-by: aph diff -r 7d3cde494494 -r 2d795829f39f src/hotspot/cpu/arm/interpreterRT_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(); diff -r 7d3cde494494 -r 2d795829f39f src/hotspot/cpu/arm/macroAssembler_arm.cpp --- 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); diff -r 7d3cde494494 -r 2d795829f39f src/hotspot/cpu/arm/macroAssembler_arm.hpp --- 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 diff -r 7d3cde494494 -r 2d795829f39f src/hotspot/cpu/arm/sharedRuntime_arm.cpp --- 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; diff -r 7d3cde494494 -r 2d795829f39f src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp --- 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);