Author: Spenser Andrew Bauman <saba...@gmail.com>
Branch: remove-getfield-pure
Changeset: r81514:b131bc726e2b
Date: 2015-12-31 11:49 -0500
http://bitbucket.org/pypy/pypy/changeset/b131bc726e2b/

Log:    Sync with master

diff too long, truncating to 2000 out of 2109 lines

diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.4.1
+Version: 1.4.2
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.4.1"
-__version_info__ = (1, 4, 1)
+__version__ = "1.4.2"
+__version_info__ = (1, 4, 2)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/pypy/module/_cffi_backend/cglob.py 
b/pypy/module/_cffi_backend/cglob.py
--- a/pypy/module/_cffi_backend/cglob.py
+++ b/pypy/module/_cffi_backend/cglob.py
@@ -3,6 +3,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.module._cffi_backend.cdataobj import W_CData
 from pypy.module._cffi_backend import newtype
+from rpython.rlib import rgil
 from rpython.rlib.objectmodel import we_are_translated
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -26,7 +27,9 @@
             if not we_are_translated():
                 FNPTR = rffi.CCallback([], rffi.VOIDP)
                 fetch_addr = rffi.cast(FNPTR, self.fetch_addr)
+                rgil.release()
                 result = fetch_addr()
+                rgil.acquire()
             else:
                 # careful in translated versions: we need to call fetch_addr,
                 # but in a GIL-releasing way.  The easiest is to invoke a
diff --git a/pypy/module/_cffi_backend/ctypefunc.py 
b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -423,7 +423,9 @@
             exchange_offset += rffi.getintfield(self.atypes[i], 'c_size')
 
         # store the exchange data size
-        cif_descr.exchange_size = exchange_offset
+        # we also align it to the next multiple of 8, in an attempt to
+        # work around bugs(?) of libffi (see cffi issue #241)
+        cif_descr.exchange_size = self.align_arg(exchange_offset)
 
     def fb_extra_fields(self, cif_descr):
         cif_descr.abi = self.fabi
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -386,7 +386,7 @@
             return
 
         @cpython_api([PyObject, PyObject], PyObject,
-                     error=lltype.nullptr(rffi.VOIDP.TO), external=True)
+                     external=True)
         @func_renamer("cpyext_tp_getattro_%s" % (typedef.name,))
         def slot_tp_getattro(space, w_self, w_name):
             return space.call_function(getattr_fn, w_self, w_name)
diff --git a/pypy/module/cpyext/test/test_typeobject.py 
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -414,15 +414,26 @@
                      return NULL;
                  }
                  PyObject *name = PyString_FromString("attr1");
-                 PyIntObject *attr1 = obj->ob_type->tp_getattro(obj, name);
-                 if (attr1->ob_ival != value->ob_ival)
+                 PyIntObject *attr = obj->ob_type->tp_getattro(obj, name);
+                 if (attr->ob_ival != value->ob_ival)
                  {
                      PyErr_SetString(PyExc_ValueError,
                                      "tp_getattro returned wrong value");
                      return NULL;
                  }
                  Py_DECREF(name);
-                 Py_DECREF(attr1);
+                 Py_DECREF(attr);
+                 name = PyString_FromString("attr2");
+                 attr = obj->ob_type->tp_getattro(obj, name);
+                 if (attr == NULL && 
PyErr_ExceptionMatches(PyExc_AttributeError))
+                 {
+                     PyErr_Clear();
+                 } else {
+                     PyErr_SetString(PyExc_ValueError,
+                                     "tp_getattro should have raised");
+                     return NULL;
+                 }
+                 Py_DECREF(name);
                  Py_RETURN_TRUE;
              '''
              )
@@ -637,7 +648,7 @@
                 IntLikeObject *intObj;
                 long intval;
 
-                if (!PyArg_ParseTuple(args, "i", &intval))
+                if (!PyArg_ParseTuple(args, "l", &intval))
                     return NULL;
 
                 IntLike_Type.tp_as_number = &intlike_as_number;
@@ -657,7 +668,7 @@
                 IntLikeObjectNoOp *intObjNoOp;
                 long intval;
 
-                if (!PyArg_ParseTuple(args, "i", &intval))
+                if (!PyArg_ParseTuple(args, "l", &intval))
                     return NULL;
 
                 IntLike_Type_NoOp.tp_flags |= Py_TPFLAGS_CHECKTYPES;
diff --git a/pypy/module/pypyjit/test_pypy_c/test_struct.py 
b/pypy/module/pypyjit/test_pypy_c/test_struct.py
--- a/pypy/module/pypyjit/test_pypy_c/test_struct.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_struct.py
@@ -45,7 +45,7 @@
 
         # the newstr and the strsetitems are because the string is forced,
         # which is in turn because the optimizer doesn't know how to handle a
-        # getarrayitem_gc_i on a virtual string. It could be improved, but it
+        # gc_load_indexed_i on a virtual string. It could be improved, but it
         # is also true that in real life cases struct.unpack is called on
         # strings which come from the outside, so it's a minor issue.
         assert loop.match_by_id("unpack", """
@@ -55,17 +55,17 @@
             strsetitem(p88, 1, i14)
             strsetitem(p88, 2, i17)
             strsetitem(p88, 3, i20)
-            i91 = getarrayitem_gc_i(p88, 0, descr=<ArrayS 4>)
+            i91 = gc_load_indexed_i(p88, 0, 1, _, -4)
         """)
 
     def test_struct_object(self):
         def main(n):
             import struct
-            s = struct.Struct("i")
+            s = struct.Struct("ii")
             i = 1
             while i < n:
-                buf = s.pack(i)       # ID: pack
-                x = s.unpack(buf)[0]  # ID: unpack
+                buf = s.pack(-1, i)     # ID: pack
+                x = s.unpack(buf)[1]    # ID: unpack
                 i += x / i
             return i
 
@@ -88,10 +88,15 @@
 
         assert loop.match_by_id('unpack', """
             # struct.unpack
-            p88 = newstr(4)
-            strsetitem(p88, 0, i11)
-            strsetitem(p88, 1, i14)
-            strsetitem(p88, 2, i17)
-            strsetitem(p88, 3, i20)
-            i91 = getarrayitem_gc_i(p88, 0, descr=<ArrayS 4>)
+            p88 = newstr(8)
+            strsetitem(p88, 0, 255)
+            strsetitem(p88, 1, 255)
+            strsetitem(p88, 2, 255)
+            strsetitem(p88, 3, 255)
+            strsetitem(p88, 4, i11)
+            strsetitem(p88, 5, i14)
+            strsetitem(p88, 6, i17)
+            strsetitem(p88, 7, i20)
+            i90 = gc_load_indexed_i(p88, 0, 1, _, -4)
+            i91 = gc_load_indexed_i(p88, 4, 1, _, -4)
         """)
diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py
--- a/rpython/annotator/signature.py
+++ b/rpython/annotator/signature.py
@@ -100,6 +100,7 @@
         self.argtypes = argtypes
 
     def __call__(self, funcdesc, inputcells):
+        from rpython.rlib.objectmodel import NOT_CONSTANT
         from rpython.rtyper.lltypesystem import lltype
         args_s = []
         from rpython.annotator import model as annmodel
@@ -115,6 +116,9 @@
                 args_s.append(s_input)
             elif argtype is None:
                 args_s.append(inputcells[i])     # no change
+            elif argtype is NOT_CONSTANT:
+                from rpython.annotator.model import not_const
+                args_s.append(not_const(inputcells[i]))
             else:
                 args_s.append(annotation(argtype, 
bookkeeper=funcdesc.bookkeeper))
         if len(inputcells) != len(args_s):
diff --git a/rpython/jit/backend/arm/regalloc.py 
b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -804,7 +804,7 @@
         base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
         ofs = boxes[1].getint()
         value_loc = self.make_sure_var_in_reg(boxes[2], boxes)
-        size = abs(boxes[3].getint())
+        size = boxes[3].getint()
         ofs_size = default_imm_size if size < 8 else VMEM_imm_size
         if check_imm_arg(ofs, size=ofs_size):
             ofs_loc = imm(ofs)
@@ -849,7 +849,7 @@
         index_loc = self.make_sure_var_in_reg(boxes[1], boxes)
         assert boxes[3].getint() == 1    # scale
         ofs = boxes[4].getint()
-        size = abs(boxes[5].getint())
+        size = boxes[5].getint()
         assert check_imm_arg(ofs)
         return [value_loc, base_loc, index_loc, imm(size), imm(ofs)]
 
diff --git a/rpython/jit/backend/llgraph/runner.py 
b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -13,6 +13,7 @@
 
 from rpython.rtyper.llinterp import LLInterpreter, LLException
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
+from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.rtyper import rclass
 
 from rpython.rlib.clibffi import FFI_DEFAULT_ABI
@@ -635,18 +636,9 @@
         return array.getlength()
 
     def bh_getarrayitem_gc(self, a, index, descr):
+        a = support.cast_arg(lltype.Ptr(descr.A), a)
+        array = a._obj
         assert index >= 0
-        if descr.A is descr.OUTERA:
-            a = support.cast_arg(lltype.Ptr(descr.A), a)
-        else:
-            # we use rffi.cast instead of support.cast_arg because the types
-            # might not be "compatible" enough from the lltype point of
-            # view. In particular, this happens when we use
-            # str_storage_getitem, in which an rpy_string is casted to
-            # rpy_string_as_Signed (or similar)
-            a = rffi.cast(lltype.Ptr(descr.OUTERA), a)
-            a = getattr(a, descr.OUTERA._arrayfld)
-        array = a._obj
         return support.cast_result(descr.A.OF, array.getitem(index))
 
     bh_getarrayitem_gc_pure_i = bh_getarrayitem_gc
@@ -711,6 +703,24 @@
         else:
             return self.bh_raw_load_i(struct, offset, descr)
 
+    def bh_gc_load_indexed_i(self, struct, index, scale, base_ofs, bytes):
+        if   bytes == 1: T = rffi.UCHAR
+        elif bytes == 2: T = rffi.USHORT
+        elif bytes == 4: T = rffi.UINT
+        elif bytes == 8: T = rffi.ULONGLONG
+        elif bytes == -1: T = rffi.SIGNEDCHAR
+        elif bytes == -2: T = rffi.SHORT
+        elif bytes == -4: T = rffi.INT
+        elif bytes == -8: T = rffi.LONGLONG
+        else: raise NotImplementedError(bytes)
+        x = llop.gc_load_indexed(T, struct, index, scale, base_ofs)
+        return lltype.cast_primitive(lltype.Signed, x)
+
+    def bh_gc_load_indexed_f(self, struct, index, scale, base_ofs, bytes):
+        if bytes != 8:
+            raise Exception("gc_load_indexed_f is only for 'double'!")
+        return llop.gc_load_indexed(rffi.DOUBLE, struct, index, scale, 
base_ofs)
+
     def bh_increment_debug_counter(self, addr):
         p = rffi.cast(rffi.CArrayPtr(lltype.Signed), addr)
         p[0] += 1
diff --git a/rpython/jit/backend/llsupport/llmodel.py 
b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -725,6 +725,16 @@
     def bh_raw_load_f(self, addr, offset, descr):
         return self.read_float_at_mem(addr, offset)
 
+    def bh_gc_load_indexed_i(self, addr, index, scale, base_ofs, bytes):
+        offset = base_ofs + scale * index
+        return self.read_int_at_mem(addr, offset, abs(bytes), bytes < 0)
+
+    def bh_gc_load_indexed_f(self, addr, index, scale, base_ofs, bytes):
+        # only for 'double'!
+        assert bytes == rffi.sizeof(lltype.Float)
+        offset = base_ofs + scale * index
+        return self.read_float_at_mem(addr, offset)
+
     def bh_new(self, sizedescr):
         return self.gc_ll_descr.gc_malloc(sizedescr)
 
diff --git a/rpython/jit/backend/llsupport/rewrite.py 
b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -126,11 +126,11 @@
     def emit_gc_store_or_indexed(self, op, ptr_box, index_box, value_box,
                                  itemsize, factor, offset):
         factor, offset, index_box = \
-                self._emit_mul_add_if_factor_offset_not_supported(index_box,
+                self._emit_mul_if_factor_offset_not_supported(index_box,
                         factor, offset)
         #
-        if factor == 1 and offset == 0:
-            args = [ptr_box, index_box, value_box, ConstInt(itemsize)]
+        if index_box is None:
+            args = [ptr_box, ConstInt(offset), value_box, ConstInt(itemsize)]
             newload = ResOperation(rop.GC_STORE, args)
         else:
             args = [ptr_box, index_box, value_box, ConstInt(factor),
@@ -153,18 +153,15 @@
         index_box = op.getarg(1)
         self.emit_gc_load_or_indexed(op, ptr_box, index_box, itemsize, 1, ofs, 
sign)
 
-    def _emit_mul_add_if_factor_offset_not_supported(self, index_box, factor, 
offset):
-        orig_factor = factor
-        # factor
-        must_manually_load_const = False # offset != 0 and not 
self.cpu.load_constant_offset
-        if factor != 1 and (factor not in self.cpu.load_supported_factors or \
-                            (not index_box.is_constant() and 
must_manually_load_const)):
-            # enter here if the factor is supported by the cpu
-            # OR the index is not constant and a new resop must be emitted
-            # to add the offset
-            if isinstance(index_box, ConstInt):
-                index_box = ConstInt(index_box.value * factor)
-            else:
+    def _emit_mul_if_factor_offset_not_supported(self, index_box,
+                                                 factor, offset):
+        # Returns (factor, offset, index_box) where index_box is either
+        # a non-constant BoxInt or None.
+        if isinstance(index_box, ConstInt):
+            return 1, index_box.value * factor + offset, None
+        else:
+            if factor != 1 and factor not in self.cpu.load_supported_factors:
+                # the factor is supported by the cpu
                 # x & (x - 1) == 0 is a quick test for power of 2
                 assert factor > 0
                 if (factor & (factor - 1)) == 0:
@@ -174,20 +171,13 @@
                     index_box = ResOperation(rop.INT_MUL,
                             [index_box, ConstInt(factor)])
                 self.emit_op(index_box)
-            factor = 1
-        # adjust the constant offset
-        #if must_manually_load_const:
-        #    if isinstance(index_box, ConstInt):
-        #        index_box = ConstInt(index_box.value + offset)
-        #    else:
-        #        index_box = ResOperation(rop.INT_ADD, [index_box, 
ConstInt(offset)])
-        #        self.emit_op(index_box)
-        #    offset = 0
-        return factor, offset, index_box
+                factor = 1
+            return factor, offset, index_box
 
-    def emit_gc_load_or_indexed(self, op, ptr_box, index_box, itemsize, 
factor, offset, sign, type='i'):
+    def emit_gc_load_or_indexed(self, op, ptr_box, index_box, itemsize,
+                                factor, offset, sign, type='i'):
         factor, offset, index_box = \
-                self._emit_mul_add_if_factor_offset_not_supported(index_box,
+                self._emit_mul_if_factor_offset_not_supported(index_box,
                         factor, offset)
         #
         if sign:
@@ -197,8 +187,8 @@
         optype = type
         if op is not None:
             optype = op.type
-        if factor == 1 and offset == 0:
-            args = [ptr_box, index_box, ConstInt(itemsize)]
+        if index_box is None:
+            args = [ptr_box, ConstInt(offset), ConstInt(itemsize)]
             newload = ResOperation(OpHelpers.get_gc_load(optype), args)
         else:
             args = [ptr_box, index_box, ConstInt(factor),
@@ -547,9 +537,8 @@
             ofs, size, sign = unpack_fielddescr(descrs.jfi_frame_depth)
             if sign:
                 size = -size
-            args = [ConstInt(frame_info), ConstInt(0), ConstInt(1),
-                    ConstInt(ofs), ConstInt(size)]
-            size = ResOperation(rop.GC_LOAD_INDEXED_I, args)
+            args = [ConstInt(frame_info), ConstInt(ofs), ConstInt(size)]
+            size = ResOperation(rop.GC_LOAD_I, args)
             self.emit_op(size)
             frame = ResOperation(rop.NEW_ARRAY, [size],
                                  descr=descrs.arraydescr)
@@ -560,9 +549,8 @@
             ofs, size, sign = unpack_fielddescr(descrs.jfi_frame_size)
             if sign:
                 size = -size
-            args = [ConstInt(frame_info), ConstInt(0), ConstInt(1),
-                    ConstInt(ofs), ConstInt(size)]
-            size = ResOperation(rop.GC_LOAD_INDEXED_I, args)
+            args = [ConstInt(frame_info), ConstInt(ofs), ConstInt(size)]
+            size = ResOperation(rop.GC_LOAD_I, args)
             self.emit_op(size)
             frame = self.gen_malloc_nursery_varsize_frame(size)
             self.gen_initialize_tid(frame, descrs.arraydescr.tid)
@@ -612,15 +600,12 @@
             descr = self.cpu.getarraydescr_for_frame(arg.type)
             assert self.cpu.JITFRAME_FIXED_SIZE & 1 == 0
             _, itemsize, _ = self.cpu.unpack_arraydescr_size(descr)
-            index = index_list[i] // itemsize # index is in bytes
-            # emit GC_LOAD_INDEXED
-            itemsize, basesize, _ = unpack_arraydescr(descr)
-            factor, offset, index_box = \
-                    
self._emit_mul_add_if_factor_offset_not_supported(ConstInt(index),
-                            itemsize, basesize)
-            args = [frame, index_box, arg, ConstInt(factor),
-                    ConstInt(offset), ConstInt(itemsize)]
-            self.emit_op(ResOperation(rop.GC_STORE_INDEXED, args))
+            array_offset = index_list[i]   # index, already measured in bytes
+            # emit GC_STORE
+            _, basesize, _ = unpack_arraydescr(descr)
+            offset = basesize + array_offset
+            args = [frame, ConstInt(offset), arg, ConstInt(itemsize)]
+            self.emit_op(ResOperation(rop.GC_STORE, args))
 
         descr = op.getdescr()
         assert isinstance(descr, JitCellToken)
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py 
b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -30,13 +30,26 @@
 
 class RewriteTests(object):
     def check_rewrite(self, frm_operations, to_operations, **namespace):
-        def trans_getarray_to_load(descr):
-            size = descr.basesize
-            if descr.is_item_signed():
-                size = -size
-            return ','.join([str(n) for n in [descr.itemsize,
-                                              descr.basesize,
-                                              size]])
+        def setfield(baseptr, newvalue, descr):
+            assert isinstance(baseptr, str)
+            assert isinstance(newvalue, (str, int))
+            assert not isinstance(descr, (str, int))
+            return 'gc_store(%s, %d, %s, %d)' % (baseptr, descr.offset,
+                                                 newvalue, descr.field_size)
+        def setarrayitem(baseptr, index, newvalue, descr):
+            assert isinstance(baseptr, str)
+            assert isinstance(index, (str, int))
+            assert isinstance(newvalue, (str, int))
+            assert not isinstance(descr, (str, int))
+            if isinstance(index, int):
+                offset = descr.basesize + index * descr.itemsize
+                return 'gc_store(%s, %d, %s, %d)' % (baseptr, offset,
+                                                     newvalue, descr.itemsize)
+            else:
+                return 'gc_store_indexed(%s, %s, %s, %d, %d, %s)' % (
+                    baseptr, index, newvalue,
+                    descr.itemsize, descr.basesize, descr.itemsize)
+        #
         WORD = globals()['WORD']
         S = lltype.GcStruct('S', ('x', lltype.Signed),
                                  ('y', lltype.Signed))
@@ -376,7 +389,7 @@
             gc_store(p1, 0, 5678, 8)
             p2 = nursery_ptr_increment(p1, %(tdescr.size)d)
             gc_store(p2, 0, 1234, 8)
-            gc_store(p1, %(tdescr.gc_fielddescrs[0].offset)s, 0, 
%(tdescr.gc_fielddescrs[0].offset)s)
+            %(setfield('p1', 0, tdescr.gc_fielddescrs[0]))s
             jump()
         """)
 
@@ -485,7 +498,7 @@
         """, """
         [i0]
         p0 = call_malloc_nursery_varsize(1, 1, i0, descr=strdescr)
-        gc_store_indexed(p0, 0, i0, 1, %(strlendescr.offset)s, 
%(strlendescr.field_size)s)
+        gc_store(p0, %(strlendescr.offset)s, i0, %(strlendescr.field_size)s)
         gc_store(p0, 0, 0, %(strlendescr.field_size)s)
         jump(i0)
         """)
@@ -611,19 +624,19 @@
                       %(strdescr.basesize + 16 * strdescr.itemsize + \
                         unicodedescr.basesize + 10 * unicodedescr.itemsize)d)
             gc_store(p0, 0,  %(strdescr.tid)d, %(tiddescr.field_size)s)
-            gc_store_indexed(p0, 0,  14, 1, %(strlendescr.offset)s, 
%(strlendescr.field_size)s)
+            gc_store(p0, %(strlendescr.offset)s, 14, 
%(strlendescr.field_size)s)
             gc_store(p0, 0,  0, %(strhashdescr.field_size)s)
             p1 = nursery_ptr_increment(p0, %(strdescr.basesize + 16 * 
strdescr.itemsize)d)
             gc_store(p1, 0,  %(unicodedescr.tid)d, %(tiddescr.field_size)s)
-            gc_store_indexed(p1, 0,  10, 1, %(unicodelendescr.offset)s, 
%(unicodelendescr.field_size)s)
+            gc_store(p1, %(unicodelendescr.offset)s, 10, 
%(unicodelendescr.field_size)s)
             gc_store(p1, 0,  0, %(unicodehashdescr.field_size)s)
             p2 = call_malloc_nursery_varsize(2, %(unicodedescr.itemsize)d, i2,\
                                 descr=unicodedescr)
-            gc_store_indexed(p2, 0,  i2, 1, %(unicodelendescr.offset)s, 
%(unicodelendescr.field_size)s)
+            gc_store(p2, %(unicodelendescr.offset)s, i2, 
%(unicodelendescr.field_size)s)
             gc_store(p2, 0,  0, %(unicodehashdescr.field_size)s)
             p3 = call_malloc_nursery_varsize(1, 1, i2, \
                                 descr=strdescr)
-            gc_store_indexed(p3, 0,  i2, 1, %(strlendescr.offset)s, 
%(strlendescr.field_size)s)
+            gc_store(p3, %(strlendescr.offset)s, i2, 
%(strlendescr.field_size)s)
             gc_store(p3, 0,  0, %(strhashdescr.field_size)s)
             jump()
         """)
@@ -636,7 +649,7 @@
         """, """
             [p1, p2]
             cond_call_gc_wb(p1, descr=wbdescr)
-            gc_store_indexed(p1, 0,  p2, 1, %(tzdescr.offset)s, 
%(tzdescr.field_size)s)
+            gc_store(p1, %(tzdescr.offset)s, p2, %(tzdescr.field_size)s)
             jump()
         """)
 
@@ -650,7 +663,7 @@
         """, """
             [p1, i2, p3]
             cond_call_gc_wb(p1, descr=wbdescr)
-            gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p1', 'i2', 'p3', cdescr))s
             jump()
         """)
 
@@ -671,7 +684,7 @@
             zero_array(p1, 0, 129, descr=cdescr)
             call_n(123456)
             cond_call_gc_wb(p1, descr=wbdescr)
-            gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p1', 'i2', 'p3', cdescr))s
             jump()
         """)
 
@@ -693,7 +706,7 @@
             zero_array(p1, 0, 130, descr=cdescr)
             call_n(123456)
             cond_call_gc_wb_array(p1, i2, descr=wbdescr)
-            gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p1', 'i2', 'p3', cdescr))s
             jump()
         """)
 
@@ -705,7 +718,7 @@
         """, """
             [p1, i2, p3]
             cond_call_gc_wb_array(p1, i2, descr=wbdescr)
-            gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p1', 'i2', 'p3', cdescr))s
             jump()
         """)
 
@@ -725,7 +738,7 @@
             zero_array(p1, 0, 5, descr=cdescr)
             label(p1, i2, p3)
             cond_call_gc_wb_array(p1, i2, descr=wbdescr)
-            gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p1', 'i2', 'p3', cdescr))s
             jump()
         """)
 
@@ -743,12 +756,12 @@
         size = interiorzdescr.arraydescr.itemsize
         self.check_rewrite("""
             [p1, p2]
-            setinteriorfield_gc(p1, 0, p2, descr=interiorzdescr)
+            setinteriorfield_gc(p1, 7, p2, descr=interiorzdescr)
             jump(p1, p2)
         """, """
             [p1, p2]
-            cond_call_gc_wb_array(p1, 0, descr=wbdescr)
-            gc_store_indexed(p1, 0, p2, %(scale)s, %(offset)s, %(size)s)
+            cond_call_gc_wb_array(p1, 7, descr=wbdescr)
+            gc_store(p1, %(offset + 7 * scale)s, p2, %(size)s)
             jump(p1, p2)
         """, interiorzdescr=interiorzdescr, scale=scale,
              offset=offset, size=size)
@@ -763,7 +776,7 @@
             [p1]
             p0 = call_malloc_nursery(%(tdescr.size)d)
             gc_store(p0, 0,  5678, %(tiddescr.field_size)s)
-            gc_store_indexed(p0, 0,  p1, 1, %(tzdescr.offset)s, 
%(tzdescr.field_size)s)
+            gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s)
             jump()
         """)
 
@@ -781,7 +794,7 @@
             p1 = nursery_ptr_increment(p0, %(tdescr.size)d)
             gc_store(p1, 0,  1234, %(tiddescr.field_size)s)
             # <<<no cond_call_gc_wb here>>>
-            gc_store_indexed(p0, 0,  p1, 1, %(tzdescr.offset)s, 
%(tzdescr.field_size)s)
+            gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s)
             jump()
         """)
 
@@ -798,7 +811,7 @@
             gc_store(p0, 0,  8111, %(tiddescr.field_size)s)
             gc_store(p0, 0,  5, %(clendescr.field_size)s)
             zero_array(p0, 0, 5, descr=cdescr)
-            gc_store_indexed(p0, i2, p1, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 'i2', 'p1', cdescr))s
             jump()
         """)
 
@@ -816,8 +829,8 @@
             gc_store(p0, 0,  8111, %(tiddescr.field_size)s)
             gc_store(p0, 0,  5, %(clendescr.field_size)s)
             zero_array(p0, 2, 3, descr=cdescr)
-            gc_store_indexed(p0, 1, p1, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 0, p2, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 1, 'p1', cdescr))s
+            %(setarrayitem('p0', 0, 'p2', cdescr))s
             jump()
         """)
 
@@ -835,8 +848,8 @@
             gc_store(p0, 0,  8111, %(tiddescr.field_size)s)
             gc_store(p0, 0,  5, %(clendescr.field_size)s)
             zero_array(p0, 0, 3, descr=cdescr)
-            gc_store_indexed(p0, 3, p1, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 4, p2, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 3, 'p1', cdescr))s
+            %(setarrayitem('p0', 4, 'p2', cdescr))s
             jump()
         """)
 
@@ -855,9 +868,9 @@
             gc_store(p0, 0,  8111, %(tiddescr.field_size)s)
             gc_store(p0, 0,  5, %(clendescr.field_size)s)
             zero_array(p0, 0, 5, descr=cdescr)
-            gc_store_indexed(p0, 3, p1, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 2, p2, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 3, 'p1', cdescr))s
+            %(setarrayitem('p0', 2, 'p2', cdescr))s
+            %(setarrayitem('p0', 1, 'p2', cdescr))s
             jump()
         """)
 
@@ -878,11 +891,11 @@
             gc_store(p0, 0,  8111, %(tiddescr.field_size)s)
             gc_store(p0, 0,  5, %(clendescr.field_size)s)
             zero_array(p0, 5, 0, descr=cdescr)
-            gc_store_indexed(p0, 3, p1, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 4, p2, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 0, p1, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 2, p2, %(trans_getarray_to_load(cdescr))s)
-            gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 3, 'p1', cdescr))s
+            %(setarrayitem('p0', 4, 'p2', cdescr))s
+            %(setarrayitem('p0', 0, 'p1', cdescr))s
+            %(setarrayitem('p0', 2, 'p2', cdescr))s
+            %(setarrayitem('p0', 1, 'p2', cdescr))s
             jump()
         """)
 
@@ -901,10 +914,10 @@
             gc_store(p0, 0,  8111, %(tiddescr.field_size)s)
             gc_store(p0, 0,  5, %(clendescr.field_size)s)
             zero_array(p0, 1, 4, descr=cdescr)
-            gc_store_indexed(p0, 0, p1, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 0, 'p1', cdescr))s
             call_n(321321)
             cond_call_gc_wb(p0, descr=wbdescr)
-            gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 1, 'p2', cdescr))s
             jump()
         """)
 
@@ -923,10 +936,10 @@
             gc_store(p0, 0,  8111, %(tiddescr.field_size)s)
             gc_store(p0, 0,  5, %(clendescr.field_size)s)
             zero_array(p0, 1, 4, descr=cdescr)
-            gc_store_indexed(p0, 0, p1, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 0, 'p1', cdescr))s
             label(p0, p2)
             cond_call_gc_wb_array(p0, 1, descr=wbdescr)
-            gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s)
+            %(setarrayitem('p0', 1, 'p2', cdescr))s
             jump()
         """)
 
@@ -955,7 +968,7 @@
             gc_store(p0, 0,  i3, %(blendescr.field_size)s)
             zero_array(p0, 0, i3, descr=bdescr)
             cond_call_gc_wb_array(p0, 0, descr=wbdescr)
-            gc_store_indexed(p0, 0, p1, 1, %(bdescr.basesize)s, 1)
+            %(setarrayitem('p0', 0, 'p1', bdescr))s
             jump()
         """)
 
@@ -991,10 +1004,10 @@
             gc_store(p0, %(tdescr.gc_fielddescrs[0].offset)s, 0, 
%(tdescr.gc_fielddescrs[0].offset)s)
             p1 = call_malloc_nursery_varsize(1, 1, i0, \
                                 descr=strdescr)
-            gc_store_indexed(p1, 0,  i0, 1, %(strlendescr.offset)s, 
%(strlendescr.field_size)s)
+            gc_store(p1, %(strlendescr.offset)s, i0, 
%(strlendescr.field_size)s)
             gc_store(p1, 0,  0, %(strhashdescr.field_size)s)
             cond_call_gc_wb(p0, descr=wbdescr)
-            gc_store_indexed(p0, 0,  p1, 1, %(tzdescr.offset)s, 
%(tzdescr.field_size)s)
+            gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s)
             jump()
         """)
 
@@ -1012,7 +1025,7 @@
             gc_store(p0, %(tdescr.gc_fielddescrs[0].offset)s, 0, 
%(tdescr.gc_fielddescrs[0].offset)s)
             label(p0, p1)
             cond_call_gc_wb(p0, descr=wbdescr)
-            gc_store_indexed(p0, 0,  p1, 1, %(tzdescr.offset)s, 
%(tzdescr.field_size)s)
+            gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s)
             jump()
         """)
 
@@ -1025,8 +1038,8 @@
         """, """
             [p0, p1, p2]
             cond_call_gc_wb(p0, descr=wbdescr)
-            gc_store_indexed(p0, 0,  p1, 1, %(tzdescr.offset)s, 
%(tzdescr.field_size)s)
-            gc_store_indexed(p0, 0,  p2, 1, %(tzdescr.offset)s, 
%(tzdescr.field_size)s)
+            gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s)
+            gc_store(p0, %(tzdescr.offset)s, p2, %(tzdescr.field_size)s)
             jump(p1, p2, p0)
         """)
 
@@ -1036,20 +1049,20 @@
         i2 = call_assembler_i(i0, f0, descr=casmdescr)
         """, """
         [i0, f0]
-        i1 = gc_load_indexed_i(ConstClass(frame_info), 0, 1, 1, 
%(jfi_frame_size.field_size)s)
+        i1 = gc_load_i(ConstClass(frame_info), %(jfi_frame_size.offset)s, 
%(jfi_frame_size.field_size)s)
         p1 = call_malloc_nursery_varsize_frame(i1)
         gc_store(p1, 0,  0, %(tiddescr.field_size)s)
-        i2 = gc_load_indexed_i(ConstClass(frame_info), 0, 1, 1, 
%(jfi_frame_depth.field_size)s)
-        gc_store_indexed(p1, 0, 0, 1, 1, %(jf_extra_stack_depth.field_size)s)
-        gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_savedata.field_size)s)
-        gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_force_descr.field_size)s)
-        gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_descr.field_size)s)
-        gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_guard_exc.field_size)s)
-        gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_forward.field_size)s)
+        i2 = gc_load_i(ConstClass(frame_info), %(jfi_frame_depth.offset)s, 
%(jfi_frame_depth.field_size)s)
+        %(setfield('p1', 0, jf_extra_stack_depth))s
+        %(setfield('p1', 'NULL', jf_savedata))s
+        %(setfield('p1', 'NULL', jf_force_descr))s
+        %(setfield('p1', 'NULL', jf_descr))s
+        %(setfield('p1', 'NULL', jf_guard_exc))s
+        %(setfield('p1', 'NULL', jf_forward))s
         gc_store(p1, 0, i2, %(framelendescr.field_size)s)
-        gc_store_indexed(p1, 0, ConstClass(frame_info), 1, 1, 
%(jf_frame_info.field_size)s)
-        gc_store_indexed(p1, 0, i0, 8, 3, 8)
-        gc_store_indexed(p1, 1, f0, 8, 5, 8)
+        %(setfield('p1', 'ConstClass(frame_info)', jf_frame_info))s
+        gc_store(p1, 3, i0, 8)
+        gc_store(p1, 13, f0, 8)
         i3 = call_assembler_i(p1, descr=casmdescr)
         """)
 
@@ -1101,7 +1114,7 @@
             p0 = call_malloc_nursery(%(tdescr.size)d)
             gc_store(p0, 0,  5678, %(tiddescr.field_size)s)
             gc_store(p0, %(tdescr.gc_fielddescrs[0].offset)s, 0, 
%(tdescr.gc_fielddescrs[0].offset)s)
-            p1 = gc_load_indexed_r(p0, 0, 1, %(tzdescr.field_size)s, 
%(tzdescr.field_size)s)
+            p1 = gc_load_r(p0, %(tzdescr.offset)s, %(tzdescr.field_size)s)
             jump(p1)
         """)
 
@@ -1155,23 +1168,19 @@
         #    'i5 = int_add(i1,%(raw_sfdescr.basesize)s);'
         #    'gc_store(p0,i5,i2,%(raw_sfdescr.itemsize)s)'],
         [True, (1,2,4,8), 'i3 = getfield_gc_f(p0,descr=ydescr)' '->'
-           'i3 = 
gc_load_indexed_f(p0,0,1,%(ydescr.offset)s,%(ydescr.field_size)s)'],
-        [True, (1,2,4,8), 'i3 = getfield_gc_f(p0,descr=ydescr)' '->'
-           'i3 = 
gc_load_indexed_f(p0,0,1,%(ydescr.offset)s,%(ydescr.field_size)s)'],
-        [True, (1,2,4,8), 'i3 = setfield_raw(p0,i1,descr=ydescr)' '->'
-           'i3 = gc_store_indexed(p0,0,i1,1,'
-           '%(ydescr.offset)s,%(ydescr.field_size)s)'],
-        [True, (1,2,4,8), 'i3 = setfield_gc(p0,p0,descr=zdescr)' '->'
+           'i3 = gc_load_f(p0,%(ydescr.offset)s,%(ydescr.field_size)s)'],
+        [True, (1,2,4,8), 'setfield_raw(p0,i1,descr=ydescr)' '->'
+           'gc_store(p0,%(ydescr.offset)s,i1,%(ydescr.field_size)s)'],
+        [True, (1,2,4,8), 'setfield_gc(p0,p0,descr=zdescr)' '->'
            'cond_call_gc_wb(p0, descr=wbdescr);'
-           'i3 = gc_store_indexed(p0,0,p0,1,'
-           '%(zdescr.offset)s,%(zdescr.field_size)s)'],
+           'gc_store(p0,%(zdescr.offset)s,p0,%(zdescr.field_size)s)'],
         [False, (1,), 'i3 = arraylen_gc(p0, descr=adescr)' '->'
                       'i3 = gc_load_i(p0,0,%(adescr.itemsize)s)'],
         #[False, (1,),  'i3 = strlen(p0)' '->'
         #               'i3 = gc_load_i(p0,'
         #               '%(strlendescr.offset)s,%(strlendescr.field_size)s)'],
         [True,  (1,),  'i3 = strlen(p0)' '->'
-                       'i3 = gc_load_indexed_i(p0,0,1,'
+                       'i3 = gc_load_i(p0,'
                                  '%(strlendescr.offset)s,'
                                  '%(strlendescr.field_size)s)'],
         #[False, (1,),  'i3 = unicodelen(p0)' '->'
@@ -1179,7 +1188,7 @@
         #                       '%(unicodelendescr.offset)s,'
         #                       '%(unicodelendescr.field_size)s)'],
         [True,  (1,),  'i3 = unicodelen(p0)' '->'
-                       'i3 = gc_load_indexed_i(p0,0,1,'
+                       'i3 = gc_load_i(p0,'
                                '%(unicodelendescr.offset)s,'
                                '%(unicodelendescr.field_size)s)'],
 
diff --git a/rpython/jit/backend/ppc/opassembler.py 
b/rpython/jit/backend/ppc/opassembler.py
--- a/rpython/jit/backend/ppc/opassembler.py
+++ b/rpython/jit/backend/ppc/opassembler.py
@@ -20,7 +20,7 @@
                                                  PPCBuilder, PPCGuardToken)
 from rpython.jit.backend.ppc.regalloc import TempPtr, TempInt
 from rpython.jit.backend.llsupport import symbolic, jitframe
-from rpython.jit.backend.llsupport.descr import InteriorFieldDescr, CallDescr
+from rpython.jit.backend.llsupport.descr import CallDescr
 from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
 from rpython.rtyper.lltypesystem import rstr, rffi, lltype
 from rpython.rtyper.annlowlevel import cast_instance_to_gcref
@@ -706,8 +706,10 @@
 
     _mixin_ = True
 
-    def _write_to_mem(self, value_loc, base_loc, ofs, size):
-        if size.value == 8:
+    def _write_to_mem(self, value_loc, base_loc, ofs, size_loc):
+        assert size_loc.is_imm()
+        size = size_loc.value
+        if size == 8:
             if value_loc.is_fp_reg():
                 if ofs.is_imm():
                     self.mc.stfd(value_loc.value, base_loc.value, ofs.value)
@@ -718,17 +720,17 @@
                     self.mc.std(value_loc.value, base_loc.value, ofs.value)
                 else:
                     self.mc.stdx(value_loc.value, base_loc.value, ofs.value)
-        elif size.value == 4:
+        elif size == 4:
             if ofs.is_imm():
                 self.mc.stw(value_loc.value, base_loc.value, ofs.value)
             else:
                 self.mc.stwx(value_loc.value, base_loc.value, ofs.value)
-        elif size.value == 2:
+        elif size == 2:
             if ofs.is_imm():
                 self.mc.sth(value_loc.value, base_loc.value, ofs.value)
             else:
                 self.mc.sthx(value_loc.value, base_loc.value, ofs.value)
-        elif size.value == 1:
+        elif size == 1:
             if ofs.is_imm():
                 self.mc.stb(value_loc.value, base_loc.value, ofs.value)
             else:
@@ -736,18 +738,35 @@
         else:
             assert 0, "size not supported"
 
-    def emit_setfield_gc(self, op, arglocs, regalloc):
-        value_loc, base_loc, ofs, size = arglocs
-        self._write_to_mem(value_loc, base_loc, ofs, size)
+    def emit_gc_store(self, op, arglocs, regalloc):
+        value_loc, base_loc, ofs_loc, size_loc = arglocs
+        self._write_to_mem(value_loc, base_loc, ofs_loc, size_loc)
 
-    emit_setfield_raw = emit_setfield_gc
-    emit_zero_ptr_field = emit_setfield_gc
+    def _apply_offset(self, index_loc, ofs_loc):
+        # If offset != 0 then we have to add it here.  Note that
+        # mc.addi() would not be valid with operand r0.
+        assert ofs_loc.is_imm()                # must be an immediate...
+        assert _check_imm_arg(ofs_loc.getint())   # ...that fits 16 bits
+        assert index_loc is not r.SCRATCH2
+        # (simplified version of _apply_scale())
+        if ofs_loc.value > 0:
+            self.mc.addi(r.SCRATCH2.value, index_loc.value, ofs_loc.value)
+            index_loc = r.SCRATCH2
+        return index_loc
 
-    def _load_from_mem(self, res, base_loc, ofs, size, signed):
+    def emit_gc_store_indexed(self, op, arglocs, regalloc):
+        base_loc, index_loc, value_loc, ofs_loc, size_loc = arglocs
+        index_loc = self._apply_offset(index_loc, ofs_loc)
+        self._write_to_mem(value_loc, base_loc, index_loc, size_loc)
+
+    def _load_from_mem(self, res, base_loc, ofs, size_loc, sign_loc):
         # res, base_loc, ofs, size and signed are all locations
         assert base_loc is not r.SCRATCH
-        sign = signed.value
-        if size.value == 8:
+        assert size_loc.is_imm()
+        size = size_loc.value
+        assert sign_loc.is_imm()
+        sign = sign_loc.value
+        if size == 8:
             if res.is_fp_reg():
                 if ofs.is_imm():
                     self.mc.lfd(res.value, base_loc.value, ofs.value)
@@ -758,7 +777,7 @@
                     self.mc.ld(res.value, base_loc.value, ofs.value)
                 else:
                     self.mc.ldx(res.value, base_loc.value, ofs.value)
-        elif size.value == 4:
+        elif size == 4:
             if IS_PPC_64 and sign:
                 if ofs.is_imm():
                     self.mc.lwa(res.value, base_loc.value, ofs.value)
@@ -769,7 +788,7 @@
                     self.mc.lwz(res.value, base_loc.value, ofs.value)
                 else:
                     self.mc.lwzx(res.value, base_loc.value, ofs.value)
-        elif size.value == 2:
+        elif size == 2:
             if sign:
                 if ofs.is_imm():
                     self.mc.lha(res.value, base_loc.value, ofs.value)
@@ -780,7 +799,7 @@
                     self.mc.lhz(res.value, base_loc.value, ofs.value)
                 else:
                     self.mc.lhzx(res.value, base_loc.value, ofs.value)
-        elif size.value == 1:
+        elif size == 1:
             if ofs.is_imm():
                 self.mc.lbz(res.value, base_loc.value, ofs.value)
             else:
@@ -790,22 +809,28 @@
         else:
             assert 0, "size not supported"
 
-    def _genop_getfield(self, op, arglocs, regalloc):
-        base_loc, ofs, res, size, sign = arglocs
-        self._load_from_mem(res, base_loc, ofs, size, sign)
+    def _genop_gc_load(self, op, arglocs, regalloc):
+        base_loc, ofs_loc, res_loc, size_loc, sign_loc = arglocs
+        self._load_from_mem(res_loc, base_loc, ofs_loc, size_loc, sign_loc)
 
-    emit_getfield_gc_i = _genop_getfield
-    emit_getfield_gc_r = _genop_getfield
-    emit_getfield_gc_f = _genop_getfield
-    emit_getfield_gc_pure_i = _genop_getfield
-    emit_getfield_gc_pure_r = _genop_getfield
-    emit_getfield_gc_pure_f = _genop_getfield
-    emit_getfield_raw_i = _genop_getfield
-    emit_getfield_raw_f = _genop_getfield
+    emit_gc_load_i = _genop_gc_load
+    emit_gc_load_r = _genop_gc_load
+    emit_gc_load_f = _genop_gc_load
+
+    def _genop_gc_load_indexed(self, op, arglocs, regalloc):
+        base_loc, index_loc, res_loc, ofs_loc, size_loc, sign_loc = arglocs
+        index_loc = self._apply_offset(index_loc, ofs_loc)
+        self._load_from_mem(res_loc, base_loc, index_loc, size_loc, sign_loc)
+
+    emit_gc_load_indexed_i = _genop_gc_load_indexed
+    emit_gc_load_indexed_r = _genop_gc_load_indexed
+    emit_gc_load_indexed_f = _genop_gc_load_indexed
 
     SIZE2SCALE = dict([(1<<_i, _i) for _i in range(32)])
 
     def _multiply_by_constant(self, loc, multiply_by, scratch_loc):
+        # XXX should die together with _apply_scale() but can't because
+        # of emit_zero_array() and malloc_cond_varsize() at the moment
         assert loc.is_reg()
         if multiply_by == 1:
             return loc
@@ -827,6 +852,9 @@
         return scratch_loc
 
     def _apply_scale(self, ofs, index_loc, itemsize):
+        # XXX should die now that getarrayitem and getinteriorfield are gone
+        # but can't because of emit_zero_array() at the moment
+
         # For arrayitem and interiorfield reads and writes: this returns an
         # offset suitable for use in ld/ldx or similar instructions.
         # The result will be either the register r2 or a 16-bit immediate.
@@ -857,44 +885,6 @@
                 index_loc = r.SCRATCH2
             return index_loc
 
-    def _genop_getarray_or_interiorfield(self, op, arglocs, regalloc):
-        (base_loc, index_loc, res_loc, ofs_loc,
-            itemsize, fieldsize, fieldsign) = arglocs
-        ofs_loc = self._apply_scale(ofs_loc, index_loc, itemsize)
-        self._load_from_mem(res_loc, base_loc, ofs_loc, fieldsize, fieldsign)
-
-    emit_getinteriorfield_gc_i = _genop_getarray_or_interiorfield
-    emit_getinteriorfield_gc_r = _genop_getarray_or_interiorfield
-    emit_getinteriorfield_gc_f = _genop_getarray_or_interiorfield
-
-    def emit_setinteriorfield_gc(self, op, arglocs, regalloc):
-        (base_loc, index_loc, value_loc, ofs_loc,
-            itemsize, fieldsize) = arglocs
-        ofs_loc = self._apply_scale(ofs_loc, index_loc, itemsize)
-        self._write_to_mem(value_loc, base_loc, ofs_loc, fieldsize)
-
-    emit_setinteriorfield_raw = emit_setinteriorfield_gc
-
-    def emit_arraylen_gc(self, op, arglocs, regalloc):
-        res, base_loc, ofs = arglocs
-        self.mc.load(res.value, base_loc.value, ofs.value)
-
-    emit_setarrayitem_gc = emit_setinteriorfield_gc
-    emit_setarrayitem_raw = emit_setarrayitem_gc
-
-    emit_getarrayitem_gc_i = _genop_getarray_or_interiorfield
-    emit_getarrayitem_gc_r = _genop_getarray_or_interiorfield
-    emit_getarrayitem_gc_f = _genop_getarray_or_interiorfield
-    emit_getarrayitem_gc_pure_i = _genop_getarray_or_interiorfield
-    emit_getarrayitem_gc_pure_r = _genop_getarray_or_interiorfield
-    emit_getarrayitem_gc_pure_f = _genop_getarray_or_interiorfield
-    emit_getarrayitem_raw_i = _genop_getarray_or_interiorfield
-    emit_getarrayitem_raw_f = _genop_getarray_or_interiorfield
-
-    emit_raw_store = emit_setarrayitem_gc
-    emit_raw_load_i = _genop_getarray_or_interiorfield
-    emit_raw_load_f = _genop_getarray_or_interiorfield
-
     def _copy_in_scratch2(self, loc):
         if loc.is_imm():
             self.mc.li(r.SCRATCH2.value, loc.value)
@@ -998,10 +988,6 @@
 
     _mixin_ = True
 
-    emit_strlen = FieldOpAssembler._genop_getfield
-    emit_strgetitem = FieldOpAssembler._genop_getarray_or_interiorfield
-    emit_strsetitem = FieldOpAssembler.emit_setarrayitem_gc
-
     def emit_copystrcontent(self, op, arglocs, regalloc):
         self._emit_copycontent(arglocs, is_unicode=False)
 
@@ -1059,12 +1045,8 @@
 
 
 class UnicodeOpAssembler(object):
-
     _mixin_ = True
-
-    emit_unicodelen = FieldOpAssembler._genop_getfield
-    emit_unicodegetitem = FieldOpAssembler._genop_getarray_or_interiorfield
-    emit_unicodesetitem = FieldOpAssembler.emit_setarrayitem_gc
+    # empty!
 
 
 class AllocOpAssembler(object):
diff --git a/rpython/jit/backend/ppc/regalloc.py 
b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -17,12 +17,9 @@
 from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.rtyper.annlowlevel import cast_instance_to_gcref
 from rpython.jit.backend.llsupport import symbolic
-from rpython.jit.backend.llsupport.descr import ArrayDescr
+from rpython.jit.backend.llsupport.descr import unpack_arraydescr
 import rpython.jit.backend.ppc.register as r
 import rpython.jit.backend.ppc.condition as c
-from rpython.jit.backend.llsupport.descr import unpack_arraydescr
-from rpython.jit.backend.llsupport.descr import unpack_fielddescr
-from rpython.jit.backend.llsupport.descr import unpack_interiorfielddescr
 from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
 from rpython.rlib.objectmodel import we_are_translated
 from rpython.rlib.debug import debug_print
@@ -691,159 +688,69 @@
                                  src_locations2, dst_locations2, fptmploc)
         return []
 
-    def prepare_setfield_gc(self, op):
-        ofs, size, _ = unpack_fielddescr(op.getdescr())
+    def prepare_gc_store(self, op):
         base_loc = self.ensure_reg(op.getarg(0))
-        value_loc = self.ensure_reg(op.getarg(1))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
-        return [value_loc, base_loc, ofs_loc, imm(size)]
+        ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(1))
+        value_loc = self.ensure_reg(op.getarg(2))
+        size_loc = self.ensure_reg_or_any_imm(op.getarg(3))
+        return [value_loc, base_loc, ofs_loc, size_loc]
 
-    prepare_setfield_raw = prepare_setfield_gc
+    def _prepare_gc_load(self, op):
+        base_loc = self.ensure_reg(op.getarg(0))
+        ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(1))
+        self.free_op_vars()
+        res_loc = self.force_allocate_reg(op)
+        size_box = op.getarg(2)
+        assert isinstance(size_box, ConstInt)
+        nsize = size_box.value      # negative for "signed"
+        size_loc = imm(abs(nsize))
+        if nsize < 0:
+            sign = 1
+        else:
+            sign = 0
+        return [base_loc, ofs_loc, res_loc, size_loc, imm(sign)]
 
-    def _prepare_getfield(self, op):
-        ofs, size, sign = unpack_fielddescr(op.getdescr())
+    prepare_gc_load_i = _prepare_gc_load
+    prepare_gc_load_r = _prepare_gc_load
+    prepare_gc_load_f = _prepare_gc_load
+
+    def prepare_gc_store_indexed(self, op):
         base_loc = self.ensure_reg(op.getarg(0))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
+        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
+        value_loc = self.ensure_reg(op.getarg(2))
+        assert op.getarg(3).getint() == 1    # scale
+        ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(4))
+        assert ofs_loc.is_imm()  # the arg(4) should always be a small constant
+        size_loc = self.ensure_reg_or_any_imm(op.getarg(5))
+        return [base_loc, index_loc, value_loc, ofs_loc, size_loc]
+
+    def _prepare_gc_load_indexed(self, op):
+        base_loc = self.ensure_reg(op.getarg(0))
+        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
+        assert op.getarg(2).getint() == 1    # scale
+        ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(3))
+        assert ofs_loc.is_imm()  # the arg(3) should always be a small constant
         self.free_op_vars()
-        res = self.force_allocate_reg(op)
-        return [base_loc, ofs_loc, res, imm(size), imm(sign)]
+        res_loc = self.force_allocate_reg(op)
+        size_box = op.getarg(4)
+        assert isinstance(size_box, ConstInt)
+        nsize = size_box.value      # negative for "signed"
+        size_loc = imm(abs(nsize))
+        if nsize < 0:
+            sign = 1
+        else:
+            sign = 0
+        return [base_loc, index_loc, res_loc, ofs_loc, size_loc, imm(sign)]
 
-    prepare_getfield_gc_i = _prepare_getfield
-    prepare_getfield_gc_r = _prepare_getfield
-    prepare_getfield_gc_f = _prepare_getfield
-    prepare_getfield_raw_i = _prepare_getfield
-    prepare_getfield_raw_f = _prepare_getfield
-    prepare_getfield_gc_pure_i = _prepare_getfield
-    prepare_getfield_gc_pure_r = _prepare_getfield
-    prepare_getfield_gc_pure_f = _prepare_getfield
+    prepare_gc_load_indexed_i = _prepare_gc_load_indexed
+    prepare_gc_load_indexed_r = _prepare_gc_load_indexed
+    prepare_gc_load_indexed_f = _prepare_gc_load_indexed
 
     def prepare_increment_debug_counter(self, op):
         base_loc = self.ensure_reg(op.getarg(0))
         temp_loc = r.SCRATCH2
         return [base_loc, temp_loc]
 
-    def _prepare_getinteriorfield(self, op):
-        t = unpack_interiorfielddescr(op.getdescr())
-        ofs, itemsize, fieldsize, sign = t
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
-        self.free_op_vars()
-        result_loc = self.force_allocate_reg(op)
-        return [base_loc, index_loc, result_loc, ofs_loc,
-                imm(itemsize), imm(fieldsize), imm(sign)]
-
-    prepare_getinteriorfield_gc_i = _prepare_getinteriorfield
-    prepare_getinteriorfield_gc_r = _prepare_getinteriorfield
-    prepare_getinteriorfield_gc_f = _prepare_getinteriorfield
-
-    def prepare_setinteriorfield_gc(self, op):
-        t = unpack_interiorfielddescr(op.getdescr())
-        ofs, itemsize, fieldsize, _ = t
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        value_loc = self.ensure_reg(op.getarg(2))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
-        return [base_loc, index_loc, value_loc, ofs_loc,
-                imm(itemsize), imm(fieldsize)]
-
-    prepare_setinteriorfield_raw = prepare_setinteriorfield_gc
-
-    def prepare_arraylen_gc(self, op):
-        arraydescr = op.getdescr()
-        assert isinstance(arraydescr, ArrayDescr)
-        ofs = arraydescr.lendescr.offset
-        assert _check_imm_arg(ofs)
-        base_loc = self.ensure_reg(op.getarg(0))
-        self.free_op_vars()
-        res = self.force_allocate_reg(op)
-        return [res, base_loc, imm(ofs)]
-
-    def prepare_setarrayitem_gc(self, op):
-        size, ofs, _ = unpack_arraydescr(op.getdescr())
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        value_loc = self.ensure_reg(op.getarg(2))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
-        imm_size = imm(size)
-        return [base_loc, index_loc, value_loc, ofs_loc,
-                imm_size, imm_size]
-
-    prepare_setarrayitem_raw = prepare_setarrayitem_gc
-
-    def prepare_raw_store(self, op):
-        size, ofs, _ = unpack_arraydescr(op.getdescr())
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        value_loc = self.ensure_reg(op.getarg(2))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
-        return [base_loc, index_loc, value_loc, ofs_loc,
-                imm(1), imm(size)]
-
-    def _prepare_getarrayitem(self, op):
-        size, ofs, sign = unpack_arraydescr(op.getdescr())
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
-        self.free_op_vars()
-        result_loc = self.force_allocate_reg(op)
-        imm_size = imm(size)
-        return [base_loc, index_loc, result_loc, ofs_loc,
-                imm_size, imm_size, imm(sign)]
-
-    prepare_getarrayitem_gc_i = _prepare_getarrayitem
-    prepare_getarrayitem_gc_r = _prepare_getarrayitem
-    prepare_getarrayitem_gc_f = _prepare_getarrayitem
-    prepare_getarrayitem_raw_i = _prepare_getarrayitem
-    prepare_getarrayitem_raw_f = _prepare_getarrayitem
-    prepare_getarrayitem_gc_pure_i = _prepare_getarrayitem
-    prepare_getarrayitem_gc_pure_r = _prepare_getarrayitem
-    prepare_getarrayitem_gc_pure_f = _prepare_getarrayitem
-
-    def _prepare_raw_load(self, op):
-        size, ofs, sign = unpack_arraydescr(op.getdescr())
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
-        self.free_op_vars()
-        result_loc = self.force_allocate_reg(op)
-        return [base_loc, index_loc, result_loc, ofs_loc,
-                imm(1), imm(size), imm(sign)]
-
-    prepare_raw_load_i = _prepare_raw_load
-    prepare_raw_load_f = _prepare_raw_load
-
-    def prepare_strlen(self, op):
-        basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
-                                             self.cpu.translate_support_code)
-        base_loc = self.ensure_reg(op.getarg(0))
-        self.free_op_vars()
-        result_loc = self.force_allocate_reg(op)
-        return [base_loc, imm(ofs_length), result_loc, imm(WORD), imm(0)]
-
-    def prepare_strgetitem(self, op):
-        basesize, itemsize, _ = symbolic.get_array_token(rstr.STR,
-                                    self.cpu.translate_support_code)
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize))
-        self.free_op_vars()
-        result_loc = self.force_allocate_reg(op)
-        imm_size = imm(itemsize)
-        return [base_loc, index_loc, result_loc, ofs_loc,
-                imm_size, imm_size, imm(0)]
-
-    def prepare_strsetitem(self, op):
-        basesize, itemsize, _ = symbolic.get_array_token(rstr.STR,
-                                    self.cpu.translate_support_code)
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        value_loc = self.ensure_reg(op.getarg(2))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize))
-        imm_size = imm(itemsize)
-        return [base_loc, index_loc, value_loc, ofs_loc,
-                imm_size, imm_size]
-
     def prepare_copystrcontent(self, op):
         src_ptr_loc = self.ensure_reg(op.getarg(0))
         dst_ptr_loc = self.ensure_reg(op.getarg(1))
@@ -856,37 +763,6 @@
 
     prepare_copyunicodecontent = prepare_copystrcontent
 
-    def prepare_unicodelen(self, op):
-        basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
-                                             self.cpu.translate_support_code)
-        base_loc = self.ensure_reg(op.getarg(0))
-        self.free_op_vars()
-        result_loc = self.force_allocate_reg(op)
-        return [base_loc, imm(ofs_length), result_loc, imm(WORD), imm(0)]
-
-    def prepare_unicodegetitem(self, op):
-        basesize, itemsize, _ = symbolic.get_array_token(rstr.UNICODE,
-                                    self.cpu.translate_support_code)
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize))
-        self.free_op_vars()
-        result_loc = self.force_allocate_reg(op)
-        imm_size = imm(itemsize)
-        return [base_loc, index_loc, result_loc, ofs_loc,
-                imm_size, imm_size, imm(0)]
-
-    def prepare_unicodesetitem(self, op):
-        basesize, itemsize, _ = symbolic.get_array_token(rstr.UNICODE,
-                                    self.cpu.translate_support_code)
-        base_loc = self.ensure_reg(op.getarg(0))
-        index_loc = self.ensure_reg_or_any_imm(op.getarg(1))
-        value_loc = self.ensure_reg(op.getarg(2))
-        ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize))
-        imm_size = imm(itemsize)
-        return [base_loc, index_loc, value_loc, ofs_loc,
-                imm_size, imm_size]
-
     prepare_same_as_i = helper.prepare_unary_op
     prepare_same_as_r = helper.prepare_unary_op
     prepare_same_as_f = helper.prepare_unary_op
@@ -1078,12 +954,6 @@
         arglocs = self._prepare_guard(op)
         return arglocs
 
-    def prepare_zero_ptr_field(self, op):
-        base_loc = self.ensure_reg(op.getarg(0))
-        ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(1))
-        value_loc = self.ensure_reg(ConstInt(0))
-        return [value_loc, base_loc, ofs_loc, imm(WORD)]
-
     def prepare_zero_array(self, op):
         itemsize, ofs, _ = unpack_arraydescr(op.getdescr())
         base_loc = self.ensure_reg(op.getarg(0))
diff --git a/rpython/jit/backend/ppc/runner.py 
b/rpython/jit/backend/ppc/runner.py
--- a/rpython/jit/backend/ppc/runner.py
+++ b/rpython/jit/backend/ppc/runner.py
@@ -21,6 +21,9 @@
     IS_64_BIT = True
     backend_name = 'ppc64'
 
+    # can an ISA instruction handle a factor to the offset?
+    load_supported_factors = (1,)
+
     from rpython.jit.backend.ppc.register import JITFRAME_FIXED_SIZE
     frame_reg = r.SP
     all_reg_indexes = [-1] * 32
diff --git a/rpython/jit/backend/x86/regalloc.py 
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -4,8 +4,7 @@
 
 import os, sys
 from rpython.jit.backend.llsupport import symbolic
-from rpython.jit.backend.llsupport.descr import (ArrayDescr, CallDescr,
-    unpack_arraydescr, unpack_fielddescr, unpack_interiorfielddescr)
+from rpython.jit.backend.llsupport.descr import CallDescr, unpack_arraydescr
 from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
 from rpython.jit.backend.llsupport.regalloc import (FrameManager, BaseRegalloc,
      RegisterManager, TempVar, compute_vars_longevity, is_comparison_or_ovf_op,
@@ -1039,7 +1038,8 @@
         base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
         size_box = op.getarg(3)
         assert isinstance(size_box, ConstInt)
-        size = abs(size_box.value)
+        size = size_box.value
+        assert size >= 1
         if size == 1:
             need_lower_byte = True
         else:
@@ -1061,7 +1061,8 @@
         assert isinstance(size_box, ConstInt)
         factor = scale_box.value
         offset = offset_box.value
-        size = abs(size_box.value)
+        size = size_box.value
+        assert size >= 1
         if size == 1:
             need_lower_byte = True
         else:
@@ -1083,9 +1084,9 @@
         result_loc = self.force_allocate_reg(op)
         size_box = op.getarg(2)
         assert isinstance(size_box, ConstInt)
-        size = size_box.value
-        size_loc = imm(abs(size))
-        if size < 0:
+        nsize = size_box.value      # negative for "signed"
+        size_loc = imm(abs(nsize))
+        if nsize < 0:
             sign_loc = imm1
         else:
             sign_loc = imm0
@@ -1108,9 +1109,9 @@
         assert isinstance(size_box, ConstInt)
         scale = scale_box.value
         offset = offset_box.value
-        size = size_box.value
-        size_loc = imm(abs(size))
-        if size < 0:
+        nsize = size_box.value      # negative for "signed"
+        size_loc = imm(abs(nsize))
+        if nsize < 0:
             sign_loc = imm1
         else:
             sign_loc = imm0
diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1021,18 +1021,20 @@
             kind = getkind(op.result.concretetype)[0]
             return SpaceOperation('getinteriorfield_gc_%s' % kind, args,
                                   op.result)
-        elif isinstance(op.args[0].concretetype.TO, lltype.GcStruct):
-            # special-case 2: GcStruct with Array field
-            v_inst, c_field, v_index = op.args
-            STRUCT = v_inst.concretetype.TO
-            ARRAY = getattr(STRUCT, c_field.value)
-            assert isinstance(ARRAY, lltype.Array)
-            arraydescr = self.cpu.arraydescrof(STRUCT)
-            kind = getkind(op.result.concretetype)[0]
-            assert kind in ('i', 'f')
-            return SpaceOperation('getarrayitem_gc_%s' % kind,
-                                  [op.args[0], v_index, arraydescr],
-                                  op.result)
+        #elif isinstance(op.args[0].concretetype.TO, lltype.GcStruct):
+        #    # special-case 2: GcStruct with Array field
+        #    ---was added in the faster-rstruct branch,---
+        #    ---no longer directly supported---
+        #    v_inst, c_field, v_index = op.args
+        #    STRUCT = v_inst.concretetype.TO
+        #    ARRAY = getattr(STRUCT, c_field.value)
+        #    assert isinstance(ARRAY, lltype.Array)
+        #    arraydescr = self.cpu.arraydescrof(STRUCT)
+        #    kind = getkind(op.result.concretetype)[0]
+        #    assert kind in ('i', 'f')
+        #    return SpaceOperation('getarrayitem_gc_%s' % kind,
+        #                          [op.args[0], v_index, arraydescr],
+        #                          op.result)
         else:
             assert False, 'not supported'
 
@@ -1084,6 +1086,25 @@
         return SpaceOperation('raw_load_%s' % kind,
                               [op.args[0], op.args[1], descr], op.result)
 
+    def rewrite_op_gc_load_indexed(self, op):
+        T = op.result.concretetype
+        kind = getkind(T)[0]
+        assert kind != 'r'
+        descr = self.cpu.arraydescrof(rffi.CArray(T))
+        if (not isinstance(op.args[2], Constant) or
+            not isinstance(op.args[3], Constant)):
+            raise NotImplementedError("gc_load_indexed: 'scale' and 'base_ofs'"
+                                      " should be constants")
+        # xxx hard-code the size in bytes at translation time, which is
+        # probably fine and avoids lots of issues later
+        bytes = descr.get_item_size_in_bytes()
+        if descr.is_item_signed():
+            bytes = -bytes
+        c_bytes = Constant(bytes, lltype.Signed)
+        return SpaceOperation('gc_load_indexed_%s' % kind,
+                              [op.args[0], op.args[1],
+                               op.args[2], op.args[3], c_bytes], op.result)
+
     def _rewrite_equality(self, op, opname):
         arg0, arg1 = op.args
         if isinstance(arg0, Constant) and not arg0.value:
diff --git a/rpython/jit/metainterp/blackhole.py 
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1434,6 +1434,13 @@
     def bhimpl_raw_load_f(cpu, addr, offset, arraydescr):
         return cpu.bh_raw_load_f(addr, offset, arraydescr)
 
+    @arguments("cpu", "r", "i", "i", "i", "i", returns="i")
+    def bhimpl_gc_load_indexed_i(cpu, addr, index, scale, base_ofs, bytes):
+        return cpu.bh_gc_load_indexed_i(addr, index,scale,base_ofs, bytes)
+    @arguments("cpu", "r", "i", "i", "i", "i", returns="f")
+    def bhimpl_gc_load_indexed_f(cpu, addr, index, scale, base_ofs, bytes):
+        return cpu.bh_gc_load_indexed_f(addr, index,scale,base_ofs, bytes)
+
     @arguments("r", "d", "d")
     def bhimpl_record_quasiimmut_field(struct, fielddescr, mutatefielddescr):
         pass
diff --git a/rpython/jit/metainterp/history.py 
b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -68,8 +68,8 @@
         return box.value
 
 def repr_rpython(box, typechars):
-    return '%s/%s%d' % (box._get_hash_(), typechars,
-                        compute_unique_id(box))
+    return '%s/%s' % (box._get_hash_(), typechars,
+                        ) #compute_unique_id(box))
 
 
 class XxxAbstractValue(object):
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py 
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -526,16 +526,10 @@
         cf.do_setfield(self, op)
 
     def optimize_GETARRAYITEM_GC_I(self, op):
-        # When using str_storage_getitem it might happen that op.getarg(0) is
-        # a virtual string, NOT an array. In that case, we cannot cache the
-        # getarrayitem as if it were an array, obviously. In theory we could
-        # improve by writing special code to interpter the buffer of the
-        # virtual string as if it were an array, but it looks complicate,
-        # fragile and not worth it.
         arrayinfo = self.ensure_ptr_info_arg0(op)
         indexb = self.getintbound(op.getarg(1))
         cf = None
-        if indexb.is_constant() and not arrayinfo.is_vstring():
+        if indexb.is_constant():
             index = indexb.getint()
             arrayinfo.getlenbound(None).make_gt_const(index)
             # use the cache on (arraydescr, index), which is a constant
@@ -552,7 +546,7 @@
         self.make_nonnull(op.getarg(0))
         self.emit_operation(op)
         # the remember the result of reading the array item
-        if cf is not None and not arrayinfo.is_vstring():
+        if cf is not None:
             arrayinfo.setitem(op.getdescr(), indexb.getint(),
                               self.get_box_replacement(op.getarg(0)),
                               self.get_box_replacement(op), cf,
diff --git a/rpython/jit/metainterp/optimizeopt/info.py 
b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -24,9 +24,6 @@
     def is_virtual(self):
         return False
 
-    def is_vstring(self):
-        return False
-
     def is_precise(self):
         return False
 
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py 
b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -271,10 +271,8 @@
             self.emit_operation(op)
 
     def optimize_GETARRAYITEM_GC_I(self, op):
-        # When using str_storage_getitem we op.getarg(0) is a string, NOT an
-        # array, hence the check. In that case, it will be forced
         opinfo = self.getptrinfo(op.getarg(0))
-        if opinfo and opinfo.is_virtual() and not opinfo.is_vstring():
+        if opinfo and opinfo.is_virtual():
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
                 item = opinfo.getitem(op.getdescr(), indexbox.getint())
diff --git a/rpython/jit/metainterp/optimizeopt/vstring.py 
b/rpython/jit/metainterp/optimizeopt/vstring.py
--- a/rpython/jit/metainterp/optimizeopt/vstring.py
+++ b/rpython/jit/metainterp/optimizeopt/vstring.py
@@ -62,9 +62,6 @@
         self.mode = mode
         self.length = length
 
-    def is_vstring(self):
-        return True
-
     def getlenbound(self, mode):
         from rpython.jit.metainterp.optimizeopt import intutils
 
diff --git a/rpython/jit/metainterp/pyjitpl.py 
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -801,6 +801,27 @@
         return self.execute_with_descr(rop.RAW_LOAD_F, arraydescr,
                                        addrbox, offsetbox)
 
+    def _remove_symbolics(self, c):
+        if not we_are_translated():
+            from rpython.rtyper.lltypesystem import ll2ctypes
+            assert isinstance(c, ConstInt)
+            c = ConstInt(ll2ctypes.lltype2ctypes(c.value))
+        return c
+
+    @arguments("box", "box", "box", "box", "box")
+    def opimpl_gc_load_indexed_i(self, addrbox, indexbox,
+                                 scalebox, baseofsbox, bytesbox):
+        return self.execute(rop.GC_LOAD_INDEXED_I, addrbox, indexbox,
+                            self._remove_symbolics(scalebox),
+                            self._remove_symbolics(baseofsbox), bytesbox)
+
+    @arguments("box", "box", "box", "box", "box")
+    def opimpl_gc_load_indexed_f(self, addrbox, indexbox,
+                                 scalebox, baseofsbox, bytesbox):
+        return self.execute(rop.GC_LOAD_INDEXED_F, addrbox, indexbox,
+                            self._remove_symbolics(scalebox),
+                            self._remove_symbolics(baseofsbox), bytesbox)
+
     @arguments("box")
     def opimpl_hint_force_virtualizable(self, box):
         self.metainterp.gen_store_back_in_vable(box)
diff --git a/rpython/jit/metainterp/resoperation.py 
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -1212,8 +1212,12 @@
     '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations -----
 
     # same paramters as GC_LOAD, but one additional for the value to store
-    # note that the itemsize is not signed!
+    # note that the itemsize is not signed (always > 0)
     # (gcptr, index, value, [scale, base_offset,] itemsize)
+    # invariants for GC_STORE: index is constant, but can be large
+    # invariants for GC_STORE_INDEXED: index is a non-constant box;
+    #                                  scale is a constant;
+    #                                  base_offset is a small constant
     'GC_STORE/4d/n',
     'GC_STORE_INDEXED/6d/n',
 
diff --git a/rpython/jit/metainterp/test/test_strstorage.py 
b/rpython/jit/metainterp/test/test_strstorage.py
--- a/rpython/jit/metainterp/test/test_strstorage.py
+++ b/rpython/jit/metainterp/test/test_strstorage.py
@@ -19,7 +19,7 @@
         res = self.interp_operations(f, [], supports_singlefloats=True)
         #
         kind = getkind(TYPE)[0] # 'i' or 'f'
-        self.check_operations_history({'getarrayitem_gc_%s' % kind: 1,
+        self.check_operations_history({'gc_load_indexed_%s' % kind: 1,
                                        'finish': 1})
         #
         if TYPE == lltype.SingleFloat:
@@ -29,8 +29,8 @@
             return longlong.int2singlefloat(res)
         return res
 
-    def str_storage_supported(self, TYPE):
-        py.test.skip('this is not a JIT test')
+    #def str_storage_supported(self, TYPE):
+    #    py.test.skip('this is not a JIT test')
 
     def test_force_virtual_str_storage(self):
         byteorder = sys.byteorder
@@ -48,6 +48,6 @@
             'strsetitem': 1,          # str forcing
             'call_pure_r': 1,         # str forcing (copystrcontent)
             'guard_no_exception': 1,  # str forcing
-            'getarrayitem_gc_i': 1,   # str_storage_getitem
+            'gc_load_indexed_i': 1,   # str_storage_getitem
             'finish': 1
             })
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -114,6 +114,8 @@
 
 specialize = _Specialize()
 
+NOT_CONSTANT = object()      # to use in enforceargs()
+
 def enforceargs(*types_, **kwds):
     """ Decorate a function with forcing of RPython-level types on arguments.
     None means no enforcing.
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -9,7 +9,7 @@
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.rlib.rarithmetic import intmask, widen
 from rpython.rlib.objectmodel import (
-    specialize, enforceargs, register_replacement_for)
+    specialize, enforceargs, register_replacement_for, NOT_CONSTANT)
 from rpython.rlib.signature import signature
 from rpython.rlib import types
 from rpython.annotator.model import s_Str0
@@ -415,7 +415,7 @@
 
 @replace_os_function('open')
 @specialize.argtype(0)
-@enforceargs(None, int, int, typecheck=False)
+@enforceargs(NOT_CONSTANT, int, int, typecheck=False)
 def open(path, flags, mode):
     if _prefer_unicode(path):
         fd = c_wopen(_as_unicode0(path), flags, mode)
diff --git a/rpython/rlib/rstruct/nativefmttable.py 
b/rpython/rlib/rstruct/nativefmttable.py
--- a/rpython/rlib/rstruct/nativefmttable.py
+++ b/rpython/rlib/rstruct/nativefmttable.py
@@ -11,7 +11,6 @@
 from rpython.rlib.rstruct.standardfmttable import native_is_bigendian
 from rpython.rlib.rstruct.error import StructError
 from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.strstorage import str_storage_getitem
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
diff --git a/rpython/rlib/rstruct/standardfmttable.py 
b/rpython/rlib/rstruct/standardfmttable.py
--- a/rpython/rlib/rstruct/standardfmttable.py
+++ b/rpython/rlib/rstruct/standardfmttable.py
@@ -12,7 +12,7 @@
 from rpython.rlib.rstruct import ieee
 from rpython.rlib.rstruct.error import StructError, StructOverflowError
 from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.strstorage import str_storage_getitem, str_storage_supported
+from rpython.rlib.strstorage import str_storage_getitem
 from rpython.rlib import rarithmetic
 from rpython.rtyper.lltypesystem import rffi
 
@@ -185,13 +185,14 @@
             data = fmtiter.read(size)
             fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian))
             return
-        if not str_storage_supported(TYPE):
-            # this happens e.g. on win32 and ARM32: we cannot read the string
-            # content as an array of doubles because it's not properly
-            # aligned. But we can read a longlong and convert to float
-            assert TYPE == rffi.DOUBLE
-            assert rffi.sizeof(TYPE) == 8
-            return unpack_longlong2float(fmtiter)
+        ## XXX check if the following code is still needed
+        ## if not str_storage_supported(TYPE):
+        ##     # this happens e.g. on win32 and ARM32: we cannot read the 
string
+        ##     # content as an array of doubles because it's not properly
+        ##     # aligned. But we can read a longlong and convert to float
+        ##     assert TYPE == rffi.DOUBLE
+        ##     assert rffi.sizeof(TYPE) == 8
+        ##     return unpack_longlong2float(fmtiter)
         try:
             # fast path
             val = unpack_fastpath(TYPE)(fmtiter)
@@ -246,7 +247,7 @@
 
     @specialize.argtype(0)
     def unpack_int_fastpath_maybe(fmtiter):
-        if fmtiter.bigendian != native_is_bigendian or not 
str_storage_supported(TYPE):
+        if fmtiter.bigendian != native_is_bigendian or not native_is_ieee754: 
## or not str_storage_supported(TYPE):
             return False
         try:
             intvalue = unpack_fastpath(TYPE)(fmtiter)
diff --git a/rpython/rlib/rurandom.py b/rpython/rlib/rurandom.py
--- a/rpython/rlib/rurandom.py
+++ b/rpython/rlib/rurandom.py
@@ -86,27 +86,29 @@
 else:  # Posix implementation
     def init_urandom():
         """NOT_RPYTHON
-        Return an array of one int, initialized to 0.
-        It is filled automatically the first time urandom() is called.
         """
-        return lltype.malloc(rffi.CArray(lltype.Signed), 1,
-                             immortal=True, zero=True)
+        return None
 
     def urandom(context, n):
         "Read n bytes from /dev/urandom."
         result = ''
         if n == 0:
             return result
-        if not context[0]:
-            context[0] = os.open("/dev/urandom", os.O_RDONLY, 0777)
-        while n > 0:
-            try:
-                data = os.read(context[0], n)
-            except OSError, e:
-                if e.errno != errno.EINTR:
-                    raise
-                data = ''
-            result += data
-            n -= len(data)
+        # XXX should somehow cache the file descriptor.  It's a mess.
+        # CPython has a 99% solution and hopes for the remaining 1%
+        # not to occur.  For now, we just don't cache the file
+        # descriptor (any more... 6810f401d08e).
+        fd = os.open("/dev/urandom", os.O_RDONLY, 0777)
+        try:
+            while n > 0:
+                try:
+                    data = os.read(fd, n)
+                except OSError, e:
+                    if e.errno != errno.EINTR:
+                        raise
+                    data = ''
+                result += data
+                n -= len(data)
+        finally:
+            os.close(fd)
         return result
-
diff --git a/rpython/rlib/strstorage.py b/rpython/rlib/strstorage.py
--- a/rpython/rlib/strstorage.py
+++ b/rpython/rlib/strstorage.py
@@ -9,54 +9,31 @@
 #      rstr.py:copy_string_contents), which has no chance to work during
 #      tracing
 #
-#   2. use llop.raw_load: despite the name, llop.raw_load DOES support reading
-#      from GC pointers. However:
-#
-#        a. we would like to use a CompositeOffset as the offset (using the
-#           same logic as in rstr.py:_get_raw_str_buf), but this is not (yet)
-#           supported before translation: it works only if you pass an actual
-#           integer
-#
-#        b. raw_load from a GC pointer is not (yet) supported by the
-#           JIT. There are plans to introduce a gc_load operation: when it
-#           will be there, we could fix the issue above and actually use it to
-#           implement str_storage_getitem
-#
-#   3. the actual solution: cast rpy_string to a GcStruct which has the very
+#   2. cast rpy_string to a GcStruct which has the very
 #      same layout, with the only difference that its 'chars' field is no
 #      longer an Array(Char) but e.e. an Array(Signed). Then, we just need to
-#      read the appropriate index into the array
+#      read the appropriate index into the array.  To support this solution,
+#      the JIT's optimizer needed a few workarounds.  This was removed.
+#
+#   3. use the newly introduced 'llop.gc_load_indexed'.
+#
 
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
-from rpython.rtyper.lltypesystem.rstr import STR, _get_raw_str_buf
+
+from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.rtyper.lltypesystem.rstr import STR
 from rpython.rtyper.annlowlevel import llstr
-from rpython.rlib.objectmodel import specialize, we_are_translated
+from rpython.rlib.objectmodel import specialize
 
-@specialize.memo()
-def _rpy_string_as_type(TP):
-    # sanity check that STR is actually what we think it is
-    assert STR._flds == {
-        'hash': lltype.Signed,
-        'chars': lltype.Array(lltype.Char, hints={'immutable': True})
-        }
-    STR_AS_TP = lltype.GcStruct('rpy_string_as_%s' % TP,
-                                ('hash',  lltype.Signed),
-                                ('chars', lltype.Array(TP, hints={'immutable': 
True})))
-    return STR_AS_TP
-
-@specialize.arg(0)
-def str_storage_supported(TP):
-    # on some architectures (e.g. win32 and arm32) an array of longlongs needs
-    # to be aligned at 8 bytes boundaries, so we cannot safely cast from STR
-    # to STR_AS_TP. In that case, we str_storage_getitem is simply not
-    # supported
-    return rffi.sizeof(TP) <= rffi.sizeof(lltype.Signed)
 
 @specialize.ll()
-def str_storage_getitem(TP, s, index):
-    assert str_storage_supported(TP) # sanity check
-    STR_AS_TP = _rpy_string_as_type(TP)
+def str_storage_getitem(TP, s, byte_offset):
+    # WARNING: the 'byte_offset' is, as its name says, measured in bytes;
+    # however, it should be aligned for TP, otherwise on some platforms this
+    # code will crash!
     lls = llstr(s)
-    str_as_tp = rffi.cast(lltype.Ptr(STR_AS_TP), lls)
-    index = index / rffi.sizeof(TP)
-    return str_as_tp.chars[index]
+    base_ofs = (llmemory.offsetof(STR, 'chars') +
+                llmemory.itemoffsetof(STR.chars, 0))
+    scale_factor = llmemory.sizeof(lltype.Char)
+    return llop.gc_load_indexed(TP, lls, byte_offset,
+                                scale_factor, base_ofs)
diff --git a/rpython/rlib/test/test_objectmodel.py 
b/rpython/rlib/test/test_objectmodel.py
--- a/rpython/rlib/test/test_objectmodel.py
+++ b/rpython/rlib/test/test_objectmodel.py
@@ -4,7 +4,7 @@
     r_dict, UnboxedValue, Symbolic, compute_hash, compute_identity_hash,
     compute_unique_id, current_object_addr_as_int, we_are_translated,
     prepare_dict_update, reversed_dict, specialize, enforceargs, newlist_hint,
-    resizelist_hint, is_annotation_constant, always_inline,
+    resizelist_hint, is_annotation_constant, always_inline, NOT_CONSTANT,
     iterkeys_with_hash, iteritems_with_hash, contains_with_hash,
     setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin)
 from rpython.translator.translator import TranslationContext, graphof
@@ -529,6 +529,18 @@
     TYPES = [v.concretetype for v in graph.getargs()]
     assert TYPES == [lltype.Signed, lltype.Float]
 
+def test_enforceargs_not_constant():
+    from rpython.translator.translator import TranslationContext, graphof
+    @enforceargs(NOT_CONSTANT)
+    def f(a):
+        return a
+    def f42():
+        return f(42)
+    t = TranslationContext()
+    a = t.buildannotator()
+    s = a.build_types(f42, [])
+    assert not hasattr(s, 'const')
+
 
 def getgraph(f, argtypes):
     from rpython.translator.translator import TranslationContext, graphof
diff --git a/rpython/rlib/test/test_strstorage.py 
b/rpython/rlib/test/test_strstorage.py
--- a/rpython/rlib/test/test_strstorage.py
+++ b/rpython/rlib/test/test_strstorage.py
@@ -2,7 +2,7 @@
 import sys
 import struct
 from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rlib.strstorage import str_storage_getitem, str_storage_supported
+from rpython.rlib.strstorage import str_storage_getitem
 from rpython.rlib.rarithmetic import r_singlefloat
 from rpython.rtyper.test.tool import BaseRtypingTest
 
@@ -10,14 +10,14 @@
 
 class BaseStrStorageTest:
 
-    def test_str_getitem_supported(self):
-        if IS_32BIT:
-            expected = False
-        else:
-            expected = True
-        #
-        assert self.str_storage_supported(rffi.LONGLONG) == expected
-        assert self.str_storage_supported(rffi.DOUBLE) == expected
+    ## def test_str_getitem_supported(self):
+    ##     if IS_32BIT:
+    ##         expected = False
+    ##     else:
+    ##         expected = True
+    ##     #
+    ##     assert self.str_storage_supported(rffi.LONGLONG) == expected
+    ##     assert self.str_storage_supported(rffi.DOUBLE) == expected
 
     def test_signed(self):
         buf = struct.pack('@ll', 42, 43)
@@ -34,8 +34,8 @@
         assert int(x) == 43
 
     def test_float(self):
-        if not str_storage_supported(lltype.Float):
-            py.test.skip('str_storage_getitem(lltype.Float) not supported on 
this machine')
+        ## if not str_storage_supported(lltype.Float):
+        ##     py.test.skip('str_storage_getitem(lltype.Float) not supported 
on this machine')
         buf = struct.pack('@dd', 12.3, 45.6)
         size = struct.calcsize('@d')
         assert self.str_storage_getitem(lltype.Float, buf, 0) == 12.3
@@ -52,20 +52,45 @@
 
 class TestDirect(BaseStrStorageTest):
 
-    def str_storage_supported(self, TYPE):
-        return str_storage_supported(TYPE)
+    ## def str_storage_supported(self, TYPE):
+    ##     return str_storage_supported(TYPE)
 
     def str_storage_getitem(self, TYPE, buf, offset):
         return str_storage_getitem(TYPE, buf, offset)
 
 class TestRTyping(BaseStrStorageTest, BaseRtypingTest):
 
-    def str_storage_supported(self, TYPE):
-        def fn():
-            return str_storage_supported(TYPE)
-        return self.interpret(fn, [])
+    ## def str_storage_supported(self, TYPE):
+    ##     def fn():
+    ##         return str_storage_supported(TYPE)
+    ##     return self.interpret(fn, [])
 
     def str_storage_getitem(self, TYPE, buf, offset):
         def fn(offset):
             return str_storage_getitem(TYPE, buf, offset)
         return self.interpret(fn, [offset])
+
+
+class TestCompiled(BaseStrStorageTest):
+    cache = {}
+
+    def str_storage_getitem(self, TYPE, buf, offset):
+        if TYPE not in self.cache:
+            from rpython.translator.c.test.test_genc import compile
+
+            assert isinstance(TYPE, lltype.Primitive)
+            if TYPE in (lltype.Float, lltype.SingleFloat):
+                TARGET_TYPE = lltype.Float
+            else:
+                TARGET_TYPE = lltype.Signed
+
+            def llf(buf, offset):
+                x = str_storage_getitem(TYPE, buf, offset)
+                return lltype.cast_primitive(TARGET_TYPE, x)
+
+            fn = compile(llf, [str, int])
+            self.cache[TYPE] = fn
+        #
+        fn = self.cache[TYPE]
+        x = fn(buf, offset)
+        return lltype.cast_primitive(TYPE, x)
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py 
b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -902,6 +902,14 @@
                 llobj = ctypes.sizeof(get_ctypes_type(llobj.TYPE)) * 
llobj.repeat
             elif isinstance(llobj, ComputedIntSymbolic):
                 llobj = llobj.compute_fn()
+            elif isinstance(llobj, llmemory.CompositeOffset):
+                llobj = sum([lltype2ctypes(c) for c in llobj.offsets])
+            elif isinstance(llobj, llmemory.FieldOffset):
+                CSTRUCT = get_ctypes_type(llobj.TYPE)
+                llobj = getattr(CSTRUCT, llobj.fldname).offset
+            elif isinstance(llobj, llmemory.ArrayItemsOffset):
+                CARRAY = get_ctypes_type(llobj.TYPE)
+                llobj = CARRAY.items.offset
             else:
                 raise NotImplementedError(llobj)  # don't know about symbolic 
value
 
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -417,6 +417,7 @@
     'raw_load':             LLOp(sideeffects=False, canrun=True),
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to