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 }