[pypy-commit] pypy shadowstack-perf: In-progress: try to use r15 for signalling exceptions.

arigo noreply at buildbot.pypy.org
Fri Jul 8 21:27:04 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: shadowstack-perf
Changeset: r45424:65ec9d93dc63
Date: 2011-07-08 20:38 +0200
http://bitbucket.org/pypy/pypy/changeset/65ec9d93dc63/

Log:	In-progress: try to use r15 for signalling exceptions.

diff --git a/pypy/rlib/register.py b/pypy/rlib/register.py
--- a/pypy/rlib/register.py
+++ b/pypy/rlib/register.py
@@ -15,10 +15,12 @@
 
 # For now, only for x86-64.  Tries to use the register r15.
 eci = ExternalCompilationInfo(
-    post_include_bits=['register void* pypy_r15 asm("r15");\n'
-                       '#define PYPY_GET_R15() pypy_r15\n'
-                       '#define PYPY_SET_R15(x) (pypy_r15 = x)\n'
-                       ],
+    post_include_bits=[
+        'register void *pypy_r15 asm("r15");\n'
+        '#define PYPY_GET_SPECIAL_REG() pypy_r15\n'
+        '#define PYPY_SPECIAL_REG_NONNULL() (pypy_r15 != NULL)\n'
+        '#define PYPY_SET_SPECIAL_REG(x) (pypy_r15 = x)\n'
+        ],
     )
 
 _test_eci = eci.merge(ExternalCompilationInfo(
@@ -38,27 +40,42 @@
 
     from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 
-    # use load_from_reg(TYPE) and store_into_reg(llvalue) to load and store
-    # a value out of the special register.  When running on top of Python.
+    # use addr=load_from_reg() and store_into_reg(addr) to load and store
+    # an Address out of the special register.  When running on top of Python,
     # the behavior is emulated.
 
     _value_reg = None
 
-    def _pypy_get_r15():
+    def _pypy_get_special_reg():
         assert _value_reg is not None
         return _value_reg
 
-    def _pypy_set_r15(addr):
+    def _pypy_special_reg_nonnull():
+        assert _value_reg is not None
+        return bool(_value_reg)
+
+    def _pypy_set_special_reg(addr):
         global _value_reg
         _value_reg = addr
 
-    load_from_reg = rffi.llexternal('PYPY_GET_R15', [], llmemory.Address,
-                                    _callable=_pypy_get_r15,
+    load_from_reg = rffi.llexternal('PYPY_GET_SPECIAL_REG', [],
+                                    llmemory.Address,
+                                    _callable=_pypy_get_special_reg,
                                     compilation_info=eci,
                                     _nowrapper=True)
 
-    store_into_reg = rffi.llexternal('PYPY_SET_R15', [llmemory.Address],
-                                     lltype.Void,
-                                     _callable=_pypy_set_r15,
+    reg_is_nonnull = rffi.llexternal('PYPY_SPECIAL_REG_NONNULL', [],
+                                     lltype.Bool,
+                                     _callable=_pypy_special_reg_nonnull,
                                      compilation_info=eci,
                                      _nowrapper=True)
+
+    store_into_reg = rffi.llexternal('PYPY_SET_SPECIAL_REG',
+                                     [llmemory.Address],
+                                     lltype.Void,
+                                     _callable=_pypy_set_special_reg,
+                                     compilation_info=eci,
+                                     _nowrapper=True)
+
+    # xxx temporary
+    nonnull = llmemory.cast_int_to_adr(-1)
diff --git a/pypy/rlib/test/test_register.py b/pypy/rlib/test/test_register.py
--- a/pypy/rlib/test/test_register.py
+++ b/pypy/rlib/test/test_register.py
@@ -1,6 +1,7 @@
 import py
 from pypy.rlib import register
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.translator.c.test.test_standalone import StandaloneTests
 
 
 def test_register():
@@ -36,13 +37,19 @@
         res = interpret(f, [41])
         assert res == 41
 
+
+class TestLoadStoreCompiled(StandaloneTests):
+    def setup_class(cls):
+        if register.register_number is None:
+            py.test.skip("rlib/register not supported on this platform")
+
     def test_compiled(self):
-        from pypy.translator.c.test.test_genc import compile
-        def f(n):
-            a = rffi.cast(llmemory.Address, n)
+        def f(argv):
+            a = rffi.cast(llmemory.Address, 43)
             register.store_into_reg(a)
             b = register.load_from_reg()
-            return rffi.cast(lltype.Signed, b)
-        cfn = compile(f, [int])
-        res = cfn(43)
-        assert res == 43
+            print rffi.cast(lltype.Signed, b)
+            return 0
+        t, cbuilder = self.compile(f)
+        data = cbuilder.cmdexec('')
+        assert data.startswith('43\n')
diff --git a/pypy/translator/c/src/main.h b/pypy/translator/c/src/main.h
--- a/pypy/translator/c/src/main.h
+++ b/pypy/translator/c/src/main.h
@@ -34,6 +34,10 @@
     char *errmsg;
     int i, exitcode;
     RPyListOfString *list;
+#ifdef PYPY_GET_SPECIAL_REG
+    void *pypy_reg_oldvalue = PYPY_GET_SPECIAL_REG();
+    PYPY_SET_SPECIAL_REG((void*)-1);
+#endif
 
     pypy_asm_stack_bottom();
     instrument_setup();
@@ -70,6 +74,10 @@
         pypy_debug_catch_fatal_exception();
     }
 
+#ifdef PYPY_GET_SPECIAL_REG
+    PYPY_SET_SPECIAL_REG(pypy_reg_oldvalue);
+#endif
+
     return exitcode;
 
  memory_out:
@@ -79,7 +87,7 @@
     fprintf(stderr, "Fatal error during initialization: %s\n", errmsg);
 #endif
     abort();
-    return 1;
+    return 1;   /* not actually reachable */
 }
 
 int PYPY_MAIN_FUNCTION(int argc, char *argv[])
diff --git a/pypy/translator/exceptiontransform.py b/pypy/translator/exceptiontransform.py
--- a/pypy/translator/exceptiontransform.py
+++ b/pypy/translator/exceptiontransform.py
@@ -14,6 +14,7 @@
 from pypy.rlib.rarithmetic import r_singlefloat
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.rstackovf import _StackOverflow
+from pypy.rlib import register
 from pypy.annotation import model as annmodel
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 from pypy.tool.sourcetools import func_with_new_name
@@ -72,9 +73,19 @@
             assertion_error_ll_exc_type)
         self.c_n_i_error_ll_exc_type = constant_value(n_i_error_ll_exc_type)
 
+        if register.register_number is not None:
+            self.c_nonnull_specialregister = constant_value(register.nonnull)
+            self.c_load_from_reg = constant_value(register.load_from_reg)
+            self.c_reg_is_nonnull = constant_value(register.reg_is_nonnull)
+            self.c_store_into_reg = constant_value(register.store_into_reg)
+
         def rpyexc_occured():
-            exc_type = exc_data.exc_type
-            return bool(exc_type)
+            if register.register_number is None:
+                exc_type = exc_data.exc_type
+                return bool(exc_type)
+            else:
+                # an exception occurred iff the special register is 0
+                return register.load_from_reg() == llmemory.NULL
 
         def rpyexc_fetch_type():
             return exc_data.exc_type
@@ -83,6 +94,8 @@
             return exc_data.exc_value
 
         def rpyexc_clear():
+            if register.register_number is not None:
+                register.store_into_reg(register.nonnull)
             exc_data.exc_type = null_type
             exc_data.exc_value = null_value
 
@@ -99,11 +112,15 @@
             exc_data.exc_type = etype
             exc_data.exc_value = evalue
             lloperation.llop.debug_start_traceback(lltype.Void, etype)
+            if register.register_number is not None:
+                register.store_into_reg(llmemory.NULL)
 
         def rpyexc_reraise(etype, evalue):
             exc_data.exc_type = etype
             exc_data.exc_value = evalue
             lloperation.llop.debug_reraise_traceback(lltype.Void, etype)
+            if register.register_number is not None:
+                register.store_into_reg(llmemory.NULL)
 
         def rpyexc_fetch_exception():
             evalue = rpyexc_fetch_value()
@@ -114,6 +131,8 @@
             if evalue:
                 exc_data.exc_type = rclass.ll_inst_type(evalue)
                 exc_data.exc_value = evalue
+                if register.register_number is not None:
+                    register.store_into_reg(llmemory.NULL)
 
         def rpyexc_raise_stack_overflow():
             rpyexc_raise(stackovf_ll_exc_type, stackovf_ll_exc)
@@ -409,6 +428,8 @@
         #
         self.gen_setfield('exc_value', self.c_null_evalue, llops)
         self.gen_setfield('exc_type',  self.c_null_etype,  llops)
+        if register.register_number is not None:
+            self.gen_setspecialregister(self.c_nonnull_specialregister, llops)
         excblock.operations[:] = llops
         newgraph.exceptblock.inputargs[0].concretetype = self.lltype_of_exception_type
         newgraph.exceptblock.inputargs[1].concretetype = self.lltype_of_exception_value
@@ -432,9 +453,11 @@
         if alloc_shortcut:
             T = spaceop.result.concretetype
             var_no_exc = self.gen_nonnull(spaceop.result, llops)
-        else:
+        elif register.register_number is None:
             v_exc_type = self.gen_getfield('exc_type', llops)
             var_no_exc = self.gen_isnull(v_exc_type, llops)
+        else:
+            var_no_exc = self.gen_specialreg_no_exc(llops)
 
         block.operations.extend(llops)
         
@@ -527,6 +550,17 @@
     def gen_nonnull(self, v, llops):
         return llops.genop('ptr_nonzero', [v], lltype.Bool)
 
+    def gen_getspecialregister(self, llops):
+        return llops.genop('direct_call', [self.c_load_from_reg],
+                           resulttype = llmemory.Address)
+
+    def gen_specialreg_no_exc(self, llops):
+        return llops.genop('direct_call', [self.c_reg_is_nonnull],
+                           resulttype = lltype.Bool)
+
+    def gen_setspecialregister(self, v, llops):
+        llops.genop('direct_call', [self.c_store_into_reg, v])
+
     def same_obj(self, ptr1, ptr2):
         return ptr1._same_obj(ptr2)
 


More information about the pypy-commit mailing list