[pypy-commit] pypy optresult-unroll: Implement and test guard_subclass.
arigo
noreply at buildbot.pypy.org
Fri Sep 4 15:06:36 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: optresult-unroll
Changeset: r79419:17252241ecf0
Date: 2015-09-04 14:09 +0100
http://bitbucket.org/pypy/pypy/changeset/17252241ecf0/
Log: Implement and test guard_subclass.
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
@@ -693,6 +693,17 @@
expected_typeid >>= 2
return expected_typeid
+ def get_translated_info_for_typeinfo(self):
+ from rpython.memory.gctypelayout import GCData
+ type_info_group = llop.gc_get_type_info_group(llmemory.Address)
+ type_info_group = rffi.cast(lltype.Signed, type_info_group)
+ if WORD == 4:
+ shift_by = 2
+ elif WORD == 8:
+ shift_by = 0
+ sizeof_ti = rffi.sizeof(GCData.TYPE_INFO)
+ return (type_info_group, shift_by, sizeof_ti)
+
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,
@@ -700,16 +711,8 @@
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)
+ return (infobits_offset, self._T_IS_RPYTHON_INSTANCE)
# ____________________________________________________________
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
@@ -54,6 +54,8 @@
self.vtable_offset, _ = symbolic.get_field_token(rclass.OBJECT,
'typeptr',
translate_support_code)
+ self.subclassrange_min_offset, _ = symbolic.get_field_token(
+ rclass.OBJECT_VTABLE, 'subclassrange_min', translate_support_code)
if translate_support_code:
self._setup_exception_handling_translated()
else:
diff --git a/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py b/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
--- a/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
+++ b/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
@@ -72,14 +72,24 @@
""", namespace={'finaldescr': finaldescr,
'faildescr': faildescr})
+ loop4 = parse("""
+ [p0]
+ guard_subclass(p0, ConstInt(vtable_B), descr=faildescr) []
+ finish(descr=finaldescr)
+ """, namespace={'finaldescr': finaldescr,
+ 'faildescr': faildescr,
+ 'vtable_B': vtable_B})
+
def g():
cpu.setup_once()
token1 = JitCellToken()
token2 = JitCellToken()
token3 = JitCellToken()
+ token4 = 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)
+ cpu.compile_loop(loop4.inputargs, loop4.operations, token4)
for token, p0 in [
(token1, rffi.cast(llmemory.GCREF, A())),
@@ -94,6 +104,10 @@
(token3, rffi.cast(llmemory.GCREF, A())),
(token3, rffi.cast(llmemory.GCREF, B())),
(token3, rffi.cast(llmemory.GCREF, [44, 45])),
+
+ (token4, rffi.cast(llmemory.GCREF, A())),
+ (token4, rffi.cast(llmemory.GCREF, B())),
+ (token4, rffi.cast(llmemory.GCREF, C())),
]:
frame = execute_token(token, p0)
descr = cpu.get_latest_descr(frame)
@@ -122,7 +136,11 @@
'match\n'
'match\n'
- 'fail\n')
+ 'fail\n'
+
+ 'fail\n'
+ 'match\n'
+ 'match\n')
def test_guards_translated_with_gctypeptr():
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
@@ -11,6 +11,7 @@
from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref
+from rpython.rtyper import rclass
from rpython.rlib.jit import AsmInfo
from rpython.jit.backend.model import CompiledLoopToken
from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs,
@@ -1786,17 +1787,58 @@
[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)
+ #
+ base_type_info, shift_by, sizeof_ti = (
+ self.cpu.gc_ll_descr.get_translated_info_for_typeinfo())
+ infobits_offset, IS_OBJECT_FLAG = (
+ self.cpu.gc_ll_descr.get_translated_info_for_guard_is_object())
+ loc_infobits = addr_add(imm(base_type_info), loc_typeid,
+ scale=shift_by, offset=infobits_offset)
self.mc.TEST(loc_infobits, imm(IS_OBJECT_FLAG))
#
self.implement_guard(guard_token, 'Z')
+ def genop_guard_guard_subclass(self, op, guard_op,
+ guard_token, locs, ign_2):
+ assert self.cpu.supports_guard_gc_type
+ [loc_object, loc_check_against_class, loc_tmp] = locs
+ assert isinstance(loc_object, RegLoc)
+ assert isinstance(loc_tmp, RegLoc)
+ offset = self.cpu.vtable_offset
+ offset2 = self.cpu.subclassrange_min_offset
+ if offset is not None:
+ # read this field to get the vtable pointer
+ self.mc.MOV_rm(loc_tmp.value, (loc_object.value, offset))
+ # read the vtable's subclassrange_min field
+ self.mc.MOV_rm(loc_tmp.value, (loc_tmp.value, offset2))
+ else:
+ # read the typeid
+ if IS_X86_32:
+ self.mc.MOVZX16(loc_tmp, mem(loc_object, 0))
+ else:
+ self.mc.MOV32(loc_tmp, mem(loc_object, 0))
+ # read the vtable's subclassrange_min field, as a single
+ # step with the correct offset
+ base_type_info, shift_by, sizeof_ti = (
+ self.cpu.gc_ll_descr.get_translated_info_for_typeinfo())
+ self.mc.MOV(loc_tmp, addr_add(imm(base_type_info), loc_tmp,
+ scale = shift_by,
+ offset = sizeof_ti + offset2))
+ # get the two bounds to check against
+ vtable_ptr = loc_check_against_class.getint()
+ vtable_ptr = rffi.cast(rclass.CLASSTYPE, vtable_ptr)
+ check_min = vtable_ptr.subclassrange_min
+ check_max = vtable_ptr.subclassrange_max
+ # check by doing the unsigned comparison (tmp - min) < (max - min)
+ self.mc.SUB_ri(loc_tmp.value, check_min)
+ self.mc.CMP_ri(loc_tmp.value, check_max - check_min)
+ # the guard fails if we get a "not below" result
+ self.implement_guard(guard_token, 'NB')
+
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
@@ -438,7 +438,12 @@
self.perform_guard(op, [x, y], None)
def consider_guard_subclass(self, op):
- assert 0 # xxx
+ x = self.make_sure_var_in_reg(op.getarg(0))
+ y = self.loc(op.getarg(1))
+ tmp_box = TempVar()
+ z = self.rm.force_allocate_reg(tmp_box)
+ self.rm.possibly_free_var(tmp_box)
+ self.perform_guard(op, [x, y, z], None)
def _consider_binop_part(self, op, symm=False):
x = op.getarg(0)
More information about the pypy-commit
mailing list