def postprocess_UNICODEGETITEM(self, op): b1 = self.getintbound(op) b1.make_ge(IntLowerBound(0)) v2 = self.getptrinfo(op.getarg(0)) intbound = self.getintbound(op.getarg(1)) if (intbound.has_lower and v2 is not None and v2.getlenbound(vstring.mode_unicode) is not None): lb = IntLowerBound(intbound.lower + 1) v2.getlenbound(vstring.mode_unicode).make_ge(lb)
def postprocess_STRGETITEM(self, op): v1 = self.getintbound(op) v2 = self.getptrinfo(op.getarg(0)) intbound = self.getintbound(op.getarg(1)) if (intbound.has_lower and v2 is not None and v2.getlenbound(vstring.mode_string) is not None): lb = IntLowerBound(intbound.lower + 1) v2.getlenbound(vstring.mode_string).make_ge(lb) v1.make_ge(IntLowerBound(0)) v1.make_lt(IntUpperBound(256))
def _generate_guards(self, other, box, runtime_box, state): if state.force_boxes and isinstance(other, VirtualStateInfo): return self._generate_virtual_guards(other, box, runtime_box, state) if not isinstance(other, NotVirtualStateInfoPtr): raise VirtualStatesCantMatch( 'The VirtualStates does not match as a ' + 'virtual appears where a pointer is needed ' + 'and it is too late to force it.') extra_guards = state.extra_guards if self.lenbound: if other.lenbound is None: other_bound = IntLowerBound(0) else: other_bound = other.lenbound if not self.lenbound.contains_bound(other_bound): raise VirtualStatesCantMatch("length bound does not match") if self.level == LEVEL_NONNULL: return self._generate_guards_nonnull(other, box, runtime_box, extra_guards, state) elif self.level == LEVEL_KNOWNCLASS: return self._generate_guards_knownclass(other, box, runtime_box, extra_guards, state) return NotVirtualStateInfo._generate_guards(self, other, box, runtime_box, state)
def optimize_GETFIELD_RAW_I(self, op): self.emit_operation(op) descr = op.getdescr() if descr.is_integer_bounded(): b1 = self.getintbound(op) b1.make_ge(IntLowerBound(descr.get_integer_min())) b1.make_le(IntUpperBound(descr.get_integer_max()))
def optimize_GETARRAYITEM_RAW_I(self, op): self.emit_operation(op) descr = op.getdescr() if descr and descr.is_item_integer_bounded(): intbound = self.getintbound(op) intbound.make_ge(IntLowerBound(descr.get_item_integer_min())) intbound.make_le(IntUpperBound(descr.get_item_integer_max()))
def optimize_GETARRAYITEM_RAW(self, op): self.emit_operation(op) descr = op.getdescr() if descr and descr.is_item_integer_bounded(): v1 = self.getvalue(op.result) v1.getintbound().make_ge(IntLowerBound(descr.get_item_integer_min())) v1.getintbound().make_le(IntUpperBound(descr.get_item_integer_max()))
def bound(a, b): if a is None and b is None: return IntUnbounded() elif a is None: return IntUpperBound(b) elif b is None: return IntLowerBound(a) else: return IntBound(a, b)
def getlenbound(self, mode): from rpython.jit.metainterp.optimizeopt.intutils import ConstIntBound,\ IntLowerBound if mode is None: # XXX we can do better if we know it's an array return IntLowerBound(0) else: return ConstIntBound(self.getstrlen(None, None, mode).getint())
def getlenbound(self, mode): from rpython.jit.metainterp.optimizeopt.intutils import (ConstIntBound, IntLowerBound) length = self.getstrlen1(mode) if length < 0: # XXX we can do better if we know it's an array return IntLowerBound(0) return ConstIntBound(length)
def make_len_gt(self, mode, descr, val): if self.lenbound: if self.lenbound.mode != mode or self.lenbound.descr != descr: # XXX a rare case? it seems to occur sometimes when # running lib-python's test_io.py in PyPy on Linux 32... from rpython.jit.metainterp.optimize import InvalidLoop raise InvalidLoop("bad mode/descr") self.lenbound.bound.make_gt(IntBound(val, val)) else: self.lenbound = LenBound(mode, descr, IntLowerBound(val + 1))
def postprocess_GETARRAYITEM_RAW_I(self, op): descr = op.getdescr() if descr and descr.is_item_integer_bounded(): intbound = self.getintbound(op) intbound.make_ge(IntLowerBound(descr.get_item_integer_min())) intbound.make_le(IntUpperBound(descr.get_item_integer_max()))
def postprocess_GETFIELD_RAW_I(self, op): descr = op.getdescr() if descr.is_integer_bounded(): b1 = self.getintbound(op) b1.make_ge(IntLowerBound(descr.get_integer_min())) b1.make_le(IntUpperBound(descr.get_integer_max()))
def optimize_UNICODEGETITEM(self, op): self.emit_operation(op) v1 = self.getvalue(op.result) v1.getintbound().make_ge(IntLowerBound(0))
def optimize_STRGETITEM(self, op): self.emit_operation(op) v1 = self.getvalue(op.result) v1.getintbound().make_ge(IntLowerBound(0)) v1.getintbound().make_lt(IntUpperBound(256))
def _generate_guards(self, other, box, runtime_box, state): # XXX This will always retrace instead of forcing anything which # might be what we want sometimes? if not isinstance(other, NotVirtualStateInfo): raise VirtualStatesCantMatch( 'The VirtualStates does not match as a ' + 'virtual appears where a pointer is needed ' + 'and it is too late to force it.') extra_guards = state.extra_guards cpu = state.cpu if self.lenbound: if other.lenbound is None: other_bound = IntLowerBound(0) else: other_bound = other.lenbound if not self.lenbound.contains_bound(other_bound): raise VirtualStatesCantMatch("length bound does not match") 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, runtime_box, extra_guards, state.optimizer) # the following conditions often peek into the runtime value that the # box had when tracing. This value is only used as an educated guess. # It is used here to choose between either emitting a guard and jumping # to an existing compiled loop or retracing the loop. Both alternatives # will always generate correct behaviour, but performance will differ. elif self.level == LEVEL_NONNULL: if other.level == LEVEL_UNKNOWN: if runtime_box is not None and runtime_box.nonnull(): op = ResOperation(rop.GUARD_NONNULL, [box]) extra_guards.append(op) return else: raise VirtualStatesCantMatch( "other not known to be nonnull") elif other.level == LEVEL_NONNULL: return elif other.level == LEVEL_KNOWNCLASS: return # implies nonnull else: assert other.level == LEVEL_CONSTANT assert other.constbox if not other.constbox.nonnull(): raise VirtualStatesCantMatch("constant is null") return elif self.level == LEVEL_KNOWNCLASS: if other.level == LEVEL_UNKNOWN: 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]) extra_guards.append(op) return else: raise VirtualStatesCantMatch("other's class is unknown") elif other.level == LEVEL_NONNULL: 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]) extra_guards.append(op) return else: raise VirtualStatesCantMatch("other's class is unknown") elif other.level == LEVEL_KNOWNCLASS: if self.known_class.same_constant(other.known_class): return raise VirtualStatesCantMatch("classes don't match") else: assert other.level == LEVEL_CONSTANT if (other.constbox.nonnull() and self.known_class.same_constant( cpu.ts.cls_of_box(other.constbox))): return else: raise VirtualStatesCantMatch("classes don't match") else: assert self.level == LEVEL_CONSTANT if other.level == LEVEL_CONSTANT: if self.constbox.same_constant(other.constbox): return raise VirtualStatesCantMatch("different constants") if runtime_box is not None and self.constbox.same_constant( runtime_box.constbox()): op = ResOperation(rop.GUARD_VALUE, [box, self.constbox]) extra_guards.append(op) return else: raise VirtualStatesCantMatch("other not constant") assert 0, "unreachable"