Author: Maciej Fijalkowski <[email protected]>
Branch: optresult-unroll
Changeset: r79417:798a1f163fda
Date: 2015-09-04 13:28 +0200
http://bitbucket.org/pypy/pypy/changeset/798a1f163fda/
Log: merge
diff --git a/rpython/jit/backend/llsupport/descr.py
b/rpython/jit/backend/llsupport/descr.py
--- a/rpython/jit/backend/llsupport/descr.py
+++ b/rpython/jit/backend/llsupport/descr.py
@@ -64,7 +64,7 @@
return heaptracker.adr2int(llmemory.cast_ptr_to_adr(self.vtable))
def get_type_id(self):
- assert self.tid != 0
+ assert self.tid
return self.tid
def get_size_descr(gccache, STRUCT,
vtable=lltype.nullptr(rclass.OBJECT_VTABLE)):
@@ -293,7 +293,7 @@
assert False
def get_type_id(self):
- assert self.tid != 0
+ assert self.tid
return self.tid
def repr_of_descr(self):
diff --git a/rpython/jit/backend/llsupport/gc.py
b/rpython/jit/backend/llsupport/gc.py
--- a/rpython/jit/backend/llsupport/gc.py
+++ b/rpython/jit/backend/llsupport/gc.py
@@ -24,6 +24,7 @@
class MovableObjectTracker(object):
ptr_array_type = lltype.GcArray(llmemory.GCREF)
+ ptr_array_gcref = lltype.nullptr(llmemory.GCREF.TO)
def __init__(self, cpu, const_pointers):
size = len(const_pointers)
@@ -438,6 +439,7 @@
self._make_gcrootmap()
self._setup_gcclass()
self._setup_tid()
+ self._setup_guard_is_object()
self._setup_write_barrier()
self._setup_str()
self._make_functions(really_not_translated)
@@ -662,6 +664,54 @@
def get_malloc_slowpath_array_addr(self):
return self.get_malloc_fn_addr('malloc_array')
+ def get_typeid_from_classptr_if_gcremovetypeptr(self, classptr):
+ """Returns the typeid corresponding from a vtable pointer 'classptr'.
+ This function only works if cpu.vtable_offset is None, i.e. in
+ a translation with --gcremovetypeptr.
+ """
+ from rpython.memory.gctypelayout import GCData
+ assert self.gcdescr.config.translation.gcremovetypeptr
+
+ # hard-coded assumption: to go from an object to its class
+ # we would use the following algorithm:
+ # - read the typeid from mem(locs[0]), i.e. at offset 0;
+ # this is a complete word (N=4 bytes on 32-bit, N=8 on
+ # 64-bits)
+ # - keep the lower half of what is read there (i.e.
+ # truncate to an unsigned 'N / 2' bytes value)
+ # - multiply by 4 (on 32-bits only) and use it as an
+ # offset in type_info_group
+ # - add 16/32 bytes, to go past the TYPE_INFO structure
+ # here, we have to go back from 'classptr' back to the typeid,
+ # so we do (part of) these computations in reverse.
+
+ sizeof_ti = rffi.sizeof(GCData.TYPE_INFO)
+ type_info_group = llop.gc_get_type_info_group(llmemory.Address)
+ type_info_group = rffi.cast(lltype.Signed, type_info_group)
+ expected_typeid = classptr - sizeof_ti - type_info_group
+ if WORD == 4:
+ expected_typeid >>= 2
+ return expected_typeid
+
+ def _setup_guard_is_object(self):
+ from rpython.memory.gctypelayout import GCData, T_IS_RPYTHON_INSTANCE
+ self._infobits_offset, _ = symbolic.get_field_token(GCData.TYPE_INFO,
+ 'infobits', True)
+ self._T_IS_RPYTHON_INSTANCE = T_IS_RPYTHON_INSTANCE
+
+ def get_translated_info_for_guard_is_object(self):
+ type_info_group = llop.gc_get_type_info_group(llmemory.Address)
+ type_info_group = rffi.cast(lltype.Signed, type_info_group)
+ infobits_offset = rffi.cast(lltype.Signed, self._infobits_offset)
+ if WORD == 4:
+ shift_by = 2
+ elif WORD == 8:
+ shift_by = 0
+ return (type_info_group + infobits_offset,
+ shift_by,
+ self._T_IS_RPYTHON_INSTANCE)
+
+
# ____________________________________________________________
def get_ll_description(gcdescr, translator=None, rtyper=None):
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
@@ -25,6 +25,12 @@
HAS_CODEMAP = False
+ done_with_this_frame_descr_int = None # overridden by pyjitpl.py
+ done_with_this_frame_descr_float = None
+ done_with_this_frame_descr_ref = None
+ done_with_this_frame_descr_void = None
+ exit_frame_with_exception_descr_ref = None
+
def __init__(self, rtyper, stats, opts, translate_support_code=False,
gcdescr=None):
assert type(opts) is not bool
diff --git a/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
b/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
@@ -0,0 +1,132 @@
+from rpython.jit.backend.detect_cpu import getcpuclass
+from rpython.jit.tool.oparser import parse
+from rpython.jit.metainterp.history import JitCellToken, NoStats
+from rpython.jit.metainterp.history import BasicFinalDescr, BasicFailDescr
+from rpython.jit.metainterp.gc import get_description
+from rpython.annotator.listdef import s_list_of_strings
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
+from rpython.rtyper.rclass import getclassrepr, getinstancerepr
+from rpython.translator.unsimplify import call_initial_function
+from rpython.translator.translator import TranslationContext
+from rpython.translator.c import genc
+
+
+def run_guards_translated(gcremovetypeptr):
+ class A(object):
+ pass
+ class B(A):
+ pass
+ class C(B):
+ pass
+ def main(argv):
+ A(); B(); C()
+ return 0
+
+ t = TranslationContext()
+ t.config.translation.gc = "minimark"
+ t.config.translation.gcremovetypeptr = gcremovetypeptr
+ ann = t.buildannotator()
+ ann.build_types(main, [s_list_of_strings], main_entry_point=True)
+ rtyper = t.buildrtyper()
+ rtyper.specialize()
+
+ classdef = ann.bookkeeper.getuniqueclassdef(B)
+ rclass = getclassrepr(rtyper, classdef)
+ rinstance = getinstancerepr(rtyper, classdef)
+ LLB = rinstance.lowleveltype.TO
+ vtable_B = rclass.getvtable()
+ adr_vtable_B = llmemory.cast_ptr_to_adr(vtable_B)
+ vtable_B = llmemory.cast_adr_to_int(adr_vtable_B, mode="symbolic")
+
+ CPU = getcpuclass()
+ cpu = CPU(rtyper, NoStats(),
+ translate_support_code=True,
+ gcdescr=get_description(t.config))
+ execute_token = cpu.make_execute_token(llmemory.GCREF)
+ finaldescr = BasicFinalDescr()
+ faildescr = BasicFailDescr()
+
+ descr_B = cpu.sizeof(LLB, vtable_B)
+ typeid_B = descr_B.get_type_id()
+
+ loop1 = parse("""
+ [p0]
+ guard_class(p0, ConstInt(vtable_B), descr=faildescr) []
+ finish(descr=finaldescr)
+ """, namespace={'finaldescr': finaldescr,
+ 'faildescr': faildescr,
+ 'vtable_B': vtable_B})
+
+ loop2 = parse("""
+ [p0]
+ guard_gc_type(p0, ConstInt(typeid_B), descr=faildescr) []
+ finish(descr=finaldescr)
+ """, namespace={'finaldescr': finaldescr,
+ 'faildescr': faildescr,
+ 'typeid_B': typeid_B})
+
+ loop3 = parse("""
+ [p0]
+ guard_is_object(p0, descr=faildescr) []
+ finish(descr=finaldescr)
+ """, namespace={'finaldescr': finaldescr,
+ 'faildescr': faildescr})
+
+ def g():
+ cpu.setup_once()
+ token1 = JitCellToken()
+ token2 = JitCellToken()
+ token3 = JitCellToken()
+ cpu.compile_loop(loop1.inputargs, loop1.operations, token1)
+ cpu.compile_loop(loop2.inputargs, loop2.operations, token2)
+ cpu.compile_loop(loop3.inputargs, loop3.operations, token3)
+
+ for token, p0 in [
+ (token1, rffi.cast(llmemory.GCREF, A())),
+ (token1, rffi.cast(llmemory.GCREF, B())),
+ (token1, rffi.cast(llmemory.GCREF, C())),
+
+ (token2, rffi.cast(llmemory.GCREF, A())),
+ (token2, rffi.cast(llmemory.GCREF, B())),
+ (token2, rffi.cast(llmemory.GCREF, C())),
+ (token2, rffi.cast(llmemory.GCREF, [42, 43])),
+
+ (token3, rffi.cast(llmemory.GCREF, A())),
+ (token3, rffi.cast(llmemory.GCREF, B())),
+ (token3, rffi.cast(llmemory.GCREF, [44, 45])),
+ ]:
+ frame = execute_token(token, p0)
+ descr = cpu.get_latest_descr(frame)
+ if descr is finaldescr:
+ print 'match'
+ elif descr is faildescr:
+ print 'fail'
+ else:
+ print '???'
+
+ call_initial_function(t, g)
+
+ cbuilder = genc.CStandaloneBuilder(t, main, t.config)
+ cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
+ cbuilder.compile()
+
+ data = cbuilder.cmdexec('')
+ assert data == ('fail\n'
+ 'match\n'
+ 'fail\n'
+
+ 'fail\n'
+ 'match\n'
+ 'fail\n'
+ 'fail\n'
+
+ 'match\n'
+ 'match\n'
+ 'fail\n')
+
+
+def test_guards_translated_with_gctypeptr():
+ run_guards_translated(gcremovetypeptr=False)
+
+def test_guards_translated_without_gctypeptr():
+ run_guards_translated(gcremovetypeptr=True)
diff --git a/rpython/jit/backend/x86/assembler.py
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1741,25 +1741,10 @@
if offset is not None:
self.mc.CMP(mem(loc_ptr, offset), loc_classptr)
else:
- # XXX hard-coded assumption: to go from an object to its class
- # we use the following algorithm:
- # - read the typeid from mem(locs[0]), i.e. at offset 0;
- # this is a complete word (N=4 bytes on 32-bit, N=8 on
- # 64-bits)
- # - keep the lower half of what is read there (i.e.
- # truncate to an unsigned 'N / 2' bytes value)
- # - multiply by 4 (on 32-bits only) and use it as an
- # offset in type_info_group
- # - add 16/32 bytes, to go past the TYPE_INFO structure
assert isinstance(loc_classptr, ImmedLoc)
classptr = loc_classptr.value
- # here, we have to go back from 'classptr' to the value expected
- # from reading the half-word in the object header.
- from rpython.memory.gctypelayout import GCData
- sizeof_ti = rffi.sizeof(GCData.TYPE_INFO)
- type_info_group = llop.gc_get_type_info_group(llmemory.Address)
- type_info_group = rffi.cast(lltype.Signed, type_info_group)
- expected_typeid = classptr - sizeof_ti - type_info_group
+ expected_typeid = (self.cpu.gc_ll_descr
+ .get_typeid_from_classptr_if_gcremovetypeptr(classptr))
self._cmp_guard_gc_type(loc_ptr, ImmedLoc(expected_typeid))
def _cmp_guard_gc_type(self, loc_ptr, loc_expected_typeid):
@@ -1795,6 +1780,23 @@
self._cmp_guard_gc_type(locs[0], locs[1])
self.implement_guard(guard_token, 'NE')
+ def genop_guard_guard_is_object(self, ign_1, guard_op,
+ guard_token, locs, ign_2):
+ assert self.cpu.supports_guard_gc_type
+ [loc_object, loc_typeid] = locs
+ # idea: read the typeid, fetch the field 'infobits' from the big
+ # typeinfo table, and check the flag 'T_IS_RPYTHON_INSTANCE'.
+ base_type_info, shift_by, IS_OBJECT_FLAG = (
+ self.cpu.gc_ll_descr.get_translated_info_for_guard_is_object())
+ if IS_X86_32:
+ self.mc.MOVZX16(loc_typeid, mem(loc_object, 0))
+ else:
+ self.mc.MOV32(loc_typeid, mem(loc_object, 0))
+ loc_infobits = addr_add(imm(base_type_info), loc_typeid,
scale=shift_by)
+ self.mc.TEST(loc_infobits, imm(IS_OBJECT_FLAG))
+ #
+ self.implement_guard(guard_token, 'Z')
+
def implement_guard_recovery(self, guard_opnum, faildescr, failargs,
fail_locs, frame_depth):
exc = (guard_opnum == rop.GUARD_EXCEPTION or
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
@@ -431,10 +431,14 @@
consider_guard_gc_type = consider_guard_class
def consider_guard_is_object(self, op):
- xxx
+ x = self.make_sure_var_in_reg(op.getarg(0))
+ tmp_box = TempVar()
+ y = self.rm.force_allocate_reg(tmp_box)
+ self.rm.possibly_free_var(tmp_box)
+ self.perform_guard(op, [x, y], None)
def consider_guard_subclass(self, op):
- xxx
+ assert 0 # xxx
def _consider_binop_part(self, op, symm=False):
x = op.getarg(0)
@@ -798,6 +802,7 @@
def _consider_real_call(self, op):
effectinfo = op.getdescr().get_extra_info()
+ assert effectinfo is not None
oopspecindex = effectinfo.oopspecindex
if oopspecindex != EffectInfo.OS_NONE:
if IS_X86_32:
diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py
--- a/rpython/jit/backend/x86/rx86.py
+++ b/rpython/jit/backend/x86/rx86.py
@@ -674,6 +674,9 @@
TEST8_bi = insn(rex_nw, '\xF6', orbyte(0<<3), stack_bp(1), immediate(2,
'b'))
TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_(1), immediate(2, 'b'))
TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
+ TEST_ai = insn(rex_w, '\xF7', orbyte(0<<3),
mem_reg_plus_scaled_reg_plus_const(1), immediate(2))
+ TEST_mi = insn(rex_w, '\xF7', orbyte(0<<3), mem_reg_plus_const(1),
immediate(2))
+ TEST_ji = insn(rex_w, '\xF7', orbyte(0<<3), abs_(1), immediate(2))
BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1))
BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_(1))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit