more work towards OpenJDK classpath support

The biggest change in this commit is to split the system classloader
into two: one for boot classes (e.g. java.lang.*) and another for
application classes.  This is necessary to make OpenJDK's security
checks happy.

The rest of the changes include bugfixes and additional JVM method
implementations in classpath-openjdk.cpp.
This commit is contained in:
Joel Dice 2010-09-14 10:49:41 -06:00
parent 561ee6dff9
commit d819a75f36
28 changed files with 1250 additions and 1491 deletions

View File

@ -104,14 +104,15 @@ public class Classes {
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return Enum.valueOf
(getClass(loadVMClass(loader, typeName, 1, typeName.length - 3)),
(SystemClassLoader.getClass
(loadVMClass(loader, typeName, 1, typeName.length - 3)),
new String(name, 0, name.length - 1, false));
}
case 'c':{
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return getClass(loadVMClass(loader, name, 1, name.length - 3));
return SystemClassLoader.getClass(loadVMClass(loader, name, 1, name.length - 3));
}
case '@':
@ -136,7 +137,7 @@ public class Classes {
{
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
Object[] annotation = new Object[(read2(in) + 1) * 2];
annotation[1] = getClass
annotation[1] = SystemClassLoader.getClass
(loadVMClass(loader, typeName, 1, typeName.length - 3));
for (int i = 2; i < annotation.length; i += 2) {

View File

@ -14,7 +14,7 @@ import java.net.URL;
import java.net.MalformedURLException;
public class SystemClassLoader extends ClassLoader {
private static native VMClass findVMClass(String name)
private native VMClass findVMClass(String name)
throws ClassNotFoundException;
protected Class findClass(String name) throws ClassNotFoundException {
@ -23,14 +23,14 @@ public class SystemClassLoader extends ClassLoader {
public static native Class getClass(VMClass vmClass);
private static native VMClass findLoadedVMClass(String name);
private native VMClass findLoadedVMClass(String name);
protected Class reallyFindLoadedClass(String name){
VMClass c = findLoadedVMClass(name);
return c == null ? null : getClass(c);
}
private static native boolean resourceExists(String name);
private native boolean resourceExists(String name);
protected URL findResource(String name) {
if (resourceExists(name)) {

View File

@ -14,6 +14,7 @@ import avian.VMClass;
import avian.ClassAddendum;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import avian.Classes;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@ -69,23 +70,23 @@ public final class Class <T>
public static String getName(VMClass c) {
if (c.name == null) {
if ((c.vmFlags & PrimitiveFlag) != 0) {
if (c == SystemClassLoader.primitiveClass('V')) {
if (c == Classes.primitiveClass('V')) {
c.name = "void\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('Z')) {
} else if (c == Classes.primitiveClass('Z')) {
c.name = "boolean\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('B')) {
} else if (c == Classes.primitiveClass('B')) {
c.name = "byte\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('C')) {
} else if (c == Classes.primitiveClass('C')) {
c.name = "char\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('S')) {
} else if (c == Classes.primitiveClass('S')) {
c.name = "short\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('I')) {
} else if (c == Classes.primitiveClass('I')) {
c.name = "int\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('F')) {
} else if (c == Classes.primitiveClass('F')) {
c.name = "float\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('J')) {
} else if (c == Classes.primitiveClass('J')) {
c.name = "long\0".getBytes();
} else if (c == SystemClassLoader.primitiveClass('D')) {
} else if (c == Classes.primitiveClass('D')) {
c.name = "double\0".getBytes();
} else {
throw new AssertionError();
@ -150,9 +151,9 @@ public final class Class <T>
loader = Class.class.vmClass.loader;
}
Class c = loader.loadClass(name);
SystemClassLoader.link(c.vmClass, loader);
Classes.link(c.vmClass, loader);
if (initialize) {
SystemClassLoader.initialize(c.vmClass);
Classes.initialize(c.vmClass);
}
return c;
}
@ -170,7 +171,7 @@ public final class Class <T>
} else {
if (name.length() == 1) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass(name.charAt(0)));
(Classes.primitiveClass(name.charAt(0)));
} else {
throw new ClassNotFoundException(name);
}
@ -184,29 +185,21 @@ public final class Class <T>
if (isArray()) {
String n = getName();
if ("[Z".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('Z'));
return SystemClassLoader.getClass(Classes.primitiveClass('Z'));
} else if ("[B".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('B'));
return SystemClassLoader.getClass(Classes.primitiveClass('B'));
} else if ("[S".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('S'));
return SystemClassLoader.getClass(Classes.primitiveClass('S'));
} else if ("[C".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('C'));
return SystemClassLoader.getClass(Classes.primitiveClass('C'));
} else if ("[I".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('I'));
return SystemClassLoader.getClass(Classes.primitiveClass('I'));
} else if ("[F".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('F'));
return SystemClassLoader.getClass(Classes.primitiveClass('F'));
} else if ("[J".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('J'));
return SystemClassLoader.getClass(Classes.primitiveClass('J'));
} else if ("[D".equals(n)) {
return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('D'));
return SystemClassLoader.getClass(Classes.primitiveClass('D'));
}
if (vmClass.staticTable == null) throw new AssertionError();
@ -217,12 +210,12 @@ public final class Class <T>
}
public boolean isAssignableFrom(Class c) {
return SystemClassLoader.isAssignableFrom(vmClass, c.vmClass);
return Classes.isAssignableFrom(vmClass, c.vmClass);
}
private static Field findField(VMClass vmClass, String name) {
if (vmClass.fieldTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (Field.getName(vmClass.fieldTable[i]).equals(name)) {
@ -269,7 +262,7 @@ public final class Class <T>
Class[] parameterTypes)
{
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
if (parameterTypes == null) {
parameterTypes = new Class[0];
@ -365,7 +358,7 @@ public final class Class <T>
public Constructor[] getDeclaredConstructors() {
Constructor[] array = new Constructor[countConstructors(false)];
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
int index = 0;
for (int i = 0; i < vmClass.methodTable.length; ++i) {
@ -381,7 +374,7 @@ public final class Class <T>
public Constructor[] getConstructors() {
Constructor[] array = new Constructor[countConstructors(true)];
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
int index = 0;
for (int i = 0; i < vmClass.methodTable.length; ++i) {
@ -423,7 +416,7 @@ public final class Class <T>
public Field[] getFields() {
Field[] array = new Field[countPublicFields()];
if (vmClass.fieldTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
int ai = 0;
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
@ -454,7 +447,7 @@ public final class Class <T>
public Method[] getDeclaredMethods() {
Method[] array = new Method[countMethods(false)];
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
int ai = 0;
for (int i = 0; i < vmClass.methodTable.length; ++i) {
@ -470,7 +463,7 @@ public final class Class <T>
public Method[] getMethods() {
Method[] array = new Method[countMethods(true)];
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
int index = 0;
for (int i = 0; i < vmClass.methodTable.length; ++i) {
@ -487,7 +480,7 @@ public final class Class <T>
public Class[] getInterfaces() {
if (vmClass.interfaceTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
int stride = (isInterface() ? 1 : 2);
Class[] array = new Class[vmClass.interfaceTable.length / stride];
@ -534,8 +527,8 @@ public final class Class <T>
}
public static boolean isInstance(VMClass c, Object o) {
return o != null && SystemClassLoader.isAssignableFrom
(c, SystemClassLoader.getVMClass(o));
return o != null && Classes.isAssignableFrom
(c, Classes.getVMClass(o));
}
public boolean isInstance(Object o) {
@ -620,7 +613,7 @@ public final class Class <T>
public <T extends Annotation> T getAnnotation(Class<T> class_) {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
SystemClassLoader.link(c, c.loader);
Classes.link(c, c.loader);
Object[] table = (Object[]) c.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
@ -636,7 +629,7 @@ public final class Class <T>
public Annotation[] getDeclaredAnnotations() {
if (vmClass.addendum.annotationTable != null) {
SystemClassLoader.link(vmClass);
Classes.link(vmClass);
Object[] table = (Object[]) vmClass.addendum.annotationTable;
Annotation[] array = new Annotation[table.length];

View File

@ -47,7 +47,7 @@ public abstract class ClassLoader {
}
return avian.SystemClassLoader.getClass
(avian.SystemClassLoader.defineVMClass(this, b, offset, length));
(avian.Classes.defineVMClass(this, b, offset, length));
}
protected Class findClass(String name) throws ClassNotFoundException {
@ -88,7 +88,7 @@ public abstract class ClassLoader {
}
protected void resolveClass(Class c) {
avian.SystemClassLoader.link(c.vmClass, this);
avian.Classes.link(c.vmClass, this);
}
private ClassLoader getParent() {

View File

@ -12,7 +12,7 @@ package java.lang;
public class OutOfMemoryError extends VirtualMachineError {
public OutOfMemoryError(String message) {
super(message, null);
super(message);
}
public OutOfMemoryError() {

View File

@ -13,6 +13,7 @@ package java.lang.reflect;
import avian.VMField;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import avian.Classes;
import java.lang.annotation.Annotation;
@ -204,7 +205,7 @@ public class Field<T> extends AccessibleObject {
} else {
throw new IllegalArgumentException
("needed " + getType() + ", got "
+ Class.getName(SystemClassLoader.vmClass(target)) +
+ Class.getName(Classes.vmClass(target)) +
" when setting " + Class.getName(vmField.class_) + "." + getName());
}
break;

View File

@ -515,8 +515,7 @@ public class Proxy {
byte[] classData = out.toByteArray();
return avian.SystemClassLoader.getClass
(avian.SystemClassLoader.defineVMClass
(loader, classData, 0, classData.length));
(avian.Classes.defineVMClass(loader, classData, 0, classData.length));
}
public static Object newProxyInstance(ClassLoader loader,

View File

@ -0,0 +1,13 @@
/* Copyright (c) 2010, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package sun.reflect;
public class ConstantPool { }

View File

@ -1,4 +1,4 @@
#MAKEFLAGS = -s
MAKEFLAGS = -s
name = avian
version = 0.3

View File

@ -55,11 +55,13 @@ class BootImage {
unsigned heapSize;
unsigned codeSize;
unsigned classCount;
unsigned bootClassCount;
unsigned appClassCount;
unsigned stringCount;
unsigned callCount;
unsigned loader;
unsigned bootLoader;
unsigned appLoader;
unsigned types;
unsigned methodTree;
unsigned methodTreeSentinal;

View File

@ -18,10 +18,11 @@ using namespace vm;
namespace {
int64_t
search(Thread* t, object name, object (*op)(Thread*, object),
bool replaceDots)
search(Thread* t, object loader, object name,
object (*op)(Thread*, object, object), bool replaceDots)
{
if (LIKELY(name)) {
PROTECT(t, loader);
PROTECT(t, name);
object n = makeByteArray(t, stringLength(t, name) + 1);
@ -32,7 +33,7 @@ search(Thread* t, object name, object (*op)(Thread*, object),
replace('.', '/', s);
}
object r = op(t, n);
object r = op(t, loader, n);
if (t->exception) {
return 0;
}
@ -45,86 +46,45 @@ search(Thread* t, object name, object (*op)(Thread*, object),
}
}
object
resolveSystemClassThrow(Thread* t, object loader, object spec)
{
return resolveSystemClass(t, loader, spec, true);
}
} // namespace
extern "C" JNIEXPORT void JNICALL
Avian_avian_SystemClassLoader_acquireClassLock
(Thread* t, object, uintptr_t*)
{
acquire(t, t->m->classLock);
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_SystemClassLoader_releaseClassLock
(Thread* t, object, uintptr_t*)
{
release(t, t->m->classLock);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_getVMClass
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(objectClass(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_defineVMClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
object b = reinterpret_cast<object>(arguments[1]);
int offset = arguments[2];
int length = arguments[3];
uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(length));
memcpy(buffer, &byteArrayBody(t, b, offset), length);
object c = defineClass(t, loader, buffer, length);
t->m->heap->free(buffer, length);
return reinterpret_cast<int64_t>(c);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findLoadedVMClass
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
object loader = reinterpret_cast<object>(arguments[0]);
object name = reinterpret_cast<object>(arguments[1]);
return search(t, name, findLoadedSystemClass, true);
return search(t, loader, name, findLoadedClass, true);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findVMClass
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
return search(t, name, resolveSystemClass, true);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_resolveVMClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
object spec = reinterpret_cast<object>(arguments[1]);
object name = reinterpret_cast<object>(arguments[1]);
return reinterpret_cast<int64_t>(resolveClass(t, loader, spec));
return search(t, loader, name, resolveSystemClassThrow, true);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_resourceExists
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
object loader = reinterpret_cast<object>(arguments[0]);
object name = reinterpret_cast<object>(arguments[1]);
if (LIKELY(name)) {
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
return t->m->finder->exists(RUNTIME_ARRAY_BODY(n));
return getFinder(t, loader)->exists(RUNTIME_ARRAY_BODY(n));
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
@ -133,35 +93,11 @@ Avian_avian_SystemClassLoader_resourceExists
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_primitiveClass
Avian_avian_SystemClassLoader_getClass
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_SystemClassLoader_initialize
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
initClass(t, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_isAssignableFrom
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
object that = reinterpret_cast<object>(arguments[1]);
if (LIKELY(that)) {
return vm::isAssignableFrom(t, this_, that);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0;
}
return reinterpret_cast<int64_t>
(getJClass(t, reinterpret_cast<object>(arguments[0])));
}
#ifdef AVIAN_HEAPDUMP
@ -208,7 +144,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
System::Region* r = t->m->finder->find(RUNTIME_ARRAY_BODY(p));
System::Region* r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p));
if (r) {
jint rSize = r->length();
r->dispose();
@ -229,7 +165,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
return reinterpret_cast<int64_t>
(t->m->finder->find(RUNTIME_ARRAY_BODY(p)));
(t->m->appFinder->find(RUNTIME_ARRAY_BODY(p)));
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);

View File

@ -49,15 +49,16 @@ class MyClasspath : public Classpath {
const unsigned NormalPriority = 5;
return vm::makeThread
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, t->m->loader, 0, 0,
group);
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0,
root(t, Machine::BootLoader), 0, 0, group);
}
virtual void
runThread(Thread* t)
{
object method = resolveMethod
(t, t->m->loader, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
(t, root(t, Machine::BootLoader), "java/lang/Thread", "run",
"(Ljava/lang/Thread;)V");
if (t->exception == 0) {
t->m->processor->invoke(t, method, 0, t->javaThread);
@ -75,7 +76,7 @@ class MyClasspath : public Classpath {
trace = makeTrace(t);
}
object result = make(t, arrayBody(t, t->m->types, type));
object result = make(t, vm::type(t, type));
set(t, result, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace);
@ -84,6 +85,12 @@ class MyClasspath : public Classpath {
return result;
}
virtual void
boot(Thread*)
{
// ignore
}
virtual void
dispose()
{
@ -352,7 +359,7 @@ Avian_java_lang_reflect_Array_makeObjectArray
int length = arguments[1];
return reinterpret_cast<int64_t>
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
(makeObjectArray(t, elementType, length));
}
extern "C" JNIEXPORT int64_t JNICALL
@ -408,7 +415,8 @@ Avian_java_lang_System_getVMProperty
int64_t r = 0;
if (::strcmp(RUNTIME_ARRAY_BODY(n), "java.lang.classpath") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, "%s", t->m->finder->path()));
r = reinterpret_cast<int64_t>
(makeString(t, "%s", t->m->appFinder->path()));
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "avian.version") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, AVIAN_VERSION));
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "file.encoding") == 0) {
@ -499,7 +507,8 @@ Avian_java_lang_Runtime_addShutdownHook
ACQUIRE(t, t->m->shutdownLock);
t->m->shutdownHooks = makePair(t, hook, t->m->shutdownHooks);
setRoot(t, Machine::ShutdownHooks,
makePair(t, hook, root(t, Machine::ShutdownHooks)));
}
extern "C" JNIEXPORT int64_t JNICALL
@ -516,15 +525,13 @@ Avian_java_lang_Throwable_resolveTrace
object trace = reinterpret_cast<object>(*arguments);
PROTECT(t, trace);
unsigned length = arrayLength(t, trace);
object elementType = arrayBody
(t, t->m->types, Machine::StackTraceElementType);
object array = makeObjectArray
(t, classLoader(t, elementType), elementType, length);
unsigned length = objectArrayLength(t, trace);
object elementType = type(t, Machine::StackTraceElementType);
object array = makeObjectArray(t, elementType, length);
PROTECT(t, array);
for (unsigned i = 0; i < length; ++i) {
object ste = makeStackTraceElement(t, arrayBody(t, trace, i));
object ste = makeStackTraceElement(t, objectArrayBody(t, trace, i));
set(t, array, ArrayBody + (i * BytesPerWord), ste);
}
@ -599,3 +606,85 @@ Avian_java_lang_Thread_setDaemon
setDaemon(t, thread, daemon);
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_Classes_acquireClassLock
(Thread* t, object, uintptr_t*)
{
acquire(t, t->m->classLock);
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_Classes_releaseClassLock
(Thread* t, object, uintptr_t*)
{
release(t, t->m->classLock);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Classes_resolveVMClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
object spec = reinterpret_cast<object>(arguments[1]);
return reinterpret_cast<int64_t>(resolveClass(t, loader, spec));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Classes_primitiveClass
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Classes_defineVMClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
object b = reinterpret_cast<object>(arguments[1]);
int offset = arguments[2];
int length = arguments[3];
uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(length));
memcpy(buffer, &byteArrayBody(t, b, offset), length);
object c = defineClass(t, loader, buffer, length);
t->m->heap->free(buffer, length);
return reinterpret_cast<int64_t>(c);
}
extern "C" JNIEXPORT void JNICALL
Avian_avian_Classes_initialize
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
initClass(t, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Classes_isAssignableFrom
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
object that = reinterpret_cast<object>(arguments[1]);
if (LIKELY(that)) {
return vm::isAssignableFrom(t, this_, that);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0;
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Classes_getVMClass
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(objectClass(t, reinterpret_cast<object>(arguments[0])));
}

View File

@ -56,8 +56,7 @@ getTrace(Thread* t, unsigned skipCount)
if (skipCount == 0) {
object method = walker->method();
if (isAssignableFrom
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
methodClass(t, method))
(t, type(t, Machine::ThrowableType), methodClass(t, method))
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0))
== 0)
@ -80,7 +79,7 @@ getTrace(Thread* t, unsigned skipCount)
t->m->processor->walkStack(t, &v);
if (v.trace == 0) v.trace = makeArray(t, 0);
if (v.trace == 0) v.trace = makeObjectArray(t, 0);
return v.trace;
}

View File

@ -40,6 +40,7 @@
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/socket.h>
# include <fcntl.h>
# include <errno.h>
@ -77,10 +78,10 @@ CREAT(string_t path, int mode)
namespace local {
const unsigned InterfaceVersion = 4;
const unsigned PageSize = 4 * 1024;
Machine* globalMachine;
const char*
primitiveName(Thread* t, object c)
{
@ -144,6 +145,8 @@ class MyClasspath : public Classpath {
virtual object
makeJclass(Thread* t, object class_)
{
PROTECT(t, class_);
object name = makeClassNameString(t, getClassName(t, class_));
return vm::makeJclass
@ -153,9 +156,7 @@ class MyClasspath : public Classpath {
virtual object
makeString(Thread* t, object array, int32_t offset, int32_t length)
{
if (objectClass(t, array)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, array) == type(t, Machine::ByteArrayType)) {
PROTECT(t, array);
object charArray = makeCharArray(t, length);
@ -183,19 +184,25 @@ class MyClasspath : public Classpath {
}
return vm::makeThread
(t, 0, NormalPriority, 0, 0, false, false, false, 0, group, t->m->loader,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, 0, false);
(t, 0, NormalPriority, 0, 0, false, false, false, 0, group,
root(t, Machine::BootLoader), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0,
0, false);
}
virtual void
runThread(Thread* t)
{
object method = resolveMethod
(t, t->m->loader, "java/lang/Thread", "run", "()V");
(t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V");
if (LIKELY(t->exception == 0)) {
t->m->processor->invoke(t, method, t->javaThread);
}
acquire(t, t->javaThread);
t->flags &= ~Thread::ActiveFlag;
notifyAll(t, t->javaThread);
release(t, t->javaThread);
}
virtual object
@ -209,7 +216,7 @@ class MyClasspath : public Classpath {
trace = makeTrace(t);
}
object result = make(t, arrayBody(t, t->m->types, type));
object result = make(t, vm::type(t, type));
set(t, result, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace);
@ -228,7 +235,22 @@ class MyClasspath : public Classpath {
}
t->m->processor->invoke
(t, t->m->loader, "java/lang/System", "initializeSystemClass", "()V", 0);
(t, root(t, Machine::BootLoader), "java/lang/System",
"initializeSystemClass", "()V", 0);
if (UNLIKELY(t->exception)) return;
object constructor = resolveMethod
(t, type(t, Machine::ClassLoaderType), "<init>",
"(Ljava/lang/ClassLoader;)V");
if (UNLIKELY(t->exception)) return;
PROTECT(t, constructor);
t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0);
if (UNLIKELY(t->exception)) return;
t->m->processor->invoke
(t, constructor, root(t, Machine::AppLoader),
root(t, Machine::BootLoader));
}
virtual void
@ -281,16 +303,16 @@ countFields(Thread* t, object c, bool publicOnly)
{
object table = classFieldTable(t, c);
if (publicOnly) {
return objectArrayLength(t, table);
} else {
unsigned count = 0;
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object vmField = arrayBody(t, table, i);
if ((not publicOnly) or (fieldFlags(t, vmField) & ACC_PUBLIC)) {
if (fieldFlags(t, vmField) & ACC_PUBLIC) {
++ count;
}
}
return count;
} else {
return objectArrayLength(t, table);
}
}
@ -430,8 +452,7 @@ resolveParameterJTypes(Thread* t, object loader, object spec,
PROTECT(t, list);
object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
*parameterCount);
(t, type(t, Machine::JclassType), *parameterCount);
PROTECT(t, array);
for (int i = *parameterCount - 1; i >= 0; --i) {
@ -447,15 +468,14 @@ object
resolveExceptionJTypes(Thread* t, object loader, object addendum)
{
if (addendum == 0) {
return makeObjectArray
(t, loader, arrayBody(t, t->m->types, Machine::JclassType), 0);
return makeObjectArray(t, type(t, Machine::JclassType), 0);
}
PROTECT(t, loader);
PROTECT(t, addendum);
object array = makeObjectArray
(t, loader, arrayBody(t, t->m->types, Machine::JclassType),
(t, type(t, Machine::JclassType),
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
PROTECT(t, array);
@ -467,9 +487,7 @@ resolveExceptionJTypes(Thread* t, object loader, object addendum)
object o = singletonObject(t, addendumPool(t, addendum), index);
if (objectClass(t, o)
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
o = resolveClass(t, loader, referenceName(t, o));
if (UNLIKELY(t->exception)) return 0;
@ -532,6 +550,38 @@ Avian_sun_misc_Unsafe_registerNatives
// ignore
}
extern "C" JNIEXPORT int64_t
Avian_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2
(Thread* t, object, uintptr_t* arguments)
{
//object name = reinterpret_cast<object>(arguments[1]);
object data = reinterpret_cast<object>(arguments[2]);
int32_t offset = arguments[3];
int32_t length = arguments[4];
object loader = reinterpret_cast<object>(arguments[5]);
//object domain = reinterpret_cast<object>(arguments[6]);
uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(length));
memcpy(buffer, &byteArrayBody(t, data, offset), length);
object c = defineClass(t, loader, buffer, length);
return c ? reinterpret_cast<int64_t>(getJClass(t, c)) : 0;
}
extern "C" JNIEXPORT int64_t
Avian_sun_misc_Unsafe_allocateInstance
(Thread* t, object, uintptr_t* arguments)
{
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[1]));
PROTECT(t, c);
initClass(t, c);
if (UNLIKELY(t->exception)) return 0;
return reinterpret_cast<int64_t>(make(t, c));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_staticFieldOffset
(Thread* t, object, uintptr_t* arguments)
@ -564,15 +614,90 @@ Avian_sun_misc_Unsafe_objectFieldOffset
(t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield)));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getObject
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
return cast<uintptr_t>(o, offset);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putObject
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
uintptr_t value = arguments[4];
set(t, o, offset, reinterpret_cast<object>(value));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
return cast<int32_t>(o, offset);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
int32_t value = arguments[4];
cast<int32_t>(o, offset) = value;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getBoolean
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
return cast<uint8_t>(o, offset);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putBoolean
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
uint8_t value = arguments[4];
cast<uint8_t>(o, offset) = value;
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
int64_t value; memcpy(&value, arguments + 4, 8);
cast<int64_t>(o, offset) = value;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getObjectVolatile
(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
unsigned offset = arguments[2];
object value = cast<object>(o, offset);
int64_t offset; memcpy(&offset, arguments + 2, 8);
uintptr_t value = cast<uintptr_t>(o, offset);
loadMemoryBarrier();
return reinterpret_cast<int64_t>(value);
return value;
}
extern "C" JNIEXPORT int64_t JNICALL
@ -588,6 +713,25 @@ Avian_sun_misc_Unsafe_compareAndSwapInt
(&cast<int32_t>(target, offset), expect, update);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapObject
(Thread* t, object, uintptr_t* arguments)
{
object target = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
intptr_t expect = arguments[4];
intptr_t update = arguments[5];
bool success = __sync_bool_compare_and_swap
(&cast<intptr_t>(target, offset), expect, update);
if (success) {
mark(t, target, offset);
}
return success;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapLong
(Thread*, object, uintptr_t* arguments)
@ -625,6 +769,17 @@ Avian_sun_misc_Unsafe_freeMemory
}
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_setMemory
(Thread*, object, uintptr_t* arguments)
{
int64_t p; memcpy(&p, arguments + 1, 8);
int64_t count; memcpy(&count, arguments + 3, 8);
int8_t v = arguments[5];
memset(reinterpret_cast<int8_t*>(p), v, count);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putLong__JJ
(Thread*, object, uintptr_t* arguments)
@ -635,6 +790,16 @@ Avian_sun_misc_Unsafe_putLong__JJ
*reinterpret_cast<int64_t*>(p) = v;
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putInt__JI
(Thread*, object, uintptr_t* arguments)
{
int64_t p; memcpy(&p, arguments + 1, 8);
int32_t v = arguments[3];
*reinterpret_cast<int32_t*>(p) = v;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getByte__J
(Thread*, object, uintptr_t* arguments)
@ -644,6 +809,22 @@ Avian_sun_misc_Unsafe_getByte__J
return *reinterpret_cast<int8_t*>(p);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getInt__J
(Thread*, object, uintptr_t* arguments)
{
int64_t p; memcpy(&p, arguments + 1, 8);
return *reinterpret_cast<int32_t*>(p);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_pageSize
(Thread*, object, uintptr_t*)
{
return local::PageSize;
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_ensureClassInitialized
(Thread* t, object, uintptr_t* arguments)
@ -732,7 +913,7 @@ JVM_InitProperties(Thread* t, jobject properties)
ENTER(t, Thread::ActiveState);
object method = resolveMethod
(t, t->m->loader, "java/util/Properties", "setProperty",
(t, root(t, Machine::BootLoader), "java/util/Properties", "setProperty",
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
if (UNLIKELY(t->exception)) {
@ -776,6 +957,9 @@ JVM_InitProperties(Thread* t, jobject properties)
local::setProperty(t, method, *properties, "sun.boot.library.path",
getenv("LD_LIBRARY_PATH"));
local::setProperty(t, method, *properties, "java.protocol.handler.pkgs",
"avian");
#endif
local::setProperty(t, method, *properties, "file.encoding", "ASCII");
#ifdef ARCH_x86_32
@ -811,10 +995,16 @@ extern "C" JNIEXPORT void JNICALL
JVM_OnExit(void (*)(void)) { abort(); }
extern "C" JNIEXPORT void JNICALL
JVM_Exit(jint) { abort(); }
JVM_Exit(jint code)
{
exit(code);
}
extern "C" JNIEXPORT void JNICALL
JVM_Halt(jint) { abort(); }
JVM_Halt(jint code)
{
exit(code);
}
extern "C" JNIEXPORT void JNICALL
JVM_GC()
@ -896,7 +1086,7 @@ JVM_GetStackTraceDepth(Thread* t, jobject throwable)
{
ENTER(t, Thread::ActiveState);
return arrayLength(t, throwableTrace(t, *throwable));
return objectArrayLength(t, throwableTrace(t, *throwable));
}
extern "C" JNIEXPORT jobject JNICALL
@ -906,7 +1096,7 @@ JVM_GetStackTraceElement(Thread* t, jobject throwable, jint index)
return makeLocalReference
(t, makeStackTraceElement
(t, arrayBody(t, throwableTrace(t, *throwable), index)));
(t, objectArrayBody(t, throwableTrace(t, *throwable), index)));
}
extern "C" JNIEXPORT void JNICALL
@ -947,25 +1137,7 @@ JVM_IsThreadAlive(Thread* t, jobject thread)
ENTER(t, Thread::ActiveState);
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread));
if (p) {
switch (p->state) {
case Thread::ActiveState:
case Thread::IdleState:
case Thread::ExclusiveState:
return true;
case Thread::NoState:
case Thread::ZombieState:
case Thread::JoinedState:
case Thread::ExitState:
return false;
default:
abort(t);
}
} else {
return false;
}
return p and (p->flags & Thread::ActiveFlag) != 0;
}
extern "C" JNIEXPORT void JNICALL
@ -1013,7 +1185,19 @@ extern "C" JNIEXPORT void JNICALL
JVM_Interrupt(Thread*, jobject) { abort(); }
extern "C" JNIEXPORT jboolean JNICALL
JVM_IsInterrupted(Thread*, jobject, jboolean) { abort(); }
JVM_IsInterrupted(Thread* t, jobject thread, jboolean clear)
{
ENTER(t, Thread::ActiveState);
acquire(t, *thread);
bool v = threadInterrupted(t, *thread);
if (clear) {
threadInterrupted(t, *thread) = false;
}
release(t, *thread);
return v;
}
extern "C" JNIEXPORT jboolean JNICALL
JVM_HoldsLock(Thread*, jclass, jobject) { abort(); }
@ -1042,13 +1226,12 @@ JVM_GetClassContext(Thread* t)
PROTECT(t, trace);
object context = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
arrayLength(t, trace));
(t, type(t, Machine::JclassType), objectArrayLength(t, trace));
PROTECT(t, context);
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) {
object c = getJClass
(t, methodClass(t, traceElementMethod(t, arrayBody(t, trace, i))));
(t, methodClass(t, traceElementMethod(t, objectArrayBody(t, trace, i))));
set(t, context, ArrayBody + (i * BytesPerWord), c);
}
@ -1084,16 +1267,31 @@ JVM_LoadClass0(Thread*, jobject, jclass,
jstring) { abort(); }
extern "C" JNIEXPORT jint JNICALL
JVM_GetArrayLength(Thread*, jobject) { abort(); }
JVM_GetArrayLength(Thread* t, jobject array)
{
ENTER(t, Thread::ActiveState);
return cast<uintptr_t>(*array, BytesPerWord);
}
extern "C" JNIEXPORT jobject JNICALL
JVM_GetArrayElement(Thread*, jobject, jint) { abort(); }
JVM_GetArrayElement(Thread* t, jobject array, jint index)
{
ENTER(t, Thread::ActiveState);
return makeLocalReference(t, objectArrayBody(t, *array, index));
}
extern "C" JNIEXPORT jvalue JNICALL
JVM_GetPrimitiveArrayElement(Thread*, jobject, jint, jint) { abort(); }
extern "C" JNIEXPORT void JNICALL
JVM_SetArrayElement(Thread*, jobject, jint, jobject) { abort(); }
JVM_SetArrayElement(Thread* t, jobject array, jint index, jobject value)
{
ENTER(t, Thread::ActiveState);
set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0));
}
extern "C" JNIEXPORT void JNICALL
JVM_SetPrimitiveArrayElement(Thread*, jobject, jint, jvalue,
@ -1126,8 +1324,7 @@ JVM_NewArray(Thread* t, jclass elementClass, jint length)
default: abort(t);
}
} else {
return makeLocalReference
(t, makeObjectArray(t, t->m->loader, c, length));
return makeLocalReference(t, makeObjectArray(t, c, length));
}
}
@ -1152,32 +1349,32 @@ JVM_FindPrimitiveClass(Thread* t, const char* name)
case 'b':
if (name[1] == 'o') {
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JbooleanType)));
(t, getJClass(t, type(t, Machine::JbooleanType)));
} else {
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JbyteType)));
(t, getJClass(t, type(t, Machine::JbyteType)));
}
case 'c':
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JcharType)));
(t, getJClass(t, type(t, Machine::JcharType)));
case 'd':
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JdoubleType)));
(t, getJClass(t, type(t, Machine::JdoubleType)));
case 'f':
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JfloatType)));
(t, getJClass(t, type(t, Machine::JfloatType)));
case 'i':
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JintType)));
(t, getJClass(t, type(t, Machine::JintType)));
case 'l':
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JlongType)));
(t, getJClass(t, type(t, Machine::JlongType)));
case 's':
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JshortType)));
(t, getJClass(t, type(t, Machine::JshortType)));
case 'v':
return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JvoidType)));
(t, getJClass(t, type(t, Machine::JvoidType)));
default:
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType);
@ -1194,7 +1391,8 @@ JVM_FindClassFromClassLoader(Thread* t, const char* name, jboolean init,
{
ENTER(t, Thread::ActiveState);
object c = resolveClass(t, loader ? *loader : t->m->loader, name);
object c = resolveClass
(t, loader ? *loader : root(t, Machine::BootLoader), name);
if (t->exception) {
if (throwError) {
t->exception = t->m->classpath->makeThrowable
@ -1224,25 +1422,13 @@ JVM_FindLoadedClass(Thread* t, jobject loader, jstring name)
{
ENTER(t, Thread::ActiveState);
ACQUIRE(t, t->m->classLock);
object spec = makeByteArray(t, stringLength(t, *name) + 1);
{ char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0));
stringChars(t, *name, s);
replace('.', '/', s);
}
object c;
if (loader == 0 or *loader == t->m->loader) {
c = findLoadedSystemClass(t, spec);
} else {
object map = classLoaderMap(t, *loader);
if (map) {
c = hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual);
} else {
c = 0;
}
}
object c = findLoadedClass(t, *loader, spec);
return c ? makeLocalReference(t, getJClass(t, c)) : 0;
}
@ -1275,8 +1461,7 @@ JVM_GetClassInterfaces(Thread* t, jclass c)
(classFlags(t, jclassVmClass(t, *c)) & ACC_INTERFACE) == 0 ? 2 : 1;
object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
arrayLength(t, table) / stride);
(t, type(t, Machine::JclassType), arrayLength(t, table) / stride);
PROTECT(t, array);
for (unsigned i = 0; i < objectArrayLength(t, array); ++i) {
@ -1287,9 +1472,7 @@ JVM_GetClassInterfaces(Thread* t, jclass c)
return makeLocalReference(t, array);
} else {
return makeLocalReference
(t, makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
0));
(t, makeObjectArray(t, type(t, Machine::JclassType), 0));
}
}
@ -1299,7 +1482,8 @@ JVM_GetClassLoader(Thread* t, jclass c)
ENTER(t, Thread::ActiveState);
object loader = classLoader(t, jclassVmClass(t, *c));
return loader == t->m->loader ? 0 : makeLocalReference(t, loader);
return loader == root(t, Machine::BootLoader)
? 0 : makeLocalReference(t, loader);
}
extern "C" JNIEXPORT jboolean JNICALL
@ -1385,8 +1569,10 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly)
object table = classMethodTable(t, jclassVmClass(t, *c));
if (table) {
PROTECT(t, table);
object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JmethodType),
(t, type(t, Machine::JmethodType),
local::countMethods(t, jclassVmClass(t, *c), publicOnly));
PROTECT(t, array);
@ -1461,9 +1647,7 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly)
return makeLocalReference(t, array);
} else {
return makeLocalReference
(t, makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JmethodType),
0));
(t, makeObjectArray(t, type(t, Machine::JmethodType), 0));
}
}
@ -1474,8 +1658,10 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
object table = classFieldTable(t, jclassVmClass(t, *c));
if (table) {
PROTECT(t, table);
object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JfieldType),
(t, type(t, Machine::JfieldType),
local::countFields(t, jclassVmClass(t, *c), publicOnly));
PROTECT(t, array);
@ -1501,6 +1687,8 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
return 0;
}
PROTECT(t, type);
type = getJClass(t, type);
object signature = t->m->classpath->makeString
@ -1524,12 +1712,12 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
set(t, array, ArrayBody + ((ai++) * BytesPerWord), field);
}
}
assert(t, ai == objectArrayLength(t, array));
return makeLocalReference(t, array);
} else {
return makeLocalReference
(t, makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JfieldType), 0));
(t, makeObjectArray(t, type(t, Machine::JfieldType), 0));
}
}
@ -1540,8 +1728,10 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly)
object table = classMethodTable(t, jclassVmClass(t, *c));
if (table) {
PROTECT(t, table);
object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JconstructorType),
(t, type(t, Machine::JconstructorType),
local::countConstructors(t, jclassVmClass(t, *c), publicOnly));
PROTECT(t, array);
@ -1598,9 +1788,7 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly)
return makeLocalReference(t, array);
} else {
return makeLocalReference
(t, makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JconstructorType),
0));
(t, makeObjectArray(t, type(t, Machine::JconstructorType), 0));
}
}
@ -1739,8 +1927,11 @@ JVM_DoPrivileged
{
ENTER(t, Thread::ActiveState);
// todo: cache these class and method lookups in the t->m->classpath
// object:
object privilegedAction = resolveClass
(t, t->m->loader, "java/security/PrivilegedAction");
(t, root(t, Machine::BootLoader), "java/security/PrivilegedAction");
if (UNLIKELY(t->exception)) {
return 0;
@ -1752,7 +1943,8 @@ JVM_DoPrivileged
(t, privilegedAction, "run", "()Ljava/lang/Object;");
} else {
object privilegedExceptionAction = resolveClass
(t, t->m->loader, "java/security/PrivilegedExceptionAction");
(t, root(t, Machine::BootLoader),
"java/security/PrivilegedExceptionAction");
if (UNLIKELY(t->exception)) {
return 0;
@ -1769,10 +1961,8 @@ JVM_DoPrivileged
return makeLocalReference(t, result);
} else {
if (wrapException and not
(instanceOf
(t, arrayBody(t, t->m->types, Machine::ErrorType), t->exception)
or instanceOf
(t, arrayBody(t, t->m->types, Machine::RuntimeExceptionType),
(instanceOf(t, type(t, Machine::ErrorType), t->exception)
or instanceOf(t, type(t, Machine::RuntimeExceptionType),
t->exception)))
{
object cause = t->exception;
@ -1781,7 +1971,8 @@ JVM_DoPrivileged
t->exception = 0;
object paeClass = resolveClass
(t, t->m->loader, "java/security/PrivilegedActionException");
(t, root(t, Machine::BootLoader),
"java/security/PrivilegedActionException");
if (LIKELY(t->exception == 0)) {
PROTECT(t, paeClass);
@ -2003,37 +2194,83 @@ extern "C" JNIEXPORT jint JNICALL
JVM_Sync(jint) { abort(); }
extern "C" JNIEXPORT jint JNICALL
JVM_InitializeSocketLibrary(void) { abort(); }
JVM_InitializeSocketLibrary()
{
#ifdef PLATFORM_WINDOWS
static bool wsaInitialized = false;
if (not wsaInitialized) {
WSADATA data;
int r = WSAStartup(MAKEWORD(2, 2), &data);
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
return -1;
} else {
wsaInitialized = true;
}
}
#endif
return 0;
}
extern "C" JNIEXPORT jint JNICALL
JVM_Socket(jint, jint, jint) { abort(); }
JVM_Socket(jint domain, jint type, jint protocol)
{
return socket(domain, type, protocol);
}
extern "C" JNIEXPORT jint JNICALL
JVM_SocketClose(jint) { abort(); }
JVM_SocketClose(jint socket)
{
#ifdef PLATFORM_WINDOWS
return closesocket(socket);
#else
return close(socket);
#endif
}
extern "C" JNIEXPORT jint JNICALL
JVM_SocketShutdown(jint, jint) { abort(); }
JVM_SocketShutdown(jint socket, jint how)
{
return shutdown(socket, how);
}
extern "C" JNIEXPORT jint JNICALL
JVM_Recv(jint, char*, jint, jint) { abort(); }
JVM_Recv(jint socket, char* dst, jint count, jint flags)
{
return recv(socket, dst, count, flags);
}
extern "C" JNIEXPORT jint JNICALL
JVM_Send(jint, char*, jint, jint) { abort(); }
JVM_Send(jint socket, char* src, jint count, jint flags)
{
return send(socket, src, count, flags);
}
extern "C" JNIEXPORT jint JNICALL
JVM_Timeout(int, long) { abort(); }
extern "C" JNIEXPORT jint JNICALL
JVM_Listen(jint, jint) { abort(); }
JVM_Listen(jint socket, jint count)
{
return listen(socket, count);
}
extern "C" JNIEXPORT jint JNICALL
JVM_Connect(jint, struct sockaddr*, jint) { abort(); }
JVM_Connect(jint socket, sockaddr* address, jint addressLength)
{
return connect(socket, address, addressLength);
}
extern "C" JNIEXPORT jint JNICALL
JVM_Bind(jint, struct sockaddr*, jint) { abort(); }
extern "C" JNIEXPORT jint JNICALL
JVM_Accept(jint, struct sockaddr*, jint*) { abort(); }
JVM_Accept(jint socket, struct sockaddr* address, jint* addressLength)
{
socklen_t length = *addressLength;
int r = accept(socket, address, &length);
*addressLength = length;
return r;
}
extern "C" JNIEXPORT jint JNICALL
JVM_RecvFrom(jint, char*, int,
@ -2047,7 +2284,13 @@ extern "C" JNIEXPORT jint JNICALL
JVM_SocketAvailable(jint, jint*) { abort(); }
extern "C" JNIEXPORT jint JNICALL
JVM_GetSockName(jint, struct sockaddr*, int*) { abort(); }
JVM_GetSockName(jint socket, struct sockaddr* address, int* addressLength)
{
socklen_t length = *addressLength;
int r = getsockname(socket, address, &length);
*addressLength = length;
return r;
}
extern "C" JNIEXPORT jint JNICALL
JVM_GetSockOpt(jint, int, int, char*, int*) { abort(); }

View File

@ -22,7 +22,7 @@
#ifdef __x86_64__
#define THREAD_STACK 2224
#define THREAD_STACK 2216
#if defined __MINGW32__ || defined __CYGWIN32__

View File

@ -40,7 +40,7 @@ namespace {
namespace local {
const bool DebugCompile = true;
const bool DebugCompile = false;
const bool DebugNatives = false;
const bool DebugCallTable = false;
const bool DebugMethodTree = false;
@ -61,6 +61,20 @@ const unsigned InitialZoneCapacityInBytes = 64 * 1024;
const unsigned ExecutableAreaSizeInBytes = 16 * 1024 * 1024;
enum Root {
CallTable,
MethodTree,
MethodTreeSentinal,
ObjectPools,
StaticTableArray,
VirtualThunks,
ReceiveMethod,
WindMethod,
RewindMethod
};
const unsigned RootCount = RewindMethod + 1;
inline bool
isVmInvokeUnsafeStack(void* ip)
{
@ -169,7 +183,7 @@ class MyThread: public Thread {
// in this function, we "atomically" update the thread context
// fields in such a way to ensure that another thread may
// interrupt us at any time and still get a consistent, accurate
// stack trace. See MyProcess::getStackTrace for details.
// stack trace. See MyProcessor::getStackTrace for details.
assert(t, t->transition == 0);
@ -277,7 +291,7 @@ resolveTarget(MyThread* t, void* stack, object method)
PROTECT(t, method);
PROTECT(t, class_);
resolveSystemClass(t, className(t, class_));
resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_));
if (UNLIKELY(t->exception)) return 0;
}
@ -294,7 +308,7 @@ resolveTarget(MyThread* t, object class_, unsigned index)
if (classVmFlags(t, class_) & BootstrapFlag) {
PROTECT(t, class_);
resolveSystemClass(t, className(t, class_));
resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_));
if (UNLIKELY(t->exception)) return 0;
}
@ -302,10 +316,10 @@ resolveTarget(MyThread* t, object class_, unsigned index)
}
object&
methodTree(MyThread* t);
root(Thread* t, Root root);
object
methodTreeSentinal(MyThread* t);
void
setRoot(Thread* t, Root root, object value);
unsigned
compiledSize(intptr_t address)
@ -348,8 +362,8 @@ methodForIp(MyThread* t, void* ip)
// compile(MyThread*, Allocator*, BootContext*, object)):
loadMemoryBarrier();
return treeQuery(t, methodTree(t), reinterpret_cast<intptr_t>(ip),
methodTreeSentinal(t), compareIpToMethodBounds);
return treeQuery(t, root(t, MethodTree), reinterpret_cast<intptr_t>(ip),
root(t, MethodTreeSentinal), compareIpToMethodBounds);
}
class MyStackWalker: public Processor::StackWalker {
@ -2067,18 +2081,6 @@ unwind(MyThread* t)
vmJump(ip, base, stack, t, 0, 0);
}
object&
objectPools(MyThread* t);
object&
windMethod(MyThread* t);
object&
rewindMethod(MyThread* t);
object&
receiveMethod(MyThread* t);
uintptr_t
defaultThunk(MyThread* t);
@ -2408,11 +2410,10 @@ longToFloat(int64_t a)
}
uint64_t
makeBlankObjectArray(MyThread* t, object loader, object class_, int32_t length)
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
{
if (length >= 0) {
return reinterpret_cast<uint64_t>
(makeObjectArray(t, loader, class_, length));
return reinterpret_cast<uint64_t>(makeObjectArray(t, class_, length));
} else {
object message = makeString(t, "%d", length);
t->exception = t->m->classpath->makeThrowable
@ -2595,14 +2596,14 @@ void NO_RETURN
throwArrayIndexOutOfBounds(MyThread* t)
{
if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) {
t->tracing = true;
atomicOr(&(t->flags), Thread::TracingFlag);
t->exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType);
t->tracing = false;
(t, Machine::ArrayIndexOutOfBoundsExceptionType);
atomicAnd(&(t->flags), ~Thread::TracingFlag);
} else {
// not enough memory available for a new exception and stack trace
// -- use a preallocated instance instead
t->exception = t->m->arrayIndexOutOfBoundsException;
t->exception = root(t, Machine::ArrayIndexOutOfBoundsException);
}
unwind(t);
@ -2658,7 +2659,7 @@ makeNew64(Thread* t, object class_)
void
gcIfNecessary(MyThread* t)
{
if (UNLIKELY(t->useBackupHeap)) {
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
collect(t, Heap::MinorCollection);
}
}
@ -3411,9 +3412,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
frame->trace(0, 0),
BytesPerWord,
Compiler::ObjectType,
4, c->register_(t->arch->thread()),
frame->append(classLoader(t, methodClass(t, context->method))),
frame->append(class_), length));
3, c->register_(t->arch->thread()), frame->append(class_), length));
} break;
case areturn: {
@ -4374,16 +4373,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
if (objectClass(t, v) == type(t, Machine::ReferenceType)) {
object class_ = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return;
frame->pushObject(frame->append(getJClass(t, class_)));
} else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ClassType))
{
} else if (objectClass(t, v) == type(t, Machine::ClassType)) {
frame->pushObject(frame->append(getJClass(t, v)));
} else {
frame->pushObject(frame->append(v));
@ -5723,8 +5718,8 @@ finish(MyThread* t, Allocator* allocator, Context* context)
initArray(t, pool, context->objectPoolCount + 1);
mark(t, pool, 0);
set(t, pool, ArrayBody, objectPools(t));
objectPools(t) = pool;
set(t, pool, ArrayBody, root(t, ObjectPools));
setRoot(t, ObjectPools, pool);
unsigned i = 1;
for (PoolElement* p = context->objectPool; p; p = p->next) {
@ -6009,14 +6004,6 @@ compileMethod2(MyThread* t, void* ip)
t->trace->targetMethod = 0;
}
if (false) {
compile(t, codeAllocator(t), 0, resolveMethod
(t, t->m->loader,
"org/eclipse/swt/widgets/TableItem",
"getBounds",
"(IIZZZZJ)Lorg/eclipse/swt/internal/win32/RECT;"));
}
if (UNLIKELY(t->exception)) {
return 0;
} else {
@ -6494,9 +6481,7 @@ findFrameMap(MyThread* t, void* stack, object method, int32_t offset,
int32_t** map, unsigned* start)
{
object table = codePool(t, methodCode(t, method));
if (objectClass(t, table)
== arrayBody(t, t->m->types, Machine::IntArrayType))
{
if (objectClass(t, table) == type(t, Machine::IntArrayType)) {
findFrameMapInSimpleTable(t, method, table, offset, map, start);
} else {
findFrameMapInGeneralTable(t, stack, method, table, offset, map, start);
@ -6813,16 +6798,16 @@ callContinuation(MyThread* t, object continuation, object result,
nextContinuation = continuationContextContinuation(t, rewindContext);
action = Rewind;
if (rewindMethod(t) == 0) {
if (root(t, RewindMethod) == 0) {
PROTECT(t, nextContinuation);
object method = resolveMethod
(t, t->m->loader, "avian/Continuations", "rewind",
(t, root(t, Machine::BootLoader), "avian/Continuations", "rewind",
"(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;"
"Ljava/lang/Throwable;)V");
if (method) {
rewindMethod(t) = method;
setRoot(t, RewindMethod, method);
compile(t, local::codeAllocator(t), 0, method);
@ -6864,7 +6849,7 @@ callContinuation(MyThread* t, object continuation, object result,
transition(t, 0, 0, 0, nextContinuation, t->trace);
jumpAndInvoke
(t, rewindMethod(t), base, stack,
(t, root(t, RewindMethod), base, stack,
continuationContextBefore(t, continuationContext(t, nextContinuation)),
continuation, result, exception);
} break;
@ -6890,26 +6875,27 @@ callWithCurrentContinuation(MyThread* t, object receiver)
{ PROTECT(t, receiver);
if (receiveMethod(t) == 0) {
if (root(t, ReceiveMethod) == 0) {
object m = resolveMethod
(t, t->m->loader, "avian/CallbackReceiver", "receive",
(t, root(t, Machine::BootLoader), "avian/CallbackReceiver", "receive",
"(Lavian/Callback;)Ljava/lang/Object;");
if (m) {
receiveMethod(t) = m;
setRoot(t, ReceiveMethod, m);
object continuationClass = arrayBody
(t, t->m->types, Machine::ContinuationType);
object continuationClass = type(t, Machine::ContinuationType);
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
resolveSystemClass(t, vm::className(t, continuationClass));
resolveSystemClass
(t, root(t, Machine::BootLoader),
vm::className(t, continuationClass));
}
}
}
if (LIKELY(t->exception == 0)) {
method = findInterfaceMethod
(t, receiveMethod(t), objectClass(t, receiver));
(t, root(t, ReceiveMethod), objectClass(t, receiver));
PROTECT(t, method);
compile(t, local::codeAllocator(t), 0, method);
@ -6938,14 +6924,14 @@ dynamicWind(MyThread* t, object before, object thunk, object after)
PROTECT(t, thunk);
PROTECT(t, after);
if (windMethod(t) == 0) {
if (root(t, WindMethod) == 0) {
object method = resolveMethod
(t, t->m->loader, "avian/Continuations", "wind",
(t, root(t, Machine::BootLoader), "avian/Continuations", "wind",
"(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;"
"Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;");
if (method) {
windMethod(t) = method;
setRoot(t, WindMethod, method);
compile(t, local::codeAllocator(t), 0, method);
}
}
@ -6962,7 +6948,7 @@ dynamicWind(MyThread* t, object before, object thunk, object after)
}
if (LIKELY(t->exception == 0)) {
jumpAndInvoke(t, windMethod(t), base, stack, before, thunk, after);
jumpAndInvoke(t, root(t, WindMethod), base, stack, before, thunk, after);
} else {
unwind(t);
}
@ -7117,7 +7103,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
}
if (t->exception) {
if (UNLIKELY(t->useBackupHeap)) {
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
collect(t, Heap::MinorCollection);
}
return 0;
@ -7173,14 +7159,14 @@ class SegFaultHandler: public System::SignalHandler {
*base, t->continuation, t->trace);
if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) {
t->tracing = true;
atomicOr(&(t->flags), Thread::TracingFlag);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->tracing = false;
atomicAnd(&(t->flags), ~Thread::TracingFlag);
} else {
// not enough memory available for a new NPE and stack trace
// -- use a preallocated instance instead
t->exception = t->m->nullPointerException;
t->exception = root(t, Machine::NullPointerException);
}
// printTrace(t, t->exception);
@ -7220,12 +7206,12 @@ boot(MyThread* t, BootImage* image);
class MyProcessor;
void
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p);
MyProcessor*
processor(MyThread* t);
void
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p);
class MyProcessor: public Processor {
public:
class Thunk {
@ -7255,15 +7241,7 @@ class MyProcessor: public Processor {
MyProcessor(System* s, Allocator* allocator, bool useNativeFeatures):
s(s),
allocator(allocator),
callTable(0),
methodTree(0),
methodTreeSentinal(0),
objectPools(0),
staticTableArray(0),
virtualThunks(0),
receiveMethod(0),
windMethod(0),
rewindMethod(0),
roots(0),
bootImage(0),
codeAllocator(s, 0, 0),
callTableSize(0),
@ -7365,15 +7343,7 @@ class MyProcessor: public Processor {
MyThread* t = static_cast<MyThread*>(vmt);
if (t == t->m->rootThread) {
v->visit(&callTable);
v->visit(&methodTree);
v->visit(&methodTreeSentinal);
v->visit(&objectPools);
v->visit(&staticTableArray);
v->visit(&virtualThunks);
v->visit(&receiveMethod);
v->visit(&windMethod);
v->visit(&rewindMethod);
v->visit(&roots);
}
for (MyThread::CallTrace* trace = t->trace; trace; trace = trace->next) {
@ -7499,16 +7469,6 @@ class MyProcessor: public Processor {
PROTECT(t, method);
if (false) {
compile(static_cast<MyThread*>(t),
local::codeAllocator(static_cast<MyThread*>(t)), 0,
resolveMethod(t, t->m->loader,
"com/ecovate/nat/logic/Cache",
"findInCache",
"(Ljava/lang/String;Ljava/lang/String;JZ)Lcom/ecovate/shared/xmlrpc/Resource;"));
trap();
}
compile(static_cast<MyThread*>(t),
local::codeAllocator(static_cast<MyThread*>(t)), 0, method);
@ -7636,9 +7596,9 @@ class MyProcessor: public Processor {
}
if (ensure(t, traceSize(target))) {
t->tracing = true;
atomicOr(&(t->flags), Thread::TracingFlag);
trace = makeTrace(t, target);
t->tracing = false;
atomicAnd(&(t->flags), ~Thread::TracingFlag);
}
}
@ -7650,7 +7610,7 @@ class MyProcessor: public Processor {
t->m->system->visit(t->systemThread, target->systemThread, &visitor);
if (UNLIKELY(t->useBackupHeap)) {
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
PROTECT(t, visitor.trace);
collect(t, Heap::MinorCollection);
@ -7679,10 +7639,10 @@ class MyProcessor: public Processor {
*addresses = bootContext.addresses;
}
virtual void visitRoots(HeapWalker* w) {
bootImage->methodTree = w->visitRoot(methodTree);
bootImage->methodTreeSentinal = w->visitRoot(methodTreeSentinal);
bootImage->virtualThunks = w->visitRoot(virtualThunks);
virtual void visitRoots(Thread* t, HeapWalker* w) {
bootImage->methodTree = w->visitRoot(root(t, MethodTree));
bootImage->methodTreeSentinal = w->visitRoot(root(t, MethodTreeSentinal));
bootImage->virtualThunks = w->visitRoot(root(t, VirtualThunks));
}
virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) {
@ -7693,8 +7653,10 @@ class MyProcessor: public Processor {
(t->m->heap->allocate(callTableSize * sizeof(unsigned) * 2));
unsigned index = 0;
for (unsigned i = 0; i < arrayLength(t, callTable); ++i) {
for (object p = arrayBody(t, callTable, i); p; p = callNodeNext(t, p)) {
for (unsigned i = 0; i < arrayLength(t, root(t, CallTable)); ++i) {
for (object p = arrayBody(t, root(t, CallTable), i);
p; p = callNodeNext(t, p))
{
table[index++] = callNodeAddress(t, p)
- reinterpret_cast<uintptr_t>(codeAllocator.base);
table[index++] = w->map()->find(callNodeTarget(t, p))
@ -7712,14 +7674,19 @@ class MyProcessor: public Processor {
codeAllocator.capacity = ExecutableAreaSizeInBytes;
}
roots = makeArray(t, RootCount);
if (image) {
local::boot(static_cast<MyThread*>(t), image);
} else {
callTable = makeArray(t, 128);
methodTree = methodTreeSentinal = makeTreeNode(t, 0, 0, 0);
set(t, methodTree, TreeNodeLeft, methodTreeSentinal);
set(t, methodTree, TreeNodeRight, methodTreeSentinal);
setRoot(t, CallTable, makeArray(t, 128));
setRoot(t, MethodTreeSentinal, makeTreeNode(t, 0, 0, 0));
setRoot(t, MethodTree, root(t, MethodTreeSentinal));
set(t, root(t, MethodTree), TreeNodeLeft,
root(t, MethodTreeSentinal));
set(t, root(t, MethodTree), TreeNodeRight,
root(t, MethodTreeSentinal));
}
local::compileThunks(static_cast<MyThread*>(t), &codeAllocator, this);
@ -7776,43 +7743,10 @@ class MyProcessor: public Processor {
abort(t);
}
}
virtual void registerNative(Thread* t, object method, void* function) {
PROTECT(t, method);
expect(t, methodFlags(t, method) & ACC_NATIVE);
object native = makeNative(t, function, false);
// ensure other threads only see the methodCode field populated
// once the object it points do has been populated:
storeStoreMemoryBarrier();
set(t, method, MethodCode, native);
}
virtual void unregisterNatives(Thread* t, object c) {
if (classMethodTable(t, c)) {
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object method = arrayBody(t, classMethodTable(t, c), i);
if (methodFlags(t, method) & ACC_NATIVE) {
set(t, method, MethodCode, 0);
}
}
}
}
System* s;
Allocator* allocator;
object callTable;
object methodTree;
object methodTreeSentinal;
object objectPools;
object staticTableArray;
object virtualThunks;
object receiveMethod;
object windMethod;
object rewindMethod;
object roots;
BootImage* bootImage;
SegFaultHandler segFaultHandler;
FixedAllocator codeAllocator;
@ -7883,11 +7817,10 @@ isThunkUnsafeStack(MyProcessor::ThunkCollection* thunks, void* ip)
bool
isVirtualThunk(MyThread* t, void* ip)
{
MyProcessor* p = processor(t);
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) {
uintptr_t start = wordArrayBody(t, p->virtualThunks, i);
uintptr_t end = start + wordArrayBody(t, p->virtualThunks, i + 1);
for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks)); i += 2)
{
uintptr_t start = wordArrayBody(t, root(t, VirtualThunks), i);
uintptr_t end = start + wordArrayBody(t, root(t, VirtualThunks), i + 1);
if (reinterpret_cast<uintptr_t>(ip) >= start
and reinterpret_cast<uintptr_t>(ip) < end)
@ -7921,8 +7854,7 @@ findCallNode(MyThread* t, void* address)
// compile(MyThread*, Allocator*, BootContext*, object)):
loadMemoryBarrier();
MyProcessor* p = processor(t);
object table = p->callTable;
object table = root(t, CallTable);
intptr_t key = reinterpret_cast<intptr_t>(address);
unsigned index = static_cast<uintptr_t>(key) & (arrayLength(t, table) - 1);
@ -8002,8 +7934,8 @@ insertCallNode(MyThread* t, object table, unsigned* size, object node)
void
insertCallNode(MyThread* t, object node)
{
MyProcessor* p = processor(t);
p->callTable = insertCallNode(t, p->callTable, &(p->callTableSize), node);
setRoot(t, CallTable, insertCallNode
(t, root(t, CallTable), &(processor(t)->callTableSize), node));
}
object
@ -8022,14 +7954,19 @@ makeClassMap(Thread* t, unsigned* table, unsigned count, uintptr_t* heap)
}
object
makeStaticTableArray(Thread* t, unsigned* table, unsigned count,
uintptr_t* heap)
makeStaticTableArray(Thread* t, unsigned* bootTable, unsigned bootCount,
unsigned* appTable, unsigned appCount, uintptr_t* heap)
{
object array = makeArray(t, count);
object array = makeArray(t, bootCount + appCount);
for (unsigned i = 0; i < count; ++i) {
for (unsigned i = 0; i < bootCount; ++i) {
set(t, array, ArrayBody + (i * BytesPerWord),
classStaticTable(t, bootObject(heap, table[i])));
classStaticTable(t, bootObject(heap, bootTable[i])));
}
for (unsigned i = 0; i < appCount; ++i) {
set(t, array, ArrayBody + ((bootCount + i) * BytesPerWord),
classStaticTable(t, bootObject(heap, appTable[i])));
}
return array;
@ -8134,9 +8071,9 @@ fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
}
void
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
fixupMethods(Thread* t, object map, BootImage* image, uint8_t* code)
{
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
for (HashMapIterator it(t, map); it.hasMore();) {
object c = tripleSecond(t, it.next());
if (classMethodTable(t, c)) {
@ -8213,12 +8150,10 @@ fixupThunks(MyThread* t, BootImage* image, uint8_t* code)
void
fixupVirtualThunks(MyThread* t, BootImage* image, uint8_t* code)
{
MyProcessor* p = processor(t);
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) {
if (wordArrayBody(t, p->virtualThunks, i)) {
wordArrayBody(t, p->virtualThunks, i)
= (wordArrayBody(t, p->virtualThunks, i) - image->codeBase)
for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks)); i += 2) {
if (wordArrayBody(t, root(t, VirtualThunks), i)) {
wordArrayBody(t, root(t, VirtualThunks), i)
= (wordArrayBody(t, root(t, VirtualThunks), i) - image->codeBase)
+ reinterpret_cast<uintptr_t>(code);
}
}
@ -8229,8 +8164,9 @@ boot(MyThread* t, BootImage* image)
{
assert(t, image->magic == BootImage::Magic);
unsigned* classTable = reinterpret_cast<unsigned*>(image + 1);
unsigned* stringTable = classTable + image->classCount;
unsigned* bootClassTable = reinterpret_cast<unsigned*>(image + 1);
unsigned* appClassTable = bootClassTable + image->bootClassCount;
unsigned* stringTable = appClassTable + image->appClassCount;
unsigned* callTable = stringTable + image->stringCount;
uintptr_t* heapMap = reinterpret_cast<uintptr_t*>
@ -8254,39 +8190,48 @@ boot(MyThread* t, BootImage* image)
t->m->heap->setImmortalHeap(heap, image->heapSize / BytesPerWord);
t->m->loader = bootObject(heap, image->loader);
setRoot(t, Machine::BootLoader, bootObject(heap, image->bootLoader));
setRoot(t, Machine::AppLoader, bootObject(heap, image->appLoader));
t->m->types = bootObject(heap, image->types);
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
p->methodTree = bootObject(heap, image->methodTree);
p->methodTreeSentinal = bootObject(heap, image->methodTreeSentinal);
setRoot(t, MethodTree, bootObject(heap, image->methodTree));
setRoot(t, MethodTreeSentinal, bootObject(heap, image->methodTreeSentinal));
p->virtualThunks = bootObject(heap, image->virtualThunks);
setRoot(t, VirtualThunks, bootObject(heap, image->virtualThunks));
fixupCode(t, codeMap, codeMapSizeInWords, code, heap);
syncInstructionCache(code, image->codeSize);
t->m->classMap = makeClassMap(t, classTable, image->classCount, heap);
setRoot(t, Machine::ClassMap, makeClassMap
(t, bootClassTable, image->bootClassCount, heap));
t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap);
set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap
(t, appClassTable, image->appClassCount, heap));
setRoot(t, Machine::StringMap, makeStringMap
(t, stringTable, image->stringCount, heap));
p->callTableSize = image->callCount;
p->callTable = makeCallTable
(t, heap, callTable, image->callCount,
reinterpret_cast<uintptr_t>(code));
p->staticTableArray = makeStaticTableArray
(t, classTable, image->classCount, heap);
setRoot(t, CallTable, makeCallTable
(t, heap, callTable, image->callCount,
reinterpret_cast<uintptr_t>(code)));
setRoot(t, StaticTableArray, makeStaticTableArray
(t, bootClassTable, image->bootClassCount,
appClassTable, image->appClassCount, heap));
fixupThunks(t, image, code);
fixupVirtualThunks(t, image, code);
fixupMethods(t, image, code);
fixupMethods(t, root(t, Machine::ClassMap), image, code);
fixupMethods(t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code);
t->m->bootstrapClassMap = makeHashMap(t, 0, 0);
setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0));
}
intptr_t
@ -8539,30 +8484,6 @@ processor(MyThread* t)
return static_cast<MyProcessor*>(t->m->processor);
}
object&
objectPools(MyThread* t)
{
return processor(t)->objectPools;
}
object&
windMethod(MyThread* t)
{
return processor(t)->windMethod;
}
object&
rewindMethod(MyThread* t)
{
return processor(t)->rewindMethod;
}
object&
receiveMethod(MyThread* t)
{
return processor(t)->receiveMethod;
}
uintptr_t
defaultThunk(MyThread* t)
{
@ -8639,32 +8560,30 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size)
uintptr_t
virtualThunk(MyThread* t, unsigned index)
{
MyProcessor* p = processor(t);
if (p->virtualThunks == 0
or wordArrayLength(t, p->virtualThunks) <= index * 2)
if (root(t, VirtualThunks) == 0
or wordArrayLength(t, root(t, VirtualThunks)) <= index * 2)
{
object newArray = makeWordArray(t, nextPowerOfTwo((index + 1) * 2));
if (p->virtualThunks) {
if (root(t, VirtualThunks)) {
memcpy(&wordArrayBody(t, newArray, 0),
&wordArrayBody(t, p->virtualThunks, 0),
wordArrayLength(t, p->virtualThunks) * BytesPerWord);
&wordArrayBody(t, root(t, VirtualThunks), 0),
wordArrayLength(t, root(t, VirtualThunks)) * BytesPerWord);
}
p->virtualThunks = newArray;
setRoot(t, VirtualThunks, newArray);
}
if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) {
if (wordArrayBody(t, root(t, VirtualThunks), index * 2) == 0) {
ACQUIRE(t, t->m->classLock);
if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) {
if (wordArrayBody(t, root(t, VirtualThunks), index * 2) == 0) {
unsigned size;
uintptr_t thunk = compileVirtualThunk(t, index, &size);
wordArrayBody(t, p->virtualThunks, index * 2) = thunk;
wordArrayBody(t, p->virtualThunks, (index * 2) + 1) = size;
wordArrayBody(t, root(t, VirtualThunks), index * 2) = thunk;
wordArrayBody(t, root(t, VirtualThunks), (index * 2) + 1) = size;
}
}
return wordArrayBody(t, p->virtualThunks, index * 2);
return wordArrayBody(t, root(t, VirtualThunks), index * 2);
}
void
@ -8717,10 +8636,12 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
methodCode(t, method),
reinterpret_cast<intptr_t>(compiled));
methodTree(t) = treeInsert
(t, &(context.zone), methodTree(t),
reinterpret_cast<intptr_t>(compiled), clone, methodTreeSentinal(t),
compareIpToMethodBounds);
setRoot
(t, MethodTree, treeInsert
(t, &(context.zone), root(t, MethodTree),
reinterpret_cast<intptr_t>(compiled), clone,
root(t, MethodTreeSentinal),
compareIpToMethodBounds));
storeStoreMemoryBarrier();
@ -8731,22 +8652,23 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
= compiled;
}
treeUpdate(t, methodTree(t), reinterpret_cast<intptr_t>(compiled),
method, methodTreeSentinal(t), compareIpToMethodBounds);
treeUpdate(t, root(t, MethodTree), reinterpret_cast<intptr_t>(compiled),
method, root(t, MethodTreeSentinal), compareIpToMethodBounds);
}
}
}
object&
methodTree(MyThread* t)
root(Thread* t, Root root)
{
return processor(t)->methodTree;
return arrayBody(t, processor(static_cast<MyThread*>(t))->roots, root);
}
object
methodTreeSentinal(MyThread* t)
void
setRoot(Thread* t, Root root, object value)
{
return processor(t)->methodTreeSentinal;
set(t, processor(static_cast<MyThread*>(t))->roots,
ArrayBody + (root * BytesPerWord), value);
}
FixedAllocator*

View File

@ -10,11 +10,11 @@
#ifdef __x86_64__
#define THREAD_CONTINUATION 2232
#define THREAD_CONTINUATION 2224
#define THREAD_EXCEPTION 80
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2240
#define THREAD_EXCEPTION_OFFSET 2248
#define THREAD_EXCEPTION_HANDLER 2256
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2232
#define THREAD_EXCEPTION_OFFSET 2240
#define THREAD_EXCEPTION_HANDLER 2248
#define CONTINUATION_NEXT 8
#define CONTINUATION_ADDRESS 32

View File

@ -1,505 +0,0 @@
/* Copyright (c) 2009, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "machine.h"
#include "constants.h"
#include "processor.h"
#include "util.h"
using namespace vm;
namespace {
void
setProperty(Thread* t, object method, object properties,
const char* name, const void* value, const char* format = "%s")
{
PROTECT(t, method);
PROTECT(t, properties);
object n = makeString(t, "%s", name);
PROTECT(t, n);
object v = makeString(t, format, value);
t->m->processor->invoke(t, method, properties, n, v);
}
} // namespace
namespace vm {
jobject JNICALL
NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
{
const char* pointerClassName;
const char* initSpec;
if (BytesPerWord == 8) {
pointerClassName = "gnu/classpath/Pointer64";
initSpec = "(J)V";
} else {
pointerClassName = "gnu/classpath/Pointer32";
initSpec = "(I)V";
}
object pointerClass = resolveClass(t, t->m->loader, pointerClassName);
if (UNLIKELY(pointerClass == 0)) return 0;
PROTECT(t, pointerClass);
object pointerConstructor = resolveMethod
(t, pointerClass, "<init>", initSpec);
if (UNLIKELY(pointerConstructor == 0)) return 0;
object pointer = make(t, pointerClass);
PROTECT(t, pointer);
t->m->processor->invoke(t, pointerConstructor, pointer, address);
if (UNLIKELY(t->exception)) return 0;
object bufferClass = resolveClass
(t, t->m->loader, "java/nio/DirectByteBufferImpl$ReadWrite");
if (UNLIKELY(bufferClass == 0)) return 0;
PROTECT(t, bufferClass);
object bufferConstructor = resolveMethod
(t, bufferClass, "<init>", "(Lgnu/classpath/Pointer;int)V");
if (UNLIKELY(bufferConstructor == 0)) return 0;
object buffer = make(t, bufferClass);
PROTECT(t, buffer);
t->m->processor->invoke
(t, bufferConstructor, buffer, &pointer, static_cast<jint>(capacity));
if (UNLIKELY(t->exception)) return 0;
return makeLocalReference(t, buffer);
}
void* JNICALL
GetDirectBufferAddress(Thread* t, jobject buffer)
{
object addressField = resolveField
(t, objectClass(t, *buffer), "address", "Lgnu/classpath/Pointer;");
if (UNLIKELY(addressField == 0)) return 0;
object address = cast<object>(*buffer, fieldOffset(t, addressField));
if (address == 0) return 0;
const char* dataSpec;
if (BytesPerWord == 8) {
dataSpec = "J";
} else {
dataSpec = "I";
}
object dataField = resolveField
(t, objectClass(t, address), "data", dataSpec);
if (UNLIKELY(dataField == 0)) return 0;
return cast<void*>(address, fieldOffset(t, dataField));
}
jlong JNICALL
GetDirectBufferCapacity(Thread* t, jobject buffer)
{
object capField = resolveField(t, objectClass(t, *buffer), "cap", "I");
if (UNLIKELY(capField == 0)) return 0;
return cast<jint>(*buffer, fieldOffset(t, capField));
}
} // namespace vm
extern "C" JNIEXPORT void JNICALL
Avian_gnu_classpath_VMSystemProperties_preInit
(Thread* t, object, uintptr_t* arguments)
{
object properties = reinterpret_cast<object>(arguments[0]);
PROTECT(t, properties);
object method = resolveMethod
(t, t->m->loader, "java/util/Properties", "setProperty",
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
if (UNLIKELY(t->exception)) {
return;
}
PROTECT(t, method);
setProperty(t, method, properties, "java.version", "1.5");
setProperty(t, method, properties, "java.specification.version", "1.5");
setProperty(t, method, properties, "java.vm.name", "Avian");
setProperty(t, method, properties, "java.protocol.handler.pkgs", "avian");
setProperty(t, method, properties, "file.encoding", "ASCII");
// specify a bogus library path so we can do our own search in
// VMRuntime.nativeLoad:
#define LIBRARY_PATH_SENTINAL "*"
setProperty(t, method, properties, "java.library.path",
LIBRARY_PATH_SENTINAL);
#ifdef PLATFORM_WINDOWS
# define FILE_SEPARATOR "\\"
setProperty(t, method, properties, "line.separator", "\r\n");
setProperty(t, method, properties, "file.separator", FILE_SEPARATOR);
setProperty(t, method, properties, "path.separator", ";");
setProperty(t, method, properties, "os.name", "Windows");
TCHAR buffer[MAX_PATH];
GetTempPath(MAX_PATH, buffer);
setProperty(t, method, properties, "java.io.tmpdir", buffer);
setProperty(t, method, properties, "java.home", buffer);
setProperty(t, method, properties, "user.home",
_wgetenv(L"USERPROFILE"), "%ls");
GetCurrentDirectory(MAX_PATH, buffer);
setProperty(t, method, properties, "user.dir", buffer);
#else
# define FILE_SEPARATOR "/"
setProperty(t, method, properties, "line.separator", "\n");
setProperty(t, method, properties, "file.separator", FILE_SEPARATOR);
setProperty(t, method, properties, "path.separator", ":");
# ifdef __APPLE__
setProperty(t, method, properties, "os.name", "Mac OS X");
# else
setProperty(t, method, properties, "os.name", "Linux");
# endif
setProperty(t, method, properties, "java.io.tmpdir", "/tmp");
setProperty(t, method, properties, "java.home", "/tmp");
setProperty(t, method, properties, "user.home", getenv("HOME"));
setProperty(t, method, properties, "user.dir", getenv("PWD"));
#endif
#ifdef ARCH_x86_32
setProperty(t, method, properties, "gnu.cpu.endian", "little");
setProperty(t, method, properties, "os.arch", "x86");
#elif defined ARCH_x86_64
setProperty(t, method, properties, "gnu.cpu.endian", "little");
setProperty(t, method, properties, "os.arch", "x86_64");
#elif defined ARCH_powerpc
setProperty(t, method, properties, "gnu.cpu.endian", "big");
setProperty(t, method, properties, "os.arch", "ppc");
#elif defined ARCH_arm
setProperty(t, method, properties, "os.arch", "arm");
#else
setProperty(t, method, properties, "os.arch", "unknown");
#endif
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_gnu_classpath_VMStackWalker_getClassContext
(Thread* t, object, uintptr_t*)
{
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t):
t(t), skipCount(1), trace(0), index(0), protector(t, &trace)
{ }
virtual bool visit(Processor::StackWalker* walker) {
if (skipCount == 0) {
if (trace == 0) {
trace = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType),
walker->count());
}
assert(t, index < objectArrayLength(t, trace));
set(t, trace, ArrayBody + (index * BytesPerWord),
methodClass(t, walker->method()));
++ index;
return true;
} else {
-- skipCount;
return true;
}
}
Thread* t;
unsigned skipCount;
object trace;
unsigned index;
Thread::SingleProtector protector;
} v(t);
t->m->processor->walkStack(t, &v);
if (v.trace == 0) {
v.trace = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType), 0);
}
return reinterpret_cast<int64_t>(v.trace);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_gnu_classpath_VMStackWalker_getClassLoader
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(classLoader(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMRuntime_mapLibraryName
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
PROTECT(t, name);
const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1;
const unsigned nameLength = stringLength(t, name);
const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1;
const unsigned total = soPrefixLength + nameLength + soSuffixLength;
object s = makeByteArray(t, total + 1);
char* p = reinterpret_cast<char*>(&byteArrayBody(t, s, 0));
memcpy(p, SO_PREFIX, soPrefixLength);
stringChars(t, name, p + soPrefixLength);
memcpy(p + soPrefixLength + nameLength, SO_SUFFIX, soSuffixLength);
p[total] = 0;
return reinterpret_cast<int64_t>(makeString(t, s, 0, total, 0));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_System_arraycopy
(Thread*, object, uintptr_t*);
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_VMSystem_arraycopy
(Thread* t, object, uintptr_t* arguments)
{
Avian_java_lang_System_arraycopy(t, 0, arguments);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_load
(Thread* t, object, uintptr_t*);
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMRuntime_nativeLoad
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
// given that we set java.library.path to LIBRARY_PATH_SENTINAL, we
// can determine which names are filenames and which are library
// names by looking for the prefix LIBRARY_PATH_SENTINAL
// FILE_SEPARATOR
unsigned length = stringLength(t, name);
char n[length + 1];
stringChars(t, name, n);
const unsigned pathPrefixLength
= sizeof(LIBRARY_PATH_SENTINAL) - 1
+ sizeof(FILE_SEPARATOR) - 1;
bool mapName = (strncmp(n, LIBRARY_PATH_SENTINAL FILE_SEPARATOR,
pathPrefixLength) == 0);
if (mapName) {
// strip the path prefix, SO prefix, and SO suffix before passing
// the name to Runtime.load
const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1;
const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1;
const unsigned newOffset
= stringOffset(t, name) + pathPrefixLength + soPrefixLength;
const unsigned newLength
= length - pathPrefixLength - soPrefixLength - soSuffixLength;
name = makeString(t, stringData(t, name), newOffset, newLength, 0);
}
uintptr_t args[] = { reinterpret_cast<uintptr_t>(name), mapName };
Avian_java_lang_Runtime_load(t, 0, args);
if (t->exception) {
t->exception = 0;
return 0;
} else {
return 1;
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_primitiveClass
(Thread*, object, uintptr_t*);
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMClassLoader_getPrimitiveClass
(Thread* t, object, uintptr_t* arguments)
{
return Avian_java_lang_Class_primitiveClass(t, 0, arguments);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_defineClass
(Thread*, object, uintptr_t*);
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMClassLoader_defineClass
(Thread* t, object, uintptr_t* arguments)
{
uintptr_t args[]
= { arguments[0], arguments[2], arguments[3], arguments[4] };
// object name = reinterpret_cast<object>(arguments[1]);
// char n[stringLength(t, name) + 1];
// stringChars(t, name, n);
// fprintf(stderr, "define class %s in %p\n", n,
// reinterpret_cast<void*>(arguments[0]));
return Avian_avian_SystemClassLoader_defineClass(t, 0, args);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_System_identityHashCode
(Thread*, object, uintptr_t*);
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMSystem_identityHashCode
(Thread* t, object, uintptr_t* arguments)
{
return Avian_java_lang_System_identityHashCode(t, 0, arguments);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_gc
(Thread*, object, uintptr_t*);
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_VMRuntime_gc
(Thread* t, object, uintptr_t*)
{
Avian_java_lang_Runtime_gc(t, 0, 0);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_VMRuntime_runFinalizationForExit
(Thread*, object, uintptr_t*)
{
// ignore
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_VMRuntime_exit
(Thread*, object, uintptr_t* arguments)
{
exit(arguments[0]);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findClass
(Thread*, object, uintptr_t*);
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMClassLoader_loadClass
(Thread* t, object, uintptr_t* arguments)
{
uintptr_t args[] = { 0, arguments[0] };
// object name = reinterpret_cast<object>(arguments[0]);
// char n[stringLength(t, name) + 1];
// stringChars(t, name, n);
// fprintf(stderr, "load bootstrap class %s in %p\n", n, t->m->loader);
int64_t result = Avian_avian_SystemClassLoader_findClass(t, 0, args);
// fprintf(stderr, "result %p\n", reinterpret_cast<void*>(result));
return result;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_VMClassLoader_resolveClass
(Thread*, object, uintptr_t*)
{
// ignore
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_VMClassLoader_findLoadedClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
object map = getClassLoaderMap(t, loader);
if (map) {
PROTECT(t, loader);
object name = reinterpret_cast<object>(arguments[1]);
PROTECT(t, name);
object n = makeByteArray(t, stringLength(t, name) + 1);
char* s = reinterpret_cast<char*>(&byteArrayBody(t, n, 0));
stringChars(t, name, s);
replace('.', '/', s);
return reinterpret_cast<int64_t>
(hashMapFind
(t, getClassLoaderMap(t, loader), n, byteArrayHash, byteArrayEqual));
} else {
return 0;
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapInt
(Thread*, object, uintptr_t* arguments)
{
object target = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
int32_t expect = arguments[4];
int32_t update = arguments[5];
return __sync_bool_compare_and_swap
(&cast<int32_t>(target, offset), expect, update);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapLong
(Thread*, object, uintptr_t* arguments)
{
object target = reinterpret_cast<object>(arguments[1]);
int64_t offset; memcpy(&offset, arguments + 2, 8);
int64_t expect; memcpy(&expect, arguments + 4, 8);
int64_t update; memcpy(&update, arguments + 6, 8);
return __sync_bool_compare_and_swap
(&cast<int64_t>(target, offset), expect, update);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_objectFieldOffset
(Thread* t, object, uintptr_t* arguments)
{
return fieldOffset(t, reinterpret_cast<object>(arguments[1]));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8
(Thread*, object, uintptr_t*)
{
return 0;
}

View File

@ -76,8 +76,7 @@ dumpHeap(Thread* t, FILE* out)
local::write1(out, local::Size);
local::write4(out, local::objectSize(t, p));
if (objectClass(t, p) == arrayBody(t, t->m->types, Machine::ClassType))
{
if (objectClass(t, p) == type(t, Machine::ClassType)) {
object name = className(t, p);
if (name) {
local::write1(out, local::ClassName);

View File

@ -429,80 +429,17 @@ class MyStackWalker: public Processor::StackWalker {
int frame;
};
object
makeNativeMethodData(Thread* t, object method, void* function)
{
PROTECT(t, method);
unsigned count = methodParameterCount(t, method) + 2;
object data = makeNativeMethodData(t,
function,
0, // argument table size
count);
unsigned argumentTableSize = BytesPerWord * 2;
unsigned index = 0;
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
const char* s = reinterpret_cast<const char*>
(&byteArrayBody(t, methodSpec(t, method), 0));
++ s; // skip '('
while (*s and *s != ')') {
unsigned code = fieldCode(t, *s);
nativeMethodDataParameterTypes(t, data, index++) = fieldType(t, code);
switch (*s) {
case 'L':
argumentTableSize += BytesPerWord;
while (*s and *s != ';') ++ s;
++ s;
break;
case '[':
argumentTableSize += BytesPerWord;
while (*s == '[') ++ s;
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
break;
default:
++ s;
break;
}
break;
default:
argumentTableSize += pad(primitiveSize(t, code));
++ s;
break;
}
}
nativeMethodDataArgumentTableSize(t, data) = argumentTableSize;
return data;
}
inline void
resolveNativeMethodData(Thread* t, object method)
resolveNative(Thread* t, object method)
{
if (methodCode(t, method) == 0) {
void* p = resolveNativeMethod(t, method);
if (LIKELY(p)) {
PROTECT(t, method);
object data = makeNativeMethodData(t, method, p);
// ensure other threads see updated methodVmFlags before
// methodCode, and that the native method data is initialized
// before it is visible to those threads:
object native = resolveNativeMethod(t, method);
if (LIKELY(native)) {
// ensure other threads only see the methodCode field populated
// once the object it points do has been populated:
storeStoreMemoryBarrier();
set(t, method, MethodCode, data);
set(t, method, MethodCode, native);
} else {
object message = makeString
(t, "%s.%s%s",
@ -600,27 +537,35 @@ pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect)
}
void
marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
object data, bool indirect)
marshalArguments(Thread* t, uintptr_t* args, uint8_t* types, unsigned sp,
object method, bool indirect)
{
unsigned offset = 0;
unsigned sp = frameBase(t, t->frame);
for (; i < count; ++i) {
unsigned type = nativeMethodDataParameterTypes(t, data, i + 1);
MethodSpecIterator it
(t, reinterpret_cast<const char*>
(&byteArrayBody(t, methodSpec(t, method), 0)));
unsigned argOffset = 0;
unsigned typeOffset = 0;
while (it.hasNext()) {
unsigned type = fieldType(t, fieldCode(t, *it.next()));
if (types) {
types[typeOffset++] = type;
}
switch (type) {
case INT8_TYPE:
case INT16_TYPE:
case INT32_TYPE:
case FLOAT_TYPE:
args[offset++] = peekInt(t, sp++);
args[argOffset++] = peekInt(t, sp++);
break;
case DOUBLE_TYPE:
case INT64_TYPE: {
uint64_t v = peekLong(t, sp);
memcpy(args + offset, &v, 8);
offset += (8 / BytesPerWord);
memcpy(args + argOffset, &v, 8);
argOffset += (8 / BytesPerWord);
sp += 2;
} break;
@ -630,9 +575,9 @@ marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
if (*v == 0) {
v = 0;
}
args[offset++] = reinterpret_cast<uintptr_t>(v);
args[argOffset++] = reinterpret_cast<uintptr_t>(v);
} else {
args[offset++] = reinterpret_cast<uintptr_t>(peekObject(t, sp++));
args[argOffset++] = reinterpret_cast<uintptr_t>(peekObject(t, sp++));
}
} break;
@ -642,39 +587,51 @@ marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
}
unsigned
invokeNativeSlow(Thread* t, object method)
invokeNativeSlow(Thread* t, object method, void* function)
{
PROTECT(t, method);
object data = methodCode(t, method);
PROTECT(t, data);
pushFrame(t, method);
unsigned count = nativeMethodDataLength(t, data) - 1;
unsigned size = nativeMethodDataArgumentTableSize(t, data);
uintptr_t args[size / BytesPerWord];
unsigned offset = 0;
args[offset++] = reinterpret_cast<uintptr_t>(t);
unsigned i = 0;
unsigned footprint = methodParameterFootprint(t, method) + 1;
if (methodFlags(t, method) & ACC_STATIC) {
++ i;
args[offset++] = reinterpret_cast<uintptr_t>
(pushReference(t, methodClass(t, method)));
++ footprint;
}
unsigned count = methodParameterCount(t, method) + 2;
marshalArguments(t, args + offset, i, count, data, true);
RUNTIME_ARRAY(uintptr_t, args, footprint);
unsigned argOffset = 0;
RUNTIME_ARRAY(uint8_t, types, count);
unsigned typeOffset = 0;
RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast<uintptr_t>(t);
RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE;
object jclass = 0;
PROTECT(t, jclass);
unsigned sp;
if (methodFlags(t, method) & ACC_STATIC) {
sp = frameBase(t, t->frame);
jclass = getJClass(t, methodClass(t, method));
RUNTIME_ARRAY_BODY(args)[argOffset++]
= reinterpret_cast<uintptr_t>(&jclass);
} else {
sp = frameBase(t, t->frame);
object* v = reinterpret_cast<object*>(t->stack + ((sp++) * 2) + 1);
if (*v == 0) {
v = 0;
}
RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast<uintptr_t>(v);
}
RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE;
marshalArguments
(t, RUNTIME_ARRAY_BODY(args) + argOffset,
RUNTIME_ARRAY_BODY(types) + typeOffset, sp, method, true);
unsigned returnCode = methodReturnCode(t, method);
unsigned returnType = fieldType(t, returnCode);
void* function = nativeMethodDataFunction(t, data);
uint8_t types[nativeMethodDataLength(t, data)];
memcpy(&types,
&nativeMethodDataParameterTypes(t, data, 0),
nativeMethodDataLength(t, data));
uint64_t result;
if (DebugRun) {
@ -682,25 +639,15 @@ invokeNativeSlow(Thread* t, object method)
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
&byteArrayBody(t, methodName(t, method), 0));
}
// if (strcmp(reinterpret_cast<const char*>
// (&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
// "org/eclipse/swt/internal/C") == 0
// and strcmp(reinterpret_cast<const char*>
// (&byteArrayBody(t, methodName(t, method), 0)),
// "memmove") == 0)
// {
// asm("int3");
// }
{ ENTER(t, Thread::IdleState);
result = t->m->system->call
(function,
args,
types,
count + 1,
size,
RUNTIME_ARRAY_BODY(args),
RUNTIME_ARRAY_BODY(types),
count,
footprint * BytesPerWord,
returnType);
}
@ -728,24 +675,32 @@ invokeNative(Thread* t, object method)
{
PROTECT(t, method);
resolveNativeMethodData(t, method);
resolveNative(t, method);
if (UNLIKELY(t->exception)) {
return VoidField;
}
if (methodVmFlags(t, method) & FastNative) {
object native = methodCode(t, method);
if (nativeFast(t, native)) {
pushFrame(t, method);
object data = methodCode(t, method);
uintptr_t arguments[methodParameterFootprint(t, method)];
unsigned footprint = methodParameterFootprint(t, method) + 1;
RUNTIME_ARRAY(uintptr_t, args, footprint);
unsigned sp = frameBase(t, t->frame);
unsigned argOffset = 0;
if (methodFlags(t, method) & ACC_STATIC) {
++ footprint;
} else {
RUNTIME_ARRAY_BODY(args)[argOffset++]
= reinterpret_cast<uintptr_t>(peekObject(t, sp++));
}
marshalArguments
(t, arguments, (methodFlags(t, method) & ACC_STATIC) ? 1 : 0,
nativeMethodDataLength(t, data) - 1, data, false);
(t, RUNTIME_ARRAY_BODY(args) + argOffset, 0, sp, method, false);
uint64_t result = reinterpret_cast<FastNativeFunction>
(nativeMethodDataFunction(t, methodCode(t, method)))
(t, method, arguments);
(nativeFunction(t, native))(t, method, RUNTIME_ARRAY_BODY(args));
popFrame(t);
@ -757,7 +712,7 @@ invokeNative(Thread* t, object method)
return methodReturnCode(t, method);
} else {
return invokeNativeSlow(t, method);
return invokeNativeSlow(t, method, nativeFunction(t, native));
}
}
@ -1004,9 +959,7 @@ interpret(Thread* t)
object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
pushObject(t, makeObjectArray
(t, classLoader(t, methodClass(t, frameMethod(t, frame))),
class_, count));
pushObject(t, makeObjectArray(t, class_, count));
} else {
object message = makeString(t, "%d", count);
exception = t->m->classpath->makeThrowable
@ -1070,9 +1023,7 @@ interpret(Thread* t)
object array = popObject(t);
if (LIKELY(array)) {
if (objectClass(t, array)
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
{
if (objectClass(t, array) == type(t, Machine::BooleanArrayType)) {
if (LIKELY(index >= 0 and
static_cast<uintptr_t>(index)
< booleanArrayLength(t, array)))
@ -1113,9 +1064,7 @@ interpret(Thread* t)
object array = popObject(t);
if (LIKELY(array)) {
if (objectClass(t, array)
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
{
if (objectClass(t, array) == type(t, Machine::BooleanArrayType)) {
if (LIKELY(index >= 0 and
static_cast<uintptr_t>(index)
< booleanArrayLength(t, array)))
@ -2259,17 +2208,13 @@ interpret(Thread* t)
if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
if (objectClass(t, v) == type(t, Machine::ReferenceType)) {
object class_ = resolveClassInPool
(t, frameMethod(t, frame), index - 1);
if (UNLIKELY(exception)) goto throw_;
pushObject(t, getJClass(t, class_));
} else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ClassType))
{
} else if (objectClass(t, v) == type(t, Machine::ClassType)) {
pushObject(t, getJClass(t, v));
} else {
pushObject(t, v);
@ -3031,7 +2976,7 @@ invoke(Thread* t, object method)
class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint));
if (classVmFlags(t, class_) & BootstrapFlag) {
resolveClass(t, t->m->loader, className(t, class_));
resolveClass(t, root(t, Machine::BootLoader), className(t, class_));
}
if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
@ -3333,7 +3278,7 @@ class MyProcessor: public Processor {
abort(s);
}
virtual void visitRoots(HeapWalker*) {
virtual void visitRoots(vm::Thread*, HeapWalker*) {
abort(s);
}

View File

@ -176,9 +176,7 @@ GetStringCritical(Thread* t, jstring s, jboolean* isCopy)
}
object data = stringData(t, *s);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
return GetStringChars(t, s, isCopy);
} else {
return &charArrayBody(t, data, stringOffset(t, *s));
@ -188,9 +186,7 @@ GetStringCritical(Thread* t, jstring s, jboolean* isCopy)
void JNICALL
ReleaseStringCritical(Thread* t, jstring s, const jchar* chars)
{
if (objectClass(t, stringData(t, *s))
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, stringData(t, *s)) == type(t, Machine::ByteArrayType)) {
ReleaseStringChars(t, s, chars);
}
@ -294,7 +290,7 @@ DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer,
ENTER(t, Thread::ActiveState);
object c = defineClass
(t, loader ? *loader : t->m->loader,
(t, loader ? *loader : root(t, Machine::BootLoader),
reinterpret_cast<const uint8_t*>(buffer), length);
return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c));
@ -308,7 +304,7 @@ FindClass(Thread* t, const char* name)
object n = makeByteArray(t, strlen(name) + 1);
replace('.', '/', name, &byteArrayBody(t, n, 0));
object c = resolveClass(t, t->m->loader, n);
object c = resolveClass(t, root(t, Machine::AppLoader), n);
return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c));
}
@ -430,8 +426,9 @@ methodID(Thread* t, object method)
ACQUIRE(t, t->m->referenceLock);
if (methodNativeID(t, method) == 0) {
t->m->jniMethodTable = vectorAppend(t, t->m->jniMethodTable, method);
methodNativeID(t, method) = vectorSize(t, t->m->jniMethodTable);
setRoot(t, Machine::JNIMethodTable, vectorAppend
(t, root(t, Machine::JNIMethodTable), method));
methodNativeID(t, method) = vectorSize(t, root(t, Machine::JNIMethodTable));
}
}
@ -470,7 +467,7 @@ GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
inline object
getMethod(Thread* t, jmethodID m)
{
object method = vectorBody(t, t->m->jniMethodTable, m - 1);
object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1);
assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
@ -733,7 +730,7 @@ CallVoidMethod(Thread* t, jobject o, jmethodID m, ...)
inline object
getStaticMethod(Thread* t, jmethodID m)
{
object method = vectorBody(t, t->m->jniMethodTable, m - 1);
object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1);
assert(t, methodFlags(t, method) & ACC_STATIC);
@ -1342,9 +1339,7 @@ NewObjectArray(Thread* t, jsize length, jclass class_, jobject init)
{
ENTER(t, Thread::ActiveState);
object a = makeObjectArray
(t, classLoader(t, jclassVmClass(t, *class_)), jclassVmClass(t, *class_),
length);
object a = makeObjectArray(t, jclassVmClass(t, *class_), length);
object value = (init ? *init : 0);
for (jsize i = 0; i < length; ++i) {
set(t, a, ArrayBody + (i * BytesPerWord), value);
@ -1934,7 +1929,7 @@ RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods,
object method = findMethod(t, c, methods[i].name, methods[i].signature);
if (UNLIKELY(t->exception)) return -1;
t->m->processor->registerNative(t, method, methods[i].function);
registerNative(t, method, methods[i].function);
}
}
@ -1946,7 +1941,7 @@ UnregisterNatives(Thread* t, jclass c)
{
ENTER(t, Thread::ActiveState);
t->m->processor->unregisterNatives(t, *c);
unregisterNatives(t, *c);
return 0;
}
@ -2314,21 +2309,21 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
unsigned bcppl = strlen(bootClasspathPrepend);
unsigned bcpl = strlen(bootClasspath);
unsigned bcpal = strlen(bootClasspathAppend);
unsigned cpl = strlen(classpath);
unsigned classpathBufferSize = bcppl + bcpl + bcpal + cpl + 4;
RUNTIME_ARRAY(char, classpathBuffer, classpathBufferSize);
char* classpathPointer = RUNTIME_ARRAY_BODY(classpathBuffer);
unsigned bootClasspathBufferSize = bcppl + bcpl + bcpal + 3;
RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize);
char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer);
local::append
(&classpathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR);
local::append(&classpathPointer, bootClasspath, bcpl, PATH_SEPARATOR);
local::append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR);
local::append(&classpathPointer, classpath, cpl, 0);
(&bootClasspathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR);
local::append(&bootClasspathPointer, bootClasspath, bcpl,
bcpal ? PATH_SEPARATOR : 0);
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
System* s = makeSystem(crashDumpDirectory);
Heap* h = makeHeap(s, heapLimit);
Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary);
Finder* bf = makeFinder
(s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
Finder* af = makeFinder(s, classpath, bootLibrary);
Processor* p = makeProcessor(s, h, true);
Classpath* c = makeClasspath(s, h);
@ -2342,15 +2337,9 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
}
*m = new (h->allocate(sizeof(Machine)))
Machine(s, h, f, p, c, properties, propertyCount);
Machine(s, h, bf, af, p, c, properties, propertyCount);
*t = p->makeThread(*m, 0, 0);
enter(*t, Thread::ActiveState);
c->boot(*t);
enter(*t, Thread::IdleState);
return 0;
}

View File

@ -167,25 +167,29 @@ turnOffTheLights(Thread* t)
enter(t, Thread::ExitState);
for (object* p = &(t->m->finalizers); *p;) {
object f = *p;
*p = finalizerNext(t, *p);
{ object p = 0;
PROTECT(t, p);
void (*function)(Thread*, object);
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
if (function) {
function(t, finalizerTarget(t, f));
for (p = t->m->finalizers; p;) {
object f = p;
p = finalizerNext(t, p);
void (*function)(Thread*, object);
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
if (function) {
function(t, finalizerTarget(t, f));
}
}
}
for (object* p = &(t->m->tenuredFinalizers); *p;) {
object f = *p;
*p = finalizerNext(t, *p);
for (p = t->m->tenuredFinalizers; p;) {
object f = p;
p = finalizerNext(t, p);
void (*function)(Thread*, object);
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
if (function) {
function(t, finalizerTarget(t, f));
void (*function)(Thread*, object);
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
if (function) {
function(t, finalizerTarget(t, f));
}
}
}
@ -197,14 +201,16 @@ turnOffTheLights(Thread* t)
Heap* h = m->heap;
Processor* p = m->processor;
Classpath* c = m->classpath;
Finder* f = m->finder;
Finder* bf = m->bootFinder;
Finder* af = m->appFinder;
m->dispose();
h->disposeFixies();
c->dispose();
p->dispose();
h->dispose();
f->dispose();
bf->dispose();
af->dispose();
s->dispose();
}
@ -554,10 +560,10 @@ postCollect(Thread* t)
t->heapOffset = 0;
t->heapIndex = 0;
if (t->useBackupHeap) {
if (t->flags & Thread::UseBackupHeapFlag) {
memset(t->backupHeap, 0, ThreadBackupHeapSizeInBytes);
t->useBackupHeap = false;
t->flags &= ~Thread::UseBackupHeapFlag;
t->backupHeapIndex = 0;
}
@ -711,7 +717,8 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
void
removeByteArray(Thread* t, object o)
{
hashMapRemove(t, t->m->byteArrayMap, o, byteArrayHash, objectEqual);
hashMapRemove
(t, root(t, Machine::ByteArrayMap), o, byteArrayHash, objectEqual);
}
object
@ -720,11 +727,11 @@ internByteArray(Thread* t, object array)
PROTECT(t, array);
object n = hashMapFindNode
(t, t->m->byteArrayMap, array, byteArrayHash, byteArrayEqual);
(t, root(t, Machine::ByteArrayMap), array, byteArrayHash, byteArrayEqual);
if (n) {
return jreferenceTarget(t, tripleFirst(t, n));
} else {
hashMapInsert(t, t->m->byteArrayMap, array, 0, byteArrayHash);
hashMapInsert(t, root(t, Machine::ByteArrayMap), array, 0, byteArrayHash);
addFinalizer(t, array, removeByteArray);
return array;
}
@ -752,9 +759,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
case CONSTANT_Utf8: {
if (singletonObject(t, pool, i) == 0) {
object value = parseUtf8(t, s, s.read2());
if (objectClass(t, value)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, value) == type(t, Machine::ByteArrayType)) {
value = internByteArray(t, value);
}
set(t, pool, SingletonBody + (i * BytesPerWord), value);
@ -1698,8 +1703,19 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
object elementClass)
{
// todo: arrays should implement Cloneable and Serializable
object vtable = classVirtualTable
(t, arrayBody(t, t->m->types, Machine::JobjectType));
if (classVmFlags(t, type(t, Machine::JobjectType)) & BootstrapFlag) {
PROTECT(t, spec);
PROTECT(t, elementClass);
resolveSystemClass
(t, root(t, Machine::BootLoader),
className(t, type(t, Machine::JobjectType)));
if (UNLIKELY(t->exception)) return 0;
}
object vtable = classVirtualTable(t, type(t, Machine::JobjectType));
object c = t->m->processor->makeClass
(t,
@ -1708,10 +1724,10 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
2 * BytesPerWord,
BytesPerWord,
dimensions,
classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)),
classObjectMask(t, type(t, Machine::ArrayType)),
spec,
0,
arrayBody(t, t->m->types, Machine::JobjectType),
type(t, Machine::JobjectType),
0,
vtable,
0,
@ -1727,7 +1743,7 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
}
object
makeArrayClass(Thread* t, object loader, object spec)
makeArrayClass(Thread* t, object loader, object spec, bool throw_)
{
PROTECT(t, loader);
PROTECT(t, spec);
@ -1765,30 +1781,31 @@ makeArrayClass(Thread* t, object loader, object spec)
}
object elementClass = hashMapFind
(t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
(t, root(t, Machine::BootstrapClassMap), elementSpec, byteArrayHash,
byteArrayEqual);
if (elementClass == 0) {
elementClass = resolveClass(t, loader, elementSpec);
if (UNLIKELY(t->exception)) return 0;
elementClass = resolveClass(t, loader, elementSpec, throw_);
if (elementClass == 0) return 0;
}
return makeArrayClass(t, loader, dimensions, spec, elementClass);
}
object
resolveArrayClass(Thread* t, object loader, object spec)
resolveArrayClass(Thread* t, object loader, object spec, bool throw_)
{
object c = hashMapFind
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
(t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash,
byteArrayEqual);
if (c) {
set(t, c, ClassVirtualTable,
classVirtualTable
(t, arrayBody(t, t->m->types, Machine::JobjectType)));
classVirtualTable(t, type(t, Machine::JobjectType)));
return c;
} else {
return makeArrayClass(t, loader, spec);
return makeArrayClass(t, loader, spec, throw_);
}
}
@ -1803,7 +1820,8 @@ removeMonitor(Thread* t, object o)
hash = objectHash(t, o);
}
object m = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual);
object m = hashMapRemove
(t, root(t, Machine::MonitorMap), o, objectHash, objectEqual);
expect(t, m);
@ -1815,14 +1833,15 @@ removeMonitor(Thread* t, object o)
void
removeString(Thread* t, object o)
{
hashMapRemove(t, t->m->stringMap, o, stringHash, objectEqual);
hashMapRemove(t, root(t, Machine::StringMap), o, stringHash, objectEqual);
}
void
bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
unsigned fixedSize, unsigned arrayElementSize, unsigned vtableLength)
{
object super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
object super = (superType >= 0
? vm::type(t, static_cast<Machine::Type>(superType)) : 0);
object mask;
if (objectMask) {
@ -1831,7 +1850,8 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
and intArrayBody(t, classObjectMask(t, super), 0)
== static_cast<int32_t>(objectMask))
{
mask = classObjectMask(t, arrayBody(t, t->m->types, superType));
mask = classObjectMask
(t, vm::type(t, static_cast<Machine::Type>(superType)));
} else {
mask = makeIntArray(t, 1);
intArrayBody(t, mask, 0) = objectMask;
@ -1840,14 +1860,15 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
mask = 0;
}
super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
super = (superType >= 0
? vm::type(t, static_cast<Machine::Type>(superType)) : 0);
object class_ = t->m->processor->makeClass
(t, 0, BootstrapFlag, fixedSize, arrayElementSize,
arrayElementSize ? 1 : 0, mask, 0, 0, super, 0, 0, 0, 0, 0, 0,
t->m->loader, vtableLength);
root(t, Machine::BootLoader), vtableLength);
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
setType(t, type, class_);
}
void
@ -1857,7 +1878,7 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
PROTECT(t, bootMethod);
object n = makeByteArray(t, name);
object class_ = arrayBody(t, t->m->types, type);
object class_ = vm::type(t, type);
set(t, class_, ClassName, n);
@ -1870,14 +1891,16 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
arrayBody(t, vtable, i) = bootMethod;
}
} else {
vtable = classVirtualTable(t, arrayBody(t, t->m->types, superType));
vtable = classVirtualTable
(t, vm::type(t, static_cast<Machine::Type>(superType)));
}
set(t, class_, ClassVirtualTable, vtable);
t->m->processor->initVtable(t, class_);
hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash);
hashMapInsert
(t, root(t, Machine::BootstrapClassMap), n, class_, byteArrayHash);
}
void
@ -1887,92 +1910,103 @@ boot(Thread* t)
m->unsafe = true;
m->loader = allocate(t, FixedSizeOfSystemClassLoader, true);
m->roots = allocate(t, pad((Machine::RootCount + 2) * BytesPerWord), true);
arrayLength(t, m->roots) = Machine::RootCount;
setRoot(t, Machine::BootLoader,
allocate(t, FixedSizeOfSystemClassLoader, true));
setRoot(t, Machine::AppLoader,
allocate(t, FixedSizeOfSystemClassLoader, true));
m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
arrayLength(t, m->types) = TypeCount;
#include "type-initializations.cpp"
object arrayClass = arrayBody(t, m->types, Machine::ArrayType);
object arrayClass = type(t, Machine::ArrayType);
set(t, m->types, 0, arrayClass);
set(t, m->roots, 0, arrayClass);
object loaderClass = arrayBody
(t, m->types, Machine::SystemClassLoaderType);
set(t, m->loader, 0, loaderClass);
object loaderClass = type(t, Machine::SystemClassLoaderType);
set(t, root(t, Machine::BootLoader), 0, loaderClass);
set(t, root(t, Machine::AppLoader), 0, loaderClass);
#ifdef AVIAN_GNU
classLoaderInitialized(t, m->loader) = true;
#endif
object objectClass = type(t, Machine::JobjectType);
object objectClass = arrayBody(t, m->types, Machine::JobjectType);
object classClass = arrayBody(t, m->types, Machine::ClassType);
object classClass = type(t, Machine::ClassType);
set(t, classClass, 0, classClass);
set(t, classClass, ClassSuper, objectClass);
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
object intArrayClass = type(t, Machine::IntArrayType);
set(t, intArrayClass, 0, classClass);
set(t, intArrayClass, ClassSuper, objectClass);
m->unsafe = false;
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
classVmFlags(t, type(t, Machine::SingletonType))
|= SingletonFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
classVmFlags(t, type(t, Machine::ContinuationType))
|= ContinuationFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
classVmFlags(t, type(t, Machine::JreferenceType))
|= ReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
classVmFlags(t, type(t, Machine::WeakReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::SoftReferenceType))
classVmFlags(t, type(t, Machine::SoftReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType))
classVmFlags(t, type(t, Machine::PhantomReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JbooleanType))
classVmFlags(t, type(t, Machine::JbooleanType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JbyteType))
classVmFlags(t, type(t, Machine::JbyteType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JcharType))
classVmFlags(t, type(t, Machine::JcharType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JshortType))
classVmFlags(t, type(t, Machine::JshortType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JintType))
classVmFlags(t, type(t, Machine::JintType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JlongType))
classVmFlags(t, type(t, Machine::JlongType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JfloatType))
classVmFlags(t, type(t, Machine::JfloatType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JdoubleType))
classVmFlags(t, type(t, Machine::JdoubleType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType))
classVmFlags(t, type(t, Machine::JvoidType))
|= PrimitiveFlag;
set(t, arrayBody(t, m->types, Machine::BooleanArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JbooleanType));
set(t, arrayBody(t, m->types, Machine::ByteArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JbyteType));
set(t, arrayBody(t, m->types, Machine::CharArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JcharType));
set(t, arrayBody(t, m->types, Machine::ShortArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JshortType));
set(t, arrayBody(t, m->types, Machine::IntArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JintType));
set(t, arrayBody(t, m->types, Machine::LongArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JlongType));
set(t, arrayBody(t, m->types, Machine::FloatArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JfloatType));
set(t, arrayBody(t, m->types, Machine::DoubleArrayType), ClassStaticTable,
arrayBody(t, m->types, Machine::JdoubleType));
set(t, type(t, Machine::BooleanArrayType), ClassStaticTable,
type(t, Machine::JbooleanType));
set(t, type(t, Machine::ByteArrayType), ClassStaticTable,
type(t, Machine::JbyteType));
set(t, type(t, Machine::CharArrayType), ClassStaticTable,
type(t, Machine::JcharType));
set(t, type(t, Machine::ShortArrayType), ClassStaticTable,
type(t, Machine::JshortType));
set(t, type(t, Machine::IntArrayType), ClassStaticTable,
type(t, Machine::JintType));
set(t, type(t, Machine::LongArrayType), ClassStaticTable,
type(t, Machine::JlongType));
set(t, type(t, Machine::FloatArrayType), ClassStaticTable,
type(t, Machine::JfloatType));
set(t, type(t, Machine::DoubleArrayType), ClassStaticTable,
type(t, Machine::JdoubleType));
m->classMap = makeHashMap(t, 0, 0);
setRoot(t, Machine::ClassMap, makeHashMap(t, 0, 0));
m->bootstrapClassMap = makeHashMap(t, 0, 0);
{ object map = makeHashMap(t, 0, 0);
set(t, root(t, Machine::AppLoader), ClassLoaderMap, map);
}
m->stringMap = makeWeakHashMap(t, 0, 0);
set(t, root(t, Machine::AppLoader), ClassLoaderParent,
root(t, Machine::BootLoader));
setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0));
setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0));
m->processor->boot(t, 0);
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1);
@ -2074,15 +2108,16 @@ class HeapClient: public Heap::Client {
namespace vm {
Machine::Machine(System* system, Heap* heap, Finder* finder,
Processor* processor, Classpath* classpath,
Machine::Machine(System* system, Heap* heap, Finder* bootFinder,
Finder* appFinder, Processor* processor, Classpath* classpath,
const char** properties, unsigned propertyCount):
vtable(&javaVMVTable),
system(system),
heapClient(new (heap->allocate(sizeof(HeapClient)))
HeapClient(this)),
heap(heap),
finder(finder),
bootFinder(bootFinder),
appFinder(appFinder),
processor(processor),
classpath(classpath),
rootThread(0),
@ -2102,24 +2137,13 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
referenceLock(0),
shutdownLock(0),
libraries(0),
loader(0),
classMap(0),
loadClassMethod(0),
bootstrapClassMap(0),
monitorMap(0),
stringMap(0),
byteArrayMap(0),
types(0),
jniMethodTable(0),
roots(0),
finalizers(0),
tenuredFinalizers(0),
finalizeQueue(0),
weakReferences(0),
tenuredWeakReferences(0),
shutdownHooks(0),
objectsToFinalize(0),
nullPointerException(0),
arrayIndexOutOfBoundsException(0),
unsafe(false),
triedBuiltinOnLoad(false),
heapPoolIndex(0)
@ -2194,13 +2218,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
(m->heap->allocate(ThreadHeapSizeInBytes))),
heap(defaultHeap),
backupHeapIndex(0),
useBackupHeap(false),
waiting(false),
tracing(false),
daemon(false)
#ifdef VM_STRESS
, stress(false)
#endif // VM_STRESS
flags(ActiveFlag)
{ }
void
@ -2241,16 +2259,10 @@ Thread::init()
boot(this);
}
m->byteArrayMap = makeWeakHashMap(this, 0, 0);
m->monitorMap = makeWeakHashMap(this, 0, 0);
setRoot(this, Machine::ByteArrayMap, makeWeakHashMap(this, 0, 0));
setRoot(this, Machine::MonitorMap, makeWeakHashMap(this, 0, 0));
m->jniMethodTable = makeVector(this, 0, 0);
m->nullPointerException = m->classpath->makeThrowable
(this, Machine::NullPointerExceptionType);
m->arrayIndexOutOfBoundsException = m->classpath->makeThrowable
(this, Machine::IndexOutOfBoundsExceptionType);
setRoot(this, Machine::JNIMethodTable, makeVector(this, 0, 0));
m->localThread->set(this);
} else {
@ -2265,6 +2277,21 @@ Thread::init()
}
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
if (parent == 0) {
enter(this, Thread::ActiveState);
m->classpath->boot(this);
setRoot(this, Machine::NullPointerException, m->classpath->makeThrowable
(this, Machine::NullPointerExceptionType));
setRoot(this, Machine::ArrayIndexOutOfBoundsException,
m->classpath->makeThrowable
(this, Machine::IndexOutOfBoundsExceptionType));
enter(this, Thread::IdleState);
}
}
void
@ -2303,10 +2330,10 @@ shutDown(Thread* t)
{
ACQUIRE(t, t->m->shutdownLock);
object hooks = t->m->shutdownHooks;
object hooks = root(t, Machine::ShutdownHooks);
PROTECT(t, hooks);
t->m->shutdownHooks = 0;
setRoot(t, Machine::ShutdownHooks, 0);
object h = hooks;
PROTECT(t, h);
@ -2364,7 +2391,6 @@ enter(Thread* t, Thread::State s)
return;
}
#ifdef USE_ATOMIC_OPERATIONS
# define INCREMENT atomicIncrement
# define ACQUIRE_LOCK ACQUIRE_RAW(t, t->m->stateLock)
@ -2411,12 +2437,24 @@ enter(Thread* t, Thread::State s)
// The java.lang.Thread implementation may or may not notify the
// VM when the daemon field in the Java object changes, so we sync
// up the native field whenever the thread transitions to idle:
if (t->daemon != threadDaemon(t, t->javaThread)) {
// todo: this won't always help if some other thread sets the
// daemon field. The thread trying to shut down the VM really
// just needs to count from scratch every time any thread makes a
// transition.
if (UNLIKELY(((t->flags & Thread::DaemonFlag) != 0)
!= threadDaemon(t, t->javaThread)))
{
ACQUIRE_LOCK;
t->daemon = threadDaemon(t, t->javaThread);
if (threadDaemon(t, t->javaThread)) {
atomicOr(&(t->flags), Thread::DaemonFlag);
} else {
atomicAnd(&(t->flags), ~Thread::DaemonFlag);
}
if (t->daemon) {
if (t->flags & Thread::DaemonFlag) {
++ t->m->daemonCount;
} else {
expect(t, t->m->daemonCount);
@ -2426,7 +2464,7 @@ enter(Thread* t, Thread::State s)
t->m->stateLock->notifyAll(t->systemThread);
}
if (t->state == Thread::ActiveState) {
if (LIKELY(t->state == Thread::ActiveState)) {
// fast path
assert(t, t->m->activeCount > 0);
INCREMENT(&(t->m->activeCount), -1);
@ -2475,7 +2513,7 @@ enter(Thread* t, Thread::State s)
} break;
case Thread::ActiveState:
if (t->state == Thread::IdleState and t->m->exclusive == 0) {
if (LIKELY(t->state == Thread::IdleState and t->m->exclusive == 0)) {
// fast path
INCREMENT(&(t->m->activeCount), 1);
@ -2563,7 +2601,7 @@ object
allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned sizeInBytes, bool objectMask)
{
if (UNLIKELY(t->useBackupHeap)) {
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
expect(t, t->backupHeapIndex + ceiling(sizeInBytes, BytesPerWord)
<= ThreadBackupHeapSizeInWords);
@ -2571,7 +2609,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
t->backupHeapIndex += ceiling(sizeInBytes, BytesPerWord);
cast<object>(o, 0) = 0;
return o;
} else if (UNLIKELY(t->tracing)) {
} else if (UNLIKELY(t->flags & Thread::TracingFlag)) {
expect(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
<= ThreadHeapSizeInWords);
return allocateSmall(t, sizeInBytes);
@ -2721,9 +2759,7 @@ stringUTFLength(Thread* t, object string, unsigned start, unsigned length)
if (length) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
result = length;
} else {
for (unsigned i = 0; i < length; ++i) {
@ -2746,9 +2782,7 @@ stringChars(Thread* t, object string, unsigned start, unsigned length,
{
if (length) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string) + start),
length);
@ -2767,9 +2801,7 @@ stringChars(Thread* t, object string, unsigned start, unsigned length,
{
if (length) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
for (unsigned i = 0; i < length; ++i) {
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + start + i);
}
@ -2791,9 +2823,7 @@ stringUTFChars(Thread* t, object string, unsigned start, unsigned length,
if (length) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string) + start),
length);
@ -2824,11 +2854,14 @@ stringUTFChars(Thread* t, object string, unsigned start, unsigned length,
bool
isAssignableFrom(Thread* t, object a, object b)
{
assert(t, a);
assert(t, b);
if (a == b) return true;
if (classFlags(t, a) & ACC_INTERFACE) {
if (classVmFlags(t, b) & BootstrapFlag) {
resolveSystemClass(t, className(t, b));
resolveSystemClass(t, root(t, Machine::BootLoader), className(t, b));
if (UNLIKELY(t->exception)) {
t->exception = 0;
return false;
@ -2966,15 +2999,6 @@ primitiveSize(Thread* t, unsigned code)
}
}
object
findLoadedSystemClass(Thread* t, object spec)
{
PROTECT(t, spec);
ACQUIRE(t, t->m->classLock);
return hashMapFind(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
}
object
parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
{
@ -3084,18 +3108,27 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
}
object
resolveSystemClass(Thread* t, object spec)
resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
{
PROTECT(t, loader);
PROTECT(t, spec);
ACQUIRE(t, t->m->classLock);
object class_ = hashMapFind
(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
(t, getClassLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
if (class_ == 0) {
if (classLoaderParent(t, loader)) {
class_ = resolveSystemClass
(t, classLoaderParent(t, loader), spec, false);
if (class_) {
return class_;
}
}
if (byteArrayBody(t, spec, 0) == '[') {
class_ = resolveArrayClass(t, t->m->loader, spec);
class_ = resolveArrayClass(t, loader, spec, throw_);
} else {
RUNTIME_ARRAY(char, file, byteArrayLength(t, spec) + 6);
memcpy(RUNTIME_ARRAY_BODY(file),
@ -3105,7 +3138,8 @@ resolveSystemClass(Thread* t, object spec)
".class",
7);
System::Region* region = t->m->finder->find(RUNTIME_ARRAY_BODY(file));
System::Region* region = getFinder(t, loader)->find
(RUNTIME_ARRAY_BODY(file));
if (region) {
if (Verbose) {
@ -3113,8 +3147,7 @@ resolveSystemClass(Thread* t, object spec)
}
// parse class file
class_ = parseClass
(t, t->m->loader, region->start(), region->length());
class_ = parseClass(t, loader, region->start(), region->length());
region->dispose();
if (LIKELY(t->exception == 0)) {
@ -3125,7 +3158,7 @@ resolveSystemClass(Thread* t, object spec)
}
object bootstrapClass = hashMapFind
(t, t->m->bootstrapClassMap, spec, byteArrayHash,
(t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash,
byteArrayEqual);
if (bootstrapClass) {
@ -3141,8 +3174,9 @@ resolveSystemClass(Thread* t, object spec)
if (class_) {
PROTECT(t, class_);
hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash);
} else if (t->exception == 0) {
hashMapInsert
(t, getClassLoaderMap(t, loader), spec, class_, byteArrayHash);
} else if (throw_ and t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = t->m->classpath->makeThrowable
(t, Machine::ClassNotFoundExceptionType, message);
@ -3153,10 +3187,26 @@ resolveSystemClass(Thread* t, object spec)
}
object
resolveClass(Thread* t, object loader, object spec)
findLoadedClass(Thread* t, object loader, object spec)
{
if (loader == t->m->loader) {
return resolveSystemClass(t, spec);
PROTECT(t, spec);
ACQUIRE(t, t->m->classLock);
object map = getClassLoaderMap(t, loader);
if (map) {
return hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual);
} else {
return 0;
}
}
object
resolveClass(Thread* t, object loader, object spec, bool throw_)
{
if (loader == root(t, Machine::BootLoader)
or loader == root(t, Machine::AppLoader))
{
return resolveSystemClass(t, loader, spec, throw_);
} else {
PROTECT(t, loader);
PROTECT(t, spec);
@ -3173,39 +3223,44 @@ resolveClass(Thread* t, object loader, object spec)
if (class_ == 0) {
if (byteArrayBody(t, spec, 0) == '[') {
class_ = resolveArrayClass(t, loader, spec);
class_ = resolveArrayClass(t, loader, spec, throw_);
} else {
if (t->m->loadClassMethod == 0) {
if (root(t, Machine::LoadClassMethod) == 0) {
object m = resolveMethod
(t, t->m->loader, "java/lang/ClassLoader", "loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
(t, root(t, Machine::BootLoader), "java/lang/ClassLoader",
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
if (m) {
t->m->loadClassMethod = m;
setRoot(t, Machine::LoadClassMethod, m);
object classLoaderClass = arrayBody
(t, t->m->types, Machine::ClassLoaderType);
object classLoaderClass = type(t, Machine::ClassLoaderType);
if (classVmFlags(t, classLoaderClass) & BootstrapFlag) {
resolveSystemClass(t, vm::className(t, classLoaderClass));
resolveSystemClass
(t, root(t, Machine::BootLoader),
vm::className(t, classLoaderClass));
}
}
}
if (LIKELY(t->exception == 0)) {
object method = findVirtualMethod
(t, t->m->loadClassMethod, objectClass(t, loader));
(t, root(t, Machine::LoadClassMethod), objectClass(t, loader));
if (LIKELY(t->exception == 0)) {
PROTECT(t, method);
object specString = makeString
(t, "%s", &byteArrayBody(t, spec, 0));
RUNTIME_ARRAY(char, s, byteArrayLength(t, spec));
replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast<char*>
(&byteArrayBody(t, spec, 0)));
replace('/', '.', reinterpret_cast<char*>
(&byteArrayBody(t, stringData(t, specString), 0)));
object specString = makeString(t, "%s", s);
class_ = t->m->processor->invoke(t, method, loader, specString);
if (LIKELY(class_ and t->exception == 0)) {
class_ = jclassVmClass(t, class_);
}
}
}
}
@ -3216,7 +3271,7 @@ resolveClass(Thread* t, object loader, object spec)
hashMapInsert(t, classLoaderMap(t, loader), spec, class_,
byteArrayHash);
} else if (t->exception == 0) {
} else if (throw_ and t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = t->m->classpath->makeThrowable
(t, Machine::ClassNotFoundExceptionType, message);
@ -3399,10 +3454,10 @@ initClass(Thread* t, object c)
}
object
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count)
makeObjectArray(Thread* t, object elementClass, unsigned count)
{
object arrayClass = resolveObjectArrayClass
(t, loader, className(t, elementClass));
(t, classLoader(t, elementClass), className(t, elementClass));
PROTECT(t, arrayClass);
object array = makeArray(t, count);
@ -3524,7 +3579,8 @@ objectMonitor(Thread* t, object o, bool createNew)
{
assert(t, t->state == Thread::ActiveState);
object m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
object m = hashMapFind
(t, root(t, Machine::MonitorMap), o, objectHash, objectEqual);
if (m) {
if (DebugMonitors) {
@ -3538,7 +3594,9 @@ objectMonitor(Thread* t, object o, bool createNew)
{ ENTER(t, Thread::ExclusiveState);
m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
m = hashMapFind
(t, root(t, Machine::MonitorMap), o, objectHash, objectEqual);
if (m) {
if (DebugMonitors) {
fprintf(stderr, "found monitor %p for object %x\n",
@ -3556,7 +3614,7 @@ objectMonitor(Thread* t, object o, bool createNew)
objectHash(t, o));
}
hashMapInsert(t, t->m->monitorMap, o, m, objectHash);
hashMapInsert(t, root(t, Machine::MonitorMap), o, m, objectHash);
addFinalizer(t, o, removeMonitor);
}
@ -3574,11 +3632,13 @@ intern(Thread* t, object s)
ACQUIRE(t, t->m->referenceLock);
object n = hashMapFindNode(t, t->m->stringMap, s, stringHash, stringEqual);
object n = hashMapFindNode
(t, root(t, Machine::StringMap), s, stringHash, stringEqual);
if (n) {
return jreferenceTarget(t, tripleFirst(t, n));
} else {
hashMapInsert(t, t->m->stringMap, s, 0, stringHash);
hashMapInsert(t, root(t, Machine::StringMap), s, 0, stringHash);
addFinalizer(t, s, removeString);
return s;
}
@ -3615,20 +3675,20 @@ collect(Thread* t, Heap::CollectionType type)
if (not stress) t->stress = false;
#endif
object f = m->finalizeQueue;
m->finalizeQueue = 0;
object f = t->m->finalizeQueue;
t->m->finalizeQueue = 0;
for (; f; f = finalizerNext(t, f)) {
void (*function)(Thread*, object);
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
if (function) {
function(t, finalizerTarget(t, f));
} else {
m->objectsToFinalize = makePair
(t, finalizerTarget(t, f), m->objectsToFinalize);
setRoot(t, Machine::ObjectsToFinalize, makePair
(t, finalizerTarget(t, f), root(t, Machine::ObjectsToFinalize)));
}
}
if (m->objectsToFinalize and m->finalizeThread == 0) {
if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) {
m->finalizeThread = m->processor->makeThread
(m, t->m->classpath->makeThread(t, m->rootThread), m->rootThread);
@ -3702,19 +3762,8 @@ walkNext(Thread* t, object o, int previous)
void
visitRoots(Machine* m, Heap::Visitor* v)
{
v->visit(&(m->loader));
v->visit(&(m->classMap));
v->visit(&(m->loadClassMethod));
v->visit(&(m->bootstrapClassMap));
v->visit(&(m->monitorMap));
v->visit(&(m->stringMap));
v->visit(&(m->byteArrayMap));
v->visit(&(m->types));
v->visit(&(m->jniMethodTable));
v->visit(&(m->shutdownHooks));
v->visit(&(m->objectsToFinalize));
v->visit(&(m->nullPointerException));
v->visit(&(m->arrayIndexOutOfBoundsException));
v->visit(&(m->roots));
for (Thread* t = m->rootThread; t; t = t->peer) {
::visitRoots(t, v);
@ -3751,8 +3800,8 @@ printTrace(Thread* t, object exception)
}
object trace = throwableTrace(t, e);
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
object e = arrayBody(t, trace, i);
for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) {
object e = objectArrayBody(t, trace, i);
const int8_t* class_ = &byteArrayBody
(t, className(t, methodClass(t, traceElementMethod(t, e))), 0);
const int8_t* method = &byteArrayBody
@ -3789,11 +3838,11 @@ makeTrace(Thread* t, Processor::StackWalker* walker)
virtual bool visit(Processor::StackWalker* walker) {
if (trace == 0) {
trace = makeArray(t, walker->count());
trace = makeObjectArray(t, walker->count());
}
object e = makeTraceElement(t, walker->method(), walker->ip());
vm_assert(t, index < arrayLength(t, trace));
vm_assert(t, index < objectArrayLength(t, trace));
set(t, trace, ArrayBody + (index * BytesPerWord), e);
++ index;
return true;
@ -3807,7 +3856,7 @@ makeTrace(Thread* t, Processor::StackWalker* walker)
walker->walk(&v);
return v.trace ? v.trace : makeArray(t, 0);
return v.trace ? v.trace : makeObjectArray(t, 0);
}
object
@ -3828,7 +3877,7 @@ makeTrace(Thread* t, Thread* target)
t->m->processor->walkStack(target, &v);
return v.trace ? v.trace : makeArray(t, 0);
return v.trace ? v.trace : makeObjectArray(t, 0);
}
void
@ -3842,7 +3891,9 @@ runFinalizeThread(Thread* t)
while (true) {
{ ACQUIRE(t, t->m->stateLock);
while (t->m->finalizeThread and t->m->objectsToFinalize == 0) {
while (t->m->finalizeThread
and root(t, Machine::ObjectsToFinalize) == 0)
{
ENTER(t, Thread::IdleState);
t->m->stateLock->wait(t->systemThread, 0);
}
@ -3850,8 +3901,8 @@ runFinalizeThread(Thread* t)
if (t->m->finalizeThread == 0) {
return;
} else {
list = t->m->objectsToFinalize;
t->m->objectsToFinalize = 0;
list = root(t, Machine::ObjectsToFinalize);
setRoot(t, Machine::ObjectsToFinalize, 0);
}
}
@ -3926,7 +3977,7 @@ vmPrintTrace(Thread* t)
int line = t->m->processor->lineNumber
(t, walker->method(), walker->ip());
fprintf(stderr, " at %s.%s (%x) ", class_, method, walker->ip());
fprintf(stderr, " at %s.%s ", class_, method);
switch (line) {
case NativeLine:

View File

@ -1120,6 +1120,24 @@ struct JNIEnvVTable {
#endif
};
inline void
atomicOr(uint32_t* p, int v)
{
for (uint32_t old = *p;
not atomicCompareAndSwap32(p, old, old | v);
old = *p)
{ }
}
inline void
atomicAnd(uint32_t* p, int v)
{
for (uint32_t old = *p;
not atomicCompareAndSwap32(p, old, old & v);
old = *p)
{ }
}
inline int
strcmp(const int8_t* a, const int8_t* b)
{
@ -1164,8 +1182,26 @@ class Machine {
ImmortalAllocation
};
Machine(System* system, Heap* heap, Finder* finder, Processor* processor,
Classpath* classpath, const char** properties,
enum Root {
BootLoader,
AppLoader,
ClassMap,
LoadClassMethod,
BootstrapClassMap,
MonitorMap,
StringMap,
ByteArrayMap,
JNIMethodTable,
ShutdownHooks,
ObjectsToFinalize,
NullPointerException,
ArrayIndexOutOfBoundsException
};
static const unsigned RootCount = ArrayIndexOutOfBoundsException + 1;
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
Processor* processor, Classpath* classpath, const char** properties,
unsigned propertyCount);
~Machine() {
@ -1178,7 +1214,8 @@ class Machine {
System* system;
Heap::Client* heapClient;
Heap* heap;
Finder* finder;
Finder* bootFinder;
Finder* appFinder;
Processor* processor;
Classpath* classpath;
Thread* rootThread;
@ -1198,24 +1235,13 @@ class Machine {
System::Monitor* referenceLock;
System::Monitor* shutdownLock;
System::Library* libraries;
object loader;
object classMap;
object loadClassMethod;
object bootstrapClassMap;
object monitorMap;
object stringMap;
object byteArrayMap;
object types;
object jniMethodTable;
object roots;
object finalizers;
object tenuredFinalizers;
object finalizeQueue;
object weakReferences;
object tenuredWeakReferences;
object shutdownHooks;
object objectsToFinalize;
object nullPointerException;
object arrayIndexOutOfBoundsException;
bool unsafe;
bool triedBuiltinOnLoad;
JavaVMVTable javaVMVTable;
@ -1261,6 +1287,13 @@ class Thread {
ExitState
};
static const unsigned UseBackupHeapFlag = 1 << 0;
static const unsigned WaitingFlag = 1 << 1;
static const unsigned TracingFlag = 1 << 2;
static const unsigned DaemonFlag = 1 << 3;
static const unsigned StressFlag = 1 << 4;
static const unsigned ActiveFlag = 1 << 5;
class Protector {
public:
Protector(Thread* t): t(t), next(t->protector) {
@ -1371,11 +1404,7 @@ class Thread {
uintptr_t* heap;
uintptr_t backupHeap[ThreadBackupHeapSizeInWords];
unsigned backupHeapIndex;
bool useBackupHeap;
bool waiting;
bool tracing;
bool daemon;
bool stress;
unsigned flags;
};
class Classpath {
@ -1600,9 +1629,9 @@ ensure(Thread* t, unsigned sizeInBytes)
> ThreadHeapSizeInWords)
{
if (sizeInBytes <= ThreadBackupHeapSizeInBytes) {
expect(t, not t->useBackupHeap);
expect(t, (t->flags & Thread::UseBackupHeapFlag) == 0);
t->useBackupHeap = true;
atomicOr(&(t->flags), Thread::UseBackupHeapFlag);
return true;
} else {
@ -1719,16 +1748,52 @@ instanceOf(Thread* t, object class_, object o);
#include "type-declarations.cpp"
inline object&
root(Thread* t, Machine::Root root)
{
return arrayBody(t, t->m->roots, root);
}
inline void
setRoot(Thread* t, Machine::Root root, object value)
{
set(t, t->m->roots, ArrayBody + (root * BytesPerWord), value);
}
inline object
type(Thread* t, Machine::Type type)
{
return arrayBody(t, t->m->types, type);
}
inline void
setType(Thread* t, Machine::Type type, object value)
{
set(t, t->m->types, ArrayBody + (type * BytesPerWord), value);
}
inline object
getClassLoaderMap(Thread* t, object loader)
{
if (loader == t->m->loader) {
return t->m->classMap;
if (loader == root(t, Machine::BootLoader)) {
return root(t, Machine::ClassMap);
} else {
return classLoaderMap(t, loader);
}
}
inline Finder*
getFinder(Thread* t, object loader)
{
if (loader == root(t, Machine::BootLoader)) {
return t->m->bootFinder;
} else if (loader == root(t, Machine::AppLoader)) {
return t->m->appFinder;
} else {
abort(t);
}
}
inline bool
objectFixed(Thread*, object o)
{
@ -1927,9 +1992,7 @@ stringHash(Thread* t, object s)
{
if (stringHashCode(t, s) == 0 and stringLength(t, s)) {
object data = stringData(t, s);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
stringHashCode(t, s) = hash
(&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s));
} else {
@ -1944,9 +2007,7 @@ inline uint16_t
stringCharAt(Thread* t, object s, int i)
{
object data = stringData(t, s);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
return byteArrayBody(t, data, stringOffset(t, s) + i);
} else {
return charArrayBody(t, data, stringOffset(t, s) + i);
@ -2063,7 +2124,7 @@ fieldSize(Thread* t, object field)
}
object
findLoadedSystemClass(Thread* t, object spec);
findLoadedClass(Thread* t, object loader, object spec);
inline bool
emptyMethod(Thread* t, object method)
@ -2080,7 +2141,7 @@ object
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length);
object
resolveClass(Thread* t, object loader, object name);
resolveClass(Thread* t, object loader, object name, bool throw_ = true);
inline object
resolveClass(Thread* t, object loader, const char* name)
@ -2091,12 +2152,12 @@ resolveClass(Thread* t, object loader, const char* name)
}
object
resolveSystemClass(Thread* t, object name);
resolveSystemClass(Thread* t, object loader, object name, bool throw_ = true);
inline object
resolveSystemClass(Thread* t, const char* name)
resolveSystemClass(Thread* t, object loader, const char* name)
{
return resolveSystemClass(t, makeByteArray(t, "%s", name));
return resolveSystemClass(t, loader, makeByteArray(t, "%s", name));
}
void
@ -2150,13 +2211,12 @@ void
initClass(Thread* t, object c);
object
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count);
makeObjectArray(Thread* t, object elementClass, unsigned count);
inline object
makeObjectArray(Thread* t, unsigned count)
{
return makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JobjectType), count);
return makeObjectArray(t, type(t, Machine::JobjectType), count);
}
object
@ -2398,10 +2458,10 @@ monitorAppendWait(Thread* t, object monitor)
{
assert(t, monitorOwner(t, monitor) == t);
expect(t, not t->waiting);
expect(t, (t->flags & Thread::WaitingFlag) == 0);
expect(t, t->waitNext == 0);
t->waiting = true;
atomicOr(&(t->flags), Thread::WaitingFlag);
if (monitorWaitTail(t, monitor)) {
static_cast<Thread*>(monitorWaitTail(t, monitor))->waitNext = t;
@ -2434,7 +2494,7 @@ monitorRemoveWait(Thread* t, object monitor)
}
t->waitNext = 0;
t->waiting = false;
atomicAnd(&(t->flags), ~Thread::WaitingFlag);
return;
} else {
@ -2489,7 +2549,7 @@ monitorWait(Thread* t, object monitor, int64_t time)
monitorDepth(t, monitor) = depth;
if (t->waiting) {
if (t->flags & Thread::WaitingFlag) {
monitorRemoveWait(t, monitor);
} else {
expect(t, not monitorFindWait(t, monitor));
@ -2509,7 +2569,7 @@ monitorPollWait(Thread* t, object monitor)
if (next) {
monitorWaitHead(t, monitor) = next->waitNext;
next->waiting = false;
atomicAnd(&(next->flags), ~Thread::WaitingFlag);
next->waitNext = 0;
if (next == monitorWaitTail(t, monitor)) {
monitorWaitTail(t, monitor) = 0;
@ -2677,7 +2737,13 @@ setDaemon(Thread* t, object thread, bool daemon)
if ((threadDaemon(t, thread) != 0) != daemon) {
threadDaemon(t, thread) = daemon;
t->daemon = daemon;
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, thread));
if (daemon) {
atomicOr(&(p->flags), Thread::DaemonFlag);
} else {
atomicAnd(&(p->flags), ~Thread::DaemonFlag);
}
if (daemon) {
++ t->m->daemonCount;
@ -2832,7 +2898,7 @@ resolveClassInObject(Thread* t, object loader, object container,
unsigned classOffset)
{
object o = cast<object>(container, classOffset);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
if (objectClass(t, o) == type(t, Machine::ByteArrayType)) {
PROTECT(t, container);
o = resolveClass(t, loader, o);
@ -2847,7 +2913,7 @@ inline object
resolveClassInPool(Thread* t, object loader, object method, unsigned index)
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) {
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
PROTECT(t, method);
o = resolveClass(t, loader, referenceName(t, o));
@ -2872,7 +2938,7 @@ resolve(Thread* t, object loader, object method, unsigned index,
Machine::Type errorType)
{
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
if (objectClass(t, o) == type(t, Machine::ReferenceType))
{
PROTECT(t, method);
@ -2953,21 +3019,49 @@ inline object
primitiveClass(Thread* t, char name)
{
switch (name) {
case 'B': return arrayBody(t, t->m->types, Machine::JbyteType);
case 'C': return arrayBody(t, t->m->types, Machine::JcharType);
case 'D': return arrayBody(t, t->m->types, Machine::JdoubleType);
case 'F': return arrayBody(t, t->m->types, Machine::JfloatType);
case 'I': return arrayBody(t, t->m->types, Machine::JintType);
case 'J': return arrayBody(t, t->m->types, Machine::JlongType);
case 'S': return arrayBody(t, t->m->types, Machine::JshortType);
case 'V': return arrayBody(t, t->m->types, Machine::JvoidType);
case 'Z': return arrayBody(t, t->m->types, Machine::JbooleanType);
case 'B': return type(t, Machine::JbyteType);
case 'C': return type(t, Machine::JcharType);
case 'D': return type(t, Machine::JdoubleType);
case 'F': return type(t, Machine::JfloatType);
case 'I': return type(t, Machine::JintType);
case 'J': return type(t, Machine::JlongType);
case 'S': return type(t, Machine::JshortType);
case 'V': return type(t, Machine::JvoidType);
case 'Z': return type(t, Machine::JbooleanType);
default:
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType);
return 0;
}
}
inline void
registerNative(Thread* t, object method, void* function)
{
PROTECT(t, method);
expect(t, methodFlags(t, method) & ACC_NATIVE);
object native = makeNative(t, function, false);
// ensure other threads only see the methodCode field populated
// once the object it points to has been populated:
storeStoreMemoryBarrier();
set(t, method, MethodCode, native);
}
inline void
unregisterNatives(Thread* t, object c) {
if (classMethodTable(t, c)) {
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object method = arrayBody(t, classMethodTable(t, c), i);
if (methodFlags(t, method) & ACC_NATIVE) {
set(t, method, MethodCode, 0);
}
}
}
}
object
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length);

View File

@ -77,7 +77,8 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
&byteArrayBody(t, spec, 1),
byteArrayLength(t, spec) - 1);
object class_ = resolveSystemClass(t, elementSpec);
object class_ = resolveClass
(t, classLoader(t, objectClass(t, array)), elementSpec);
PROTECT(t, class_);
for (int32_t i = 0; i < counts[index]; ++i) {

View File

@ -128,7 +128,7 @@ class Processor {
DelayedPromise** addresses, object method) = 0;
virtual void
visitRoots(HeapWalker* w) = 0;
visitRoots(Thread* t, HeapWalker* w) = 0;
virtual unsigned*
makeCallTable(Thread* t, HeapWalker* w) = 0;
@ -153,10 +153,6 @@ class Processor {
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
= 0;
virtual void registerNative(Thread* t, object method, void* function) = 0;
virtual void unregisterNatives(Thread* t, object c) = 0;
object
invoke(Thread* t, object method, object this_, ...)
{

View File

@ -1137,7 +1137,7 @@ parseMember(Object* t, Object* p, Object* declarations)
bool isNew;
Object* member = parseMember(t, cdr(cdr(p)), declarations, &isNew);
memberName(member) = string(car(cdr(p)));
return isNew ? member : 0;
return 0;
} else {
return Scalar::make(t, declaration(spec, declarations), spec,
string(car(cdr(p))),

View File

@ -37,11 +37,6 @@
(type fieldAddendum avian/FieldAddendum)
(type nativeMethodData
(void* function)
(uint16_t argumentTableSize)
(array uint8_t parameterTypes))
(type pointer
(void* value))

View File

@ -318,8 +318,7 @@ hashMapFindNode(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
if (array) {
@ -367,9 +366,7 @@ hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
}
if (oldArray) {
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
for (unsigned i = 0; i < arrayLength(t, oldArray); ++i) {
object next;
for (object p = arrayBody(t, oldArray, i); p; p = next) {
@ -407,8 +404,7 @@ hashMapInsert(Thread* t, object map, object key, object value,
uint32_t h = hash(t, key);
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
@ -432,7 +428,8 @@ hashMapInsert(Thread* t, object map, object key, object value,
object r = makeWeakReference(t, 0, 0, 0, 0);
jreferenceTarget(t, r) = key;
jreferenceVmNext(t, r) = t->m->weakReferences;
k = t->m->weakReferences = r;
t->m->weakReferences = r;
k = r;
array = hashMapArray(t, map);
}
@ -465,8 +462,7 @@ hashMapRemove(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
object o = 0;