[pypy-svn] pypy default: hg merge jit-unroll-loops

hakanardo commits-noreply at bitbucket.org
Mon Jan 3 20:47:11 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: 
Changeset: r40354:94b3c483fba5
Date: 2011-01-03 20:38 +0100
http://bitbucket.org/pypy/pypy/changeset/94b3c483fba5/

Log:	hg merge jit-unroll-loops

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