[pypy-svn] r72877 - in pypy/trunk/pypy/jit/backend/llsupport: . test

fijal at codespeak.net fijal at codespeak.net
Fri Mar 26 04:42:11 CET 2010


Author: fijal
Date: Fri Mar 26 04:42:09 2010
New Revision: 72877

Added:
   pypy/trunk/pypy/jit/backend/llsupport/support.py
      - copied unchanged from r72876, pypy/branch/kill-asm-call/pypy/jit/backend/llsupport/support.py
Modified:
   pypy/trunk/pypy/jit/backend/llsupport/descr.py
   pypy/trunk/pypy/jit/backend/llsupport/gc.py
   pypy/trunk/pypy/jit/backend/llsupport/llmodel.py
   pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py
   pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py
Log:
Merge the kill-asm-call branch.

This branch implements calls as small stubs that gets rendered as C calls
instead of small assembler stubs. Mostly a cleanup, but also might be slightly
memory and cpu friendly.


Modified: pypy/trunk/pypy/jit/backend/llsupport/descr.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/descr.py	(original)
+++ pypy/trunk/pypy/jit/backend/llsupport/descr.py	Fri Mar 26 04:42:09 2010
@@ -1,7 +1,9 @@
-from pypy.rpython.lltypesystem import lltype
-from pypy.jit.backend.llsupport import symbolic
+import py
+from pypy.rpython.lltypesystem import lltype, rffi, llmemory
+from pypy.jit.backend.llsupport import symbolic, support
 from pypy.jit.metainterp.history import AbstractDescr, getkind, BoxInt, BoxPtr
 from pypy.jit.metainterp.history import BasicFailDescr, LoopToken, BoxFloat
+from pypy.jit.metainterp import history
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 
 # The point of the class organization in this file is to make instances
@@ -11,8 +13,9 @@
 
 
 class GcCache(object):
-    def __init__(self, translate_support_code):
+    def __init__(self, translate_support_code, rtyper=None):
         self.translate_support_code = translate_support_code
+        self.rtyper = rtyper
         self._cache_size = {}
         self._cache_field = {}
         self._cache_array = {}
@@ -176,6 +179,7 @@
 # CallDescrs
 
 class BaseCallDescr(AbstractDescr):
+    empty_box = BoxInt(0)
     _clsname = ''
     loop_token = None
     arg_classes = ''     # <-- annotation hack
@@ -187,17 +191,9 @@
     def get_extra_info(self):
         return self.extrainfo
 
-    def instantiate_arg_classes(self):
-        result = []
-        for c in self.arg_classes:
-            if   c == 'i': box = BoxInt()
-            elif c == 'f': box = BoxFloat()
-            else:          box = BoxPtr()
-            result.append(box)
-        return result
-
     _returns_a_pointer = False        # unless overridden by GcPtrCallDescr
     _returns_a_float   = False        # unless overridden by FloatCallDescr
+    _returns_a_void    = False        # unless overridden by VoidCallDescr
 
     def returns_a_pointer(self):
         return self._returns_a_pointer
@@ -205,39 +201,59 @@
     def returns_a_float(self):
         return self._returns_a_float
 
+    def returns_a_void(self):
+        return self._returns_a_void
+
     def get_result_size(self, translate_support_code):
         raise NotImplementedError
 
-    def get_token_for_call(self, cpu):
-        if self.loop_token is not None:
-            return self.loop_token
-        args = [BoxInt()] + self.instantiate_arg_classes()
-        if self.get_result_size(cpu.translate_support_code) == 0:
-            result = None
-            result_list = []
-        else:
-            if self.returns_a_pointer():
-                result = BoxPtr()
-            elif self.returns_a_float():
-                result = BoxFloat()
+    def get_call_stub(self):
+        return self.call_stub
+
+    def create_call_stub(self, rtyper, RESULT):
+        def process(no, c):
+            if c == 'i':
+                return 'args[%d].getint()' % (no,)
+            elif c == 'f':
+                return 'args[%d].getfloat()' % (no,)
+            elif c == 'r':
+                return 'args[%d].getref_base()' % (no,)
             else:
