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_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 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_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_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_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_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_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_is_likely_virtual(self): h = HeapCache() h.new(box1) assert h.is_unescaped(box1) assert h.is_likely_virtual(box1) h.reset(reset_virtuals=False) assert not h.is_unescaped(box1) assert h.is_likely_virtual(box1) h._escape(box1) assert not h.is_unescaped(box1) assert not h.is_likely_virtual(box1)
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_ops_dont_escape(self): h = HeapCache() h.new(box1) h.new(box2) assert h.is_unescaped(box1) assert h.is_unescaped(box2) h.invalidate_caches(rop.INSTANCE_PTR_EQ, None, [box1, box2]) assert h.is_unescaped(box1) assert h.is_unescaped(box2) h.invalidate_caches(rop.INSTANCE_PTR_NE, None, [box1, box2]) assert h.is_unescaped(box1) assert h.is_unescaped(box2)
def test_is_likely_virtual_2(self): h = HeapCache() box1 = RefFrontendOp(1) 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.reset() # reset everything assert not h.is_unescaped(box1) assert not h.is_likely_virtual(box1)
def test_is_likely_virtual_3(self): h = HeapCache() box1 = RefFrontendOp(1) 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.class_now_known(box1) # interaction of the two families of flags assert not h.is_unescaped(box1) assert h.is_likely_virtual(box1)
def test_call_doesnt_invalidate_unescaped_boxes(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) h.new(box1) assert h.is_unescaped(box1) h.setfield(box1, box2, descr1) h.invalidate_caches(rop.CALL_N, FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE), [] ) assert h.getfield(box1, descr1) is box2
def test_is_likely_virtual(self): h = HeapCache() box1 = RefFrontendOp(1) 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_known_nullity_more_cases(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) h.class_now_known(box1) assert h.is_nullity_known(box1) h.new(box2) assert h.is_nullity_known(box2) h.reset() assert not h.is_nullity_known(box1) assert not h.is_nullity_known(box2)
def test_bug_missing_ignored_operations(self): h = HeapCache() h.new(box1) h.new(box2) h.setfield(box1, box2, descr1) assert h.getfield(box1, descr1) is box2 h.invalidate_caches(rop.STRSETITEM, None, []) h.invalidate_caches(rop.UNICODESETITEM, None, []) h.invalidate_caches(rop.SETFIELD_RAW, None, []) h.invalidate_caches(rop.SETARRAYITEM_RAW, None, []) h.invalidate_caches(rop.SETINTERIORFIELD_RAW, None, []) h.invalidate_caches(rop.RAW_STORE, None, []) assert h.is_unescaped(box1) assert h.is_unescaped(box2) assert h.getfield(box1, descr1) is box2
def test_bug_heap_cache_is_cleared_but_not_is_unescaped_1(self): # bug if only the getfield() link is cleared (heap_cache) but not # the is_unescaped() flags: we can do later a GETFIELD(box1) which # will give us a fresh box3, which is actually equal to box2. This # box3 is escaped, but box2 is still unescaped. Bug shown e.g. by # calling some residual code that changes the values on box3: then # the content of box2 is still cached at the old value. h = HeapCache() 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 h.invalidate_caches(rop.CALL_MAY_FORCE, None, []) assert not h.is_unescaped(box1) assert not h.is_unescaped(box2) assert h.getfield(box1, descr1) is None
def test_unescaped_testing(self): h = HeapCache() h.new(box1) h.new(box2) assert h.is_unescaped(box1) assert h.is_unescaped(box2) # Putting a virtual inside of another virtual doesn't escape it. h.invalidate_caches(rop.SETFIELD_GC, None, [box1, box2]) assert h.is_unescaped(box2) # Reading a field from a virtual doesn't escape it. h.invalidate_caches(rop.GETFIELD_GC, None, [box1]) assert h.is_unescaped(box1) # Escaping a virtual transitively escapes anything inside of it. assert not h.is_unescaped(box3) h.invalidate_caches(rop.SETFIELD_GC, None, [box3, box1]) assert not h.is_unescaped(box1) assert not h.is_unescaped(box2)
def test_heapcache_write_fields_multiple_array(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) 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() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) 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() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) 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_bug_heap_cache_is_cleared_but_not_is_unescaped_2(self): h = HeapCache() 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 extraeffect = 5 EF_LOOPINVARIANT = 1 EF_ELIDABLE_CANNOT_RAISE = 2 EF_ELIDABLE_CAN_RAISE = 3 descr.get_extra_info = XTra h.invalidate_caches(rop.CALL, descr, []) assert h.is_unescaped(box1) assert h.is_unescaped(box2) assert h.getfield(box1, descr1) is box2
def test_unescaped_array(self): h = HeapCache() 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, FakeCallDescr(FakeEffectinfo.EF_RANDOM_EFFECTS), [box1] ) assert not h.is_unescaped(box1) assert not h.is_unescaped(box2)
def test_heapcache_write_fields_multiple(self): h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) h.setfield(box1, box2, descr1) assert h.getfield(box1, descr1) is box2 h.setfield(box3, box4, descr1) assert h.getfield(box3, descr1) is box4 assert h.getfield(box1, descr1) is None # box1 and box3 can alias h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) h.new(box1) h.setfield(box1, box2, descr1) assert h.getfield(box1, descr1) is box2 h.setfield(box3, box4, descr1) assert h.getfield(box3, descr1) is box4 assert h.getfield(box1, descr1) is None # box1 and box3 can alias h = HeapCache() box1 = RefFrontendOp(1) box2 = RefFrontendOp(2) box3 = RefFrontendOp(3) box4 = RefFrontendOp(4) h.new(box1) h.new(box3) h.setfield(box1, box2, descr1) assert h.getfield(box1, descr1) is box2 h.setfield(box3, box4, descr1) assert h.getfield(box3, descr1) is box4 assert h.getfield(box1, descr1) is box2 # box1 and box3 cannot alias h.setfield(box1, box3, descr1) assert h.getfield(box1, descr1) is box3