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

View File

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

View File

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

View File

@ -47,7 +47,7 @@ public abstract class ClassLoader {
} }
return avian.SystemClassLoader.getClass 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 { protected Class findClass(String name) throws ClassNotFoundException {
@ -88,7 +88,7 @@ public abstract class ClassLoader {
} }
protected void resolveClass(Class c) { protected void resolveClass(Class c) {
avian.SystemClassLoader.link(c.vmClass, this); avian.Classes.link(c.vmClass, this);
} }
private ClassLoader getParent() { private ClassLoader getParent() {

View File

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

View File

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

View File

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

View File

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

View File

@ -18,10 +18,11 @@ using namespace vm;
namespace { namespace {
int64_t int64_t
search(Thread* t, object name, object (*op)(Thread*, object), search(Thread* t, object loader, object name,
bool replaceDots) object (*op)(Thread*, object, object), bool replaceDots)
{ {
if (LIKELY(name)) { if (LIKELY(name)) {
PROTECT(t, loader);
PROTECT(t, name); PROTECT(t, name);
object n = makeByteArray(t, stringLength(t, name) + 1); object n = makeByteArray(t, stringLength(t, name) + 1);
@ -32,7 +33,7 @@ search(Thread* t, object name, object (*op)(Thread*, object),
replace('.', '/', s); replace('.', '/', s);
} }
object r = op(t, n); object r = op(t, loader, n);
if (t->exception) { if (t->exception) {
return 0; 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 } // 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 extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findLoadedVMClass Avian_avian_SystemClassLoader_findLoadedVMClass
(Thread* t, object, uintptr_t* arguments) (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 extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_findVMClass Avian_avian_SystemClassLoader_findVMClass
(Thread* t, object, uintptr_t* arguments) (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 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 extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_resourceExists Avian_avian_SystemClassLoader_resourceExists
(Thread* t, object, uintptr_t* arguments) (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)) { if (LIKELY(name)) {
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1); RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n)); 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 { } else {
t->exception = t->m->classpath->makeThrowable t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType); (t, Machine::NullPointerExceptionType);
@ -133,35 +93,11 @@ Avian_avian_SystemClassLoader_resourceExists
} }
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_SystemClassLoader_primitiveClass Avian_avian_SystemClassLoader_getClass
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
{ {
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0])); return reinterpret_cast<int64_t>
} (getJClass(t, reinterpret_cast<object>(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;
}
} }
#ifdef AVIAN_HEAPDUMP #ifdef AVIAN_HEAPDUMP
@ -208,7 +144,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
stringChars(t, path, RUNTIME_ARRAY_BODY(p)); 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) { if (r) {
jint rSize = r->length(); jint rSize = r->length();
r->dispose(); r->dispose();
@ -229,7 +165,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open
stringChars(t, path, RUNTIME_ARRAY_BODY(p)); stringChars(t, path, RUNTIME_ARRAY_BODY(p));
return reinterpret_cast<int64_t> return reinterpret_cast<int64_t>
(t->m->finder->find(RUNTIME_ARRAY_BODY(p))); (t->m->appFinder->find(RUNTIME_ARRAY_BODY(p)));
} else { } else {
t->exception = t->m->classpath->makeThrowable t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType); (t, Machine::NullPointerExceptionType);

View File

@ -49,15 +49,16 @@ class MyClasspath : public Classpath {
const unsigned NormalPriority = 5; const unsigned NormalPriority = 5;
return vm::makeThread return vm::makeThread
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, t->m->loader, 0, 0, (t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0,
group); root(t, Machine::BootLoader), 0, 0, group);
} }
virtual void virtual void
runThread(Thread* t) runThread(Thread* t)
{ {
object method = resolveMethod 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) { if (t->exception == 0) {
t->m->processor->invoke(t, method, 0, t->javaThread); t->m->processor->invoke(t, method, 0, t->javaThread);
@ -75,7 +76,7 @@ class MyClasspath : public Classpath {
trace = makeTrace(t); 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, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace); set(t, result, ThrowableTrace, trace);
@ -84,6 +85,12 @@ class MyClasspath : public Classpath {
return result; return result;
} }
virtual void
boot(Thread*)
{
// ignore
}
virtual void virtual void
dispose() dispose()
{ {
@ -352,7 +359,7 @@ Avian_java_lang_reflect_Array_makeObjectArray
int length = arguments[1]; int length = arguments[1];
return reinterpret_cast<int64_t> return reinterpret_cast<int64_t>
(makeObjectArray(t, classLoader(t, elementType), elementType, length)); (makeObjectArray(t, elementType, length));
} }
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
@ -408,7 +415,8 @@ Avian_java_lang_System_getVMProperty
int64_t r = 0; int64_t r = 0;
if (::strcmp(RUNTIME_ARRAY_BODY(n), "java.lang.classpath") == 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) { } else if (::strcmp(RUNTIME_ARRAY_BODY(n), "avian.version") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, AVIAN_VERSION)); r = reinterpret_cast<int64_t>(makeString(t, AVIAN_VERSION));
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "file.encoding") == 0) { } else if (::strcmp(RUNTIME_ARRAY_BODY(n), "file.encoding") == 0) {
@ -499,7 +507,8 @@ Avian_java_lang_Runtime_addShutdownHook
ACQUIRE(t, t->m->shutdownLock); 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 extern "C" JNIEXPORT int64_t JNICALL
@ -516,15 +525,13 @@ Avian_java_lang_Throwable_resolveTrace
object trace = reinterpret_cast<object>(*arguments); object trace = reinterpret_cast<object>(*arguments);
PROTECT(t, trace); PROTECT(t, trace);
unsigned length = arrayLength(t, trace); unsigned length = objectArrayLength(t, trace);
object elementType = arrayBody object elementType = type(t, Machine::StackTraceElementType);
(t, t->m->types, Machine::StackTraceElementType); object array = makeObjectArray(t, elementType, length);
object array = makeObjectArray
(t, classLoader(t, elementType), elementType, length);
PROTECT(t, array); PROTECT(t, array);
for (unsigned i = 0; i < length; ++i) { 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); set(t, array, ArrayBody + (i * BytesPerWord), ste);
} }
@ -599,3 +606,85 @@ Avian_java_lang_Thread_setDaemon
setDaemon(t, thread, daemon); 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) { if (skipCount == 0) {
object method = walker->method(); object method = walker->method();
if (isAssignableFrom if (isAssignableFrom
(t, arrayBody(t, t->m->types, Machine::ThrowableType), (t, type(t, Machine::ThrowableType), methodClass(t, method))
methodClass(t, method))
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"), and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0)) &byteArrayBody(t, methodName(t, method), 0))
== 0) == 0)
@ -80,7 +79,7 @@ getTrace(Thread* t, unsigned skipCount)
t->m->processor->walkStack(t, &v); 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; return v.trace;
} }

View File

@ -40,6 +40,7 @@
# include <unistd.h> # include <unistd.h>
# include <sys/types.h> # include <sys/types.h>
# include <sys/stat.h> # include <sys/stat.h>
# include <sys/socket.h>
# include <fcntl.h> # include <fcntl.h>
# include <errno.h> # include <errno.h>
@ -77,10 +78,10 @@ CREAT(string_t path, int mode)
namespace local { namespace local {
const unsigned InterfaceVersion = 4; const unsigned InterfaceVersion = 4;
const unsigned PageSize = 4 * 1024;
Machine* globalMachine; Machine* globalMachine;
const char* const char*
primitiveName(Thread* t, object c) primitiveName(Thread* t, object c)
{ {
@ -144,6 +145,8 @@ class MyClasspath : public Classpath {
virtual object virtual object
makeJclass(Thread* t, object class_) makeJclass(Thread* t, object class_)
{ {
PROTECT(t, class_);
object name = makeClassNameString(t, getClassName(t, class_)); object name = makeClassNameString(t, getClassName(t, class_));
return vm::makeJclass return vm::makeJclass
@ -153,9 +156,7 @@ class MyClasspath : public Classpath {
virtual object virtual object
makeString(Thread* t, object array, int32_t offset, int32_t length) makeString(Thread* t, object array, int32_t offset, int32_t length)
{ {
if (objectClass(t, array) if (objectClass(t, array) == type(t, Machine::ByteArrayType)) {
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
PROTECT(t, array); PROTECT(t, array);
object charArray = makeCharArray(t, length); object charArray = makeCharArray(t, length);
@ -183,19 +184,25 @@ class MyClasspath : public Classpath {
} }
return vm::makeThread return vm::makeThread
(t, 0, NormalPriority, 0, 0, false, false, false, 0, group, t->m->loader, (t, 0, NormalPriority, 0, 0, false, false, false, 0, group,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, 0, false); root(t, Machine::BootLoader), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0,
0, false);
} }
virtual void virtual void
runThread(Thread* t) runThread(Thread* t)
{ {
object method = resolveMethod 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)) { if (LIKELY(t->exception == 0)) {
t->m->processor->invoke(t, method, t->javaThread); 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 virtual object
@ -209,7 +216,7 @@ class MyClasspath : public Classpath {
trace = makeTrace(t); 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, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace); set(t, result, ThrowableTrace, trace);
@ -228,7 +235,22 @@ class MyClasspath : public Classpath {
} }
t->m->processor->invoke 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 virtual void
@ -281,16 +303,16 @@ countFields(Thread* t, object c, bool publicOnly)
{ {
object table = classFieldTable(t, c); object table = classFieldTable(t, c);
if (publicOnly) { if (publicOnly) {
return objectArrayLength(t, table);
} else {
unsigned count = 0; unsigned count = 0;
for (unsigned i = 0; i < arrayLength(t, table); ++i) { for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object vmField = arrayBody(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; ++ count;
} }
} }
return count; return count;
} else {
return objectArrayLength(t, table);
} }
} }
@ -430,8 +452,7 @@ resolveParameterJTypes(Thread* t, object loader, object spec,
PROTECT(t, list); PROTECT(t, list);
object array = makeObjectArray object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType), (t, type(t, Machine::JclassType), *parameterCount);
*parameterCount);
PROTECT(t, array); PROTECT(t, array);
for (int i = *parameterCount - 1; i >= 0; --i) { for (int i = *parameterCount - 1; i >= 0; --i) {
@ -447,15 +468,14 @@ object
resolveExceptionJTypes(Thread* t, object loader, object addendum) resolveExceptionJTypes(Thread* t, object loader, object addendum)
{ {
if (addendum == 0) { if (addendum == 0) {
return makeObjectArray return makeObjectArray(t, type(t, Machine::JclassType), 0);
(t, loader, arrayBody(t, t->m->types, Machine::JclassType), 0);
} }
PROTECT(t, loader); PROTECT(t, loader);
PROTECT(t, addendum); PROTECT(t, addendum);
object array = makeObjectArray object array = makeObjectArray
(t, loader, arrayBody(t, t->m->types, Machine::JclassType), (t, type(t, Machine::JclassType),
shortArrayLength(t, methodAddendumExceptionTable(t, addendum))); shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
PROTECT(t, array); PROTECT(t, array);
@ -467,9 +487,7 @@ resolveExceptionJTypes(Thread* t, object loader, object addendum)
object o = singletonObject(t, addendumPool(t, addendum), index); object o = singletonObject(t, addendumPool(t, addendum), index);
if (objectClass(t, o) if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
== arrayBody(t, t->m->types, Machine::ReferenceType))
{
o = resolveClass(t, loader, referenceName(t, o)); o = resolveClass(t, loader, referenceName(t, o));
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
@ -532,6 +550,38 @@ Avian_sun_misc_Unsafe_registerNatives
// ignore // 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 extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_staticFieldOffset Avian_sun_misc_Unsafe_staticFieldOffset
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
@ -564,15 +614,90 @@ Avian_sun_misc_Unsafe_objectFieldOffset
(t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield))); (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 extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getObjectVolatile Avian_sun_misc_Unsafe_getObjectVolatile
(Thread*, object, uintptr_t* arguments) (Thread*, object, uintptr_t* arguments)
{ {
object o = reinterpret_cast<object>(arguments[1]); object o = reinterpret_cast<object>(arguments[1]);
unsigned offset = arguments[2]; int64_t offset; memcpy(&offset, arguments + 2, 8);
object value = cast<object>(o, offset);
uintptr_t value = cast<uintptr_t>(o, offset);
loadMemoryBarrier(); loadMemoryBarrier();
return reinterpret_cast<int64_t>(value); return value;
} }
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
@ -588,6 +713,25 @@ Avian_sun_misc_Unsafe_compareAndSwapInt
(&cast<int32_t>(target, offset), expect, update); (&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 extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_compareAndSwapLong Avian_sun_misc_Unsafe_compareAndSwapLong
(Thread*, object, uintptr_t* arguments) (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 extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_putLong__JJ Avian_sun_misc_Unsafe_putLong__JJ
(Thread*, object, uintptr_t* arguments) (Thread*, object, uintptr_t* arguments)
@ -635,6 +790,16 @@ Avian_sun_misc_Unsafe_putLong__JJ
*reinterpret_cast<int64_t*>(p) = v; *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 extern "C" JNIEXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_getByte__J Avian_sun_misc_Unsafe_getByte__J
(Thread*, object, uintptr_t* arguments) (Thread*, object, uintptr_t* arguments)
@ -644,6 +809,22 @@ Avian_sun_misc_Unsafe_getByte__J
return *reinterpret_cast<int8_t*>(p); 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 extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_ensureClassInitialized Avian_sun_misc_Unsafe_ensureClassInitialized
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
@ -732,7 +913,7 @@ JVM_InitProperties(Thread* t, jobject properties)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = resolveMethod 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;"); "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
if (UNLIKELY(t->exception)) { if (UNLIKELY(t->exception)) {
@ -776,6 +957,9 @@ JVM_InitProperties(Thread* t, jobject properties)
local::setProperty(t, method, *properties, "sun.boot.library.path", local::setProperty(t, method, *properties, "sun.boot.library.path",
getenv("LD_LIBRARY_PATH")); getenv("LD_LIBRARY_PATH"));
local::setProperty(t, method, *properties, "java.protocol.handler.pkgs",
"avian");
#endif #endif
local::setProperty(t, method, *properties, "file.encoding", "ASCII"); local::setProperty(t, method, *properties, "file.encoding", "ASCII");
#ifdef ARCH_x86_32 #ifdef ARCH_x86_32
@ -811,10 +995,16 @@ extern "C" JNIEXPORT void JNICALL
JVM_OnExit(void (*)(void)) { abort(); } JVM_OnExit(void (*)(void)) { abort(); }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
JVM_Exit(jint) { abort(); } JVM_Exit(jint code)
{
exit(code);
}
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
JVM_Halt(jint) { abort(); } JVM_Halt(jint code)
{
exit(code);
}
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
JVM_GC() JVM_GC()
@ -896,7 +1086,7 @@ JVM_GetStackTraceDepth(Thread* t, jobject throwable)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
return arrayLength(t, throwableTrace(t, *throwable)); return objectArrayLength(t, throwableTrace(t, *throwable));
} }
extern "C" JNIEXPORT jobject JNICALL extern "C" JNIEXPORT jobject JNICALL
@ -906,7 +1096,7 @@ JVM_GetStackTraceElement(Thread* t, jobject throwable, jint index)
return makeLocalReference return makeLocalReference
(t, makeStackTraceElement (t, makeStackTraceElement
(t, arrayBody(t, throwableTrace(t, *throwable), index))); (t, objectArrayBody(t, throwableTrace(t, *throwable), index)));
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
@ -947,25 +1137,7 @@ JVM_IsThreadAlive(Thread* t, jobject thread)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread)); Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread));
if (p) { return p and (p->flags & Thread::ActiveFlag) != 0;
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;
}
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
@ -1013,7 +1185,19 @@ extern "C" JNIEXPORT void JNICALL
JVM_Interrupt(Thread*, jobject) { abort(); } JVM_Interrupt(Thread*, jobject) { abort(); }
extern "C" JNIEXPORT jboolean JNICALL 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 extern "C" JNIEXPORT jboolean JNICALL
JVM_HoldsLock(Thread*, jclass, jobject) { abort(); } JVM_HoldsLock(Thread*, jclass, jobject) { abort(); }
@ -1042,13 +1226,12 @@ JVM_GetClassContext(Thread* t)
PROTECT(t, trace); PROTECT(t, trace);
object context = makeObjectArray object context = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType), (t, type(t, Machine::JclassType), objectArrayLength(t, trace));
arrayLength(t, trace));
PROTECT(t, context); PROTECT(t, context);
for (unsigned i = 0; i < arrayLength(t, trace); ++i) { for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) {
object c = getJClass 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); set(t, context, ArrayBody + (i * BytesPerWord), c);
} }
@ -1084,16 +1267,31 @@ JVM_LoadClass0(Thread*, jobject, jclass,
jstring) { abort(); } jstring) { abort(); }
extern "C" JNIEXPORT jint JNICALL 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 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 extern "C" JNIEXPORT jvalue JNICALL
JVM_GetPrimitiveArrayElement(Thread*, jobject, jint, jint) { abort(); } JVM_GetPrimitiveArrayElement(Thread*, jobject, jint, jint) { abort(); }
extern "C" JNIEXPORT void JNICALL 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 extern "C" JNIEXPORT void JNICALL
JVM_SetPrimitiveArrayElement(Thread*, jobject, jint, jvalue, JVM_SetPrimitiveArrayElement(Thread*, jobject, jint, jvalue,
@ -1126,8 +1324,7 @@ JVM_NewArray(Thread* t, jclass elementClass, jint length)
default: abort(t); default: abort(t);
} }
} else { } else {
return makeLocalReference return makeLocalReference(t, makeObjectArray(t, c, length));
(t, makeObjectArray(t, t->m->loader, c, length));
} }
} }
@ -1152,32 +1349,32 @@ JVM_FindPrimitiveClass(Thread* t, const char* name)
case 'b': case 'b':
if (name[1] == 'o') { if (name[1] == 'o') {
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JbooleanType))); (t, getJClass(t, type(t, Machine::JbooleanType)));
} else { } else {
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JbyteType))); (t, getJClass(t, type(t, Machine::JbyteType)));
} }
case 'c': case 'c':
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JcharType))); (t, getJClass(t, type(t, Machine::JcharType)));
case 'd': case 'd':
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JdoubleType))); (t, getJClass(t, type(t, Machine::JdoubleType)));
case 'f': case 'f':
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JfloatType))); (t, getJClass(t, type(t, Machine::JfloatType)));
case 'i': case 'i':
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JintType))); (t, getJClass(t, type(t, Machine::JintType)));
case 'l': case 'l':
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JlongType))); (t, getJClass(t, type(t, Machine::JlongType)));
case 's': case 's':
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JshortType))); (t, getJClass(t, type(t, Machine::JshortType)));
case 'v': case 'v':
return makeLocalReference return makeLocalReference
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JvoidType))); (t, getJClass(t, type(t, Machine::JvoidType)));
default: default:
t->exception = t->m->classpath->makeThrowable t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType); (t, Machine::IllegalArgumentExceptionType);
@ -1194,7 +1391,8 @@ JVM_FindClassFromClassLoader(Thread* t, const char* name, jboolean init,
{ {
ENTER(t, Thread::ActiveState); 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 (t->exception) {
if (throwError) { if (throwError) {
t->exception = t->m->classpath->makeThrowable t->exception = t->m->classpath->makeThrowable
@ -1224,25 +1422,13 @@ JVM_FindLoadedClass(Thread* t, jobject loader, jstring name)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
ACQUIRE(t, t->m->classLock);
object spec = makeByteArray(t, stringLength(t, *name) + 1); object spec = makeByteArray(t, stringLength(t, *name) + 1);
{ char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0)); { char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0));
stringChars(t, *name, s); stringChars(t, *name, s);
replace('.', '/', s); replace('.', '/', s);
} }
object c; object c = findLoadedClass(t, *loader, spec);
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;
}
}
return c ? makeLocalReference(t, getJClass(t, c)) : 0; 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; (classFlags(t, jclassVmClass(t, *c)) & ACC_INTERFACE) == 0 ? 2 : 1;
object array = makeObjectArray object array = makeObjectArray
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType), (t, type(t, Machine::JclassType), arrayLength(t, table) / stride);
arrayLength(t, table) / stride);
PROTECT(t, array); PROTECT(t, array);
for (unsigned i = 0; i < objectArrayLength(t, array); ++i) { for (unsigned i = 0; i < objectArrayLength(t, array); ++i) {
@ -1287,9 +1472,7 @@ JVM_GetClassInterfaces(Thread* t, jclass c)
return makeLocalReference(t, array); return makeLocalReference(t, array);
} else { } else {
return makeLocalReference return makeLocalReference
(t, makeObjectArray (t, makeObjectArray(t, type(t, Machine::JclassType), 0));
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
0));
} }
} }
@ -1299,7 +1482,8 @@ JVM_GetClassLoader(Thread* t, jclass c)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object loader = classLoader(t, jclassVmClass(t, *c)); 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 extern "C" JNIEXPORT jboolean JNICALL
@ -1385,8 +1569,10 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly)
object table = classMethodTable(t, jclassVmClass(t, *c)); object table = classMethodTable(t, jclassVmClass(t, *c));
if (table) { if (table) {
PROTECT(t, table);
object array = makeObjectArray 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)); local::countMethods(t, jclassVmClass(t, *c), publicOnly));
PROTECT(t, array); PROTECT(t, array);
@ -1461,9 +1647,7 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly)
return makeLocalReference(t, array); return makeLocalReference(t, array);
} else { } else {
return makeLocalReference return makeLocalReference
(t, makeObjectArray (t, makeObjectArray(t, type(t, Machine::JmethodType), 0));
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JmethodType),
0));
} }
} }
@ -1474,8 +1658,10 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
object table = classFieldTable(t, jclassVmClass(t, *c)); object table = classFieldTable(t, jclassVmClass(t, *c));
if (table) { if (table) {
PROTECT(t, table);
object array = makeObjectArray 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)); local::countFields(t, jclassVmClass(t, *c), publicOnly));
PROTECT(t, array); PROTECT(t, array);
@ -1501,6 +1687,8 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
return 0; return 0;
} }
PROTECT(t, type);
type = getJClass(t, type); type = getJClass(t, type);
object signature = t->m->classpath->makeString 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); set(t, array, ArrayBody + ((ai++) * BytesPerWord), field);
} }
} }
assert(t, ai == objectArrayLength(t, array));
return makeLocalReference(t, array); return makeLocalReference(t, array);
} else { } else {
return makeLocalReference return makeLocalReference
(t, makeObjectArray (t, makeObjectArray(t, type(t, Machine::JfieldType), 0));
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JfieldType), 0));
} }
} }
@ -1540,8 +1728,10 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly)
object table = classMethodTable(t, jclassVmClass(t, *c)); object table = classMethodTable(t, jclassVmClass(t, *c));
if (table) { if (table) {
PROTECT(t, table);
object array = makeObjectArray 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)); local::countConstructors(t, jclassVmClass(t, *c), publicOnly));
PROTECT(t, array); PROTECT(t, array);
@ -1598,9 +1788,7 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly)
return makeLocalReference(t, array); return makeLocalReference(t, array);
} else { } else {
return makeLocalReference return makeLocalReference
(t, makeObjectArray (t, makeObjectArray(t, type(t, Machine::JconstructorType), 0));
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JconstructorType),
0));
} }
} }
@ -1739,8 +1927,11 @@ JVM_DoPrivileged
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
// todo: cache these class and method lookups in the t->m->classpath
// object:
object privilegedAction = resolveClass object privilegedAction = resolveClass
(t, t->m->loader, "java/security/PrivilegedAction"); (t, root(t, Machine::BootLoader), "java/security/PrivilegedAction");
if (UNLIKELY(t->exception)) { if (UNLIKELY(t->exception)) {
return 0; return 0;
@ -1752,7 +1943,8 @@ JVM_DoPrivileged
(t, privilegedAction, "run", "()Ljava/lang/Object;"); (t, privilegedAction, "run", "()Ljava/lang/Object;");
} else { } else {
object privilegedExceptionAction = resolveClass object privilegedExceptionAction = resolveClass
(t, t->m->loader, "java/security/PrivilegedExceptionAction"); (t, root(t, Machine::BootLoader),
"java/security/PrivilegedExceptionAction");
if (UNLIKELY(t->exception)) { if (UNLIKELY(t->exception)) {
return 0; return 0;
@ -1769,10 +1961,8 @@ JVM_DoPrivileged
return makeLocalReference(t, result); return makeLocalReference(t, result);
} else { } else {
if (wrapException and not if (wrapException and not
(instanceOf (instanceOf(t, type(t, Machine::ErrorType), t->exception)
(t, arrayBody(t, t->m->types, Machine::ErrorType), t->exception) or instanceOf(t, type(t, Machine::RuntimeExceptionType),
or instanceOf
(t, arrayBody(t, t->m->types, Machine::RuntimeExceptionType),
t->exception))) t->exception)))
{ {
object cause = t->exception; object cause = t->exception;
@ -1781,7 +1971,8 @@ JVM_DoPrivileged
t->exception = 0; t->exception = 0;
object paeClass = resolveClass object paeClass = resolveClass
(t, t->m->loader, "java/security/PrivilegedActionException"); (t, root(t, Machine::BootLoader),
"java/security/PrivilegedActionException");
if (LIKELY(t->exception == 0)) { if (LIKELY(t->exception == 0)) {
PROTECT(t, paeClass); PROTECT(t, paeClass);
@ -2003,37 +2194,83 @@ extern "C" JNIEXPORT jint JNICALL
JVM_Sync(jint) { abort(); } JVM_Sync(jint) { abort(); }
extern "C" JNIEXPORT jint JNICALL 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 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 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 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 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 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 extern "C" JNIEXPORT jint JNICALL
JVM_Timeout(int, long) { abort(); } JVM_Timeout(int, long) { abort(); }
extern "C" JNIEXPORT jint JNICALL 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 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 extern "C" JNIEXPORT jint JNICALL
JVM_Bind(jint, struct sockaddr*, jint) { abort(); } JVM_Bind(jint, struct sockaddr*, jint) { abort(); }
extern "C" JNIEXPORT jint JNICALL 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 extern "C" JNIEXPORT jint JNICALL
JVM_RecvFrom(jint, char*, int, JVM_RecvFrom(jint, char*, int,
@ -2047,7 +2284,13 @@ extern "C" JNIEXPORT jint JNICALL
JVM_SocketAvailable(jint, jint*) { abort(); } JVM_SocketAvailable(jint, jint*) { abort(); }
extern "C" JNIEXPORT jint JNICALL 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 extern "C" JNIEXPORT jint JNICALL
JVM_GetSockOpt(jint, int, int, char*, int*) { abort(); } JVM_GetSockOpt(jint, int, int, char*, int*) { abort(); }

View File

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

View File

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

View File

@ -10,11 +10,11 @@
#ifdef __x86_64__ #ifdef __x86_64__
#define THREAD_CONTINUATION 2232 #define THREAD_CONTINUATION 2224
#define THREAD_EXCEPTION 80 #define THREAD_EXCEPTION 80
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2240 #define THREAD_EXCEPTION_STACK_ADJUSTMENT 2232
#define THREAD_EXCEPTION_OFFSET 2248 #define THREAD_EXCEPTION_OFFSET 2240
#define THREAD_EXCEPTION_HANDLER 2256 #define THREAD_EXCEPTION_HANDLER 2248
#define CONTINUATION_NEXT 8 #define CONTINUATION_NEXT 8
#define CONTINUATION_ADDRESS 32 #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::write1(out, local::Size);
local::write4(out, local::objectSize(t, p)); 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); object name = className(t, p);
if (name) { if (name) {
local::write1(out, local::ClassName); local::write1(out, local::ClassName);

View File

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

View File

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

View File

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

View File

@ -1120,6 +1120,24 @@ struct JNIEnvVTable {
#endif #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 inline int
strcmp(const int8_t* a, const int8_t* b) strcmp(const int8_t* a, const int8_t* b)
{ {
@ -1164,8 +1182,26 @@ class Machine {
ImmortalAllocation ImmortalAllocation
}; };
Machine(System* system, Heap* heap, Finder* finder, Processor* processor, enum Root {
Classpath* classpath, const char** properties, 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); unsigned propertyCount);
~Machine() { ~Machine() {
@ -1178,7 +1214,8 @@ class Machine {
System* system; System* system;
Heap::Client* heapClient; Heap::Client* heapClient;
Heap* heap; Heap* heap;
Finder* finder; Finder* bootFinder;
Finder* appFinder;
Processor* processor; Processor* processor;
Classpath* classpath; Classpath* classpath;
Thread* rootThread; Thread* rootThread;
@ -1198,24 +1235,13 @@ class Machine {
System::Monitor* referenceLock; System::Monitor* referenceLock;
System::Monitor* shutdownLock; System::Monitor* shutdownLock;
System::Library* libraries; System::Library* libraries;
object loader;
object classMap;
object loadClassMethod;
object bootstrapClassMap;
object monitorMap;
object stringMap;
object byteArrayMap;
object types; object types;
object jniMethodTable; object roots;
object finalizers; object finalizers;
object tenuredFinalizers; object tenuredFinalizers;
object finalizeQueue; object finalizeQueue;
object weakReferences; object weakReferences;
object tenuredWeakReferences; object tenuredWeakReferences;
object shutdownHooks;
object objectsToFinalize;
object nullPointerException;
object arrayIndexOutOfBoundsException;
bool unsafe; bool unsafe;
bool triedBuiltinOnLoad; bool triedBuiltinOnLoad;
JavaVMVTable javaVMVTable; JavaVMVTable javaVMVTable;
@ -1261,6 +1287,13 @@ class Thread {
ExitState 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 { class Protector {
public: public:
Protector(Thread* t): t(t), next(t->protector) { Protector(Thread* t): t(t), next(t->protector) {
@ -1371,11 +1404,7 @@ class Thread {
uintptr_t* heap; uintptr_t* heap;
uintptr_t backupHeap[ThreadBackupHeapSizeInWords]; uintptr_t backupHeap[ThreadBackupHeapSizeInWords];
unsigned backupHeapIndex; unsigned backupHeapIndex;
bool useBackupHeap; unsigned flags;
bool waiting;
bool tracing;
bool daemon;
bool stress;
}; };
class Classpath { class Classpath {
@ -1600,9 +1629,9 @@ ensure(Thread* t, unsigned sizeInBytes)
> ThreadHeapSizeInWords) > ThreadHeapSizeInWords)
{ {
if (sizeInBytes <= ThreadBackupHeapSizeInBytes) { 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; return true;
} else { } else {
@ -1719,16 +1748,52 @@ instanceOf(Thread* t, object class_, object o);
#include "type-declarations.cpp" #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 inline object
getClassLoaderMap(Thread* t, object loader) getClassLoaderMap(Thread* t, object loader)
{ {
if (loader == t->m->loader) { if (loader == root(t, Machine::BootLoader)) {
return t->m->classMap; return root(t, Machine::ClassMap);
} else { } else {
return classLoaderMap(t, loader); 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 inline bool
objectFixed(Thread*, object o) objectFixed(Thread*, object o)
{ {
@ -1927,9 +1992,7 @@ stringHash(Thread* t, object s)
{ {
if (stringHashCode(t, s) == 0 and stringLength(t, s)) { if (stringHashCode(t, s) == 0 and stringLength(t, s)) {
object data = stringData(t, s); object data = stringData(t, s);
if (objectClass(t, data) if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
stringHashCode(t, s) = hash stringHashCode(t, s) = hash
(&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s)); (&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s));
} else { } else {
@ -1944,9 +2007,7 @@ inline uint16_t
stringCharAt(Thread* t, object s, int i) stringCharAt(Thread* t, object s, int i)
{ {
object data = stringData(t, s); object data = stringData(t, s);
if (objectClass(t, data) if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
return byteArrayBody(t, data, stringOffset(t, s) + i); return byteArrayBody(t, data, stringOffset(t, s) + i);
} else { } else {
return charArrayBody(t, data, stringOffset(t, s) + i); return charArrayBody(t, data, stringOffset(t, s) + i);
@ -2063,7 +2124,7 @@ fieldSize(Thread* t, object field)
} }
object object
findLoadedSystemClass(Thread* t, object spec); findLoadedClass(Thread* t, object loader, object spec);
inline bool inline bool
emptyMethod(Thread* t, object method) emptyMethod(Thread* t, object method)
@ -2080,7 +2141,7 @@ object
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length); parseClass(Thread* t, object loader, const uint8_t* data, unsigned length);
object object
resolveClass(Thread* t, object loader, object name); resolveClass(Thread* t, object loader, object name, bool throw_ = true);
inline object inline object
resolveClass(Thread* t, object loader, const char* name) resolveClass(Thread* t, object loader, const char* name)
@ -2091,12 +2152,12 @@ resolveClass(Thread* t, object loader, const char* name)
} }
object object
resolveSystemClass(Thread* t, object name); resolveSystemClass(Thread* t, object loader, object name, bool throw_ = true);
inline object 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 void
@ -2150,13 +2211,12 @@ void
initClass(Thread* t, object c); initClass(Thread* t, object c);
object object
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count); makeObjectArray(Thread* t, object elementClass, unsigned count);
inline object inline object
makeObjectArray(Thread* t, unsigned count) makeObjectArray(Thread* t, unsigned count)
{ {
return makeObjectArray return makeObjectArray(t, type(t, Machine::JobjectType), count);
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JobjectType), count);
} }
object object
@ -2398,10 +2458,10 @@ monitorAppendWait(Thread* t, object monitor)
{ {
assert(t, monitorOwner(t, monitor) == t); assert(t, monitorOwner(t, monitor) == t);
expect(t, not t->waiting); expect(t, (t->flags & Thread::WaitingFlag) == 0);
expect(t, t->waitNext == 0); expect(t, t->waitNext == 0);
t->waiting = true; atomicOr(&(t->flags), Thread::WaitingFlag);
if (monitorWaitTail(t, monitor)) { if (monitorWaitTail(t, monitor)) {
static_cast<Thread*>(monitorWaitTail(t, monitor))->waitNext = t; static_cast<Thread*>(monitorWaitTail(t, monitor))->waitNext = t;
@ -2434,7 +2494,7 @@ monitorRemoveWait(Thread* t, object monitor)
} }
t->waitNext = 0; t->waitNext = 0;
t->waiting = false; atomicAnd(&(t->flags), ~Thread::WaitingFlag);
return; return;
} else { } else {
@ -2489,7 +2549,7 @@ monitorWait(Thread* t, object monitor, int64_t time)
monitorDepth(t, monitor) = depth; monitorDepth(t, monitor) = depth;
if (t->waiting) { if (t->flags & Thread::WaitingFlag) {
monitorRemoveWait(t, monitor); monitorRemoveWait(t, monitor);
} else { } else {
expect(t, not monitorFindWait(t, monitor)); expect(t, not monitorFindWait(t, monitor));
@ -2509,7 +2569,7 @@ monitorPollWait(Thread* t, object monitor)
if (next) { if (next) {
monitorWaitHead(t, monitor) = next->waitNext; monitorWaitHead(t, monitor) = next->waitNext;
next->waiting = false; atomicAnd(&(next->flags), ~Thread::WaitingFlag);
next->waitNext = 0; next->waitNext = 0;
if (next == monitorWaitTail(t, monitor)) { if (next == monitorWaitTail(t, monitor)) {
monitorWaitTail(t, monitor) = 0; monitorWaitTail(t, monitor) = 0;
@ -2677,7 +2737,13 @@ setDaemon(Thread* t, object thread, bool daemon)
if ((threadDaemon(t, thread) != 0) != daemon) { if ((threadDaemon(t, thread) != 0) != daemon) {
threadDaemon(t, thread) = 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) { if (daemon) {
++ t->m->daemonCount; ++ t->m->daemonCount;
@ -2832,7 +2898,7 @@ resolveClassInObject(Thread* t, object loader, object container,
unsigned classOffset) unsigned classOffset)
{ {
object o = cast<object>(container, 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); PROTECT(t, container);
o = resolveClass(t, loader, o); o = resolveClass(t, loader, o);
@ -2847,7 +2913,7 @@ inline object
resolveClassInPool(Thread* t, object loader, object method, unsigned index) resolveClassInPool(Thread* t, object loader, object method, unsigned index)
{ {
object o = singletonObject(t, codePool(t, methodCode(t, method)), 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); PROTECT(t, method);
o = resolveClass(t, loader, referenceName(t, o)); o = resolveClass(t, loader, referenceName(t, o));
@ -2872,7 +2938,7 @@ resolve(Thread* t, object loader, object method, unsigned index,
Machine::Type errorType) Machine::Type errorType)
{ {
object o = singletonObject(t, codePool(t, methodCode(t, method)), 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); PROTECT(t, method);
@ -2953,15 +3019,15 @@ inline object
primitiveClass(Thread* t, char name) primitiveClass(Thread* t, char name)
{ {
switch (name) { switch (name) {
case 'B': return arrayBody(t, t->m->types, Machine::JbyteType); case 'B': return type(t, Machine::JbyteType);
case 'C': return arrayBody(t, t->m->types, Machine::JcharType); case 'C': return type(t, Machine::JcharType);
case 'D': return arrayBody(t, t->m->types, Machine::JdoubleType); case 'D': return type(t, Machine::JdoubleType);
case 'F': return arrayBody(t, t->m->types, Machine::JfloatType); case 'F': return type(t, Machine::JfloatType);
case 'I': return arrayBody(t, t->m->types, Machine::JintType); case 'I': return type(t, Machine::JintType);
case 'J': return arrayBody(t, t->m->types, Machine::JlongType); case 'J': return type(t, Machine::JlongType);
case 'S': return arrayBody(t, t->m->types, Machine::JshortType); case 'S': return type(t, Machine::JshortType);
case 'V': return arrayBody(t, t->m->types, Machine::JvoidType); case 'V': return type(t, Machine::JvoidType);
case 'Z': return arrayBody(t, t->m->types, Machine::JbooleanType); case 'Z': return type(t, Machine::JbooleanType);
default: default:
t->exception = t->m->classpath->makeThrowable t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType); (t, Machine::IllegalArgumentExceptionType);
@ -2969,6 +3035,34 @@ primitiveClass(Thread* t, char name)
} }
} }
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 object
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length); 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), &byteArrayBody(t, spec, 1),
byteArrayLength(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_); PROTECT(t, class_);
for (int32_t i = 0; i < counts[index]; ++i) { for (int32_t i = 0; i < counts[index]; ++i) {

View File

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

View File

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

View File

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

View File

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