-                result = BoxInt()
-            result_list = [result]
-        operations = [
-            ResOperation(rop.CALL, args[:], result, self),
-            ResOperation(rop.GUARD_NO_EXCEPTION, [], None,
-                         descr=BasicFailDescr()),
-            ResOperation(rop.FINISH, result_list, None,
-                         descr=BasicFailDescr())]
-        operations[1].fail_args = []
-        loop_token = LoopToken()
-        # note: the 'args' that we pass below is not the same object as the
-        # 'args[:]' that was passed above to ResOperation, because we want
-        # the argument to ResOperation to be non-resizable, but the argument
-        # to compile_loop to be resizable.
-        cpu.compile_loop(args, operations, loop_token)
-        self.loop_token = loop_token
-        return loop_token
+                raise Exception("Unknown type %s for type %s" % (c, TP))
+
+        def TYPE(arg):
+            if arg == 'i':
+                return lltype.Signed
+            elif arg == 'f':
+                return lltype.Float
+            elif arg == 'r':
+                return llmemory.GCREF
+            elif arg == 'v':
+                return lltype.Void
+            
+        args = ", ".join([process(i + 1, c) for i, c in
+                          enumerate(self.arg_classes)])
+
+        if self.returns_a_pointer():
+            result = 'history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, res))'
+        elif self.returns_a_float():
+            result = 'history.BoxFloat(res)'
+        elif self.returns_a_void():
+            result = 'None'
+        else:
+            result = 'history.BoxInt(rffi.cast(lltype.Signed, res))'
+        source = py.code.Source("""
+        def call_stub(args):
+            fnptr = rffi.cast(lltype.Ptr(FUNC), args[0].getint())
+            res = support.maybe_on_top_of_llinterp(rtyper, fnptr)(%(args)s)
+            return %(result)s
+        """ % locals())
+        ARGS = [TYPE(arg) for arg in self.arg_classes]
+        FUNC = lltype.FuncType(ARGS, RESULT)
+        d = locals().copy()
+        d.update(globals())
+        exec source.compile() in d
+        self.call_stub = d['call_stub']
 
     def repr_of_descr(self):
         return '<%s>' % self._clsname
@@ -245,15 +261,20 @@
 
 class NonGcPtrCallDescr(BaseCallDescr):
     _clsname = 'NonGcPtrCallDescr'
+    
     def get_result_size(self, translate_support_code):
         return symbolic.get_size_of_ptr(translate_support_code)
 
 class GcPtrCallDescr(NonGcPtrCallDescr):
+    empty_box = BoxPtr(lltype.nullptr(llmemory.GCREF.TO))
     _clsname = 'GcPtrCallDescr'
     _returns_a_pointer = True
 
 class VoidCallDescr(NonGcPtrCallDescr):
+    empty_box = None
     _clsname = 'VoidCallDescr'
+    _returns_a_void = True
+    
     def get_result_size(self, translate_support_code):
         return 0
 
@@ -281,6 +302,7 @@
         return cache[key]
     except KeyError:
         calldescr = cls(arg_classes, extrainfo)
+        calldescr.create_call_stub(gccache.rtyper, RESULT)
         cache[key] = calldescr
         return calldescr
 
@@ -308,6 +330,7 @@
         #
         if TYPE is lltype.Float:
             setattr(Descr, floatattrname, True)
+            Descr.empty_box = BoxFloat(0.0)
         #
         _cache[nameprefix, TYPE] = Descr
         return Descr

Modified: pypy/trunk/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/gc.py	(original)
+++ pypy/trunk/pypy/jit/backend/llsupport/gc.py	Fri Mar 26 04:42:09 2010
@@ -19,8 +19,8 @@
 # ____________________________________________________________
 
 class GcLLDescription(GcCache):
-    def __init__(self, gcdescr, translator=None):
-        GcCache.__init__(self, translator is not None)
+    def __init__(self, gcdescr, translator=None, rtyper=None):
+        GcCache.__init__(self, translator is not None, rtyper)
         self.gcdescr = gcdescr
     def _freeze_(self):
         return True
@@ -41,8 +41,8 @@
     moving_gc = False
     gcrootmap = None
 
-    def __init__(self, gcdescr, translator):
-        GcLLDescription.__init__(self, gcdescr, translator)
+    def __init__(self, gcdescr, translator, rtyper):
+        GcLLDescription.__init__(self, gcdescr, translator, rtyper)
         # grab a pointer to the Boehm 'malloc' function
         from pypy.rpython.tool import rffi_platform
         compilation_info = rffi_platform.configure_boehm()
