Author: Armin Rigo <[email protected]>
Branch: stmgc-c7
Changeset: r70218:09a81b58e77a
Date: 2014-03-23 17:58 +0100
http://bitbucket.org/pypy/pypy/changeset/09a81b58e77a/
Log: hg merge default
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py
b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -70,14 +70,14 @@
p13 = new(descr=...)
p15 = new_array(8, descr=<ArrayX .*>)
setfield_gc(p13, p15, descr=<FieldP dicttable.entries .*>)
- i17 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12,
descr=<Calli . rri EF=4>)
+ i17 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12,
descr=<Calli . rri EF=4 OS=4>)
setfield_gc(p13, 16, descr=<FieldS dicttable.resize_counter .*>)
guard_no_exception(descr=...)
p20 = new_with_vtable(ConstClass(W_IntObject))
call(ConstClass(_ll_dict_setitem_lookup_done_trampoline), p13,
p10, p20, i12, i17, descr=<Callv 0 rrrii EF=4>)
setfield_gc(p20, i5, descr=<FieldS .*W_IntObject.inst_intval .*>)
guard_no_exception(descr=...)
- i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12,
descr=<Calli . rri EF=4>)
+ i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12,
descr=<Calli . rri EF=4 OS=4>)
guard_no_exception(descr=...)
i26 = int_and(i23, .*)
i27 = int_is_true(i26)
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
@@ -141,15 +141,16 @@
i = 0
b = B(1)
while i < 100:
- b.x
- v = b.x # ID: loadattr
+ v = b.x # ID: loadattr1
+ v = b.x # ID: loadattr2
i += v
return i
log = self.run(main, [], threshold=80)
loop, = log.loops_by_filename(self.filepath)
- assert loop.match_by_id('loadattr',
+ assert loop.match_by_id('loadattr1',
'''
+ guard_not_invalidated(descr=...)
i19 = call(ConstClass(ll_dict_lookup), _, _, _, descr=...)
guard_no_exception(descr=...)
i21 = int_and(i19, _)
@@ -161,6 +162,7 @@
i29 = int_is_true(i28)
guard_true(i29, descr=...)
''')
+ assert loop.match_by_id('loadattr2', "") # completely folded away
def test_python_contains(self):
def main():
diff --git a/rpython/jit/backend/arm/opassembler.py
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -584,7 +584,10 @@
emit_op_getfield_gc_pure = emit_op_getfield_gc
def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond):
- # XXX implement me
+ base_loc, value_loc = arglocs
+ self.mc.LDR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
+ self.mc.ADD_ri(value_loc.value, value_loc.value, 1, cond=fcond)
+ self.mc.STR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
return fcond
def emit_op_getinteriorfield_gc(self, op, arglocs, regalloc, fcond):
diff --git a/rpython/jit/backend/arm/regalloc.py
b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -850,8 +850,12 @@
prepare_op_getfield_gc_pure = prepare_op_getfield_gc
def prepare_op_increment_debug_counter(self, op, fcond):
- # XXX implement me
- return []
+ boxes = op.getarglist()
+ a0, = boxes
+ base_loc = self.make_sure_var_in_reg(a0, boxes)
+ value_loc = self.get_scratch_reg(INT, boxes)
+ self.free_temp_vars()
+ return [base_loc, value_loc]
def prepare_op_getinteriorfield_gc(self, op, fcond):
t = unpack_interiorfielddescr(op.getdescr())
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py
b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -556,7 +556,7 @@
p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d)
setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr)
setfield_gc(p1, 10, descr=unicodelendescr)
- p2 = call_malloc_nursery_varsize(2, 4, i2, \
+ p2 = call_malloc_nursery_varsize(2, %(unicodedescr.itemsize)d, i2,\
descr=unicodedescr)
setfield_gc(p2, i2, descr=unicodelendescr)
p3 = call_malloc_nursery_varsize(1, 1, i2, \
diff --git a/rpython/jit/backend/x86/arch.py b/rpython/jit/backend/x86/arch.py
--- a/rpython/jit/backend/x86/arch.py
+++ b/rpython/jit/backend/x86/arch.py
@@ -15,14 +15,14 @@
#
# +--------------------+ <== aligned to 16 bytes
# | return address |
-# +--------------------+
-# | STM resume buf | (16 extra bytes, only with STM)
-# +--------------------+
-# | saved regs |
-# +--------------------+
-# | scratch |
-# | space |
-# +--------------------+ <== aligned to 16 bytes
+# +--------------------+ ------------------------.
+# | resume buf (if STM)| STM_FRAME_FIXED_SIZE |
+# +--------------------+ ----------------------. |
+# | saved regs | FRAME_FIXED_SIZE | |
+# +--------------------+ --------------------. | |
+# | scratch | PASS_ON_MY_FRAME | | |
+# | space | | | |
+# +--------------------+ <== aligned to 16 -----' ----' ----'
# STACK TOP
# All the rest of the data is in a GC-managed variable-size "frame".
@@ -33,16 +33,17 @@
# start of every frame: the saved value of some registers
if WORD == 4:
- # ebp + ebx + esi + edi + 14 extra words + return address = 19 words
+ # ebp + ebx + esi + edi + 15 extra words = 19 words
FRAME_FIXED_SIZE = 19
- PASS_ON_MY_FRAME = 14
+ PASS_ON_MY_FRAME = 15
JITFRAME_FIXED_SIZE = 6 + 8 * 2 # 6 GPR + 8 XMM * 2 WORDS/float
else:
- # rbp + rbx + r12 + r13 + r14 + r15 + 12 extra words + return address = 19
+ # rbp + rbx + r12 + r13 + r14 + r15 + 13 extra words = 19
FRAME_FIXED_SIZE = 19
- PASS_ON_MY_FRAME = 12
+ PASS_ON_MY_FRAME = 13
JITFRAME_FIXED_SIZE = 28 # 13 GPR + 15 XMM
assert PASS_ON_MY_FRAME >= 12 # asmgcc needs at least JIT_USE_WORDS + 3
STM_RESUME_BUF = 16 / WORD
+STM_FRAME_FIXED_SIZE = FRAME_FIXED_SIZE + STM_RESUME_BUF
diff --git a/rpython/jit/codewriter/effectinfo.py
b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -106,8 +106,10 @@
needs_inevitable=False):
key = (frozenset_or_none(readonly_descrs_fields),
frozenset_or_none(readonly_descrs_arrays),
+ frozenset_or_none(readonly_descrs_interiorfields),
frozenset_or_none(write_descrs_fields),
frozenset_or_none(write_descrs_arrays),
+ frozenset_or_none(write_descrs_interiorfields),
extraeffect,
oopspecindex,
can_invalidate,
@@ -231,6 +233,18 @@
descr = cpu.interiorfielddescrof(T, fieldname)
descrs_interiorfields.append(descr)
+ # a read or a write to an interiorfield, inside an array of
+ # structs, is additionally recorded as a read or write of
+ # the array itself
+ extraef = set()
+ for tup in effects:
+ if tup[0] == "interiorfield" or tup[0] == "readinteriorfield":
+ T = deref(tup[1])
+ if isinstance(T, lltype.Array) and consider_array(T):
+ extraef.add((tup[0].replace("interiorfield", "array"),
+ tup[1]))
+ effects |= extraef
+
for tup in effects:
if tup[0] == "struct":
add_struct(write_descrs_fields, tup)
diff --git a/rpython/jit/codewriter/jtransform.py
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1868,8 +1868,7 @@
def _handle_dict_lookup_call(self, op, oopspec_name, args):
extradescr1 = self.cpu.fielddescrof(op.args[1].concretetype.TO,
'entries')
- extradescr2 = self.cpu.interiorfielddescrof(
- op.args[1].concretetype.TO.entries.TO, 'key')
+ extradescr2 =
self.cpu.arraydescrof(op.args[1].concretetype.TO.entries.TO)
return self._handle_oopspec_call(op, args, EffectInfo.OS_DICT_LOOKUP,
extradescr=[extradescr1, extradescr2])
diff --git a/rpython/jit/codewriter/test/test_flatten.py
b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -73,7 +73,7 @@
def guess_call_kind(self, op):
return 'residual'
def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
- extraeffect=None):
+ extraeffect=None, extradescr=None):
try:
name = op.args[0].value._obj._name
if 'cannot_raise' in name or name.startswith('cast_'):
diff --git a/rpython/jit/codewriter/test/test_longlong.py
b/rpython/jit/codewriter/test/test_longlong.py
--- a/rpython/jit/codewriter/test/test_longlong.py
+++ b/rpython/jit/codewriter/test/test_longlong.py
@@ -17,7 +17,7 @@
class FakeBuiltinCallControl:
def guess_call_kind(self, op):
return 'builtin'
- def getcalldescr(self, op, oopspecindex=None, extraeffect=None):
+ def getcalldescr(self, op, oopspecindex=None, extraeffect=None,
extradescr=None):
assert oopspecindex is not None # in this test
return 'calldescr-%d' % oopspecindex
def calldescr_canraise(self, calldescr):
diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py
--- a/rpython/jit/metainterp/logger.py
+++ b/rpython/jit/metainterp/logger.py
@@ -82,6 +82,9 @@
def _make_log_operations(self):
return LogOperations(self.metainterp_sd, self.guard_number)
+ def repr_of_resop(self, op):
+ return LogOperations(self.metainterp_sd,
self.guard_number).repr_of_resop(op)
+
class LogOperations(object):
"""
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -177,7 +177,7 @@
self.cached_arrayitems = {}
# cached dict items: {dict descr: {(optval, index): box-or-const}}
self.cached_dict_reads = {}
- # cache of corresponding array descrs
+ # cache of corresponding {array descrs: dict 'entries' field descr}
self.corresponding_array_descrs = {}
#
self._lazy_setfields_and_arrayitems = []
@@ -309,12 +309,11 @@
descrs = op.getdescr().get_extra_info().extradescrs
assert descrs # translation hint
descr1 = descrs[0]
- descr2 = descrs[1]
- if descr1 in self.cached_dict_reads:
+ try:
d = self.cached_dict_reads[descr1]
- else:
+ except KeyError:
d = self.cached_dict_reads[descr1] = args_dict()
- self.corresponding_array_descrs[descr2] = descr1
+ self.corresponding_array_descrs[descrs[1]] = descr1
args = self.optimizer.make_args_key(op)
try:
res_v = d[args]
@@ -348,9 +347,8 @@
self.force_lazy_setfield(fielddescr, can_cache=False)
for arraydescr in effectinfo.write_descrs_arrays:
self.force_lazy_setarrayitem(arraydescr, can_cache=False)
- for descr in effectinfo.write_descrs_interiorfields:
- if descr in self.corresponding_array_descrs:
- dictdescr = self.corresponding_array_descrs.pop(descr)
+ if arraydescr in self.corresponding_array_descrs:
+ dictdescr = self.corresponding_array_descrs.pop(arraydescr)
try:
del self.cached_dict_reads[dictdescr]
except KeyError:
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py
b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -242,8 +242,9 @@
box = value.box
assert isinstance(box, Const)
if not box.same_constant(constbox):
- raise InvalidLoop('A GUARD_{VALUE,TRUE,FALSE} was proven to' +
- 'always fail')
+ r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_{VALUE,TRUE,FALSE} (%s) was proven '
+ 'to always fail' % r)
return
if emit_operation:
self.emit_operation(op)
@@ -255,7 +256,9 @@
if value.is_null():
return
elif value.is_nonnull():
- raise InvalidLoop('A GUARD_ISNULL was proven to always fail')
+ r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_ISNULL (%s) was proven to always fail'
+ % r)
self.emit_operation(op)
value.make_constant(self.optimizer.cpu.ts.CONST_NULL)
@@ -264,7 +267,9 @@
if value.is_nonnull():
return
elif value.is_null():
- raise InvalidLoop('A GUARD_NONNULL was proven to always fail')
+ r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_NONNULL (%s) was proven to always fail'
+ % r)
self.emit_operation(op)
value.make_nonnull(op)
@@ -292,7 +297,8 @@
assert previous_classbox is not None
assert expected_classbox is not None
if not previous_classbox.same_constant(expected_classbox):
- raise InvalidLoop('A GUARD_VALUE was proven to always
fail')
+ r =
self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_VALUE (%s) was proven to always
fail' % r)
op = old_guard_op.copy_and_change(rop.GUARD_VALUE,
args = [old_guard_op.getarg(0),
op.getarg(1)])
self.optimizer.replaces_guard[op] = old_guard_op
@@ -333,7 +339,9 @@
if realclassbox is not None:
if realclassbox.same_constant(expectedclassbox):
return
- raise InvalidLoop('A GUARD_CLASS was proven to always fail')
+ r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail'
+ % r)
if value.last_guard:
# there already has been a guard_nonnull or guard_class or
# guard_nonnull_class on this value.
@@ -356,8 +364,9 @@
def optimize_GUARD_NONNULL_CLASS(self, op):
value = self.getvalue(op.getarg(0))
if value.is_null():
- raise InvalidLoop('A GUARD_NONNULL_CLASS was proven to always ' +
- 'fail')
+ r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_NONNULL_CLASS (%s) was proven to '
+ 'always fail' % r)
self.optimize_GUARD_CLASS(op)
def optimize_CALL_LOOPINVARIANT(self, op):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py
b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -319,6 +319,9 @@
def log_loop(*args):
pass
+ class logger_ops:
+ repr_of_resop = repr
+
class warmrunnerdesc:
class memory_manager:
retrace_limit = 5
diff --git a/rpython/jit/metainterp/optimizeopt/util.py
b/rpython/jit/metainterp/optimizeopt/util.py
--- a/rpython/jit/metainterp/optimizeopt/util.py
+++ b/rpython/jit/metainterp/optimizeopt/util.py
@@ -139,7 +139,13 @@
txt1 = str(op1)
txt2 = str(op2)
while txt1 or txt2:
- print '%s| %s' % (txt1[:width].ljust(width), txt2[:width])
+ part1 = txt1[:width]
+ part2 = txt2[:width]
+ if part1 == part2:
+ sep = '| '
+ else:
+ sep = '<>'
+ print '%s%s%s' % (part1.ljust(width), sep, part2)
txt1 = txt1[width:]
txt2 = txt2[width:]
print '-' * totwidth
diff --git a/rpython/jit/metainterp/test/test_dict.py
b/rpython/jit/metainterp/test/test_dict.py
--- a/rpython/jit/metainterp/test/test_dict.py
+++ b/rpython/jit/metainterp/test/test_dict.py
@@ -294,6 +294,54 @@
assert res == f(10)
self.check_simple_loop(call=3)
+ def test_dict_eq_can_release_gil(self):
+ from rpython.rtyper.lltypesystem import lltype, rffi
+ if type(self.newdict()) is not dict:
+ py.test.skip("this is an r_dict test")
+ T = rffi.CArrayPtr(rffi.TIME_T)
+ external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True)
+ myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+ def key(x):
+ return x % 2
+ def eq(x, y):
+ external(lltype.nullptr(T.TO))
+ return (x % 2) == (y % 2)
+
+ def f(n):
+ dct = objectmodel.r_dict(eq, key)
+ total = n
+ x = 44444
+ y = 55555
+ z = 66666
+ while total:
+ myjitdriver.jit_merge_point(total=total, dct=dct)
+ dct[total] = total
+ x = dct[total]
+ y = dct[total]
+ z = dct[total]
+ total -= 1
+ return len(dct) + x + y + z
+
+ res = self.meta_interp(f, [10], listops=True)
+ assert res == 2 + 1 + 1 + 1
+ self.check_simple_loop(call_may_force=4, # ll_dict_lookup_trampoline
+ call=1) # ll_dict_setitem_lookup_done_trampoline
+
+ def test_bug42(self):
+ myjitdriver = JitDriver(greens = [], reds = 'auto')
+ def f(n):
+ mdict = {0: None, 1: None, 2: None, 3: None, 4: None,
+ 5: None, 6: None, 7: None, 8: None, 9: None}
+ while n > 0:
+ myjitdriver.jit_merge_point()
+ n -= 1
+ if n in mdict:
+ del mdict[n]
+ if n in mdict:
+ raise Exception
+ self.meta_interp(f, [10])
+ self.check_simple_loop(call_may_force=0, call=3)
+
class TestLLtype(DictTests, LLJitMixin):
pass
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit