Author: Maciej Fijalkowski <[email protected]>
Branch: optresult
Changeset: r77565:b5d3b92eec4c
Date: 2015-05-26 11:42 +0200
http://bitbucket.org/pypy/pypy/changeset/b5d3b92eec4c/
Log: start passing the merge-guards kind of tests
diff --git a/rpython/jit/metainterp/optimizeopt/info.py
b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -49,11 +49,27 @@
class NonNullPtrInfo(PtrInfo):
- _attrs_ = ()
-
+ _attrs_ = ('last_guard_pos',)
+ last_guard_pos = -1
+
def is_nonnull(self):
return True
+ def get_known_class(self, cpu):
+ return None
+
+ def get_last_guard(self, optimizer):
+ if self.last_guard_pos == -1:
+ return None
+ return optimizer._newoperations[self.last_guard_pos]
+
+ def reset_last_guard_pos(self):
+ self.last_guard_pos = -1
+
+ def mark_last_guard(self, optimizer):
+ self.last_guard_pos = len(optimizer._newoperations) - 1
+ assert self.get_last_guard(optimizer).is_guard()
+
class AbstractVirtualPtrInfo(NonNullPtrInfo):
_attrs_ = ('flags',)
@@ -111,7 +127,7 @@
return count
class InstancePtrInfo(AbstractStructPtrInfo):
- _attrs_ = ('_known_class')
+ _attrs_ = ('_known_class',)
_fields = None
def __init__(self, known_class=None, is_virtual=False):
@@ -121,7 +137,7 @@
def get_known_class(self, cpu):
return self._known_class
-
+
class StructPtrInfo(AbstractStructPtrInfo):
def __init__(self, is_virtual=False):
if is_virtual:
@@ -260,6 +276,9 @@
if not self._const.nonnull():
return None
return cpu.ts.cls_of_box(self._const)
+
+ def get_last_guard(self, optimizer):
+ return None
class XPtrOptInfo(AbstractInfo):
_attrs_ = ('_tag', 'known_class', 'last_guard_pos', 'lenbound')
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
@@ -295,12 +295,11 @@
return ptrinfo.getnullness()
assert False
- def make_constant_class(self, op, class_const):
+ def make_constant_class(self, op, class_const, update_last_guard=True):
op = self.get_box_replacement(op)
- opinfo = op.get_forwarded()
- if opinfo is not None:
- return opinfo
opinfo = info.InstancePtrInfo(class_const)
+ if update_last_guard:
+ opinfo.mark_last_guard(self.optimizer)
op.set_forwarded(opinfo)
return opinfo
@@ -466,7 +465,7 @@
self.optimizations = optimizations
def replace_guard(self, op, value):
- assert isinstance(value, PtrOptValue)
+ assert isinstance(value, info.InstancePtrInfo)
if value.last_guard_pos == -1:
return
self.replaces_guard[op] = value.last_guard_pos
@@ -598,6 +597,10 @@
opinfo = arg0.get_forwarded()
if isinstance(opinfo, info.AbstractVirtualPtrInfo):
return opinfo
+ elif opinfo is not None:
+ last_guard_pos = opinfo.last_guard_pos
+ else:
+ last_guard_pos = -1
assert opinfo is None or opinfo.__class__ is info.NonNullPtrInfo
if op.is_getfield() or op.getopnum() == rop.SETFIELD_GC:
is_object = op.getdescr().parent_descr.is_object()
@@ -608,8 +611,11 @@
opinfo.init_fields(op.getdescr().parent_descr)
elif op.is_getarrayitem() or op.getopnum() == rop.SETARRAYITEM_GC:
opinfo = info.ArrayPtrInfo(op.getdescr())
+ elif op.getopnum() == rop.GUARD_CLASS:
+ opinfo = info.InstancePtrInfo()
else:
- zzz
+ xxx
+ opinfo.last_guard_pos = last_guard_pos
arg0.set_forwarded(opinfo)
return opinfo
diff --git a/rpython/jit/metainterp/optimizeopt/pure.py
b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -12,6 +12,7 @@
self.next_index = 0
def add(self, op):
+ assert isinstance(op, AbstractResOp)
next_index = self.next_index
self.next_index = (next_index + 1) % self.REMEMBER_LIMIT
self.lst[next_index] = op
@@ -180,7 +181,6 @@
self.optimizer.optpure = self
def pure(self, opnum, op):
- op = self.get_box_replacement(op)
recentops = self.getrecentops(opnum)
recentops.add(op)
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
@@ -287,52 +287,49 @@
'fail' % r)
self.emit_operation(op)
self.make_nonnull(op.getarg(0))
+ self.getptrinfo(op.getarg(0)).mark_last_guard(self.optimizer)
def optimize_GUARD_VALUE(self, op):
- ## value = self.getvalue(op.getarg(0))
- ## if value.is_virtual():
- ## arg = value.get_constant_class(self.optimizer.cpu)
- ## if arg:
- ## addr = arg.getaddr()
- ## name =
self.optimizer.metainterp_sd.get_name_from_address(addr)
- ## else:
- ## name = "<unknown>"
- ## raise InvalidLoop('A promote of a virtual %s (a recently
allocated object) never makes sense!' % name)
- ## old_guard_op = value.get_last_guard(self.optimizer)
- ## if old_guard_op and not isinstance(old_guard_op.getdescr(),
- ## compile.ResumeAtPositionDescr):
- ## # 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
- ## 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
- ## # be executed with wrong classes.
- ## previous_classbox =
value.get_constant_class(self.optimizer.cpu)
- ## expected_classbox =
self.optimizer.cpu.ts.cls_of_box(op.getarg(1))
- ## assert previous_classbox is not None
- ## assert expected_classbox is not None
- ## if not previous_classbox.same_constant(expected_classbox):
- ## r =
self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
- ## raise InvalidLoop('A GUARD_VALUE (%s) was proven to
always fail' % r)
- ## descr = compile.ResumeGuardValueDescr()
- ## op = old_guard_op.copy_and_change(rop.GUARD_VALUE,
- ## args = [old_guard_op.getarg(0), op.getarg(1)],
- ## descr = descr)
- ## # Note: we give explicitly a new descr for 'op'; this is why the
- ## # old descr must not be ResumeAtPositionDescr (checked above).
- ## # Better-safe-than-sorry but it should never occur: we should
- ## # not put in short preambles guard_xxx and guard_value
- ## # on the same box.
- ## self.optimizer.replace_guard(op, value)
- ## descr.make_a_counter_per_value(op)
- ## # to be safe
- ## if isinstance(value, PtrOptValue):
- ## value.last_guard_pos = -1
+ arg0 = op.getarg(0)
+ if arg0.type == 'r':
+ info = self.getptrinfo(arg0)
+ if info:
+ if info.is_virtual():
+ xxx
+ 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,
+ old_guard_op)
constbox = op.getarg(1)
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
+ assert expected_classbox is not None
+ if not previous_classbox.same_constant(
+ expected_classbox):
+ r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_VALUE (%s) was proven to '
+ 'always fail' % r)
+ descr = compile.ResumeGuardValueDescr()
+ op = old_guard_op.copy_and_change(rop.GUARD_VALUE,
+ args = [old_guard_op.getarg(0), op.getarg(1)],
+ descr = descr)
+ # Note: we give explicitly a new descr for 'op'; this is why the
+ # old descr must not be ResumeAtPositionDescr (checked above).
+ # Better-safe-than-sorry but it should never occur: we should
+ # not put in short preambles guard_xxx and guard_value
+ # on the same box.
+ self.optimizer.replace_guard(op, info)
+ descr.make_a_counter_per_value(op)
+ # to be safe
+ info.reset_last_guard_pos()
+ return op
+
def optimize_GUARD_TRUE(self, op):
self.optimize_guard(op, CONST_1)
@@ -351,42 +348,39 @@
def optimize_GUARD_CLASS(self, op):
expectedclassbox = op.getarg(1)
- info = self.getptrinfo(op.getarg(0))
+ info = self.ensure_ptr_info_arg0(op)
assert isinstance(expectedclassbox, Const)
- if info is not None:
- realclassbox = info.get_known_class(self.optimizer.cpu)
- if realclassbox is not None:
- if realclassbox.same_constant(expectedclassbox):
- return
- r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
- raise InvalidLoop('A GUARD_CLASS (%s) was proven to always
fail'
- % r)
- old_guard_op = info.get_last_guard(self.optimizer)
- if old_guard_op and not isinstance(old_guard_op.getdescr(),
- compile.ResumeAtPositionDescr):
- xxx
- # there already has been a guard_nonnull or guard_class or
- # guard_nonnull_class on this value.
- if old_guard_op.getopnum() == rop.GUARD_NONNULL:
- # it was a guard_nonnull, which we replace with a
- # guard_nonnull_class.
- descr = compile.ResumeGuardNonnullClassDescr()
- op = old_guard_op.copy_and_change (rop.GUARD_NONNULL_CLASS,
- args = [old_guard_op.getarg(0), op.getarg(1)],
- descr=descr)
- # Note: we give explicitly a new descr for 'op'; this is
why the
- # old descr must not be ResumeAtPositionDescr (checked
above).
- # Better-safe-than-sorry but it should never occur: we
should
- # not put in short preambles guard_nonnull and guard_class
- # on the same box.
- self.optimizer.replace_guard(op, value)
- # not emitting the guard, so we have to pass None to
- # make_constant_class, so last_guard_pos is not updated
- self.emit_operation(op)
- value.make_constant_class(None, expectedclassbox)
- return
+ realclassbox = info.get_known_class(self.optimizer.cpu)
+ if realclassbox is not None:
+ if realclassbox.same_constant(expectedclassbox):
+ return
+ r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+ raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail'
+ % r)
+ old_guard_op = info.get_last_guard(self.optimizer)
+ if old_guard_op and not isinstance(old_guard_op.getdescr(),
+ compile.ResumeAtPositionDescr):
+ # there already has been a guard_nonnull or guard_class or
+ # guard_nonnull_class on this value.
+ if old_guard_op.getopnum() == rop.GUARD_NONNULL:
+ # it was a guard_nonnull, which we replace with a
+ # guard_nonnull_class.
+ descr = compile.ResumeGuardNonnullClassDescr()
+ op = old_guard_op.copy_and_change (rop.GUARD_NONNULL_CLASS,
+ args = [old_guard_op.getarg(0), op.getarg(1)],
+ descr=descr)
+ # Note: we give explicitly a new descr for 'op'; this is why
the
+ # old descr must not be ResumeAtPositionDescr (checked above).
+ # Better-safe-than-sorry but it should never occur: we should
+ # not put in short preambles guard_nonnull and guard_class
+ # on the same box.
+ self.optimizer.replace_guard(op, info)
+ self.emit_operation(op)
+ self.make_constant_class(op.getarg(0), expectedclassbox,
+ False)
+ return
+ self.emit_operation(op)
self.make_constant_class(op.getarg(0), expectedclassbox)
- self.emit_operation(op)
def optimize_GUARD_NONNULL_CLASS(self, op):
value = self.getvalue(op.getarg(0))
diff --git a/rpython/jit/metainterp/test/test_resume.py
b/rpython/jit/metainterp/test/test_resume.py
--- a/rpython/jit/metainterp/test/test_resume.py
+++ b/rpython/jit/metainterp/test/test_resume.py
@@ -2,9 +2,6 @@
import py
import sys
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
-from rpython.jit.metainterp.optimizeopt.optimizer import OptValue
-from rpython.jit.metainterp.optimizeopt.virtualize import VirtualValue,
VArrayValue
-from rpython.jit.metainterp.optimizeopt.virtualize import VStructValue,
AbstractVirtualValue
from rpython.jit.metainterp.resume import *
from rpython.jit.metainterp.history import BoxInt, BoxPtr, ConstInt
from rpython.jit.metainterp.history import ConstPtr, ConstFloat
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit