Author: Maciej Fijalkowski <fij...@gmail.com> Branch: optresult-unroll Changeset: r79393:0cd368883dd1 Date: 2015-09-03 18:17 +0200 http://bitbucket.org/pypy/pypy/changeset/0cd368883dd1/
Log: merge diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -913,9 +913,25 @@ if TYPE != typeid.STRUCT_OR_ARRAY: self.fail_guard(descr) - def execute_guard_nonnull_gc_type(self, descr, arg, typeid): - self.execute_guard_nonnull(descr, arg) - self.execute_guard_gc_type(descr, arg, typeid) + def execute_guard_is_object(self, descr, arg): + TYPE = arg._obj.container._TYPE + while TYPE is not rclass.OBJECT: + if not isinstance(TYPE, lltype.GcStruct): # or TYPE is None + self.fail_guard(descr) + return + _, TYPE = TYPE._first_struct() + + def execute_guard_subclass(self, descr, arg, klass): + value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, arg) + expected_class = llmemory.cast_adr_to_ptr( + llmemory.cast_int_to_adr(klass), + rclass.CLASSTYPE) + if (expected_class.subclassrange_min + <= value.typeptr.subclassrange_min + <= expected_class.subclassrange_max): + pass + else: + self.fail_guard(descr) def execute_guard_no_exception(self, descr): if self.last_exception is not None: diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -4840,9 +4840,6 @@ c_typeid = ConstInt(descr.get_type_id()) self.execute_operation(rop.GUARD_GC_TYPE, [t_box, c_typeid], 'void') assert not self.guard_failed - self.execute_operation(rop.GUARD_NONNULL_GC_TYPE, [t_box, c_typeid], - 'void') - assert not self.guard_failed def test_passing_guard_gc_type_array(self): if not self.cpu.supports_guard_gc_type: @@ -4852,9 +4849,6 @@ c_typeid = ConstInt(arraydescr.get_type_id()) self.execute_operation(rop.GUARD_GC_TYPE, [a_box, c_typeid], 'void') assert not self.guard_failed - self.execute_operation(rop.GUARD_NONNULL_GC_TYPE, [a_box, c_typeid], - 'void') - assert not self.guard_failed def test_failing_guard_gc_type(self): if not self.cpu.supports_guard_gc_type: @@ -4866,17 +4860,78 @@ c_ttypeid = ConstInt(tdescr.get_type_id()) c_utypeid = ConstInt(udescr.get_type_id()) c_atypeid = ConstInt(adescr.get_type_id()) - null_box = self.null_instance() for opname, args in [(rop.GUARD_GC_TYPE, [t_box, c_utypeid]), (rop.GUARD_GC_TYPE, [u_box, c_ttypeid]), (rop.GUARD_GC_TYPE, [a_box, c_utypeid]), (rop.GUARD_GC_TYPE, [t_box, c_atypeid]), - (rop.GUARD_NONNULL_GC_TYPE, [t_box, c_utypeid]), - (rop.GUARD_NONNULL_GC_TYPE, [u_box, c_ttypeid]), - (rop.GUARD_NONNULL_GC_TYPE, [a_box, c_ttypeid]), - (rop.GUARD_NONNULL_GC_TYPE, [u_box, c_atypeid]), - (rop.GUARD_NONNULL_GC_TYPE, [null_box, c_ttypeid]), - (rop.GUARD_NONNULL_GC_TYPE, [null_box, c_atypeid]), ]: assert self.execute_operation(opname, args, 'void') == None assert self.guard_failed + + def test_guard_is_object(self): + if not self.cpu.supports_guard_gc_type: + py.test.skip("guard_gc_type not available") + t_box, _, _ = self.alloc_instance(self.T) + self.execute_operation(rop.GUARD_IS_OBJECT, [t_box], 'void') + # + assert not self.guard_failed + a_box, _ = self.alloc_array_of(rffi.SHORT, 342) + self.execute_operation(rop.GUARD_IS_OBJECT, [a_box], 'void') + assert self.guard_failed + # + S = lltype.GcStruct('S') + s = lltype.malloc(S, immortal=True, zero=True) + s_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, s)) + self.execute_operation(rop.GUARD_IS_OBJECT, [s_box], 'void') + assert self.guard_failed + + def test_guard_subclass(self): + if not self.cpu.supports_guard_gc_type: + py.test.skip("guard_gc_type not available") + + xtp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) + xtp.subclassrange_min = 1 + xtp.subclassrange_max = 3 + X = lltype.GcStruct('X', ('parent', rclass.OBJECT), + hints={'vtable': xtp._obj}) + xptr = lltype.malloc(X) + xptr.parent.typeptr = xtp + x_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, xptr)) + X_box = ConstInt(heaptracker.adr2int(llmemory.cast_ptr_to_adr(xtp))) + + ytp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) + ytp.subclassrange_min = 2 + ytp.subclassrange_max = 2 + assert rclass.ll_issubclass(ytp, xtp) + Y = lltype.GcStruct('Y', ('parent', X), + hints={'vtable': ytp._obj}) + yptr = lltype.malloc(Y) + yptr.parent.parent.typeptr = ytp + y_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, yptr)) + Y_box = ConstInt(heaptracker.adr2int(llmemory.cast_ptr_to_adr(ytp))) + + ztp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) + ztp.subclassrange_min = 4 + ztp.subclassrange_max = 5 + assert not rclass.ll_issubclass(ztp, xtp) + assert not rclass.ll_issubclass(xtp, ztp) + Z = lltype.GcStruct('Z', ('parent', rclass.OBJECT), + hints={'vtable': ztp._obj}) + zptr = lltype.malloc(Z) + zptr.parent.typeptr = ztp + z_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, zptr)) + Z_box = ConstInt(heaptracker.adr2int(llmemory.cast_ptr_to_adr(ztp))) + + for num, arg, klass, is_subclass in [ + (1, x_box, X_box, True), + (2, x_box, Y_box, False), + (3, x_box, Z_box, False), + (4, y_box, X_box, True), + (5, y_box, Y_box, True), + (6, y_box, Z_box, False), + (7, z_box, X_box, False), + (8, z_box, Y_box, False), + (9, z_box, Z_box, True), + ]: + self.execute_operation(rop.GUARD_SUBCLASS, [arg, klass], 'void') + assert self.guard_failed == (not is_subclass) 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 @@ -1734,7 +1734,9 @@ self.mc.CMP(locs[0], locs[1]) self.implement_guard(guard_token, 'NE') - def _cmp_guard_class(self, loc_ptr, loc_classptr): + def _cmp_guard_class(self, locs): + loc_ptr = locs[0] + loc_classptr = locs[1] offset = self.cpu.vtable_offset if offset is not None: self.mc.CMP(mem(loc_ptr, offset), loc_classptr) @@ -1770,18 +1772,8 @@ assert isinstance(loc_expected_typeid, ImmedLoc) self.mc.CMP32_mi((loc_ptr.value, 0), loc_expected_typeid.value) - def _cmp_guard_class_or_gc_type(self, guard_op, locs): - if ( guard_op.getopnum() == rop.GUARD_CLASS or - guard_op.getopnum() == rop.GUARD_NONNULL_CLASS): - self._cmp_guard_class(locs[0], locs[1]) - elif (guard_op.getopnum() == rop.GUARD_GC_TYPE or - guard_op.getopnum() == rop.GUARD_NONNULL_GC_TYPE): - self._cmp_guard_gc_type(locs[0], locs[1]) - else: - assert 0 - def genop_guard_guard_class(self, ign_1, guard_op, guard_token, locs, ign_2): - self._cmp_guard_class_or_gc_type(guard_op, locs) + self._cmp_guard_class(locs) self.implement_guard(guard_token, 'NE') def genop_guard_guard_nonnull_class(self, ign_1, guard_op, @@ -1790,7 +1782,7 @@ # Patched below self.mc.J_il8(rx86.Conditions['B'], 0) jb_location = self.mc.get_relative_pos() - self._cmp_guard_class_or_gc_type(guard_op, locs) + self._cmp_guard_class(locs) # patch the JB above offset = self.mc.get_relative_pos() - jb_location assert 0 < offset <= 127 @@ -1798,8 +1790,10 @@ # self.implement_guard(guard_token, 'NE') - genop_guard_guard_gc_type = genop_guard_guard_class - genop_guard_guard_nonnull_gc_type = genop_guard_guard_nonnull_class + def genop_guard_guard_gc_type(self, ign_1, guard_op, + guard_token, locs, ign_2): + self._cmp_guard_gc_type(locs[0], locs[1]) + self.implement_guard(guard_token, 'NE') def implement_guard_recovery(self, guard_opnum, faildescr, failargs, fail_locs, frame_depth): 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 @@ -429,7 +429,12 @@ consider_guard_nonnull_class = consider_guard_class consider_guard_gc_type = consider_guard_class - consider_guard_nonnull_gc_type = consider_guard_class + + def consider_guard_is_object(self, op): + xxx + + def consider_guard_subclass(self, op): + xxx def _consider_binop_part(self, op, symm=False): x = op.getarg(0) diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -661,8 +661,9 @@ 'GUARD_NONNULL/1d/n', 'GUARD_ISNULL/1d/n', 'GUARD_NONNULL_CLASS/2d/n', - 'GUARD_GC_TYPE/2d/n', - 'GUARD_NONNULL_GC_TYPE/2d/n', + 'GUARD_GC_TYPE/2d/n', # only if supports_guard_gc_type + 'GUARD_IS_OBJECT/1d/n', # only if supports_guard_gc_type + 'GUARD_SUBCLASS/2d/n', # only if supports_guard_gc_type '_GUARD_FOLDABLE_LAST', 'GUARD_NO_EXCEPTION/0d/n', # may be called with an exception currently set 'GUARD_EXCEPTION/1d/r', # may be called with an exception currently set _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit