< prev index next >

src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp

Print this page

 153     ldp(c_rarg3, c_rarg2, Address(post(sp, 2 * wordSize)));
 154   } else {
 155     mov(c_rarg1, arg1);
 156     mov(c_rarg2, arg2);
 157     mov(c_rarg3, arg3);
 158   }
 159   return call_RT(oop_result1, metadata_result, entry, 3);
 160 }
 161 
 162 enum return_state_t {
 163   does_not_return, requires_return
 164 };
 165 
 166 
 167 // Implementation of StubFrame
 168 
 169 class StubFrame: public StackObj {
 170  private:
 171   StubAssembler* _sasm;
 172   bool _return_state;

 173 
 174  public:
 175   StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state=requires_return);
 176   void load_argument(int offset_in_words, Register reg);
 177 




 178   ~StubFrame();


 179 };;
 180 
 181 void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
 182   set_info(name, must_gc_arguments);
 183   enter();
 184 }
 185 
 186 void StubAssembler::epilogue() {
 187   leave();








 188   ret(lr);
 189 }
 190 
 191 #define __ _sasm->
 192 
 193 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state) {
 194   _sasm = sasm;
 195   _return_state = return_state;
 196   __ prologue(name, must_gc_arguments);
 197 }
 198 











 199 // load parameters that were stored with LIR_Assembler::store_parameter
 200 // Note: offsets for store_parameter and load_argument must match
 201 void StubFrame::load_argument(int offset_in_words, Register reg) {
 202   __ load_parameter(offset_in_words, reg);
 203 }
 204 
 205 StubFrame::~StubFrame() {
 206   if (_return_state == requires_return) {
 207     __ epilogue();
 208   } else {
 209     __ should_not_reach_here();
 210   }
 211 }
 212 
 213 #undef __
 214 
 215 
 216 // Implementation of Runtime1
 217 
 218 #define __ sasm->
 219 
 220 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;
 221 
 222 // Stack layout for saving/restoring  all the registers needed during a runtime
 223 // call (this includes deoptimization)
 224 // Note: note that users of this frame may well have arguments to some runtime
 225 // while these values are on the stack. These positions neglect those arguments
 226 // but the code in save_live_registers will take the argument count into
 227 // account.
 228 //
 229 
 230 enum reg_save_layout {

 235 // Tries to smart of about FP registers.  In particular we separate
 236 // saving and describing the FPU registers for deoptimization since we
 237 // have to save the FPU registers twice if we describe them.  The
 238 // deopt blob is the only thing which needs to describe FPU registers.
 239 // In all other cases it should be sufficient to simply save their
 240 // current value.
 241 
 242 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs];
 243 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs];
 244 static int reg_save_size_in_words;
 245 static int frame_size_in_bytes = -1;
 246 
 247 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) {
 248   int frame_size_in_bytes = reg_save_frame_size * BytesPerWord;
 249   sasm->set_frame_size(frame_size_in_bytes / BytesPerWord);
 250   int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
 251   OopMap* oop_map = new OopMap(frame_size_in_slots, 0);
 252 
 253   for (int i = 0; i < FrameMap::nof_cpu_regs; i++) {
 254     Register r = as_Register(i);
 255     if (i <= 18 && i != rscratch1->encoding() && i != rscratch2->encoding()) {
 256       int sp_offset = cpu_reg_save_offsets[i];
 257       oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
 258                                 r->as_VMReg());
 259     }
 260   }
 261 
 262   if (save_fpu_registers) {
 263     for (int i = 0; i < FrameMap::nof_fpu_regs; i++) {
 264       FloatRegister r = as_FloatRegister(i);
 265       {
 266         int sp_offset = fpu_reg_save_offsets[i];
 267         oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
 268                                   r->as_VMReg());
 269       }
 270     }
 271   }
 272   return oop_map;
 273 }
 274 
 275 static OopMap* save_live_registers(StubAssembler* sasm,

 320 
 321 
 322 void Runtime1::initialize_pd() {
 323   int i;
 324   int sp_offset = 0;
 325 
 326   // all float registers are saved explicitly
 327   assert(FrameMap::nof_fpu_regs == 32, "double registers not handled here");
 328   for (i = 0; i < FrameMap::nof_fpu_regs; i++) {
 329     fpu_reg_save_offsets[i] = sp_offset;
 330     sp_offset += 2;   // SP offsets are in halfwords
 331   }
 332 
 333   for (i = 0; i < FrameMap::nof_cpu_regs; i++) {
 334     Register r = as_Register(i);
 335     cpu_reg_save_offsets[i] = sp_offset;
 336     sp_offset += 2;   // SP offsets are in halfwords
 337   }
 338 }
 339 









 340 
 341 // target: the entry point of the method that creates and posts the exception oop
 342 // has_argument: true if the exception needs arguments (passed in rscratch1 and rscratch2)
 343 
 344 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {
 345   // make a frame and preserve the caller's caller-save registers
 346   OopMap* oop_map = save_live_registers(sasm);
 347   int call_offset;
 348   if (!has_argument) {
 349     call_offset = __ call_RT(noreg, noreg, target);
 350   } else {
 351     __ mov(c_rarg1, rscratch1);
 352     __ mov(c_rarg2, rscratch2);
 353     call_offset = __ call_RT(noreg, noreg, target);
 354   }
 355   OopMapSet* oop_maps = new OopMapSet();
 356   oop_maps->add_gc_map(call_offset, oop_map);
 357   return oop_maps;
 358 }
 359 

 845         __ check_klass_subtype_slow_path(r4, r0, r2, r5, nullptr, &miss);
 846 
 847         // fallthrough on success:
 848         __ mov(rscratch1, 1);
 849         __ str(rscratch1, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
 850         __ pop(RegSet::of(r0, r2, r4, r5), sp);
 851         __ ret(lr);
 852 
 853         __ bind(miss);
 854         __ str(zr, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
 855         __ pop(RegSet::of(r0, r2, r4, r5), sp);
 856         __ ret(lr);
 857       }
 858       break;
 859 
 860     case monitorenter_nofpu_id:
 861       save_fpu_registers = false;
 862       // fall through
 863     case monitorenter_id:
 864       {
 865         StubFrame f(sasm, "monitorenter", dont_gc_arguments);
 866         OopMap* map = save_live_registers(sasm, save_fpu_registers);
 867 
 868         // Called with store_parameter and not C abi
 869 
 870         f.load_argument(1, r0); // r0,: object
 871         f.load_argument(0, r1); // r1,: lock address
 872 
 873         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), r0, r1);
 874 
 875         oop_maps = new OopMapSet();
 876         oop_maps->add_gc_map(call_offset, map);
 877         restore_live_registers(sasm, save_fpu_registers);
 878       }
 879       break;
 880 
 881     case monitorexit_nofpu_id:
 882       save_fpu_registers = false;
 883       // fall through
 884     case monitorexit_id:
 885       {

 153     ldp(c_rarg3, c_rarg2, Address(post(sp, 2 * wordSize)));
 154   } else {
 155     mov(c_rarg1, arg1);
 156     mov(c_rarg2, arg2);
 157     mov(c_rarg3, arg3);
 158   }
 159   return call_RT(oop_result1, metadata_result, entry, 3);
 160 }
 161 
 162 enum return_state_t {
 163   does_not_return, requires_return
 164 };
 165 
 166 
 167 // Implementation of StubFrame
 168 
 169 class StubFrame: public StackObj {
 170  private:
 171   StubAssembler* _sasm;
 172   bool _return_state;
 173   bool _use_pop_on_epilogue;
 174 
 175   StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
 176             return_state_t return_state, bool use_pop_on_epilogue);

 177 
 178  public:
 179   StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, bool use_pop_on_epilogue);
 180   StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state);
 181   StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments);
 182   ~StubFrame();
 183 
 184   void load_argument(int offset_in_words, Register reg);
 185 };;
 186 
 187 void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
 188   set_info(name, must_gc_arguments);
 189   enter();
 190 }
 191 
 192 void StubAssembler::epilogue(bool use_pop) {
 193   // use_pop when this frame may have been frozen on one carrier
 194   // thread then thawed on another carrier thread, rendering the fp
 195   // register invalid. We must restore the previous FP because it is
 196   // used as a call-saved scratch register by compiled code.
 197   if (use_pop) {
 198     ldp(rfp, lr, Address(post(sp, 2 * wordSize)));
 199   } else {
 200     leave();
 201   }
 202   ret(lr);
 203 }
 204 
 205 #define __ _sasm->
 206 
 207 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
 208                      return_state_t return_state, bool use_pop_on_epilogue)
 209   : _sasm(sasm), _return_state(return_state), _use_pop_on_epilogue(use_pop_on_epilogue) {
 210   __ prologue(name, must_gc_arguments);
 211 }
 212 
 213 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
 214                      bool use_pop_on_epilogue) :
 215   StubFrame(sasm, name, must_gc_arguments, requires_return, use_pop_on_epilogue) {}
 216 
 217 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
 218                      return_state_t return_state) :
 219   StubFrame(sasm, name, must_gc_arguments, return_state, /*use_pop_on_epilogue*/false) {}
 220 
 221 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) :
 222   StubFrame(sasm, name, must_gc_arguments, requires_return, /*use_pop_on_epilogue*/false) {}
 223 
 224 // load parameters that were stored with LIR_Assembler::store_parameter
 225 // Note: offsets for store_parameter and load_argument must match
 226 void StubFrame::load_argument(int offset_in_words, Register reg) {
 227   __ load_parameter(offset_in_words, reg);
 228 }
 229 
 230 StubFrame::~StubFrame() {
 231   __ epilogue(_use_pop_on_epilogue);




 232 }
 233 
 234 #undef __
 235 
 236 
 237 // Implementation of Runtime1
 238 
 239 #define __ sasm->
 240 
 241 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;
 242 
 243 // Stack layout for saving/restoring  all the registers needed during a runtime
 244 // call (this includes deoptimization)
 245 // Note: note that users of this frame may well have arguments to some runtime
 246 // while these values are on the stack. These positions neglect those arguments
 247 // but the code in save_live_registers will take the argument count into
 248 // account.
 249 //
 250 
 251 enum reg_save_layout {

 256 // Tries to smart of about FP registers.  In particular we separate
 257 // saving and describing the FPU registers for deoptimization since we
 258 // have to save the FPU registers twice if we describe them.  The
 259 // deopt blob is the only thing which needs to describe FPU registers.
 260 // In all other cases it should be sufficient to simply save their
 261 // current value.
 262 
 263 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs];
 264 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs];
 265 static int reg_save_size_in_words;
 266 static int frame_size_in_bytes = -1;
 267 
 268 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) {
 269   int frame_size_in_bytes = reg_save_frame_size * BytesPerWord;
 270   sasm->set_frame_size(frame_size_in_bytes / BytesPerWord);
 271   int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
 272   OopMap* oop_map = new OopMap(frame_size_in_slots, 0);
 273 
 274   for (int i = 0; i < FrameMap::nof_cpu_regs; i++) {
 275     Register r = as_Register(i);
 276     if (r == rthread || (i <= 18 && i != rscratch1->encoding() && i != rscratch2->encoding())) {
 277       int sp_offset = cpu_reg_save_offsets[i];
 278       oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
 279                                 r->as_VMReg());
 280     }
 281   }
 282 
 283   if (save_fpu_registers) {
 284     for (int i = 0; i < FrameMap::nof_fpu_regs; i++) {
 285       FloatRegister r = as_FloatRegister(i);
 286       {
 287         int sp_offset = fpu_reg_save_offsets[i];
 288         oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
 289                                   r->as_VMReg());
 290       }
 291     }
 292   }
 293   return oop_map;
 294 }
 295 
 296 static OopMap* save_live_registers(StubAssembler* sasm,

 341 
 342 
 343 void Runtime1::initialize_pd() {
 344   int i;
 345   int sp_offset = 0;
 346 
 347   // all float registers are saved explicitly
 348   assert(FrameMap::nof_fpu_regs == 32, "double registers not handled here");
 349   for (i = 0; i < FrameMap::nof_fpu_regs; i++) {
 350     fpu_reg_save_offsets[i] = sp_offset;
 351     sp_offset += 2;   // SP offsets are in halfwords
 352   }
 353 
 354   for (i = 0; i < FrameMap::nof_cpu_regs; i++) {
 355     Register r = as_Register(i);
 356     cpu_reg_save_offsets[i] = sp_offset;
 357     sp_offset += 2;   // SP offsets are in halfwords
 358   }
 359 }
 360 
 361 // return: offset in 64-bit words.
 362 uint Runtime1::runtime_blob_current_thread_offset(frame f) {
 363   CodeBlob* cb = f.cb();
 364   assert(cb == Runtime1::blob_for(Runtime1::monitorenter_id) ||
 365          cb == Runtime1::blob_for(Runtime1::monitorenter_nofpu_id), "must be");
 366   assert(cb != nullptr && cb->is_runtime_stub(), "invalid frame");
 367   int offset = cpu_reg_save_offsets[rthread->encoding()];
 368   return offset / 2;   // SP offsets are in halfwords
 369 }
 370 
 371 // target: the entry point of the method that creates and posts the exception oop
 372 // has_argument: true if the exception needs arguments (passed in rscratch1 and rscratch2)
 373 
 374 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {
 375   // make a frame and preserve the caller's caller-save registers
 376   OopMap* oop_map = save_live_registers(sasm);
 377   int call_offset;
 378   if (!has_argument) {
 379     call_offset = __ call_RT(noreg, noreg, target);
 380   } else {
 381     __ mov(c_rarg1, rscratch1);
 382     __ mov(c_rarg2, rscratch2);
 383     call_offset = __ call_RT(noreg, noreg, target);
 384   }
 385   OopMapSet* oop_maps = new OopMapSet();
 386   oop_maps->add_gc_map(call_offset, oop_map);
 387   return oop_maps;
 388 }
 389 

 875         __ check_klass_subtype_slow_path(r4, r0, r2, r5, nullptr, &miss);
 876 
 877         // fallthrough on success:
 878         __ mov(rscratch1, 1);
 879         __ str(rscratch1, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
 880         __ pop(RegSet::of(r0, r2, r4, r5), sp);
 881         __ ret(lr);
 882 
 883         __ bind(miss);
 884         __ str(zr, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
 885         __ pop(RegSet::of(r0, r2, r4, r5), sp);
 886         __ ret(lr);
 887       }
 888       break;
 889 
 890     case monitorenter_nofpu_id:
 891       save_fpu_registers = false;
 892       // fall through
 893     case monitorenter_id:
 894       {
 895         StubFrame f(sasm, "monitorenter", dont_gc_arguments, /*use_pop_on_epilogue*/true);
 896         OopMap* map = save_live_registers(sasm, save_fpu_registers);
 897 
 898         // Called with store_parameter and not C abi
 899 
 900         f.load_argument(1, r0); // r0,: object
 901         f.load_argument(0, r1); // r1,: lock address
 902 
 903         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), r0, r1);
 904 
 905         oop_maps = new OopMapSet();
 906         oop_maps->add_gc_map(call_offset, map);
 907         restore_live_registers(sasm, save_fpu_registers);
 908       }
 909       break;
 910 
 911     case monitorexit_nofpu_id:
 912       save_fpu_registers = false;
 913       // fall through
 914     case monitorexit_id:
 915       {
< prev index next >