[pypy-commit] pypy default: merge heads

fijal noreply at buildbot.pypy.org
Mon Oct 24 20:19:26 CEST 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: 
Changeset: r48388:76d0bea6c4e7
Date: 2011-10-24 20:19 +0200
http://bitbucket.org/pypy/pypy/changeset/76d0bea6c4e7/

Log:	merge heads

diff --git a/pypy/interpreter/astcompiler/ast.py b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter import typedef
 from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.tool.pairtype import extendabletype
 from pypy.tool.sourcetools import func_with_new_name
@@ -2925,14 +2925,13 @@
 def Module_get_body(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -2968,14 +2967,13 @@
 def Interactive_get_body(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -3015,8 +3013,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     return space.wrap(w_self.body)
 
 def Expression_set_body(space, w_self, w_new_value):
@@ -3057,14 +3054,13 @@
 def Suite_get_body(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -3104,8 +3100,7 @@
             return w_obj
     if not w_self.initialization_state & w_self._lineno_mask:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'lineno'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'lineno')
     return space.wrap(w_self.lineno)
 
 def stmt_set_lineno(space, w_self, w_new_value):
@@ -3126,8 +3121,7 @@
             return w_obj
     if not w_self.initialization_state & w_self._col_offset_mask:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'col_offset'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'col_offset')
     return space.wrap(w_self.col_offset)
 
 def stmt_set_col_offset(space, w_self, w_new_value):
@@ -3157,8 +3151,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'name'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'name')
     return space.wrap(w_self.name)
 
 def FunctionDef_set_name(space, w_self, w_new_value):
@@ -3179,8 +3172,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'args'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'args')
     return space.wrap(w_self.args)
 
 def FunctionDef_set_args(space, w_self, w_new_value):
@@ -3197,14 +3189,13 @@
 def FunctionDef_get_body(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -3215,14 +3206,13 @@
 def FunctionDef_get_decorator_list(space, w_self):
     if not w_self.initialization_state & 8:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'decorator_list'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'decorator_list')
     if w_self.w_decorator_list is None:
         if w_self.decorator_list is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.decorator_list]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_decorator_list = w_list
     return w_self.w_decorator_list
 
@@ -3266,8 +3256,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'name'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'name')
     return space.wrap(w_self.name)
 
 def ClassDef_set_name(space, w_self, w_new_value):
@@ -3284,14 +3273,13 @@
 def ClassDef_get_bases(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'bases'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'bases')
     if w_self.w_bases is None:
         if w_self.bases is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.bases]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_bases = w_list
     return w_self.w_bases
 
@@ -3302,14 +3290,13 @@
 def ClassDef_get_body(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -3320,14 +3307,13 @@
 def ClassDef_get_decorator_list(space, w_self):
     if not w_self.initialization_state & 8:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'decorator_list'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'decorator_list')
     if w_self.w_decorator_list is None:
         if w_self.decorator_list is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.decorator_list]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_decorator_list = w_list
     return w_self.w_decorator_list
 
@@ -3372,8 +3358,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Return_set_value(space, w_self, w_new_value):
@@ -3414,14 +3399,13 @@
 def Delete_get_targets(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'targets'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'targets')
     if w_self.w_targets is None:
         if w_self.targets is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.targets]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_targets = w_list
     return w_self.w_targets
 
@@ -3457,14 +3441,13 @@
 def Assign_get_targets(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'targets'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'targets')
     if w_self.w_targets is None:
         if w_self.targets is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.targets]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_targets = w_list
     return w_self.w_targets
 
@@ -3479,8 +3462,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Assign_set_value(space, w_self, w_new_value):
@@ -3527,8 +3509,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'target'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'target')
     return space.wrap(w_self.target)
 
 def AugAssign_set_target(space, w_self, w_new_value):
@@ -3549,8 +3530,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'op'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'op')
     return operator_to_class[w_self.op - 1]()
 
 def AugAssign_set_op(space, w_self, w_new_value):
@@ -3573,8 +3553,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def AugAssign_set_value(space, w_self, w_new_value):
@@ -3621,8 +3600,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'dest'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'dest')
     return space.wrap(w_self.dest)
 
 def Print_set_dest(space, w_self, w_new_value):
@@ -3639,14 +3617,13 @@
 def Print_get_values(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'values'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'values')
     if w_self.w_values is None:
         if w_self.values is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.values]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_values = w_list
     return w_self.w_values
 
@@ -3661,8 +3638,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'nl'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'nl')
     return space.wrap(w_self.nl)
 
 def Print_set_nl(space, w_self, w_new_value):
@@ -3710,8 +3686,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'target'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'target')
     return space.wrap(w_self.target)
 
 def For_set_target(space, w_self, w_new_value):
@@ -3732,8 +3707,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'iter'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'iter')
     return space.wrap(w_self.iter)
 
 def For_set_iter(space, w_self, w_new_value):
@@ -3750,14 +3724,13 @@
 def For_get_body(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -3768,14 +3741,13 @@
 def For_get_orelse(space, w_self):
     if not w_self.initialization_state & 8:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'orelse'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'orelse')
     if w_self.w_orelse is None:
         if w_self.orelse is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.orelse]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_orelse = w_list
     return w_self.w_orelse
 
@@ -3819,8 +3791,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'test'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'test')
     return space.wrap(w_self.test)
 
 def While_set_test(space, w_self, w_new_value):
@@ -3837,14 +3808,13 @@
 def While_get_body(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -3855,14 +3825,13 @@
 def While_get_orelse(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'orelse'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'orelse')
     if w_self.w_orelse is None:
         if w_self.orelse is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.orelse]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_orelse = w_list
     return w_self.w_orelse
 
@@ -3905,8 +3874,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'test'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'test')
     return space.wrap(w_self.test)
 
 def If_set_test(space, w_self, w_new_value):
@@ -3923,14 +3891,13 @@
 def If_get_body(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -3941,14 +3908,13 @@
 def If_get_orelse(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'orelse'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'orelse')
     if w_self.w_orelse is None:
         if w_self.orelse is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.orelse]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_orelse = w_list
     return w_self.w_orelse
 
@@ -3991,8 +3957,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'context_expr'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'context_expr')
     return space.wrap(w_self.context_expr)
 
 def With_set_context_expr(space, w_self, w_new_value):
@@ -4013,8 +3978,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'optional_vars'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'optional_vars')
     return space.wrap(w_self.optional_vars)
 
 def With_set_optional_vars(space, w_self, w_new_value):
@@ -4031,14 +3995,13 @@
 def With_get_body(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -4080,8 +4043,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'type'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'type')
     return space.wrap(w_self.type)
 
 def Raise_set_type(space, w_self, w_new_value):
@@ -4102,8 +4064,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'inst'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'inst')
     return space.wrap(w_self.inst)
 
 def Raise_set_inst(space, w_self, w_new_value):
@@ -4124,8 +4085,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'tback'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'tback')
     return space.wrap(w_self.tback)
 
 def Raise_set_tback(space, w_self, w_new_value):
@@ -4168,14 +4128,13 @@
 def TryExcept_get_body(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -4186,14 +4145,13 @@
 def TryExcept_get_handlers(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'handlers'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'handlers')
     if w_self.w_handlers is None:
         if w_self.handlers is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.handlers]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_handlers = w_list
     return w_self.w_handlers
 
@@ -4204,14 +4162,13 @@
 def TryExcept_get_orelse(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'orelse'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'orelse')
     if w_self.w_orelse is None:
         if w_self.orelse is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.orelse]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_orelse = w_list
     return w_self.w_orelse
 
@@ -4251,14 +4208,13 @@
 def TryFinally_get_body(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -4269,14 +4225,13 @@
 def TryFinally_get_finalbody(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'finalbody'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'finalbody')
     if w_self.w_finalbody is None:
         if w_self.finalbody is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.finalbody]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_finalbody = w_list
     return w_self.w_finalbody
 
@@ -4318,8 +4273,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'test'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'test')
     return space.wrap(w_self.test)
 
 def Assert_set_test(space, w_self, w_new_value):
@@ -4340,8 +4294,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'msg'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'msg')
     return space.wrap(w_self.msg)
 
 def Assert_set_msg(space, w_self, w_new_value):
@@ -4383,14 +4336,13 @@
 def Import_get_names(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'names'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'names')
     if w_self.w_names is None:
         if w_self.names is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.names]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_names = w_list
     return w_self.w_names
 
@@ -4430,8 +4382,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'module'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'module')
     return space.wrap(w_self.module)
 
 def ImportFrom_set_module(space, w_self, w_new_value):
@@ -4451,14 +4402,13 @@
 def ImportFrom_get_names(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'names'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'names')
     if w_self.w_names is None:
         if w_self.names is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.names]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_names = w_list
     return w_self.w_names
 
@@ -4473,8 +4423,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'level'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'level')
     return space.wrap(w_self.level)
 
 def ImportFrom_set_level(space, w_self, w_new_value):
@@ -4522,8 +4471,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     return space.wrap(w_self.body)
 
 def Exec_set_body(space, w_self, w_new_value):
@@ -4544,8 +4492,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'globals'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'globals')
     return space.wrap(w_self.globals)
 
 def Exec_set_globals(space, w_self, w_new_value):
@@ -4566,8 +4513,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'locals'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'locals')
     return space.wrap(w_self.locals)
 
 def Exec_set_locals(space, w_self, w_new_value):
@@ -4610,14 +4556,13 @@
 def Global_get_names(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'names'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'names')
     if w_self.w_names is None:
         if w_self.names is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.names]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_names = w_list
     return w_self.w_names
 
@@ -4657,8 +4602,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Expr_set_value(space, w_self, w_new_value):
@@ -4754,8 +4698,7 @@
             return w_obj
     if not w_self.initialization_state & w_self._lineno_mask:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'lineno'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'lineno')
     return space.wrap(w_self.lineno)
 
 def expr_set_lineno(space, w_self, w_new_value):
@@ -4776,8 +4719,7 @@
             return w_obj
     if not w_self.initialization_state & w_self._col_offset_mask:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'col_offset'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'col_offset')
     return space.wrap(w_self.col_offset)
 
 def expr_set_col_offset(space, w_self, w_new_value):
@@ -4807,8 +4749,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'op'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'op')
     return boolop_to_class[w_self.op - 1]()
 
 def BoolOp_set_op(space, w_self, w_new_value):
@@ -4827,14 +4768,13 @@
 def BoolOp_get_values(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'values'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'values')
     if w_self.w_values is None:
         if w_self.values is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.values]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_values = w_list
     return w_self.w_values
 
@@ -4875,8 +4815,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'left'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'left')
     return space.wrap(w_self.left)
 
 def BinOp_set_left(space, w_self, w_new_value):
@@ -4897,8 +4836,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'op'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'op')
     return operator_to_class[w_self.op - 1]()
 
 def BinOp_set_op(space, w_self, w_new_value):
@@ -4921,8 +4859,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'right'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'right')
     return space.wrap(w_self.right)
 
 def BinOp_set_right(space, w_self, w_new_value):
@@ -4969,8 +4906,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'op'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'op')
     return unaryop_to_class[w_self.op - 1]()
 
 def UnaryOp_set_op(space, w_self, w_new_value):
@@ -4993,8 +4929,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'operand'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'operand')
     return space.wrap(w_self.operand)
 
 def UnaryOp_set_operand(space, w_self, w_new_value):
@@ -5040,8 +4975,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'args'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'args')
     return space.wrap(w_self.args)
 
 def Lambda_set_args(space, w_self, w_new_value):
@@ -5062,8 +4996,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     return space.wrap(w_self.body)
 
 def Lambda_set_body(space, w_self, w_new_value):
@@ -5109,8 +5042,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'test'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'test')
     return space.wrap(w_self.test)
 
 def IfExp_set_test(space, w_self, w_new_value):
@@ -5131,8 +5063,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     return space.wrap(w_self.body)
 
 def IfExp_set_body(space, w_self, w_new_value):
@@ -5153,8 +5084,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'orelse'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'orelse')
     return space.wrap(w_self.orelse)
 
 def IfExp_set_orelse(space, w_self, w_new_value):
@@ -5197,14 +5127,13 @@
 def Dict_get_keys(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'keys'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'keys')
     if w_self.w_keys is None:
         if w_self.keys is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.keys]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_keys = w_list
     return w_self.w_keys
 
@@ -5215,14 +5144,13 @@
 def Dict_get_values(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'values'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'values')
     if w_self.w_values is None:
         if w_self.values is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.values]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_values = w_list
     return w_self.w_values
 
@@ -5260,14 +5188,13 @@
 def Set_get_elts(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'elts'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'elts')
     if w_self.w_elts is None:
         if w_self.elts is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.elts]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_elts = w_list
     return w_self.w_elts
 
@@ -5307,8 +5234,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'elt'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'elt')
     return space.wrap(w_self.elt)
 
 def ListComp_set_elt(space, w_self, w_new_value):
@@ -5325,14 +5251,13 @@
 def ListComp_get_generators(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'generators'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'generators')
     if w_self.w_generators is None:
         if w_self.generators is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.generators]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_generators = w_list
     return w_self.w_generators
 
@@ -5373,8 +5298,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'elt'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'elt')
     return space.wrap(w_self.elt)
 
 def SetComp_set_elt(space, w_self, w_new_value):
@@ -5391,14 +5315,13 @@
 def SetComp_get_generators(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'generators'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'generators')
     if w_self.w_generators is None:
         if w_self.generators is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.generators]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_generators = w_list
     return w_self.w_generators
 
@@ -5439,8 +5362,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'key'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'key')
     return space.wrap(w_self.key)
 
 def DictComp_set_key(space, w_self, w_new_value):
@@ -5461,8 +5383,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def DictComp_set_value(space, w_self, w_new_value):
@@ -5479,14 +5400,13 @@
 def DictComp_get_generators(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'generators'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'generators')
     if w_self.w_generators is None:
         if w_self.generators is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.generators]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_generators = w_list
     return w_self.w_generators
 
@@ -5528,8 +5448,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'elt'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'elt')
     return space.wrap(w_self.elt)
 
 def GeneratorExp_set_elt(space, w_self, w_new_value):
@@ -5546,14 +5465,13 @@
 def GeneratorExp_get_generators(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'generators'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'generators')
     if w_self.w_generators is None:
         if w_self.generators is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.generators]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_generators = w_list
     return w_self.w_generators
 
@@ -5594,8 +5512,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Yield_set_value(space, w_self, w_new_value):
@@ -5640,8 +5557,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'left'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'left')
     return space.wrap(w_self.left)
 
 def Compare_set_left(space, w_self, w_new_value):
@@ -5658,14 +5574,13 @@
 def Compare_get_ops(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'ops'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'ops')
     if w_self.w_ops is None:
         if w_self.ops is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [cmpop_to_class[node - 1]() for node in w_self.ops]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_ops = w_list
     return w_self.w_ops
 
@@ -5676,14 +5591,13 @@
 def Compare_get_comparators(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'comparators'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'comparators')
     if w_self.w_comparators is None:
         if w_self.comparators is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.comparators]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_comparators = w_list
     return w_self.w_comparators
 
@@ -5726,8 +5640,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'func'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'func')
     return space.wrap(w_self.func)
 
 def Call_set_func(space, w_self, w_new_value):
@@ -5744,14 +5657,13 @@
 def Call_get_args(space, w_self):
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'args'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'args')
     if w_self.w_args is None:
         if w_self.args is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.args]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_args = w_list
     return w_self.w_args
 
@@ -5762,14 +5674,13 @@
 def Call_get_keywords(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'keywords'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'keywords')
     if w_self.w_keywords is None:
         if w_self.keywords is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.keywords]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_keywords = w_list
     return w_self.w_keywords
 
@@ -5784,8 +5695,7 @@
             return w_obj
     if not w_self.initialization_state & 8:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'starargs'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'starargs')
     return space.wrap(w_self.starargs)
 
 def Call_set_starargs(space, w_self, w_new_value):
@@ -5806,8 +5716,7 @@
             return w_obj
     if not w_self.initialization_state & 16:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'kwargs'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'kwargs')
     return space.wrap(w_self.kwargs)
 
 def Call_set_kwargs(space, w_self, w_new_value):
@@ -5858,8 +5767,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Repr_set_value(space, w_self, w_new_value):
@@ -5904,8 +5812,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'n'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'n')
     return w_self.n
 
 def Num_set_n(space, w_self, w_new_value):
@@ -5950,8 +5857,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 's'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 's')
     return w_self.s
 
 def Str_set_s(space, w_self, w_new_value):
@@ -5996,8 +5902,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Attribute_set_value(space, w_self, w_new_value):
@@ -6018,8 +5923,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'attr'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'attr')
     return space.wrap(w_self.attr)
 
 def Attribute_set_attr(space, w_self, w_new_value):
@@ -6040,8 +5944,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'ctx'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'ctx')
     return expr_context_to_class[w_self.ctx - 1]()
 
 def Attribute_set_ctx(space, w_self, w_new_value):
@@ -6090,8 +5993,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Subscript_set_value(space, w_self, w_new_value):
@@ -6112,8 +6014,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'slice'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'slice')
     return space.wrap(w_self.slice)
 
 def Subscript_set_slice(space, w_self, w_new_value):
@@ -6134,8 +6035,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'ctx'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'ctx')
     return expr_context_to_class[w_self.ctx - 1]()
 
 def Subscript_set_ctx(space, w_self, w_new_value):
@@ -6184,8 +6084,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'id'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'id')
     return space.wrap(w_self.id)
 
 def Name_set_id(space, w_self, w_new_value):
@@ -6206,8 +6105,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'ctx'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'ctx')
     return expr_context_to_class[w_self.ctx - 1]()
 
 def Name_set_ctx(space, w_self, w_new_value):
@@ -6251,14 +6149,13 @@
 def List_get_elts(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'elts'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'elts')
     if w_self.w_elts is None:
         if w_self.elts is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.elts]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_elts = w_list
     return w_self.w_elts
 
@@ -6273,8 +6170,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'ctx'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'ctx')
     return expr_context_to_class[w_self.ctx - 1]()
 
 def List_set_ctx(space, w_self, w_new_value):
