1 /** 2 * This module contains a specialized bitset implementation. 3 * 4 * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com. 5 * All rights reserved. 6 * License: 7 * This software is provided 'as-is', without any express or implied 8 * warranty. In no event will the authors be held liable for any damages 9 * arising from the use of this software. 10 * 11 * Permission is granted to anyone to use this software for any purpose, 12 * including commercial applications, and to alter it and redistribute it 13 * freely, in both source and binary form, subject to the following 14 * restrictions: 15 * 16 * o The origin of this software must not be misrepresented; you must not 17 * claim that you wrote the original software. If you use this software 18 * in a product, an acknowledgment in the product documentation would be 19 * appreciated but is not required. 20 * o Altered source versions must be plainly marked as such, and must not 21 * be misrepresented as being the original software. 22 * o This notice may not be removed or altered from any source 23 * distribution. 24 * Authors: Walter Bright, David Friedman, Sean Kelly 25 */ 26 module rt.gc.basic.gcbits; 27 28 private import tango.core.BitManip; 29 private import tango.stdc.string : memset, memcpy; 30 private import tango.stdc.stdlib : free, calloc; 31 private extern (C) void onOutOfMemoryError(); 32 33 34 version (DigitalMars) 35 { 36 version = bitops; 37 } 38 else version (GNU) 39 { 40 // use the unoptimized version 41 } 42 else version(LDC) 43 { 44 // ditto 45 } 46 else version (D_InlineAsm_X86) 47 { 48 version = Asm86; 49 } 50 51 struct GCBits 52 { 53 alias size_t wordtype; 54 55 const BITS_PER_WORD = (wordtype.sizeof * 8); 56 const BITS_SHIFT = (wordtype.sizeof == 8 ? 6 : 5); 57 const BITS_MASK = (BITS_PER_WORD - 1); 58 const BITS_1 = cast(wordtype)1; 59 60 wordtype* data = null; 61 size_t nwords = 0; // allocated words in data[] excluding sentinals 62 size_t nbits = 0; // number of bits in data[] excluding sentinals 63 64 void Dtor() 65 { 66 if (data) 67 { 68 free(data); 69 data = null; 70 } 71 } 72 73 invariant 74 { 75 if (data) 76 { 77 assert(nwords * data[0].sizeof * 8 >= nbits); 78 } 79 } 80 81 void alloc(size_t nbits) 82 { 83 this.nbits = nbits; 84 nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT; 85 data = cast(wordtype*)calloc(nwords + 2, wordtype.sizeof); 86 if (!data) 87 onOutOfMemoryError(); 88 } 89 90 wordtype test(size_t i) 91 in 92 { 93 assert(i < nbits); 94 } 95 body 96 { 97 //return (cast(bit *)(data + 1))[i]; 98 return data[1 + (i >> BITS_SHIFT)] & (BITS_1 << (i & BITS_MASK)); 99 } 100 101 void set(size_t i) 102 in 103 { 104 assert(i < nbits); 105 } 106 body 107 { 108 //(cast(bit *)(data + 1))[i] = 1; 109 data[1 + (i >> BITS_SHIFT)] |= (BITS_1 << (i & BITS_MASK)); 110 } 111 112 void clear(size_t i) 113 in 114 { 115 assert(i < nbits); 116 } 117 body 118 { 119 //(cast(bit *)(data + 1))[i] = 0; 120 data[1 + (i >> BITS_SHIFT)] &= ~(BITS_1 << (i & BITS_MASK)); 121 } 122 123 wordtype testClear(size_t i) 124 { 125 version (bitops) 126 { 127 return std.intrinsic.btr(data + 1, i); 128 } 129 else version (Asm86) 130 { 131 asm 132 { 133 naked ; 134 mov EAX,data[EAX] ; 135 mov ECX,i-4[ESP] ; 136 btr 4[EAX],ECX ; 137 sbb EAX,EAX ; 138 ret 4 ; 139 } 140 } 141 else 142 { wordtype result; 143 144 //result = (cast(bit *)(data + 1))[i]; 145 //(cast(bit *)(data + 1))[i] = 0; 146 147 wordtype* p = &data[1 + (i >> BITS_SHIFT)]; 148 wordtype mask = (BITS_1 << (i & BITS_MASK)); 149 result = *p & mask; 150 *p &= ~mask; 151 return result; 152 } 153 } 154 155 wordtype testSet(size_t i) 156 { 157 version (bitops) 158 { 159 return std.intrinsic.bts(data + 1, i); 160 } 161 else version (Asm86) 162 { 163 asm 164 { 165 naked ; 166 mov EAX,data[EAX] ; 167 mov ECX,i-4[ESP] ; 168 bts 4[EAX],ECX ; 169 sbb EAX,EAX ; 170 ret 4 ; 171 } 172 } 173 else 174 { 175 //result = (cast(bit *)(data + 1))[i]; 176 //(cast(bit *)(data + 1))[i] = 0; 177 178 auto p = &data[1 + (i >> BITS_SHIFT)]; 179 auto mask = (BITS_1 << (i & BITS_MASK)); 180 auto result = *p & mask; 181 *p |= mask; 182 return result; 183 } 184 } 185 186 void zero() 187 { 188 version(MEMCPY_NON_SIG_SAFE) { 189 uint * d1=data+1,dEnd=d1+nwords; 190 for (;d1!=dEnd;++d1) 191 *d1=0u; 192 } else { 193 memset(data + 1, 0, nwords * wordtype.sizeof); 194 } 195 } 196 197 void copy(GCBits *f) 198 in 199 { 200 assert(nwords == f.nwords); 201 } 202 body 203 { 204 version(MEMCPY_NON_SIG_SAFE) { 205 wordtype * d1=data+1,d2=f.data+1,dEnd=d1+nwords; 206 for (;d1!=dEnd;++d1,++d2) 207 *d1=*d2; 208 } else { 209 memcpy(data + 1, f.data + 1, nwords * wordtype.sizeof); 210 } 211 } 212 213 wordtype* base() 214 in 215 { 216 assert(data); 217 } 218 body 219 { 220 return data + 1; 221 } 222 } 223 224 unittest 225 { 226 GCBits b; 227 228 b.alloc(786); 229 assert(b.test(123) == 0); 230 assert(b.testClear(123) == 0); 231 b.set(123); 232 assert(b.test(123) != 0); 233 assert(b.testClear(123) != 0); 234 assert(b.test(123) == 0); 235 236 b.set(785); 237 b.set(0); 238 assert(b.test(785) != 0); 239 assert(b.test(0) != 0); 240 b.zero(); 241 assert(b.test(785) == 0); 242 assert(b.test(0) == 0); 243 244 GCBits b2; 245 b2.alloc(786); 246 b2.set(38); 247 b.copy(&b2); 248 assert(b.test(38) != 0); 249 b2.Dtor(); 250 251 b.Dtor(); 252 }