The direct memory interface

The direct memory interface reference

Introduction

This document is the reference manual for the direct memory layer functions. These functions are used for accessing object and array fields, and also deal with GC-safe points. Please refer to How to be GC-safe in CVM for context and examples.

WARNING: The use of the direct heap access operations is GC-unsafe. Therefore, these operations should be used with extreme care in a few select places, and only within GC-unsafe regions. VM code should use the indirect memory layer almost all the time when outside the interpreter.

Table of Contents

Object field accesses

The following macros access object fields. The result-producing ones take an l-value as the last argument, and assign to it.

Accessing fields of 32-bit width

In these macros, the first parameter is a direct object reference, the second is an offset in number of words from the beginning of the object, counting the first header word as 0, and the third is an l-value to read into or a value to write.

Note that the implementation of GC read and write barriers are hidden beneath the Ref typed accessors.

Weakly-typed 32-bit read and write:

    macro void CVMD_fieldRead32( CVMObject* o, CVMUint32 off, CVMJavaVal32 res)
    macro void CVMD_fieldWrite32(CVMObject* o, CVMUint32 off, CVMJavaVal32 res)

Strongly-typed 32-bit read and write:

    macro void CVMD_fieldReadRef(    CVMObject* o, CVMUint32 off, CVMObject* item)
    macro void CVMD_fieldWriteRef(   CVMObject* o, CVMUint32 off, CVMObject* item)

    macro void CVMD_fieldReadInt(    CVMObject* o, CVMUint32 off, CVMJavaInt item)
    macro void CVMD_fieldWriteInt(   CVMObject* o, CVMUint32 off, CVMJavaInt item)

    macro void CVMD_fieldReadFloat(  CVMObject* o, CVMUint32 off, CVMJavaFloat item)
    macro void CVMD_fieldWriteFloat( CVMObject* o, CVMUint32 off, CVMJavaFloat item)

Accessing fields of 64-bit width

In these macros, the first parameter is a direct object reference, the second is an offset in number of words from the beginning of the object, counting the first header word as 0, and the third is an l-value of type CVMJavaVal64 to read into or a value to write.

The weakly-typed versions read from and write into a word-aligned two-word area pointed to by location.

Weakly-typed 64-bit read and write:

    macro void CVMD_fieldRead64(   CVMObject* o, CVMUint32 off, CVMJavaVal32* location)
    macro void CVMD_fieldWrite64(  CVMObject* o, CVMUint32 off, CVMJavaVal32* location)

Strongly-typed 64-bit read and write:

    macro void CVMD_fieldReadLong(   CVMObject* o, CVMUint32 off, CVMJavaVal64 val64)
    macro void CVMD_fieldWriteLong(  CVMObject* o, CVMUint32 off, CVMJavaVal64 val64)

    macro void CVMD_fieldReadDouble( CVMObject* o, CVMUint32 off, CVMJavaVal64 val64)
    macro void CVMD_fieldWriteDouble(CVMObject* o, CVMUint32 off, CVMJavaVal64 val64)

Array accesses

The following macros access object fields. The result-producing ones take an l-value as the last argument, and assign to it.

Accessing elements of 32-bit width and below

In these macros, the first parameter is a direct array reference, the second is the array index where the first array element is at index 0, and the third is an l-value to read into, or a value to write.

These macros are all strongly typed. All the Java basic types are represented.

Note that the implementation of GC read and write barriers are hidden beneath the Ref typed accessors.

    macro void CVMD_arrayReadRef(    CVMArrayOfRef* arr,   CVMUint32 index, CVMObject* item)
    macro void CVMD_arrayWriteRef(   CVMArrayOfRef* arr,   CVMUint32 index, CVMObject* item)

    macro void CVMD_arrayReadInt(    CVMArrayOfInt* arr,   CVMUint32 index, CVMJavaInt item)
    macro void CVMD_arrayWriteInt(   CVMArrayOfInt* arr,   CVMUint32 index, CVMJavaInt item)

    macro void CVMD_arrayReadByte(   CVMArrayOfByte* arr,  CVMUint32 index, CVMJavaByte item)
    macro void CVMD_arrayWriteByte(  CVMArrayOfByte* arr,  CVMUint32 index, CVMJavaByte item)

    macro void CVMD_arrayReadBool(   CVMArrayOfBool* arr,  CVMUint32 index, CVMJavaBool item)
    macro void CVMD_arrayWriteBool(  CVMArrayOfBool* arr,  CVMUint32 index, CVMJavaBool item)

    macro void CVMD_arrayReadShort(  CVMArrayOfShort* arr, CVMUint32 index, CVMJavaShort item)
    macro void CVMD_arrayWriteShort( CVMArrayOfShort* arr, CVMUint32 index, CVMJavaShort item)

    macro void CVMD_arrayReadChar(   CVMArrayOfChar*  arr, CVMUint32 index, CVMJavaChar item)
    macro void CVMD_arrayWriteChar(  CVMArrayOfChar*  arr, CVMUint32 index, CVMJavaChar item)

    macro void CVMD_arrayReadFloat(  CVMArrayOfFloat* arr, CVMUint32 index, CVMJavaFloat item)
    macro void CVMD_arrayWriteFloat( CVMArrayOfFloat* arr, CVMUint32 index, CVMJavaFloat item)

