Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit