[pypy-commit] pypy numpypy-axisops: merge with default
mattip
noreply at buildbot.pypy.org
Wed Dec 28 02:59:46 CET 2011
Author: mattip
Branch: numpypy-axisops
Changeset: r50919:1714b0167e37
Date: 2011-12-28 03:02 +0200
http://bitbucket.org/pypy/pypy/changeset/1714b0167e37/
Log: merge with default
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -98,7 +98,6 @@
"Abstract. Get the expected number of locals."
raise TypeError, "abstract"
- @jit.dont_look_inside
def fast2locals(self):
# Copy values from the fastlocals to self.w_locals
if self.w_locals is None:
@@ -112,7 +111,6 @@
w_name = self.space.wrap(name)
self.space.setitem(self.w_locals, w_name, w_value)
- @jit.dont_look_inside
def locals2fast(self):
# Copy values from self.w_locals to the fastlocals
assert self.w_locals is not None
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -619,7 +619,8 @@
self.descr_reqcls,
args)
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
@@ -655,7 +656,8 @@
self.descr_reqcls,
args)
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
@@ -674,7 +676,8 @@
self.descr_reqcls,
args.prepend(w_obj))
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
@@ -690,7 +693,8 @@
raise OperationError(space.w_SystemError,
space.wrap("unexpected DescrMismatch error"))
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
@@ -708,7 +712,8 @@
self.descr_reqcls,
Arguments(space, [w1]))
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
@@ -726,7 +731,8 @@
self.descr_reqcls,
Arguments(space, [w1, w2]))
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
@@ -744,7 +750,8 @@
self.descr_reqcls,
Arguments(space, [w1, w2, w3]))
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
@@ -763,7 +770,8 @@
Arguments(space,
[w1, w2, w3, w4]))
except Exception, e:
- raise self.handle_exception(space, e)
+ self.handle_exception(space, e)
+ w_result = None
if w_result is None:
w_result = space.w_None
return w_result
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
@@ -39,6 +39,7 @@
from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.jit.codewriter import longlong
from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.objectmodel import compute_unique_id
# darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0,
# better safe than sorry
@@ -58,7 +59,8 @@
self.is_guard_not_invalidated = is_guard_not_invalidated
DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed),
- ('bridge', lltype.Signed), # 0 or 1
+ ('type', lltype.Char), # 'b'ridge, 'l'abel or
+ # 'e'ntry point
('number', lltype.Signed))
class Assembler386(object):
@@ -147,12 +149,15 @@
def finish_once(self):
if self._debug:
debug_start('jit-backend-counts')
- for struct in self.loop_run_counters:
- if struct.bridge:
- prefix = 'bridge '
+ for i in range(len(self.loop_run_counters)):
+ struct = self.loop_run_counters[i]
+ if struct.type == 'l':
+ prefix = 'TargetToken(%d)' % struct.number
+ elif struct.type == 'b':
+ prefix = 'bridge ' + str(struct.number)
else:
- prefix = 'loop '
- debug_print(prefix + str(struct.number) + ':' + str(struct.i))
+ prefix = 'entry ' + str(struct.number)
+ debug_print(prefix + ':' + str(struct.i))
debug_stop('jit-backend-counts')
def _build_float_constants(self):
@@ -422,8 +427,8 @@
self.setup(looptoken)
if log:
- self._register_counter(False, looptoken.number)
- operations = self._inject_debugging_code(looptoken, operations)
+ operations = self._inject_debugging_code(looptoken, operations,
+ 'e', looptoken.number)
regalloc = RegAlloc(self, self.cpu.translate_support_code)
#
@@ -489,8 +494,8 @@
self.setup(original_loop_token)
if log:
- self._register_counter(True, descr_number)
- operations = self._inject_debugging_code(faildescr, operations)
+ operations = self._inject_debugging_code(faildescr, operations,
+ 'b', descr_number)
arglocs = self.rebuild_faillocs_from_descr(failure_recovery)
if not we_are_translated():
@@ -597,17 +602,21 @@
return self.mc.materialize(self.cpu.asmmemmgr, allblocks,
self.cpu.gc_ll_descr.gcrootmap)
- def _register_counter(self, bridge, number):
- if self._debug:
- # YYY very minor leak -- we need the counters to stay alive
- # forever, just because we want to report them at the end
- # of the process
- struct = lltype.malloc(DEBUG_COUNTER, flavor='raw',
- track_allocation=False)
- struct.i = 0
- struct.bridge = int(bridge)
+ def _register_counter(self, tp, number, token):
+ # YYY very minor leak -- we need the counters to stay alive
+ # forever, just because we want to report them at the end
+ # of the process
+ struct = lltype.malloc(DEBUG_COUNTER, flavor='raw',
+ track_allocation=False)
+ struct.i = 0
+ struct.type = tp
+ if tp == 'b' or tp == 'e':
struct.number = number
- self.loop_run_counters.append(struct)
+ else:
+ assert token
+ struct.number = compute_unique_id(token)
+ self.loop_run_counters.append(struct)
+ return struct
def _find_failure_recovery_bytecode(self, faildescr):
adr_jump_offset = faildescr._x86_adr_jump_offset
@@ -651,27 +660,36 @@
targettoken._x86_loop_code += rawstart
self.target_tokens_currently_compiling = None
+ def _append_debugging_code(self, operations, tp, number, token):
+ counter = self._register_counter(tp, number, token)
+ c_adr = ConstInt(rffi.cast(lltype.Signed, counter))
+ box = BoxInt()
+ box2 = BoxInt()
+ ops = [ResOperation(rop.GETFIELD_RAW, [c_adr],
+ box, descr=self.debug_counter_descr),
+ ResOperation(rop.INT_ADD, [box, ConstInt(1)], box2),
+ ResOperation(rop.SETFIELD_RAW, [c_adr, box2],
+ None, descr=self.debug_counter_descr)]
+ operations.extend(ops)
+
@specialize.argtype(1)
- def _inject_debugging_code(self, looptoken, operations):
+ def _inject_debugging_code(self, looptoken, operations, tp, number):
if self._debug:
# before doing anything, let's increase a counter
s = 0
for op in operations:
s += op.getopnum()
looptoken._x86_debug_checksum = s
- c_adr = ConstInt(rffi.cast(lltype.Signed,
- self.loop_run_counters[-1]))
- box = BoxInt()
- box2 = BoxInt()
- ops = [ResOperation(rop.GETFIELD_RAW, [c_adr],
- box, descr=self.debug_counter_descr),
- ResOperation(rop.INT_ADD, [box, ConstInt(1)], box2),
- ResOperation(rop.SETFIELD_RAW, [c_adr, box2],
- None, descr=self.debug_counter_descr)]
- if operations[0].getopnum() == rop.LABEL:
- operations = [operations[0]] + ops + operations[1:]
- else:
- operations = ops + operations
+
+ newoperations = []
+ self._append_debugging_code(newoperations, tp, number,
+ None)
+ for op in operations:
+ newoperations.append(op)
+ if op.getopnum() == rop.LABEL:
+ self._append_debugging_code(newoperations, 'l', number,
+ op.getdescr())
+ operations = newoperations
return operations
def _assemble(self, regalloc, operations):
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -519,6 +519,7 @@
from pypy.tool.logparser import parse_log_file, extract_category
from pypy.rlib import debug
+ targettoken, preambletoken = TargetToken(), TargetToken()
loop = """
[i0]
label(i0, descr=preambletoken)
@@ -533,8 +534,8 @@
guard_false(i12) []
jump(i11, descr=targettoken)
"""
- ops = parse(loop, namespace={'targettoken': TargetToken(),
- 'preambletoken': TargetToken()})
+ ops = parse(loop, namespace={'targettoken': targettoken,
+ 'preambletoken': preambletoken})
debug._log = dlog = debug.DebugLog()
try:
self.cpu.assembler.set_debug(True)
@@ -545,11 +546,16 @@
struct = self.cpu.assembler.loop_run_counters[0]
assert struct.i == 1
struct = self.cpu.assembler.loop_run_counters[1]
- assert struct.i == 10
+ assert struct.i == 1
+ struct = self.cpu.assembler.loop_run_counters[2]
+ assert struct.i == 9
self.cpu.finish_once()
finally:
debug._log = None
- assert ('jit-backend-counts', [('debug_print', 'loop -1:10')]) in dlog
+ l0 = ('debug_print', 'entry -1:1')
+ l1 = ('debug_print', preambletoken.repr_of_descr() + ':1')
+ l2 = ('debug_print', targettoken.repr_of_descr() + ':9')
+ assert ('jit-backend-counts', [l0, l1, l2]) in dlog
def test_debugger_checksum(self):
loop = """
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -162,7 +162,6 @@
_ll_4_list_setslice = rlist.ll_listsetslice
_ll_2_list_delslice_startonly = rlist.ll_listdelslice_startonly
_ll_3_list_delslice_startstop = rlist.ll_listdelslice_startstop
-_ll_1_list_list2fixed = lltypesystem_rlist.ll_list2fixed
_ll_2_list_inplace_mul = rlist.ll_inplace_mul
_ll_2_list_getitem_foldable = _ll_2_list_getitem
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
@@ -112,33 +112,26 @@
"""
from pypy.jit.metainterp.optimizeopt import optimize_trace
- history = metainterp.history
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
+ history = metainterp.history
- if False:
- part = partial_trace
- assert False
- procedur_token = metainterp.get_procedure_token(greenkey)
- assert procedure_token
- all_target_tokens = []
- else:
- jitcell_token = make_jitcell_token(jitdriver_sd)
- part = create_empty_loop(metainterp)
- part.inputargs = inputargs[:]
- h_ops = history.operations
- part.resume_at_jump_descr = resume_at_jump_descr
- part.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(jitcell_token))] + \
- [h_ops[i].clone() for i in range(start, len(h_ops))] + \
- [ResOperation(rop.LABEL, jumpargs, None, descr=jitcell_token)]
+ jitcell_token = make_jitcell_token(jitdriver_sd)
+ part = create_empty_loop(metainterp)
+ part.inputargs = inputargs[:]
+ h_ops = history.operations
+ part.resume_at_jump_descr = resume_at_jump_descr
+ part.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(jitcell_token))] + \
+ [h_ops[i].clone() for i in range(start, len(h_ops))] + \
+ [ResOperation(rop.LABEL, jumpargs, None, descr=jitcell_token)]
- try:
- optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
- except InvalidLoop:
- return None
- target_token = part.operations[0].getdescr()
- assert isinstance(target_token, TargetToken)
- all_target_tokens = [target_token]
+ try:
+ optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
+ except InvalidLoop:
+ return None
+ target_token = part.operations[0].getdescr()
+ assert isinstance(target_token, TargetToken)
+ all_target_tokens = [target_token]
loop = create_empty_loop(metainterp)
loop.inputargs = part.inputargs
@@ -319,7 +312,10 @@
metainterp_sd.stats.compiled()
metainterp_sd.log("compiled new " + type)
#
- metainterp_sd.logger_ops.log_loop(loop.inputargs, loop.operations, n, type, ops_offset)
+ loopname = jitdriver_sd.warmstate.get_location_str(greenkey)
+ metainterp_sd.logger_ops.log_loop(loop.inputargs, loop.operations, n,
+ type, ops_offset,
+ name=loopname)
#
if metainterp_sd.warmrunnerdesc is not None: # for tests
metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(original_jitcell_token)
diff --git a/pypy/jit/metainterp/heapcache.py b/pypy/jit/metainterp/heapcache.py
--- a/pypy/jit/metainterp/heapcache.py
+++ b/pypy/jit/metainterp/heapcache.py
@@ -79,9 +79,9 @@
opnum == rop.COPYSTRCONTENT or
opnum == rop.COPYUNICODECONTENT):
return
- if rop._OVF_FIRST <= opnum <= rop._OVF_LAST:
- return
- if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST:
+ if (rop._OVF_FIRST <= opnum <= rop._OVF_LAST or
+ rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST or
+ rop._GUARD_FIRST <= opnum <= rop._GUARD_LAST):
return
if opnum == rop.CALL or opnum == rop.CALL_LOOPINVARIANT:
effectinfo = descr.get_extra_info()
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
@@ -13,14 +13,14 @@
self.metainterp_sd = metainterp_sd
self.guard_number = guard_number
- def log_loop(self, inputargs, operations, number=0, type=None, ops_offset=None):
+ def log_loop(self, inputargs, operations, number=0, type=None, ops_offset=None, name=''):
if type is None:
debug_start("jit-log-noopt-loop")
logops = self._log_operations(inputargs, operations, ops_offset)
debug_stop("jit-log-noopt-loop")
else:
debug_start("jit-log-opt-loop")
- debug_print("# Loop", number, ":", type,
+ debug_print("# Loop", number, '(%s)' % name , ":", type,
"with", len(operations), "ops")
logops = self._log_operations(inputargs, operations, ops_offset)
debug_stop("jit-log-opt-loop")
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
@@ -1,10 +1,13 @@
from __future__ import with_statement
from pypy.jit.metainterp.optimizeopt.test.test_util import (
- LLtypeMixin, BaseTest, Storage, _sortboxes, FakeDescrWithSnapshot)
+ LLtypeMixin, BaseTest, Storage, _sortboxes, FakeDescrWithSnapshot,
+ FakeMetaInterpStaticData)
from pypy.jit.metainterp.history import TreeLoop, JitCellToken, TargetToken
from pypy.jit.metainterp.resoperation import rop, opname, ResOperation
from pypy.jit.metainterp.optimize import InvalidLoop
from py.test import raises
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
class BaseTestMultiLabel(BaseTest):
enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap:unroll"
@@ -84,6 +87,8 @@
return optimized
+class OptimizeoptTestMultiLabel(BaseTestMultiLabel):
+
def test_simple(self):
ops = """
[i1]
@@ -381,6 +386,55 @@
"""
self.optimize_loop(ops, expected)
-class TestLLtype(BaseTestMultiLabel, LLtypeMixin):
+
+class OptRenameStrlen(Optimization):
+ def propagate_forward(self, op):
+ dispatch_opt(self, op)
+
+ def optimize_STRLEN(self, op):
+ newop = op.clone()
+ newop.result = op.result.clonebox()
+ self.emit_operation(newop)
+ self.make_equal_to(op.result, self.getvalue(newop.result))
+
+dispatch_opt = make_dispatcher_method(OptRenameStrlen, 'optimize_',
+ default=OptRenameStrlen.emit_operation)
+
+class BaseTestOptimizerRenamingBoxes(BaseTestMultiLabel):
+
+ def _do_optimize_loop(self, loop, call_pure_results):
+ from pypy.jit.metainterp.optimizeopt.unroll import optimize_unroll
+ from pypy.jit.metainterp.optimizeopt.util import args_dict
+ from pypy.jit.metainterp.optimizeopt.pure import OptPure
+
+ self.loop = loop
+ loop.call_pure_results = args_dict()
+ metainterp_sd = FakeMetaInterpStaticData(self.cpu)
+ optimize_unroll(metainterp_sd, loop, [OptRenameStrlen(), OptPure()], True)
+
+ def test_optimizer_renaming_boxes(self):
+ ops = """
+ [p1]
+ i1 = strlen(p1)
+ label(p1)
+ i2 = strlen(p1)
+ i3 = int_add(i2, 7)
+ jump(p1)
+ """
+ expected = """
+ [p1]
+ i1 = strlen(p1)
+ label(p1, i1)
+ i11 = same_as(i1)
+ i2 = int_add(i11, 7)
+ jump(p1, i11)
+ """
+ self.optimize_loop(ops, expected)
+
+
+
+class TestLLtype(OptimizeoptTestMultiLabel, LLtypeMixin):
pass
+class TestOptimizerRenamingBoxesLLtype(BaseTestOptimizerRenamingBoxes, LLtypeMixin):
+ pass
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -7759,7 +7759,7 @@
jump(i0, p0, i2)
"""
self.optimize_loop(ops, expected)
-
+
class TestLLtype(OptimizeOptTest, LLtypeMixin):
pass
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -265,7 +265,12 @@
self.optimizer.importable_values[value] = imp
newvalue = self.optimizer.getvalue(op.result)
newresult = newvalue.get_key_box()
- assert newresult is op.result or newvalue.is_constant()
+ # note that emitting here SAME_AS should not happen, but
+ # in case it does, we would prefer to be suboptimal in asm
+ # to a fatal RPython exception.
+ if newresult is not op.result and not newvalue.is_constant():
+ op = ResOperation(rop.SAME_AS, [op.result], newresult)
+ self.optimizer._newoperations.append(op)
self.optimizer.flush()
self.optimizer.emitting_dissabled = False
diff --git a/pypy/jit/metainterp/test/test_compile.py b/pypy/jit/metainterp/test/test_compile.py
--- a/pypy/jit/metainterp/test/test_compile.py
+++ b/pypy/jit/metainterp/test/test_compile.py
@@ -18,7 +18,7 @@
self.seen.append((inputargs, operations, token))
class FakeLogger(object):
- def log_loop(self, inputargs, operations, number=0, type=None, ops_offset=None):
+ def log_loop(self, inputargs, operations, number=0, type=None, ops_offset=None, name=''):
pass
def repr_of_resop(self, op):
diff --git a/pypy/jit/metainterp/test/test_heapcache.py b/pypy/jit/metainterp/test/test_heapcache.py
--- a/pypy/jit/metainterp/test/test_heapcache.py
+++ b/pypy/jit/metainterp/test/test_heapcache.py
@@ -255,6 +255,11 @@
assert h.getarrayitem(box1, descr1, index1) is box2
assert h.getarrayitem(box1, descr1, index2) is box4
+ h.invalidate_caches(rop.GUARD_TRUE, None, [])
+ assert h.getfield(box1, descr1) is box2
+ assert h.getarrayitem(box1, descr1, index1) is box2
+ assert h.getarrayitem(box1, descr1, index2) is box4
+
h.invalidate_caches(
rop.CALL_LOOPINVARIANT, FakeCallDescr(FakeEffektinfo.EF_LOOPINVARIANT), [])
diff --git a/pypy/jit/metainterp/test/test_logger.py b/pypy/jit/metainterp/test/test_logger.py
--- a/pypy/jit/metainterp/test/test_logger.py
+++ b/pypy/jit/metainterp/test/test_logger.py
@@ -180,7 +180,7 @@
def test_intro_loop(self):
bare_logger = logger.Logger(self.make_metainterp_sd())
output = capturing(bare_logger.log_loop, [], [], 1, "foo")
- assert output.splitlines()[0] == "# Loop 1 : foo with 0 ops"
+ assert output.splitlines()[0] == "# Loop 1 () : foo with 0 ops"
pure_parse(output)
def test_intro_bridge(self):
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -4,6 +4,7 @@
class PyPyModule(MixedModule):
interpleveldefs = {
'debug_repr': 'interp_extras.debug_repr',
+ 'remove_invalidates': 'interp_extras.remove_invalidates',
}
appleveldefs = {}
diff --git a/pypy/module/micronumpy/interp_extras.py b/pypy/module/micronumpy/interp_extras.py
--- a/pypy/module/micronumpy/interp_extras.py
+++ b/pypy/module/micronumpy/interp_extras.py
@@ -5,3 +5,11 @@
@unwrap_spec(array=BaseArray)
def debug_repr(space, array):
return space.wrap(array.find_sig().debug_repr())
+
+ at unwrap_spec(array=BaseArray)
+def remove_invalidates(space, array):
+ """ Array modification will no longer invalidate any of it's
+ potential children. Use only for performance debugging
+ """
+ del array.invalidates[:]
+ return space.w_None
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
@@ -1,6 +1,6 @@
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
+from pypy.interpreter.gateway import interp2app, NoneNotWrapped
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.module.micronumpy import interp_ufuncs, interp_dtype, signature
from pypy.module.micronumpy.strides import calculate_slice_strides
@@ -14,22 +14,26 @@
numpy_driver = jit.JitDriver(
greens=['shapelen', 'sig'],
virtualizables=['frame'],
- reds=['result_size', 'frame', 'ri', 'self', 'result']
+ reds=['result_size', 'frame', 'ri', 'self', 'result'],
+ get_printable_location=signature.new_printable_location('numpy'),
)
all_driver = jit.JitDriver(
greens=['shapelen', 'sig'],
virtualizables=['frame'],
- reds=['frame', 'self', 'dtype']
+ reds=['frame', 'self', 'dtype'],
+ get_printable_location=signature.new_printable_location('all'),
)
any_driver = jit.JitDriver(
greens=['shapelen', 'sig'],
virtualizables=['frame'],
- reds=['frame', 'self', 'dtype']
+ reds=['frame', 'self', 'dtype'],
+ get_printable_location=signature.new_printable_location('any'),
)
slice_driver = jit.JitDriver(
greens=['shapelen', 'sig'],
virtualizables=['frame'],
- reds=['self', 'frame', 'source', 'res_iter']
+ reds=['self', 'frame', 'source', 'res_iter'],
+ get_printable_location=signature.new_printable_location('slice'),
)
def _find_shape_and_elems(space, w_iterable):
@@ -294,7 +298,8 @@
def _reduce_argmax_argmin_impl(op_name):
reduce_driver = jit.JitDriver(
greens=['shapelen', 'sig'],
- reds=['result', 'idx', 'frame', 'self', 'cur_best', 'dtype']
+ reds=['result', 'idx', 'frame', 'self', 'cur_best', 'dtype'],
+ get_printable_location=signature.new_printable_location(op_name),
)
def loop(self):
sig = self.find_sig()
@@ -581,8 +586,8 @@
strides.append(concrete.strides[i])
backstrides.append(concrete.backstrides[i])
shape.append(concrete.shape[i])
- return space.wrap(W_NDimSlice(concrete.start, strides[:],
- backstrides[:], shape[:], concrete))
+ return space.wrap(W_NDimSlice(concrete.start, strides,
+ backstrides, shape, concrete))
def descr_get_flatiter(self, space):
return space.wrap(W_FlatIterator(self))
@@ -886,8 +891,8 @@
if self.order == 'C':
strides.reverse()
backstrides.reverse()
- self.strides = strides[:]
- self.backstrides = backstrides[:]
+ self.strides = strides
+ self.backstrides = backstrides
def array_sig(self, res_shape):
if res_shape is not None and self.shape != res_shape:
@@ -1092,9 +1097,9 @@
strides.reverse()
backstrides.reverse()
new_shape.reverse()
- self.strides = strides[:]
- self.backstrides = backstrides[:]
- self.shape = new_shape[:]
+ self.strides = strides
+ self.backstrides = backstrides
+ self.shape = new_shape
return
new_strides = calc_new_strides(new_shape, self.shape, self.strides)
if new_strides is None:
@@ -1104,7 +1109,7 @@
for nd in range(len(new_shape)):
new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
self.strides = new_strides[:]
- self.backstrides = new_backstrides[:]
+ self.backstrides = new_backstrides
self.shape = new_shape[:]
class W_NDimArray(ConcreteArray):
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -1,10 +1,10 @@
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_boxes, interp_dtype, types
-from pypy.module.micronumpy.signature import (ReduceSignature,
- ScalarSignature, find_sig)
+from pypy.module.micronumpy import interp_boxes, interp_dtype
+from pypy.module.micronumpy.signature import ReduceSignature, ScalarSignature,\
+ find_sig, new_printable_location
from pypy.rlib import jit
from pypy.rlib.rarithmetic import LONG_BIT
from pypy.tool.sourcetools import func_with_new_name
@@ -12,7 +12,8 @@
reduce_driver = jit.JitDriver(
greens = ['shapelen', "sig"],
virtualizables = ["frame"],
- reds = ["frame", "self", "dtype", "value", "obj"]
+ reds = ["frame", "self", "dtype", "value", "obj"],
+ get_printable_location=new_printable_location('reduce'),
)
class W_Ufunc(Wrappable):
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -5,6 +5,11 @@
from pypy.module.micronumpy.strides import calculate_slice_strides
from pypy.rlib.jit import hint, unroll_safe, promote
+def new_printable_location(driver_name):
+ def get_printable_location(shapelen, sig):
+ return 'numpy ' + sig.debug_repr() + ' [%d dims,%s]' % (shapelen, driver_name)
+ return get_printable_location
+
def sigeq(one, two):
return one.eq(two)
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -1,4 +1,9 @@
+from pypy.rlib import jit
+
+ at jit.look_inside_iff(lambda shape, start, strides, backstrides, chunks:
+ jit.isconstant(len(chunks))
+)
def calculate_slice_strides(shape, start, strides, backstrides, chunks):
rstrides = []
rbackstrides = []
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -906,6 +906,15 @@
b[0] = 3
assert debug_repr(b) == 'Array'
+ def test_remove_invalidates(self):
+ from numpypy import array
+ from numpypy.pypy import remove_invalidates
+ a = array([1, 2, 3])
+ b = a + a
+ remove_invalidates(a)
+ a[0] = 14
+ assert b[0] == 28
+
def test_virtual_views(self):
from numpypy import arange
a = arange(15)
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -537,7 +537,7 @@
builder.append(by)
builder.append_slice(input, upper, len(input))
else:
- # An ok guess for the result size
+ # First compute the exact result size
count = input.count(sub)
if count > maxsplit and maxsplit > 0:
count = maxsplit
@@ -553,21 +553,16 @@
builder = StringBuilder(result_size)
start = 0
sublen = len(sub)
- first = True
while maxsplit != 0:
next = input.find(sub, start)
if next < 0:
break
- if not first:
- builder.append(by)
- first = False
builder.append_slice(input, start, next)
+ builder.append(by)
start = next + sublen
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
- if not first:
- builder.append(by)
builder.append_slice(input, start, len(input))
return space.wrap(builder.build())
diff --git a/pypy/rlib/rsre/rsre_jit.py b/pypy/rlib/rsre/rsre_jit.py
--- a/pypy/rlib/rsre/rsre_jit.py
+++ b/pypy/rlib/rsre/rsre_jit.py
@@ -22,7 +22,7 @@
info = '%s/%d' % (info, args[debugprint[2]])
else:
info = ''
- return '%s%s %s' % (name, info, s)
+ return 're %s%s %s' % (name, info, s)
#
self.get_printable_location = get_printable_location
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
@@ -375,7 +375,6 @@
newitems = malloc(LIST.items.TO, n)
rgc.ll_arraycopy(olditems, newitems, 0, 0, n)
return newitems
-ll_list2fixed.oopspec = 'list.list2fixed(l)'
def ll_list2fixed_exact(l):
ll_assert(l.length == len(l.items), "ll_list2fixed_exact: bad length")
diff --git a/pypy/rpython/test/test_generator.py b/pypy/rpython/test/test_generator.py
--- a/pypy/rpython/test/test_generator.py
+++ b/pypy/rpython/test/test_generator.py
@@ -54,6 +54,26 @@
res = self.interpret(f, [0])
assert res == 42
+ def test_except_block(self):
+ def foo():
+ raise ValueError
+ def g(a, b, c):
+ yield a
+ yield b
+ try:
+ foo()
+ except ValueError:
+ pass
+ yield c
+ def f():
+ gen = g(3, 5, 8)
+ x = gen.next() * 100
+ x += gen.next() * 10
+ x += gen.next()
+ return x
+ res = self.interpret(f, [])
+ assert res == 358
+
class TestLLtype(BaseTestGenerator, LLRtypeMixin):
pass
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -3,6 +3,7 @@
from pypy.jit.metainterp.resoperation import opname
from pypy.jit.tool.oparser import OpParser
from pypy.tool.logparser import parse_log_file, extract_category
+from copy import copy
class Op(object):
bridge = None
@@ -23,19 +24,13 @@
self.failargs = failargs
def getarg(self, i):
- return self._getvar(self.args[i])
+ return self.args[i]
def getargs(self):
- return [self._getvar(v) for v in self.args]
+ return self.args[:]
def getres(self):
- return self._getvar(self.res)
-
- def getdescr(self):
- return self.descr
-
- def _getvar(self, v):
- return v
+ return self.res
def is_guard(self):
return self._is_guard
@@ -43,7 +38,7 @@
def repr(self):
args = self.getargs()
if self.descr is not None:
- args.append('descr=%s' % self.getdescr())
+ args.append('descr=%s' % self.descr)
arglist = ', '.join(args)
if self.res is not None:
return '%s = %s(%s)' % (self.getres(), self.name, arglist)
@@ -52,8 +47,6 @@
def __repr__(self):
return self.repr()
- ## return '<%s (%s)>' % (self.name, ', '.join([repr(a)
- ## for a in self.args]))
class SimpleParser(OpParser):
@@ -145,18 +138,27 @@
is_bytecode = True
inline_level = None
- def __init__(self, operations, storage):
- if operations[0].name == 'debug_merge_point':
- self.inline_level = int(operations[0].args[0])
- m = re.search('<code object ([<>\w]+)\. file \'(.+?)\'\. line (\d+)> #(\d+) (\w+)',
- operations[0].args[1])
- if m is None:
- # a non-code loop, like StrLiteralSearch or something
- self.bytecode_name = operations[0].args[1][1:-1]
- else:
- self.name, self.filename, lineno, bytecode_no, self.bytecode_name = m.groups()
- self.startlineno = int(lineno)
- self.bytecode_no = int(bytecode_no)
+ def parse_code_data(self, arg):
+ m = re.search('<code object ([<>\w]+)[\.,] file \'(.+?)\'[\.,] line (\d+)> #(\d+) (\w+)',
+ arg)
+ if m is None:
+ # a non-code loop, like StrLiteralSearch or something
+ self.bytecode_name = arg
+ else:
+ self.name, self.filename, lineno, bytecode_no, self.bytecode_name = m.groups()
+ self.startlineno = int(lineno)
+ self.bytecode_no = int(bytecode_no)
+
+
+ def __init__(self, operations, storage, loopname):
+ for op in operations:
+ if op.name == 'debug_merge_point':
+ self.inline_level = int(op.args[0])
+ self.parse_code_data(op.args[1][1:-1])
+ break
+ else:
+ self.inline_level = 0
+ self.parse_code_data(loopname)
self.operations = operations
self.storage = storage
self.code = storage.disassemble_code(self.filename, self.startlineno,
@@ -164,7 +166,7 @@
def repr(self):
if self.filename is None:
- return "Unknown"
+ return self.bytecode_name
return "%s, file '%s', line %d" % (self.name, self.filename,
self.startlineno)
@@ -219,7 +221,8 @@
self.storage = storage
@classmethod
- def from_operations(cls, operations, storage, limit=None, inputargs=''):
+ def from_operations(cls, operations, storage, limit=None, inputargs='',
+ loopname=''):
""" Slice given operation list into a chain of TraceForOpcode chunks.
Also detect inlined functions and make them Function
"""
@@ -245,13 +248,13 @@
for op in operations:
if op.name == 'debug_merge_point':
if so_far:
- append_to_res(cls.TraceForOpcode(so_far, storage))
+ append_to_res(cls.TraceForOpcode(so_far, storage, loopname))
if limit:
break
so_far = []
so_far.append(op)
if so_far:
- append_to_res(cls.TraceForOpcode(so_far, storage))
+ append_to_res(cls.TraceForOpcode(so_far, storage, loopname))
# wrap stack back up
if not stack:
# no ops whatsoever
@@ -299,7 +302,7 @@
def repr(self):
if self.filename is None:
- return "Unknown"
+ return self.chunks[0].bytecode_name
return "%s, file '%s', line %d" % (self.name, self.filename,
self.startlineno)
@@ -384,9 +387,30 @@
parser.postprocess(loop, backend_tp=bname,
backend_dump=dump,
dump_start=start_ofs))
- loops.append(loop)
+ loops += split_trace(loop)
return log, loops
+def split_trace(trace):
+ labels = [0]
+ if trace.comment and 'Guard' in trace.comment:
+ descrs = ['bridge ' + re.search('Guard (\d+)', trace.comment).group(1)]
+ else:
+ descrs = ['entry ' + re.search('Loop (\d+)', trace.comment).group(1)]
+ for i, op in enumerate(trace.operations):
+ if op.name == 'label':
+ labels.append(i)
+ descrs.append(op.descr)
+ labels.append(len(trace.operations) - 1)
+ parts = []
+ for i in range(len(labels) - 1):
+ start, stop = labels[i], labels[i+1]
+ part = copy(trace)
+ part.operations = trace.operations[start : stop + 1]
+ part.descr = descrs[i]
+ part.comment = trace.comment
+ parts.append(part)
+
+ return parts
def parse_log_counts(input, loops):
if not input:
@@ -394,11 +418,7 @@
lines = input[-1].splitlines()
mapping = {}
for loop in loops:
- com = loop.comment
- if 'Loop' in com:
- mapping['loop ' + re.search('Loop (\d+)', com).group(1)] = loop
- else:
- mapping['bridge ' + re.search('Guard (\d+)', com).group(1)] = loop
+ mapping[loop.descr] = loop
for line in lines:
if line:
num, count = line.split(':', 2)
diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -1,6 +1,7 @@
from pypy.tool.jitlogparser.parser import (SimpleParser, TraceForOpcode,
Function, adjust_bridges,
- import_log, Op)
+ import_log, split_trace, Op,
+ parse_log_counts)
from pypy.tool.jitlogparser.storage import LoopStorage
import py, sys
@@ -32,23 +33,26 @@
''')
res = Function.from_operations(ops.operations, LoopStorage())
assert len(res.chunks) == 1
- assert res.chunks[0].repr()
+ assert 'SomeRandomStuff' in res.chunks[0].repr()
def test_split():
ops = parse('''
[i0]
+ label()
debug_merge_point(0, "<code object stuff. file '/I/dont/exist.py'. line 200> #10 ADD")
debug_merge_point(0, "<code object stuff. file '/I/dont/exist.py'. line 200> #11 SUB")
i1 = int_add(i0, 1)
debug_merge_point(0, "<code object stuff. file '/I/dont/exist.py'. line 200> #11 SUB")
i2 = int_add(i1, 1)
''')
- res = Function.from_operations(ops.operations, LoopStorage())
- assert len(res.chunks) == 3
+ res = Function.from_operations(ops.operations, LoopStorage(), loopname='<loopname>')
+ assert len(res.chunks) == 4
assert len(res.chunks[0].operations) == 1
- assert len(res.chunks[1].operations) == 2
+ assert len(res.chunks[1].operations) == 1
assert len(res.chunks[2].operations) == 2
- assert res.chunks[2].bytecode_no == 11
+ assert len(res.chunks[3].operations) == 2
+ assert res.chunks[3].bytecode_no == 11
+ assert res.chunks[0].bytecode_name == '<loopname>'
def test_inlined_call():
ops = parse("""
@@ -231,3 +235,51 @@
myrepr = 'c = foobar(a, b, descr=mydescr)'
assert op.repr() == myrepr
assert op.repr() == myrepr # do it twice
+
+def test_split_trace():
+ loop = parse('''
+ [i7]
+ i9 = int_lt(i7, 1003)
+ label(i9, descr=grrr)
+ guard_true(i9, descr=<Guard2>) []
+ i13 = getfield_raw(151937600, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+ label(i13, descr=asb)
+ i19 = int_lt(i13, 1003)
+ guard_true(i19, descr=<Guard2>) []
+ i113 = getfield_raw(151937600, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+ ''')
+ loop.comment = 'Loop 0'
+ parts = split_trace(loop)
+ assert len(parts) == 3
+ assert len(parts[0].operations) == 2
+ assert len(parts[1].operations) == 4
+ assert len(parts[2].operations) == 4
+ assert parts[1].descr == 'grrr'
+ assert parts[2].descr == 'asb'
+
+def test_parse_log_counts():
+ loop = parse('''
+ [i7]
+ i9 = int_lt(i7, 1003)
+ label(i9, descr=grrr)
+ guard_true(i9, descr=<Guard2>) []
+ i13 = getfield_raw(151937600, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+ label(i13, descr=asb)
+ i19 = int_lt(i13, 1003)
+ guard_true(i19, descr=<Guard3>) []
+ i113 = getfield_raw(151937600, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+ ''')
+ bridge = parse('''
+ # bridge out of Guard 2 with 1 ops
+ []
+ i0 = int_lt(1, 2)
+ finish(i0)
+ ''')
+ bridge.comment = 'bridge out of Guard 2 with 1 ops'
+ loop.comment = 'Loop 0'
+ loops = split_trace(loop) + split_trace(bridge)
+ input = ['grrr:123\nasb:12\nbridge 2:1234']
+ parse_log_counts(input, loops)
+ assert loops[-1].count == 1234
+ assert loops[1].count == 123
+ assert loops[2].count == 12
diff --git a/pypy/translator/generator.py b/pypy/translator/generator.py
--- a/pypy/translator/generator.py
+++ b/pypy/translator/generator.py
@@ -2,7 +2,7 @@
from pypy.objspace.flow.model import Variable, Constant, FunctionGraph
from pypy.translator.unsimplify import insert_empty_startblock
from pypy.translator.unsimplify import split_block
-from pypy.translator.simplify import eliminate_empty_blocks
+from pypy.translator.simplify import eliminate_empty_blocks, simplify_graph
from pypy.tool.sourcetools import func_with_new_name
from pypy.interpreter.argument import Signature
@@ -64,6 +64,7 @@
def next(self):
entry = self.current
self.current = None
+ assert entry is not None # else, recursive generator invocation
(next_entry, return_value) = func(entry)
self.current = next_entry
return return_value
@@ -91,6 +92,10 @@
block.inputargs = [v_entry1]
def tweak_generator_body_graph(Entry, graph):
+ # First, always run simplify_graph in order to reduce the number of
+ # variables passed around
+ simplify_graph(graph)
+ #
assert graph.startblock.operations[0].opname == 'generator_mark'
graph.startblock.operations.pop(0)
#
@@ -100,12 +105,20 @@
#
mappings = [Entry]
#
+ stopblock = Block([])
+ v0 = Variable(); v1 = Variable()
+ stopblock.operations = [
+ SpaceOperation('simple_call', [Constant(StopIteration)], v0),
+ SpaceOperation('type', [v0], v1),
+ ]
+ stopblock.closeblock(Link([v1, v0], graph.exceptblock))
+ #
for block in list(graph.iterblocks()):
for exit in block.exits:
if exit.target is graph.returnblock:
- exit.args = [Constant(StopIteration),
- Constant(StopIteration())]
- exit.target = graph.exceptblock
+ exit.args = []
+ exit.target = stopblock
+ assert block is not stopblock
for index in range(len(block.operations)-1, -1, -1):
op = block.operations[index]
if op.opname == 'yield':
diff --git a/pypy/translator/sandbox/pypy_interact.py b/pypy/translator/sandbox/pypy_interact.py
--- a/pypy/translator/sandbox/pypy_interact.py
+++ b/pypy/translator/sandbox/pypy_interact.py
@@ -26,7 +26,8 @@
from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc
from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc
from pypy.translator.sandbox.vfs import Dir, RealDir, RealFile
-from pypy.tool.lib_pypy import LIB_ROOT
+import pypy
+LIB_ROOT = os.path.dirname(os.path.dirname(pypy.__file__))
class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc):
debug = True
diff --git a/pypy/translator/sandbox/sandlib.py b/pypy/translator/sandbox/sandlib.py
--- a/pypy/translator/sandbox/sandlib.py
+++ b/pypy/translator/sandbox/sandlib.py
@@ -30,8 +30,9 @@
# load(). Also, marshal.load(f) blocks with the GIL held when
# f is a pipe with no data immediately avaialble, preventing the
# _waiting_thread to run.
-from pypy.tool.lib_pypy import import_from_lib_pypy
-marshal = import_from_lib_pypy('marshal')
+import pypy
+marshal = py.path.local(pypy.__file__).join('..', '..', 'lib_pypy',
+ 'marshal.py').pyimport()
# Non-marshal result types
RESULTTYPE_STATRESULT = object()
More information about the pypy-commit
mailing list