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