Author: Armin Rigo <ar...@tunes.org> Branch: errno-again Changeset: r75404:666a00c88bbb Date: 2015-01-16 20:42 +0100 http://bitbucket.org/pypy/pypy/changeset/666a00c88bbb/
Log: in-progress diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3091,12 +3091,11 @@ py.test.skip("Windows test only") eci = ExternalCompilationInfo( separate_module_sources=[r''' - #include <stdio.h> - #include <errno.h> + #include <windows.h> RPY_EXPORTED long test_call_release_gil_readsaved_lasterror( long a, long b, long c, long d, long e, long f, long g) { long r = GetLastError(); - printf("GetLastError() result: %ld\n", r); + //printf("GetLastError() result: %ld\n", r); r += 100 * (a + 10*b + 100*c + 1000*d + 10000*e + 100000*f + 1000000*g); return r; @@ -3132,6 +3131,9 @@ # assert result == 24 + 345678900 + def test_call_release_gil_err_all(self): + xxx + def test_guard_not_invalidated(self): cpu = self.cpu i0 = BoxInt() diff --git a/rpython/jit/backend/x86/callbuilder.py b/rpython/jit/backend/x86/callbuilder.py --- a/rpython/jit/backend/x86/callbuilder.py +++ b/rpython/jit/backend/x86/callbuilder.py @@ -20,6 +20,7 @@ CALL_ALIGN = 16 // WORD stdcall_or_cdecl = sys.platform == "win32" +handle_lasterror = sys.platform == "win32" def align_stack_words(words): return (words + CALL_ALIGN - 1) & ~(CALL_ALIGN-1) @@ -31,6 +32,8 @@ # arguments, we need to decrease esp temporarily stack_max = PASS_ON_MY_FRAME + result_value_saved_early = False + def __init__(self, assembler, fnloc, arglocs, resloc=eax, restype=INT, ressize=WORD): AbstractCallBuilder.__init__(self, assembler, fnloc, arglocs, @@ -150,6 +153,23 @@ self.mc.ADD(ebp, imm(1)) # ebp any more def write_real_errno(self, save_err): + tlofsreg = None + mc = self.mc + + if handle_lasterror and (save_err & rffi.RFFI_READSAVED_LASTERROR): + # must call SetLastError(). There are no registers to save + # because we are on 32-bit in this case: no register contains + # the arguments to the main function we want to call afterwards. + from rpython.rlib.rwin32 import _SetLastError + SetLastError_addr = self.asm.cpu.cast_ptr_to_int(_SetLastError) + assert isinstance(self, CallBuilder32) # Windows 32-bit only + # + rpy_lasterror = llerrno.get_rpy_lasterror_offset(self.asm.cpu) + tlofsreg = edi # saved across the call to SetLastError + mc.MOV_rs(edi.value, THREADLOCAL_OFS - self.current_esp) + mc.PUSH_m((edi.value, rpy_lasterror)) + mc.CALL(imm(SetLastError_addr)) + if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read 'rpy_errno' and write it into the # real 'errno'. Most registers are free here, including the @@ -157,35 +177,54 @@ # pass the arguments on x86-64. rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) - mc = self.mc - mc.MOV_rs(eax.value, THREADLOCAL_OFS - self.current_esp) + if tlofsreg is None: + tlofsreg = eax + mc.MOV_rs(eax.value, THREADLOCAL_OFS - self.current_esp) if IS_X86_32: tmpreg = edx else: tmpreg = r11 # edx is used for 3rd argument - mc.MOV_rm(tmpreg.value, (eax.value, p_errno)) - mc.MOV32_rm(eax.value, (eax.value, rpy_errno)) + mc.MOV_rm(tmpreg.value, (tlofsreg.value, p_errno)) + mc.MOV32_rm(eax.value, (tlofsreg.value, rpy_errno)) mc.MOV32_mr((tmpreg.value, 0), eax.value) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) - mc = self.mc - mc.MOV_rs(eax.value, THREADLOCAL_OFS - self.current_esp) - mc.MOV_rm(eax.value, (eax.value, p_errno)) + if tlofsreg is None: + tlofsreg = eax + mc.MOV_rs(eax.value, THREADLOCAL_OFS - self.current_esp) + mc.MOV_rm(eax.value, (tlofsreg.value, p_errno)) mc.MOV32_mi((eax.value, 0), 0) def read_real_errno(self, save_err): + esi_is_threadlocal_ofs = False + mc = self.mc + if save_err & rffi.RFFI_SAVE_ERRNO: # Just after a call, read the real 'errno' and save a copy of # it inside our thread-local 'rpy_errno'. Most registers are # free here, including the callee-saved ones, except 'ebx'. rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) - mc = self.mc mc.MOV_rs(esi.value, THREADLOCAL_OFS) mc.MOV_rm(edi.value, (esi.value, p_errno)) mc.MOV32_rm(edi.value, (edi.value, 0)) mc.MOV32_mr((esi.value, rpy_errno), edi.value) + esi_is_threadlocal_ofs = True + + if handle_lasterror and (save_err & rffi.RFFI_SAVE_LASTERROR): + from rpython.rlib.rwin32 import _GetLastError + GetLastError_addr = self.asm.cpu.cast_ptr_to_int(_GetLastError) + assert isinstance(self, CallBuilder32) # Windows 32-bit only + # + rpy_lasterror = llerrno.get_rpy_lasterror_offset(self.asm.cpu) + self.save_result_value(save_edx=True) + self.result_value_saved_early = True + mc.CALL(imm(GetLastError_addr)) + # + if not esi_is_threadlocal_ofs: + mc.MOV_rs(esi.value, THREADLOCAL_OFS) + mc.MOV32_mr((esi.value, rpy_lasterror), eax.value) def move_real_result_and_call_reacqgil_addr(self, fastgil): from rpython.jit.backend.x86 import rx86 @@ -205,8 +244,9 @@ if IS_X86_32: assert css >= 16 if self.restype == 'L': # long long result: eax/edx - mc.MOV_sr(12, edx.value) - restore_edx = True + if not self.result_value_saved_early: + mc.MOV_sr(12, edx.value) + restore_edx = True css_value = edx old_value = ecx elif IS_X86_64: @@ -255,14 +295,16 @@ je_location = mc.get_relative_pos() # # Yes, we need to call the reacqgil() function - self.save_result_value_reacq() + if not self.result_value_saved_early: + self.save_result_value(save_edx=False) if self.asm._is_asmgcc(): if IS_X86_32: mc.MOV_sr(4, old_value.value) mc.MOV_sr(0, css_value.value) # on X86_64, they are already in the right registers mc.CALL(imm(self.asm.reacqgil_addr)) - self.restore_result_value_reacq() + if not self.result_value_saved_early: + self.restore_result_value(save_edx=False) # # patch the JE above offset = mc.get_relative_pos() - je_location @@ -272,6 +314,9 @@ if restore_edx: mc.MOV_rs(edx.value, 12) # restore this # + if self.result_value_saved_early: + self.restore_result_value(save_edx=True) + # if not we_are_translated(): # for testing: now we can accesss mc.SUB(ebp, imm(1)) # ebp again # @@ -284,11 +329,11 @@ #else: # for shadowstack, done for us by _reload_frame_if_necessary() - def save_result_value_reacq(self): + def save_result_value(self, save_edx): """Overridden in CallBuilder32 and CallBuilder64""" raise NotImplementedError - def restore_result_value_reacq(self): + def restore_result_value(self, save_edx): """Overridden in CallBuilder32 and CallBuilder64""" raise NotImplementedError @@ -378,7 +423,7 @@ else: CallBuilderX86.load_result(self) - def save_result_value_reacq(self): + def save_result_value(self, save_edx): # Temporarily save the result value into [ESP+8]. We use "+8" # in order to leave the two initial words free, in case it's needed. # Also note that in this 32-bit case, a long long return value is @@ -390,7 +435,8 @@ # a float or a long long return if self.restype == 'L': self.mc.MOV_sr(8, eax.value) # long long - #self.mc.MOV_sr(12, edx.value) -- already done by the caller + if save_edx: + self.mc.MOV_sr(12, edx.value) else: self.mc.FSTPL_s(8) # float return else: @@ -401,15 +447,16 @@ assert self.ressize <= WORD self.mc.MOV_sr(8, eax.value) - def restore_result_value_reacq(self): - # Opposite of save_result_value_reacq() + def restore_result_value(self, save_edx): + # Opposite of save_result_value() if self.ressize == 0: # void return return if self.resloc.is_float(): # a float or a long long return if self.restype == 'L': self.mc.MOV_rs(eax.value, 8) # long long - #self.mc.MOV_rs(edx.value, 12) -- will be done by the caller + if save_edx: + self.mc.MOV_rs(edx.value, 12) else: self.mc.FLDL_s(8) # float return else: @@ -534,7 +581,7 @@ else: CallBuilderX86.load_result(self) - def save_result_value_reacq(self): + def save_result_value(self, save_edx): # Temporarily save the result value into [ESP]. if self.ressize == 0: # void return return @@ -551,8 +598,8 @@ assert self.restype == INT self.mc.MOV_sr(0, eax.value) - def restore_result_value_reacq(self): - # Opposite of save_result_value_reacq() + def restore_result_value(self, save_edx): + # Opposite of save_result_value() if self.ressize == 0: # void return return # diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -536,6 +536,7 @@ PUSH_r = insn(rex_nw, register(1), '\x50') PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) + PUSH_m = insn(rex_nw, '\xFF', orbyte(6<<3), mem_reg_plus_const(1)) PUSH_i8 = insn('\x6A', immediate(1, 'b')) PUSH_i32 = insn('\x68', immediate(1, 'i')) def PUSH_i(mc, immed): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit