1 /** 2 * This module provides an interface to the garbage collector used by 3 * applications written in the D programming language. It allows the 4 * garbage collector in the runtime to be swapped without affecting 5 * binary compatibility of applications. 6 * 7 * Using this module is not necessary in typical D code. It is mostly 8 * useful when doing low-level _memory management. 9 * 10 * Notes_to_users: 11 * 12 $(OL 13 $(LI The GC is a conservative mark-and-sweep collector. It only runs a 14 collection cycle when an allocation is requested of it, never 15 otherwise. Hence, if the program is not doing allocations, 16 there will be no GC collection pauses. The pauses occur because 17 all threads the GC knows about are halted so the threads' stacks 18 and registers can be scanned for references to GC allocated data. 19 ) 20 21 $(LI The GC does not know about threads that were created by directly calling 22 the OS/C runtime thread creation APIs and D threads that were detached 23 from the D runtime after creation. 24 Such threads will not be paused for a GC collection, and the GC might not detect 25 references to GC allocated data held by them. This can cause memory corruption. 26 There are several ways to resolve this issue: 27 $(OL 28 $(LI Do not hold references to GC allocated data in such threads.) 29 $(LI Register/unregister such data with calls to $(LREF addRoot)/$(LREF removeRoot) and 30 $(LREF addRange)/$(LREF removeRange).) 31 $(LI Maintain another reference to that same data in another thread that the 32 GC does know about.) 33 $(LI Disable GC collection cycles while that thread is active with $(LREF disable)/$(LREF enable).) 34 $(LI Register the thread with the GC using $(REF thread_attachThis, core,thread,osthread)/$(REF thread_detachThis, core,thread,threadbase).) 35 ) 36 ) 37 ) 38 * 39 * Notes_to_implementors: 40 * $(UL 41 * $(LI On POSIX systems, the signals `SIGRTMIN` and `SIGRTMIN + 1` are reserved 42 * by this module for use in the garbage collector implementation. 43 * Typically, they will be used to stop and resume other threads 44 * when performing a collection, but an implementation may choose 45 * not to use this mechanism (or not stop the world at all, in the 46 * case of concurrent garbage collectors).) 47 * 48 * $(LI Registers, the stack, and any other _memory locations added through 49 * the $(D GC.$(LREF addRange)) function are always scanned conservatively. 50 * This means that even if a variable is e.g. of type $(D float), 51 * it will still be scanned for possible GC pointers. And, if the 52 * word-interpreted representation of the variable matches a GC-managed 53 * _memory block's address, that _memory block is considered live.) 54 * 55 * $(LI Implementations are free to scan the non-root heap in a precise 56 * manner, so that fields of types like $(D float) will not be considered 57 * relevant when scanning the heap. Thus, casting a GC pointer to an 58 * integral type (e.g. $(D size_t)) and storing it in a field of that 59 * type inside the GC heap may mean that it will not be recognized 60 * if the _memory block was allocated with precise type info or with 61 * the $(D GC.BlkAttr.$(LREF NO_SCAN)) attribute.) 62 * 63 * $(LI Destructors will always be executed while other threads are 64 * active; that is, an implementation that stops the world must not 65 * execute destructors until the world has been resumed.) 66 * 67 * $(LI A destructor of an object must not access object references 68 * within the object. This means that an implementation is free to 69 * optimize based on this rule.) 70 * 71 * $(LI An implementation is free to perform heap compaction and copying 72 * so long as no valid GC pointers are invalidated in the process. 73 * However, _memory allocated with $(D GC.BlkAttr.$(LREF NO_MOVE)) must 74 * not be moved/copied.) 75 * 76 * $(LI Implementations must support interior pointers. That is, if the 77 * only reference to a GC-managed _memory block points into the 78 * middle of the block rather than the beginning (for example), the 79 * GC must consider the _memory block live. The exception to this 80 * rule is when a _memory block is allocated with the 81 * $(D GC.BlkAttr.$(LREF NO_INTERIOR)) attribute; it is the user's 82 * responsibility to make sure such _memory blocks have a proper pointer 83 * to them when they should be considered live.) 84 * 85 * $(LI It is acceptable for an implementation to store bit flags into 86 * pointer values and GC-managed _memory blocks, so long as such a 87 * trick is not visible to the application. In practice, this means 88 * that only a stop-the-world collector can do this.) 89 * 90 * $(LI Implementations are free to assume that GC pointers are only 91 * stored on word boundaries. Unaligned pointers may be ignored 92 * entirely.) 93 * 94 * $(LI Implementations are free to run collections at any point. It is, 95 * however, recommendable to only do so when an allocation attempt 96 * happens and there is insufficient _memory available.) 97 * ) 98 * 99 * Copyright: Copyright Sean Kelly 2005 - 2015. 100 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 101 * Authors: Sean Kelly, Alex Rønne Petersen 102 * Source: $(DRUNTIMESRC core/_memory.d) 103 */ 104 105 module core.memory; 106 107 version (ARM) 108 version = AnyARM; 109 else version (AArch64) 110 version = AnyARM; 111 112 version (iOS) 113 version = iOSDerived; 114 else version (TVOS) 115 version = iOSDerived; 116 else version (WatchOS) 117 version = iOSDerived; 118 119 private 120 { 121 extern (C) uint gc_getAttr( void* p ) pure nothrow; 122 extern (C) uint gc_setAttr( void* p, uint a ) pure nothrow; 123 extern (C) uint gc_clrAttr( void* p, uint a ) pure nothrow; 124 125 extern (C) void* gc_addrOf( void* p ) pure nothrow @nogc; 126 extern (C) size_t gc_sizeOf( void* p ) pure nothrow @nogc; 127 128 struct BlkInfo_ 129 { 130 void* base; 131 size_t size; 132 uint attr; 133 } 134 135 extern (C) BlkInfo_ gc_query(return scope void* p) pure nothrow; 136 extern (C) GC.Stats gc_stats ( ) @safe nothrow @nogc; 137 extern (C) GC.ProfileStats gc_profileStats ( ) nothrow @nogc @safe; 138 } 139 140 version (CoreDoc) 141 { 142 /** 143 * The minimum size of a system page in bytes. 144 * 145 * This is a compile time, platform specific value. This value might not 146 * be accurate, since it might be possible to change this value. Whenever 147 * possible, please use $(LREF pageSize) instead, which is initialized 148 * during runtime. 149 * 150 * The minimum size is useful when the context requires a compile time known 151 * value, like the size of a static array: `ubyte[minimumPageSize] buffer`. 152 */ 153 enum minimumPageSize : size_t; 154 } 155 else version (AnyARM) 156 { 157 version (iOSDerived) 158 enum size_t minimumPageSize = 16384; 159 else 160 enum size_t minimumPageSize = 4096; 161 } 162 else 163 enum size_t minimumPageSize = 4096; 164 165 /// 166 unittest 167 { 168 ubyte[minimumPageSize] buffer; 169 } 170 171 /** 172 * The size of a system page in bytes. 173 * 174 * This value is set at startup time of the application. It's safe to use 175 * early in the start process, like in shared module constructors and 176 * initialization of the D runtime itself. 177 */ 178 immutable size_t pageSize; 179 180 /// 181 unittest 182 { 183 ubyte[] buffer = new ubyte[pageSize]; 184 } 185 186 // The reason for this elaborated way of declaring a function is: 187 // 188 // * `pragma(crt_constructor)` is used to declare a constructor that is called by 189 // the C runtime, before C main. This allows the `pageSize` value to be used 190 // during initialization of the D runtime. This also avoids any issues with 191 // static module constructors and circular references. 192 // 193 // * `pragma(mangle)` is used because `pragma(crt_constructor)` requires a 194 // function with C linkage. To avoid any name conflict with other C symbols, 195 // standard D mangling is used. 196 // 197 // * The extra function declaration, without the body, is to be able to get the 198 // D mangling of the function without the need to hardcode the value. 199 // 200 // * The extern function declaration also has the side effect of making it 201 // impossible to manually call the function with standard syntax. This is to 202 // make it more difficult to call the function again, manually. 203 private void initialize(); 204 pragma(crt_constructor) 205 pragma(mangle, initialize.mangleof) 206 private extern (C) void _initialize() @system 207 { 208 import rt.sys.config; 209 mixin("import " ~ osMemoryImport ~ " : getPageSize;"); 210 211 (cast() pageSize) = getPageSize(); 212 } 213 214 /** 215 * This struct encapsulates all garbage collection functionality for the D 216 * programming language. 217 */ 218 struct GC 219 { 220 @disable this(); 221 222 /** 223 * Aggregation of GC stats to be exposed via public API 224 */ 225 static struct Stats 226 { 227 /// number of used bytes on the GC heap (might only get updated after a collection) 228 size_t usedSize; 229 /// number of free bytes on the GC heap (might only get updated after a collection) 230 size_t freeSize; 231 /// number of bytes allocated for current thread since program start 232 ulong allocatedInCurrentThread; 233 } 234 235 /** 236 * Aggregation of current profile information 237 */ 238 static struct ProfileStats 239 { 240 import core.time : Duration; 241 /// total number of GC cycles 242 size_t numCollections; 243 /// total time spent doing GC 244 Duration totalCollectionTime; 245 /// total time threads were paused doing GC 246 Duration totalPauseTime; 247 /// largest time threads were paused during one GC cycle 248 Duration maxPauseTime; 249 /// largest time spent doing one GC cycle 250 Duration maxCollectionTime; 251 } 252 253 extern(C): 254 255 /** 256 * Enables automatic garbage collection behavior if collections have 257 * previously been suspended by a call to disable. This function is 258 * reentrant, and must be called once for every call to disable before 259 * automatic collections are enabled. 260 */ 261 pragma(mangle, "gc_enable") static void enable() @safe nothrow pure; 262 263 264 /** 265 * Disables automatic garbage collections performed to minimize the 266 * process footprint. Collections may continue to occur in instances 267 * where the implementation deems necessary for correct program behavior, 268 * such as during an out of memory condition. This function is reentrant, 269 * but enable must be called once for each call to disable. 270 */ 271 pragma(mangle, "gc_disable") static void disable() @safe nothrow pure; 272 273 274 /** 275 * Begins a full collection. While the meaning of this may change based 276 * on the garbage collector implementation, typical behavior is to scan 277 * all stack segments for roots, mark accessible memory blocks as alive, 278 * and then to reclaim free space. This action may need to suspend all 279 * running threads for at least part of the collection process. 280 */ 281 pragma(mangle, "gc_collect") static void collect() @safe nothrow pure; 282 283 /** 284 * Indicates that the managed memory space be minimized by returning free 285 * physical memory to the operating system. The amount of free memory 286 * returned depends on the allocator design and on program behavior. 287 */ 288 pragma(mangle, "gc_minimize") static void minimize() @safe nothrow pure; 289 290 extern(D): 291 292 /** 293 * Elements for a bit field representing memory block attributes. These 294 * are manipulated via the getAttr, setAttr, clrAttr functions. 295 */ 296 enum BlkAttr : uint 297 { 298 NONE = 0b0000_0000, /// No attributes set. 299 FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect. 300 NO_SCAN = 0b0000_0010, /// Do not scan through this block on collect. 301 NO_MOVE = 0b0000_0100, /// Do not move this memory block on collect. 302 /** 303 This block contains the info to allow appending. 304 305 This can be used to manually allocate arrays. Initial slice size is 0. 306 307 Note: The slice's usable size will not match the block size. Use 308 $(LREF capacity) to retrieve actual usable capacity. 309 310 Example: 311 ---- 312 // Allocate the underlying array. 313 int* pToArray = cast(int*)GC.malloc(10 * int.sizeof, GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE); 314 // Bind a slice. Check the slice has capacity information. 315 int[] slice = pToArray[0 .. 0]; 316 assert(capacity(slice) > 0); 317 // Appending to the slice will not relocate it. 318 slice.length = 5; 319 slice ~= 1; 320 assert(slice.ptr == p); 321 ---- 322 */ 323 APPENDABLE = 0b0000_1000, 324 325 /** 326 This block is guaranteed to have a pointer to its base while it is 327 alive. Interior pointers can be safely ignored. This attribute is 328 useful for eliminating false pointers in very large data structures 329 and is only implemented for data structures at least a page in size. 330 */ 331 NO_INTERIOR = 0b0001_0000, 332 333 STRUCTFINAL = 0b0010_0000, // the block has a finalizer for (an array of) structs 334 } 335 336 337 /** 338 * Contains aggregate information about a block of managed memory. The 339 * purpose of this struct is to support a more efficient query style in 340 * instances where detailed information is needed. 341 * 342 * base = A pointer to the base of the block in question. 343 * size = The size of the block, calculated from base. 344 * attr = Attribute bits set on the memory block. 345 */ 346 alias BlkInfo = BlkInfo_; 347 348 349 /** 350 * Returns a bit field representing all block attributes set for the memory 351 * referenced by p. If p references memory not originally allocated by 352 * this garbage collector, points to the interior of a memory block, or if 353 * p is null, zero will be returned. 354 * 355 * Params: 356 * p = A pointer to the root of a valid memory block or to null. 357 * 358 * Returns: 359 * A bit field containing any bits set for the memory block referenced by 360 * p or zero on error. 361 */ 362 static uint getAttr( const scope void* p ) nothrow 363 { 364 return gc_getAttr(cast(void*) p); 365 } 366 367 368 /// ditto 369 static uint getAttr(void* p) pure nothrow 370 { 371 return gc_getAttr( p ); 372 } 373 374 375 /** 376 * Sets the specified bits for the memory references by p. If p references 377 * memory not originally allocated by this garbage collector, points to the 378 * interior of a memory block, or if p is null, no action will be 379 * performed. 380 * 381 * Params: 382 * p = A pointer to the root of a valid memory block or to null. 383 * a = A bit field containing any bits to set for this memory block. 384 * 385 * Returns: 386 * The result of a call to getAttr after the specified bits have been 387 * set. 388 */ 389 static uint setAttr( const scope void* p, uint a ) nothrow 390 { 391 return gc_setAttr(cast(void*) p, a); 392 } 393 394 395 /// ditto 396 static uint setAttr(void* p, uint a) pure nothrow 397 { 398 return gc_setAttr( p, a ); 399 } 400 401 402 /** 403 * Clears the specified bits for the memory references by p. If p 404 * references memory not originally allocated by this garbage collector, 405 * points to the interior of a memory block, or if p is null, no action 406 * will be performed. 407 * 408 * Params: 409 * p = A pointer to the root of a valid memory block or to null. 410 * a = A bit field containing any bits to clear for this memory block. 411 * 412 * Returns: 413 * The result of a call to getAttr after the specified bits have been 414 * cleared. 415 */ 416 static uint clrAttr( const scope void* p, uint a ) nothrow 417 { 418 return gc_clrAttr(cast(void*) p, a); 419 } 420 421 422 /// ditto 423 static uint clrAttr(void* p, uint a) pure nothrow 424 { 425 return gc_clrAttr( p, a ); 426 } 427 428 extern(C): 429 430 /** 431 * Requests an aligned block of managed memory from the garbage collector. 432 * This memory may be deleted at will with a call to free, or it may be 433 * discarded and cleaned up automatically during a collection run. If 434 * allocation fails, this function will call onOutOfMemory which is 435 * expected to throw an OutOfMemoryError. 436 * 437 * Params: 438 * sz = The desired allocation size in bytes. 439 * ba = A bitmask of the attributes to set on this block. 440 * ti = TypeInfo to describe the memory. The GC might use this information 441 * to improve scanning for pointers or to call finalizers. 442 * 443 * Returns: 444 * A reference to the allocated memory or null if insufficient memory 445 * is available. 446 * 447 * Throws: 448 * OutOfMemoryError on allocation failure. 449 */ 450 version (D_ProfileGC) 451 pragma(mangle, "gc_mallocTrace") static void* malloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null, 452 string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow; 453 else 454 pragma(mangle, "gc_malloc") static void* malloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null) pure nothrow; 455 456 /** 457 * Requests an aligned block of managed memory from the garbage collector. 458 * This memory may be deleted at will with a call to free, or it may be 459 * discarded and cleaned up automatically during a collection run. If 460 * allocation fails, this function will call onOutOfMemory which is 461 * expected to throw an OutOfMemoryError. 462 * 463 * Params: 464 * sz = The desired allocation size in bytes. 465 * ba = A bitmask of the attributes to set on this block. 466 * ti = TypeInfo to describe the memory. The GC might use this information 467 * to improve scanning for pointers or to call finalizers. 468 * 469 * Returns: 470 * Information regarding the allocated memory block or BlkInfo.init on 471 * error. 472 * 473 * Throws: 474 * OutOfMemoryError on allocation failure. 475 */ 476 version (D_ProfileGC) 477 pragma(mangle, "gc_qallocTrace") static BlkInfo qalloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null, 478 string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow; 479 else 480 pragma(mangle, "gc_qalloc") static BlkInfo qalloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null) pure nothrow; 481 482 483 /** 484 * Requests an aligned block of managed memory from the garbage collector, 485 * which is initialized with all bits set to zero. This memory may be 486 * deleted at will with a call to free, or it may be discarded and cleaned 487 * up automatically during a collection run. If allocation fails, this 488 * function will call onOutOfMemory which is expected to throw an 489 * OutOfMemoryError. 490 * 491 * Params: 492 * sz = The desired allocation size in bytes. 493 * ba = A bitmask of the attributes to set on this block. 494 * ti = TypeInfo to describe the memory. The GC might use this information 495 * to improve scanning for pointers or to call finalizers. 496 * 497 * Returns: 498 * A reference to the allocated memory or null if insufficient memory 499 * is available. 500 * 501 * Throws: 502 * OutOfMemoryError on allocation failure. 503 */ 504 version (D_ProfileGC) 505 pragma(mangle, "gc_callocTrace") static void* calloc(size_t sz, uint ba = 0, const TypeInfo ti = null, 506 string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow; 507 else 508 pragma(mangle, "gc_calloc") static void* calloc(size_t sz, uint ba = 0, const TypeInfo ti = null) pure nothrow; 509 510 511 /** 512 * Extend, shrink or allocate a new block of memory keeping the contents of 513 * an existing block 514 * 515 * If `sz` is zero, the memory referenced by p will be deallocated as if 516 * by a call to `free`. 517 * If `p` is `null`, new memory will be allocated via `malloc`. 518 * If `p` is pointing to memory not allocated from the GC or to the interior 519 * of an allocated memory block, no operation is performed and null is returned. 520 * 521 * Otherwise, a new memory block of size `sz` will be allocated as if by a 522 * call to `malloc`, or the implementation may instead resize or shrink the memory 523 * block in place. 524 * The contents of the new memory block will be the same as the contents 525 * of the old memory block, up to the lesser of the new and old sizes. 526 * 527 * The caller guarantees that there are no other live pointers to the 528 * passed memory block, still it might not be freed immediately by `realloc`. 529 * The garbage collector can reclaim the memory block in a later 530 * collection if it is unused. 531 * If allocation fails, this function will throw an `OutOfMemoryError`. 532 * 533 * If `ba` is zero (the default) the attributes of the existing memory 534 * will be used for an allocation. 535 * If `ba` is not zero and no new memory is allocated, the bits in ba will 536 * replace those of the current memory block. 537 * 538 * Params: 539 * p = A pointer to the base of a valid memory block or to `null`. 540 * sz = The desired allocation size in bytes. 541 * ba = A bitmask of the BlkAttr attributes to set on this block. 542 * ti = TypeInfo to describe the memory. The GC might use this information 543 * to improve scanning for pointers or to call finalizers. 544 * 545 * Returns: 546 * A reference to the allocated memory on success or `null` if `sz` is 547 * zero or the pointer does not point to the base of an GC allocated 548 * memory block. 549 * 550 * Throws: 551 * `OutOfMemoryError` on allocation failure. 552 */ 553 version (D_ProfileGC) 554 pragma(mangle, "gc_reallocTrace") static void* realloc(return scope void* p, size_t sz, uint ba = 0, const TypeInfo ti = null, 555 string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow; 556 else 557 pragma(mangle, "gc_realloc") static void* realloc(return scope void* p, size_t sz, uint ba = 0, const TypeInfo ti = null) pure nothrow; 558 559 // https://issues.dlang.org/show_bug.cgi?id=13111 560 /// 561 unittest 562 { 563 enum size1 = 1 << 11 + 1; // page in large object pool 564 enum size2 = 1 << 22 + 1; // larger than large object pool size 565 566 auto data1 = cast(ubyte*)GC.calloc(size1); 567 auto data2 = cast(ubyte*)GC.realloc(data1, size2); 568 569 GC.BlkInfo info = GC.query(data2); 570 assert(info.size >= size2); 571 } 572 573 574 /** 575 * Requests that the managed memory block referenced by p be extended in 576 * place by at least mx bytes, with a desired extension of sz bytes. If an 577 * extension of the required size is not possible or if p references memory 578 * not originally allocated by this garbage collector, no action will be 579 * taken. 580 * 581 * Params: 582 * p = A pointer to the root of a valid memory block or to null. 583 * mx = The minimum extension size in bytes. 584 * sz = The desired extension size in bytes. 585 * ti = TypeInfo to describe the full memory block. The GC might use 586 * this information to improve scanning for pointers or to 587 * call finalizers. 588 * 589 * Returns: 590 * The size in bytes of the extended memory block referenced by p or zero 591 * if no extension occurred. 592 * 593 * Note: 594 * Extend may also be used to extend slices (or memory blocks with 595 * $(LREF APPENDABLE) info). However, use the return value only 596 * as an indicator of success. $(LREF capacity) should be used to 597 * retrieve actual usable slice capacity. 598 */ 599 version (D_ProfileGC) 600 pragma(mangle, "gc_extendTrace") static size_t extend(void* p, size_t mx, size_t sz, const TypeInfo ti = null, 601 string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow; 602 else 603 pragma(mangle, "gc_extend") static size_t extend(void* p, size_t mx, size_t sz, const TypeInfo ti = null) pure nothrow; 604 605 /// Standard extending 606 unittest 607 { 608 size_t size = 1000; 609 int* p = cast(int*)GC.malloc(size * int.sizeof, GC.BlkAttr.NO_SCAN); 610 611 //Try to extend the allocated data by 1000 elements, preferred 2000. 612 size_t u = GC.extend(p, 1000 * int.sizeof, 2000 * int.sizeof); 613 if (u != 0) 614 size = u / int.sizeof; 615 } 616 /// slice extending 617 unittest 618 { 619 int[] slice = new int[](1000); 620 int* p = slice.ptr; 621 622 //Check we have access to capacity before attempting the extend 623 if (slice.capacity) 624 { 625 //Try to extend slice by 1000 elements, preferred 2000. 626 size_t u = GC.extend(p, 1000 * int.sizeof, 2000 * int.sizeof); 627 if (u != 0) 628 { 629 slice.length = slice.capacity; 630 assert(slice.length >= 2000); 631 } 632 } 633 } 634 635 636 /** 637 * Requests that at least sz bytes of memory be obtained from the operating 638 * system and marked as free. 639 * 640 * Params: 641 * sz = The desired size in bytes. 642 * 643 * Returns: 644 * The actual number of bytes reserved or zero on error. 645 */ 646 pragma(mangle, "gc_reserve") static size_t reserve(size_t sz) nothrow pure; 647 648 649 /** 650 * Deallocates the memory referenced by p. If p is null, no action occurs. 651 * If p references memory not originally allocated by this garbage 652 * collector, if p points to the interior of a memory block, or if this 653 * method is called from a finalizer, no action will be taken. The block 654 * will not be finalized regardless of whether the FINALIZE attribute is 655 * set. If finalization is desired, call $(REF1 destroy, object) prior to `GC.free`. 656 * 657 * Params: 658 * p = A pointer to the root of a valid memory block or to null. 659 */ 660 pragma(mangle, "gc_free") static void free(void* p) pure nothrow @nogc; 661 662 extern(D): 663 664 /** 665 * Returns the base address of the memory block containing p. This value 666 * is useful to determine whether p is an interior pointer, and the result 667 * may be passed to routines such as sizeOf which may otherwise fail. If p 668 * references memory not originally allocated by this garbage collector, if 669 * p is null, or if the garbage collector does not support this operation, 670 * null will be returned. 671 * 672 * Params: 673 * p = A pointer to the root or the interior of a valid memory block or to 674 * null. 675 * 676 * Returns: 677 * The base address of the memory block referenced by p or null on error. 678 */ 679 static inout(void)* addrOf( inout(void)* p ) nothrow @nogc pure @trusted 680 { 681 return cast(inout(void)*)gc_addrOf(cast(void*)p); 682 } 683 684 /// ditto 685 static void* addrOf(void* p) pure nothrow @nogc @trusted 686 { 687 return gc_addrOf(p); 688 } 689 690 /** 691 * Returns the true size of the memory block referenced by p. This value 692 * represents the maximum number of bytes for which a call to realloc may 693 * resize the existing block in place. If p references memory not 694 * originally allocated by this garbage collector, points to the interior 695 * of a memory block, or if p is null, zero will be returned. 696 * 697 * Params: 698 * p = A pointer to the root of a valid memory block or to null. 699 * 700 * Returns: 701 * The size in bytes of the memory block referenced by p or zero on error. 702 */ 703 static size_t sizeOf( const scope void* p ) nothrow @nogc /* FIXME pure */ 704 { 705 return gc_sizeOf(cast(void*)p); 706 } 707 708 709 /// ditto 710 static size_t sizeOf(void* p) pure nothrow @nogc 711 { 712 return gc_sizeOf( p ); 713 } 714 715 // verify that the reallocation doesn't leave the size cache in a wrong state 716 unittest 717 { 718 auto data = cast(int*)realloc(null, 4096); 719 size_t size = GC.sizeOf(data); 720 assert(size >= 4096); 721 data = cast(int*)GC.realloc(data, 4100); 722 size = GC.sizeOf(data); 723 assert(size >= 4100); 724 } 725 726 /** 727 * Returns aggregate information about the memory block containing p. If p 728 * references memory not originally allocated by this garbage collector, if 729 * p is null, or if the garbage collector does not support this operation, 730 * BlkInfo.init will be returned. Typically, support for this operation 731 * is dependent on support for addrOf. 732 * 733 * Params: 734 * p = A pointer to the root or the interior of a valid memory block or to 735 * null. 736 * 737 * Returns: 738 * Information regarding the memory block referenced by p or BlkInfo.init 739 * on error. 740 */ 741 static BlkInfo query(return scope const void* p) nothrow 742 { 743 return gc_query(cast(void*)p); 744 } 745 746 747 /// ditto 748 static BlkInfo query(return scope void* p) pure nothrow 749 { 750 return gc_query( p ); 751 } 752 753 /** 754 * Returns runtime stats for currently active GC implementation 755 * See `core.memory.GC.Stats` for list of available metrics. 756 */ 757 static Stats stats() @safe nothrow @nogc 758 { 759 return gc_stats(); 760 } 761 762 /** 763 * Returns runtime profile stats for currently active GC implementation 764 * See `core.memory.GC.ProfileStats` for list of available metrics. 765 */ 766 static ProfileStats profileStats() nothrow @nogc @safe 767 { 768 return gc_profileStats(); 769 } 770 771 extern(C): 772 773 /** 774 * Adds an internal root pointing to the GC memory block referenced by p. 775 * As a result, the block referenced by p itself and any blocks accessible 776 * via it will be considered live until the root is removed again. 777 * 778 * If p is null, no operation is performed. 779 * 780 * Params: 781 * p = A pointer into a GC-managed memory block or null. 782 * 783 * Example: 784 * --- 785 * // Typical C-style callback mechanism; the passed function 786 * // is invoked with the user-supplied context pointer at a 787 * // later point. 788 * extern(C) void addCallback(void function(void*), void*); 789 * 790 * // Allocate an object on the GC heap (this would usually be 791 * // some application-specific context data). 792 * auto context = new Object; 793 * 794 * // Make sure that it is not collected even if it is no 795 * // longer referenced from D code (stack, GC heap, …). 796 * GC.addRoot(cast(void*)context); 797 * 798 * // Also ensure that a moving collector does not relocate 799 * // the object. 800 * GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE); 801 * 802 * // Now context can be safely passed to the C library. 803 * addCallback(&myHandler, cast(void*)context); 804 * 805 * extern(C) void myHandler(void* ctx) 806 * { 807 * // Assuming that the callback is invoked only once, the 808 * // added root can be removed again now to allow the GC 809 * // to collect it later. 810 * GC.removeRoot(ctx); 811 * GC.clrAttr(ctx, GC.BlkAttr.NO_MOVE); 812 * 813 * auto context = cast(Object)ctx; 814 * // Use context here… 815 * } 816 * --- 817 */ 818 pragma(mangle, "gc_addRoot") static void addRoot(const void* p) nothrow @nogc pure; 819 820 821 /** 822 * Removes the memory block referenced by p from an internal list of roots 823 * to be scanned during a collection. If p is null or is not a value 824 * previously passed to addRoot() then no operation is performed. 825 * 826 * Params: 827 * p = A pointer into a GC-managed memory block or null. 828 */ 829 pragma(mangle, "gc_removeRoot") static void removeRoot(const void* p) nothrow @nogc pure; 830 831 832 /** 833 * Adds $(D p[0 .. sz]) to the list of memory ranges to be scanned for 834 * pointers during a collection. If p is null, no operation is performed. 835 * 836 * Note that $(D p[0 .. sz]) is treated as an opaque range of memory assumed 837 * to be suitably managed by the caller. In particular, if p points into a 838 * GC-managed memory block, addRange does $(I not) mark this block as live. 839 * 840 * Params: 841 * p = A pointer to a valid memory address or to null. 842 * sz = The size in bytes of the block to add. If sz is zero then the 843 * no operation will occur. If p is null then sz must be zero. 844 * ti = TypeInfo to describe the memory. The GC might use this information 845 * to improve scanning for pointers or to call finalizers 846 * 847 * Example: 848 * --- 849 * // Allocate a piece of memory on the C heap. 850 * enum size = 1_000; 851 * auto rawMemory = core.stdc.stdlib.malloc(size); 852 * 853 * // Add it as a GC range. 854 * GC.addRange(rawMemory, size); 855 * 856 * // Now, pointers to GC-managed memory stored in 857 * // rawMemory will be recognized on collection. 858 * --- 859 */ 860 pragma(mangle, "gc_addRange") 861 static void addRange(const void* p, size_t sz, const TypeInfo ti = null) @nogc nothrow pure; 862 863 864 /** 865 * Removes the memory range starting at p from an internal list of ranges 866 * to be scanned during a collection. If p is null or does not represent 867 * a value previously passed to addRange() then no operation is 868 * performed. 869 * 870 * Params: 871 * p = A pointer to a valid memory address or to null. 872 */ 873 pragma(mangle, "gc_removeRange") static void removeRange(const void* p) nothrow @nogc pure; 874 875 876 /** 877 * Runs any finalizer that is located in address range of the 878 * given code segment. This is used before unloading shared 879 * libraries. All matching objects which have a finalizer in this 880 * code segment are assumed to be dead, using them while or after 881 * calling this method has undefined behavior. 882 * 883 * Params: 884 * segment = address range of a code segment. 885 */ 886 pragma(mangle, "gc_runFinalizers") static void runFinalizers(const scope void[] segment); 887 888 /** 889 * Queries the GC whether the current thread is running object finalization 890 * as part of a GC collection, or an explicit call to runFinalizers. 891 * 892 * As some GC implementations (such as the current conservative one) don't 893 * support GC memory allocation during object finalization, this function 894 * can be used to guard against such programming errors. 895 * 896 * Returns: 897 * true if the current thread is in a finalizer, a destructor invoked by 898 * the GC. 899 */ 900 pragma(mangle, "gc_inFinalizer") static bool inFinalizer() nothrow @nogc @safe; 901 902 /// 903 @safe nothrow @nogc unittest 904 { 905 // Only code called from a destructor is executed during finalization. 906 assert(!GC.inFinalizer); 907 } 908 909 /// 910 unittest 911 { 912 enum Outcome 913 { 914 notCalled, 915 calledManually, 916 calledFromDruntime 917 } 918 919 static class Resource 920 { 921 static Outcome outcome; 922 923 this() 924 { 925 outcome = Outcome.notCalled; 926 } 927 928 ~this() 929 { 930 if (GC.inFinalizer) 931 { 932 outcome = Outcome.calledFromDruntime; 933 934 import core.exception : InvalidMemoryOperationError; 935 try 936 { 937 /* 938 * Presently, allocating GC memory during finalization 939 * is forbidden and leads to 940 * `InvalidMemoryOperationError` being thrown. 941 * 942 * `GC.inFinalizer` can be used to guard against 943 * programming erros such as these and is also a more 944 * efficient way to verify whether a destructor was 945 * invoked by the GC. 946 */ 947 cast(void) GC.malloc(1); 948 assert(false); 949 } 950 catch (InvalidMemoryOperationError e) 951 { 952 return; 953 } 954 assert(false); 955 } 956 else 957 outcome = Outcome.calledManually; 958 } 959 } 960 961 static void createGarbage() 962 { 963 auto r = new Resource; 964 r = null; 965 } 966 967 assert(Resource.outcome == Outcome.notCalled); 968 createGarbage(); 969 GC.collect; 970 assert( 971 Resource.outcome == Outcome.notCalled || 972 Resource.outcome == Outcome.calledFromDruntime); 973 974 auto r = new Resource; 975 GC.runFinalizers((cast(const void*)typeid(Resource).destructor)[0..1]); 976 assert(Resource.outcome == Outcome.calledFromDruntime); 977 Resource.outcome = Outcome.notCalled; 978 979 debug(MEMSTOMP) {} else 980 { 981 // assume Resource data is still available 982 r.destroy; 983 assert(Resource.outcome == Outcome.notCalled); 984 } 985 986 r = new Resource; 987 assert(Resource.outcome == Outcome.notCalled); 988 r.destroy; 989 assert(Resource.outcome == Outcome.calledManually); 990 } 991 992 /** 993 * Returns the number of bytes allocated for the current thread 994 * since program start. It is the same as 995 * GC.stats().allocatedInCurrentThread, but faster. 996 */ 997 pragma(mangle, "gc_allocatedInCurrentThread") static ulong allocatedInCurrentThread() nothrow; 998 999 /// Using allocatedInCurrentThread 1000 nothrow unittest 1001 { 1002 ulong currentlyAllocated = GC.allocatedInCurrentThread(); 1003 struct DataStruct 1004 { 1005 long l1; 1006 long l2; 1007 long l3; 1008 long l4; 1009 } 1010 DataStruct* unused = new DataStruct; 1011 assert(GC.allocatedInCurrentThread() == currentlyAllocated + 32); 1012 assert(GC.stats().allocatedInCurrentThread == currentlyAllocated + 32); 1013 } 1014 } 1015 1016 /** 1017 * Pure variants of C's memory allocation functions `malloc`, `calloc`, and 1018 * `realloc` and deallocation function `free`. 1019 * 1020 * UNIX 98 requires that errno be set to ENOMEM upon failure. 1021 * Purity is achieved by saving and restoring the value of `errno`, thus 1022 * behaving as if it were never changed. 1023 * 1024 * See_Also: 1025 * $(LINK2 https://dlang.org/spec/function.html#pure-functions, D's rules for purity), 1026 * which allow for memory allocation under specific circumstances. 1027 */ 1028 void* pureMalloc()(size_t size) @trusted pure @nogc nothrow 1029 { 1030 const errnosave = fakePureErrno; 1031 void* ret = fakePureMalloc(size); 1032 fakePureErrno = errnosave; 1033 return ret; 1034 } 1035 /// ditto 1036 void* pureCalloc()(size_t nmemb, size_t size) @trusted pure @nogc nothrow 1037 { 1038 const errnosave = fakePureErrno; 1039 void* ret = fakePureCalloc(nmemb, size); 1040 fakePureErrno = errnosave; 1041 return ret; 1042 } 1043 /// ditto 1044 void* pureRealloc()(void* ptr, size_t size) @system pure @nogc nothrow 1045 { 1046 const errnosave = fakePureErrno; 1047 void* ret = fakePureRealloc(ptr, size); 1048 fakePureErrno = errnosave; 1049 return ret; 1050 } 1051 1052 /// ditto 1053 void pureFree()(void* ptr) @system pure @nogc nothrow 1054 { 1055 version (Posix) 1056 { 1057 // POSIX free doesn't set errno 1058 fakePureFree(ptr); 1059 } 1060 else 1061 { 1062 const errnosave = fakePureErrno; 1063 fakePureFree(ptr); 1064 fakePureErrno = errnosave; 1065 } 1066 } 1067 1068 /// 1069 @system pure nothrow @nogc unittest 1070 { 1071 ubyte[] fun(size_t n) pure 1072 { 1073 void* p = pureMalloc(n); 1074 p !is null || n == 0 || assert(0); 1075 scope(failure) p = pureRealloc(p, 0); 1076 p = pureRealloc(p, n *= 2); 1077 p !is null || n == 0 || assert(0); 1078 return cast(ubyte[]) p[0 .. n]; 1079 } 1080 1081 auto buf = fun(100); 1082 assert(buf.length == 200); 1083 pureFree(buf.ptr); 1084 } 1085 1086 @system pure nothrow @nogc unittest 1087 { 1088 const int errno = fakePureErrno(); 1089 1090 void* x = pureMalloc(10); // normal allocation 1091 assert(errno == fakePureErrno()); // errno shouldn't change 1092 assert(x !is null); // allocation should succeed 1093 1094 x = pureRealloc(x, 10); // normal reallocation 1095 assert(errno == fakePureErrno()); // errno shouldn't change 1096 assert(x !is null); // allocation should succeed 1097 1098 fakePureFree(x); 1099 1100 void* y = pureCalloc(10, 1); // normal zeroed allocation 1101 assert(errno == fakePureErrno()); // errno shouldn't change 1102 assert(y !is null); // allocation should succeed 1103 1104 fakePureFree(y); 1105 1106 version (LDC_AddressSanitizer) 1107 { 1108 // Test must be disabled because ASan will report an error: requested allocation size 0xffffffffffffff00 (0x700 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 1109 } 1110 else 1111 { 1112 // Workaround bug in glibc 2.26 1113 // See also: https://issues.dlang.org/show_bug.cgi?id=17956 1114 void* z = pureMalloc(size_t.max & ~255); // won't affect `errno` 1115 assert(errno == fakePureErrno()); // errno shouldn't change 1116 } 1117 version (LDC) 1118 { 1119 // LLVM's 'Combine redundant instructions' optimization pass 1120 // completely elides allocating `y` and `z`. Allocations with 1121 // sizes > 0 are apparently assumed to always succeed (and 1122 // return non-null), so the following assert fails with -O3. 1123 } 1124 else 1125 { 1126 assert(z is null); 1127 } 1128 } 1129 1130 // locally purified for internal use here only 1131 1132 static import core.stdc.errno; 1133 static if (__traits(getOverloads, core.stdc.errno, "errno").length == 1 1134 && __traits(getLinkage, core.stdc.errno.errno) == "C") 1135 { 1136 extern(C) pragma(mangle, __traits(identifier, core.stdc.errno.errno)) 1137 private ref int fakePureErrno() @nogc nothrow pure @system; 1138 } 1139 else 1140 { 1141 extern(C) private @nogc nothrow pure @system 1142 { 1143 pragma(mangle, __traits(identifier, core.stdc.errno.getErrno)) 1144 @property int fakePureErrno(); 1145 1146 pragma(mangle, __traits(identifier, core.stdc.errno.setErrno)) 1147 @property int fakePureErrno(int); 1148 } 1149 } 1150 1151 version (D_BetterC) {} 1152 else // TODO: remove this function after Phobos no longer needs it. 1153 extern (C) private @system @nogc nothrow 1154 { 1155 ref int fakePureErrnoImpl() 1156 { 1157 import core.stdc.errno; 1158 return errno(); 1159 } 1160 } 1161 1162 extern (C) private pure @system @nogc nothrow 1163 { 1164 pragma(mangle, "malloc") void* fakePureMalloc(size_t); 1165 pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size); 1166 pragma(mangle, "realloc") void* fakePureRealloc(void* ptr, size_t size); 1167 1168 pragma(mangle, "free") void fakePureFree(void* ptr); 1169 } 1170 1171 /** 1172 Destroys and then deallocates an object. 1173 1174 In detail, `__delete(x)` returns with no effect if `x` is `null`. Otherwise, it 1175 performs the following actions in sequence: 1176 $(UL 1177 $(LI 1178 Calls the destructor `~this()` for the object referred to by `x` 1179 (if `x` is a class or interface reference) or 1180 for the object pointed to by `x` (if `x` is a pointer to a `struct`). 1181 Arrays of structs call the destructor, if defined, for each element in the array. 1182 If no destructor is defined, this step has no effect. 1183 ) 1184 $(LI 1185 Frees the memory allocated for `x`. If `x` is a reference to a class 1186 or interface, the memory allocated for the underlying instance is freed. If `x` is 1187 a pointer, the memory allocated for the pointed-to object is freed. If `x` is a 1188 built-in array, the memory allocated for the array is freed. 1189 If `x` does not refer to memory previously allocated with `new` (or the lower-level 1190 equivalents in the GC API), the behavior is undefined. 1191 ) 1192 $(LI 1193 Lastly, `x` is set to `null`. Any attempt to read or write the freed memory via 1194 other references will result in undefined behavior. 1195 ) 1196 ) 1197 1198 Note: Users should prefer $(REF1 destroy, object) to explicitly finalize objects, 1199 and only resort to $(REF __delete, core,memory) when $(REF destroy, object) 1200 wouldn't be a feasible option. 1201 1202 Params: 1203 x = aggregate object that should be destroyed 1204 1205 See_Also: $(REF1 destroy, object), $(REF free, core,GC) 1206 1207 History: 1208 1209 The `delete` keyword allowed to free GC-allocated memory. 1210 As this is inherently not `@safe`, it has been deprecated. 1211 This function has been added to provide an easy transition from `delete`. 1212 It performs the same functionality as the former `delete` keyword. 1213 */ 1214 void __delete(T)(ref T x) @system 1215 { 1216 static void _destructRecurse(S)(ref S s) 1217 if (is(S == struct)) 1218 { 1219 static if (__traits(hasMember, S, "__xdtor") && 1220 // Bugzilla 14746: Check that it's the exact member of S. 1221 __traits(isSame, S, __traits(parent, s.__xdtor))) 1222 s.__xdtor(); 1223 } 1224 1225 // See also: https://github.com/dlang/dmd/blob/v2.078.0/src/dmd/e2ir.d#L3886 1226 static if (is(T == interface)) 1227 { 1228 .object.destroy(x); 1229 } 1230 else static if (is(T == class)) 1231 { 1232 .object.destroy(x); 1233 } 1234 else static if (is(T == U*, U)) 1235 { 1236 static if (is(U == struct)) 1237 { 1238 if (x) 1239 _destructRecurse(*x); 1240 } 1241 } 1242 else static if (is(T : E[], E)) 1243 { 1244 static if (is(E == struct)) 1245 { 1246 foreach_reverse (ref e; x) 1247 _destructRecurse(e); 1248 } 1249 } 1250 else 1251 { 1252 static assert(0, "It is not possible to delete: `" ~ T.stringof ~ "`"); 1253 } 1254 1255 static if (is(T == interface) || 1256 is(T == class) || 1257 is(T == U2*, U2)) 1258 { 1259 GC.free(GC.addrOf(cast(void*) x)); 1260 x = null; 1261 } 1262 else static if (is(T : E2[], E2)) 1263 { 1264 GC.free(GC.addrOf(cast(void*) x.ptr)); 1265 x = null; 1266 } 1267 } 1268 1269 /// Deleting classes 1270 unittest 1271 { 1272 bool dtorCalled; 1273 class B 1274 { 1275 int test; 1276 ~this() 1277 { 1278 dtorCalled = true; 1279 } 1280 } 1281 B b = new B(); 1282 B a = b; 1283 b.test = 10; 1284 1285 assert(GC.addrOf(cast(void*) b) != null); 1286 __delete(b); 1287 assert(b is null); 1288 assert(dtorCalled); 1289 assert(GC.addrOf(cast(void*) b) == null); 1290 // but be careful, a still points to it 1291 assert(a !is null); 1292 assert(GC.addrOf(cast(void*) a) == null); // but not a valid GC pointer 1293 } 1294 1295 /// Deleting interfaces 1296 unittest 1297 { 1298 bool dtorCalled; 1299 interface A 1300 { 1301 int quack(); 1302 } 1303 class B : A 1304 { 1305 int a; 1306 int quack() 1307 { 1308 a++; 1309 return a; 1310 } 1311 ~this() 1312 { 1313 dtorCalled = true; 1314 } 1315 } 1316 A a = new B(); 1317 a.quack(); 1318 1319 assert(GC.addrOf(cast(void*) a) != null); 1320 __delete(a); 1321 assert(a is null); 1322 assert(dtorCalled); 1323 assert(GC.addrOf(cast(void*) a) == null); 1324 } 1325 1326 /// Deleting structs 1327 unittest 1328 { 1329 bool dtorCalled; 1330 struct A 1331 { 1332 string test; 1333 ~this() 1334 { 1335 dtorCalled = true; 1336 } 1337 } 1338 auto a = new A("foo"); 1339 1340 assert(GC.addrOf(cast(void*) a) != null); 1341 __delete(a); 1342 assert(a is null); 1343 assert(dtorCalled); 1344 assert(GC.addrOf(cast(void*) a) == null); 1345 1346 // https://issues.dlang.org/show_bug.cgi?id=22779 1347 A *aptr; 1348 __delete(aptr); 1349 } 1350 1351 /// Deleting arrays 1352 unittest 1353 { 1354 int[] a = [1, 2, 3]; 1355 auto b = a; 1356 1357 assert(GC.addrOf(b.ptr) != null); 1358 __delete(b); 1359 assert(b is null); 1360 assert(GC.addrOf(b.ptr) == null); 1361 // but be careful, a still points to it 1362 assert(a !is null); 1363 assert(GC.addrOf(a.ptr) == null); // but not a valid GC pointer 1364 } 1365 1366 /// Deleting arrays of structs 1367 unittest 1368 { 1369 int dtorCalled; 1370 struct A 1371 { 1372 int a; 1373 ~this() 1374 { 1375 assert(dtorCalled == a); 1376 dtorCalled++; 1377 } 1378 } 1379 auto arr = [A(1), A(2), A(3)]; 1380 arr[0].a = 2; 1381 arr[1].a = 1; 1382 arr[2].a = 0; 1383 1384 assert(GC.addrOf(arr.ptr) != null); 1385 __delete(arr); 1386 assert(dtorCalled == 3); 1387 assert(GC.addrOf(arr.ptr) == null); 1388 } 1389 1390 // Deleting raw memory 1391 unittest 1392 { 1393 import core.memory : GC; 1394 auto a = GC.malloc(5); 1395 assert(GC.addrOf(cast(void*) a) != null); 1396 __delete(a); 1397 assert(a is null); 1398 assert(GC.addrOf(cast(void*) a) == null); 1399 } 1400 1401 // __delete returns with no effect if x is null 1402 unittest 1403 { 1404 Object x = null; 1405 __delete(x); 1406 1407 struct S { ~this() { } } 1408 class C { } 1409 interface I { } 1410 1411 int[] a; __delete(a); 1412 S[] as; __delete(as); 1413 C c; __delete(c); 1414 I i; __delete(i); 1415 C* pc = &c; __delete(*pc); 1416 I* pi = &i; __delete(*pi); 1417 int* pint; __delete(pint); 1418 S* ps; __delete(ps); 1419 } 1420 1421 // https://issues.dlang.org/show_bug.cgi?id=19092 1422 unittest 1423 { 1424 const(int)[] x = [1, 2, 3]; 1425 assert(GC.addrOf(x.ptr) != null); 1426 __delete(x); 1427 assert(x is null); 1428 assert(GC.addrOf(x.ptr) == null); 1429 1430 immutable(int)[] y = [1, 2, 3]; 1431 assert(GC.addrOf(y.ptr) != null); 1432 __delete(y); 1433 assert(y is null); 1434 assert(GC.addrOf(y.ptr) == null); 1435 } 1436 1437 // test realloc behaviour 1438 unittest 1439 { 1440 static void set(int* p, size_t size) 1441 { 1442 foreach (i; 0 .. size) 1443 *p++ = cast(int) i; 1444 } 1445 static void verify(int* p, size_t size) 1446 { 1447 foreach (i; 0 .. size) 1448 assert(*p++ == i); 1449 } 1450 static void test(size_t memsize) 1451 { 1452 int* p = cast(int*) GC.malloc(memsize * int.sizeof); 1453 assert(p); 1454 set(p, memsize); 1455 verify(p, memsize); 1456 1457 int* q = cast(int*) GC.realloc(p + 4, 2 * memsize * int.sizeof); 1458 assert(q == null); 1459 1460 q = cast(int*) GC.realloc(p + memsize / 2, 2 * memsize * int.sizeof); 1461 assert(q == null); 1462 1463 q = cast(int*) GC.realloc(p + memsize - 1, 2 * memsize * int.sizeof); 1464 assert(q == null); 1465 1466 int* r = cast(int*) GC.realloc(p, 5 * memsize * int.sizeof); 1467 verify(r, memsize); 1468 set(r, 5 * memsize); 1469 1470 int* s = cast(int*) GC.realloc(r, 2 * memsize * int.sizeof); 1471 verify(s, 2 * memsize); 1472 1473 assert(GC.realloc(s, 0) == null); // free 1474 assert(GC.addrOf(p) == null); 1475 } 1476 1477 test(16); 1478 test(200); 1479 test(800); // spans large and small pools 1480 test(1200); 1481 test(8000); 1482 1483 void* p = GC.malloc(100); 1484 assert(GC.realloc(&p, 50) == null); // non-GC pointer 1485 } 1486 1487 // test GC.profileStats 1488 unittest 1489 { 1490 auto stats = GC.profileStats(); 1491 GC.collect(); 1492 auto nstats = GC.profileStats(); 1493 assert(nstats.numCollections > stats.numCollections); 1494 } 1495 1496 // in rt.lifetime: 1497 private extern (C) void* _d_newitemU(scope const TypeInfo _ti) @system pure nothrow; 1498 1499 /** 1500 Moves a value to a new GC allocation. 1501 1502 Params: 1503 value = Value to be moved. If the argument is an lvalue and a struct with a 1504 destructor or postblit, it will be reset to its `.init` value. 1505 1506 Returns: 1507 A pointer to the new GC-allocated value. 1508 */ 1509 T* moveToGC(T)(auto ref T value) 1510 { 1511 static T* doIt(ref T value) @trusted 1512 { 1513 import core.lifetime : moveEmplace; 1514 auto mem = cast(T*) _d_newitemU(typeid(T)); // allocate but don't initialize 1515 moveEmplace(value, *mem); 1516 return mem; 1517 } 1518 1519 return doIt(value); // T dtor might be @system 1520 } 1521 1522 /// 1523 @safe pure nothrow unittest 1524 { 1525 struct S 1526 { 1527 int x; 1528 this(this) @disable; 1529 ~this() @safe pure nothrow @nogc {} 1530 } 1531 1532 S* p; 1533 1534 // rvalue 1535 p = moveToGC(S(123)); 1536 assert(p.x == 123); 1537 1538 // lvalue 1539 auto lval = S(456); 1540 p = moveToGC(lval); 1541 assert(p.x == 456); 1542 assert(lval.x == 0); 1543 } 1544 1545 // @system dtor 1546 unittest 1547 { 1548 struct S 1549 { 1550 int x; 1551 ~this() @system {} 1552 } 1553 1554 // lvalue case is @safe, ref param isn't destructed 1555 static assert(__traits(compiles, (ref S lval) @safe { moveToGC(lval); })); 1556 1557 // rvalue case is @system, value param is destructed 1558 static assert(!__traits(compiles, () @safe { moveToGC(S(0)); })); 1559 }