[pypy-commit] pypy result-in-resops: A branch to kill boxes. In a glorious attempt to break everything, do it

fijal noreply at buildbot.pypy.org
Thu Jul 19 19:13:16 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: result-in-resops
Changeset: r56230:b0e43ca7c304
Date: 2012-07-19 19:12 +0200
http://bitbucket.org/pypy/pypy/changeset/b0e43ca7c304/

Log:	A branch to kill boxes. In a glorious attempt to break everything,
	do it

diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -1,5 +1,8 @@
-from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.objectmodel import we_are_translated, specialize
+from pypy.rpython.lltypesystem.llmemory import GCREF
+from pypy.rpython.lltypesystem.lltype import typeOf
 
+ at specialize.arg(0)
 def ResOperation(opnum, args, result, descr=None):
     cls = opclasses[opnum]
     op = cls(result)
@@ -18,11 +21,6 @@
     pc = 0
     opnum = 0
 
-    _attrs_ = ('result',)
-
-    def __init__(self, result):
-        self.result = result
-
     def getopnum(self):
         return self.opnum
 
@@ -175,6 +173,50 @@
             return False     # for tests
         return opboolresult[opnum]
 
+    def getint(self):
+        raise NotImplementedError
+
+    def getfloat(self):
+        raise NotImplementedError
+
+    def getpointer(self):
+        raise NotImplementedError
+
+class ResOpNone(object):
+    _mixin_ = True
+    
+    def __init__(self):
+        pass # no return value
+
+class ResOpInt(object):
+    _mixin_ = True
+    
+    def __init__(self, intval):
+        assert isinstance(intval, int)
+        self.intval = intval
+
+    def getint(self):
+        return self.intval
+
+class ResOpFloat(object):
+    _mixin_ = True
+    
+    def __init__(self, floatval):
+        assert isinstance(floatval, float)
+        self.floatval = floatval
+
+    def getfloat(self):
+        return self.floatval
+
+class ResOpPointer(object):
+    _mixin_ = True
+    
+    def __init__(self, pval):
+        assert typeOf(pval) == GCREF
+        self.pval = pval
+
+    def getpointer(self):
+        return self.pval
 
 # ===================
 # Top of the hierachy
@@ -371,96 +413,96 @@
 
 _oplist = [
     '_FINAL_FIRST',
-    'JUMP/*d',
-    'FINISH/*d',
+    'JUMP/*d/N',
+    'FINISH/*d/N',
     '_FINAL_LAST',
 
-    'LABEL/*d',
+    'LABEL/*d/N',
 
     '_GUARD_FIRST',
     '_GUARD_FOLDABLE_FIRST',
-    'GUARD_TRUE/1d',
-    'GUARD_FALSE/1d',
-    'GUARD_VALUE/2d',
-    'GUARD_CLASS/2d',
-    'GUARD_NONNULL/1d',
-    'GUARD_ISNULL/1d',
-    'GUARD_NONNULL_CLASS/2d',
+    'GUARD_TRUE/1d/N',
+    'GUARD_FALSE/1d/N',
+    'GUARD_VALUE/2d/N',
+    'GUARD_CLASS/2d/N',
+    'GUARD_NONNULL/1d/N',
+    'GUARD_ISNULL/1d/N',
+    'GUARD_NONNULL_CLASS/2d/N',
     '_GUARD_FOLDABLE_LAST',
-    'GUARD_NO_EXCEPTION/0d',    # may be called with an exception currently set
-    'GUARD_EXCEPTION/1d',       # may be called with an exception currently set
-    'GUARD_NO_OVERFLOW/0d',
-    'GUARD_OVERFLOW/0d',
-    'GUARD_NOT_FORCED/0d',      # may be called with an exception currently set
-    'GUARD_NOT_INVALIDATED/0d',
+    'GUARD_NO_EXCEPTION/0d/N',   # may be called with an exception currently set
+    'GUARD_EXCEPTION/1d/N',      # may be called with an exception currently set
+    'GUARD_NO_OVERFLOW/0d/N',
+    'GUARD_OVERFLOW/0d/N',
+    'GUARD_NOT_FORCED/0d/N',     # may be called with an exception currently set
+    'GUARD_NOT_INVALIDATED/0d/N',
     '_GUARD_LAST', # ----- end of guard operations -----
 
     '_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations -----
     '_ALWAYS_PURE_FIRST', # ----- start of always_pure operations -----
-    'INT_ADD/2',
-    'INT_SUB/2',
-    'INT_MUL/2',
-    'INT_FLOORDIV/2',
-    'UINT_FLOORDIV/2',
-    'INT_MOD/2',
-    'INT_AND/2',
-    'INT_OR/2',
-    'INT_XOR/2',
-    'INT_RSHIFT/2',
-    'INT_LSHIFT/2',
-    'UINT_RSHIFT/2',
-    'FLOAT_ADD/2',
-    'FLOAT_SUB/2',
-    'FLOAT_MUL/2',
-    'FLOAT_TRUEDIV/2',
-    'FLOAT_NEG/1',
-    'FLOAT_ABS/1',
-    'CAST_FLOAT_TO_INT/1',          # don't use for unsigned ints; we would
-    'CAST_INT_TO_FLOAT/1',          # need some messy code in the backend
-    'CAST_FLOAT_TO_SINGLEFLOAT/1',
-    'CAST_SINGLEFLOAT_TO_FLOAT/1',
-    'CONVERT_FLOAT_BYTES_TO_LONGLONG/1',
-    'CONVERT_LONGLONG_BYTES_TO_FLOAT/1',
+    'INT_ADD/2/i',
+    'INT_SUB/2/i',
+    'INT_MUL/2/i',
+    'INT_FLOORDIV/2/i',
+    'UINT_FLOORDIV/2/i',
+    'INT_MOD/2/i',
+    'INT_AND/2/i',
+    'INT_OR/2/i',
+    'INT_XOR/2/i',
+    'INT_RSHIFT/2/i',
+    'INT_LSHIFT/2/i',
+    'UINT_RSHIFT/2/i',
+    'FLOAT_ADD/2/f',
+    'FLOAT_SUB/2/f',
+    'FLOAT_MUL/2/f',
+    'FLOAT_TRUEDIV/2/f',
+    'FLOAT_NEG/1/f',
+    'FLOAT_ABS/1/f',
+    'CAST_FLOAT_TO_INT/1/i',          # don't use for unsigned ints; we would
+    'CAST_INT_TO_FLOAT/1/f',          # need some messy code in the backend
+    'CAST_FLOAT_TO_SINGLEFLOAT/1/f',
+    'CAST_SINGLEFLOAT_TO_FLOAT/1/f',
+    'CONVERT_FLOAT_BYTES_TO_LONGLONG/1/f',
+    'CONVERT_LONGLONG_BYTES_TO_FLOAT/1/f',
     #
-    'INT_LT/2b',
-    'INT_LE/2b',
-    'INT_EQ/2b',
-    'INT_NE/2b',
-    'INT_GT/2b',
-    'INT_GE/2b',
-    'UINT_LT/2b',
-    'UINT_LE/2b',
-    'UINT_GT/2b',
-    'UINT_GE/2b',
-    'FLOAT_LT/2b',
-    'FLOAT_LE/2b',
-    'FLOAT_EQ/2b',
-    'FLOAT_NE/2b',
-    'FLOAT_GT/2b',
-    'FLOAT_GE/2b',
+    'INT_LT/2b/i',
+    'INT_LE/2b/i',
+    'INT_EQ/2b/i',
+    'INT_NE/2b/i',
+    'INT_GT/2b/i',
+    'INT_GE/2b/i',
+    'UINT_LT/2b/i',
+    'UINT_LE/2b/i',
+    'UINT_GT/2b/i',
+    'UINT_GE/2b/i',
+    'FLOAT_LT/2b/i',
+    'FLOAT_LE/2b/i',
+    'FLOAT_EQ/2b/i',
+    'FLOAT_NE/2b/i',
+    'FLOAT_GT/2b/i',
+    'FLOAT_GE/2b/i',
     #
-    'INT_IS_ZERO/1b',
-    'INT_IS_TRUE/1b',
-    'INT_NEG/1',
-    'INT_INVERT/1',
+    'INT_IS_ZERO/1b/i',
+    'INT_IS_TRUE/1b/i',
+    'INT_NEG/1/i',
+    'INT_INVERT/1/i',
     #
-    'SAME_AS/1',      # gets a Const or a Box, turns it into another Box
-    'CAST_PTR_TO_INT/1',
-    'CAST_INT_TO_PTR/1',
+    'SAME_AS/1/*',      # gets a Const or a Box, turns it into another Box
+    'CAST_PTR_TO_INT/1/i',
+    'CAST_INT_TO_PTR/1/p',
     #
-    'PTR_EQ/2b',
-    'PTR_NE/2b',
-    'INSTANCE_PTR_EQ/2b',
-    'INSTANCE_PTR_NE/2b',
+    'PTR_EQ/2b/i',
+    'PTR_NE/2b/i',
+    'INSTANCE_PTR_EQ/2b/i',
+    'INSTANCE_PTR_NE/2b/i',
     #
-    'ARRAYLEN_GC/1d',
-    'STRLEN/1',
-    'STRGETITEM/2',
-    'GETFIELD_GC_PURE/1d',
-    'GETFIELD_RAW_PURE/1d',
-    'GETARRAYITEM_GC_PURE/2d',
-    'UNICODELEN/1',
-    'UNICODEGETITEM/2',
+    'ARRAYLEN_GC/1d/i',
+    'STRLEN/1/i',
+    'STRGETITEM/2/i',
+    'GETFIELD_GC_PURE/1d/*',
+    'GETFIELD_RAW_PURE/1d/*',
+    'GETARRAYITEM_GC_PURE/2d/*',
+    'UNICODELEN/1/i',
+    'UNICODEGETITEM/2/i',
     #
     # ootype operations
     #'INSTANCEOF/1db',
@@ -468,64 +510,64 @@
     #
     '_ALWAYS_PURE_LAST',  # ----- end of always_pure operations -----
 
-    'GETARRAYITEM_GC/2d',
-    'GETARRAYITEM_RAW/2d',
-    'GETINTERIORFIELD_GC/2d',
-    'GETINTERIORFIELD_RAW/2d',
-    'GETFIELD_GC/1d',
-    'GETFIELD_RAW/1d',
+    'GETARRAYITEM_GC/2d/*',
+    'GETARRAYITEM_RAW/2d/*',
+    'GETINTERIORFIELD_GC/2d/*',
+    'GETINTERIORFIELD_RAW/2d/*',
+    'GETFIELD_GC/1d/*',
+    'GETFIELD_RAW/1d/*',
     '_MALLOC_FIRST',
-    'NEW/0d',
-    'NEW_WITH_VTABLE/1',
-    'NEW_ARRAY/1d',
-    'NEWSTR/1',
-    'NEWUNICODE/1',
+    'NEW/0d/p',
+    'NEW_WITH_VTABLE/1/p',
+    'NEW_ARRAY/1d/p',
+    'NEWSTR/1/p',
+    'NEWUNICODE/1/p',
     '_MALLOC_LAST',
-    'FORCE_TOKEN/0',
-    'VIRTUAL_REF/2',         # removed before it's passed to the backend
-    'READ_TIMESTAMP/0',
-    'MARK_OPAQUE_PTR/1b',
+    'FORCE_TOKEN/0/i',
+    'VIRTUAL_REF/2/i',         # removed before it's passed to the backend
+    'READ_TIMESTAMP/0/f',
+    'MARK_OPAQUE_PTR/1b/N',
     '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations -----
 
-    'SETARRAYITEM_GC/3d',
-    'SETARRAYITEM_RAW/3d',
-    'SETINTERIORFIELD_GC/3d',
-    'SETINTERIORFIELD_RAW/3d',
-    'SETFIELD_GC/2d',
-    'SETFIELD_RAW/2d',
-    'STRSETITEM/3',
-    'UNICODESETITEM/3',
+    'SETARRAYITEM_GC/3d/N',
+    'SETARRAYITEM_RAW/3d/N',
+    'SETINTERIORFIELD_GC/3d/N',
+    'SETINTERIORFIELD_RAW/3d/N',
+    'SETFIELD_GC/2d/N',
+    'SETFIELD_RAW/2d/N',
+    'STRSETITEM/3/N',
+    'UNICODESETITEM/3/N',
     #'RUNTIMENEW/1',     # ootype operation
-    'COND_CALL_GC_WB/2d', # [objptr, newvalue] (for the write barrier)
-    'COND_CALL_GC_WB_ARRAY/3d', # [objptr, arrayindex, newvalue] (write barr.)
-    'DEBUG_MERGE_POINT/*',      # debugging only
-    'JIT_DEBUG/*',              # debugging only
-    'VIRTUAL_REF_FINISH/2',   # removed before it's passed to the backend
-    'COPYSTRCONTENT/5',       # src, dst, srcstart, dststart, length
-    'COPYUNICODECONTENT/5',
-    'QUASIIMMUT_FIELD/1d',    # [objptr], descr=SlowMutateDescr
-    'RECORD_KNOWN_CLASS/2',   # [objptr, clsptr]
-    'KEEPALIVE/1',
+    'COND_CALL_GC_WB/2d/N', # [objptr, newvalue] (for the write barrier)
+    'COND_CALL_GC_WB_ARRAY/3d/N', # [objptr, arrayindex, newvalue] (write barr.)
+    'DEBUG_MERGE_POINT/*/N',      # debugging only
+    'JIT_DEBUG/*/N',              # debugging only
+    'VIRTUAL_REF_FINISH/2/N',   # removed before it's passed to the backend
+    'COPYSTRCONTENT/5/N',       # src, dst, srcstart, dststart, length
+    'COPYUNICODECONTENT/5/N',
+    'QUASIIMMUT_FIELD/1d/N',    # [objptr], descr=SlowMutateDescr
+    'RECORD_KNOWN_CLASS/2/N',   # [objptr, clsptr]
+    'KEEPALIVE/1/N',
 
     '_CANRAISE_FIRST', # ----- start of can_raise operations -----
     '_CALL_FIRST',
-    'CALL/*d',
-    'CALL_ASSEMBLER/*d',  # call already compiled assembler
-    'CALL_MAY_FORCE/*d',
-    'CALL_LOOPINVARIANT/*d',
-    'CALL_RELEASE_GIL/*d',  # release the GIL and "close the stack" for asmgcc
+    'CALL/*d/*',
+    'CALL_ASSEMBLER/*d/*',  # call already compiled assembler
+    'CALL_MAY_FORCE/*d/*',
+    'CALL_LOOPINVARIANT/*d/*',
+    'CALL_RELEASE_GIL/*d/*',  # release the GIL and "close the stack" for asmgcc
     #'OOSEND',                     # ootype operation
     #'OOSEND_PURE',                # ootype operation
-    'CALL_PURE/*d',             # removed before it's passed to the backend
-    'CALL_MALLOC_GC/*d',      # like CALL, but NULL => propagate MemoryError
-    'CALL_MALLOC_NURSERY/1',  # nursery malloc, const number of bytes, zeroed
+    'CALL_PURE/*d/*',             # removed before it's passed to the backend
+    'CALL_MALLOC_GC/*d/*',      # like CALL, but NULL => propagate MemoryError
+    'CALL_MALLOC_NURSERY/1/*',  # nursery malloc, const number of bytes, zeroed
     '_CALL_LAST',
     '_CANRAISE_LAST', # ----- end of can_raise operations -----
 
     '_OVF_FIRST', # ----- start of is_ovf operations -----
-    'INT_ADD_OVF/2',
-    'INT_SUB_OVF/2',
-    'INT_MUL_OVF/2',
+    'INT_ADD_OVF/2/i',
+    'INT_SUB_OVF/2/i',
+    'INT_MUL_OVF/2/i',
     '_OVF_LAST', # ----- end of is_ovf operations -----
     '_LAST',     # for the backend to add more internal operations
 ]
@@ -543,11 +585,10 @@
 
 
 def setup(debug_print=False):
-    for i, name in enumerate(_oplist):
-        if debug_print:
-            print '%30s = %d' % (name, i)
-        if '/' in name:
-            name, arity = name.split('/')
+    i = 0
+    for basename in _oplist:
+        if '/' in basename:
+            basename, arity, tp = basename.split('/')
             withdescr = 'd' in arity
             boolresult = 'b' in arity
             arity = arity.rstrip('db')
@@ -556,38 +597,51 @@
             else:
                 arity = int(arity)
         else:
-            arity, withdescr, boolresult = -1, True, False       # default
-        setattr(rop, name, i)
-        if not name.startswith('_'):
+            arity, withdescr, boolresult, tp = -1, True, False, "N"  # default
+        if not basename.startswith('_'):
+            clss = create_classes_for_op(basename, i, arity, withdescr, tp)
+        else:
+            clss = []
+            setattr(rop, basename, i)
+        for cls, name in clss:
+            if debug_print:
+                print '%30s = %d' % (name, i)
             opname[i] = name
-            cls = create_class_for_op(name, i, arity, withdescr)
-        else:
-            cls = None
-        opclasses.append(cls)
-        oparity.append(arity)
-        opwithdescr.append(withdescr)
-        opboolresult.append(boolresult)
-    assert len(opclasses)==len(oparity)==len(opwithdescr)==len(opboolresult)==len(_oplist)
+            setattr(rop, name, i)
+            i += 1
+            opclasses.append(cls)
+            oparity.append(arity)
+            opwithdescr.append(withdescr)
+            opboolresult.append(boolresult)
+            assert (len(opclasses)==len(oparity)==len(opwithdescr)
+                    ==len(opboolresult))
 
-def get_base_class(mixin, base):
+def get_base_class(mixin, tpmixin, base):
     try:
-        return get_base_class.cache[(mixin, base)]
+        return get_base_class.cache[(mixin, tpmixin, base)]
     except KeyError:
         arity_name = mixin.__name__[:-2]  # remove the trailing "Op"
-        name = arity_name + base.__name__ # something like BinaryPlainResOp
-        bases = (mixin, base)
+        name = arity_name + base.__name__ + tpmixin.__name__[5:]
+        # something like BinaryPlainResOpInt
+        bases = (mixin, tpmixin, base)
         cls = type(name, bases, {})
-        get_base_class.cache[(mixin, base)] = cls
+        get_base_class.cache[(mixin, tpmixin, base)] = cls
         return cls
 get_base_class.cache = {}
 
-def create_class_for_op(name, opnum, arity, withdescr):
+def create_classes_for_op(name, opnum, arity, withdescr, tp):
     arity2mixin = {
         0: NullaryOp,
         1: UnaryOp,
         2: BinaryOp,
         3: TernaryOp
         }
+    tpmixin = {
+        'N': ResOpNone,
+        'i': ResOpInt,
+        'f': ResOpFloat,
+        'p': ResOpPointer,
+    }
 
     is_guard = name.startswith('GUARD')
     if is_guard:
@@ -599,10 +653,20 @@
         baseclass = PlainResOp
     mixin = arity2mixin.get(arity, N_aryOp)
 
-    cls_name = '%s_OP' % name
-    bases = (get_base_class(mixin, baseclass),)
-    dic = {'opnum': opnum}
-    return type(cls_name, bases, dic)
+    if tp == '*':
+        res = []
+        for tp in ['f', 'p', 'i']:
+            cls_name = '%s_OP_%s' % (name, tp)
+            bases = (get_base_class(mixin, tpmixin[tp], baseclass),)
+            dic = {'opnum': opnum}
+            res.append((type(cls_name, bases, dic), name + '_' + tp))
+            opnum += 1
+        return res   
+    else:
+        cls_name = '%s_OP' % name
+        bases = (get_base_class(mixin, tpmixin[tp], baseclass),)
+        dic = {'opnum': opnum}
+        return [(type(cls_name, bases, dic), name)]
 
 setup(__name__ == '__main__')   # print out the table when run directly
 del _oplist
diff --git a/pypy/jit/metainterp/test/test_resoperation.py b/pypy/jit/metainterp/test/test_resoperation.py
--- a/pypy/jit/metainterp/test/test_resoperation.py
+++ b/pypy/jit/metainterp/test/test_resoperation.py
@@ -32,10 +32,10 @@
     assert issubclass(cls, rop.BinaryOp)
     assert cls.getopnum.im_func(cls) == rop.rop.INT_ADD
 
