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,
|