int fetestexcept(int excepts) { #if defined(__aarch64__) // Fetch exception flags. return mrs_fpsr() & excepts; #elif defined(__x86_64__) // Combine the x87 and SSE exception flags. return (fnstsw() | stmxcsr()) & excepts; #else #error "Unsupported platform" #endif }
address generate_call_stub(address& return_address) { StubCodeMark mark(this, "StubRoutines", "call_stub"); address start = __ pc(); // stub code parameters / addresses assert(frame::entry_frame_call_wrapper_offset == 2, "adjust this code"); bool sse_save = false; const Address esp_after_call(ebp, -4 * wordSize); // same as in generate_catch_exception()! const Address mxcsr_save (ebp, -4 * wordSize); const Address result (ebp, 3 * wordSize); const Address result_type (ebp, 4 * wordSize); const Address method (ebp, 5 * wordSize); const Address entry_point (ebp, 6 * wordSize); const Address parameters (ebp, 7 * wordSize); const Address parameter_size(ebp, 8 * wordSize); const Address thread (ebp, 9 * wordSize); // same as in generate_catch_exception()! #ifdef COMPILER2 sse_save = VM_Version::supports_sse(); #endif // stub code __ enter(); // save edi, esi, & ebx, according to C calling conventions __ pushl(edi); __ pushl(esi); __ pushl(ebx); __ subl(esp, wordSize); // space for %mxcsr save // save and initialize %mxcsr if (sse_save) { __ stmxcsr(mxcsr_save); __ ldmxcsr(Address((int) StubRoutines::addr_mxcsr_std(), relocInfo::none)); } #ifdef ASSERT // make sure we have no pending exceptions { Label L; __ movl(ecx, thread); __ cmpl(Address(ecx, Thread::pending_exception_offset()), (int)NULL); __ jcc(Assembler::equal, L); __ stop("StubRoutines::call_stub: entered with pending exception"); __ bind(L); } #endif // pass parameters if any Label parameters_done; __ movl(ecx, parameter_size); // parameter counter __ testl(ecx, ecx); __ jcc(Assembler::zero, parameters_done); // parameter passing loop Label loop; __ movl(edx, parameters); // parameter pointer __ movl(esi, ecx); // parameter counter is in esi now __ movl(ecx, Address(edx)); // get first parameter in case it is a receiver __ bind(loop); __ movl(eax, Address(edx)); // get parameter __ addl(edx, wordSize); // advance to next parameter __ decl(esi); // decrement counter __ pushl(eax); // pass parameter __ jcc(Assembler::notZero, loop); // call Java function __ bind(parameters_done); __ movl(ebx, method); // get methodOop __ movl(esi, entry_point); // get entry_point __ call(esi, relocInfo::none); return_address = __ pc(); // store result depending on type // (everything that is not T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT) __ movl(edi, result); Label is_long, is_float, is_double, exit; __ movl(esi, result_type); __ cmpl(esi, T_LONG); __ jcc(Assembler::equal, is_long); __ cmpl(esi, T_FLOAT); __ jcc(Assembler::equal, is_float); __ cmpl(esi, T_DOUBLE); __ jcc(Assembler::equal, is_double); // handle T_INT case __ movl(Address(edi), eax); __ bind(exit); // pop parameters __ movl(ecx, parameter_size); __ leal(esp, Address(esp, ecx, Address::times_4)); // check if parameters have been popped correctly #ifdef ASSERT Label esp_wrong; __ leal(edi, esp_after_call); __ cmpl(esp, edi); __ jcc(Assembler::notEqual, esp_wrong); #endif // restore %mxcsr if (sse_save) { __ ldmxcsr(mxcsr_save); } // restore edi & esi __ addl(esp, wordSize); // remove %mxcsr save area __ popl(ebx); __ popl(esi); __ popl(edi); // return __ popl(ebp); __ ret(0); // handle return types different from T_INT __ bind(is_long); __ movl(Address(edi, 0 * wordSize), eax); __ movl(Address(edi, 1 * wordSize), edx); __ jmp(exit); __ bind(is_float); __ fstp_s(Address(edi)); __ jmp(exit); __ bind(is_double); __ fstp_d(Address(edi)); __ jmp(exit); #ifdef ASSERT // stack pointer misadjusted __ bind(esp_wrong); __ stop("esp wrong after Java call"); #endif return start; }