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