[pypy-svn] pypy jit-virtual_state: Generate guards instead of retracing when it is likely it will pass and thereby make the excisting compiled loop reusable
hakanardo
commits-noreply at bitbucket.org
Sun Feb 6 12:58:33 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-virtual_state
Changeset: r41645:22bd566e537d
Date: 2011-02-06 12:56 +0100
http://bitbucket.org/pypy/pypy/changeset/22bd566e537d/
Log: Generate guards instead of retracing when it is likely it will pass
and thereby make the excisting compiled loop reusable
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
@@ -105,12 +105,14 @@
newop.result = newop.result.clonebox()
self.argmap[old_result] = newop.result
- descr = newop.getdescr()
+ self.inline_descr_inplace(newop.getdescr())
+
+ return newop
+
+ def inline_descr_inplace(self, descr):
if isinstance(descr, ResumeGuardDescr):
descr.rd_snapshot = self.inline_snapshot(descr.rd_snapshot)
-
- return newop
-
+
def inline_arg(self, arg):
if arg is None:
return None
@@ -137,6 +139,12 @@
return False
return True
+ def generate_guards(self, other, args, cpu, extra_guards):
+ assert len(self.state) == len(other.state) == len(args)
+ for i in range(len(self.state)):
+ self.state[i].generate_guards(other.state[i], args[i],
+ cpu, extra_guards)
+
class VirtualStateAdder(resume.ResumeDataVirtualAdder):
def __init__(self, optimizer):
self.fieldboxes = {}
@@ -200,6 +208,29 @@
return False
return self.intbound.contains_bound(other.intbound)
+ def _generate_guards(self, other, box, cpu, extra_guards):
+ if not isinstance(other, NotVirtualInfo):
+ raise InvalidLoop
+ if self.level == LEVEL_KNOWNCLASS and \
+ box.value and \
+ self.known_class.same_constant(cpu.ts.cls_of_box(box)):
+ # Note: This is only a hint on what the class of box was
+ # during the trace. There are actually no guarentees that this
+ # box realy comes from a trace. The hint is used here to choose
+ # between either eimtting a guard_class and jumping to an
+ # excisting compiled loop or retracing the loop. Both
+ # alternatives will always generate correct behaviour, but
+ # performace will differ.
+ op = ResOperation(rop.GUARD_CLASS, [box, self.known_class], None)
+ extra_guards.append(op)
+ return
+ # Remaining cases are probably not interesting
+ raise InvalidLoop
+ if self.level == LEVEL_CONSTANT:
+ import pdb; pdb.set_trace()
+ raise NotImplementedError
+
+
class UnrollOptimizer(Optimization):
"""Unroll the loop into two iterations. The first one will
become the preamble or entry bridge (don't think there is a
@@ -281,6 +312,9 @@
short_loop.inputargs = newargs
ops = [inliner.inline_op(op) for op in short_loop.operations]
short_loop.operations = ops
+ descr = start_resumedescr.clone_if_mutable()
+ inliner.inline_descr_inplace(descr)
+ short_loop.start_resumedescr = descr
assert isinstance(loop.preamble.token, LoopToken)
if loop.preamble.token.short_preamble:
@@ -585,6 +619,7 @@
class OptInlineShortPreamble(Optimization):
def __init__(self, retraced):
self.retraced = retraced
+ self.inliner = None
def reconstruct_for_next_iteration(self, optimizer, valuemap):
@@ -604,14 +639,32 @@
args = op.getarglist()
modifier = VirtualStateAdder(self.optimizer)
virtual_state = modifier.get_virtual_state(args)
- for sh in short:
+ for sh in short:
+ ok = False
+ extra_guards = []
if sh.virtual_state.generalization_of(virtual_state):
+ ok = True
+ else:
+ try:
+ cpu = self.optimizer.cpu
+ sh.virtual_state.generate_guards(virtual_state,
+ args, cpu,
+ extra_guards)
+ ok = True
+ except InvalidLoop:
+ pass
+ if ok:
# FIXME: Do we still need the dry run
#if self.inline(sh.operations, sh.inputargs,
# op.getarglist(), dryrun=True):
try:
self.inline(sh.operations, sh.inputargs,
op.getarglist())
+ for guard in extra_guards:
+ descr = sh.start_resumedescr.clone_if_mutable()
+ self.inliner.inline_descr_inplace(descr)
+ guard.setdescr(descr)
+ self.emit_operation(guard)
except InvalidLoop:
debug_print("Inlining failed unexpectedly",
"jumping to preamble instead")
@@ -624,7 +677,7 @@
def inline(self, loop_operations, loop_args, jump_args, dryrun=False):
- inliner = Inliner(loop_args, jump_args)
+ self.inliner = inliner = Inliner(loop_args, jump_args)
for op in loop_operations:
newop = inliner.inline_op(op)
@@ -637,7 +690,7 @@
return True
- def inline_arg(self, arg):
- if isinstance(arg, Const):
- return arg
- return self.argmap[arg]
+ #def inline_arg(self, arg):
+ # if isinstance(arg, Const):
+ # return arg
+ # return self.argmap[arg]
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -10,6 +10,7 @@
from pypy.rlib.objectmodel import we_are_translated, specialize
from pypy.rlib.debug import have_debug_prints, ll_assert
from pypy.rlib.debug import debug_start, debug_stop, debug_print
+from pypy.jit.metainterp.optimizeutil import InvalidLoop
# Logic to encode the chain of frames and the state of the boxes at a
# guard operation, and to decode it again. This is a bit advanced,
@@ -427,12 +428,24 @@
# raise NotImplementedError
def equals(self, fieldnums):
return tagged_list_eq(self.fieldnums, fieldnums)
+
def set_content(self, fieldnums):
self.fieldnums = fieldnums
def debug_prints(self):
raise NotImplementedError
+ def generalization_of(self, other):
+ raise NotImplementedError
+
+ def generate_guards(self, other, box, cpu, extra_guards):
+ if self.generalization_of(other):
+ return
+ self._generate_guards(other, box, cpu, extra_guards)
+
+ def _generate_guards(self, other, box, cpu, extra_guards):
+ raise NotImplementedError
+
class AbstractVirtualStructInfo(AbstractVirtualInfo):
def __init__(self, fielddescrs):
self.fielddescrs = fielddescrs
@@ -468,6 +481,9 @@
def _generalization_of(self, other):
raise NotImplementedError
+
+ def _generate_guards(self, other, box, cpu, extra_guards):
+ raise InvalidLoop
More information about the Pypy-commit
mailing list