Index: gc-howto.html =================================================================== --- gc-howto.html (revision 454321) +++ gc-howto.html (working copy) @@ -36,7 +36,7 @@ - Apache Harmony - How to Plug in a GC for DRLVM + Apache Harmony - Apache Harmony @@ -204,364 +204,81 @@ + + + + + + + + + + + + + + + + + + + + + +executable ij.exe. +The default garbage collector is gc.dll located in the same +bin/ directory as ij.exe.

+ + + + + +
+

+ How to Write DRL GC +

+
-
- - - - - - -How to write DRL GC - - - -
-
-

This document provides instructions on creating a custom garbage collector implementation -in C++ and configuring the DRL virtual machine to use it. The document describes -the major steps of this procedure, namely:

-
    -
  • -Establishing the build infrastructure - -
  • -
  • - -Implementing the GC interface - -
  • -
  • - -Implementing the garbage collector algorithm - -
  • -
  • - -Running the VM with the custom GC - -
  • -
-
Note
-

Plugging-in a user-designed garbage collector presupposes an operating DRL -virtual machine built according to the instructions of the README.txt file -supplied with the VM source package.

-
-
-

1. Establishing the build infrastructure

-
+
+

+ Contents +

+
+ +
    +
  1. About This Document
  2. +
  3. Establishing the Build Infrastructure
  4. +
  5. Implementing the GC Interface
  6. +
  7. Implementing the GC Algorithm
  8. +
  9. Running the VM with the Custom GC
  10. +
+ +
+

+ 1. About This Document +

+

This document provides instructions on creating a custom garbage + collector implementation (GC, version 1.0, 2006-07-20) in C++ and + configuring the DRL virtual machine to use it. The document + describes the major steps of this procedure, namely: establishing + the build infrastructure, implementing the GC interface, implementing + the GC algorithm, and running the VM with the custom GC.

+

Note

+

Plugging-in a user-designed garbage collector presupposes +an operating DRL virtual machine built according to the instructions of the +README.txt filesupplied with the VM source package.

+
+

+ 2. Establishing the Build Infrastructure +

+ +

At this stage, you create the directory and set up the build infrastructure to build the dynamic library. At the end of this stage, you will be fully set for adding the garbage collector code and building it.

DRLVM can load a custom garbage collector from a dynamic library. It is recommended that you build your dynamic library using a DRLVM build infrastructure. Below is an example of creating of a -build descriptor on the Windows* / IA-32 architecture.

-

1.1. Create a directory for a new GC module, for example:

-
-
-
vm$ mkdir gc_copying
+build descriptor on the Windows/IA-32 architecture.

+
+

+ 2.1 Creating a Directory for a New GC Module +

+

The example below shows how to create a directory for a new GC module:

+
vm$ mkdir gc_copying
 vm$ mkdir gc_copying/src
-vm$ cd gc_copying/src
- -

That is where you will put the source code, see Section 3, -Implementing the garbage collector algorithm.

-

1.2. Create a build descriptor file

-

Create the build descriptor file build/make/components/vm/gc_copying.xml +vm$ cd gc_copying/src + +

In the newly created directory you will store the source code. For more information, refer to the +Implementing the GC Algorithm section.

+
+

+ 2.2 Creating a Build Descriptor File +

+ +

Create the build descriptor file build/make/components/vm/gc_copying.xml with the following content:

-
-
-
<project name="vm.gc_copying">
+
+
<project name="vm.gc_copying">
     <target name="init" depends="common_vm">
         <property name="build.depends" value="extra.apr,vm.vmcore" />
         <property name="outtype" value="shared" />
@@ -597,216 +314,267 @@
             </select>
         </linker>
     </target>
-</project>
-
+</project> +

You can add other macro definitions, include directories or compiler-specific command-line options to match your needs.

-

1.3. Create a C++ file with essential includes, namely:

-
-
-
#include "open/gc.h"
+
+

+ + 2.3 Creating a C++ file with essential include files +

+

Create a C++ file with essential include files, namely:

+ +
#include "open/gc.h"
 #include "open/vm_gc.h"
 #include "open/vm.h"
 
 #define LOG_DOMAIN "gc"
-#include "cxxlog.h"
- -

These include files are located in directories vm/include/open and -vm/port/include. Consult their content for documentation and details of the +#include "cxxlog.h" + +

These include files are located in directories vm/include/open and +vm/port/include. Consult their content for documentation and details of the interface.

-

1.4. Test the configuration

+
+

+ 2.4 Testing the Configuration +

+

Run the build system to test whether the infrastructure is set up correctly:

-
-
-
build$ build.bat -DCOMPONENTS=vm.gc_copying
-
-

On a successful build, the .dll file is placed to the VM build directory -build/win_ia32_icl_debug/deploy/jre/bin/. The name of the directory may differ -depending on your system and the compiler used. This empty library will not -work, you have to write your GC first!

- -

2. Implementing the GC interface

-
+ +
build$ build.bat -DCOMPONENTS=vm.gc_copying
+ +

On a successful build, the .dll file is placed to the VM build directory +build/win_ia32_icl_debug/deploy/jre/bin/. The name of the directory may differ +depending on your system and the compiler used.

+

Note

+

This empty library will not +work, you have to write your GC first.

+
+

+ 3. Implementing the GC interface +

+

This section lists the functions that a garbage collector interface must -implement. Declarations of these functions are in gc.h. For details, consult -the Developer's Guide and documentation in gc.h and vm_gc.h.

-

2.1. GC lifecycle

+implement. Declarations of these functions are in gc.h. For details, consult +the Developer's Guide and documentation in gc.h and vm_gc.h.

+
+

+ 3.1 GC Lifecycle +

+
  • -gc_init() initializes the garbage collector +gc_init() initializes the garbage collector
  • -gc_wrapup() shuts down the GC +gc_wrapup() shuts down the GC
  • -gc_vm_initialized() notifies the GC about the VM transition from the +gc_vm_initialized() notifies the GC about the VM transition from the initialization stage to running user applications
  • -gc_thread_init() and gc_thread_kill() notify the GC about creation and +gc_thread_init() and gc_thread_kill() notify the GC about creation and termination of user threads that may request memory allocation or other GC services
  • -gc_class_prepared() notifies the GC about loaded and prepared classes +gc_class_prepared() notifies the GC about loaded and prepared classes
-

2.2. Object allocation

+
+

+ 3.2. Object allocation +

+
  • -gc_alloc() performs slow allocation, can trigger garbage collection +gc_alloc() performs slow allocation, can trigger garbage collection
  • -gc_alloc_fast() performs faster allocation, should not trigger garbage +gc_alloc_fast() performs faster allocation, should not trigger garbage collection
  • -gc_add_root_set_entry() is responsible for enumeration +gc_add_root_set_entry() is responsible for enumeration
  • -gc_add_root_set_entry() enumerates one root pointer +gc_add_root_set_entry() enumerates one root pointer
-

See the Root set enumeration section in the Developer's Guide for details.

-

2.3. Miscellaneous

+

See the +Root Set Enumeration section in the +Developer's Guide for details.

+
+

+ 3.3. Miscellaneous +

  • -gc_supports_compressed_references() indicates whether GC supports compressed references +gc_supports_compressed_references() indicates whether GC supports compressed references
  • -gc_is_object_pinned() indicates whether the GC will move an object or not +gc_is_object_pinned() indicates whether the GC will move an object or not
  • -gc_force_gc() forces a garbage collection +gc_force_gc() forces a garbage collection
-

2.4. Optional

+
+

+ 3.4. Optional +

+

The virtual machine can operate without the functions listed below, but certain features will be unavailable.

  • -gc_free_memory() returns the estimated amount of memory available for allocation +gc_free_memory() returns the estimated amount of memory available for allocation
  • -gc_pin_object() requests that the GC does not move an object +gc_pin_object() requests that the GC does not move an object
  • -gc_unpin_object() removes the restriction on not moving an object +gc_unpin_object() removes the restriction on not moving an object
  • -gc_get_next_live_object() iterates over live objects during the stop-the-world +gc_get_next_live_object() iterates over live objects during the stop-the-world phase of garbage collection
  • -gc_finalize_on_exit() transfers finalizable queue contents to the VM core on +gc_finalize_on_exit() transfers finalizable queue contents to the VM core on shutdown
  • -gc_time_since_last_gc() returns the amount of time that elapsed since the +gc_time_since_last_gc() returns the amount of time that elapsed since the previous collection, in milliseconds
  • -gc_total_memory() returns the overall amount of memory used for the Java heap +gc_total_memory() returns the overall amount of memory used for the Java heap
  • -gc_max_memory() returns the maximum amount of memory that can be used for the +gc_max_memory() returns the maximum amount of memory that can be used for the Java heap
-

2.5. The VM_GC interface

+
+

+ 3.5. The VM_GC Interface +

+

The garbage collector requires VM support in its operation. The virtual machine -exports the VM_GC interface to meet the needs of the garbage collector. -Besides, the GC uses the VM_common interface.

-

The VM_GC interface describes the services that the VM provides specifically -for the garbage collector. Please refer to the header file vm_gc.h to see the +exports the VM_GC interface to meet the needs of the garbage collector. +Besides, the GC uses the VM_common interface.

+

The VM_GC interface describes the services that the VM +provides specifically +for the garbage collector. Please refer to the header file vm_gc.h to see the complete list and documentation.

The VM exports two functions to provide the global locking service for the -garbage collector: vm_gc_lock_enum() and vm_gc_unlock_enum(). These two +garbage collector: vm_gc_lock_enum() and vm_gc_unlock_enum(). These two functions differ from plain system locks in their ability to gracefully interoperate with VM threading services. In case of contention on the GC lock, -that is, when multiple threads call vm_gc_lock_enum() simultaneously, one +that is, when multiple threads call vm_gc_lock_enum() simultaneously, one thread gets the lock, and others remain blocked. If the thread that grabbed the GC lock does a garbage collection, the blocked threads are considered safely -suspended. Other ways to lock user threads for a long time can lead to a +suspended. Other ways to lock user threads for a long time can lead to a deadlock because the VM will have no way to find out whether the thread is blocked or running.

-

A detailed description of GC procedure is given in the Developers' Guide.

+

A detailed description of GC procedure is given in the +Developer's Guide.

DRLVM provides two functions to support thread suspension and root set enumeration simultaneously:

  • -vm_enumerate_root_set_all_threads() suspends all user threads and initiates +vm_enumerate_root_set_all_threads() suspends all user threads and initiates root set enumeration
  • -vm_resume_threads_after() resumes execution of user threads +vm_resume_threads_after() resumes execution of user threads

These functions effectively restrict the garbage collector to stop-the-world algorithms only.

- -

3. Implementing the garbage collector algorithm

-
+
+

+ 4. Implementing the GC Algorithm +

+

This section gives step-by-step instructions on how to implement the garbage collection algorithm. The example shows a semispace copying collector.

-
Note
-

This example does not implement object finalization and weak references.

-

3.1. Algorithm Overview

+

Note

+

This example does not implement object finalization and weak references.

+
+

+ 4.1. Algorithm Overview +

+

The heap is divided into two equally sized contiguous semispaces. -During normal operation, only one semispace is used (current semispace), -and the other one is reserved for garbage collection. +During normal operation, only one semispace is used (current semispace), +and the other one is reserved for garbage collection. Allocation requests are satisfied by contiguous allocation from the current semispace. Each application thread reserves a thread-local -allocation buffer (TLAB) under a global lock, and serves most of the allocation +allocation buffer (TLAB) under a global lock, and serves most of the allocation requests without locking, by incrementing the allocation pointer local to the buffer.

When the application requests an allocation that does not fit into the remaining free space of the current semispace, a garbage collection is initiated. The current -semispace becomes the evacuation space (fromspace), and the reserved semispace -becomes the destination space (tospace). The VM suspends all application threads and +semispace becomes the evacuation space (fromspace), and the reserved semispace +becomes the destination space (tospace). The VM suspends all application threads and enumerates root references.

The GC copies the objects reachable from root references to the destination space. When an object is copied from evacuation space to destination space, the GC installs @@ -827,32 +595,30 @@ evacuated to the destination space, and the evacuation space can be safely reclaimed. The GC then changes the semispace roles: it uses the destination space for further allocation and reserves the evacuation space for the next garbage collection. The change of -the semispace roles is commonly referred to as flip.

+the semispace roles is commonly referred to as flip.

After the semispace flip, the GC resumes user threads.

Please refer to the excellent survey for detailed description of this algorithm and other basic garbage collection techniques, "Uniprocessor Garbage Collection Techniques", Paul R. Wilson.

