< prev index next >

src/hotspot/cpu/x86/stubGenerator_x86_64.cpp

Print this page
rev 50307 : [mq]: cont

*** 33,42 **** --- 33,43 ---- #include "oops/instanceOop.hpp" #include "oops/method.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/methodHandles.hpp" + #include "runtime/continuation.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp"
*** 4786,4795 **** --- 4787,5011 ---- return start; } + void push_FrameInfo(MacroAssembler* _masm, Register fi, Register sp, Register fp, address pc) { + if(!sp->is_valid()) __ push(0); else { + if (sp == rsp) { + __ movptr(fi, rsp); + __ push(fi); + } else { + __ push(sp); + } + } + + if(!fp->is_valid()) __ push(0); else __ push(fp); + + __ lea(fi, ExternalAddress(pc)); + __ push(fi); + + __ movptr(fi, rsp); // make fi point to the beginning of FramInfo + } + + void push_FrameInfo(MacroAssembler* _masm, Register fi, Register sp, Register fp, Register pc) { + if(!sp->is_valid()) __ push(0); else { + if (sp == rsp) { + __ movptr(fi, rsp); + __ push(fi); + } else { + __ push(sp); + } + } + + if(!fp->is_valid()) __ push(0); else __ push(fp); + + if(!pc->is_valid()) __ push(0); else __ push(pc); + + __ movptr(fi, rsp); // make fi point to the beginning of FramInfo + } + + void pop_FrameInfo(MacroAssembler* _masm, Register sp, Register fp, Register pc) { + if(!pc->is_valid()) __ lea(rsp, Address(rsp, wordSize)); else __ pop(pc); + if(!fp->is_valid()) __ lea(rsp, Address(rsp, wordSize)); else __ pop(fp); + if(!sp->is_valid()) __ lea(rsp, Address(rsp, wordSize)); else __ pop(sp); + } + + // c_rarg1 ContinuationScope + address generate_cont_doYield() { + const char *name = "cont_doYield"; + + enum layout { + frameinfo_11 = frame::arg_reg_save_area_bytes/BytesPerInt, + frameinfo_12, + frameinfo_21, + frameinfo_22, + frameinfo_31, + frameinfo_32, + rbp_off, + rbpH_off, + return_off, + return_off2, + framesize // inclusive of return address + }; + // assert(is_even(framesize/2), "sp not 16-byte aligned"); + int insts_size = 512; + int locs_size = 64; + CodeBuffer code(name, insts_size, locs_size); + OopMapSet* oop_maps = new OopMapSet(); + MacroAssembler* masm = new MacroAssembler(&code); + MacroAssembler* _masm = masm; + + // MacroAssembler* masm = _masm; + // StubCodeMark mark(this, "StubRoutines", name); + + address start = __ pc(); + + Register fi = c_rarg1; + + __ movq(c_rarg2, c_rarg0); // scopes argument + __ movptr(rax, Address(rsp, 0)); // use return address as the frame pc // __ lea(rax, InternalAddress(pcxxxx)); + __ lea(fi, Address(rsp, wordSize)); // skip return address + __ movptr(c_rarg3, rbp); + + __ enter(); + + // // return address and rbp are already in place + // __ subptr(rsp, (framesize-4) << LogBytesPerInt); // prolog + + push_FrameInfo(masm, fi, fi, c_rarg3, rax); + + int frame_complete = __ pc() - start; + address the_pc = __ pc(); + + __ set_last_Java_frame(rsp, rbp, the_pc); // may be unnecessary. also, consider MacroAssembler::call_VM_leaf_base + + __ call_VM(noreg, CAST_FROM_FN_PTR(address, Continuation::freeze), fi, c_rarg2, false); // do NOT check exceptions; they'll get forwarded to the caller + + Label pinned; + __ pop(rax); // read the pc from the FrameInfo + __ testq(rax, rax); + __ jcc(Assembler::zero, pinned); + + __ pop(rbp); // not pinned -- jump to Continuation.run (the entry frame) + __ pop(fi); + __ movptr(rsp, fi); + __ jmp(rax); + + __ bind(pinned); // pinned -- return to caller + __ lea(rsp, Address(rsp, wordSize*2)); // "pop" the rest of the FrameInfo struct + + __ leave(); + __ ret(0); + + // return start; + + OopMap* map = new OopMap(framesize, 1); + // map->set_callee_saved(VMRegImpl::stack2reg(rbp_off), rbp->as_VMReg()); + oop_maps->add_gc_map(the_pc - start, map); + + RuntimeStub* stub = // codeBlob framesize is in words (not VMRegImpl::slot_size) + RuntimeStub::new_runtime_stub(name, + &code, + frame_complete, + (framesize >> (LogBytesPerWord - LogBytesPerInt)), + oop_maps, false); + return stub->entry_point(); + } + + address generate_cont_thaw(bool return_barrier) { + address start = __ pc(); + + // TODO: Handle Valhalla return types. May require generating different return barriers. + + Register fi = r11; + + if (!return_barrier) { + __ pop(c_rarg3); // pop return address. if we don't do this, we get a drift, where the bottom-most frozen frame continuously grows + // __ lea(rsp, Address(rsp, wordSize)); // pop return address. if we don't do this, we get a drift, where the bottom-most frozen frame continuously grows + } + + Label thaw_fail; + __ movptr(fi, rsp); + __ push(rax); __ push_d(xmm0); // preserve possible return value from a method returning to the return barrier + __ movl(c_rarg2, return_barrier); + push_FrameInfo(_masm, fi, fi, rbp, c_rarg3); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), fi, c_rarg2); + __ testq(rax, rax); // rax contains the size of the frames to thaw, 0 if overflow or no more frames + __ jcc(Assembler::zero, thaw_fail); + + pop_FrameInfo(_masm, fi, rbp, c_rarg3); // c_rarg3 would still be our return address + __ pop_d(xmm0); __ pop(rdx); // TEMPORARILY restore return value (we're going to push it again, but rsp is about to move) + + __ subq(rsp, rax); // make room for the thawed frames + // __ movptr(fi, rsp); // where we'll start copying frame (the lowest address) + __ push(rdx); __ push_d(xmm0); // save original return value -- again + __ movl(c_rarg2, return_barrier); + push_FrameInfo(_masm, fi, fi, rbp, c_rarg3); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::thaw), fi, c_rarg2); + + __ bind(thaw_fail); + pop_FrameInfo(_masm, fi, rbp, rdx); + // __ movl(rbp, 0); + __ pop_d(xmm0); __ pop(rax); // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK) + __ movptr(rsp, fi); // we're now on the yield frame (which is above us b/c rsp has been pushed down) + __ jmp(rdx); + + return start; + } + + address generate_cont_thaw() { + StubCodeMark mark(this, "StubRoutines", "Cont thaw"); + address start = __ pc(); + generate_cont_thaw(false); + return start; + } + + address generate_cont_returnBarrier() { + // TODO: will probably need multiple return barriers depending on return type + StubCodeMark mark(this, "StubRoutines", "cont return barrier"); + address start = __ pc(); + + if (CONT_FULL_STACK) + __ stop("RETURN BARRIER -- UNREACHABLE 0"); + + generate_cont_thaw(true); + + return start; + } + + address generate_cont_getPC() { + StubCodeMark mark(this, "StubRoutines", "GetPC"); + address start = __ pc(); + + __ movptr(rax, Address(rsp, 0)); + __ ret(0); + + return start; + } + + address generate_cont_getSP() { + StubCodeMark mark(this, "StubRoutines", "getSP"); + address start = __ pc(); + + __ lea(rax, Address(rsp, wordSize)); + __ ret(0); + + return start; + } + + address generate_cont_getFP() { + StubCodeMark mark(this, "StubRoutines", "GetFP"); + address start = __ pc(); + + __ stop("WHAT?"); + __ lea(rax, Address(rsp, wordSize)); + __ ret(0); + + return start; + } + #undef __ #define __ masm-> // Continuation point for throwing of implicit exceptions that are // not handled in the current activation. Fabricates an exception
*** 5017,5026 **** --- 5233,5251 ---- StubRoutines::_dtan = generate_libmTan(); } } } + void generate_phase1() { + // Continuation stubs: + StubRoutines::_cont_thaw = generate_cont_thaw(); + StubRoutines::_cont_returnBarrier = generate_cont_returnBarrier(); + StubRoutines::_cont_doYield = generate_cont_doYield(); + StubRoutines::_cont_getSP = generate_cont_getSP(); + StubRoutines::_cont_getPC = generate_cont_getPC(); + } + void generate_all() { // Generates all stubs and initializes the entry points // These entry points require SharedInfo::stack0 to be set up in // non-core builds and need to be relocatable, so they each
*** 5139,5155 **** StubRoutines::_vectorizedMismatch = generate_vectorizedMismatch(); } } public: ! StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { ! if (all) { ! generate_all(); ! } else { generate_initial(); } } }; // end class declaration ! void StubGenerator_generate(CodeBuffer* code, bool all) { ! StubGenerator g(code, all); } --- 5364,5382 ---- StubRoutines::_vectorizedMismatch = generate_vectorizedMismatch(); } } public: ! StubGenerator(CodeBuffer* code, int phase) : StubCodeGenerator(code) { ! if (phase == 0) { generate_initial(); + } else if (phase == 1) { + generate_phase1(); + } else { + generate_all(); } } }; // end class declaration ! void StubGenerator_generate(CodeBuffer* code, int phase) { ! StubGenerator g(code, phase); }
< prev index next >