@@ -6319,14 +6215,13 @@
 def Tuple_get_elts(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'elts'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'elts')
     if w_self.w_elts is None:
         if w_self.elts is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.elts]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_elts = w_list
     return w_self.w_elts
 
@@ -6341,8 +6236,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'ctx'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'ctx')
     return expr_context_to_class[w_self.ctx - 1]()
 
 def Tuple_set_ctx(space, w_self, w_new_value):
@@ -6391,8 +6285,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return w_self.value
 
 def Const_set_value(space, w_self, w_new_value):
@@ -6510,8 +6403,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'lower'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'lower')
     return space.wrap(w_self.lower)
 
 def Slice_set_lower(space, w_self, w_new_value):
@@ -6532,8 +6424,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'upper'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'upper')
     return space.wrap(w_self.upper)
 
 def Slice_set_upper(space, w_self, w_new_value):
@@ -6554,8 +6445,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'step'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'step')
     return space.wrap(w_self.step)
 
 def Slice_set_step(space, w_self, w_new_value):
@@ -6598,14 +6488,13 @@
 def ExtSlice_get_dims(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'dims'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'dims')
     if w_self.w_dims is None:
         if w_self.dims is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.dims]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_dims = w_list
     return w_self.w_dims
 
@@ -6645,8 +6534,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def Index_set_value(space, w_self, w_new_value):
@@ -6915,8 +6803,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'target'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'target')
     return space.wrap(w_self.target)
 
 def comprehension_set_target(space, w_self, w_new_value):
@@ -6937,8 +6824,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'iter'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'iter')
     return space.wrap(w_self.iter)
 
 def comprehension_set_iter(space, w_self, w_new_value):
@@ -6955,14 +6841,13 @@
 def comprehension_get_ifs(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'ifs'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'ifs')
     if w_self.w_ifs is None:
         if w_self.ifs is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.ifs]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_ifs = w_list
     return w_self.w_ifs
 
@@ -7004,8 +6889,7 @@
             return w_obj
     if not w_self.initialization_state & w_self._lineno_mask:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'lineno'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'lineno')
     return space.wrap(w_self.lineno)
 
 def excepthandler_set_lineno(space, w_self, w_new_value):
@@ -7026,8 +6910,7 @@
             return w_obj
     if not w_self.initialization_state & w_self._col_offset_mask:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'col_offset'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'col_offset')
     return space.wrap(w_self.col_offset)
 
 def excepthandler_set_col_offset(space, w_self, w_new_value):
@@ -7057,8 +6940,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'type'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'type')
     return space.wrap(w_self.type)
 
 def ExceptHandler_set_type(space, w_self, w_new_value):
@@ -7079,8 +6961,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'name'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'name')
     return space.wrap(w_self.name)
 
 def ExceptHandler_set_name(space, w_self, w_new_value):
@@ -7097,14 +6978,13 @@
 def ExceptHandler_get_body(space, w_self):
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'body'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'body')
     if w_self.w_body is None:
         if w_self.body is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.body]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_body = w_list
     return w_self.w_body
 
@@ -7142,14 +7022,13 @@
 def arguments_get_args(space, w_self):
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'args'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'args')
     if w_self.w_args is None:
         if w_self.args is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.args]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_args = w_list
     return w_self.w_args
 
@@ -7164,8 +7043,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'vararg'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'vararg')
     return space.wrap(w_self.vararg)
 
 def arguments_set_vararg(space, w_self, w_new_value):
@@ -7189,8 +7067,7 @@
             return w_obj
     if not w_self.initialization_state & 4:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'kwarg'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'kwarg')
     return space.wrap(w_self.kwarg)
 
 def arguments_set_kwarg(space, w_self, w_new_value):
@@ -7210,14 +7087,13 @@
 def arguments_get_defaults(space, w_self):
     if not w_self.initialization_state & 8:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'defaults'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'defaults')
     if w_self.w_defaults is None:
         if w_self.defaults is None:
-            w_list = space.newlist([])
+            list_w = []
         else:
             list_w = [space.wrap(node) for node in w_self.defaults]
-            w_list = space.newlist(list_w)
+        w_list = space.newlist(list_w)
         w_self.w_defaults = w_list
     return w_self.w_defaults
 
@@ -7261,8 +7137,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'arg'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'arg')
     return space.wrap(w_self.arg)
 
 def keyword_set_arg(space, w_self, w_new_value):
@@ -7283,8 +7158,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'value'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'value')
     return space.wrap(w_self.value)
 
 def keyword_set_value(space, w_self, w_new_value):
@@ -7330,8 +7204,7 @@
             return w_obj
     if not w_self.initialization_state & 1:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'name'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'name')
     return space.wrap(w_self.name)
 
 def alias_set_name(space, w_self, w_new_value):
@@ -7352,8 +7225,7 @@
             return w_obj
     if not w_self.initialization_state & 2:
         typename = space.type(w_self).getname(space)
-        w_err = space.wrap("'%s' object has no attribute 'asname'" % typename)
-        raise OperationError(space.w_AttributeError, w_err)
+        raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'asname')
     return space.wrap(w_self.asname)
 
 def alias_set_asname(space, w_self, w_new_value):
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -414,13 +414,12 @@
             self.emit("        return w_obj", 1)
         self.emit("if not w_self.initialization_state & %s:" % (flag,), 1)
         self.emit("typename = space.type(w_self).getname(space)", 2)
-        self.emit("w_err = space.wrap(\"'%%s' object has no attribute '%s'\" %% typename)" %
+        self.emit("raise operationerrfmt(space.w_AttributeError, \"'%%s' object has no attribute '%%s'\", typename, '%s')" %
                   (field.name,), 2)
-        self.emit("raise OperationError(space.w_AttributeError, w_err)", 2)
         if field.seq:
             self.emit("if w_self.w_%s is None:" % (field.name,), 1)
             self.emit("if w_self.%s is None:" % (field.name,), 2)
-            self.emit("w_list = space.newlist([])", 3)
+            self.emit("list_w = []", 3)
             self.emit("else:", 2)
             if field.type.value in self.data.simple_types:
                 wrapper = "%s_to_class[node - 1]()" % (field.type,)
@@ -428,7 +427,7 @@
                 wrapper = "space.wrap(node)"
             self.emit("list_w = [%s for node in w_self.%s]" %
                       (wrapper, field.name), 3)
-            self.emit("w_list = space.newlist(list_w)", 3)
+            self.emit("w_list = space.newlist(list_w)", 2)
             self.emit("w_self.w_%s = w_list" % (field.name,), 2)
             self.emit("return w_self.w_%s" % (field.name,), 1)
         elif field.type.value in self.data.simple_types:
@@ -540,7 +539,7 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter import typedef
 from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.tool.pairtype import extendabletype
 from pypy.tool.sourcetools import func_with_new_name
@@ -639,9 +638,7 @@
             missing = required[i]
             if missing is not None:
                  err = "required field \\"%s\\" missing from %s"
-                 err = err % (missing, host)
-                 w_err = space.wrap(err)
-                 raise OperationError(space.w_TypeError, w_err)
+                 raise operationerrfmt(space.w_TypeError, err, missing, host)
     raise AssertionError("should not reach here")
 
 
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -7,9 +7,7 @@
 import weakref
 from pypy.objspace.flow.model import Variable, Constant
 from pypy.annotation import model as annmodel
-from pypy.jit.metainterp.history import (ConstInt, ConstPtr,
-                                         BoxInt, BoxPtr, BoxObj, BoxFloat,
-                                         REF, INT, FLOAT)
+from pypy.jit.metainterp.history import REF, INT, FLOAT
 from pypy.jit.codewriter import heaptracker
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
 from pypy.rpython.ootypesystem import ootype
@@ -17,7 +15,7 @@
 from pypy.rpython.llinterp import LLException
 from pypy.rpython.extregistry import ExtRegistryEntry
 
-from pypy.jit.metainterp import resoperation, executor
+from pypy.jit.metainterp import resoperation
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.backend.llgraph import symbolic
 from pypy.jit.codewriter import longlong
@@ -334,6 +332,13 @@
     assert isinstance(type, str) and len(type) == 1
     op.descr = Descr(ofs, type, arg_types=arg_types)
 
+def compile_add_descr_arg(loop, ofs, type, arg_types):
+    from pypy.jit.backend.llgraph.runner import Descr
+    loop = _from_opaque(loop)
+    op = loop.operations[-1]
+    assert isinstance(type, str) and len(type) == 1
+    op.args.append(Descr(ofs, type, arg_types=arg_types))
+
 def compile_add_loop_token(loop, descr):
     if we_are_translated():
         raise ValueError("CALL_ASSEMBLER not supported")
@@ -438,8 +443,11 @@
         self._may_force = -1
 
     def getenv(self, v):
+        from pypy.jit.backend.llgraph.runner import Descr
         if isinstance(v, Constant):
             return v.value
+        elif isinstance(v, Descr):
+            return v
         else:
             return self.env[v]
 
@@ -807,6 +815,29 @@
         else:
             raise NotImplementedError
 
+    def op_getinteriorfield_gc(self, descr, array, index):
+        if descr.typeinfo == REF:
+            return do_getinteriorfield_gc_ptr(array, index, descr.ofs)
+        elif descr.typeinfo == INT:
+            return do_getinteriorfield_gc_int(array, index, descr.ofs)
+        elif descr.typeinfo == FLOAT:
+            return do_getinteriorfield_gc_float(array, index, descr.ofs)
+        else:
+            raise NotImplementedError
+
+    def op_setinteriorfield_gc(self, descr, array, index, newvalue):
+        if descr.typeinfo == REF:
+            return do_setinteriorfield_gc_ptr(array, index, descr.ofs,
+                                              newvalue)
+        elif descr.typeinfo == INT:
+            return do_setinteriorfield_gc_int(array, index, descr.ofs,
+                                              newvalue)
+        elif descr.typeinfo == FLOAT:
+            return do_setinteriorfield_gc_float(array, index, descr.ofs,
+                                                newvalue)
+        else:
+            raise NotImplementedError
+
     def op_setfield_gc(self, fielddescr, struct, newvalue):
         if fielddescr.typeinfo == REF:
             do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
@@ -1354,6 +1385,22 @@
 def do_getfield_gc_ptr(struct, fieldnum):
     return cast_to_ptr(_getfield_gc(struct, fieldnum))
 
+def _getinteriorfield_gc(struct, fieldnum):
+    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
+    return getattr(struct, fieldname)
+
+def do_getinteriorfield_gc_int(array, index, fieldnum):
+    struct = array._obj.container.getitem(index)
+    return cast_to_int(_getinteriorfield_gc(struct, fieldnum))
+
+def do_getinteriorfield_gc_float(array, index, fieldnum):
+    struct = array._obj.container.getitem(index)
+    return cast_to_floatstorage(_getinteriorfield_gc(struct, fieldnum))
+
+def do_getinteriorfield_gc_ptr(array, index, fieldnum):
+    struct = array._obj.container.getitem(index)
+    return cast_to_ptr(_getinteriorfield_gc(struct, fieldnum))
+
 def _getfield_raw(struct, fieldnum):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1409,26 +1456,28 @@
     newvalue = cast_from_ptr(ITEMTYPE, newvalue)
     array.setitem(index, newvalue)
 
-def do_setfield_gc_int(struct, fieldnum, newvalue):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
-    FIELDTYPE = getattr(STRUCT, fieldname)
-    newvalue = cast_from_int(FIELDTYPE, newvalue)
-    setattr(ptr, fieldname, newvalue)
+def new_setfield_gc(cast_func):
+    def do_setfield_gc(struct, fieldnum, newvalue):
+        STRUCT, fieldname = symbolic.TokenToField[fieldnum]
+        ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
+        FIELDTYPE = getattr(STRUCT, fieldname)
+        newvalue = cast_func(FIELDTYPE, newvalue)
+        setattr(ptr, fieldname, newvalue)
+    return do_setfield_gc
+do_setfield_gc_int = new_setfield_gc(cast_from_int)
+do_setfield_gc_float = new_setfield_gc(cast_from_floatstorage)
+do_setfield_gc_ptr = new_setfield_gc(cast_from_ptr)
 
-def do_setfield_gc_float(struct, fieldnum, newvalue):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
-    FIELDTYPE = getattr(STRUCT, fieldname)
-    newvalue = cast_from_floatstorage(FIELDTYPE, newvalue)
-    setattr(ptr, fieldname, newvalue)
-
-def do_setfield_gc_ptr(struct, fieldnum, newvalue):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
-    FIELDTYPE = getattr(STRUCT, fieldname)
-    newvalue = cast_from_ptr(FIELDTYPE, newvalue)
-    setattr(ptr, fieldname, newvalue)
+def new_setinteriorfield_gc(cast_func):
+    def do_setinteriorfield_gc(array, index, fieldnum, newvalue):
+        STRUCT, fieldname = symbolic.TokenToField[fieldnum]
+        struct = array._obj.container.getitem(index)
+        FIELDTYPE = getattr(STRUCT, fieldname)
+        setattr(struct, fieldname, cast_func(FIELDTYPE, newvalue))
+    return do_setinteriorfield_gc
+do_setinteriorfield_gc_int = new_setinteriorfield_gc(cast_from_int)
+do_setinteriorfield_gc_float = new_setinteriorfield_gc(cast_from_floatstorage)
+do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)        
 
 def do_setfield_raw_int(struct, fieldnum, newvalue):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
@@ -1694,6 +1743,7 @@
 setannotation(compile_start_float_var, annmodel.SomeInteger())
 setannotation(compile_add, annmodel.s_None)
 setannotation(compile_add_descr, annmodel.s_None)
+setannotation(compile_add_descr_arg, annmodel.s_None)
 setannotation(compile_add_var, annmodel.s_None)
 setannotation(compile_add_int_const, annmodel.s_None)
 setannotation(compile_add_ref_const, annmodel.s_None)
@@ -1741,6 +1791,9 @@
 setannotation(do_getfield_raw_int, annmodel.SomeInteger())
 setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF))
 setannotation(do_getfield_raw_float, s_FloatStorage)
+setannotation(do_getinteriorfield_gc_int, annmodel.SomeInteger())
+setannotation(do_getinteriorfield_gc_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_getinteriorfield_gc_float, s_FloatStorage)
 setannotation(do_new, annmodel.SomePtr(llmemory.GCREF))
 setannotation(do_new_array, annmodel.SomePtr(llmemory.GCREF))
 setannotation(do_setarrayitem_gc_int, annmodel.s_None)
@@ -1754,6 +1807,9 @@
 setannotation(do_setfield_raw_int, annmodel.s_None)
 setannotation(do_setfield_raw_ptr, annmodel.s_None)
 setannotation(do_setfield_raw_float, annmodel.s_None)
+setannotation(do_setinteriorfield_gc_int, annmodel.s_None)
+setannotation(do_setinteriorfield_gc_ptr, annmodel.s_None)
+setannotation(do_setinteriorfield_gc_float, annmodel.s_None)
 setannotation(do_newstr, annmodel.SomePtr(llmemory.GCREF))
 setannotation(do_strsetitem, annmodel.s_None)
 setannotation(do_newunicode, annmodel.SomePtr(llmemory.GCREF))
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -2,21 +2,19 @@
 Minimal-API wrapper around the llinterpreter to run operations.
 """
 
-import sys
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.jit.metainterp import history
-from pypy.jit.metainterp.history import REF, INT, FLOAT
+from pypy.jit.metainterp.history import REF, INT, FLOAT, STRUCT
 from pypy.jit.metainterp.warmstate import unwrap
-from pypy.jit.metainterp.resoperation import ResOperation, rop
+from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.backend import model
 from pypy.jit.backend.llgraph import llimpl, symbolic
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.jit.codewriter import heaptracker, longlong
-from pypy.rlib import rgc
 
 class MiniStats:
     pass
@@ -62,6 +60,9 @@
     def is_array_of_floats(self):
         return self.typeinfo == FLOAT
 
+    def is_array_of_structs(self):
+        return self.typeinfo == STRUCT
+
     def as_vtable_size_descr(self):
         return self
 
@@ -177,8 +178,10 @@
             llimpl.compile_add(c, op.getopnum())
             descr = op.getdescr()
             if isinstance(descr, Descr):
-                llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo, descr.arg_types)
-            if isinstance(descr, history.LoopToken) and op.getopnum() != rop.JUMP:
+                llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo,
+                                         descr.arg_types)
+            if (isinstance(descr, history.LoopToken) and
+                op.getopnum() != rop.JUMP):
                 llimpl.compile_add_loop_token(c, descr)
             if self.is_oo and isinstance(descr, (OODescr, MethDescr)):
                 # hack hack, not rpython
@@ -193,6 +196,9 @@
                     llimpl.compile_add_ref_const(c, x.value, self.ts.BASETYPE)
                 elif isinstance(x, history.ConstFloat):
                     llimpl.compile_add_float_const(c, x.value)
+                elif isinstance(x, Descr):
+                    llimpl.compile_add_descr_arg(c, x.ofs, x.typeinfo,
+                                                 x.arg_types)
                 else:
                     raise Exception("'%s' args contain: %r" % (op.getopname(),
                                                                x))
@@ -316,6 +322,13 @@
         token = history.getkind(getattr(S, fieldname))
         return self.getdescr(ofs, token[0], name=fieldname)
 
+    def interiorfielddescrof(self, A, fieldname):
+        S = A.OF
+        ofs2 = symbolic.get_size(A)
+        ofs, size = symbolic.get_field_token(S, fieldname)
+        token = history.getkind(getattr(S, fieldname))
+        return self.getdescr(ofs, token[0], name=fieldname, extrainfo=ofs2)
+
     def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
         arg_types = []
         for ARG in ARGS:
@@ -353,8 +366,13 @@
     def arraydescrof(self, A):
         assert A.OF != lltype.Void
         size = symbolic.get_size(A)
-        token = history.getkind(A.OF)
-        return self.getdescr(size, token[0])
+        if isinstance(A.OF, lltype.Ptr) or isinstance(A.OF, lltype.Primitive):
+            token = history.getkind(A.OF)[0]
+        elif isinstance(A.OF, lltype.Struct):
+            token = 's'
+        else:
+            token = '?'
+        return self.getdescr(size, token)
 
     # ---------- the backend-dependent operations ----------
 
@@ -406,6 +424,29 @@
         assert isinstance(fielddescr, Descr)
         return llimpl.do_getfield_raw_float(struct, fielddescr.ofs)
 
+    def bh_getinteriorfield_gc_i(self, array, index, descr):
+        assert isinstance(descr, Descr)
+        return llimpl.do_getinteriorfield_gc_int(array, index, descr.ofs)
+    def bh_getinteriorfield_gc_r(self, array, index, descr):
+        assert isinstance(descr, Descr)
+        return llimpl.do_getinteriorfield_gc_ptr(array, index, descr.ofs)
+    def bh_getinteriorfield_gc_f(self, array, index, descr):
+        assert isinstance(descr, Descr)
+        return llimpl.do_getinteriorfield_gc_float(array, index, descr.ofs)
+
+    def bh_setinteriorfield_gc_i(self, array, index, descr, value):
+        assert isinstance(descr, Descr)
+        return llimpl.do_setinteriorfield_gc_int(array, index, descr.ofs,
+                                                 value)
+    def bh_setinteriorfield_gc_r(self, array, index, descr, value):
+        assert isinstance(descr, Descr)
+        return llimpl.do_setinteriorfield_gc_ptr(array, index, descr.ofs,
+                                                 value)
+    def bh_setinteriorfield_gc_f(self, array, index, descr, value):
+        assert isinstance(descr, Descr)
+        return llimpl.do_setinteriorfield_gc_float(array, index, descr.ofs,
+                                                   value)
+
     def bh_new(self, sizedescr):
         assert isinstance(sizedescr, Descr)
         return llimpl.do_new(sizedescr.ofs)
@@ -418,7 +459,6 @@
 
     def bh_classof(self, struct):
         struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
-        result = struct.typeptr
         result_adr = llmemory.cast_ptr_to_adr(struct.typeptr)
         return heaptracker.adr2int(result_adr)
 
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -1,13 +1,10 @@
 import py
-from pypy.rpython.lltypesystem import lltype, rffi, llmemory, rclass
+from pypy.rpython.lltypesystem import lltype, rffi, llmemory
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.jit.backend.llsupport import symbolic, support
-from pypy.jit.metainterp.history import AbstractDescr, getkind, BoxInt, BoxPtr
-from pypy.jit.metainterp.history import BasicFailDescr, LoopToken, BoxFloat
+from pypy.jit.metainterp.history import AbstractDescr, getkind
 from pypy.jit.metainterp import history
-from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.codewriter import heaptracker, longlong
-from pypy.rlib.rarithmetic import r_longlong, r_ulonglong
 
 # The point of the class organization in this file is to make instances
 # as compact as possible.  This is done by not storing the field size or
@@ -23,6 +20,7 @@
         self._cache_field = {}
         self._cache_array = {}
         self._cache_call = {}
+        self._cache_interiorfield = {}
 
     def init_size_descr(self, STRUCT, sizedescr):
         assert isinstance(STRUCT, lltype.GcStruct)
@@ -142,7 +140,6 @@
         cachedict[fieldname] = fielddescr
         return fielddescr
 
-
 # ____________________________________________________________
 # ArrayDescrs
 
@@ -167,6 +164,7 @@
 
     _is_array_of_pointers = False      # unless overridden by GcPtrArrayDescr
     _is_array_of_floats   = False      # unless overridden by FloatArrayDescr
+    _is_array_of_structs  = False      # unless overridden by StructArrayDescr
     _is_item_signed       = False      # unless overridden by XxxArrayDescr
 
     def is_array_of_pointers(self):
@@ -175,6 +173,9 @@
     def is_array_of_floats(self):
         return self._is_array_of_floats
 
+    def is_array_of_structs(self):
+        return self._is_array_of_structs
+
     def is_item_signed(self):
         return self._is_item_signed
 
@@ -199,6 +200,10 @@
     def get_item_size(self, translate_support_code):
         return symbolic.get_size(lltype.Float, translate_support_code)
 
+class StructArrayDescr(BaseArrayDescr):
+    _clsname = 'StructArrayDescr'
+    _is_array_of_structs = True
+
 class BaseArrayNoLengthDescr(BaseArrayDescr):
     def get_base_size(self, translate_support_code):
         return 0
@@ -218,6 +223,13 @@
 def getArrayDescrClass(ARRAY):
     if ARRAY.OF is lltype.Float:
         return FloatArrayDescr
+    elif isinstance(ARRAY.OF, lltype.Struct):
+        class Descr(StructArrayDescr):
+            _clsname = '%sArrayDescr' % ARRAY.OF._name
+            def get_item_size(self, translate_support_code):
+                return symbolic.get_size(ARRAY.OF, translate_support_code)
+        Descr.__name__ = Descr._clsname
+        return Descr
     return getDescrClass(ARRAY.OF, BaseArrayDescr, GcPtrArrayDescr,
                          NonGcPtrArrayDescr, 'Array', 'get_item_size',
                          '_is_array_of_floats', '_is_item_signed')
@@ -252,6 +264,36 @@
         cache[ARRAY] = arraydescr
         return arraydescr
 
+# ____________________________________________________________
+# InteriorFieldDescr
+
+class InteriorFieldDescr(AbstractDescr):
+    arraydescr = BaseArrayDescr()     # workaround for the annotator
+    fielddescr = BaseFieldDescr('', 0)
+
+    def __init__(self, arraydescr, fielddescr):
+        self.arraydescr = arraydescr
+        self.fielddescr = fielddescr
+
+    def is_pointer_field(self):
+        return self.fielddescr.is_pointer_field()
+
+    def is_float_field(self):
+        return self.fielddescr.is_float_field()
+
+    def repr_of_descr(self):
+        return '<InteriorFieldDescr %s>' % self.fielddescr.repr_of_descr()
+
+def get_interiorfield_descr(gc_ll_descr, ARRAY, FIELDTP, name):
+    cache = gc_ll_descr._cache_interiorfield
+    try:
+        return cache[(ARRAY, FIELDTP, name)]
+    except KeyError:
+        arraydescr = get_array_descr(gc_ll_descr, ARRAY)
+        fielddescr = get_field_descr(gc_ll_descr, FIELDTP, name)
+        descr = InteriorFieldDescr(arraydescr, fielddescr)
+        cache[(ARRAY, FIELDTP, name)] = descr
+        return descr
 
 # ____________________________________________________________
 # CallDescrs
@@ -525,7 +567,8 @@
         #
         if TYPE is lltype.Float or is_longlong(TYPE):
             setattr(Descr, floatattrname, True)
-        elif TYPE is not lltype.Bool and rffi.cast(TYPE, -1) == -1:
+        elif (TYPE is not lltype.Bool and isinstance(TYPE, lltype.Number) and
+              rffi.cast(TYPE, -1) == -1):
             setattr(Descr, signedattrname, True)
         #
         _cache[nameprefix, TYPE] = Descr
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -45,6 +45,14 @@
     def freeing_block(self, start, stop):
         pass
 
+    def get_funcptr_for_newarray(self):
+        return llhelper(self.GC_MALLOC_ARRAY, self.malloc_array)
+    def get_funcptr_for_newstr(self):
+        return llhelper(self.GC_MALLOC_STR_UNICODE, self.malloc_str)
+    def get_funcptr_for_newunicode(self):
+        return llhelper(self.GC_MALLOC_STR_UNICODE, self.malloc_unicode)
+
+
     def record_constptrs(self, op, gcrefs_output_list):
         for i in range(op.numargs()):
             v = op.getarg(i)
@@ -96,6 +104,39 @@
         malloc_fn_ptr = self.configure_boehm_once()
         self.funcptr_for_new = malloc_fn_ptr
 
+        def malloc_array(basesize, itemsize, ofs_length, num_elem):
+            try:
+                size = ovfcheck(basesize + ovfcheck(itemsize * num_elem))
+            except OverflowError:
+                return lltype.nullptr(llmemory.GCREF.TO)
+            res = self.funcptr_for_new(size)
+            if not res:
+                return res
+            rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem
+            return res
+        self.malloc_array = malloc_array
+        self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType(
+            [lltype.Signed] * 4, llmemory.GCREF))
+
+
+        (str_basesize, str_itemsize, str_ofs_length
+         ) = symbolic.get_array_token(rstr.STR, self.translate_support_code)
+        (unicode_basesize, unicode_itemsize, unicode_ofs_length
+         ) = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code)
+        def malloc_str(length):
+            return self.malloc_array(
+                str_basesize, str_itemsize, str_ofs_length, length
+            )
+        def malloc_unicode(length):
+            return self.malloc_array(
+                unicode_basesize, unicode_itemsize, unicode_ofs_length, length
+            )
+        self.malloc_str = malloc_str
+        self.malloc_unicode = malloc_unicode
+        self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType(
+            [lltype.Signed], llmemory.GCREF))
+
+
         # on some platform GC_init is required before any other
         # GC_* functions, call it here for the benefit of tests
         # XXX move this to tests
@@ -116,39 +157,27 @@
         ofs_length = arraydescr.get_ofs_length(self.translate_support_code)
         basesize = arraydescr.get_base_size(self.translate_support_code)
         itemsize = arraydescr.get_item_size(self.translate_support_code)
-        size = basesize + itemsize * num_elem
-        res = self.funcptr_for_new(size)
-        rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem
-        return res
+        return self.malloc_array(basesize, itemsize, ofs_length, num_elem)
 
     def gc_malloc_str(self, num_elem):
-        basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
-                                                   self.translate_support_code)
-        assert itemsize == 1
-        size = basesize + num_elem
-        res = self.funcptr_for_new(size)
-        rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem
-        return res
+        return self.malloc_str(num_elem)
 
     def gc_malloc_unicode(self, num_elem):
-        basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
-                                                   self.translate_support_code)
-        size = basesize + num_elem * itemsize
-        res = self.funcptr_for_new(size)
-        rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem
-        return res
+        return self.malloc_unicode(num_elem)
 
     def args_for_new(self, sizedescr):
         assert isinstance(sizedescr, BaseSizeDescr)
         return [sizedescr.size]
 
+    def args_for_new_array(self, arraydescr):
+        ofs_length = arraydescr.get_ofs_length(self.translate_support_code)
+        basesize = arraydescr.get_base_size(self.translate_support_code)
+        itemsize = arraydescr.get_item_size(self.translate_support_code)
+        return [basesize, itemsize, ofs_length]
+
     def get_funcptr_for_new(self):
         return self.funcptr_for_new
 
-    get_funcptr_for_newarray = None
-    get_funcptr_for_newstr = None
-    get_funcptr_for_newunicode = None
-
     def rewrite_assembler(self, cpu, operations, gcrefs_output_list):
         # record all GCREFs too, because Boehm cannot see them and keep them
         # alive if they end up as constants in the assembler
@@ -752,15 +781,6 @@
     def get_funcptr_for_new(self):
         return llhelper(self.GC_MALLOC_BASIC, self.malloc_basic)
 
-    def get_funcptr_for_newarray(self):
-        return llhelper(self.GC_MALLOC_ARRAY, self.malloc_array)
-
-    def get_funcptr_for_newstr(self):
-        return llhelper(self.GC_MALLOC_STR_UNICODE, self.malloc_str)
-
-    def get_funcptr_for_newunicode(self):
-        return llhelper(self.GC_MALLOC_STR_UNICODE, self.malloc_unicode)
-
     def do_write_barrier(self, gcref_struct, gcref_newptr):
         hdr_addr = llmemory.cast_ptr_to_adr(gcref_struct)
         hdr_addr -= self.gcheaderbuilder.size_gc_header
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -1,24 +1,18 @@
-import sys
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rpython.llinterp import LLInterpreter, LLException
+from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.objectmodel import we_are_translated, specialize
-from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values,\
-     BoxFloat
 from pypy.jit.metainterp import history
 from pypy.jit.codewriter import heaptracker, longlong
 from pypy.jit.backend.model import AbstractCPU
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
-from pypy.jit.backend.llsupport.descr import get_size_descr,  BaseSizeDescr
-from pypy.jit.backend.llsupport.descr import get_field_descr, BaseFieldDescr
-from pypy.jit.backend.llsupport.descr import get_array_descr, BaseArrayDescr
-from pypy.jit.backend.llsupport.descr import get_call_descr
-from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr
-from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr
+from pypy.jit.backend.llsupport.descr import (get_size_descr,
+     get_field_descr, BaseFieldDescr, get_array_descr, BaseArrayDescr,
+     get_call_descr, BaseIntCallDescr, GcPtrCallDescr, FloatCallDescr,
+     VoidCallDescr, InteriorFieldDescr, get_interiorfield_descr)
 from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
-from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
 
 
 class AbstractLLCPU(AbstractCPU):
@@ -241,6 +235,9 @@
     def arraydescrof(self, A):
         return get_array_descr(self.gc_ll_descr, A)
 
+    def interiorfielddescrof(self, A, fieldname):
+        return get_interiorfield_descr(self.gc_ll_descr, A, A.OF, fieldname)
+
     def unpack_arraydescr(self, arraydescr):
         assert isinstance(arraydescr, BaseArrayDescr)
         return arraydescr.get_base_size(self.translate_support_code)
@@ -358,6 +355,100 @@
     bh_getarrayitem_raw_i = bh_getarrayitem_gc_i
     bh_getarrayitem_raw_f = bh_getarrayitem_gc_f
 
+    def bh_getinteriorfield_gc_i(self, gcref, itemindex, descr):
+        assert isinstance(descr, InteriorFieldDescr)
+        arraydescr = descr.arraydescr
+        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs += descr.fielddescr.offset
+        fieldsize = descr.fielddescr.get_field_size(self.translate_support_code)
+        sign = descr.fielddescr.is_field_signed()
+        fullofs = itemindex * size + ofs
+        # --- start of GC unsafe code (no GC operation!) ---
+        items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), fullofs)
+        for STYPE, UTYPE, itemsize in unroll_basic_sizes:
+            if fieldsize == itemsize:
+                if sign:
+                    item = rffi.cast(rffi.CArrayPtr(STYPE), items)
+                    val = item[0]
+                    val = rffi.cast(lltype.Signed, val)
+                else:
+                    item = rffi.cast(rffi.CArrayPtr(UTYPE), items)
+                    val = item[0]
+                    val = rffi.cast(lltype.Signed, val)
+                # --- end of GC unsafe code ---
+                return val
+        else:
+            raise NotImplementedError("size = %d" % fieldsize)
+
+    def bh_getinteriorfield_gc_r(self, gcref, itemindex, descr):
+        assert isinstance(descr, InteriorFieldDescr)
+        arraydescr = descr.arraydescr
+        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs += descr.fielddescr.offset
+        # --- start of GC unsafe code (no GC operation!) ---
+        items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs +
+                            size * itemindex)
+        items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items)
+        pval = self._cast_int_to_gcref(items[0])
+        # --- end of GC unsafe code ---
+        return pval
+
+    def bh_getinteriorfield_gc_f(self, gcref, itemindex, descr):
+        assert isinstance(descr, InteriorFieldDescr)
+        arraydescr = descr.arraydescr
+        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs += descr.fielddescr.offset
+        # --- start of GC unsafe code (no GC operation!) ---
+        items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs +
+                            size * itemindex)
+        items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
+        fval = items[0]
+        # --- end of GC unsafe code ---
+        return fval
+
+    def bh_setinteriorfield_gc_i(self, gcref, itemindex, descr, value):
+        assert isinstance(descr, InteriorFieldDescr)
+        arraydescr = descr.arraydescr
+        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs += descr.fielddescr.offset
+        fieldsize = descr.fielddescr.get_field_size(self.translate_support_code)
+        ofs = itemindex * size + ofs
+        # --- start of GC unsafe code (no GC operation!) ---
+        items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
+        for TYPE, _, itemsize in unroll_basic_sizes:
+            if fieldsize == itemsize:
+                items = rffi.cast(rffi.CArrayPtr(TYPE), items)
+                items[0] = rffi.cast(TYPE, value)
+                # --- end of GC unsafe code ---
+                return
+        else:
+            raise NotImplementedError("size = %d" % fieldsize)
+
+    def bh_setinteriorfield_gc_r(self, gcref, itemindex, descr, newvalue):
+        assert isinstance(descr, InteriorFieldDescr)
+        arraydescr = descr.arraydescr
+        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs += descr.fielddescr.offset
+        self.gc_ll_descr.do_write_barrier(gcref, newvalue)
+        # --- start of GC unsafe code (no GC operation!) ---
+        items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref),
+                            ofs + size * itemindex)
+        items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items)
+        items[0] = self.cast_gcref_to_int(newvalue)
+        # --- end of GC unsafe code ---
+
+    def bh_setinteriorfield_gc_f(self, gcref, itemindex, descr, newvalue):
+        assert isinstance(descr, InteriorFieldDescr)
+        arraydescr = descr.arraydescr
+        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs += descr.fielddescr.offset
+        # --- start of GC unsafe code (no GC operation!) ---
+        items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref),
+                            ofs + size * itemindex)
+        items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
+        items[0] = newvalue
+        # --- end of GC unsafe code ---
+
     def bh_strlen(self, string):
         s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
         return len(s.chars)
@@ -475,7 +566,6 @@
 
     def bh_classof(self, struct):
         struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
-        result = struct.typeptr
         result_adr = llmemory.cast_ptr_to_adr(struct.typeptr)
         return heaptracker.adr2int(result_adr)
 
diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -287,7 +287,6 @@
         self.reg_bindings[to_v] = reg
 
     def _move_variable_away(self, v, prev_loc):
-        reg = None
         if self.free_regs:
             loc = self.free_regs.pop()
             self.reg_bindings[v] = loc
diff --git a/pypy/jit/backend/llsupport/test/test_asmmemmgr.py b/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
--- a/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
+++ b/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
@@ -211,14 +211,14 @@
     debug._log = debug.DebugLog()
     try:
         mc._dump(addr, 'test-logname-section')
-        log = list(debug._log)
+        log = list(debug._log) 
     finally:
         debug._log = None
     encoded = ''.join(writtencode).encode('hex').upper()
     ataddr = '@%x' % addr
     assert log == [('test-logname-section',
                     [('debug_print', 'CODE_DUMP', ataddr, '+0 ', encoded)])]
-    #
+    
     lltype.free(p, flavor='raw')
 
 def test_blockbuildermixin2():
diff --git a/pypy/jit/backend/llsupport/test/test_descr.py b/pypy/jit/backend/llsupport/test/test_descr.py
--- a/pypy/jit/backend/llsupport/test/test_descr.py
+++ b/pypy/jit/backend/llsupport/test/test_descr.py
@@ -3,7 +3,6 @@
 from pypy.jit.backend.llsupport import symbolic
 from pypy.rlib.objectmodel import Symbolic
 from pypy.rpython.annlowlevel import llhelper
-from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr
 from pypy.jit.metainterp import history
 from pypy.jit.codewriter import longlong
 import sys, struct, py
@@ -149,7 +148,9 @@
     A2 = lltype.GcArray(lltype.Ptr(T))
     A3 = lltype.GcArray(lltype.Ptr(U))
     A4 = lltype.GcArray(lltype.Float)
-    A5 = lltype.GcArray(lltype.SingleFloat)
+    A5 = lltype.GcArray(lltype.Struct('x', ('v', lltype.Signed),
+                                      ('k', lltype.Signed)))
+    A6 = lltype.GcArray(lltype.SingleFloat)
     assert getArrayDescrClass(A2) is GcPtrArrayDescr
     assert getArrayDescrClass(A3) is NonGcPtrArrayDescr
     cls = getArrayDescrClass(A1)
@@ -158,7 +159,7 @@
     clsf = getArrayDescrClass(A4)
     assert clsf != cls
     assert clsf == getArrayDescrClass(lltype.GcArray(lltype.Float))
-    clss = getArrayDescrClass(A5)
+    clss = getArrayDescrClass(A6)
     assert clss not in (clsf, cls)
     assert clss == getArrayDescrClass(lltype.GcArray(rffi.UINT))
     #
@@ -168,11 +169,12 @@
     descr3 = get_array_descr(c0, A3)
     descr4 = get_array_descr(c0, A4)
     descr5 = get_array_descr(c0, A5)
+    descr6 = get_array_descr(c0, A6)
     assert descr1.__class__ is cls
     assert descr2.__class__ is GcPtrArrayDescr
     assert descr3.__class__ is NonGcPtrArrayDescr
     assert descr4.__class__ is clsf
-    assert descr5.__class__ is clss
+    assert descr6.__class__ is clss
     assert descr1 == get_array_descr(c0, lltype.GcArray(lltype.Char))
     assert not descr1.is_array_of_pointers()
     assert     descr2.is_array_of_pointers()
@@ -202,7 +204,8 @@
     assert descr2.get_item_size(False) == rffi.sizeof(lltype.Ptr(T))
     assert descr3.get_item_size(False) == rffi.sizeof(lltype.Ptr(U))
     assert descr4.get_item_size(False) == rffi.sizeof(lltype.Float)
-    assert descr5.get_item_size(False) == rffi.sizeof(lltype.SingleFloat)
+    assert descr5.get_item_size(False) == rffi.sizeof(lltype.Signed) * 2
+    assert descr6.get_item_size(False) == rffi.sizeof(lltype.SingleFloat)
     #
     assert isinstance(descr1.get_base_size(True), Symbolic)
     assert isinstance(descr2.get_base_size(True), Symbolic)
@@ -348,7 +351,6 @@
                             (rffi.SHORT,      True), (rffi.USHORT, False),
                             (rffi.INT,        True), (rffi.UINT,   False),
                             (rffi.LONG,       True), (rffi.ULONG,  False)]:
-        A = lltype.GcArray(RESTYPE)
         for tsc in [False, True]:
             c2 = GcCache(tsc)
             descr1 = get_call_descr(c2, [], RESTYPE)
@@ -379,7 +381,6 @@
     descr3i = get_array_descr(c0, lltype.GcArray(lltype.Char))
     assert descr3i.repr_of_descr() == '<CharArrayDescr>'
     #
-    cache = {}
     descr4 = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Ptr(S))
     assert 'GcPtrCallDescr' in descr4.repr_of_descr()
     #
@@ -412,10 +413,10 @@
     ARGS = [lltype.Float, lltype.Ptr(ARRAY)]
     RES = lltype.Float
 
-    def f(a, b):
+    def f2(a, b):
         return float(b[0]) + a
 
-    fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f)
+    fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f2)
     descr2 = get_call_descr(c0, ARGS, RES)
     a = lltype.malloc(ARRAY, 3)
     opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a)
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -1,5 +1,5 @@
 from pypy.rlib.debug import debug_start, debug_print, debug_stop
-from pypy.jit.metainterp import history, compile
+from pypy.jit.metainterp import history
 
 
 class AbstractCPU(object):
@@ -213,6 +213,10 @@
     def typedescrof(TYPE):
         raise NotImplementedError
 
+    @staticmethod
+    def interiorfielddescrof(A, fieldname):
+        raise NotImplementedError
+
     # ---------- the backend-dependent operations ----------
 
     # lltype specific operations
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -5,7 +5,7 @@
                                          BoxInt, Box, BoxPtr,
                                          LoopToken,
                                          ConstInt, ConstPtr,
-                                         BoxObj, Const,
+                                         BoxObj,
                                          ConstObj, BoxFloat, ConstFloat)
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.typesystem import deref
@@ -111,7 +111,7 @@
         self.cpu.set_future_value_int(0, 2)
         fail = self.cpu.execute_token(looptoken)
         res = self.cpu.get_latest_value_int(0)
-        assert res == 3        
+        assert res == 3
         assert fail.identifier == 1
 
     def test_compile_loop(self):
@@ -127,7 +127,7 @@
             ]
         inputargs = [i0]
         operations[2].setfailargs([i1])
-        
+
         self.cpu.compile_loop(inputargs, operations, looptoken)
         self.cpu.set_future_value_int(0, 2)
         fail = self.cpu.execute_token(looptoken)
@@ -148,7 +148,7 @@
             ]
         inputargs = [i0]
         operations[2].setfailargs([None, None, i1, None])
-        
+
         self.cpu.compile_loop(inputargs, operations, looptoken)
         self.cpu.set_future_value_int(0, 2)
         fail = self.cpu.execute_token(looptoken)
@@ -372,7 +372,7 @@
         for opnum, boxargs, retvalue in get_int_tests():
             res = self.execute_operation(opnum, boxargs, 'int')
             assert res.value == retvalue
-        
+
     def test_float_operations(self):
         from pypy.jit.metainterp.test.test_executor import get_float_tests
         for opnum, boxargs, rettype, retvalue in get_float_tests(self.cpu):
@@ -438,7 +438,7 @@
 
     def test_ovf_operations_reversed(self):
         self.test_ovf_operations(reversed=True)
-        
+
     def test_bh_call(self):
         cpu = self.cpu
         #
@@ -503,7 +503,7 @@
                                          [funcbox, BoxInt(num), BoxInt(num)],
                                          'int', descr=dyn_calldescr)
             assert res.value == 2 * num
-            
+
 
         if cpu.supports_floats:
             def func(f0, f1, f2, f3, f4, f5, f6, i0, i1, f7, f8, f9):
@@ -543,7 +543,7 @@
         funcbox = self.get_funcbox(self.cpu, func_ptr)
         res = self.execute_operation(rop.CALL, [funcbox] + map(BoxInt, args), 'int', descr=calldescr)
         assert res.value == func(*args)
-        
+
     def test_call_stack_alignment(self):
         # test stack alignment issues, notably for Mac OS/X.
         # also test the ordering of the arguments.
@@ -615,7 +615,7 @@
         res = self.execute_operation(rop.GETFIELD_GC, [t_box],
                                      'int', descr=shortdescr)
         assert res.value == 1331
-        
+
         #
         u_box, U_box = self.alloc_instance(self.U)
         fielddescr2 = self.cpu.fielddescrof(self.S, 'next')
@@ -695,7 +695,7 @@
 
     def test_failing_guard_class(self):
         t_box, T_box = self.alloc_instance(self.T)
-        u_box, U_box = self.alloc_instance(self.U)        
+        u_box, U_box = self.alloc_instance(self.U)
         null_box = self.null_instance()
         for opname, args in [(rop.GUARD_CLASS, [t_box, U_box]),
                              (rop.GUARD_CLASS, [u_box, T_box]),
@@ -787,7 +787,7 @@
         r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(3)],
                                    'int', descr=arraydescr)
         assert r.value == 160
-        
+
         #
         if isinstance(A, lltype.GcArray):
             A = lltype.Ptr(A)
@@ -880,6 +880,73 @@
                                    'int', descr=arraydescr)
         assert r.value == 7441
 
+    def test_array_of_structs(self):
+        TP = lltype.GcStruct('x')
+        ITEM = lltype.Struct('x',
+                             ('vs', lltype.Signed),
+                             ('vu', lltype.Unsigned),
+                             ('vsc', rffi.SIGNEDCHAR),
+                             ('vuc', rffi.UCHAR),
+                             ('vss', rffi.SHORT),
+                             ('vus', rffi.USHORT),
+                             ('vsi', rffi.INT),
+                             ('vui', rffi.UINT),
+                             ('k', lltype.Float),
+                             ('p', lltype.Ptr(TP)))
+        a_box, A = self.alloc_array_of(ITEM, 15)
+        s_box, S = self.alloc_instance(TP)
+        kdescr = self.cpu.interiorfielddescrof(A, 'k')
+        pdescr = self.cpu.interiorfielddescrof(A, 'p')
+        self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(3),
+                                                         boxfloat(1.5)],
+                               'void', descr=kdescr)
+        f = self.cpu.bh_getinteriorfield_gc_f(a_box.getref_base(), 3, kdescr)
+        assert longlong.getrealfloat(f) == 1.5
+        self.cpu.bh_setinteriorfield_gc_f(a_box.getref_base(), 3, kdescr, longlong.getfloatstorage(2.5))
+        r = self.execute_operation(rop.GETINTERIORFIELD_GC, [a_box, BoxInt(3)],
+                                   'float', descr=kdescr)
+        assert r.getfloat() == 2.5
+        #
+        NUMBER_FIELDS = [('vs', lltype.Signed),
+                         ('vu', lltype.Unsigned),
+                         ('vsc', rffi.SIGNEDCHAR),
+                         ('vuc', rffi.UCHAR),
+                         ('vss', rffi.SHORT),
+                         ('vus', rffi.USHORT),
+                         ('vsi', rffi.INT),
+                         ('vui', rffi.UINT)]
+        for name, TYPE in NUMBER_FIELDS[::-1]:
+            vdescr = self.cpu.interiorfielddescrof(A, name)
+            self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(3),
+                                                             BoxInt(-15)],
+                                   'void', descr=vdescr)
+        for name, TYPE in NUMBER_FIELDS:
+            vdescr = self.cpu.interiorfielddescrof(A, name)
+            i = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 3,
+                                                  vdescr)
+            assert i == rffi.cast(lltype.Signed, rffi.cast(TYPE, -15))
+        for name, TYPE in NUMBER_FIELDS[::-1]:
+            vdescr = self.cpu.interiorfielddescrof(A, name)
+            self.cpu.bh_setinteriorfield_gc_i(a_box.getref_base(), 3,
+                                              vdescr, -25)
+        for name, TYPE in NUMBER_FIELDS:
+            vdescr = self.cpu.interiorfielddescrof(A, name)
+            r = self.execute_operation(rop.GETINTERIORFIELD_GC,
+                                       [a_box, BoxInt(3)],
+                                       'int', descr=vdescr)
+            assert r.getint() == rffi.cast(lltype.Signed, rffi.cast(TYPE, -25))
+        #
+        self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(4),
+                                                         s_box],
+                               'void', descr=pdescr)
+        r = self.cpu.bh_getinteriorfield_gc_r(a_box.getref_base(), 4, pdescr)
+        assert r == s_box.getref_base()
+        self.cpu.bh_setinteriorfield_gc_r(a_box.getref_base(), 3, pdescr,
+                                          s_box.getref_base())
+        r = self.execute_operation(rop.GETINTERIORFIELD_GC, [a_box, BoxInt(3)],
+                                   'ref', descr=pdescr)
+        assert r.getref_base() == s_box.getref_base()
+
     def test_string_basic(self):
         s_box = self.alloc_string("hello\xfe")
         r = self.execute_operation(rop.STRLEN, [s_box], 'int')
@@ -1402,7 +1469,7 @@
         addr = llmemory.cast_ptr_to_adr(func_ptr)
         return ConstInt(heaptracker.adr2int(addr))
 
-    
+
     MY_VTABLE = rclass.OBJECT_VTABLE    # for tests only
 
     S = lltype.GcForwardReference()
@@ -1439,7 +1506,6 @@
         return BoxPtr(lltype.nullptr(llmemory.GCREF.TO))
 
     def alloc_array_of(self, ITEM, length):
-        cpu = self.cpu
         A = lltype.GcArray(ITEM)
         a = lltype.malloc(A, length)
         a_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a))
@@ -2318,7 +2384,7 @@
         for opname, arg, res in ops:
             self.execute_operation(opname, [arg], 'void')
             assert self.guard_failed == res
-        
+
         lltype.free(x, flavor='raw')
 
     def test_assembler_call(self):
@@ -2398,7 +2464,7 @@
         FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
             lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES,
             EffectInfo.MOST_GENERAL)
-        
+
         ops = '''
         [f0, f1]
         f2 = float_add(f0, f1)
@@ -2489,7 +2555,7 @@
         FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
             lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES,
             EffectInfo.MOST_GENERAL)
-        
+
         ops = '''
         [f0, f1]
         f2 = float_add(f0, f1)
@@ -2940,4 +3006,4 @@
 
     def alloc_unicode(self, unicode):
         py.test.skip("implement me")
-    
+
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1,7 +1,7 @@
 import sys, os
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
-from pypy.jit.metainterp.history import Const, Box, BoxInt, BoxPtr, BoxFloat
+from pypy.jit.metainterp.history import Const, Box, BoxInt, ConstInt
 from pypy.jit.metainterp.history import (AbstractFailDescr, INT, REF, FLOAT,
                                          LoopToken)
 from pypy.rpython.lltypesystem import lltype, rffi, rstr, llmemory
@@ -36,7 +36,6 @@
 from pypy.rlib import rgc
 from pypy.rlib.clibffi import FFI_DEFAULT_ABI
 from pypy.jit.backend.x86.jump import remap_frame_layout
-from pypy.jit.metainterp.history import ConstInt, BoxInt
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.codewriter import longlong
 
@@ -729,8 +728,8 @@
         # Also, make sure this is consistent with FRAME_FIXED_SIZE.
         self.mc.PUSH_r(ebp.value)
         self.mc.MOV_rr(ebp.value, esp.value)
-        for regloc in self.cpu.CALLEE_SAVE_REGISTERS:
-            self.mc.PUSH_r(regloc.value)
+        for loc in self.cpu.CALLEE_SAVE_REGISTERS:
+            self.mc.PUSH_r(loc.value)
 
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap and gcrootmap.is_shadow_stack:
@@ -994,7 +993,7 @@
         effectinfo = op.getdescr().get_extra_info()
         oopspecindex = effectinfo.oopspecindex
         genop_llong_list[oopspecindex](self, op, arglocs, resloc)
-        
+
     def regalloc_perform_math(self, op, arglocs, resloc):
         effectinfo = op.getdescr().get_extra_info()
         oopspecindex = effectinfo.oopspecindex
@@ -1311,7 +1310,7 @@
     genop_guard_float_eq = _cmpop_guard_float("E", "E", "NE","NE")
     genop_guard_float_gt = _cmpop_guard_float("A", "B", "BE","AE")
     genop_guard_float_ge = _cmpop_guard_float("AE","BE", "B", "A")
-    
+
     def genop_math_sqrt(self, op, arglocs, resloc):
         self.mc.SQRTSD(arglocs[0], resloc)
 
@@ -1597,12 +1596,27 @@
     genop_getarrayitem_gc_pure = genop_getarrayitem_gc
     genop_getarrayitem_raw = genop_getarrayitem_gc
 
+    def genop_getinteriorfield_gc(self, op, arglocs, resloc):
+        base_loc, ofs_loc, itemsize_loc, fieldsize_loc, index_loc, sign_loc = arglocs
+        # XXX should not use IMUL in most cases
+        self.mc.IMUL(index_loc, itemsize_loc)
+        src_addr = AddressLoc(base_loc, index_loc, 0, ofs_loc.value)
+        self.load_from_mem(resloc, src_addr, fieldsize_loc, sign_loc)
+
+
     def genop_discard_setfield_gc(self, op, arglocs):
         base_loc, ofs_loc, size_loc, value_loc = arglocs
         assert isinstance(size_loc, ImmedLoc)
         dest_addr = AddressLoc(base_loc, ofs_loc)
         self.save_into_mem(dest_addr, value_loc, size_loc)
 
+    def genop_discard_setinteriorfield_gc(self, op, arglocs):
+        base_loc, ofs_loc, itemsize_loc, fieldsize_loc, index_loc, value_loc = arglocs
+        # XXX should not use IMUL in most cases
+        self.mc.IMUL(index_loc, itemsize_loc)
+        dest_addr = AddressLoc(base_loc, index_loc, 0, ofs_loc.value)
+        self.save_into_mem(dest_addr, value_loc, fieldsize_loc)
+
     def genop_discard_setarrayitem_gc(self, op, arglocs):
         base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs
         assert isinstance(baseofs, ImmedLoc)
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -7,7 +7,7 @@
                                          ResOperation, BoxPtr, ConstFloat,
                                          BoxFloat, LoopToken, INT, REF, FLOAT)
 from pypy.jit.backend.x86.regloc import *
-from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr
+from pypy.rpython.lltypesystem import lltype, rffi, rstr
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib import rgc
 from pypy.jit.backend.llsupport import symbolic
@@ -17,11 +17,12 @@
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.backend.llsupport.descr import BaseFieldDescr, BaseArrayDescr
 from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr
+from pypy.jit.backend.llsupport.descr import InteriorFieldDescr
 from pypy.jit.backend.llsupport.regalloc import FrameManager, RegisterManager,\
      TempBox
 from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE
 from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64, MY_COPY_OF_REGS
-from pypy.rlib.rarithmetic import r_longlong, r_uint
+from pypy.rlib.rarithmetic import r_longlong
 
 class X86RegisterManager(RegisterManager):
 
@@ -433,7 +434,7 @@
             if self.can_merge_with_next_guard(op, i, operations):
                 oplist_with_guard[op.getopnum()](self, op, operations[i + 1])
                 i += 1
-            elif not we_are_translated() and op.getopnum() == -124: 
+            elif not we_are_translated() and op.getopnum() == -124:
                 self._consider_force_spill(op)
             else:
                 oplist[op.getopnum()](self, op)
@@ -815,7 +816,7 @@
         save_all_regs = guard_not_forced_op is not None
         self.xrm.before_call(force_store, save_all_regs=save_all_regs)
         if not save_all_regs:
-            gcrootmap = gc_ll_descr = self.assembler.cpu.gc_ll_descr.gcrootmap
+            gcrootmap = self.assembler.cpu.gc_ll_descr.gcrootmap
             if gcrootmap and gcrootmap.is_shadow_stack:
                 save_all_regs = 2
         self.rm.before_call(force_store, save_all_regs=save_all_regs)
@@ -972,74 +973,27 @@
             return self._call(op, arglocs)
 
     def consider_newstr(self, op):
-        gc_ll_descr = self.assembler.cpu.gc_ll_descr
-        if gc_ll_descr.get_funcptr_for_newstr is not None:
-            # framework GC
-            loc = self.loc(op.getarg(0))
-            return self._call(op, [loc])
-        # boehm GC (XXX kill the following code at some point)
-        ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.STR, self.translate_support_code)
-        assert itemsize == 1
-        return self._malloc_varsize(ofs_items, ofs, 0, op.getarg(0),
-                                    op.result)
+        loc = self.loc(op.getarg(0))
+        return self._call(op, [loc])
 
     def consider_newunicode(self, op):
-        gc_ll_descr = self.assembler.cpu.gc_ll_descr
-        if gc_ll_descr.get_funcptr_for_newunicode is not None:
-            # framework GC
-            loc = self.loc(op.getarg(0))
-            return self._call(op, [loc])
-        # boehm GC (XXX kill the following code at some point)
-        ofs_items, _, ofs = symbolic.get_array_token(rstr.UNICODE,
-                                                   self.translate_support_code)
-        scale = self._get_unicode_item_scale()
-        return self._malloc_varsize(ofs_items, ofs, scale, op.getarg(0),
-                                    op.result)
-
-    def _malloc_varsize(self, ofs_items, ofs_length, scale, v, res_v):
-        # XXX kill this function at some point
-        if isinstance(v, Box):
-            loc = self.rm.make_sure_var_in_reg(v, [v])
-            tempbox = TempBox()
-            other_loc = self.rm.force_allocate_reg(tempbox, [v])
-            self.assembler.load_effective_addr(loc, ofs_items,scale, other_loc)
-        else:
-            tempbox = None
-            other_loc = imm(ofs_items + (v.getint() << scale))
-        self._call(ResOperation(rop.NEW, [], res_v),
-                   [other_loc], [v])
-        loc = self.rm.make_sure_var_in_reg(v, [res_v])
-        assert self.loc(res_v) == eax
-        # now we have to reload length to some reasonable place
-        self.rm.possibly_free_var(v)
-        if tempbox is not None:
-            self.rm.possibly_free_var(tempbox)
-        self.PerformDiscard(ResOperation(rop.SETFIELD_GC, [None, None], None),
-                            [eax, imm(ofs_length), imm(WORD), loc])
+        loc = self.loc(op.getarg(0))
+        return self._call(op, [loc])
 
     def consider_new_array(self, op):
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
-        if gc_ll_descr.get_funcptr_for_newarray is not None:
-            # framework GC
-            box_num_elem = op.getarg(0)
-            if isinstance(box_num_elem, ConstInt):
-                num_elem = box_num_elem.value
-                if gc_ll_descr.can_inline_malloc_varsize(op.getdescr(),
-                                                         num_elem):
-                    self.fastpath_malloc_varsize(op, op.getdescr(), num_elem)
-                    return
-            args = self.assembler.cpu.gc_ll_descr.args_for_new_array(
-                op.getdescr())
-            arglocs = [imm(x) for x in args]
-            arglocs.append(self.loc(box_num_elem))
-            self._call(op, arglocs)
-            return
-        # boehm GC (XXX kill the following code at some point)
-        itemsize, basesize, ofs_length, _, _ = (
-            self._unpack_arraydescr(op.getdescr()))
-        scale_of_field = _get_scale(itemsize)
-        self._malloc_varsize(basesize, ofs_length, scale_of_field,
-                             op.getarg(0), op.result)
+        box_num_elem = op.getarg(0)
+        if isinstance(box_num_elem, ConstInt):
+            num_elem = box_num_elem.value
+            if gc_ll_descr.can_inline_malloc_varsize(op.getdescr(),
+                                                     num_elem):
+                self.fastpath_malloc_varsize(op, op.getdescr(), num_elem)
+                return
+        args = self.assembler.cpu.gc_ll_descr.args_for_new_array(
+            op.getdescr())
+        arglocs = [imm(x) for x in args]
+        arglocs.append(self.loc(box_num_elem))
+        self._call(op, arglocs)
 
     def _unpack_arraydescr(self, arraydescr):
         assert isinstance(arraydescr, BaseArrayDescr)
@@ -1058,6 +1012,16 @@
         sign = fielddescr.is_field_signed()
         return imm(ofs), imm(size), ptr, sign
 
+    def _unpack_interiorfielddescr(self, descr):
+        assert isinstance(descr, InteriorFieldDescr)
+        arraydescr = descr.arraydescr
+        ofs = arraydescr.get_base_size(self.translate_support_code)
+        itemsize = arraydescr.get_item_size(self.translate_support_code)
+        fieldsize = descr.fielddescr.get_field_size(self.translate_support_code)
+        sign = descr.fielddescr.is_field_signed()
+        ofs += descr.fielddescr.offset
+        return imm(ofs), imm(itemsize), imm(fieldsize), sign
+
     def consider_setfield_gc(self, op):
         ofs_loc, size_loc, _, _ = self._unpack_fielddescr(op.getdescr())
         assert isinstance(size_loc, ImmedLoc)
@@ -1074,6 +1038,21 @@
 
     consider_setfield_raw = consider_setfield_gc
 
+    def consider_setinteriorfield_gc(self, op):
+        t = self._unpack_interiorfielddescr(op.getdescr())
+        ofs, itemsize, fieldsize, _ = t
+        args = op.getarglist()
+        tmpvar = TempBox()
+        base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
+        index_loc = self.rm.force_result_in_reg(tmpvar, op.getarg(1),
+                                                args)
+        # we're free to modify index now
+        value_loc = self.make_sure_var_in_reg(op.getarg(2), args)
+        self.possibly_free_vars(args)
+        self.rm.possibly_free_var(tmpvar)
+        self.PerformDiscard(op, [base_loc, ofs, itemsize, fieldsize,
+                                 index_loc, value_loc])
+
     def consider_strsetitem(self, op):
         args = op.getarglist()
         base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
@@ -1135,6 +1114,24 @@
     consider_getarrayitem_raw = consider_getarrayitem_gc
     consider_getarrayitem_gc_pure = consider_getarrayitem_gc
 
+    def consider_getinteriorfield_gc(self, op):
+        t = self._unpack_interiorfielddescr(op.getdescr())
+        ofs, itemsize, fieldsize, sign = t
+        if sign:
+            sign_loc = imm1
+        else:
+            sign_loc = imm0
+        args = op.getarglist()
+        tmpvar = TempBox()
+        base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
+        index_loc = self.rm.force_result_in_reg(tmpvar, op.getarg(1),
+                                                args)
+        self.rm.possibly_free_vars_for_op(op)
+        self.rm.possibly_free_var(tmpvar)
+        result_loc = self.force_allocate_reg(op.result)
+        self.Perform(op, [base_loc, ofs, itemsize, fieldsize,
+                          index_loc, sign_loc], result_loc)
+
     def consider_int_is_true(self, op, guard_op):
         # doesn't need arg to be in a register
         argloc = self.loc(op.getarg(0))
@@ -1241,7 +1238,6 @@
         self.rm.possibly_free_var(srcaddr_box)
 
     def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode):
-        cpu = self.assembler.cpu
         if is_unicode:
             ofs_items, _, _ = symbolic.get_array_token(rstr.UNICODE,
                                                   self.translate_support_code)
@@ -1300,7 +1296,7 @@
         tmpreg = X86RegisterManager.all_regs[0]
         tmploc = self.rm.force_allocate_reg(box, selected_reg=tmpreg)
         xmmtmp = X86XMMRegisterManager.all_regs[0]
-        xmmtmploc = self.xrm.force_allocate_reg(box1, selected_reg=xmmtmp)
+        self.xrm.force_allocate_reg(box1, selected_reg=xmmtmp)
         # Part about non-floats
         # XXX we don't need a copy, we only just the original list
         src_locations1 = [self.loc(op.getarg(i)) for i in range(op.numargs())
@@ -1380,7 +1376,7 @@
     return lambda self, op: fn(self, op, None)
 
 def is_comparison_or_ovf_op(opnum):
-    from pypy.jit.metainterp.resoperation import opclasses, AbstractResOp
+    from pypy.jit.metainterp.resoperation import opclasses
     cls = opclasses[opnum]
     # hack hack: in theory they are instance method, but they don't use
     # any instance field, we can use a fake object
diff --git a/pypy/jit/backend/x86/test/test_del.py b/pypy/jit/backend/x86/test/test_del.py
--- a/pypy/jit/backend/x86/test/test_del.py
+++ b/pypy/jit/backend/x86/test/test_del.py
@@ -1,5 +1,4 @@
 
-import py
 from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
 from pypy.jit.metainterp.test.test_del import DelTests
 
diff --git a/pypy/jit/backend/x86/test/test_dict.py b/pypy/jit/backend/x86/test/test_dict.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/x86/test/test_dict.py
@@ -0,0 +1,9 @@
+
+from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
+from pypy.jit.metainterp.test.test_dict import DictTests
+
+
+class TestDict(Jit386Mixin, DictTests):
+    # for the individual tests see
+    # ====> ../../../metainterp/test/test_dict.py
+    pass
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -31,7 +31,7 @@
 
     # for the individual tests see
     # ====> ../../test/runner_test.py
-    
+
     def setup_method(self, meth):
         self.cpu = CPU(rtyper=None, stats=FakeStats())
         self.cpu.setup_once()
@@ -69,22 +69,16 @@
 
     def test_allocations(self):
         from pypy.rpython.lltypesystem import rstr
-        
+
         allocs = [None]
         all = []
+        orig_new = self.cpu.gc_ll_descr.funcptr_for_new
         def f(size):
             allocs.insert(0, size)
-            buf = ctypes.create_string_buffer(size)
-            all.append(buf)
-            return ctypes.cast(buf, ctypes.c_void_p).value
-        func = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)(f)
-        addr = ctypes.cast(func, ctypes.c_void_p).value
-        # ctypes produces an unsigned value. We need it to be signed for, eg,
-        # relative addressing to work properly.
-        addr = rffi.cast(lltype.Signed, addr)
-        
+            return orig_new(size)
+
         self.cpu.assembler.setup_once()
-        self.cpu.assembler.malloc_func_addr = addr
+        self.cpu.gc_ll_descr.funcptr_for_new = f
         ofs = symbolic.get_field_token(rstr.STR, 'chars', False)[0]
 
         res = self.execute_operation(rop.NEWSTR, [ConstInt(7)], 'ref')
@@ -108,7 +102,7 @@
         res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)],
                                          'ref', descr)
         assert allocs[0] == 10*WORD + ofs + WORD
-        resbuf = self._resbuf(res)            
+        resbuf = self._resbuf(res)
         assert resbuf[ofs/WORD] == 10
 
         # ------------------------------------------------------------
@@ -116,7 +110,7 @@
         res = self.execute_operation(rop.NEW_ARRAY, [BoxInt(10)],
                                          'ref', descr)
         assert allocs[0] == 10*WORD + ofs + WORD
-        resbuf = self._resbuf(res)                        
+        resbuf = self._resbuf(res)
         assert resbuf[ofs/WORD] == 10
 
     def test_stringitems(self):
@@ -146,7 +140,7 @@
                                                      ConstInt(2), BoxInt(38)],
                                'void', descr)
         assert resbuf[itemsofs/WORD + 2] == 38
-        
+
         self.execute_operation(rop.SETARRAYITEM_GC, [res,
                                                      BoxInt(3), BoxInt(42)],
                                'void', descr)
@@ -167,7 +161,7 @@
                                                          BoxInt(2)],
                                    'int', descr)
         assert r.value == 38
-        
+
         r = self.execute_operation(rop.GETARRAYITEM_GC, [res, BoxInt(3)],
                                    'int', descr)
         assert r.value == 42
@@ -226,7 +220,7 @@
         self.execute_operation(rop.SETFIELD_GC, [res, BoxInt(1234)], 'void', ofs_i)
         i = self.execute_operation(rop.GETFIELD_GC, [res], 'int', ofs_i)
         assert i.value == 1234
-        
+
         #u = self.execute_operation(rop.GETFIELD_GC, [res, ofs_u], 'int')
         #assert u.value == 5
         self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(1)], 'void',
@@ -299,7 +293,7 @@
                     else:
                         assert result != execute(self.cpu, None,
                                                  op, None, b).value
-                    
+
 
     def test_stuff_followed_by_guard(self):
         boxes = [(BoxInt(1), BoxInt(0)),
@@ -523,7 +517,7 @@
     def test_debugger_on(self):
         from pypy.tool.logparser import parse_log_file, extract_category
         from pypy.rlib import debug
-        
+
         loop = """
         [i0]
         debug_merge_point('xyz', 0)
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -52,9 +52,11 @@
         newoperations = []
         #
         def do_rename(var, var_or_const):
+            if var.concretetype is lltype.Void:
+                renamings[var] = Constant(None, lltype.Void)
+                return
             renamings[var] = var_or_const
-            if (isinstance(var_or_const, Constant)
-                and var.concretetype != lltype.Void):
+            if isinstance(var_or_const, Constant):
                 value = var_or_const.value
                 value = lltype._cast_whatever(var.concretetype, value)
                 renamings_constants[var] = Constant(value, var.concretetype)
@@ -441,6 +443,8 @@
     rewrite_op_gc_identityhash = _do_builtin_call
     rewrite_op_gc_id           = _do_builtin_call
     rewrite_op_uint_mod        = _do_builtin_call
+    rewrite_op_cast_float_to_uint = _do_builtin_call
+    rewrite_op_cast_uint_to_float = _do_builtin_call
 
     # ----------
     # getfield/setfield/mallocs etc.
@@ -735,29 +739,54 @@
         return SpaceOperation(opname, [op.args[0]], op.result)
 
     def rewrite_op_getinteriorfield(self, op):
-        # only supports strings and unicodes
         assert len(op.args) == 3
-        assert op.args[1].value == 'chars'
         optype = op.args[0].concretetype
         if optype == lltype.Ptr(rstr.STR):
             opname = "strgetitem"
+            return SpaceOperation(opname, [op.args[0], op.args[2]], op.result)
+        elif optype == lltype.Ptr(rstr.UNICODE):
+            opname = "unicodegetitem"
+            return SpaceOperation(opname, [op.args[0], op.args[2]], op.result)
         else:
-            assert optype == lltype.Ptr(rstr.UNICODE)
-            opname = "unicodegetitem"
-        return SpaceOperation(opname, [op.args[0], op.args[2]], op.result)
+            v_inst, v_index, c_field = op.args
+            if op.result.concretetype is lltype.Void:
+                return
+            # only GcArray of Struct supported
+            assert isinstance(v_inst.concretetype.TO, lltype.GcArray)
+            STRUCT = v_inst.concretetype.TO.OF
+            assert isinstance(STRUCT, lltype.Struct)
+            descr = self.cpu.interiorfielddescrof(v_inst.concretetype.TO,
+                                                  c_field.value)
+            args = [v_inst, v_index, descr]
+            kind = getkind(op.result.concretetype)[0]
+            return SpaceOperation('getinteriorfield_gc_%s' % kind, args,
+                                  op.result)
 
     def rewrite_op_setinteriorfield(self, op):
-        # only supports strings and unicodes
         assert len(op.args) == 4
-        assert op.args[1].value == 'chars'
         optype = op.args[0].concretetype
         if optype == lltype.Ptr(rstr.STR):
             opname = "strsetitem"
+            return SpaceOperation(opname, [op.args[0], op.args[2], op.args[3]],
+                                  op.result)
+        elif optype == lltype.Ptr(rstr.UNICODE):
+            opname = "unicodesetitem"
+            return SpaceOperation(opname, [op.args[0], op.args[2], op.args[3]],
+                                  op.result)
         else:
-            assert optype == lltype.Ptr(rstr.UNICODE)
-            opname = "unicodesetitem"
-        return SpaceOperation(opname, [op.args[0], op.args[2], op.args[3]],
-                              op.result)
+            v_inst, v_index, c_field, v_value = op.args
+            if v_value.concretetype is lltype.Void:
+                return
+            # only GcArray of Struct supported
+            assert isinstance(v_inst.concretetype.TO, lltype.GcArray)
+            STRUCT = v_inst.concretetype.TO.OF
+            assert isinstance(STRUCT, lltype.Struct)
+            descr = self.cpu.interiorfielddescrof(v_inst.concretetype.TO,
+                                                  c_field.value)
+            kind = getkind(v_value.concretetype)[0]
+            args = [v_inst, v_index, v_value, descr]
+            return SpaceOperation('setinteriorfield_gc_%s' % kind, args,
+                                  op.result)
 
     def _rewrite_equality(self, op, opname):
         arg0, arg1 = op.args
