[pypy-commit] pypy virtual-dicts: merged default

alex_gaynor noreply at buildbot.pypy.org
Wed Oct 26 21:07:46 CEST 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: virtual-dicts
Changeset: r48484:5e5b44d30598
Date: 2011-10-26 14:18 -0400
http://bitbucket.org/pypy/pypy/changeset/5e5b44d30598/

Log:	merged default

diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -17,6 +17,12 @@
 projects, or anything else in PyPy, pop up on IRC or write to us on the
 `mailing list`_.
 
+Make big integers faster
+-------------------------
+
+PyPy's implementation of the Python ``long`` type is slower than CPython's.
+Find out why and optimize them.
+
 Numpy improvements
 ------------------
 
diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -178,6 +178,8 @@
         cur_max_age = -1
         candidate = None
         for next in self.reg_bindings:
+            if isinstance(next, TempBox):
+                continue
             reg = self.reg_bindings[next]
             if next in forbidden_vars:
                 continue
diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py
--- a/pypy/jit/backend/llsupport/test/test_gc.py
+++ b/pypy/jit/backend/llsupport/test/test_gc.py
@@ -250,10 +250,11 @@
                                   has_finalizer, has_light_finalizer,
                                   contains_weakptr):
         assert not contains_weakptr
+        assert not has_finalizer           # in these tests
+        assert not has_light_finalizer     # in these tests
         p = llmemory.raw_malloc(size)
         p = llmemory.cast_adr_to_ptr(p, RESTYPE)
-        flags = (int(has_finalizer) << 16) | (int(has_light_finalizer) << 17)
-        tid = llop.combine_ushort(lltype.Signed, type_id, flags)
+        tid = llop.combine_ushort(lltype.Signed, type_id, 0)
         self.record.append(("fixedsize", repr(size), tid, p))
         return p
 
diff --git a/pypy/jit/backend/test/test_ll_random.py b/pypy/jit/backend/test/test_ll_random.py
--- a/pypy/jit/backend/test/test_ll_random.py
+++ b/pypy/jit/backend/test/test_ll_random.py
@@ -28,16 +28,27 @@
         fork.structure_types_and_vtables = self.structure_types_and_vtables
         return fork
 
-    def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct):
+    def _choose_ptr_vars(self, from_, type, array_of_structs):
+        ptrvars = []
+        for i in range(len(from_)):
+            v, S = from_[i][:2]
+            if not isinstance(S, type):
+                continue
+            if ((isinstance(S, lltype.Array) and
+                 isinstance(S.OF, lltype.Struct)) == array_of_structs):
+                ptrvars.append((v, S))
+        return ptrvars
+
+    def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct,
+                          array_of_structs=False):
         while True:
-            ptrvars = [(v, S) for (v, S) in self.ptrvars
-                              if isinstance(S, type)]
+            ptrvars = self._choose_ptr_vars(self.ptrvars, type,
+                                            array_of_structs)
             if ptrvars and r.random() < 0.8:
                 v, S = r.choice(ptrvars)
             else:
-                prebuilt_ptr_consts = [(v, S)
-                                 for (v, S, _) in self.prebuilt_ptr_consts
-                                 if isinstance(S, type)]
+                prebuilt_ptr_consts = self._choose_ptr_vars(
+                    self.prebuilt_ptr_consts, type, array_of_structs)
                 if prebuilt_ptr_consts and r.random() < 0.7:
                     v, S = r.choice(prebuilt_ptr_consts)
                 else:
@@ -48,7 +59,8 @@
                                                 has_vtable=must_have_vtable)
                     else:
                         # create a new constant array
-                        p = self.get_random_array(r)
+                        p = self.get_random_array(r,
+                                    must_be_array_of_structs=array_of_structs)
                     S = lltype.typeOf(p).TO
                     v = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, p))
                     self.prebuilt_ptr_consts.append((v, S,
@@ -74,7 +86,8 @@
                 TYPE = lltype.Signed
         return TYPE
 
-    def get_random_structure_type(self, r, with_vtable=None, cache=True):
+    def get_random_structure_type(self, r, with_vtable=None, cache=True,
+                                  type=lltype.GcStruct):
         if cache and self.structure_types and r.random() < 0.5:
             return r.choice(self.structure_types)
         fields = []
@@ -85,7 +98,7 @@
         for i in range(r.randrange(1, 5)):
             TYPE = self.get_random_primitive_type(r)
             fields.append(('f%d' % i, TYPE))
-        S = lltype.GcStruct('S%d' % self.counter, *fields, **kwds)
+        S = type('S%d' % self.counter, *fields, **kwds)
         self.counter += 1
         if cache:
             self.structure_types.append(S)
@@ -125,17 +138,29 @@
                 setattr(p, fieldname, rffi.cast(TYPE, r.random_integer()))
         return p
 
-    def get_random_array_type(self, r):
-        TYPE = self.get_random_primitive_type(r)
+    def get_random_array_type(self, r, can_be_array_of_struct=False,
+                              must_be_array_of_structs=False):
+        if ((can_be_array_of_struct and r.random() < 0.1) or
+            must_be_array_of_structs):
+            TYPE = self.get_random_structure_type(r, cache=False,
+                                                  type=lltype.Struct)
+        else:
+            TYPE = self.get_random_primitive_type(r)
         return lltype.GcArray(TYPE)
 
-    def get_random_array(self, r):
-        A = self.get_random_array_type(r)
+    def get_random_array(self, r, must_be_array_of_structs=False):
+        A = self.get_random_array_type(r,
+                           must_be_array_of_structs=must_be_array_of_structs)
         length = (r.random_integer() // 15) % 300  # length: between 0 and 299
                                                    # likely to be small
         p = lltype.malloc(A, length)
-        for i in range(length):
-            p[i] = rffi.cast(A.OF, r.random_integer())
+        if isinstance(A.OF, lltype.Primitive):
+            for i in range(length):
+                p[i] = rffi.cast(A.OF, r.random_integer())
+        else:
+            for i in range(length):
+                for fname, TP in A.OF._flds.iteritems():
+                    setattr(p[i], fname, rffi.cast(TP, r.random_integer()))
         return p
 
     def get_index(self, length, r):
@@ -155,8 +180,16 @@
                     dic[fieldname] = getattr(p, fieldname)
         else:
             assert isinstance(S, lltype.Array)
-            for i in range(len(p)):
-                dic[i] = p[i]
+            if isinstance(S.OF, lltype.Struct):
+                for i in range(len(p)):
+                    item = p[i]
+                    s1 = {}
+                    for fieldname in S.OF._names:
+                        s1[fieldname] = getattr(item, fieldname)
+                    dic[i] = s1
+            else:
+                for i in range(len(p)):
+                    dic[i] = p[i]
         return dic
 
     def print_loop_prebuilt(self, names, writevar, s):
@@ -220,7 +253,7 @@
 
 class GetFieldOperation(test_random.AbstractOperation):
     def field_descr(self, builder, r):
-        v, S = builder.get_structptr_var(r)
+        v, S = builder.get_structptr_var(r, )
         names = S._names
         if names[0] == 'parent':
             names = names[1:]
@@ -239,6 +272,28 @@
                 continue
             break
 
+class GetInteriorFieldOperation(test_random.AbstractOperation):
+    def field_descr(self, builder, r):
+        v, A = builder.get_structptr_var(r, type=lltype.Array,
+                                         array_of_structs=True)
+        array = v.getref(lltype.Ptr(A))
+        v_index = builder.get_index(len(array), r)
+        name = r.choice(A.OF._names)
+        descr = builder.cpu.interiorfielddescrof(A, name)
+        descr._random_info = 'cpu.interiorfielddescrof(%s, %r)' % (A.OF._name,
+                                                                   name)
+        TYPE = getattr(A.OF, name)
+        return v, v_index, descr, TYPE
+
+    def produce_into(self, builder, r):
+        while True:
+            try:
+                v, v_index, descr, _ = self.field_descr(builder, r)
+                self.put(builder, [v, v_index], descr)
+            except lltype.UninitializedMemoryAccess:
+                continue
+            break
+
 class SetFieldOperation(GetFieldOperation):
     def produce_into(self, builder, r):
         v, descr, TYPE = self.field_descr(builder, r)
@@ -251,6 +306,18 @@
                 break
         builder.do(self.opnum, [v, w], descr)
 
+class SetInteriorFieldOperation(GetInteriorFieldOperation):
+    def produce_into(self, builder, r):
+        v, v_index, descr, TYPE = self.field_descr(builder, r)
+        while True:
+            if r.random() < 0.3:
+                w = ConstInt(r.random_integer())
+            else:
+                w = r.choice(builder.intvars)
+            if rffi.cast(lltype.Signed, rffi.cast(TYPE, w.value)) == w.value:
+                break
+        builder.do(self.opnum, [v, v_index, w], descr)
+
 class NewOperation(test_random.AbstractOperation):
     def size_descr(self, builder, S):
         descr = builder.cpu.sizeof(S)
@@ -306,7 +373,7 @@
 
 class NewArrayOperation(ArrayOperation):
     def produce_into(self, builder, r):
-        A = builder.get_random_array_type(r)
+        A = builder.get_random_array_type(r, can_be_array_of_struct=True)
         v_size = builder.get_index(300, r)
         v_ptr = builder.do(self.opnum, [v_size], self.array_descr(builder, A))
         builder.ptrvars.append((v_ptr, A))
@@ -586,7 +653,9 @@
 for i in range(4):      # make more common
     OPERATIONS.append(GetFieldOperation(rop.GETFIELD_GC))
     OPERATIONS.append(GetFieldOperation(rop.GETFIELD_GC))
+    OPERATIONS.append(GetInteriorFieldOperation(rop.GETINTERIORFIELD_GC))
     OPERATIONS.append(SetFieldOperation(rop.SETFIELD_GC))
+    OPERATIONS.append(SetInteriorFieldOperation(rop.SETINTERIORFIELD_GC))
     OPERATIONS.append(NewOperation(rop.NEW))
     OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE))
 
diff --git a/pypy/jit/backend/test/test_random.py b/pypy/jit/backend/test/test_random.py
--- a/pypy/jit/backend/test/test_random.py
+++ b/pypy/jit/backend/test/test_random.py
@@ -595,6 +595,10 @@
             for name, value in fields.items():
                 if isinstance(name, str):
                     setattr(container, name, value)
+                elif isinstance(value, dict):
+                    item = container.getitem(name)
+                    for key1, value1 in value.items():
+                        setattr(item, key1, value1)
                 else:
                     container.setitem(name, value)
 
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1613,7 +1613,10 @@
     def genop_discard_setinteriorfield_gc(self, op, arglocs):
         base_loc, ofs_loc, itemsize_loc, fieldsize_loc, index_loc, value_loc = arglocs
         # XXX should not use IMUL in most cases
-        self.mc.IMUL(index_loc, itemsize_loc)
+        if isinstance(index_loc, ImmedLoc):
+            index_loc = imm(index_loc.value * itemsize_loc.value)
+        else:
+            self.mc.IMUL(index_loc, itemsize_loc)
         dest_addr = AddressLoc(base_loc, index_loc, 0, ofs_loc.value)
         self.save_into_mem(dest_addr, value_loc, fieldsize_loc)
 
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -1042,14 +1042,18 @@
         t = self._unpack_interiorfielddescr(op.getdescr())
         ofs, itemsize, fieldsize, _ = t
         args = op.getarglist()
-        tmpvar = TempBox()
+        if fieldsize.value == 1:
+            need_lower_byte = True
+        else:
+            need_lower_byte = False
         base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
-        index_loc = self.rm.force_result_in_reg(tmpvar, op.getarg(1),
-                                                args)
+        tempvar = TempBox()
+        index_loc = self.rm.force_result_in_reg(tempvar, op.getarg(1), args)
         # we're free to modify index now
-        value_loc = self.make_sure_var_in_reg(op.getarg(2), args)
+        value_loc = self.make_sure_var_in_reg(op.getarg(2), args,
+                                              need_lower_byte=need_lower_byte)
+        self.rm.possibly_free_var(tempvar)
         self.possibly_free_vars(args)
-        self.rm.possibly_free_var(tmpvar)
         self.PerformDiscard(op, [base_loc, ofs, itemsize, fieldsize,
                                  index_loc, value_loc])
 
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -16,7 +16,8 @@
         if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
                        'imp', 'sys', 'array', '_ffi', 'itertools', 'operator',
                        'posix', '_socket', '_sre', '_lsprof', '_weakref',
-                       '__pypy__', 'cStringIO', '_collections', 'struct']:
+                       '__pypy__', 'cStringIO', '_collections', 'struct',
+                       'mmap']:
             return True
         return False
 
diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -245,6 +245,9 @@
 if sys.platform != 'win32':
     @unwrap_spec(secs=float)
     def sleep(space, secs):
+        if secs < 0:
+            raise OperationError(space.w_IOError,
+                                 space.wrap("Invalid argument: negative time in sleep"))
         pytime.sleep(secs)
 else:
     from pypy.rlib import rwin32
@@ -265,6 +268,9 @@
                                    OSError(EINTR, "sleep() interrupted"))
     @unwrap_spec(secs=float)
     def sleep(space, secs):
+        if secs < 0:
+            raise OperationError(space.w_IOError,
+                                 space.wrap("Invalid argument: negative time in sleep"))
         # as decreed by Guido, only the main thread can be
         # interrupted.
         main_thread = space.fromcache(State).main_thread
diff --git a/pypy/module/rctime/test/test_rctime.py b/pypy/module/rctime/test/test_rctime.py
--- a/pypy/module/rctime/test/test_rctime.py
+++ b/pypy/module/rctime/test/test_rctime.py
@@ -20,8 +20,9 @@
         import sys
         import os
         raises(TypeError, rctime.sleep, "foo")
-        rctime.sleep(1.2345)
-        
+        rctime.sleep(0.12345)
+        raises(IOError, rctime.sleep, -1.0)
+
     def test_clock(self):
         import time as rctime
         rctime.clock()
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -83,11 +83,12 @@
         if self.config.objspace.std.withtproxy:
             transparent.setup(self)
 
+        interplevel_classes = {}
         for type, classes in self.model.typeorder.iteritems():
-            if len(classes) >= 3:
+            if len(classes) >= 3: # XXX what does this 3 mean??!
                 # W_Root, AnyXxx and actual object
-                self.gettypefor(type).interplevel_cls = classes[0][0]
-
+                interplevel_classes[self.gettypefor(type)] = classes[0][0]
+        self._interplevel_classes = interplevel_classes
 
     def get_builtin_types(self):
         return self.builtin_types
@@ -579,7 +580,7 @@
             raise OperationError(self.w_TypeError,
                                  self.wrap("need type object"))
         if is_annotation_constant(w_type):
-            cls = w_type.interplevel_cls
+            cls = self._get_interplevel_cls(w_type)
             if cls is not None:
                 assert w_inst is not None
                 if isinstance(w_inst, cls):
@@ -589,3 +590,9 @@
     @specialize.arg_or_var(2)
     def isinstance_w(space, w_inst, w_type):
         return space._type_isinstance(w_inst, w_type)
+
+    @specialize.memo()
+    def _get_interplevel_cls(self, w_type):
+        if not hasattr(self, "_interplevel_classes"):
+            return None # before running initialize
+        return self._interplevel_classes.get(w_type, None)
diff --git a/pypy/objspace/std/smallintobject.py b/pypy/objspace/std/smallintobject.py
--- a/pypy/objspace/std/smallintobject.py
+++ b/pypy/objspace/std/smallintobject.py
@@ -12,6 +12,7 @@
 from pypy.rlib.rbigint import rbigint
 from pypy.rlib.rarithmetic import r_uint
 from pypy.tool.sourcetools import func_with_new_name
+from pypy.objspace.std.inttype import wrapint
 
 class W_SmallIntObject(W_Object, UnboxedValue):
     __slots__ = 'intval'
@@ -48,14 +49,36 @@
 def delegate_SmallInt2Complex(space, w_small):
     return space.newcomplex(float(w_small.intval), 0.0)
 
+def add__SmallInt_SmallInt(space, w_a, w_b):
+    return wrapint(space, w_a.intval + w_b.intval) # cannot overflow
+
+def sub__SmallInt_SmallInt(space, w_a, w_b):
+    return wrapint(space, w_a.intval - w_b.intval) # cannot overflow
+
+def floordiv__SmallInt_SmallInt(space, w_a, w_b):
+    return wrapint(space, w_a.intval // w_b.intval) # cannot overflow
+
+div__SmallInt_SmallInt = floordiv__SmallInt_SmallInt
+
+def mod__SmallInt_SmallInt(space, w_a, w_b):
+    return wrapint(space, w_a.intval % w_b.intval) # cannot overflow
+
+def divmod__SmallInt_SmallInt(space, w_a, w_b):
+    w = wrapint(space, w_a.intval // w_b.intval) # cannot overflow
+    z = wrapint(space, w_a.intval % w_b.intval)
+    return space.newtuple([w, z])
+
 def copy_multimethods(ns):
     """Copy integer multimethods for small int."""
     for name, func in intobject.__dict__.iteritems():
         if "__Int" in name:
             new_name = name.replace("Int", "SmallInt")
-            # Copy the function, so the annotator specializes it for
-            # W_SmallIntObject.
-            ns[new_name] = func_with_new_name(func, new_name)
+            if new_name not in ns:
+                # Copy the function, so the annotator specializes it for
+                # W_SmallIntObject.
+                ns[new_name] = func = func_with_new_name(func, new_name, globals=ns)
+        else:
+            ns[name] = func
     ns["get_integer"] = ns["pos__SmallInt"] = ns["int__SmallInt"]
     ns["get_negint"] = ns["neg__SmallInt"]
 
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -102,3 +102,11 @@
             def __repr__(self):
                 return 123456
         assert A().__str__() == 123456
+
+def test_isinstance_shortcut():
+    from pypy.objspace.std import objspace
+    space = objspace.StdObjSpace()
+    w_a = space.wrap("a")
+    space.type = None
+    space.isinstance_w(w_a, space.w_str) # does not crash
+
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -102,7 +102,6 @@
                           'instancetypedef',
                           'terminator',
                           '_version_tag?',
-                          'interplevel_cls',
                           ]
 
     # for config.objspace.std.getattributeshortcut
@@ -117,9 +116,6 @@
     # of the __new__ is an instance of the type
     w_bltin_new = None
 
-    interplevel_cls = None # not None for prebuilt instances of
-                           # interpreter-level types
-
     @dont_look_inside
     def __init__(w_self, space, name, bases_w, dict_w,
                  overridetypedef=None):
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -1713,6 +1713,7 @@
         return v
 
     def setitem(self, index, value):
+        assert typeOf(value) == self._TYPE.OF
         self.items[index] = value
 
 assert not '__dict__' in dir(_array)
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -959,8 +959,6 @@
                             os_ftruncate(rffi.cast(rffi.INT, fd),
                                          rffi.cast(rffi.LONGLONG, length)))
             if res < 0:
-                # Note: for consistency we raise OSError, but CPython
-                # raises IOError here
                 raise OSError(rposix.get_errno(), "os_ftruncate failed")
 
         return extdef([int, r_longlong], s_None,
diff --git a/pypy/tool/sourcetools.py b/pypy/tool/sourcetools.py
--- a/pypy/tool/sourcetools.py
+++ b/pypy/tool/sourcetools.py
@@ -216,9 +216,11 @@
 
 # ____________________________________________________________
 
-def func_with_new_name(func, newname):
+def func_with_new_name(func, newname, globals=None):
     """Make a renamed copy of a function."""
-    f = new.function(func.func_code, func.func_globals,
+    if globals is None:
+        globals = func.func_globals
+    f = new.function(func.func_code, globals,
                         newname, func.func_defaults,
                         func.func_closure)
     if func.func_dict:
diff --git a/pypy/translator/c/primitive.py b/pypy/translator/c/primitive.py
--- a/pypy/translator/c/primitive.py
+++ b/pypy/translator/c/primitive.py
@@ -144,14 +144,19 @@
         obj = value._obj
         if isinstance(obj, int):
             # a tagged pointer
-            assert obj & 1 == 1
-            return '((%s) %d)' % (cdecl("void*", ''), obj)
+            return _name_tagged(obj, db)
         realobj = obj.container
+        if isinstance(realobj, int):
+            return _name_tagged(realobj, db)
         realvalue = cast_opaque_ptr(Ptr(typeOf(realobj)), value)
         return db.get(realvalue)
     else:
         return 'NULL'
 
+def _name_tagged(obj, db):
+    assert obj & 1 == 1
+    return '((%s) %d)' % (cdecl("void*", ''), obj)
+
 def name_small_integer(value, db):
     """Works for integers of size at most INT or UINT."""
     if isinstance(value, Symbolic):
diff --git a/pypy/translator/c/test/test_rtagged.py b/pypy/translator/c/test/test_rtagged.py
--- a/pypy/translator/c/test/test_rtagged.py
+++ b/pypy/translator/c/test/test_rtagged.py
@@ -77,3 +77,12 @@
     data = g.read()
     g.close()
     assert data.rstrip().endswith('ALL OK')
+
+def test_name_gcref():
+    from pypy.rpython.lltypesystem import lltype, llmemory, rclass
+    from pypy.translator.c import primitive
+    from pypy.translator.c.database import LowLevelDatabase
+    x = lltype.cast_int_to_ptr(rclass.OBJECTPTR, 19)
+    y = lltype.cast_opaque_ptr(llmemory.GCREF, x)
+    db = LowLevelDatabase()
+    assert primitive.name_gcref(y, db) == "((void*) 19)"


More information about the pypy-commit mailing list