[pypy-commit] pypy stmgc-c4: add weakref support and log rewritten jit trace

Raemi noreply at buildbot.pypy.org
Mon Jul 22 17:56:41 CEST 2013


Author: Remi Meier <remi.meier at gmail.com>
Branch: stmgc-c4
Changeset: r65526:ac7d49c563e5
Date: 2013-07-22 17:55 +0200
http://bitbucket.org/pypy/pypy/changeset/ac7d49c563e5/

Log:	add weakref support and log rewritten jit trace

diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -397,16 +397,24 @@
             if IS_X86_32:
                 # we have 2 extra words on stack for retval and we pass 1 extra
                 # arg, so we need to substract 2 words
+                # ||val|retadr|
                 mc.SUB_ri(esp.value, 2 * WORD)
+                # ||val|retadr|x|x||
                 mc.MOV_rs(eax.value, 3 * WORD) # 2 + 1
                 mc.MOV_sr(0, eax.value)
+                # ||val|retadr|x|val||
             else:
+                # ||val|retadr||
                 mc.MOV_rs(edi.value, WORD)
         else:
+            # ||retadr|
             # we have one word to align
             mc.SUB_ri(esp.value, 7 * WORD) # align and reserve some space
+            # ||retadr|x||x|x||x|x||x|x||
             mc.MOV_sr(WORD, eax.value) # save for later
+            # ||retadr|x||x|x||x|x||rax|x||
             mc.MOVSD_sx(3 * WORD, xmm0.value)
+            # ||retadr|x||x|x||xmm0|x||rax|x||
             if IS_X86_32:
                 mc.MOV_sr(4 * WORD, edx.value)
                 mc.MOV_sr(0, ebp.value)
@@ -427,19 +435,24 @@
         if descr.returns_modified_object:
             # new addr in eax, save to now unused arg
             if for_frame:
+                # ||retadr|x||x|x||xmm0|x||rax|x||
                 mc.PUSH_r(eax.value)
+                # ||retadr|x||x|x||xmm0|x||rax|x||result|
             elif IS_X86_32:
                 mc.MOV_sr(3 * WORD, eax.value)
+                # ||val|retadr|x|val||
+                # -> ||result|retaddr|x|val||
             else:
                 mc.MOV_sr(WORD, eax.value)
+                # ||val|retadr|| -> ||result|retadr||
                 
         if withcards:
             # A final TEST8 before the RET, for the caller.  Careful to
             # not follow this instruction with another one that changes
             # the status of the CPU flags!
-            assert not is_stm
+            assert not is_stm and not descr.returns_modified_object
             if IS_X86_32:
-                mc.MOV_rs(eax.value, 3*WORD)
+                mc.MOV_rs(eax.value, 3 * WORD)
             else:
                 mc.MOV_rs(eax.value, WORD)
             mc.TEST8(addr_add_const(eax, descr.jit_wb_if_flag_byteofs),
@@ -460,14 +473,18 @@
         else:
             if IS_X86_32:
                 mc.MOV_rs(edx.value, 5 * WORD)
+            # ||retadr|x||x|x||xmm0|x||rax|x||result|
             mc.MOVSD_xs(xmm0.value, 4 * WORD)
             mc.MOV_rs(eax.value, 2 * WORD) # restore
             self._restore_exception(mc, exc0, exc1)
             mc.MOV(exc0, RawEspLoc(WORD * 6, REF))
             mc.MOV(exc1, RawEspLoc(WORD * 7, INT))
 
-            mc.POP_r(eax.value) # return value
-            
+            if IS_X86_32:
+                mc.POP_r(edx.value) # return value
+            else:
+                mc.POP_r(edi.value) # return value
+
             mc.LEA_rs(esp.value, 7 * WORD)
 
             mc.RET()
@@ -478,7 +495,8 @@
         else:
             descr.set_b_slowpath(withcards + 2 * withfloats, rawstart)
 
-    def assemble_loop(self, loopname, inputargs, operations, looptoken, log):
+    def assemble_loop(self, loopname, inputargs, operations, looptoken, log,
+                      logger=None):
         '''adds the following attributes to looptoken:
                _ll_function_addr    (address of the generated func, as an int)
                _ll_loop_code       (debug: addr of the start of the ResOps)
@@ -513,6 +531,9 @@
         self._check_frame_depth_debug(self.mc)
         operations = regalloc.prepare_loop(inputargs, operations, looptoken,
                                            clt.allgcrefs)
+        if logger:
+            logger.log_loop(inputargs, operations, -2, "rewritten", 
+                            name=loopname)
         looppos = self.mc.get_relative_pos()
         frame_depth_no_fixed_size = self._assemble(regalloc, inputargs,
                                                    operations)
@@ -554,7 +575,7 @@
                        size_excluding_failure_stuff - looppos)
 
     def assemble_bridge(self, faildescr, inputargs, operations,
-                        original_loop_token, log):
+                        original_loop_token, log, logger=None):
         if not we_are_translated():
             # Arguments should be unique
             assert len(set(inputargs)) == len(inputargs)
@@ -572,6 +593,8 @@
                                              operations,
                                              self.current_clt.allgcrefs,
                                              self.current_clt.frame_info)
+        if logger:
+            logger.log_bridge(inputargs, operations, "rewritten")
         self._check_frame_depth(self.mc, regalloc.get_gcmap())
         frame_depth_no_fixed_size = self._assemble(regalloc, inputargs, operations)
         codeendpos = self.mc.get_relative_pos()
@@ -2138,10 +2161,21 @@
         if not is_frame:
             mc.PUSH(loc_base)
         if is_frame and align_stack:
+            # ||retadr|
             mc.SUB_ri(esp.value, 16 - WORD) # erase the return address
+            # ||retadr|...||
         func = descr.get_b_slowpath(helper_num)
         mc.CALL(imm(func))
-        mc.MOV_rr(loc_base.value, eax.value)
+
+        # result in eax, except if is_frame
+        if is_frame:
+            if IS_X86_32:
+                mc.MOV_rr(loc_base.value, edx.value)
+            else:
+                mc.MOV_rr(loc_base.value, edi.value)
+        else:
+            mc.MOV_rr(loc_base.value, eax.value)
+            
         if is_frame and align_stack:
             mc.ADD_ri(esp.value, 16 - WORD) # erase the return address
 
diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py
--- a/rpython/jit/backend/x86/runner.py
+++ b/rpython/jit/backend/x86/runner.py
@@ -90,16 +90,18 @@
         lines = machine_code_dump(data, addr, self.backend_name, label_list)
         print ''.join(lines)
 
-    def compile_loop(self, inputargs, operations, looptoken, log=True, name=''):
+    def compile_loop(self, inputargs, operations, looptoken, log=True, name='',
+                     logger=None):
         return self.assembler.assemble_loop(name, inputargs, operations,
-                                            looptoken, log=log)
+                                            looptoken, log=log, logger=logger)
 
     def compile_bridge(self, faildescr, inputargs, operations,
-                       original_loop_token, log=True):
+                       original_loop_token, log=True, logger=None):
         clt = original_loop_token.compiled_loop_token
         clt.compiling_a_bridge()
         return self.assembler.assemble_bridge(faildescr, inputargs, operations,
-                                              original_loop_token, log=log)
+                                              original_loop_token, log=log,
+                                              logger=logger)
 
     def clear_latest_values(self, count):
         setitem = self.assembler.fail_boxes_ptr.setitem
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -303,14 +303,17 @@
     metainterp_sd.logger_ops.log_loop(inputargs, operations, -2,
                                       'compiling', name=name)
     return metainterp_sd.cpu.compile_loop(inputargs, operations, looptoken,
-                                          log=log, name=name)
+                                          log=log, name=name,
+                                          logger=metainterp_sd.logger_ops)
 
 def do_compile_bridge(metainterp_sd, faildescr, inputargs, operations,
                       original_loop_token, log=True):
     metainterp_sd.logger_ops.log_bridge(inputargs, operations, "compiling")
     assert isinstance(faildescr, AbstractFailDescr)
     return metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations,
-                                            original_loop_token, log=log)
+                                            original_loop_token, log=log,
+                                            logger=metainterp_sd.logger_ops)
+                                            
 
 def send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, type):
     vinfo = jitdriver_sd.virtualizable_info
diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py
--- a/rpython/jit/metainterp/logger.py
+++ b/rpython/jit/metainterp/logger.py
@@ -39,6 +39,10 @@
             debug_start("jit-log-compiling-bridge")
             logops = self._log_operations(inputargs, operations, ops_offset)
             debug_stop("jit-log-compiling-bridge")
+        elif extra == "rewritten":
+            debug_start("jit-log-rewritten-bridge")
+            logops = self._log_operations(inputargs, operations, ops_offset)
+            debug_stop("jit-log-rewritten-bridge")
         else:
             debug_start("jit-log-opt-bridge")
             debug_print("# bridge out of Guard",
diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py
--- a/rpython/memory/gc/stmgc.py
+++ b/rpython/memory/gc/stmgc.py
@@ -104,7 +104,7 @@
         # XXX finalizers are ignored for now
         #ll_assert(not needs_finalizer, 'XXX needs_finalizer')
         #ll_assert(not is_finalizer_light, 'XXX is_finalizer_light')
-        ll_assert(not contains_weakptr, 'XXX contains_weakptr')
+        #ll_assert(not contains_weakptr, 'XXX contains_weakptr')
         # XXX call optimized versions, e.g. if size < GC_NURSERY_SECTION
         return llop.stm_allocate(llmemory.GCREF, size, typeid16)
 
@@ -117,6 +117,9 @@
         (obj + offset_to_length).signed[0] = length
         return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
 
+    def malloc_weakref(self, typeid16, size, obj):
+        return llop.stm_weakref_allocate(llmemory.GCREF, size,
+                                         typeid16, obj)
 
     def can_move(self, obj):
         """Means the reference will stay valid, except if not
diff --git a/rpython/memory/gctransform/stmframework.py b/rpython/memory/gctransform/stmframework.py
--- a/rpython/memory/gctransform/stmframework.py
+++ b/rpython/memory/gctransform/stmframework.py
@@ -1,8 +1,10 @@
 from rpython.annotator import model as annmodel
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.memory.gctransform.framework import (
+from rpython.memory.gctransform.framework import ( TYPE_ID,
      BaseFrameworkGCTransformer, BaseRootWalker, sizeofaddr)
+from rpython.memory.gctypelayout import WEAKREF, WEAKREFPTR
+from rpython.rtyper import rmodel
 
 
 class StmFrameworkGCTransformer(BaseFrameworkGCTransformer):
@@ -12,6 +14,13 @@
                                                       s_gc, s_typeid16)
         gc = self.gcdata.gc
         #
+        s_gcref = annmodel.SomePtr(llmemory.GCREF)
+
+        self.malloc_weakref_ptr = self._getfn(
+            GCClass.malloc_weakref.im_func,
+            [s_gc, s_typeid16, annmodel.SomeInteger(nonneg=True),
+             s_gcref], s_gcref)
+        #
         def pypy_stmcb_size(obj):
             return gc.get_size(obj)
         pypy_stmcb_size.c_name = "pypy_stmcb_size"
@@ -49,6 +58,40 @@
     def gct_gc_adr_of_root_stack_top(self, hop):
         hop.genop("stm_get_root_stack_top", [], resultvar=hop.spaceop.result)
 
+    def gct_weakref_create(self, hop):
+        op = hop.spaceop
+        
+        type_id = self.get_type_id(WEAKREF)
+        
+        c_type_id = rmodel.inputconst(TYPE_ID, type_id)
+        info = self.layoutbuilder.get_info(type_id)
+        c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
+        malloc_ptr = self.malloc_weakref_ptr
+        c_null = rmodel.inputconst(llmemory.Address, llmemory.NULL)
+        args = [self.c_const_gc, c_type_id, c_size, c_null]
+        # XXX: for now, set weakptr ourselves and simply pass NULL
+
+        # push and pop the current live variables *including* the argument
+        # to the weakref_create operation, which must be kept alive and
+        # moved if the GC needs to collect
+        livevars = self.push_roots(hop, keep_current_args=True)
+        v_result = hop.genop("direct_call", [malloc_ptr] + args,
+                             resulttype=llmemory.GCREF)
+        v_result = hop.genop("cast_opaque_ptr", [v_result],
+                            resulttype=WEAKREFPTR)
+        self.pop_roots(hop, livevars)
+        # cast_ptr_to_adr must be done after malloc, as the GC pointer
+        # might have moved just now.
+        v_instance, = op.args
+        v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
+                           resulttype=llmemory.Address)
+        hop.genop("bare_setfield",
+                  [v_result, rmodel.inputconst(lltype.Void, "weakptr"), v_addr])
+        v_weakref = hop.genop("cast_ptr_to_weakrefptr", [v_result],
+                              resulttype=llmemory.WeakRefPtr)
+        hop.cast_result(v_weakref)
+
+        
     def _gct_with_roots_pushed(self, hop):
         livevars = self.push_roots(hop)
         self.default(hop)
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -445,6 +445,8 @@
     'stm_leave_callback_call':LLOp(),
     'stm_abort_and_retry':    LLOp(),
 
+    'stm_weakref_allocate':   LLOp(sideeffects=False, canmallocgc=True),
+    
     'stm_threadlocalref_get': LLOp(sideeffects=False),
     'stm_threadlocalref_set': LLOp(),
     'stm_threadlocal_get':    LLOp(sideeffects=False),
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -593,6 +593,7 @@
     OP_STM_POP_ROOT_INTO                = _OP_STM
     OP_STM_GET_ROOT_STACK_TOP           = _OP_STM
     OP_STM_ALLOCATE                     = _OP_STM
+    OP_STM_WEAKREF_ALLOCATE             = _OP_STM
     OP_STM_GET_TID                      = _OP_STM
     OP_STM_HASH                         = _OP_STM
     OP_STM_ID                           = _OP_STM
diff --git a/rpython/translator/stm/funcgen.py b/rpython/translator/stm/funcgen.py
--- a/rpython/translator/stm/funcgen.py
+++ b/rpython/translator/stm/funcgen.py
@@ -99,6 +99,14 @@
     return '%s = (%s)stm_shadowstack;' % (
         result, cdecl(funcgen.lltypename(op.result), ''))
 
+def stm_weakref_allocate(funcgen, op):
+    arg0 = funcgen.expr(op.args[0])
+    arg1 = funcgen.expr(op.args[1])
+    arg2 = funcgen.expr(op.args[2])
+    result = funcgen.expr(op.result)
+    return '%s = stm_weakref_allocate(%s, %s, %s);' % (result, arg0, 
+                                                       arg1, arg2)
+    
 def stm_allocate(funcgen, op):
     arg0 = funcgen.expr(op.args[0])
     arg1 = funcgen.expr(op.args[1])


More information about the pypy-commit mailing list