Accessing elements of 64-bit width

In these macros, the first parameter is a direct array reference, the second is the array index where the first array element is at index 0, and the third is an l-value of type CVMJavaVal64 to read into or a value to write.

The weakly-typed versions read from and write to a word-aligned two-word area pointed to by location:

    macro void CVMD_arrayRead64(   <CVMArrayOf64>* o, CVMUint32 off, CVMJavaVal32* location)
    macro void CVMD_arrayWrite64(  <CVMArrayOf64>* o, CVMUint32 off, CVMJavaVal32* location)
where <CVMArrayOf64> is either CVMArrayOfLong or CVMArrayOfDouble.

Strongly-typed versions:

    macro void CVMD_arrayReadLong(   <CVMArrayOf64>* o, CVMUint32 index, CVMJavaVal64 val64)
    macro void CVMD_arrayWriteLong(  <CVMArrayOf64>* o, CVMUint32 index, CVMJavaVal64 val64)

    macro void CVMD_arrayReadDouble( <CVMArrayOf64>* o, CVMUint32 index, CVMJavaVal64 val64)
    macro void CVMD_arrayWriteDouble(<CVMArrayOf64>* o, CVMUint32 index, CVMJavaVal64 val64)
where <CVMArrayOf64> is either CVMArrayOfLong or CVMArrayOfDouble.

Miscellaneous array operations

All generic object operations apply to arrays as well. In particular, the header of an array object starts out with an object header, with an additional length entry, so any operation on the header of an object may be performed on an array header.

Below are array-specific operations.

Getting the length of an array:

    macro CVMJavaInt32 CVMD_arrayGetLength(<CVMArrayOfAny>* o)
where <CVMArrayOfAny> is any direct array reference.

GC-safety of threads

Each thread has a GC-safety state associated with it. Threads that cannot tolerate GC are marked as GC-unsafe. A thread whose state can be scanned by GC is marked GC-safe. GC can occur only when all threads in the system are GC-safe. When a thread requests GC, all threads that are currently GC-unsafe are rolled forward to their next GC-safe point.

Here are a couple of operations to create GC-unsafe windows of operation, and to request GC-safe points.

GC-unsafe blocks

When a GC-safe thread wants to perform a GC-unsafe operation, it marks itself as unable to tolerate GC, performs the GC-unsafe operation, and then marks itself again as GC-safe. CVMD_gcUnsafeExec() is the way to create such a window of GC-unsafety. At the end of the GC-unsafe window, the thread calling CVMD_gcUnsafeExec() polls for a GC request. If there is one, the thread suspends itself to rendezvous with all the other threads rolling forward to their GC points. Execution continues after GC.
    macro void CVMD_gcUnsafeExec(CVMExecEnv* ee, code gcUnsafeAction)
where ee is a pointer to the current thread's execution environment, and gcUnsafeAction is a segment of GC-unsafe code.

GC-safe blocks: Requesting a GC-safe point

GC-unsafe code must occasionally offer to become GC-safe to bound the time from a GC request to the beginning of GC. CVMD_gcSafeExec and CVMD_gcSafeCheckPoint are the two macros that allow that.

The first macro is used for code that will not block. The assumption here is that there is some cached state in the GC-unsafe code which needs to be saved if GC is needed.

    macro void CVMD_gcSafeCheckPoint(CVMExecEnv* ee, code saveAction, code restoreAction)
The thread calling CVMD_gcSafeCheckPoint() checks whether there is a GC request. If there is, the thread executes saveAction to save state necessary for GC, marks itself as GC-safe, and suspends itself to rendezvous with all the other threads rolling forward to their GC points. After GC completes, the thread is resumed, marks itself as GC-unsafe again, and executes restoreAction to do any caching operations necessary to continue execution.

The second macro is used for code that may potentially block. In this case, whatever cached state the GC-unsafe code has must be saved before calling the macro.

    macro void CVMD_gcSafeExec(CVMExecEnv* ee,
                               code saveAction,
                               code safeAction,
                               code restoreAction)
The thread calling CVMD_gcSafeExec() executes saveAction unconditionally, marks itself GC-safe, and checks to see if there is a GC-request. If there is one, the thread suspends itself to rendezvous with all the other threads rolling forward to their GC points. After GC is over, the thread is resumed, still in a GC-safe state. It executes safeAction, potentially blocking. After waking up from the blocking action, the thread marks itself as GC-unsafe, and finally executes restoreAction to cache state and continues with GC-unsafe execution.