[pypy-svn] pypy fast-forward: Merge heads
amauryfa
commits-noreply at bitbucket.org
Tue Jan 11 22:13:58 CET 2011
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: fast-forward
Changeset: r40597:c820655adece
Date: 2011-01-11 22:13 +0100
http://bitbucket.org/pypy/pypy/changeset/c820655adece/
Log: Merge heads
diff --git a/pypy/jit/metainterp/specnode.py b/pypy/jit/metainterp/specnode.py
deleted file mode 100644
--- a/pypy/jit/metainterp/specnode.py
+++ /dev/null
@@ -1,127 +0,0 @@
-from pypy.tool.pairtype import extendabletype
-from pypy.jit.metainterp.history import Const
-
-
-class SpecNode(object):
- __metaclass__ = extendabletype # extended in optimizefindnode.py
- __slots__ = ()
-
- def equals(self, other, ge): # 'ge' stands for greater-or-equal;
- raise NotImplementedError # if false, the default is 'equal'.
-
- def extract_runtime_data(self, cpu, valuebox, resultlist):
- raise NotImplementedError
-
-
-class NotSpecNode(SpecNode):
- __slots__ = ()
-
- def equals(self, other, ge):
- return isinstance(other, NotSpecNode) or ge
-
- def extract_runtime_data(self, cpu, valuebox, resultlist):
- resultlist.append(valuebox)
-
-
-prebuiltNotSpecNode = NotSpecNode()
-
-
-class ConstantSpecNode(SpecNode):
- def __init__(self, constbox):
- assert isinstance(constbox, Const)
- self.constbox = constbox
-
- def equals(self, other, ge):
- return isinstance(other, ConstantSpecNode) and \
- self.constbox.same_constant(other.constbox)
-
- def extract_runtime_data(self, cpu, valuebox, resultlist):
- pass
-
-
-class AbstractVirtualStructSpecNode(SpecNode):
- def __init__(self, fields):
- self.fields = fields # list: [(fieldofs, subspecnode)]
-
- def equal_fields(self, other, ge):
- if len(self.fields) != len(other.fields):
- return False
- for i in range(len(self.fields)):
- o1, s1 = self.fields[i]
- o2, s2 = other.fields[i]
- if not (o1 is o2 and s1.equals(s2, ge)):
- return False
- return True
-
- def extract_runtime_data(self, cpu, valuebox, resultlist):
- from pypy.jit.metainterp import executor, history, resoperation
- for ofs, subspecnode in self.fields:
- assert isinstance(ofs, history.AbstractDescr)
- fieldbox = executor.execute(cpu, None,
- resoperation.rop.GETFIELD_GC,
- ofs, valuebox)
- subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
-
-
-class VirtualInstanceSpecNode(AbstractVirtualStructSpecNode):
- def __init__(self, known_class, fields):
- AbstractVirtualStructSpecNode.__init__(self, fields)
- assert isinstance(known_class, Const)
- self.known_class = known_class
-
- def equals(self, other, ge):
- if not (isinstance(other, VirtualInstanceSpecNode) and
- self.known_class.same_constant(other.known_class)):
- return False
- return self.equal_fields(other, ge)
-
-
-class VirtualArraySpecNode(SpecNode):
- def __init__(self, arraydescr, items):
- self.arraydescr = arraydescr
- self.items = items # list of subspecnodes
-
- def equals(self, other, ge):
- if not (isinstance(other, VirtualArraySpecNode) and
- len(self.items) == len(other.items)):
- return False
- assert self.arraydescr == other.arraydescr
- for i in range(len(self.items)):
- s1 = self.items[i]
- s2 = other.items[i]
- if not s1.equals(s2, ge):
- return False
- return True
-
- def extract_runtime_data(self, cpu, valuebox, resultlist):
- from pypy.jit.metainterp import executor, history, resoperation
- for i in range(len(self.items)):
- itembox = executor.execute(cpu, None,
- resoperation.rop.GETARRAYITEM_GC,
- self.arraydescr,
- valuebox, history.ConstInt(i))
- subspecnode = self.items[i]
- subspecnode.extract_runtime_data(cpu, itembox, resultlist)
-
-
-class VirtualStructSpecNode(AbstractVirtualStructSpecNode):
- def __init__(self, typedescr, fields):
- AbstractVirtualStructSpecNode.__init__(self, fields)
- self.typedescr = typedescr
-
- def equals(self, other, ge):
- if not isinstance(other, VirtualStructSpecNode):
- return False
- assert self.typedescr == other.typedescr
- return self.equal_fields(other, ge)
-
-
-def equals_specnodes(specnodes1, specnodes2, ge=False):
- assert len(specnodes1) == len(specnodes2)
- for i in range(len(specnodes1)):
- if not specnodes1[i].equals(specnodes2[i], ge):
- return False
- return True
-
-def more_general_specnodes(specnodes1, specnodes2):
- return equals_specnodes(specnodes1, specnodes2, ge=True)
diff --git a/pypy/jit/metainterp/test/test_specnode.py b/pypy/jit/metainterp/test/test_specnode.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_specnode.py
+++ /dev/null
@@ -1,132 +0,0 @@
-from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.jit.metainterp.history import AbstractDescr, BoxPtr, ConstInt, ConstPtr
-from pypy.jit.metainterp.specnode import prebuiltNotSpecNode
-from pypy.jit.metainterp.specnode import VirtualInstanceSpecNode
-from pypy.jit.metainterp.specnode import VirtualArraySpecNode
-from pypy.jit.metainterp.specnode import VirtualStructSpecNode
-from pypy.jit.metainterp.specnode import ConstantSpecNode
-from pypy.jit.metainterp.specnode import equals_specnodes
-from pypy.jit.metainterp.specnode import more_general_specnodes
-from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin
-
-def _get_vspecnode(classnum=123):
- return VirtualInstanceSpecNode(ConstInt(classnum),
- [(LLtypeMixin.valuedescr, prebuiltNotSpecNode),
- (LLtypeMixin.nextdescr, prebuiltNotSpecNode)])
-
-def _get_aspecnode(length=2):
- return VirtualArraySpecNode(LLtypeMixin.arraydescr,
- [prebuiltNotSpecNode] * length)
-
-def _get_sspecnode():
- return VirtualStructSpecNode(LLtypeMixin.ssize,
- [(LLtypeMixin.adescr, prebuiltNotSpecNode),
- (LLtypeMixin.bdescr, prebuiltNotSpecNode)])
-
-def _get_cspecnode(s):
- from pypy.rpython.module.support import LLSupport
- llstr = lltype.cast_opaque_ptr(llmemory.GCREF, LLSupport.to_rstr(s))
- box = ConstPtr(llstr)
- return ConstantSpecNode(box)
-
-def test_equals_specnodes():
- assert equals_specnodes([prebuiltNotSpecNode, prebuiltNotSpecNode],
- [prebuiltNotSpecNode, prebuiltNotSpecNode])
- vspecnode1 = _get_vspecnode(1)
- vspecnode2 = _get_vspecnode(2)
- assert equals_specnodes([vspecnode1], [vspecnode1])
- assert not equals_specnodes([vspecnode1], [vspecnode2])
- assert not equals_specnodes([vspecnode1], [prebuiltNotSpecNode])
- assert not equals_specnodes([prebuiltNotSpecNode], [vspecnode2])
- aspecnode1 = _get_aspecnode(1)
- aspecnode2 = _get_aspecnode(2)
- assert equals_specnodes([aspecnode2], [aspecnode2])
- assert not equals_specnodes([aspecnode1], [aspecnode2])
- assert not equals_specnodes([aspecnode1], [prebuiltNotSpecNode])
- assert not equals_specnodes([prebuiltNotSpecNode], [aspecnode2])
- sspecnode1 = _get_sspecnode()
- assert equals_specnodes([sspecnode1], [sspecnode1])
- assert not equals_specnodes([sspecnode1], [prebuiltNotSpecNode])
- assert not equals_specnodes([prebuiltNotSpecNode], [sspecnode1])
- #
- foonode = _get_cspecnode('foo')
- barnode = _get_cspecnode('bar')
- assert equals_specnodes([foonode], [foonode])
- assert not equals_specnodes([foonode], [barnode])
- assert not equals_specnodes([foonode], [prebuiltNotSpecNode])
-
-def test_more_general_specnodes():
- assert more_general_specnodes([prebuiltNotSpecNode, prebuiltNotSpecNode],
- [prebuiltNotSpecNode, prebuiltNotSpecNode])
- vspecnode1 = _get_vspecnode(1)
- vspecnode2 = _get_vspecnode(2)
- assert more_general_specnodes([vspecnode1], [vspecnode1])
- assert not more_general_specnodes([vspecnode1], [vspecnode2])
- assert not more_general_specnodes([vspecnode1], [prebuiltNotSpecNode])
- assert more_general_specnodes([prebuiltNotSpecNode], [vspecnode2])
- aspecnode1 = _get_aspecnode(1)
- aspecnode2 = _get_aspecnode(2)
- assert more_general_specnodes([aspecnode2], [aspecnode2])
- assert not more_general_specnodes([aspecnode1], [aspecnode2])
- assert not more_general_specnodes([aspecnode1], [prebuiltNotSpecNode])
- assert more_general_specnodes([prebuiltNotSpecNode], [aspecnode2])
- sspecnode1 = _get_sspecnode()
- assert more_general_specnodes([sspecnode1], [sspecnode1])
- assert not more_general_specnodes([sspecnode1], [prebuiltNotSpecNode])
- assert more_general_specnodes([prebuiltNotSpecNode], [sspecnode1])
- #
- foonode = _get_cspecnode('foo')
- barnode = _get_cspecnode('bar')
- assert more_general_specnodes([foonode], [foonode])
- assert not more_general_specnodes([foonode], [barnode])
- assert not more_general_specnodes([foonode], [prebuiltNotSpecNode])
- assert more_general_specnodes([prebuiltNotSpecNode], [foonode])
-
-def test_extract_runtime_data_0():
- res = []
- node = _get_cspecnode('foo')
- node.extract_runtime_data("cpu", "box1", res)
- assert res == []
-
-def test_extract_runtime_data_1():
- res = []
- prebuiltNotSpecNode.extract_runtime_data("cpu", "box1", res)
- prebuiltNotSpecNode.extract_runtime_data("cpu", "box2", res)
- assert res == ["box1", "box2"]
-
-def test_extract_runtime_data_2():
- structure = lltype.malloc(LLtypeMixin.NODE)
- structure.value = 515
- structure.next = lltype.malloc(LLtypeMixin.NODE)
- structbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, structure))
- vspecnode = _get_vspecnode()
- res = []
- vspecnode.extract_runtime_data(LLtypeMixin.cpu, structbox, res)
- assert len(res) == 2
- assert res[0].value == structure.value
- assert res[1].value._obj.container._as_ptr() == structure.next
-
-def test_extract_runtime_data_3():
- array = lltype.malloc(lltype.GcArray(lltype.Signed), 2)
- array[0] = 123
- array[1] = 456
- arraybox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, array))
- aspecnode = _get_aspecnode()
- res = []
- aspecnode.extract_runtime_data(LLtypeMixin.cpu, arraybox, res)
- assert len(res) == 2
- assert res[0].value == 123
- assert res[1].value == 456
-
-def test_extract_runtime_data_4():
- struct = lltype.malloc(LLtypeMixin.S)
- struct.a = 123
- struct.b = lltype.malloc(LLtypeMixin.NODE)
- structbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, struct))
- sspecnode = _get_sspecnode()
- res = []
- sspecnode.extract_runtime_data(LLtypeMixin.cpu, structbox, res)
- assert len(res) == 2
- assert res[0].value == 123
- assert (lltype.cast_opaque_ptr(lltype.Ptr(LLtypeMixin.NODE), res[1].value)
- == struct.b)
diff --git a/pypy/jit/metainterp/test/test_loop_nopspec.py b/pypy/jit/metainterp/test/test_loop_nopspec.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_loop_nopspec.py
+++ /dev/null
@@ -1,27 +0,0 @@
-
-from pypy.jit.metainterp.test import test_loop, test_send
-from pypy.jit.metainterp.warmspot import ll_meta_interp
-from pypy.rlib.jit import OPTIMIZER_NO_PERFECTSPEC
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
-
-class LoopNoPSpecTest(test_send.SendTests):
- def meta_interp(self, func, args, **kwds):
- return ll_meta_interp(func, args, optimizer=OPTIMIZER_NO_PERFECTSPEC,
- CPUClass=self.CPUClass,
- type_system=self.type_system,
- **kwds)
-
- def check_loops(self, *args, **kwds):
- pass
-
- def check_loop_count(self, count):
- pass
-
- def check_jumps(self, maxcount):
- pass
-
-class TestLLtype(LoopNoPSpecTest, LLJitMixin):
- pass
-
-class TestOOtype(LoopNoPSpecTest, OOJitMixin):
- pass
diff --git a/pypy/jit/metainterp/test/test_loop_spec.py b/pypy/jit/metainterp/test/test_loop_spec.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_loop_spec.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import py
-from pypy.rlib.jit import OPTIMIZER_FULL
-from pypy.jit.metainterp.test import test_loop
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
-
-class LoopSpecTest(test_loop.LoopTest):
- optimizer = OPTIMIZER_FULL
- automatic_promotion_result = {
- 'int_add' : 3, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1,
- 'guard_value' : 1
- }
-
- # ====> test_loop.py
-
-class TestLLtype(LoopSpecTest, LLJitMixin):
- pass
-
-class TestOOtype(LoopSpecTest, OOJitMixin):
- pass
diff --git a/pypy/jit/metainterp/test/test_loop_dummy.py b/pypy/jit/metainterp/test/test_loop_dummy.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_loop_dummy.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# xxx mostly pointless
-
-from pypy.jit.metainterp.test import test_loop, test_send
-from pypy.jit.metainterp.warmspot import ll_meta_interp
-from pypy.rlib.jit import OPTIMIZER_SIMPLE
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
-
-class LoopDummyTest(test_send.SendTests):
- def meta_interp(self, func, args, **kwds):
- return ll_meta_interp(func, args, optimizer=OPTIMIZER_SIMPLE,
- CPUClass=self.CPUClass,
- type_system=self.type_system,
- **kwds)
-
- def check_loops(self, *args, **kwds):
- pass
-
- def check_loop_count(self, count):
- pass
-
- def check_jumps(self, maxcount):
- pass
-
-class TestLLtype(LoopDummyTest, LLJitMixin):
- pass
-
-class TestOOtype(LoopDummyTest, OOJitMixin):
- pass
diff --git a/pypy/jit/metainterp/viewnode.py b/pypy/jit/metainterp/viewnode.py
deleted file mode 100644
--- a/pypy/jit/metainterp/viewnode.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import py
-from pypy.jit.metainterp import specnode, optimizefindnode
-from pypy.tool.pairtype import extendabletype
-
-class __extend__(specnode.NotSpecNode):
- def _dot(self, seen):
- if self in seen:
- return
- seen.add(self)
- yield '%s [label="<Not>"]' % (id(self), )
-
-class __extend__(specnode.ConstantSpecNode):
- def _dot(self, seen):
- if self in seen:
- return
- seen.add(self)
- yield '%s [label="<Const: %s>"]' % (id(self), self.constbox)
-
-class __extend__(specnode.AbstractVirtualStructSpecNode):
- def _dot(self, seen):
- if self in seen:
- return
- seen.add(self)
- yield '%s [label="<%s>"]' % (
- id(self),
- self.__class__.__name__[:-len("SpecNode")])
- for label, node in self.fields:
- yield '%s -> %s [label="%s"]' % (id(self), id(node), label.name)
- for line in node._dot(seen):
- yield line
-
-class __extend__(specnode.VirtualArraySpecNode):
- def _dot(self, seen):
- if self in seen:
- return
- seen.add(self)
- yield '%s [label="<Array: %s>"]' % (
- id(self),
- len(self.items))
- for i, node in enumerate(self.items):
- yield '%s -> %s [label="%s"]' % (id(self), id(node), i)
- for line in node._dot(seen):
- yield line
-
-
-class __extend__(optimizefindnode.InstanceNode):
- __metaclass__ = extendabletype # evil
-
- def _dot(self, seen):
- if self in seen:
- return
- seen.add(self)
- if self.knownclsbox:
- name = "Virtual "
- if isinstance(self.knownclsbox.value, int):
- name += str(self.knownclsbox.value)
- else:
- name += str(self.knownclsbox.value.adr.ptr).rpartition("_vtable")[0].rpartition('.')[2]
- elif self.structdescr:
- name = "Struct " + str(self.structdescr)
- elif self.arraydescr:
- name = "Array"
- else:
- name = "Not"
- if self.escaped:
- name = "ESC " + name
- if self.fromstart:
- name = "START " + name
- if self.unique == optimizefindnode.UNIQUE_NO:
- color = "blue"
- else:
- color = "black"
-
- yield 'orig%s [label="in: [%s]", shape=box, color=%s]' % (
- id(self), name, color)
- yield '%s [label="out: [%s]", shape=box, color=%s]' % (
- id(self), name, color)
- yield 'orig%s -> %s [color=red]' % (id(self), id(self))
- if self.origfields:
- for descr, node in self.origfields.iteritems():
- yield 'orig%s -> orig%s [label="%s"]' % (id(self), id(node), descr.name)
- for line in node._dot(seen):
- yield line
- if self.curfields:
- for descr, node in self.curfields.iteritems():
- yield '%s -> %s [label="%s"]' % (id(self), id(node), descr.name)
- for line in node._dot(seen):
- yield line
- if self.origitems:
- for i, node in sorted(self.origitems.iteritems()):
- yield 'orig%s -> orig%s [label="%s"]' % (id(self), id(node), i)
- for line in node._dot(seen):
- yield line
- if self.curitems:
- for i, node in sorted(self.curitems.iteritems()):
- yield '%s -> %s [label="%s"]' % (id(self), id(node), i)
- for line in node._dot(seen):
- yield line
-
-
-def view(*objects):
- from dotviewer import graphclient
- content = ["digraph G{"]
- seen = set()
- for obj in objects:
- content.extend(obj._dot(seen))
- content.append("}")
- p = py.test.ensuretemp("specnodes").join("temp.dot")
- p.write("\n".join(content))
- graphclient.display_dot_file(str(p))
-
-def viewnodes(l1, l2):
- from dotviewer import graphclient
- content = ["digraph G{"]
- seen = set()
- for obj in l1 + l2:
- content.extend(obj._dot(seen))
- for i, (o1, o2) in enumerate(zip(l1, l2)):
- content.append("%s -> %s [color=green]" % (id(o1), i))
- content.append("%s -> orig%s [color=green]" % (i, id(o2)))
- content.append("}")
- p = py.test.ensuretemp("specnodes").join("temp.dot")
- p.write("\n".join(content))
- graphclient.display_dot_file(str(p))
diff --git a/pypy/jit/backend/x86/test/test_loop_spec.py b/pypy/jit/backend/x86/test/test_loop_spec.py
deleted file mode 100644
--- a/pypy/jit/backend/x86/test/test_loop_spec.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import py
-from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
-from pypy.jit.metainterp.test import test_loop_spec
-
-class TestLoopSpec(Jit386Mixin, test_loop_spec.LoopSpecTest):
- # for the individual tests see
- # ====> ../../../metainterp/test/test_loop.py
- pass
diff --git a/pypy/jit/metainterp/optimize_nopspec.py b/pypy/jit/metainterp/optimize_nopspec.py
deleted file mode 100644
--- a/pypy/jit/metainterp/optimize_nopspec.py
+++ /dev/null
@@ -1,45 +0,0 @@
-
-from pypy.rlib.debug import debug_start, debug_stop
-from pypy.jit.metainterp.optimizeopt import optimize_loop_1, optimize_bridge_1
-from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder
-from pypy.jit.metainterp.optimizefindnode import BridgeSpecializationFinder
-
-def optimize_loop(metainterp_sd, old_loop_tokens, loop):
- debug_start("jit-optimize")
- try:
- return _optimize_loop(metainterp_sd, old_loop_tokens, loop)
- finally:
- debug_stop("jit-optimize")
-
-def _optimize_loop(metainterp_sd, old_loop_tokens, loop):
- cpu = metainterp_sd.cpu
- metainterp_sd.logger_noopt.log_loop(loop.inputargs, loop.operations)
- # XXX the following lines are probably still needed, to discard invalid
- # loops. bit silly to run a full perfect specialization and throw the
- # result away.
- finder = PerfectSpecializationFinder(cpu)
- finder.find_nodes_loop(loop, False)
- if old_loop_tokens:
- return old_loop_tokens[0]
- optimize_loop_1(metainterp_sd, loop)
- return None
-
-def optimize_bridge(metainterp_sd, old_loop_tokens, bridge):
- debug_start("jit-optimize")
- try:
- return _optimize_bridge(metainterp_sd, old_loop_tokens, bridge)
- finally:
- debug_stop("jit-optimize")
-
-def _optimize_bridge(metainterp_sd, old_loop_tokens, bridge):
- cpu = metainterp_sd.cpu
- metainterp_sd.logger_noopt.log_loop(bridge.inputargs, bridge.operations)
- # XXX same comment as above applies
- finder = BridgeSpecializationFinder(cpu)
- finder.find_nodes_bridge(bridge)
- if old_loop_tokens:
- old_loop_token = old_loop_tokens[0]
- bridge.operations[-1].setdescr(old_loop_token) # patch jump target
- optimize_bridge_1(metainterp_sd, bridge)
- return old_loop_token
- return None
diff --git a/pypy/jit/metainterp/optimizefindnode.py b/pypy/jit/metainterp/optimizefindnode.py
deleted file mode 100644
--- a/pypy/jit/metainterp/optimizefindnode.py
+++ /dev/null
@@ -1,576 +0,0 @@
-from pypy.jit.metainterp.specnode import SpecNode
-from pypy.jit.metainterp.specnode import NotSpecNode, prebuiltNotSpecNode
-from pypy.jit.metainterp.specnode import ConstantSpecNode
-from pypy.jit.metainterp.specnode import VirtualInstanceSpecNode
-from pypy.jit.metainterp.specnode import VirtualArraySpecNode
-from pypy.jit.metainterp.specnode import VirtualStructSpecNode
-from pypy.jit.metainterp.history import AbstractValue, ConstInt, Const
-from pypy.jit.metainterp.resoperation import rop
-from pypy.jit.metainterp.executor import execute_nonspec
-from pypy.jit.metainterp.optimizeutil import _findall, sort_descrs
-from pypy.jit.metainterp.optimizeutil import InvalidLoop
-
-# ____________________________________________________________
-
-UNIQUE_UNKNOWN = '\x00'
-UNIQUE_NO = '\x01'
-UNIQUE_INST = '\x02'
-UNIQUE_ARRAY = '\x03'
-UNIQUE_STRUCT = '\x04'
-
-class InstanceNode(object):
- """An instance of this class is used to match the start and
- the end of the loop, so it contains both 'origfields' that represents
- the field's status at the start and 'curfields' that represents it
- at the current point (== the end when optimizefindnode is complete).
- """
- escaped = False # if True, then all the rest of the info is pointless
- unique = UNIQUE_UNKNOWN # for find_unique_nodes()
-
- # fields used to store the shape of the potential VirtualInstance
- knownclsbox = None # set only on freshly-allocated or fromstart structures
- origfields = None # optimization; equivalent to an empty dict
- curfields = None # optimization; equivalent to an empty dict
-
- knownvaluebox = None # a Const with the value of this box, if constant
-
- # fields used to store the shape of the potential VirtualList
- arraydescr = None # set only on freshly-allocated or fromstart arrays
- #arraysize = .. # valid if and only if arraydescr is not None
- origitems = None # optimization; equivalent to an empty dict
- curitems = None # optimization; equivalent to an empty dict
-
- # fields used to store the shape of the potential VirtualStruct
- structdescr = None # set only on freshly-allocated or fromstart structs
- #origfields = .. # same as above
- #curfields = .. # same as above
-
- dependencies = None
-
- def __init__(self, fromstart=False):
- self.fromstart = fromstart # for loops only: present since the start
-
- def is_constant(self):
- return self.knownvaluebox is not None
-
- def add_escape_dependency(self, other):
- assert not self.escaped
- if self.dependencies is None:
- self.dependencies = []
- self.dependencies.append(other)
-
- def mark_escaped(self):
- # invariant: if escaped=True, then dependencies is None
- if not self.escaped:
- self.escaped = True
- self.unique = UNIQUE_NO
- # ^^^ always set unique to UNIQUE_NO when we set escaped to True.
- # See for example test_find_nodes_store_into_loop_constant_2.
- if self.dependencies is not None:
- deps = self.dependencies
- self.dependencies = None
- for box in deps:
- box.mark_escaped()
-
- def set_unique_nodes(self):
- if self.fromstart:
- self.mark_escaped()
- if self.escaped or self.unique != UNIQUE_UNKNOWN:
- # this node is not suitable for being a virtual, or we
- # encounter it more than once when doing the recursion
- self.unique = UNIQUE_NO
- elif self.knownclsbox is not None:
- self.unique = UNIQUE_INST
- if self.curfields is not None:
- for subnode in self.curfields.itervalues():
- subnode.set_unique_nodes()
- elif self.arraydescr is not None:
- self.unique = UNIQUE_ARRAY
- if self.curitems is not None:
- for subnode in self.curitems.itervalues():
- subnode.set_unique_nodes()
- elif self.structdescr is not None:
- self.unique = UNIQUE_STRUCT
- if self.curfields is not None:
- for subnode in self.curfields.itervalues():
- subnode.set_unique_nodes()
- else:
- assert 0, "most probably unreachable"
-
- def __repr__(self):
- flags = ''
- if self.escaped: flags += 'e'
- if self.fromstart: flags += 's'
- if self.knownclsbox: flags += 'c'
- if self.arraydescr: flags += str(self.arraysize)
- if self.structdescr: flags += 'S'
- return "<InstanceNode (%s)>" % (flags,)
-
-# ____________________________________________________________
-# General find_nodes_xxx() interface, for both loops and bridges
-
-class NodeFinder(object):
- """Abstract base class."""
- node_escaped = InstanceNode()
- node_escaped.unique = UNIQUE_NO
- node_escaped.escaped = True
-
- def __init__(self, cpu):
- self.cpu = cpu
- self.nodes = {} # Box -> InstanceNode
-
- def getnode(self, box):
- if isinstance(box, Const):
- return self.set_constant_node(box, box)
- return self.nodes.get(box, self.node_escaped)
-
- def set_constant_node(self, box, constbox):
- assert isinstance(constbox, Const)
- node = InstanceNode()
- node.unique = UNIQUE_NO
- node.escaped = True
- node.knownvaluebox = constbox
- self.nodes[box] = node
- return node
-
- def get_constant_box(self, box):
- if isinstance(box, Const):
- return box
- try:
- node = self.nodes[box]
- except KeyError:
- return None
- else:
- return node.knownvaluebox
-
- def find_nodes(self, operations):
- for op in operations:
- opnum = op.getopnum()
- for value, func in find_nodes_ops:
- if opnum == value:
- func(self, op)
- break
- else:
- self.find_nodes_default(op)
-
- def find_nodes_default(self, op):
- if op.is_always_pure():
- for i in range(op.numargs()):
- arg = op.getarg(i)
- if self.get_constant_box(arg) is None:
- break
- else:
- # all constant arguments: we can constant-fold
- argboxes = [self.get_constant_box(op.getarg(i))
- for i in range(op.numargs())]
- resbox = execute_nonspec(self.cpu, None,
- op.getopnum(), argboxes, op.getdescr())
- self.set_constant_node(op.result, resbox.constbox())
- # default case: mark the arguments as escaping
- for i in range(op.numargs()):
- self.getnode(op.getarg(i)).mark_escaped()
-
- def find_nodes_no_escape(self, op):
- pass # for operations that don't escape their arguments
-
- find_nodes_PTR_EQ = find_nodes_no_escape
- find_nodes_PTR_NE = find_nodes_no_escape
- ##find_nodes_INSTANCEOF = find_nodes_no_escape
- find_nodes_GUARD_NONNULL = find_nodes_no_escape
- find_nodes_GUARD_ISNULL = find_nodes_no_escape
-
- def find_nodes_NEW_WITH_VTABLE(self, op):
- instnode = InstanceNode()
- box = op.getarg(0)
- assert isinstance(box, Const)
- instnode.knownclsbox = box
- self.nodes[op.result] = instnode
-
- def find_nodes_NEW(self, op):
- instnode = InstanceNode()
- instnode.structdescr = op.getdescr()
- self.nodes[op.result] = instnode
-
- def find_nodes_NEW_ARRAY(self, op):
- lengthbox = op.getarg(0)
- lengthbox = self.get_constant_box(lengthbox)
- if lengthbox is None:
- return # var-sized arrays are not virtual
- arraynode = InstanceNode()
- arraynode.arraysize = lengthbox.getint()
- arraynode.arraydescr = op.getdescr()
- self.nodes[op.result] = arraynode
-
- def find_nodes_ARRAYLEN_GC(self, op):
- arraynode = self.getnode(op.getarg(0))
- if arraynode.arraydescr is not None:
- resbox = ConstInt(arraynode.arraysize)
- self.set_constant_node(op.result, resbox)
-
- def find_nodes_GUARD_CLASS(self, op):
- instnode = self.getnode(op.getarg(0))
- if instnode.fromstart: # only useful (and safe) in this case
- box = op.getarg(1)
- assert isinstance(box, Const)
- instnode.knownclsbox = box
-
- def find_nodes_GUARD_VALUE(self, op):
- instnode = self.getnode(op.getarg(0))
- if instnode.fromstart: # only useful (and safe) in this case
- box = op.getarg(1)
- assert isinstance(box, Const)
- instnode.knownvaluebox = box
-
- def find_nodes_SETFIELD_GC(self, op):
- instnode = self.getnode(op.getarg(0))
- fieldnode = self.getnode(op.getarg(1))
- if instnode.escaped:
- fieldnode.mark_escaped()
- return # nothing to be gained from tracking the field
- field = op.getdescr()
- assert isinstance(field, AbstractValue)
- if instnode.curfields is None:
- instnode.curfields = {}
- instnode.curfields[field] = fieldnode
- instnode.add_escape_dependency(fieldnode)
-
- def find_nodes_GETFIELD_GC(self, op):
- instnode = self.getnode(op.getarg(0))
- if instnode.escaped:
- return # nothing to be gained from tracking the field
- field = op.getdescr()
- assert isinstance(field, AbstractValue)
- if instnode.curfields is not None and field in instnode.curfields:
- fieldnode = instnode.curfields[field]
- elif instnode.origfields is not None and field in instnode.origfields:
- fieldnode = instnode.origfields[field]
- elif instnode.fromstart:
- fieldnode = InstanceNode(fromstart=True)
- instnode.add_escape_dependency(fieldnode)
- if instnode.origfields is None:
- instnode.origfields = {}
- instnode.origfields[field] = fieldnode
- else:
- return # nothing to be gained from tracking the field
- self.nodes[op.result] = fieldnode
-
- find_nodes_GETFIELD_GC_PURE = find_nodes_GETFIELD_GC
-
- def find_nodes_SETARRAYITEM_GC(self, op):
- indexbox = op.getarg(1)
- indexbox = self.get_constant_box(indexbox)
- if indexbox is None:
- self.find_nodes_default(op) # not a Const index
- return
- arraynode = self.getnode(op.getarg(0))
- itemnode = self.getnode(op.getarg(2))
- if arraynode.escaped:
- itemnode.mark_escaped()
- return # nothing to be gained from tracking the item
- if arraynode.curitems is None:
- arraynode.curitems = {}
- arraynode.curitems[indexbox.getint()] = itemnode
- arraynode.add_escape_dependency(itemnode)
-
- def find_nodes_GETARRAYITEM_GC(self, op):
- indexbox = op.getarg(1)
- indexbox = self.get_constant_box(indexbox)
- if indexbox is None:
- self.find_nodes_default(op) # not a Const index
- return
- arraynode = self.getnode(op.getarg(0))
- if arraynode.escaped:
- return # nothing to be gained from tracking the item
- index = indexbox.getint()
- if arraynode.curitems is not None and index in arraynode.curitems:
- itemnode = arraynode.curitems[index]
- elif arraynode.origitems is not None and index in arraynode.origitems:
- itemnode = arraynode.origitems[index]
- elif arraynode.fromstart:
- itemnode = InstanceNode(fromstart=True)
- arraynode.add_escape_dependency(itemnode)
- if arraynode.origitems is None:
- arraynode.origitems = {}
- arraynode.origitems[index] = itemnode
- else:
- return # nothing to be gained from tracking the item
- self.nodes[op.result] = itemnode
-
- find_nodes_GETARRAYITEM_GC_PURE = find_nodes_GETARRAYITEM_GC
-
- def find_nodes_JUMP(self, op):
- # only set up the 'unique' field of the InstanceNodes;
- # real handling comes later (build_result_specnodes() for loops).
- for i in range(op.numargs()):
- box = op.getarg(i)
- self.getnode(box).set_unique_nodes()
-
- def find_nodes_FINISH(self, op):
- # only for bridges, and only for the ones that end in a 'return'
- # or 'raise'; all other cases end with a JUMP.
- for i in range(op.numargs()):
- box = op.getarg(i)
- self.getnode(box).unique = UNIQUE_NO
-
-find_nodes_ops = _findall(NodeFinder, 'find_nodes_')
-
-# ____________________________________________________________
-# Perfect specialization -- for loops only
-
-class PerfectSpecializationFinder(NodeFinder):
- node_fromstart = InstanceNode(fromstart=True)
-
- def find_nodes_loop(self, loop, build_specnodes=True):
- self._loop = loop
- self.setup_input_nodes(loop.inputargs)
- self.find_nodes(loop.operations)
- if build_specnodes:
- self.build_result_specnodes(loop)
-
- def show(self):
- from pypy.jit.metainterp.viewnode import viewnodes, view
- op = self._loop.operations[-1]
- assert op.getopnum() == rop.JUMP
- exitnodes = [self.getnode(arg) for arg in op.args]
- viewnodes(self.inputnodes, exitnodes)
- if hasattr(self._loop.token, "specnodes"):
- view(*self._loop.token.specnodes)
-
-
- def setup_input_nodes(self, inputargs):
- inputnodes = []
- for box in inputargs:
- instnode = InstanceNode(fromstart=True)
- inputnodes.append(instnode)
- self.nodes[box] = instnode
- self.inputnodes = inputnodes
-
- def build_result_specnodes(self, loop):
- # Build the list of specnodes based on the result
- # computed by NodeFinder.find_nodes().
- op = loop.operations[-1]
- assert op.getopnum() == rop.JUMP
- assert len(self.inputnodes) == op.numargs()
- while True:
- self.restart_needed = False
- specnodes = []
- for i in range(op.numargs()):
- inputnode = self.inputnodes[i]
- exitnode = self.getnode(op.getarg(i))
- specnodes.append(self.intersect(inputnode, exitnode))
- if not self.restart_needed:
- break
- loop.token.specnodes = specnodes
-
- def intersect(self, inputnode, exitnode):
- assert inputnode.fromstart
- if inputnode.is_constant() and \
- exitnode.is_constant():
- if inputnode.knownvaluebox.same_constant(exitnode.knownvaluebox):
- return ConstantSpecNode(inputnode.knownvaluebox)
- else:
- raise InvalidLoop
- if inputnode.escaped:
- return prebuiltNotSpecNode
- unique = exitnode.unique
- if unique == UNIQUE_NO:
- if inputnode is not self.node_fromstart:
- # Mark the input node as escaped, and schedule a complete
- # restart of intersect(). This is needed because there is
- # an order dependency: calling inputnode.mark_escaped()
- # might set the field exitnode.unique to UNIQUE_NO in some
- # other node. If inputnode is node_fromstart, there is no
- # problem (and it must not be mutated by mark_escaped() then).
- inputnode.mark_escaped()
- self.restart_needed = True
- return prebuiltNotSpecNode
- if unique == UNIQUE_INST:
- return self.intersect_instance(inputnode, exitnode)
- if unique == UNIQUE_ARRAY:
- return self.intersect_array(inputnode, exitnode)
- if unique == UNIQUE_STRUCT:
- return self.intersect_struct(inputnode, exitnode)
- assert 0, "unknown value for exitnode.unique: %d" % ord(unique)
-
- def compute_common_fields(self, orig, d):
- fields = []
- if orig is not None:
- if d is not None:
- d = d.copy()
- else:
- d = {}
- for ofs in orig:
- d.setdefault(ofs, self.node_escaped)
- if d is not None:
- lst = d.keys()
- # we always use the "standardized" order of fields
- sort_descrs(lst)
- for ofs in lst:
- try:
- if orig is None:
- raise KeyError
- node = orig[ofs]
- except KeyError:
- # field stored at exit, but not read at input. Must
- # still be allocated, otherwise it will be incorrectly
- # uninitialized after a guard failure.
- node = self.node_fromstart
- specnode = self.intersect(node, d[ofs])
- fields.append((ofs, specnode))
- return fields
-
- def intersect_instance(self, inputnode, exitnode):
- if (inputnode.knownclsbox is not None and
- not inputnode.knownclsbox.same_constant(exitnode.knownclsbox)):
- # unique match, but the class is known to be a mismatch
- raise InvalidLoop
- #
- fields = self.compute_common_fields(inputnode.origfields,
- exitnode.curfields)
- return VirtualInstanceSpecNode(exitnode.knownclsbox, fields)
-
- def intersect_array(self, inputnode, exitnode):
- assert inputnode.arraydescr is None
- #
- items = []
- for i in range(exitnode.arraysize):
- if exitnode.curitems is None:
- exitsubnode = self.node_escaped
- else:
- exitsubnode = exitnode.curitems.get(i, self.node_escaped)
- if inputnode.origitems is None:
- node = self.node_fromstart
- else:
- node = inputnode.origitems.get(i, self.node_fromstart)
- specnode = self.intersect(node, exitsubnode)
- items.append(specnode)
- return VirtualArraySpecNode(exitnode.arraydescr, items)
-
- def intersect_struct(self, inputnode, exitnode):
- assert inputnode.structdescr is None
- #
- fields = self.compute_common_fields(inputnode.origfields,
- exitnode.curfields)
- return VirtualStructSpecNode(exitnode.structdescr, fields)
-
-# ____________________________________________________________
-# A subclass of NodeFinder for bridges only
-
-class __extend__(SpecNode):
- def make_instance_node(self):
- raise NotImplementedError
- def matches_instance_node(self, exitnode):
- raise NotImplementedError
-
-class __extend__(NotSpecNode):
- def make_instance_node(self):
- return NodeFinder.node_escaped
- def matches_instance_node(self, exitnode):
- return True
-
-class __extend__(ConstantSpecNode):
- def make_instance_node(self):
- raise AssertionError, "not implemented (but not used actually)"
- def matches_instance_node(self, exitnode):
- if exitnode.knownvaluebox is None:
- return False
- return self.constbox.same_constant(exitnode.knownvaluebox)
-
-class __extend__(VirtualInstanceSpecNode):
- def make_instance_node(self):
- instnode = InstanceNode()
- instnode.knownclsbox = self.known_class
- instnode.curfields = {}
- for ofs, subspecnode in self.fields:
- instnode.curfields[ofs] = subspecnode.make_instance_node()
- return instnode
-
- def matches_instance_node(self, exitnode):
- if exitnode.unique == UNIQUE_NO:
- return False
- #
- assert exitnode.unique == UNIQUE_INST
- if not self.known_class.same_constant(exitnode.knownclsbox):
- # unique match, but the class is known to be a mismatch
- return False
- #
- return matches_fields(self.fields, exitnode.curfields)
-
-def matches_fields(fields, d):
- seen = 0
- for ofs, subspecnode in fields:
- try:
- if d is None:
- raise KeyError
- instnode = d[ofs]
- seen += 1
- except KeyError:
- instnode = NodeFinder.node_escaped
- if not subspecnode.matches_instance_node(instnode):
- return False
- if d is not None and len(d) > seen:
- return False # some key is in d but not in fields
- return True
-
-class __extend__(VirtualArraySpecNode):
- def make_instance_node(self):
- raise AssertionError, "not implemented (but not used actually)"
- def matches_instance_node(self, exitnode):
- if exitnode.unique == UNIQUE_NO:
- return False
- #
- assert exitnode.unique == UNIQUE_ARRAY
- assert self.arraydescr == exitnode.arraydescr
- if len(self.items) != exitnode.arraysize:
- # the size is known to be a mismatch
- return False
- #
- d = exitnode.curitems
- for i in range(exitnode.arraysize):
- try:
- if d is None:
- raise KeyError
- itemnode = d[i]
- except KeyError:
- itemnode = NodeFinder.node_escaped
- subspecnode = self.items[i]
- if not subspecnode.matches_instance_node(itemnode):
- return False
- return True
-
-class __extend__(VirtualStructSpecNode):
- def make_instance_node(self):
- raise AssertionError, "not implemented (but not used actually)"
- def matches_instance_node(self, exitnode):
- if exitnode.unique == UNIQUE_NO:
- return False
- #
- assert exitnode.unique == UNIQUE_STRUCT
- assert self.typedescr == exitnode.structdescr
- #
- return matches_fields(self.fields, exitnode.curfields)
-
-
-class BridgeSpecializationFinder(NodeFinder):
-
- def find_nodes_bridge(self, bridge, specnodes=None):
- if specnodes is not None: # not used actually
- self.setup_bridge_input_nodes(specnodes, bridge.inputargs)
- self.find_nodes(bridge.operations)
- self.jump_op = bridge.operations[-1]
-
- def setup_bridge_input_nodes(self, specnodes, inputargs):
- assert len(specnodes) == len(inputargs)
- for i in range(len(inputargs)):
- instnode = specnodes[i].make_instance_node()
- box = inputargs[i]
- self.nodes[box] = instnode
-
- def bridge_matches(self, nextloop_specnodes):
- jump_op = self.jump_op
- assert jump_op.numargs() == len(nextloop_specnodes)
- for i in range(len(nextloop_specnodes)):
- exitnode = self.getnode(jump_op.getarg(i))
- if not nextloop_specnodes[i].matches_instance_node(exitnode):
- return False
- return True
diff --git a/pypy/module/array/benchmark/loop.py b/pypy/module/array/benchmark/loop.py
deleted file mode 100644
--- a/pypy/module/array/benchmark/loop.py
+++ /dev/null
@@ -1,7 +0,0 @@
-def h():
- s=0
- i=0
- while i<100000:
- s+=i
- i+=1
- return s
diff --git a/pypy/jit/metainterp/test/test_optimizefindnode.py b/pypy/jit/metainterp/test/test_optimizefindnode.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_optimizefindnode.py
+++ /dev/null
@@ -1,1199 +0,0 @@
-import py, random
-
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
-from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
-
-from pypy.jit.backend.llgraph import runner
-from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr,
- Const, TreeLoop, BoxObj,
- ConstObj, AbstractDescr)
-from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder
-from pypy.jit.metainterp.optimizefindnode import BridgeSpecializationFinder
-from pypy.jit.metainterp.optimizeutil import sort_descrs, InvalidLoop
-from pypy.jit.metainterp.specnode import NotSpecNode, prebuiltNotSpecNode
-from pypy.jit.metainterp.specnode import VirtualInstanceSpecNode
-from pypy.jit.metainterp.specnode import VirtualArraySpecNode
-from pypy.jit.metainterp.specnode import VirtualStructSpecNode
-from pypy.jit.metainterp.specnode import ConstantSpecNode
-from pypy.jit.codewriter.effectinfo import EffectInfo
-from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int
-from pypy.jit.tool.oparser import parse
-
-def test_sort_descrs():
- class PseudoDescr(AbstractDescr):
- def __init__(self, n):
- self.n = n
- def sort_key(self):
- return self.n
- for i in range(17):
- lst = [PseudoDescr(j) for j in range(i)]
- lst2 = lst[:]
- random.shuffle(lst2)
- sort_descrs(lst2)
- assert lst2 == lst
-
-# ____________________________________________________________
-
-class LLtypeMixin(object):
- type_system = 'lltype'
-
- def get_class_of_box(self, box):
- return box.getref(rclass.OBJECTPTR).typeptr
-
- node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
- node_vtable.name = rclass.alloc_array_name('node')
- node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable)
- node_vtable2 = lltype.malloc(OBJECT_VTABLE, immortal=True)
- node_vtable2.name = rclass.alloc_array_name('node2')
- node_vtable_adr2 = llmemory.cast_ptr_to_adr(node_vtable2)
- cpu = runner.LLtypeCPU(None)
-
- NODE = lltype.GcForwardReference()
- NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT),
- ('value', lltype.Signed),
- ('floatval', lltype.Float),
- ('next', lltype.Ptr(NODE))))
- NODE2 = lltype.GcStruct('NODE2', ('parent', NODE),
- ('other', lltype.Ptr(NODE)))
- node = lltype.malloc(NODE)
- node.parent.typeptr = node_vtable
- nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node))
- myptr = nodebox.value
- myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(NODE))
- nodebox2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node))
- nodesize = cpu.sizeof(NODE)
- nodesize2 = cpu.sizeof(NODE2)
- valuedescr = cpu.fielddescrof(NODE, 'value')
- floatdescr = cpu.fielddescrof(NODE, 'floatval')
- nextdescr = cpu.fielddescrof(NODE, 'next')
- otherdescr = cpu.fielddescrof(NODE2, 'other')
-
- NODEOBJ = lltype.GcStruct('NODEOBJ', ('parent', OBJECT),
- ('ref', lltype.Ptr(OBJECT)))
- nodeobj = lltype.malloc(NODEOBJ)
- nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj)
- refdescr = cpu.fielddescrof(NODEOBJ, 'ref')
-
- arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
- floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
-
- # a GcStruct not inheriting from OBJECT
- S = lltype.GcStruct('TUPLE', ('a', lltype.Signed), ('b', lltype.Ptr(NODE)))
- ssize = cpu.sizeof(S)
- adescr = cpu.fielddescrof(S, 'a')
- bdescr = cpu.fielddescrof(S, 'b')
- sbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)))
- arraydescr2 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(S)))
-
- T = lltype.GcStruct('TUPLE',
- ('c', lltype.Signed),
- ('d', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))
- tsize = cpu.sizeof(T)
- cdescr = cpu.fielddescrof(T, 'c')
- ddescr = cpu.fielddescrof(T, 'd')
- arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE)))
-
- U = lltype.GcStruct('U',
- ('parent', OBJECT),
- ('one', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))
- u_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
- u_vtable_adr = llmemory.cast_ptr_to_adr(u_vtable)
- usize = cpu.sizeof(U)
- onedescr = cpu.fielddescrof(U, 'one')
-
- FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
- plaincalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
- nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], []))
- writeadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [adescr], []))
- writearraydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [adescr], [arraydescr]))
- readadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([adescr], [], []))
- mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([nextdescr], [], [],
- EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE))
- arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], oopspecindex=EffectInfo.OS_ARRAYCOPY))
-
- for _name, _os in [
- ('strconcatdescr', 'OS_STR_CONCAT'),
- ('strslicedescr', 'OS_STR_SLICE'),
- ('strequaldescr', 'OS_STR_EQUAL'),
- ('streq_slice_checknull_descr', 'OS_STREQ_SLICE_CHECKNULL'),
- ('streq_slice_nonnull_descr', 'OS_STREQ_SLICE_NONNULL'),
- ('streq_slice_char_descr', 'OS_STREQ_SLICE_CHAR'),
- ('streq_nonnull_descr', 'OS_STREQ_NONNULL'),
- ('streq_nonnull_char_descr', 'OS_STREQ_NONNULL_CHAR'),
- ('streq_checknull_char_descr', 'OS_STREQ_CHECKNULL_CHAR'),
- ('streq_lengthok_descr', 'OS_STREQ_LENGTHOK'),
- ]:
- _oopspecindex = getattr(EffectInfo, _os)
- locals()[_name] = \
- cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], oopspecindex=_oopspecindex))
- #
- _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
- locals()[_name.replace('str', 'unicode')] = \
- cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], oopspecindex=_oopspecindex))
-
- s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE))
- #
-
- class LoopToken(AbstractDescr):
- pass
- asmdescr = LoopToken() # it can be whatever, it's not a descr though
-
- from pypy.jit.metainterp.virtualref import VirtualRefInfo
- class FakeWarmRunnerDesc:
- pass
- FakeWarmRunnerDesc.cpu = cpu
- vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc)
- virtualtokendescr = vrefinfo.descr_virtual_token
- virtualrefindexdescr = vrefinfo.descr_virtualref_index
- virtualforceddescr = vrefinfo.descr_forced
- jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable
- jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable)
-
- register_known_gctype(cpu, node_vtable, NODE)
- register_known_gctype(cpu, node_vtable2, NODE2)
- register_known_gctype(cpu, u_vtable, U)
- register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF)
-
- namespace = locals()
-
-class OOtypeMixin_xxx_disabled(object):
- type_system = 'ootype'
-
-## def get_class_of_box(self, box):
-## root = box.getref(ootype.ROOT)
-## return ootype.classof(root)
-
-## cpu = runner.OOtypeCPU(None)
-## NODE = ootype.Instance('NODE', ootype.ROOT, {})
-## NODE._add_fields({'value': ootype.Signed,
-## 'floatval' : ootype.Float,
-## 'next': NODE})
-## NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE})
-
-## node_vtable = ootype.runtimeClass(NODE)
-## node_vtable_adr = ootype.cast_to_object(node_vtable)
-## node_vtable2 = ootype.runtimeClass(NODE2)
-## node_vtable_adr2 = ootype.cast_to_object(node_vtable2)
-
-## node = ootype.new(NODE)
-## nodebox = BoxObj(ootype.cast_to_object(node))
-## myptr = nodebox.value
-## myptr2 = ootype.cast_to_object(ootype.new(NODE))
-## nodebox2 = BoxObj(ootype.cast_to_object(node))
-## valuedescr = cpu.fielddescrof(NODE, 'value')
-## floatdescr = cpu.fielddescrof(NODE, 'floatval')
-## nextdescr = cpu.fielddescrof(NODE, 'next')
-## otherdescr = cpu.fielddescrof(NODE2, 'other')
-## nodesize = cpu.typedescrof(NODE)
-## nodesize2 = cpu.typedescrof(NODE2)
-
-## arraydescr = cpu.arraydescrof(ootype.Array(ootype.Signed))
-## floatarraydescr = cpu.arraydescrof(ootype.Array(ootype.Float))
-
-## # a plain Record
-## S = ootype.Record({'a': ootype.Signed, 'b': NODE})
-## ssize = cpu.typedescrof(S)
-## adescr = cpu.fielddescrof(S, 'a')
-## bdescr = cpu.fielddescrof(S, 'b')
-## sbox = BoxObj(ootype.cast_to_object(ootype.new(S)))
-## arraydescr2 = cpu.arraydescrof(ootype.Array(S))
-
-## T = ootype.Record({'c': ootype.Signed,
-## 'd': ootype.Array(NODE)})
-## tsize = cpu.typedescrof(T)
-## cdescr = cpu.fielddescrof(T, 'c')
-## ddescr = cpu.fielddescrof(T, 'd')
-## arraydescr3 = cpu.arraydescrof(ootype.Array(NODE))
-
-## U = ootype.Instance('U', ootype.ROOT, {'one': ootype.Array(NODE)})
-## usize = cpu.typedescrof(U)
-## onedescr = cpu.fielddescrof(U, 'one')
-## u_vtable = ootype.runtimeClass(U)
-## u_vtable_adr = ootype.cast_to_object(u_vtable)
-
-## # force a consistent order
-## valuedescr.sort_key()
-## nextdescr.sort_key()
-## adescr.sort_key()
-## bdescr.sort_key()
-
-## FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
-## nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) # XXX fix ootype
-
-## cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE),
-## node_vtable_adr2: cpu.typedescrof(NODE2),
-## u_vtable_adr: cpu.typedescrof(U)}
-## namespace = locals()
-
-class BaseTest(object):
- invent_fail_descr = None
-
- def parse(self, s, boxkinds=None):
- return parse(s, self.cpu, self.namespace,
- type_system=self.type_system,
- boxkinds=boxkinds,
- invent_fail_descr=self.invent_fail_descr)
-
- def unpack_specnodes(self, text):
- #
- def constclass(cls_vtable):
- if self.type_system == 'lltype':
- return ConstInt(adr2int(llmemory.cast_ptr_to_adr(cls_vtable)))
- else:
- return ConstObj(ootype.cast_to_object(cls_vtable))
- def constant(value):
- if isinstance(lltype.typeOf(value), lltype.Ptr):
- return ConstPtr(value)
- elif isinstance(ootype.typeOf(value), ootype.OOType):
- return ConstObj(ootype.cast_to_object(value))
- else:
- return ConstInt(value)
-
- def parsefields(kwds_fields):
- fields = []
- for key, value in kwds_fields.items():
- fields.append((self.namespace[key], value))
- fields.sort(key = lambda (x, _): x.sort_key())
- return fields
- def makeConstant(value):
- return ConstantSpecNode(constant(value))
- def makeVirtual(cls_vtable, **kwds_fields):
- fields = parsefields(kwds_fields)
- return VirtualInstanceSpecNode(constclass(cls_vtable), fields)
- def makeVirtualArray(arraydescr, *items):
- return VirtualArraySpecNode(arraydescr, items)
- def makeVirtualStruct(typedescr, **kwds_fields):
- fields = parsefields(kwds_fields)
- return VirtualStructSpecNode(typedescr, fields)
- #
- context = {'Not': prebuiltNotSpecNode,
- 'Constant': makeConstant,
- 'Virtual': makeVirtual,
- 'VArray': makeVirtualArray,
- 'VStruct': makeVirtualStruct}
- lst = eval('[' + text + ']', self.namespace, context)
- return lst
-
- def check_specnodes(self, specnodes, text):
- lst = self.unpack_specnodes(text)
- assert len(specnodes) == len(lst)
- for x, y in zip(specnodes, lst):
- assert x.equals(y, ge=False)
- return True
-
-# ____________________________________________________________
-
-class BaseTestOptimizeFindNode(BaseTest):
-
- def find_nodes(self, ops, spectext, boxkinds=None):
- assert boxkinds is None or isinstance(boxkinds, dict)
- loop = self.parse(ops, boxkinds=boxkinds)
- perfect_specialization_finder = PerfectSpecializationFinder(self.cpu)
- perfect_specialization_finder.find_nodes_loop(loop)
- self.check_specnodes(loop.token.specnodes, spectext)
- return (loop.getboxes(), perfect_specialization_finder.getnode)
-
- def test_find_nodes_simple(self):
- ops = """
- [i]
- i0 = int_sub(i, 1)
- guard_value(i0, 0) [i0]
- jump(i0)
- """
- boxes, getnode = self.find_nodes(ops, 'Not')
- assert getnode(boxes.i).fromstart
- assert not getnode(boxes.i0).fromstart
-
- def test_find_nodes_non_escape(self):
- ops = """
- [p0]
- p1 = getfield_gc(p0, descr=nextdescr)
- i0 = getfield_gc(p1, descr=valuedescr)
- i1 = int_sub(i0, 1)
- p2 = getfield_gc(p0, descr=nextdescr)
- setfield_gc(p2, i1, descr=valuedescr)
- p3 = new_with_vtable(ConstClass(node_vtable))
- jump(p3)
- """
- boxes, getnode = self.find_nodes(ops,
- 'Virtual(node_vtable, nextdescr=Not)')
- assert not getnode(boxes.p0).escaped
- assert getnode(boxes.p1).escaped
- assert getnode(boxes.p2).escaped
- assert getnode(boxes.p0).fromstart
- assert getnode(boxes.p1).fromstart
- assert getnode(boxes.p2).fromstart
-
- def test_find_nodes_escape(self):
- ops = """
- [p0]
- p1 = getfield_gc(p0, descr=nextdescr)
- p2 = getfield_gc(p1, descr=nextdescr)
- i0 = getfield_gc(p2, descr=valuedescr)
- i1 = int_sub(i0, 1)
- escape(p1)
- p3 = getfield_gc(p0, descr=nextdescr)
- setfield_gc(p3, i1, descr=valuedescr)
- p4 = getfield_gc(p1, descr=nextdescr)
- setfield_gc(p4, i1, descr=valuedescr)
- p5 = new_with_vtable(ConstClass(node_vtable))
- jump(p5)
- """
- boxes, getnode = self.find_nodes(ops,
- 'Virtual(node_vtable, nextdescr=Not)')
- assert not getnode(boxes.p0).escaped
- assert getnode(boxes.p1).escaped
- assert getnode(boxes.p2).escaped # forced by p1
- assert getnode(boxes.p3).escaped # forced because p3 == p1
- assert getnode(boxes.p4).escaped # forced by p1
- assert getnode(boxes.p0).fromstart
- assert getnode(boxes.p1).fromstart
- assert getnode(boxes.p2).fromstart
- assert getnode(boxes.p3).fromstart
- assert not getnode(boxes.p4).fromstart
-
- def test_find_nodes_new_1(self):
- ops = """
- [p1]
- p2 = new_with_vtable(ConstClass(node_vtable))
- jump(p2)
- """
- boxes, getnode = self.find_nodes(ops, 'Virtual(node_vtable)')
-
- boxp1 = getnode(boxes.p1)
- boxp2 = getnode(boxes.p2)
- assert not boxp1.escaped
- assert not boxp2.escaped
-
- assert not boxp1.origfields
- assert not boxp1.curfields
- assert not boxp2.origfields
- assert not boxp2.curfields
-
- assert boxp1.fromstart
- assert not boxp2.fromstart
-
- assert boxp1.knownclsbox is None
- assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr
-
- def test_find_nodes_new_2(self):
- ops = """
- [i1, p1]
- p2 = new_with_vtable(ConstClass(node_vtable))
- p3 = new_with_vtable(ConstClass(node_vtable2))
- setfield_gc(p2, p3, descr=nextdescr)
- setfield_gc(p3, i1, descr=valuedescr)
- jump(i1, p2)
- """
- self.find_nodes(ops,
- '''Not,
- Virtual(node_vtable,
- nextdescr=Virtual(node_vtable2,
- valuedescr=Not))''')
-
- def test_find_nodes_new_3(self):
- ops = """
- [sum, p1]
- guard_class(p1, ConstClass(node_vtable)) []
- i1 = getfield_gc(p1, descr=valuedescr)
- i2 = int_sub(i1, 1)
- sum2 = int_add(sum, i1)
- p2 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p2, i2, descr=valuedescr)
- p3 = new_with_vtable(ConstClass(node_vtable2))
- setfield_gc(p2, p3, descr=nextdescr)
- jump(sum2, p2)
- """
- boxes, getnode = self.find_nodes(
- ops,
- '''Not,
- Virtual(node_vtable,
- valuedescr=Not,
- nextdescr=Virtual(node_vtable2))''',
- boxkinds={'sum': BoxInt, 'sum2': BoxInt})
- assert getnode(boxes.sum) is not getnode(boxes.sum2)
- assert getnode(boxes.p1) is not getnode(boxes.p2)
-
- boxp1 = getnode(boxes.p1)
- boxp2 = getnode(boxes.p2)
- boxp3 = getnode(boxes.p3)
- assert not boxp1.escaped
- assert not boxp2.escaped
- assert not boxp3.escaped
-
- assert not boxp1.curfields
- assert boxp1.origfields[self.valuedescr] is getnode(boxes.i1)
- assert not boxp2.origfields
- assert boxp2.curfields[self.nextdescr] is boxp3
-
- assert boxp1.fromstart
- assert not boxp2.fromstart
- assert not boxp3.fromstart
-
- assert boxp2.knownclsbox.getaddr() == self.node_vtable_adr
- assert boxp3.knownclsbox.getaddr() == self.node_vtable_adr2
-
- def test_find_nodes_new_aliasing_0(self):
- ops = """
- [p1, p2]
- p3 = new_with_vtable(ConstClass(node_vtable))
- jump(p3, p3)
- """
- # both p1 and p2 must be NotSpecNodes; it's not possible to pass
- # the same Virtual both in p1 and p2 (at least so far).
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_new_aliasing_1(self):
- ops = """
- [sum, p1]
- guard_class(p1, ConstClass(node_vtable)) []
- p3 = getfield_gc(p1, descr=nextdescr)
- guard_class(p3, ConstClass(node_vtable)) []
- i1 = getfield_gc(p1, descr=valuedescr)
- i2 = int_sub(i1, 1)
- sum2 = int_add(sum, i1)
- p2 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p2, i2, descr=valuedescr)
- setfield_gc(p2, p2, descr=nextdescr)
- jump(sum2, p2)
- """
- # the issue is the cycle "p2->p2", which cannot be represented
- # with SpecNodes so far
- self.find_nodes(ops, 'Not, Not',
- boxkinds={'sum': BoxInt, 'sum2': BoxInt})
-
- def test_find_nodes_new_aliasing_2(self):
- ops = """
- [p1, p2]
- escape(p2)
- p3 = new_with_vtable(ConstClass(node_vtable))
- jump(p3, p3)
- """
- # both p1 and p2 must be NotSpecNodes; it's not possible to pass
- # in p1 a Virtual and not in p2, as they both come from the same p3.
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_new_mismatch(self):
- ops = """
- [p1]
- guard_class(p1, ConstClass(node_vtable)) []
- p2 = new_with_vtable(ConstClass(node_vtable2))
- jump(p2)
- """
- # this is not a valid loop at all, because of the mismatch
- # between the produced and the consumed class.
- py.test.raises(InvalidLoop, self.find_nodes, ops, None)
-
- def test_find_nodes_new_aliasing_mismatch(self):
- ops = """
- [p0, p1]
- guard_class(p0, ConstClass(node_vtable)) []
- guard_class(p1, ConstClass(node_vtable2)) []
- p2 = new_with_vtable(ConstClass(node_vtable2))
- jump(p2, p2)
- """
- # this is also not really a valid loop, but it's not detected
- # because p2 is passed more than once in the jump().
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_new_escapes(self):
- ops = """
- [p0]
- escape(p0)
- p1 = new_with_vtable(ConstClass(node_vtable))
- jump(p1)
- """
- self.find_nodes(ops, 'Not')
-
- def test_find_nodes_new_unused(self):
- ops = """
- [p0]
- p1 = new_with_vtable(ConstClass(node_vtable))
- p2 = new_with_vtable(ConstClass(node_vtable))
- p3 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, p2, descr=nextdescr)
- setfield_gc(p2, p3, descr=nextdescr)
- jump(p1)
- """
- self.find_nodes(ops, '''
- Virtual(node_vtable,
- nextdescr=Virtual(node_vtable,
- nextdescr=Virtual(node_vtable)))''')
-
- def test_find_nodes_ptr_eq(self):
- ops = """
- [p3, p4, p2]
- p0 = new_with_vtable(ConstClass(node_vtable))
- p1 = new_with_vtable(ConstClass(node_vtable))
- guard_nonnull(p0) []
- i3 = ptr_ne(p0, NULL)
- guard_true(i3) []
- i4 = ptr_eq(p0, NULL)
- guard_false(i4) []
- i5 = ptr_ne(NULL, p0)
- guard_true(i5) []
- i6 = ptr_eq(NULL, p0)
- guard_false(i6) []
- i7 = ptr_ne(p0, p1)
- guard_true(i7) []
- i8 = ptr_eq(p0, p1)
- guard_false(i8) []
- i9 = ptr_ne(p0, p2)
- guard_true(i9) []
- i10 = ptr_eq(p0, p2)
- guard_false(i10) []
- i11 = ptr_ne(p2, p1)
- guard_true(i11) []
- i12 = ptr_eq(p2, p1)
- guard_false(i12) []
- jump(p0, p1, p2)
- """
- self.find_nodes(ops, '''Virtual(node_vtable),
- Virtual(node_vtable),
- Not''')
-
- def test_find_nodes_call(self):
- ops = """
- [i0, p2]
- p0 = new_with_vtable(ConstClass(node_vtable))
- i1 = call_pure(i0, p0) # forces p0 to not be virtual
- jump(i1, p0)
- """
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_default_field(self):
- ops = """
- [p0]
- i0 = getfield_gc(p0, descr=valuedescr)
- guard_value(i0, 5) []
- p1 = new_with_vtable(ConstClass(node_vtable))
- # the field 'value' has its default value of 0
- jump(p1)
- """
- # The answer must contain the 'value' field, because otherwise
- # we might get incorrect results: when tracing, i0 was 5.
- self.find_nodes(ops, 'Virtual(node_vtable, valuedescr=Not)')
-
- def test_find_nodes_nonvirtual_guard_class(self):
- ops = """
- [p1]
- guard_class(p1, ConstClass(node_vtable)) [p1]
- jump(p1)
- """
- self.find_nodes(ops, 'Not')
-
- def test_find_nodes_p12_simple(self):
- ops = """
- [p1]
- i3 = getfield_gc(p1, descr=valuedescr)
- escape(i3)
- jump(p1)
- """
- self.find_nodes(ops, 'Not')
-
- def test_find_nodes_p123_simple(self):
- ops = """
- [i1, p2, p3]
- i3 = getfield_gc(p3, descr=valuedescr)
- escape(i3)
- p1 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, i1, descr=valuedescr)
- jump(i1, p1, p2)
- """
- # We cannot track virtuals that survive for more than two iterations.
- self.find_nodes(ops, 'Not, Not, Not')
-
- def test_find_nodes_p1234_simple(self):
- ops = """
- [i1, p2, p3, p4]
- i4 = getfield_gc(p4, descr=valuedescr)
- escape(i4)
- p1 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, i1, descr=valuedescr)
- jump(i1, p1, p2, p3)
- """
- # We cannot track virtuals that survive for more than two iterations.
- self.find_nodes(ops, 'Not, Not, Not, Not')
-
- def test_find_nodes_p123_guard_class(self):
- ops = """
- [i1, p2, p3]
- guard_class(p3, ConstClass(node_vtable)) [i1, p2, p3]
- i3 = getfield_gc(p3, descr=valuedescr)
- escape(i3)
- p1 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, i1, descr=valuedescr)
- jump(i1, p1, p2)
- """
- # We cannot track virtuals that survive for more than two iterations.
- self.find_nodes(ops, 'Not, Not, Not')
-
- def test_find_nodes_p123_rec(self):
- ops = """
- [i1, p2, p0d]
- p3 = getfield_gc(p0d, descr=nextdescr)
- i3 = getfield_gc(p3, descr=valuedescr)
- escape(i3)
- p1 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, i1, descr=valuedescr)
- p0c = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p0c, p2, descr=nextdescr)
- jump(i1, p1, p0c)
- """
- # We cannot track virtuals that survive for more than two iterations.
- self.find_nodes(ops, '''Not,
- Not,
- Virtual(node_vtable, nextdescr=Not)''')
-
- def test_find_nodes_setfield_bug(self):
- ops = """
- [p1, p2]
- escape(p1)
- setfield_gc(p1, p2, descr=nextdescr)
- p3 = new_with_vtable(ConstClass(node_vtable))
- jump(p1, p3)
- """
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_array_virtual_1(self):
- ops = """
- [i1, p2]
- i2 = getarrayitem_gc(p2, 1, descr=arraydescr)
- escape(i2)
- p3 = new_array(3, descr=arraydescr)
- setarrayitem_gc(p3, 1, i1, descr=arraydescr)
- jump(i1, p3)
- """
- self.find_nodes(ops, 'Not, VArray(arraydescr, Not, Not, Not)')
-
- def test_find_nodes_array_virtual_2(self):
- ops = """
- [i1, p2]
- i2 = arraylen_gc(p2, descr=arraydescr)
- escape(i2)
- p3 = new_array(3, descr=arraydescr)
- setarrayitem_gc(p3, 1, i1, descr=arraydescr)
- jump(i1, p3)
- """
- self.find_nodes(ops, 'Not, VArray(arraydescr, Not, Not, Not)')
-
- def test_find_nodes_array_virtual_3(self):
- ops = """
- [pvalue1, p2]
- pvalue2 = new_with_vtable(ConstClass(node_vtable2))
- ps2 = getarrayitem_gc(p2, 1, descr=arraydescr)
- setfield_gc(ps2, pvalue2, descr=nextdescr)
- ps3 = getarrayitem_gc(p2, 1, descr=arraydescr)
- pvalue3 = getfield_gc(ps3, descr=nextdescr)
- ps1 = new_with_vtable(ConstClass(node_vtable))
- p3 = new_array(3, descr=arraydescr)
- setarrayitem_gc(p3, 1, ps1, descr=arraydescr)
- jump(pvalue3, p3)
- """
- self.find_nodes(ops, 'Virtual(node_vtable2), VArray(arraydescr, Not, Virtual(node_vtable), Not)')
-
- def test_find_nodes_array_virtual_empty(self):
- ops = """
- [i1, p2]
- p3 = new_array(3, descr=arraydescr)
- jump(i1, p3)
- """
- self.find_nodes(ops, 'Not, VArray(arraydescr, Not, Not, Not)')
-
- def test_find_nodes_array_nonvirtual_1(self):
- ops = """
- [i1, p2]
- i2 = getarrayitem_gc(p2, i1, descr=arraydescr)
- escape(i2)
- p3 = new_array(4, descr=arraydescr)
- setarrayitem_gc(p3, i1, i2, descr=arraydescr)
- jump(i1, p3)
- """
- # Does not work because of the variable index, 'i1'.
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_array_forced_1(self):
- ops = """
- [p1, i1]
- p2 = new_array(1, descr=arraydescr)
- setarrayitem_gc(p2, 0, p1, descr=arraydescr)
- p3 = getarrayitem_gc(p2, i1, descr=arraydescr)
- p4 = new_with_vtable(ConstClass(node_vtable))
- jump(p4, i1)
- """
- # escapes because getarrayitem_gc uses a non-constant index
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_arrayitem_forced(self):
- ops = """
- [p1]
- p2 = new_array(1, descr=arraydescr)
- escape(p2)
- p4 = new_with_vtable(ConstClass(node_vtable))
- setarrayitem_gc(p2, 0, p4, descr=arraydescr)
- jump(p4)
- """
- self.find_nodes(ops, 'Not')
-
- def test_find_nodes_struct_virtual_1(self):
- ops = """
- [i1, p2]
- i2 = getfield_gc(p2, descr=adescr)
- escape(i2)
- p3 = new(descr=ssize)
- setfield_gc(p3, i1, descr=adescr)
- jump(i1, p3)
- """
- self.find_nodes(ops, 'Not, VStruct(ssize, adescr=Not)')
-
- def test_find_nodes_struct_nonvirtual_1(self):
- ops = """
- [i1, p2]
- i2 = getfield_gc(p2, descr=adescr)
- escape(p2)
- p3 = new(descr=ssize)
- setfield_gc(p3, i1, descr=adescr)
- jump(i1, p3)
- """
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_guard_value_constant(self):
- ops = """
- [p1]
- guard_value(p1, ConstPtr(myptr)) []
- jump(ConstPtr(myptr))
- """
- self.find_nodes(ops, 'Constant(myptr)')
-
- def test_find_nodes_guard_value_constant_mismatch(self):
- ops = """
- [p1]
- guard_value(p1, ConstPtr(myptr2)) []
- jump(ConstPtr(myptr))
- """
- py.test.raises(InvalidLoop, self.find_nodes, ops, None)
-
- def test_find_nodes_guard_value_escaping_constant(self):
- ops = """
- [p1]
- escape(p1)
- guard_value(p1, ConstPtr(myptr)) []
- jump(ConstPtr(myptr))
- """
- self.find_nodes(ops, 'Constant(myptr)')
-
- def test_find_nodes_guard_value_same_as_constant(self):
- ops = """
- [p1]
- guard_value(p1, ConstPtr(myptr)) []
- p2 = same_as(ConstPtr(myptr))
- jump(p2)
- """
- self.find_nodes(ops, 'Constant(myptr)')
-
- def test_find_nodes_store_into_loop_constant_1(self):
- ops = """
- [i0, p1, p4]
- p2 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, p2, descr=nextdescr)
- jump(i0, p1, p2)
- """
- self.find_nodes(ops, 'Not, Not, Not')
-
- def test_find_nodes_store_into_loop_constant_2(self):
- ops = """
- [i0, p4, p1]
- p2 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, p2, descr=nextdescr)
- jump(i0, p2, p1)
- """
- self.find_nodes(ops, 'Not, Not, Not')
-
- def test_find_nodes_store_into_loop_constant_3(self):
- ops = """
- [i0, p1]
- p2 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, p2, descr=nextdescr)
- call(i0)
- jump(i0, p1)
- """
- self.find_nodes(ops, 'Not, Not')
-
- def test_find_nodes_arithmetic_propagation_bug_0(self):
- ops = """
- [p1]
- i1 = getarrayitem_gc(p1, 0, descr=arraydescr)
- escape(i1)
- i2 = int_add(0, 1)
- p2 = new_array(i2, descr=arraydescr)
- i3 = escape()
- setarrayitem_gc(p2, 0, i3, descr=arraydescr)
- jump(p2)
- """
- self.find_nodes(ops, 'VArray(arraydescr, Not)')
-
- def test_find_nodes_arithmetic_propagation_bug_1(self):
- ops = """
- [p1]
- i1 = getarrayitem_gc(p1, 0, descr=arraydescr)
- escape(i1)
- i2 = same_as(1)
- p2 = new_array(i2, descr=arraydescr)
- setarrayitem_gc(p2, 0, 5)
- jump(p2)
- """
- self.find_nodes(ops, 'VArray(arraydescr, Not)')
-
- def test_find_nodes_arithmetic_propagation_bug_2(self):
- ops = """
- [p1]
- i0 = int_sub(17, 17)
- i1 = getarrayitem_gc(p1, i0, descr=arraydescr)
- escape(i1)
- i2 = int_add(0, 1)
- p2 = new_array(i2, descr=arraydescr)
- i3 = escape()
- setarrayitem_gc(p2, i0, i3, descr=arraydescr)
- jump(p2)
- """
- self.find_nodes(ops, 'VArray(arraydescr, Not)')
-
- def test_find_nodes_arithmetic_propagation_bug_3(self):
- ops = """
- [p1]
- i1 = getarrayitem_gc(p1, 0, descr=arraydescr)
- escape(i1)
- p3 = new_array(1, descr=arraydescr)
- i2 = arraylen_gc(p3, descr=arraydescr)
- p2 = new_array(i2, descr=arraydescr)
- i3 = escape()
- setarrayitem_gc(p2, 0, i3, descr=arraydescr)
- jump(p2)
- """
- self.find_nodes(ops, 'VArray(arraydescr, Not)')
-
- def test_find_nodes_bug_1(self):
- ops = """
- [p12]
- guard_nonnull(p12) []
- guard_class(p12, ConstClass(node_vtable)) []
- guard_class(p12, ConstClass(node_vtable)) []
- i22 = getfield_gc_pure(p12, descr=valuedescr)
- escape(i22)
- guard_nonnull(p12) []
- guard_class(p12, ConstClass(node_vtable)) []
- guard_class(p12, ConstClass(node_vtable)) []
- i29 = getfield_gc_pure(p12, descr=valuedescr)
- i31 = int_add_ovf(i29, 1)
- guard_no_overflow() []
- p33 = new_with_vtable(ConstClass(node_vtable)) # NODE
- setfield_gc(p33, i31, descr=valuedescr)
- #
- p35 = new_array(1, descr=arraydescr3) # Array(NODE)
- setarrayitem_gc(p35, 0, p33, descr=arraydescr3)
- p38 = new_with_vtable(ConstClass(u_vtable)) # U
- setfield_gc(p38, p35, descr=onedescr)
- guard_nonnull(p38) []
- guard_nonnull(p38) []
- guard_class(p38, ConstClass(u_vtable)) []
- p42 = getfield_gc(p38, descr=onedescr) # Array(NODE)
- i43 = arraylen_gc(p42, descr=arraydescr3)
- i45 = int_sub(i43, 0)
- p46 = new(descr=tsize) # T
- setfield_gc(p46, i45, descr=cdescr)
- p47 = new_array(i45, descr=arraydescr3) # Array(NODE)
- setfield_gc(p46, p47, descr=ddescr)
- i48 = int_lt(0, i43)
- guard_true(i48) []
- p49 = getarrayitem_gc(p42, 0, descr=arraydescr3) # NODE
- p50 = getfield_gc(p46, descr=ddescr) # Array(NODE)
- setarrayitem_gc(p50, 0, p49, descr=arraydescr3)
- i52 = int_lt(1, i43)
- guard_false(i52) []
- i53 = getfield_gc(p46, descr=cdescr)
- i55 = int_ne(i53, 1)
- guard_false(i55) []
- p56 = getfield_gc(p46, descr=ddescr) # Array(NODE)
- p58 = getarrayitem_gc(p56, 0, descr=arraydescr3) # NODE
- guard_nonnull(p38) []
- jump(p58)
- """
- self.find_nodes(ops, 'Virtual(node_vtable, valuedescr=Not)')
-
- # ------------------------------
- # Bridge tests
-
- def find_bridge(self, ops, inputspectext, outputspectext, boxkinds=None,
- mismatch=False):
- assert boxkinds is None or isinstance(boxkinds, dict)
- inputspecnodes = self.unpack_specnodes(inputspectext)
- outputspecnodes = self.unpack_specnodes(outputspectext)
- bridge = self.parse(ops, boxkinds=boxkinds)
- bridge_specialization_finder = BridgeSpecializationFinder(self.cpu)
- bridge_specialization_finder.find_nodes_bridge(bridge, inputspecnodes)
- matches = bridge_specialization_finder.bridge_matches(outputspecnodes)
- if mismatch:
- assert not matches
- else:
- assert matches
-
- def test_bridge_simple(self):
- ops = """
- [i0]
- i1 = int_add(i0, 1)
- jump(i1)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not', 'Virtual(node_vtable)', mismatch=True)
-
- def test_bridge_simple_known_class(self):
- ops = """
- [p0]
- setfield_gc(p0, 123, descr=valuedescr)
- jump(p0)
- """
- self.find_bridge(ops, 'Not', 'Not')
-
- def test_bridge_simple_constant(self):
- ops = """
- []
- jump(ConstPtr(myptr))
- """
- self.find_bridge(ops, '', 'Not')
- self.find_bridge(ops, '', 'Constant(myptr)')
- self.find_bridge(ops, '', 'Constant(myptr2)', mismatch=True)
-
- def test_bridge_simple_constant_mismatch(self):
- ops = """
- [p0]
- jump(p0)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not', 'Constant(myptr)', mismatch=True)
-
- def test_bridge_simple_virtual_1(self):
- ops = """
- [i0]
- p0 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p0, i0, descr=valuedescr)
- jump(p0)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not', 'Virtual(node_vtable, valuedescr=Not)')
- self.find_bridge(ops, 'Not',
- '''Virtual(node_vtable,
- valuedescr=Not,
- nextdescr=Not)''')
- #
- self.find_bridge(ops, 'Not', 'Virtual(node_vtable)',
- mismatch=True) # missing valuedescr
- self.find_bridge(ops, 'Not', 'Virtual(node_vtable, nextdescr=Not)',
- mismatch=True) # missing valuedescr
- self.find_bridge(ops, 'Not', 'Virtual(node_vtable2, valuedescr=Not)',
- mismatch=True) # bad class
-
- def test_bridge_simple_virtual_struct(self):
- ops = """
- [i0]
- p0 = new(descr=ssize)
- setfield_gc(p0, i0, descr=adescr)
- jump(p0)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not', 'VStruct(ssize, adescr=Not)')
-
- def test_bridge_simple_virtual_struct_non_unique(self):
- ops = """
- [i0]
- p0 = new(descr=ssize)
- setfield_gc(p0, i0, descr=adescr)
- jump(p0, p0)
- """
- self.find_bridge(ops, 'Not', 'Not, Not')
- self.find_bridge(ops, 'Not', 'VStruct(ssize), VStruct(ssize)',
- mismatch=True)
-
-
- def test_bridge_simple_virtual_2(self):
- ops = """
- [p0]
- setfield_gc(p0, 123, descr=valuedescr)
- jump(p0)
- """
- self.find_bridge(ops, 'Virtual(node_vtable)', 'Not')
- self.find_bridge(ops, 'Virtual(node_vtable)',
- 'Virtual(node_vtable, valuedescr=Not)')
- self.find_bridge(ops, 'Virtual(node_vtable, valuedescr=Not)',
- 'Virtual(node_vtable, valuedescr=Not)')
- self.find_bridge(ops, 'Virtual(node_vtable, valuedescr=Not)',
- '''Virtual(node_vtable,
- valuedescr=Not,
- nextdescr=Not)''')
- self.find_bridge(ops, '''Virtual(node_vtable,
- valuedescr=Not,
- nextdescr=Not)''',
- '''Virtual(node_vtable,
- valuedescr=Not,
- nextdescr=Not)''')
- #
- self.find_bridge(ops, 'Virtual(node_vtable)', 'Virtual(node_vtable)',
- mismatch=True) # because of missing valuedescr
- self.find_bridge(ops, 'Virtual(node_vtable)',
- 'Virtual(node_vtable2, valuedescr=Not)',
- mismatch=True) # bad class
-
- def test_bridge_virtual_mismatch_1(self):
- ops = """
- [i0]
- p0 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p0, i0, descr=valuedescr)
- jump(p0, p0)
- """
- self.find_bridge(ops, 'Not', 'Not, Not')
- #
- self.find_bridge(ops, 'Not',
- '''Virtual(node_vtable, valuedescr=Not),
- Virtual(node_vtable, valuedescr=Not)''',
- mismatch=True) # duplicate p0
-
- def test_bridge_guard_class(self):
- ops = """
- [p1]
- p2 = getfield_gc(p1, descr=nextdescr)
- guard_class(p2, ConstClass(node_vtable)) []
- jump(p2)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Virtual(node_vtable2, nextdescr=Not)', 'Not')
- self.find_bridge(ops,
- '''Virtual(node_vtable,
- nextdescr=Virtual(node_vtable,
- nextdescr=Not))''',
- '''Virtual(node_vtable,
- nextdescr=Not)''')
- #
- self.find_bridge(ops, 'Not', 'Virtual(node_vtable)',
- mismatch=True)
-
- def test_bridge_unused(self):
- ops = """
- []
- p1 = new_with_vtable(ConstClass(node_vtable))
- p2 = new_with_vtable(ConstClass(node_vtable))
- p3 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, p2, descr=nextdescr)
- setfield_gc(p2, p3, descr=nextdescr)
- jump(p1)
- """
- self.find_bridge(ops, '',
- '''Not''')
- self.find_bridge(ops, '',
- '''Virtual(node_vtable,
- nextdescr=Not)''')
- self.find_bridge(ops, '',
- '''Virtual(node_vtable,
- nextdescr=Virtual(node_vtable,
- nextdescr=Not))''')
- self.find_bridge(ops, '',
- '''Virtual(node_vtable,
- nextdescr=Virtual(node_vtable,
- nextdescr=Virtual(node_vtable)))''')
- self.find_bridge(ops, '',
- '''Virtual(node_vtable,
- nextdescr=Virtual(node_vtable,
- nextdescr=Virtual(node_vtable,
- nextdescr=Not)))''')
-
- def test_bridge_to_finish(self):
- ops = """
- [i1]
- i2 = int_add(i1, 5)
- finish(i2)
- """
- self.find_bridge(ops, 'Not', 'Not')
-
- def test_bridge_virtual_to_finish(self):
- ops = """
- [i1]
- p1 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, i1, descr=valuedescr)
- finish(p1)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not',
- 'Virtual(node_vtable, valuedescr=Not)',
- mismatch=True)
-
- def test_bridge_array_virtual_1(self):
- ops = """
- [i1]
- p1 = new_array(3, descr=arraydescr)
- setarrayitem_gc(p1, 0, i1, descr=arraydescr)
- jump(p1)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not', 'VArray(arraydescr, Not, Not, Not)')
-
- def test_bridge_array_virtual_size_mismatch(self):
- ops = """
- [i1]
- p1 = new_array(5, descr=arraydescr)
- setarrayitem_gc(p1, 0, i1, descr=arraydescr)
- jump(p1)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not', 'VArray(arraydescr, Not, Not, Not)',
- mismatch=True)
-
- def test_bridge_array_virtual_2(self):
- ops = """
- [i1]
- p1 = new_array(3, descr=arraydescr)
- setarrayitem_gc(p1, 0, i1, descr=arraydescr)
- escape(p1)
- jump(p1)
- """
- self.find_bridge(ops, 'Not', 'Not')
- self.find_bridge(ops, 'Not', 'VArray(arraydescr, Not, Not, Not)',
- mismatch=True)
-
- def test_bridge_nested_structs(self):
- ops = """
- []
- p1 = new_with_vtable(ConstClass(node_vtable))
- p2 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p1, p2, descr=nextdescr)
- jump(p1)
- """
- self.find_bridge(ops, '', 'Not')
- self.find_bridge(ops, '', 'Virtual(node_vtable, nextdescr=Not)')
- self.find_bridge(ops, '',
- 'Virtual(node_vtable, nextdescr=Virtual(node_vtable))')
- self.find_bridge(ops, '',
- 'Virtual(node_vtable, nextdescr=Virtual(node_vtable2))',
- mismatch=True)
-
-
-class TestLLtype(BaseTestOptimizeFindNode, LLtypeMixin):
- pass
-
-##class TestOOtype(BaseTestOptimizeFindNode, OOtypeMixin):
-## def test_find_nodes_instanceof(self):
-## ops = """
-## [i0]
-## p0 = new_with_vtable(ConstClass(node_vtable))
-## i1 = instanceof(p0, descr=nodesize)
-## jump(i1)
-## """
-## boxes, getnode = self.find_nodes(ops, 'Not')
-## assert not getnode(boxes.p0).escaped
More information about the Pypy-commit
mailing list