@@ -821,26 +850,44 @@
         elif not float_arg and float_res:
             # some int -> some float
             ops = []
-            v1 = varoftype(lltype.Signed)
-            oplist = self.rewrite_operation(
-                SpaceOperation('force_cast', [v_arg], v1)
-            )
-            if oplist:
-                ops.extend(oplist)
+            v2 = varoftype(lltype.Float)
+            sizesign = rffi.size_and_sign(v_arg.concretetype)
+            if sizesign <= rffi.size_and_sign(lltype.Signed):
+                # cast from a type that fits in an int: either the size is
+                # smaller, or it is equal and it is not unsigned
+                v1 = varoftype(lltype.Signed)
+                oplist = self.rewrite_operation(
+                    SpaceOperation('force_cast', [v_arg], v1)
+                )
+                if oplist:
+                    ops.extend(oplist)
+                else:
+                    v1 = v_arg
+                op = self.rewrite_operation(
+                    SpaceOperation('cast_int_to_float', [v1], v2)
+                )
+                ops.append(op)
             else:
-                v1 = v_arg
-            v2 = varoftype(lltype.Float)
-            op = self.rewrite_operation(
-                SpaceOperation('cast_int_to_float', [v1], v2)
-            )
-            ops.append(op)
+                if sizesign == rffi.size_and_sign(lltype.Unsigned):
+                    opname = 'cast_uint_to_float'
+                elif sizesign == rffi.size_and_sign(lltype.SignedLongLong):
+                    opname = 'cast_longlong_to_float'
+                elif sizesign == rffi.size_and_sign(lltype.UnsignedLongLong):
+                    opname = 'cast_ulonglong_to_float'
+                else:
+                    raise AssertionError('cast_x_to_float: %r' % (sizesign,))
+                ops1 = self.rewrite_operation(
+                    SpaceOperation(opname, [v_arg], v2)
+                )
+                if not isinstance(ops1, list): ops1 = [ops1]
+                ops.extend(ops1)
             op2 = self.rewrite_operation(
                 SpaceOperation('force_cast', [v2], v_result)
             )
             if op2:
                 ops.append(op2)
             else:
-                op.result = v_result
+                ops[-1].result = v_result
             return ops
         elif float_arg and not float_res:
             # some float -> some int
@@ -853,18 +900,36 @@
                 ops.append(op1)
             else:
                 v1 = v_arg
-            v2 = varoftype(lltype.Signed)
-            op = self.rewrite_operation(
-                SpaceOperation('cast_float_to_int', [v1], v2)
-            )
-            ops.append(op)
-            oplist = self.rewrite_operation(
-                SpaceOperation('force_cast', [v2], v_result)
-            )
-            if oplist:
-                ops.extend(oplist)
+            sizesign = rffi.size_and_sign(v_result.concretetype)
+            if sizesign <= rffi.size_and_sign(lltype.Signed):
+                # cast to a type that fits in an int: either the size is
+                # smaller, or it is equal and it is not unsigned
+                v2 = varoftype(lltype.Signed)
+                op = self.rewrite_operation(
+                    SpaceOperation('cast_float_to_int', [v1], v2)
+                )
+                ops.append(op)
+                oplist = self.rewrite_operation(
+                    SpaceOperation('force_cast', [v2], v_result)
+                )
+                if oplist:
+                    ops.extend(oplist)
+                else:
+                    op.result = v_result
             else:
-                op.result = v_result
+                if sizesign == rffi.size_and_sign(lltype.Unsigned):
+                    opname = 'cast_float_to_uint'
+                elif sizesign == rffi.size_and_sign(lltype.SignedLongLong):
+                    opname = 'cast_float_to_longlong'
+                elif sizesign == rffi.size_and_sign(lltype.UnsignedLongLong):
+                    opname = 'cast_float_to_ulonglong'
+                else:
+                    raise AssertionError('cast_float_to_x: %r' % (sizesign,))
+                ops1 = self.rewrite_operation(
+                    SpaceOperation(opname, [v1], v_result)
+                )
+                if not isinstance(ops1, list): ops1 = [ops1]
+                ops.extend(ops1)
             return ops
         else:
             assert False
