blob: 8b67f6c39bf7e9a3c05745e2bc78537049a11579 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _OBJECT_HANDLES_H
#define _OBJECT_HANDLES_H
/**
* @file
* This module manages object handles and other forms of GC root protection. It is
* not exposed outside VM - other modules should use pure JNI instead.
*
* There are three managed pointer protection facilities:
* 1) Object handles on M2nFrames
* 2) Native object handles
* 3) GC frames
* GC frames are C++ objects that protect object references and managed pointers directly.
* A function can set up a GC frame to protect its references and then pass those references
* to functions it calls.
* Handles protect indirectly.
* A function creates handles for the references and passes the handles rather than the references.
*/
#include "vm_core_types.h"
#include "object_layout.h"
#include "jni.h"
/**
* GC frames store memory locations which contain managed pointers, so they are updated
* during garbage collection. Note, GC suspension must be disabled when created or deleting
* a frame and when adding objects or managed pointers.
*/
#define GC_FRAME_DEFAULT_SIZE 10
class GcFrame {
public:
GcFrame();
~GcFrame();
void add_object(ManagedObject**);
void add_managed_pointer(ManagedPointer*);
// Enumerate all roots being protected including those of subsequent frames.
void enumerate();
private:
void ensure_capacity();
// A GcFrameNode contains capacity elements which can hold either objects references or managed pointers.
// The objects come first, ie, from index 0 to obj_size-1
// The managed pointers come last, ie, from index obj_size to obj_size+mp_size-1
// Inv: obj_size+mp_size<=capacity
struct GcFrameNode {
unsigned obj_size, mp_size, capacity;
GcFrameNode* next;
void** elements[GC_FRAME_DEFAULT_SIZE]; // Objects go several first, then managed pointers
} firstSetOfNodes;
GcFrameNode* nodes;
GcFrame* next;
};
//////////////////////////////////////////////////////////////////////////
// Handles
// GC must be disabled when object is set, and the object loaded from object
// is only valid while GC is disabled.
// FIXME will be empty as in JNI
struct _jobject { ManagedObject* object; };
typedef jobject ObjectHandle;
///**
// * Reference to an object.
// */
//struct _ObjectHandle {
// ManagedObject* object;
//};
//
///**
// * Internal object handle. The difference with <code>jobject</code> is
// * <code>jobject</code> can be passed to user JNI code and freed by
// * <code>DeleteLocalRef</code>.
// */
//typedef const struct _ObjectHandle* ObjectHandle;
//
///**
// * Reference to an instance of <code>java.lang.Class</code>.
// */
//struct _ClassHandle: _ObjectHandle {};
//
///**
// * <code>ObjectHandle</code> which refers to a class.
// */
//typedef const struct _ClassHandle* ClassHandle;
#ifndef NDEBUG
/**
* Checks if an object is exactly <code>java.lang.Class.class</code>.
* This function must be called when GC suspension is disabled.
*/
bool
managed_object_is_java_lang_class(ManagedObject*);
/**
* Checks if an object is exactly <code>java.lang.Class.class</code>.
* This function must be called when GC suspension is enabled.
*/
bool
object_is_java_lang_class(ObjectHandle);
/**
* Checks if an object's virtual table points to the correct class.
* This function must be called when GC suspension is disabled.
*/
bool
managed_object_is_valid(ManagedObject*);
/**
* Checks if an object's virtual table points to the correct class.
* This function must be called when GC suspension is enabled.
*/
bool
object_is_valid(ObjectHandle);
#endif /* NDEBUG */
/*
* Global handles
*/
/**
* Creates global handle, which needs to be explicitly freed.
*/
ObjectHandle oh_allocate_global_handle();
ObjectHandle oh_allocate_global_handle_from_jni();
/**
* Frees global handle.
*/
void oh_deallocate_global_handle(ObjectHandle);
/**
* Called during root enumeration process to enumerate global handles.
*/
void oh_enumerate_global_handles();
/*
* Weak global handles
*/
/**
* Creates weak global handle, which needs to be explicitly freed.
*/
ObjectHandle oh_allocate_weak_global_handle_from_jni();
/**
* Frees weak global handle.
*/
void oh_deallocate_weak_global_handle(ObjectHandle);
/* For interface simplicity, weak global handles are also enumerated in function oh_enumerate_global_handles */
//////////////////////////////////////////////////////////////////////////
// Local Handles
// Local handles are stored in either M2nFrames or in native object handles
// structures. The most recent such frame or structure is used for allocation.
// M2nFrame handles are freed when the frame is popped. Native object handles
// are freed upon exit from the scope that declared the native object handles
// structure. Handles are invalid and should not be used after they are freed.
VMEXPORT // temporary solution for interpreter unplug
ObjectHandle oh_allocate_local_handle();
ObjectHandle oh_allocate_local_handle_from_jni();
ObjectHandle oh_convert_to_local_handle(ManagedObject* pointer);
ObjectHandle oh_copy_to_local_handle(ObjectHandle oh);
// The following function invalidates a local handle and allows (at next GC) the collection
// of the object if it is now garbage.
void oh_discard_local_handle(ObjectHandle);
struct ObjectHandles;
VMEXPORT // temporary solution for interpreter unplug
void oh_enumerate_handles(ObjectHandles*);
void oh_free_handles(ObjectHandles*);
//VMEXPORT // temporary solution for interpreter unplug
class VMEXPORT NativeObjectHandles {
public:
NativeObjectHandles();
~NativeObjectHandles();
// Allocate a handle in this structure
ObjectHandle allocate();
// Enumerate all handles in this and subsequent structures
void enumerate();
private:
friend void oh_discard_local_handle(ObjectHandle);
ObjectHandles* handles;
NativeObjectHandles* next;
};
//////////////////////////////////////////////////////////////////////////
// Routines for creating handles in stubs
// Fill ObjectHandles sructure as empty.
void oh_null_init_handles(ObjectHandles* handles);
// Add to a LIL code stub code to allocate space for handles structures
// This LIL code will initialise the structures except for the actual object references, and will
// set the handles pointer in the M2nFrame
// number_handles - Number of handles to allocate space for
// base_var - LIL variable to hold pointer to base of handles structure
// helper_var - LIL variable to use to initialise structure
LilCodeStub* oh_gen_allocate_handles(LilCodeStub*, unsigned number_handles, const char* base_var, const char* helper_var);
// Calculate the offset of the base of a previously allocated structure to a particular handle
// The base variable (see oh_gen_allocate_handles) plus this offset is the value to use for the handle
POINTER_SIZE_INT oh_get_handle_offset(unsigned handle_indx);
// Initialise a handle in a previously allocated structure
// base_var - LIL variable that points to the base of the handles structure
// handle_indx - Index of handle to initialise
// val - LIL operand for the object reference to use to initialise handle
// null_check - If true check for a managed null and store an unmanaged null instead
LilCodeStub* oh_gen_init_handle(LilCodeStub*, const char* base_var, unsigned handle_indx, const char* val, bool null_check);
//////////////////////////////////////////////////////////////////////////
// 20031218: Needed for old stub code
// To be deprecated soon - do not use in new code!
struct ObjectHandlesOld {
_jobject handle;
ObjectHandlesOld* prev;
ObjectHandlesOld* next;
bool allocated_on_the_stack;
};
struct ObjectHandlesNew {
#ifdef _IPF_
U_32 capacity;
U_32 size;
#else //IA32
uint16 capacity;
uint16 size;
#endif //IA32
ObjectHandlesNew* next;
ManagedObject* refs[1];
};
// free and delete all local object handles
VMEXPORT // temporary solution for interpreter unplug
void free_local_object_handles2(ObjectHandles*);
void free_local_object_handles3(ObjectHandles*);
#endif // _OBJECT_HANDLES