Native Code Interface Specification Previous
Previous
Native Code Interface
Native Code Interface
Next
Next

New Native Code interface

Implications for exisiting code , Implications and Benefits , Functions for GC

In the design of the native code interface in the Microsoft VM for Java, we have addressed many of the implications of prior interfaces as discussed above. Internally, object references are pointers directly to the object. The following diagram describes the internal storage details of objects within the Microsoft native code model.

A pointer to our object is a pointer directly to the method table pointer in the object which is located just under the Data. Directly above the method table (which is a different data structure than current implementations support) is the data. When the Microsoft VM calls native code, it calls the target function directly without going through stubs located in the DLL library. There are stubs, but they are optimized, CPU specific code generated by the VM.

For source code compatability and header compatability, this native code model does support unhand. All the unhand does is cast the handle it to a pointer (and add 4 to its address). In the future, we will have another version of unhand (such as ms_unhand) which won't do any arithmetic (but should still be used), there will also be another header file generator which knows that there is this extra method table element at the base and will create appropriate C structures representing this. This will ensure that everything is fully accessible.

Since the Microsoft VM does not conservatively garbage collect native stacks, if any native code has outstanding pointer references during a garbage collection, the same problems as with the current native code model could be encountered. To remedy this while still providing maximum speed/minimum overhead, we have defined conventions to ensure a deterministic, low overhead solution with respect to outstanding native code pointers. These conventions rely on the fact that native code is responsible for enabling/disabling garbage collection as necessary, and informing the VM of locations in memory where object pointers exist.


Implications for exisiting code

This new native code interface is not binary compatible with the current interface. Existing Java applications that use the native keyword will need to consider the use they make of native code and how long they will be in native code functions. If you just call native code and return, it's OK to leave source code as it was in the previous model. If you're going to do block or take an undetermined amount of time to perform some task before returning to the VM, then you need to ensure that you allow GC. By default, garbage collection is turned off when you enter native code.


Implications and Benefits


Benefit : performance improvement

The target method is called directly from the VM. On the fly, the VM creates an assembler stub which sets up a frame appropriate for the calling convention of the current machine architecture. The process is as follows (the pushes are needed to transpose calling conventions)
setup native frame
push
push
push
call native method

In a way, this is similar to what happens in the existing native code interface, but it's carried out in a highly optimized form within the VM. This allows the VM to share stubs among similar methods and reduce working set, or optimize absolutely for speed. In either case, the native code libraries themselves can be smaller because they don't contain additional code for parameter unwrapping.


Benefit :  VM chooses optimizations, performance improvement.

Benefit : performance improvement

Benefit : performance improvement

C code is just as portable as before. For the existing native code interface, there's less machine specific code within the VM to support the model, but there's always porting work required. Stubs are duplicated in every library (DLL or equivalent).


Functions for GC

In order to allow the control over the garbage collector by libraries using the new native code interface, the following functions are defined.


void enable_gc ();

If you're going to block for any length of time, or if you know you don't have any pointers that you care about, or those pointers have been wrapped in handles or GC frames, then you can call enable_gc(). This allows the GC to operate if necessary. If you're going to block, you're forced to wrap your pointers in handles or GC frames (see push_gc_frame and create_gc_handle below). Internally, enable_gc decrements the GC block count. If some thread calls enable_gc, it means that they're not preventing a garbage collection from occuring. However, a call to enable_gc doesn't necessarily cause garbage collection to occur.


void disable_gc ();

Increments GC block count and prevents GC from occurring.


BOOL check_gc ();

Returns TRUE if a GC occured during this call. This allows code to optimize its reloading of pointers. This can be used in strategic areas where code may be disabling GC for extended periods of time. Calling check_gc doesn't force a GC to occur, it just allows GC to happen if it is needed. Equivalent to decrement the GC block count, blocks if necessary to allow GC, then increments the block count.


DWORD get_gc_disable_count ();

Used for diagnostic purposes. Since enable_gc/disable_gc uses a counter, this provides a way to verify that the count is what is expected.


VOID push_gc_frame (CGCFrame *pGCF, VOID *pObjArr, DWORD size);

As mentioned above, pointers can be wrapped in handles or GCFrames. push_gc_frame packages up a number of pointers into a structure, which causes the pointers to be added to the root set for the garbage collector. This is a way of avoiding creating handles for them individually, so that whenever objects are moved due to garbage collection, the pointers in a CGCFrame will be updated to point to the new locations of the objects. CGCFrame is an abstract structure which is controlled by the VM.


VOID pop_gc_frame (CGCFrame);

Undoes the effect of the corresponding push_gc_frame. This is required to clear the stack of existing GC frames.


GCHANDLE create_gc_handle (Hobject *phObj);

Registers a single pointer with the garbage collector and returns a pointer to the registered pointer. The original variable passed is not automatically updated as objects are moved, but the updated value can be obtained by indirecting through the GCHANDLE.


VOID close_gc_handle (GCHANDLE gch);

Unregisters a handle created with create_gc_handle. This must be called in order to allow the garbage collector to free the object referenced by a handle.

GCFrames are nested on stack frames, and hence must be popped before you leave the stack frame. Handles are more long lived entities, but allow only for a single object reference per handle. The developer should select the most appropriate for the native code that is being written.

Top© 1996 Microsoft Corporation. All rights reserved.