@@ -1070,8 +1135,6 @@
     # The new operation is optionally further processed by rewrite_operation().
     for _old, _new in [('bool_not', 'int_is_zero'),
                        ('cast_bool_to_float', 'cast_int_to_float'),
-                       ('cast_uint_to_float', 'cast_int_to_float'),
-                       ('cast_float_to_uint', 'cast_float_to_int'),
 
                        ('int_add_nonneg_ovf', 'int_add_ovf'),
                        ('keepalive', '-live-'),
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -13,7 +13,6 @@
 from pypy.translator.simplify import get_funcobj
 from pypy.translator.unsimplify import split_block
 from pypy.objspace.flow.model import Constant
-from pypy import conftest
 from pypy.translator.translator import TranslationContext
 from pypy.annotation.policy import AnnotatorPolicy
 from pypy.annotation import model as annmodel
@@ -48,15 +47,13 @@
     a.build_types(func, argtypes, main_entry_point=True)
     rtyper = t.buildrtyper(type_system = type_system)
     rtyper.specialize()
-    if inline:
-        auto_inlining(t, threshold=inline)
+    #if inline:
+    #    auto_inlining(t, threshold=inline)
     if backendoptimize:
         from pypy.translator.backendopt.all import backend_optimizations
         backend_optimizations(t, inline_threshold=inline or 0,
                 remove_asserts=True, really_remove_asserts=True)
 
-    #if conftest.option.view:
-    #    t.view()
     return rtyper
 
 def getgraph(func, values):
@@ -232,6 +229,17 @@
     else:
         return x
 
+def _ll_1_cast_uint_to_float(x):
+    # XXX on 32-bit platforms, this should be done using cast_longlong_to_float
+    # (which is a residual call right now in the x86 backend)
+    return llop.cast_uint_to_float(lltype.Float, x)
+
+def _ll_1_cast_float_to_uint(x):
+    # XXX on 32-bit platforms, this should be done using cast_float_to_longlong
+    # (which is a residual call right now in the x86 backend)
+    return llop.cast_float_to_uint(lltype.Unsigned, x)
+
+
 # math support
 # ------------
 
@@ -456,6 +464,8 @@
         return LLtypeHelpers._dictnext_items(lltype.Ptr(RES), iter)
     _ll_1_dictiter_nextitems.need_result_type = True
 
+    _ll_1_dict_resize = ll_rdict.ll_dict_resize
+
     # ---------- strings and unicode ----------
 
     _ll_1_str_str2unicode = ll_rstr.LLHelpers.ll_str2unicode
diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py
--- a/pypy/jit/codewriter/test/test_flatten.py
+++ b/pypy/jit/codewriter/test/test_flatten.py
@@ -8,7 +8,7 @@
 from pypy.rpython.lltypesystem import lltype, rclass, rstr
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
 from pypy.translator.unsimplify import varoftype
-from pypy.rlib.rarithmetic import ovfcheck, r_uint
+from pypy.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
 from pypy.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver
 from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib import jit
@@ -70,7 +70,8 @@
         return 'residual'
     def getcalldescr(self, op, oopspecindex=None, extraeffect=None):
         try:
-            if 'cannot_raise' in op.args[0].value._obj.graph.name:
+            name = op.args[0].value._obj._name
+            if 'cannot_raise' in name or name.startswith('cast_'):
                 return self._descr_cannot_raise
         except AttributeError:
             pass
@@ -900,6 +901,67 @@
             int_return %i4
         """, transform=True)
 
+        def f(dbl):
+            return rffi.cast(rffi.UCHAR, dbl)
+        self.encoding_test(f, [12.456], """
+            cast_float_to_int %f0 -> %i0
+            int_and %i0, $255 -> %i1
+            int_return %i1
+        """, transform=True)
+
+        def f(dbl):
+            return rffi.cast(lltype.Unsigned, dbl)
+        self.encoding_test(f, [12.456], """
+            residual_call_irf_i $<* fn cast_float_to_uint>, <Descr>, I[], R[], F[%f0] -> %i0
+            int_return %i0
+        """, transform=True)
+
+        def f(i):
+            return rffi.cast(lltype.Float, chr(i))    # "char -> float"
+        self.encoding_test(f, [12], """
+            cast_int_to_float %i0 -> %f0
+            float_return %f0
+        """, transform=True)
+
+        def f(i):
+            return rffi.cast(lltype.Float, r_uint(i))    # "uint -> float"
+        self.encoding_test(f, [12], """
+            residual_call_irf_f $<* fn cast_uint_to_float>, <Descr>, I[%i0], R[], F[] -> %f0
+            float_return %f0
+        """, transform=True)
+
+        if not longlong.is_64_bit:
+            def f(dbl):
+                return rffi.cast(lltype.SignedLongLong, dbl)
+            self.encoding_test(f, [12.3], """
+                residual_call_irf_f $<* fn llong_from_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
+
+            def f(dbl):
+                return rffi.cast(lltype.UnsignedLongLong, dbl)
+            self.encoding_test(f, [12.3], """
+                residual_call_irf_f $<* fn ullong_from_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
+
+            def f(x):
+                ll = r_longlong(x)
+                return rffi.cast(lltype.Float, ll)
+            self.encoding_test(f, [12], """
+                residual_call_irf_f $<* fn llong_from_int>, <Descr>, I[%i0], R[], F[] -> %f0
+                residual_call_irf_f $<* fn llong_to_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
+
+            def f(x):
+                ll = r_ulonglong(x)
+                return rffi.cast(lltype.Float, ll)
+            self.encoding_test(f, [12], """
+                residual_call_irf_f $<* fn ullong_from_int>, <Descr>, I[%i0], R[], F[] -> %f0
+                residual_call_irf_f $<* fn ullong_u_to_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
 
     def test_direct_ptradd(self):
         from pypy.rpython.lltypesystem import rffi
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -1,4 +1,3 @@
-import py
 import random
 try:
     from itertools import product
@@ -16,13 +15,13 @@
 
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.jit.codewriter.jtransform import Transformer
-from pypy.jit.metainterp.history import getkind
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rlist
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
 from pypy.rpython.lltypesystem.module import ll_math
 from pypy.translator.unsimplify import varoftype
 from pypy.jit.codewriter import heaptracker, effectinfo
 from pypy.jit.codewriter.flatten import ListOfKind
+from pypy.jit.codewriter.jtransform import Transformer
+from pypy.jit.metainterp.history import getkind
 
 def const(x):
     return Constant(x, lltype.typeOf(x))
@@ -37,6 +36,8 @@
         return ('calldescr', FUNC, ARGS, RESULT)
     def fielddescrof(self, STRUCT, name):
         return ('fielddescr', STRUCT, name)
+    def interiorfielddescrof(self, ARRAY, name):
+        return ('interiorfielddescr', ARRAY, name)
     def arraydescrof(self, ARRAY):
         return FakeDescr(('arraydescr', ARRAY))
     def sizeof(self, STRUCT):
@@ -539,7 +540,7 @@
 
 def test_rename_on_links():
     v1 = Variable()
-    v2 = Variable()
+    v2 = Variable(); v2.concretetype = llmemory.Address
     v3 = Variable()
     block = Block([v1])
     block.operations = [SpaceOperation('cast_pointer', [v1], v2)]
@@ -676,6 +677,22 @@
     assert op1.args == [v, v_index]
     assert op1.result == v_result
 
+def test_dict_getinteriorfield():
+    DICT = lltype.GcArray(lltype.Struct('ENTRY', ('v', lltype.Signed),
+                                        ('k', lltype.Signed)))
+    v = varoftype(lltype.Ptr(DICT))
+    i = varoftype(lltype.Signed)
+    v_result = varoftype(lltype.Signed)
+    op = SpaceOperation('getinteriorfield', [v, i, Constant('v', lltype.Void)],
+                        v_result)
+    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    assert op1.opname == 'getinteriorfield_gc_i'
+    assert op1.args == [v, i, ('interiorfielddescr', DICT, 'v')]
+    op = SpaceOperation('getinteriorfield', [v, i, Constant('v', lltype.Void)],
+                        Constant(None, lltype.Void))
+    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    assert op1 is None
+
 def test_str_setinteriorfield():
     v = varoftype(lltype.Ptr(rstr.STR))
     v_index = varoftype(lltype.Signed)
@@ -702,6 +719,23 @@
     assert op1.args == [v, v_index, v_newchr]
     assert op1.result == v_void
 
+def test_dict_setinteriorfield():
+    DICT = lltype.GcArray(lltype.Struct('ENTRY', ('v', lltype.Signed),
+                                        ('k', lltype.Signed)))
+    v = varoftype(lltype.Ptr(DICT))
+    i = varoftype(lltype.Signed)
+    v_void = varoftype(lltype.Void)
+    op = SpaceOperation('setinteriorfield', [v, i, Constant('v', lltype.Void),
+                                             i],
+                        v_void)
+    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    assert op1.opname == 'setinteriorfield_gc_i'
+    assert op1.args == [v, i, i, ('interiorfielddescr', DICT, 'v')]
+    op = SpaceOperation('setinteriorfield', [v, i, Constant('v', lltype.Void),
+                                             v_void], v_void)
+    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    assert not op1
+
 def test_promote_1():
     v1 = varoftype(lltype.Signed)
     v2 = varoftype(lltype.Signed)
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -6,7 +6,6 @@
 from pypy.rlib.debug import make_sure_not_resized
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rpython.llinterp import LLException
 from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
 from pypy.jit.codewriter import heaptracker, longlong
 from pypy.jit.metainterp.jitexc import JitException, get_llexception, reraise
@@ -631,6 +630,9 @@
         a = longlong.getrealfloat(a)
         # note: we need to call int() twice to care for the fact that
         # int(-2147483648.0) returns a long :-(
+        # we could also call intmask() instead of the outermost int(), but
+        # it's probably better to explicitly crash (by getting a long) if a
+        # non-translated version tries to cast a too large float to an int.
         return int(int(a))
 
     @arguments("i", returns="f")
@@ -1154,6 +1156,26 @@
         array = cpu.bh_getfield_gc_r(vable, fdescr)
         return cpu.bh_arraylen_gc(adescr, array)
 
+    @arguments("cpu", "r", "i", "d", returns="i")
+    def bhimpl_getinteriorfield_gc_i(cpu, array, index, descr):
+        return cpu.bh_getinteriorfield_gc_i(array, index, descr)
+    @arguments("cpu", "r", "i", "d", returns="r")
+    def bhimpl_getinteriorfield_gc_r(cpu, array, index, descr):
+        return cpu.bh_getinteriorfield_gc_r(array, index, descr)
+    @arguments("cpu", "r", "i", "d", returns="f")
+    def bhimpl_getinteriorfield_gc_f(cpu, array, index, descr):
+        return cpu.bh_getinteriorfield_gc_f(array, index, descr)
+
+    @arguments("cpu", "r", "i", "d", "i")
+    def bhimpl_setinteriorfield_gc_i(cpu, array, index, descr, value):
+        cpu.bh_setinteriorfield_gc_i(array, index, descr, value)
+    @arguments("cpu", "r", "i", "d", "r")
+    def bhimpl_setinteriorfield_gc_r(cpu, array, index, descr, value):
+        cpu.bh_setinteriorfield_gc_r(array, index, descr, value)
+    @arguments("cpu", "r", "i", "d", "f")
+    def bhimpl_setinteriorfield_gc_f(cpu, array, index, descr, value):
+        cpu.bh_setinteriorfield_gc_f(array, index, descr, value)
+
     @arguments("cpu", "r", "d", returns="i")
     def bhimpl_getfield_gc_i(cpu, struct, fielddescr):
         return cpu.bh_getfield_gc_i(struct, fielddescr)
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -1,11 +1,8 @@
 """This implements pyjitpl's execution of operations.
 """
 
-import py
-from pypy.rpython.lltypesystem import lltype, llmemory, rstr
-from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask, r_longlong
+from pypy.rpython.lltypesystem import lltype, rstr
+from pypy.rlib.rarithmetic import ovfcheck, r_longlong
 from pypy.rlib.rtimer import read_timestamp
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, check_descr
@@ -123,6 +120,29 @@
     else:
         cpu.bh_setarrayitem_raw_i(arraydescr, array, index, itembox.getint())
 
+def do_getinteriorfield_gc(cpu, _, arraybox, indexbox, descr):
+    array = arraybox.getref_base()
+    index = indexbox.getint()
+    if descr.is_pointer_field():
+        return BoxPtr(cpu.bh_getinteriorfield_gc_r(array, index, descr))
+    elif descr.is_float_field():
+        return BoxFloat(cpu.bh_getinteriorfield_gc_f(array, index, descr))
+    else:
+        return BoxInt(cpu.bh_getinteriorfield_gc_i(array, index, descr))
+
+def do_setinteriorfield_gc(cpu, _, arraybox, indexbox, valuebox, descr):
+    array = arraybox.getref_base()
+    index = indexbox.getint()
+    if descr.is_pointer_field():
+        cpu.bh_setinteriorfield_gc_r(array, index, descr,
+                                     valuebox.getref_base())
+    elif descr.is_float_field():
+        cpu.bh_setinteriorfield_gc_f(array, index, descr,
+                                     valuebox.getfloatstorage())
+    else:
+        cpu.bh_setinteriorfield_gc_i(array, index, descr,
+                                     valuebox.getint())
+
 def do_getfield_gc(cpu, _, structbox, fielddescr):
     struct = structbox.getref_base()
     if fielddescr.is_pointer_field():
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -16,6 +16,7 @@
 INT   = 'i'
 REF   = 'r'
 FLOAT = 'f'
+STRUCT = 's'
 HOLE  = '_'
 VOID  = 'v'
 
@@ -172,6 +173,11 @@
         """
         raise NotImplementedError
 
+    def is_array_of_structs(self):
+        """ Implement for array descr
+        """
+        raise NotImplementedError
+
     def is_pointer_field(self):
         """ Implement for field descr
         """
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -448,6 +448,9 @@
         if v2.is_constant() and v2.box.getint() == 1:
             self.make_equal_to(op.result, v1)
             return
+        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():
             val = v2.box.getint()
             if val & (val - 1) == 0 and val > 0: # val == 2**shift
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -2181,6 +2181,17 @@
         """
         self.optimize_loop(ops, expected)
 
+        ops = """
+        [i0]
+        i1 = int_floordiv(0, i0)
+        jump(i1)
+        """
+        expected = """
+        [i0]
+        jump(0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_fold_partially_constant_ops_ovf(self):
         ops = """
         [i0]
@@ -4789,6 +4800,18 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_ptr_eq_str_constant(self):
+        ops = """
+        []
+        i0 = ptr_eq(s"abc", s"\x00")
+        finish(i0)
+        """
+        expected = """
+        []
+        finish(0)
+        """
+        self.optimize_loop(ops, expected)
+
 
 class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
     pass
diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -59,7 +59,7 @@
 
     def import_from(self, other, optimizer):
         raise NotImplementedError("should not be called at this level")
-    
+
 def get_fielddescrlist_cache(cpu):
     if not hasattr(cpu, '_optimizeopt_fielddescrlist_cache'):
         result = descrlist_dict()
@@ -113,7 +113,7 @@
         #
         if not we_are_translated():
             op.name = 'FORCE ' + self.source_op.name
-            
+
         if self._is_immutable_and_filled_with_constants(optforce):
             box = optforce.optimizer.constant_fold(op)
             self.make_constant(box)
@@ -239,12 +239,12 @@
         for index in range(len(self._items)):
             self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce)
         return self
-    
+
     def _really_force(self, optforce):
         assert self.source_op is not None
         if not we_are_translated():
             self.source_op.name = 'FORCE ' + self.source_op.name
-        optforce.emit_operation(self.source_op)        
+        optforce.emit_operation(self.source_op)
         self.box = box = self.source_op.result
         for index in range(len(self._items)):
             subvalue = self._items[index]
@@ -276,7 +276,7 @@
 
     def new(self):
         return OptVirtualize()
-        
+
     def make_virtual(self, known_class, box, source_op=None):
         vvalue = VirtualValue(self.optimizer.cpu, known_class, box, source_op)
         self.make_equal_to(box, vvalue)
@@ -386,7 +386,8 @@
 
     def optimize_NEW_ARRAY(self, op):
         sizebox = self.get_constant_box(op.getarg(0))
-        if sizebox is not None:
+        # For now we can't make arrays of structs virtual.
+        if sizebox is not None and not op.getdescr().is_array_of_structs():
             # if the original 'op' did not have a ConstInt as argument,
             # build a new one with the ConstInt argument
             if not isinstance(op.getarg(0), ConstInt):
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -36,6 +36,7 @@
 
 
 class MIFrame(object):
+    debug = False
 
     def __init__(self, metainterp):
         self.metainterp = metainterp
@@ -548,6 +549,14 @@
     opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any
     opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any
 
+    @arguments("box", "box", "descr")
+    def _opimpl_getinteriorfield_gc_any(self, array, index, descr):
+        return self.execute_with_descr(rop.GETINTERIORFIELD_GC, descr,
+                                       array, index)
+    opimpl_getinteriorfield_gc_i = _opimpl_getinteriorfield_gc_any
+    opimpl_getinteriorfield_gc_f = _opimpl_getinteriorfield_gc_any
+    opimpl_getinteriorfield_gc_r = _opimpl_getinteriorfield_gc_any
+
     @specialize.arg(1)
     def _opimpl_getfield_gc_any_pureornot(self, opnum, box, fielddescr):
         tobox = self.metainterp.heapcache.getfield(box, fielddescr)
@@ -588,6 +597,15 @@
     opimpl_setfield_gc_r = _opimpl_setfield_gc_any
     opimpl_setfield_gc_f = _opimpl_setfield_gc_any
 
+    @arguments("box", "box", "box", "descr")
+    def _opimpl_setinteriorfield_gc_any(self, array, index, value, descr):
+        self.execute_with_descr(rop.SETINTERIORFIELD_GC, descr,
+                                array, index, value)
+    opimpl_setinteriorfield_gc_i = _opimpl_setinteriorfield_gc_any
+    opimpl_setinteriorfield_gc_f = _opimpl_setinteriorfield_gc_any
+    opimpl_setinteriorfield_gc_r = _opimpl_setinteriorfield_gc_any
+                                
+
     @arguments("box", "descr")
     def _opimpl_getfield_raw_any(self, box, fielddescr):
         return self.execute_with_descr(rop.GETFIELD_RAW, fielddescr, box)
@@ -2588,17 +2606,21 @@
         self.pc = position
         #
         if not we_are_translated():
-            print '\tpyjitpl: %s(%s)' % (name, ', '.join(map(repr, args))),
+            if self.debug:
+                print '\tpyjitpl: %s(%s)' % (name, ', '.join(map(repr, args))),
             try:
                 resultbox = unboundmethod(self, *args)
             except Exception, e:
-                print '-> %s!' % e.__class__.__name__
+                if self.debug:
+                    print '-> %s!' % e.__class__.__name__
                 raise
             if num_return_args == 0:
-                print
+                if self.debug:
+                    print
                 assert resultbox is None
             else:
-                print '-> %r' % (resultbox,)
+                if self.debug:
+                    print '-> %r' % (resultbox,)
                 assert argcodes[next_argcode] == '>'
                 result_argcode = argcodes[next_argcode + 1]
                 assert resultbox.type == {'i': history.INT,
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -1,5 +1,4 @@
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.debug import make_sure_not_resized
 
 def ResOperation(opnum, args, result, descr=None):
     cls = opclasses[opnum]
@@ -405,8 +404,8 @@
     'FLOAT_TRUEDIV/2',
     'FLOAT_NEG/1',
     'FLOAT_ABS/1',
-    'CAST_FLOAT_TO_INT/1',
-    'CAST_INT_TO_FLOAT/1',
+    'CAST_FLOAT_TO_INT/1',          # don't use for unsigned ints; we would
+    'CAST_INT_TO_FLOAT/1',          # need some messy code in the backend
     'CAST_FLOAT_TO_SINGLEFLOAT/1',
     'CAST_SINGLEFLOAT_TO_FLOAT/1',
     #
@@ -457,6 +456,7 @@
 
     'GETARRAYITEM_GC/2d',
     'GETARRAYITEM_RAW/2d',
+    'GETINTERIORFIELD_GC/2d',
     'GETFIELD_GC/1d',
     'GETFIELD_RAW/1d',
     '_MALLOC_FIRST',
@@ -473,6 +473,7 @@
 
     'SETARRAYITEM_GC/3d',
     'SETARRAYITEM_RAW/3d',
+    'SETINTERIORFIELD_GC/3d',
     'SETFIELD_GC/2d',
     'SETFIELD_RAW/2d',
     'STRSETITEM/3',
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -3435,7 +3435,39 @@
             return sa
         res = self.meta_interp(f, [16])
         assert res == f(16)
-        
+
+    def test_ptr_eq_str_constants(self):
+        myjitdriver = JitDriver(greens = [], reds = ["n", "x"])
+        class A(object):
+            def __init__(self, v):
+                self.v = v
+        def f(n, x):
+            while n > 0:
+                myjitdriver.jit_merge_point(n=n, x=x)
+                z = 0 / x
+                a1 = A("key")
+                a2 = A("\x00")
+                n -= [a1, a2][z].v is not a2.v
+            return n
+        res = self.meta_interp(f, [10, 1])
+        assert res == 0
+
+    def test_virtual_array_of_structs(self):
+        myjitdriver = JitDriver(greens = [], reds=["n", "d"])
+        def f(n):
+            d = None
+            while n > 0:
+                myjitdriver.jit_merge_point(n=n, d=d)
+                d = {}
+                if n % 2:
+                    d["k"] = n
+                else:
+                    d["z"] = n
+                n -= len(d)
+            return n
+        res = self.meta_interp(f, [10])
+        assert res == 0
+
 
 
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
diff --git a/pypy/jit/metainterp/test/test_dict.py b/pypy/jit/metainterp/test/test_dict.py
--- a/pypy/jit/metainterp/test/test_dict.py
+++ b/pypy/jit/metainterp/test/test_dict.py
@@ -91,7 +91,7 @@
         res1 = f(100)
         res2 = self.meta_interp(f, [100], listops=True)
         assert res1 == res2
-        self.check_loops(int_mod=1) # the hash was traced
+        self.check_loops(int_mod=1) # the hash was traced and eq, but cached
 
     def test_dict_setdefault(self):
         myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
@@ -128,7 +128,7 @@
         assert f(100) == 50
         res = self.meta_interp(f, [100], listops=True)
         assert res == 50
-        self.check_loops(int_mod=1)
+        self.check_loops(int_mod=1) # key + eq, but cached
 
     def test_repeated_lookup(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'd'])
@@ -153,10 +153,12 @@
 
         res = self.meta_interp(f, [100], listops=True)
         assert res == f(50)
-        self.check_loops({"call": 7, "guard_false": 1, "guard_no_exception": 6,
+        self.check_loops({"call": 5, "getfield_gc": 1, "getinteriorfield_gc": 1,
+                          "guard_false": 1, "guard_no_exception": 4,
                           "guard_true": 1, "int_and": 1, "int_gt": 1,
                           "int_is_true": 1, "int_sub": 1, "jump": 1,
-                          "new_with_vtable": 1, "setfield_gc": 1})
+                          "new_with_vtable": 1, "new": 1, "new_array": 1,
+                          "setfield_gc": 3, })
 
 
 class TestOOtype(DictTests, OOJitMixin):
diff --git a/pypy/jit/metainterp/test/test_float.py b/pypy/jit/metainterp/test/test_float.py
--- a/pypy/jit/metainterp/test/test_float.py
+++ b/pypy/jit/metainterp/test/test_float.py
@@ -1,5 +1,6 @@
-import math
+import math, sys
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
+from pypy.rlib.rarithmetic import intmask, r_uint
 
 
 class FloatTests:
@@ -45,6 +46,34 @@
         res = self.interp_operations(f, [-2.0])
         assert res == -8.5
 
+    def test_cast_float_to_int(self):
+        def g(f):
+            return int(f)
+        res = self.interp_operations(g, [-12345.9])
+        assert res == -12345
+
+    def test_cast_float_to_uint(self):
+        def g(f):
+            return intmask(r_uint(f))
+        res = self.interp_operations(g, [sys.maxint*2.0])
+        assert res == intmask(long(sys.maxint*2.0))
+        res = self.interp_operations(g, [-12345.9])
+        assert res == -12345
+
+    def test_cast_int_to_float(self):
+        def g(i):
+            return float(i)
+        res = self.interp_operations(g, [-12345])
+        assert type(res) is float and res == -12345.0
+
+    def test_cast_uint_to_float(self):
+        def g(i):
+            return float(r_uint(i))
+        res = self.interp_operations(g, [intmask(sys.maxint*2)])
+        assert type(res) is float and res == float(sys.maxint*2)
+        res = self.interp_operations(g, [-12345])
+        assert type(res) is float and res == float(long(r_uint(-12345)))
+
 
 class TestOOtype(FloatTests, OOJitMixin):
     pass
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -206,7 +206,7 @@
         self.make_enter_functions()
         self.rewrite_jit_merge_points(policy)
 
-        verbose = not self.cpu.translate_support_code
+        verbose = False # not self.cpu.translate_support_code
         self.codewriter.make_jitcodes(verbose=verbose)
         self.rewrite_can_enter_jits()
         self.rewrite_set_param()
diff --git a/pypy/module/__builtin__/app_io.py b/pypy/module/__builtin__/app_io.py
--- a/pypy/module/__builtin__/app_io.py
+++ b/pypy/module/__builtin__/app_io.py
@@ -71,7 +71,7 @@
         return line[:-1]
     return line
 
-def input(prompt=None):
+def input(prompt=''):
     """Equivalent to eval(raw_input(prompt))."""
     return eval(raw_input(prompt))
 
diff --git a/pypy/module/__builtin__/test/test_rawinput.py b/pypy/module/__builtin__/test/test_rawinput.py
--- a/pypy/module/__builtin__/test/test_rawinput.py
+++ b/pypy/module/__builtin__/test/test_rawinput.py
@@ -3,29 +3,32 @@
 
 class AppTestRawInput():
 
-    def test_raw_input(self):
+    def test_input_and_raw_input(self):
         import sys, StringIO
         for prompt, expected in [("def:", "abc/ def:/ghi\n"),
                                  ("", "abc/ /ghi\n"),
                                  (42, "abc/ 42/ghi\n"),
                                  (None, "abc/ None/ghi\n"),
                                  (Ellipsis, "abc/ /ghi\n")]:
-            save = sys.stdin, sys.stdout
-            try:
-                sys.stdin = StringIO.StringIO("foo\nbar\n")
-                out = sys.stdout = StringIO.StringIO()
-                print "abc",    # softspace = 1
-                out.write('/')
-                if prompt is Ellipsis:
-                    got = raw_input()
-                else:
-                    got = raw_input(prompt)
-                out.write('/')
-                print "ghi"
-            finally:
-                sys.stdin, sys.stdout = save
-            assert out.getvalue() == expected
-            assert got == "foo"
+            for inputfn, inputtext, gottext in [
+                    (raw_input, "foo\nbar\n", "foo"),
+                    (input, "40+2\n", 42)]:
+                save = sys.stdin, sys.stdout
+                try:
+                    sys.stdin = StringIO.StringIO(inputtext)
+                    out = sys.stdout = StringIO.StringIO()
+                    print "abc",    # softspace = 1
+                    out.write('/')
+                    if prompt is Ellipsis:
+                        got = inputfn()
+                    else:
+                        got = inputfn(prompt)
+                    out.write('/')
+                    print "ghi"
+                finally:
+                    sys.stdin, sys.stdout = save
+                assert out.getvalue() == expected
+                assert got == gottext
 
     def test_softspace(self):
         import sys
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -46,7 +46,7 @@
         assert loop.match_by_id("getitem", """
             i28 = call(ConstClass(ll_dict_lookup__dicttablePtr_objectPtr_Signed), p18, p6, i25, descr=...)
             ...
-            p33 = call(ConstClass(ll_get_value__dicttablePtr_Signed), p18, i28, descr=...)
+            p33 = getinteriorfield_gc(p31, i26, descr=<InteriorFieldDescr <GcPtrFieldDescr dictentry.value .*>>)
             ...
         """)
 
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -93,7 +93,8 @@
             i46 = call(ConstClass(ll_startswith__rpy_stringPtr_rpy_stringPtr), p28, ConstPtr(ptr45), descr=<BoolCallDescr>)
             guard_false(i46, descr=...)
             p51 = new_with_vtable(21136408)
-            setfield_gc(p51, _, descr=...)    # 6 setfields, but the order is dict-order-dependent
+            setfield_gc(p51, _, descr=...)    # 7 setfields, but the order is dict-order-dependent
+            setfield_gc(p51, _, descr=...)
             setfield_gc(p51, _, descr=...)
             setfield_gc(p51, _, descr=...)
             setfield_gc(p51, _, descr=...)
diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -120,6 +120,8 @@
             out.append_slice(s, last_literal, end)
             return out.build()
 
+        # This is only ever called if we're already unrolling _do_build_string
+        @jit.unroll_safe
         def _parse_field(self, start, end):
             s = self.template
             # Find ":" or "!"
@@ -149,6 +151,7 @@
                 i += 1
             return s[start:end], None, end
 
+        @jit.unroll_safe
         def _get_argument(self, name):
             # First, find the argument.
             space = self.space
@@ -207,6 +210,7 @@
                     raise OperationError(space.w_IndexError, w_msg)
             return self._resolve_lookups(w_arg, name, i, end)
 
+        @jit.unroll_safe
         def _resolve_lookups(self, w_obj, name, start, end):
             # Resolve attribute and item lookups.
             space = self.space
diff --git a/pypy/rlib/rerased.py b/pypy/rlib/rerased.py
--- a/pypy/rlib/rerased.py
+++ b/pypy/rlib/rerased.py
@@ -135,6 +135,8 @@
     _about_ = erase_int
 
     def compute_result_annotation(self, s_obj):
+        config = self.bookkeeper.annotator.translator.config
+        assert config.translation.taggedpointers, "need to enable tagged pointers to use erase_int"
         assert annmodel.SomeInteger().contains(s_obj)
         return SomeErased()
 
@@ -228,6 +230,8 @@
 
     def convert_const(self, value):
         if value._identity is _identity_for_ints:
+            config = self.rtyper.annotator.translator.config
+            assert config.translation.taggedpointers, "need to enable tagged pointers to use erase_int"
             return lltype.cast_int_to_ptr(self.lowleveltype, value._x * 2 + 1)
         bk = self.rtyper.annotator.bookkeeper
         s_obj = value._identity.get_input_annotation(bk)
diff --git a/pypy/rlib/test/test_rerased.py b/pypy/rlib/test/test_rerased.py
--- a/pypy/rlib/test/test_rerased.py
+++ b/pypy/rlib/test/test_rerased.py
@@ -10,6 +10,13 @@
 
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
+def make_annotator():
+    a = RPythonAnnotator()
+    a.translator.config.translation.taggedpointers = True
+    return a
+
+
+
 class X(object):
     pass
 
@@ -55,7 +62,7 @@
 def test_annotate_1():
     def f():
         return eraseX(X())
-    a = RPythonAnnotator()
+    a = make_annotator()
     s = a.build_types(f, [])
     assert isinstance(s, SomeErased)
 
@@ -66,7 +73,7 @@
         #assert not is_integer(e)
         x2 = uneraseX(e)
         return x2
-    a = RPythonAnnotator()
+    a = make_annotator()
     s = a.build_types(f, [])
     assert isinstance(s, annmodel.SomeInstance)
     assert s.classdef == a.bookkeeper.getuniqueclassdef(X)
@@ -77,7 +84,7 @@
         #assert is_integer(e)
         x2 = unerase_int(e)
         return x2
-    a = RPythonAnnotator()
+    a = make_annotator()
     s = a.build_types(f, [])
     assert isinstance(s, annmodel.SomeInteger)
 
@@ -105,7 +112,7 @@
         x = make(n)
         return check(x, n)
     #
-    a = RPythonAnnotator()
+    a = make_annotator()
     s = a.build_types(f, [int])
     assert isinstance(s, annmodel.SomeInteger)
 
@@ -135,7 +142,7 @@
             else:
                 return inst
     #
-    a = RPythonAnnotator()
+    a = make_annotator()
     s = a.build_types(f, [])
     assert isinstance(s, annmodel.SomeInstance)
     assert s.classdef == a.bookkeeper.getuniqueclassdef(A)
@@ -155,7 +162,7 @@
             e = e2
         return unerase(e)
     #
-    a = RPythonAnnotator()
+    a = make_annotator()
     s = a.build_types(f, [int])
     assert isinstance(s, annmodel.SomeInstance)
     assert s.classdef == a.bookkeeper.getuniqueclassdef(X)
@@ -165,11 +172,14 @@
     e1 = erase_int(42)
     def f(i):
         return unerase_int(e1)
-    a = RPythonAnnotator()
+    a = make_annotator()
     s = a.build_types(f, [int])
     assert isinstance(s, annmodel.SomeInteger)
 
 class BaseTestRErased(BaseRtypingTest):
+    def interpret(self, *args, **kwargs):
+        kwargs["taggedpointers"] = True
+        return BaseRtypingTest.interpret(self, *args, **kwargs)
     def test_rtype_1(self):
         def f():
             return eraseX(X())
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -1095,13 +1095,6 @@
             assert y >= 0
         return self.op_int_add_ovf(x, y)
 
-    def op_cast_float_to_int(self, f):
-        assert type(f) is float
-        try:
-            return ovfcheck(int(f))
-        except OverflowError:
-            self.make_llexception()
-
     def op_int_is_true(self, x):
         # special case
         if type(x) is CDefinedIntSymbolic:
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -15,12 +15,11 @@
     load_library_kwargs = {}
 
 import os
-from pypy import conftest
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.extfunc import ExtRegistryEntry
 from pypy.rlib.objectmodel import Symbolic, ComputedIntSymbolic
 from pypy.tool.uid import fixid
-from pypy.rlib.rarithmetic import r_uint, r_singlefloat, r_longfloat, base_int, intmask
+from pypy.rlib.rarithmetic import r_singlefloat, r_longfloat, base_int, intmask
 from pypy.annotation import model as annmodel
 from pypy.rpython.llinterp import LLInterpreter, LLException
 from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
@@ -531,6 +530,10 @@
     def __str__(self):
         return repr(self)
 
+    def _setparentstructure(self, parent, parentindex):
+        super(_parentable_mixin, self)._setparentstructure(parent, parentindex)
+        self._keepparent = parent   # always keep a strong ref
+
 class _struct_mixin(_parentable_mixin):
     """Mixin added to _struct containers when they become ctypes-based."""
     __slots__ = ()
@@ -566,7 +569,10 @@
         return 0, sys.maxint
 
     def getitem(self, index, uninitialized_ok=False):
-        return self._storage.contents._getitem(index, boundscheck=False)
+        res = self._storage.contents._getitem(index, boundscheck=False)
+        if isinstance(self._TYPE.OF, lltype.ContainerType):
+            res._obj._setparentstructure(self, index)
+        return res
 
     def setitem(self, index, value):
         self._storage.contents._setitem(index, value, boundscheck=False)
@@ -1279,6 +1285,8 @@
             self.intval = intmask(void_p.value)
 
     def __eq__(self, other):
+        if not other:
+            return self.intval == 0
         if isinstance(other, _llgcopaque):
             return self.intval == other.intval
         storage = object()
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -343,8 +343,8 @@
     'cast_uint_to_float':   LLOp(canfold=True),
     'cast_longlong_to_float' :LLOp(canfold=True),
     'cast_ulonglong_to_float':LLOp(canfold=True),
-    'cast_float_to_int':    LLOp(canraise=(OverflowError,), tryfold=True),
-    'cast_float_to_uint':   LLOp(canfold=True),    # XXX need OverflowError?
+    'cast_float_to_int':    LLOp(canfold=True),
+    'cast_float_to_uint':   LLOp(canfold=True),
     'cast_float_to_longlong' :LLOp(canfold=True),
     'cast_float_to_ulonglong':LLOp(canfold=True),
     'truncate_longlong_to_int':LLOp(canfold=True),
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -1522,7 +1522,7 @@
             and parentindex in (self._parent_type._names[0], 0)
             and self._TYPE._gckind == typeOf(parent)._gckind):
             # keep strong reference to parent, we share the same allocation
-            self._keepparent = parent 
+            self._keepparent = parent
 
     def _parentstructure(self, check=True):
         if self._wrparent is not None:
@@ -1730,7 +1730,8 @@
         # Keep the parent array alive, we share the same allocation.
         # Don't do it if we are inside a GC object, though -- it's someone
         # else's job to keep the GC object alive
-        if typeOf(top_container(parent))._gckind == 'raw':
+        if (typeOf(top_container(parent))._gckind == 'raw' or
+            hasattr(top_container(parent)._storage, 'contents')):  # ll2ctypes
             self._keepparent = parent
 
     def __str__(self):
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -355,6 +355,10 @@
     assert type(b) is bool
     return float(b)
 
+def op_cast_float_to_int(f):
+    assert type(f) is float
+    return intmask(int(f))
+
 def op_cast_float_to_uint(f):
     assert type(f) is float
     return r_uint(long(f))
diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -1,16 +1,14 @@
 from pypy.tool.pairtype import pairtype
-from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Constant
-from pypy.rpython.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
-     rtype_newdict
+from pypy.rpython.rdict import (AbstractDictRepr, AbstractDictIteratorRepr,
+     rtype_newdict)
 from pypy.rpython.lltypesystem import lltype
+from pypy.rlib import objectmodel, jit
 from pypy.rlib.rarithmetic import r_uint, intmask, LONG_BIT
-from pypy.rlib.objectmodel import hlinvoke
-from pypy.rpython import robject
-from pypy.rlib import objectmodel, jit
 from pypy.rpython import rmodel
 from pypy.rpython.error import TyperError
 
+
 HIGHEST_BIT = intmask(1 << (LONG_BIT - 1))
 MASK = intmask(HIGHEST_BIT - 1)
 
@@ -417,17 +415,16 @@
     ENTRIES = lltype.typeOf(entries).TO
     return ENTRIES.fasthashfn(entries[i].key)
 
- at jit.dont_look_inside
 def ll_get_value(d, i):
     return d.entries[i].value
 
 def ll_keyhash_custom(d, key):
     DICT = lltype.typeOf(d).TO
-    return hlinvoke(DICT.r_rdict_hashfn, d.fnkeyhash, key)
+    return objectmodel.hlinvoke(DICT.r_rdict_hashfn, d.fnkeyhash, key)
 
 def ll_keyeq_custom(d, key1, key2):
     DICT = lltype.typeOf(d).TO
-    return hlinvoke(DICT.r_rdict_eqfn, d.fnkeyeq, key1, key2)
+    return objectmodel.hlinvoke(DICT.r_rdict_eqfn, d.fnkeyeq, key1, key2)
 
 def ll_dict_len(d):
     return d.num_items
@@ -448,6 +445,8 @@
     i = ll_dict_lookup(d, key, hash)
     return _ll_dict_setitem_lookup_done(d, key, value, hash, i)
 
+# Leaving as dont_look_inside ATM, it has a few branches which could lead to
+# many bridges if we don't consider their possible frequency.
 @jit.dont_look_inside
 def _ll_dict_setitem_lookup_done(d, key, value, hash, i):
     valid = (i & HIGHEST_BIT) == 0
@@ -492,6 +491,8 @@
         raise KeyError
     _ll_dict_del(d, i)
 
+# XXX: Move the size checking and resize into a single call which is opauqe to
+# the JIT to avoid extra branches.
 @jit.dont_look_inside
 def _ll_dict_del(d, i):
     d.entries.mark_deleted(i)
@@ -532,6 +533,7 @@
 # ------- a port of CPython's dictobject.c's lookdict implementation -------
 PERTURB_SHIFT = 5
 
+ at jit.dont_look_inside
 def ll_dict_lookup(d, key, hash):
     entries = d.entries
     ENTRIES = lltype.typeOf(entries).TO
@@ -621,7 +623,6 @@
     d.num_items = 0
     d.resize_counter = DICT_INITSIZE * 2
     return d
-ll_newdict.oopspec = 'newdict()'
 
 def ll_newdict_size(DICT, length_estimate):
     length_estimate = (length_estimate // 2) * 3
@@ -633,7 +634,6 @@
     d.num_items = 0
     d.resize_counter = n * 2
     return d
-ll_newdict_size.oopspec = 'newdict()'
 
 # pypy.rpython.memory.lldict uses a dict based on Struct and Array
 # instead of GcStruct and GcArray, which is done by using different
@@ -866,7 +866,6 @@
         global_popitem_index.nextindex = base + counter
     return i
 
- at jit.dont_look_inside
 def ll_popitem(ELEM, dic):
     i = _ll_getnextitem(dic)
     entry = dic.entries[i]
diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
--- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
@@ -8,6 +8,7 @@
 from pypy.rpython.lltypesystem.ll2ctypes import uninitialized2ctypes
 from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED, force_cast
 from pypy.rpython.lltypesystem.ll2ctypes import cast_adr_to_int, get_ctypes_type
+from pypy.rpython.lltypesystem.ll2ctypes import _llgcopaque
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib import rposix
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -1349,6 +1350,11 @@
         round = ctypes2lltype(llmemory.GCREF, lltype2ctypes(opaque.hide()))
         assert Opaque.show(round) is opaque
 
+    def test_array_of_structs(self):
+        A = lltype.GcArray(lltype.Struct('x', ('v', lltype.Signed)))
+        a = lltype.malloc(A, 5)
+        a2 = ctypes2lltype(lltype.Ptr(A), lltype2ctypes(a))
+        assert a2._obj.getitem(0)._obj._parentstructure() is a2._obj
 
 class TestPlatform(object):
     def test_lib_on_libpaths(self):
@@ -1390,3 +1396,7 @@
         f = rffi.llexternal('f', [rffi.INT, rffi.INT], rffi.INT,
                             compilation_info=eci)
         assert f(3, 4) == 7
+
+    def test_llgcopaque_eq(self):
+        assert _llgcopaque(1) != None
+        assert _llgcopaque(0) == None
diff --git a/pypy/translator/c/database.py b/pypy/translator/c/database.py
--- a/pypy/translator/c/database.py
+++ b/pypy/translator/c/database.py
@@ -176,7 +176,7 @@
                      # introduced by the GC transformer, or the type_info_table
         return node
 
-    def get(self, obj):
+    def get(self, obj, funcgen=None):
         if isinstance(obj, CConstant):
             return obj.c_name  # without further checks
         T = typeOf(obj)
@@ -228,6 +228,8 @@
                     return '((%s) %d)' % (cdecl(self.gettype(T), ''),
                                           obj._obj)
                 node = self.getcontainernode(container)
+                if node._funccodegen_owner is None:
+                    node._funccodegen_owner = funcgen
                 return node.getptrname()
             else:
                 return '((%s) NULL)' % (cdecl(self.gettype(T), ''), )
@@ -284,14 +286,16 @@
             finish_callbacks.append(('GC transformer: finished tables',
                                      self.gctransformer.get_finish_tables()))
 
-        def add_dependencies(newdependencies):
+        def add_dependencies(newdependencies, parent=None):
             for value in newdependencies:
                 #if isinstance(value, _uninitialized):
                 #    continue
                 if isinstance(typeOf(value), ContainerType):
-                    self.getcontainernode(value)
+                    node = self.getcontainernode(value)
+                    if parent and node._funccodegen_owner is not None:
+                        node._funccodegen_owner = parent._funccodegen_owner
                 else:
-                    self.get(value)
+                    self.get(value, parent and parent._funccodegen_owner)
 
         while True:
             while True:
@@ -303,7 +307,7 @@
                 if i == len(self.containerlist):
                     break
                 node = self.containerlist[i]
-                add_dependencies(node.enum_dependencies())
+                add_dependencies(node.enum_dependencies(), node)
                 i += 1
                 self.completedcontainers = i
                 if i == show_i:
diff --git a/pypy/translator/c/gc.py b/pypy/translator/c/gc.py
--- a/pypy/translator/c/gc.py
+++ b/pypy/translator/c/gc.py
@@ -170,6 +170,7 @@
     nodekind = 'refcnt rtti'
     globalcontainer = True
     typename = 'void (@)(void *)'
+    _funccodegen_owner = None
 
     def __init__(self, db, T, obj):
         assert T == RuntimeTypeInfo
@@ -266,6 +267,7 @@
     nodekind = 'boehm rtti'
     globalcontainer = True
     typename = 'char @'
+    _funccodegen_owner = None
 
     def __init__(self, db, T, obj):
         assert T == RuntimeTypeInfo
diff --git a/pypy/translator/c/gcc/test/test_asmgcroot.py b/pypy/translator/c/gcc/test/test_asmgcroot.py
--- a/pypy/translator/c/gcc/test/test_asmgcroot.py
+++ b/pypy/translator/c/gcc/test/test_asmgcroot.py
@@ -21,6 +21,7 @@
         config = get_pypy_config(translating=True)
         config.translation.gc = cls.gcpolicy
         config.translation.gcrootfinder = "asmgcc"
+        config.translation.taggedpointers = getattr(cls, "taggedpointers", False)
         return config
 
     @classmethod
diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -682,8 +682,7 @@
     def getbasecfilefornode(self, node, basecname):
         # For FuncNode instances, use the python source filename (relative to
         # the top directory):
-        if hasattr(node.obj, 'graph'):
-            g = node.obj.graph
+        def invent_nice_name(g):
             # Lookup the filename from the function.
             # However, not all FunctionGraph objs actually have a "func":
             if hasattr(g, 'func'):
@@ -693,6 +692,15 @@
                     if pypkgpath:
                         relpypath =  localpath.relto(pypkgpath)
                         return relpypath.replace('.py', '.c')
+            return None
+        if hasattr(node.obj, 'graph'):
+            name = invent_nice_name(node.obj.graph)
+            if name is not None:
+                return name
+        elif node._funccodegen_owner is not None:
+            name = invent_nice_name(node._funccodegen_owner.graph)
+            if name is not None:
+                return "data_" + name
         return basecname
 
     def splitnodesimpl(self, basecname, nodes, nextra, nbetween,
diff --git a/pypy/translator/c/node.py b/pypy/translator/c/node.py
--- a/pypy/translator/c/node.py
+++ b/pypy/translator/c/node.py
@@ -485,6 +485,7 @@
         __slots__ = """db obj 
                        typename implementationtypename
                         name
+                        _funccodegen_owner
                         globalcontainer""".split()
     eci_name = '_compilation_info'
 
@@ -509,6 +510,7 @@
         if self.typename != self.implementationtypename:
             if db.gettypedefnode(T).extra_union_for_varlength:
                 self.name += '.b'
+        self._funccodegen_owner = None
 
     def getptrname(self):
         return '(&%s)' % self.name
@@ -842,6 +844,9 @@
         if self.funcgens:
             argnames = self.funcgens[0].argnames()  #Assume identical for all funcgens
             self.implementationtypename = self.db.gettype(self.T, argnames=argnames)
+            self._funccodegen_owner = self.funcgens[0]
+        else:
+            self._funccodegen_owner = None
 
     def basename(self):
         return self.obj._name
@@ -1005,6 +1010,7 @@
     globalcontainer = True
     typename = 'PyObject @'
     implementationtypename = 'PyObject *@'
+    _funccodegen_owner = None
 
     def __init__(self, db, T, obj):
         # obj is a _pyobject here; obj.value is the underlying CPython object
diff --git a/pypy/translator/c/primitive.py b/pypy/translator/c/primitive.py
--- a/pypy/translator/c/primitive.py
+++ b/pypy/translator/c/primitive.py
@@ -141,7 +141,12 @@
 
 def name_gcref(value, db):
     if value:
-        realobj = value._obj.container
+        obj = value._obj
+        if isinstance(obj, int):
+            # a tagged pointer
+            assert obj & 1 == 1
+            return '((%s) %d)' % (cdecl("void*", ''), obj)
+        realobj = obj.container
         realvalue = cast_opaque_ptr(Ptr(typeOf(realobj)), value)
         return db.get(realvalue)
     else:
diff --git a/pypy/translator/c/test/test_newgc.py b/pypy/translator/c/test/test_newgc.py
--- a/pypy/translator/c/test/test_newgc.py
+++ b/pypy/translator/c/test/test_newgc.py
@@ -1487,6 +1487,43 @@
         res = self.run("tagged")
         assert res == expected
 
+    def define_erased(cls):
+        from pypy.rlib import rerased
+        erase, unerase = rerased.new_erasing_pair("test")
+        class Unrelated(object):
+            pass
+
+        u = Unrelated()
+        u.tagged = True
+        u.x = rerased.erase_int(41)
+        class A(object):
+            pass
+        def fn():
+            n = 1
+            while n >= 0:
+                if u.tagged:
+                    n = rerased.unerase_int(u.x)
+                    a = A()
+                    a.n = n - 1
+                    u.x = erase(a)
+                    u.tagged = False
+                else:
+                    n = unerase(u.x).n
+                    u.x = rerased.erase_int(n - 1)
+                    u.tagged = True
+        def func():
+            rgc.collect() # check that a prebuilt erased integer doesn't explode
+            u.x = rerased.erase_int(1000)
+            u.tagged = True
+            fn()
+            return 1
+        return func
+
+    def test_erased(self):
+        expected = self.run_orig("erased")
+        res = self.run("erased")
+        assert res == expected
+
 from pypy.rlib.objectmodel import UnboxedValue
 
 class TaggedBase(object):


More information about the pypy-commit mailing list