Author: Maciej Fijalkowski <fij...@gmail.com> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit