1 /** 2 * The memory module provides an interface to the garbage collector and to 3 * any other OS or API-level memory management facilities. 4 * 5 * Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved. 6 * License: BSD style: $(LICENSE) 7 * Authors: Sean Kelly 8 */ 9 module tango.core.Memory; 10 11 public import core.memory; 12 13 /+private 14 { 15 extern (C) void gc_init(); 16 extern (C) void gc_term(); 17 18 extern (C) void gc_enable(); 19 extern (C) void gc_disable(); 20 extern (C) void gc_collect(); 21 extern (C) void gc_minimize(); 22 23 extern (C) uint gc_getAttr( void* p ); 24 extern (C) uint gc_setAttr( void* p, uint a ); 25 extern (C) uint gc_clrAttr( void* p, uint a ); 26 27 extern (C) void* gc_malloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init); 28 extern (C) void* gc_calloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init); 29 extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init); 30 extern (C) size_t gc_extend( void* p, size_t mx, size_t sz ); 31 extern (C) size_t gc_reserve( size_t sz ); 32 extern (C) void gc_free( void* p ); 33 34 extern (C) void* gc_addrOf( void* p ); 35 extern (C) size_t gc_sizeOf( void* p ); 36 37 struct BlkInfo_ 38 { 39 void* base; 40 size_t size; 41 uint attr; 42 } 43 44 extern (C) BlkInfo_ gc_query( void* p ); 45 46 extern (C) void gc_addRoot( void* p ); 47 extern (C) void gc_addRange( void* p, size_t sz ); 48 49 extern (C) void gc_removeRoot( void* p ); 50 extern (C) void gc_removeRange( void* p ); 51 52 extern(C) Object gc_weakpointerGet(void* wp); 53 extern(C) void* gc_weakpointerCreate(Object r); 54 extern(C) void gc_weakpointerDestroy(void* wp); 55 56 alias extern(D) void delegate() ddel; 57 alias extern(D) void delegate(int, int) dint; 58 59 extern (C) void gc_monitor(ddel begin, dint end ); 60 } 61 62 63 /** 64 * This struct encapsulates all garbage collection functionality for the D 65 * programming language. 66 * 67 * Documentation of runtime configuration: 68 * 69 * The environment variable D_PRECISE_HEAP can be used to control the behavior 70 * of the GC at runtime. 71 * D_PRECISE_HEAP=1 enable precise scanning 72 * D_PRECISE_HEAP=0 disable precise scanning (may save space because no bitmasks need to be stored) 73 */ 74 struct GC 75 { 76 /** 77 * Enables the garbage collector if collections have previously been 78 * suspended by a call to disable. This function is reentrant, and 79 * must be called once for every call to disable before the garbage 80 * collector is enabled. 81 */ 82 static void enable() 83 { 84 gc_enable(); 85 } 86 87 88 /** 89 * Disables the garbage collector. This function is reentrant, but 90 * enable must be called once for each call to disable. 91 */ 92 static void disable() 93 { 94 gc_disable(); 95 } 96 97 98 /** 99 * Begins a full collection. While the meaning of this may change based 100 * on the garbage collector implementation, typical behavior is to scan 101 * all stack segments for roots, mark accessible memory blocks as alive, 102 * and then to reclaim free space. This action may need to suspend all 103 * running threads for at least part of the collection process. 104 */ 105 static void collect() 106 { 107 gc_collect(); 108 } 109 110 /** 111 * Indicates that the managed memory space be minimized by returning free 112 * physical memory to the operating system. The amount of free memory 113 * returned depends on the allocator design and on program behavior. 114 */ 115 static void minimize() 116 { 117 gc_minimize(); 118 } 119 120 121 /** 122 * Elements for a bit field representing memory block attributes. These 123 * are manipulated via the getAttr, setAttr, clrAttr functions. 124 */ 125 enum BlkAttr : uint 126 { 127 FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect. 128 NO_SCAN = 0b0000_0010, /// Do not scan through this block on collect. 129 NO_MOVE = 0b0000_0100 /// Do not move this memory block on collect. 130 } 131 132 133 /** 134 * Contains aggregate information about a block of managed memory. The 135 * purpose of this struct is to support a more efficient query style in 136 * instances where detailed information is needed. 137 * 138 * base = A pointer to the base of the block in question. 139 * size = The size of the block, calculated from base. 140 * attr = Attribute bits set on the memory block. 141 */ 142 alias BlkInfo_ BlkInfo; 143 144 145 /** 146 * Returns a bit field representing all block attributes set for the memory 147 * referenced by p. If p references memory not originally allocated by this 148 * garbage collector, points to the interior of a memory block, or if p is 149 * null, zero will be returned. 150 * 151 * Params: 152 * p = A pointer to the root of a valid memory block or to null. 153 * 154 * Returns: 155 * A bit field containing any bits set for the memory block referenced by 156 * p or zero on error. 157 */ 158 static uint getAttr( void* p ) 159 { 160 return gc_getAttr( p ); 161 } 162 163 164 /** 165 * Sets the specified bits for the memory references by p. If p references 166 * memory not originally allocated by this garbage collector, points to the 167 * interior of a memory block, or if p is null, no action will be performed. 168 * 169 * Params: 170 * p = A pointer to the root of a valid memory block or to null. 171 * a = A bit field containing any bits to set for this memory block. 172 * 173 * The result of a call to getAttr after the specified bits have been 174 * set. 175 */ 176 static uint setAttr( void* p, uint a ) 177 { 178 return gc_setAttr( p, a ); 179 } 180 181 182 /** 183 * Clears the specified bits for the memory references by p. If p 184 * references memory not originally allocated by this garbage collector, 185 * points to the interior of a memory block, or if p is null, no action 186 * will be performed. 187 * 188 * Params: 189 * p = A pointer to the root of a valid memory block or to null. 190 * a = A bit field containing any bits to clear for this memory block. 191 * 192 * Returns: 193 * The result of a call to getAttr after the specified bits have been 194 * cleared. 195 */ 196 static uint clrAttr( void* p, uint a ) 197 { 198 return gc_clrAttr( p, a ); 199 } 200 201 202 /** 203 * Requests an aligned block of managed memory from the garbage collector. 204 * This memory may be deleted at will with a call to free, or it may be 205 * discarded and cleaned up automatically during a collection run. If 206 * allocation fails, this function will call onOutOfMemory which is 207 * expected to throw an OutOfMemoryException. 208 * 209 * Params: 210 * sz = The desired allocation size in bytes. 211 * ba = A bitmask of the attributes to set on this block. 212 * bitMask = The pointer offset information for precise heap scanning. 213 * 214 * Returns: 215 * A reference to the allocated memory or null if insufficient memory 216 * is available. 217 * 218 * Throws: 219 * OutOfMemoryException on allocation failure. 220 */ 221 static void* malloc( size_t sz, uint ba = 0, 222 PointerMap bitMask = PointerMap.init ) 223 { 224 return gc_malloc( sz, ba, bitMask ); 225 } 226 227 228 /** 229 * Requests an aligned block of managed memory from the garbage collector, 230 * which is initialized with all bits set to zero. This memory may be 231 * deleted at will with a call to free, or it may be discarded and cleaned 232 * up automatically during a collection run. If allocation fails, this 233 * function will call onOutOfMemory which is expected to throw an 234 * OutOfMemoryException. 235 * 236 * Params: 237 * sz = The desired allocation size in bytes. 238 * ba = A bitmask of the attributes to set on this block. 239 * bitMask = The pointer offset information for precise heap scanning. 240 * 241 * Returns: 242 * A reference to the allocated memory or null if insufficient memory 243 * is available. 244 * 245 * Throws: 246 * OutOfMemoryException on allocation failure. 247 */ 248 static void* calloc( size_t sz, uint ba = 0, 249 PointerMap bitMask = PointerMap.init ) 250 { 251 return gc_calloc( sz, ba, bitMask ); 252 } 253 254 255 /** 256 * If sz is zero, the memory referenced by p will be deallocated as if 257 * by a call to free. A new memory block of size sz will then be 258 * allocated as if by a call to malloc, or the implementation may instead 259 * resize the memory block in place. The contents of the new memory block 260 * will be the same as the contents of the old memory block, up to the 261 * lesser of the new and old sizes. Note that existing memory will only 262 * be freed by realloc if sz is equal to zero. The garbage collector is 263 * otherwise expected to later reclaim the memory block if it is unused. 264 * If allocation fails, this function will call onOutOfMemory which is 265 * expected to throw an OutOfMemoryException. If p references memory not 266 * originally allocated by this garbage collector, or if it points to the 267 * interior of a memory block, no action will be taken. If ba is zero 268 * (the default) and p references the head of a valid, known memory block 269 * then any bits set on the current block will be set on the new block if a 270 * reallocation is required. If ba is not zero and p references the head 271 * of a valid, known memory block then the bits in ba will replace those on 272 * the current memory block and will also be set on the new block if a 273 * reallocation is required. Similarly, if bitMask is non-null, then 274 * the bitmask for the current block will propagated to the new block. 275 * Otherwise, the bitmask provided will be propagated to the old block. 276 * 277 * Params: 278 * p = A pointer to the root of a valid memory block or to null. 279 * sz = The desired allocation size in bytes. 280 * ba = A bitmask of the attributes to set on this block. 281 * bitMask = The pointer offset information for precise heap scanning. 282 * 283 * Returns: 284 * A reference to the allocated memory on success or null if sz is 285 * zero. On failure, the original value of p is returned. 286 * 287 * Throws: 288 * OutOfMemoryException on allocation failure. 289 */ 290 static void* realloc( void* p, size_t sz, uint ba = 0, 291 PointerMap bitMask = PointerMap.init ) 292 { 293 return gc_realloc( p, sz, ba, bitMask ); 294 } 295 296 297 /** 298 * Requests that the managed memory block referenced by p be extended in 299 * place by at least mx bytes, with a desired extension of sz bytes. If an 300 * extension of the required size is not possible, if p references memory 301 * not originally allocated by this garbage collector, or if p points to 302 * the interior of a memory block, no action will be taken. 303 * 304 * Params: 305 * mx = The minimum extension size in bytes. 306 * sz = The desired extension size in bytes. 307 * 308 * Returns: 309 * The size in bytes of the extended memory block referenced by p or zero 310 * if no extension occurred. 311 */ 312 static size_t extend( void* p, size_t mx, size_t sz ) 313 { 314 return gc_extend( p, mx, sz ); 315 } 316 317 318 /** 319 * Requests that at least sz bytes of memory be obtained from the operating 320 * system and marked as free. 321 * 322 * Params: 323 * sz = The desired size in bytes. 324 * 325 * Returns: 326 * The actual number of bytes reserved or zero on error. 327 */ 328 static size_t reserve( size_t sz ) 329 { 330 return gc_reserve( sz ); 331 } 332 333 334 /** 335 * Deallocates the memory referenced by p. If p is null, no action 336 * occurs. If p references memory not originally allocated by this 337 * garbage collector, or if it points to the interior of a memory block, 338 * no action will be taken. The block will not be finalized regardless 339 * of whether the FINALIZE attribute is set. If finalization is desired, 340 * use delete instead. 341 * 342 * Params: 343 * p = A pointer to the root of a valid memory block or to null. 344 */ 345 static void free( void* p ) 346 { 347 gc_free( p ); 348 } 349 350 351 /** 352 * Returns the base address of the memory block containing p. This value 353 * is useful to determine whether p is an interior pointer, and the result 354 * may be passed to routines such as sizeOf which may otherwise fail. If p 355 * references memory not originally allocated by this garbage collector, if 356 * p is null, or if the garbage collector does not support this operation, 357 * null will be returned. 358 * 359 * Params: 360 * p = A pointer to the root or the interior of a valid memory block or to 361 * null. 362 * 363 * Returns: 364 * The base address of the memory block referenced by p or null on error. 365 */ 366 static void* addrOf( void* p ) 367 { 368 return gc_addrOf( p ); 369 } 370 371 372 /** 373 * Returns the true size of the memory block referenced by p. This value 374 * represents the maximum number of bytes for which a call to realloc may 375 * resize the existing block in place. If p references memory not 376 * originally allocated by this garbage collector, points to the interior 377 * of a memory block, or if p is null, zero will be returned. 378 * 379 * Params: 380 * p = A pointer to the root of a valid memory block or to null. 381 * 382 * Returns: 383 * The size in bytes of the memory block referenced by p or zero on error. 384 */ 385 static size_t sizeOf( void* p ) 386 { 387 return gc_sizeOf( p ); 388 } 389 390 391 /** 392 * Returns aggregate information about the memory block containing p. If p 393 * references memory not originally allocated by this garbage collector, if 394 * p is null, or if the garbage collector does not support this operation, 395 * BlkInfo.init will be returned. Typically, support for this operation 396 * is dependent on support for addrOf. 397 * 398 * Params: 399 * p = A pointer to the root or the interior of a valid memory block or to 400 * null. 401 * 402 * Returns: 403 * Information regarding the memory block referenced by p or BlkInfo.init 404 * on error. 405 */ 406 static BlkInfo query( void* p ) 407 { 408 return gc_query( p ); 409 } 410 411 412 /** 413 * Adds the memory address referenced by p to an internal list of roots to 414 * be scanned during a collection. If p is null, no operation is 415 * performed. 416 * 417 * Params: 418 * p = A pointer to a valid memory address or to null. 419 */ 420 static void addRoot( void* p ) 421 { 422 gc_addRoot( p ); 423 } 424 425 426 /** 427 * Adds the memory block referenced by p and of size sz to an internal list 428 * of ranges to be scanned during a collection. If p is null, no operation 429 * is performed. 430 * 431 * Params: 432 * p = A pointer to a valid memory address or to null. 433 * sz = The size in bytes of the block to add. If sz is zero then the 434 * no operation will occur. If p is null then sz must be zero. 435 */ 436 static void addRange( void* p, size_t sz ) 437 { 438 gc_addRange( p, sz ); 439 } 440 441 442 /** 443 * Removes the memory block referenced by p from an internal list of roots 444 * to be scanned during a collection. If p is null or does not represent 445 * a value previously passed to add(void*) then no operation is performed. 446 * 447 * p = A pointer to a valid memory address or to null. 448 */ 449 static void removeRoot( void* p ) 450 { 451 gc_removeRoot( p ); 452 } 453 454 455 /** 456 * Removes the memory block referenced by p from an internal list of ranges 457 * to be scanned during a collection. If p is null or does not represent 458 * a value previously passed to add(void*, size_t) then no operation is 459 * performed. 460 * 461 * Params: 462 * p = A pointer to a valid memory address or to null. 463 */ 464 static void removeRange( void* p ) 465 { 466 gc_removeRange( p ); 467 } 468 469 /** 470 * Removes the memory block referenced by p from an internal list of ranges 471 * to be scanned during a collection. If p is null or does not represent 472 * a value previously passed to add(void*, size_t) then no operation is 473 * performed. 474 * 475 * Params: 476 * p = A pointer to a valid memory address or to null. 477 */ 478 static void monitor( void delegate() begin, void delegate(int, int) end ) 479 { 480 gc_monitor( begin, end ); 481 } 482 483 484 /** 485 * Create a weak pointer to the given object. 486 * Returns a pointer to an opaque struct allocated in C memory. 487 */ 488 static void* weakPointerCreate( Object o ) 489 { 490 return gc_weakpointerCreate (o); 491 } 492 493 494 /** 495 * Destroy a weak pointer returned by weakpointerCreate(). 496 * If null is passed, nothing happens. 497 */ 498 static void weakPointerDestroy( void* p ) 499 { 500 return gc_weakpointerDestroy (p); 501 } 502 503 504 /** 505 * Query a weak pointer and return either the object passed to 506 * weakpointerCreate, or null if it was free'd in the meantime. 507 * If null is passed, null is returned. 508 */ 509 static Object weakPointerGet( void* p ) 510 { 511 return gc_weakpointerGet (p); 512 } 513 514 515 /** 516 * Returns the amount to allocate to keep some extra space 517 * for large allocations the extra allocated space decreases, but is still enough 518 * so that the number of reallocations when linearly growing stays logaritmic 519 * Params: 520 * newlength = the number of elements to allocate 521 * elSize = size of one element 522 */ 523 static size_t growLength (size_t newlength, size_t elSize=1) 524 { 525 return growLength (newlength, elSize, 100, 0, 1); 526 } 527 528 529 /** 530 * Returns the amount to allocate to keep some extra space 531 * for large allocations the extra allocated space decreases, but is still enough 532 * so that the number of reallocations when linearly growing stays logaritmic 533 * Params: 534 * newlength = the number of elements to allocate 535 * elSize = size of one element 536 * a = maximum extra space in percent (the allocated space gets rounded up, so might be larger) 537 * b = flatness factor, how fast the extra space decreases with array size (the larger the more constant) 538 * minBits = minimum number of bits of newlength 539 */ 540 static size_t growLength (size_t newlength, size_t elSize, size_t a, size_t b=0, size_t minBits=1) 541 { 542 static size_t log2(size_t c) 543 { 544 // could use the bsr bit op 545 size_t i=1; 546 while(c >>= 1) 547 ++i; 548 return i; 549 } 550 551 size_t newext = 0; 552 size_t newcap = newlength*elSize; 553 long mult = 100 + a*(minBits+b) / (log2(newlength)+b); 554 newext = elSize*cast(size_t)(((newcap * mult)+99) / 100); 555 newcap = newext > newcap ? newext : newcap; // just to handle overflows 556 return newcap; 557 } 558 }+/