2021-11-28 | Paul Boddie | file changeset files shortlog | 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 |
paul@59 | 1 | class C: |
paul@59 | 2 | class D: |
paul@59 | 3 | class E: |
paul@59 | 4 | def m(self, x): |
paul@65 | 5 | self.x = x |
paul@522 | 6 | return self.x.__len__ |
paul@62 | 7 | n = 123 |
paul@66 | 8 | o = "123" |
paul@74 | 9 | |
paul@62 | 10 | p = "456" |
paul@71 | 11 | q = 789 |
paul@59 | 12 | |
paul@74 | 13 | class F(E): |
paul@74 | 14 | def r(self, y): |
paul@74 | 15 | s = self.o |
paul@74 | 16 | C.D.F.t = 234 |
paul@74 | 17 | return self.o.__len__ |
paul@74 | 18 | t = 123 |
paul@75 | 19 | def u(self): |
paul@75 | 20 | return self.o |
paul@75 | 21 | def v(self): |
paul@75 | 22 | return self.u().__len__ |
paul@74 | 23 | |
paul@114 | 24 | def static(): |
paul@59 | 25 | c = C |
paul@59 | 26 | d = C.D |
paul@59 | 27 | e = C.D.E |
paul@59 | 28 | f = C.D.E.m |
paul@62 | 29 | g = C.D.E.n |
paul@62 | 30 | h = C.D.p |
paul@114 | 31 | |
paul@266 | 32 | print c # __main__.C |
paul@266 | 33 | print d # __main__.C.D |
paul@266 | 34 | print e # __main__.C.D.E |
paul@266 | 35 | print f # __main__.C.D.E.m |
paul@266 | 36 | print g # 123 |
paul@522 | 37 | print h # 456 |
paul@266 | 38 | |
paul@114 | 39 | def static_via_constant(): |
paul@62 | 40 | i = C.D.p.__len__ |
paul@114 | 41 | |
paul@522 | 42 | print i # __builtins__.str.basestring.bytelength |
paul@266 | 43 | |
paul@114 | 44 | def assign(): |
paul@71 | 45 | C.D.q = 987 |
paul@114 | 46 | |
paul@114 | 47 | def indirect(): |
paul@114 | 48 | e = C.D.E |
paul@59 | 49 | inst = e() |
paul@59 | 50 | method = inst.m |
paul@65 | 51 | return method("5") |
paul@59 | 52 | |
paul@114 | 53 | def broken(): |
paul@114 | 54 | inst2 = C.D.F() |
paul@114 | 55 | l = inst2.u().__len__ |
paul@266 | 56 | return l |
paul@114 | 57 | |
paul@114 | 58 | static() |
paul@114 | 59 | static_via_constant() |
paul@114 | 60 | assign() |
paul@522 | 61 | print indirect() # __builtins__.str.basestring.bytelength |
paul@522 | 62 | print indirect()() # 1 |
paul@522 | 63 | print broken() # __builtins__.str.basestring.bytelength |
paul@266 | 64 | print broken()() # 3 |
paul@266 | 65 | |
paul@266 | 66 | print C.D.q # 987 |
paul@114 | 67 | |
paul@114 | 68 | # Static chains. |
paul@114 | 69 | |
paul@59 | 70 | c = C |
paul@59 | 71 | d = C.D |
paul@59 | 72 | e = C.D.E |
paul@59 | 73 | f = C.D.E.m |
paul@62 | 74 | g = C.D.E.n |
paul@62 | 75 | h = C.D.p |
paul@114 | 76 | |
paul@266 | 77 | print c # __main__.C |
paul@266 | 78 | print d # __main__.C.D |
paul@266 | 79 | print e # __main__.C.D.E |
paul@266 | 80 | print f # __main__.C.D.E.m |
paul@266 | 81 | print g # 123 |
paul@266 | 82 | print h # "456" |
paul@266 | 83 | |
paul@114 | 84 | # Static via constant. |
paul@114 | 85 | |
paul@62 | 86 | i = C.D.p.__len__ |
paul@114 | 87 | |
paul@522 | 88 | print i # __builtins__.str.basestring.bytelength |
paul@266 | 89 | print i() # 3 |
paul@266 | 90 | |
paul@114 | 91 | # Static assignment. |
paul@114 | 92 | |
paul@266 | 93 | C.D.q = 654 |
paul@266 | 94 | |
paul@266 | 95 | print C.D.q # 654 |
paul@114 | 96 | |
paul@114 | 97 | # Indirect accesses. |
paul@114 | 98 | |
paul@59 | 99 | inst = e() |
paul@59 | 100 | method = inst.m |
paul@522 | 101 | print method("5") # __builtins__.str.basestring.bytelength |
paul@522 | 102 | print method("5")() # 1 |
paul@114 | 103 | |
paul@114 | 104 | # Broken chains. |
paul@114 | 105 | |
paul@114 | 106 | inst2 = C.D.F() |
paul@114 | 107 | l = inst2.u().__len__ |
paul@522 | 108 | print l # __builtins__.str.basestring.bytelength |
paul@266 | 109 | print l() # 3 |