llvm.org GIT mirror llvm / 326e24f
GarbageCollection.html is expanded to encompass the coming capabilities. This is a major rewrite and is easier to read en toto rather than patchwise. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42414 91177308-0d34-0410-b5e6-96231b3b80d8 Gordon Henriksen 11 years ago
4 changed file(s) with 1227 addition(s) and 298 deletion(s). Raw diff Collapse all Expand all
11 "http://www.w3.org/TR/html4/strict.dtd">
22
33
4
45 Accurate Garbage Collection with LLVM
56
7
612
713
814
1319
1420
  • Introduction
  • 1521
    16
  • GC features provided and algorithms supported
  • 22
  • GC features provided and algorithms
  • 23 supported
    1724
    1825
    1926
    20
  • Interfaces for user programs
  • 27
  • Using the collectors
  • 2128
    22
  • Identifying GC roots on the stack: llvm.gcroot
  • 23
  • Allocating memory from the GC
  • 24
  • Reading and writing references to the heap
  • 25
  • Explicit invocation of the garbage collector
  • 29
  • ShadowStack -
  • 30 A highly portable collector
    31
  • SemiSpace -
  • 32 A simple copying collector runtime
    33
  • Ocaml -
  • 34 An Objective Caml-compatible collector
    2635
    2736
    2837
    29
  • Implementing a garbage collector
  • 38
  • Collection intrinsics
  • 3039
    31
  • Implementing llvm_gc_read and llvm_gc_write
  • 32
  • Callback functions used to implement the garbage collector
  • 40
  • Identifying GC roots on the stack:
  • 41 llvm.gcroot
    42
  • Reading and writing references in the heap
  • 43
    44
  • Write barrier: llvm.gcwrite
  • 45
  • Read barrier: llvm.gcread
  • 46
    47
    3348
    3449
    35
  • GC implementations available
  • 50
    51
  • Recommended runtime interface
  • 3652
    37
  • SemiSpace - A simple copying garbage collector
  • 53
  • Garbage collector startup and
  • 54 initialization
    55
  • Allocating memory from the GC
  • 56
  • Explicit invocation of the garbage
  • 57 collector
    58
  • Tracing GC pointers from the program
  • 59 stack
    60
  • Tracing GC pointers from static roots
  • 3861
    3962
    4063
    41
    56101
    57102
    58103

    Garbage collection is a widely used technique that frees the programmer from

    59 having to know the life-times of heap objects, making software easier to produce
    60 and maintain. Many programming languages rely on garbage collection for
    61 automatic memory management. There are two primary forms of garbage collection:
    104 having to know the lifetimes of heap objects, making software easier to produce
    105 and maintain. Many programming languages rely on garbage collection for
    106 automatic memory management. There are two primary forms of garbage collection:
    62107 conservative and accurate.

    63108
    64109

    Conservative garbage collection often does not require any special support

    65110 from either the language or the compiler: it can handle non-type-safe
    66111 programming languages (such as C/C++) and does not require any special
    67 information from the compiler. The
    112 information from the compiler. The
    68113 Boehm collector is
    69114 an example of a state-of-the-art conservative collector.

    70115
    71116

    Accurate garbage collection requires the ability to identify all pointers in

    72117 the program at run-time (which requires that the source-language be type-safe in
    73 most cases). Identifying pointers at run-time requires compiler support to
    118 most cases). Identifying pointers at run-time requires compiler support to
    74119 locate all places that hold live pointer variables at run-time, including the
    75 processor stack and registers.

    76
    77

    78 Conservative garbage collection is attractive because it does not require any
    79 special compiler support, but it does have problems. In particular, because the
    120 processor stack and registers.

    121
    122

    Conservative garbage collection is attractive because it does not require any

    123 special compiler support, but it does have problems. In particular, because the
    80124 conservative garbage collector cannot know that a particular word in the
    81125 machine is a pointer, it cannot move live objects in the heap (preventing the
    82126 use of compacting and generational GC algorithms) and it can occasionally suffer
    83127 from memory leaks due to integer values that happen to point to objects in the
    84 program. In addition, some aggressive compiler transformations can break
    85 conservative garbage collectors (though these seem rare in practice).
    86

    87
    88

    89 Accurate garbage collectors do not suffer from any of these problems, but they
    90 can suffer from degraded scalar optimization of the program. In particular,
    128 program. In addition, some aggressive compiler transformations can break
    129 conservative garbage collectors (though these seem rare in practice).

    130
    131

    Accurate garbage collectors do not suffer from any of these problems, but

    132 they can suffer from degraded scalar optimization of the program. In particular,
    91133 because the runtime must be able to identify and update all pointers active in
    92 the program, some optimizations are less effective. In practice, however, the
    134 the program, some optimizations are less effective. In practice, however, the
    93135 locality and performance benefits of using aggressive garbage allocation
    94 techniques dominates any low-level losses.
    95

    96
    97

    98 This document describes the mechanisms and interfaces provided by LLVM to
    99 support accurate garbage collection.
    100

    136 techniques dominates any low-level losses.

    137
    138

    This document describes the mechanisms and interfaces provided by LLVM to

    139 support accurate garbage collection.

    101140
    102141
    103142
    108147
    109148
    110149
    111

    112 LLVM provides support for a broad class of garbage collection algorithms,
    113 including compacting semi-space collectors, mark-sweep collectors, generational
    114 collectors, and even reference counting implementations. It includes support
    115 for read and write barriers, and associating
    116 href="#roots">meta-data with stack objects (used for tagless garbage
    117 collection). All LLVM code generators support garbage collection, including the
    118 C backend.
    119

    120
    121

    122 We hope that the primitive support built into LLVM is sufficient to support a
    123 broad class of garbage collected languages, including Scheme, ML, scripting
    124 languages, Java, C#, etc. That said, the implemented garbage collectors may
    125 need to be extended to support language-specific features such as finalization,
    126 weak references, or other features. As these needs are identified and
    127 implemented, they should be added to this specification.
    128

    129
    130

    131 LLVM does not currently support garbage collection of multi-threaded programs or
    132 GC-safe points other than function calls, but these will be added in the future
    133 as there is interest.
    134 </p>
    150 <p>LLVM's intermediate representation provides garbage
    151 collection intrinsics which offer support for a broad class of
    152 collector models. For instance, the intrinsics permit:

    153
    154
    155
  • semi-space collectors
  • 156
  • mark-sweep collectors
  • 157
  • generational collectors
  • 158
  • reference counting
  • 159
  • incremental collectors
  • 160
  • concurrent collectors
  • 161
  • cooperative collectors
  • 162
    163
    164

    We hope that the primitive support built into the LLVM IR is sufficient to

    165 support a broad class of garbage collected languages including Scheme, ML, Java,
    166 C#, Perl, Python, Lua, Ruby, other scripting languages, and more.

    167
    168

    However, LLVM does not itself implement a garbage collector. This is because

    169 collectors are tightly coupled to object models, and LLVM is agnostic to object
    170 models. Since LLVM is agnostic to object models, it would be inappropriate for
    171 LLVM to dictate any particular collector. Instead, LLVM provides a framework for
    172 garbage collector implementations in two manners:

    173
    174
    175
  • At compile time with collector plugins for
  • 176 the compiler. Collector plugins have ready access to important garbage
    177 collector algorithms. Leveraging these tools, it is straightforward to
    178 emit type-accurate stack maps for your runtime in as little as ~100 lines of
    179 C++ code.
    180
    181
  • At runtime with suggested runtime
  • 182 interfaces, which allow front-end compilers to support a range of
    183 collection runtimes.
    184
    135185
    136186
    137187
    138188
    139189
    140 Interfaces for user programs
    141
    142
    143
    144
    145
    146

    This section describes the interfaces provided by LLVM and by the garbage

    147 collector run-time that should be used by user programs. As such, this is the
    148 interface that front-end authors should generate code for.
    149

    150
    151
    152
    153
    154
    155 Identifying GC roots on the stack: llvm.gcroot
    156
    157
    158
    >
    190 Using the collectors>
    191
    192
    193
    194
    195
    196

    In general, using a collector implies:

    197
    198
    199
  • Emitting compatible code, including initialization in the main
  • 200 program.
    201
  • Loading a compiler plugin if the collector is not statically linked with
  • 202 your compiler. For llc, use the -load option.
    203
  • Selecting the collection algorithm with llc -gc= or by setting
  • 204 llvm::TheCollector.
    205
  • Linking your final executable with the garbage collector runtime.
  • 206
    207
    208

    This table summarizes the available runtimes.

    209
    210
    211
    212 Collector
    213 llc arguments
    214 Linkage
    215 gcroot
    216 gcread
    217 gcwrite
    218
    219
    220 SemiSpace
    221 -gc=shadow-stack
    222 TODO FIXME
    223 required
    224 optional
    225 optional
    226
    227
    228 Ocaml
    229 -gc=ocaml
    230 provided by ocamlopt
    231 required
    232 optional
    233 optional
    234
    235
    236
    237

    The sections for Collection intrinsics and

    238 Recommended runtime interface detail the interfaces that
    239 collectors may require user programs to utilize.

    240
    241
    242
    243
    244
    245 ShadowStack - A highly portable collector
    246
    247
    248
    249 Collector *llvm::createShadowStackCollector();
    250
    251
    252
    253
    254

    The ShadowStack collector is invoked with llc -gc=shadow-stack.

    255 Unlike many collectors which rely on a cooperative code generator to generate
    256 stack maps, this algorithm carefully maintains a linked list of stack root
    257 descriptors [Henderson2002]. This so-called "shadow
    258 stack," mirrors the machine stack. Maintaining this data structure is slower
    259 than using stack maps, but has a significant portability advantage because it
    260 requires no special support from the target code generator.

    261
    262

    The ShadowStack collector does not use read or write barriers, so the user

    263 program may use load and store instead of llvm.gcread
    264 and llvm.gcwrite.

    265
    266

    The ShadowStack collector is a compiler plugin only. It must be paired with a

    267 compatible runtime.

    268
    269
    270
    271
    272
    273 SemiSpace - A simple copying collector runtime
    274
    275
    276
    277
    278

    The SemiSpace runtime implements with the suggested

    279 runtime interface and is compatible the ShadowStack collector's code
    280 generation.

    281
    282

    SemiSpace is a very simple copying collector. When it starts up, it

    283 allocates two blocks of memory for the heap. It uses a simple bump-pointer
    284 allocator to allocate memory from the first block until it runs out of space.
    285 When it runs out of space, it traces through all of the roots of the program,
    286 copying blocks to the other half of the memory space.

    287
    288

    This runtime is highly experimental and has not been used in a real project.

    289 Enhancements would be welcomed.

    290
    291
    292
    293
    294
    295 Ocaml - An Objective Caml-compatible collector
    296
    297
    298
    299 Collector *llvm::createOcamlCollector();
    300
    301
    302
    303
    304

    The ocaml collector is invoked with llc -gc=ocaml. It supports the

    305 Objective Caml language runtime by emitting
    306 a type-accurate stack map in the form of an ocaml 3.10.0-compatible frametable.
    307 The linkage requirements are satisfied automatically by the ocamlopt
    308 compiler when linking an executable.

    309
    310

    The ocaml collector does not use read or write barriers, so the user program

    311 may use load and store instead of llvm.gcread and
    312 llvm.gcwrite.

    313
    314
    315
    316
    317
    318
    319 Collection intrinsics
    320
    321
    322
    323
    324
    325

    This section describes the garbage collection facilities provided by the

    326 LLVM intermediate representation.

    327
    328

    These facilities are limited to those strictly necessary for compilation.

    329 They are not intended to be a complete interface to any garbage collector.
    330 Notably, heap allocation is not among the supplied primitives. A user program
    331 will also need to interface with the runtime, using either the
    332 suggested runtime interface or another interface
    333 specified by the runtime.

    334
    335
    336
    337
    338
    339 Identifying GC roots on the stack: llvm.gcroot
    340
    159341
    160342
    161343 void %llvm.gcroot(i8** %ptrloc, i8* %metadata)
    162344
    163345
    164

    165 The llvm.gcroot intrinsic is used to inform LLVM of a pointer variable
    166 on the stack. The first argument contains the address of the variable on the
    167 stack, and the second contains a pointer to metadata that should be associated
    168 with the pointer (which must be a constant or global value address).

    169
    170

    171 Consider the following fragment of Java code:
    172 </p>
    346 <div class="doc_text">
    347
    348

    The llvm.gcroot intrinsic is used to inform LLVM of a pointer

    349 variable on the stack. The first argument must be an alloca instruction
    350 or a bitcast of an alloca. The second contains a pointer to metadata that
    351 should be associated with the pointer, and must be a constant or global
    352 value address. If your target collector uses tags, use a null pointer for
    353 metadata.

    354
    355

    Consider the following fragment of Java code:

    173356
    174357
    
                      
                    
    175358 {
    178361 }
    179362
    180363
    181

    182 This block (which may be located in the middle of a function or in a loop nest),
    183 could be compiled to this LLVM code:
    184 </p>
    364 <p>This block (which may be located in the middle of a function or in a loop
    365 nest), could be compiled to this LLVM code:

    185366
    186367
    
                      
                    
    187368 Entry:
    188369 ;; In the entry block for the function, allocate the
    189370 ;; stack space for X, which is an LLVM pointer.
    190371 %X = alloca %Object*
    372
    373 ;; Tell LLVM that the stack space is a stack root.
    374 ;; Java has type-tags on objects, so we pass null as metadata.
    375 %tmp = bitcast %Object** %X to i8**
    376 call void %llvm.gcroot(%i8** %X, i8* null)
    191377 ...
    192
    193 ;; Java null-initializes pointers.
    194 store %Object* null, %Object** %X
    195378
    196379 ;; "CodeBlock" is the block corresponding to the start
    197380 ;; of the scope above.
    198381 CodeBlock:
    199 ;; Initialize the object, telling LLVM that it is now live.
    200 ;; Java has type-tags on objects, so it doesn't need any
    201 ;; metadata.
    202 %tmp = bitcast %Object** %X to i8**
    203 call void %llvm.gcroot(i8** %tmp, i8* null)
    382 ;; Java null-initializes pointers.
    383 store %Object* null, %Object** %X
    384
    204385 ...
    205386
    206387 ;; As the pointer goes out of scope, store a null value into
    213394
    214395
    215396
    216 Allocating memory from the GC
    217
    218
    219
    >
    397 Reading and writing references in the heap>
    398
    399
    400
    401
    402

    Some collectors need to be informed when the mutator (the program that needs

    403 garbage collection) either reads a pointer from or writes a pointer to a field
    404 of a heap object. The code fragments inserted at these points are called
    405 read barriers and write barriers, respectively. The amount of
    406 code that needs to be executed is usually quite small and not on the critical
    407 path of any computation, so the overall performance impact of the barrier is
    408 tolerable.

    409
    410

    Barriers often require access to the object pointer rather than the

    411 derived pointer (which is a pointer to the field within the
    412 object). Accordingly, these intrinsics take both pointers as separate arguments
    413 for completeness. In this snippet, %object is the object pointer, and
    414 %derived is the derived pointer:

    415
    416
                      
                    
    417 > ;; An array type.
    418 %class.Array = type { %class.Object, i32, [0 x %class.Object*] }
    419 ...
    420
    421 ;; Load the object pointer from a gcroot.
    422 %object = load %class.Array** %object_addr
    423
    424 ;; Compute the derived pointer.
    425 %derived = getelementptr %obj, i32 0, i32 2, i32 %n
    426
    427
    428
    429
    430
    431 Write barrier: llvm.gcwrite
    432
    220433
    221434
    222 void *llvm_gc_allocate(unsigned Size)
    435 void @llvm.gcwrite(i8* %value, i8* %object, i8** %derived)
    223436
    224437
    225

    The llvm_gc_allocate function is a global function defined by the

    226 garbage collector implementation to allocate memory. It returns a
    227 zeroed-out block of memory of the appropriate size.

    228
    229
    230
    231
    232
    233 Reading and writing references to the heap
    234
    235
    236
    438
    439
    440

    For write barriers, LLVM provides the llvm.gcwrite intrinsic

    441 function. It has exactly the same semantics as a non-volatile store to
    442 the derived pointer (the third argument).

    443
    444

    Many important algorithms require write barriers, including generational

    445 and concurrent collectors. Additionally, write barriers could be used to
    446 implement reference counting.

    447
    448

    The use of this intrinsic is optional if the target collector does use

    449 write barriers. If so, the collector will replace it with the corresponding
    450 store.

    451
    452
    453
    454
    455
    456 Read barrier: llvm.gcread
    457
    237458
    238459
    239 i8 *%llvm.gcread(i8 *, i8 **)
    240 void %llvm.gcwrite(i8*, i8*, i8**)
    460 i8* @llvm.gcread(i8* %object, i8** %derived)
    241461
    242462
    243

    Several of the more interesting garbage collectors (e.g., generational

    244 collectors) need to be informed when the mutator (the program that needs garbage
    245 collection) reads or writes object references into the heap. In the case of a
    246 generational collector, it needs to keep track of which "old" generation objects
    247 have references stored into them. The amount of code that typically needs to be
    248 executed is usually quite small (and not on the critical path of any
    249 computation), so the overall performance impact of the inserted code is
    250 tolerable.

    251
    252

    To support garbage collectors that use read or write barriers, LLVM provides

    253 the llvm.gcread and llvm.gcwrite intrinsics. The first
    254 intrinsic has exactly the same semantics as a non-volatile LLVM load and the
    255 second has the same semantics as a non-volatile LLVM store, with the
    256 additions that they also take a pointer to the start of the memory
    257 object as an argument. At code generation
    258 time, these intrinsics are replaced with calls into the garbage collector
    259 (llvm_gc_read and
    260 href="#llvm_gc_readwrite">llvm_gc_write respectively), which are then
    261 inlined into the code.
    262

    263
    264

    265 If you are writing a front-end for a garbage collected language, every load or
    266 store of a reference from or to the heap should use these intrinsics instead of
    267 normal LLVM loads/stores.>
    463
    >
    464
    465

    For read barriers, LLVM provides the llvm.gcread intrinsic function.

    466 It has exactly the same semantics as a non-volatile load from the
    467 derived pointer (the second argument).

    468
    469

    Read barriers are needed by fewer algorithms than write barriers, and may

    470 have a greater performance impact since pointer reads are more frequent than
    471 writes.

    472
    473

    As with llvm.gcwrite, a target collector might not require the use

    474 of this intrinsic.

    475
    476
    477
    478
    479
    480 Recommended runtime interface
    481
    482
    483
    484
    485
    486

    LLVM specifies the following recommended runtime interface to the garbage

    487 collection at runtime. A program should use these interfaces to accomplish the
    488 tasks not supported by the intrinsics.

    489
    490

    Unlike the intrinsics, which are integral to LLVM's code generator, there is

    491 nothing unique about these interfaces; a front-end compiler and runtime are free
    492 to agree to a different specification.

    493
    494

    Note: This interface is a work in progress.

    268495
    269496
    270497
    276503
    277504
    278505
    279 void %llvm_gc_initialize(unsigned %InitialHeapSize)
    506 void llvm_gc_initialize(unsigned InitialHeapSize);
    280507
    281508
    282509

    283510 The llvm_gc_initialize function should be called once before any other
    284 garbage collection functions are called. This gives the garbage collector the
    285 chance to initialize itself and allocate the heap spaces. The initial heap size
    286 to allocate should be specified as an argument.
    511 garbage collection functions are called. This gives the garbage collector the
    512 chance to initialize itself and allocate the heap. The initial heap size to
    513 allocate should be specified as an argument.
    287514

    288515
    289516
    290517
    291518
    292519
    520 Allocating memory from the GC
    521
    522
    523
    524
    525
    526 void *llvm_gc_allocate(unsigned Size);
    527
    528
    529

    The llvm_gc_allocate function is a global function defined by the

    530 garbage collector implementation to allocate memory. It returns a
    531 zeroed-out block of memory of the specified size, sufficiently aligned to store
    532 any object.

    533
    534
    535
    536
    537
    293538 Explicit invocation of the garbage collector
    294539
    295540
    296541
    297542
    298543
    299 void %llvm_gc_collect()
    544 void llvm_gc_collect();
    300545
    301546
    302547

    303548 The llvm_gc_collect function is exported by the garbage collector
    304549 implementations to provide a full collection, even when the heap is not
    305 exhausted. This can be used by end-user code as a hint, and may be ignored by
    550 exhausted. This can be used by end-user code as a hint, and may be ignored by
    306551 the garbage collector.
    307552

    308553
    309554
    310555
    311
    312
    313
    314 Implementing a garbage collector
    315
    316
    317
    318
    319
    320

    321 Implementing a garbage collector for LLVM is fairly straight-forward. The LLVM
    322 garbage collectors are provided in a form that makes them easy to link into the
    323 language-specific runtime that a language front-end would use. They require
    324 functionality from the language-specific runtime to get information about
    325 href="#gcdescriptors">where pointers are located in heap objects.
    326

    327
    328

    The

    329 implementation must include the
    330 href="#allocate">llvm_gc_allocate and
    331 href="#explicit">llvm_gc_collect functions, and it must implement
    332 the read/write barrier functions as well. To
    333 do this, it will probably have to trace through the roots
    334 from the stack and understand the GC descriptors
    335 for heap objects. Luckily, there are some example
    336 implementations available.
    337

    338
    339
    340
    341
    342
    343 Implementing llvm_gc_read and llvm_gc_write
    344
    345
    346
    347
    348 void *llvm_gc_read(void*, void **)
    349 void llvm_gc_write(void*, void *, void**)
    350
    351
    352

    353 These functions must be implemented in every garbage collector, even if
    354 they do not need read/write barriers. In this case, just load or store the
    355 pointer, then return.
    356

    357
    358

    359 If an actual read or write barrier is needed, it should be straight-forward to
    360 implement it.
    361

    362
    363
    364
    365
    366
    367 Callback functions used to implement the garbage collector
    368
    369
    370
    371

    372 Garbage collector implementations make use of call-back functions that are
    373 implemented by other parts of the LLVM system.
    374

    375
    376
    377
    378 <div class="doc_subsubsection">
    556 <!-- ======================================================================= -->
    557
    379558 Tracing GC pointers from the program stack
    380559
    381560
    387566

    388567 The llvm_cg_walk_gcroots function is a function provided by the code
    389568 generator that iterates through all of the GC roots on the stack, calling the
    390 specified function pointer with each record. For each GC root, the address of
    569 specified function pointer with each record. For each GC root, the address of
    391570 the pointer and the meta-data (from the
    392571 href="#roots">llvm.gcroot intrinsic) are provided.
    393572

    394573
    395574
    396
    397 <div class="doc_subsubsection">
    575 <!-- ======================================================================= -->
    576
    398577 Tracing GC pointers from static roots
    399578
    400579
    403582
    404583
    405584
    406
    407 <div class="doc_subsubsection">
    585 <!-- *********************************************************************** -->
    586
    587 Implementing a collector plugin
    588
    589
    590
    591
    592
    593

    To implement a collector plugin, it is necessary to subclass

    594 llvm::Collector, which can be accomplished in a few lines of
    595 boilerplate code. LLVM's infrastructure provides access to several important
    596 algorithms. For an uncontroversial collector, all that remains may be to emit
    597 the assembly code for the collector's unique stack map data structure, which
    598 might be accomplished in as few as 100 LOC.

    599
    600

    To subclass llvm::Collector and register a collector:

    601
    602
    // lib/MyGC/MyGC.cpp - Example LLVM collector plugin
    
                      
                    
    603
    604 #include "llvm/CodeGen/Collector.h"
    605 #include "llvm/CodeGen/Collectors.h"
    606 #include "llvm/CodeGen/CollectorMetadata.h"
    607 #include "llvm/Support/Compiler.h"
    608
    609 using namespace llvm;
    610
    611 namespace {
    612 class VISIBILITY_HIDDEN MyCollector : public Collector {
    613 public:
    614 MyCollector() {}
    615 };
    616
    617 CollectorRegistry::Add<MyCollector>
    618 X("mygc", "My custom garbage collector.");
    619 }
    620
    621

    Using the LLVM makefiles (like the

    622 href="http://llvm.org/viewvc/llvm-project/llvm/trunk/projects/sample/">sample
    623 project), this can be built into a plugin using a simple makefile:

    624
    625
                      
                    
    626 ># lib/MyGC/Makefile
    627
    628 LEVEL := ../..
    629 LIBRARYNAME = MyGC
    630 LOADABLE_MODULE = 1
    631
    632 include $(LEVEL)/Makefile.common
    633
    634
                      
                    
    635 >
    636
    637

    Once the plugin is compiled, user code may be compiled using llc

    638 -load=MyGC.so -gc=mygc (though MyGC.so may have some
    639 other platform-specific extension).

    640
    641
    642

    To use a collector in a tool other than llc, simply assign a

    643 Collector to the llvm::TheCollector variable:

    644
    645
                      
                    
    646 >TheCollector = new MyGC();
    647
    648
    649
    650
    651
    652
    653 Overview of available features
    654
    655
    656
    657
    658

    The boilerplate collector above does nothing. More specifically:

    659
    660
    661
  • llvm.gcread calls are replaced with the corresponding
  • 662 load instruction.
    663
  • llvm.gcwrite calls are replaced with the corresponding
  • 664 store instruction.
    665
  • No stack map is emitted, and no safe points are added.
  • 666
    667
    668

    Collector provides a range of features through which a plugin

    669 collector may do useful work. This matrix summarizes the supported (and planned)
    670 features and correlates them with the collection techniques which typically
    671 require them.

    672
    673
    674
    675 Algorithm
    676 Done
    677 shadow stack
    678 refcount
    679 mark-sweep
    680 copying
    681 incremental
    682 threaded
    683 concurrent
    684
    685
    686 stack map
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697 initialize roots
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708 derived pointers
    709 NO
    710
    711
    712
    713
    714
    715 ✘*
    716 ✘*
    717
    718
    719 custom lowering
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730 gcroot
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741 gcwrite
    742
    743
    744
    745
    746
    747
    748
    749
    750
    751
    752 gcread
    753
    754
    755
    756
    757
    758
    759
    760
    761
    762
    763 safe points
    764
    765
    766
    767
    768
    769
    770
    771
    772
    773
    774 in calls
    775
    776
    777
    778
    779
    780
    781
    782
    783
    784
    785 before calls
    786
    787
    788
    789
    790
    791
    792
    793
    794
    795
    796 for loops
    797 NO
    798
    799
    800
    801
    802
    803
    804
    805
    806
    807 before escape
    808
    809
    810
    811
    812
    813
    814
    815
    816
    817
    818 emit code at safe points
    819 NO
    820
    821
    822
    823
    824
    825
    826
    827
    828
    829 output
    830
    831
    832
    833
    834
    835
    836
    837
    838
    839
    840 assembly
    841
    842
    843
    844
    845
    846
    847
    848
    849
    850
    851 JIT
    852 NO
    853
    854
    855
    856
    857
    858
    859
    860
    861
    862 obj
    863 NO
    864
    865
    866
    867
    868
    869
    870
    871
    872
    873 live analysis
    874 NO
    875
    876
    877
    878
    879
    880
    881
    882
    883
    884 register map
    885 NO
    886
    887
    888
    889
    890
    891
    892
    893
    894
    895
    896
    * Derived pointers only pose a
    897 hazard to copying collectors.
    898
    in gray denotes a feature which
    899 could be utilized if available.
    900
    901
    902
    903
    904

    To be clear, the collection techniques above are defined as:

    905
    906
    907
    Shadow Stack
    908
    The mutator carefully maintains a linked list of stack root
    909 descriptors.
    910
    Reference Counting
    911
    The mutator maintains a reference count for each object and frees an
    912 object when its count falls to zero.
    913
    Mark-Sweep
    914
    When the heap is exhausted, the collector marks reachable objects starting
    915 from the roots, then deallocates unreachable objects in a sweep
    916 phase.
    917
    Copying
    918
    As reachability analysis proceeds, the collector copies objects from one
    919 heap area to another, compacting them in the process. Copying collectors
    920 enable highly efficient "bump pointer" allocation and can improve locality
    921 of reference.
    922
    Incremental
    923
    (Including generational collectors.) Incremental collectors generally have
    924 all the properties of a copying collector (regardless of whether the
    925 mature heap is compacting), but bring the added complexity of requiring
    926 write barriers.
    927
    Threaded
    928
    Denotes a multithreaded mutator; the collector must still stop the mutator
    929 ("stop the world") before beginning reachability analysis. Stopping a
    930 multithreaded mutator is a complicated problem. It generally requires
    931 highly platform specific code in the runtime, and the production of
    932 carefully designed machine code at safe points.
    933
    Concurrent
    934
    In this technique, the mutator and the collector run concurrently, with
    935 the goal of eliminating pause times. In a cooperative collector,
    936 the mutator further aids with collection should a pause occur, allowing
    937 collection to take advantage of multiprocessor hosts. The "stop the world"
    938 problem of threaded collectors is generally still present to a limited
    939 extent. Sophisticated marking algorithms are necessary. Read barriers may
    940 be necessary.
    941
    942
    943

    As the matrix indicates, LLVM's garbage collection infrastructure is already

    944 suitable for a wide variety of collectors, but does not currently extend to
    945 multithreaded programs. This will be added in the future as there is
    946 interest.

    947
    948
    949
    950
    951
    952 Computing stack maps
    953
    954
    955
    956
    957
                      
                    
    958 >CollectorMetadata &MD = ...;
    959 unsigned FrameSize = MD.getFrameSize();
    960 size_t RootCount = MD.roots_size();
    961
    962 for (CollectorMetadata::roots_iterator RI = MD.roots_begin(),
    963 RE = MD.roots_end(); RI != RE; ++RI) {
    964 int RootNum = RI->Num;
    965 int RootStackOffset = RI->StackOffset;
    966 Constant *RootMetadata = RI->Metadata;
    967 }
    968
    969

    LLVM automatically computes a stack map. All a Collector needs to do

    970 is access it using CollectorMetadata::roots_begin() and
    971 -end(). If the llvm.gcroot intrinsic is eliminated before code
    972 generation by a custom lowering pass, LLVM's stack map will be empty.

    973
    974
    975
    976
    977
    978
    979 Initializing roots to null: InitRoots
    980
    981
    982
    983
    984
                      
                    
    985 >MyCollector::MyCollector() {
    986 InitRoots = true;
    987 }
    988
    989

    When set, LLVM will automatically initialize each root to null upon

    990 entry to the function. This prevents the reachability analysis from finding
    991 uninitialized values in stack roots at runtime, which will almost certainly
    992 cause it to segfault. This initialization occurs before custom lowering, so the
    993 two may be used together.

    994
    995

    Since LLVM does not yet compute liveness information, this feature should be

    996 used by all collectors which do not custom lower llvm.gcroot, and even
    997 some that do.

    998
    999
    1000
    1001
    1002
    1003
    1004 Custom lowering of intrinsics: CustomRoots,
    1005 CustomReadBarriers, and CustomWriteBarriers
    1006
    1007
    1008
    1009
    1010

    For collectors with barriers or unusual treatment of stack roots, these

    1011 flags allow the collector to perform any required transformation on the LLVM
    1012 IR:

    1013
    1014
                      
                    
    1015 >class MyCollector : public Collector {
    1016 public:
    1017 MyCollector() {
    1018 CustomRoots = true;
    1019 CustomReadBarriers = true;
    1020 CustomWriteBarriers = true;
    1021 }
    1022
    1023 protected:
    1024 virtual Pass *createCustomLoweringPass() const {
    1025 return new MyGCLoweringFunctionPass();
    1026 }
    1027 };
    1028
    1029

    If any of these flags are set, then LLVM suppresses its default lowering for

    1030 the corresponding intrinsics and instead passes them on to a custom lowering
    1031 pass specified by the collector.

    1032
    1033

    LLVM's default action for each intrinsic is as follows:

    1034
    1035
    1036
  • llvm.gcroot: Pass through to the code generator to generate a
  • 1037 stack map.
    1038
  • llvm.gcread: Substitute a load instruction.
  • 1039
  • llvm.gcwrite: Substitute a store instruction.
  • 1040
    1041
    1042

    If CustomReadBarriers or CustomWriteBarriers are specified,

    1043 the custom lowering pass must eliminate the corresponding
    1044 barriers.

    1045
    1046

    This template can be used as a starting point for a lowering pass:

    1047
    1048
                      
                    
    1049 >#include "llvm/Function.h"
    1050 #include "llvm/Module.h"
    1051 #include "llvm/Instructions.h"
    1052
    1053 namespace {
    1054 class VISIBILITY_HIDDEN MyGCLoweringFunctionPass : public FunctionPass {
    1055 static char ID;
    1056 public:
    1057 MyGCLoweringFunctionPass() : FunctionPass(intptr_t(&ID)) {}
    1058
    1059 const char *getPassName() const { return "Lower GC Intrinsics"; }
    1060
    1061 bool runOnFunction(Function &F) {
    1062 Module *M = F.getParent();
    1063
    1064 Function *GCReadInt = M->getFunction("llvm.gcread"),
    1065 *GCWriteInt = M->getFunction("llvm.gcwrite"),
    1066 *GCRootInt = M->getFunction("llvm.gcroot");
    1067
    1068 bool MadeChange = false;
    1069
    1070 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
    1071 for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;)
    1072 if (CallInst *CI = dyn_cast<CallInst>(II++))
    1073 if (Function *F = CI->getCalledFunction())
    1074 if (F == GCWriteInt) {
    1075 // Handle llvm.gcwrite.
    1076 CI->eraseFromParent();
    1077 MadeChange = true;
    1078 } else if (F == GCReadInt) {
    1079 // Handle llvm.gcread.
    1080 CI->eraseFromParent();
    1081 MadeChange = true;
    1082 } else if (F == GCRootInt) {
    1083 // Handle llvm.gcroot.
    1084 CI->eraseFromParent();
    1085 MadeChange = true;
    1086 }
    1087
    1088 return MadeChange;
    1089 }
    1090 };
    1091
    1092 char MyGCLoweringFunctionPass::ID = 0;
    1093 }
    1094
    1095
    1096
    1097
    1098
    1099
    1100 Generating safe points: NeededSafePoints
    1101
    1102
    1103
    1104
    1105

    LLVM can compute four kinds of safe points:

    1106
    1107
                      
                    
    1108 >namespace GC {
    1109 /// PointKind - The type of a collector-safe point.
    1110 ///
    1111 enum PointKind {
    1112 Loop, //< Instr is a loop (backwards branch).
    1113 Return, //< Instr is a return instruction.
    1114 PreCall, //< Instr is a call instruction.
    1115 PostCall //< Instr is the return address of a call.
    1116 };
    1117 }
    1118
    1119

    A collector can request any combination of the four by setting the

    1120 NeededSafePoints mask:

    1121
    1122
                      
                    
    1123 >MyCollector::MyCollector() {
    1124 NeededSafePoints = 1 << GC::Loop
    1125 | 1 << GC::Return
    1126 | 1 << GC::PreCall
    1127 | 1 << GC::PostCall;
    1128 }
    1129
    1130

    It can then use the following routines to access safe points.

    1131
    1132
    
                      
                    
    1133 CollectorMetadata &MD = ...;
    1134 size_t PointCount = MD.size();
    1135
    1136 for (CollectorMetadata::iterator PI = MD.begin(),
    1137 PE = MD.end(); PI != PE; ++PI) {
    1138 GC::PointKind PointKind = PI->Kind;
    1139 unsigned PointNum = PI->Num;
    1140 }
    1141
    1142

    Almost every collector requires PostCall safe points, since these

    1143 correspond to the moments when the function is suspended during a call to a
    1144 subroutine.

    1145
    1146

    Threaded programs generally require Loop safe points to guarantee

    1147 that the application will reach a safe point within a bounded amount of time,
    1148 even if it is executing a long-running loop which contains no function
    1149 calls.

    1150
    1151

    Threaded collectors may also require Return and PreCall

    1152 safe points to implement "stop the world" techniques using self-modifying code,
    1153 where it is important that the program not exit the function without reaching a
    1154 safe point (because only the topmost function has been patched).

    1155
    1156
    1157
    1158
    1159
    1160
    1161 Emitting assembly code:
    1162 beginAssembly and finishAssembly
    1163
    1164
    1165
    1166
    1167

    LLVM allows a collector to print arbitrary assembly code before and after

    1168 the rest of a module's assembly code. From the latter callback, the collector
    1169 can print stack maps from CollectorModuleMetadata populated by the code
    1170 generator.

    1171
    1172

    Note that LLVM does not currently support garbage collection code generation

    1173 in the JIT, nor using the object writers.

    1174
    1175
                      
                    
    1176 >class MyCollector : public Collector {
    1177 virtual void beginAssembly(Module &M, std::ostream &OS, AsmPrinter &AP,
    1178 const TargetAsmInfo &TAI) const;
    1179
    1180 virtual void finishAssembly(Module &M, CollectorModuleMetadata &MMD,
    1181 std::ostream &OS, AsmPrinter &AP,
    1182 const TargetAsmInfo &TAI) const;
    1183 }
    1184
    1185

    The collector should use AsmPrinter and TargetAsmInfo to

    1186 print portable assembly code to the std::ostream. The collector may
    1187 access the stack maps for the entire module using the methods of
    1188 CollectorModuleMetadata. Here's a realistic example:

    1189
    1190
                      
                    
    1191 >#include "llvm/CodeGen/AsmPrinter.h"
    1192 #include "llvm/Function.h"
    1193 #include "llvm/Target/TargetAsmInfo.h"
    1194
    1195 void MyCollector::finishAssembly(Module &M,
    1196 CollectorModuleMetadata &MMD,
    1197 std::ostream &OS, AsmPrinter &AP,
    1198 const TargetAsmInfo &TAI) const {
    1199 // Set up for emitting addresses.
    1200 const char *AddressDirective;
    1201 int AddressAlignLog;
    1202 if (TAI.getAddressSize() == sizeof(int32_t)) {
    1203 AddressDirective = TAI.getData32bitsDirective();
    1204 AddressAlignLog = 2;
    1205 } else {
    1206 AddressDirective = TAI.getData64bitsDirective();
    1207 AddressAlignLog = 3;
    1208 }
    1209
    1210 // Put this in the data section.
    1211 AP.SwitchToDataSection(TAI.getDataSection());
    1212
    1213 // For each function...
    1214 for (CollectorModuleMetadata::iterator FI = MMD.begin(),
    1215 FE = MMD.end(); FI != FE; ++FI) {
    1216 CollectorMetadata &MD = **FI;
    1217
    1218 // Emit this data structure:
    1219 //
    1220 // struct {
    1221 // int32_t PointCount;
    1222 // struct {
    1223 // void *SafePointAddress;
    1224 // int32_t LiveCount;
    1225 // int32_t LiveOffsets[LiveCount];
    1226 // } Points[PointCount];
    1227 // } __gcmap_<FUNCTIONNAME>;
    1228
    1229 // Align to address width.
    1230 AP.EmitAlignment(AddressAlignLog);
    1231
    1232 // Emit the symbol by which the stack map can be found.
    1233 std::string Symbol;
    1234 Symbol += TAI.getGlobalPrefix();
    1235 Symbol += "__gcmap_";
    1236 Symbol += MD.getFunction().getName();
    1237 if (const char *GlobalDirective = TAI.getGlobalDirective())
    1238 OS << GlobalDirective << Symbol << "\n";
    1239 OS << TAI.getGlobalPrefix() << Symbol << ":\n";
    1240
    1241 // Emit PointCount.
    1242 AP.EmitInt32(MD.size());
    1243 AP.EOL("safe point count");
    1244
    1245 // And each safe point...
    1246 for (CollectorMetadata::iterator PI = MD.begin(),
    1247 PE = MD.end(); PI != PE; ++PI) {
    1248 // Align to address width.
    1249 AP.EmitAlignment(AddressAlignLog);
    1250
    1251 // Emit the address of the safe point.
    1252 OS << AddressDirective
    1253 << TAI.getPrivateGlobalPrefix() << "label" << PI->Num;
    1254 AP.EOL("safe point address");
    1255
    1256 // Emit the stack frame size.
    1257 AP.EmitInt32(MD.getFrameSize());
    1258 AP.EOL("stack frame size");
    1259
    1260 // Emit the number of live roots in the function.
    1261 AP.EmitInt32(MD.live_size(PI));
    1262 AP.EOL("live root count");
    1263
    1264 // And for each live root...
    1265 for (CollectorMetadata::live_iterator LI = MD.live_begin(PI),
    1266 LE = MD.live_end(PI);
    1267 LI != LE; ++LI) {
    1268 // Print its offset within the stack frame.
    1269 AP.EmitInt32(LI->StackOffset);
    1270 AP.EOL("stack offset");
    1271 }
    1272 }
    1273 }
    1274 }
    1275
    1276
    1277
    1278
    1279
    1280
    1281
    1282 Implementing a collector runtime
    1283
    1284
    1285
    1286
    1287
    1288

    Implementing a garbage collector for LLVM is fairly straightforward. The

    1289 LLVM garbage collectors are provided in a form that makes them easy to link into
    1290 the language-specific runtime that a language front-end would use. They require
    1291 functionality from the language-specific runtime to get information about
    1292 href="#gcdescriptors">where pointers are located in heap objects.

    1293
    1294

    The implementation must include the

    1295 llvm_gc_allocate and
    1296 llvm_gc_collect functions. To do this, it will
    1297 probably have to trace through the roots
    1298 from the stack and understand the GC descriptors
    1299 for heap objects. Luckily, there are some example
    1300 implementations available.
    1301

    1302
    1303
    1304
    1305
    1306
    4081307 Tracing GC pointers from heap objects
    4091308
    4101309
    4151314
    4161315
    4171316
  • In languages with polymorphic objects, pointers from an object header are
  • 418 usually used to identify the GC pointers in the heap object. This is common for
    1317 usually used to identify the GC pointers in the heap object. This is common for
    4191318 object-oriented languages like Self, Smalltalk, Java, or C#.
    4201319
    4211320
  • If heap objects are not polymorphic, often the "shape" of the heap can be
  • 4221321 determined from the roots of the heap or from some other meta-data [
    4231322 href="#appel89">Appel89, Goldberg91,
    424 href="#tolmach94">Tolmach94]. In this case, the garbage collector can
    425 propagate the information around from meta data stored with the roots. This
    426 often eliminates the need to have a header on objects in the heap. This is
    1323 href="#tolmach94">Tolmach94]. In this case, the garbage collector can
    1324 propagate the information around from meta data stored with the roots. This
    1325 often eliminates the need to have a header on objects in the heap. This is
    4271326 common in the ML family.
    4281327
    4291328
  • If all heap objects have pointers in the same locations, or pointers can be
  • 4301329 distinguished just by looking at them (e.g., the low order bit is clear), no
    431 book-keeping is needed at all. This is common for Lisp-like languages.
    1330 book-keeping is needed at all. This is common for Lisp-like languages.
    4321331
    4331332
    4341333

    The LLVM garbage collectors are capable of supporting all of these styles of

    435 language, including ones that mix various implementations. To do this, it
    1334 language, including ones that mix various implementations. To do this, it
    4361335 allows the source-language to associate meta-data with the
    4371336 href="#roots">stack roots, and the heap tracing routines can propagate the
    438 information. In addition, LLVM allows the front-end to extract GC information
    439 from in any form from a specific object pointer (this supports situations #1 and
    440 #3).
    1337 information. In addition, LLVM allows the front-end to extract GC information
    1338 in any form from a specific object pointer (this supports situations #1 and #3).
    4411339

    4421340
    443

    Making this efficient

    444
    445
    446
    447
    448
    449
    450
    451
    452
    453 GC implementations available
    454
    455
    456
    457
    458
    459

    460 To make this more concrete, the currently implemented LLVM garbage collectors
    461 all live in the llvm/runtime/GC/* directories in the LLVM source-base.
    462 If you are interested in implementing an algorithm, there are many interesting
    463 possibilities (mark/sweep, a generational collector, a reference counting
    464 collector, etc), or you could choose to improve one of the existing algorithms.
    465

    466
    467
    468
    469
    470
    471 SemiSpace - A simple copying garbage collector
    472
    473
    474
    475

    476 SemiSpace is a very simple copying collector. When it starts up, it allocates
    477 two blocks of memory for the heap. It uses a simple bump-pointer allocator to
    478 allocate memory from the first block until it runs out of space. When it runs
    479 out of space, it traces through all of the roots of the program, copying blocks
    480 to the other half of the memory space.
    481

    482
    483
    484
    485
    486
    487 Possible Improvements
    488
    489
    490
    491
    492

    493 If a collection cycle happens and the heap is not compacted very much (say less
    494 than 25% of the allocated memory was freed), the memory regions should be
    495 doubled in size.

    496
    497
    1341
    1342
    4981343
    4991344
    5001345
    5081353 W. Appel. Lisp and Symbolic Computation 19(7):703-705, July 1989.

    5091354
    5101355

    [Goldberg91] Tag-free garbage collection for

    511 strongly typed programming languages. Benjamin Goldberg. ACM SIGPLAN
    1356 strongly typed programming languages. Benjamin Goldberg. ACM SIGPLAN
    5121357 PLDI'91.

    5131358
    5141359

    [Tolmach94] Tag-free garbage collection using

    515 explicit type parameters. Andrew Tolmach. Proceedings of the 1994 ACM
    1360 explicit type parameters. Andrew Tolmach. Proceedings of the 1994 ACM
    5161361 conference on LISP and functional programming.

    5171362
    518 </div>
    1363 <p>[Henderson2002]
    1364 href="http://citeseer.ist.psu.edu/henderson02accurate.html">
    1365 Accurate Garbage Collection in an Uncooperative Environment.
    1366 Fergus Henderson. International Symposium on Memory Management 2002.

    1367
    1368
    1369
    5191370
    5201371
    5211372
    91104 subexpression compuation. For example (a+b)*(a+b) has two 92105 subexpressions that are the same: (a+b). This optimization would 93106 perform the addition only once and then perform the multiply (but only if 94 its compulationally correct/safe). 107 it's compulationally correct/safe). 95108 96109
    97110 98111 99112
    100113
    114
    DAG
    115
    Directed Acyclic Graph
    116
    Derived Pointer
    117
    A pointer to the interior of an object, such that a garbage collector 118 is unable to use the pointer for reachability analysis. While a derived 119 pointer is live, the corresponding object pointer must be kept in a root, 120 otherwise the collector might free the referenced object. With copying 121 collectors, derived pointers pose an additional hazard that they may be 122 invalidated at any safe point. This term is used in 123 opposition to object pointer.
    101124
    DSA
    102125
    Data Structure Analysis
    103126
    DSE
    104127
    Dead Store Elimination
    128
    129
    130 131 132
    133
    134
    GC
    135
    Garbage Collection. The practice of using reachability analysis instead 136 of explicit memory management to reclaim unused memory.
    137
    138
    139 140 141
    142
    143
    Heap
    144
    In garbage collection, the region of memory which is managed using 145 reachability analysis.
    105146
    106147
    107148 115156
    Inter-Procedural Optimization. Refers to any variety of code 116157 optimization that occurs between procedures, functions or compilation units 117158 (modules).
    159
    ISel
    160
    Instruction Selection.
    118161 119162
    120163 131174
    132175 133176 177 178
    179
    180
    Object Pointer
    181
    A pointer to an object such that the garbage collector is able to trace 182 references contained within the object. This term is used in opposition to 183 derived pointer.
    184
    185
    186 187 134188 135189
    136190
    146200
    Reassociation
    Rearranging 147201 associative expressions to promote better redundancy elimination and other 148202 optimization. For example, changing (A+B-A) into (B+A-A), permitting it to 149 be optimized into (B+0) then (B). 203 be optimized into (B+0) then (B).
    204
    Root
    In garbage collection, a 205 pointer variable lying outside of the heap from which 206 the collector begins its reachability analysis. In the context of code 207 generation, "root" almost always refers to a "stack root"—a local or 208 temporary variable within an executing function.
    150209
    151210
    152211 154213 155214
    156215
    216
    Safe Point
    217
    In garbage collection, it is necessary to identify stack 218 roots so that reachability analysis may proceed. It may be infeasible to 219 provide this information for every instruction, so instead the information 220 may is calculated only at designated safe points. With a copying collector, 221 derived pointers must not be retained across 222 safe points and object pointers must be 223 reloaded from stack roots.
    224
    SDISel
    225
    Selection DAG Instruction Selection.
    157226
    SCC
    158227
    Strongly Connected Component
    159228
    SCCP
    162231
    Scalar Replacement of Aggregates
    163232
    SSA
    164233
    Static Single Assignment
    234
    Stack Map
    235
    In garbage collection, metadata emitted by the code generator which 236 identifies roots within the stack frame of an executing 237 function.
    165238
    166239
    167240
    +1
    -1
    docs/llvm.css less more
    1212
    1313 TR, TD { border: 2px solid gray; padding: 4pt 4pt 2pt 2pt; }
    1414 TH { border: 2px solid gray; font-weight: bold; font-size: 105%;
    15 color: black; background: url("img/lines.gif");
    15 background: url("img/lines.gif");
    1616 font-family: "Georgia,Palatino,Times,Roman,SanSerif"; text-align:center;
    1717 vertical-align: middle; }
    1818 TABLE { text-align: center; border: 2px solid black;
    +5
    -0
    runtime/GC/SemiSpace/README.txt less more
    0 //===----------------------------------------------------------------------===//
    1
    2 Possible enhancement: If a collection cycle happens and the heap is not
    3 compacted very much (say less than 25% of the allocated memory was freed), the
    4 memory regions should be doubled in size.