def test_heapcache_write_fields_multiple_array(self): h = HeapCache() h.setarrayitem(box1, index1, box2, descr1) assert h.getarrayitem(box1, index1, descr1) is box2 h.setarrayitem(box3, index1, box4, descr1) assert h.getarrayitem(box3, index1, descr1) is box4 assert h.getarrayitem(box1, index1, descr1) is None # box1 and box3 can alias h = HeapCache() h.new(box1) h.setarrayitem(box1, index1, box2, descr1) assert h.getarrayitem(box1, index1, descr1) is box2 h.setarrayitem(box3, index1, box4, descr1) assert h.getarrayitem(box3, index1, descr1) is box4 assert h.getarrayitem(box1, index1, descr1) is None # box1 and box3 can alias h = HeapCache() h.new(box1) h.new(box3) h.setarrayitem(box1, index1, box2, descr1) assert h.getarrayitem(box1, index1, descr1) is box2 h.setarrayitem(box3, index1, box4, descr1) assert h.getarrayitem(box3, index1, descr1) is box4 assert h.getarrayitem(box1, index1, descr1) is box2 # box1 and box3 cannot alias h.setarrayitem(box1, index1, box3, descr1) assert h.getarrayitem(box3, index1, descr1) is box4 assert h.getarrayitem(box1, index1, descr1) is box3 # box1 and box3 cannot alias
def test_unescaped_array(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) lengthbox1 = IntFrontendOp(11) lengthbox2 = IntFrontendOp(12) h.new_array(box1, lengthbox1) assert h.is_unescaped(box1) h.invalidate_caches(rop.SETARRAYITEM_GC, None, [box1, index1, box2]) assert h.is_unescaped(box1) h.invalidate_caches(rop.SETARRAYITEM_GC, None, [box2, index1, box1]) assert not h.is_unescaped(box1) h = HeapCache() h.new_array(box1, lengthbox1) h.new(box2) assert h.is_unescaped(box1) assert h.is_unescaped(box2) h.invalidate_caches(rop.SETARRAYITEM_GC, None, [box1, lengthbox2, box2]) assert h.is_unescaped(box1) assert h.is_unescaped(box2) h.invalidate_caches( rop.CALL_N, FakeCallDescr(FakeEffectinfo.EF_RANDOM_EFFECTS), [box1] ) assert not h.is_unescaped(box1) assert not h.is_unescaped(box2)
def test_ll_arraycopy(self): h = HeapCache() h.new_array(box1, lengthbox1) h.setarrayitem(box1, index1, box2, descr1) h.new_array(box2, lengthbox1) # Just need the destination box for this call h.invalidate_caches( rop.CALL, arraycopydescr1, [None, box5, box2, index1, index1, index1] ) assert h.getarrayitem(box1, index1, descr1) is box2 h.invalidate_caches( rop.CALL, arraycopydescr1, [None, box5, box3, index1, index1, index1] ) assert h.getarrayitem(box1, index1, descr1) is box2 h.setarrayitem(box4, index1, box2, descr1) assert h.getarrayitem(box4, index1, descr1) is box2 h.invalidate_caches( rop.CALL, arraycopydescr1, [None, box3, box5, index1, index1, index2] ) assert h.getarrayitem(box4, index1, descr1) is None
def test_quasiimmut_seen_consts(self): h = HeapCache() box1 = ConstPtr(rffi.cast(llmemory.GCREF, 1)) box2 = ConstPtr(rffi.cast(llmemory.GCREF, 1)) box3 = ConstPtr(rffi.cast(llmemory.GCREF, 1)) box4 = ConstPtr(rffi.cast(llmemory.GCREF, 1)) assert not h.is_quasi_immut_known(descr1, box1) assert not h.is_quasi_immut_known(descr1, box2) assert not h.is_quasi_immut_known(descr2, box3) assert not h.is_quasi_immut_known(descr2, box4) h.quasi_immut_now_known(descr1, box1) assert h.is_quasi_immut_known(descr1, box1) assert h.is_quasi_immut_known(descr1, box2) assert not h.is_quasi_immut_known(descr2, box3) assert not h.is_quasi_immut_known(descr2, box4) h.quasi_immut_now_known(descr2, box3) assert h.is_quasi_immut_known(descr1, box1) assert h.is_quasi_immut_known(descr1, box2) assert h.is_quasi_immut_known(descr2, box3) assert h.is_quasi_immut_known(descr2, box4) # invalidate the descr1 cache vbox1 = RefFrontendOp(1) vbox2 = RefFrontendOp(2) h.setfield(vbox1, vbox2, descr1) assert not h.is_quasi_immut_known(descr1, box1) assert not h.is_quasi_immut_known(descr1, box2) # a call invalidates everything h.invalidate_caches( rop.CALL_N, FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE), []) assert not h.is_quasi_immut_known(descr2, box3) assert not h.is_quasi_immut_known(descr2, box4)
def test_ll_arraycopy(self): h = HeapCache() h.new_array(box1, lengthbox1) h.setarrayitem(box1, index1, box2, descr1) h.new_array(box2, lengthbox1) # Just need the destination box for this call h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), [None, box5, box2, index1, index1, index1] ) assert h.getarrayitem(box1, index1, descr1) is box2 h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), [None, box5, box3, index1, index1, index1] ) assert h.getarrayitem(box1, index1, descr1) is box2 h.setarrayitem(box4, index1, box2, descr1) assert h.getarrayitem(box4, index1, descr1) is box2 h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), [None, box3, box5, index1, index1, index2] ) assert h.getarrayitem(box4, index1, descr1) is None
def test_circular_virtuals(self): h = HeapCache() h.new(box1) h.new(box2) h.invalidate_caches(rop.SETFIELD_GC, None, [box1, box2]) h.invalidate_caches(rop.SETFIELD_GC, None, [box2, box1]) h.invalidate_caches(rop.SETFIELD_GC, None, [box3, box1]) # does not crash
def test_nonstandard_virtualizable_const(self): h = HeapCache() # rare but not impossible situation for some interpreters: we have a # *constant* nonstandard virtualizable c_box = ConstPtr(ConstPtr.value) h.nonstandard_virtualizables_now_known(c_box) # should not crash assert not h.is_known_nonstandard_virtualizable(c_box)
def test_ll_arraycopy(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) box5 = RefFrontendOp(5) lengthbox1 = IntFrontendOp(11) lengthbox2 = IntFrontendOp(12) h.new_array(box1, lengthbox1) h.setarrayitem(box1, index1, box2, descr1) h.new_array(box2, lengthbox1) # Just need the destination box for this call h.invalidate_caches( rop.CALL_N, arraycopydescr1, [None, box5, box2, index1, index1, index1] ) assert h.getarrayitem(box1, index1, descr1) is box2 h.invalidate_caches( rop.CALL_N, arraycopydescr1, [None, box5, box3, index1, index1, index1] ) assert h.getarrayitem(box1, index1, descr1) is box2 h.setarrayitem(box4, index1, box2, descr1) assert h.getarrayitem(box4, index1, descr1) is box2 h.invalidate_caches( rop.CALL_N, arraycopydescr1, [None, box3, box5, index1, index1, index2] ) assert h.getarrayitem(box4, index1, descr1) is None
def test_invalidate_cache(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box4 = RefFrontendOp(4) h.setfield(box1, box2, descr1) h.setarrayitem(box1, index1, box2, descr1) h.setarrayitem(box1, index2, box4, descr1) h.invalidate_caches(rop.INT_ADD, None, []) h.invalidate_caches(rop.INT_ADD_OVF, None, []) h.invalidate_caches(rop.SETFIELD_RAW, None, []) h.invalidate_caches(rop.SETARRAYITEM_RAW, None, []) assert h.getfield(box1, descr1) is box2 assert h.getarrayitem(box1, index1, descr1) is box2 assert h.getarrayitem(box1, index2, descr1) is box4 h.invalidate_caches( rop.CALL_N, FakeCallDescr(FakeEffectinfo.EF_ELIDABLE_CANNOT_RAISE), []) assert h.getfield(box1, descr1) is box2 assert h.getarrayitem(box1, index1, descr1) is box2 assert h.getarrayitem(box1, index2, descr1) is box4 h.invalidate_caches(rop.GUARD_TRUE, None, []) assert h.getfield(box1, descr1) is box2 assert h.getarrayitem(box1, index1, descr1) is box2 assert h.getarrayitem(box1, index2, descr1) is box4 h.invalidate_caches( rop.CALL_LOOPINVARIANT_N, FakeCallDescr(FakeEffectinfo.EF_LOOPINVARIANT), []) h.invalidate_caches( rop.CALL_N, FakeCallDescr(FakeEffectinfo.EF_RANDOM_EFFECTS), []) assert h.getfield(box1, descr1) is None assert h.getarrayitem(box1, index1, descr1) is None assert h.getarrayitem(box1, index2, descr1) is None
def test_heapcache_fields(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) assert h.getfield(box1, descr1) is None assert h.getfield(box1, descr2) is None h.setfield(box1, box2, descr1) assert h.getfield(box1, descr1) is box2 assert h.getfield(box1, descr2) is None h.setfield(box1, box3, descr2) assert h.getfield(box1, descr1) is box2 assert h.getfield(box1, descr2) is box3 h.setfield(box1, box3, descr1) assert h.getfield(box1, descr1) is box3 assert h.getfield(box1, descr2) is box3 h.setfield(box3, box1, descr1) assert h.getfield(box3, descr1) is box1 assert h.getfield(box1, descr1) is None assert h.getfield(box1, descr2) is box3 h.reset() assert h.getfield(box1, descr1) is None assert h.getfield(box1, descr2) is None assert h.getfield(box3, descr1) is None
def test_bug_heap_cache_is_cleared_but_not_is_unescaped_2(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) h.new(box1) h.new(box2) h.setfield(box1, box2, descr1) h.invalidate_caches(rop.SETFIELD_GC, None, [box1, box2]) assert h.getfield(box1, descr1) is box2 descr = BasicFailDescr() class XTra: oopspecindex = 0 OS_ARRAYCOPY = 42 OS_ARRAYMOVE = 49 extraeffect = 5 EF_LOOPINVARIANT = 1 EF_ELIDABLE_CANNOT_RAISE = 2 EF_ELIDABLE_OR_MEMORYERROR = 3 EF_ELIDABLE_CAN_RAISE = 4 descr.get_extra_info = XTra h.invalidate_caches(rop.CALL_N, descr, []) assert h.is_unescaped(box1) assert h.is_unescaped(box2) assert h.getfield(box1, descr1) is box2
def test_ll_arraycopy_differing_descrs_nonconst_index(self): h = HeapCache() h.setarrayitem(box1, index1, box2, descr2) assert h.getarrayitem(box1, index1, descr2) is box2 h.invalidate_caches(rop.CALL, arraycopydescr1, [None, box3, box2, index1, index1, BoxInt()]) assert h.getarrayitem(box1, index1, descr2) is box2
def test_ll_arraycopy_differing_descrs(self): h = HeapCache() h.setarrayitem(box1, index1, box2, descr2) assert h.getarrayitem(box1, index1, descr2) is box2 h.new_array(box2, lengthbox2) h.invalidate_caches(rop.CALL, arraycopydescr1, [None, box3, box2, index1, index1, index2]) assert h.getarrayitem(box1, index1, descr2) is box2
def test_length_cache(self): h = HeapCache() h.new_array(box1, lengthbox1) assert h.arraylen(box1) is lengthbox1 assert h.arraylen(box2) is None h.arraylen_now_known(box2, lengthbox2) assert h.arraylen(box2) is lengthbox2
def test_call_doesnt_invalidate_unescaped_boxes(self): h = HeapCache() h.new(box1) assert h.is_unescaped(box1) h.setfield(box1, box2, descr1) h.invalidate_caches(rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE), []) assert h.getfield(box1, descr1) is box2
def test_call_doesnt_invalidate_unescaped_array_boxes(self): h = HeapCache() h.new_array(box1, lengthbox1) assert h.is_unescaped(box1) h.setarrayitem(box1, index1, box3, descr1) h.invalidate_caches(rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE), []) assert h.getarrayitem(box1, index1, descr1) is box3
def test_heapcache_array_nonconst_index(self): h = HeapCache() h.setarrayitem(box1, index1, box2, descr1) h.setarrayitem(box1, index2, box4, descr1) assert h.getarrayitem(box1, index1, descr1) is box2 assert h.getarrayitem(box1, index2, descr1) is box4 h.setarrayitem(box1, box2, box3, descr1) assert h.getarrayitem(box1, index1, descr1) is None assert h.getarrayitem(box1, index2, descr1) is None
def test_ll_arraycopy_result_propogated(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) h.setarrayitem(box1, index1, box2, descr1) h.invalidate_caches(rop.CALL_N, arraycopydescr1, [None, box1, box3, index1, index1, index2]) assert h.getarrayitem(box3, index1, descr1) is box2
def test_ll_arraycopy_result_propogated(self): h = HeapCache() h.setarrayitem(box1, index1, box2, descr1) h.invalidate_caches( rop.CALL, arraycopydescr1, [None, box1, box3, index1, index1, index2] ) assert h.getarrayitem(box3, index1, descr1) is box2
def test_unescaped(self): h = HeapCache() assert not h.is_unescaped(box1) h.new(box2) assert h.is_unescaped(box2) h.invalidate_caches(rop.SETFIELD_GC, None, [box2, box1]) assert h.is_unescaped(box2) h.invalidate_caches(rop.SETFIELD_GC, None, [box1, box2]) assert not h.is_unescaped(box2)
def test_ll_arraycopy_dest_new(self): h = HeapCache() h.new_array(box1, lengthbox1) h.setarrayitem(box3, index1, box4, descr1) h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), [None, box2, box1, index1, index1, index2] )
def test_ll_arraycopy_result_propogated(self): h = HeapCache() h.setarrayitem(box1, index1, box2, descr1) h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), [None, box1, box3, index1, index1, index2] ) assert h.getarrayitem(box3, index1, descr1) is box2
def test_nonstandard_virtualizable_allocation(self): h = HeapCache() box1 = RefFrontendOp(1) h.new(box1) # we've seen the allocation, so it's not the virtualizable assert h.is_known_nonstandard_virtualizable(box1) h.reset() assert not h.is_known_nonstandard_virtualizable(box1)
def test_ll_arraycopy_dest_new(self): h = HeapCache() h.new_array(box1, lengthbox1) h.setarrayitem(box3, index1, box4, descr1) h.invalidate_caches( rop.CALL, arraycopydescr1, [None, box2, box1, index1, index1, index2] )
def test_circular_virtuals(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) h.new(box1) h.new(box2) h.invalidate_caches(rop.SETFIELD_GC, None, [box1, box2]) h.invalidate_caches(rop.SETFIELD_GC, None, [box2, box1]) h.invalidate_caches(rop.SETFIELD_GC, None, [box3, box1]) # does not crash
def test_ll_arraycopy_differing_descrs_nonconst_index(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) h.setarrayitem(box1, index1, box2, descr2) assert h.getarrayitem(box1, index1, descr2) is box2 h.invalidate_caches(rop.CALL_N, arraycopydescr1, [None, box3, box2, index1, index1, InputArgInt()]) assert h.getarrayitem(box1, index1, descr2) is box2
def test_known_class_box(self): h = HeapCache() assert not h.is_class_known(1) assert not h.is_class_known(2) h.class_now_known(1) assert h.is_class_known(1) assert not h.is_class_known(2) h.reset() assert not h.is_class_known(1) assert not h.is_class_known(2)
def test_ll_arraycopy_dest_new(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) lengthbox1 = IntFrontendOp(11) h.new_array(box1, lengthbox1) h.setarrayitem(box3, index1, box4, descr1) h.invalidate_caches(rop.CALL_N, arraycopydescr1, [None, box2, box1, index1, index1, index2])
def test_is_likely_virtual(self): h = HeapCache() h.new(box1) assert h.is_unescaped(box1) assert h.is_likely_virtual(box1) h.reset_keep_likely_virtuals() assert not h.is_unescaped(box1) assert h.is_likely_virtual(box1) h._escape_box(box1) assert not h.is_unescaped(box1) assert not h.is_likely_virtual(box1)
def test_nonstandard_virtualizable(self): h = HeapCache() assert not h.is_nonstandard_virtualizable(1) assert not h.is_nonstandard_virtualizable(2) h.nonstandard_virtualizables_now_known(1) assert h.is_nonstandard_virtualizable(1) assert not h.is_nonstandard_virtualizable(2) h.reset() assert not h.is_nonstandard_virtualizable(1) assert not h.is_nonstandard_virtualizable(2)