A.f = eval("lambda self: %s" % (42 + i + 1, ))
cache_counter = __pypy__.method_cache_counter("f")
- # the cache hits come from A.f = ..., which first does a lookup on A as
+ # a bit of explanation about what's going on. (1) is the line "a.f()"
+ # and (2) is "A.f = ...".
+ # at line (1) we do the lookup on type(a).f
+ # at line (2) we do a setattr on A. However, descr_setattr does also a
+ # lookup of type(A).f i.e. type.f, to check if by chance 'f' is a data
+ # At the first iteration:
+ # (1) is a miss because it's the first lookup of A.f. The result is cached
+ # (2) is a miss because it is the first lookup of type.f. The
+ # (non-existant) result is cached. The version of A changes, and 'f'
+ # is changed to be a cell object, so that subsequest assignments won't
+ # change the version of A
+ # At the second iteration:
+ # (1) is a miss because the version of A changed just before
+ # (2) is a hit, because type.f is cached. The version of A no longer changes
+ # At the third and subsequent iterations:
+ # (1) is a hit, because the version of A did not change
+ # (2) is a hit, see above
assert cache_counter == (17, 3)