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

Reply via email to