< prev index next >

src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp

Print this page
rev 54670 : Port of valuetypes to aarch64


 299 
 300     // tell the simulator we have returned to the stub
 301 
 302     // we do this here because the notify will already have been done
 303     // if we get to the next instruction via an exception
 304     //
 305     // n.b. adding this instruction here affects the calculation of
 306     // whether or not a routine returns to the call stub (used when
 307     // doing stack walks) since the normal test is to check the return
 308     // pc against the address saved below. so we may need to allow for
 309     // this extra instruction in the check.
 310 
 311     if (NotifySimulator) {
 312       __ notify(Assembler::method_reentry);
 313     }
 314     // save current address for use by exception handling code
 315 
 316     return_address = __ pc();
 317 
 318     // store result depending on type (everything that is not
 319     // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
 320     // n.b. this assumes Java returns an integral result in r0
 321     // and a floating result in j_farg0
 322     __ ldr(j_rarg2, result);
 323     Label is_long, is_float, is_double, exit;
 324     __ ldr(j_rarg1, result_type);
 325     __ cmp(j_rarg1, (u1)T_OBJECT);
 326     __ br(Assembler::EQ, is_long);


 327     __ cmp(j_rarg1, (u1)T_LONG);
 328     __ br(Assembler::EQ, is_long);
 329     __ cmp(j_rarg1, (u1)T_FLOAT);
 330     __ br(Assembler::EQ, is_float);
 331     __ cmp(j_rarg1, (u1)T_DOUBLE);
 332     __ br(Assembler::EQ, is_double);
 333 
 334     // handle T_INT case
 335     __ strw(r0, Address(j_rarg2));
 336 
 337     __ BIND(exit);
 338 
 339     // pop parameters
 340     __ sub(esp, rfp, -sp_after_call_off * wordSize);
 341 
 342 #ifdef ASSERT
 343     // verify that threads correspond
 344     {
 345       Label L, S;
 346       __ ldr(rscratch1, thread);


5652     //       MACC(Ra, Ra, t0, t1, t2);
5653     //     }
5654     //     iters =  (2*len-i)/2;
5655     //     assert(iters == len-j, "must be");
5656     //     for (; iters--; j++) {
5657     //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
5658     //       MACC(Rm, Rn, t0, t1, t2);
5659     //       Rm = *++Pm;
5660     //       Rn = *--Pn;
5661     //     }
5662     //     Pm_base[i-len] = t0;
5663     //     t0 = t1; t1 = t2; t2 = 0;
5664     //   }
5665 
5666     //   while (t0)
5667     //     t0 = sub(Pm_base, Pn_base, t0, len);
5668     // }
5669   };
5670 
5671 


















































































































































































5672   // Initialization
5673   void generate_initial() {
5674     // Generate initial stubs and initializes the entry points
5675 
5676     // entry points that exist in all platforms Note: This is code
5677     // that could be shared among different platforms - however the
5678     // benefit seems to be smaller than the disadvantage of having a
5679     // much more complicated generator structure. See also comment in
5680     // stubRoutines.hpp.
5681 
5682     StubRoutines::_forward_exception_entry = generate_forward_exception();
5683 
5684     StubRoutines::_call_stub_entry =
5685       generate_call_stub(StubRoutines::_call_stub_return_address);
5686 
5687     // is referenced by megamorphic call
5688     StubRoutines::_catch_exception_entry = generate_catch_exception();
5689 
5690     // Build this early so it's available for the interpreter.
5691     StubRoutines::_throw_StackOverflowError_entry =


5701       StubRoutines::_crc_table_adr = (address)StubRoutines::aarch64::_crc_table;
5702       StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
5703     }
5704 
5705     if (UseCRC32CIntrinsics) {
5706       StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
5707     }
5708 
5709     // Disabled until JDK-8210858 is fixed
5710     // if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dlog)) {
5711     //   StubRoutines::_dlog = generate_dlog();
5712     // }
5713 
5714     if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dsin)) {
5715       StubRoutines::_dsin = generate_dsin_dcos(/* isCos = */ false);
5716     }
5717 
5718     if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dcos)) {
5719       StubRoutines::_dcos = generate_dsin_dcos(/* isCos = */ true);
5720     }






5721   }
5722 
5723   void generate_all() {
5724     // support for verify_oop (must happen after universe_init)
5725     StubRoutines::_verify_oop_subroutine_entry     = generate_verify_oop();
5726     StubRoutines::_throw_AbstractMethodError_entry =
5727       generate_throw_exception("AbstractMethodError throw_exception",
5728                                CAST_FROM_FN_PTR(address,
5729                                                 SharedRuntime::
5730                                                 throw_AbstractMethodError));
5731 
5732     StubRoutines::_throw_IncompatibleClassChangeError_entry =
5733       generate_throw_exception("IncompatibleClassChangeError throw_exception",
5734                                CAST_FROM_FN_PTR(address,
5735                                                 SharedRuntime::
5736                                                 throw_IncompatibleClassChangeError));
5737 
5738     StubRoutines::_throw_NullPointerException_at_call_entry =
5739       generate_throw_exception("NullPointerException at call throw_exception",
5740                                CAST_FROM_FN_PTR(address,




 299 
 300     // tell the simulator we have returned to the stub
 301 
 302     // we do this here because the notify will already have been done
 303     // if we get to the next instruction via an exception
 304     //
 305     // n.b. adding this instruction here affects the calculation of
 306     // whether or not a routine returns to the call stub (used when
 307     // doing stack walks) since the normal test is to check the return
 308     // pc against the address saved below. so we may need to allow for
 309     // this extra instruction in the check.
 310 
 311     if (NotifySimulator) {
 312       __ notify(Assembler::method_reentry);
 313     }
 314     // save current address for use by exception handling code
 315 
 316     return_address = __ pc();
 317 
 318     // store result depending on type (everything that is not
 319     // T_OBJECT, T_VALUETYPE, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
 320     // n.b. this assumes Java returns an integral result in r0
 321     // and a floating result in j_farg0
 322     __ ldr(j_rarg2, result);
 323     Label is_long, is_float, is_double, exit;
 324     __ ldr(j_rarg1, result_type);
 325     __ cmp(j_rarg1, (u1)T_OBJECT);
 326     __ br(Assembler::EQ, is_long);
 327     __ cmp(j_rarg1, (u1)T_VALUETYPE);
 328     __ br(Assembler::EQ, is_long);
 329     __ cmp(j_rarg1, (u1)T_LONG);
 330     __ br(Assembler::EQ, is_long);
 331     __ cmp(j_rarg1, (u1)T_FLOAT);
 332     __ br(Assembler::EQ, is_float);
 333     __ cmp(j_rarg1, (u1)T_DOUBLE);
 334     __ br(Assembler::EQ, is_double);
 335 
 336     // handle T_INT case
 337     __ strw(r0, Address(j_rarg2));
 338 
 339     __ BIND(exit);
 340 
 341     // pop parameters
 342     __ sub(esp, rfp, -sp_after_call_off * wordSize);
 343 
 344 #ifdef ASSERT
 345     // verify that threads correspond
 346     {
 347       Label L, S;
 348       __ ldr(rscratch1, thread);


5654     //       MACC(Ra, Ra, t0, t1, t2);
5655     //     }
5656     //     iters =  (2*len-i)/2;
5657     //     assert(iters == len-j, "must be");
5658     //     for (; iters--; j++) {
5659     //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
5660     //       MACC(Rm, Rn, t0, t1, t2);
5661     //       Rm = *++Pm;
5662     //       Rn = *--Pn;
5663     //     }
5664     //     Pm_base[i-len] = t0;
5665     //     t0 = t1; t1 = t2; t2 = 0;
5666     //   }
5667 
5668     //   while (t0)
5669     //     t0 = sub(Pm_base, Pn_base, t0, len);
5670     // }
5671   };
5672 
5673 
5674   // Call here from the interpreter or compiled code to either load
5675   // multiple returned values from the value type instance being
5676   // returned to registers or to store returned values to a newly
5677   // allocated value type instance.
5678   address generate_return_value_stub(address destination, const char* name, bool has_res) {
5679 
5680     // Information about frame layout at time of blocking runtime call.
5681     // Note that we only have to preserve callee-saved registers since
5682     // the compilers are responsible for supplying a continuation point
5683     // if they expect all registers to be preserved.
5684     // n.b. aarch64 asserts that frame::arg_reg_save_area_bytes == 0
5685     enum layout {
5686       rfp_off = 0, rfp_off2,
5687 
5688       j_rarg7_off, j_rarg7_2,
5689       j_rarg6_off, j_rarg6_2,
5690       j_rarg5_off, j_rarg5_2,
5691       j_rarg4_off, j_rarg4_2,
5692       j_rarg3_off, j_rarg3_2,
5693       j_rarg2_off, j_rarg2_2,
5694       j_rarg1_off, j_rarg1_2,
5695       j_rarg0_off, j_rarg0_2,
5696 
5697       j_farg0_off, j_farg0_2,
5698       j_farg1_off, j_farg1_2,
5699       j_farg2_off, j_farg2_2,
5700       j_farg3_off, j_farg3_2,
5701       j_farg4_off, j_farg4_2,
5702       j_farg5_off, j_farg5_2,
5703       j_farg6_off, j_farg6_2,
5704       j_farg7_off, j_farg7_2,
5705  
5706       return_off, return_off2,
5707       framesize // inclusive of return address
5708     };
5709 
5710     int insts_size = 512;
5711     int locs_size  = 64;
5712 
5713     CodeBuffer code(name, insts_size, locs_size);
5714     OopMapSet* oop_maps  = new OopMapSet();
5715     MacroAssembler* masm = new MacroAssembler(&code);
5716 
5717     address start = __ pc();
5718 
5719     const Address f7_save       (rfp, j_farg7_off * wordSize);
5720     const Address f6_save       (rfp, j_farg6_off * wordSize);
5721     const Address f5_save       (rfp, j_farg5_off * wordSize);
5722     const Address f4_save       (rfp, j_farg4_off * wordSize);
5723     const Address f3_save       (rfp, j_farg3_off * wordSize);
5724     const Address f2_save       (rfp, j_farg2_off * wordSize);
5725     const Address f1_save       (rfp, j_farg1_off * wordSize);
5726     const Address f0_save       (rfp, j_farg0_off * wordSize);
5727 
5728     const Address r0_save      (rfp, j_rarg0_off * wordSize);
5729     const Address r1_save      (rfp, j_rarg1_off * wordSize);
5730     const Address r2_save      (rfp, j_rarg2_off * wordSize);
5731     const Address r3_save      (rfp, j_rarg3_off * wordSize);
5732     const Address r4_save      (rfp, j_rarg4_off * wordSize);
5733     const Address r5_save      (rfp, j_rarg5_off * wordSize);
5734     const Address r6_save      (rfp, j_rarg6_off * wordSize);
5735     const Address r7_save      (rfp, j_rarg7_off * wordSize);
5736 
5737     // Generate oop map
5738     OopMap* map = new OopMap(framesize, 0);
5739 
5740     map->set_callee_saved(VMRegImpl::stack2reg(rfp_off), rfp->as_VMReg());
5741     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg7_off), j_rarg7->as_VMReg());
5742     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg6_off), j_rarg6->as_VMReg());
5743     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg5_off), j_rarg5->as_VMReg());
5744     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg4_off), j_rarg4->as_VMReg());
5745     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg3_off), j_rarg3->as_VMReg());
5746     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg2_off), j_rarg2->as_VMReg());
5747     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg1_off), j_rarg1->as_VMReg());
5748     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg0_off), j_rarg0->as_VMReg());
5749 
5750     map->set_callee_saved(VMRegImpl::stack2reg(j_farg0_off), j_farg0->as_VMReg());
5751     map->set_callee_saved(VMRegImpl::stack2reg(j_farg1_off), j_farg1->as_VMReg());
5752     map->set_callee_saved(VMRegImpl::stack2reg(j_farg2_off), j_farg2->as_VMReg());
5753     map->set_callee_saved(VMRegImpl::stack2reg(j_farg3_off), j_farg3->as_VMReg());
5754     map->set_callee_saved(VMRegImpl::stack2reg(j_farg4_off), j_farg4->as_VMReg());
5755     map->set_callee_saved(VMRegImpl::stack2reg(j_farg5_off), j_farg5->as_VMReg());
5756     map->set_callee_saved(VMRegImpl::stack2reg(j_farg6_off), j_farg6->as_VMReg());
5757     map->set_callee_saved(VMRegImpl::stack2reg(j_farg7_off), j_farg7->as_VMReg());
5758 
5759     // This is an inlined and slightly modified version of call_VM
5760     // which has the ability to fetch the return PC out of
5761     // thread-local storage and also sets up last_Java_sp slightly
5762     // differently than the real call_VM
5763 
5764     __ enter(); // Save FP and LR before call
5765 
5766     assert(is_even(framesize/2), "sp not 16-byte aligned");
5767 
5768     // lr and fp are already in place
5769     __ sub(sp, rfp, ((unsigned)framesize - 4) << LogBytesPerInt); // prolog
5770 
5771     __ strd(j_farg7, f7_save); 
5772     __ strd(j_farg6, f6_save); 
5773     __ strd(j_farg5, f5_save); 
5774     __ strd(j_farg4, f4_save); 
5775     __ strd(j_farg3, f3_save); 
5776     __ strd(j_farg2, f2_save); 
5777     __ strd(j_farg1, f1_save); 
5778     __ strd(j_farg0, f0_save); 
5779 
5780     __ str(j_rarg0, r0_save); 
5781     __ str(j_rarg1, r1_save); 
5782     __ str(j_rarg2, r2_save); 
5783     __ str(j_rarg3, r3_save); 
5784     __ str(j_rarg4, r4_save); 
5785     __ str(j_rarg5, r5_save); 
5786     __ str(j_rarg6, r6_save); 
5787     __ str(j_rarg7, r7_save); 
5788 
5789     int frame_complete = __ pc() - start;
5790 
5791     // Set up last_Java_sp and last_Java_fp
5792     address the_pc = __ pc();
5793     __ set_last_Java_frame(sp, rfp, the_pc, rscratch1);
5794 
5795     // Call runtime
5796     __ mov(c_rarg0, rthread);
5797     __ mov(c_rarg1, r0);
5798 
5799     BLOCK_COMMENT("call runtime_entry");
5800     __ mov(rscratch1, destination);
5801     __ blrt(rscratch1, 2 /* number_of_arguments */, 0, 1);
5802 
5803     oop_maps->add_gc_map(the_pc - start, map);
5804 
5805     __ reset_last_Java_frame(false); 
5806     __ maybe_isb(); 
5807 
5808     __ ldrd(j_farg7, f7_save); 
5809     __ ldrd(j_farg6, f6_save); 
5810     __ ldrd(j_farg5, f5_save); 
5811     __ ldrd(j_farg4, f4_save); 
5812     __ ldrd(j_farg3, f3_save); 
5813     __ ldrd(j_farg3, f2_save); 
5814     __ ldrd(j_farg1, f1_save); 
5815     __ ldrd(j_farg0, f0_save); 
5816 
5817     __ ldr(j_rarg0, r0_save); 
5818     __ ldr(j_rarg1, r1_save); 
5819     __ ldr(j_rarg2, r2_save); 
5820     __ ldr(j_rarg3, r3_save); 
5821     __ ldr(j_rarg4, r4_save); 
5822     __ ldr(j_rarg5, r5_save); 
5823     __ ldr(j_rarg6, r6_save); 
5824     __ ldr(j_rarg7, r7_save); 
5825 
5826     __ leave();
5827 
5828     // check for pending exceptions
5829     Label pending;
5830     __ ldr(rscratch1, Address(rthread, in_bytes(Thread::pending_exception_offset())));
5831     __ cmp(rscratch1, (u1)NULL_WORD);
5832     __ br(Assembler::NE, pending);
5833 
5834     if (has_res) {
5835       __ get_vm_result(r0, rthread);
5836     }
5837     __ ret(lr);
5838 
5839     __ bind(pending);
5840     __ ldr(r0, Address(rthread, in_bytes(Thread::pending_exception_offset())));
5841     __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
5842 
5843 
5844     // codeBlob framesize is in words (not VMRegImpl::slot_size)
5845     int frame_size_in_words = (framesize >> (LogBytesPerWord - LogBytesPerInt));
5846     RuntimeStub* stub =
5847       RuntimeStub::new_runtime_stub(name, &code, frame_complete, frame_size_in_words, oop_maps, false);
5848 
5849     return stub->entry_point();
5850   }
5851 
5852   // Initialization
5853   void generate_initial() {
5854     // Generate initial stubs and initializes the entry points
5855 
5856     // entry points that exist in all platforms Note: This is code
5857     // that could be shared among different platforms - however the
5858     // benefit seems to be smaller than the disadvantage of having a
5859     // much more complicated generator structure. See also comment in
5860     // stubRoutines.hpp.
5861 
5862     StubRoutines::_forward_exception_entry = generate_forward_exception();
5863 
5864     StubRoutines::_call_stub_entry =
5865       generate_call_stub(StubRoutines::_call_stub_return_address);
5866 
5867     // is referenced by megamorphic call
5868     StubRoutines::_catch_exception_entry = generate_catch_exception();
5869 
5870     // Build this early so it's available for the interpreter.
5871     StubRoutines::_throw_StackOverflowError_entry =


5881       StubRoutines::_crc_table_adr = (address)StubRoutines::aarch64::_crc_table;
5882       StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
5883     }
5884 
5885     if (UseCRC32CIntrinsics) {
5886       StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
5887     }
5888 
5889     // Disabled until JDK-8210858 is fixed
5890     // if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dlog)) {
5891     //   StubRoutines::_dlog = generate_dlog();
5892     // }
5893 
5894     if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dsin)) {
5895       StubRoutines::_dsin = generate_dsin_dcos(/* isCos = */ false);
5896     }
5897 
5898     if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dcos)) {
5899       StubRoutines::_dcos = generate_dsin_dcos(/* isCos = */ true);
5900     }
5901 
5902 
5903     StubRoutines::_load_value_type_fields_in_regs = 
5904          generate_return_value_stub(CAST_FROM_FN_PTR(address, SharedRuntime::load_value_type_fields_in_regs), "load_value_type_fields_in_regs", false);
5905     StubRoutines::_store_value_type_fields_to_buf = 
5906          generate_return_value_stub(CAST_FROM_FN_PTR(address, SharedRuntime::store_value_type_fields_to_buf), "store_value_type_fields_to_buf", true);
5907   }
5908 
5909   void generate_all() {
5910     // support for verify_oop (must happen after universe_init)
5911     StubRoutines::_verify_oop_subroutine_entry     = generate_verify_oop();
5912     StubRoutines::_throw_AbstractMethodError_entry =
5913       generate_throw_exception("AbstractMethodError throw_exception",
5914                                CAST_FROM_FN_PTR(address,
5915                                                 SharedRuntime::
5916                                                 throw_AbstractMethodError));
5917 
5918     StubRoutines::_throw_IncompatibleClassChangeError_entry =
5919       generate_throw_exception("IncompatibleClassChangeError throw_exception",
5920                                CAST_FROM_FN_PTR(address,
5921                                                 SharedRuntime::
5922                                                 throw_IncompatibleClassChangeError));
5923 
5924     StubRoutines::_throw_NullPointerException_at_call_entry =
5925       generate_throw_exception("NullPointerException at call throw_exception",
5926                                CAST_FROM_FN_PTR(address,


< prev index next >