changeset 7851:e06cbcf76984 jdk8u91-b14-aarch32-160510

8156067: aarch32: backport better byte behaviour Reviewed-by: enevill Contributed-by: snazarkin@azul.com
author enevill
date Fri, 06 May 2016 12:00:02 +0100
parents 1d0974d906a5
children eb48bdceeb3e
files src/cpu/aarch32/vm/interp_masm_aarch32.cpp src/cpu/aarch32/vm/interp_masm_aarch32.hpp src/cpu/aarch32/vm/templateTable_aarch32.cpp
diffstat 3 files changed, 89 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/aarch32/vm/interp_masm_aarch32.cpp	Tue May 03 11:05:40 2016 +0100
+++ b/src/cpu/aarch32/vm/interp_masm_aarch32.cpp	Fri May 06 12:00:02 2016 +0100
@@ -43,6 +43,35 @@
 
 // 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;
+
+  // common case first
+
+  cmp(rscratch1, T_INT);
+  b(done, Assembler::EQ);
+
+  // mask integer result to narrower return type.
+  cmp(rscratch1, T_BOOLEAN);
+  andr(result, result, 0x1, Assembler::EQ);
+
+  cmp(rscratch1, T_BYTE);
+  sbfx(result, result, 0, 8, Assembler::EQ);
+
+  cmp(rscratch1, T_CHAR);
+  ubfx(result, result, 0, 16, Assembler::EQ);  // truncate upper 16 bits
+
+  sbfx(result, result, 0, 16, Assembler::NE);  // sign-extend short
+
+  // Nothing to do for T_INT
+  bind(done);
+}
+
 #ifndef CC_INTERP
 
 void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) {
@@ -80,6 +109,7 @@
                verify_oop(r0, state);               break;
     case ltos: ldrd(r0, val_addr);                  break;
     case btos:                                   // fall through
+    case ztos:                                   // fall through
     case ctos:                                   // fall through
     case stos:                                   // fall through
     case itos: ldr(r0, val_addr);                   break;
@@ -318,6 +348,7 @@
   switch (state) {
   case atos: pop_ptr();                 break;
   case btos:
+  case ztos:
   case ctos:
   case stos:
   case itos: pop_i();                   break;
@@ -335,6 +366,7 @@
   switch (state) {
   case atos: push_ptr();                break;
   case btos:
+  case ztos:
   case ctos:
   case stos:
   case itos: push_i();                  break;
--- a/src/cpu/aarch32/vm/interp_masm_aarch32.hpp	Tue May 03 11:05:40 2016 +0100
+++ b/src/cpu/aarch32/vm/interp_masm_aarch32.hpp	Fri May 06 12:00:02 2016 +0100
@@ -251,6 +251,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/src/cpu/aarch32/vm/templateTable_aarch32.cpp	Tue May 03 11:05:40 2016 +0100
+++ b/src/cpu/aarch32/vm/templateTable_aarch32.cpp	Fri May 06 12:00:02 2016 +0100
@@ -245,6 +245,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,15 @@
   // r2: index
   // r3: array
   index_check(r3, r2); // prefer index in r2
+
+  // Need to check whether array is boolean or byte
+  // since both types share the bastore bytecode.
+  __ load_klass(r1, r3);
+  __ ldr(r1, Address(r1, Klass::layout_helper_offset()));
+  int diffbit = Klass::layout_helper_boolean_diffbit();
+  __ tst(r1, diffbit);
+  __ andr(r0, r0, 1, Assembler::NE);  // if it is a T_BOOLEAN array, mask the stored value to 0/1
+
   __ lea(rscratch1, Address(r3, r2));
   __ strb(r0, Address(rscratch1,
                       arrayOopDesc::base_offset_in_bytes(T_BYTE)));
@@ -2298,6 +2308,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);
+  }
+
   __ reg_printf("About to attmpt to remove activation with rfp = %p\n", rfp);
   __ remove_activation(state);
   __ reg_printf("Finshed _return, about to jump to lr = %p\n", lr);
@@ -2522,7 +2539,7 @@
   const Address field(obj, off);
 
 
-  Label Done, notByte, notInt, notShort, notChar,
+  Label Done, notByte, notBool, notInt, notShort, notChar,
               notLong, notFloat, notObj, notDouble;
 
   //__ bkpt(324);
@@ -2543,6 +2560,20 @@
   __ b(Done);
 
   __ bind(notByte);
+  __ cmp(flags, ztos);
+  __ b(notBool, Assembler::NE);
+
+  // 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);
   __ b(notObj, Assembler::NE);
   // atos
@@ -2736,7 +2767,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
@@ -2762,6 +2793,22 @@
   }
 
   __ bind(notByte);
+  __ cmp(rscratch1, ztos);
+  __ b(notBool, Assembler::NE);
+
+  // ztos
+  {
+    __ pop(ztos);
+    if (!is_static) pop_and_check_object(obj);
+    __ andr(r0, r0, 0x1);
+    __ strb(r0, field);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_zputfield, bc, r1, true, byte_no);
+    }
+    __ b(Done);
+  }
+
+  __ bind(notBool);
   __ cmp(rscratch1, atos);
   __ b(notObj, Assembler::NE);
 
@@ -2930,6 +2977,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;
@@ -2955,6 +3003,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;
@@ -3011,6 +3060,9 @@
   case Bytecodes::_fast_iputfield:
     __ str(r0, field);
     break;
+  case Bytecodes::_fast_zputfield:
+    __ andr(r0, r0, 0x1);  // boolean is true if LSB is 1
+    // fall through to bputfield
   case Bytecodes::_fast_bputfield:
     __ strb(r0, field);
     break;