1 
2 module traits_getPointerBitmap;
3 
4 import std.stdio;
5 static import std.traits;
6 
7 // version = RTInfo;
8 // debug = LOG;
9 
10 version(RTInfo)
11     import gc.rtinfo;
12 else
13     enum bool RTInfoMark__Monitor = false; // is __monitor GC allocated?
14     
15 
16 enum bytesPerPtr = (size_t.sizeof);
17 enum bytesPerBitmapWord = bytesPerPtr * bytesPerPtr * 8;
18 
19 template allocatedSize(T)
20 {
21     static if (is (T == class))
22         enum allocatedSize = __traits(classInstanceSize, T);
23     else
24         enum allocatedSize = T.sizeof;
25 }
26 
27 bool testBit(const(size_t)* p, size_t biti)
28 {
29     enum BITS_SHIFT = (size_t.sizeof == 8 ? 6 : 5);
30     enum BITS_MASK = (bytesPerPtr - 1);
31 
32     return (p[biti >> BITS_SHIFT] & (1 << (biti & BITS_MASK))) != 0;
33 }
34 
35 void __testType(T)(size_t[] expected)
36 {
37     // check compile time info
38     enum bits  = (T.sizeof + bytesPerPtr - 1) / bytesPerPtr;
39     enum words = (T.sizeof + bytesPerBitmapWord - 1) / bytesPerBitmapWord;
40     version(RTInfo)
41         enum info = RTInfoImpl2!(Unqual!T); // we want the array, not the pointer
42     else
43         enum info = __traits(getPointerBitmap,T); // we want the array, not the pointer
44     
45     debug(LOG) writef("%-20s:", T.stringof);
46     debug(LOG) writef(" CT:%s", info);
47     debug(LOG) writef(" EXP:%d %s", allocatedSize!T, expected);
48     assert(info[0] == allocatedSize!T);
49     assert(info[1..$] == expected);
50     assert(words == expected.length);
51 
52     debug(LOG) writeln();
53 }
54 
55 ///////////////////////////////////////
56 struct S(T, aliasTo = void)
57 {
58     static if(!is(aliasTo == void))
59     {
60         aliasTo a;
61         alias a this;
62     }
63 
64     size_t x;
65     T t = void;
66     void* p;
67 
68 }
69 
70 template tOff(T)
71 {
72     enum tOff = T.t.offsetof / bytesPerPtr;
73 }
74 
75 template pOff(T)
76 {
77     enum pOff = T.p.offsetof / bytesPerPtr;
78 }
79 
80 class C(T, aliasTo = void)
81 {
82     static if(!is(aliasTo == void))
83     {
84         aliasTo a;
85         alias a this;
86     }
87 
88     size_t x;
89     T t = void;
90     void* p;
91 }
92 
93 ///////////////////////////////////////
94 
95 void _testType(T)(size_t[] expected)
96 {
97     __testType!(T)(expected);
98     __testType!(const(T))(expected);
99     __testType!(immutable(T))(expected);
100     version(RTInfo) {} else // Unqual does not work with shared(T[N])
101         __testType!(shared(T))(expected);
102 }
103 
104 void testType(T)(size_t[] expected)
105 {
106     _testType!(T)(expected);
107 
108     // generate bit pattern for S!T
109     assert(expected.length == 1);
110     size_t[] sexp;
111 
112     sexp ~= (expected[0] << tOff!(S!T)) | (1 << pOff!((S!T)));
113     _testType!(S!T)(sexp);
114 
115     // prepend Object
116     sexp[0] = (expected[0] << tOff!(S!(T, Object))) | (1 << pOff!(S!(T, Object))) | 1;
117     _testType!(S!(T, Object))(sexp);
118 
119     // prepend string
120     sexp[0] = (expected[0] << tOff!(S!(T, string))) | (1 << pOff!(S!(T, string))) | 2; // arr ptr
121     _testType!(S!(T, string))(sexp);
122 
123     // generate bit pattern for C!T
124     C!T ct = null;
125     size_t mutexBit = (RTInfoMark__Monitor ? 2 : 0);
126     size_t ctpOff = ct.p.offsetof / bytesPerPtr;
127     size_t cttOff = ct.t.offsetof / bytesPerPtr;
128     sexp[0] = (expected[0] << cttOff) | (1 << ctpOff) | mutexBit;
129     _testType!(C!(T))(sexp);
130 
131     C!(T, string) cts = null;
132     size_t ctspOff = cts.p.offsetof / bytesPerPtr;
133     size_t ctstOff = cts.t.offsetof / bytesPerPtr;
134     // generate bit pattern for C!T
135     sexp[0] = (expected[0] << ctstOff) | (1 << ctspOff) | mutexBit | 0b1000; // arr ptr
136     _testType!(C!(T, string))(sexp);
137 }
138 
139 ///////////////////////////////////////
140 alias void[2*size_t.sizeof] void2;
141 alias size_t[3] int3;
142 alias size_t*[3] pint3;
143 alias string[3] sint3;
144 alias string[3][2] sint3_2;
145 alias int delegate() dg;
146 alias int function() fn;
147 alias typeof(null) NullType;
148 
149 // span multiple bitmap elements
150 struct Large
151 {
152     size_t[30] data1;
153     void* p1;
154     size_t[1] val1;
155 
156     size_t[28] data2;
157     void* p2;
158     size_t[3] val2;
159 
160     size_t[16] data3;
161     void* p3;
162     size_t[15] val3;
163 }
164 
165 class N
166 {
167     struct Nested
168     {
169         // no outer for structs
170         size_t x;
171         void* p1;
172         Large* s;
173 
174         void foo() {} // need member fnction to not be POD
175     }
176     class CNested
177     {
178         // implicit vtptr,monitor
179         size_t x;
180         void* p1;
181         size_t y;
182         // implicit outer
183     }
184     class CNestedDerived : CNested
185     {
186         size_t[3] z;
187         void* p;
188     }
189 }
190 
191 union U
192 {
193     size_t data[4];
194     Large*[] arr; // { length, ptr }
195 
196     struct
197     {
198         size_t d1;
199         size_t d2;
200         size_t d3;
201         void* p;
202     }
203 }
204 
205 void testRTInfo()
206 {
207     testType!(bool)         ([ 0b0 ]);
208     testType!(ubyte)        ([ 0b0 ]);
209     testType!(short)        ([ 0b0 ]);
210     testType!(int)          ([ 0b0 ]);
211     testType!(long)         ([ 0b00 ]);
212     testType!(double)       ([ 0b00 ]);
213     testType!(ifloat)       ([ 0b0 ]);
214     testType!(cdouble)      ([ 0b0000 ]);
215     testType!(dg)           ([ 0b01 ]);
216     testType!(fn)           ([ 0b0 ]);
217     testType!(S!fn)         ([ 0b100 ]);
218     testType!(NullType)     ([ 0b0 ]);
219     version(D_LP64)
220         testType!(__vector(float[4]))  ([ 0b00 ]);
221 
222     testType!(Object[int])       ([ 0b1 ]);
223     testType!(Object[])       ([ 0b10 ]);
224     testType!(string)         ([ 0b10 ]);
225 
226     testType!(int3)           ([ 0b000 ]);
227     testType!(pint3)          ([ 0b111 ]);
228     testType!(sint3)          ([ 0b101010 ]);
229     testType!(sint3_2)        ([ 0b101010101010 ]);
230     testType!(void2)          ([ 0b11 ]);
231     testType!(U)              ([ 0b1010 ]);
232 
233     version(D_LP64)
234         _testType!(Large)          ([ 0x1000_0000__4000_0000, 0x0001_0000 ]);
235     else
236         _testType!(Large)          ([ 0x4000_0000, 0x1000_0000, 0x0001_0000 ]);
237 
238     _testType!(N.CNested)     ([ 0b101000 ]);
239     _testType!(N.CNestedDerived) ([ 0b1000101000 ]);
240 
241     testType!(N.Nested)       ([ 0b110 ]);
242 
243     struct SFNested
244     {
245         size_t[2] d;
246         void* p1;
247         fn f;
248         // implicite outer
249 
250         void foo() {} // need member fnction to not be POD
251     }
252 
253     class CFNested
254     {
255         // implicit vtptr,monitor
256         size_t[2] d;
257         void* p1;
258         // implicite outer
259     }
260 
261     testType!(SFNested)      ([ 0b10100 ]);
262     _testType!(CFNested)     ([ 0b110000 ]);
263 }
264 
265 void main() 
266 {
267     testRTInfo();
268 }