@@ -327,11 +327,11 @@
 class GcLLDescr_framework(GcLLDescription):
     DEBUG = False    # forced to True by x86/test/test_zrpy_gc.py
 
-    def __init__(self, gcdescr, translator, llop1=llop):
+    def __init__(self, gcdescr, translator, rtyper, llop1=llop):
         from pypy.rpython.memory.gctypelayout import _check_typeid
         from pypy.rpython.memory.gcheader import GCHeaderBuilder
         from pypy.rpython.memory.gctransform import framework
-        GcLLDescription.__init__(self, gcdescr, translator)
+        GcLLDescription.__init__(self, gcdescr, translator, rtyper)
         assert self.translate_support_code, "required with the framework GC"
         self.translator = translator
         self.llop1 = llop1
@@ -611,7 +611,7 @@
 
 # ____________________________________________________________
 
-def get_ll_description(gcdescr, translator=None):
+def get_ll_description(gcdescr, translator=None, rtyper=None):
     # translator is None if translate_support_code is False.
     if gcdescr is not None:
         name = gcdescr.config.translation.gctransformer
@@ -622,4 +622,4 @@
     except KeyError:
         raise NotImplementedError("GC transformer %r not supported by "
                                   "the JIT backend" % (name,))
-    return cls(gcdescr, translator)
+    return cls(gcdescr, translator, rtyper)

Modified: pypy/trunk/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/llmodel.py	(original)
+++ pypy/trunk/pypy/jit/backend/llsupport/llmodel.py	Fri Mar 26 04:42:09 2010
@@ -1,7 +1,7 @@
 import sys
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.llinterp import LLInterpreter, LLException
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values,\
@@ -13,6 +13,9 @@
 from pypy.jit.backend.llsupport.descr import get_field_descr, BaseFieldDescr
 from pypy.jit.backend.llsupport.descr import get_array_descr, BaseArrayDescr
 from pypy.jit.backend.llsupport.descr import get_call_descr,  BaseCallDescr
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+
+empty_int_box = BoxInt(0)
 
 class AbstractLLCPU(AbstractCPU):
     from pypy.jit.metainterp.typesystem import llhelper as ts
@@ -31,7 +34,7 @@
             translator = rtyper.annotator.translator
         else:
             translator = None
-        self.gc_ll_descr = get_ll_description(gcdescr, translator)
+        self.gc_ll_descr = get_ll_description(gcdescr, translator, rtyper)
         if translator and translator.config.translation.gcremovetypeptr:
             self.vtable_offset = None
         else:
@@ -474,20 +477,23 @@
         if not we_are_translated():
             assert (list(calldescr.arg_classes) ==
                     [arg.type for arg in args[1:]])
-        loop_token = calldescr.get_token_for_call(self)
-        set_future_values(self, args)
-        self.execute_token(loop_token)
-        # Note: if an exception is set, the rest of the code does a bit of
-        # nonsense but nothing wrong (the return value should be ignored)
-        if calldescr.returns_a_pointer():
-            return BoxPtr(self.get_latest_value_ref(0))
-        elif calldescr.returns_a_float():
-            return BoxFloat(self.get_latest_value_float(0))
-        elif calldescr.get_result_size(self.translate_support_code) > 0:
-            return BoxInt(self.get_latest_value_int(0))
-        else:
-            return None
-
+        callstub = calldescr.get_call_stub()
+        try:
+            return callstub(args)
+        except Exception, e:
+            if not we_are_translated():
+                if not type(e) is LLException:
+                    raise
+                self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF,
+                                                              e.args[1])
+                self.saved_exception = rffi.cast(lltype.Signed, e.args[0])
+            else:
+                ptr = cast_instance_to_base_ptr(e)
+                self.saved_exc_value = lltype.cast_opaque_ptr(llmemory.GCREF,
+                                                              ptr)
+                self.saved_exception = rffi.cast(lltype.Signed, ptr.typeptr)
+            return calldescr.empty_box
+            
     def do_cast_ptr_to_int(self, ptrbox):
         return BoxInt(self.cast_gcref_to_int(ptrbox.getref_base()))
 

Modified: pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py	(original)
+++ pypy/trunk/pypy/jit/backend/llsupport/test/test_descr.py	Fri Mar 26 04:42:09 2010
@@ -2,7 +2,8 @@
 from pypy.jit.backend.llsupport.descr import *
 from pypy.jit.backend.llsupport import symbolic
 from pypy.rlib.objectmodel import Symbolic
-
+from pypy.rpython.annlowlevel import llhelper
+from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr
 
 def test_get_size_descr():
     c0 = GcCache(False)
@@ -147,6 +148,7 @@
     assert not descr1.returns_a_pointer()
     assert not descr1.returns_a_float()
     assert descr1.arg_classes == "ii"
+    assert isinstance(descr1.empty_box, BoxInt)
     #
     T = lltype.GcStruct('T')
     descr2 = get_call_descr(c0, [lltype.Ptr(T)], lltype.Ptr(T))
@@ -154,15 +156,22 @@
     assert descr2.returns_a_pointer()
     assert not descr2.returns_a_float()
     assert descr2.arg_classes == "r"
+    assert isinstance(descr2.empty_box, BoxPtr)
     #
     U = lltype.GcStruct('U', ('x', lltype.Signed))
     assert descr2 == get_call_descr(c0, [lltype.Ptr(U)], lltype.Ptr(U))
     #
+    V = lltype.Struct('V', ('x', lltype.Signed))
+    assert isinstance(get_call_descr(c0, [], lltype.Ptr(V)).empty_box, BoxInt)
+    #
+    assert get_call_descr(c0, [], lltype.Void).empty_box is None
+    #
     descr4 = get_call_descr(c0, [lltype.Float, lltype.Float], lltype.Float)
     assert descr4.get_result_size(False) == rffi.sizeof(lltype.Float)
     assert not descr4.returns_a_pointer()
     assert descr4.returns_a_float()
     assert descr4.arg_classes == "ff"
+    assert isinstance(descr4.empty_box, BoxFloat)
 
 def test_get_call_descr_translated():
     c1 = GcCache(True)
@@ -227,3 +236,34 @@
     #
     descr4f = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Float)
     assert 'FloatCallDescr' in descr4f.repr_of_descr()
+
+def test_call_stubs():
+    c0 = GcCache(False)
+    ARGS = [lltype.Char, lltype.Signed]
+    RES = lltype.Char
+    descr1 = get_call_descr(c0, ARGS, RES)
+    def f(a, b):
+        return 'c'
+
+    call_stub = descr1.get_call_stub()
+    fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f)
+
+    res = call_stub([BoxInt(rffi.cast(lltype.Signed, fnptr)),
+                     BoxInt(1), BoxInt(2)])
+    assert res.getint() == ord('c')
+
+    ARRAY = lltype.GcArray(lltype.Signed)
+    ARGS = [lltype.Float, lltype.Ptr(ARRAY)]
+    RES = lltype.Float
+
+    def f(a, b):
+        return float(b[0]) + a
+
+    fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f)
+    descr2 = get_call_descr(c0, ARGS, RES)
+    a = lltype.malloc(ARRAY, 3)
+    opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a)
+    a[0] = 1
+    res = descr2.get_call_stub()([BoxInt(rffi.cast(lltype.Signed, fnptr)),
+                                  BoxFloat(3.5), BoxPtr(opaquea)])
+    assert res.getfloat() == 4.5

Modified: pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py	(original)
+++ pypy/trunk/pypy/jit/backend/llsupport/test/test_gc.py	Fri Mar 26 04:42:09 2010
@@ -9,7 +9,7 @@
 
 
 def test_boehm():
-    gc_ll_descr = GcLLDescr_boehm(None, None)
+    gc_ll_descr = GcLLDescr_boehm(None, None, None)
     #
     record = []
     prev_funcptr_for_new = gc_ll_descr.funcptr_for_new
@@ -167,7 +167,8 @@
         gcdescr = get_description(config_)
         translator = FakeTranslator()
         llop1 = FakeLLOp()
-        gc_ll_descr = GcLLDescr_framework(gcdescr, FakeTranslator(), llop1)
+        gc_ll_descr = GcLLDescr_framework(gcdescr, FakeTranslator(), None,
+                                          llop1)
         gc_ll_descr.initialize()
         self.llop1 = llop1
         self.gc_ll_descr = gc_ll_descr



More information about the Pypy-commit mailing list