Author: Maciej Fijalkowski <fij...@gmail.com> Branch: optresult-unroll Changeset: r79238:ebc71358494b Date: 2015-08-27 01:21 +0200 http://bitbucket.org/pypy/pypy/changeset/ebc71358494b/
Log: start reworking virtualstate 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 @@ -202,14 +202,13 @@ jitcelltoken = jump_op.getdescr() virtual_state = self.get_virtual_state(jump_op.getarglist()) args = [self.get_box_replacement(op) for op in jump_op.getarglist()] - infos = [self.optimizer.getinfo(arg) for arg in args] for target_token in jitcelltoken.target_tokens: target_virtual_state = target_token.virtual_state if target_virtual_state is None: continue try: extra_guards = target_virtual_state.generate_guards( - virtual_state, args, infos, self.optimizer.cpu) + virtual_state, args, jump_op.getarglist(), self.optimizer) patchguardop = self.optimizer.patchguardop for guard in extra_guards.extra_guards: if isinstance(guard, GuardResOp): diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py @@ -1,13 +1,11 @@ from rpython.jit.metainterp.walkvirtual import VirtualVisitor -from rpython.jit.metainterp.history import (ConstInt, Const, - ConstPtr, ConstFloat) +from rpython.jit.metainterp.history import ConstInt, ConstPtr, ConstFloat from rpython.jit.metainterp.optimizeopt import info from rpython.jit.metainterp.optimizeopt.intutils import \ - ConstIntBound, MININT, MAXINT, IntBound + MININT, MAXINT, IntBound from rpython.jit.metainterp.resoperation import rop, ResOperation,\ - AbstractInputArg -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.objectmodel import we_are_translated + InputArgInt, InputArgRef, InputArgFloat +from rpython.rlib.debug import debug_print LEVEL_UNKNOWN = '\x00' LEVEL_NONNULL = '\x01' @@ -22,16 +20,11 @@ self.msg = msg self.state = state -def get_forwarded(box): - if not isinstance(box, Const): - return box.get_forwarded() - if box.type == 'i': - return ConstIntBound(box.getint()) - xxx class GenerateGuardState(object): - def __init__(self, cpu=None, guards=None, renum=None, bad=None): - self.cpu = cpu + def __init__(self, optimizer=None, guards=None, renum=None, bad=None): + self.optimizer = optimizer + self.cpu = optimizer.cpu if guards is None: guards = [] self.extra_guards = guards @@ -42,20 +35,29 @@ bad = {} self.bad = bad + def get_runtime_field(self, box, descr): + if descr.is_pointer_field(): + xxx + elif descr.is_float_field(): + yyy + else: + struct = box.getref_base() + return InputArgInt(self.cpu.bh_getfield_gc_i(struct, descr)) + class AbstractVirtualStateInfo(object): position = -1 - def generate_guards(self, other, op, opinfo, state): + def generate_guards(self, other, op, runtime_op, state): """ generate guards (output in the list extra_guards) that make runtime values of the shape other match the shape of self. if that's not possible, VirtualStatesCantMatch is thrown and bad gets keys set which parts of the state are the problem. - the function can peek into opinfo (and particularly also the op) + the function can peek into the information about the op, as well + as runtime value (passed in runtime_op) as a guiding heuristic whether making such guards makes sense. if None is passed in for op, no guard is ever generated, and this function degenerates to a generalization check.""" - assert opinfo is None or opinfo.is_constant() or isinstance(opinfo, info.AbstractInfo) assert self.position != -1 if self.position in state.renum: if state.renum[self.position] != other.position: @@ -69,14 +71,14 @@ else: state.renum[self.position] = other.position try: - self._generate_guards(other, op, opinfo, state) + self._generate_guards(other, op, runtime_op, state) except VirtualStatesCantMatch, e: state.bad[self] = state.bad[other] = None if e.state is None: e.state = state raise e - def _generate_guards(self, other, value, state): + def _generate_guards(self, other, box, runtime_box, state): raise VirtualStatesCantMatch( 'Generating guards for making the VirtualStates ' + 'at hand match have not been implemented') @@ -114,14 +116,15 @@ def __init__(self, fielddescrs): self.fielddescrs = fielddescrs - def _generate_guards(self, other, box, opinfo, state): + def _generate_guards(self, other, box, runtime_box, state): if not self._generalization_of_structpart(other): raise VirtualStatesCantMatch("different kinds of structs") assert isinstance(other, AbstractVirtualStructStateInfo) assert len(self.fielddescrs) == len(self.fieldstate) assert len(other.fielddescrs) == len(other.fieldstate) - if box is not None: + opinfo = state.optimizer.getptrinfo(box) + if runtime_box is not None: assert opinfo.is_virtual() if len(self.fielddescrs) != len(other.fielddescrs): @@ -130,21 +133,18 @@ for i in range(len(self.fielddescrs)): if other.fielddescrs[i] is not self.fielddescrs[i]: raise VirtualStatesCantMatch("field descrs don't match") - if box is not None: + if runtime_box is not None: fieldbox = opinfo._fields[self.fielddescrs[i].get_index()] # must be there - if fieldbox is not None: - fieldinfo = get_forwarded(fieldbox) - else: - fieldinfo = None + fieldbox_runtime = state.get_runtime_field(runtime_box, + self.fielddescrs[i]) else: fieldbox = None - fieldinfo = None - # XXX all those ifs are for tests, not sure what to do + fieldbox_runtime = None if self.fieldstate[i] is not None: self.fieldstate[i].generate_guards(other.fieldstate[i], fieldbox, - fieldinfo, state) + fieldbox_runtime, state) def _generalization_of_structpart(self, other): @@ -205,6 +205,7 @@ self.arraydescr = arraydescr def _generate_guards(self, other, box, opinfo, state): + xxx if not isinstance(other, VArrayStateInfo): raise VirtualStatesCantMatch("other is not an array") if self.arraydescr is not other.arraydescr: @@ -251,6 +252,7 @@ self.fielddescrs = fielddescrs def _generate_guards(self, other, box, opinfo, state): + xxxx if not isinstance(other, VArrayStructStateInfo): raise VirtualStatesCantMatch("other is not an VArrayStructStateInfo") if self.arraydescr is not other.arraydescr: @@ -344,7 +346,7 @@ def is_virtual(self): return False - def _generate_guards(self, other, box, opinfo, state): + def _generate_guards(self, other, box, runtime_box, state): if self.is_opaque: box = None # generating guards for opaque pointers isn't safe # XXX This will always retrace instead of forcing anything which @@ -365,7 +367,7 @@ if self.level == LEVEL_UNKNOWN: # confusingly enough, this is done also for pointers # which have the full range as the "bound", so it always works - return self._generate_guards_intbounds(other, box, opinfo, + return self._generate_guards_intbounds(other, box, runtime_box, extra_guards) # the following conditions often peek into the runtime value that the @@ -375,7 +377,7 @@ # will always generate correct behaviour, but performance will differ. elif self.level == LEVEL_NONNULL: if other.level == LEVEL_UNKNOWN: - if box is not None and box.nonnull(): + if runtime_box is not None and runtime_box.nonnull(): op = ResOperation(rop.GUARD_NONNULL, [box], None) extra_guards.append(op) return @@ -394,15 +396,16 @@ elif self.level == LEVEL_KNOWNCLASS: if other.level == LEVEL_UNKNOWN: - if (box and box.nonnull() and - self.known_class.same_constant(cpu.ts.cls_of_box(box))): + if (runtime_box and runtime_box.nonnull() and + self.known_class.same_constant(cpu.ts.cls_of_box(runtime_box))): op = ResOperation(rop.GUARD_NONNULL_CLASS, [box, self.known_class], None) extra_guards.append(op) return else: raise VirtualStatesCantMatch("other's class is unknown") elif other.level == LEVEL_NONNULL: - if box and self.known_class.same_constant(cpu.ts.cls_of_box(box)): + if (runtime_box and self.known_class.same_constant( + cpu.ts.cls_of_box(runtime_box))): op = ResOperation(rop.GUARD_CLASS, [box, self.known_class], None) extra_guards.append(op) return @@ -426,7 +429,7 @@ if self.constbox.same_constant(other.constbox): return raise VirtualStatesCantMatch("different constants") - if box is not None and self.constbox.same_constant(box.constbox()): + if runtime_box is not None and self.constbox.same_constant(runtime_box.constbox()): op = ResOperation(rop.GUARD_VALUE, [box, self.constbox], None) extra_guards.append(op) return @@ -434,12 +437,13 @@ raise VirtualStatesCantMatch("other not constant") assert 0, "unreachable" - def _generate_guards_intbounds(self, other, box, opinfo, extra_guards): + def _generate_guards_intbounds(self, other, box, runtime_box, extra_guards): if self.intbound is None: return if self.intbound.contains_bound(other.intbound): return - if (box is not None and self.intbound.contains(box.getint())): + if (runtime_box is not None and + self.intbound.contains(runtime_box.getint())): # this may generate a few more guards than needed, but they are # optimized away when emitting them self.intbound.make_guards(box, extra_guards) @@ -523,12 +527,13 @@ return False return True - def generate_guards(self, other, boxes, infos, cpu): - assert len(self.state) == len(other.state) == len(boxes) == len(infos) - state = GenerateGuardState(cpu) + def generate_guards(self, other, boxes, runtime_boxes, optimizer): + assert (len(self.state) == len(other.state) == len(boxes) == + len(runtime_boxes)) + state = GenerateGuardState(optimizer) for i in range(len(self.state)): - self.state[i].generate_guards(other.state[i], boxes[i], infos[i], - state) + self.state[i].generate_guards(other.state[i], boxes[i], + runtime_boxes[i], state) return state def make_inputargs(self, inputargs, optimizer, force_boxes=False, @@ -578,24 +583,6 @@ def already_seen_virtual(self, keybox): return keybox in self.fieldboxes - #def state(self, box): - # xxx - # value = self.getvalue(box) - # box = value.get_key_box() - # try: - # info = self.info[box] - # except KeyError: - # self.info[box] = info = value.visitor_dispatch_virtual_type(self) - # if value.is_virtual(): - # flds = self.fieldboxes[box] - # info.fieldstate = [self.state_or_none(b, value) for b in flds] - # return info - - #def state_or_none(self, box, value): - # if box is None: - # box = value.get_missing_null_value().box - # return self.state(box) - def create_state_or_none(self, box, opt): if box is None: return None diff --git a/rpython/jit/metainterp/test/test_del.py b/rpython/jit/metainterp/test/test_del.py --- a/rpython/jit/metainterp/test/test_del.py +++ b/rpython/jit/metainterp/test/test_del.py @@ -22,7 +22,7 @@ n -= 1 return 42 self.meta_interp(f, [20]) - self.check_resops({'call': 4, # calls to a helper function + self.check_resops({'call_r': 4, # calls to a helper function 'guard_no_exception': 4, # follows the calls 'int_sub': 2, 'int_gt': 2, @@ -80,7 +80,7 @@ return 1 res = self.meta_interp(f, [20], enable_opts='') assert res == 1 - self.check_resops(call=1) # for the case B(), but not for the case A() + self.check_resops(call_r=1) # for the case B(), but not for the case A() def test_keepalive(self): py.test.skip("XXX fails") # hum, I think the test itself is broken diff --git a/rpython/jit/metainterp/test/test_dict.py b/rpython/jit/metainterp/test/test_dict.py --- a/rpython/jit/metainterp/test/test_dict.py +++ b/rpython/jit/metainterp/test/test_dict.py @@ -190,11 +190,11 @@ # not cached anyway. res = self.meta_interp(f, [100], listops=True) assert res == f(50) - self.check_resops({'new_array_clear': 2, 'getfield_gc': 2, + self.check_resops({'new_array_clear': 2, 'getfield_gc_r': 2, 'guard_true': 4, 'jump': 1, - 'new_with_vtable': 2, 'getinteriorfield_gc': 2, + 'new_with_vtable': 2, 'getinteriorfield_gc_i': 2, 'setfield_gc': 14, 'int_gt': 2, 'int_sub': 2, - 'call': 10, 'int_ge': 2, + 'call_i': 6, 'call_n': 2, 'call_r': 2, 'int_ge': 2, 'guard_no_exception': 8, 'new': 2}) def test_unrolling_of_dict_iter(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit