Author: Armin Rigo <ar...@tunes.org> Branch: optresult-unroll Changeset: r79410:39efc5926eb8 Date: 2015-09-04 10:28 +0200 http://bitbucket.org/pypy/pypy/changeset/39efc5926eb8/
Log: Untested so far: guard_is_object 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 @@ -438,6 +438,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 +663,48 @@ 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 translator.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 IS_X86_32: + 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) + return (type_info_group + infobits_offset, self._T_IS_RPYTHON_INSTANCE) + + # ____________________________________________________________ def get_ll_description(gcdescr, translator=None, rtyper=None): 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,25 @@ 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, 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)) + shift_by = 2 + else: + self.mc.MOVZX32(loc_typeid, mem(loc_object, 0)) + shift_by = 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,7 +431,11 @@ 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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit