Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r82267:96c2ec82f010 Date: 2016-02-15 16:32 +0100 http://bitbucket.org/pypy/pypy/changeset/96c2ec82f010/
Log: Test and fix for another corner case (likely shown by Krakatau) 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 @@ -380,7 +380,7 @@ raise InvalidLoop("promote of a virtual") old_guard_op = info.get_last_guard(self.optimizer) if old_guard_op is not None: - op = self.replace_guard_class_with_guard_value(op, info, + op = self.replace_old_guard_with_guard_value(op, info, old_guard_op) elif arg0.type == 'f': arg0 = self.get_box_replacement(arg0) @@ -390,11 +390,26 @@ assert isinstance(constbox, Const) self.optimize_guard(op, constbox) - def replace_guard_class_with_guard_value(self, op, info, old_guard_op): - if old_guard_op.opnum != rop.GUARD_NONNULL: - previous_classbox = info.get_known_class(self.optimizer.cpu) - expected_classbox = self.optimizer.cpu.ts.cls_of_box(op.getarg(1)) - assert previous_classbox is not None + def replace_old_guard_with_guard_value(self, op, info, old_guard_op): + # there already has been a guard_nonnull or guard_class or + # guard_nonnull_class on this value, which is rather silly. + # This function replaces the original guard with a + # guard_value. Must be careful: doing so is unsafe if the + # original guard checks for something inconsistent, + # i.e. different than what it would give if the guard_value + # passed (this is a rare case, but possible). If we get + # inconsistent results in this way, then we must not do the + # replacement, otherwise we'd put guard_value up there but all + # intermediate ops might be executed by assuming something + # different, from the old guard that is now removed... + + c_value = op.getarg(1) + if not c_value.nonnull(): + raise InvalidLoop('A GUARD_VALUE(..., NULL) follows some other ' + 'guard that it is not NULL') + previous_classbox = info.get_known_class(self.optimizer.cpu) + if previous_classbox is not None: + expected_classbox = self.optimizer.cpu.ts.cls_of_box(c_value) assert expected_classbox is not None if not previous_classbox.same_constant( expected_classbox): diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -3063,6 +3063,16 @@ self.optimize_loop(ops, expected, preamble) #self.check_expanded_fail_descr("i0", rop.GUARD_VALUE) + def test_invalid_guard_value_after_guard_class(self): + ops = """ + [p1, i0, i1, i2, p2] + guard_class(p1, ConstClass(node_vtable)) [i0] + i3 = int_add(i1, i2) + guard_value(p1, NULL) [i1] + jump(p2, i0, i1, i3, p2) + """ + self.raises(InvalidLoop, self.optimize_loop, ops, ops) + def test_guard_class_oois(self): ops = """ [p1] _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit