#include "config.h"
+#include <assert.h>
#include <stdint.h>
+#if defined(ENABLE_GC_CACAO)
+# include "threads/thread.hpp"
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
#include "vm/global.h"
#include "vm/method.h"
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+
+class GC {
+public:
+ // Critical section functions.
+ static void critical_enter(void);
+ static void critical_leave(void);
+};
+
+extern "C" {
+#endif
+
/* reference types ************************************************************/
#ifdef __cplusplus
}
+
+/**
+ * Enters a LLNI critical section which prevents the GC from moving
+ * objects around on the collected heap.
+ *
+ * There are no race conditions possible while entering such a critical
+ * section, because each thread only modifies its own thread local flag
+ * and the GC reads the flags while the world is stopped.
+ */
+inline void GC::critical_enter()
+{
+#if defined(ENABLE_GC_CACAO)
+ threadobject *t;
+
+ t = THREADOBJECT;
+ assert(!t->gc_critical);
+ t->gc_critical = true;
+#endif
+}
+
+/**
+ * Leaves a LLNI critical section and allows the GC to move objects
+ * around on the collected heap again.
+ */
+inline void GC::critical_leave()
+{
+#if defined(ENABLE_GC_CACAO)
+ threadobject *t;
+
+ t = THREADOBJECT;
+ assert(t->gc_critical);
+ t->gc_critical = false;
+#endif
+}
+
#endif
#endif /* _GC_HPP */
{
java_object_t* o;
T result;
-
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
+
+ GC::critical_enter();
// XXX This should be _handle->get_object();
o = LLNI_UNWRAP(h);
result = raw_get<T>(o, offset);
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+ GC::critical_leave();
return result;
-}
+}
template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
{
java_object_t* o;
java_object_t* result;
java_handle_t* hresult;
-
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
+
+ GC::critical_enter();
// XXX This should be _handle->get_object();
o = LLNI_UNWRAP(h);
hresult = LLNI_WRAP(result);
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+ GC::critical_leave();
return hresult;
}
{
java_object_t* o;
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
+ GC::critical_enter();
// XXX This should be h->get_object();
o = LLNI_UNWRAP(h);
raw_set(o, offset, value);
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+ GC::critical_leave();
}
template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
java_object_t* o;
java_object_t* ovalue;
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
+ GC::critical_enter();
// XXX This should be h->get_object();
o = LLNI_UNWRAP(h);
raw_set(o, offset, ovalue);
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+ GC::critical_leave();
}
inline vftbl_t* java_lang_Object::get_vftbl() const
{
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
+ GC::critical_enter();
// XXX This should be h->get_object();
java_object_t* o = LLNI_UNWRAP(_handle);
vftbl_t* vftbl = o->vftbl;
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+ GC::critical_leave();
return vftbl;
}