Commits

Armin Rigo committed 2494530

Start to integrate the r15-for-exception branch...

Comments (0)

Files changed (5)

pypy/rlib/register.py

 
 # 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_SPECIAL_REG() pypy_r15\n'
-        '#define PYPY_SPECIAL_REG_NONNULL() (pypy_r15 != NULL)\n'
-        '#define PYPY_SET_SPECIAL_REG(x) (pypy_r15 = x)\n'
-        ],
+    post_include_bits=["""
+register long pypy_r15 asm("r15");
+#define PYPY_GET_SPECIAL_REG() ((void *)(pypy_r15 & ~1))
+#define PYPY_SET_SPECIAL_REG(x) (pypy_r15 = (long)(x) | (pypy_r15 & 1))
+#define PYPY_INCR_SPECIAL_REG(d) (pypy_r15 += (d))
+#define PYPY_SPECIAL_REG_GETEXC() (pypy_r15 & 1)
+#define PYPY_SPECIAL_REG_SETEXC(x) (pypy_r15 = (x) ? pypy_r15|1 : pypy_r15&~1)
+"""],
     )
 
 _test_eci = eci.merge(ExternalCompilationInfo(
     post_include_bits=["""
             void f(void) {
-                pypy_r15 = &f;
+                pypy_r15 = 12345;
             }
     """]))
 
     # the behavior is emulated.
 
     _value_reg = None
+    _exc_marker = False
 
     def _pypy_get_special_reg():
         assert _value_reg is not None
         return _value_reg
 
-    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
 
+    def _pypy_incr_special_reg(delta):
+        global _value_reg
+        assert _value_reg is not None
+        _value_reg += delta
+
+    def _pypy_special_reg_getexc():
+        return _exc_marker
+
+    def _pypy_special_reg_setexc(flag):
+        global _value_reg
+        _exc_marker = flag
+
     load_from_reg = rffi.llexternal('PYPY_GET_SPECIAL_REG', [],
                                     llmemory.Address,
                                     _callable=_pypy_get_special_reg,
                                     compilation_info=eci,
                                     _nowrapper=True)
 
-    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,
                                      compilation_info=eci,
                                      _nowrapper=True)
 
-    # xxx temporary
-    nonnull = llmemory.cast_int_to_adr(-1)
+    incr_reg = rffi.llexternal('PYPY_INCR_SPECIAL_REG',
+                               [lltype.Signed],
+                               lltype.Void,
+                               _callable=_pypy_set_special_reg,
+                               compilation_info=eci,
+                               _nowrapper=True)
+
+    get_exception = rffi.llexternal('PYPY_SPECIAL_REG_GETEXC', [],
+                                    lltype.Bool,
+                                    _callable=_pypy_special_reg_getexc,
+                                    compilation_info=eci,
+                                    _nowrapper=True)
+
+    set_exception = rffi.llexternal('PYPY_SPECIAL_REG_SETEXC', [lltype.Bool],
+                                    lltype.Void,
+                                    _callable=_pypy_special_reg_setexc,
+                                    compilation_info=eci,
+                                    _nowrapper=True)

pypy/rpython/memory/gctransform/framework.py

 
         def getfn(ll_function, args_s, s_result, inline=False,
                   minimal_transform=True):
+            if isinstance(ll_function, lltype._ptr):
+                # assume that args_s and s_result match
+                from pypy.objspace.flow.model import Constant
+                return Constant(ll_function, lltype.typeOf(ll_function))
+            #
             graph = annhelper.getgraph(ll_function, args_s, s_result)
             if minimal_transform:
                 self.need_minimal_transform(graph)
                                            [annmodel.SomeAddress()],
                                            annmodel.s_None,
                                            inline = True)
+            self.incr_stack_top_ptr = getfn(root_walker.incr_stack_top,
+                                            [annmodel.SomeInteger()],
+                                            annmodel.s_None,
+                                            inline = True)
         else:
             self.get_stack_top_ptr = None
             self.set_stack_top_ptr = None
+            self.incr_stack_top_ptr = None
         self.weakref_deref_ptr = self.inittime_helper(
             ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
         

pypy/rpython/memory/gctransform/shadowstack.py

 from pypy.rpython.memory.gctransform.framework import BaseRootWalker
 from pypy.rpython.memory.gctransform.framework import sizeofaddr
 from pypy.rpython import rmodel
+from pypy.rlib import register
 from pypy.rlib.debug import ll_assert
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.tool.algo.regalloc import perform_register_allocation
         # NB. 'self' is frozen, but we can use self.gcdata to store state
         gcdata = self.gcdata
 
-        def get_stack_top():
-            return gcdata.root_stack_top
-        self.get_stack_top = get_stack_top
-
-        def set_stack_top(addr):
-            gcdata.root_stack_top = addr
-        self.set_stack_top = set_stack_top
+        if register.register_number is not None:
+            self.get_stack_top = register.load_from_reg
+            self.set_stack_top = register.store_into_reg
+            self.incr_stack_top = register.incr_reg
+        else:
+            def get_stack_top():
+                return gcdata.root_stack_top
+            self.get_stack_top = get_stack_top
+            def set_stack_top(addr):
+                gcdata.root_stack_top = addr
+            self.set_stack_top = set_stack_top
+            def incr_stack_top(delta):
+                gcdata.root_stack_top += delta
+            self.incr_stack_top = incr_stack_top
 
         self.rootstackhook = gctransformer.root_stack_jit_hook
         if self.rootstackhook is None:
 
     def push_stack(self, addr):
         top = self.get_stack_top()
+        self.incr_stack_top(sizeofaddr)
         top.address[0] = addr
-        self.set_stack_top(top + sizeofaddr)
 
     def pop_stack(self):
         top = self.get_stack_top() - sizeofaddr
-        self.set_stack_top(top)
+        self.incr_stack_top(-sizeofaddr)
         return top.address[0]
 
     def allocate_stack(self):
     def setup_root_walker(self):
         stackbase = self.allocate_stack()
         ll_assert(bool(stackbase), "could not allocate root stack")
-        self.gcdata.root_stack_top  = stackbase
+        self.set_stack_top(stackbase)
         self.gcdata.root_stack_base = stackbase
         BaseRootWalker.setup_root_walker(self)
 
         gc = self.gc
         rootstackhook = self.rootstackhook
         addr = gcdata.root_stack_base
-        end = gcdata.root_stack_top
+        end = self.get_stack_top()
         while addr != end:
             addr += rootstackhook(collect_stack_root, gc, addr)
         if self.collect_stacks_from_other_threads is not None:
                         blocks_pop_roots[block] = len(llops)
             block.operations[:] = llops
         numcolors = -negnumcolors
-        c_framesize = rmodel.inputconst(lltype.Signed, numcolors * sizeofaddr)
+        framesize = numcolors * sizeofaddr
+        c_framesize = rmodel.inputconst(lltype.Signed, framesize)
+        c_minusframesize = rmodel.inputconst(lltype.Signed, -framesize)
         #
         # For each block, determine in which category it is:
         #
             if "stop" in blockstate[block]:     # "stop" or "startstop"
                 llops = LowLevelOpList()
                 i = blocks_pop_roots[block]
-                v_topaddr = get_v_topaddr(block, firstuse=i)
-                v_baseaddr = llops.genop("adr_sub", [v_topaddr, c_framesize],
-                                         resulttype=llmemory.Address)
-                llops.genop("direct_call", [gct.set_stack_top_ptr, v_baseaddr])
+                llops.genop("direct_call", [gct.incr_stack_top_ptr,
+                                            c_minusframesize])
                 block.operations[i:i] = llops
                 # ^^^ important: done first, in case it's a startstop block,
                 #     otherwise the index in 'blocks_push_roots[block]' is

pypy/translator/c/src/mem.h

 #ifdef PYPY_GET_SPECIAL_REG      /* pypy/rlib/register.py */
 #  define OP_GC_STACK_BOTTOM(r)        pypy_asm_stack_bottom();        \
                                        r = PYPY_GET_SPECIAL_REG();     \
-                                       PYPY_SET_SPECIAL_REG((void*)-1)
+                                       PYPY_SPECIAL_REG_SETEXC(0)
 #  define OP_GC_STACK_BOTTOM_STOP(v,r) PYPY_SET_SPECIAL_REG(v)
 #else
 #  define OP_GC_STACK_BOTTOM(r)         pypy_asm_stack_bottom()

pypy/translator/exceptiontransform.py

         use_special_reg = standalone and register.register_number is not None
         self.use_special_reg = use_special_reg
         if use_special_reg:
-            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)
+            self.c_get_exception = constant_value(register.get_exception)
+            self.c_set_exception = constant_value(register.set_exception)
 
         def rpyexc_occured():
             if use_special_reg:
-                # an exception occurred iff the special register is 0
-                return register.load_from_reg() == llmemory.NULL
+                return register.get_exception()
             else:
                 exc_type = exc_data.exc_type
                 return bool(exc_type)
 
         def rpyexc_clear():
             if use_special_reg:
-                register.store_into_reg(register.nonnull)
+                register.set_exception(False)
             exc_data.exc_type = null_type
             exc_data.exc_value = null_value
 
             exc_data.exc_value = evalue
             lloperation.llop.debug_start_traceback(lltype.Void, etype)
             if use_special_reg:
-                register.store_into_reg(llmemory.NULL)
+                register.set_exception(True)
 
         def rpyexc_reraise(etype, evalue):
             exc_data.exc_type = etype
             exc_data.exc_value = evalue
             lloperation.llop.debug_reraise_traceback(lltype.Void, etype)
             if use_special_reg:
-                register.store_into_reg(llmemory.NULL)
+                register.set_exception(True)
 
         def rpyexc_fetch_exception():
             evalue = rpyexc_fetch_value()
                 exc_data.exc_type = rclass.ll_inst_type(evalue)
                 exc_data.exc_value = evalue
                 if use_special_reg:
-                    register.store_into_reg(llmemory.NULL)
+                    register.set_exception(True)
 
         def rpyexc_raise_stack_overflow():
             rpyexc_raise(stackovf_ll_exc_type, stackovf_ll_exc)
         self.gen_setfield('exc_value', self.c_null_evalue, llops)
         self.gen_setfield('exc_type',  self.c_null_etype,  llops)
         if self.use_special_reg:
-            self.gen_setspecialregister(self.c_nonnull_specialregister, llops)
+            self.gen_setexception(False, llops)
         excblock.operations[:] = llops
         newgraph.exceptblock.inputargs[0].concretetype = self.lltype_of_exception_type
         newgraph.exceptblock.inputargs[1].concretetype = self.lltype_of_exception_value
     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):
+        v = llops.genop('direct_call', [self.c_get_exception],
+                        resulttype = lltype.Bool)
+        return llops.genop('bool_not', [v], resulttype=lltype.Bool)
 
-    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 gen_setexception(self, flag, llops):
+        v = inputconst(lltype.Bool, flag)
+        llops.genop('direct_call', [self.c_set_exception, v])
 
     def same_obj(self, ptr1, ptr2):
         return ptr1._same_obj(ptr2)