[pypy-commit] pypy pypy-dont-copy-ops: start working on lack of copying of ops
fijal
noreply at buildbot.pypy.org
Thu Dec 25 21:47:15 CET 2014
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: pypy-dont-copy-ops
Changeset: r75121:1fd614fe5b30
Date: 2014-12-25 22:35 +0200
http://bitbucket.org/pypy/pypy/changeset/1fd614fe5b30/
Log: start working on lack of copying of ops
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -123,9 +123,10 @@
part = create_empty_loop(metainterp)
part.inputargs = inputargs[:]
h_ops = history.operations
- 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)]
+ label = ResOperation(rop.LABEL, inputargs, None,
+ descr=TargetToken(jitcell_token))
+ end_label = ResOperation(rop.LABEL, jumpargs, None, descr=jitcell_token)
+ part.operations = [label] + h_ops + [end_label]
try:
start_state = optimize_trace(metainterp_sd, part, enable_opts,
@@ -203,7 +204,7 @@
h_ops = history.operations
part.operations = [partial_trace.operations[-1]] + \
- [h_ops[i].clone() for i in range(start, len(h_ops))] + \
+ h_ops + \
[ResOperation(rop.JUMP, jumpargs, None, descr=loop_jitcell_token)]
label = part.operations[0]
orignial_label = label.clone()
@@ -783,7 +784,7 @@
new_trace.inputargs = metainterp.history.inputargs[:]
# clone ops, as optimize_bridge can mutate the ops
- new_trace.operations = [op.clone() for op in metainterp.history.operations]
+ new_trace.operations = metainterp.history.operations[:]
metainterp_sd = metainterp.staticdata
state = metainterp.jitdriver_sd.warmstate
if isinstance(resumekey, ResumeAtPositionDescr):
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -74,7 +74,7 @@
if other.getlevel() == LEVEL_CONSTANT:
self.make_constant(other.get_key_box())
elif other.getlevel() == LEVEL_KNOWNCLASS:
- self.make_constant_class(other.get_known_class(), None)
+ self.make_constant_class(None, other.get_known_class())
else:
if other.getlevel() == LEVEL_NONNULL:
self.ensure_nonnull()
@@ -192,7 +192,7 @@
self.box = constbox
self.setlevel(LEVEL_CONSTANT)
- def get_last_guard(self):
+ def get_last_guard(self, optimizer):
return None
def get_known_class(self):
@@ -208,10 +208,10 @@
return None
class PtrOptValue(OptValue):
- _attrs_ = ('known_class', 'last_guard', 'lenbound')
+ _attrs_ = ('known_class', 'last_guard_pos', 'lenbound')
known_class = None
- last_guard = None
+ last_guard_pos = -1
lenbound = None
def __init__(self, box, level=None, known_class=None, intbound=None):
@@ -224,7 +224,7 @@
self.box = other_value.box
self.known_class = other_value.known_class
self._tag = other_value._tag
- self.last_guard = other_value.last_guard
+ self.last_guard_pos = other_value.last_guard_pos
self.lenbound = other_value.lenbound
def make_len_gt(self, mode, descr, val):
@@ -235,16 +235,17 @@
else:
self.lenbound = LenBound(mode, descr, IntLowerBound(val + 1))
- def make_nonnull(self, guardop):
+ def make_nonnull(self, optimizer):
assert self.getlevel() < LEVEL_NONNULL
self.setlevel(LEVEL_NONNULL)
- self.last_guard = guardop
+ self.last_guard_pos = len(optimizer._newoperations)
- def make_constant_class(self, classbox, guardop):
+ def make_constant_class(self, optimizer, classbox):
assert self.getlevel() < LEVEL_KNOWNCLASS
self.known_class = classbox
self.setlevel(LEVEL_KNOWNCLASS)
- self.last_guard = guardop
+ if optimizer is not None:
+ self.last_guard_pos = len(optimizer._newoperations)
def import_from(self, other, optimizer):
OptValue.import_from(self, other, optimizer)
@@ -299,8 +300,10 @@
def getlenbound(self):
return self.lenbound
- def get_last_guard(self):
- return self.last_guard
+ def get_last_guard(self, optimizer):
+ if self.last_guard_pos == -1:
+ return None
+ return optimizer._newoperations[self.last_guard_pos]
def get_known_class(self):
return self.known_class
@@ -345,7 +348,7 @@
return True
return False
- def make_nonnull(self, guardop):
+ def make_nonnull(self, optimizer):
assert self.getlevel() < LEVEL_NONNULL
self.setlevel(LEVEL_NONNULL)
@@ -545,6 +548,12 @@
self.optimizations = optimizations
+ def replace_guard(self, op, value):
+ assert isinstance(value, PtrOptValue)
+ if value.last_guard_pos == -1:
+ return
+ self.replaces_guard[op] = value.last_guard_pos
+
def force_at_end_of_preamble(self):
for o in self.optimizations:
o.force_at_end_of_preamble()
@@ -705,6 +714,8 @@
@specialize.argtype(0)
def _emit_operation(self, op):
assert op.getopnum() != rop.CALL_PURE
+ changed = False
+ orig_op = op
for i in range(op.numargs()):
arg = op.getarg(i)
try:
@@ -713,32 +724,31 @@
pass
else:
self.ensure_imported(value)
- op.setarg(i, value.force_box(self))
+ newbox = value.force_box(self)
+ if not changed and arg is not newbox:
+ op = op.clone()
+ changed = True
+ op.setarg(i, newbox)
self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
if op.is_guard():
self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS)
pendingfields = self.pendingfields
self.pendingfields = None
- if self.replaces_guard and op in self.replaces_guard:
- self.replace_op(self.replaces_guard[op], op)
+ if self.replaces_guard and orig_op in self.replaces_guard:
+ self.replace_op(self.replaces_guard[orig_op], op)
del self.replaces_guard[op]
return
else:
- op = self.store_final_boxes_in_guard(op, pendingfields)
+ guard_op = op.clone()
+ op = self.store_final_boxes_in_guard(guard_op, pendingfields)
elif op.can_raise():
self.exception_might_have_happened = True
self._newoperations.append(op)
- def replace_op(self, old_op, new_op):
- # XXX: Do we want to cache indexes to prevent search?
- i = len(self._newoperations)
- while i > 0:
- i -= 1
- if self._newoperations[i] is old_op:
- self._newoperations[i] = new_op
- break
- else:
- assert False
+ def replace_op(self, old_op_pos, new_op):
+ old_op = self._newoperations[old_op_pos]
+ assert old_op.is_guard()
+ self._newoperations[old_op_pos] = new_op
def store_final_boxes_in_guard(self, op, pendingfields):
assert pendingfields is not None
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -284,7 +284,7 @@
raise InvalidLoop('A GUARD_NONNULL (%s) was proven to always fail'
% r)
self.emit_operation(op)
- value.make_nonnull(op)
+ value.make_nonnull(self.optimizer)
def optimize_GUARD_VALUE(self, op):
value = self.getvalue(op.getarg(0))
@@ -296,11 +296,11 @@
else:
name = "<unknown>"
raise InvalidLoop('A promote of a virtual %s (a recently allocated object) never makes sense!' % name)
- if value.get_last_guard():
+ old_guard_op = value.get_last_guard(self.optimizer)
+ if old_guard_op:
# there already has been a guard_nonnull or guard_class or
# guard_nonnull_class on this value, which is rather silly.
# replace the original guard with a guard_value
- old_guard_op = value.get_last_guard()
if old_guard_op.getopnum() != rop.GUARD_NONNULL:
# This is only safe if the class of the guard_value matches the
# class of the guard_*_class, otherwise the intermediate ops might
@@ -314,7 +314,7 @@
raise InvalidLoop('A GUARD_VALUE (%s) was proven to always fail' % r)
op = old_guard_op.copy_and_change(rop.GUARD_VALUE,
args = [old_guard_op.getarg(0), op.getarg(1)])
- self.optimizer.replaces_guard[op] = old_guard_op
+ self.optimizer.replace_guard(op, value)
# hack hack hack. Change the guard_opnum on
# new_guard_op.getdescr() so that when resuming,
# the operation is not skipped by pyjitpl.py.
@@ -324,7 +324,7 @@
descr.make_a_counter_per_value(op)
# to be safe
if isinstance(value, PtrOptValue):
- value.last_guard = None
+ value.last_guard_pos = -1
constbox = op.getarg(1)
assert isinstance(constbox, Const)
self.optimize_guard(op, constbox)
@@ -343,7 +343,7 @@
if realclassbox is not None:
assert realclassbox.same_constant(expectedclassbox)
return
- value.make_constant_class(expectedclassbox, None)
+ value.make_constant_class(None, expectedclassbox)
def optimize_GUARD_CLASS(self, op):
value = self.getvalue(op.getarg(0))
@@ -357,16 +357,16 @@
raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail'
% r)
assert isinstance(value, PtrOptValue)
- if value.last_guard:
+ old_guard_op = value.get_last_guard(self.optimizer)
+ if old_guard_op:
# there already has been a guard_nonnull or guard_class or
# guard_nonnull_class on this value.
- old_guard_op = value.last_guard
if old_guard_op.getopnum() == rop.GUARD_NONNULL:
# it was a guard_nonnull, which we replace with a
# guard_nonnull_class.
op = old_guard_op.copy_and_change (rop.GUARD_NONNULL_CLASS,
args = [old_guard_op.getarg(0), op.getarg(1)])
- self.optimizer.replaces_guard[op] = old_guard_op
+ self.optimizer.replace_guard(op, value)
# hack hack hack. Change the guard_opnum on
# new_guard_op.getdescr() so that when resuming,
# the operation is not skipped by pyjitpl.py.
@@ -374,7 +374,7 @@
assert isinstance(descr, compile.ResumeGuardDescr)
descr.guard_opnum = rop.GUARD_NONNULL_CLASS
self.emit_operation(op)
- value.make_constant_class(expectedclassbox, op)
+ value.make_constant_class(self.optimizer, expectedclassbox)
def optimize_GUARD_NONNULL_CLASS(self, op):
value = self.getvalue(op.getarg(0))
diff --git a/rpython/jit/metainterp/optimizeopt/simplify.py b/rpython/jit/metainterp/optimizeopt/simplify.py
--- a/rpython/jit/metainterp/optimizeopt/simplify.py
+++ b/rpython/jit/metainterp/optimizeopt/simplify.py
@@ -48,6 +48,7 @@
def optimize_JUMP(self, op):
if not self.unroll:
+ op = op.clone()
descr = op.getdescr()
assert isinstance(descr, JitCellToken)
if not descr.target_tokens:
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -134,6 +134,7 @@
else:
debug_print("Retrace count reached, jumping to preamble")
assert cell_token.target_tokens[0].virtual_state is None
+ jumpop = jumpop.clone()
jumpop.setdescr(cell_token.target_tokens[0])
self.optimizer.send_extra_operation(jumpop)
return
@@ -506,6 +507,7 @@
self.import_box(a, inputargs, short_jumpargs, jumpargs)
def jump_to_already_compiled_trace(self, jumpop, patchguardop):
+ jumpop = jumpop.clone()
assert jumpop.getopnum() == rop.JUMP
cell_token = jumpop.getdescr()
More information about the pypy-commit
mailing list