-    cls = rop.opclasses[rop.rop.CALL]
+    cls = rop.opclasses[rop.rop.CALL_i]
     assert issubclass(cls, rop.ResOpWithDescr)
     assert issubclass(cls, rop.N_aryOp)
-    assert cls.getopnum.im_func(cls) == rop.rop.CALL
+    assert cls.getopnum.im_func(cls) == rop.rop.CALL_i
 
     cls = rop.opclasses[rop.rop.GUARD_TRUE]
     assert issubclass(cls, rop.GuardResOp)
@@ -46,31 +46,43 @@
     INT_ADD = rop.opclasses[rop.rop.INT_ADD]
     assert len(INT_ADD.__bases__) == 1
     BinaryPlainResOp = INT_ADD.__bases__[0]
-    assert BinaryPlainResOp.__name__ == 'BinaryPlainResOp'
-    assert BinaryPlainResOp.__bases__ == (rop.BinaryOp, rop.PlainResOp)
+    assert BinaryPlainResOp.__name__ == 'BinaryPlainResOpInt'
+    assert BinaryPlainResOp.__bases__ == (rop.BinaryOp, rop.ResOpInt,
+                                          rop.PlainResOp)
     INT_SUB = rop.opclasses[rop.rop.INT_SUB]
     assert INT_SUB.__bases__[0] is BinaryPlainResOp
 
 def test_instantiate():
-    op = rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c')
+    from pypy.rpython.lltypesystem import lltype, llmemory
+    
+    op = rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 15)
     assert op.getarglist() == ['a', 'b']
-    assert op.result == 'c'
+    assert op.getint() == 15
 
     mydescr = AbstractDescr()
-    op = rop.ResOperation(rop.rop.CALL, ['a', 'b'], 'c', descr=mydescr)
+    op = rop.ResOperation(rop.rop.CALL_f, ['a', 'b'], 15.5, descr=mydescr)
     assert op.getarglist() == ['a', 'b']
-    assert op.result == 'c'
+    assert op.getfloat() == 15.5
     assert op.getdescr() is mydescr
 
+    op = rop.ResOperation(rop.rop.CALL_p, ['a', 'b'],
+                          lltype.nullptr(llmemory.GCREF.TO), descr=mydescr)
+    assert op.getarglist() == ['a', 'b']
+    assert not op.getpointer()
+    assert op.getdescr() is mydescr    
+
 def test_can_malloc():
+    from pypy.rpython.lltypesystem import lltype, llmemory
+
     mydescr = AbstractDescr()
-    assert rop.ResOperation(rop.rop.NEW, [], 'b').can_malloc()
-    call = rop.ResOperation(rop.rop.CALL, ['a', 'b'], 'c', descr=mydescr)
+    p = lltype.malloc(llmemory.GCREF.TO)
+    assert rop.ResOperation(rop.rop.NEW, [], p).can_malloc()
+    call = rop.ResOperation(rop.rop.CALL_i, ['a', 'b'], 3, descr=mydescr)
     assert call.can_malloc()
-    assert not rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c').can_malloc()
+    assert not rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 3).can_malloc()
 
 def test_get_deep_immutable_oplist():
-    ops = [rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c')]
+    ops = [rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 3)]
     newops = rop.get_deep_immutable_oplist(ops)
     py.test.raises(TypeError, "newops.append('foobar')")
     py.test.raises(TypeError, "newops[0] = 'foobar'")


More information about the pypy-commit mailing list