[pypy-commit] pypy better-jit-hooks: merge default
fijal
noreply at buildbot.pypy.org
Tue Jan 3 13:04:29 CET 2012
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: better-jit-hooks
Changeset: r50990:ec5dfe7d9d1a
Date: 2012-01-03 13:18 +0200
http://bitbucket.org/pypy/pypy/changeset/ec5dfe7d9d1a/
Log: merge default
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -27,7 +27,7 @@
DEALINGS IN THE SOFTWARE.
-PyPy Copyright holders 2003-2011
+PyPy Copyright holders 2003-2012
-----------------------------------
Except when otherwise stated (look for LICENSE files or information at
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
@@ -59,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):
@@ -150,10 +151,12 @@
debug_start('jit-backend-counts')
for i in range(len(self.loop_run_counters)):
struct = self.loop_run_counters[i]
- if not struct.bridge:
+ if struct.type == 'l':
prefix = 'TargetToken(%d)' % struct.number
+ elif struct.type == 'b':
+ prefix = 'bridge ' + str(struct.number)
else:
- prefix = 'bridge ' + str(struct.number)
+ prefix = 'entry ' + str(struct.number)
debug_print(prefix + ':' + str(struct.i))
debug_stop('jit-backend-counts')
@@ -425,7 +428,7 @@
self.setup(looptoken)
if log:
operations = self._inject_debugging_code(looptoken, operations,
- False, looptoken.number)
+ 'e', looptoken.number)
regalloc = RegAlloc(self, self.cpu.translate_support_code)
#
@@ -492,7 +495,7 @@
self.setup(original_loop_token)
if log:
operations = self._inject_debugging_code(faildescr, operations,
- True, descr_number)
+ 'b', descr_number)
arglocs = self.rebuild_faillocs_from_descr(failure_recovery)
if not we_are_translated():
@@ -599,15 +602,15 @@
return self.mc.materialize(self.cpu.asmmemmgr, allblocks,
self.cpu.gc_ll_descr.gcrootmap)
- def _register_counter(self, bridge, number, token):
+ 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.bridge = int(bridge)
- if bridge:
+ struct.type = tp
+ if tp == 'b' or tp == 'e':
struct.number = number
else:
assert token
@@ -657,8 +660,8 @@
targettoken._x86_loop_code += rawstart
self.target_tokens_currently_compiling = None
- def _append_debugging_code(self, operations, bridge, number, token):
- counter = self._register_counter(bridge, number, token)
+ 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()
@@ -670,7 +673,7 @@
operations.extend(ops)
@specialize.argtype(1)
- def _inject_debugging_code(self, looptoken, operations, bridge, number):
+ def _inject_debugging_code(self, looptoken, operations, tp, number):
if self._debug:
# before doing anything, let's increase a counter
s = 0
@@ -679,13 +682,12 @@
looptoken._x86_debug_checksum = s
newoperations = []
- if bridge:
- self._append_debugging_code(newoperations, bridge, number,
- None)
+ 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, bridge, number,
+ self._append_debugging_code(newoperations, 'l', number,
op.getdescr())
operations = newoperations
return 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
@@ -420,8 +420,8 @@
debug._log = None
#
assert ops_offset is looptoken._x86_ops_offset
- # getfield_raw/int_add/setfield_raw + ops + None
- assert len(ops_offset) == 3 + len(operations) + 1
+ # 2*(getfield_raw/int_add/setfield_raw) + ops + None
+ assert len(ops_offset) == 2*3 + len(operations) + 1
assert (ops_offset[operations[0]] <=
ops_offset[operations[1]] <=
ops_offset[operations[2]] <=
@@ -546,13 +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 == 1
+ struct = self.cpu.assembler.loop_run_counters[2]
assert struct.i == 9
self.cpu.finish_once()
finally:
debug._log = None
+ 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', [l1, l2]) in dlog
+ 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
@@ -176,10 +169,10 @@
loop.original_jitcell_token = jitcell_token
for label in all_target_tokens:
assert isinstance(label, TargetToken)
- label.original_jitcell_token = jitcell_token
if label.virtual_state and label.short_preamble:
metainterp_sd.logger_ops.log_short_preamble([], label.short_preamble)
jitcell_token.target_tokens = all_target_tokens
+ propagate_original_jitcell_token(loop)
send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, "loop")
record_loop_or_bridge(metainterp_sd, loop)
return all_target_tokens[0]
@@ -247,11 +240,11 @@
for box in loop.inputargs:
assert isinstance(box, Box)
- target_token = loop.operations[-1].getdescr()
+ target_token = loop.operations[-1].getdescr()
resumekey.compile_and_attach(metainterp, loop)
+
target_token = label.getdescr()
assert isinstance(target_token, TargetToken)
- target_token.original_jitcell_token = loop.original_jitcell_token
record_loop_or_bridge(metainterp_sd, loop)
return target_token
@@ -288,6 +281,15 @@
assert i == len(inputargs)
loop.operations = extra_ops + loop.operations
+def propagate_original_jitcell_token(trace):
+ for op in trace.operations:
+ if op.getopnum() == rop.LABEL:
+ token = op.getdescr()
+ assert isinstance(token, TargetToken)
+ assert token.original_jitcell_token is None
+ token.original_jitcell_token = trace.original_jitcell_token
+
+
def send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, type):
vinfo = jitdriver_sd.virtualizable_info
if vinfo is not None:
@@ -319,7 +321,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)
@@ -558,6 +563,7 @@
inputargs = metainterp.history.inputargs
if not we_are_translated():
self._debug_suboperations = new_loop.operations
+ propagate_original_jitcell_token(new_loop)
send_bridge_to_backend(metainterp.jitdriver_sd, metainterp.staticdata,
self, inputargs, new_loop.operations,
new_loop.original_jitcell_token)
@@ -744,6 +750,7 @@
jitdriver_sd = metainterp.jitdriver_sd
redargs = new_loop.inputargs
new_loop.original_jitcell_token = jitcell_token = make_jitcell_token(jitdriver_sd)
+ propagate_original_jitcell_token(new_loop)
send_loop_to_backend(self.original_greenkey, metainterp.jitdriver_sd,
metainterp_sd, new_loop, "entry bridge")
# send the new_loop to warmspot.py, to be called directly the next time
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,66 @@
"""
self.optimize_loop(ops, expected)
-class TestLLtype(BaseTestMultiLabel, LLtypeMixin):
+ def test_virtual_as_field_of_forced_box(self):
+ ops = """
+ [p0]
+ pv1 = new_with_vtable(ConstClass(node_vtable))
+ label(pv1, p0)
+ pv2 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(pv2, pv1, descr=valuedescr)
+ jump(pv1, pv2)
+ """
+ with raises(InvalidLoop):
+ self.optimize_loop(ops, ops)
+
+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
@@ -269,10 +269,8 @@
# 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():
- # XXX fix me?
- #self.short_boxes.alias(newresult, op.result)
op = ResOperation(rop.SAME_AS, [op.result], newresult)
- self.optimizer._newoperations = [op] + self.optimizer._newoperations
+ self.optimizer._newoperations.append(op)
self.optimizer.flush()
self.optimizer.emitting_dissabled = False
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -409,7 +409,13 @@
if self.level == LEVEL_CONSTANT:
return
assert 0 <= self.position_in_notvirtuals
- boxes[self.position_in_notvirtuals] = value.force_box(optimizer)
+ if optimizer:
+ box = value.force_box(optimizer)
+ else:
+ if value.is_virtual():
+ raise BadVirtualState
+ box = value.get_key_box()
+ boxes[self.position_in_notvirtuals] = box
def _enum(self, virtual_state):
if self.level == LEVEL_CONSTANT:
@@ -471,8 +477,14 @@
optimizer = optimizer.optearlyforce
assert len(values) == len(self.state)
inputargs = [None] * len(self.notvirtuals)
+
+ # We try twice. The first time around we allow boxes to be forced
+ # which might change the virtual state if the box appear in more
+ # than one place among the inputargs.
for i in range(len(values)):
self.state[i].enum_forced_boxes(inputargs, values[i], optimizer)
+ for i in range(len(values)):
+ self.state[i].enum_forced_boxes(inputargs, values[i], None)
if keyboxes:
for i in range(len(values)):
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -976,10 +976,13 @@
self.verify_green_args(jitdriver_sd, greenboxes)
self.debug_merge_point(jitdriver_sd, jdindex, self.metainterp.in_recursion,
greenboxes)
-
+
if self.metainterp.seen_loop_header_for_jdindex < 0:
- if not jitdriver_sd.no_loop_header or not any_operation:
+ if not any_operation:
return
+ if self.metainterp.in_recursion or not self.metainterp.get_procedure_token(greenboxes, True):
+ if not jitdriver_sd.no_loop_header:
+ return
# automatically add a loop_header if there is none
self.metainterp.seen_loop_header_for_jdindex = jdindex
#
@@ -2052,9 +2055,15 @@
from pypy.jit.metainterp.resoperation import opname
raise NotImplementedError(opname[opnum])
- def get_procedure_token(self, greenkey):
+ def get_procedure_token(self, greenkey, with_compiled_targets=False):
cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
- return cell.get_procedure_token()
+ token = cell.get_procedure_token()
+ if with_compiled_targets:
+ if not token:
+ return None
+ if not token.target_tokens:
+ return None
+ return token
def compile_loop(self, original_boxes, live_arg_boxes, start, resume_at_jump_descr):
num_green_args = self.jitdriver_sd.num_green_args
@@ -2087,11 +2096,9 @@
def compile_trace(self, live_arg_boxes, resume_at_jump_descr):
num_green_args = self.jitdriver_sd.num_green_args
greenkey = live_arg_boxes[:num_green_args]
- target_jitcell_token = self.get_procedure_token(greenkey)
+ target_jitcell_token = self.get_procedure_token(greenkey, True)
if not target_jitcell_token:
return
- if not target_jitcell_token.target_tokens:
- return
self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None,
descr=target_jitcell_token)
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2697,7 +2697,7 @@
# bridge back to the preamble of the first loop is produced. A guard in
# this bridge is later traced resulting in a failed attempt of retracing
# the second loop.
- self.check_trace_count(8)
+ self.check_trace_count(9)
# FIXME: Add a gloabl retrace counter and test that we are not trying more than 5 times.
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/jit/metainterp/test/test_loop.py b/pypy/jit/metainterp/test/test_loop.py
--- a/pypy/jit/metainterp/test/test_loop.py
+++ b/pypy/jit/metainterp/test/test_loop.py
@@ -756,7 +756,7 @@
res = self.meta_interp(interpret, [1])
assert res == interpret(1)
# XXX it's unsure how many loops should be there
- self.check_trace_count(3)
+ self.check_trace_count(2)
def test_path_with_operations_not_from_start(self):
jitdriver = JitDriver(greens = ['k'], reds = ['n', 'z'])
diff --git a/pypy/jit/metainterp/test/test_virtual.py b/pypy/jit/metainterp/test/test_virtual.py
--- a/pypy/jit/metainterp/test/test_virtual.py
+++ b/pypy/jit/metainterp/test/test_virtual.py
@@ -880,7 +880,7 @@
elif op == 'j':
j = Int(0)
elif op == '+':
- sa += i.val * j.val
+ sa += (i.val + 2) * (j.val + 2)
elif op == 'a':
i = Int(i.val + 1)
elif op == 'b':
@@ -902,6 +902,7 @@
assert res == f(10)
self.check_aborted_count(0)
self.check_target_token_count(3)
+ self.check_resops(int_mul=2)
def test_nested_loops_bridge(self):
class Int(object):
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):
@@ -291,7 +295,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()
@@ -375,6 +380,9 @@
def descr_get_dtype(self, space):
return space.wrap(self.find_dtype())
+ def descr_get_ndim(self, space):
+ return space.wrap(len(self.shape))
+
@jit.unroll_safe
def descr_get_shape(self, space):
return space.newtuple([space.wrap(i) for i in self.shape])
@@ -404,7 +412,7 @@
def descr_repr(self, space):
res = StringBuilder()
res.append("array(")
- concrete = self.get_concrete()
+ concrete = self.get_concrete_or_scalar()
dtype = concrete.find_dtype()
if not concrete.size:
res.append('[]')
@@ -416,9 +424,13 @@
res.append(')')
else:
concrete.to_str(space, 1, res, indent=' ')
- if (dtype is not interp_dtype.get_dtype_cache(space).w_float64dtype and
- dtype is not interp_dtype.get_dtype_cache(space).w_int64dtype) or \
- not self.size:
+ if (dtype is interp_dtype.get_dtype_cache(space).w_float64dtype or \
+ dtype.kind == interp_dtype.SIGNEDLTR and \
+ dtype.itemtype.get_element_size() == rffi.sizeof(lltype.Signed)) \
+ and self.size:
+ # Do not print dtype
+ pass
+ else:
res.append(", dtype=" + dtype.name)
res.append(")")
return space.wrap(res.build())
@@ -578,8 +590,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))
@@ -820,8 +832,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:
@@ -835,80 +847,80 @@
each line will begin with indent.
'''
size = self.size
+ ccomma = ',' * comma
+ ncomma = ',' * (1 - comma)
+ dtype = self.find_dtype()
if size < 1:
builder.append('[]')
return
+ elif size == 1:
+ builder.append(dtype.itemtype.str_format(self.getitem(0)))
+ return
if size > 1000:
# Once this goes True it does not go back to False for recursive
# calls
use_ellipsis = True
- dtype = self.find_dtype()
ndims = len(self.shape)
i = 0
- start = True
builder.append('[')
if ndims > 1:
if use_ellipsis:
- for i in range(3):
- if start:
- start = False
- else:
- builder.append(',' * comma + '\n')
- if ndims == 3:
+ for i in range(min(3, self.shape[0])):
+ if i > 0:
+ builder.append(ccomma + '\n')
+ if ndims >= 3:
builder.append('\n' + indent)
else:
builder.append(indent)
- # create_slice requires len(chunks) > 1 in order to reduce
- # shape
- view = self.create_slice([(i, 0, 0, 1), (0, self.shape[1], 1, self.shape[1])]).get_concrete()
- view.to_str(space, comma, builder, indent=indent + ' ', use_ellipsis=use_ellipsis)
- builder.append('\n' + indent + '..., ')
- i = self.shape[0] - 3
+ view = self.create_slice([(i, 0, 0, 1)]).get_concrete()
+ view.to_str(space, comma, builder, indent=indent + ' ',
+ use_ellipsis=use_ellipsis)
+ if i < self.shape[0] - 1:
+ builder.append(ccomma +'\n' + indent + '...' + ncomma)
+ i = self.shape[0] - 3
+ else:
+ i += 1
while i < self.shape[0]:
- if start:
- start = False
- else:
- builder.append(',' * comma + '\n')
- if ndims == 3:
+ if i > 0:
+ builder.append(ccomma + '\n')
+ if ndims >= 3:
builder.append('\n' + indent)
else:
builder.append(indent)
# create_slice requires len(chunks) > 1 in order to reduce
# shape
- view = self.create_slice([(i, 0, 0, 1), (0, self.shape[1], 1, self.shape[1])]).get_concrete()
- view.to_str(space, comma, builder, indent=indent + ' ', use_ellipsis=use_ellipsis)
+ view = self.create_slice([(i, 0, 0, 1)]).get_concrete()
+ view.to_str(space, comma, builder, indent=indent + ' ',
+ use_ellipsis=use_ellipsis)
i += 1
elif ndims == 1:
- spacer = ',' * comma + ' '
+ spacer = ccomma + ' '
item = self.start
# An iterator would be a nicer way to walk along the 1d array, but
# how do I reset it if printing ellipsis? iterators have no
# "set_offset()"
i = 0
if use_ellipsis:
- for i in range(3):
- if start:
- start = False
- else:
+ for i in range(min(3, self.shape[0])):
+ if i > 0:
builder.append(spacer)
builder.append(dtype.itemtype.str_format(self.getitem(item)))
item += self.strides[0]
- # Add a comma only if comma is False - this prevents adding two
- # commas
- builder.append(spacer + '...' + ',' * (1 - comma))
- # Ugly, but can this be done with an iterator?
- item = self.start + self.backstrides[0] - 2 * self.strides[0]
- i = self.shape[0] - 3
+ if i < self.shape[0] - 1:
+ # Add a comma only if comma is False - this prevents adding
+ # two commas
+ builder.append(spacer + '...' + ncomma)
+ # Ugly, but can this be done with an iterator?
+ item = self.start + self.backstrides[0] - 2 * self.strides[0]
+ i = self.shape[0] - 3
+ else:
+ i += 1
while i < self.shape[0]:
- if start:
- start = False
- else:
+ if i > 0:
builder.append(spacer)
builder.append(dtype.itemtype.str_format(self.getitem(item)))
item += self.strides[0]
i += 1
- else:
- builder.append('[')
builder.append(']')
@jit.unroll_safe
@@ -1025,9 +1037,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:
@@ -1037,7 +1049,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):
@@ -1180,6 +1192,7 @@
shape = GetSetProperty(BaseArray.descr_get_shape,
BaseArray.descr_set_shape),
size = GetSetProperty(BaseArray.descr_get_size),
+ ndim = GetSetProperty(BaseArray.descr_get_ndim),
T = GetSetProperty(BaseArray.descr_get_transpose),
flat = GetSetProperty(BaseArray.descr_get_flatiter),
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,9 +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
@@ -11,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
@@ -158,6 +158,7 @@
assert calc_new_strides([24], [2, 4, 3], [48, 6, 1]) is None
assert calc_new_strides([24], [2, 4, 3], [24, 6, 2]) == [2]
+
class AppTestNumArray(BaseNumpyAppTest):
def test_ndarray(self):
from numpypy import ndarray, array, dtype
@@ -179,6 +180,19 @@
ar = array(range(5))
assert type(ar) is type(ar + ar)
+ def test_ndim(self):
+ from numpypy import array
+ x = array(0.2)
+ assert x.ndim == 0
+ x = array([1,2])
+ assert x.ndim == 1
+ x = array([[1,2], [3,4]])
+ assert x.ndim == 2
+ x = array([[[1,2], [3,4]], [[5,6], [7,8]] ])
+ assert x.ndim == 3
+ # numpy actually raises an AttributeError, but numpypy raises an AttributeError
+ raises (TypeError, 'x.ndim=3')
+
def test_init(self):
from numpypy import zeros
a = zeros(15)
@@ -725,19 +739,19 @@
a = identity(0)
assert len(a) == 0
assert a.dtype == dtype('float64')
- assert a.shape == (0,0)
+ assert a.shape == (0, 0)
b = identity(1, dtype=int32)
assert len(b) == 1
assert b[0][0] == 1
- assert b.shape == (1,1)
+ assert b.shape == (1, 1)
assert b.dtype == dtype('int32')
c = identity(2)
- assert c.shape == (2,2)
- assert (c == [[1,0],[0,1]]).all()
+ assert c.shape == (2, 2)
+ assert (c == [[1, 0], [0, 1]]).all()
d = identity(3, dtype='int32')
- assert d.shape == (3,3)
+ assert d.shape == (3, 3)
assert d.dtype == dtype('int32')
- assert (d == [[1,0,0],[0,1,0],[0,0,1]]).all()
+ assert (d == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]).all()
def test_prod(self):
from numpypy import array
@@ -898,6 +912,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)
@@ -945,13 +968,13 @@
def test_tolist_view(self):
from numpypy import array
- a = array([[1,2],[3,4]])
+ a = array([[1, 2], [3, 4]])
assert (a + a).tolist() == [[2, 4], [6, 8]]
def test_tolist_slice(self):
from numpypy import array
a = array([[17.1, 27.2], [40.3, 50.3]])
- assert a[:,0].tolist() == [17.1, 40.3]
+ assert a[:, 0].tolist() == [17.1, 40.3]
assert a[0].tolist() == [17.1, 27.2]
@@ -1081,11 +1104,11 @@
from numpypy import zeros, ones
a = zeros((3, 3))
b = ones((3, 3))
- a[:,1:3] = b[:,1:3]
+ a[:, 1:3] = b[:, 1:3]
assert (a == [[0, 1, 1], [0, 1, 1], [0, 1, 1]]).all()
a = zeros((3, 3))
b = ones((3, 3))
- a[:,::2] = b[:,::2]
+ a[:, ::2] = b[:, ::2]
assert (a == [[1, 0, 1], [1, 0, 1], [1, 0, 1]]).all()
def test_broadcast_ufunc(self):
@@ -1224,6 +1247,7 @@
assert isinstance(i['data'][0], int)
raises(TypeError, getattr, array(3), '__array_interface__')
+
class AppTestSupport(BaseNumpyAppTest):
def setup_class(cls):
import struct
@@ -1266,17 +1290,17 @@
assert g[1] == 2
assert g[2] == 3
h = fromstring("1, , 2, 3", dtype=uint8, sep=",")
- assert (h == [1,0,2,3]).all()
+ assert (h == [1, 0, 2, 3]).all()
i = fromstring("1 2 3", dtype=uint8, sep=" ")
- assert (i == [1,2,3]).all()
+ assert (i == [1, 2, 3]).all()
j = fromstring("1\t\t\t\t2\t3", dtype=uint8, sep="\t")
- assert (j == [1,2,3]).all()
+ assert (j == [1, 2, 3]).all()
k = fromstring("1,x,2,3", dtype=uint8, sep=",")
- assert (k == [1,0]).all()
+ assert (k == [1, 0]).all()
l = fromstring("1,x,2,3", dtype='float32', sep=",")
- assert (l == [1.0,-1.0]).all()
+ assert (l == [1.0, -1.0]).all()
m = fromstring("1,,2,3", sep=",")
- assert (m == [1.0,-1.0,2.0,3.0]).all()
+ assert (m == [1.0, -1.0, 2.0, 3.0]).all()
n = fromstring("3.4 2.0 3.8 2.2", dtype=int32, sep=" ")
assert (n == [3]).all()
o = fromstring("1.0 2f.0f 3.8 2.2", dtype=float32, sep=" ")
@@ -1324,7 +1348,6 @@
j = fromstring(self.ulongval, dtype='L')
assert j[0] == 12
-
def test_fromstring_invalid(self):
from numpypy import fromstring, uint16, uint8, int32
#default dtype is 64-bit float, so 3 bytes should fail
@@ -1338,6 +1361,7 @@
class AppTestRepr(BaseNumpyAppTest):
def test_repr(self):
from numpypy import array, zeros
+ intSize = array(5).dtype.itemsize
a = array(range(5), float)
assert repr(a) == "array([0.0, 1.0, 2.0, 3.0, 4.0])"
a = array([], float)
@@ -1345,14 +1369,26 @@
a = zeros(1001)
assert repr(a) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
a = array(range(5), long)
- assert repr(a) == "array([0, 1, 2, 3, 4])"
+ if a.dtype.itemsize == intSize:
+ assert repr(a) == "array([0, 1, 2, 3, 4])"
+ else:
+ assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int64)"
+ a = array(range(5), 'int32')
+ if a.dtype.itemsize == intSize:
+ assert repr(a) == "array([0, 1, 2, 3, 4])"
+ else:
+ assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int32)"
a = array([], long)
assert repr(a) == "array([], dtype=int64)"
a = array([True, False, True, False], "?")
assert repr(a) == "array([True, False, True, False], dtype=bool)"
+ a = zeros([])
+ assert repr(a) == "array(0.0)"
+ a = array(0.2)
+ assert repr(a) == "array(0.2)"
def test_repr_multi(self):
- from numpypy import array, zeros
+ from numpypy import arange, zeros
a = zeros((3, 4))
assert repr(a) == '''array([[0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0],
@@ -1365,6 +1401,16 @@
[[0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0]]])'''
+ a = arange(1002).reshape((2, 501))
+ assert repr(a) == '''array([[0, 1, 2, ..., 498, 499, 500],
+ [501, 502, 503, ..., 999, 1000, 1001]])'''
+ assert repr(a.T) == '''array([[0, 501],
+ [1, 502],
+ [2, 503],
+ ...,
+ [498, 999],
+ [499, 1000],
+ [500, 1001]])'''
def test_repr_slice(self):
from numpypy import array, zeros
@@ -1408,7 +1454,7 @@
a = zeros((400, 400), dtype=int)
assert str(a) == "[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n" \
- " [0 0 0 ..., 0 0 0]\n ..., \n [0 0 0 ..., 0 0 0]\n" \
+ " [0 0 0 ..., 0 0 0]\n ...,\n [0 0 0 ..., 0 0 0]\n" \
" [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]"
a = zeros((2, 2, 2))
r = str(a)
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
@@ -8,10 +8,12 @@
from pypy.tool import logparser
from pypy.jit.tool.jitoutput import parse_prof
from pypy.module.pypyjit.test_pypy_c.model import (Log, find_ids_range,
- find_ids, TraceWithIds,
+ find_ids,
OpMatcher, InvalidMatch)
class BaseTestPyPyC(object):
+ log_string = 'jit-log-opt,jit-log-noopt,jit-log-virtualstate,jit-summary'
+
def setup_class(cls):
if '__pypy__' not in sys.builtin_module_names:
py.test.skip("must run this test with pypy")
@@ -52,8 +54,7 @@
cmdline += ['--jit', ','.join(jitcmdline)]
cmdline.append(str(self.filepath))
#
- print cmdline, logfile
- env={'PYPYLOG': 'jit-log-opt,jit-log-noopt,jit-log-virtualstate,jit-summary:' + str(logfile)}
+ env={'PYPYLOG': self.log_string + ':' + str(logfile)}
pipe = subprocess.Popen(cmdline,
env=env,
stdout=subprocess.PIPE,
diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
@@ -98,7 +98,8 @@
end = time.time()
return end - start
#
- log = self.run(main, [get_libc_name(), 200], threshold=150)
+ log = self.run(main, [get_libc_name(), 200], threshold=150,
+ import_site=True)
assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead
loops = log.loops_by_id('sleep')
assert len(loops) == 1 # make sure that we actually JITted the loop
@@ -121,7 +122,7 @@
return fabs._ptr.getaddr(), x
libm_name = get_libm_name(sys.platform)
- log = self.run(main, [libm_name])
+ log = self.run(main, [libm_name], import_site=True)
fabs_addr, res = log.result
assert res == -4.0
loop, = log.loops_by_filename(self.filepath)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -15,7 +15,7 @@
i += letters[i % len(letters)] == uletters[i % len(letters)]
return i
- log = self.run(main, [300])
+ log = self.run(main, [300], import_site=True)
assert log.result == 300
loop, = log.loops_by_filename(self.filepath)
assert loop.match("""
@@ -55,7 +55,7 @@
i += int(long(string.digits[i % len(string.digits)], 16))
return i
- log = self.run(main, [1100])
+ log = self.run(main, [1100], import_site=True)
assert log.result == main(1100)
loop, = log.loops_by_filename(self.filepath)
assert loop.match("""
diff --git a/pypy/module/sys/app.py b/pypy/module/sys/app.py
--- a/pypy/module/sys/app.py
+++ b/pypy/module/sys/app.py
@@ -66,11 +66,11 @@
return None
copyright_str = """
-Copyright 2003-2011 PyPy development team.
+Copyright 2003-2012 PyPy development team.
All Rights Reserved.
For further information, see <http://pypy.org>
-Portions Copyright (c) 2001-2008 Python Software Foundation.
+Portions Copyright (c) 2001-2012 Python Software Foundation.
All Rights Reserved.
Portions Copyright (c) 2000 BeOpen.com.
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/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -528,6 +528,9 @@
set_param(driver, name1, int(value))
except ValueError:
raise
+ break
+ else:
+ raise ValueError
set_user_param._annspecialcase_ = 'specialize:arg(0)'
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
@@ -24,27 +24,24 @@
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)
+ return self.res
def getdescr(self):
return self.descr
- def _getvar(self, v):
- return v
-
def is_guard(self):
return self._is_guard
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)
@@ -53,8 +50,6 @@
def __repr__(self):
return self.repr()
- ## return '<%s (%s)>' % (self.name, ', '.join([repr(a)
- ## for a in self.args]))
class SimpleParser(OpParser):
@@ -146,18 +141,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,
@@ -165,7 +169,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)
@@ -181,7 +185,10 @@
return self.code.map[self.bytecode_no]
def getlineno(self):
- return self.getopcode().lineno
+ code = self.getopcode()
+ if code is None:
+ return None
+ return code.lineno
lineno = property(getlineno)
def getline_starts_here(self):
@@ -220,7 +227,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
"""
@@ -246,13 +254,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
@@ -300,7 +308,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)
@@ -385,18 +393,27 @@
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 = [i for i, op in enumerate(trace.operations)
- if op.name == 'label']
- labels = [0] + labels + [len(trace.operations) - 1]
+ 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
@@ -407,11 +424,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/storage.py b/pypy/tool/jitlogparser/storage.py
--- a/pypy/tool/jitlogparser/storage.py
+++ b/pypy/tool/jitlogparser/storage.py
@@ -6,7 +6,6 @@
import py
import os
from lib_pypy.disassembler import dis
-from pypy.tool.jitlogparser.parser import Function
from pypy.tool.jitlogparser.module_finder import gather_all_code_objs
class LoopStorage(object):
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, split_trace, 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("""
@@ -236,16 +240,46 @@
loop = parse('''
[i7]
i9 = int_lt(i7, 1003)
- label(i9)
+ label(i9, descr=grrr)
guard_true(i9, descr=<Guard2>) []
i13 = getfield_raw(151937600, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
- label(i13)
+ 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
@@ -13,7 +13,8 @@
ATM this only works with PyPy translated with Boehm or
the semispace or generation GCs.
--timeout=N limit execution time to N (real-time) seconds.
- --log=FILE log all user input into the FILE
+ --log=FILE log all user input into the FILE.
+ --verbose log all proxied system calls.
Note that you can get readline-like behavior with a tool like 'ledit',
provided you use enough -u options:
@@ -26,18 +27,19 @@
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
argv0 = '/bin/pypy-c'
virtual_cwd = '/tmp'
virtual_env = {}
virtual_console_isatty = True
- def __init__(self, executable, arguments, tmpdir=None):
+ def __init__(self, executable, arguments, tmpdir=None, debug=True):
self.executable = executable = os.path.abspath(executable)
self.tmpdir = tmpdir
+ self.debug = debug
super(PyPySandboxedProc, self).__init__([self.argv0] + arguments,
executable=executable)
@@ -67,12 +69,13 @@
if __name__ == '__main__':
from getopt import getopt # and not gnu_getopt!
- options, arguments = getopt(sys.argv[1:], 't:h',
+ options, arguments = getopt(sys.argv[1:], 't:hv',
['tmp=', 'heapsize=', 'timeout=', 'log=',
- 'help'])
+ 'verbose', 'help'])
tmpdir = None
timeout = None
logfile = None
+ debug = False
extraoptions = []
def help():
@@ -104,6 +107,8 @@
timeout = int(value)
elif option == '--log':
logfile = value
+ elif option in ['-v', '--verbose']:
+ debug = True
elif option in ['-h', '--help']:
help()
else:
@@ -113,7 +118,7 @@
help()
sandproc = PyPySandboxedProc(arguments[0], extraoptions + arguments[1:],
- tmpdir=tmpdir)
+ tmpdir=tmpdir, debug=debug)
if timeout is not None:
sandproc.settimeout(timeout, interrupt_main=True)
if logfile is not None:
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
@@ -4,25 +4,29 @@
for the outer process, which can run CPython or PyPy.
"""
-import py
import sys, os, posixpath, errno, stat, time
-from pypy.tool.ansi_print import AnsiLog
import subprocess
from pypy.tool.killsubprocess import killsubprocess
from pypy.translator.sandbox.vfs import UID, GID
+import py
-class MyAnsiLog(AnsiLog):
- KW_TO_COLOR = {
- 'call': ((34,), False),
- 'result': ((34,), False),
- 'exception': ((34,), False),
- 'vpath': ((35,), False),
- 'timeout': ((1, 31), True),
- }
+def create_log():
+ """Make and return a log for the sandbox to use, if needed."""
+ # These imports are local to avoid importing pypy if we don't need to.
+ from pypy.tool.ansi_print import AnsiLog
-log = py.log.Producer("sandlib")
-py.log.setconsumer("sandlib", MyAnsiLog())
+ class MyAnsiLog(AnsiLog):
+ KW_TO_COLOR = {
+ 'call': ((34,), False),
+ 'result': ((34,), False),
+ 'exception': ((34,), False),
+ 'vpath': ((35,), False),
+ 'timeout': ((1, 31), True),
+ }
+ log = py.log.Producer("sandlib")
+ py.log.setconsumer("sandlib", MyAnsiLog())
+ return log
# Note: we use lib_pypy/marshal.py instead of the built-in marshal
# for two reasons. The built-in module could be made to segfault
@@ -30,8 +34,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()
@@ -126,6 +131,7 @@
for the external functions xxx that you want to support.
"""
debug = False
+ log = None
os_level_sandboxing = False # Linux only: /proc/PID/seccomp
def __init__(self, args, executable=None):
@@ -142,6 +148,9 @@
self.currenttimeout = None
self.currentlyidlefrom = None
+ if self.debug:
+ self.log = create_log()
+
def withlock(self, function, *args, **kwds):
lock = self.popenlock
if lock is not None:
@@ -169,7 +178,8 @@
if delay <= 0.0:
break # expired!
time.sleep(min(delay*1.001, 1))
- log.timeout("timeout!")
+ if self.log:
+ self.log.timeout("timeout!")
self.kill()
#if interrupt_main:
# if hasattr(os, 'kill'):
@@ -246,22 +256,22 @@
args = read_message(child_stdout)
except EOFError, e:
break
- if self.debug and not self.is_spam(fnname, *args):
- log.call('%s(%s)' % (fnname,
+ if self.log and not self.is_spam(fnname, *args):
+ self.log.call('%s(%s)' % (fnname,
', '.join([shortrepr(x) for x in args])))
try:
answer, resulttype = self.handle_message(fnname, *args)
except Exception, e:
tb = sys.exc_info()[2]
write_exception(child_stdin, e, tb)
- if self.debug:
+ if self.log:
if str(e):
- log.exception('%s: %s' % (e.__class__.__name__, e))
+ self.log.exception('%s: %s' % (e.__class__.__name__, e))
else:
- log.exception('%s' % (e.__class__.__name__,))
+ self.log.exception('%s' % (e.__class__.__name__,))
else:
- if self.debug and not self.is_spam(fnname, *args):
- log.result(shortrepr(answer))
+ if self.log and not self.is_spam(fnname, *args):
+ self.log.result(shortrepr(answer))
try:
write_message(child_stdin, 0) # error code - 0 for ok
write_message(child_stdin, answer, resulttype)
@@ -440,7 +450,8 @@
node = dirnode.join(name)
else:
node = dirnode
- log.vpath('%r => %r' % (vpath, node))
+ if self.log:
+ self.log.vpath('%r => %r' % (vpath, node))
return node
def do_ll_os__ll_os_stat(self, vpathname):
More information about the pypy-commit
mailing list