aboutsummaryrefslogtreecommitdiff
path: root/tests/nbody-java/xmlvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/nbody-java/xmlvm.c')
-rw-r--r--tests/nbody-java/xmlvm.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/tests/nbody-java/xmlvm.c b/tests/nbody-java/xmlvm.c
new file mode 100644
index 00000000..35e04d16
--- /dev/null
+++ b/tests/nbody-java/xmlvm.c
@@ -0,0 +1,565 @@
+/*
+ * Copyright (c) 2002-2011 by XMLVM.org
+ *
+ * Project Info: http://www.xmlvm.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include "xmlvm.h"
+#include "xmlvm-util.h"
+#include "java_lang_System.h"
+#include "java_lang_Class.h"
+#include "java_lang_String.h"
+#include "java_lang_Throwable.h"
+#include "org_xmlvm_runtime_FinalizerNotifier.h"
+#include "org_xmlvm_runtime_XMLVMUtil.h"
+#include <stdio.h>
+#include <string.h>
+
+
+XMLVM_STATIC_INITIALIZER_CONTROLLER* staticInitializerController;
+
+// This exception value is only used for the main thread.
+// Since a call to Thread.currentThread() contains try-catch blocks, this must
+// be defined before the "main" java.lang.Thread is defined.
+XMLVM_JMP_BUF xmlvm_exception_env_main_thread;
+
+
+#ifdef XMLVM_ENABLE_STACK_TRACES
+
+
+#include "uthash.h"
+
+#define HASH_ADD_JAVA_LONG(head,javalongfield,add) \
+ HASH_ADD(hh,head,javalongfield,sizeof(JAVA_LONG),add)
+#define HASH_FIND_JAVA_LONG(head,findjavalong,out) \
+ HASH_FIND(hh,head,findjavalong,sizeof(JAVA_LONG),out)
+
+// A map of type UTHash with a key of JAVA_LONG and value of JAVA_OBJECT
+struct hash_struct {
+ JAVA_LONG key;
+ JAVA_OBJECT value;
+ UT_hash_handle hh; // makes this structure hashable
+};
+
+
+// Map of thread id to its stack trace
+struct hash_struct** threadToStackTraceMapPtr;
+
+
+#endif
+
+
+void xmlvm_init()
+{
+#ifdef XMLVM_ENABLE_STACK_TRACES
+ threadToStackTraceMapPtr = malloc(sizeof(struct hash_struct**));
+ struct hash_struct* map = NULL; // This must be set to NULL according to the UTHash documentation
+ *threadToStackTraceMapPtr = map;
+
+ JAVA_LONG nativeThreadId = (JAVA_LONG) pthread_self();
+ createStackForNewThread(nativeThreadId);
+#endif
+
+#ifndef XMLVM_NO_GC
+//#ifdef DEBUG
+// setenv("GC_PRINT_STATS", "1", 1);
+//#endif
+ GC_INIT();
+ GC_enable_incremental();
+#endif
+
+ staticInitializerController = XMLVM_MALLOC(sizeof(XMLVM_STATIC_INITIALIZER_CONTROLLER));
+ staticInitializerController->initMutex = XMLVM_MALLOC(sizeof(pthread_mutex_t));
+ if (0 != pthread_mutex_init(staticInitializerController->initMutex, NULL)) {
+ XMLVM_ERROR("Error initializing static initializer mutex", __FILE__, __FUNCTION__, __LINE__);
+ }
+
+ __INIT_org_xmlvm_runtime_XMLVMArray();
+ java_lang_Class_initNativeLayer__();
+ __INIT_java_lang_System();
+ org_xmlvm_runtime_XMLVMUtil_init__();
+ /*
+ * The implementation of the constant pool makes use of cross-compiled Java data structures.
+ * During initialization of the VM done up to this point there are some circular dependencies
+ * between class initializers of various classes and the constant pool that lead to some
+ * inconsistencies. The easiest way to fix this is to clear the constant pool cache.
+ */
+ xmlvm_clear_constant_pool_cache();
+
+#ifndef XMLVM_NO_GC
+#ifndef EMSCRIPTEN
+ GC_finalize_on_demand = 1;
+ GC_java_finalization = 1;
+ java_lang_Thread* finalizerThread = (java_lang_Thread*) org_xmlvm_runtime_FinalizerNotifier_startFinalizerThread__();
+ GC_finalizer_notifier = org_xmlvm_runtime_FinalizerNotifier_finalizerNotifier__;
+#endif
+#endif
+
+ reference_array = XMLVMUtil_NEW_ArrayList();
+}
+
+void xmlvm_destroy(java_lang_Thread* mainThread)
+{
+#ifdef EMSCRIPTEN
+ return; // Let the JS engine handle clean up
+#endif
+
+ java_lang_Thread_threadTerminating__(mainThread);
+
+#ifdef XMLVM_ENABLE_STACK_TRACES
+ JAVA_LONG nativeThreadId = (JAVA_LONG) pthread_self();
+ destroyStackForExitingThread(nativeThreadId);
+#endif
+
+ // Unregister the current thread. Only an explicitly registered
+ // thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS)
+ // is allowed (and required) to call this function. (As a special
+ // exception, it is also allowed to once unregister the main thread.)
+#ifndef XMLVM_NO_GC
+ GC_unregister_my_thread();
+#endif
+
+ // Call pthread_exit(0) so that the main thread does not terminate until
+ // the other threads have finished
+ pthread_exit(0);
+}
+
+/**
+ * Lock a mutex. If an error occurs, terminate the program.
+ */
+static void lockOrExit(char* className, pthread_mutex_t* mut)
+{
+ int result = pthread_mutex_lock(mut);
+ if (0 != result) {
+ printf("Error locking mutex in %s: %i\n", className, result);
+ exit(1);
+ }
+// else { printf("SUCCESSFUL mutex lock in %s\n", className); }
+}
+
+/**
+ * Unlock a mutex. If an error occurs, terminate the program.
+ */
+static void unlockOrExit(char* className, pthread_mutex_t* mut)
+{
+ int result = pthread_mutex_unlock(mut);
+ if (0 != result) {
+ printf("Error unlocking mutex in %s: %i\n", className, result);
+ exit(1);
+ }
+// else { printf("SUCCESSFUL mutex unlock in %s\n", className); }
+}
+
+/**
+ * Lock the static initializer mutex.
+ */
+void staticInitializerLock(void* tibDefinition)
+{
+ char* className = ((struct __TIB_DEFINITION_TEMPLATE*)tibDefinition)->className;
+ lockOrExit(className, staticInitializerController->initMutex);
+}
+
+/**
+ * Unlock the static initializer mutex.
+ */
+void staticInitializerUnlock(void* tibDefinition)
+{
+ char* className = ((struct __TIB_DEFINITION_TEMPLATE*)tibDefinition)->className;
+ unlockOrExit(className, staticInitializerController->initMutex);
+}
+
+int xmlvm_java_string_cmp(JAVA_OBJECT s1, const char* s2)
+{
+ java_lang_String* str = (java_lang_String*) s1;
+ JAVA_INT len = str->fields.java_lang_String.count_;
+ if (len != strlen(s2)) {
+ return 0;
+ }
+ JAVA_INT offset = str->fields.java_lang_String.offset_;
+ org_xmlvm_runtime_XMLVMArray* value = (org_xmlvm_runtime_XMLVMArray*) str->fields.java_lang_String.value_;
+ JAVA_ARRAY_CHAR* valueArray = (JAVA_ARRAY_CHAR*) value->fields.org_xmlvm_runtime_XMLVMArray.array_;
+ for (int i = 0; i < len; i++) {
+ if (valueArray[i + offset] != s2[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+const char* xmlvm_java_string_to_const_char(JAVA_OBJECT s)
+{
+ if (s == JAVA_NULL) {
+ return "null";
+ }
+ java_lang_String* str = (java_lang_String*) s;
+ JAVA_INT len = str->fields.java_lang_String.count_;
+ char* cs = XMLVM_ATOMIC_MALLOC(len + 1);
+ JAVA_INT offset = str->fields.java_lang_String.offset_;
+ org_xmlvm_runtime_XMLVMArray* value = (org_xmlvm_runtime_XMLVMArray*) str->fields.java_lang_String.value_;
+ JAVA_ARRAY_CHAR* valueArray = (JAVA_ARRAY_CHAR*) value->fields.org_xmlvm_runtime_XMLVMArray.array_;
+ int i = 0;
+ for (i = 0; i < len; i++) {
+ cs[i] = valueArray[i + offset];
+ }
+ cs[i] = '\0';
+ return cs;
+}
+
+JAVA_OBJECT xmlvm_create_java_string(const char* s)
+{
+ java_lang_String* str = __NEW_java_lang_String();
+ org_xmlvm_runtime_XMLVMArray* charArray = XMLVMArray_createFromString(s);
+ java_lang_String___INIT____char_1ARRAY(str, charArray);
+ return XMLVMUtil_getFromStringPool(str);
+}
+
+JAVA_OBJECT xmlvm_create_java_string_array(int count, const char **s)
+{
+ JAVA_OBJECT javaStrings[count];
+ for (int i = 0; i < count; i++) {
+ javaStrings[i] = xmlvm_create_java_string(s[i]);
+ }
+ JAVA_OBJECT javaStringArray = XMLVMArray_createSingleDimension(__CLASS_java_lang_String, count);
+ XMLVMArray_fillArray(javaStringArray, javaStrings);
+ return javaStringArray;
+}
+
+static JAVA_OBJECT* stringConstants = JAVA_NULL;
+
+JAVA_OBJECT xmlvm_create_java_string_from_pool(int pool_id)
+{
+ if (stringConstants == JAVA_NULL) {
+ // TODO: use XMLVM_ATOMIC_MALLOC?
+ stringConstants = XMLVM_MALLOC(xmlvm_constant_pool_size * sizeof(JAVA_OBJECT));
+ XMLVM_BZERO(stringConstants, xmlvm_constant_pool_size * sizeof(JAVA_OBJECT));
+ }
+ if (stringConstants[pool_id] != JAVA_NULL) {
+ return stringConstants[pool_id];
+ }
+ java_lang_String* str = __NEW_java_lang_String();
+ org_xmlvm_runtime_XMLVMArray* charArray = XMLVMArray_createSingleDimensionWithData(__CLASS_char,
+ xmlvm_constant_pool_length[pool_id],
+ (JAVA_OBJECT) xmlvm_constant_pool_data[pool_id]);
+ java_lang_String___INIT____char_1ARRAY(str, charArray);
+ JAVA_OBJECT poolStr = XMLVMUtil_getFromStringPool(str);
+ stringConstants[pool_id] = poolStr;
+ return poolStr;
+}
+
+void xmlvm_clear_constant_pool_cache()
+{
+ XMLVM_BZERO(stringConstants, xmlvm_constant_pool_size * sizeof(JAVA_OBJECT));
+}
+
+
+//---------------------------------------------------------------------------------------------
+// XMLVMClass
+
+JAVA_OBJECT XMLVM_CREATE_CLASS_OBJECT(void* tib)
+{
+ JAVA_OBJECT clazz = __NEW_java_lang_Class();
+ java_lang_Class___INIT____java_lang_Object(clazz, tib);
+ return clazz;
+}
+
+
+JAVA_OBJECT XMLVM_CREATE_ARRAY_CLASS_OBJECT(JAVA_OBJECT baseType)
+{
+ __TIB_DEFINITION_org_xmlvm_runtime_XMLVMArray* tib = XMLVM_MALLOC(sizeof(__TIB_DEFINITION_org_xmlvm_runtime_XMLVMArray));
+ XMLVM_MEMCPY(tib, &__TIB_org_xmlvm_runtime_XMLVMArray, sizeof(__TIB_DEFINITION_org_xmlvm_runtime_XMLVMArray));
+ tib->flags = XMLVM_TYPE_ARRAY;
+ tib->baseType = baseType;
+ tib->arrayType = JAVA_NULL;
+ JAVA_OBJECT clazz = __NEW_java_lang_Class();
+ java_lang_Class___INIT____java_lang_Object(clazz, tib);
+ tib->clazz = clazz;
+ // Set the arrayType in in baseType to this newly created array type class
+ java_lang_Class* baseTypeClass = (java_lang_Class*) baseType;
+ __TIB_DEFINITION_TEMPLATE* baseTypeTIB = (__TIB_DEFINITION_TEMPLATE*) baseTypeClass->fields.java_lang_Class.tib_;
+ baseTypeTIB->arrayType = clazz;
+ return clazz;
+}
+
+
+int XMLVM_ISA(JAVA_OBJECT obj, JAVA_OBJECT clazz)
+{
+ if (obj == JAVA_NULL) {
+ return 0;
+ }
+
+ int dimension_tib1 = 0;
+ int dimension_tib2 = 0;
+ __TIB_DEFINITION_TEMPLATE* tib1 = (__TIB_DEFINITION_TEMPLATE*) ((java_lang_Object*) obj)->tib;
+ __TIB_DEFINITION_TEMPLATE* tib2 = (__TIB_DEFINITION_TEMPLATE*) ((java_lang_Class*) clazz)->fields.java_lang_Class.tib_;
+
+ if (tib1 == &__TIB_org_xmlvm_runtime_XMLVMArray) {
+ java_lang_Class* clazz = ((org_xmlvm_runtime_XMLVMArray*) obj)->fields.org_xmlvm_runtime_XMLVMArray.type_;
+ tib1 = clazz->fields.java_lang_Class.tib_;
+ }
+
+ while (tib1->baseType != JAVA_NULL) {
+ tib1 = ((java_lang_Class*) tib1->baseType)->fields.java_lang_Class.tib_;
+ dimension_tib1++;
+ }
+
+ while (tib2->baseType != JAVA_NULL) {
+ tib2 = ((java_lang_Class*) tib2->baseType)->fields.java_lang_Class.tib_;
+ dimension_tib2++;
+ }
+
+ if (dimension_tib1 < dimension_tib2) {
+ return 0;
+ }
+
+ while (tib1 != JAVA_NULL) {
+ if (tib1 == tib2) {
+ return 1;
+ }
+ // Check all implemented interfaces
+ int i;
+ for (i = 0; i < tib1->numImplementedInterfaces; i++) {
+ if (tib1->implementedInterfaces[0][i] == tib2) {
+ return 1;
+ }
+ }
+ tib1 = tib1->extends;
+ }
+ return 0;
+}
+
+//---------------------------------------------------------------------------------------------
+// Stack traces
+
+#ifdef XMLVM_ENABLE_STACK_TRACES
+
+void createStackForNewThread(JAVA_LONG threadId)
+{
+ struct hash_struct *s = malloc(sizeof(struct hash_struct));
+ s->key = threadId;
+
+ XMLVM_STACK_TRACE_CURRENT* newStack = malloc(sizeof(XMLVM_STACK_TRACE_CURRENT));
+ newStack->stackSize = 0;
+ newStack->topOfStack = NULL;
+
+ s->value = newStack;
+ HASH_ADD_JAVA_LONG((struct hash_struct *)*threadToStackTraceMapPtr, key, s);
+}
+
+void destroyStackForExitingThread(JAVA_LONG threadId)
+{
+ struct hash_struct *s;
+ HASH_FIND_JAVA_LONG((struct hash_struct *)*threadToStackTraceMapPtr, &threadId, s);
+ if (s == NULL) {
+ printf("ERROR: Unable to destroy stack trace for exiting thread!\n");
+ exit(-1);
+ } else {
+ HASH_DEL((struct hash_struct *)*threadToStackTraceMapPtr, s);
+ free(s->value);
+ free(s);
+ }
+}
+
+XMLVM_STACK_TRACE_CURRENT* getCurrentStackTrace()
+{
+ JAVA_LONG currentThreadId = (JAVA_LONG)pthread_self();
+ struct hash_struct *s;
+ HASH_FIND_JAVA_LONG((struct hash_struct *)*threadToStackTraceMapPtr, &currentThreadId, s);
+ if (s == NULL) {
+ printf("ERROR: Unable to find stack trace for current thread!\n");
+ exit(-1);
+ }
+ return (XMLVM_STACK_TRACE_CURRENT*)s->value;
+}
+
+void xmlvmEnterMethod(XMLVM_STACK_TRACE_CURRENT* threadStack, const char* className, const char* methodName, const char* fileName)
+{
+ //printf("Entering method %s\n", className);
+
+ XMLVM_STACK_TRACE_ELEMENT* newLocationElement = malloc(sizeof(XMLVM_STACK_TRACE_ELEMENT));
+ newLocationElement->className = className;
+ newLocationElement->methodName = methodName;
+ newLocationElement->fileName = fileName;
+ newLocationElement->lineNumber = -2;
+
+ XMLVM_STACK_TRACE_LINK* link = malloc(sizeof(XMLVM_STACK_TRACE_LINK));
+ link->nextLink = threadStack->topOfStack;
+ if (threadStack->topOfStack != NULL) {
+ link->element = threadStack->topOfStack->currentLocation;
+ }
+ link->currentLocation = newLocationElement;
+
+ // Push what was the current location onto the stack and set the new current location
+ threadStack->stackSize++;
+ threadStack->topOfStack = link;
+}
+
+void xmlvmSourcePosition(XMLVM_STACK_TRACE_CURRENT* threadStack, const char* fileName, int lineNumber)
+{
+ //printf("Source position update %i\n", lineNumber);
+
+ threadStack->topOfStack->currentLocation->fileName = fileName;
+ threadStack->topOfStack->currentLocation->lineNumber = lineNumber;
+}
+
+void xmlvmExitMethod(XMLVM_STACK_TRACE_CURRENT* threadStack)
+{
+ //printf("Exiting method\n");
+
+ XMLVM_STACK_TRACE_LINK* linkToDestroy = threadStack->topOfStack;
+ threadStack->topOfStack = linkToDestroy->nextLink;
+ threadStack->stackSize--;
+
+ free(linkToDestroy->currentLocation);
+ free(linkToDestroy);
+}
+
+void xmlvmUnwindException(XMLVM_STACK_TRACE_CURRENT* threadStack, int unwindToStackSize)
+{
+ while (unwindToStackSize + 1 < threadStack->stackSize) {
+ //printf("Unwinding stack after catching an exception: %i > %i\n", unwindToStackSize, threadStack->stackSize);
+ xmlvmExitMethod(threadStack);
+ }
+}
+
+#endif
+
+
+#ifdef XMLVM_ENABLE_CLASS_LOGGING
+//---------------------------------------------------------------------------------------------
+// Reflection/Class Usage logging
+
+FILE *logFile = 0;
+int useLogging = 1;
+
+void xmlvmClassUsed(const char *prefix, const char *className) {
+ if (useLogging && (logFile == 0)) {
+ logFile = fopen("touched_classes.txt", "w");
+ }
+ if (useLogging && (logFile != 0)) {
+ fprintf(logFile, "%s:%s\n", prefix, className);
+ } else {
+ useLogging = 0; // Failed to open file, so stop
+ }
+}
+
+#endif
+
+//---------------------------------------------------------------------------------------------
+// XMLVMArray
+
+
+JAVA_OBJECT XMLVMArray_createSingleDimension(JAVA_OBJECT type, JAVA_INT size)
+{
+ return org_xmlvm_runtime_XMLVMArray_createSingleDimension___java_lang_Class_int(type, size);
+}
+
+JAVA_OBJECT XMLVMArray_createSingleDimensionWithData(JAVA_OBJECT type, JAVA_INT size, JAVA_OBJECT data)
+{
+ return org_xmlvm_runtime_XMLVMArray_createSingleDimensionWithData___java_lang_Class_int_java_lang_Object(type, size, data);
+}
+
+
+JAVA_OBJECT XMLVMArray_createMultiDimensions(JAVA_OBJECT type, JAVA_OBJECT dimensions)
+{
+ return org_xmlvm_runtime_XMLVMArray_createMultiDimensions___java_lang_Class_org_xmlvm_runtime_XMLVMArray(type, dimensions);
+}
+
+JAVA_OBJECT XMLVMArray_createFromString(const char* str)
+{
+ int len = strlen(str);
+ int size = len * sizeof(JAVA_ARRAY_CHAR);
+ int i;
+ JAVA_ARRAY_CHAR* data = XMLVM_ATOMIC_MALLOC(size);
+ for (i = 0; i < len; i++) {
+ data[i] = *str++;
+ }
+ return XMLVMArray_createSingleDimensionWithData(__CLASS_char, len, data);
+}
+
+void XMLVMArray_fillArray(JAVA_OBJECT array, void* data)
+{
+ org_xmlvm_runtime_XMLVMArray_fillArray___org_xmlvm_runtime_XMLVMArray_java_lang_Object(array, data);
+}
+
+int XMLVMArray_count(JAVA_OBJECT array)
+{
+ org_xmlvm_runtime_XMLVMArray* a = (org_xmlvm_runtime_XMLVMArray*) array;
+ return a->fields.org_xmlvm_runtime_XMLVMArray.length_;
+}
+
+void xmlvm_unhandled_exception()
+{
+ java_lang_Thread* curThread;
+ curThread = (java_lang_Thread*) java_lang_Thread_currentThread__();
+ JAVA_OBJECT exception = curThread->fields.java_lang_Thread.xmlvmException_;
+
+ JAVA_OBJECT thread_name;
+#ifdef XMLVM_VTABLE_IDX_java_lang_Thread_getName__
+ thread_name = ((Func_OO) ((java_lang_Thread*) curThread)->tib->vtable[XMLVM_VTABLE_IDX_java_lang_Thread_getName__])(curThread);
+#else
+ thread_name = java_lang_Thread_getName__(curThread);
+#endif
+
+#ifdef XMLVM_ENABLE_STACK_TRACES
+
+ printf("Exception in thread \"%s\" ",
+ xmlvm_java_string_to_const_char(thread_name));
+ java_lang_Throwable_printStackTrace__(exception);
+
+#else
+
+ JAVA_OBJECT message;
+#ifdef XMLVM_VTABLE_IDX_java_lang_Throwable_getMessage__
+ message = ((Func_OO) ((java_lang_Throwable*) exception)->tib->vtable[XMLVM_VTABLE_IDX_java_lang_Throwable_getMessage__])(exception);
+#else
+ message = java_lang_Throwable_getMessage__(exception);
+#endif
+
+ JAVA_OBJECT exception_class;
+#ifdef XMLVM_VTABLE_IDX_java_lang_Object_getClass__
+ exception_class = ((Func_OO) ((java_lang_Object*) exception)->tib->vtable[XMLVM_VTABLE_IDX_java_lang_Object_getClass__])(exception);
+#else
+ exception_class = java_lang_Object_getClass__(exception);
+#endif
+
+ JAVA_OBJECT class_name;
+#ifdef XMLVM_VTABLE_IDX_java_lang_Class_getName__
+ class_name = ((Func_OO) ((java_lang_Class*) exception_class)->tib->vtable[XMLVM_VTABLE_IDX_java_lang_Class_getName__])(exception_class);
+#else
+ class_name = java_lang_Class_getName__(exception_class);
+#endif
+
+ printf("Exception in thread \"%s\" %s: %s\n",
+ xmlvm_java_string_to_const_char(thread_name),
+ xmlvm_java_string_to_const_char(class_name),
+ xmlvm_java_string_to_const_char(message));
+
+#endif
+}
+
+void xmlvm_unimplemented_native_method()
+{
+ XMLVM_ERROR("Unimplemented native method", __FILE__, __FUNCTION__, __LINE__);
+}
+
+void XMLVM_ERROR(const char* msg, const char* file, const char* function, int line)
+{
+ printf("XMLVM Error: %s: (%s):%s:%d\n", msg, function, file, line);
+ exit(-1);
+}
+