[pypy-commit] pypy ppc-jit-backend: merge

hager noreply at buildbot.pypy.org
Wed Feb 8 15:05:57 CET 2012


Author: Sven Hager <hager.sven at googlemail.com>
Branch: ppc-jit-backend
Changeset: r52233:b877b6a48b06
Date: 2012-02-08 15:05 +0100
http://bitbucket.org/pypy/pypy/changeset/b877b6a48b06/

Log:	merge

diff --git a/pypy/jit/backend/arm/runner.py b/pypy/jit/backend/arm/runner.py
--- a/pypy/jit/backend/arm/runner.py
+++ b/pypy/jit/backend/arm/runner.py
@@ -112,7 +112,7 @@
                             (frame_depth +
                             len(all_regs) * WORD +
                             len(all_vfp_regs) * 2 * WORD))
-        fail_index_2 = self.assembler.failure_recovery_func(
+        fail_index_2 = self.assembler.decode_registers_and_descr(
             faildescr._failure_recovery_code,
             addr_of_force_index,
             addr_end_of_frame)
diff --git a/pypy/jit/backend/ppc/asmfunc.py b/pypy/jit/backend/ppc/asmfunc.py
--- a/pypy/jit/backend/ppc/asmfunc.py
+++ b/pypy/jit/backend/ppc/asmfunc.py
@@ -5,6 +5,7 @@
 from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.jit.backend.ppc.arch import IS_PPC_32, IS_PPC_64, WORD
+from pypy.rlib.rarithmetic import r_uint
 
 _ppcgen = None
 
@@ -19,17 +20,14 @@
         self.code = MachineCodeBlockWrapper()
         if IS_PPC_64:
             # allocate function descriptor - 3 doublewords
-            self.emit(0)
-            self.emit(0)
-            self.emit(0)
-            self.emit(0)
-            self.emit(0)
-            self.emit(0)
+            for i in range(6):
+                self.emit(r_uint(0))
 
-    def emit(self, insn):
-        bytes = struct.pack("i", insn)
-        for byte in bytes:
-            self.code.writechar(byte)
+    def emit(self, word):
+        self.code.writechar(chr((word >> 24) & 0xFF))
+        self.code.writechar(chr((word >> 16) & 0xFF))
+        self.code.writechar(chr((word >> 8) & 0xFF))
+        self.code.writechar(chr(word & 0xFF))
 
     def get_function(self):
         i = self.code.materialize(AsmMemoryManager(), [])
diff --git a/pypy/jit/backend/ppc/assembler.py b/pypy/jit/backend/ppc/assembler.py
--- a/pypy/jit/backend/ppc/assembler.py
+++ b/pypy/jit/backend/ppc/assembler.py
@@ -51,7 +51,7 @@
                 inst.fields[f] = l
         buf = []
         for inst in self.insts:
-            buf.append(inst.assemble())
+            buf.append(inst)#.assemble())
         if dump:
             for i in range(len(buf)):
                 inst = self.disassemble(buf[i], self.rlabels, i*4)
@@ -61,12 +61,12 @@
         return buf
 
     def assemble(self, dump=os.environ.has_key('PPY_DEBUG')):
-        insns = self.assemble0(dump)
+        #insns = self.assemble0(dump)
         from pypy.jit.backend.ppc import asmfunc
-        c = asmfunc.AsmCode(len(insns)*4)
-        for i in insns:
-            c.emit(i)
-        return c.get_function()
+        c = asmfunc.AsmCode(len(self.insts)*4)
+        for i in self.insts:
+            c.emit(i)#.assemble())
+        #return c.get_function()
 
     def get_idescs(cls):
         r = []
diff --git a/pypy/jit/backend/ppc/codebuilder.py b/pypy/jit/backend/ppc/codebuilder.py
--- a/pypy/jit/backend/ppc/codebuilder.py
+++ b/pypy/jit/backend/ppc/codebuilder.py
@@ -22,11 +22,11 @@
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.history import (BoxInt, ConstInt, ConstPtr,
                                          ConstFloat, Box, INT, REF, FLOAT)
-from pypy.jit.backend.x86.support import values_array
 from pypy.tool.udir import udir
 from pypy.rlib.objectmodel import we_are_translated
 
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.jit.backend.ppc.rassemblermaker import make_rassembler
 
 A = Form("frD", "frA", "frB", "XO3", "Rc")
 A1 = Form("frD", "frB", "XO3", "Rc")
@@ -888,10 +888,7 @@
 
     mtcr = BA.mtcrf(CRM=0xFF)
 
-    def emit(self, insn):
-        bytes = struct.pack("i", insn)
-        for byte in bytes:
-            self.writechar(byte)
+PPCAssembler = make_rassembler(PPCAssembler)
 
 def hi(w):
     return w >> 16
@@ -964,9 +961,16 @@
     def __init__(self, failargs_limit=1000, r0_in_use=False):
         PPCAssembler.__init__(self)
         self.init_block_builder()
-        self.fail_boxes_int = values_array(lltype.Signed, failargs_limit)
         self.r0_in_use = r0_in_use
 
+    def check(self, desc, v, *args):
+        desc.__get__(self)(*args)
+        ins = self.insts.pop()
+        expected = ins.assemble()
+        if expected < 0:
+            expected += 1<<32
+        assert v == expected
+
     def load_imm(self, rD, word):
         rD = rD.as_key()
         if word <= 32767 and word >= -32768:
@@ -990,7 +994,8 @@
             self.ldx(rD.value, 0, rD.value)
 
     def store_reg(self, source_reg, addr):
-        self.alloc_scratch_reg(addr)
+        self.alloc_scratch_reg()
+        self.load_imm(r.SCRATCH, addr)
         if IS_PPC_32:
             self.stwx(source_reg.value, 0, r.SCRATCH.value)
         else:
@@ -1015,13 +1020,15 @@
         BI = condition[0]
         BO = condition[1]
 
-        self.alloc_scratch_reg(addr)
+        self.alloc_scratch_reg()
+        self.load_imm(r.SCRATCH, addr)
         self.mtctr(r.SCRATCH.value)
         self.free_scratch_reg()
         self.bcctr(BO, BI)
 
     def b_abs(self, address, trap=False):
-        self.alloc_scratch_reg(address)
+        self.alloc_scratch_reg()
+        self.load_imm(r.SCRATCH, address)
         self.mtctr(r.SCRATCH.value)
         self.free_scratch_reg()
         if trap:
@@ -1075,7 +1082,7 @@
         self.assemble(show)
         insts = self.insts
         for inst in insts:
-            self.write32(inst.assemble())
+            self.write32(inst)#.assemble())
 
     def _dump_trace(self, addr, name, formatter=-1):
         if not we_are_translated():
@@ -1148,11 +1155,9 @@
                     # 64 bit unsigned
                     self.cmpld(block, a, b)
                 
-    def alloc_scratch_reg(self, value=None):
+    def alloc_scratch_reg(self):
         assert not self.r0_in_use
         self.r0_in_use = True
-        if value is not None:
-            self.load_imm(r.r0, value)
 
     def free_scratch_reg(self):
         assert self.r0_in_use
diff --git a/pypy/jit/backend/ppc/form.py b/pypy/jit/backend/ppc/form.py
--- a/pypy/jit/backend/ppc/form.py
+++ b/pypy/jit/backend/ppc/form.py
@@ -14,8 +14,8 @@
         self.fields = fields
         self.lfields = [k for (k,v) in fields.iteritems()
                         if isinstance(v, str)]
-        if not self.lfields:
-            self.assemble() # for error checking only
+        #if not self.lfields:
+        #    self.assemble() # for error checking only
     def assemble(self):
         r = 0
         for field in self.fields:
diff --git a/pypy/jit/backend/ppc/helper/assembler.py b/pypy/jit/backend/ppc/helper/assembler.py
--- a/pypy/jit/backend/ppc/helper/assembler.py
+++ b/pypy/jit/backend/ppc/helper/assembler.py
@@ -83,7 +83,7 @@
 
 def decode64(mem, index):
     value = 0
-    for x in unrolling_iterable(range(8)):
+    for x in range(8):
         value |= (ord(mem[index + x]) << (56 - x * 8))
     return intmask(value)
 
diff --git a/pypy/jit/backend/ppc/helper/regalloc.py b/pypy/jit/backend/ppc/helper/regalloc.py
--- a/pypy/jit/backend/ppc/helper/regalloc.py
+++ b/pypy/jit/backend/ppc/helper/regalloc.py
@@ -10,7 +10,7 @@
     return False
 
 def _check_imm_arg(arg, size=IMM_SIZE, allow_zero=True):
-    #assert not isinstance(arg, ConstInt)
+    assert not isinstance(arg, ConstInt)
     #if not we_are_translated():
     #    if not isinstance(arg, int):
     #        import pdb; pdb.set_trace()
@@ -25,8 +25,8 @@
     def f(self, op):
         boxes = op.getarglist()
         arg0, arg1 = boxes
-        imm_a0 = _check_imm_arg(arg0)
-        imm_a1 = _check_imm_arg(arg1)
+        imm_a0 = check_imm_box(arg0)
+        imm_a1 = check_imm_box(arg1)
         l0 = self._ensure_value_is_boxed(arg0, forbidden_vars=boxes)
 
         if imm_a1 and not imm_a0:
@@ -63,8 +63,8 @@
     def f(self, op):
         boxes = op.getarglist()
         b0, b1 = boxes
-        imm_b0 = _check_imm_arg(b0)
-        imm_b1 = _check_imm_arg(b1)
+        imm_b0 = check_imm_box(b0)
+        imm_b1 = check_imm_box(b1)
         l0 = self._ensure_value_is_boxed(b0, boxes)
         l1 = self._ensure_value_is_boxed(b1, boxes)
         locs = [l0, l1]
diff --git a/pypy/jit/backend/ppc/opassembler.py b/pypy/jit/backend/ppc/opassembler.py
--- a/pypy/jit/backend/ppc/opassembler.py
+++ b/pypy/jit/backend/ppc/opassembler.py
@@ -288,7 +288,8 @@
                     adr = self.fail_boxes_int.get_addr_for_num(i)
                 else:
                     assert 0
-                self.mc.alloc_scratch_reg(adr)
+                self.mc.alloc_scratch_reg()
+                self.mc.load_imm(r.SCRATCH, adr)
                 self.mc.storex(loc.value, 0, r.SCRATCH.value)
                 self.mc.free_scratch_reg()
             elif loc.is_vfp_reg():
@@ -372,7 +373,8 @@
         if resloc:
             self.mc.load(resloc.value, loc.value, 0)
 
-        self.mc.alloc_scratch_reg(0)
+        self.mc.alloc_scratch_reg()
+        self.mc.load_imm(r.SCRATCH, 0)
         self.mc.store(r.SCRATCH.value, loc.value, 0)
         self.mc.store(r.SCRATCH.value, loc1.value, 0)
         self.mc.free_scratch_reg()
@@ -748,7 +750,8 @@
             bytes_loc = regalloc.force_allocate_reg(bytes_box, forbidden_vars)
             scale = self._get_unicode_item_scale()
             assert length_loc.is_reg()
-            self.mc.alloc_scratch_reg(1 << scale)
+            self.mc.alloc_scratch_reg()
+            self.mc.load_imm(r.SCRATCH, 1 << scale)
             if IS_PPC_32:
                 self.mc.mullw(bytes_loc.value, r.SCRATCH.value, length_loc.value)
             else:
@@ -857,7 +860,8 @@
     def set_vtable(self, box, vtable):
         if self.cpu.vtable_offset is not None:
             adr = rffi.cast(lltype.Signed, vtable)
-            self.mc.alloc_scratch_reg(adr)
+            self.mc.alloc_scratch_reg()
+            self.mc.load_imm(r.SCRATCH, adr)
             self.mc.store(r.SCRATCH.value, r.RES.value, self.cpu.vtable_offset)
             self.mc.free_scratch_reg()
 
@@ -986,7 +990,8 @@
         # check value
         resloc = regalloc.try_allocate_reg(resbox)
         assert resloc is r.RES
-        self.mc.alloc_scratch_reg(value)
+        self.mc.alloc_scratch_reg()
+        self.mc.load_imm(r.SCRATCH, value)
         self.mc.cmp_op(0, resloc.value, r.SCRATCH.value)
         self.mc.free_scratch_reg()
         regalloc.possibly_free_var(resbox)
@@ -1026,16 +1031,16 @@
 
         # Reset the vable token --- XXX really too much special logic here:-(
         if jd.index_of_virtualizable >= 0:
-            from pypy.jit.backend.llsupport.descr import BaseFieldDescr
+            from pypy.jit.backend.llsupport.descr import FieldDescr
             fielddescr = jd.vable_token_descr
-            assert isinstance(fielddescr, BaseFieldDescr)
+            assert isinstance(fielddescr, FieldDescr)
             ofs = fielddescr.offset
             resloc = regalloc.force_allocate_reg(resbox)
-            self.alloc_scratch_reg()
+            self.mc.alloc_scratch_reg()
             self.mov_loc_loc(arglocs[1], r.SCRATCH)
             self.mc.li(resloc.value, 0)
             self.mc.storex(resloc.value, 0, r.SCRATCH.value)
-            self.free_scratch_reg()
+            self.mc.free_scratch_reg()
             regalloc.possibly_free_var(resbox)
 
         if op.result is not None:
@@ -1051,7 +1056,8 @@
                 raise AssertionError(kind)
             resloc = regalloc.force_allocate_reg(op.result)
             regalloc.possibly_free_var(resbox)
-            self.mc.alloc_scratch_reg(adr)
+            self.mc.alloc_scratch_reg()
+            self.mc.load_imm(r.SCRATCH, adr)
             if op.result.type == FLOAT:
                 assert 0, "not implemented yet"
             else:
@@ -1082,6 +1088,15 @@
 
     emit_guard_call_release_gil = emit_guard_call_may_force
 
+    def call_release_gil(self, gcrootmap, save_registers):
+        # XXX don't know whether this is correct
+        # XXX use save_registers here
+        assert gcrootmap.is_shadow_stack
+        with Saved_Volatiles(self.mc):
+            self._emit_call(NO_FORCE_INDEX, self.releasegil_addr, 
+                            [], self._regalloc)
+
+
 
 class OpAssembler(IntOpAssembler, GuardOpAssembler,
                   MiscOpAssembler, FieldOpAssembler,
diff --git a/pypy/jit/backend/ppc/ppc_assembler.py b/pypy/jit/backend/ppc/ppc_assembler.py
--- a/pypy/jit/backend/ppc/ppc_assembler.py
+++ b/pypy/jit/backend/ppc/ppc_assembler.py
@@ -3,23 +3,23 @@
 from pypy.jit.backend.ppc.ppc_form import PPCForm as Form
 from pypy.jit.backend.ppc.ppc_field import ppc_fields
 from pypy.jit.backend.ppc.regalloc import (TempInt, PPCFrameManager,
-                                           Regalloc)
+                                                  Regalloc)
 from pypy.jit.backend.ppc.assembler import Assembler
 from pypy.jit.backend.ppc.opassembler import OpAssembler
 from pypy.jit.backend.ppc.symbol_lookup import lookup
 from pypy.jit.backend.ppc.codebuilder import PPCBuilder
 from pypy.jit.backend.ppc.jump import remap_frame_layout
 from pypy.jit.backend.ppc.arch import (IS_PPC_32, IS_PPC_64, WORD,
-                                       NONVOLATILES, MAX_REG_PARAMS,
-                                       GPR_SAVE_AREA, BACKCHAIN_SIZE,
-                                       FPR_SAVE_AREA,
-                                       FLOAT_INT_CONVERSION, FORCE_INDEX,
-                                       SIZE_LOAD_IMM_PATCH_SP)
+                                              NONVOLATILES, MAX_REG_PARAMS,
+                                              GPR_SAVE_AREA, BACKCHAIN_SIZE,
+                                              FPR_SAVE_AREA,
+                                              FLOAT_INT_CONVERSION, FORCE_INDEX,
+                                              SIZE_LOAD_IMM_PATCH_SP)
 from pypy.jit.backend.ppc.helper.assembler import (gen_emit_cmp_op, 
                                                    encode32, encode64,
                                                    decode32, decode64,
                                                    count_reg_args,
-                                                   Saved_Volatiles)
+                                                          Saved_Volatiles)
 import pypy.jit.backend.ppc.register as r
 import pypy.jit.backend.ppc.condition as c
 from pypy.jit.metainterp.history import (Const, ConstPtr, JitCellToken, 
@@ -106,6 +106,7 @@
         self._regalloc = None
         self.max_stack_params = 0
         self.propagate_exception_path = 0
+        self.setup_failure_recovery()
 
     def _save_nonvolatiles(self):
         """ save nonvolatile GPRs in GPR SAVE AREA 
@@ -237,6 +238,7 @@
         descr = decode32(enc, i+1)
         self.fail_boxes_count = fail_index
         self.fail_force_index = spp_loc
+        assert isinstance(descr, int)
         return descr
 
     def decode_inputargs(self, enc):
@@ -382,7 +384,6 @@
         gc_ll_descr.initialize()
         self._build_propagate_exception_path()
         self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn)
-        self.setup_failure_recovery()
         self.exit_code_adr = self._gen_exit_path()
         self._leave_jitted_hook_save_exc = self._gen_leave_jitted_hook_code(True)
         self._leave_jitted_hook = self._gen_leave_jitted_hook_code(False)
@@ -600,8 +601,7 @@
             if op.is_ovf():
                 if (operations[i + 1].getopnum() != rop.GUARD_NO_OVERFLOW and
                     operations[i + 1].getopnum() != rop.GUARD_OVERFLOW):
-                    not_implemented("int_xxx_ovf not followed by "
-                                    "guard_(no)_overflow")
+                    assert 0, "int_xxx_ovf not followed by guard_(no)_overflow"
                 return True
             return False
         if (operations[i + 1].getopnum() != rop.GUARD_TRUE and
@@ -682,7 +682,8 @@
         memaddr = self.gen_descr_encoding(descr, args, arglocs)
 
         # store addr in force index field
-        self.mc.alloc_scratch_reg(memaddr)
+        self.mc.alloc_scratch_reg()
+        self.mc.load_imm(r.SCRATCH, memaddr)
         self.mc.store(r.SCRATCH.value, r.SPP.value, self.ENCODING_AREA)
         self.mc.free_scratch_reg()
 
@@ -886,7 +887,8 @@
             return 0
 
     def _write_fail_index(self, fail_index):
-        self.mc.alloc_scratch_reg(fail_index)
+        self.mc.alloc_scratch_reg()
+        self.mc.load_imm(r.SCRATCH, fail_index)
         self.mc.store(r.SCRATCH.value, r.SPP.value, self.ENCODING_AREA)
         self.mc.free_scratch_reg()
             
diff --git a/pypy/jit/backend/ppc/rassemblermaker.py b/pypy/jit/backend/ppc/rassemblermaker.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/ppc/rassemblermaker.py
@@ -0,0 +1,74 @@
+from pypy.tool.sourcetools import compile2
+from pypy.rlib.rarithmetic import r_uint
+from pypy.jit.backend.ppc.form import IDesc, IDupDesc
+from pypy.jit.backend.ppc.ppc_field import IField
+
+##     "opcode": ( 0,  5),
+##     "rA":     (11, 15, 'unsigned', regname._R),
+##     "rB":     (16, 20, 'unsigned', regname._R),
+##     "Rc":     (31, 31),
+##     "rD":     ( 6, 10, 'unsigned', regname._R),
+##     "OE":     (21, 21),
+##     "XO2":    (22, 30),
+
+## XO = Form("rD", "rA", "rB", "OE", "XO2", "Rc")
+
+##     add   = XO(31, XO2=266, OE=0, Rc=0)
+
+##     def add(rD, rA, rB):
+##         v = 0
+##         v |= (31&(2**(5-0+1)-1)) << (32-5-1)
+##         ...
+##         return v
+
+def make_func(name, desc):
+    sig = []
+    fieldvalues = []
+    for field in desc.fields:
+        if field in desc.specializations:
+            fieldvalues.append((field, desc.specializations[field]))
+        else:
+            sig.append(field.name)
+            fieldvalues.append((field, field.name))
+    if isinstance(desc, IDupDesc):
+        for destfield, srcfield in desc.dupfields.iteritems():
+            fieldvalues.append((destfield, srcfield.name))
+    body = ['v = r_uint(0)']
+    assert 'v' not in sig # that wouldn't be funny
+    #body.append('print %r'%name + ', ' + ', '.join(["'%s:', %s"%(s, s) for s in sig]))
+    for field, value in fieldvalues:
+        if field.name == 'spr':
+            body.append('spr1 = (%s&31) << 5 | (%s >> 5 & 31)'%(value, value))
+            value = 'spr1'
+        elif field.name == 'mbe':
+            body.append('mbe1 = (%s & 31) << 1 | (%s & 32) >> 5' % (value, value))
+            value = 'mbe1'
+        elif field.name == 'sh':
+            body.append('sh1 = (%s & 31) << 10 | (%s & 32) >> 5' % (value, value))
+            value = 'sh1'
+        if isinstance(field, IField):
+            body.append('v |= ((%3s >> 2) & r_uint(%#05x)) << 2' % (value, field.mask))
+        else:
+            body.append('v |= (%3s & r_uint(%#05x)) << %d'%(value,
+                                                            field.mask,
+                                                            (32 - field.right - 1)))
+    #body.append('self.check(desc, v, %s)' % ', '.join(sig))
+    body.append('self.emit(v)')
+    src = 'def %s(self, %s):\n    %s'%(name, ', '.join(sig), '\n    '.join(body))
+    d = {'r_uint':r_uint, 'desc': desc}
+    #print src
+    exec compile2(src) in d
+    return d[name]
+
+def make_rassembler(cls):
+    bases = [make_rassembler(b) for b in cls.__bases__]
+    ns = {}
+    for k, v in cls.__dict__.iteritems():
+        if isinstance(v, IDesc):
+            v = make_func(k, v)
+        ns[k] = v
+    rcls = type('R' + cls.__name__, tuple(bases), ns)
+    def emit(self, value):
+        self.insts.append(value)
+    rcls.emit = emit
+    return rcls
diff --git a/pypy/jit/backend/ppc/regalloc.py b/pypy/jit/backend/ppc/regalloc.py
--- a/pypy/jit/backend/ppc/regalloc.py
+++ b/pypy/jit/backend/ppc/regalloc.py
@@ -2,15 +2,15 @@
                                                  TempBox, compute_vars_longevity)
 from pypy.jit.backend.ppc.arch import (WORD, MY_COPY_OF_REGS)
 from pypy.jit.backend.ppc.jump import (remap_frame_layout_mixed,
-                                       remap_frame_layout)
+                                              remap_frame_layout)
 from pypy.jit.backend.ppc.locations import imm
 from pypy.jit.backend.ppc.helper.regalloc import (_check_imm_arg,
-                                                   check_imm_box,
-                                                   prepare_cmp_op,
-                                                   prepare_unary_int_op,
-                                                   prepare_binary_int_op,
-                                                   prepare_binary_int_op_with_imm,
-                                                   prepare_unary_cmp)
+                                                         check_imm_box,
+                                                         prepare_cmp_op,
+                                                         prepare_unary_int_op,
+                                                         prepare_binary_int_op,
+                                                         prepare_binary_int_op_with_imm,
+                                                         prepare_unary_cmp)
 from pypy.jit.metainterp.history import (INT, REF, FLOAT, Const, ConstInt, 
                                          ConstPtr, Box)
 from pypy.jit.metainterp.history import JitCellToken, TargetToken
@@ -512,7 +512,7 @@
                 loc, box = self._ensure_value_is_boxed(op.getarg(i), argboxes)
                 arglocs.append(loc)
                 argboxes.append(box)
-            self.assembler.call_release_gil(gcrootmap, arglocs, fcond)
+            self.assembler.call_release_gil(gcrootmap, arglocs)
             self.possibly_free_vars(argboxes)
         # do the call
         faildescr = guard_op.getdescr()
@@ -522,7 +522,8 @@
         self.assembler.emit_call(op, args, self, fail_index)
         # then reopen the stack
         if gcrootmap:
-            self.assembler.call_reacquire_gil(gcrootmap, r.r0, fcond)
+            assert 0, "not implemented yet"
+            # self.assembler.call_reacquire_gil(gcrootmap, registers)
         locs = self._prepare_guard(guard_op)
         self.possibly_free_vars(guard_op.getfailargs())
         return locs
@@ -595,11 +596,10 @@
         args = op.getarglist()
         base_loc = self._ensure_value_is_boxed(op.getarg(0), args)
         index_loc = self._ensure_value_is_boxed(op.getarg(1), args)
-        c_ofs = ConstInt(ofs)
-        if _check_imm_arg(c_ofs):
+        if _check_imm_arg(ofs):
             ofs_loc = imm(ofs)
         else:
-            ofs_loc = self._ensure_value_is_boxed(c_ofs, args)
+            ofs_loc = self._ensure_value_is_boxed(ConstInt(ofs), args)
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         result_loc = self.force_allocate_reg(op.result)
@@ -614,11 +614,10 @@
         base_loc = self._ensure_value_is_boxed(op.getarg(0), args)
         index_loc = self._ensure_value_is_boxed(op.getarg(1), args)
         value_loc = self._ensure_value_is_boxed(op.getarg(2), args)
-        c_ofs = ConstInt(ofs)
-        if _check_imm_arg(c_ofs):
+        if _check_imm_arg(ofs):
             ofs_loc = imm(ofs)
         else:
-            ofs_loc = self._ensure_value_is_boxed(c_ofs, args)
+            ofs_loc = self._ensure_value_is_boxed(ConstInt(ofs), args)
         return [base_loc, index_loc, value_loc, ofs_loc, imm(ofs),
                                         imm(itemsize), imm(fieldsize)]
 
@@ -640,8 +639,7 @@
         base_loc = self._ensure_value_is_boxed(args[0], args)
         ofs_loc = self._ensure_value_is_boxed(args[1], args)
         value_loc = self._ensure_value_is_boxed(args[2], args)
-        scratch_loc = self.rm.get_scratch_reg(INT, 
-                [base_loc, ofs_loc, value_loc])
+        scratch_loc = self.rm.get_scratch_reg(INT, args)
         assert _check_imm_arg(ofs)
         return [value_loc, base_loc, ofs_loc, scratch_loc, imm(scale), imm(ofs)]
     prepare_setarrayitem_raw = prepare_setarrayitem_gc
@@ -652,7 +650,7 @@
         scale = get_scale(size)
         base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
         ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
-        scratch_loc = self.rm.get_scratch_reg(INT, [base_loc, ofs_loc])
+        scratch_loc = self.rm.get_scratch_reg(INT, boxes)
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         res = self.force_allocate_reg(op.result)
@@ -766,11 +764,13 @@
     def prepare_call(self, op):
         effectinfo = op.getdescr().get_extra_info()
         if effectinfo is not None:
-            oopspecindex = effectinfo.oopspecindex
-            if oopspecindex == EffectInfo.OS_MATH_SQRT:
-                args = self.prepare_op_math_sqrt(op, fcond)
-                self.assembler.emit_op_math_sqrt(op, args, self, fcond)
-                return
+	    # XXX TODO
+            #oopspecindex = effectinfo.oopspecindex
+            #if oopspecindex == EffectInfo.OS_MATH_SQRT:
+            #    args = self.prepare_op_math_sqrt(op, fcond)
+            #    self.assembler.emit_op_math_sqrt(op, args, self, fcond)
+            #    return
+            pass
         args = [imm(rffi.cast(lltype.Signed, op.getarg(0).getint()))]
         return args
 
diff --git a/pypy/jit/backend/ppc/runner.py b/pypy/jit/backend/ppc/runner.py
--- a/pypy/jit/backend/ppc/runner.py
+++ b/pypy/jit/backend/ppc/runner.py
@@ -44,7 +44,7 @@
     def setup_once(self):
         self.asm.setup_once()
 
-    def compile_loop(self, inputargs, operations, looptoken, log=True, name=''):
+    def compile_loop(self, inputargs, operations, looptoken, log=True, name=""):
         self.asm.assemble_loop(inputargs, operations, looptoken, log)
 
     def compile_bridge(self, faildescr, inputargs, operations, 
@@ -97,7 +97,7 @@
         rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
 
         # start of "no gc operation!" block
-        fail_index_2 = self.asm.failure_recovery_func(
+        fail_index_2 = self.asm.decode_registers_and_descr(
                 faildescr._failure_recovery_code, spilling_pointer)
         self.asm.leave_jitted_hook()
         # end of "no gc operation!" block
diff --git a/pypy/jit/backend/ppc/test/test_func_builder.py b/pypy/jit/backend/ppc/test/test_func_builder.py
--- a/pypy/jit/backend/ppc/test/test_func_builder.py
+++ b/pypy/jit/backend/ppc/test/test_func_builder.py
@@ -78,7 +78,7 @@
         f = make_func(a, "O", "O")
         assert f(1) == 1
         b = MyPPCAssembler()
-        from pypy.jit.backend.ppc.ppcgen import util
+        from pypy.jit.backend.ppc import util
         # eurgh!:
         b.load_word(r0, util.access_at(id(f.code), 8) + f.FAST_ENTRY_LABEL)
         b.mtctr(r0)
diff --git a/pypy/jit/backend/ppc/test/test_ppc.py b/pypy/jit/backend/ppc/test/test_ppc.py
--- a/pypy/jit/backend/ppc/test/test_ppc.py
+++ b/pypy/jit/backend/ppc/test/test_ppc.py
@@ -2,6 +2,7 @@
 import random, sys, os
 
 from pypy.jit.backend.ppc.codebuilder import BasicPPCAssembler, PPCBuilder
+from pypy.jit.backend.ppc.symbol_lookup import lookup
 from pypy.jit.backend.ppc.regname import *
 from pypy.jit.backend.ppc.register import *
 from pypy.jit.backend.ppc import form
@@ -58,6 +59,7 @@
     def setup_class(cls):
         if autodetect_main_model() not in ["ppc", "ppc64"]: 
             py.test.skip("can't test all of ppcgen on non-PPC!")
+        py.test.xfail("assemble does not return a function any longer, fix tests")
 
     """
     Tests are build like this:
diff --git a/pypy/jit/backend/ppc/test/test_rassemblermaker.py b/pypy/jit/backend/ppc/test/test_rassemblermaker.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/ppc/test/test_rassemblermaker.py
@@ -0,0 +1,39 @@
+from pypy.jit.backend.ppc.rassemblermaker import make_rassembler
+from pypy.jit.backend.ppc.ppc_assembler import PPCAssembler
+
+RPPCAssembler = make_rassembler(PPCAssembler)
+
+_a = PPCAssembler()
+_a.add(3, 3, 4)
+add_r3_r3_r4 = _a.insts[0].assemble()
+
+def test_simple():
+    ra = RPPCAssembler()
+    ra.add(3, 3, 4)
+    assert ra.insts == [add_r3_r3_r4]
+
+def test_rtyped():
+    from pypy.rpython.test.test_llinterp import interpret
+    def f():
+        ra = RPPCAssembler()
+        ra.add(3, 3, 4)
+        ra.lwz(1, 1, 1)  # ensure that high bit doesn't produce long but r_uint
+        return ra.insts[0]
+    res = interpret(f, [])
+    assert res == add_r3_r3_r4
+
+def test_mnemonic():
+    mrs = []
+    for A in PPCAssembler, RPPCAssembler:
+        a = A()
+        a.mr(3, 4)
+        mrs.append(a.insts[0])
+    assert mrs[0].assemble() == mrs[1]
+
+def test_spr_coding():
+    mrs = []
+    for A in PPCAssembler, RPPCAssembler:
+        a = A()
+        a.mtctr(3)
+        mrs.append(a.insts[0])
+    assert mrs[0].assemble() == mrs[1]
diff --git a/pypy/jit/backend/ppc/test/test_zrpy_gc.py b/pypy/jit/backend/ppc/test/test_zrpy_gc.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/ppc/test/test_zrpy_gc.py
@@ -0,0 +1,795 @@
+"""
+This is a test that translates a complete JIT together with a GC and runs it.
+It is testing that the GC-dependent aspects basically work, mostly the mallocs
+and the various cases of write barrier.
+"""
+
+import weakref
+import py, os
+from pypy.annotation import policy as annpolicy
+from pypy.rlib import rgc
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rlib.jit import JitDriver, dont_look_inside
+from pypy.rlib.jit import elidable, unroll_safe
+from pypy.jit.backend.llsupport.gc import GcLLDescr_framework
+from pypy.tool.udir import udir
+from pypy.config.translationoption import DEFL_GC
+
+class X(object):
+    def __init__(self, x=0):
+        self.x = x
+
+    next = None
+
+class CheckError(Exception):
+    pass
+
+def check(flag):
+    if not flag:
+        raise CheckError
+
+def get_g(main):
+    main._dont_inline_ = True
+    def g(name, n):
+        x = X()
+        x.foo = 2
+        main(n, x)
+        x.foo = 5
+        return weakref.ref(x)
+    g._dont_inline_ = True
+    return g
+
+
+def get_entry(g):
+
+    def entrypoint(args):
+        name = ''
+        n = 2000
+        argc = len(args)
+        if argc > 1:
+            name = args[1]
+        if argc > 2:
+            n = int(args[2])
+        r_list = []
+        for i in range(20):
+            r = g(name, n)
+            r_list.append(r)
+            rgc.collect()
+        rgc.collect(); rgc.collect()
+        freed = 0
+        for r in r_list:
+            if r() is None:
+                freed += 1
+        print freed
+        return 0
+
+    return entrypoint
+
+
+def get_functions_to_patch():
+    from pypy.jit.backend.llsupport import gc
+    #
+    can_use_nursery_malloc1 = gc.GcLLDescr_framework.can_use_nursery_malloc
+    def can_use_nursery_malloc2(*args):
+        try:
+            if os.environ['PYPY_NO_INLINE_MALLOC']:
+                return False
+        except KeyError:
+            pass
+        return can_use_nursery_malloc1(*args)
+    #
+    return {(gc.GcLLDescr_framework, 'can_use_nursery_malloc'):
+                can_use_nursery_malloc2}
+
+def compile(f, gc, enable_opts='', **kwds):
+    from pypy.annotation.listdef import s_list_of_strings
+    from pypy.translator.translator import TranslationContext
+    from pypy.jit.metainterp.warmspot import apply_jit
+    from pypy.translator.c import genc
+    #
+    t = TranslationContext()
+    t.config.translation.gc = gc
+    if gc != 'boehm':
+        t.config.translation.gcremovetypeptr = True
+    for name, value in kwds.items():
+        setattr(t.config.translation, name, value)
+    ann = t.buildannotator(policy=annpolicy.StrictAnnotatorPolicy())
+    ann.build_types(f, [s_list_of_strings], main_entry_point=True)
+    t.buildrtyper().specialize()
+
+    if kwds['jit']:
+        patch = get_functions_to_patch()
+        old_value = {}
+        try:
+            for (obj, attr), value in patch.items():
+                old_value[obj, attr] = getattr(obj, attr)
+                setattr(obj, attr, value)
+            #
+            apply_jit(t, enable_opts=enable_opts)
+            #
+        finally:
+            for (obj, attr), oldvalue in old_value.items():
+                setattr(obj, attr, oldvalue)
+
+    cbuilder = genc.CStandaloneBuilder(t, f, t.config)
+    cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
+    cbuilder.compile()
+    return cbuilder
+
+def run(cbuilder, args=''):
+    #
+    pypylog = udir.join('test_zrpy_gc.log')
+    data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog})
+    return data.strip()
+
+def compile_and_run(f, gc, **kwds):
+    cbuilder = compile(f, gc, **kwds)
+    return run(cbuilder)
+
+
+
+def test_compile_boehm():
+    myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
+    @dont_look_inside
+    def see(lst, n):
+        assert len(lst) == 3
+        assert lst[0] == n+10
+        assert lst[1] == n+20
+        assert lst[2] == n+30
+    def main(n, x):
+        while n > 0:
+            myjitdriver.can_enter_jit(n=n, x=x)
+            myjitdriver.jit_merge_point(n=n, x=x)
+            y = X()
+            y.foo = x.foo
+            n -= y.foo
+            see([n+10, n+20, n+30], n)
+    res = compile_and_run(get_entry(get_g(main)), "boehm", jit=True)
+    assert int(res) >= 16
+
+# ______________________________________________________________________
+
+
+class BaseFrameworkTests(object):
+    compile_kwds = {}
+
+    def setup_class(cls):
+        funcs = []
+        name_to_func = {}
+        for fullname in dir(cls):
+            if not fullname.startswith('define'):
+                continue
+            definefunc = getattr(cls, fullname)
+            _, name = fullname.split('_', 1)
+            beforefunc, loopfunc, afterfunc = definefunc.im_func(cls)
+            if beforefunc is None:
+                def beforefunc(n, x):
+                    return n, x, None, None, None, None, None, None, None, None, None, ''
+            if afterfunc is None:
+                def afterfunc(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+                    pass
+            beforefunc.func_name = 'before_'+name
+            loopfunc.func_name = 'loop_'+name
+            afterfunc.func_name = 'after_'+name
+            funcs.append((beforefunc, loopfunc, afterfunc))
+            assert name not in name_to_func
+            name_to_func[name] = len(name_to_func)
+        print name_to_func
+        def allfuncs(name, n):
+            x = X()
+            x.foo = 2
+            main_allfuncs(name, n, x)
+            x.foo = 5
+            return weakref.ref(x)
+        def main_allfuncs(name, n, x):
+            num = name_to_func[name]
+            n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][0](n, x)
+            while n > 0:
+                myjitdriver.can_enter_jit(num=num, n=n, x=x, x0=x0, x1=x1,
+                        x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s)
+                myjitdriver.jit_merge_point(num=num, n=n, x=x, x0=x0, x1=x1,
+                        x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s)
+
+                n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][1](
+                        n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s)
+            funcs[num][2](n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s)
+        myjitdriver = JitDriver(greens = ['num'],
+                                reds = ['n', 'x', 'x0', 'x1', 'x2', 'x3', 'x4',
+                                        'x5', 'x6', 'x7', 'l', 's'])
+        cls.main_allfuncs = staticmethod(main_allfuncs)
+        cls.name_to_func = name_to_func
+        OLD_DEBUG = GcLLDescr_framework.DEBUG
+        try:
+            GcLLDescr_framework.DEBUG = True
+            cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC,
+                                   gcrootfinder=cls.gcrootfinder, jit=True,
+                                   **cls.compile_kwds)
+        finally:
+            GcLLDescr_framework.DEBUG = OLD_DEBUG
+
+    def _run(self, name, n, env):
+        res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env)
+        assert int(res) == 20
+
+    def run(self, name, n=2000):
+        pypylog = udir.join('TestCompileFramework.log')
+        env = {'PYPYLOG': ':%s' % pypylog,
+               'PYPY_NO_INLINE_MALLOC': '1'}
+        self._run(name, n, env)
+        env['PYPY_NO_INLINE_MALLOC'] = ''
+        self._run(name, n, env)
+
+    def run_orig(self, name, n, x):
+        self.main_allfuncs(name, n, x)
+
+
+class CompileFrameworkTests(BaseFrameworkTests):
+    # Test suite using (so far) the minimark GC.
+
+##    def define_libffi_workaround(cls):
+##        # XXX: this is a workaround for a bug in database.py.  It seems that
+##        # the problem is triggered by optimizeopt/fficall.py, and in
+##        # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in
+##        # these tests, that line is the only place where libffi.Func is
+##        # referenced.
+##        #
+##        # The problem occurs because the gctransformer tries to annotate a
+##        # low-level helper to call the __del__ of libffi.Func when it's too
+##        # late.
+##        #
+##        # This workaround works by forcing the annotator (and all the rest of
+##        # the toolchain) to see libffi.Func in a "proper" context, not just as
+##        # the target of cast_base_ptr_to_instance.  Note that the function
+##        # below is *never* called by any actual test, it's just annotated.
+##        #
+##        from pypy.rlib.libffi import get_libc_name, CDLL, types, ArgChain
+##        libc_name = get_libc_name()
+##        def f(n, x, *args):
+##            libc = CDLL(libc_name)
+##            ptr = libc.getpointer('labs', [types.slong], types.slong)
+##            chain = ArgChain()
+##            chain.arg(n)
+##            n = ptr.call(chain, lltype.Signed)
+##            return (n, x) + args
+##        return None, f, None
+
+    def define_compile_framework_1(cls):
+        # a moving GC.  Supports malloc_varsize_nonmovable.  Simple test, works
+        # without write_barriers and root stack enumeration.
+        def f(n, x, *args):
+            y = X()
+            y.foo = x.foo
+            n -= y.foo
+            return (n, x) + args
+        return None, f, None
+
+    def test_compile_framework_1(self):
+        self.run('compile_framework_1')
+
+    def define_compile_framework_2(cls):
+        # More complex test, requires root stack enumeration but
+        # not write_barriers.
+        def f(n, x, *args):
+            prev = x
+            for j in range(101):    # f() runs 20'000 times, thus allocates
+                y = X()             # a total of 2'020'000 objects
+                y.foo = prev.foo
+                prev = y
+            n -= prev.foo
+            return (n, x) + args
+        return None, f, None
+
+    def test_compile_framework_2(self):
+        self.run('compile_framework_2')
+
+    def define_compile_framework_3(cls):
+        # Third version of the test.  Really requires write_barriers.
+        def f(n, x, *args):
+            x.next = None
+            for j in range(101):    # f() runs 20'000 times, thus allocates
+                y = X()             # a total of 2'020'000 objects
+                y.foo = j+1
+                y.next = x.next
+                x.next = y
+            check(x.next.foo == 101)
+            total = 0
+            y = x
+            for j in range(101):
+                y = y.next
+                total += y.foo
+            check(not y.next)
+            check(total == 101*102/2)
+            n -= x.foo
+            return (n, x) + args
+        return None, f, None
+
+
+
+    def test_compile_framework_3(self):
+        x_test = X()
+        x_test.foo = 5
+        self.run_orig('compile_framework_3', 6, x_test)     # check that it does not raise CheckError
+        self.run('compile_framework_3')
+
+    def define_compile_framework_3_extra(cls):
+        # Extra version of the test, with tons of live vars around the residual
+        # call that all contain a GC pointer.
+        @dont_look_inside
+        def residual(n=26):
+            x = X()
+            x.next = X()
+            x.next.foo = n
+            return x
+        #
+        def before(n, x):
+            residual(5)
+            x0 = residual()
+            x1 = residual()
+            x2 = residual()
+            x3 = residual()
+            x4 = residual()
+            x5 = residual()
+            x6 = residual()
+            x7 = residual()
+            n *= 19
+            return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            x8 = residual()
+            x9 = residual()
+            check(x0.next.foo == 26)
+            check(x1.next.foo == 26)
+            check(x2.next.foo == 26)
+            check(x3.next.foo == 26)
+            check(x4.next.foo == 26)
+            check(x5.next.foo == 26)
+            check(x6.next.foo == 26)
+            check(x7.next.foo == 26)
+            check(x8.next.foo == 26)
+            check(x9.next.foo == 26)
+            x0, x1, x2, x3, x4, x5, x6, x7 = x7, x4, x6, x5, x3, x2, x9, x8
+            n -= 1
+            return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None
+        return before, f, None
+
+    def test_compile_framework_3_extra(self):
+        self.run_orig('compile_framework_3_extra', 6, None)     # check that it does not raise CheckError
+        self.run('compile_framework_3_extra')
+
+    def define_compile_framework_4(cls):
+        # Fourth version of the test, with __del__.
+        from pypy.rlib.debug import debug_print
+        class Counter:
+            cnt = 0
+        counter = Counter()
+        class Z:
+            def __del__(self):
+                counter.cnt -= 1
+        def before(n, x):
+            debug_print('counter.cnt =', counter.cnt)
+            check(counter.cnt < 5)
+            counter.cnt = n // x.foo
+            return n, x, None, None, None, None, None, None, None, None, None, None
+        def f(n, x, *args):
+            Z()
+            n -= x.foo
+            return (n, x) + args
+        return before, f, None
+
+    def test_compile_framework_4(self):
+        self.run('compile_framework_4')
+
+    def define_compile_framework_5(cls):
+        # Test string manipulation.
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            n -= x.foo
+            s += str(n)
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            check(len(s) == 1*5 + 2*45 + 3*450 + 4*500)
+        return None, f, after
+
+    def test_compile_framework_5(self):
+        self.run('compile_framework_5')
+
+    def define_compile_framework_7(cls):
+        # Array of pointers (test the write barrier for setarrayitem_gc)
+        def before(n, x):
+            return n, x, None, None, None, None, None, None, None, None, [X(123)], None
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            if n < 1900:
+                check(l[0].x == 123)
+                l = [None] * 16
+                l[0] = X(123)
+                l[1] = X(n)
+                l[2] = X(n+10)
+                l[3] = X(n+20)
+                l[4] = X(n+30)
+                l[5] = X(n+40)
+                l[6] = X(n+50)
+                l[7] = X(n+60)
+                l[8] = X(n+70)
+                l[9] = X(n+80)
+                l[10] = X(n+90)
+                l[11] = X(n+100)
+                l[12] = X(n+110)
+                l[13] = X(n+120)
+                l[14] = X(n+130)
+                l[15] = X(n+140)
+            if n < 1800:
+                check(len(l) == 16)
+                check(l[0].x == 123)
+                check(l[1].x == n)
+                check(l[2].x == n+10)
+                check(l[3].x == n+20)
+                check(l[4].x == n+30)
+                check(l[5].x == n+40)
+                check(l[6].x == n+50)
+                check(l[7].x == n+60)
+                check(l[8].x == n+70)
+                check(l[9].x == n+80)
+                check(l[10].x == n+90)
+                check(l[11].x == n+100)
+                check(l[12].x == n+110)
+                check(l[13].x == n+120)
+                check(l[14].x == n+130)
+                check(l[15].x == n+140)
+            n -= x.foo
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            check(len(l) == 16)
+            check(l[0].x == 123)
+            check(l[1].x == 2)
+            check(l[2].x == 12)
+            check(l[3].x == 22)
+            check(l[4].x == 32)
+            check(l[5].x == 42)
+            check(l[6].x == 52)
+            check(l[7].x == 62)
+            check(l[8].x == 72)
+            check(l[9].x == 82)
+            check(l[10].x == 92)
+            check(l[11].x == 102)
+            check(l[12].x == 112)
+            check(l[13].x == 122)
+            check(l[14].x == 132)
+            check(l[15].x == 142)
+        return before, f, after
+
+    def test_compile_framework_7(self):
+        self.run('compile_framework_7')
+
+    def define_compile_framework_7_interior(cls):
+        # Array of structs containing pointers (test the write barrier
+        # for setinteriorfield_gc)
+        S = lltype.GcStruct('S', ('i', lltype.Signed))
+        A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)),
+                                                  ('y', lltype.Ptr(S)),
+                                                  ('z', lltype.Ptr(S))))
+        class Glob:
+            a = lltype.nullptr(A)
+        glob = Glob()
+        #
+        def make_s(i):
+            s = lltype.malloc(S)
+            s.i = i
+            return s
+        #
+        @unroll_safe
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            a = glob.a
+            if not a:
+                a = glob.a = lltype.malloc(A, 10)
+            i = 0
+            while i < 10:
+                a[i].x = make_s(n + i * 100 + 1)
+                a[i].y = make_s(n + i * 100 + 2)
+                a[i].z = make_s(n + i * 100 + 3)
+                i += 1
+            i = 0
+            while i < 10:
+                check(a[i].x.i == n + i * 100 + 1)
+                check(a[i].y.i == n + i * 100 + 2)
+                check(a[i].z.i == n + i * 100 + 3)
+                i += 1
+            n -= x.foo
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        return None, f, None
+
+    def test_compile_framework_7_interior(self):
+        self.run('compile_framework_7_interior')
+
+    def define_compile_framework_8(cls):
+        # Array of pointers, of unknown length (test write_barrier_from_array)
+        def before(n, x):
+            return n, x, None, None, None, None, None, None, None, None, [X(123)], None
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            if n < 1900:
+                check(l[0].x == 123)
+                l = [None] * (16 + (n & 7))
+                l[0] = X(123)
+                l[1] = X(n)
+                l[2] = X(n+10)
+                l[3] = X(n+20)
+                l[4] = X(n+30)
+                l[5] = X(n+40)
+                l[6] = X(n+50)
+                l[7] = X(n+60)
+                l[8] = X(n+70)
+                l[9] = X(n+80)
+                l[10] = X(n+90)
+                l[11] = X(n+100)
+                l[12] = X(n+110)
+                l[13] = X(n+120)
+                l[14] = X(n+130)
+                l[15] = X(n+140)
+            if n < 1800:
+                check(len(l) == 16 + (n & 7))
+                check(l[0].x == 123)
+                check(l[1].x == n)
+                check(l[2].x == n+10)
+                check(l[3].x == n+20)
+                check(l[4].x == n+30)
+                check(l[5].x == n+40)
+                check(l[6].x == n+50)
+                check(l[7].x == n+60)
+                check(l[8].x == n+70)
+                check(l[9].x == n+80)
+                check(l[10].x == n+90)
+                check(l[11].x == n+100)
+                check(l[12].x == n+110)
+                check(l[13].x == n+120)
+                check(l[14].x == n+130)
+                check(l[15].x == n+140)
+            n -= x.foo
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            check(len(l) >= 16)
+            check(l[0].x == 123)
+            check(l[1].x == 2)
+            check(l[2].x == 12)
+            check(l[3].x == 22)
+            check(l[4].x == 32)
+            check(l[5].x == 42)
+            check(l[6].x == 52)
+            check(l[7].x == 62)
+            check(l[8].x == 72)
+            check(l[9].x == 82)
+            check(l[10].x == 92)
+            check(l[11].x == 102)
+            check(l[12].x == 112)
+            check(l[13].x == 122)
+            check(l[14].x == 132)
+            check(l[15].x == 142)
+        return before, f, after
+
+    def test_compile_framework_8(self):
+        self.run('compile_framework_8')
+
+    def define_compile_framework_9(cls):
+        # Like compile_framework_8, but with variable indexes and large
+        # arrays, testing the card_marking case
+        def before(n, x):
+            return n, x, None, None, None, None, None, None, None, None, [X(123)], None
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            if n < 1900:
+                check(l[0].x == 123)
+                num = 512 + (n & 7)
+                l = [None] * num
+                l[0] = X(123)
+                l[1] = X(n)
+                l[2] = X(n+10)
+                l[3] = X(n+20)
+                l[4] = X(n+30)
+                l[5] = X(n+40)
+                l[6] = X(n+50)
+                l[7] = X(n+60)
+                l[num-8] = X(n+70)
+                l[num-9] = X(n+80)
+                l[num-10] = X(n+90)
+                l[num-11] = X(n+100)
+                l[-12] = X(n+110)
+                l[-13] = X(n+120)
+                l[-14] = X(n+130)
+                l[-15] = X(n+140)
+            if n < 1800:
+                num = 512 + (n & 7)
+                check(len(l) == num)
+                check(l[0].x == 123)
+                check(l[1].x == n)
+                check(l[2].x == n+10)
+                check(l[3].x == n+20)
+                check(l[4].x == n+30)
+                check(l[5].x == n+40)
+                check(l[6].x == n+50)
+                check(l[7].x == n+60)
+                check(l[num-8].x == n+70)
+                check(l[num-9].x == n+80)
+                check(l[num-10].x == n+90)
+                check(l[num-11].x == n+100)
+                check(l[-12].x == n+110)
+                check(l[-13].x == n+120)
+                check(l[-14].x == n+130)
+                check(l[-15].x == n+140)
+            n -= x.foo
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            check(len(l) >= 512)
+            check(l[0].x == 123)
+            check(l[1].x == 2)
+            check(l[2].x == 12)
+            check(l[3].x == 22)
+            check(l[4].x == 32)
+            check(l[5].x == 42)
+            check(l[6].x == 52)
+            check(l[7].x == 62)
+            check(l[-8].x == 72)
+            check(l[-9].x == 82)
+            check(l[-10].x == 92)
+            check(l[-11].x == 102)
+            check(l[-12].x == 112)
+            check(l[-13].x == 122)
+            check(l[-14].x == 132)
+            check(l[-15].x == 142)
+        return before, f, after
+
+    def test_compile_framework_9(self):
+        self.run('compile_framework_9')
+
+    def define_compile_framework_external_exception_handling(cls):
+        def before(n, x):
+            x = X(0)
+            return n, x, None, None, None, None, None, None, None, None, None, None
+
+        @dont_look_inside
+        def g(x):
+            if x > 200:
+                return 2
+            raise ValueError
+        @dont_look_inside
+        def h(x):
+            if x > 150:
+                raise ValueError
+            return 2
+
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            try:
+                x.x += g(n)
+            except ValueError:
+                x.x += 1
+            try:
+                x.x += h(n)
+            except ValueError:
+                x.x -= 1
+            n -= 1
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+
+        def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            check(x.x == 1800 * 2 + 1850 * 2 + 200 - 150)
+
+        return before, f, None
+
+    def test_compile_framework_external_exception_handling(self):
+        self.run('compile_framework_external_exception_handling')
+
+    def define_compile_framework_bug1(self):
+        @elidable
+        def nonmoving():
+            x = X(1)
+            for i in range(7):
+                rgc.collect()
+            return x
+
+        @dont_look_inside
+        def do_more_stuff():
+            x = X(5)
+            for i in range(7):
+                rgc.collect()
+            return x
+
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            x0 = do_more_stuff()
+            check(nonmoving().x == 1)
+            n -= 1
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+
+        return None, f, None
+
+    def test_compile_framework_bug1(self):
+        self.run('compile_framework_bug1', 200)
+
+    def define_compile_framework_vref(self):
+        from pypy.rlib.jit import virtual_ref, virtual_ref_finish
+        class A:
+            pass
+        glob = A()
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            a = A()
+            glob.v = vref = virtual_ref(a)
+            virtual_ref_finish(vref, a)
+            n -= 1
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        return None, f, None
+
+    def test_compile_framework_vref(self):
+        self.run('compile_framework_vref', 200)
+
+    def define_compile_framework_float(self):
+        # test for a bug: the fastpath_malloc does not save and restore
+        # xmm registers around the actual call to the slow path
+        class A:
+            x0 = x1 = x2 = x3 = x4 = x5 = x6 = x7 = 0
+        @dont_look_inside
+        def escape1(a):
+            a.x0 += 0
+            a.x1 += 6
+            a.x2 += 12
+            a.x3 += 18
+            a.x4 += 24
+            a.x5 += 30
+            a.x6 += 36
+            a.x7 += 42
+        @dont_look_inside
+        def escape2(n, f0, f1, f2, f3, f4, f5, f6, f7):
+            check(f0 == n + 0.0)
+            check(f1 == n + 0.125)
+            check(f2 == n + 0.25)
+            check(f3 == n + 0.375)
+            check(f4 == n + 0.5)
+            check(f5 == n + 0.625)
+            check(f6 == n + 0.75)
+            check(f7 == n + 0.875)
+        @unroll_safe
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            i = 0
+            while i < 42:
+                m = n + i
+                f0 = m + 0.0
+                f1 = m + 0.125
+                f2 = m + 0.25
+                f3 = m + 0.375
+                f4 = m + 0.5
+                f5 = m + 0.625
+                f6 = m + 0.75
+                f7 = m + 0.875
+                a1 = A()
+                # at this point, all or most f's are still in xmm registers
+                escape1(a1)
+                escape2(m, f0, f1, f2, f3, f4, f5, f6, f7)
+                i += 1
+            n -= 1
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        return None, f, None
+
+    def test_compile_framework_float(self):
+        self.run('compile_framework_float')
+
+    def define_compile_framework_minimal_size_in_nursery(self):
+        S = lltype.GcStruct('S')    # no fields!
+        T = lltype.GcStruct('T', ('i', lltype.Signed))
+        @unroll_safe
+        def f42(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            lst1 = []
+            lst2 = []
+            i = 0
+            while i < 42:
+                s1 = lltype.malloc(S)
+                t1 = lltype.malloc(T)
+                t1.i = 10000 + i + n
+                lst1.append(s1)
+                lst2.append(t1)
+                i += 1
+            i = 0
+            while i < 42:
+                check(lst2[i].i == 10000 + i + n)
+                i += 1
+            n -= 1
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        return None, f42, None
+
+    def test_compile_framework_minimal_size_in_nursery(self):
+        self.run('compile_framework_minimal_size_in_nursery')
+
+
+class TestShadowStack(CompileFrameworkTests):
+    gcrootfinder = "shadowstack"
+
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
@@ -47,8 +47,7 @@
         return ExternalCompilationInfo(
             pre_include_bits=['/* using %s */' % (gct.__class__.__name__,),
                               '#define MALLOC_ZERO_FILLED %d' % (gct.malloc_zero_filled,),
-                              ],
-            post_include_bits=['typedef void *GC_hidden_pointer;']
+                              ]
             )
 
     def get_prebuilt_hash(self, obj):


More information about the pypy-commit mailing list