8154957: AArch64: Better byte behavior
authoraph
Mon, 25 Apr 2016 14:22:36 +0000
changeset 38072 964dfd630089
parent 38070 db258b8fc791
child 38073 20edca0f3777
8154957: AArch64: Better byte behavior Summary: The fix for 8132051 is needed for AArch64. Reviewed-by: roland
hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp
hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp	Fri Apr 22 19:40:39 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp	Mon Apr 25 14:22:36 2016 +0000
@@ -331,7 +331,7 @@
     length.load_item();
 
   }
-  if (needs_store_check) {
+  if (needs_store_check || x->check_boolean()) {
     value.load_item();
   } else {
     value.load_for_store(x->elt_type());
@@ -380,7 +380,8 @@
     // Seems to be a precise
     post_barrier(LIR_OprFact::address(array_addr), value.result());
   } else {
-    __ move(value.result(), array_addr, null_check_info);
+    LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
+    __ move(result, array_addr, null_check_info);
   }
 }
 
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp	Fri Apr 22 19:40:39 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp	Mon Apr 25 14:22:36 2016 +0000
@@ -40,7 +40,43 @@
 #include "runtime/thread.inline.hpp"
 
 
-// Implementation of InterpreterMacroAssembler
+void InterpreterMacroAssembler::narrow(Register result) {
+
+  // Get method->_constMethod->_result_type
+  ldr(rscratch1, Address(rfp, frame::interpreter_frame_method_offset * wordSize));
+  ldr(rscratch1, Address(rscratch1, Method::const_offset()));
+  ldrb(rscratch1, Address(rscratch1, ConstMethod::result_type_offset()));
+
+  Label done, notBool, notByte, notChar;
+
+  // common case first
+  cmpw(rscratch1, T_INT);
+  br(Assembler::EQ, done);
+
+  // mask integer result to narrower return type.
+  cmpw(rscratch1, T_BOOLEAN);
+  br(Assembler::NE, notBool);
+  andw(result, result, 0x1);
+  b(done);
+
+  bind(notBool);
+  cmpw(rscratch1, T_BYTE);
+  br(Assembler::NE, notByte);
+  sbfx(result, result, 0, 8);
+  b(done);
+
+  bind(notByte);
+  cmpw(rscratch1, T_CHAR);
+  br(Assembler::NE, notChar);
+  ubfx(result, result, 0, 16);  // truncate upper 16 bits
+  b(done);
+
+  bind(notChar);
+  sbfx(result, result, 0, 16);     // sign-extend short
+
+  // Nothing to do for T_INT
+  bind(done);
+}
 
 void InterpreterMacroAssembler::jump_to_entry(address entry) {
   assert(entry, "Entry must have been generated by now");
@@ -81,6 +117,7 @@
                verify_oop(r0, state);               break;
     case ltos: ldr(r0, val_addr);                   break;
     case btos:                                   // fall through
+    case ztos:                                   // fall through
     case ctos:                                   // fall through
     case stos:                                   // fall through
     case itos: ldrw(r0, val_addr);                  break;
@@ -314,6 +351,7 @@
   switch (state) {
   case atos: pop_ptr();                 break;
   case btos:
+  case ztos:
   case ctos:
   case stos:
   case itos: pop_i();                   break;
@@ -331,6 +369,7 @@
   switch (state) {
   case atos: push_ptr();                break;
   case btos:
+  case ztos:
   case ctos:
   case stos:
   case itos: push_i();                  break;
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp	Fri Apr 22 19:40:39 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp	Mon Apr 25 14:22:36 2016 +0000
@@ -245,6 +245,9 @@
   void update_mdp_by_constant(Register mdp_in, int constant);
   void update_mdp_for_ret(Register return_bci);
 
+  // narrow int return value
+  void narrow(Register result);
+
   void profile_taken_branch(Register mdp, Register bumped_count);
   void profile_not_taken_branch(Register mdp);
   void profile_call(Register mdp);
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Fri Apr 22 19:40:39 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Mon Apr 25 14:22:36 2016 +0000
@@ -1184,6 +1184,10 @@
                      Register result, Register cnt1,
                      int elem_size, bool is_string);
 
+  void fill_words(Register base, Register cnt, Register value);
+  void zero_words(Register base, Register cnt);
+  void zero_words(Register base, u_int64_t cnt);
+
   void byte_array_inflate(Register src, Register dst, Register len,
                           FloatRegister vtmp1, FloatRegister vtmp2,
                           FloatRegister vtmp3, Register tmp4);
--- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp	Fri Apr 22 19:40:39 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp	Mon Apr 25 14:22:36 2016 +0000
@@ -229,6 +229,7 @@
   switch (bc) {
   case Bytecodes::_fast_aputfield:
   case Bytecodes::_fast_bputfield:
+  case Bytecodes::_fast_zputfield:
   case Bytecodes::_fast_cputfield:
   case Bytecodes::_fast_dputfield:
   case Bytecodes::_fast_fputfield:
@@ -1082,6 +1083,17 @@
   // r1: index
   // r3: array
   index_check(r3, r1); // prefer index in r1
+
+  // Need to check whether array is boolean or byte
+  // since both types share the bastore bytecode.
+  __ load_klass(r2, r3);
+  __ ldrw(r2, Address(r2, Klass::layout_helper_offset()));
+  int diffbit_index = exact_log2(Klass::layout_helper_boolean_diffbit());
+  Label L_skip;
+  __ tbz(r2, diffbit_index, L_skip);
+  __ andw(r0, r0, 1);  // if it is a T_BOOLEAN array, mask the stored value to 0/1
+  __ bind(L_skip);
+
   __ lea(rscratch1, Address(r3, r1, Address::uxtw(0)));
   __ strb(r0, Address(rscratch1,
                       arrayOopDesc::base_offset_in_bytes(T_BYTE)));
@@ -2193,6 +2205,13 @@
   if (_desc->bytecode() == Bytecodes::_return)
     __ membar(MacroAssembler::StoreStore);
 
+  // Narrow result if state is itos but result type is smaller.
+  // Need to narrow in the return bytecode rather than in generate_return_entry
+  // since compiled code callers expect the result to already be narrowed.
+  if (state == itos) {
+    __ narrow(r0);
+  }
+
   __ remove_activation(state);
   __ ret(lr);
 }
@@ -2386,7 +2405,7 @@
 
   const Address field(obj, off);
 
-  Label Done, notByte, notInt, notShort, notChar,
+  Label Done, notByte, notBool, notInt, notShort, notChar,
               notLong, notFloat, notObj, notDouble;
 
   // x86 uses a shift and mask or wings it with a shift plus assert
@@ -2409,6 +2428,20 @@
   __ b(Done);
 
   __ bind(notByte);
+  __ cmp(flags, ztos);
+  __ br(Assembler::NE, notBool);
+
+  // ztos (same code as btos)
+  __ ldrsb(r0, field);
+  __ push(ztos);
+  // Rewrite bytecode to be faster
+  if (!is_static) {
+    // use btos rewriting, no truncating to t/f bit is needed for getfield.
+    patch_bytecode(Bytecodes::_fast_bgetfield, bc, r1);
+  }
+  __ b(Done);
+
+  __ bind(notBool);
   __ cmp(flags, atos);
   __ br(Assembler::NE, notObj);
   // atos
@@ -2604,7 +2637,7 @@
   // field address
   const Address field(obj, off);
 
-  Label notByte, notInt, notShort, notChar,
+  Label notByte, notBool, notInt, notShort, notChar,
         notLong, notFloat, notObj, notDouble;
 
   // x86 uses a shift and mask or wings it with a shift plus assert
@@ -2629,6 +2662,22 @@
   }
 
   __ bind(notByte);
+  __ cmp(flags, ztos);
+  __ br(Assembler::NE, notBool);
+
+  // ztos
+  {
+    __ pop(ztos);
+    if (!is_static) pop_and_check_object(obj);
+    __ andw(r0, r0, 0x1);
+    __ strb(r0, field);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_zputfield, bc, r1, true, byte_no);
+    }
+    __ b(Done);
+  }
+
+  __ bind(notBool);
   __ cmp(flags, atos);
   __ br(Assembler::NE, notObj);
 
@@ -2783,6 +2832,7 @@
     switch (bytecode()) {          // load values into the jvalue object
     case Bytecodes::_fast_aputfield: __ push_ptr(r0); break;
     case Bytecodes::_fast_bputfield: // fall through
+    case Bytecodes::_fast_zputfield: // fall through
     case Bytecodes::_fast_sputfield: // fall through
     case Bytecodes::_fast_cputfield: // fall through
     case Bytecodes::_fast_iputfield: __ push_i(r0); break;
@@ -2808,6 +2858,7 @@
     switch (bytecode()) {             // restore tos values
     case Bytecodes::_fast_aputfield: __ pop_ptr(r0); break;
     case Bytecodes::_fast_bputfield: // fall through
+    case Bytecodes::_fast_zputfield: // fall through
     case Bytecodes::_fast_sputfield: // fall through
     case Bytecodes::_fast_cputfield: // fall through
     case Bytecodes::_fast_iputfield: __ pop_i(r0); break;
@@ -2863,6 +2914,9 @@
   case Bytecodes::_fast_iputfield:
     __ strw(r0, field);
     break;
+  case Bytecodes::_fast_zputfield:
+    __ andw(r0, r0, 0x1);  // boolean is true if LSB is 1
+    // fall through to bputfield
   case Bytecodes::_fast_bputfield:
     __ strb(r0, field);
     break;