[pypy-commit] pypy reflex-support: merge default into branch
wlav
noreply at buildbot.pypy.org
Thu Mar 1 09:07:34 CET 2012
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r53036:3847eddabfa1
Date: 2012-02-28 10:35 -0800
http://bitbucket.org/pypy/pypy/changeset/3847eddabfa1/
Log: merge default into branch
diff --git a/lib-python/modified-2.7/ctypes/test/test_arrays.py b/lib-python/modified-2.7/ctypes/test/test_arrays.py
--- a/lib-python/modified-2.7/ctypes/test/test_arrays.py
+++ b/lib-python/modified-2.7/ctypes/test/test_arrays.py
@@ -1,12 +1,23 @@
import unittest
from ctypes import *
+from test.test_support import impl_detail
formats = "bBhHiIlLqQfd"
+# c_longdouble commented out for PyPy, look at the commend in test_longdouble
formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
- c_long, c_ulonglong, c_float, c_double, c_longdouble
+ c_long, c_ulonglong, c_float, c_double #, c_longdouble
class ArrayTestCase(unittest.TestCase):
+
+ @impl_detail('long double not supported by PyPy', pypy=False)
+ def test_longdouble(self):
+ """
+ This test is empty. It's just here to remind that we commented out
+ c_longdouble in "formats". If pypy will ever supports c_longdouble, we
+ should kill this test and uncomment c_longdouble inside formats.
+ """
+
def test_simple(self):
# create classes holding simple numeric types, and check
# various properties.
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -13,7 +13,7 @@
and not p.basename.startswith('test')]
essential_modules = dict.fromkeys(
- ["exceptions", "_file", "sys", "__builtin__", "posix"]
+ ["exceptions", "_file", "sys", "__builtin__", "posix", "_warnings"]
)
default_modules = essential_modules.copy()
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1471,8 +1471,8 @@
def warn(self, msg, w_warningcls):
self.appexec([self.wrap(msg), w_warningcls], """(msg, warningcls):
- import warnings
- warnings.warn(msg, warningcls, stacklevel=2)
+ import _warnings
+ _warnings.warn(msg, warningcls, stacklevel=2)
""")
def resolve_target(self, w_obj):
diff --git a/pypy/interpreter/pyparser/parsestring.py b/pypy/interpreter/pyparser/parsestring.py
--- a/pypy/interpreter/pyparser/parsestring.py
+++ b/pypy/interpreter/pyparser/parsestring.py
@@ -1,5 +1,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import unicodehelper
+from pypy.rlib.rstring import StringBuilder
def parsestr(space, encoding, s, unicode_literals=False):
# compiler.transformer.Transformer.decode_literal depends on what
@@ -115,21 +116,23 @@
the string is UTF-8 encoded and should be re-encoded in the
specified encoding.
"""
- lis = []
+ builder = StringBuilder(len(s))
ps = 0
end = len(s)
- while ps < end:
- if s[ps] != '\\':
- # note that the C code has a label here.
- # the logic is the same.
+ while 1:
+ ps2 = ps
+ while ps < end and s[ps] != '\\':
if recode_encoding and ord(s[ps]) & 0x80:
w, ps = decode_utf8(space, s, ps, end, recode_encoding)
- # Append bytes to output buffer.
- lis.append(w)
+ builder.append(w)
+ ps2 = ps
else:
- lis.append(s[ps])
ps += 1
- continue
+ if ps > ps2:
+ builder.append_slice(s, ps2, ps)
+ if ps == end:
+ break
+
ps += 1
if ps == end:
raise_app_valueerror(space, 'Trailing \\ in string')
@@ -140,25 +143,25 @@
if ch == '\n':
pass
elif ch == '\\':
- lis.append('\\')
+ builder.append('\\')
elif ch == "'":
- lis.append("'")
+ builder.append("'")
elif ch == '"':
- lis.append('"')
+ builder.append('"')
elif ch == 'b':
- lis.append("\010")
+ builder.append("\010")
elif ch == 'f':
- lis.append('\014') # FF
+ builder.append('\014') # FF
elif ch == 't':
- lis.append('\t')
+ builder.append('\t')
elif ch == 'n':
- lis.append('\n')
+ builder.append('\n')
elif ch == 'r':
- lis.append('\r')
+ builder.append('\r')
elif ch == 'v':
- lis.append('\013') # VT
+ builder.append('\013') # VT
elif ch == 'a':
- lis.append('\007') # BEL, not classic C
+ builder.append('\007') # BEL, not classic C
elif ch in '01234567':
# Look for up to two more octal digits
span = ps
@@ -168,13 +171,13 @@
# emulate a strange wrap-around behavior of CPython:
# \400 is the same as \000 because 0400 == 256
num = int(octal, 8) & 0xFF
- lis.append(chr(num))
+ builder.append(chr(num))
ps = span
elif ch == 'x':
if ps+2 <= end and isxdigit(s[ps]) and isxdigit(s[ps + 1]):
hexa = s[ps : ps + 2]
num = int(hexa, 16)
- lis.append(chr(num))
+ builder.append(chr(num))
ps += 2
else:
raise_app_valueerror(space, 'invalid \\x escape')
@@ -184,13 +187,13 @@
# this was not an escape, so the backslash
# has to be added, and we start over in
# non-escape mode.
- lis.append('\\')
+ builder.append('\\')
ps -= 1
assert ps >= 0
continue
# an arbitry number of unescaped UTF-8 bytes may follow.
- buf = ''.join(lis)
+ buf = builder.build()
return buf
diff --git a/pypy/interpreter/streamutil.py b/pypy/interpreter/streamutil.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/streamutil.py
@@ -0,0 +1,17 @@
+from pypy.rlib.streamio import StreamError
+from pypy.interpreter.error import OperationError, wrap_oserror2
+
+def wrap_streamerror(space, e, w_filename=None):
+ if isinstance(e, StreamError):
+ return OperationError(space.w_ValueError,
+ space.wrap(e.message))
+ elif isinstance(e, OSError):
+ return wrap_oserror_as_ioerror(space, e, w_filename)
+ else:
+ # should not happen: wrap_streamerror() is only called when
+ # StreamErrors = (OSError, StreamError) are raised
+ return OperationError(space.w_IOError, space.w_None)
+
+def wrap_oserror_as_ioerror(space, e, w_filename=None):
+ return wrap_oserror2(space, e, w_filename,
+ w_exception_class=space.w_IOError)
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -769,11 +769,19 @@
self.generate_function('malloc_unicode', malloc_unicode,
[lltype.Signed])
- # Rarely called: allocate a fixed-size amount of bytes, but
- # not in the nursery, because it is too big. Implemented like
- # malloc_nursery_slowpath() above.
- self.generate_function('malloc_fixedsize', malloc_nursery_slowpath,
- [lltype.Signed])
+ # Never called as far as I can tell, but there for completeness:
+ # allocate a fixed-size object, but not in the nursery, because
+ # it is too big.
+ def malloc_big_fixedsize(size, tid):
+ if self.DEBUG:
+ self._random_usage_of_xmm_registers()
+ type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
+ check_typeid(type_id)
+ return llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
+ type_id, size,
+ False, False, False)
+ self.generate_function('malloc_big_fixedsize', malloc_big_fixedsize,
+ [lltype.Signed] * 2)
def _bh_malloc(self, sizedescr):
from pypy.rpython.memory.gctypelayout import check_typeid
diff --git a/pypy/jit/backend/llsupport/rewrite.py b/pypy/jit/backend/llsupport/rewrite.py
--- a/pypy/jit/backend/llsupport/rewrite.py
+++ b/pypy/jit/backend/llsupport/rewrite.py
@@ -96,8 +96,10 @@
def handle_new_fixedsize(self, descr, op):
assert isinstance(descr, SizeDescr)
size = descr.size
- self.gen_malloc_nursery(size, op.result)
- self.gen_initialize_tid(op.result, descr.tid)
+ if self.gen_malloc_nursery(size, op.result):
+ self.gen_initialize_tid(op.result, descr.tid)
+ else:
+ self.gen_malloc_fixedsize(size, descr.tid, op.result)
def handle_new_array(self, arraydescr, op):
v_length = op.getarg(0)
@@ -112,8 +114,8 @@
pass # total_size is still -1
elif arraydescr.itemsize == 0:
total_size = arraydescr.basesize
- if 0 <= total_size <= 0xffffff: # up to 16MB, arbitrarily
- self.gen_malloc_nursery(total_size, op.result)
+ if (total_size >= 0 and
+ self.gen_malloc_nursery(total_size, op.result)):
self.gen_initialize_tid(op.result, arraydescr.tid)
self.gen_initialize_len(op.result, v_length, arraydescr.lendescr)
elif self.gc_ll_descr.kind == 'boehm':
@@ -147,13 +149,22 @@
# mark 'v_result' as freshly malloced
self.recent_mallocs[v_result] = None
- def gen_malloc_fixedsize(self, size, v_result):
- """Generate a CALL_MALLOC_GC(malloc_fixedsize_fn, Const(size)).
- Note that with the framework GC, this should be called very rarely.
+ def gen_malloc_fixedsize(self, size, typeid, v_result):
+ """Generate a CALL_MALLOC_GC(malloc_fixedsize_fn, ...).
+ Used on Boehm, and on the framework GC for large fixed-size
+ mallocs. (For all I know this latter case never occurs in
+ practice, but better safe than sorry.)
"""
- addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_fixedsize')
- self._gen_call_malloc_gc([ConstInt(addr), ConstInt(size)], v_result,
- self.gc_ll_descr.malloc_fixedsize_descr)
+ if self.gc_ll_descr.fielddescr_tid is not None: # framework GC
+ assert (size & (WORD-1)) == 0, "size not aligned?"
+ addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_big_fixedsize')
+ args = [ConstInt(addr), ConstInt(size), ConstInt(typeid)]
+ descr = self.gc_ll_descr.malloc_big_fixedsize_descr
+ else: # Boehm
+ addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_fixedsize')
+ args = [ConstInt(addr), ConstInt(size)]
+ descr = self.gc_ll_descr.malloc_fixedsize_descr
+ self._gen_call_malloc_gc(args, v_result, descr)
def gen_boehm_malloc_array(self, arraydescr, v_num_elem, v_result):
"""Generate a CALL_MALLOC_GC(malloc_array_fn, ...) for Boehm."""
@@ -211,8 +222,7 @@
"""
size = self.round_up_for_allocation(size)
if not self.gc_ll_descr.can_use_nursery_malloc(size):
- self.gen_malloc_fixedsize(size, v_result)
- return
+ return False
#
op = None
if self._op_malloc_nursery is not None:
@@ -238,6 +248,7 @@
self._previous_size = size
self._v_last_malloced_nursery = v_result
self.recent_mallocs[v_result] = None
+ return True
def gen_initialize_tid(self, v_newgcobj, tid):
if self.gc_ll_descr.fielddescr_tid is not None:
diff --git a/pypy/jit/backend/llsupport/test/test_rewrite.py b/pypy/jit/backend/llsupport/test/test_rewrite.py
--- a/pypy/jit/backend/llsupport/test/test_rewrite.py
+++ b/pypy/jit/backend/llsupport/test/test_rewrite.py
@@ -119,12 +119,19 @@
jump()
""", """
[]
- p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
- %(adescr.basesize + 10 * adescr.itemsize)d, \
- descr=malloc_fixedsize_descr)
- setfield_gc(p0, 10, descr=alendescr)
+ p0 = call_malloc_gc(ConstClass(malloc_array), \
+ %(adescr.basesize)d, \
+ 10, \
+ %(adescr.itemsize)d, \
+ %(adescr.lendescr.offset)d, \
+ descr=malloc_array_descr)
jump()
""")
+## should ideally be:
+## p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
+## %(adescr.basesize + 10 * adescr.itemsize)d, \
+## descr=malloc_fixedsize_descr)
+## setfield_gc(p0, 10, descr=alendescr)
def test_new_array_variable(self):
self.check_rewrite("""
@@ -178,13 +185,20 @@
jump()
""", """
[i1]
- p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
- %(unicodedescr.basesize + \
- 10 * unicodedescr.itemsize)d, \
- descr=malloc_fixedsize_descr)
- setfield_gc(p0, 10, descr=unicodelendescr)
+ p0 = call_malloc_gc(ConstClass(malloc_array), \
+ %(unicodedescr.basesize)d, \
+ 10, \
+ %(unicodedescr.itemsize)d, \
+ %(unicodelendescr.offset)d, \
+ descr=malloc_array_descr)
jump()
""")
+## should ideally be:
+## p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
+## %(unicodedescr.basesize + \
+## 10 * unicodedescr.itemsize)d, \
+## descr=malloc_fixedsize_descr)
+## setfield_gc(p0, 10, descr=unicodelendescr)
class TestFramework(RewriteTests):
@@ -203,7 +217,7 @@
#
class FakeCPU(object):
def sizeof(self, STRUCT):
- descr = SizeDescrWithVTable(102)
+ descr = SizeDescrWithVTable(104)
descr.tid = 9315
return descr
self.cpu = FakeCPU()
@@ -368,11 +382,9 @@
jump()
""", """
[]
- p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
- %(bdescr.basesize + 104)d, \
- descr=malloc_fixedsize_descr)
- setfield_gc(p0, 8765, descr=tiddescr)
- setfield_gc(p0, 103, descr=blendescr)
+ p0 = call_malloc_gc(ConstClass(malloc_array), 1, \
+ %(bdescr.tid)d, 103, \
+ descr=malloc_array_descr)
jump()
""")
@@ -435,9 +447,8 @@
jump()
""", """
[p1]
- p0 = call_malloc_gc(ConstClass(malloc_fixedsize), 104, \
- descr=malloc_fixedsize_descr)
- setfield_gc(p0, 9315, descr=tiddescr)
+ p0 = call_malloc_gc(ConstClass(malloc_big_fixedsize), 104, 9315, \
+ descr=malloc_big_fixedsize_descr)
setfield_gc(p0, ConstClass(o_vtable), descr=vtable_descr)
jump()
""")
diff --git a/pypy/jit/backend/x86/test/test_gc_integration.py b/pypy/jit/backend/x86/test/test_gc_integration.py
--- a/pypy/jit/backend/x86/test/test_gc_integration.py
+++ b/pypy/jit/backend/x86/test/test_gc_integration.py
@@ -184,6 +184,8 @@
self.addrs[1] = self.addrs[0] + 64
self.calls = []
def malloc_slowpath(size):
+ if self.gcrootmap is not None: # hook
+ self.gcrootmap.hook_malloc_slowpath()
self.calls.append(size)
# reset the nursery
nadr = rffi.cast(lltype.Signed, self.nursery)
@@ -257,3 +259,218 @@
assert gc_ll_descr.addrs[0] == nurs_adr + 24
# this should call slow path once
assert gc_ll_descr.calls == [24]
+
+ def test_save_regs_around_malloc(self):
+ S1 = lltype.GcStruct('S1')
+ S2 = lltype.GcStruct('S2', ('s0', lltype.Ptr(S1)),
+ ('s1', lltype.Ptr(S1)),
+ ('s2', lltype.Ptr(S1)),
+ ('s3', lltype.Ptr(S1)),
+ ('s4', lltype.Ptr(S1)),
+ ('s5', lltype.Ptr(S1)),
+ ('s6', lltype.Ptr(S1)),
+ ('s7', lltype.Ptr(S1)),
+ ('s8', lltype.Ptr(S1)),
+ ('s9', lltype.Ptr(S1)),
+ ('s10', lltype.Ptr(S1)),
+ ('s11', lltype.Ptr(S1)),
+ ('s12', lltype.Ptr(S1)),
+ ('s13', lltype.Ptr(S1)),
+ ('s14', lltype.Ptr(S1)),
+ ('s15', lltype.Ptr(S1)))
+ cpu = self.cpu
+ self.namespace = self.namespace.copy()
+ for i in range(16):
+ self.namespace['ds%i' % i] = cpu.fielddescrof(S2, 's%d' % i)
+ ops = '''
+ [p0]
+ p1 = getfield_gc(p0, descr=ds0)
+ p2 = getfield_gc(p0, descr=ds1)
+ p3 = getfield_gc(p0, descr=ds2)
+ p4 = getfield_gc(p0, descr=ds3)
+ p5 = getfield_gc(p0, descr=ds4)
+ p6 = getfield_gc(p0, descr=ds5)
+ p7 = getfield_gc(p0, descr=ds6)
+ p8 = getfield_gc(p0, descr=ds7)
+ p9 = getfield_gc(p0, descr=ds8)
+ p10 = getfield_gc(p0, descr=ds9)
+ p11 = getfield_gc(p0, descr=ds10)
+ p12 = getfield_gc(p0, descr=ds11)
+ p13 = getfield_gc(p0, descr=ds12)
+ p14 = getfield_gc(p0, descr=ds13)
+ p15 = getfield_gc(p0, descr=ds14)
+ p16 = getfield_gc(p0, descr=ds15)
+ #
+ # now all registers are in use
+ p17 = call_malloc_nursery(40)
+ p18 = call_malloc_nursery(40) # overflow
+ #
+ finish(p1, p2, p3, p4, p5, p6, p7, p8, \
+ p9, p10, p11, p12, p13, p14, p15, p16)
+ '''
+ s2 = lltype.malloc(S2)
+ for i in range(16):
+ setattr(s2, 's%d' % i, lltype.malloc(S1))
+ s2ref = lltype.cast_opaque_ptr(llmemory.GCREF, s2)
+ #
+ self.interpret(ops, [s2ref])
+ gc_ll_descr = cpu.gc_ll_descr
+ gc_ll_descr.check_nothing_in_nursery()
+ assert gc_ll_descr.calls == [40]
+ # check the returned pointers
+ for i in range(16):
+ s1ref = self.cpu.get_latest_value_ref(i)
+ s1 = lltype.cast_opaque_ptr(lltype.Ptr(S1), s1ref)
+ assert s1 == getattr(s2, 's%d' % i)
+
+
+class MockShadowStackRootMap(MockGcRootMap):
+ is_shadow_stack = True
+ MARKER_FRAME = 88 # this marker follows the frame addr
+ S1 = lltype.GcStruct('S1')
+
+ def __init__(self):
+ self.addrs = lltype.malloc(rffi.CArray(lltype.Signed), 20,
+ flavor='raw')
+ # root_stack_top
+ self.addrs[0] = rffi.cast(lltype.Signed, self.addrs) + 3*WORD
+ # random stuff
+ self.addrs[1] = 123456
+ self.addrs[2] = 654321
+ self.check_initial_and_final_state()
+ self.callshapes = {}
+ self.should_see = []
+
+ def check_initial_and_final_state(self):
+ assert self.addrs[0] == rffi.cast(lltype.Signed, self.addrs) + 3*WORD
+ assert self.addrs[1] == 123456
+ assert self.addrs[2] == 654321
+
+ def get_root_stack_top_addr(self):
+ return rffi.cast(lltype.Signed, self.addrs)
+
+ def compress_callshape(self, shape, datablockwrapper):
+ assert shape[0] == 'shape'
+ return ['compressed'] + shape[1:]
+
+ def write_callshape(self, mark, force_index):
+ assert mark[0] == 'compressed'
+ assert force_index not in self.callshapes
+ assert force_index == 42 + len(self.callshapes)
+ self.callshapes[force_index] = mark
+
+ def hook_malloc_slowpath(self):
+ num_entries = self.addrs[0] - rffi.cast(lltype.Signed, self.addrs)
+ assert num_entries == 5*WORD # 3 initially, plus 2 by the asm frame
+ assert self.addrs[1] == 123456 # unchanged
+ assert self.addrs[2] == 654321 # unchanged
+ frame_addr = self.addrs[3] # pushed by the asm frame
+ assert self.addrs[4] == self.MARKER_FRAME # pushed by the asm frame
+ #
+ from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS
+ addr = rffi.cast(rffi.CArrayPtr(lltype.Signed),
+ frame_addr + FORCE_INDEX_OFS)
+ force_index = addr[0]
+ assert force_index == 43 # in this test: the 2nd call_malloc_nursery
+ #
+ # The callshapes[43] saved above should list addresses both in the
+ # COPY_AREA and in the "normal" stack, where all the 16 values p1-p16
+ # of test_save_regs_at_correct_place should have been stored. Here
+ # we replace them with new addresses, to emulate a moving GC.
+ shape = self.callshapes[force_index]
+ assert len(shape[1:]) == len(self.should_see)
+ new_objects = [None] * len(self.should_see)
+ for ofs in shape[1:]:
+ assert isinstance(ofs, int) # not a register at all here
+ addr = rffi.cast(rffi.CArrayPtr(lltype.Signed), frame_addr + ofs)
+ contains = addr[0]
+ for j in range(len(self.should_see)):
+ obj = self.should_see[j]
+ if contains == rffi.cast(lltype.Signed, obj):
+ assert new_objects[j] is None # duplicate?
+ break
+ else:
+ assert 0 # the value read from the stack looks random?
+ new_objects[j] = lltype.malloc(self.S1)
+ addr[0] = rffi.cast(lltype.Signed, new_objects[j])
+ self.should_see[:] = new_objects
+
+
+class TestMallocShadowStack(BaseTestRegalloc):
+
+ def setup_method(self, method):
+ cpu = CPU(None, None)
+ cpu.gc_ll_descr = GCDescrFastpathMalloc()
+ cpu.gc_ll_descr.gcrootmap = MockShadowStackRootMap()
+ cpu.setup_once()
+ for i in range(42):
+ cpu.reserve_some_free_fail_descr_number()
+ self.cpu = cpu
+
+ def test_save_regs_at_correct_place(self):
+ cpu = self.cpu
+ gc_ll_descr = cpu.gc_ll_descr
+ S1 = gc_ll_descr.gcrootmap.S1
+ S2 = lltype.GcStruct('S2', ('s0', lltype.Ptr(S1)),
+ ('s1', lltype.Ptr(S1)),
+ ('s2', lltype.Ptr(S1)),
+ ('s3', lltype.Ptr(S1)),
+ ('s4', lltype.Ptr(S1)),
+ ('s5', lltype.Ptr(S1)),
+ ('s6', lltype.Ptr(S1)),
+ ('s7', lltype.Ptr(S1)),
+ ('s8', lltype.Ptr(S1)),
+ ('s9', lltype.Ptr(S1)),
+ ('s10', lltype.Ptr(S1)),
+ ('s11', lltype.Ptr(S1)),
+ ('s12', lltype.Ptr(S1)),
+ ('s13', lltype.Ptr(S1)),
+ ('s14', lltype.Ptr(S1)),
+ ('s15', lltype.Ptr(S1)))
+ self.namespace = self.namespace.copy()
+ for i in range(16):
+ self.namespace['ds%i' % i] = cpu.fielddescrof(S2, 's%d' % i)
+ ops = '''
+ [p0]
+ p1 = getfield_gc(p0, descr=ds0)
+ p2 = getfield_gc(p0, descr=ds1)
+ p3 = getfield_gc(p0, descr=ds2)
+ p4 = getfield_gc(p0, descr=ds3)
+ p5 = getfield_gc(p0, descr=ds4)
+ p6 = getfield_gc(p0, descr=ds5)
+ p7 = getfield_gc(p0, descr=ds6)
+ p8 = getfield_gc(p0, descr=ds7)
+ p9 = getfield_gc(p0, descr=ds8)
+ p10 = getfield_gc(p0, descr=ds9)
+ p11 = getfield_gc(p0, descr=ds10)
+ p12 = getfield_gc(p0, descr=ds11)
+ p13 = getfield_gc(p0, descr=ds12)
+ p14 = getfield_gc(p0, descr=ds13)
+ p15 = getfield_gc(p0, descr=ds14)
+ p16 = getfield_gc(p0, descr=ds15)
+ #
+ # now all registers are in use
+ p17 = call_malloc_nursery(40)
+ p18 = call_malloc_nursery(40) # overflow
+ #
+ finish(p1, p2, p3, p4, p5, p6, p7, p8, \
+ p9, p10, p11, p12, p13, p14, p15, p16)
+ '''
+ s2 = lltype.malloc(S2)
+ for i in range(16):
+ s1 = lltype.malloc(S1)
+ setattr(s2, 's%d' % i, s1)
+ gc_ll_descr.gcrootmap.should_see.append(s1)
+ s2ref = lltype.cast_opaque_ptr(llmemory.GCREF, s2)
+ #
+ self.interpret(ops, [s2ref])
+ gc_ll_descr.check_nothing_in_nursery()
+ assert gc_ll_descr.calls == [40]
+ gc_ll_descr.gcrootmap.check_initial_and_final_state()
+ # check the returned pointers
+ for i in range(16):
+ s1ref = self.cpu.get_latest_value_ref(i)
+ s1 = lltype.cast_opaque_ptr(lltype.Ptr(S1), s1ref)
+ for j in range(16):
+ assert s1 != getattr(s2, 's%d' % j)
+ assert s1 == gc_ll_descr.gcrootmap.should_see[i]
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -289,8 +289,21 @@
assert isinstance(token, TargetToken)
assert token.original_jitcell_token is None
token.original_jitcell_token = trace.original_jitcell_token
-
-
+
+
+def do_compile_loop(metainterp_sd, inputargs, operations, looptoken,
+ log=True, name=''):
+ 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)
+
+def do_compile_bridge(metainterp_sd, faildescr, inputargs, operations,
+ original_loop_token, log=True):
+ metainterp_sd.logger_ops.log_bridge(inputargs, operations, -2)
+ return metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations,
+ original_loop_token, log=log)
+
def send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, type):
vinfo = jitdriver_sd.virtualizable_info
if vinfo is not None:
@@ -319,9 +332,9 @@
metainterp_sd.profiler.start_backend()
debug_start("jit-backend")
try:
- asminfo = metainterp_sd.cpu.compile_loop(loop.inputargs, operations,
- original_jitcell_token,
- name=loopname)
+ asminfo = do_compile_loop(metainterp_sd, loop.inputargs,
+ operations, original_jitcell_token,
+ name=loopname)
finally:
debug_stop("jit-backend")
metainterp_sd.profiler.end_backend()
@@ -333,7 +346,6 @@
metainterp_sd.stats.compiled()
metainterp_sd.log("compiled new " + type)
#
- loopname = jitdriver_sd.warmstate.get_location_str(greenkey)
if asminfo is not None:
ops_offset = asminfo.ops_offset
else:
@@ -365,9 +377,9 @@
metainterp_sd.profiler.start_backend()
debug_start("jit-backend")
try:
- asminfo = metainterp_sd.cpu.compile_bridge(faildescr, inputargs,
- operations,
- original_loop_token)
+ asminfo = do_compile_bridge(metainterp_sd, faildescr, inputargs,
+ operations,
+ original_loop_token)
finally:
debug_stop("jit-backend")
metainterp_sd.profiler.end_backend()
diff --git a/pypy/jit/metainterp/logger.py b/pypy/jit/metainterp/logger.py
--- a/pypy/jit/metainterp/logger.py
+++ b/pypy/jit/metainterp/logger.py
@@ -18,6 +18,10 @@
debug_start("jit-log-noopt-loop")
logops = self._log_operations(inputargs, operations, ops_offset)
debug_stop("jit-log-noopt-loop")
+ elif number == -2:
+ debug_start("jit-log-compiling-loop")
+ logops = self._log_operations(inputargs, operations, ops_offset)
+ debug_stop("jit-log-compiling-loop")
else:
debug_start("jit-log-opt-loop")
debug_print("# Loop", number, '(%s)' % name , ":", type,
@@ -31,6 +35,10 @@
debug_start("jit-log-noopt-bridge")
logops = self._log_operations(inputargs, operations, ops_offset)
debug_stop("jit-log-noopt-bridge")
+ elif number == -2:
+ debug_start("jit-log-compiling-bridge")
+ logops = self._log_operations(inputargs, operations, ops_offset)
+ debug_stop("jit-log-compiling-bridge")
else:
debug_start("jit-log-opt-bridge")
debug_print("# bridge out of Guard", number,
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py b/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
@@ -398,6 +398,50 @@
with raises(InvalidLoop):
self.optimize_loop(ops, ops)
+ def test_maybe_issue1045_related(self):
+ ops = """
+ [p8]
+ p54 = getfield_gc(p8, descr=valuedescr)
+ mark_opaque_ptr(p54)
+ i55 = getfield_gc(p54, descr=nextdescr)
+ p57 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p57, i55, descr=otherdescr)
+ p69 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p69, i55, descr=otherdescr)
+ i71 = int_eq(i55, -9223372036854775808)
+ guard_false(i71) []
+ i73 = int_mod(i55, 2)
+ i75 = int_rshift(i73, 63)
+ i76 = int_and(2, i75)
+ i77 = int_add(i73, i76)
+ p79 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p79, i77, descr=otherdescr)
+ i81 = int_eq(i77, 1)
+ guard_false(i81) []
+ i0 = int_ge(i55, 1)
+ guard_true(i0) []
+ label(p57)
+ jump(p57)
+ """
+ expected = """
+ [p8]
+ p54 = getfield_gc(p8, descr=valuedescr)
+ i55 = getfield_gc(p54, descr=nextdescr)
+ i71 = int_eq(i55, -9223372036854775808)
+ guard_false(i71) []
+ i73 = int_mod(i55, 2)
+ i75 = int_rshift(i73, 63)
+ i76 = int_and(2, i75)
+ i77 = int_add(i73, i76)
+ i81 = int_eq(i77, 1)
+ guard_false(i81) []
+ i0 = int_ge(i55, 1)
+ guard_true(i0) []
+ label(i55)
+ jump(i55)
+ """
+ self.optimize_loop(ops, expected)
+
class OptRenameStrlen(Optimization):
def propagate_forward(self, op):
dispatch_opt(self, op)
@@ -457,7 +501,6 @@
jump(p1, i11)
"""
self.optimize_loop(ops, expected)
-
class TestLLtype(OptimizeoptTestMultiLabel, LLtypeMixin):
diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py b/pypy/jit/metainterp/test/test_quasiimmut.py
--- a/pypy/jit/metainterp/test/test_quasiimmut.py
+++ b/pypy/jit/metainterp/test/test_quasiimmut.py
@@ -8,7 +8,7 @@
from pypy.jit.metainterp.quasiimmut import get_current_qmut_instance
from pypy.jit.metainterp.test.support import LLJitMixin
from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.rlib.jit import JitDriver, dont_look_inside
+from pypy.rlib.jit import JitDriver, dont_look_inside, unroll_safe
def test_get_current_qmut_instance():
@@ -480,6 +480,32 @@
assert res == 1
self.check_jitcell_token_count(2)
+ def test_for_loop_array(self):
+ myjitdriver = JitDriver(greens=[], reds=["n", "i"])
+ class Foo(object):
+ _immutable_fields_ = ["x?[*]"]
+ def __init__(self, x):
+ self.x = x
+ f = Foo([1, 3, 5, 6])
+ @unroll_safe
+ def g(v):
+ for x in f.x:
+ if x & 1 == 0:
+ v += 1
+ return v
+ def main(n):
+ i = 0
+ while i < n:
+ myjitdriver.jit_merge_point(n=n, i=i)
+ i = g(i)
+ return i
+ res = self.meta_interp(main, [10])
+ assert res == 10
+ self.check_resops({
+ "int_add": 2, "int_lt": 2, "jump": 1, "guard_true": 2,
+ "guard_not_invalidated": 2
+ })
+
class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin):
pass
diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -5,14 +5,13 @@
from pypy.rlib import streamio
from pypy.rlib.rarithmetic import r_longlong
from pypy.rlib.rstring import StringBuilder
-from pypy.module._file.interp_stream import (W_AbstractStream, StreamErrors,
- wrap_streamerror, wrap_oserror_as_ioerror)
+from pypy.module._file.interp_stream import W_AbstractStream, StreamErrors
from pypy.module.posix.interp_posix import dispatch_filename
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
interp_attrproperty, make_weakref_descr, interp_attrproperty_w)
from pypy.interpreter.gateway import interp2app, unwrap_spec
-
+from pypy.interpreter.streamutil import wrap_streamerror, wrap_oserror_as_ioerror
class W_File(W_AbstractStream):
"""An interp-level file object. This implements the same interface than
diff --git a/pypy/module/_file/interp_stream.py b/pypy/module/_file/interp_stream.py
--- a/pypy/module/_file/interp_stream.py
+++ b/pypy/module/_file/interp_stream.py
@@ -2,27 +2,13 @@
from pypy.rlib import streamio
from pypy.rlib.streamio import StreamErrors
-from pypy.interpreter.error import OperationError, wrap_oserror2
+from pypy.interpreter.error import OperationError
from pypy.interpreter.baseobjspace import ObjSpace, Wrappable
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.streamutil import wrap_streamerror, wrap_oserror_as_ioerror
-def wrap_streamerror(space, e, w_filename=None):
- if isinstance(e, streamio.StreamError):
- return OperationError(space.w_ValueError,
- space.wrap(e.message))
- elif isinstance(e, OSError):
- return wrap_oserror_as_ioerror(space, e, w_filename)
- else:
- # should not happen: wrap_streamerror() is only called when
- # StreamErrors = (OSError, StreamError) are raised
- return OperationError(space.w_IOError, space.w_None)
-
-def wrap_oserror_as_ioerror(space, e, w_filename=None):
- return wrap_oserror2(space, e, w_filename,
- w_exception_class=space.w_IOError)
-
class W_AbstractStream(Wrappable):
"""Base class for interp-level objects that expose streams to app-level"""
slock = None
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -56,6 +56,8 @@
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
+#define _Py_ForgetReference(ob) /* nothing */
+
#define Py_None (&_Py_NoneStruct)
/*
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -1,10 +1,11 @@
from pypy.module.imp import importing
from pypy.module._file.interp_file import W_File
from pypy.rlib import streamio
+from pypy.rlib.streamio import StreamErrors
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.module import Module
from pypy.interpreter.gateway import unwrap_spec
-from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror
+from pypy.interpreter.streamutil import wrap_streamerror
def get_suffixes(space):
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -357,7 +357,7 @@
def test_cannot_write_pyc(self):
import sys, os
- p = os.path.join(sys.path[-1], 'readonly')
+ p = os.path.join(sys.path[0], 'readonly')
try:
os.chmod(p, 0555)
except:
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -779,8 +779,6 @@
"""
Intermediate class for performing binary operations.
"""
- _immutable_fields_ = ['left', 'right']
-
def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, left, right):
VirtualArray.__init__(self, name, shape, res_dtype)
self.ufunc = ufunc
@@ -856,8 +854,6 @@
self.right.create_sig(), done_func)
class AxisReduce(Call2):
- _immutable_fields_ = ['left', 'right']
-
def __init__(self, ufunc, name, identity, shape, dtype, left, right, dim):
Call2.__init__(self, ufunc, name, shape, dtype, dtype,
left, right)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -60,6 +60,9 @@
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = pipe.communicate()
+ if getattr(pipe, 'returncode', 0) < 0:
+ raise IOError("subprocess was killed by signal %d" % (
+ pipe.returncode,))
if stderr.startswith('SKIP:'):
py.test.skip(stderr)
if stderr.startswith('debug_alloc.h:'): # lldebug builds
diff --git a/pypy/module/pypyjit/test_pypy_c/test_alloc.py b/pypy/module/pypyjit/test_pypy_c/test_alloc.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_alloc.py
@@ -0,0 +1,26 @@
+import py, sys
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+class TestAlloc(BaseTestPyPyC):
+
+ SIZES = dict.fromkeys([2 ** n for n in range(26)] + # up to 32MB
+ [2 ** n - 1 for n in range(26)])
+
+ def test_newstr_constant_size(self):
+ for size in TestAlloc.SIZES:
+ yield self.newstr_constant_size, size
+
+ def newstr_constant_size(self, size):
+ src = """if 1:
+ N = %(size)d
+ part_a = 'a' * N
+ part_b = 'b' * N
+ for i in xrange(20):
+ ao = '%%s%%s' %% (part_a, part_b)
+ def main():
+ return 42
+""" % {'size': size}
+ log = self.run(src, [], threshold=10)
+ assert log.result == 42
+ loop, = log.loops_by_filename(self.filepath)
+ # assert did not crash
diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py b/pypy/module/pypyjit/test_pypy_c/test_instance.py
--- a/pypy/module/pypyjit/test_pypy_c/test_instance.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py
@@ -201,3 +201,28 @@
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id("compare", "") # optimized away
+ def test_super(self):
+ def main():
+ class A(object):
+ def m(self, x):
+ return x + 1
+ class B(A):
+ def m(self, x):
+ return super(B, self).m(x)
+ i = 0
+ while i < 300:
+ i = B().m(i)
+ return i
+
+ log = self.run(main, [])
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match("""
+ i78 = int_lt(i72, 300)
+ guard_true(i78, descr=...)
+ guard_not_invalidated(descr=...)
+ i79 = force_token()
+ i80 = force_token()
+ i81 = int_add(i72, 1)
+ --TICK--
+ jump(..., descr=...)
+ """)
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
@@ -103,6 +103,7 @@
'terminator',
'_version_tag?',
'name?',
+ 'mro_w?[*]',
]
# for config.objspace.std.getattributeshortcut
@@ -345,9 +346,9 @@
return w_self._lookup_where(name)
+ @unroll_safe
def lookup_starting_at(w_self, w_starttype, name):
space = w_self.space
- # XXX Optimize this with method cache
look = False
for w_class in w_self.mro_w:
if w_class is w_starttype:
diff --git a/pypy/rpython/lltypesystem/rlist.py b/pypy/rpython/lltypesystem/rlist.py
--- a/pypy/rpython/lltypesystem/rlist.py
+++ b/pypy/rpython/lltypesystem/rlist.py
@@ -392,7 +392,11 @@
('list', r_list.lowleveltype),
('index', Signed)))
self.ll_listiter = ll_listiter
- self.ll_listnext = ll_listnext
+ if (isinstance(r_list, FixedSizeListRepr)
+ and not r_list.listitem.mutated):
+ self.ll_listnext = ll_listnext_foldable
+ else:
+ self.ll_listnext = ll_listnext
self.ll_getnextindex = ll_getnextindex
def ll_listiter(ITERPTR, lst):
@@ -409,5 +413,14 @@
iter.index = index + 1 # cannot overflow because index < l.length
return l.ll_getitem_fast(index)
+def ll_listnext_foldable(iter):
+ from pypy.rpython.rlist import ll_getitem_foldable_nonneg
+ l = iter.list
+ index = iter.index
+ if index >= l.ll_length():
+ raise StopIteration
+ iter.index = index + 1 # cannot overflow because index < l.length
+ return ll_getitem_foldable_nonneg(l, index)
+
def ll_getnextindex(iter):
return iter.index
diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -608,6 +608,11 @@
specified as 0 if the object is not varsized. The returned
object is fully initialized and zero-filled."""
#
+ # Here we really need a valid 'typeid', not 0 (as the JIT might
+ # try to send us if there is still a bug).
+ ll_assert(bool(self.combine(typeid, 0)),
+ "external_malloc: typeid == 0")
+ #
# Compute the total size, carefully checking for overflows.
size_gc_header = self.gcheaderbuilder.size_gc_header
nonvarsize = size_gc_header + self.fixed_size(typeid)
diff --git a/pypy/rpython/test/test_rlist.py b/pypy/rpython/test/test_rlist.py
--- a/pypy/rpython/test/test_rlist.py
+++ b/pypy/rpython/test/test_rlist.py
@@ -8,6 +8,7 @@
from pypy.rpython.rlist import *
from pypy.rpython.lltypesystem.rlist import ListRepr, FixedSizeListRepr, ll_newlist, ll_fixed_newlist
from pypy.rpython.lltypesystem import rlist as ll_rlist
+from pypy.rpython.llinterp import LLException
from pypy.rpython.ootypesystem import rlist as oo_rlist
from pypy.rpython.rint import signed_repr
from pypy.objspace.flow.model import Constant, Variable
@@ -1477,6 +1478,80 @@
assert func1.oopspec == 'list.getitem_foldable(l, index)'
assert not hasattr(func2, 'oopspec')
+ def test_iterate_over_immutable_list(self):
+ from pypy.rpython import rlist
+ class MyException(Exception):
+ pass
+ lst = list('abcdef')
+ def dummyfn():
+ total = 0
+ for c in lst:
+ total += ord(c)
+ return total
+ #
+ prev = rlist.ll_getitem_foldable_nonneg
+ try:
+ def seen_ok(l, index):
+ if index == 5:
+ raise KeyError # expected case
+ return prev(l, index)
+ rlist.ll_getitem_foldable_nonneg = seen_ok
+ e = raises(LLException, self.interpret, dummyfn, [])
+ assert 'KeyError' in str(e.value)
+ finally:
+ rlist.ll_getitem_foldable_nonneg = prev
+
+ def test_iterate_over_immutable_list_quasiimmut_attr(self):
+ from pypy.rpython import rlist
+ class MyException(Exception):
+ pass
+ class Foo:
+ _immutable_fields_ = ['lst?[*]']
+ lst = list('abcdef')
+ foo = Foo()
+ def dummyfn():
+ total = 0
+ for c in foo.lst:
+ total += ord(c)
+ return total
+ #
+ prev = rlist.ll_getitem_foldable_nonneg
+ try:
+ def seen_ok(l, index):
+ if index == 5:
+ raise KeyError # expected case
+ return prev(l, index)
+ rlist.ll_getitem_foldable_nonneg = seen_ok
+ e = raises(LLException, self.interpret, dummyfn, [])
+ assert 'KeyError' in str(e.value)
+ finally:
+ rlist.ll_getitem_foldable_nonneg = prev
+
+ def test_iterate_over_mutable_list(self):
+ from pypy.rpython import rlist
+ class MyException(Exception):
+ pass
+ lst = list('abcdef')
+ def dummyfn():
+ total = 0
+ for c in lst:
+ total += ord(c)
+ lst[0] = 'x'
+ return total
+ #
+ prev = rlist.ll_getitem_foldable_nonneg
+ try:
+ def seen_ok(l, index):
+ if index == 5:
+ raise KeyError # expected case
+ return prev(l, index)
+ rlist.ll_getitem_foldable_nonneg = seen_ok
+ res = self.interpret(dummyfn, [])
+ assert res == sum(map(ord, 'abcdef'))
+ finally:
+ rlist.ll_getitem_foldable_nonneg = prev
+
+
class TestOOtype(BaseTestRlist, OORtypeMixin):
rlist = oo_rlist
type_system = 'ootype'
More information about the pypy-commit
mailing list