[vmkit-commits] [vmkit] r144125 - in /vmkit/trunk/lib/J3: ClassLib/Classpath.inc ClassLib/VMStaticInstance.h Compiler/JavaAOTCompiler.cpp Compiler/Makefile VMCore/Jnjvm.cpp VMCore/Makefile VMCore/VirtualTables.cpp

Will Dietz wdietz2 at illinois.edu
Tue Nov 8 13:44:19 PST 2011


Author: wdietz2
Date: Tue Nov  8 15:44:19 2011
New Revision: 144125

URL: http://llvm.org/viewvc/llvm-project?rev=144125&view=rev
Log:
Implement a number of Java.sun.misc.Unsafe.* methods.

Of particular interest is the addition of VMStaticInstance, used to
enable us to return a reference to a static instance, even though a
static instance isn't a heap object (and prevents the underlying
static instance from being GC'd while this reference is live).

This is required for us to support staticFieldBase/staticFieldOffset.

Added:
    vmkit/trunk/lib/J3/ClassLib/VMStaticInstance.h
Modified:
    vmkit/trunk/lib/J3/ClassLib/Classpath.inc
    vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp
    vmkit/trunk/lib/J3/Compiler/Makefile
    vmkit/trunk/lib/J3/VMCore/Jnjvm.cpp
    vmkit/trunk/lib/J3/VMCore/Makefile
    vmkit/trunk/lib/J3/VMCore/VirtualTables.cpp

Modified: vmkit/trunk/lib/J3/ClassLib/Classpath.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/ClassLib/Classpath.inc?rev=144125&r1=144124&r2=144125&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/ClassLib/Classpath.inc (original)
+++ vmkit/trunk/lib/J3/ClassLib/Classpath.inc Tue Nov  8 15:44:19 2011
@@ -15,12 +15,23 @@
 #include "JavaThread.h"
 #include "JavaUpcalls.h"
 #include "Jnjvm.h"
+#include "Reader.h"
+#include "VMStaticInstance.h"
 
 
 using namespace j3;
 
 extern "C" {
 
+// Convert a 'base' JavaObject to its pointer representation.
+// Handles our special VMStaticInstance wrapper.
+static inline uint8 *baseToPtr(JavaObject *base) {
+  if (VMStaticInstance::isVMStaticInstance(base))
+    return (uint8*)((VMStaticInstance*)base)->getStaticInstance();
+  else
+    return (uint8*)base;
+}
+
 // Define hasClassInitializer because of a buggy implementation in Classpath.
 JNIEXPORT bool JNICALL Java_java_io_VMObjectStreamClass_hasClassInitializer(
 #ifdef NATIVE_JNI
@@ -359,6 +370,185 @@
   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()->resolveClass();
+  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) {
+  JavaObject* res = 0;
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(_field, 0);
+  llvm_gcroot(res, 0);
+  BEGIN_NATIVE_EXCEPTION(0)
+
+  JavaField * field = JavaObjectField::getInternalField(_field);
+  assert(field);
+  field->classDef->initialiseClass(JavaThread::get()->getJVM());
+
+  res = VMStaticInstance::allocate(field->classDef);
+
+  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**) (baseToPtr(base) + offset);
+  res = *ptr;
+  END_NATIVE_EXCEPTION;
+
+  return res;
+}
+
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_arrayBaseOffset(
+JavaObject* unsafe, JavaObject* clazz) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_arrayIndexScale(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+JavaObject* unsafe, JavaObject* clazz) {
+  UNIMPLEMENTED();
+  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()->throwException(obj);
+}
+
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_registerNatives(JavaObject*) {
   // Nothing
 }
@@ -369,7 +559,7 @@
 JavaObject* unsafe, JavaObject* base, jlong offset) { \
   jtype res = 0; \
   BEGIN_NATIVE_EXCEPTION(0) \
-  jtype* ptr = (jtype*) (((uint8 *) base) + offset); \
+  jtype* ptr = (jtype*) (baseToPtr(base) + offset); \
   res = *ptr; \
   END_NATIVE_EXCEPTION \
  \
@@ -379,7 +569,7 @@
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_put ## Type ## __Ljava_lang_Object_2J ## shorttype( \
 JavaObject* unsafe, JavaObject* base, jlong offset, jtype val) { \
   BEGIN_NATIVE_EXCEPTION(0) \
-  jtype* ptr = (jtype*) (((uint8 *) base) + offset); \
+  jtype* ptr = (jtype*) (baseToPtr(base) + offset); \
   *ptr = val; \
   END_NATIVE_EXCEPTION \
 }

Added: vmkit/trunk/lib/J3/ClassLib/VMStaticInstance.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/ClassLib/VMStaticInstance.h?rev=144125&view=auto
==============================================================================
--- vmkit/trunk/lib/J3/ClassLib/VMStaticInstance.h (added)
+++ vmkit/trunk/lib/J3/ClassLib/VMStaticInstance.h Tue Nov  8 15:44:19 2011
@@ -0,0 +1,81 @@
+//===-------- VMStaticInstance.h - Java wrapper for a static instance------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_VMSTATICINSTANCE_H
+#define JNJVM_VMSTATICINSTANCE_H
+
+#include "ClasspathReflect.h"
+#include "JavaObject.h"
+#include "MvmGC.h"
+
+namespace j3 {
+
+/// VMStaticInstance - Used as a placeholder for a staticInstance, tracing to
+/// the corresponding Class to ensure it doesn't get improperly GC'd.
+/// This placeholder is used solely in getStaticFieldBase and the various
+/// put/get methods in sun.misc.Unsafe, any other use is invalid.
+/// Largely inspired by VMClassLoader.
+///
+class VMStaticInstance : public JavaObject {
+private:
+
+  /// OwningClass - The Class this is represents a static instance of.
+  Class * OwningClass;
+
+public:
+
+  static VMStaticInstance* allocate(Class * Class) {
+    VMStaticInstance* res = 0;
+    llvm_gcroot(res, 0);
+    llvm_gcroot(Class, 0);
+    res = (VMStaticInstance*)gc::operator new(sizeof(VMStaticInstance), &VT);
+    res->OwningClass = Class;
+
+    return res;
+  }
+
+  /// VT - The VirtualTable for this GC-class.
+  ///
+  static VirtualTable VT;
+
+  /// Is the object a VMStaticInstance object?
+  ///
+  static bool isVMStaticInstance(JavaObject* obj) {
+    llvm_gcroot(obj, 0);
+    return obj->getVirtualTable() == &VT;
+  }
+
+  /// ~VMStaticInstance - Nothing. Placeholder method
+  /// to give the VirtualTable.
+  ///
+  static void staticDestructor(VMStaticInstance* obj) {
+    llvm_gcroot(obj, 0);
+    // Nothing to do here
+  }
+
+  /// staticTracer - Trace through to our Class
+  ///
+  static void staticTracer(VMStaticInstance* obj, word_t closure) {
+    llvm_gcroot(obj, 0);
+    assert(obj->OwningClass);
+    obj->OwningClass->classLoader->tracer(closure);
+  }
+
+  /// getStaticInstance - Get the static instance contained in this object
+  ///
+  void * getStaticInstance() {
+    assert(OwningClass);
+    return OwningClass->getStaticInstance();
+  }
+
+};
+
+}
+
+#endif // JNJVM_VMSTATICINSTANCE_H

Modified: vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp?rev=144125&r1=144124&r2=144125&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp (original)
+++ vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp Tue Nov  8 15:44:19 2011
@@ -32,6 +32,7 @@
 #include "JavaUpcalls.h"
 #include "Jnjvm.h"
 #include "Reader.h"
+#include "VMStaticInstance.h"
 #include "Zip.h"
 
 #include <cstdio>