3.2. Source code explained

-

The full source code of the collector is available in gc_copying.cpp.

-

The structure TLS (thread-local storage) +

The full source code of the collector is available in gc_copying.cpp.

+

The structure TLS (thread-local storage) is used for the optimizing fast path allocation. The GC allocates a buffer of free space from the heap with appropriate locking and further uses this buffer for thread-local allocation.

-
-
-
// This structure is allocated for each user thread.
+
+
// This structure is allocated for each user thread.
 // It contains the thread-local allocation area.
 
 struct TLS {
     byte* current;  // the allocation pointer
     byte* limit;    // the end of the allocation area
-};
-
+}; +

Define the main GC structure to contain the Java heap and the data necessary for GC operation, as shown below.

-
-
-
// Encapsulates all GC data.
+
+
// Encapsulates all GC data.
 struct GC {
 
     unsigned int semisize;   // the size of the semispace
@@ -895,13 +661,12 @@
 
     std::list<InteriorPointer> interior_pointers;
     void repoint_all_roots_with_interior_points();
-};
-
+}; +

The following structure stores object information: the object field layout and the object size.

-
-
-
// Structure OI (from "object information")
+
+
// Structure OI (from "object information")
 // is used to cache GC information for each Java class
 // loaded by the virtual machine.
 // Each VTable stores the pointer to an OI (Object information) structure.
@@ -915,107 +680,98 @@
     int size;           // the object size or the array element size
     int* offsets;       // zero-terminated list of slot offsets in an object
                         // undefined for array
-};
-
-

The data stored in the OI structure is initialized and accessed by the GC only.

+}; + +

The data stored in the OI structure is initialized and accessed by the GC only.

The following structures convey the static assumptions that GC makes about object layout. The VM must use the same object layout assumptions for the correct GC operation.

-

The VTable structure contains the virtual table of the object methods, +

The VTable structure contains the virtual table of the object methods, and is linked from the object header. The VM reserves some space (at least 4 bytes) for exclusive use by GC. The GC uses 4 bytes of GC-private space to put the pointer -to the object information structure struct OI.

-
-
-
// The VTable structure has 4 bytes reserved
+to the object information structure struct OI.

+ + +
// The VTable structure has 4 bytes reserved
 // for GC use at the beginning.
 // The pointer to the OI structure is stored there.
 struct VTable {
     OI* oi;
     // Other VTable fields are not used in GC.
-};
-
-

The GC assumes that each Java* object has a fixed header: (1) a pointer -to the VTable structure, and then a (2) 32 bit word with flags. +}; + +

The GC assumes that each Java object has a fixed header: (1) a pointer +to the VTable structure, and then a (2) 32 bit word with flags. The 25 highest bits are used by the VM Thread Manager component to -implement Java* monitors and 7 lowest bits are used by GC and for +implement Java monitors and 7 lowest bits are used by GC and for storing the object hash code.

-
-
-
// Describes the object header format assumed by GC.
+
+
// Describes the object header format assumed by GC.
 struct Object {
     VTable *vt;
     uint32 lockword;
-};
-
+}; +

The array objects have the same header, and a 4 byte length field at the offset 8.

-
-
-
// Describes the array header format assumed by GC.
+
+
// Describes the array header format assumed by GC.
 struct Array {
     VTable *vt;
     uint32 lockword;
     uint32 length;
-};
-
-
Note
-

The layout described is valid for the IA-32 platform only.

+}; +

Note

+

The layout described is valid for the IA-32 platform only.

A number of convenience functions use object layout knowledge to perform -various data manipulations. The function init_vt() writes the VTable pointer +various data manipulations. The function init_vt() writes the VTable pointer to an object.

-
-
-
void init_vt(Managed_Object_Handle p, Allocation_Handle ah) {
+
+
void init_vt(Managed_Object_Handle p, Allocation_Handle ah) {
     Object* obj = (Object*)p;
     obj->vt = (VTable*)ah;
-}
-
-

The function obj_oi() retrieves object information structure +} + +

The function obj_oi() retrieves object information structure pointer from an object.

-
-
-
OI* obj_oi(Managed_Object_Handle p) {
+
+
OI* obj_oi(Managed_Object_Handle p) {
     Object* obj = (Object*)p;
     return obj->vt->oi;
-}
-
-

The function array_length() retrieves the length of an array +} + +

The function array_length() retrieves the length of an array object.

-
-
-
int array_length(Managed_Object_Handle p) {
+
+
int array_length(Managed_Object_Handle p) {
     Array* array = (Array*)p;
     return array->length;
-}
-
-

The function vt_oi() retrieves the OI structure pointer +} + +

The function vt_oi() retrieves the OI structure pointer from the VTable pointer.

-
-
-
OI* vt_oi(VTable_Handle p) {
+
+
OI* vt_oi(VTable_Handle p) {
     VTable* vt = (VTable*)p;
     return vt->oi;
-}
-
-

The function ah_oi() retrieves the OI structure pointer -using Allocation_Handle. On 32-bit architectures, the +} + +

The function ah_oi() retrieves the OI structure pointer +using Allocation_Handle. On 32-bit architectures, the VTable pointer is a 32-bit pointer, and Allocation_Handle is a 32-bit integer.

-
-
-
OI* ah_oi(Allocation_Handle ah) {
+
+
OI* ah_oi(Allocation_Handle ah) {
     // Allocation_Handle is a VTable pointer on 32-bit platforms.
     return vt_oi((VTable_Handle)ah);
-}
-
-

The object_size() function computes the size of an object. Array size is +} + +

The object_size() function computes the size of an object. Array size is calculated by summing the header size and the element size multiplied by array length. Afterwards the size is aligned to be multiple of 4. The non-array object size is cached in the OI structure.

-
-
-
int object_size (Managed_Object_Handle obj) {
+
+
int object_size (Managed_Object_Handle obj) {
     OI* oi = obj_oi(obj);
     if (oi->is_array) {
         // 4-byte alignment
@@ -1023,29 +779,26 @@
     } else {
         return oi->size;
     }
-}
-
+} +

In this example, the garbage collector is created statically as a global instance of structure GC:

-
-
-
GC gc;
-
-

The function init() statically configures size parameters. Normally, this -function uses the function vm_get_property() to read configuration options + +

GC gc;
+ +

The function init() statically configures size parameters. Normally, this +function uses the function vm_get_property() to read configuration options specified as property values on the command line. In this example, we use constant values for simplicity.

-
-
-
void GC::init() {
+
+
void GC::init() {
     semisize = 500*1024*1024;
-    chunk_size = 64*1024;
-
-

As the next step, the init() function allocates space for the heap, divides it + chunk_size = 64*1024; + +

As the next step, the init() function allocates space for the heap, divides it into two semispaces, and initializes the allocation semispace.

-
-
-
    space = (byte*) malloc(semisize*2);
+
+
    space = (byte*) malloc(semisize*2);
     assert(space); assert(((int)space & 3) == 0);
     fromspace = space;
     tospace = fromspace + semisize; assert(((int)tospace & 3) == 0);
@@ -1062,14 +815,13 @@
     memset(current, 0, limit - current);
 
     interior_pointers.clear();
-}
-
+} +

The global allocation function uses a lock to protect the heap from simultaneous access from multiple threads. The locking mechanism -is trivially implemented in a platform-dependent way. See the full source code in gc_copying.cpp.

-
-
-
byte* GC::galloc(unsigned size) {
+is trivially implemented in a platform-dependent way. See the full source code in gc_copying.cpp.

+ +
byte* GC::galloc(unsigned size) {
     byte* r = NULL;
     lock.lock();
     if (current + size <= limit) {
@@ -1078,15 +830,14 @@
     }
     lock.unlock();
     return r;
-}
-
+} +

The local allocation function uses the thread-local allocation area for object -allocation, and uses galloc() to allocate a new chunk for a thread-local +allocation, and uses galloc() to allocate a new chunk for a thread-local allocation area as needed.

-
-
-
byte* GC::alloc(unsigned size, TLS* tls) {
 
+
byte* GC::alloc(unsigned size, TLS* tls) {
+
     byte* obj = NULL;
 
     assert(NULL == tls->current || fromspace <= tls->current);
@@ -1115,26 +866,24 @@
     }
 
     return obj;
-}
-
+} +

The forwarding pointers are installed in the lockword structure, the second word of an object.

-
-
-
byte* GC::forwarded (void* obj) {
+
+
byte* GC::forwarded (void* obj) {
     int* p = (int*)obj + 1;
     int lockword = *p;
     if (lockword & 1)
         return (byte*)(lockword & (~1));
     else
         return NULL;
-}
-
-

The function move() copies the object data to the evacuation semispace and +} + +

The function move() copies the object data to the evacuation semispace and installs the forwarding pointer in the old object copy.

-
-
-
byte* GC::move (void* obj) {
+
+
byte* GC::move (void* obj) {
     int size = object_size(obj);
     assert(tospace <= copy); assert(copy + size <= toend);
 
@@ -1148,15 +897,14 @@
     *plockword = ((int)nobj) | 1;
 
     return nobj;
-}
-
-

The function root() handles one root during root set enumeration. If the root +} + +

The function root() handles one root during root set enumeration. If the root points to an object already reached, the root is updated with the forwarded pointer value. Otherwise, the GC moves the object to the destination space and installs the forwarding pointer in the old object copy.

-
-
-
void GC::root(void** root) {
+
+
void GC::root(void** root) {
     byte* obj = (byte*)(*root);
     byte* nobj = forwarded(obj);
     if (NULL == nobj) {
@@ -1165,12 +913,11 @@
     TRACE2("gc.root", "root " << root << " repointed from "
             << (void*)obj << " to " << (void*)nobj);
     *root = nobj;
-}
-
-

The function trace() scans one object.

-
-
-
void GC::trace (byte* obj) {
+}
+ +

The function trace() scans one object.

+ +
void GC::trace (byte* obj) {
     OI* oi = obj_oi(obj);
     TRACE2("gc.trace", "trace " << (void*)obj
         << " (" << (void*)object_size(obj) << ", " << oi->name << ")");
@@ -1206,22 +953,22 @@
             *field = nobj;
         }
     }
-}
-
-

The function collect_alloc() is the main function controlling garbage +} + +

The function collect_alloc() is the main function controlling garbage collection. This function reclaims unused memory and the retries the allocation. The GC attempts to allocate the memory before resuming other threads. This prevents the thread that triggered the garbage collection from starving.

-
Note
-

The thread is starving when it gets no resources for a long time +

Note

+

+The thread is starving when it gets no resources for a long time because other threads grab the resource before it can even try. If the garbage collector resumes user threads before retrying the allocation, these threads may use all available space quickly before the allocation succeeds. In this case, the allocation will fail for an indefinite number of times.

-
-
-
byte* GC::collect_alloc(unsigned size, TLS* tls) {
 
+
byte* GC::collect_alloc(unsigned size, TLS* tls) {
+
     scan = tospace;
     copy = tospace;
     toend = tospace + semisize;
@@ -1271,22 +1018,22 @@
 
     vm_resume_threads_after();
     return obj;
-}
+}

The exported GC interface is mostly implemented by delegating the task to the -method of the structure GC. The GC initialization function init() is called -from gc_init().

+method of the structure GC. The GC initialization function init() is called +from gc_init().

-
void gc_init() {
+
void gc_init() {
     gc.init();
-}
+}

Thread local allocation areas are reset on thread creation and thread termination events.

-
void gc_thread_init(void* tp) {
+
void gc_thread_init(void* tp) {
     TRACE2("gc.thread", "gc_thread_init " << tp);
     TLS* tls = (TLS*) tp;
     std::list<TLS*>::iterator i =
@@ -1308,13 +1055,12 @@
 
     tls->current = NULL;
     tls->limit = NULL;
-}
-
-

The slow path allocation function gc_alloc() checks whether the allocation space is +} + +

The slow path allocation function gc_alloc() checks whether the allocation space is exhausted and starts garbage collection when necessary.

-
-
-
Managed_Object_Handle gc_alloc (unsigned size, Allocation_Handle ah, void *tp) {
+
+
Managed_Object_Handle gc_alloc (unsigned size, Allocation_Handle ah, void *tp) {
     Managed_Object_Handle obj;
     TLS* tls = (TLS*) tp;
 
@@ -1358,13 +1104,12 @@
     assert(NULL == obj ||
         (gc.fromspace <= obj && obj < gc.limit && ((int)obj & 3) == 0));
     return obj;
-}
-
+} +

If the memory is exhausted, the no-collection allocation function -gc_alloc_fast() returns NULL, and does not start garbage collection.

-
-
-
Managed_Object_Handle gc_alloc_fast (unsigned size, Allocation_Handle ah, void *tp) {
+gc_alloc_fast() returns NULL, and does not start garbage collection.

+ +
Managed_Object_Handle gc_alloc_fast (unsigned size, Allocation_Handle ah, void *tp) {
     Managed_Object_Handle obj;
     TLS* tls = (TLS*) tp;
     size = size & 0x3fffffff;
@@ -1379,24 +1124,22 @@
     assert(NULL == obj ||
         (gc.fromspace <= obj && obj < gc.limit && ((int)obj & 3) == 0));
     return obj;
-}
-
-

The root set enumeration function passes the root reference to the root() +} + +

The root set enumeration function passes the root reference to the root() function.

-
-
-
void gc_add_root_set_entry(Managed_Object_Handle *ref, Boolean is_pinned) {
+
+
void gc_add_root_set_entry(Managed_Object_Handle *ref, Boolean is_pinned) {
     assert(!is_pinned);
     TRACE2("gc.root", "gc_add_root_set_entry " << ref << " -> " << *ref);
     if (NULL == *ref) return;
     gc.root(ref);
-}
-
-

The function build_slot_offset_array() is used to construct a NULL-terminated +} + +

The function build_slot_offset_array() is used to construct a NULL-terminated list of offsets of reference fields.

-
-
-
static int *build_slot_offset_array(Class_Handle ch)
+
+
static int *build_slot_offset_array(Class_Handle ch)
 {
     unsigned num_ref_fields = 0;
     // Get the total number of fields including primitive fields.
@@ -1433,13 +1176,12 @@
     *p = 0;
 
     return ref_array;
-}
-
-

The GC caches object layout information when the function gc_class_prepared() +} + +

The GC caches object layout information when the function gc_class_prepared() is called.

-
-
-
void gc_class_prepared (Class_Handle ch, VTable_Handle vth) {
+
+
void gc_class_prepared (Class_Handle ch, VTable_Handle vth) {
     TRACE2("gc.prepared", "gc_class_prepared("
             << class_get_name(ch) << ")");
     OI** vt = (OI**) vth;
@@ -1465,50 +1207,53 @@
         oi->offsets = build_slot_offset_array(ch);
         oi->has_slots = (oi->offsets != NULL);
     }
-}
-
-

The function gc_force_gc() starts a forced garbage collection using the global +} + +

The function gc_force_gc() starts a forced garbage collection using the global GC lock to ensure that only one thread is doing a collection at any time. It -passes null arguments to collect_alloc(), because it requires no +passes null arguments to collect_alloc(), because it requires no allocation.

-
-
-
void gc_force_gc () {
+
+
void gc_force_gc () {
     vm_gc_lock_enum();
     gc.collect_alloc(0, NULL);
     vm_gc_unlock_enum();
-}
-
+} +

Other functions of the GC interface are empty or trivial, and not described in -this document. You can see the full listing in the gc_copying.cpp file.

+this document. You can see the full listing in the gc_copying.cpp file.

After you completed coding the garbage collector, you can build a GC dynamic library, as described above, by typing

-
-
-
build$ build.bat -DCOMPONENTS=vm.gc_copying
-
- -

4. Running VM with the custom GC

-
+ +
build$ build.bat -DCOMPONENTS=vm.gc_copying
+ +
+

+ 5. Running the VM with the Custom GC +

+

This section describes how to run the DRL virtual machine with the custom garbage collector library.

You can specify the name of the dynamic library on the command line. For -example, to load a GC gc_copying.dll, execute the following:

-
-
-
ij -Dvm.dlls=gc_copying Hello
-
-

The virtual machine searches for a dynamic library gc_copying.dll in the +example, to load a GC gc_copying.dll, execute the following:

+ +
ij -Dvm.dlls=gc_copying Hello
+ +

The virtual machine searches for a dynamic library gc_copying.dll in the default locations, that is, the value for the PATH variable and the location of -executable ij.exe. -The default garbage collector is gc.dll located in the same bin/ directory as ij.exe.

- - - - - -
+

Back to top

+ + @@ -1543,6 +1288,3 @@ - - -