mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
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:
parent
561ee6dff9
commit
d819a75f36
@ -104,14 +104,15 @@ public class Classes {
|
||||
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||
|
||||
return Enum.valueOf
|
||||
(getClass(loadVMClass(loader, typeName, 1, typeName.length - 3)),
|
||||
(SystemClassLoader.getClass
|
||||
(loadVMClass(loader, typeName, 1, typeName.length - 3)),
|
||||
new String(name, 0, name.length - 1, false));
|
||||
}
|
||||
|
||||
case 'c':{
|
||||
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||
|
||||
return getClass(loadVMClass(loader, name, 1, name.length - 3));
|
||||
return SystemClassLoader.getClass(loadVMClass(loader, name, 1, name.length - 3));
|
||||
}
|
||||
|
||||
case '@':
|
||||
@ -136,7 +137,7 @@ public class Classes {
|
||||
{
|
||||
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||
Object[] annotation = new Object[(read2(in) + 1) * 2];
|
||||
annotation[1] = getClass
|
||||
annotation[1] = SystemClassLoader.getClass
|
||||
(loadVMClass(loader, typeName, 1, typeName.length - 3));
|
||||
|
||||
for (int i = 2; i < annotation.length; i += 2) {
|
||||
|
@ -14,7 +14,7 @@ import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
public class SystemClassLoader extends ClassLoader {
|
||||
private static native VMClass findVMClass(String name)
|
||||
private native VMClass findVMClass(String name)
|
||||
throws ClassNotFoundException;
|
||||
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
@ -23,14 +23,14 @@ public class SystemClassLoader extends ClassLoader {
|
||||
|
||||
public static native Class getClass(VMClass vmClass);
|
||||
|
||||
private static native VMClass findLoadedVMClass(String name);
|
||||
private native VMClass findLoadedVMClass(String name);
|
||||
|
||||
protected Class reallyFindLoadedClass(String name){
|
||||
VMClass c = findLoadedVMClass(name);
|
||||
return c == null ? null : getClass(c);
|
||||
}
|
||||
|
||||
private static native boolean resourceExists(String name);
|
||||
private native boolean resourceExists(String name);
|
||||
|
||||
protected URL findResource(String name) {
|
||||
if (resourceExists(name)) {
|
||||
|
@ -14,6 +14,7 @@ import avian.VMClass;
|
||||
import avian.ClassAddendum;
|
||||
import avian.AnnotationInvocationHandler;
|
||||
import avian.SystemClassLoader;
|
||||
import avian.Classes;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
@ -69,23 +70,23 @@ public final class Class <T>
|
||||
public static String getName(VMClass c) {
|
||||
if (c.name == null) {
|
||||
if ((c.vmFlags & PrimitiveFlag) != 0) {
|
||||
if (c == SystemClassLoader.primitiveClass('V')) {
|
||||
if (c == Classes.primitiveClass('V')) {
|
||||
c.name = "void\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('Z')) {
|
||||
} else if (c == Classes.primitiveClass('Z')) {
|
||||
c.name = "boolean\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('B')) {
|
||||
} else if (c == Classes.primitiveClass('B')) {
|
||||
c.name = "byte\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('C')) {
|
||||
} else if (c == Classes.primitiveClass('C')) {
|
||||
c.name = "char\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('S')) {
|
||||
} else if (c == Classes.primitiveClass('S')) {
|
||||
c.name = "short\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('I')) {
|
||||
} else if (c == Classes.primitiveClass('I')) {
|
||||
c.name = "int\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('F')) {
|
||||
} else if (c == Classes.primitiveClass('F')) {
|
||||
c.name = "float\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('J')) {
|
||||
} else if (c == Classes.primitiveClass('J')) {
|
||||
c.name = "long\0".getBytes();
|
||||
} else if (c == SystemClassLoader.primitiveClass('D')) {
|
||||
} else if (c == Classes.primitiveClass('D')) {
|
||||
c.name = "double\0".getBytes();
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
@ -150,9 +151,9 @@ public final class Class <T>
|
||||
loader = Class.class.vmClass.loader;
|
||||
}
|
||||
Class c = loader.loadClass(name);
|
||||
SystemClassLoader.link(c.vmClass, loader);
|
||||
Classes.link(c.vmClass, loader);
|
||||
if (initialize) {
|
||||
SystemClassLoader.initialize(c.vmClass);
|
||||
Classes.initialize(c.vmClass);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@ -170,7 +171,7 @@ public final class Class <T>
|
||||
} else {
|
||||
if (name.length() == 1) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass(name.charAt(0)));
|
||||
(Classes.primitiveClass(name.charAt(0)));
|
||||
} else {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
@ -184,29 +185,21 @@ public final class Class <T>
|
||||
if (isArray()) {
|
||||
String n = getName();
|
||||
if ("[Z".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('Z'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('Z'));
|
||||
} else if ("[B".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('B'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('B'));
|
||||
} else if ("[S".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('S'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('S'));
|
||||
} else if ("[C".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('C'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('C'));
|
||||
} else if ("[I".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('I'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('I'));
|
||||
} else if ("[F".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('F'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('F'));
|
||||
} else if ("[J".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('J'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('J'));
|
||||
} else if ("[D".equals(n)) {
|
||||
return SystemClassLoader.getClass
|
||||
(SystemClassLoader.primitiveClass('D'));
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('D'));
|
||||
}
|
||||
|
||||
if (vmClass.staticTable == null) throw new AssertionError();
|
||||
@ -217,12 +210,12 @@ public final class Class <T>
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(Class c) {
|
||||
return SystemClassLoader.isAssignableFrom(vmClass, c.vmClass);
|
||||
return Classes.isAssignableFrom(vmClass, c.vmClass);
|
||||
}
|
||||
|
||||
private static Field findField(VMClass vmClass, String name) {
|
||||
if (vmClass.fieldTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||
if (Field.getName(vmClass.fieldTable[i]).equals(name)) {
|
||||
@ -269,7 +262,7 @@ public final class Class <T>
|
||||
Class[] parameterTypes)
|
||||
{
|
||||
if (vmClass.methodTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
if (parameterTypes == null) {
|
||||
parameterTypes = new Class[0];
|
||||
@ -365,7 +358,7 @@ public final class Class <T>
|
||||
public Constructor[] getDeclaredConstructors() {
|
||||
Constructor[] array = new Constructor[countConstructors(false)];
|
||||
if (vmClass.methodTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < vmClass.methodTable.length; ++i) {
|
||||
@ -381,7 +374,7 @@ public final class Class <T>
|
||||
public Constructor[] getConstructors() {
|
||||
Constructor[] array = new Constructor[countConstructors(true)];
|
||||
if (vmClass.methodTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < vmClass.methodTable.length; ++i) {
|
||||
@ -423,7 +416,7 @@ public final class Class <T>
|
||||
public Field[] getFields() {
|
||||
Field[] array = new Field[countPublicFields()];
|
||||
if (vmClass.fieldTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
int ai = 0;
|
||||
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||
@ -454,7 +447,7 @@ public final class Class <T>
|
||||
public Method[] getDeclaredMethods() {
|
||||
Method[] array = new Method[countMethods(false)];
|
||||
if (vmClass.methodTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
int ai = 0;
|
||||
for (int i = 0; i < vmClass.methodTable.length; ++i) {
|
||||
@ -470,7 +463,7 @@ public final class Class <T>
|
||||
public Method[] getMethods() {
|
||||
Method[] array = new Method[countMethods(true)];
|
||||
if (vmClass.methodTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < vmClass.methodTable.length; ++i) {
|
||||
@ -487,7 +480,7 @@ public final class Class <T>
|
||||
|
||||
public Class[] getInterfaces() {
|
||||
if (vmClass.interfaceTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
int stride = (isInterface() ? 1 : 2);
|
||||
Class[] array = new Class[vmClass.interfaceTable.length / stride];
|
||||
@ -534,8 +527,8 @@ public final class Class <T>
|
||||
}
|
||||
|
||||
public static boolean isInstance(VMClass c, Object o) {
|
||||
return o != null && SystemClassLoader.isAssignableFrom
|
||||
(c, SystemClassLoader.getVMClass(o));
|
||||
return o != null && Classes.isAssignableFrom
|
||||
(c, Classes.getVMClass(o));
|
||||
}
|
||||
|
||||
public boolean isInstance(Object o) {
|
||||
@ -620,7 +613,7 @@ public final class Class <T>
|
||||
public <T extends Annotation> T getAnnotation(Class<T> class_) {
|
||||
for (VMClass c = vmClass; c != null; c = c.super_) {
|
||||
if (c.addendum != null && c.addendum.annotationTable != null) {
|
||||
SystemClassLoader.link(c, c.loader);
|
||||
Classes.link(c, c.loader);
|
||||
|
||||
Object[] table = (Object[]) c.addendum.annotationTable;
|
||||
for (int i = 0; i < table.length; ++i) {
|
||||
@ -636,7 +629,7 @@ public final class Class <T>
|
||||
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
if (vmClass.addendum.annotationTable != null) {
|
||||
SystemClassLoader.link(vmClass);
|
||||
Classes.link(vmClass);
|
||||
|
||||
Object[] table = (Object[]) vmClass.addendum.annotationTable;
|
||||
Annotation[] array = new Annotation[table.length];
|
||||
|
@ -47,7 +47,7 @@ public abstract class ClassLoader {
|
||||
}
|
||||
|
||||
return avian.SystemClassLoader.getClass
|
||||
(avian.SystemClassLoader.defineVMClass(this, b, offset, length));
|
||||
(avian.Classes.defineVMClass(this, b, offset, length));
|
||||
}
|
||||
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
@ -88,7 +88,7 @@ public abstract class ClassLoader {
|
||||
}
|
||||
|
||||
protected void resolveClass(Class c) {
|
||||
avian.SystemClassLoader.link(c.vmClass, this);
|
||||
avian.Classes.link(c.vmClass, this);
|
||||
}
|
||||
|
||||
private ClassLoader getParent() {
|
||||
|
@ -12,7 +12,7 @@ package java.lang;
|
||||
|
||||
public class OutOfMemoryError extends VirtualMachineError {
|
||||
public OutOfMemoryError(String message) {
|
||||
super(message, null);
|
||||
super(message);
|
||||
}
|
||||
|
||||
public OutOfMemoryError() {
|
||||
|
@ -13,6 +13,7 @@ package java.lang.reflect;
|
||||
import avian.VMField;
|
||||
import avian.AnnotationInvocationHandler;
|
||||
import avian.SystemClassLoader;
|
||||
import avian.Classes;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
@ -204,7 +205,7 @@ public class Field<T> extends AccessibleObject {
|
||||
} else {
|
||||
throw new IllegalArgumentException
|
||||
("needed " + getType() + ", got "
|
||||
+ Class.getName(SystemClassLoader.vmClass(target)) +
|
||||
+ Class.getName(Classes.vmClass(target)) +
|
||||
" when setting " + Class.getName(vmField.class_) + "." + getName());
|
||||
}
|
||||
break;
|
||||
|
@ -515,8 +515,7 @@ public class Proxy {
|
||||
|
||||
byte[] classData = out.toByteArray();
|
||||
return avian.SystemClassLoader.getClass
|
||||
(avian.SystemClassLoader.defineVMClass
|
||||
(loader, classData, 0, classData.length));
|
||||
(avian.Classes.defineVMClass(loader, classData, 0, classData.length));
|
||||
}
|
||||
|
||||
public static Object newProxyInstance(ClassLoader loader,
|
||||
|
13
classpath/sun/reflect/ConstantPool.java
Normal file
13
classpath/sun/reflect/ConstantPool.java
Normal 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 { }
|
@ -55,11 +55,13 @@ class BootImage {
|
||||
unsigned heapSize;
|
||||
unsigned codeSize;
|
||||
|
||||
unsigned classCount;
|
||||
unsigned bootClassCount;
|
||||
unsigned appClassCount;
|
||||
unsigned stringCount;
|
||||
unsigned callCount;
|
||||
|
||||
unsigned loader;
|
||||
unsigned bootLoader;
|
||||
unsigned appLoader;
|
||||
unsigned types;
|
||||
unsigned methodTree;
|
||||
unsigned methodTreeSentinal;
|
||||
|
110
src/builtin.cpp
110
src/builtin.cpp
@ -18,10 +18,11 @@ using namespace vm;
|
||||
namespace {
|
||||
|
||||
int64_t
|
||||
search(Thread* t, object name, object (*op)(Thread*, object),
|
||||
bool replaceDots)
|
||||
search(Thread* t, object loader, object name,
|
||||
object (*op)(Thread*, object, object), bool replaceDots)
|
||||
{
|
||||
if (LIKELY(name)) {
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, name);
|
||||
|
||||
object n = makeByteArray(t, stringLength(t, name) + 1);
|
||||
@ -32,7 +33,7 @@ search(Thread* t, object name, object (*op)(Thread*, object),
|
||||
replace('.', '/', s);
|
||||
}
|
||||
|
||||
object r = op(t, n);
|
||||
object r = op(t, loader, n);
|
||||
if (t->exception) {
|
||||
return 0;
|
||||
}
|
||||
@ -45,86 +46,45 @@ search(Thread* t, object name, object (*op)(Thread*, object),
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
resolveSystemClassThrow(Thread* t, object loader, object spec)
|
||||
{
|
||||
return resolveSystemClass(t, loader, spec, true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_avian_SystemClassLoader_acquireClassLock
|
||||
(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
acquire(t, t->m->classLock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_avian_SystemClassLoader_releaseClassLock
|
||||
(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
release(t, t->m->classLock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_getVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>
|
||||
(objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_defineVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object loader = reinterpret_cast<object>(arguments[0]);
|
||||
object b = reinterpret_cast<object>(arguments[1]);
|
||||
int offset = arguments[2];
|
||||
int length = arguments[3];
|
||||
|
||||
uint8_t* buffer = static_cast<uint8_t*>
|
||||
(t->m->heap->allocate(length));
|
||||
memcpy(buffer, &byteArrayBody(t, b, offset), length);
|
||||
object c = defineClass(t, loader, buffer, length);
|
||||
t->m->heap->free(buffer, length);
|
||||
|
||||
return reinterpret_cast<int64_t>(c);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_findLoadedVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object name = reinterpret_cast<object>(arguments[0]);
|
||||
object loader = reinterpret_cast<object>(arguments[0]);
|
||||
object name = reinterpret_cast<object>(arguments[1]);
|
||||
|
||||
return search(t, name, findLoadedSystemClass, true);
|
||||
return search(t, loader, name, findLoadedClass, true);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_findVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object name = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
return search(t, name, resolveSystemClass, true);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_resolveVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object loader = reinterpret_cast<object>(arguments[0]);
|
||||
object spec = reinterpret_cast<object>(arguments[1]);
|
||||
object name = reinterpret_cast<object>(arguments[1]);
|
||||
|
||||
return reinterpret_cast<int64_t>(resolveClass(t, loader, spec));
|
||||
return search(t, loader, name, resolveSystemClassThrow, true);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_resourceExists
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object name = reinterpret_cast<object>(arguments[0]);
|
||||
object loader = reinterpret_cast<object>(arguments[0]);
|
||||
object name = reinterpret_cast<object>(arguments[1]);
|
||||
|
||||
if (LIKELY(name)) {
|
||||
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
|
||||
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||
return t->m->finder->exists(RUNTIME_ARRAY_BODY(n));
|
||||
return getFinder(t, loader)->exists(RUNTIME_ARRAY_BODY(n));
|
||||
} else {
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::NullPointerExceptionType);
|
||||
@ -133,35 +93,11 @@ Avian_avian_SystemClassLoader_resourceExists
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_primitiveClass
|
||||
Avian_avian_SystemClassLoader_getClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_avian_SystemClassLoader_initialize
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
initClass(t, this_);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_isAssignableFrom
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
object that = reinterpret_cast<object>(arguments[1]);
|
||||
|
||||
if (LIKELY(that)) {
|
||||
return vm::isAssignableFrom(t, this_, that);
|
||||
} else {
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::NullPointerExceptionType);
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<int64_t>
|
||||
(getJClass(t, reinterpret_cast<object>(arguments[0])));
|
||||
}
|
||||
|
||||
#ifdef AVIAN_HEAPDUMP
|
||||
@ -208,7 +144,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength
|
||||
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
||||
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||
|
||||
System::Region* r = t->m->finder->find(RUNTIME_ARRAY_BODY(p));
|
||||
System::Region* r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p));
|
||||
if (r) {
|
||||
jint rSize = r->length();
|
||||
r->dispose();
|
||||
@ -229,7 +165,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open
|
||||
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||
|
||||
return reinterpret_cast<int64_t>
|
||||
(t->m->finder->find(RUNTIME_ARRAY_BODY(p)));
|
||||
(t->m->appFinder->find(RUNTIME_ARRAY_BODY(p)));
|
||||
} else {
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::NullPointerExceptionType);
|
||||
|
@ -49,15 +49,16 @@ class MyClasspath : public Classpath {
|
||||
const unsigned NormalPriority = 5;
|
||||
|
||||
return vm::makeThread
|
||||
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, t->m->loader, 0, 0,
|
||||
group);
|
||||
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0,
|
||||
root(t, Machine::BootLoader), 0, 0, group);
|
||||
}
|
||||
|
||||
virtual void
|
||||
runThread(Thread* t)
|
||||
{
|
||||
object method = resolveMethod
|
||||
(t, t->m->loader, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
|
||||
(t, root(t, Machine::BootLoader), "java/lang/Thread", "run",
|
||||
"(Ljava/lang/Thread;)V");
|
||||
|
||||
if (t->exception == 0) {
|
||||
t->m->processor->invoke(t, method, 0, t->javaThread);
|
||||
@ -75,7 +76,7 @@ class MyClasspath : public Classpath {
|
||||
trace = makeTrace(t);
|
||||
}
|
||||
|
||||
object result = make(t, arrayBody(t, t->m->types, type));
|
||||
object result = make(t, vm::type(t, type));
|
||||
|
||||
set(t, result, ThrowableMessage, message);
|
||||
set(t, result, ThrowableTrace, trace);
|
||||
@ -84,6 +85,12 @@ class MyClasspath : public Classpath {
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void
|
||||
boot(Thread*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual void
|
||||
dispose()
|
||||
{
|
||||
@ -352,7 +359,7 @@ Avian_java_lang_reflect_Array_makeObjectArray
|
||||
int length = arguments[1];
|
||||
|
||||
return reinterpret_cast<int64_t>
|
||||
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
|
||||
(makeObjectArray(t, elementType, length));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
@ -408,7 +415,8 @@ Avian_java_lang_System_getVMProperty
|
||||
|
||||
int64_t r = 0;
|
||||
if (::strcmp(RUNTIME_ARRAY_BODY(n), "java.lang.classpath") == 0) {
|
||||
r = reinterpret_cast<int64_t>(makeString(t, "%s", t->m->finder->path()));
|
||||
r = reinterpret_cast<int64_t>
|
||||
(makeString(t, "%s", t->m->appFinder->path()));
|
||||
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "avian.version") == 0) {
|
||||
r = reinterpret_cast<int64_t>(makeString(t, AVIAN_VERSION));
|
||||
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "file.encoding") == 0) {
|
||||
@ -499,7 +507,8 @@ Avian_java_lang_Runtime_addShutdownHook
|
||||
|
||||
ACQUIRE(t, t->m->shutdownLock);
|
||||
|
||||
t->m->shutdownHooks = makePair(t, hook, t->m->shutdownHooks);
|
||||
setRoot(t, Machine::ShutdownHooks,
|
||||
makePair(t, hook, root(t, Machine::ShutdownHooks)));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
@ -516,15 +525,13 @@ Avian_java_lang_Throwable_resolveTrace
|
||||
object trace = reinterpret_cast<object>(*arguments);
|
||||
PROTECT(t, trace);
|
||||
|
||||
unsigned length = arrayLength(t, trace);
|
||||
object elementType = arrayBody
|
||||
(t, t->m->types, Machine::StackTraceElementType);
|
||||
object array = makeObjectArray
|
||||
(t, classLoader(t, elementType), elementType, length);
|
||||
unsigned length = objectArrayLength(t, trace);
|
||||
object elementType = type(t, Machine::StackTraceElementType);
|
||||
object array = makeObjectArray(t, elementType, length);
|
||||
PROTECT(t, array);
|
||||
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
object ste = makeStackTraceElement(t, arrayBody(t, trace, i));
|
||||
object ste = makeStackTraceElement(t, objectArrayBody(t, trace, i));
|
||||
set(t, array, ArrayBody + (i * BytesPerWord), ste);
|
||||
}
|
||||
|
||||
@ -599,3 +606,85 @@ Avian_java_lang_Thread_setDaemon
|
||||
|
||||
setDaemon(t, thread, daemon);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_avian_Classes_acquireClassLock
|
||||
(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
acquire(t, t->m->classLock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_avian_Classes_releaseClassLock
|
||||
(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
release(t, t->m->classLock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_resolveVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object loader = reinterpret_cast<object>(arguments[0]);
|
||||
object spec = reinterpret_cast<object>(arguments[1]);
|
||||
|
||||
return reinterpret_cast<int64_t>(resolveClass(t, loader, spec));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_primitiveClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_defineVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object loader = reinterpret_cast<object>(arguments[0]);
|
||||
object b = reinterpret_cast<object>(arguments[1]);
|
||||
int offset = arguments[2];
|
||||
int length = arguments[3];
|
||||
|
||||
uint8_t* buffer = static_cast<uint8_t*>
|
||||
(t->m->heap->allocate(length));
|
||||
memcpy(buffer, &byteArrayBody(t, b, offset), length);
|
||||
object c = defineClass(t, loader, buffer, length);
|
||||
t->m->heap->free(buffer, length);
|
||||
|
||||
return reinterpret_cast<int64_t>(c);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_avian_Classes_initialize
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
initClass(t, this_);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_isAssignableFrom
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
object that = reinterpret_cast<object>(arguments[1]);
|
||||
|
||||
if (LIKELY(that)) {
|
||||
return vm::isAssignableFrom(t, this_, that);
|
||||
} else {
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::NullPointerExceptionType);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_getVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>
|
||||
(objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||
}
|
||||
|
@ -56,8 +56,7 @@ getTrace(Thread* t, unsigned skipCount)
|
||||
if (skipCount == 0) {
|
||||
object method = walker->method();
|
||||
if (isAssignableFrom
|
||||
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
|
||||
methodClass(t, method))
|
||||
(t, type(t, Machine::ThrowableType), methodClass(t, method))
|
||||
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||
&byteArrayBody(t, methodName(t, method), 0))
|
||||
== 0)
|
||||
@ -80,7 +79,7 @@ getTrace(Thread* t, unsigned skipCount)
|
||||
|
||||
t->m->processor->walkStack(t, &v);
|
||||
|
||||
if (v.trace == 0) v.trace = makeArray(t, 0);
|
||||
if (v.trace == 0) v.trace = makeObjectArray(t, 0);
|
||||
|
||||
return v.trace;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
# include <unistd.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/socket.h>
|
||||
# include <fcntl.h>
|
||||
# include <errno.h>
|
||||
|
||||
@ -77,10 +78,10 @@ CREAT(string_t path, int mode)
|
||||
namespace local {
|
||||
|
||||
const unsigned InterfaceVersion = 4;
|
||||
const unsigned PageSize = 4 * 1024;
|
||||
|
||||
Machine* globalMachine;
|
||||
|
||||
|
||||
const char*
|
||||
primitiveName(Thread* t, object c)
|
||||
{
|
||||
@ -144,6 +145,8 @@ class MyClasspath : public Classpath {
|
||||
virtual object
|
||||
makeJclass(Thread* t, object class_)
|
||||
{
|
||||
PROTECT(t, class_);
|
||||
|
||||
object name = makeClassNameString(t, getClassName(t, class_));
|
||||
|
||||
return vm::makeJclass
|
||||
@ -153,9 +156,7 @@ class MyClasspath : public Classpath {
|
||||
virtual object
|
||||
makeString(Thread* t, object array, int32_t offset, int32_t length)
|
||||
{
|
||||
if (objectClass(t, array)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, array) == type(t, Machine::ByteArrayType)) {
|
||||
PROTECT(t, array);
|
||||
|
||||
object charArray = makeCharArray(t, length);
|
||||
@ -183,19 +184,25 @@ class MyClasspath : public Classpath {
|
||||
}
|
||||
|
||||
return vm::makeThread
|
||||
(t, 0, NormalPriority, 0, 0, false, false, false, 0, group, t->m->loader,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, 0, false);
|
||||
(t, 0, NormalPriority, 0, 0, false, false, false, 0, group,
|
||||
root(t, Machine::BootLoader), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0,
|
||||
0, false);
|
||||
}
|
||||
|
||||
virtual void
|
||||
runThread(Thread* t)
|
||||
{
|
||||
object method = resolveMethod
|
||||
(t, t->m->loader, "java/lang/Thread", "run", "()V");
|
||||
(t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V");
|
||||
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
t->m->processor->invoke(t, method, t->javaThread);
|
||||
}
|
||||
|
||||
acquire(t, t->javaThread);
|
||||
t->flags &= ~Thread::ActiveFlag;
|
||||
notifyAll(t, t->javaThread);
|
||||
release(t, t->javaThread);
|
||||
}
|
||||
|
||||
virtual object
|
||||
@ -209,7 +216,7 @@ class MyClasspath : public Classpath {
|
||||
trace = makeTrace(t);
|
||||
}
|
||||
|
||||
object result = make(t, arrayBody(t, t->m->types, type));
|
||||
object result = make(t, vm::type(t, type));
|
||||
|
||||
set(t, result, ThrowableMessage, message);
|
||||
set(t, result, ThrowableTrace, trace);
|
||||
@ -228,7 +235,22 @@ class MyClasspath : public Classpath {
|
||||
}
|
||||
|
||||
t->m->processor->invoke
|
||||
(t, t->m->loader, "java/lang/System", "initializeSystemClass", "()V", 0);
|
||||
(t, root(t, Machine::BootLoader), "java/lang/System",
|
||||
"initializeSystemClass", "()V", 0);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
object constructor = resolveMethod
|
||||
(t, type(t, Machine::ClassLoaderType), "<init>",
|
||||
"(Ljava/lang/ClassLoader;)V");
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
PROTECT(t, constructor);
|
||||
|
||||
t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
t->m->processor->invoke
|
||||
(t, constructor, root(t, Machine::AppLoader),
|
||||
root(t, Machine::BootLoader));
|
||||
}
|
||||
|
||||
virtual void
|
||||
@ -281,16 +303,16 @@ countFields(Thread* t, object c, bool publicOnly)
|
||||
{
|
||||
object table = classFieldTable(t, c);
|
||||
if (publicOnly) {
|
||||
return objectArrayLength(t, table);
|
||||
} else {
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||
object vmField = arrayBody(t, table, i);
|
||||
if ((not publicOnly) or (fieldFlags(t, vmField) & ACC_PUBLIC)) {
|
||||
if (fieldFlags(t, vmField) & ACC_PUBLIC) {
|
||||
++ count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
} else {
|
||||
return objectArrayLength(t, table);
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,8 +452,7 @@ resolveParameterJTypes(Thread* t, object loader, object spec,
|
||||
PROTECT(t, list);
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
|
||||
*parameterCount);
|
||||
(t, type(t, Machine::JclassType), *parameterCount);
|
||||
PROTECT(t, array);
|
||||
|
||||
for (int i = *parameterCount - 1; i >= 0; --i) {
|
||||
@ -447,15 +468,14 @@ object
|
||||
resolveExceptionJTypes(Thread* t, object loader, object addendum)
|
||||
{
|
||||
if (addendum == 0) {
|
||||
return makeObjectArray
|
||||
(t, loader, arrayBody(t, t->m->types, Machine::JclassType), 0);
|
||||
return makeObjectArray(t, type(t, Machine::JclassType), 0);
|
||||
}
|
||||
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, addendum);
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, loader, arrayBody(t, t->m->types, Machine::JclassType),
|
||||
(t, type(t, Machine::JclassType),
|
||||
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
|
||||
PROTECT(t, array);
|
||||
|
||||
@ -467,9 +487,7 @@ resolveExceptionJTypes(Thread* t, object loader, object addendum)
|
||||
|
||||
object o = singletonObject(t, addendumPool(t, addendum), index);
|
||||
|
||||
if (objectClass(t, o)
|
||||
== arrayBody(t, t->m->types, Machine::ReferenceType))
|
||||
{
|
||||
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
|
||||
o = resolveClass(t, loader, referenceName(t, o));
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
@ -532,6 +550,38 @@ Avian_sun_misc_Unsafe_registerNatives
|
||||
// ignore
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t
|
||||
Avian_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
//object name = reinterpret_cast<object>(arguments[1]);
|
||||
object data = reinterpret_cast<object>(arguments[2]);
|
||||
int32_t offset = arguments[3];
|
||||
int32_t length = arguments[4];
|
||||
object loader = reinterpret_cast<object>(arguments[5]);
|
||||
//object domain = reinterpret_cast<object>(arguments[6]);
|
||||
|
||||
uint8_t* buffer = static_cast<uint8_t*>
|
||||
(t->m->heap->allocate(length));
|
||||
memcpy(buffer, &byteArrayBody(t, data, offset), length);
|
||||
object c = defineClass(t, loader, buffer, length);
|
||||
|
||||
return c ? reinterpret_cast<int64_t>(getJClass(t, c)) : 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t
|
||||
Avian_sun_misc_Unsafe_allocateInstance
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[1]));
|
||||
PROTECT(t, c);
|
||||
|
||||
initClass(t, c);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
return reinterpret_cast<int64_t>(make(t, c));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_staticFieldOffset
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
@ -564,15 +614,90 @@ Avian_sun_misc_Unsafe_objectFieldOffset
|
||||
(t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield)));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getObject
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
|
||||
return cast<uintptr_t>(o, offset);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putObject
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
uintptr_t value = arguments[4];
|
||||
|
||||
set(t, o, offset, reinterpret_cast<object>(value));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
|
||||
return cast<int32_t>(o, offset);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
int32_t value = arguments[4];
|
||||
|
||||
cast<int32_t>(o, offset) = value;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getBoolean
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
|
||||
return cast<uint8_t>(o, offset);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putBoolean
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
uint8_t value = arguments[4];
|
||||
|
||||
cast<uint8_t>(o, offset) = value;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
int64_t value; memcpy(&value, arguments + 4, 8);
|
||||
|
||||
cast<int64_t>(o, offset) = value;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getObjectVolatile
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[1]);
|
||||
unsigned offset = arguments[2];
|
||||
object value = cast<object>(o, offset);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
|
||||
uintptr_t value = cast<uintptr_t>(o, offset);
|
||||
loadMemoryBarrier();
|
||||
return reinterpret_cast<int64_t>(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
@ -588,6 +713,25 @@ Avian_sun_misc_Unsafe_compareAndSwapInt
|
||||
(&cast<int32_t>(target, offset), expect, update);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_compareAndSwapObject
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object target = reinterpret_cast<object>(arguments[1]);
|
||||
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
||||
intptr_t expect = arguments[4];
|
||||
intptr_t update = arguments[5];
|
||||
|
||||
bool success = __sync_bool_compare_and_swap
|
||||
(&cast<intptr_t>(target, offset), expect, update);
|
||||
|
||||
if (success) {
|
||||
mark(t, target, offset);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_compareAndSwapLong
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
@ -625,6 +769,17 @@ Avian_sun_misc_Unsafe_freeMemory
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_setMemory
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int64_t count; memcpy(&count, arguments + 3, 8);
|
||||
int8_t v = arguments[5];
|
||||
|
||||
memset(reinterpret_cast<int8_t*>(p), v, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putLong__JJ
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
@ -635,6 +790,16 @@ Avian_sun_misc_Unsafe_putLong__JJ
|
||||
*reinterpret_cast<int64_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putInt__JI
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int32_t v = arguments[3];
|
||||
|
||||
*reinterpret_cast<int32_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getByte__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
@ -644,6 +809,22 @@ Avian_sun_misc_Unsafe_getByte__J
|
||||
return *reinterpret_cast<int8_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getInt__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int32_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_pageSize
|
||||
(Thread*, object, uintptr_t*)
|
||||
{
|
||||
return local::PageSize;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_ensureClassInitialized
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
@ -732,7 +913,7 @@ JVM_InitProperties(Thread* t, jobject properties)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object method = resolveMethod
|
||||
(t, t->m->loader, "java/util/Properties", "setProperty",
|
||||
(t, root(t, Machine::BootLoader), "java/util/Properties", "setProperty",
|
||||
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
|
||||
|
||||
if (UNLIKELY(t->exception)) {
|
||||
@ -776,6 +957,9 @@ JVM_InitProperties(Thread* t, jobject properties)
|
||||
local::setProperty(t, method, *properties, "sun.boot.library.path",
|
||||
getenv("LD_LIBRARY_PATH"));
|
||||
|
||||
local::setProperty(t, method, *properties, "java.protocol.handler.pkgs",
|
||||
"avian");
|
||||
|
||||
#endif
|
||||
local::setProperty(t, method, *properties, "file.encoding", "ASCII");
|
||||
#ifdef ARCH_x86_32
|
||||
@ -811,10 +995,16 @@ extern "C" JNIEXPORT void JNICALL
|
||||
JVM_OnExit(void (*)(void)) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
JVM_Exit(jint) { abort(); }
|
||||
JVM_Exit(jint code)
|
||||
{
|
||||
exit(code);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
JVM_Halt(jint) { abort(); }
|
||||
JVM_Halt(jint code)
|
||||
{
|
||||
exit(code);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
JVM_GC()
|
||||
@ -896,7 +1086,7 @@ JVM_GetStackTraceDepth(Thread* t, jobject throwable)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return arrayLength(t, throwableTrace(t, *throwable));
|
||||
return objectArrayLength(t, throwableTrace(t, *throwable));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
@ -906,7 +1096,7 @@ JVM_GetStackTraceElement(Thread* t, jobject throwable, jint index)
|
||||
|
||||
return makeLocalReference
|
||||
(t, makeStackTraceElement
|
||||
(t, arrayBody(t, throwableTrace(t, *throwable), index)));
|
||||
(t, objectArrayBody(t, throwableTrace(t, *throwable), index)));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
@ -947,25 +1137,7 @@ JVM_IsThreadAlive(Thread* t, jobject thread)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread));
|
||||
if (p) {
|
||||
switch (p->state) {
|
||||
case Thread::ActiveState:
|
||||
case Thread::IdleState:
|
||||
case Thread::ExclusiveState:
|
||||
return true;
|
||||
|
||||
case Thread::NoState:
|
||||
case Thread::ZombieState:
|
||||
case Thread::JoinedState:
|
||||
case Thread::ExitState:
|
||||
return false;
|
||||
|
||||
default:
|
||||
abort(t);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return p and (p->flags & Thread::ActiveFlag) != 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
@ -1013,7 +1185,19 @@ extern "C" JNIEXPORT void JNICALL
|
||||
JVM_Interrupt(Thread*, jobject) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
JVM_IsInterrupted(Thread*, jobject, jboolean) { abort(); }
|
||||
JVM_IsInterrupted(Thread* t, jobject thread, jboolean clear)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
acquire(t, *thread);
|
||||
bool v = threadInterrupted(t, *thread);
|
||||
if (clear) {
|
||||
threadInterrupted(t, *thread) = false;
|
||||
}
|
||||
release(t, *thread);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
JVM_HoldsLock(Thread*, jclass, jobject) { abort(); }
|
||||
@ -1042,13 +1226,12 @@ JVM_GetClassContext(Thread* t)
|
||||
PROTECT(t, trace);
|
||||
|
||||
object context = makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
|
||||
arrayLength(t, trace));
|
||||
(t, type(t, Machine::JclassType), objectArrayLength(t, trace));
|
||||
PROTECT(t, context);
|
||||
|
||||
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
|
||||
for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) {
|
||||
object c = getJClass
|
||||
(t, methodClass(t, traceElementMethod(t, arrayBody(t, trace, i))));
|
||||
(t, methodClass(t, traceElementMethod(t, objectArrayBody(t, trace, i))));
|
||||
|
||||
set(t, context, ArrayBody + (i * BytesPerWord), c);
|
||||
}
|
||||
@ -1084,16 +1267,31 @@ JVM_LoadClass0(Thread*, jobject, jclass,
|
||||
jstring) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_GetArrayLength(Thread*, jobject) { abort(); }
|
||||
JVM_GetArrayLength(Thread* t, jobject array)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return cast<uintptr_t>(*array, BytesPerWord);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
JVM_GetArrayElement(Thread*, jobject, jint) { abort(); }
|
||||
JVM_GetArrayElement(Thread* t, jobject array, jint index)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return makeLocalReference(t, objectArrayBody(t, *array, index));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jvalue JNICALL
|
||||
JVM_GetPrimitiveArrayElement(Thread*, jobject, jint, jint) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
JVM_SetArrayElement(Thread*, jobject, jint, jobject) { abort(); }
|
||||
JVM_SetArrayElement(Thread* t, jobject array, jint index, jobject value)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
JVM_SetPrimitiveArrayElement(Thread*, jobject, jint, jvalue,
|
||||
@ -1126,8 +1324,7 @@ JVM_NewArray(Thread* t, jclass elementClass, jint length)
|
||||
default: abort(t);
|
||||
}
|
||||
} else {
|
||||
return makeLocalReference
|
||||
(t, makeObjectArray(t, t->m->loader, c, length));
|
||||
return makeLocalReference(t, makeObjectArray(t, c, length));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1152,32 +1349,32 @@ JVM_FindPrimitiveClass(Thread* t, const char* name)
|
||||
case 'b':
|
||||
if (name[1] == 'o') {
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JbooleanType)));
|
||||
(t, getJClass(t, type(t, Machine::JbooleanType)));
|
||||
} else {
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JbyteType)));
|
||||
(t, getJClass(t, type(t, Machine::JbyteType)));
|
||||
}
|
||||
case 'c':
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JcharType)));
|
||||
(t, getJClass(t, type(t, Machine::JcharType)));
|
||||
case 'd':
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JdoubleType)));
|
||||
(t, getJClass(t, type(t, Machine::JdoubleType)));
|
||||
case 'f':
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JfloatType)));
|
||||
(t, getJClass(t, type(t, Machine::JfloatType)));
|
||||
case 'i':
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JintType)));
|
||||
(t, getJClass(t, type(t, Machine::JintType)));
|
||||
case 'l':
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JlongType)));
|
||||
(t, getJClass(t, type(t, Machine::JlongType)));
|
||||
case 's':
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JshortType)));
|
||||
(t, getJClass(t, type(t, Machine::JshortType)));
|
||||
case 'v':
|
||||
return makeLocalReference
|
||||
(t, getJClass(t, arrayBody(t, t->m->types, Machine::JvoidType)));
|
||||
(t, getJClass(t, type(t, Machine::JvoidType)));
|
||||
default:
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::IllegalArgumentExceptionType);
|
||||
@ -1194,7 +1391,8 @@ JVM_FindClassFromClassLoader(Thread* t, const char* name, jboolean init,
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object c = resolveClass(t, loader ? *loader : t->m->loader, name);
|
||||
object c = resolveClass
|
||||
(t, loader ? *loader : root(t, Machine::BootLoader), name);
|
||||
if (t->exception) {
|
||||
if (throwError) {
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
@ -1224,25 +1422,13 @@ JVM_FindLoadedClass(Thread* t, jobject loader, jstring name)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
object spec = makeByteArray(t, stringLength(t, *name) + 1);
|
||||
{ char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0));
|
||||
stringChars(t, *name, s);
|
||||
replace('.', '/', s);
|
||||
}
|
||||
|
||||
object c;
|
||||
if (loader == 0 or *loader == t->m->loader) {
|
||||
c = findLoadedSystemClass(t, spec);
|
||||
} else {
|
||||
object map = classLoaderMap(t, *loader);
|
||||
if (map) {
|
||||
c = hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual);
|
||||
} else {
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
object c = findLoadedClass(t, *loader, spec);
|
||||
|
||||
return c ? makeLocalReference(t, getJClass(t, c)) : 0;
|
||||
}
|
||||
@ -1275,8 +1461,7 @@ JVM_GetClassInterfaces(Thread* t, jclass c)
|
||||
(classFlags(t, jclassVmClass(t, *c)) & ACC_INTERFACE) == 0 ? 2 : 1;
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
|
||||
arrayLength(t, table) / stride);
|
||||
(t, type(t, Machine::JclassType), arrayLength(t, table) / stride);
|
||||
PROTECT(t, array);
|
||||
|
||||
for (unsigned i = 0; i < objectArrayLength(t, array); ++i) {
|
||||
@ -1287,9 +1472,7 @@ JVM_GetClassInterfaces(Thread* t, jclass c)
|
||||
return makeLocalReference(t, array);
|
||||
} else {
|
||||
return makeLocalReference
|
||||
(t, makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType),
|
||||
0));
|
||||
(t, makeObjectArray(t, type(t, Machine::JclassType), 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1299,7 +1482,8 @@ JVM_GetClassLoader(Thread* t, jclass c)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object loader = classLoader(t, jclassVmClass(t, *c));
|
||||
return loader == t->m->loader ? 0 : makeLocalReference(t, loader);
|
||||
return loader == root(t, Machine::BootLoader)
|
||||
? 0 : makeLocalReference(t, loader);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
@ -1385,8 +1569,10 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly)
|
||||
|
||||
object table = classMethodTable(t, jclassVmClass(t, *c));
|
||||
if (table) {
|
||||
PROTECT(t, table);
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JmethodType),
|
||||
(t, type(t, Machine::JmethodType),
|
||||
local::countMethods(t, jclassVmClass(t, *c), publicOnly));
|
||||
PROTECT(t, array);
|
||||
|
||||
@ -1461,9 +1647,7 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly)
|
||||
return makeLocalReference(t, array);
|
||||
} else {
|
||||
return makeLocalReference
|
||||
(t, makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JmethodType),
|
||||
0));
|
||||
(t, makeObjectArray(t, type(t, Machine::JmethodType), 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1474,8 +1658,10 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
|
||||
|
||||
object table = classFieldTable(t, jclassVmClass(t, *c));
|
||||
if (table) {
|
||||
PROTECT(t, table);
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JfieldType),
|
||||
(t, type(t, Machine::JfieldType),
|
||||
local::countFields(t, jclassVmClass(t, *c), publicOnly));
|
||||
PROTECT(t, array);
|
||||
|
||||
@ -1501,6 +1687,8 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PROTECT(t, type);
|
||||
|
||||
type = getJClass(t, type);
|
||||
|
||||
object signature = t->m->classpath->makeString
|
||||
@ -1524,12 +1712,12 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly)
|
||||
set(t, array, ArrayBody + ((ai++) * BytesPerWord), field);
|
||||
}
|
||||
}
|
||||
assert(t, ai == objectArrayLength(t, array));
|
||||
|
||||
return makeLocalReference(t, array);
|
||||
} else {
|
||||
return makeLocalReference
|
||||
(t, makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JfieldType), 0));
|
||||
(t, makeObjectArray(t, type(t, Machine::JfieldType), 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1540,8 +1728,10 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly)
|
||||
|
||||
object table = classMethodTable(t, jclassVmClass(t, *c));
|
||||
if (table) {
|
||||
PROTECT(t, table);
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JconstructorType),
|
||||
(t, type(t, Machine::JconstructorType),
|
||||
local::countConstructors(t, jclassVmClass(t, *c), publicOnly));
|
||||
PROTECT(t, array);
|
||||
|
||||
@ -1598,9 +1788,7 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly)
|
||||
return makeLocalReference(t, array);
|
||||
} else {
|
||||
return makeLocalReference
|
||||
(t, makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JconstructorType),
|
||||
0));
|
||||
(t, makeObjectArray(t, type(t, Machine::JconstructorType), 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1739,8 +1927,11 @@ JVM_DoPrivileged
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
// todo: cache these class and method lookups in the t->m->classpath
|
||||
// object:
|
||||
|
||||
object privilegedAction = resolveClass
|
||||
(t, t->m->loader, "java/security/PrivilegedAction");
|
||||
(t, root(t, Machine::BootLoader), "java/security/PrivilegedAction");
|
||||
|
||||
if (UNLIKELY(t->exception)) {
|
||||
return 0;
|
||||
@ -1752,7 +1943,8 @@ JVM_DoPrivileged
|
||||
(t, privilegedAction, "run", "()Ljava/lang/Object;");
|
||||
} else {
|
||||
object privilegedExceptionAction = resolveClass
|
||||
(t, t->m->loader, "java/security/PrivilegedExceptionAction");
|
||||
(t, root(t, Machine::BootLoader),
|
||||
"java/security/PrivilegedExceptionAction");
|
||||
|
||||
if (UNLIKELY(t->exception)) {
|
||||
return 0;
|
||||
@ -1769,10 +1961,8 @@ JVM_DoPrivileged
|
||||
return makeLocalReference(t, result);
|
||||
} else {
|
||||
if (wrapException and not
|
||||
(instanceOf
|
||||
(t, arrayBody(t, t->m->types, Machine::ErrorType), t->exception)
|
||||
or instanceOf
|
||||
(t, arrayBody(t, t->m->types, Machine::RuntimeExceptionType),
|
||||
(instanceOf(t, type(t, Machine::ErrorType), t->exception)
|
||||
or instanceOf(t, type(t, Machine::RuntimeExceptionType),
|
||||
t->exception)))
|
||||
{
|
||||
object cause = t->exception;
|
||||
@ -1781,7 +1971,8 @@ JVM_DoPrivileged
|
||||
t->exception = 0;
|
||||
|
||||
object paeClass = resolveClass
|
||||
(t, t->m->loader, "java/security/PrivilegedActionException");
|
||||
(t, root(t, Machine::BootLoader),
|
||||
"java/security/PrivilegedActionException");
|
||||
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
PROTECT(t, paeClass);
|
||||
@ -2003,37 +2194,83 @@ extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Sync(jint) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_InitializeSocketLibrary(void) { abort(); }
|
||||
JVM_InitializeSocketLibrary()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
static bool wsaInitialized = false;
|
||||
if (not wsaInitialized) {
|
||||
WSADATA data;
|
||||
int r = WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
|
||||
return -1;
|
||||
} else {
|
||||
wsaInitialized = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Socket(jint, jint, jint) { abort(); }
|
||||
JVM_Socket(jint domain, jint type, jint protocol)
|
||||
{
|
||||
return socket(domain, type, protocol);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_SocketClose(jint) { abort(); }
|
||||
JVM_SocketClose(jint socket)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return closesocket(socket);
|
||||
#else
|
||||
return close(socket);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_SocketShutdown(jint, jint) { abort(); }
|
||||
JVM_SocketShutdown(jint socket, jint how)
|
||||
{
|
||||
return shutdown(socket, how);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Recv(jint, char*, jint, jint) { abort(); }
|
||||
JVM_Recv(jint socket, char* dst, jint count, jint flags)
|
||||
{
|
||||
return recv(socket, dst, count, flags);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Send(jint, char*, jint, jint) { abort(); }
|
||||
JVM_Send(jint socket, char* src, jint count, jint flags)
|
||||
{
|
||||
return send(socket, src, count, flags);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Timeout(int, long) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Listen(jint, jint) { abort(); }
|
||||
JVM_Listen(jint socket, jint count)
|
||||
{
|
||||
return listen(socket, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Connect(jint, struct sockaddr*, jint) { abort(); }
|
||||
JVM_Connect(jint socket, sockaddr* address, jint addressLength)
|
||||
{
|
||||
return connect(socket, address, addressLength);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Bind(jint, struct sockaddr*, jint) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Accept(jint, struct sockaddr*, jint*) { abort(); }
|
||||
JVM_Accept(jint socket, struct sockaddr* address, jint* addressLength)
|
||||
{
|
||||
socklen_t length = *addressLength;
|
||||
int r = accept(socket, address, &length);
|
||||
*addressLength = length;
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_RecvFrom(jint, char*, int,
|
||||
@ -2047,7 +2284,13 @@ extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_SocketAvailable(jint, jint*) { abort(); }
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_GetSockName(jint, struct sockaddr*, int*) { abort(); }
|
||||
JVM_GetSockName(jint socket, struct sockaddr* address, int* addressLength)
|
||||
{
|
||||
socklen_t length = *addressLength;
|
||||
int r = getsockname(socket, address, &length);
|
||||
*addressLength = length;
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_GetSockOpt(jint, int, int, char*, int*) { abort(); }
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#define THREAD_STACK 2224
|
||||
#define THREAD_STACK 2216
|
||||
|
||||
#if defined __MINGW32__ || defined __CYGWIN32__
|
||||
|
||||
|
390
src/compile.cpp
390
src/compile.cpp
@ -40,7 +40,7 @@ namespace {
|
||||
|
||||
namespace local {
|
||||
|
||||
const bool DebugCompile = true;
|
||||
const bool DebugCompile = false;
|
||||
const bool DebugNatives = false;
|
||||
const bool DebugCallTable = false;
|
||||
const bool DebugMethodTree = false;
|
||||
@ -61,6 +61,20 @@ const unsigned InitialZoneCapacityInBytes = 64 * 1024;
|
||||
|
||||
const unsigned ExecutableAreaSizeInBytes = 16 * 1024 * 1024;
|
||||
|
||||
enum Root {
|
||||
CallTable,
|
||||
MethodTree,
|
||||
MethodTreeSentinal,
|
||||
ObjectPools,
|
||||
StaticTableArray,
|
||||
VirtualThunks,
|
||||
ReceiveMethod,
|
||||
WindMethod,
|
||||
RewindMethod
|
||||
};
|
||||
|
||||
const unsigned RootCount = RewindMethod + 1;
|
||||
|
||||
inline bool
|
||||
isVmInvokeUnsafeStack(void* ip)
|
||||
{
|
||||
@ -169,7 +183,7 @@ class MyThread: public Thread {
|
||||
// in this function, we "atomically" update the thread context
|
||||
// fields in such a way to ensure that another thread may
|
||||
// interrupt us at any time and still get a consistent, accurate
|
||||
// stack trace. See MyProcess::getStackTrace for details.
|
||||
// stack trace. See MyProcessor::getStackTrace for details.
|
||||
|
||||
assert(t, t->transition == 0);
|
||||
|
||||
@ -277,7 +291,7 @@ resolveTarget(MyThread* t, void* stack, object method)
|
||||
PROTECT(t, method);
|
||||
PROTECT(t, class_);
|
||||
|
||||
resolveSystemClass(t, className(t, class_));
|
||||
resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_));
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
}
|
||||
|
||||
@ -294,7 +308,7 @@ resolveTarget(MyThread* t, object class_, unsigned index)
|
||||
if (classVmFlags(t, class_) & BootstrapFlag) {
|
||||
PROTECT(t, class_);
|
||||
|
||||
resolveSystemClass(t, className(t, class_));
|
||||
resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_));
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
}
|
||||
|
||||
@ -302,10 +316,10 @@ resolveTarget(MyThread* t, object class_, unsigned index)
|
||||
}
|
||||
|
||||
object&
|
||||
methodTree(MyThread* t);
|
||||
root(Thread* t, Root root);
|
||||
|
||||
object
|
||||
methodTreeSentinal(MyThread* t);
|
||||
void
|
||||
setRoot(Thread* t, Root root, object value);
|
||||
|
||||
unsigned
|
||||
compiledSize(intptr_t address)
|
||||
@ -348,8 +362,8 @@ methodForIp(MyThread* t, void* ip)
|
||||
// compile(MyThread*, Allocator*, BootContext*, object)):
|
||||
loadMemoryBarrier();
|
||||
|
||||
return treeQuery(t, methodTree(t), reinterpret_cast<intptr_t>(ip),
|
||||
methodTreeSentinal(t), compareIpToMethodBounds);
|
||||
return treeQuery(t, root(t, MethodTree), reinterpret_cast<intptr_t>(ip),
|
||||
root(t, MethodTreeSentinal), compareIpToMethodBounds);
|
||||
}
|
||||
|
||||
class MyStackWalker: public Processor::StackWalker {
|
||||
@ -2067,18 +2081,6 @@ unwind(MyThread* t)
|
||||
vmJump(ip, base, stack, t, 0, 0);
|
||||
}
|
||||
|
||||
object&
|
||||
objectPools(MyThread* t);
|
||||
|
||||
object&
|
||||
windMethod(MyThread* t);
|
||||
|
||||
object&
|
||||
rewindMethod(MyThread* t);
|
||||
|
||||
object&
|
||||
receiveMethod(MyThread* t);
|
||||
|
||||
uintptr_t
|
||||
defaultThunk(MyThread* t);
|
||||
|
||||
@ -2408,11 +2410,10 @@ longToFloat(int64_t a)
|
||||
}
|
||||
|
||||
uint64_t
|
||||
makeBlankObjectArray(MyThread* t, object loader, object class_, int32_t length)
|
||||
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
|
||||
{
|
||||
if (length >= 0) {
|
||||
return reinterpret_cast<uint64_t>
|
||||
(makeObjectArray(t, loader, class_, length));
|
||||
return reinterpret_cast<uint64_t>(makeObjectArray(t, class_, length));
|
||||
} else {
|
||||
object message = makeString(t, "%d", length);
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
@ -2595,14 +2596,14 @@ void NO_RETURN
|
||||
throwArrayIndexOutOfBounds(MyThread* t)
|
||||
{
|
||||
if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) {
|
||||
t->tracing = true;
|
||||
atomicOr(&(t->flags), Thread::TracingFlag);
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::ArrayIndexOutOfBoundsExceptionType);
|
||||
t->tracing = false;
|
||||
(t, Machine::ArrayIndexOutOfBoundsExceptionType);
|
||||
atomicAnd(&(t->flags), ~Thread::TracingFlag);
|
||||
} else {
|
||||
// not enough memory available for a new exception and stack trace
|
||||
// -- use a preallocated instance instead
|
||||
t->exception = t->m->arrayIndexOutOfBoundsException;
|
||||
t->exception = root(t, Machine::ArrayIndexOutOfBoundsException);
|
||||
}
|
||||
|
||||
unwind(t);
|
||||
@ -2658,7 +2659,7 @@ makeNew64(Thread* t, object class_)
|
||||
void
|
||||
gcIfNecessary(MyThread* t)
|
||||
{
|
||||
if (UNLIKELY(t->useBackupHeap)) {
|
||||
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
|
||||
collect(t, Heap::MinorCollection);
|
||||
}
|
||||
}
|
||||
@ -3411,9 +3412,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->trace(0, 0),
|
||||
BytesPerWord,
|
||||
Compiler::ObjectType,
|
||||
4, c->register_(t->arch->thread()),
|
||||
frame->append(classLoader(t, methodClass(t, context->method))),
|
||||
frame->append(class_), length));
|
||||
3, c->register_(t->arch->thread()), frame->append(class_), length));
|
||||
} break;
|
||||
|
||||
case areturn: {
|
||||
@ -4374,16 +4373,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
|
||||
if (singletonIsObject(t, pool, index - 1)) {
|
||||
object v = singletonObject(t, pool, index - 1);
|
||||
if (objectClass(t, v)
|
||||
== arrayBody(t, t->m->types, Machine::ReferenceType))
|
||||
{
|
||||
if (objectClass(t, v) == type(t, Machine::ReferenceType)) {
|
||||
object class_ = resolveClassInPool(t, context->method, index - 1);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
frame->pushObject(frame->append(getJClass(t, class_)));
|
||||
} else if (objectClass(t, v)
|
||||
== arrayBody(t, t->m->types, Machine::ClassType))
|
||||
{
|
||||
} else if (objectClass(t, v) == type(t, Machine::ClassType)) {
|
||||
frame->pushObject(frame->append(getJClass(t, v)));
|
||||
} else {
|
||||
frame->pushObject(frame->append(v));
|
||||
@ -5723,8 +5718,8 @@ finish(MyThread* t, Allocator* allocator, Context* context)
|
||||
initArray(t, pool, context->objectPoolCount + 1);
|
||||
mark(t, pool, 0);
|
||||
|
||||
set(t, pool, ArrayBody, objectPools(t));
|
||||
objectPools(t) = pool;
|
||||
set(t, pool, ArrayBody, root(t, ObjectPools));
|
||||
setRoot(t, ObjectPools, pool);
|
||||
|
||||
unsigned i = 1;
|
||||
for (PoolElement* p = context->objectPool; p; p = p->next) {
|
||||
@ -6009,14 +6004,6 @@ compileMethod2(MyThread* t, void* ip)
|
||||
t->trace->targetMethod = 0;
|
||||
}
|
||||
|
||||
if (false) {
|
||||
compile(t, codeAllocator(t), 0, resolveMethod
|
||||
(t, t->m->loader,
|
||||
"org/eclipse/swt/widgets/TableItem",
|
||||
"getBounds",
|
||||
"(IIZZZZJ)Lorg/eclipse/swt/internal/win32/RECT;"));
|
||||
}
|
||||
|
||||
if (UNLIKELY(t->exception)) {
|
||||
return 0;
|
||||
} else {
|
||||
@ -6494,9 +6481,7 @@ findFrameMap(MyThread* t, void* stack, object method, int32_t offset,
|
||||
int32_t** map, unsigned* start)
|
||||
{
|
||||
object table = codePool(t, methodCode(t, method));
|
||||
if (objectClass(t, table)
|
||||
== arrayBody(t, t->m->types, Machine::IntArrayType))
|
||||
{
|
||||
if (objectClass(t, table) == type(t, Machine::IntArrayType)) {
|
||||
findFrameMapInSimpleTable(t, method, table, offset, map, start);
|
||||
} else {
|
||||
findFrameMapInGeneralTable(t, stack, method, table, offset, map, start);
|
||||
@ -6813,16 +6798,16 @@ callContinuation(MyThread* t, object continuation, object result,
|
||||
nextContinuation = continuationContextContinuation(t, rewindContext);
|
||||
action = Rewind;
|
||||
|
||||
if (rewindMethod(t) == 0) {
|
||||
if (root(t, RewindMethod) == 0) {
|
||||
PROTECT(t, nextContinuation);
|
||||
|
||||
object method = resolveMethod
|
||||
(t, t->m->loader, "avian/Continuations", "rewind",
|
||||
(t, root(t, Machine::BootLoader), "avian/Continuations", "rewind",
|
||||
"(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;"
|
||||
"Ljava/lang/Throwable;)V");
|
||||
|
||||
if (method) {
|
||||
rewindMethod(t) = method;
|
||||
setRoot(t, RewindMethod, method);
|
||||
|
||||
compile(t, local::codeAllocator(t), 0, method);
|
||||
|
||||
@ -6864,7 +6849,7 @@ callContinuation(MyThread* t, object continuation, object result,
|
||||
transition(t, 0, 0, 0, nextContinuation, t->trace);
|
||||
|
||||
jumpAndInvoke
|
||||
(t, rewindMethod(t), base, stack,
|
||||
(t, root(t, RewindMethod), base, stack,
|
||||
continuationContextBefore(t, continuationContext(t, nextContinuation)),
|
||||
continuation, result, exception);
|
||||
} break;
|
||||
@ -6890,26 +6875,27 @@ callWithCurrentContinuation(MyThread* t, object receiver)
|
||||
|
||||
{ PROTECT(t, receiver);
|
||||
|
||||
if (receiveMethod(t) == 0) {
|
||||
if (root(t, ReceiveMethod) == 0) {
|
||||
object m = resolveMethod
|
||||
(t, t->m->loader, "avian/CallbackReceiver", "receive",
|
||||
(t, root(t, Machine::BootLoader), "avian/CallbackReceiver", "receive",
|
||||
"(Lavian/Callback;)Ljava/lang/Object;");
|
||||
|
||||
if (m) {
|
||||
receiveMethod(t) = m;
|
||||
setRoot(t, ReceiveMethod, m);
|
||||
|
||||
object continuationClass = arrayBody
|
||||
(t, t->m->types, Machine::ContinuationType);
|
||||
object continuationClass = type(t, Machine::ContinuationType);
|
||||
|
||||
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
|
||||
resolveSystemClass(t, vm::className(t, continuationClass));
|
||||
resolveSystemClass
|
||||
(t, root(t, Machine::BootLoader),
|
||||
vm::className(t, continuationClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
method = findInterfaceMethod
|
||||
(t, receiveMethod(t), objectClass(t, receiver));
|
||||
(t, root(t, ReceiveMethod), objectClass(t, receiver));
|
||||
PROTECT(t, method);
|
||||
|
||||
compile(t, local::codeAllocator(t), 0, method);
|
||||
@ -6938,14 +6924,14 @@ dynamicWind(MyThread* t, object before, object thunk, object after)
|
||||
PROTECT(t, thunk);
|
||||
PROTECT(t, after);
|
||||
|
||||
if (windMethod(t) == 0) {
|
||||
if (root(t, WindMethod) == 0) {
|
||||
object method = resolveMethod
|
||||
(t, t->m->loader, "avian/Continuations", "wind",
|
||||
(t, root(t, Machine::BootLoader), "avian/Continuations", "wind",
|
||||
"(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;"
|
||||
"Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;");
|
||||
|
||||
if (method) {
|
||||
windMethod(t) = method;
|
||||
setRoot(t, WindMethod, method);
|
||||
compile(t, local::codeAllocator(t), 0, method);
|
||||
}
|
||||
}
|
||||
@ -6962,7 +6948,7 @@ dynamicWind(MyThread* t, object before, object thunk, object after)
|
||||
}
|
||||
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
jumpAndInvoke(t, windMethod(t), base, stack, before, thunk, after);
|
||||
jumpAndInvoke(t, root(t, WindMethod), base, stack, before, thunk, after);
|
||||
} else {
|
||||
unwind(t);
|
||||
}
|
||||
@ -7117,7 +7103,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||
}
|
||||
|
||||
if (t->exception) {
|
||||
if (UNLIKELY(t->useBackupHeap)) {
|
||||
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
|
||||
collect(t, Heap::MinorCollection);
|
||||
}
|
||||
return 0;
|
||||
@ -7173,14 +7159,14 @@ class SegFaultHandler: public System::SignalHandler {
|
||||
*base, t->continuation, t->trace);
|
||||
|
||||
if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) {
|
||||
t->tracing = true;
|
||||
atomicOr(&(t->flags), Thread::TracingFlag);
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::NullPointerExceptionType);
|
||||
t->tracing = false;
|
||||
atomicAnd(&(t->flags), ~Thread::TracingFlag);
|
||||
} else {
|
||||
// not enough memory available for a new NPE and stack trace
|
||||
// -- use a preallocated instance instead
|
||||
t->exception = t->m->nullPointerException;
|
||||
t->exception = root(t, Machine::NullPointerException);
|
||||
}
|
||||
|
||||
// printTrace(t, t->exception);
|
||||
@ -7220,12 +7206,12 @@ boot(MyThread* t, BootImage* image);
|
||||
|
||||
class MyProcessor;
|
||||
|
||||
void
|
||||
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p);
|
||||
|
||||
MyProcessor*
|
||||
processor(MyThread* t);
|
||||
|
||||
void
|
||||
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p);
|
||||
|
||||
class MyProcessor: public Processor {
|
||||
public:
|
||||
class Thunk {
|
||||
@ -7255,15 +7241,7 @@ class MyProcessor: public Processor {
|
||||
MyProcessor(System* s, Allocator* allocator, bool useNativeFeatures):
|
||||
s(s),
|
||||
allocator(allocator),
|
||||
callTable(0),
|
||||
methodTree(0),
|
||||
methodTreeSentinal(0),
|
||||
objectPools(0),
|
||||
staticTableArray(0),
|
||||
virtualThunks(0),
|
||||
receiveMethod(0),
|
||||
windMethod(0),
|
||||
rewindMethod(0),
|
||||
roots(0),
|
||||
bootImage(0),
|
||||
codeAllocator(s, 0, 0),
|
||||
callTableSize(0),
|
||||
@ -7365,15 +7343,7 @@ class MyProcessor: public Processor {
|
||||
MyThread* t = static_cast<MyThread*>(vmt);
|
||||
|
||||
if (t == t->m->rootThread) {
|
||||
v->visit(&callTable);
|
||||
v->visit(&methodTree);
|
||||
v->visit(&methodTreeSentinal);
|
||||
v->visit(&objectPools);
|
||||
v->visit(&staticTableArray);
|
||||
v->visit(&virtualThunks);
|
||||
v->visit(&receiveMethod);
|
||||
v->visit(&windMethod);
|
||||
v->visit(&rewindMethod);
|
||||
v->visit(&roots);
|
||||
}
|
||||
|
||||
for (MyThread::CallTrace* trace = t->trace; trace; trace = trace->next) {
|
||||
@ -7499,16 +7469,6 @@ class MyProcessor: public Processor {
|
||||
|
||||
PROTECT(t, method);
|
||||
|
||||
if (false) {
|
||||
compile(static_cast<MyThread*>(t),
|
||||
local::codeAllocator(static_cast<MyThread*>(t)), 0,
|
||||
resolveMethod(t, t->m->loader,
|
||||
"com/ecovate/nat/logic/Cache",
|
||||
"findInCache",
|
||||
"(Ljava/lang/String;Ljava/lang/String;JZ)Lcom/ecovate/shared/xmlrpc/Resource;"));
|
||||
trap();
|
||||
}
|
||||
|
||||
compile(static_cast<MyThread*>(t),
|
||||
local::codeAllocator(static_cast<MyThread*>(t)), 0, method);
|
||||
|
||||
@ -7636,9 +7596,9 @@ class MyProcessor: public Processor {
|
||||
}
|
||||
|
||||
if (ensure(t, traceSize(target))) {
|
||||
t->tracing = true;
|
||||
atomicOr(&(t->flags), Thread::TracingFlag);
|
||||
trace = makeTrace(t, target);
|
||||
t->tracing = false;
|
||||
atomicAnd(&(t->flags), ~Thread::TracingFlag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7650,7 +7610,7 @@ class MyProcessor: public Processor {
|
||||
|
||||
t->m->system->visit(t->systemThread, target->systemThread, &visitor);
|
||||
|
||||
if (UNLIKELY(t->useBackupHeap)) {
|
||||
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
|
||||
PROTECT(t, visitor.trace);
|
||||
|
||||
collect(t, Heap::MinorCollection);
|
||||
@ -7679,10 +7639,10 @@ class MyProcessor: public Processor {
|
||||
*addresses = bootContext.addresses;
|
||||
}
|
||||
|
||||
virtual void visitRoots(HeapWalker* w) {
|
||||
bootImage->methodTree = w->visitRoot(methodTree);
|
||||
bootImage->methodTreeSentinal = w->visitRoot(methodTreeSentinal);
|
||||
bootImage->virtualThunks = w->visitRoot(virtualThunks);
|
||||
virtual void visitRoots(Thread* t, HeapWalker* w) {
|
||||
bootImage->methodTree = w->visitRoot(root(t, MethodTree));
|
||||
bootImage->methodTreeSentinal = w->visitRoot(root(t, MethodTreeSentinal));
|
||||
bootImage->virtualThunks = w->visitRoot(root(t, VirtualThunks));
|
||||
}
|
||||
|
||||
virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) {
|
||||
@ -7693,8 +7653,10 @@ class MyProcessor: public Processor {
|
||||
(t->m->heap->allocate(callTableSize * sizeof(unsigned) * 2));
|
||||
|
||||
unsigned index = 0;
|
||||
for (unsigned i = 0; i < arrayLength(t, callTable); ++i) {
|
||||
for (object p = arrayBody(t, callTable, i); p; p = callNodeNext(t, p)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, root(t, CallTable)); ++i) {
|
||||
for (object p = arrayBody(t, root(t, CallTable), i);
|
||||
p; p = callNodeNext(t, p))
|
||||
{
|
||||
table[index++] = callNodeAddress(t, p)
|
||||
- reinterpret_cast<uintptr_t>(codeAllocator.base);
|
||||
table[index++] = w->map()->find(callNodeTarget(t, p))
|
||||
@ -7712,14 +7674,19 @@ class MyProcessor: public Processor {
|
||||
codeAllocator.capacity = ExecutableAreaSizeInBytes;
|
||||
}
|
||||
|
||||
roots = makeArray(t, RootCount);
|
||||
|
||||
if (image) {
|
||||
local::boot(static_cast<MyThread*>(t), image);
|
||||
} else {
|
||||
callTable = makeArray(t, 128);
|
||||
|
||||
methodTree = methodTreeSentinal = makeTreeNode(t, 0, 0, 0);
|
||||
set(t, methodTree, TreeNodeLeft, methodTreeSentinal);
|
||||
set(t, methodTree, TreeNodeRight, methodTreeSentinal);
|
||||
setRoot(t, CallTable, makeArray(t, 128));
|
||||
|
||||
setRoot(t, MethodTreeSentinal, makeTreeNode(t, 0, 0, 0));
|
||||
setRoot(t, MethodTree, root(t, MethodTreeSentinal));
|
||||
set(t, root(t, MethodTree), TreeNodeLeft,
|
||||
root(t, MethodTreeSentinal));
|
||||
set(t, root(t, MethodTree), TreeNodeRight,
|
||||
root(t, MethodTreeSentinal));
|
||||
}
|
||||
|
||||
local::compileThunks(static_cast<MyThread*>(t), &codeAllocator, this);
|
||||
@ -7776,43 +7743,10 @@ class MyProcessor: public Processor {
|
||||
abort(t);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void registerNative(Thread* t, object method, void* function) {
|
||||
PROTECT(t, method);
|
||||
|
||||
expect(t, methodFlags(t, method) & ACC_NATIVE);
|
||||
|
||||
object native = makeNative(t, function, false);
|
||||
|
||||
// ensure other threads only see the methodCode field populated
|
||||
// once the object it points do has been populated:
|
||||
storeStoreMemoryBarrier();
|
||||
|
||||
set(t, method, MethodCode, native);
|
||||
}
|
||||
|
||||
virtual void unregisterNatives(Thread* t, object c) {
|
||||
if (classMethodTable(t, c)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||
object method = arrayBody(t, classMethodTable(t, c), i);
|
||||
if (methodFlags(t, method) & ACC_NATIVE) {
|
||||
set(t, method, MethodCode, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
object callTable;
|
||||
object methodTree;
|
||||
object methodTreeSentinal;
|
||||
object objectPools;
|
||||
object staticTableArray;
|
||||
object virtualThunks;
|
||||
object receiveMethod;
|
||||
object windMethod;
|
||||
object rewindMethod;
|
||||
object roots;
|
||||
BootImage* bootImage;
|
||||
SegFaultHandler segFaultHandler;
|
||||
FixedAllocator codeAllocator;
|
||||
@ -7883,11 +7817,10 @@ isThunkUnsafeStack(MyProcessor::ThunkCollection* thunks, void* ip)
|
||||
bool
|
||||
isVirtualThunk(MyThread* t, void* ip)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
|
||||
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) {
|
||||
uintptr_t start = wordArrayBody(t, p->virtualThunks, i);
|
||||
uintptr_t end = start + wordArrayBody(t, p->virtualThunks, i + 1);
|
||||
for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks)); i += 2)
|
||||
{
|
||||
uintptr_t start = wordArrayBody(t, root(t, VirtualThunks), i);
|
||||
uintptr_t end = start + wordArrayBody(t, root(t, VirtualThunks), i + 1);
|
||||
|
||||
if (reinterpret_cast<uintptr_t>(ip) >= start
|
||||
and reinterpret_cast<uintptr_t>(ip) < end)
|
||||
@ -7921,8 +7854,7 @@ findCallNode(MyThread* t, void* address)
|
||||
// compile(MyThread*, Allocator*, BootContext*, object)):
|
||||
loadMemoryBarrier();
|
||||
|
||||
MyProcessor* p = processor(t);
|
||||
object table = p->callTable;
|
||||
object table = root(t, CallTable);
|
||||
|
||||
intptr_t key = reinterpret_cast<intptr_t>(address);
|
||||
unsigned index = static_cast<uintptr_t>(key) & (arrayLength(t, table) - 1);
|
||||
@ -8002,8 +7934,8 @@ insertCallNode(MyThread* t, object table, unsigned* size, object node)
|
||||
void
|
||||
insertCallNode(MyThread* t, object node)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
p->callTable = insertCallNode(t, p->callTable, &(p->callTableSize), node);
|
||||
setRoot(t, CallTable, insertCallNode
|
||||
(t, root(t, CallTable), &(processor(t)->callTableSize), node));
|
||||
}
|
||||
|
||||
object
|
||||
@ -8022,14 +7954,19 @@ makeClassMap(Thread* t, unsigned* table, unsigned count, uintptr_t* heap)
|
||||
}
|
||||
|
||||
object
|
||||
makeStaticTableArray(Thread* t, unsigned* table, unsigned count,
|
||||
uintptr_t* heap)
|
||||
makeStaticTableArray(Thread* t, unsigned* bootTable, unsigned bootCount,
|
||||
unsigned* appTable, unsigned appCount, uintptr_t* heap)
|
||||
{
|
||||
object array = makeArray(t, count);
|
||||
object array = makeArray(t, bootCount + appCount);
|
||||
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
for (unsigned i = 0; i < bootCount; ++i) {
|
||||
set(t, array, ArrayBody + (i * BytesPerWord),
|
||||
classStaticTable(t, bootObject(heap, table[i])));
|
||||
classStaticTable(t, bootObject(heap, bootTable[i])));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < appCount; ++i) {
|
||||
set(t, array, ArrayBody + ((bootCount + i) * BytesPerWord),
|
||||
classStaticTable(t, bootObject(heap, appTable[i])));
|
||||
}
|
||||
|
||||
return array;
|
||||
@ -8134,9 +8071,9 @@ fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
|
||||
}
|
||||
|
||||
void
|
||||
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
|
||||
fixupMethods(Thread* t, object map, BootImage* image, uint8_t* code)
|
||||
{
|
||||
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
|
||||
for (HashMapIterator it(t, map); it.hasMore();) {
|
||||
object c = tripleSecond(t, it.next());
|
||||
|
||||
if (classMethodTable(t, c)) {
|
||||
@ -8213,12 +8150,10 @@ fixupThunks(MyThread* t, BootImage* image, uint8_t* code)
|
||||
void
|
||||
fixupVirtualThunks(MyThread* t, BootImage* image, uint8_t* code)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
|
||||
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) {
|
||||
if (wordArrayBody(t, p->virtualThunks, i)) {
|
||||
wordArrayBody(t, p->virtualThunks, i)
|
||||
= (wordArrayBody(t, p->virtualThunks, i) - image->codeBase)
|
||||
for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks)); i += 2) {
|
||||
if (wordArrayBody(t, root(t, VirtualThunks), i)) {
|
||||
wordArrayBody(t, root(t, VirtualThunks), i)
|
||||
= (wordArrayBody(t, root(t, VirtualThunks), i) - image->codeBase)
|
||||
+ reinterpret_cast<uintptr_t>(code);
|
||||
}
|
||||
}
|
||||
@ -8229,8 +8164,9 @@ boot(MyThread* t, BootImage* image)
|
||||
{
|
||||
assert(t, image->magic == BootImage::Magic);
|
||||
|
||||
unsigned* classTable = reinterpret_cast<unsigned*>(image + 1);
|
||||
unsigned* stringTable = classTable + image->classCount;
|
||||
unsigned* bootClassTable = reinterpret_cast<unsigned*>(image + 1);
|
||||
unsigned* appClassTable = bootClassTable + image->bootClassCount;
|
||||
unsigned* stringTable = appClassTable + image->appClassCount;
|
||||
unsigned* callTable = stringTable + image->stringCount;
|
||||
|
||||
uintptr_t* heapMap = reinterpret_cast<uintptr_t*>
|
||||
@ -8254,39 +8190,48 @@ boot(MyThread* t, BootImage* image)
|
||||
|
||||
t->m->heap->setImmortalHeap(heap, image->heapSize / BytesPerWord);
|
||||
|
||||
t->m->loader = bootObject(heap, image->loader);
|
||||
setRoot(t, Machine::BootLoader, bootObject(heap, image->bootLoader));
|
||||
setRoot(t, Machine::AppLoader, bootObject(heap, image->appLoader));
|
||||
t->m->types = bootObject(heap, image->types);
|
||||
|
||||
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
|
||||
|
||||
p->methodTree = bootObject(heap, image->methodTree);
|
||||
p->methodTreeSentinal = bootObject(heap, image->methodTreeSentinal);
|
||||
setRoot(t, MethodTree, bootObject(heap, image->methodTree));
|
||||
setRoot(t, MethodTreeSentinal, bootObject(heap, image->methodTreeSentinal));
|
||||
|
||||
p->virtualThunks = bootObject(heap, image->virtualThunks);
|
||||
setRoot(t, VirtualThunks, bootObject(heap, image->virtualThunks));
|
||||
|
||||
fixupCode(t, codeMap, codeMapSizeInWords, code, heap);
|
||||
|
||||
syncInstructionCache(code, image->codeSize);
|
||||
|
||||
t->m->classMap = makeClassMap(t, classTable, image->classCount, heap);
|
||||
setRoot(t, Machine::ClassMap, makeClassMap
|
||||
(t, bootClassTable, image->bootClassCount, heap));
|
||||
|
||||
t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap);
|
||||
set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap
|
||||
(t, appClassTable, image->appClassCount, heap));
|
||||
|
||||
setRoot(t, Machine::StringMap, makeStringMap
|
||||
(t, stringTable, image->stringCount, heap));
|
||||
|
||||
p->callTableSize = image->callCount;
|
||||
p->callTable = makeCallTable
|
||||
(t, heap, callTable, image->callCount,
|
||||
reinterpret_cast<uintptr_t>(code));
|
||||
|
||||
p->staticTableArray = makeStaticTableArray
|
||||
(t, classTable, image->classCount, heap);
|
||||
setRoot(t, CallTable, makeCallTable
|
||||
(t, heap, callTable, image->callCount,
|
||||
reinterpret_cast<uintptr_t>(code)));
|
||||
|
||||
setRoot(t, StaticTableArray, makeStaticTableArray
|
||||
(t, bootClassTable, image->bootClassCount,
|
||||
appClassTable, image->appClassCount, heap));
|
||||
|
||||
fixupThunks(t, image, code);
|
||||
|
||||
fixupVirtualThunks(t, image, code);
|
||||
|
||||
fixupMethods(t, image, code);
|
||||
fixupMethods(t, root(t, Machine::ClassMap), image, code);
|
||||
fixupMethods(t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code);
|
||||
|
||||
t->m->bootstrapClassMap = makeHashMap(t, 0, 0);
|
||||
setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0));
|
||||
}
|
||||
|
||||
intptr_t
|
||||
@ -8539,30 +8484,6 @@ processor(MyThread* t)
|
||||
return static_cast<MyProcessor*>(t->m->processor);
|
||||
}
|
||||
|
||||
object&
|
||||
objectPools(MyThread* t)
|
||||
{
|
||||
return processor(t)->objectPools;
|
||||
}
|
||||
|
||||
object&
|
||||
windMethod(MyThread* t)
|
||||
{
|
||||
return processor(t)->windMethod;
|
||||
}
|
||||
|
||||
object&
|
||||
rewindMethod(MyThread* t)
|
||||
{
|
||||
return processor(t)->rewindMethod;
|
||||
}
|
||||
|
||||
object&
|
||||
receiveMethod(MyThread* t)
|
||||
{
|
||||
return processor(t)->receiveMethod;
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
defaultThunk(MyThread* t)
|
||||
{
|
||||
@ -8639,32 +8560,30 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size)
|
||||
uintptr_t
|
||||
virtualThunk(MyThread* t, unsigned index)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
|
||||
if (p->virtualThunks == 0
|
||||
or wordArrayLength(t, p->virtualThunks) <= index * 2)
|
||||
if (root(t, VirtualThunks) == 0
|
||||
or wordArrayLength(t, root(t, VirtualThunks)) <= index * 2)
|
||||
{
|
||||
object newArray = makeWordArray(t, nextPowerOfTwo((index + 1) * 2));
|
||||
if (p->virtualThunks) {
|
||||
if (root(t, VirtualThunks)) {
|
||||
memcpy(&wordArrayBody(t, newArray, 0),
|
||||
&wordArrayBody(t, p->virtualThunks, 0),
|
||||
wordArrayLength(t, p->virtualThunks) * BytesPerWord);
|
||||
&wordArrayBody(t, root(t, VirtualThunks), 0),
|
||||
wordArrayLength(t, root(t, VirtualThunks)) * BytesPerWord);
|
||||
}
|
||||
p->virtualThunks = newArray;
|
||||
setRoot(t, VirtualThunks, newArray);
|
||||
}
|
||||
|
||||
if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) {
|
||||
if (wordArrayBody(t, root(t, VirtualThunks), index * 2) == 0) {
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) {
|
||||
if (wordArrayBody(t, root(t, VirtualThunks), index * 2) == 0) {
|
||||
unsigned size;
|
||||
uintptr_t thunk = compileVirtualThunk(t, index, &size);
|
||||
wordArrayBody(t, p->virtualThunks, index * 2) = thunk;
|
||||
wordArrayBody(t, p->virtualThunks, (index * 2) + 1) = size;
|
||||
wordArrayBody(t, root(t, VirtualThunks), index * 2) = thunk;
|
||||
wordArrayBody(t, root(t, VirtualThunks), (index * 2) + 1) = size;
|
||||
}
|
||||
}
|
||||
|
||||
return wordArrayBody(t, p->virtualThunks, index * 2);
|
||||
return wordArrayBody(t, root(t, VirtualThunks), index * 2);
|
||||
}
|
||||
|
||||
void
|
||||
@ -8717,10 +8636,12 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
|
||||
methodCode(t, method),
|
||||
reinterpret_cast<intptr_t>(compiled));
|
||||
|
||||
methodTree(t) = treeInsert
|
||||
(t, &(context.zone), methodTree(t),
|
||||
reinterpret_cast<intptr_t>(compiled), clone, methodTreeSentinal(t),
|
||||
compareIpToMethodBounds);
|
||||
setRoot
|
||||
(t, MethodTree, treeInsert
|
||||
(t, &(context.zone), root(t, MethodTree),
|
||||
reinterpret_cast<intptr_t>(compiled), clone,
|
||||
root(t, MethodTreeSentinal),
|
||||
compareIpToMethodBounds));
|
||||
|
||||
storeStoreMemoryBarrier();
|
||||
|
||||
@ -8731,22 +8652,23 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
|
||||
= compiled;
|
||||
}
|
||||
|
||||
treeUpdate(t, methodTree(t), reinterpret_cast<intptr_t>(compiled),
|
||||
method, methodTreeSentinal(t), compareIpToMethodBounds);
|
||||
treeUpdate(t, root(t, MethodTree), reinterpret_cast<intptr_t>(compiled),
|
||||
method, root(t, MethodTreeSentinal), compareIpToMethodBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object&
|
||||
methodTree(MyThread* t)
|
||||
root(Thread* t, Root root)
|
||||
{
|
||||
return processor(t)->methodTree;
|
||||
return arrayBody(t, processor(static_cast<MyThread*>(t))->roots, root);
|
||||
}
|
||||
|
||||
object
|
||||
methodTreeSentinal(MyThread* t)
|
||||
void
|
||||
setRoot(Thread* t, Root root, object value)
|
||||
{
|
||||
return processor(t)->methodTreeSentinal;
|
||||
set(t, processor(static_cast<MyThread*>(t))->roots,
|
||||
ArrayBody + (root * BytesPerWord), value);
|
||||
}
|
||||
|
||||
FixedAllocator*
|
||||
|
@ -10,11 +10,11 @@
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#define THREAD_CONTINUATION 2232
|
||||
#define THREAD_CONTINUATION 2224
|
||||
#define THREAD_EXCEPTION 80
|
||||
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2240
|
||||
#define THREAD_EXCEPTION_OFFSET 2248
|
||||
#define THREAD_EXCEPTION_HANDLER 2256
|
||||
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2232
|
||||
#define THREAD_EXCEPTION_OFFSET 2240
|
||||
#define THREAD_EXCEPTION_HANDLER 2248
|
||||
|
||||
#define CONTINUATION_NEXT 8
|
||||
#define CONTINUATION_ADDRESS 32
|
||||
|
505
src/gnu.cpp
505
src/gnu.cpp
@ -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;
|
||||
}
|
@ -76,8 +76,7 @@ dumpHeap(Thread* t, FILE* out)
|
||||
local::write1(out, local::Size);
|
||||
local::write4(out, local::objectSize(t, p));
|
||||
|
||||
if (objectClass(t, p) == arrayBody(t, t->m->types, Machine::ClassType))
|
||||
{
|
||||
if (objectClass(t, p) == type(t, Machine::ClassType)) {
|
||||
object name = className(t, p);
|
||||
if (name) {
|
||||
local::write1(out, local::ClassName);
|
||||
|
@ -429,80 +429,17 @@ class MyStackWalker: public Processor::StackWalker {
|
||||
int frame;
|
||||
};
|
||||
|
||||
object
|
||||
makeNativeMethodData(Thread* t, object method, void* function)
|
||||
{
|
||||
PROTECT(t, method);
|
||||
|
||||
unsigned count = methodParameterCount(t, method) + 2;
|
||||
|
||||
object data = makeNativeMethodData(t,
|
||||
function,
|
||||
0, // argument table size
|
||||
count);
|
||||
|
||||
unsigned argumentTableSize = BytesPerWord * 2;
|
||||
unsigned index = 0;
|
||||
|
||||
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
|
||||
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
|
||||
|
||||
const char* s = reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||
++ s; // skip '('
|
||||
while (*s and *s != ')') {
|
||||
unsigned code = fieldCode(t, *s);
|
||||
nativeMethodDataParameterTypes(t, data, index++) = fieldType(t, code);
|
||||
|
||||
switch (*s) {
|
||||
case 'L':
|
||||
argumentTableSize += BytesPerWord;
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
argumentTableSize += BytesPerWord;
|
||||
while (*s == '[') ++ s;
|
||||
switch (*s) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ s;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
argumentTableSize += pad(primitiveSize(t, code));
|
||||
++ s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nativeMethodDataArgumentTableSize(t, data) = argumentTableSize;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void
|
||||
resolveNativeMethodData(Thread* t, object method)
|
||||
resolveNative(Thread* t, object method)
|
||||
{
|
||||
if (methodCode(t, method) == 0) {
|
||||
void* p = resolveNativeMethod(t, method);
|
||||
if (LIKELY(p)) {
|
||||
PROTECT(t, method);
|
||||
object data = makeNativeMethodData(t, method, p);
|
||||
|
||||
// ensure other threads see updated methodVmFlags before
|
||||
// methodCode, and that the native method data is initialized
|
||||
// before it is visible to those threads:
|
||||
object native = resolveNativeMethod(t, method);
|
||||
if (LIKELY(native)) {
|
||||
// ensure other threads only see the methodCode field populated
|
||||
// once the object it points do has been populated:
|
||||
storeStoreMemoryBarrier();
|
||||
|
||||
set(t, method, MethodCode, data);
|
||||
set(t, method, MethodCode, native);
|
||||
} else {
|
||||
object message = makeString
|
||||
(t, "%s.%s%s",
|
||||
@ -600,27 +537,35 @@ pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect)
|
||||
}
|
||||
|
||||
void
|
||||
marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
|
||||
object data, bool indirect)
|
||||
marshalArguments(Thread* t, uintptr_t* args, uint8_t* types, unsigned sp,
|
||||
object method, bool indirect)
|
||||
{
|
||||
unsigned offset = 0;
|
||||
unsigned sp = frameBase(t, t->frame);
|
||||
for (; i < count; ++i) {
|
||||
unsigned type = nativeMethodDataParameterTypes(t, data, i + 1);
|
||||
MethodSpecIterator it
|
||||
(t, reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, methodSpec(t, method), 0)));
|
||||
|
||||
unsigned argOffset = 0;
|
||||
unsigned typeOffset = 0;
|
||||
|
||||
while (it.hasNext()) {
|
||||
unsigned type = fieldType(t, fieldCode(t, *it.next()));
|
||||
if (types) {
|
||||
types[typeOffset++] = type;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case INT8_TYPE:
|
||||
case INT16_TYPE:
|
||||
case INT32_TYPE:
|
||||
case FLOAT_TYPE:
|
||||
args[offset++] = peekInt(t, sp++);
|
||||
args[argOffset++] = peekInt(t, sp++);
|
||||
break;
|
||||
|
||||
case DOUBLE_TYPE:
|
||||
case INT64_TYPE: {
|
||||
uint64_t v = peekLong(t, sp);
|
||||
memcpy(args + offset, &v, 8);
|
||||
offset += (8 / BytesPerWord);
|
||||
memcpy(args + argOffset, &v, 8);
|
||||
argOffset += (8 / BytesPerWord);
|
||||
sp += 2;
|
||||
} break;
|
||||
|
||||
@ -630,9 +575,9 @@ marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
|
||||
if (*v == 0) {
|
||||
v = 0;
|
||||
}
|
||||
args[offset++] = reinterpret_cast<uintptr_t>(v);
|
||||
args[argOffset++] = reinterpret_cast<uintptr_t>(v);
|
||||
} else {
|
||||
args[offset++] = reinterpret_cast<uintptr_t>(peekObject(t, sp++));
|
||||
args[argOffset++] = reinterpret_cast<uintptr_t>(peekObject(t, sp++));
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -642,39 +587,51 @@ marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
|
||||
}
|
||||
|
||||
unsigned
|
||||
invokeNativeSlow(Thread* t, object method)
|
||||
invokeNativeSlow(Thread* t, object method, void* function)
|
||||
{
|
||||
PROTECT(t, method);
|
||||
|
||||
object data = methodCode(t, method);
|
||||
PROTECT(t, data);
|
||||
|
||||
pushFrame(t, method);
|
||||
|
||||
unsigned count = nativeMethodDataLength(t, data) - 1;
|
||||
|
||||
unsigned size = nativeMethodDataArgumentTableSize(t, data);
|
||||
uintptr_t args[size / BytesPerWord];
|
||||
unsigned offset = 0;
|
||||
|
||||
args[offset++] = reinterpret_cast<uintptr_t>(t);
|
||||
|
||||
unsigned i = 0;
|
||||
unsigned footprint = methodParameterFootprint(t, method) + 1;
|
||||
if (methodFlags(t, method) & ACC_STATIC) {
|
||||
++ i;
|
||||
args[offset++] = reinterpret_cast<uintptr_t>
|
||||
(pushReference(t, methodClass(t, method)));
|
||||
++ footprint;
|
||||
}
|
||||
unsigned count = methodParameterCount(t, method) + 2;
|
||||
|
||||
marshalArguments(t, args + offset, i, count, data, true);
|
||||
RUNTIME_ARRAY(uintptr_t, args, footprint);
|
||||
unsigned argOffset = 0;
|
||||
RUNTIME_ARRAY(uint8_t, types, count);
|
||||
unsigned typeOffset = 0;
|
||||
|
||||
RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast<uintptr_t>(t);
|
||||
RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE;
|
||||
|
||||
object jclass = 0;
|
||||
PROTECT(t, jclass);
|
||||
|
||||
unsigned sp;
|
||||
if (methodFlags(t, method) & ACC_STATIC) {
|
||||
sp = frameBase(t, t->frame);
|
||||
jclass = getJClass(t, methodClass(t, method));
|
||||
RUNTIME_ARRAY_BODY(args)[argOffset++]
|
||||
= reinterpret_cast<uintptr_t>(&jclass);
|
||||
} else {
|
||||
sp = frameBase(t, t->frame);
|
||||
object* v = reinterpret_cast<object*>(t->stack + ((sp++) * 2) + 1);
|
||||
if (*v == 0) {
|
||||
v = 0;
|
||||
}
|
||||
RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast<uintptr_t>(v);
|
||||
}
|
||||
RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE;
|
||||
|
||||
marshalArguments
|
||||
(t, RUNTIME_ARRAY_BODY(args) + argOffset,
|
||||
RUNTIME_ARRAY_BODY(types) + typeOffset, sp, method, true);
|
||||
|
||||
unsigned returnCode = methodReturnCode(t, method);
|
||||
unsigned returnType = fieldType(t, returnCode);
|
||||
void* function = nativeMethodDataFunction(t, data);
|
||||
uint8_t types[nativeMethodDataLength(t, data)];
|
||||
memcpy(&types,
|
||||
&nativeMethodDataParameterTypes(t, data, 0),
|
||||
nativeMethodDataLength(t, data));
|
||||
uint64_t result;
|
||||
|
||||
if (DebugRun) {
|
||||
@ -682,25 +639,15 @@ invokeNativeSlow(Thread* t, object method)
|
||||
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
||||
&byteArrayBody(t, methodName(t, method), 0));
|
||||
}
|
||||
|
||||
// if (strcmp(reinterpret_cast<const char*>
|
||||
// (&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
|
||||
// "org/eclipse/swt/internal/C") == 0
|
||||
// and strcmp(reinterpret_cast<const char*>
|
||||
// (&byteArrayBody(t, methodName(t, method), 0)),
|
||||
// "memmove") == 0)
|
||||
// {
|
||||
// asm("int3");
|
||||
// }
|
||||
|
||||
|
||||
{ ENTER(t, Thread::IdleState);
|
||||
|
||||
result = t->m->system->call
|
||||
(function,
|
||||
args,
|
||||
types,
|
||||
count + 1,
|
||||
size,
|
||||
RUNTIME_ARRAY_BODY(args),
|
||||
RUNTIME_ARRAY_BODY(types),
|
||||
count,
|
||||
footprint * BytesPerWord,
|
||||
returnType);
|
||||
}
|
||||
|
||||
@ -728,24 +675,32 @@ invokeNative(Thread* t, object method)
|
||||
{
|
||||
PROTECT(t, method);
|
||||
|
||||
resolveNativeMethodData(t, method);
|
||||
resolveNative(t, method);
|
||||
|
||||
if (UNLIKELY(t->exception)) {
|
||||
return VoidField;
|
||||
}
|
||||
|
||||
if (methodVmFlags(t, method) & FastNative) {
|
||||
object native = methodCode(t, method);
|
||||
if (nativeFast(t, native)) {
|
||||
pushFrame(t, method);
|
||||
|
||||
object data = methodCode(t, method);
|
||||
uintptr_t arguments[methodParameterFootprint(t, method)];
|
||||
unsigned footprint = methodParameterFootprint(t, method) + 1;
|
||||
RUNTIME_ARRAY(uintptr_t, args, footprint);
|
||||
unsigned sp = frameBase(t, t->frame);
|
||||
unsigned argOffset = 0;
|
||||
if (methodFlags(t, method) & ACC_STATIC) {
|
||||
++ footprint;
|
||||
} else {
|
||||
RUNTIME_ARRAY_BODY(args)[argOffset++]
|
||||
= reinterpret_cast<uintptr_t>(peekObject(t, sp++));
|
||||
}
|
||||
|
||||
marshalArguments
|
||||
(t, arguments, (methodFlags(t, method) & ACC_STATIC) ? 1 : 0,
|
||||
nativeMethodDataLength(t, data) - 1, data, false);
|
||||
(t, RUNTIME_ARRAY_BODY(args) + argOffset, 0, sp, method, false);
|
||||
|
||||
uint64_t result = reinterpret_cast<FastNativeFunction>
|
||||
(nativeMethodDataFunction(t, methodCode(t, method)))
|
||||
(t, method, arguments);
|
||||
(nativeFunction(t, native))(t, method, RUNTIME_ARRAY_BODY(args));
|
||||
|
||||
popFrame(t);
|
||||
|
||||
@ -757,7 +712,7 @@ invokeNative(Thread* t, object method)
|
||||
|
||||
return methodReturnCode(t, method);
|
||||
} else {
|
||||
return invokeNativeSlow(t, method);
|
||||
return invokeNativeSlow(t, method, nativeFunction(t, native));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1004,9 +959,7 @@ interpret(Thread* t)
|
||||
object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
|
||||
pushObject(t, makeObjectArray
|
||||
(t, classLoader(t, methodClass(t, frameMethod(t, frame))),
|
||||
class_, count));
|
||||
pushObject(t, makeObjectArray(t, class_, count));
|
||||
} else {
|
||||
object message = makeString(t, "%d", count);
|
||||
exception = t->m->classpath->makeThrowable
|
||||
@ -1070,9 +1023,7 @@ interpret(Thread* t)
|
||||
object array = popObject(t);
|
||||
|
||||
if (LIKELY(array)) {
|
||||
if (objectClass(t, array)
|
||||
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
|
||||
{
|
||||
if (objectClass(t, array) == type(t, Machine::BooleanArrayType)) {
|
||||
if (LIKELY(index >= 0 and
|
||||
static_cast<uintptr_t>(index)
|
||||
< booleanArrayLength(t, array)))
|
||||
@ -1113,9 +1064,7 @@ interpret(Thread* t)
|
||||
object array = popObject(t);
|
||||
|
||||
if (LIKELY(array)) {
|
||||
if (objectClass(t, array)
|
||||
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
|
||||
{
|
||||
if (objectClass(t, array) == type(t, Machine::BooleanArrayType)) {
|
||||
if (LIKELY(index >= 0 and
|
||||
static_cast<uintptr_t>(index)
|
||||
< booleanArrayLength(t, array)))
|
||||
@ -2259,17 +2208,13 @@ interpret(Thread* t)
|
||||
|
||||
if (singletonIsObject(t, pool, index - 1)) {
|
||||
object v = singletonObject(t, pool, index - 1);
|
||||
if (objectClass(t, v)
|
||||
== arrayBody(t, t->m->types, Machine::ReferenceType))
|
||||
{
|
||||
if (objectClass(t, v) == type(t, Machine::ReferenceType)) {
|
||||
object class_ = resolveClassInPool
|
||||
(t, frameMethod(t, frame), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
|
||||
pushObject(t, getJClass(t, class_));
|
||||
} else if (objectClass(t, v)
|
||||
== arrayBody(t, t->m->types, Machine::ClassType))
|
||||
{
|
||||
} else if (objectClass(t, v) == type(t, Machine::ClassType)) {
|
||||
pushObject(t, getJClass(t, v));
|
||||
} else {
|
||||
pushObject(t, v);
|
||||
@ -3031,7 +2976,7 @@ invoke(Thread* t, object method)
|
||||
class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint));
|
||||
|
||||
if (classVmFlags(t, class_) & BootstrapFlag) {
|
||||
resolveClass(t, t->m->loader, className(t, class_));
|
||||
resolveClass(t, root(t, Machine::BootLoader), className(t, class_));
|
||||
}
|
||||
|
||||
if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
|
||||
@ -3333,7 +3278,7 @@ class MyProcessor: public Processor {
|
||||
abort(s);
|
||||
}
|
||||
|
||||
virtual void visitRoots(HeapWalker*) {
|
||||
virtual void visitRoots(vm::Thread*, HeapWalker*) {
|
||||
abort(s);
|
||||
}
|
||||
|
||||
|
@ -176,9 +176,7 @@ GetStringCritical(Thread* t, jstring s, jboolean* isCopy)
|
||||
}
|
||||
|
||||
object data = stringData(t, *s);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
||||
return GetStringChars(t, s, isCopy);
|
||||
} else {
|
||||
return &charArrayBody(t, data, stringOffset(t, *s));
|
||||
@ -188,9 +186,7 @@ GetStringCritical(Thread* t, jstring s, jboolean* isCopy)
|
||||
void JNICALL
|
||||
ReleaseStringCritical(Thread* t, jstring s, const jchar* chars)
|
||||
{
|
||||
if (objectClass(t, stringData(t, *s))
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, stringData(t, *s)) == type(t, Machine::ByteArrayType)) {
|
||||
ReleaseStringChars(t, s, chars);
|
||||
}
|
||||
|
||||
@ -294,7 +290,7 @@ DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer,
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object c = defineClass
|
||||
(t, loader ? *loader : t->m->loader,
|
||||
(t, loader ? *loader : root(t, Machine::BootLoader),
|
||||
reinterpret_cast<const uint8_t*>(buffer), length);
|
||||
|
||||
return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c));
|
||||
@ -308,7 +304,7 @@ FindClass(Thread* t, const char* name)
|
||||
object n = makeByteArray(t, strlen(name) + 1);
|
||||
replace('.', '/', name, &byteArrayBody(t, n, 0));
|
||||
|
||||
object c = resolveClass(t, t->m->loader, n);
|
||||
object c = resolveClass(t, root(t, Machine::AppLoader), n);
|
||||
|
||||
return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c));
|
||||
}
|
||||
@ -430,8 +426,9 @@ methodID(Thread* t, object method)
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
if (methodNativeID(t, method) == 0) {
|
||||
t->m->jniMethodTable = vectorAppend(t, t->m->jniMethodTable, method);
|
||||
methodNativeID(t, method) = vectorSize(t, t->m->jniMethodTable);
|
||||
setRoot(t, Machine::JNIMethodTable, vectorAppend
|
||||
(t, root(t, Machine::JNIMethodTable), method));
|
||||
methodNativeID(t, method) = vectorSize(t, root(t, Machine::JNIMethodTable));
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,7 +467,7 @@ GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
inline object
|
||||
getMethod(Thread* t, jmethodID m)
|
||||
{
|
||||
object method = vectorBody(t, t->m->jniMethodTable, m - 1);
|
||||
object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1);
|
||||
|
||||
assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
|
||||
|
||||
@ -733,7 +730,7 @@ CallVoidMethod(Thread* t, jobject o, jmethodID m, ...)
|
||||
inline object
|
||||
getStaticMethod(Thread* t, jmethodID m)
|
||||
{
|
||||
object method = vectorBody(t, t->m->jniMethodTable, m - 1);
|
||||
object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1);
|
||||
|
||||
assert(t, methodFlags(t, method) & ACC_STATIC);
|
||||
|
||||
@ -1342,9 +1339,7 @@ NewObjectArray(Thread* t, jsize length, jclass class_, jobject init)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object a = makeObjectArray
|
||||
(t, classLoader(t, jclassVmClass(t, *class_)), jclassVmClass(t, *class_),
|
||||
length);
|
||||
object a = makeObjectArray(t, jclassVmClass(t, *class_), length);
|
||||
object value = (init ? *init : 0);
|
||||
for (jsize i = 0; i < length; ++i) {
|
||||
set(t, a, ArrayBody + (i * BytesPerWord), value);
|
||||
@ -1934,7 +1929,7 @@ RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods,
|
||||
object method = findMethod(t, c, methods[i].name, methods[i].signature);
|
||||
if (UNLIKELY(t->exception)) return -1;
|
||||
|
||||
t->m->processor->registerNative(t, method, methods[i].function);
|
||||
registerNative(t, method, methods[i].function);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1946,7 +1941,7 @@ UnregisterNatives(Thread* t, jclass c)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
t->m->processor->unregisterNatives(t, *c);
|
||||
unregisterNatives(t, *c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2314,21 +2309,21 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
unsigned bcppl = strlen(bootClasspathPrepend);
|
||||
unsigned bcpl = strlen(bootClasspath);
|
||||
unsigned bcpal = strlen(bootClasspathAppend);
|
||||
unsigned cpl = strlen(classpath);
|
||||
|
||||
unsigned classpathBufferSize = bcppl + bcpl + bcpal + cpl + 4;
|
||||
RUNTIME_ARRAY(char, classpathBuffer, classpathBufferSize);
|
||||
char* classpathPointer = RUNTIME_ARRAY_BODY(classpathBuffer);
|
||||
|
||||
unsigned bootClasspathBufferSize = bcppl + bcpl + bcpal + 3;
|
||||
RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize);
|
||||
char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer);
|
||||
local::append
|
||||
(&classpathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR);
|
||||
local::append(&classpathPointer, bootClasspath, bcpl, PATH_SEPARATOR);
|
||||
local::append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR);
|
||||
local::append(&classpathPointer, classpath, cpl, 0);
|
||||
(&bootClasspathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR);
|
||||
local::append(&bootClasspathPointer, bootClasspath, bcpl,
|
||||
bcpal ? PATH_SEPARATOR : 0);
|
||||
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
|
||||
|
||||
System* s = makeSystem(crashDumpDirectory);
|
||||
Heap* h = makeHeap(s, heapLimit);
|
||||
Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary);
|
||||
Finder* bf = makeFinder
|
||||
(s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
||||
Finder* af = makeFinder(s, classpath, bootLibrary);
|
||||
Processor* p = makeProcessor(s, h, true);
|
||||
Classpath* c = makeClasspath(s, h);
|
||||
|
||||
@ -2342,15 +2337,9 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
}
|
||||
|
||||
*m = new (h->allocate(sizeof(Machine)))
|
||||
Machine(s, h, f, p, c, properties, propertyCount);
|
||||
Machine(s, h, bf, af, p, c, properties, propertyCount);
|
||||
|
||||
*t = p->makeThread(*m, 0, 0);
|
||||
|
||||
enter(*t, Thread::ActiveState);
|
||||
|
||||
c->boot(*t);
|
||||
|
||||
enter(*t, Thread::IdleState);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
485
src/machine.cpp
485
src/machine.cpp
@ -167,25 +167,29 @@ turnOffTheLights(Thread* t)
|
||||
|
||||
enter(t, Thread::ExitState);
|
||||
|
||||
for (object* p = &(t->m->finalizers); *p;) {
|
||||
object f = *p;
|
||||
*p = finalizerNext(t, *p);
|
||||
{ object p = 0;
|
||||
PROTECT(t, p);
|
||||
|
||||
void (*function)(Thread*, object);
|
||||
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
|
||||
if (function) {
|
||||
function(t, finalizerTarget(t, f));
|
||||
for (p = t->m->finalizers; p;) {
|
||||
object f = p;
|
||||
p = finalizerNext(t, p);
|
||||
|
||||
void (*function)(Thread*, object);
|
||||
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
|
||||
if (function) {
|
||||
function(t, finalizerTarget(t, f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (object* p = &(t->m->tenuredFinalizers); *p;) {
|
||||
object f = *p;
|
||||
*p = finalizerNext(t, *p);
|
||||
for (p = t->m->tenuredFinalizers; p;) {
|
||||
object f = p;
|
||||
p = finalizerNext(t, p);
|
||||
|
||||
void (*function)(Thread*, object);
|
||||
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
|
||||
if (function) {
|
||||
function(t, finalizerTarget(t, f));
|
||||
void (*function)(Thread*, object);
|
||||
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
|
||||
if (function) {
|
||||
function(t, finalizerTarget(t, f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,14 +201,16 @@ turnOffTheLights(Thread* t)
|
||||
Heap* h = m->heap;
|
||||
Processor* p = m->processor;
|
||||
Classpath* c = m->classpath;
|
||||
Finder* f = m->finder;
|
||||
Finder* bf = m->bootFinder;
|
||||
Finder* af = m->appFinder;
|
||||
|
||||
m->dispose();
|
||||
h->disposeFixies();
|
||||
c->dispose();
|
||||
p->dispose();
|
||||
h->dispose();
|
||||
f->dispose();
|
||||
bf->dispose();
|
||||
af->dispose();
|
||||
s->dispose();
|
||||
}
|
||||
|
||||
@ -554,10 +560,10 @@ postCollect(Thread* t)
|
||||
t->heapOffset = 0;
|
||||
t->heapIndex = 0;
|
||||
|
||||
if (t->useBackupHeap) {
|
||||
if (t->flags & Thread::UseBackupHeapFlag) {
|
||||
memset(t->backupHeap, 0, ThreadBackupHeapSizeInBytes);
|
||||
|
||||
t->useBackupHeap = false;
|
||||
t->flags &= ~Thread::UseBackupHeapFlag;
|
||||
t->backupHeapIndex = 0;
|
||||
}
|
||||
|
||||
@ -711,7 +717,8 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
|
||||
void
|
||||
removeByteArray(Thread* t, object o)
|
||||
{
|
||||
hashMapRemove(t, t->m->byteArrayMap, o, byteArrayHash, objectEqual);
|
||||
hashMapRemove
|
||||
(t, root(t, Machine::ByteArrayMap), o, byteArrayHash, objectEqual);
|
||||
}
|
||||
|
||||
object
|
||||
@ -720,11 +727,11 @@ internByteArray(Thread* t, object array)
|
||||
PROTECT(t, array);
|
||||
|
||||
object n = hashMapFindNode
|
||||
(t, t->m->byteArrayMap, array, byteArrayHash, byteArrayEqual);
|
||||
(t, root(t, Machine::ByteArrayMap), array, byteArrayHash, byteArrayEqual);
|
||||
if (n) {
|
||||
return jreferenceTarget(t, tripleFirst(t, n));
|
||||
} else {
|
||||
hashMapInsert(t, t->m->byteArrayMap, array, 0, byteArrayHash);
|
||||
hashMapInsert(t, root(t, Machine::ByteArrayMap), array, 0, byteArrayHash);
|
||||
addFinalizer(t, array, removeByteArray);
|
||||
return array;
|
||||
}
|
||||
@ -752,9 +759,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
||||
case CONSTANT_Utf8: {
|
||||
if (singletonObject(t, pool, i) == 0) {
|
||||
object value = parseUtf8(t, s, s.read2());
|
||||
if (objectClass(t, value)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, value) == type(t, Machine::ByteArrayType)) {
|
||||
value = internByteArray(t, value);
|
||||
}
|
||||
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
||||
@ -1698,8 +1703,19 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
||||
object elementClass)
|
||||
{
|
||||
// todo: arrays should implement Cloneable and Serializable
|
||||
object vtable = classVirtualTable
|
||||
(t, arrayBody(t, t->m->types, Machine::JobjectType));
|
||||
|
||||
if (classVmFlags(t, type(t, Machine::JobjectType)) & BootstrapFlag) {
|
||||
PROTECT(t, spec);
|
||||
PROTECT(t, elementClass);
|
||||
|
||||
resolveSystemClass
|
||||
(t, root(t, Machine::BootLoader),
|
||||
className(t, type(t, Machine::JobjectType)));
|
||||
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
}
|
||||
|
||||
object vtable = classVirtualTable(t, type(t, Machine::JobjectType));
|
||||
|
||||
object c = t->m->processor->makeClass
|
||||
(t,
|
||||
@ -1708,10 +1724,10 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
||||
2 * BytesPerWord,
|
||||
BytesPerWord,
|
||||
dimensions,
|
||||
classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)),
|
||||
classObjectMask(t, type(t, Machine::ArrayType)),
|
||||
spec,
|
||||
0,
|
||||
arrayBody(t, t->m->types, Machine::JobjectType),
|
||||
type(t, Machine::JobjectType),
|
||||
0,
|
||||
vtable,
|
||||
0,
|
||||
@ -1727,7 +1743,7 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
||||
}
|
||||
|
||||
object
|
||||
makeArrayClass(Thread* t, object loader, object spec)
|
||||
makeArrayClass(Thread* t, object loader, object spec, bool throw_)
|
||||
{
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, spec);
|
||||
@ -1765,30 +1781,31 @@ makeArrayClass(Thread* t, object loader, object spec)
|
||||
}
|
||||
|
||||
object elementClass = hashMapFind
|
||||
(t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
|
||||
(t, root(t, Machine::BootstrapClassMap), elementSpec, byteArrayHash,
|
||||
byteArrayEqual);
|
||||
|
||||
if (elementClass == 0) {
|
||||
elementClass = resolveClass(t, loader, elementSpec);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
elementClass = resolveClass(t, loader, elementSpec, throw_);
|
||||
if (elementClass == 0) return 0;
|
||||
}
|
||||
|
||||
return makeArrayClass(t, loader, dimensions, spec, elementClass);
|
||||
}
|
||||
|
||||
object
|
||||
resolveArrayClass(Thread* t, object loader, object spec)
|
||||
resolveArrayClass(Thread* t, object loader, object spec, bool throw_)
|
||||
{
|
||||
object c = hashMapFind
|
||||
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||
(t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash,
|
||||
byteArrayEqual);
|
||||
|
||||
if (c) {
|
||||
set(t, c, ClassVirtualTable,
|
||||
classVirtualTable
|
||||
(t, arrayBody(t, t->m->types, Machine::JobjectType)));
|
||||
classVirtualTable(t, type(t, Machine::JobjectType)));
|
||||
|
||||
return c;
|
||||
} else {
|
||||
return makeArrayClass(t, loader, spec);
|
||||
return makeArrayClass(t, loader, spec, throw_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1803,7 +1820,8 @@ removeMonitor(Thread* t, object o)
|
||||
hash = objectHash(t, o);
|
||||
}
|
||||
|
||||
object m = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual);
|
||||
object m = hashMapRemove
|
||||
(t, root(t, Machine::MonitorMap), o, objectHash, objectEqual);
|
||||
|
||||
expect(t, m);
|
||||
|
||||
@ -1815,14 +1833,15 @@ removeMonitor(Thread* t, object o)
|
||||
void
|
||||
removeString(Thread* t, object o)
|
||||
{
|
||||
hashMapRemove(t, t->m->stringMap, o, stringHash, objectEqual);
|
||||
hashMapRemove(t, root(t, Machine::StringMap), o, stringHash, objectEqual);
|
||||
}
|
||||
|
||||
void
|
||||
bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
|
||||
unsigned fixedSize, unsigned arrayElementSize, unsigned vtableLength)
|
||||
{
|
||||
object super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
|
||||
object super = (superType >= 0
|
||||
? vm::type(t, static_cast<Machine::Type>(superType)) : 0);
|
||||
|
||||
object mask;
|
||||
if (objectMask) {
|
||||
@ -1831,7 +1850,8 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
|
||||
and intArrayBody(t, classObjectMask(t, super), 0)
|
||||
== static_cast<int32_t>(objectMask))
|
||||
{
|
||||
mask = classObjectMask(t, arrayBody(t, t->m->types, superType));
|
||||
mask = classObjectMask
|
||||
(t, vm::type(t, static_cast<Machine::Type>(superType)));
|
||||
} else {
|
||||
mask = makeIntArray(t, 1);
|
||||
intArrayBody(t, mask, 0) = objectMask;
|
||||
@ -1840,14 +1860,15 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
|
||||
super = (superType >= 0
|
||||
? vm::type(t, static_cast<Machine::Type>(superType)) : 0);
|
||||
|
||||
object class_ = t->m->processor->makeClass
|
||||
(t, 0, BootstrapFlag, fixedSize, arrayElementSize,
|
||||
arrayElementSize ? 1 : 0, mask, 0, 0, super, 0, 0, 0, 0, 0, 0,
|
||||
t->m->loader, vtableLength);
|
||||
root(t, Machine::BootLoader), vtableLength);
|
||||
|
||||
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
|
||||
setType(t, type, class_);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1857,7 +1878,7 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
|
||||
PROTECT(t, bootMethod);
|
||||
|
||||
object n = makeByteArray(t, name);
|
||||
object class_ = arrayBody(t, t->m->types, type);
|
||||
object class_ = vm::type(t, type);
|
||||
|
||||
set(t, class_, ClassName, n);
|
||||
|
||||
@ -1870,14 +1891,16 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
|
||||
arrayBody(t, vtable, i) = bootMethod;
|
||||
}
|
||||
} else {
|
||||
vtable = classVirtualTable(t, arrayBody(t, t->m->types, superType));
|
||||
vtable = classVirtualTable
|
||||
(t, vm::type(t, static_cast<Machine::Type>(superType)));
|
||||
}
|
||||
|
||||
set(t, class_, ClassVirtualTable, vtable);
|
||||
|
||||
t->m->processor->initVtable(t, class_);
|
||||
|
||||
hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash);
|
||||
hashMapInsert
|
||||
(t, root(t, Machine::BootstrapClassMap), n, class_, byteArrayHash);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1887,92 +1910,103 @@ boot(Thread* t)
|
||||
|
||||
m->unsafe = true;
|
||||
|
||||
m->loader = allocate(t, FixedSizeOfSystemClassLoader, true);
|
||||
m->roots = allocate(t, pad((Machine::RootCount + 2) * BytesPerWord), true);
|
||||
arrayLength(t, m->roots) = Machine::RootCount;
|
||||
|
||||
setRoot(t, Machine::BootLoader,
|
||||
allocate(t, FixedSizeOfSystemClassLoader, true));
|
||||
|
||||
setRoot(t, Machine::AppLoader,
|
||||
allocate(t, FixedSizeOfSystemClassLoader, true));
|
||||
|
||||
m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
|
||||
arrayLength(t, m->types) = TypeCount;
|
||||
|
||||
#include "type-initializations.cpp"
|
||||
|
||||
object arrayClass = arrayBody(t, m->types, Machine::ArrayType);
|
||||
object arrayClass = type(t, Machine::ArrayType);
|
||||
set(t, m->types, 0, arrayClass);
|
||||
set(t, m->roots, 0, arrayClass);
|
||||
|
||||
object loaderClass = arrayBody
|
||||
(t, m->types, Machine::SystemClassLoaderType);
|
||||
set(t, m->loader, 0, loaderClass);
|
||||
object loaderClass = type(t, Machine::SystemClassLoaderType);
|
||||
set(t, root(t, Machine::BootLoader), 0, loaderClass);
|
||||
set(t, root(t, Machine::AppLoader), 0, loaderClass);
|
||||
|
||||
#ifdef AVIAN_GNU
|
||||
classLoaderInitialized(t, m->loader) = true;
|
||||
#endif
|
||||
object objectClass = type(t, Machine::JobjectType);
|
||||
|
||||
object objectClass = arrayBody(t, m->types, Machine::JobjectType);
|
||||
|
||||
object classClass = arrayBody(t, m->types, Machine::ClassType);
|
||||
object classClass = type(t, Machine::ClassType);
|
||||
set(t, classClass, 0, classClass);
|
||||
set(t, classClass, ClassSuper, objectClass);
|
||||
|
||||
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
||||
object intArrayClass = type(t, Machine::IntArrayType);
|
||||
set(t, intArrayClass, 0, classClass);
|
||||
set(t, intArrayClass, ClassSuper, objectClass);
|
||||
|
||||
m->unsafe = false;
|
||||
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|
||||
classVmFlags(t, type(t, Machine::SingletonType))
|
||||
|= SingletonFlag;
|
||||
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
|
||||
classVmFlags(t, type(t, Machine::ContinuationType))
|
||||
|= ContinuationFlag;
|
||||
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|
||||
classVmFlags(t, type(t, Machine::JreferenceType))
|
||||
|= ReferenceFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|
||||
classVmFlags(t, type(t, Machine::WeakReferenceType))
|
||||
|= ReferenceFlag | WeakReferenceFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::SoftReferenceType))
|
||||
classVmFlags(t, type(t, Machine::SoftReferenceType))
|
||||
|= ReferenceFlag | WeakReferenceFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType))
|
||||
classVmFlags(t, type(t, Machine::PhantomReferenceType))
|
||||
|= ReferenceFlag | WeakReferenceFlag;
|
||||
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JbooleanType))
|
||||
classVmFlags(t, type(t, Machine::JbooleanType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JbyteType))
|
||||
classVmFlags(t, type(t, Machine::JbyteType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JcharType))
|
||||
classVmFlags(t, type(t, Machine::JcharType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JshortType))
|
||||
classVmFlags(t, type(t, Machine::JshortType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JintType))
|
||||
classVmFlags(t, type(t, Machine::JintType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JlongType))
|
||||
classVmFlags(t, type(t, Machine::JlongType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JfloatType))
|
||||
classVmFlags(t, type(t, Machine::JfloatType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JdoubleType))
|
||||
classVmFlags(t, type(t, Machine::JdoubleType))
|
||||
|= PrimitiveFlag;
|
||||
classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType))
|
||||
classVmFlags(t, type(t, Machine::JvoidType))
|
||||
|= PrimitiveFlag;
|
||||
|
||||
set(t, arrayBody(t, m->types, Machine::BooleanArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JbooleanType));
|
||||
set(t, arrayBody(t, m->types, Machine::ByteArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JbyteType));
|
||||
set(t, arrayBody(t, m->types, Machine::CharArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JcharType));
|
||||
set(t, arrayBody(t, m->types, Machine::ShortArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JshortType));
|
||||
set(t, arrayBody(t, m->types, Machine::IntArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JintType));
|
||||
set(t, arrayBody(t, m->types, Machine::LongArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JlongType));
|
||||
set(t, arrayBody(t, m->types, Machine::FloatArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JfloatType));
|
||||
set(t, arrayBody(t, m->types, Machine::DoubleArrayType), ClassStaticTable,
|
||||
arrayBody(t, m->types, Machine::JdoubleType));
|
||||
set(t, type(t, Machine::BooleanArrayType), ClassStaticTable,
|
||||
type(t, Machine::JbooleanType));
|
||||
set(t, type(t, Machine::ByteArrayType), ClassStaticTable,
|
||||
type(t, Machine::JbyteType));
|
||||
set(t, type(t, Machine::CharArrayType), ClassStaticTable,
|
||||
type(t, Machine::JcharType));
|
||||
set(t, type(t, Machine::ShortArrayType), ClassStaticTable,
|
||||
type(t, Machine::JshortType));
|
||||
set(t, type(t, Machine::IntArrayType), ClassStaticTable,
|
||||
type(t, Machine::JintType));
|
||||
set(t, type(t, Machine::LongArrayType), ClassStaticTable,
|
||||
type(t, Machine::JlongType));
|
||||
set(t, type(t, Machine::FloatArrayType), ClassStaticTable,
|
||||
type(t, Machine::JfloatType));
|
||||
set(t, type(t, Machine::DoubleArrayType), ClassStaticTable,
|
||||
type(t, Machine::JdoubleType));
|
||||
|
||||
m->classMap = makeHashMap(t, 0, 0);
|
||||
setRoot(t, Machine::ClassMap, makeHashMap(t, 0, 0));
|
||||
|
||||
m->bootstrapClassMap = makeHashMap(t, 0, 0);
|
||||
{ object map = makeHashMap(t, 0, 0);
|
||||
set(t, root(t, Machine::AppLoader), ClassLoaderMap, map);
|
||||
}
|
||||
|
||||
m->stringMap = makeWeakHashMap(t, 0, 0);
|
||||
set(t, root(t, Machine::AppLoader), ClassLoaderParent,
|
||||
root(t, Machine::BootLoader));
|
||||
|
||||
setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0));
|
||||
|
||||
setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0));
|
||||
m->processor->boot(t, 0);
|
||||
|
||||
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1);
|
||||
@ -2074,15 +2108,16 @@ class HeapClient: public Heap::Client {
|
||||
|
||||
namespace vm {
|
||||
|
||||
Machine::Machine(System* system, Heap* heap, Finder* finder,
|
||||
Processor* processor, Classpath* classpath,
|
||||
Machine::Machine(System* system, Heap* heap, Finder* bootFinder,
|
||||
Finder* appFinder, Processor* processor, Classpath* classpath,
|
||||
const char** properties, unsigned propertyCount):
|
||||
vtable(&javaVMVTable),
|
||||
system(system),
|
||||
heapClient(new (heap->allocate(sizeof(HeapClient)))
|
||||
HeapClient(this)),
|
||||
heap(heap),
|
||||
finder(finder),
|
||||
bootFinder(bootFinder),
|
||||
appFinder(appFinder),
|
||||
processor(processor),
|
||||
classpath(classpath),
|
||||
rootThread(0),
|
||||
@ -2102,24 +2137,13 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
||||
referenceLock(0),
|
||||
shutdownLock(0),
|
||||
libraries(0),
|
||||
loader(0),
|
||||
classMap(0),
|
||||
loadClassMethod(0),
|
||||
bootstrapClassMap(0),
|
||||
monitorMap(0),
|
||||
stringMap(0),
|
||||
byteArrayMap(0),
|
||||
types(0),
|
||||
jniMethodTable(0),
|
||||
roots(0),
|
||||
finalizers(0),
|
||||
tenuredFinalizers(0),
|
||||
finalizeQueue(0),
|
||||
weakReferences(0),
|
||||
tenuredWeakReferences(0),
|
||||
shutdownHooks(0),
|
||||
objectsToFinalize(0),
|
||||
nullPointerException(0),
|
||||
arrayIndexOutOfBoundsException(0),
|
||||
unsafe(false),
|
||||
triedBuiltinOnLoad(false),
|
||||
heapPoolIndex(0)
|
||||
@ -2194,13 +2218,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
||||
(m->heap->allocate(ThreadHeapSizeInBytes))),
|
||||
heap(defaultHeap),
|
||||
backupHeapIndex(0),
|
||||
useBackupHeap(false),
|
||||
waiting(false),
|
||||
tracing(false),
|
||||
daemon(false)
|
||||
#ifdef VM_STRESS
|
||||
, stress(false)
|
||||
#endif // VM_STRESS
|
||||
flags(ActiveFlag)
|
||||
{ }
|
||||
|
||||
void
|
||||
@ -2241,16 +2259,10 @@ Thread::init()
|
||||
boot(this);
|
||||
}
|
||||
|
||||
m->byteArrayMap = makeWeakHashMap(this, 0, 0);
|
||||
m->monitorMap = makeWeakHashMap(this, 0, 0);
|
||||
setRoot(this, Machine::ByteArrayMap, makeWeakHashMap(this, 0, 0));
|
||||
setRoot(this, Machine::MonitorMap, makeWeakHashMap(this, 0, 0));
|
||||
|
||||
m->jniMethodTable = makeVector(this, 0, 0);
|
||||
|
||||
m->nullPointerException = m->classpath->makeThrowable
|
||||
(this, Machine::NullPointerExceptionType);
|
||||
|
||||
m->arrayIndexOutOfBoundsException = m->classpath->makeThrowable
|
||||
(this, Machine::IndexOutOfBoundsExceptionType);
|
||||
setRoot(this, Machine::JNIMethodTable, makeVector(this, 0, 0));
|
||||
|
||||
m->localThread->set(this);
|
||||
} else {
|
||||
@ -2265,6 +2277,21 @@ Thread::init()
|
||||
}
|
||||
|
||||
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
|
||||
|
||||
if (parent == 0) {
|
||||
enter(this, Thread::ActiveState);
|
||||
|
||||
m->classpath->boot(this);
|
||||
|
||||
setRoot(this, Machine::NullPointerException, m->classpath->makeThrowable
|
||||
(this, Machine::NullPointerExceptionType));
|
||||
|
||||
setRoot(this, Machine::ArrayIndexOutOfBoundsException,
|
||||
m->classpath->makeThrowable
|
||||
(this, Machine::IndexOutOfBoundsExceptionType));
|
||||
|
||||
enter(this, Thread::IdleState);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -2303,10 +2330,10 @@ shutDown(Thread* t)
|
||||
{
|
||||
ACQUIRE(t, t->m->shutdownLock);
|
||||
|
||||
object hooks = t->m->shutdownHooks;
|
||||
object hooks = root(t, Machine::ShutdownHooks);
|
||||
PROTECT(t, hooks);
|
||||
|
||||
t->m->shutdownHooks = 0;
|
||||
setRoot(t, Machine::ShutdownHooks, 0);
|
||||
|
||||
object h = hooks;
|
||||
PROTECT(t, h);
|
||||
@ -2364,7 +2391,6 @@ enter(Thread* t, Thread::State s)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_ATOMIC_OPERATIONS
|
||||
# define INCREMENT atomicIncrement
|
||||
# define ACQUIRE_LOCK ACQUIRE_RAW(t, t->m->stateLock)
|
||||
@ -2411,12 +2437,24 @@ enter(Thread* t, Thread::State s)
|
||||
// The java.lang.Thread implementation may or may not notify the
|
||||
// VM when the daemon field in the Java object changes, so we sync
|
||||
// up the native field whenever the thread transitions to idle:
|
||||
if (t->daemon != threadDaemon(t, t->javaThread)) {
|
||||
|
||||
// todo: this won't always help if some other thread sets the
|
||||
// daemon field. The thread trying to shut down the VM really
|
||||
// just needs to count from scratch every time any thread makes a
|
||||
// transition.
|
||||
|
||||
if (UNLIKELY(((t->flags & Thread::DaemonFlag) != 0)
|
||||
!= threadDaemon(t, t->javaThread)))
|
||||
{
|
||||
ACQUIRE_LOCK;
|
||||
|
||||
t->daemon = threadDaemon(t, t->javaThread);
|
||||
if (threadDaemon(t, t->javaThread)) {
|
||||
atomicOr(&(t->flags), Thread::DaemonFlag);
|
||||
} else {
|
||||
atomicAnd(&(t->flags), ~Thread::DaemonFlag);
|
||||
}
|
||||
|
||||
if (t->daemon) {
|
||||
if (t->flags & Thread::DaemonFlag) {
|
||||
++ t->m->daemonCount;
|
||||
} else {
|
||||
expect(t, t->m->daemonCount);
|
||||
@ -2426,7 +2464,7 @@ enter(Thread* t, Thread::State s)
|
||||
t->m->stateLock->notifyAll(t->systemThread);
|
||||
}
|
||||
|
||||
if (t->state == Thread::ActiveState) {
|
||||
if (LIKELY(t->state == Thread::ActiveState)) {
|
||||
// fast path
|
||||
assert(t, t->m->activeCount > 0);
|
||||
INCREMENT(&(t->m->activeCount), -1);
|
||||
@ -2475,7 +2513,7 @@ enter(Thread* t, Thread::State s)
|
||||
} break;
|
||||
|
||||
case Thread::ActiveState:
|
||||
if (t->state == Thread::IdleState and t->m->exclusive == 0) {
|
||||
if (LIKELY(t->state == Thread::IdleState and t->m->exclusive == 0)) {
|
||||
// fast path
|
||||
INCREMENT(&(t->m->activeCount), 1);
|
||||
|
||||
@ -2563,7 +2601,7 @@ object
|
||||
allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
||||
unsigned sizeInBytes, bool objectMask)
|
||||
{
|
||||
if (UNLIKELY(t->useBackupHeap)) {
|
||||
if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) {
|
||||
expect(t, t->backupHeapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||
<= ThreadBackupHeapSizeInWords);
|
||||
|
||||
@ -2571,7 +2609,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
||||
t->backupHeapIndex += ceiling(sizeInBytes, BytesPerWord);
|
||||
cast<object>(o, 0) = 0;
|
||||
return o;
|
||||
} else if (UNLIKELY(t->tracing)) {
|
||||
} else if (UNLIKELY(t->flags & Thread::TracingFlag)) {
|
||||
expect(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||
<= ThreadHeapSizeInWords);
|
||||
return allocateSmall(t, sizeInBytes);
|
||||
@ -2721,9 +2759,7 @@ stringUTFLength(Thread* t, object string, unsigned start, unsigned length)
|
||||
|
||||
if (length) {
|
||||
object data = stringData(t, string);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
||||
result = length;
|
||||
} else {
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
@ -2746,9 +2782,7 @@ stringChars(Thread* t, object string, unsigned start, unsigned length,
|
||||
{
|
||||
if (length) {
|
||||
object data = stringData(t, string);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
||||
memcpy(chars,
|
||||
&byteArrayBody(t, data, stringOffset(t, string) + start),
|
||||
length);
|
||||
@ -2767,9 +2801,7 @@ stringChars(Thread* t, object string, unsigned start, unsigned length,
|
||||
{
|
||||
if (length) {
|
||||
object data = stringData(t, string);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + start + i);
|
||||
}
|
||||
@ -2791,9 +2823,7 @@ stringUTFChars(Thread* t, object string, unsigned start, unsigned length,
|
||||
|
||||
if (length) {
|
||||
object data = stringData(t, string);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
||||
memcpy(chars,
|
||||
&byteArrayBody(t, data, stringOffset(t, string) + start),
|
||||
length);
|
||||
@ -2824,11 +2854,14 @@ stringUTFChars(Thread* t, object string, unsigned start, unsigned length,
|
||||
bool
|
||||
isAssignableFrom(Thread* t, object a, object b)
|
||||
{
|
||||
assert(t, a);
|
||||
assert(t, b);
|
||||
|
||||
if (a == b) return true;
|
||||
|
||||
if (classFlags(t, a) & ACC_INTERFACE) {
|
||||
if (classVmFlags(t, b) & BootstrapFlag) {
|
||||
resolveSystemClass(t, className(t, b));
|
||||
resolveSystemClass(t, root(t, Machine::BootLoader), className(t, b));
|
||||
if (UNLIKELY(t->exception)) {
|
||||
t->exception = 0;
|
||||
return false;
|
||||
@ -2966,15 +2999,6 @@ primitiveSize(Thread* t, unsigned code)
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
findLoadedSystemClass(Thread* t, object spec)
|
||||
{
|
||||
PROTECT(t, spec);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
return hashMapFind(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
|
||||
}
|
||||
|
||||
object
|
||||
parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
|
||||
{
|
||||
@ -3084,18 +3108,27 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
|
||||
}
|
||||
|
||||
object
|
||||
resolveSystemClass(Thread* t, object spec)
|
||||
resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
||||
{
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, spec);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
object class_ = hashMapFind
|
||||
(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
|
||||
(t, getClassLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
|
||||
|
||||
if (class_ == 0) {
|
||||
if (classLoaderParent(t, loader)) {
|
||||
class_ = resolveSystemClass
|
||||
(t, classLoaderParent(t, loader), spec, false);
|
||||
if (class_) {
|
||||
return class_;
|
||||
}
|
||||
}
|
||||
|
||||
if (byteArrayBody(t, spec, 0) == '[') {
|
||||
class_ = resolveArrayClass(t, t->m->loader, spec);
|
||||
class_ = resolveArrayClass(t, loader, spec, throw_);
|
||||
} else {
|
||||
RUNTIME_ARRAY(char, file, byteArrayLength(t, spec) + 6);
|
||||
memcpy(RUNTIME_ARRAY_BODY(file),
|
||||
@ -3105,7 +3138,8 @@ resolveSystemClass(Thread* t, object spec)
|
||||
".class",
|
||||
7);
|
||||
|
||||
System::Region* region = t->m->finder->find(RUNTIME_ARRAY_BODY(file));
|
||||
System::Region* region = getFinder(t, loader)->find
|
||||
(RUNTIME_ARRAY_BODY(file));
|
||||
|
||||
if (region) {
|
||||
if (Verbose) {
|
||||
@ -3113,8 +3147,7 @@ resolveSystemClass(Thread* t, object spec)
|
||||
}
|
||||
|
||||
// parse class file
|
||||
class_ = parseClass
|
||||
(t, t->m->loader, region->start(), region->length());
|
||||
class_ = parseClass(t, loader, region->start(), region->length());
|
||||
region->dispose();
|
||||
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
@ -3125,7 +3158,7 @@ resolveSystemClass(Thread* t, object spec)
|
||||
}
|
||||
|
||||
object bootstrapClass = hashMapFind
|
||||
(t, t->m->bootstrapClassMap, spec, byteArrayHash,
|
||||
(t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash,
|
||||
byteArrayEqual);
|
||||
|
||||
if (bootstrapClass) {
|
||||
@ -3141,8 +3174,9 @@ resolveSystemClass(Thread* t, object spec)
|
||||
if (class_) {
|
||||
PROTECT(t, class_);
|
||||
|
||||
hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash);
|
||||
} else if (t->exception == 0) {
|
||||
hashMapInsert
|
||||
(t, getClassLoaderMap(t, loader), spec, class_, byteArrayHash);
|
||||
} else if (throw_ and t->exception == 0) {
|
||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::ClassNotFoundExceptionType, message);
|
||||
@ -3153,10 +3187,26 @@ resolveSystemClass(Thread* t, object spec)
|
||||
}
|
||||
|
||||
object
|
||||
resolveClass(Thread* t, object loader, object spec)
|
||||
findLoadedClass(Thread* t, object loader, object spec)
|
||||
{
|
||||
if (loader == t->m->loader) {
|
||||
return resolveSystemClass(t, spec);
|
||||
PROTECT(t, spec);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
object map = getClassLoaderMap(t, loader);
|
||||
if (map) {
|
||||
return hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
resolveClass(Thread* t, object loader, object spec, bool throw_)
|
||||
{
|
||||
if (loader == root(t, Machine::BootLoader)
|
||||
or loader == root(t, Machine::AppLoader))
|
||||
{
|
||||
return resolveSystemClass(t, loader, spec, throw_);
|
||||
} else {
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, spec);
|
||||
@ -3173,39 +3223,44 @@ resolveClass(Thread* t, object loader, object spec)
|
||||
|
||||
if (class_ == 0) {
|
||||
if (byteArrayBody(t, spec, 0) == '[') {
|
||||
class_ = resolveArrayClass(t, loader, spec);
|
||||
class_ = resolveArrayClass(t, loader, spec, throw_);
|
||||
} else {
|
||||
if (t->m->loadClassMethod == 0) {
|
||||
if (root(t, Machine::LoadClassMethod) == 0) {
|
||||
object m = resolveMethod
|
||||
(t, t->m->loader, "java/lang/ClassLoader", "loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
(t, root(t, Machine::BootLoader), "java/lang/ClassLoader",
|
||||
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
|
||||
if (m) {
|
||||
t->m->loadClassMethod = m;
|
||||
setRoot(t, Machine::LoadClassMethod, m);
|
||||
|
||||
object classLoaderClass = arrayBody
|
||||
(t, t->m->types, Machine::ClassLoaderType);
|
||||
object classLoaderClass = type(t, Machine::ClassLoaderType);
|
||||
|
||||
if (classVmFlags(t, classLoaderClass) & BootstrapFlag) {
|
||||
resolveSystemClass(t, vm::className(t, classLoaderClass));
|
||||
resolveSystemClass
|
||||
(t, root(t, Machine::BootLoader),
|
||||
vm::className(t, classLoaderClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
object method = findVirtualMethod
|
||||
(t, t->m->loadClassMethod, objectClass(t, loader));
|
||||
(t, root(t, Machine::LoadClassMethod), objectClass(t, loader));
|
||||
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
PROTECT(t, method);
|
||||
|
||||
object specString = makeString
|
||||
(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
RUNTIME_ARRAY(char, s, byteArrayLength(t, spec));
|
||||
replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, spec, 0)));
|
||||
|
||||
replace('/', '.', reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, stringData(t, specString), 0)));
|
||||
object specString = makeString(t, "%s", s);
|
||||
|
||||
class_ = t->m->processor->invoke(t, method, loader, specString);
|
||||
|
||||
if (LIKELY(class_ and t->exception == 0)) {
|
||||
class_ = jclassVmClass(t, class_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3216,7 +3271,7 @@ resolveClass(Thread* t, object loader, object spec)
|
||||
|
||||
hashMapInsert(t, classLoaderMap(t, loader), spec, class_,
|
||||
byteArrayHash);
|
||||
} else if (t->exception == 0) {
|
||||
} else if (throw_ and t->exception == 0) {
|
||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::ClassNotFoundExceptionType, message);
|
||||
@ -3399,10 +3454,10 @@ initClass(Thread* t, object c)
|
||||
}
|
||||
|
||||
object
|
||||
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count)
|
||||
makeObjectArray(Thread* t, object elementClass, unsigned count)
|
||||
{
|
||||
object arrayClass = resolveObjectArrayClass
|
||||
(t, loader, className(t, elementClass));
|
||||
(t, classLoader(t, elementClass), className(t, elementClass));
|
||||
PROTECT(t, arrayClass);
|
||||
|
||||
object array = makeArray(t, count);
|
||||
@ -3524,7 +3579,8 @@ objectMonitor(Thread* t, object o, bool createNew)
|
||||
{
|
||||
assert(t, t->state == Thread::ActiveState);
|
||||
|
||||
object m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
|
||||
object m = hashMapFind
|
||||
(t, root(t, Machine::MonitorMap), o, objectHash, objectEqual);
|
||||
|
||||
if (m) {
|
||||
if (DebugMonitors) {
|
||||
@ -3538,7 +3594,9 @@ objectMonitor(Thread* t, object o, bool createNew)
|
||||
|
||||
{ ENTER(t, Thread::ExclusiveState);
|
||||
|
||||
m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
|
||||
m = hashMapFind
|
||||
(t, root(t, Machine::MonitorMap), o, objectHash, objectEqual);
|
||||
|
||||
if (m) {
|
||||
if (DebugMonitors) {
|
||||
fprintf(stderr, "found monitor %p for object %x\n",
|
||||
@ -3556,7 +3614,7 @@ objectMonitor(Thread* t, object o, bool createNew)
|
||||
objectHash(t, o));
|
||||
}
|
||||
|
||||
hashMapInsert(t, t->m->monitorMap, o, m, objectHash);
|
||||
hashMapInsert(t, root(t, Machine::MonitorMap), o, m, objectHash);
|
||||
|
||||
addFinalizer(t, o, removeMonitor);
|
||||
}
|
||||
@ -3574,11 +3632,13 @@ intern(Thread* t, object s)
|
||||
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
object n = hashMapFindNode(t, t->m->stringMap, s, stringHash, stringEqual);
|
||||
object n = hashMapFindNode
|
||||
(t, root(t, Machine::StringMap), s, stringHash, stringEqual);
|
||||
|
||||
if (n) {
|
||||
return jreferenceTarget(t, tripleFirst(t, n));
|
||||
} else {
|
||||
hashMapInsert(t, t->m->stringMap, s, 0, stringHash);
|
||||
hashMapInsert(t, root(t, Machine::StringMap), s, 0, stringHash);
|
||||
addFinalizer(t, s, removeString);
|
||||
return s;
|
||||
}
|
||||
@ -3615,20 +3675,20 @@ collect(Thread* t, Heap::CollectionType type)
|
||||
if (not stress) t->stress = false;
|
||||
#endif
|
||||
|
||||
object f = m->finalizeQueue;
|
||||
m->finalizeQueue = 0;
|
||||
object f = t->m->finalizeQueue;
|
||||
t->m->finalizeQueue = 0;
|
||||
for (; f; f = finalizerNext(t, f)) {
|
||||
void (*function)(Thread*, object);
|
||||
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
|
||||
if (function) {
|
||||
function(t, finalizerTarget(t, f));
|
||||
} else {
|
||||
m->objectsToFinalize = makePair
|
||||
(t, finalizerTarget(t, f), m->objectsToFinalize);
|
||||
setRoot(t, Machine::ObjectsToFinalize, makePair
|
||||
(t, finalizerTarget(t, f), root(t, Machine::ObjectsToFinalize)));
|
||||
}
|
||||
}
|
||||
|
||||
if (m->objectsToFinalize and m->finalizeThread == 0) {
|
||||
if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) {
|
||||
m->finalizeThread = m->processor->makeThread
|
||||
(m, t->m->classpath->makeThread(t, m->rootThread), m->rootThread);
|
||||
|
||||
@ -3702,19 +3762,8 @@ walkNext(Thread* t, object o, int previous)
|
||||
void
|
||||
visitRoots(Machine* m, Heap::Visitor* v)
|
||||
{
|
||||
v->visit(&(m->loader));
|
||||
v->visit(&(m->classMap));
|
||||
v->visit(&(m->loadClassMethod));
|
||||
v->visit(&(m->bootstrapClassMap));
|
||||
v->visit(&(m->monitorMap));
|
||||
v->visit(&(m->stringMap));
|
||||
v->visit(&(m->byteArrayMap));
|
||||
v->visit(&(m->types));
|
||||
v->visit(&(m->jniMethodTable));
|
||||
v->visit(&(m->shutdownHooks));
|
||||
v->visit(&(m->objectsToFinalize));
|
||||
v->visit(&(m->nullPointerException));
|
||||
v->visit(&(m->arrayIndexOutOfBoundsException));
|
||||
v->visit(&(m->roots));
|
||||
|
||||
for (Thread* t = m->rootThread; t; t = t->peer) {
|
||||
::visitRoots(t, v);
|
||||
@ -3751,8 +3800,8 @@ printTrace(Thread* t, object exception)
|
||||
}
|
||||
|
||||
object trace = throwableTrace(t, e);
|
||||
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
|
||||
object e = arrayBody(t, trace, i);
|
||||
for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) {
|
||||
object e = objectArrayBody(t, trace, i);
|
||||
const int8_t* class_ = &byteArrayBody
|
||||
(t, className(t, methodClass(t, traceElementMethod(t, e))), 0);
|
||||
const int8_t* method = &byteArrayBody
|
||||
@ -3789,11 +3838,11 @@ makeTrace(Thread* t, Processor::StackWalker* walker)
|
||||
|
||||
virtual bool visit(Processor::StackWalker* walker) {
|
||||
if (trace == 0) {
|
||||
trace = makeArray(t, walker->count());
|
||||
trace = makeObjectArray(t, walker->count());
|
||||
}
|
||||
|
||||
object e = makeTraceElement(t, walker->method(), walker->ip());
|
||||
vm_assert(t, index < arrayLength(t, trace));
|
||||
vm_assert(t, index < objectArrayLength(t, trace));
|
||||
set(t, trace, ArrayBody + (index * BytesPerWord), e);
|
||||
++ index;
|
||||
return true;
|
||||
@ -3807,7 +3856,7 @@ makeTrace(Thread* t, Processor::StackWalker* walker)
|
||||
|
||||
walker->walk(&v);
|
||||
|
||||
return v.trace ? v.trace : makeArray(t, 0);
|
||||
return v.trace ? v.trace : makeObjectArray(t, 0);
|
||||
}
|
||||
|
||||
object
|
||||
@ -3828,7 +3877,7 @@ makeTrace(Thread* t, Thread* target)
|
||||
|
||||
t->m->processor->walkStack(target, &v);
|
||||
|
||||
return v.trace ? v.trace : makeArray(t, 0);
|
||||
return v.trace ? v.trace : makeObjectArray(t, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3842,7 +3891,9 @@ runFinalizeThread(Thread* t)
|
||||
while (true) {
|
||||
{ ACQUIRE(t, t->m->stateLock);
|
||||
|
||||
while (t->m->finalizeThread and t->m->objectsToFinalize == 0) {
|
||||
while (t->m->finalizeThread
|
||||
and root(t, Machine::ObjectsToFinalize) == 0)
|
||||
{
|
||||
ENTER(t, Thread::IdleState);
|
||||
t->m->stateLock->wait(t->systemThread, 0);
|
||||
}
|
||||
@ -3850,8 +3901,8 @@ runFinalizeThread(Thread* t)
|
||||
if (t->m->finalizeThread == 0) {
|
||||
return;
|
||||
} else {
|
||||
list = t->m->objectsToFinalize;
|
||||
t->m->objectsToFinalize = 0;
|
||||
list = root(t, Machine::ObjectsToFinalize);
|
||||
setRoot(t, Machine::ObjectsToFinalize, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3926,7 +3977,7 @@ vmPrintTrace(Thread* t)
|
||||
int line = t->m->processor->lineNumber
|
||||
(t, walker->method(), walker->ip());
|
||||
|
||||
fprintf(stderr, " at %s.%s (%x) ", class_, method, walker->ip());
|
||||
fprintf(stderr, " at %s.%s ", class_, method);
|
||||
|
||||
switch (line) {
|
||||
case NativeLine:
|
||||
|
206
src/machine.h
206
src/machine.h
@ -1120,6 +1120,24 @@ struct JNIEnvVTable {
|
||||
#endif
|
||||
};
|
||||
|
||||
inline void
|
||||
atomicOr(uint32_t* p, int v)
|
||||
{
|
||||
for (uint32_t old = *p;
|
||||
not atomicCompareAndSwap32(p, old, old | v);
|
||||
old = *p)
|
||||
{ }
|
||||
}
|
||||
|
||||
inline void
|
||||
atomicAnd(uint32_t* p, int v)
|
||||
{
|
||||
for (uint32_t old = *p;
|
||||
not atomicCompareAndSwap32(p, old, old & v);
|
||||
old = *p)
|
||||
{ }
|
||||
}
|
||||
|
||||
inline int
|
||||
strcmp(const int8_t* a, const int8_t* b)
|
||||
{
|
||||
@ -1164,8 +1182,26 @@ class Machine {
|
||||
ImmortalAllocation
|
||||
};
|
||||
|
||||
Machine(System* system, Heap* heap, Finder* finder, Processor* processor,
|
||||
Classpath* classpath, const char** properties,
|
||||
enum Root {
|
||||
BootLoader,
|
||||
AppLoader,
|
||||
ClassMap,
|
||||
LoadClassMethod,
|
||||
BootstrapClassMap,
|
||||
MonitorMap,
|
||||
StringMap,
|
||||
ByteArrayMap,
|
||||
JNIMethodTable,
|
||||
ShutdownHooks,
|
||||
ObjectsToFinalize,
|
||||
NullPointerException,
|
||||
ArrayIndexOutOfBoundsException
|
||||
};
|
||||
|
||||
static const unsigned RootCount = ArrayIndexOutOfBoundsException + 1;
|
||||
|
||||
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
|
||||
Processor* processor, Classpath* classpath, const char** properties,
|
||||
unsigned propertyCount);
|
||||
|
||||
~Machine() {
|
||||
@ -1178,7 +1214,8 @@ class Machine {
|
||||
System* system;
|
||||
Heap::Client* heapClient;
|
||||
Heap* heap;
|
||||
Finder* finder;
|
||||
Finder* bootFinder;
|
||||
Finder* appFinder;
|
||||
Processor* processor;
|
||||
Classpath* classpath;
|
||||
Thread* rootThread;
|
||||
@ -1198,24 +1235,13 @@ class Machine {
|
||||
System::Monitor* referenceLock;
|
||||
System::Monitor* shutdownLock;
|
||||
System::Library* libraries;
|
||||
object loader;
|
||||
object classMap;
|
||||
object loadClassMethod;
|
||||
object bootstrapClassMap;
|
||||
object monitorMap;
|
||||
object stringMap;
|
||||
object byteArrayMap;
|
||||
object types;
|
||||
object jniMethodTable;
|
||||
object roots;
|
||||
object finalizers;
|
||||
object tenuredFinalizers;
|
||||
object finalizeQueue;
|
||||
object weakReferences;
|
||||
object tenuredWeakReferences;
|
||||
object shutdownHooks;
|
||||
object objectsToFinalize;
|
||||
object nullPointerException;
|
||||
object arrayIndexOutOfBoundsException;
|
||||
bool unsafe;
|
||||
bool triedBuiltinOnLoad;
|
||||
JavaVMVTable javaVMVTable;
|
||||
@ -1261,6 +1287,13 @@ class Thread {
|
||||
ExitState
|
||||
};
|
||||
|
||||
static const unsigned UseBackupHeapFlag = 1 << 0;
|
||||
static const unsigned WaitingFlag = 1 << 1;
|
||||
static const unsigned TracingFlag = 1 << 2;
|
||||
static const unsigned DaemonFlag = 1 << 3;
|
||||
static const unsigned StressFlag = 1 << 4;
|
||||
static const unsigned ActiveFlag = 1 << 5;
|
||||
|
||||
class Protector {
|
||||
public:
|
||||
Protector(Thread* t): t(t), next(t->protector) {
|
||||
@ -1371,11 +1404,7 @@ class Thread {
|
||||
uintptr_t* heap;
|
||||
uintptr_t backupHeap[ThreadBackupHeapSizeInWords];
|
||||
unsigned backupHeapIndex;
|
||||
bool useBackupHeap;
|
||||
bool waiting;
|
||||
bool tracing;
|
||||
bool daemon;
|
||||
bool stress;
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
class Classpath {
|
||||
@ -1600,9 +1629,9 @@ ensure(Thread* t, unsigned sizeInBytes)
|
||||
> ThreadHeapSizeInWords)
|
||||
{
|
||||
if (sizeInBytes <= ThreadBackupHeapSizeInBytes) {
|
||||
expect(t, not t->useBackupHeap);
|
||||
expect(t, (t->flags & Thread::UseBackupHeapFlag) == 0);
|
||||
|
||||
t->useBackupHeap = true;
|
||||
atomicOr(&(t->flags), Thread::UseBackupHeapFlag);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
@ -1719,16 +1748,52 @@ instanceOf(Thread* t, object class_, object o);
|
||||
|
||||
#include "type-declarations.cpp"
|
||||
|
||||
inline object&
|
||||
root(Thread* t, Machine::Root root)
|
||||
{
|
||||
return arrayBody(t, t->m->roots, root);
|
||||
}
|
||||
|
||||
inline void
|
||||
setRoot(Thread* t, Machine::Root root, object value)
|
||||
{
|
||||
set(t, t->m->roots, ArrayBody + (root * BytesPerWord), value);
|
||||
}
|
||||
|
||||
inline object
|
||||
type(Thread* t, Machine::Type type)
|
||||
{
|
||||
return arrayBody(t, t->m->types, type);
|
||||
}
|
||||
|
||||
inline void
|
||||
setType(Thread* t, Machine::Type type, object value)
|
||||
{
|
||||
set(t, t->m->types, ArrayBody + (type * BytesPerWord), value);
|
||||
}
|
||||
|
||||
inline object
|
||||
getClassLoaderMap(Thread* t, object loader)
|
||||
{
|
||||
if (loader == t->m->loader) {
|
||||
return t->m->classMap;
|
||||
if (loader == root(t, Machine::BootLoader)) {
|
||||
return root(t, Machine::ClassMap);
|
||||
} else {
|
||||
return classLoaderMap(t, loader);
|
||||
}
|
||||
}
|
||||
|
||||
inline Finder*
|
||||
getFinder(Thread* t, object loader)
|
||||
{
|
||||
if (loader == root(t, Machine::BootLoader)) {
|
||||
return t->m->bootFinder;
|
||||
} else if (loader == root(t, Machine::AppLoader)) {
|
||||
return t->m->appFinder;
|
||||
} else {
|
||||
abort(t);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
objectFixed(Thread*, object o)
|
||||
{
|
||||
@ -1927,9 +1992,7 @@ stringHash(Thread* t, object s)
|
||||
{
|
||||
if (stringHashCode(t, s) == 0 and stringLength(t, s)) {
|
||||
object data = stringData(t, s);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
||||
stringHashCode(t, s) = hash
|
||||
(&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s));
|
||||
} else {
|
||||
@ -1944,9 +2007,7 @@ inline uint16_t
|
||||
stringCharAt(Thread* t, object s, int i)
|
||||
{
|
||||
object data = stringData(t, s);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
||||
return byteArrayBody(t, data, stringOffset(t, s) + i);
|
||||
} else {
|
||||
return charArrayBody(t, data, stringOffset(t, s) + i);
|
||||
@ -2063,7 +2124,7 @@ fieldSize(Thread* t, object field)
|
||||
}
|
||||
|
||||
object
|
||||
findLoadedSystemClass(Thread* t, object spec);
|
||||
findLoadedClass(Thread* t, object loader, object spec);
|
||||
|
||||
inline bool
|
||||
emptyMethod(Thread* t, object method)
|
||||
@ -2080,7 +2141,7 @@ object
|
||||
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length);
|
||||
|
||||
object
|
||||
resolveClass(Thread* t, object loader, object name);
|
||||
resolveClass(Thread* t, object loader, object name, bool throw_ = true);
|
||||
|
||||
inline object
|
||||
resolveClass(Thread* t, object loader, const char* name)
|
||||
@ -2091,12 +2152,12 @@ resolveClass(Thread* t, object loader, const char* name)
|
||||
}
|
||||
|
||||
object
|
||||
resolveSystemClass(Thread* t, object name);
|
||||
resolveSystemClass(Thread* t, object loader, object name, bool throw_ = true);
|
||||
|
||||
inline object
|
||||
resolveSystemClass(Thread* t, const char* name)
|
||||
resolveSystemClass(Thread* t, object loader, const char* name)
|
||||
{
|
||||
return resolveSystemClass(t, makeByteArray(t, "%s", name));
|
||||
return resolveSystemClass(t, loader, makeByteArray(t, "%s", name));
|
||||
}
|
||||
|
||||
void
|
||||
@ -2150,13 +2211,12 @@ void
|
||||
initClass(Thread* t, object c);
|
||||
|
||||
object
|
||||
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count);
|
||||
makeObjectArray(Thread* t, object elementClass, unsigned count);
|
||||
|
||||
inline object
|
||||
makeObjectArray(Thread* t, unsigned count)
|
||||
{
|
||||
return makeObjectArray
|
||||
(t, t->m->loader, arrayBody(t, t->m->types, Machine::JobjectType), count);
|
||||
return makeObjectArray(t, type(t, Machine::JobjectType), count);
|
||||
}
|
||||
|
||||
object
|
||||
@ -2398,10 +2458,10 @@ monitorAppendWait(Thread* t, object monitor)
|
||||
{
|
||||
assert(t, monitorOwner(t, monitor) == t);
|
||||
|
||||
expect(t, not t->waiting);
|
||||
expect(t, (t->flags & Thread::WaitingFlag) == 0);
|
||||
expect(t, t->waitNext == 0);
|
||||
|
||||
t->waiting = true;
|
||||
atomicOr(&(t->flags), Thread::WaitingFlag);
|
||||
|
||||
if (monitorWaitTail(t, monitor)) {
|
||||
static_cast<Thread*>(monitorWaitTail(t, monitor))->waitNext = t;
|
||||
@ -2434,7 +2494,7 @@ monitorRemoveWait(Thread* t, object monitor)
|
||||
}
|
||||
|
||||
t->waitNext = 0;
|
||||
t->waiting = false;
|
||||
atomicAnd(&(t->flags), ~Thread::WaitingFlag);
|
||||
|
||||
return;
|
||||
} else {
|
||||
@ -2489,7 +2549,7 @@ monitorWait(Thread* t, object monitor, int64_t time)
|
||||
|
||||
monitorDepth(t, monitor) = depth;
|
||||
|
||||
if (t->waiting) {
|
||||
if (t->flags & Thread::WaitingFlag) {
|
||||
monitorRemoveWait(t, monitor);
|
||||
} else {
|
||||
expect(t, not monitorFindWait(t, monitor));
|
||||
@ -2509,7 +2569,7 @@ monitorPollWait(Thread* t, object monitor)
|
||||
|
||||
if (next) {
|
||||
monitorWaitHead(t, monitor) = next->waitNext;
|
||||
next->waiting = false;
|
||||
atomicAnd(&(next->flags), ~Thread::WaitingFlag);
|
||||
next->waitNext = 0;
|
||||
if (next == monitorWaitTail(t, monitor)) {
|
||||
monitorWaitTail(t, monitor) = 0;
|
||||
@ -2677,7 +2737,13 @@ setDaemon(Thread* t, object thread, bool daemon)
|
||||
|
||||
if ((threadDaemon(t, thread) != 0) != daemon) {
|
||||
threadDaemon(t, thread) = daemon;
|
||||
t->daemon = daemon;
|
||||
|
||||
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, thread));
|
||||
if (daemon) {
|
||||
atomicOr(&(p->flags), Thread::DaemonFlag);
|
||||
} else {
|
||||
atomicAnd(&(p->flags), ~Thread::DaemonFlag);
|
||||
}
|
||||
|
||||
if (daemon) {
|
||||
++ t->m->daemonCount;
|
||||
@ -2832,7 +2898,7 @@ resolveClassInObject(Thread* t, object loader, object container,
|
||||
unsigned classOffset)
|
||||
{
|
||||
object o = cast<object>(container, classOffset);
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
|
||||
if (objectClass(t, o) == type(t, Machine::ByteArrayType)) {
|
||||
PROTECT(t, container);
|
||||
|
||||
o = resolveClass(t, loader, o);
|
||||
@ -2847,7 +2913,7 @@ inline object
|
||||
resolveClassInPool(Thread* t, object loader, object method, unsigned index)
|
||||
{
|
||||
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) {
|
||||
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
|
||||
PROTECT(t, method);
|
||||
|
||||
o = resolveClass(t, loader, referenceName(t, o));
|
||||
@ -2872,7 +2938,7 @@ resolve(Thread* t, object loader, object method, unsigned index,
|
||||
Machine::Type errorType)
|
||||
{
|
||||
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
|
||||
if (objectClass(t, o) == type(t, Machine::ReferenceType))
|
||||
{
|
||||
PROTECT(t, method);
|
||||
|
||||
@ -2953,21 +3019,49 @@ inline object
|
||||
primitiveClass(Thread* t, char name)
|
||||
{
|
||||
switch (name) {
|
||||
case 'B': return arrayBody(t, t->m->types, Machine::JbyteType);
|
||||
case 'C': return arrayBody(t, t->m->types, Machine::JcharType);
|
||||
case 'D': return arrayBody(t, t->m->types, Machine::JdoubleType);
|
||||
case 'F': return arrayBody(t, t->m->types, Machine::JfloatType);
|
||||
case 'I': return arrayBody(t, t->m->types, Machine::JintType);
|
||||
case 'J': return arrayBody(t, t->m->types, Machine::JlongType);
|
||||
case 'S': return arrayBody(t, t->m->types, Machine::JshortType);
|
||||
case 'V': return arrayBody(t, t->m->types, Machine::JvoidType);
|
||||
case 'Z': return arrayBody(t, t->m->types, Machine::JbooleanType);
|
||||
case 'B': return type(t, Machine::JbyteType);
|
||||
case 'C': return type(t, Machine::JcharType);
|
||||
case 'D': return type(t, Machine::JdoubleType);
|
||||
case 'F': return type(t, Machine::JfloatType);
|
||||
case 'I': return type(t, Machine::JintType);
|
||||
case 'J': return type(t, Machine::JlongType);
|
||||
case 'S': return type(t, Machine::JshortType);
|
||||
case 'V': return type(t, Machine::JvoidType);
|
||||
case 'Z': return type(t, Machine::JbooleanType);
|
||||
default:
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::IllegalArgumentExceptionType);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
registerNative(Thread* t, object method, void* function)
|
||||
{
|
||||
PROTECT(t, method);
|
||||
|
||||
expect(t, methodFlags(t, method) & ACC_NATIVE);
|
||||
|
||||
object native = makeNative(t, function, false);
|
||||
|
||||
// ensure other threads only see the methodCode field populated
|
||||
// once the object it points to has been populated:
|
||||
storeStoreMemoryBarrier();
|
||||
|
||||
set(t, method, MethodCode, native);
|
||||
}
|
||||
|
||||
inline void
|
||||
unregisterNatives(Thread* t, object c) {
|
||||
if (classMethodTable(t, c)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||
object method = arrayBody(t, classMethodTable(t, c), i);
|
||||
if (methodFlags(t, method) & ACC_NATIVE) {
|
||||
set(t, method, MethodCode, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length);
|
||||
|
@ -77,7 +77,8 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
|
||||
&byteArrayBody(t, spec, 1),
|
||||
byteArrayLength(t, spec) - 1);
|
||||
|
||||
object class_ = resolveSystemClass(t, elementSpec);
|
||||
object class_ = resolveClass
|
||||
(t, classLoader(t, objectClass(t, array)), elementSpec);
|
||||
PROTECT(t, class_);
|
||||
|
||||
for (int32_t i = 0; i < counts[index]; ++i) {
|
||||
|
@ -128,7 +128,7 @@ class Processor {
|
||||
DelayedPromise** addresses, object method) = 0;
|
||||
|
||||
virtual void
|
||||
visitRoots(HeapWalker* w) = 0;
|
||||
visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||
|
||||
virtual unsigned*
|
||||
makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||
@ -153,10 +153,6 @@ class Processor {
|
||||
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
|
||||
= 0;
|
||||
|
||||
virtual void registerNative(Thread* t, object method, void* function) = 0;
|
||||
|
||||
virtual void unregisterNatives(Thread* t, object c) = 0;
|
||||
|
||||
object
|
||||
invoke(Thread* t, object method, object this_, ...)
|
||||
{
|
||||
|
@ -1137,7 +1137,7 @@ parseMember(Object* t, Object* p, Object* declarations)
|
||||
bool isNew;
|
||||
Object* member = parseMember(t, cdr(cdr(p)), declarations, &isNew);
|
||||
memberName(member) = string(car(cdr(p)));
|
||||
return isNew ? member : 0;
|
||||
return 0;
|
||||
} else {
|
||||
return Scalar::make(t, declaration(spec, declarations), spec,
|
||||
string(car(cdr(p))),
|
||||
|
@ -37,11 +37,6 @@
|
||||
|
||||
(type fieldAddendum avian/FieldAddendum)
|
||||
|
||||
(type nativeMethodData
|
||||
(void* function)
|
||||
(uint16_t argumentTableSize)
|
||||
(array uint8_t parameterTypes))
|
||||
|
||||
(type pointer
|
||||
(void* value))
|
||||
|
||||
|
16
src/util.cpp
16
src/util.cpp
@ -318,8 +318,7 @@ hashMapFindNode(Thread* t, object map, object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
|
||||
|
||||
object array = hashMapArray(t, map);
|
||||
if (array) {
|
||||
@ -367,9 +366,7 @@ hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
|
||||
}
|
||||
|
||||
if (oldArray) {
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
|
||||
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
|
||||
for (unsigned i = 0; i < arrayLength(t, oldArray); ++i) {
|
||||
object next;
|
||||
for (object p = arrayBody(t, oldArray, i); p; p = next) {
|
||||
@ -407,8 +404,7 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
||||
|
||||
uint32_t h = hash(t, key);
|
||||
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
|
||||
|
||||
object array = hashMapArray(t, map);
|
||||
|
||||
@ -432,7 +428,8 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
||||
object r = makeWeakReference(t, 0, 0, 0, 0);
|
||||
jreferenceTarget(t, r) = key;
|
||||
jreferenceVmNext(t, r) = t->m->weakReferences;
|
||||
k = t->m->weakReferences = r;
|
||||
t->m->weakReferences = r;
|
||||
k = r;
|
||||
|
||||
array = hashMapArray(t, map);
|
||||
}
|
||||
@ -465,8 +462,7 @@ hashMapRemove(Thread* t, object map, object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType);
|
||||
|
||||
object array = hashMapArray(t, map);
|
||||
object o = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user