Author: Armin Rigo <ar...@tunes.org>
Branch: all_ordered_dicts
Changeset: r75062:6b50206e647d
Date: 2014-12-22 17:18 +0100
http://bitbucket.org/pypy/pypy/changeset/6b50206e647d/

Log:    hg merge default

diff too long, truncating to 2000 out of 2244 lines

diff --git a/lib_pypy/readline.py b/lib_pypy/readline.py
--- a/lib_pypy/readline.py
+++ b/lib_pypy/readline.py
@@ -6,4 +6,11 @@
 are only stubs at the moment.
 """
 
-from pyrepl.readline import *
+try:
+    from pyrepl.readline import *
+except ImportError:
+    import sys
+    if sys.platform == 'win32':
+        raise ImportError("the 'readline' module is not available on Windows"
+                          " (on either PyPy or CPython)")
+    raise
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -397,7 +397,7 @@
 def test_invalid_indexing():
     p = new_primitive_type("int")
     x = cast(p, 42)
-    py.test.raises(TypeError, "p[0]")
+    py.test.raises(TypeError, "x[0]")
 
 def test_default_str():
     BChar = new_primitive_type("char")
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -618,8 +618,8 @@
         try:
             i = self.find(w_value, 0, sys.maxint)
         except ValueError:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("list.remove(x): x not in list"))
+            raise oefmt(space.w_ValueError,
+                        "list.remove(): %R is not in list", w_value)
         if i < self.length():  # otherwise list was mutated
             self.pop(i)
 
@@ -633,8 +633,7 @@
         try:
             i = self.find(w_value, i, stop)
         except ValueError:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("list.index(x): x not in list"))
+            raise oefmt(space.w_ValueError, "%R is not in list", w_value)
         return space.wrap(i)
 
     @unwrap_spec(reverse=bool)
diff --git a/pypy/objspace/std/test/test_dictproxy.py 
b/pypy/objspace/std/test/test_dictproxy.py
--- a/pypy/objspace/std/test/test_dictproxy.py
+++ b/pypy/objspace/std/test/test_dictproxy.py
@@ -15,14 +15,15 @@
         assert NotEmpty.__dict__.get("b") is None
         raises(TypeError, 'NotEmpty.__dict__[15] = "y"')
         raises(KeyError, 'del NotEmpty.__dict__[15]')
+
+        key, value = NotEmpty.__dict__.popitem()
+        assert (key == 'a' and value == 1) or (key == 'b' and value == 4)
+
         assert NotEmpty.__dict__.setdefault("string", 1) == 1
         assert NotEmpty.__dict__.setdefault("string", 2) == 1
         assert NotEmpty.string == 1
         raises(TypeError, 'NotEmpty.__dict__.setdefault(15, 1)')
 
-        key, value = NotEmpty.__dict__.popitem()
-        assert (key == 'a' and value == 1) or (key == 'b' and value == 4)
-
     def test_dictproxy_getitem(self):
         class NotEmpty(object):
             a = 1
diff --git a/pypy/objspace/std/test/test_listobject.py 
b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -976,7 +976,10 @@
 
         c = [0.0, 2.2, 4.4]
         assert c.index(0) == 0.0
-        raises(ValueError, c.index, 3)
+        e = raises(ValueError, c.index, 3)
+        import sys
+        if sys.version_info[:2] == (2, 7):     # CPython 2.7, PyPy
+            assert str(e.value) == '3 is not in list'
 
     def test_index_cpython_bug(self):
         if self.on_cpython:
@@ -1228,7 +1231,9 @@
         assert l == [0.0, 1.1, 3.3, 4.4]
         l = [0.0, 3.3, 5.5]
         raises(ValueError, c.remove, 2)
-        raises(ValueError, c.remove, 2.2)
+        e = raises(ValueError, c.remove, 2.2)
+        if not self.on_cpython:
+            assert str(e.value) == 'list.remove(): 2.2 is not in list'
 
     def test_reverse(self):
         c = list('hello world')
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -389,7 +389,7 @@
         assert isinstance(dct2, SomeOrderedDict), "OrderedDict.update(dict) 
not allowed"
         dct1.dictdef.union(dct2.dictdef)
 
-SomeDict=SomeOrderedDict
+SomeDict = SomeOrderedDict      # all dicts are ordered!
 
 
 class SomeIterator(SomeObject):
diff --git a/rpython/jit/metainterp/compile.py 
b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -128,7 +128,8 @@
                       [ResOperation(rop.LABEL, jumpargs, None, 
descr=jitcell_token)]
 
     try:
-        start_state = optimize_trace(metainterp_sd, part, enable_opts)
+        start_state = optimize_trace(metainterp_sd, part, enable_opts,
+                                     export_state=True)
     except InvalidLoop:
         return None
     target_token = part.operations[0].getdescr()
@@ -156,7 +157,7 @@
 
         try:
             optimize_trace(metainterp_sd, part, enable_opts,
-                           start_state=start_state)
+                           start_state=start_state, export_state=False)
         except InvalidLoop:
             return None
 
@@ -209,7 +210,7 @@
     assert label.getopnum() == rop.LABEL
     try:
         optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts,
-                       start_state=start_state)
+                       start_state=start_state, export_state=False)
     except InvalidLoop:
         # Fall back on jumping to preamble
         target_token = label.getdescr()
@@ -220,7 +221,8 @@
         try:
             optimize_trace(metainterp_sd, part,
                            jitdriver_sd.warmstate.enable_opts,
-                           inline_short_preamble=False, 
start_state=start_state)
+                           inline_short_preamble=False, 
start_state=start_state,
+                           export_state=False)
         except InvalidLoop:
             return None
     assert part.operations[-1].getopnum() != rop.LABEL
@@ -789,7 +791,8 @@
     else:
         inline_short_preamble = True
     try:
-        state = optimize_trace(metainterp_sd, new_trace, state.enable_opts, 
inline_short_preamble)
+        state = optimize_trace(metainterp_sd, new_trace, state.enable_opts,
+                               inline_short_preamble, export_state=True)
     except InvalidLoop:
         debug_print("compile_new_bridge: got an InvalidLoop")
         # XXX I am fairly convinced that optimize_bridge cannot actually raise
diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py 
b/rpython/jit/metainterp/optimizeopt/__init__.py
--- a/rpython/jit/metainterp/optimizeopt/__init__.py
+++ b/rpython/jit/metainterp/optimizeopt/__init__.py
@@ -48,7 +48,8 @@
     return optimizations, unroll
 
 def optimize_trace(metainterp_sd, loop, enable_opts,
-                   inline_short_preamble=True, start_state=None):
+                   inline_short_preamble=True, start_state=None,
+                   export_state=True):
     """Optimize loop.operations to remove internal overheadish operations.
     """
 
@@ -59,7 +60,8 @@
         optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts)
         if unroll:
             return optimize_unroll(metainterp_sd, loop, optimizations,
-                                   inline_short_preamble, start_state)
+                                   inline_short_preamble, start_state,
+                                   export_state)
         else:
             optimizer = Optimizer(metainterp_sd, loop, optimizations)
             optimizer.propagate_all_forward()
diff --git a/rpython/jit/metainterp/optimizeopt/generalize.py 
b/rpython/jit/metainterp/optimizeopt/generalize.py
--- a/rpython/jit/metainterp/optimizeopt/generalize.py
+++ b/rpython/jit/metainterp/optimizeopt/generalize.py
@@ -1,4 +1,5 @@
-from rpython.jit.metainterp.optimizeopt.optimizer import MININT, MAXINT
+from rpython.jit.metainterp.optimizeopt.optimizer import MININT, MAXINT,\
+     IntOptValue
 
 
 class GeneralizationStrategy(object):
@@ -14,7 +15,8 @@
         for v in self.optimizer.values.values():
             if v.is_constant():
                 continue
-            if v.intbound.lower < MININT / 2:
-                v.intbound.lower = MININT
-            if v.intbound.upper > MAXINT / 2:
-                v.intbound.upper = MAXINT
+            if isinstance(v, IntOptValue):
+                if v.intbound.lower < MININT / 2:
+                    v.intbound.lower = MININT
+                if v.intbound.upper > MAXINT / 2:
+                    v.intbound.upper = MAXINT
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py 
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -4,7 +4,7 @@
 from rpython.jit.metainterp.optimizeopt.util import args_dict
 from rpython.jit.metainterp.history import Const, ConstInt
 from rpython.jit.metainterp.jitexc import JitException
-from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, 
MODE_ARRAY, LEVEL_KNOWNCLASS, REMOVED
+from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, 
MODE_ARRAY, LEVEL_KNOWNCLASS, REMOVED, LEVEL_CONSTANT
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.optimizeopt.intutils import IntBound
 from rpython.jit.metainterp.optimize import InvalidLoop
@@ -64,6 +64,17 @@
             # cancelling its previous effects with no side effect.
             self._lazy_setfield = None
 
+    def value_updated(self, oldvalue, newvalue):
+        try:
+            fieldvalue = self._cached_fields[oldvalue]
+        except KeyError:
+            pass
+        else:
+            self._cached_fields[newvalue] = fieldvalue
+            op = self._cached_fields_getfield_op[oldvalue].clone()
+            op.setarg(0, newvalue.box)
+            self._cached_fields_getfield_op[newvalue] = op
+
     def possible_aliasing(self, optheap, structvalue):
         # If lazy_setfield is set and contains a setfield on a different
         # structvalue, then we are annoyed, because it may point to either
@@ -118,18 +129,6 @@
         self._cached_fields.clear()
         self._cached_fields_getfield_op.clear()
 
-    def turned_constant(self, newvalue, value):
-        if newvalue not in self._cached_fields and value in 
self._cached_fields:
-            self._cached_fields[newvalue] = self._cached_fields[value]
-            op = self._cached_fields_getfield_op[value].clone()
-            constbox = value.box
-            assert isinstance(constbox, Const)
-            op.setarg(0, constbox)
-            self._cached_fields_getfield_op[newvalue] = op
-        for structvalue in self._cached_fields.keys():
-            if self._cached_fields[structvalue] is value:
-                self._cached_fields[structvalue] = newvalue
-
     def produce_potential_short_preamble_ops(self, optimizer, shortboxes, 
descr):
         if self._lazy_setfield is not None:
             return
@@ -187,6 +186,17 @@
         self._seen_guard_not_invalidated = False
         self.postponed_op = None
 
+    def setup(self):
+        self.optimizer.optheap = self
+
+    def value_updated(self, oldvalue, newvalue):
+        # XXXX very unhappy about that
+        for cf in self.cached_fields.itervalues():
+            cf.value_updated(oldvalue, newvalue)
+        for submap in self.cached_arrayitems.itervalues():
+            for cf in submap.itervalues():
+                cf.value_updated(oldvalue, newvalue)
+
     def force_at_end_of_preamble(self):
         self.cached_dict_reads.clear()
         self.corresponding_array_descrs.clear()
@@ -391,16 +401,6 @@
             # ^^^ we only need to force this field; the other fields
             # of virtualref_info and virtualizable_info are not gcptrs.
 
-    def turned_constant(self, value):
-        assert value.is_constant()
-        newvalue = self.getvalue(value.box)
-        if value is not newvalue:
-            for cf in self.cached_fields.itervalues():
-                cf.turned_constant(newvalue, value)
-            for submap in self.cached_arrayitems.itervalues():
-                for cf in submap.itervalues():
-                    cf.turned_constant(newvalue, value)
-
     def force_lazy_setfield(self, descr, can_cache=True):
         try:
             cf = self.cached_fields[descr]
@@ -414,7 +414,7 @@
         except KeyError:
             return
         for idx, cf in submap.iteritems():
-            if indexvalue is None or indexvalue.intbound.contains(idx):
+            if indexvalue is None or indexvalue.getintbound().contains(idx):
                 cf.force_lazy_setfield(self, can_cache)
 
     def _assert_valid_cf(self, cf):
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py 
b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -4,7 +4,7 @@
 from rpython.jit.metainterp.optimizeopt.intutils import (IntBound, 
IntLowerBound,
     IntUpperBound)
 from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, 
CONST_1,
-    CONST_0, MODE_ARRAY, MODE_STR, MODE_UNICODE)
+    CONST_0, MODE_ARRAY, MODE_STR, MODE_UNICODE, IntOptValue)
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.resoperation import rop
 from rpython.jit.backend.llsupport import symbolic
@@ -54,7 +54,9 @@
         #        but the bounds produced by all instructions where box is
         #        an argument might also be tighten
         v = self.getvalue(box)
-        b = v.intbound
+        b = v.getintbound()
+        if b is None:
+            return # pointer
         if b.has_lower and b.has_upper and b.lower == b.upper:
             v.make_constant(ConstInt(b.lower))
 
@@ -81,11 +83,13 @@
                 self.make_constant_int(op.result, 0)
             return
         self.emit_operation(op)
-        if v1.intbound.known_ge(IntBound(0, 0)) and \
-           v2.intbound.known_ge(IntBound(0, 0)):
-            r = self.getvalue(op.result)
-            mostsignificant = v1.intbound.upper | v2.intbound.upper
-            r.intbound.intersect(IntBound(0, next_pow2_m1(mostsignificant)))
+        bound1 = v1.getintbound()
+        bound2 = v2.getintbound()
+        if bound1.known_ge(IntBound(0, 0)) and \
+           bound2.known_ge(IntBound(0, 0)):
+            r = self.getvalue(op.result).getintbound()
+            mostsignificant = bound1.upper | bound2.upper
+            r.intersect(IntBound(0, next_pow2_m1(mostsignificant)))
 
     optimize_INT_OR = optimize_INT_OR_or_XOR
     optimize_INT_XOR = optimize_INT_OR_or_XOR
@@ -99,55 +103,55 @@
         if v2.is_constant():
             val = v2.box.getint()
             if val >= 0:
-                r.intbound.intersect(IntBound(0, val))
+                r.getintbound().intersect(IntBound(0, val))
         elif v1.is_constant():
             val = v1.box.getint()
             if val >= 0:
-                r.intbound.intersect(IntBound(0, val))
-        elif v1.intbound.known_ge(IntBound(0, 0)) and \
-          v2.intbound.known_ge(IntBound(0, 0)):
-            lesser = min(v1.intbound.upper, v2.intbound.upper)
-            r.intbound.intersect(IntBound(0, next_pow2_m1(lesser)))
+                r.getintbound().intersect(IntBound(0, val))
+        elif v1.getintbound().known_ge(IntBound(0, 0)) and \
+          v2.getintbound().known_ge(IntBound(0, 0)):
+            lesser = min(v1.getintbound().upper, v2.getintbound().upper)
+            r.getintbound().intersect(IntBound(0, next_pow2_m1(lesser)))
 
     def optimize_INT_SUB(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        b = v1.intbound.sub_bound(v2.intbound)
+        b = v1.getintbound().sub_bound(v2.getintbound())
         if b.bounded():
-            r.intbound.intersect(b)
+            r.getintbound().intersect(b)
 
     def optimize_INT_ADD(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        b = v1.intbound.add_bound(v2.intbound)
+        b = v1.getintbound().add_bound(v2.getintbound())
         if b.bounded():
-            r.intbound.intersect(b)
+            r.getintbound().intersect(b)
 
     def optimize_INT_MUL(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        b = v1.intbound.mul_bound(v2.intbound)
+        b = v1.getintbound().mul_bound(v2.getintbound())
         if b.bounded():
-            r.intbound.intersect(b)
+            r.getintbound().intersect(b)
 
     def optimize_INT_FLOORDIV(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        r.intbound.intersect(v1.intbound.div_bound(v2.intbound))
+        r.getintbound().intersect(v1.getintbound().div_bound(v2.getintbound()))
 
     def optimize_INT_MOD(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        known_nonneg = (v1.intbound.known_ge(IntBound(0, 0)) and
-                        v2.intbound.known_ge(IntBound(0, 0)))
+        known_nonneg = (v1.getintbound().known_ge(IntBound(0, 0)) and
+                        v2.getintbound().known_ge(IntBound(0, 0)))
         if known_nonneg and v2.is_constant():
             val = v2.box.getint()
             if (val & (val-1)) == 0:
@@ -164,18 +168,18 @@
                     return     # give up
                 val = -val
             if known_nonneg:
-                r.intbound.make_ge(IntBound(0, 0))
+                r.getintbound().make_ge(IntBound(0, 0))
             else:
-                r.intbound.make_gt(IntBound(-val, -val))
-            r.intbound.make_lt(IntBound(val, val))
+                r.getintbound().make_gt(IntBound(-val, -val))
+            r.getintbound().make_lt(IntBound(val, val))
 
     def optimize_INT_LSHIFT(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        b = v1.intbound.lshift_bound(v2.intbound)
-        r.intbound.intersect(b)
+        b = v1.getintbound().lshift_bound(v2.getintbound())
+        r.getintbound().intersect(b)
         # intbound.lshift_bound checks for an overflow and if the
         # lshift can be proven not to overflow sets b.has_upper and
         # b.has_lower
@@ -186,14 +190,14 @@
     def optimize_INT_RSHIFT(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        b = v1.intbound.rshift_bound(v2.intbound)
+        b = v1.getintbound().rshift_bound(v2.getintbound())
         if b.has_lower and b.has_upper and b.lower == b.upper:
             # constant result (likely 0, for rshifts that kill all bits)
             self.make_constant_int(op.result, b.lower)
         else:
             self.emit_operation(op)
             r = self.getvalue(op.result)
-            r.intbound.intersect(b)
+            r.getintbound().intersect(b)
 
     def optimize_GUARD_NO_OVERFLOW(self, op):
         lastop = self.last_emitted_operation
@@ -238,7 +242,7 @@
     def optimize_INT_ADD_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        resbound = v1.intbound.add_bound(v2.intbound)
+        resbound = v1.getintbound().add_bound(v2.getintbound())
         if resbound.bounded():
             # Transform into INT_ADD.  The following guard will be killed
             # by optimize_GUARD_NO_OVERFLOW; if we see instead an
@@ -246,7 +250,7 @@
             op = op.copy_and_change(rop.INT_ADD)
         self.emit_operation(op) # emit the op
         r = self.getvalue(op.result)
-        r.intbound.intersect(resbound)
+        r.getintbound().intersect(resbound)
 
     def optimize_INT_SUB_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
@@ -254,29 +258,29 @@
         if v1 is v2:
             self.make_constant_int(op.result, 0)
             return
-        resbound = v1.intbound.sub_bound(v2.intbound)
+        resbound = v1.getintbound().sub_bound(v2.getintbound())
         if resbound.bounded():
             op = op.copy_and_change(rop.INT_SUB)
         self.emit_operation(op) # emit the op
         r = self.getvalue(op.result)
-        r.intbound.intersect(resbound)
+        r.getintbound().intersect(resbound)
 
     def optimize_INT_MUL_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        resbound = v1.intbound.mul_bound(v2.intbound)
+        resbound = v1.getintbound().mul_bound(v2.getintbound())
         if resbound.bounded():
             op = op.copy_and_change(rop.INT_MUL)
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        r.intbound.intersect(resbound)
+        r.getintbound().intersect(resbound)
 
     def optimize_INT_LT(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_lt(v2.intbound):
+        if v1.getintbound().known_lt(v2.getintbound()):
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_ge(v2.intbound) or v1 is v2:
+        elif v1.getintbound().known_ge(v2.getintbound()) or v1 is v2:
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -284,9 +288,9 @@
     def optimize_INT_GT(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_gt(v2.intbound):
+        if v1.getintbound().known_gt(v2.getintbound()):
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_le(v2.intbound) or v1 is v2:
+        elif v1.getintbound().known_le(v2.getintbound()) or v1 is v2:
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -294,9 +298,9 @@
     def optimize_INT_LE(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_le(v2.intbound) or v1 is v2:
+        if v1.getintbound().known_le(v2.getintbound()) or v1 is v2:
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_gt(v2.intbound):
+        elif v1.getintbound().known_gt(v2.getintbound()):
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -304,9 +308,9 @@
     def optimize_INT_GE(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_ge(v2.intbound) or v1 is v2:
+        if v1.getintbound().known_ge(v2.getintbound()) or v1 is v2:
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_lt(v2.intbound):
+        elif v1.getintbound().known_lt(v2.getintbound()):
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -314,9 +318,9 @@
     def optimize_INT_EQ(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_gt(v2.intbound):
+        if v1.getintbound().known_gt(v2.getintbound()):
             self.make_constant_int(op.result, 0)
-        elif v1.intbound.known_lt(v2.intbound):
+        elif v1.getintbound().known_lt(v2.getintbound()):
             self.make_constant_int(op.result, 0)
         elif v1 is v2:
             self.make_constant_int(op.result, 1)
@@ -326,9 +330,9 @@
     def optimize_INT_NE(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_gt(v2.intbound):
+        if v1.getintbound().known_gt(v2.getintbound()):
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_lt(v2.intbound):
+        elif v1.getintbound().known_lt(v2.getintbound()):
             self.make_constant_int(op.result, 1)
         elif v1 is v2:
             self.make_constant_int(op.result, 0)
@@ -337,7 +341,7 @@
 
     def optimize_INT_FORCE_GE_ZERO(self, op):
         value = self.getvalue(op.getarg(0))
-        if value.intbound.known_ge(IntBound(0, 0)):
+        if value.getintbound().known_ge(IntBound(0, 0)):
             self.make_equal_to(op.result, value)
         else:
             self.emit_operation(op)
@@ -348,50 +352,53 @@
         start = -(1 << (numbits - 1))
         stop = 1 << (numbits - 1)
         bounds = IntBound(start, stop - 1)
-        if bounds.contains_bound(value.intbound):
+        if bounds.contains_bound(value.getintbound()):
             self.make_equal_to(op.result, value)
         else:
             self.emit_operation(op)
             vres = self.getvalue(op.result)
-            vres.intbound.intersect(bounds)
+            vres.getintbound().intersect(bounds)
 
     def optimize_ARRAYLEN_GC(self, op):
         self.emit_operation(op)
         array = self.getvalue(op.getarg(0))
         result = self.getvalue(op.result)
         array.make_len_gt(MODE_ARRAY, op.getdescr(), -1)
-        array.lenbound.bound.intersect(result.intbound)
-        result.intbound = array.lenbound.bound
+        array.getlenbound().bound.intersect(result.getintbound())
+        assert isinstance(result, IntOptValue)
+        result.intbound = array.getlenbound().bound
 
     def optimize_STRLEN(self, op):
         self.emit_operation(op)
         array = self.getvalue(op.getarg(0))
         result = self.getvalue(op.result)
         array.make_len_gt(MODE_STR, op.getdescr(), -1)
-        array.lenbound.bound.intersect(result.intbound)
-        result.intbound = array.lenbound.bound
+        array.getlenbound().bound.intersect(result.getintbound())
+        assert isinstance(result, IntOptValue)
+        result.intbound = array.getlenbound().bound
 
     def optimize_UNICODELEN(self, op):
         self.emit_operation(op)
         array = self.getvalue(op.getarg(0))
         result = self.getvalue(op.result)
         array.make_len_gt(MODE_UNICODE, op.getdescr(), -1)
-        array.lenbound.bound.intersect(result.intbound)
-        result.intbound = array.lenbound.bound
+        array.getlenbound().bound.intersect(result.getintbound())
+        assert isinstance(result, IntOptValue)        
+        result.intbound = array.getlenbound().bound
 
     def optimize_STRGETITEM(self, op):
         self.emit_operation(op)
         v1 = self.getvalue(op.result)
-        v1.intbound.make_ge(IntLowerBound(0))
-        v1.intbound.make_lt(IntUpperBound(256))
+        v1.getintbound().make_ge(IntLowerBound(0))
+        v1.getintbound().make_lt(IntUpperBound(256))
 
     def optimize_GETFIELD_RAW(self, op):
         self.emit_operation(op)
         descr = op.getdescr()
         if descr.is_integer_bounded():
             v1 = self.getvalue(op.result)
-            v1.intbound.make_ge(IntLowerBound(descr.get_integer_min()))
-            v1.intbound.make_le(IntUpperBound(descr.get_integer_max()))
+            v1.getintbound().make_ge(IntLowerBound(descr.get_integer_min()))
+            v1.getintbound().make_le(IntUpperBound(descr.get_integer_max()))
 
     optimize_GETFIELD_GC = optimize_GETFIELD_RAW
 
@@ -402,30 +409,30 @@
         descr = op.getdescr()
         if descr and descr.is_item_integer_bounded():
             v1 = self.getvalue(op.result)
-            v1.intbound.make_ge(IntLowerBound(descr.get_item_integer_min()))
-            v1.intbound.make_le(IntUpperBound(descr.get_item_integer_max()))
+            
v1.getintbound().make_ge(IntLowerBound(descr.get_item_integer_min()))
+            
v1.getintbound().make_le(IntUpperBound(descr.get_item_integer_max()))
 
     optimize_GETARRAYITEM_GC = optimize_GETARRAYITEM_RAW
 
     def optimize_UNICODEGETITEM(self, op):
         self.emit_operation(op)
         v1 = self.getvalue(op.result)
-        v1.intbound.make_ge(IntLowerBound(0))
+        v1.getintbound().make_ge(IntLowerBound(0))
 
     def make_int_lt(self, box1, box2):
         v1 = self.getvalue(box1)
         v2 = self.getvalue(box2)
-        if v1.intbound.make_lt(v2.intbound):
+        if v1.getintbound().make_lt(v2.getintbound()):
             self.propagate_bounds_backward(box1)
-        if v2.intbound.make_gt(v1.intbound):
+        if v2.getintbound().make_gt(v1.getintbound()):
             self.propagate_bounds_backward(box2)
 
     def make_int_le(self, box1, box2):
         v1 = self.getvalue(box1)
         v2 = self.getvalue(box2)
-        if v1.intbound.make_le(v2.intbound):
+        if v1.getintbound().make_le(v2.getintbound()):
             self.propagate_bounds_backward(box1)
-        if v2.intbound.make_ge(v1.intbound):
+        if v2.getintbound().make_ge(v1.getintbound()):
             self.propagate_bounds_backward(box2)
 
     def make_int_gt(self, box1, box2):
@@ -472,9 +479,9 @@
             if r.box.same_constant(CONST_1):
                 v1 = self.getvalue(op.getarg(0))
                 v2 = self.getvalue(op.getarg(1))
-                if v1.intbound.intersect(v2.intbound):
+                if v1.getintbound().intersect(v2.getintbound()):
                     self.propagate_bounds_backward(op.getarg(0))
-                if v2.intbound.intersect(v1.intbound):
+                if v2.getintbound().intersect(v1.getintbound()):
                     self.propagate_bounds_backward(op.getarg(1))
 
     def propagate_bounds_INT_NE(self, op):
@@ -483,9 +490,9 @@
             if r.box.same_constant(CONST_0):
                 v1 = self.getvalue(op.getarg(0))
                 v2 = self.getvalue(op.getarg(1))
-                if v1.intbound.intersect(v2.intbound):
+                if v1.getintbound().intersect(v2.getintbound()):
                     self.propagate_bounds_backward(op.getarg(0))
-                if v2.intbound.intersect(v1.intbound):
+                if v2.getintbound().intersect(v1.getintbound()):
                     self.propagate_bounds_backward(op.getarg(1))
 
     def propagate_bounds_INT_IS_TRUE(self, op):
@@ -493,8 +500,8 @@
         if r.is_constant():
             if r.box.same_constant(CONST_1):
                 v1 = self.getvalue(op.getarg(0))
-                if v1.intbound.known_ge(IntBound(0, 0)):
-                    v1.intbound.make_gt(IntBound(0, 0))
+                if v1.getintbound().known_ge(IntBound(0, 0)):
+                    v1.getintbound().make_gt(IntBound(0, 0))
                     self.propagate_bounds_backward(op.getarg(0))
 
     def propagate_bounds_INT_IS_ZERO(self, op):
@@ -505,49 +512,49 @@
                 # Clever hack, we can't use self.make_constant_int yet because
                 # the args aren't in the values dictionary yet so it runs into
                 # an assert, this is a clever way of expressing the same thing.
-                v1.intbound.make_ge(IntBound(0, 0))
-                v1.intbound.make_lt(IntBound(1, 1))
+                v1.getintbound().make_ge(IntBound(0, 0))
+                v1.getintbound().make_lt(IntBound(1, 1))
                 self.propagate_bounds_backward(op.getarg(0))
 
     def propagate_bounds_INT_ADD(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         r = self.getvalue(op.result)
-        b = r.intbound.sub_bound(v2.intbound)
-        if v1.intbound.intersect(b):
+        b = r.getintbound().sub_bound(v2.getintbound())
+        if v1.getintbound().intersect(b):
             self.propagate_bounds_backward(op.getarg(0))
-        b = r.intbound.sub_bound(v1.intbound)
-        if v2.intbound.intersect(b):
+        b = r.getintbound().sub_bound(v1.getintbound())
+        if v2.getintbound().intersect(b):
             self.propagate_bounds_backward(op.getarg(1))
 
     def propagate_bounds_INT_SUB(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         r = self.getvalue(op.result)
-        b = r.intbound.add_bound(v2.intbound)
-        if v1.intbound.intersect(b):
+        b = r.getintbound().add_bound(v2.getintbound())
+        if v1.getintbound().intersect(b):
             self.propagate_bounds_backward(op.getarg(0))
-        b = r.intbound.sub_bound(v1.intbound).mul(-1)
-        if v2.intbound.intersect(b):
+        b = r.getintbound().sub_bound(v1.getintbound()).mul(-1)
+        if v2.getintbound().intersect(b):
             self.propagate_bounds_backward(op.getarg(1))
 
     def propagate_bounds_INT_MUL(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         r = self.getvalue(op.result)
-        b = r.intbound.div_bound(v2.intbound)
-        if v1.intbound.intersect(b):
+        b = r.getintbound().div_bound(v2.getintbound())
+        if v1.getintbound().intersect(b):
             self.propagate_bounds_backward(op.getarg(0))
-        b = r.intbound.div_bound(v1.intbound)
-        if v2.intbound.intersect(b):
+        b = r.getintbound().div_bound(v1.getintbound())
+        if v2.getintbound().intersect(b):
             self.propagate_bounds_backward(op.getarg(1))
 
     def propagate_bounds_INT_LSHIFT(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         r = self.getvalue(op.result)
-        b = r.intbound.rshift_bound(v2.intbound)
-        if v1.intbound.intersect(b):
+        b = r.getintbound().rshift_bound(v2.getintbound())
+        if v1.getintbound().intersect(b):
             self.propagate_bounds_backward(op.getarg(0))
 
     propagate_bounds_INT_ADD_OVF = propagate_bounds_INT_ADD
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py 
b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -1,9 +1,11 @@
 from rpython.jit.metainterp import jitprof, resume, compile
 from rpython.jit.metainterp.executor import execute_nonspec
-from rpython.jit.metainterp.history import BoxInt, BoxFloat, Const, ConstInt, 
REF
-from rpython.jit.metainterp.optimizeopt.intutils import IntBound, 
IntUnbounded, \
+from rpython.jit.metainterp.history import BoxInt, BoxFloat, Const, ConstInt,\
+     REF, BoxPtr, ConstPtr, ConstFloat
+from rpython.jit.metainterp.optimizeopt.intutils import IntBound, 
IntUnbounded,\
                                                      ImmutableIntUnbounded, \
-                                                     IntLowerBound, MININT, 
MAXINT
+                                                     IntLowerBound, MININT,\
+                                                     MAXINT
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.resoperation import rop, ResOperation, 
AbstractResOp
 from rpython.jit.metainterp.typesystem import llhelper
@@ -39,69 +41,19 @@
 
 class OptValue(object):
     __metaclass__ = extendabletype
-    _attrs_ = ('box', 'known_class', 'last_guard', 'level', 'intbound', 
'lenbound')
-    last_guard = None
+    _attrs_ = ('box', 'level')
 
     level = LEVEL_UNKNOWN
-    known_class = None
-    intbound = ImmutableIntUnbounded()
-    lenbound = None
 
     def __init__(self, box, level=None, known_class=None, intbound=None):
         self.box = box
         if level is not None:
             self.level = level
-        self.known_class = known_class
-        if intbound:
-            self.intbound = intbound
-        else:
-            if isinstance(box, BoxInt):
-                self.intbound = IntBound(MININT, MAXINT)
-            else:
-                self.intbound = IntUnbounded()
 
         if isinstance(box, Const):
             self.make_constant(box)
         # invariant: box is a Const if and only if level == LEVEL_CONSTANT
 
-    def make_len_gt(self, mode, descr, val):
-        if self.lenbound:
-            assert self.lenbound.mode == mode
-            assert self.lenbound.descr == descr
-            self.lenbound.bound.make_gt(IntBound(val, val))
-        else:
-            self.lenbound = LenBound(mode, descr, IntLowerBound(val + 1))
-
-    def make_guards(self, box):
-        guards = []
-        if self.level == LEVEL_CONSTANT:
-            op = ResOperation(rop.GUARD_VALUE, [box, self.box], None)
-            guards.append(op)
-        elif self.level == LEVEL_KNOWNCLASS:
-            op = ResOperation(rop.GUARD_NONNULL, [box], None)
-            guards.append(op)
-            op = ResOperation(rop.GUARD_CLASS, [box, self.known_class], None)
-            guards.append(op)
-        else:
-            if self.level == LEVEL_NONNULL:
-                op = ResOperation(rop.GUARD_NONNULL, [box], None)
-                guards.append(op)
-            self.intbound.make_guards(box, guards)
-            if self.lenbound:
-                lenbox = BoxInt()
-                if self.lenbound.mode == MODE_ARRAY:
-                    op = ResOperation(rop.ARRAYLEN_GC, [box], lenbox, 
self.lenbound.descr)
-                elif self.lenbound.mode == MODE_STR:
-                    op = ResOperation(rop.STRLEN, [box], lenbox, 
self.lenbound.descr)
-                elif self.lenbound.mode == MODE_UNICODE:
-                    op = ResOperation(rop.UNICODELEN, [box], lenbox, 
self.lenbound.descr)
-                else:
-                    debug_print("Unknown lenbound mode")
-                    assert False
-                guards.append(op)
-                self.lenbound.bound.make_guards(lenbox, guards)
-        return guards
-
     def import_from(self, other, optimizer):
         if self.level == LEVEL_CONSTANT:
             assert other.level == LEVEL_CONSTANT
@@ -110,21 +62,22 @@
         assert self.level <= LEVEL_NONNULL
         if other.level == LEVEL_CONSTANT:
             self.make_constant(other.get_key_box())
-            optimizer.turned_constant(self)
         elif other.level == LEVEL_KNOWNCLASS:
-            self.make_constant_class(other.known_class, None)
+            self.make_constant_class(other.get_known_class(), None)
         else:
             if other.level == LEVEL_NONNULL:
                 self.ensure_nonnull()
-            self.intbound.intersect(other.intbound)
-            if other.lenbound:
-                if self.lenbound:
-                    assert other.lenbound.mode == self.lenbound.mode
-                    assert other.lenbound.descr == self.lenbound.descr
-                    self.lenbound.bound.intersect(other.lenbound.bound)
-                else:
-                    self.lenbound = other.lenbound.clone()
 
+    def make_guards(self, box):
+        if self.level == LEVEL_CONSTANT:
+            op = ResOperation(rop.GUARD_VALUE, [box, self.box], None)
+            return [op]
+        return []
+
+    def copy_from(self, other_value):
+        assert isinstance(other_value, OptValue)
+        self.box = other_value.box
+        self.level = other_value.level
 
     def force_box(self, optforce):
         return self.box
@@ -168,38 +121,6 @@
             return self.box.same_constant(other.box)
         return self is other
 
-    def make_constant(self, constbox):
-        """Replace 'self.box' with a Const box."""
-        assert isinstance(constbox, Const)
-        self.box = constbox
-        self.level = LEVEL_CONSTANT
-
-        if isinstance(constbox, ConstInt):
-            val = constbox.getint()
-            self.intbound = IntBound(val, val)
-        else:
-            self.intbound = IntUnbounded()
-
-    def get_constant_class(self, cpu):
-        level = self.level
-        if level == LEVEL_KNOWNCLASS:
-            return self.known_class
-        elif level == LEVEL_CONSTANT:
-            return cpu.ts.cls_of_box(self.box)
-        else:
-            return None
-
-    def make_constant_class(self, classbox, guardop):
-        assert self.level < LEVEL_KNOWNCLASS
-        self.known_class = classbox
-        self.level = LEVEL_KNOWNCLASS
-        self.last_guard = guardop
-
-    def make_nonnull(self, guardop):
-        assert self.level < LEVEL_NONNULL
-        self.level = LEVEL_NONNULL
-        self.last_guard = guardop
-
     def is_nonnull(self):
         level = self.level
         if level == LEVEL_NONNULL or level == LEVEL_KNOWNCLASS:
@@ -208,12 +129,6 @@
             box = self.box
             assert isinstance(box, Const)
             return box.nonnull()
-        elif self.intbound:
-            if self.intbound.known_gt(IntBound(0, 0)) or \
-               self.intbound.known_lt(IntBound(0, 0)):
-                return True
-            else:
-                return False
         else:
             return False
 
@@ -266,8 +181,216 @@
     def get_missing_null_value(self):
         raise NotImplementedError    # only for VArrayValue
 
+    def make_constant(self, constbox):
+        """Replace 'self.box' with a Const box."""
+        assert isinstance(constbox, Const)
+        self.box = constbox
+        self.level = LEVEL_CONSTANT
 
-class ConstantValue(OptValue):
+    def get_last_guard(self):
+        return None
+
+    def get_known_class(self):
+        return None
+
+    def getlenbound(self):
+        return None
+
+    def getintbound(self):
+        return None
+
+    def get_constant_class(self, cpu):
+        return None
+
+class PtrOptValue(OptValue):
+    _attrs_ = ('known_class', 'last_guard', 'lenbound')
+
+    known_class = None
+    last_guard = None
+    lenbound = None
+
+    def __init__(self, box, level=None, known_class=None, intbound=None):
+        OptValue.__init__(self, box, level, None, intbound)
+        if not isinstance(box, Const):
+            self.known_class = known_class
+
+    def copy_from(self, other_value):
+        assert isinstance(other_value, PtrOptValue)
+        self.box = other_value.box
+        self.known_class = other_value.known_class
+        self.level = other_value.level
+        self.last_guard = other_value.last_guard
+        self.lenbound = other_value.lenbound
+
+    def make_len_gt(self, mode, descr, val):
+        if self.lenbound:
+            assert self.lenbound.mode == mode
+            assert self.lenbound.descr == descr
+            self.lenbound.bound.make_gt(IntBound(val, val))
+        else:
+            self.lenbound = LenBound(mode, descr, IntLowerBound(val + 1))
+
+    def make_nonnull(self, guardop):
+        assert self.level < LEVEL_NONNULL
+        self.level = LEVEL_NONNULL
+        self.last_guard = guardop
+
+    def make_constant_class(self, classbox, guardop):
+        assert self.level < LEVEL_KNOWNCLASS
+        self.known_class = classbox
+        self.level = LEVEL_KNOWNCLASS
+        self.last_guard = guardop
+
+    def import_from(self, other, optimizer):
+        OptValue.import_from(self, other, optimizer)
+        if self.level != LEVEL_CONSTANT:
+            if other.getlenbound():
+                if self.lenbound:
+                    assert other.getlenbound().mode == self.lenbound.mode
+                    assert other.getlenbound().descr == self.lenbound.descr
+                    self.lenbound.bound.intersect(other.getlenbound().bound)
+                else:
+                    self.lenbound = other.getlenbound().clone()
+
+    def make_guards(self, box):
+        guards = []
+        if self.level == LEVEL_CONSTANT:
+            op = ResOperation(rop.GUARD_VALUE, [box, self.box], None)
+            guards.append(op)
+        elif self.level == LEVEL_KNOWNCLASS:
+            op = ResOperation(rop.GUARD_NONNULL, [box], None)
+            guards.append(op)
+            op = ResOperation(rop.GUARD_CLASS, [box, self.known_class], None)
+            guards.append(op)
+        else:
+            if self.level == LEVEL_NONNULL:
+                op = ResOperation(rop.GUARD_NONNULL, [box], None)
+                guards.append(op)
+            if self.lenbound:
+                lenbox = BoxInt()
+                if self.lenbound.mode == MODE_ARRAY:
+                    op = ResOperation(rop.ARRAYLEN_GC, [box], lenbox, 
self.lenbound.descr)
+                elif self.lenbound.mode == MODE_STR:
+                    op = ResOperation(rop.STRLEN, [box], lenbox, 
self.lenbound.descr)
+                elif self.lenbound.mode == MODE_UNICODE:
+                    op = ResOperation(rop.UNICODELEN, [box], lenbox, 
self.lenbound.descr)
+                else:
+                    debug_print("Unknown lenbound mode")
+                    assert False
+                guards.append(op)
+                self.lenbound.bound.make_guards(lenbox, guards)
+        return guards
+
+    def get_constant_class(self, cpu):
+        level = self.level
+        if level == LEVEL_KNOWNCLASS:
+            return self.known_class
+        elif level == LEVEL_CONSTANT:
+            return cpu.ts.cls_of_box(self.box)
+        else:
+            return None
+
+    def getlenbound(self):
+        return self.lenbound
+
+    def get_last_guard(self):
+        return self.last_guard
+
+    def get_known_class(self):
+        return self.known_class
+
+class IntOptValue(OptValue):
+    _attrs_ = ('intbound',)
+
+    intbound = ImmutableIntUnbounded()
+
+    def __init__(self, box, level=None, known_class=None, intbound=None):
+        OptValue.__init__(self, box, level, None, None)
+        if isinstance(box, Const):
+            return
+        if intbound:
+            self.intbound = intbound
+        else:
+            if isinstance(box, BoxInt):
+                self.intbound = IntBound(MININT, MAXINT)
+            else:
+                self.intbound = IntUnbounded()
+
+    def copy_from(self, other_value):
+        assert isinstance(other_value, IntOptValue)
+        self.box = other_value.box
+        self.intbound = other_value.intbound
+        self.level = other_value.level
+
+    def make_constant(self, constbox):
+        """Replace 'self.box' with a Const box."""
+        assert isinstance(constbox, ConstInt)
+        self.box = constbox
+        self.level = LEVEL_CONSTANT
+        val = constbox.getint()
+        self.intbound = IntBound(val, val)
+
+    def is_nonnull(self):
+        if OptValue.is_nonnull(self):
+            return True
+        if self.intbound:
+            if self.intbound.known_gt(IntBound(0, 0)) or \
+               self.intbound.known_lt(IntBound(0, 0)):
+                return True
+        return False
+
+    def make_nonnull(self, guardop):
+        assert self.level < LEVEL_NONNULL
+        self.level = LEVEL_NONNULL
+
+    def import_from(self, other, optimizer):
+        OptValue.import_from(self, other, optimizer)
+        if self.level != LEVEL_CONSTANT:
+            if other.getintbound() is not None: # VRawBufferValue
+                self.intbound.intersect(other.getintbound())
+
+    def make_guards(self, box):
+        guards = []
+        if self.level == LEVEL_CONSTANT:
+            op = ResOperation(rop.GUARD_VALUE, [box, self.box], None)
+            guards.append(op)
+        elif self.level == LEVEL_KNOWNCLASS:
+            op = ResOperation(rop.GUARD_NONNULL, [box], None)
+            guards.append(op)
+        else:
+            if self.level == LEVEL_NONNULL:
+                op = ResOperation(rop.GUARD_NONNULL, [box], None)
+                guards.append(op)
+            self.intbound.make_guards(box, guards)
+        return guards
+
+    def getintbound(self):
+        return self.intbound
+
+    def get_last_guard(self):
+        return None
+
+    def get_known_class(self):
+        return None
+
+    def getlenbound(self):
+        return None
+
+class ConstantFloatValue(OptValue):
+    def __init__(self, box):
+        self.make_constant(box)
+
+    def __repr__(self):
+        return 'Constant(%r)' % (self.box,)
+
+class ConstantIntValue(IntOptValue):
+    def __init__(self, box):
+        self.make_constant(box)
+
+    def __repr__(self):
+        return 'Constant(%r)' % (self.box,)
+
+class ConstantPtrValue(PtrOptValue):
     def __init__(self, box):
         self.make_constant(box)
 
@@ -276,9 +399,9 @@
 
 CONST_0      = ConstInt(0)
 CONST_1      = ConstInt(1)
-CVAL_ZERO    = ConstantValue(CONST_0)
-CVAL_ZERO_FLOAT = ConstantValue(Const._new(0.0))
-llhelper.CVAL_NULLREF = ConstantValue(llhelper.CONST_NULL)
+CVAL_ZERO    = ConstantIntValue(CONST_0)
+CVAL_ZERO_FLOAT = ConstantFloatValue(Const._new(0.0))
+llhelper.CVAL_NULLREF = ConstantPtrValue(llhelper.CONST_NULL)
 REMOVED = AbstractResOp(None)
 
 
@@ -305,8 +428,8 @@
     def make_constant_int(self, box, intconst):
         return self.optimizer.make_constant_int(box, intconst)
 
-    def make_equal_to(self, box, value):
-        return self.optimizer.make_equal_to(box, value)
+    def make_equal_to(self, box, value, replace=False):
+        return self.optimizer.make_equal_to(box, value, replace=replace)
 
     def get_constant_box(self, box):
         return self.optimizer.get_constant_box(box)
@@ -340,9 +463,6 @@
     def setup(self):
         pass
 
-    def turned_constant(self, value):
-        pass
-
     def force_at_end_of_preamble(self):
         pass
 
@@ -390,9 +510,9 @@
         self.opaque_pointers = {}
         self.replaces_guard = {}
         self._newoperations = []
-        self.seen_results = {}
         self.optimizer = self
         self.optpure = None
+        self.optheap = None
         self.optearlyforce = None
         if loop is not None:
             self.call_pure_results = loop.call_pure_results
@@ -428,10 +548,6 @@
         for opt in self.optimizations:
             opt.produce_potential_short_preamble_ops(sb)
 
-    def turned_constant(self, value):
-        for o in self.optimizations:
-            o.turned_constant(value)
-
     def forget_numberings(self, virtualbox):
         self.metainterp_sd.profiler.count(jitprof.Counters.OPT_FORCINGS)
         self.resumedata_memo.forget_numberings(virtualbox)
@@ -457,7 +573,12 @@
         try:
             value = self.values[box]
         except KeyError:
-            value = self.values[box] = OptValue(box)
+            if isinstance(box, BoxPtr) or isinstance(box, ConstPtr):
+                value = self.values[box] = PtrOptValue(box)
+            elif isinstance(box, BoxInt) or isinstance(box, ConstInt):
+                value = self.values[box] = IntOptValue(box)
+            else:
+                value = self.values[box] = OptValue(box)
         self.ensure_imported(value)
         return value
 
@@ -485,15 +606,31 @@
 
     def clear_newoperations(self):
         self._newoperations = []
-        self.seen_results = {}
 
     def make_equal_to(self, box, value, replace=False):
         assert isinstance(value, OptValue)
-        assert replace or box not in self.values
+        if replace:
+            try:
+                cur_value = self.values[box]
+            except KeyError:
+                pass
+            else:
+                assert value.level != LEVEL_CONSTANT
+                assert cur_value.level != LEVEL_CONSTANT
+                # replacing with a different box
+                cur_value.copy_from(value)
+                return
         self.values[box] = value
 
     def make_constant(self, box, constbox):
-        self.make_equal_to(box, ConstantValue(constbox))
+        if isinstance(constbox, ConstInt):
+            self.make_equal_to(box, ConstantIntValue(constbox))
+        elif isinstance(constbox, ConstPtr):
+            self.make_equal_to(box, ConstantPtrValue(constbox))
+        elif isinstance(constbox, ConstFloat):
+            self.make_equal_to(box, ConstantFloatValue(constbox))
+        else:
+            assert False
 
     def make_constant_int(self, box, intvalue):
         self.make_constant(box, ConstInt(intvalue))
@@ -547,7 +684,8 @@
         self.first_optimization.propagate_forward(op)
 
     def propagate_forward(self, op):
-        self.producer[op.result] = op
+        if op.result is not None:
+            self.producer[op.result] = op
         dispatch_opt(self, op)
 
     def emit_operation(self, op):
@@ -580,10 +718,6 @@
                 op = self.store_final_boxes_in_guard(op, pendingfields)
         elif op.can_raise():
             self.exception_might_have_happened = True
-        if op.result:
-            if op.result in self.seen_results:
-                raise ValueError, "invalid optimization"
-            self.seen_results[op.result] = None
         self._newoperations.append(op)
 
     def replace_op(self, old_op, new_op):
diff --git a/rpython/jit/metainterp/optimizeopt/pure.py 
b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -25,6 +25,7 @@
         else:
             nextop = None
 
+        args = None
         if canfold:
             for i in range(op.numargs()):
                 if self.get_constant_box(op.getarg(i)) is None:
@@ -39,15 +40,11 @@
 
             # did we do the exact same operation already?
             args = self.optimizer.make_args_key(op)
-            oldop = self.pure_operations.get(args, None)
-            if oldop is not None and oldop.getdescr() is op.getdescr():
-                assert oldop.getopnum() == op.getopnum()
-                self.optimizer.make_equal_to(op.result,
-                                             self.getvalue(oldop.result),
-                                             True)
+            oldvalue = self.pure_operations.get(args, None)
+            if oldvalue is not None:
+                self.optimizer.make_equal_to(op.result, oldvalue, True)
                 return
             else:
-                self.pure_operations[args] = op
                 self.remember_emitting_pure(op)
 
         # otherwise, the operation remains
@@ -56,6 +53,8 @@
             self.optimizer.bool_boxes[self.getvalue(op.result)] = None
         if nextop:
             self.emit_operation(nextop)
+        if args is not None:
+            self.pure_operations[args] = self.getvalue(op.result)
 
     def optimize_CALL_PURE(self, op):
         # Step 1: check if all arguments are constant
@@ -69,16 +68,15 @@
         # Step 2: check if all arguments are the same as a previous
         # CALL_PURE.
         args = self.optimizer.make_args_key(op)
-        oldop = self.pure_operations.get(args, None)
-        if oldop is not None and oldop.getdescr() is op.getdescr():
-            assert oldop.getopnum() == op.getopnum()
+        oldvalue = self.pure_operations.get(args, None)
+        if oldvalue is not None:
             # this removes a CALL_PURE that has the same (non-constant)
             # arguments as a previous CALL_PURE.
-            self.make_equal_to(op.result, self.getvalue(oldop.result))
+            self.make_equal_to(op.result, oldvalue)
             self.last_emitted_operation = REMOVED
             return
         else:
-            self.pure_operations[args] = op
+            self.pure_operations[args] = self.getvalue(op.result)
             self.remember_emitting_pure(op)
 
         # replace CALL_PURE with just CALL
@@ -103,15 +101,12 @@
         op = ResOperation(opnum, args, result)
         key = self.optimizer.make_args_key(op)
         if key not in self.pure_operations:
-            self.pure_operations[key] = op
+            self.pure_operations[key] = self.getvalue(result)
 
     def has_pure_result(self, opnum, args, descr):
         op = ResOperation(opnum, args, None, descr)
         key = self.optimizer.make_args_key(op)
-        op = self.pure_operations.get(key, None)
-        if op is None:
-            return False
-        return op.getdescr() is descr
+        return self.pure_operations.get(key, None) is not None
 
     def get_pure_result(self, key):
         return self.pure_operations.get(key, None)
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py 
b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -6,7 +6,7 @@
 from rpython.jit.metainterp.optimize import InvalidLoop
 from rpython.jit.metainterp.optimizeopt.intutils import IntBound
 from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, 
REMOVED,
-    CONST_0, CONST_1)
+    CONST_0, CONST_1, PtrOptValue)
 from rpython.jit.metainterp.optimizeopt.util import _findall, 
make_dispatcher_method
 from rpython.jit.metainterp.resoperation import rop, ResOperation, opclasses
 from rpython.rlib.rarithmetic import highest_bit
@@ -33,9 +33,8 @@
         dispatch_opt(self, op)
 
     def try_boolinvers(self, op, targs):
-        oldop = self.get_pure_result(targs)
-        if oldop is not None and oldop.getdescr() is op.getdescr():
-            value = self.getvalue(oldop.result)
+        value = self.get_pure_result(targs)
+        if value is not None:
             if value.is_constant():
                 if value.box.same_constant(CONST_1):
                     self.make_constant(op.result, CONST_0)
@@ -59,9 +58,9 @@
         if oldopnum != -1:
             targs = self.optimizer.make_args_key(ResOperation(oldopnum, 
[args[1], args[0]],
                                                               None))
-            oldop = self.get_pure_result(targs)
-            if oldop is not None and oldop.getdescr() is op.getdescr():
-                self.make_equal_to(op.result, self.getvalue(oldop.result))
+            value = self.get_pure_result(targs)
+            if value is not None:
+                self.optimizer.make_equal_to(op.result, value, True)
                 return True
 
         if op.boolreflex == -1:
@@ -83,14 +82,14 @@
             return
         elif v2.is_constant():
             val = v2.box.getint()
-            if val == -1 or v1.intbound.lower >= 0 \
-                and v1.intbound.upper <= val & ~(val + 1):
+            if val == -1 or v1.getintbound().lower >= 0 \
+                and v1.getintbound().upper <= val & ~(val + 1):
                 self.make_equal_to(op.result, v1)
                 return
         elif v1.is_constant():
             val = v1.box.getint()
-            if val == -1 or v2.intbound.lower >= 0 \
-                and v2.intbound.upper <= val & ~(val + 1):
+            if val == -1 or v2.getintbound().lower >= 0 \
+                and v2.getintbound().upper <= val & ~(val + 1):
                 self.make_equal_to(op.result, v2)
                 return
 
@@ -262,7 +261,8 @@
         if emit_operation:
             self.emit_operation(op)
         value.make_constant(constbox)
-        self.optimizer.turned_constant(value)
+        if self.optimizer.optheap:
+            self.optimizer.optheap.value_updated(value, 
self.getvalue(constbox))
 
     def optimize_GUARD_ISNULL(self, op):
         value = self.getvalue(op.getarg(0))
@@ -296,11 +296,11 @@
             else:
                 name = "<unknown>"
             raise InvalidLoop('A promote of a virtual %s (a recently allocated 
object) never makes sense!' % name)
-        if value.last_guard:
+        if value.get_last_guard():
             # there already has been a guard_nonnull or guard_class or
             # guard_nonnull_class on this value, which is rather silly.
             # replace the original guard with a guard_value
-            old_guard_op = value.last_guard
+            old_guard_op = value.get_last_guard()
             if old_guard_op.getopnum() != rop.GUARD_NONNULL:
                 # This is only safe if the class of the guard_value matches the
                 # class of the guard_*_class, otherwise the intermediate ops 
might
@@ -323,7 +323,8 @@
             descr.guard_opnum = rop.GUARD_VALUE
             descr.make_a_counter_per_value(op)
             # to be safe
-            value.last_guard = None
+            if isinstance(value, PtrOptValue):
+                value.last_guard = None
         constbox = op.getarg(1)
         assert isinstance(constbox, Const)
         self.optimize_guard(op, constbox)
@@ -355,6 +356,7 @@
             r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
             raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail'
                               % r)
+        assert isinstance(value, PtrOptValue)
         if value.last_guard:
             # there already has been a guard_nonnull or guard_class or
             # guard_nonnull_class on this value.
@@ -564,7 +566,7 @@
         elif v1.is_constant() and v1.box.getint() == 0:
             self.make_constant_int(op.result, 0)
             return
-        if v1.intbound.known_ge(IntBound(0, 0)) and v2.is_constant():
+        if v1.getintbound().known_ge(IntBound(0, 0)) and v2.is_constant():
             val = v2.box.getint()
             if val & (val - 1) == 0 and val > 0: # val == 2**shift
                 op = op.copy_and_change(rop.INT_RSHIFT,
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py 
b/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
@@ -45,7 +45,8 @@
             part.operations = operations
 
             self.add_guard_future_condition(part)
-            state = self._do_optimize_loop(part, None, state)
+            state = self._do_optimize_loop(part, None, state,
+                                           export_state=True)
             if part.operations[-1].getopnum() == rop.LABEL:
                 last_label = [part.operations.pop()]
             else:
@@ -497,7 +498,8 @@
 
 class BaseTestOptimizerRenamingBoxes(BaseTestMultiLabel):
 
-    def _do_optimize_loop(self, loop, call_pure_results, state):
+    def _do_optimize_loop(self, loop, call_pure_results, state,
+                          export_state=False):
         from rpython.jit.metainterp.optimizeopt.unroll import optimize_unroll
         from rpython.jit.metainterp.optimizeopt.util import args_dict
         from rpython.jit.metainterp.optimizeopt.pure import OptPure
@@ -505,7 +507,7 @@
         self.loop = loop
         loop.call_pure_results = args_dict()
         metainterp_sd = FakeMetaInterpStaticData(self.cpu)
-        return optimize_unroll(metainterp_sd, loop, [OptRewrite(), 
OptRenameStrlen(), OptHeap(), OptPure()], True, state)
+        return optimize_unroll(metainterp_sd, loop, [OptRewrite(), 
OptRenameStrlen(), OptHeap(), OptPure()], True, state, export_state)
 
     def test_optimizer_renaming_boxes1(self):
         ops = """
@@ -543,8 +545,8 @@
         self.optimize_loop(ops, expected)
 
 
-class TestLLtype(OptimizeoptTestMultiLabel, LLtypeMixin):
+class XxxTestLLtype(OptimizeoptTestMultiLabel, LLtypeMixin):
     pass
 
-class TestOptimizerRenamingBoxesLLtype(BaseTestOptimizerRenamingBoxes, 
LLtypeMixin):
+class XxxTestOptimizerRenamingBoxesLLtype(BaseTestOptimizerRenamingBoxes, 
LLtypeMixin):
     pass
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -104,7 +104,7 @@
         if loop.operations[-1].getopnum() == rop.JUMP:
             loop.operations[-1].setdescr(token)
         expected = convert_old_style_to_targets(self.parse(optops), jump=True)
-        self._do_optimize_loop(loop, call_pure_results)
+        self._do_optimize_loop(loop, call_pure_results, export_state=False)
         print '\n'.join([str(o) for o in loop.operations])
         self.assert_equal(loop, expected)
 
@@ -999,6 +999,40 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_virtual_array_of_struct_arraycopy(self):
+        ops = """
+        [f0, f1]
+        p0 = new_array_clear(3, descr=complexarraydescr)
+        setinteriorfield_gc(p0, 0, f0, descr=compleximagdescr)
+        setinteriorfield_gc(p0, 0, f1, descr=complexrealdescr)
+        call(0, p0, p0, 0, 2, 1, descr=complexarraycopydescr)
+        f2 = getinteriorfield_gc(p0, 2, descr=complexrealdescr)
+        f3 = getinteriorfield_gc(p0, 2, descr=compleximagdescr)
+        escape(f2)
+        escape(f3)
+        finish(1)
+        """
+        expected = """
+        [f0, f1]
+        escape(f1)
+        escape(f0)
+        finish(1)
+        """
+        self.optimize_loop(ops, ops)
+        py.test.skip("XXX missing optimization: 
ll_arraycopy(array-of-structs)")
+
+    def test_nonvirtual_array_of_struct_arraycopy(self):
+        ops = """
+        [p0]
+        call(0, p0, p0, 0, 2, 1, descr=complexarraycopydescr)
+        f2 = getinteriorfield_gc(p0, 2, descr=compleximagdescr)
+        f3 = getinteriorfield_gc(p0, 2, descr=complexrealdescr)
+        escape(f2)
+        escape(f3)
+        finish(1)
+        """
+        self.optimize_loop(ops, ops)
+
     def test_nonvirtual_1(self):
         ops = """
         [i]
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py 
b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -223,6 +223,10 @@
     complexarraydescr = cpu.arraydescrof(complexarray)
     complexrealdescr = cpu.interiorfielddescrof(complexarray, "real")
     compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag")
+    complexarraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+            EffectInfo([], [complexarraydescr], [], [], [complexarraydescr], 
[],
+                       EffectInfo.EF_CANNOT_RAISE,
+                       oopspecindex=EffectInfo.OS_ARRAYCOPY))
 
     rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed,
                                                   hints={'nolength': True}))
@@ -390,7 +394,8 @@
         assert equaloplists(optimized.operations,
                             expected.operations, False, remap, text_right)
 
-    def _do_optimize_loop(self, loop, call_pure_results, start_state=None):
+    def _do_optimize_loop(self, loop, call_pure_results, start_state=None,
+                          export_state=False):
         from rpython.jit.metainterp.optimizeopt import optimize_trace
         from rpython.jit.metainterp.optimizeopt.util import args_dict
 
@@ -406,7 +411,8 @@
             metainterp_sd.callinfocollection = self.callinfocollection
         #
         return optimize_trace(metainterp_sd, loop, self.enable_opts,
-                              start_state=start_state)
+                              start_state=start_state,
+                              export_state=export_state)
 
     def unroll_and_optimize(self, loop, call_pure_results=None):
         self.add_guard_future_condition(loop)
@@ -426,7 +432,8 @@
         preamble.operations = [ResOperation(rop.LABEL, inputargs, None, 
descr=TargetToken(token))] + \
                               operations +  \
                               [ResOperation(rop.LABEL, jump_args, None, 
descr=token)]
-        start_state = self._do_optimize_loop(preamble, call_pure_results)
+        start_state = self._do_optimize_loop(preamble, call_pure_results,
+                                             export_state=True)
 
         assert preamble.operations[-1].getopnum() == rop.LABEL
 
@@ -440,7 +447,8 @@
         assert loop.operations[0].getopnum() == rop.LABEL
         loop.inputargs = loop.operations[0].getarglist()
 
-        self._do_optimize_loop(loop, call_pure_results, start_state)
+        self._do_optimize_loop(loop, call_pure_results, start_state,
+                               export_state=False)
         extra_same_as = []
         while loop.operations[0].getopnum() != rop.LABEL:
             extra_same_as.append(loop.operations[0])
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py 
b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
@@ -3,7 +3,8 @@
 from rpython.jit.metainterp.optimizeopt.virtualstate import VirtualStateInfo, 
VStructStateInfo, \
      VArrayStateInfo, NotVirtualStateInfo, VirtualState, ShortBoxes, 
GenerateGuardState, \
      VirtualStatesCantMatch, VArrayStructStateInfo
-from rpython.jit.metainterp.optimizeopt.optimizer import OptValue
+from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, 
PtrOptValue,\
+      IntOptValue
 from rpython.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr, ConstInt, 
ConstPtr
 from rpython.rtyper.lltypesystem import lltype, llmemory
 from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin, 
BaseTest, \
@@ -121,13 +122,13 @@
         assert isgeneral(OptValue(BoxInt()), OptValue(ConstInt(7)))
         assert not isgeneral(OptValue(ConstInt(7)), OptValue(BoxInt()))
 
-        ptr = OptValue(BoxPtr())
-        nonnull = OptValue(BoxPtr())
+        ptr = PtrOptValue(BoxPtr())
+        nonnull = PtrOptValue(BoxPtr())
         nonnull.make_nonnull(0)
-        knownclass = OptValue(BoxPtr())
+        knownclass = PtrOptValue(BoxPtr())
         clsbox = self.cpu.ts.cls_of_box(BoxPtr(self.myptr))
         knownclass.make_constant_class(clsbox, 0)
-        const = OptValue(BoxPtr)
+        const = PtrOptValue(BoxPtr)
         const.make_constant_class(clsbox, 0)
         const.make_constant(ConstPtr(self.myptr))
         inorder = [ptr, nonnull, knownclass, const]
@@ -137,8 +138,8 @@
                 if i != j:
                     assert not isgeneral(inorder[j], inorder[i])
 
-        value1 = OptValue(BoxInt())
-        value2 = OptValue(BoxInt())
+        value1 = IntOptValue(BoxInt())
+        value2 = IntOptValue(BoxInt())
         value2.intbound.make_lt(IntBound(10, 10))
         assert isgeneral(value1, value2)
         assert not isgeneral(value2, value1)
@@ -150,9 +151,9 @@
         assert isgeneral(OptValue(ConstPtr(fooref)),
                          OptValue(ConstPtr(fooref)))
 
-        value1 = OptValue(BoxPtr())
+        value1 = PtrOptValue(BoxPtr())
         value1.make_nonnull(None)
-        value2 = OptValue(ConstPtr(self.nullptr))
+        value2 = PtrOptValue(ConstPtr(self.nullptr))
         assert not isgeneral(value1, value2)
 
     def test_field_matching_generalization(self):
@@ -178,18 +179,18 @@
         fldtst(VArrayStructStateInfo(fakedescr, [[fielddescr]]), 
VArrayStructStateInfo(fakedescr, [[fielddescr]]))
 
     def test_known_class_generalization(self):
-        knownclass1 = OptValue(BoxPtr())
+        knownclass1 = PtrOptValue(BoxPtr())
         knownclass1.make_constant_class(ConstPtr(self.myptr), 0)
         info1 = NotVirtualStateInfo(knownclass1)
         info1.position = 0
-        knownclass2 = OptValue(BoxPtr())
+        knownclass2 = PtrOptValue(BoxPtr())
         knownclass2.make_constant_class(ConstPtr(self.myptr), 0)
         info2 = NotVirtualStateInfo(knownclass2)
         info2.position = 0
         self.check_no_guards(info1, info2)
         self.check_no_guards(info2, info1)
 
-        knownclass3 = OptValue(BoxPtr())
+        knownclass3 = PtrOptValue(BoxPtr())
         knownclass3.make_constant_class(ConstPtr(self.myptr2), 0)
         info3 = NotVirtualStateInfo(knownclass3)
         info3.position = 0
@@ -209,33 +210,33 @@
 
     def test_generate_guards_nonvirtual_all_combinations(self):
         # set up infos
-        unknown_val = OptValue(self.nodebox)
-        unknownnull_val = OptValue(BoxPtr(self.nullptr))
+        unknown_val = PtrOptValue(self.nodebox)
+        unknownnull_val = PtrOptValue(BoxPtr(self.nullptr))
         unknown_info = NotVirtualStateInfo(unknown_val)
 
-        nonnull_val = OptValue(self.nodebox)
+        nonnull_val = PtrOptValue(self.nodebox)
         nonnull_val.make_nonnull(None)
         nonnull_info = NotVirtualStateInfo(nonnull_val)
 
-        knownclass_val = OptValue(self.nodebox)
+        knownclass_val = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         knownclass_val.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(knownclass_val)
-        knownclass2_val = OptValue(self.nodebox2)
+        knownclass2_val = PtrOptValue(self.nodebox2)
         classbox = self.cpu.ts.cls_of_box(self.nodebox2)
         knownclass2_val.make_constant_class(classbox, -1)
         knownclass2_info = NotVirtualStateInfo(knownclass2_val)
 
-        constant_val = OptValue(BoxInt())
+        constant_val = IntOptValue(BoxInt())
         constant_val.make_constant(ConstInt(1))
         constant_info = NotVirtualStateInfo(constant_val)
-        constclass_val = OptValue(self.nodebox)
+        constclass_val = PtrOptValue(self.nodebox)
         constclass_val.make_constant(self.nodebox.constbox())
         constclass_info = NotVirtualStateInfo(constclass_val)
-        constclass2_val = OptValue(self.nodebox)
+        constclass2_val = PtrOptValue(self.nodebox)
         constclass2_val.make_constant(self.nodebox2.constbox())
         constclass2_info = NotVirtualStateInfo(constclass2_val)
-        constantnull_val = OptValue(ConstPtr(self.nullptr))
+        constantnull_val = PtrOptValue(ConstPtr(self.nullptr))
         constantnull_info = NotVirtualStateInfo(constantnull_val)
 
         # unknown unknown
@@ -354,11 +355,11 @@
 
 
     def test_intbounds(self):
-        value1 = OptValue(BoxInt(15))
+        value1 = IntOptValue(BoxInt(15))
         value1.intbound.make_ge(IntBound(0, 10))
         value1.intbound.make_le(IntBound(20, 30))
         info1 = NotVirtualStateInfo(value1)
-        info2 = NotVirtualStateInfo(OptValue(BoxInt()))
+        info2 = NotVirtualStateInfo(IntOptValue(BoxInt()))
         expected = """
         [i0]
         i1 = int_ge(i0, 0)
@@ -370,22 +371,22 @@
         self.check_invalid(info1, info2, BoxInt(50))
 
     def test_intbounds_constant(self):
-        value1 = OptValue(BoxInt(15))
+        value1 = IntOptValue(BoxInt(15))
         value1.intbound.make_ge(IntBound(0, 10))
         value1.intbound.make_le(IntBound(20, 30))
         info1 = NotVirtualStateInfo(value1)
-        info2 = NotVirtualStateInfo(OptValue(ConstInt(10000)))
+        info2 = NotVirtualStateInfo(IntOptValue(ConstInt(10000)))
         self.check_invalid(info1, info2)
         info1 = NotVirtualStateInfo(value1)
-        info2 = NotVirtualStateInfo(OptValue(ConstInt(11)))
+        info2 = NotVirtualStateInfo(IntOptValue(ConstInt(11)))
         self.check_no_guards(info1, info2)
 
     def test_known_class(self):
-        value1 = OptValue(self.nodebox)
+        value1 = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         value1.make_constant_class(classbox, -1)
         info1 = NotVirtualStateInfo(value1)
-        info2 = NotVirtualStateInfo(OptValue(self.nodebox))
+        info2 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
         expected = """
         [p0]
         guard_nonnull(p0) []        
@@ -395,7 +396,7 @@
         self.check_invalid(info1, info2, BoxPtr())
 
     def test_known_class_value(self):
-        value1 = OptValue(self.nodebox)
+        value1 = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         value1.make_constant_class(classbox, -1)
         box = self.nodebox
@@ -408,7 +409,7 @@
         self.compare(guards, expected, [box])
 
     def test_known_value(self):
-        value1 = OptValue(self.nodebox)
+        value1 = PtrOptValue(self.nodebox)
         value1.make_constant(ConstInt(1))
         box = self.nodebox
         guards = value1.make_guards(box)
@@ -419,21 +420,21 @@
         self.compare(guards, expected, [box])
 
     def test_equal_inputargs(self):
-        value = OptValue(self.nodebox)
+        value = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         value.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(value)
         vstate1 = VirtualState([knownclass_info, knownclass_info])
         assert vstate1.generalization_of(vstate1)
 
-        unknown_info1 = NotVirtualStateInfo(OptValue(self.nodebox))
+        unknown_info1 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
         vstate2 = VirtualState([unknown_info1, unknown_info1])
         assert vstate2.generalization_of(vstate2)
         assert not vstate1.generalization_of(vstate2)
         assert vstate2.generalization_of(vstate1)
 
-        unknown_info1 = NotVirtualStateInfo(OptValue(self.nodebox))
-        unknown_info2 = NotVirtualStateInfo(OptValue(self.nodebox))
+        unknown_info1 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
+        unknown_info2 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
         vstate3 = VirtualState([unknown_info1, unknown_info2])
         assert vstate3.generalization_of(vstate2)
         assert vstate3.generalization_of(vstate1)
@@ -457,12 +458,12 @@
 
 
     def test_generate_guards_on_virtual_fields_matches_array(self):
-        innervalue1 = OptValue(self.nodebox)
+        innervalue1 = PtrOptValue(self.nodebox)
         constclassbox = self.cpu.ts.cls_of_box(self.nodebox)
         innervalue1.make_constant_class(constclassbox, -1)
         innerinfo1 = NotVirtualStateInfo(innervalue1)
         innerinfo1.position = 1
-        innerinfo2 = NotVirtualStateInfo(OptValue(self.nodebox))
+        innerinfo2 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
         innerinfo2.position = 1
 
         descr = object()
@@ -474,7 +475,7 @@
         info2.fieldstate = [innerinfo2]
 
         value1 = VArrayValue(descr, None, 1, self.nodebox)
-        value1._items[0] = OptValue(self.nodebox)
+        value1._items[0] = PtrOptValue(self.nodebox)
 
         expected = """
         [p0]
@@ -484,12 +485,12 @@
         self.guards(info1, info2, value1, expected, [self.nodebox])
 
     def test_generate_guards_on_virtual_fields_matches_instance(self):
-        innervalue1 = OptValue(self.nodebox)
+        innervalue1 = PtrOptValue(self.nodebox)
         constclassbox = self.cpu.ts.cls_of_box(self.nodebox)
         innervalue1.make_constant_class(constclassbox, -1)
         innerinfo1 = NotVirtualStateInfo(innervalue1)
         innerinfo1.position = 1
-        innerinfo2 = NotVirtualStateInfo(OptValue(self.nodebox))
+        innerinfo2 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
         innerinfo2.position = 1
 
         info1 = VirtualStateInfo(ConstInt(42), [1])
@@ -499,7 +500,7 @@
         info2.fieldstate = [innerinfo2]
 
         value1 = VirtualValue(self.cpu, constclassbox, self.nodebox)
-        value1._fields = {1: OptValue(self.nodebox)}
+        value1._fields = {1: PtrOptValue(self.nodebox)}
 
         expected = """
         [p0]
@@ -509,12 +510,12 @@
         self.guards(info1, info2, value1, expected, [self.nodebox])
 
     def test_generate_guards_on_virtual_fields_matches_struct(self):
-        innervalue1 = OptValue(self.nodebox)
+        innervalue1 = PtrOptValue(self.nodebox)
         constclassbox = self.cpu.ts.cls_of_box(self.nodebox)
         innervalue1.make_constant_class(constclassbox, -1)
         innerinfo1 = NotVirtualStateInfo(innervalue1)
         innerinfo1.position = 1
-        innerinfo2 = NotVirtualStateInfo(OptValue(self.nodebox))
+        innerinfo2 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
         innerinfo2.position = 1
 
         structdescr = object()
@@ -526,7 +527,7 @@
         info2.fieldstate = [innerinfo2]
 
         value1 = VStructValue(self.cpu, structdescr, self.nodebox)
-        value1._fields = {1: OptValue(self.nodebox)}
+        value1._fields = {1: PtrOptValue(self.nodebox)}
 
         expected = """
         [p0]
@@ -536,12 +537,12 @@
         self.guards(info1, info2, value1, expected, [self.nodebox])
 
     def test_generate_guards_on_virtual_fields_matches_arraystruct(self):
-        innervalue1 = OptValue(self.nodebox)
+        innervalue1 = PtrOptValue(self.nodebox)
         constclassbox = self.cpu.ts.cls_of_box(self.nodebox)
         innervalue1.make_constant_class(constclassbox, -1)
         innerinfo1 = NotVirtualStateInfo(innervalue1)
         innerinfo1.position = 1
-        innerinfo2 = NotVirtualStateInfo(OptValue(self.nodebox))
+        innerinfo2 = NotVirtualStateInfo(PtrOptValue(self.nodebox))
         innerinfo2.position = 1
 
         arraydescr = object()
@@ -554,7 +555,7 @@
         info2.fieldstate = [innerinfo2]
 
         value1 = VArrayStructValue(arraydescr, 1, self.nodebox)
-        value1._items[0][fielddescr] = OptValue(self.nodebox)
+        value1._items[0][fielddescr] = PtrOptValue(self.nodebox)
 
         expected = """
         [p0]
@@ -568,7 +569,7 @@
 
     def test_virtuals_with_equal_fields(self):
         info1 = VirtualStateInfo(ConstInt(42), [1, 2])
-        value = OptValue(self.nodebox)
+        value = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         value.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(value)
@@ -596,7 +597,7 @@
 
     def test_virtuals_with_nonmatching_fields(self):
         info1 = VirtualStateInfo(ConstInt(42), [1, 2])
-        value = OptValue(self.nodebox)
+        value = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         value.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(value)
@@ -605,7 +606,7 @@
         assert vstate1.generalization_of(vstate1)
 
         info2 = VirtualStateInfo(ConstInt(42), [1, 2])
-        value = OptValue(self.nodebox2)
+        value = PtrOptValue(self.nodebox2)
         classbox = self.cpu.ts.cls_of_box(self.nodebox2)
         value.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(value)
@@ -618,7 +619,7 @@
 
     def test_virtuals_with_nonmatching_descrs(self):
         info1 = VirtualStateInfo(ConstInt(42), [10, 20])
-        value = OptValue(self.nodebox)
+        value = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         value.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(value)
@@ -627,7 +628,7 @@
         assert vstate1.generalization_of(vstate1)
 
         info2 = VirtualStateInfo(ConstInt(42), [1, 2])
-        value = OptValue(self.nodebox2)
+        value = PtrOptValue(self.nodebox2)
         classbox = self.cpu.ts.cls_of_box(self.nodebox2)
         value.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(value)
@@ -640,7 +641,7 @@
         
     def test_virtuals_with_nonmatching_classes(self):
         info1 = VirtualStateInfo(ConstInt(42), [1, 2])
-        value = OptValue(self.nodebox)
+        value = PtrOptValue(self.nodebox)
         classbox = self.cpu.ts.cls_of_box(self.nodebox)
         value.make_constant_class(classbox, -1)
         knownclass_info = NotVirtualStateInfo(value)
@@ -649,7 +650,7 @@
         assert vstate1.generalization_of(vstate1)
 
         info2 = VirtualStateInfo(ConstInt(7), [1, 2])
-        value = OptValue(self.nodebox2)
+        value = PtrOptValue(self.nodebox2)
         classbox = self.cpu.ts.cls_of_box(self.nodebox2)
         value.make_constant_class(classbox, -1)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to