@@ -2545,7 +2546,9 @@
 
   for (; I != E; ++I) {
     JavaObject* obj = (JavaObject*)(*I);
-    if (!VMClassLoader::isVMClassLoader(obj) && JavaObject::instanceOf(obj, cl)) {
+    if (!VMClassLoader::isVMClassLoader(obj) &&
+        !VMStaticInstance::isVMStaticInstance(obj) &&
+        JavaObject::instanceOf(obj, cl)) {
       if (currentClass != NULL) {
         if (JavaObject::getClass(obj) != currentClass) {
           return 0;

Modified: vmkit/trunk/lib/J3/Compiler/Makefile
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/Compiler/Makefile?rev=144125&r1=144124&r2=144125&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/Compiler/Makefile (original)
+++ vmkit/trunk/lib/J3/Compiler/Makefile Tue Nov  8 15:44:19 2011
@@ -14,4 +14,4 @@
 
 include $(LEVEL)/Makefile.common
 
-CXX.Flags += -I$(PROJ_OBJ_DIR)/../LLVMRuntime -I$(PROJ_SRC_DIR)/../ClassLib/$(CLASSPATH_DIR) -I$(PROJ_SRC_DIR)/../VMCore
+CXX.Flags += -I$(PROJ_OBJ_DIR)/../LLVMRuntime -I$(PROJ_SRC_DIR)/../ClassLib/$(CLASSPATH_DIR) -I$(PROJ_SRC_DIR)/../ClassLib/ -I$(PROJ_SRC_DIR)/../VMCore

Modified: vmkit/trunk/lib/J3/VMCore/Jnjvm.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/VMCore/Jnjvm.cpp?rev=144125&r1=144124&r2=144125&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/VMCore/Jnjvm.cpp (original)
+++ vmkit/trunk/lib/J3/VMCore/Jnjvm.cpp Tue Nov  8 15:44:19 2011
@@ -35,6 +35,7 @@
 #include "LockedMap.h"
 #include "Reader.h"
 #include "ReferenceQueue.h"
+#include "VMStaticInstance.h"
 #include "Zip.h"
 
 using namespace j3;
@@ -1394,6 +1395,8 @@
   JavaObject* src = (JavaObject*)object;
   if (VMClassLoader::isVMClassLoader(src)) {
     size = sizeof(VMClassLoader);
+  } else if (VMStaticInstance::isVMStaticInstance(src)) {
+    size = sizeof(VMStaticInstance);
   } else {
     CommonClass* cl = JavaObject::getClass(src);
     if (cl->isArray()) {
@@ -1416,6 +1419,8 @@
   JavaObject* src = (JavaObject*)object;
   if (VMClassLoader::isVMClassLoader(src)) {
     return "VMClassLoader";
+  } else if (VMStaticInstance::isVMStaticInstance(src)) {
+    return "VMStaticInstance";
   } else {
     CommonClass* cl = JavaObject::getClass(src);
     // This code is only used for debugging on a fatal error. It is fine to

Modified: vmkit/trunk/lib/J3/VMCore/Makefile
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/VMCore/Makefile?rev=144125&r1=144124&r2=144125&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/VMCore/Makefile (original)
+++ vmkit/trunk/lib/J3/VMCore/Makefile Tue Nov  8 15:44:19 2011
@@ -14,4 +14,4 @@
 
 include $(LEVEL)/Makefile.common
 
-CXX.Flags += -I$(PROJ_OBJ_DIR)/../ClassLib -I$(PROJ_OBJ_DIR)/../LLVMRuntime -I$(PROJ_SRC_DIR)/../ClassLib/$(CLASSPATH_DIR) -I$(PROJ_SRC_DIR)/../../../include/j3
+CXX.Flags += -I$(PROJ_OBJ_DIR)/../ClassLib -I$(PROJ_OBJ_DIR)/../LLVMRuntime -I$(PROJ_SRC_DIR)/../ClassLib/$(CLASSPATH_DIR) -I$(PROJ_SRC_DIR)/../../../include/j3 -I$(PROJ_SRC_DIR)/../ClassLib

Modified: vmkit/trunk/lib/J3/VMCore/VirtualTables.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/VMCore/VirtualTables.cpp?rev=144125&r1=144124&r2=144125&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/VMCore/VirtualTables.cpp (original)
+++ vmkit/trunk/lib/J3/VMCore/VirtualTables.cpp Tue Nov  8 15:44:19 2011
@@ -32,6 +32,7 @@
 #include "JnjvmClassLoader.h"
 #include "LockedMap.h"
 #include "ReferenceQueue.h"
+#include "VMStaticInstance.h"
 #include "Zip.h"
 
 using namespace j3;
@@ -44,7 +45,7 @@
 // Having many GC classes gives more work to the GC for the scanning phase
 // and for the relocation phase (for copying collectors).
 //
-// In J3, there is only one internal gc object, the class loader.
+// In J3, there is only one primary internal gc object, the class loader.
 // We decided that this was the best solution because
 // otherwise it would involve hacks on the java.lang.Classloader class.
 // Therefore, we create a new GC class with a finalize method that will
@@ -52,12 +53,20 @@
 // not reachable anymore. This also relies on the java.lang.Classloader class
 // referencing an object of type VMClassLoader (this is the case in GNU
 // Classpath with the vmdata field).
+// In addition, to handle support for sun.misc.Unsafe, we have a similar
+// second clsas VMStaticInstance that wraps static instances for use
+// in staticFieldBase and traces the owning ClassLoader to make sure
+// the underlying instance and class don't get GC'd improperly.
 //===----------------------------------------------------------------------===//
 
 VirtualTable VMClassLoader::VT((word_t)VMClassLoader::staticDestructor,
                                (word_t)VMClassLoader::staticDestructor,
                                (word_t)VMClassLoader::staticTracer);
 
+VirtualTable VMStaticInstance::VT((word_t)VMStaticInstance::staticDestructor,
+                                  (word_t)VMStaticInstance::staticDestructor,
+                                  (word_t)VMStaticInstance::staticTracer);
+
 //===----------------------------------------------------------------------===//
 // Trace methods for Java objects. There are four types of objects:
 // (1) java.lang.Object and primitive arrays: no need to trace anything.





More information about the vmkit-commits mailing list