2021-11-28 | Paul Boddie | raw annotate files changeset graph | Introduced support for values that can be allocated on a special thread-local stack, copied around and overwritten/mutated, demonstrating the concept using integer and floating-point numbers. Various complications arise with special attributes (such as __data__) due to the way references are tagged to indicate mutable values, and attribute slots must be cleared in locals, objects and fragments before values are stored since target slots are tested for mutable values. | tagged-address-values |
1 class C: 2 class D: 3 class E: 4 def m(self, x): 5 self.x = x 6 return self.x.__len__ 7 n = 123 8 o = "123" 9 10 p = "456" 11 q = 789 12 13 class F(E): 14 def r(self, y): 15 s = self.o 16 C.D.F.t = 234 17 return self.o.__len__ 18 t = 123 19 def u(self): 20 return self.o 21 def v(self): 22 return self.u().__len__ 23 24 def static(): 25 c = C 26 d = C.D 27 e = C.D.E 28 f = C.D.E.m 29 g = C.D.E.n 30 h = C.D.p 31 32 print c # __main__.C 33 print d # __main__.C.D 34 print e # __main__.C.D.E 35 print f # __main__.C.D.E.m 36 print g # 123 37 print h # 456 38 39 def static_via_constant(): 40 i = C.D.p.__len__ 41 42 print i # __builtins__.str.basestring.bytelength 43 44 def assign(): 45 C.D.q = 987 46 47 def indirect(): 48 e = C.D.E 49 inst = e() 50 method = inst.m 51 return method("5") 52 53 def broken(): 54 inst2 = C.D.F() 55 l = inst2.u().__len__ 56 return l 57 58 static() 59 static_via_constant() 60 assign() 61 print indirect() # __builtins__.str.basestring.bytelength 62 print indirect()() # 1 63 print broken() # __builtins__.str.basestring.bytelength 64 print broken()() # 3 65 66 print C.D.q # 987 67 68 # Static chains. 69 70 c = C 71 d = C.D 72 e = C.D.E 73 f = C.D.E.m 74 g = C.D.E.n 75 h = C.D.p 76 77 print c # __main__.C 78 print d # __main__.C.D 79 print e # __main__.C.D.E 80 print f # __main__.C.D.E.m 81 print g # 123 82 print h # "456" 83 84 # Static via constant. 85 86 i = C.D.p.__len__ 87 88 print i # __builtins__.str.basestring.bytelength 89 print i() # 3 90 91 # Static assignment. 92 93 C.D.q = 654 94 95 print C.D.q # 654 96 97 # Indirect accesses. 98 99 inst = e() 100 method = inst.m 101 print method("5") # __builtins__.str.basestring.bytelength 102 print method("5")() # 1 103 104 # Broken chains. 105 106 inst2 = C.D.F() 107 l = inst2.u().__len__ 108 print l # __builtins__.str.basestring.bytelength 109 print l() # 3