diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py index 25dec54fac..f5fc782a4d 100644 --- a/pypy/jit/backend/llgraph/runner.py +++ b/pypy/jit/backend/llgraph/runner.py @@ -8,7 +8,7 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython.llinterp import LLInterpreter from pypy.jit.metainterp import history -from pypy.jit.metainterp.history import REF, INT, FLOAT +from pypy.jit.metainterp.history import REF, INT, FLOAT, STRUCT from pypy.jit.metainterp.warmstate import unwrap from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend import model @@ -60,6 +60,9 @@ def is_array_of_pointers(self): def is_array_of_floats(self): return self.typeinfo == FLOAT + def is_array_of_structs(self): + return self.typeinfo == STRUCT + def as_vtable_size_descr(self): return self @@ -365,6 +368,8 @@ def arraydescrof(self, A): size = symbolic.get_size(A) if isinstance(A.OF, lltype.Ptr) or isinstance(A.OF, lltype.Primitive): token = history.getkind(A.OF)[0] + elif isinstance(A.OF, lltype.Struct): + token = 's' else: token = '?' return self.getdescr(size, token) diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py index 7bf5990abe..51b1888096 100644 --- a/pypy/jit/backend/llsupport/descr.py +++ b/pypy/jit/backend/llsupport/descr.py @@ -164,6 +164,7 @@ def get_item_size(self, translate_support_code): _is_array_of_pointers = False # unless overridden by GcPtrArrayDescr _is_array_of_floats = False # unless overridden by FloatArrayDescr + _is_array_of_structs = False # unless overridden by StructArrayDescr _is_item_signed = False # unless overridden by XxxArrayDescr def is_array_of_pointers(self): @@ -172,6 +173,9 @@ def is_array_of_pointers(self): def is_array_of_floats(self): return self._is_array_of_floats + def is_array_of_structs(self): + return self._is_array_of_structs + def is_item_signed(self): return self._is_item_signed @@ -196,6 +200,12 @@ def get_base_size(self, translate_support_code): def get_item_size(self, translate_support_code): return symbolic.get_size(lltype.Float, translate_support_code) +class StructArrayDescr(BaseArrayDescr): + _clsname = 'StructArrayDescr' + _is_array_of_structs = True + def get_item_size(self, translate_support_code): + return symbolic.get_size() + class BaseArrayNoLengthDescr(BaseArrayDescr): def get_base_size(self, translate_support_code): return 0 @@ -215,6 +225,13 @@ class GcPtrArrayNoLengthDescr(NonGcPtrArrayNoLengthDescr): def getArrayDescrClass(ARRAY): if ARRAY.OF is lltype.Float: return FloatArrayDescr + elif isinstance(ARRAY.OF, lltype.Struct): + class Descr(StructArrayDescr): + _clsname = '%sArrayDescr' % ARRAY.OF._name + def get_item_size(self, translate_support_code): + return symbolic.get_size(ARRAY.OF, translate_support_code) + Descr.__name__ = Descr._clsname + return Descr return getDescrClass(ARRAY.OF, BaseArrayDescr, GcPtrArrayDescr, NonGcPtrArrayDescr, 'Array', 'get_item_size', '_is_array_of_floats', '_is_item_signed') diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py index b7603a7a4b..5f9c64e928 100644 --- a/pypy/jit/metainterp/history.py +++ b/pypy/jit/metainterp/history.py @@ -16,6 +16,7 @@ INT = 'i' REF = 'r' FLOAT = 'f' +STRUCT = 's' HOLE = '_' VOID = 'v' @@ -172,6 +173,11 @@ def is_array_of_floats(self): """ raise NotImplementedError + def is_array_of_structs(self): + """ Implement for array descr + """ + raise NotImplementedError + def is_pointer_field(self): """ Implement for field descr """ diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py b/pypy/jit/metainterp/optimizeopt/virtualize.py index 9a8e76ddbd..8451b08b2d 100644 --- a/pypy/jit/metainterp/optimizeopt/virtualize.py +++ b/pypy/jit/metainterp/optimizeopt/virtualize.py @@ -59,7 +59,7 @@ def _really_force(self, optforce): def import_from(self, other, optimizer): raise NotImplementedError("should not be called at this level") - + def get_fielddescrlist_cache(cpu): if not hasattr(cpu, '_optimizeopt_fielddescrlist_cache'): result = descrlist_dict() @@ -113,7 +113,7 @@ def _really_force(self, optforce): # if not we_are_translated(): op.name = 'FORCE ' + self.source_op.name - + if self._is_immutable_and_filled_with_constants(optforce): box = optforce.optimizer.constant_fold(op) self.make_constant(box) @@ -239,12 +239,12 @@ def force_at_end_of_preamble(self, already_forced, optforce): for index in range(len(self._items)): self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) return self - + def _really_force(self, optforce): assert self.source_op is not None if not we_are_translated(): self.source_op.name = 'FORCE ' + self.source_op.name - optforce.emit_operation(self.source_op) + optforce.emit_operation(self.source_op) self.box = box = self.source_op.result for index in range(len(self._items)): subvalue = self._items[index] @@ -276,7 +276,7 @@ class OptVirtualize(optimizer.Optimization): def new(self): return OptVirtualize() - + def make_virtual(self, known_class, box, source_op=None): vvalue = VirtualValue(self.optimizer.cpu, known_class, box, source_op) self.make_equal_to(box, vvalue) @@ -386,7 +386,8 @@ def optimize_NEW(self, op): def optimize_NEW_ARRAY(self, op): sizebox = self.get_constant_box(op.getarg(0)) - if sizebox is not None: + # For now we can't make arrays of structs virtual. + if sizebox is not None and not op.getdescr().is_array_of_structs(): # if the original 'op' did not have a ConstInt as argument, # build a new one with the ConstInt argument if not isinstance(op.getarg(0), ConstInt): diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py index fe0587b702..91e20f1a36 100644 --- a/pypy/jit/metainterp/test/test_ajit.py +++ b/pypy/jit/metainterp/test/test_ajit.py @@ -3452,6 +3452,22 @@ def f(n, x): res = self.meta_interp(f, [10, 1]) assert res == 0 + def test_virtual_array_of_structs(self): + myjitdriver = JitDriver(greens = [], reds=["n", "d"]) + def f(n): + d = None + while n > 0: + myjitdriver.jit_merge_point(n=n, d=d) + d = {} + if n % 2: + d["k"] = n + else: + d["z"] = n + n -= len(d) + return n + res = self.meta_interp(f, [10]) + assert res == 0 + class TestLLtype(BaseLLtypeTests, LLJitMixin):