[vmkit-commits] [PATCH] Various patches

Nicolas Geoffray nicolas.geoffray at gmail.com
Sun Oct 23 23:27:36 PDT 2011


Are the patches attached the patches outstanding? I'm a little confused :)
Could you send one email per patch, and inline the patch int the email? I
think that will make things easier :)

In any case, here are some comments on the Unsafe implementation:

>From 77cb613be0277291c9b5592ea9548e52a608c42a Mon Sep 17 00:00:00 2001
From: Will Dietz <w at wdtz.org>
Date: Fri, 14 Oct 2011 06:07:15 -0500
Subject: [PATCH] Implement a number of Java.sun.misc.Unsafe.* methods.

Overall these implementations are generally weak robustness-wise.
---
 lib/J3/Classpath/Classpath.inc |  178
++++++++++++++++++++++++++++++++++++++++
 1 files changed, 178 insertions(+), 0 deletions(-)

diff --git a/lib/J3/Classpath/Classpath.inc b/lib/J3/Classpath/Classpath.inc
index 792b606..e7bc2c4 100644
--- a/lib/J3/Classpath/Classpath.inc
+++ b/lib/J3/Classpath/Classpath.inc
@@ -15,6 +15,7 @@
 #include "JavaThread.h"
 #include "JavaUpcalls.h"
 #include "Jnjvm.h"
+#include "Reader.h"


 using namespace j3;
@@ -359,6 +360,183 @@ JavaObject* unsafe, JavaObject* obj, jlong offset,
JavaObject* value) {
   mvm::Collector::objectReferenceWriteBarrier((gc*)obj, (gc**)ptr,
(gc*)value);
 }

+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_allocateMemory(
+JavaObject* unsafe, jlong size) {
+  // TODO: Invalid size/OOM/etc handling!
+  jlong res = 0;
+  BEGIN_NATIVE_EXCEPTION(0)
+  res = (jlong)malloc(size);
+  END_NATIVE_EXCEPTION
+  return res;
+}
+
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_freeMemory(
+JavaObject* unsafe, jlong ptr) {
+  // TODO: Exception handling...
+  BEGIN_NATIVE_EXCEPTION(0)
+  free((void*)ptr);
+  END_NATIVE_EXCEPTION
+}
+
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__JJ(
+JavaObject* unsafe, jlong ptr, jlong value) {
+  BEGIN_NATIVE_EXCEPTION(0)
+  *(jlong*)ptr = value;
+  END_NATIVE_EXCEPTION
+}
+
+JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByte__J(
+JavaObject* unsafe, jlong ptr) {
+  jbyte res = 0;
+  BEGIN_NATIVE_EXCEPTION(0)
+  res =  *(jbyte*)ptr;
+  END_NATIVE_EXCEPTION
+
+  return res;
+}
+
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_ensureClassInitialized(
+JavaObject* unsafe, JavaObject* clazz) {
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(clazz, 0);
+  BEGIN_NATIVE_EXCEPTION(0)
+
+  Jnjvm* vm = JavaThread::get()->getJVM();
+
+  CommonClass * cl = JavaObject::getClass(clazz);
+  assert(cl && cl->isClass());
+  cl->asClass()->initialiseClass(vm);
+
+  END_NATIVE_EXCEPTION;
+}
+
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_staticFieldOffset(
+JavaObject* unsafe, JavaObjectField* _field) {
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(_field, 0);
+
+  jlong res = 0;
+  BEGIN_NATIVE_EXCEPTION(0)
+
+  JavaField * field = JavaObjectField::getInternalField(_field);
+  assert(field);
+
+  res = field->ptrOffset;
+
+  END_NATIVE_EXCEPTION;
+
+  return res;
+}
+
+JNIEXPORT JavaObject* JNICALL Java_sun_misc_Unsafe_staticFieldBase(
+JavaObject* unsafe, JavaObjectField* _field) {
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(_field, 0);
+  JavaObject* res = 0;
+  BEGIN_NATIVE_EXCEPTION(0)
+
+  JavaField * field = JavaObjectField::getInternalField(_field);
+  assert(field);
+  field->classDef->initialiseClass(JavaThread::get()->getJVM());
+
+  res = (JavaObject*)field->classDef->getStaticInstance();

Unfortunately, this does not work. The static instance of a class is a
malloc'ed memory, not allocated by the GC. I looked at the comments in
Unsafe.java, saying that it's fine for the method to return something that
is not an object, but that is plain.... evil!

It looks like we have two options:
1) Return a dummy Object, that the 'put' and 'get' methods check for. The
dummy Object is specific to the VM, and contains a reference to the static
instance.
2) Make the static instance a GC-allocated object.

Both cases are tricky to implement. The first one has the advantage to be
localized: you don't need to change code in the existing code base. The
second one does need lots of changes in the existing code base, including in
the JIT which assumes that a static instance is a non-heap object.

Therefore, I would go with option 1). Take a look at the VMClassLoader class
in JnjvmClassLoader.h to see how that works. We fake up a Java Object, that
will be scanned by the GC. In your case, it looks like in order to stay
valid, the object must make sure that the class is not garbage collected.

+
+  END_NATIVE_EXCEPTION;
+
+  return res;
+}
+
+JNIEXPORT JavaObject* JNICALL Java_sun_misc_Unsafe_getObjectVolatile(
+JavaObject* unsafe, JavaObject* base, jlong offset) {
+  JavaObject * res = 0;
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(base, 0);
+  llvm_gcroot(res, 0);
+
+  BEGIN_NATIVE_EXCEPTION(0)
+  JavaObject** ptr = (JavaObject**) (((uint8 *) base) + offset);
+  res = *ptr;
+  END_NATIVE_EXCEPTION;
+
+  return res;
+}
+
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_arrayBaseOffset(
+JavaObject* unsafe, JavaObject* clazz) {
+  // TODO: Implement me
+  return 0;
+}
+
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_arrayIndexScale(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+JavaObject* unsafe, JavaObject* clazz) {
+  // TODO: Implement me
+  return 0;
+}
+
+JNIEXPORT JavaObject* JNICALL
Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2(
+JavaObject* unsafe, JavaString *name, ArrayObject * bytesArr, jint off,
jint len, JavaObject * loader, JavaObject * pd) {
+  JavaObject* res = 0;
+  llvm_gcroot(res, 0);
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(name, 0);
+  llvm_gcroot(bytesArr, 0);
+  llvm_gcroot(loader, 0);
+  llvm_gcroot(pd, 0);
+  BEGIN_NATIVE_EXCEPTION(0)
+
+  Jnjvm* vm = JavaThread::get()->getJVM();
+  JnjvmClassLoader* JCL = NULL;
+  JCL = JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm);
+
+  jint last = off + len;
+  if (last < bytesArr->size) {
+    assert(0 && "What exception to throw here?");
+  }
+  ClassBytes * bytes = new (JCL->allocator, len) ClassBytes(len);
+  memcpy(bytes->elements, JavaArray::getElements(bytesArr)+off, len);
+  const UTF8* utfName = JavaString::javaToInternal(name, JCL->hashUTF8);
+  UserClass *cl = JCL->constructClass(utfName, bytes);
+
+  if (cl) res = (JavaObject*)cl->getClassDelegatee(vm);
+
+  END_NATIVE_EXCEPTION;
+
+  return res;
+}
+
+JNIEXPORT JavaObject* JNICALL
Java_sun_misc_Unsafe_allocateInstance__Ljava_lang_Class_2(
+JavaObject* unsafe, JavaObjectClass * clazz) {
+  JavaObject* res = 0;
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(clazz, 0);
+  llvm_gcroot(res, 0);
+
+  BEGIN_NATIVE_EXCEPTION(0)
+
+  JavaThread* th = JavaThread::get();
+  Jnjvm* vm = th->getJVM();
+
+  UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz,
true);
+  if (cl->isClass())
+    res = cl->asClass()->doNew(vm);
+
+  END_NATIVE_EXCEPTION;
+
+  return res;
+}
+
+
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_throwException(
+JavaObject* unsafe, JavaObject * obj) {
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(obj, 0);
+
+  JavaThread::get()->pendingException = obj;
+}
+
 // TODO: Add the Volatile variants
 #define GET_PUT_OFFSET(Type,jtype,shorttype) \
 JNIEXPORT jtype JNICALL Java_sun_misc_Unsafe_get ## Type ##
__Ljava_lang_Object_2J( \
-- 
1.7.5.1



On Mon, Oct 24, 2011 at 12:53 AM, Will Dietz <willdtz at gmail.com> wrote:

> Sorry for the noise, just to try to stay on top of things (maybe
> sending all these patches in 1 thread was a bad idea...I was trying to
> *avoid* unnecessary clutter!)
>
> Patches outstanding:
>
> 4 (updated version attached addressing cast, printf, and NATIVE_JNI
> issues mentioned)
>
> 5, 6 --approved as-is, should I commit these?
>
> 7-- the "+1" is unnecessary as far as I can tell upon looking into it
> further--the function should return the strlen, not the space needed
> for a buffer containing the string.  Sorry for the confusion.  Updated
> version also attached.
>
> 8-- the registerNatives patch, which was sent in previous email.
>
> Thanks again! :)
>
> ~Will
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/vmkit-commits/attachments/20111024/24a8cf12/attachment.html>


More information about the vmkit-commits mailing list