[pypy-commit] pypy default: Merged in force-virtual-state (pull request #478)
sbauman
pypy.commits at gmail.com
Tue Sep 13 11:56:48 EDT 2016
Author: Spenser Bauman <sabauma at gmail.com>
Branch:
Changeset: r87082:cfcbc07174e8
Date: 2016-09-13 11:56 -0400
http://bitbucket.org/pypy/pypy/changeset/cfcbc07174e8/
Log: Merged in force-virtual-state (pull request #478)
Ensure make_inputargs fails properly when given arguments with type
information
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
@@ -3,7 +3,7 @@
from rpython.jit.metainterp.resoperation import AbstractValue, ResOperation,\
rop, OpHelpers
from rpython.jit.metainterp.history import ConstInt, Const
-from rpython.rtyper.lltypesystem import lltype
+from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation
from rpython.jit.metainterp.executor import execute
from rpython.jit.metainterp.optimize import InvalidLoop
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
@@ -11,6 +11,8 @@
from rpython.jit.metainterp.typesystem import llhelper
from rpython.rlib.objectmodel import specialize, we_are_translated
from rpython.rlib.debug import debug_print
+from rpython.rtyper import rclass
+from rpython.rtyper.lltypesystem import llmemory
from rpython.jit.metainterp.optimize import SpeculativeError
@@ -799,6 +801,21 @@
if not (0 <= index < arraylength):
raise SpeculativeError
+ @staticmethod
+ def _check_subclass(vtable1, vtable2): # checks that vtable1 is a subclass of vtable2
+ known_class = llmemory.cast_adr_to_ptr(
+ llmemory.cast_int_to_adr(vtable1),
+ rclass.CLASSTYPE)
+ expected_class = llmemory.cast_adr_to_ptr(
+ llmemory.cast_int_to_adr(vtable2),
+ rclass.CLASSTYPE)
+ # note: the test is for a range including 'max', but 'max'
+ # should never be used for actual classes. Including it makes
+ # it easier to pass artificial tests.
+ return (expected_class.subclassrange_min
+ <= known_class.subclassrange_min
+ <= expected_class.subclassrange_max)
+
def is_virtual(self, op):
if op.type == 'r':
opinfo = self.getptrinfo(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
@@ -324,40 +324,24 @@
return
self.emit_operation(op)
- def _check_subclass(self, vtable1, vtable2):
- # checks that vtable1 is a subclass of vtable2
- known_class = llmemory.cast_adr_to_ptr(
- llmemory.cast_int_to_adr(vtable1),
- rclass.CLASSTYPE)
- expected_class = llmemory.cast_adr_to_ptr(
- llmemory.cast_int_to_adr(vtable2),
- rclass.CLASSTYPE)
- # note: the test is for a range including 'max', but 'max'
- # should never be used for actual classes. Including it makes
- # it easier to pass artificial tests.
- if (expected_class.subclassrange_min
- <= known_class.subclassrange_min
- <= expected_class.subclassrange_max):
- return True
- return False
-
def optimize_GUARD_SUBCLASS(self, op):
info = self.getptrinfo(op.getarg(0))
+ optimizer = self.optimizer
if info and info.is_constant():
c = self.get_box_replacement(op.getarg(0))
- vtable = self.optimizer.cpu.ts.cls_of_box(c).getint()
- if self._check_subclass(vtable, op.getarg(1).getint()):
+ vtable = optimizer.cpu.ts.cls_of_box(c).getint()
+ if optimizer._check_subclass(vtable, op.getarg(1).getint()):
return
raise InvalidLoop("GUARD_SUBCLASS(const) proven to always fail")
if info is not None and info.is_about_object():
- known_class = info.get_known_class(self.optimizer.cpu)
+ known_class = info.get_known_class(optimizer.cpu)
if known_class:
- if self._check_subclass(known_class.getint(),
- op.getarg(1).getint()):
+ if optimizer._check_subclass(known_class.getint(),
+ op.getarg(1).getint()):
return
elif info.get_descr() is not None:
- if self._check_subclass(info.get_descr().get_vtable(),
- op.getarg(1).getint()):
+ if optimizer._check_subclass(info.get_descr().get_vtable(),
+ op.getarg(1).getint()):
return
self.emit_operation(op)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
@@ -17,12 +17,13 @@
from rpython.jit.metainterp.optimizeopt.virtualstate import \
NotVirtualStateInfo, LEVEL_CONSTANT, LEVEL_UNKNOWN, LEVEL_KNOWNCLASS,\
VirtualStateInfo
-from rpython.jit.metainterp.optimizeopt import info
+from rpython.jit.metainterp.optimizeopt import info, optimizer
from rpython.jit.codewriter import heaptracker
from rpython.jit.tool import oparser
class FakeOptimizer(object):
optearlyforce = None
+ optimizer = optimizer.Optimizer
class cpu:
remove_gctypeptr = True
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -102,6 +102,8 @@
node_vtable_adr2 = llmemory.cast_ptr_to_adr(node_vtable2)
node_vtable3 = lltype.malloc(OBJECT_VTABLE, immortal=True)
node_vtable3.name = rclass.alloc_array_name('node3')
+ node_vtable3.subclassrange_min = 3
+ node_vtable3.subclassrange_max = 3
node_vtable_adr3 = llmemory.cast_ptr_to_adr(node_vtable3)
cpu = runner.LLGraphCPU(None)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
@@ -3,7 +3,8 @@
from rpython.jit.metainterp.optimizeopt.virtualstate import VirtualStateInfo,\
VStructStateInfo, LEVEL_CONSTANT,\
VArrayStateInfo, not_virtual, VirtualState,\
- GenerateGuardState, VirtualStatesCantMatch, VArrayStructStateInfo
+ GenerateGuardState, VirtualStatesCantMatch, VArrayStructStateInfo,\
+ VirtualStateConstructor
from rpython.jit.metainterp.history import ConstInt, ConstPtr, TargetToken
from rpython.jit.metainterp.resoperation import InputArgInt, InputArgRef,\
InputArgFloat
@@ -26,6 +27,7 @@
def __init__(self, cpu):
self.cpu = cpu
self.optearlyforce = None
+ self.optimizer = Optimizer
class BaseTestGenerateGuards(BaseTest):
def setup_class(self):
@@ -87,6 +89,33 @@
vs = VirtualState([info0])
assert vs.make_inputargs(args, optimizer) == []
+ def test_make_inputargs_2(self):
+ # Ensure that make_inputargs properly errors with VirtualStatesCantMatch
+ # when the type information for a virtual field conflicts. In practice the
+ # expected and given field always share a common subclass.
+ # This check is needed as not all paths to make_inputargs in unroll.py
+ # are guarded by a call to generate_guards.
+ optimizer = FakeOptimizer(self.cpu)
+ classbox1 = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
+ innervalue1 = info.InstancePtrInfo(known_class=classbox1, is_virtual=True, descr=self.valuedescr.get_parent_descr())
+ for field in self.valuedescr.get_parent_descr().get_all_fielddescrs():
+ innervalue1.setfield(field, None, ConstInt(42))
+ classbox2 = self.cpu.ts.cls_of_box(InputArgRef(self.myptr3))
+ innervalue2 = info.InstancePtrInfo(known_class=classbox2, is_virtual=True, descr=self.valuedescr3.get_parent_descr())
+ for field in self.valuedescr3.get_parent_descr().get_all_fielddescrs():
+ innervalue2.setfield(field, None, ConstInt(42))
+
+ nodebox1 = InputArgRef(self.nodeaddr)
+ nodebox2 = InputArgRef(self.myptr3)
+ nodebox1.set_forwarded(innervalue1)
+ nodebox2.set_forwarded(innervalue2)
+
+ constr = VirtualStateConstructor(optimizer)
+ vs = constr.get_virtual_state([nodebox1])
+
+ with py.test.raises(VirtualStatesCantMatch):
+ args = vs.make_inputargs([nodebox2], optimizer, force_boxes=True)
+
def test_position_generalization(self):
def postest(info1, info2):
info1.position = 0
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
@@ -177,6 +177,14 @@
def _generalization_of_structpart(self, other):
raise NotImplementedError
+ @staticmethod
+ def descr_issubclass(descr1, descr2, optimizer):
+ if not descr1.is_object() or not descr2.is_object():
+ return True
+ vtable1 = descr1.get_vtable()
+ vtable2 = descr2.get_vtable()
+ return optimizer._check_subclass(vtable1, vtable2)
+
def enum_forced_boxes(self, boxes, box, optimizer, force_boxes=False):
box = optimizer.get_box_replacement(box)
info = optimizer.getptrinfo(box)
@@ -184,10 +192,14 @@
raise VirtualStatesCantMatch()
else:
assert isinstance(info, AbstractStructPtrInfo)
+
for i in range(len(self.fielddescrs)):
state = self.fieldstate[i]
+ descr = self.fielddescrs[i].get_parent_descr()
if not state:
continue
+ if not self.descr_issubclass(info.descr, descr, optimizer.optimizer):
+ raise VirtualStatesCantMatch()
if state.position > self.position:
fieldbox = info._fields[i]
state.enum_forced_boxes(boxes, fieldbox, optimizer, force_boxes)
More information about the pypy-commit
mailing list