[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