preliminary support for using OpenJDK's class library

Whereas the GNU Classpath port used the strategy of patching Classpath
with core classes from Avian so as to minimize changes to the VM, this
port uses the opposite strategy: abstract and isolate
classpath-specific features in the VM similar to how we abstract away
platform-specific features in system.h.  This allows us to use an
unmodified copy of OpenJDK's class library, including its core classes
and augmented by a few VM-specific classes in the "avian" package.
This commit is contained in:
Joel Dice 2010-09-10 15:05:29 -06:00
parent 17c1a552d5
commit cddea7187d
36 changed files with 4452 additions and 1603 deletions

View File

@ -0,0 +1,268 @@
/* 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 avian;
import static avian.Stream.read1;
import static avian.Stream.read2;
import java.lang.reflect.Modifier;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class Classes {
private static final int LinkFlag = 1 << 8;
public static native VMClass defineVMClass
(ClassLoader loader, byte[] b, int offset, int length);
public static native VMClass vmClass(Object o);
public static native VMClass primitiveClass(char name);
public static native void initialize(VMClass vmClass);
public static native boolean isAssignableFrom(VMClass a, VMClass b);
public static native VMClass getVMClass(Object o);
private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec)
throws ClassNotFoundException;
private static VMClass loadVMClass(ClassLoader loader,
byte[] nameBytes, int offset, int length)
{
byte[] spec = new byte[length + 1];
System.arraycopy(nameBytes, offset, spec, 0, length);
try {
VMClass c = resolveVMClass(loader, spec);
if (c == null) {
throw new NoClassDefFoundError();
}
return c;
} catch (ClassNotFoundException e) {
NoClassDefFoundError error = new NoClassDefFoundError
(new String(nameBytes, offset, length, false));
error.initCause(e);
throw error;
}
}
private static Object parseAnnotationValue(ClassLoader loader,
Object pool,
InputStream in)
throws IOException
{
switch (read1(in)) {
case 'Z':
return Boolean.valueOf(Singleton.getInt(pool, read2(in) - 1) != 0);
case 'B':
return Byte.valueOf((byte) Singleton.getInt(pool, read2(in) - 1));
case 'C':
return Character.valueOf((char) Singleton.getInt(pool, read2(in) - 1));
case 'S':
return Short.valueOf((short) Singleton.getInt(pool, read2(in) - 1));
case 'I':
return Integer.valueOf(Singleton.getInt(pool, read2(in) - 1));
case 'F':
return Float.valueOf
(Float.intBitsToFloat(Singleton.getInt(pool, read2(in) - 1)));
case 'J': {
return Long.valueOf(Singleton.getLong(pool, read2(in) - 1));
}
case 'D': {
return Double.valueOf
(Double.longBitsToDouble(Singleton.getLong(pool, read2(in) - 1)));
}
case 's': {
byte[] data = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return new String(data, 0, data.length - 1, false);
}
case 'e': {
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return Enum.valueOf
(getClass(loadVMClass(loader, typeName, 1, typeName.length - 3)),
new String(name, 0, name.length - 1, false));
}
case 'c':{
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return getClass(loadVMClass(loader, name, 1, name.length - 3));
}
case '@':
return parseAnnotation(loader, pool, in);
case '[': {
Object[] array = new Object[read2(in)];
for (int i = 0; i < array.length; ++i) {
array[i] = parseAnnotationValue(loader, pool, in);
}
return array;
}
default: throw new AssertionError();
}
}
private static Object[] parseAnnotation(ClassLoader loader,
Object pool,
InputStream in)
throws IOException
{
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
Object[] annotation = new Object[(read2(in) + 1) * 2];
annotation[1] = getClass
(loadVMClass(loader, typeName, 1, typeName.length - 3));
for (int i = 2; i < annotation.length; i += 2) {
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
annotation[i] = new String(name, 0, name.length - 1, false);
annotation[i + 1] = parseAnnotationValue(loader, pool, in);
}
return annotation;
}
private static Object[] parseAnnotationTable(ClassLoader loader,
Object pool,
InputStream in)
throws IOException
{
Object[] table = new Object[read2(in)];
for (int i = 0; i < table.length; ++i) {
table[i] = parseAnnotation(loader, pool, in);
}
return table;
}
private static void parseAnnotationTable(ClassLoader loader,
Addendum addendum)
{
if (addendum != null && addendum.annotationTable instanceof byte[]) {
try {
addendum.annotationTable = parseAnnotationTable
(loader, addendum.pool, new ByteArrayInputStream
((byte[]) addendum.annotationTable));
} catch (IOException e) {
AssertionError error = new AssertionError();
error.initCause(e);
throw error;
}
}
}
private static int resolveSpec(ClassLoader loader, byte[] spec, int start) {
int result;
int end;
switch (spec[start]) {
case 'L':
++ start;
end = start;
while (spec[end] != ';') ++ end;
result = end + 1;
break;
case '[':
end = start + 1;
while (spec[end] == '[') ++ end;
switch (spec[end]) {
case 'L':
++ end;
while (spec[end] != ';') ++ end;
++ end;
break;
default:
++ end;
}
result = end;
break;
default:
return start + 1;
}
loadVMClass(loader, spec, start, end - start);
return result;
}
public static void link(VMClass c, ClassLoader loader) {
acquireClassLock();
try {
if ((c.vmFlags & LinkFlag) == 0) {
if (c.super_ != null) {
link(c.super_, loader);
}
parseAnnotationTable(loader, c.addendum);
if (c.interfaceTable != null) {
int stride = ((c.flags & Modifier.INTERFACE) != 0 ? 1 : 2);
for (int i = 0; i < c.interfaceTable.length; i += stride) {
link((VMClass) c.interfaceTable[i], loader);
}
}
if (c.methodTable != null) {
for (int i = 0; i < c.methodTable.length; ++i) {
VMMethod m = c.methodTable[i];
for (int j = 1; j < m.spec.length;) {
j = resolveSpec(loader, m.spec, j);
}
parseAnnotationTable(loader, m.addendum);
}
}
if (c.fieldTable != null) {
for (int i = 0; i < c.fieldTable.length; ++i) {
VMField f = c.fieldTable[i];
resolveSpec(loader, f.spec, 0);
parseAnnotationTable(loader, f.addendum);
}
}
c.vmFlags |= LinkFlag;
}
} finally {
releaseClassLock();
}
}
public static void link(VMClass c) {
link(c, c.loader);
}
private static native void acquireClassLock();
private static native void releaseClassLock();
}

View File

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

View File

@ -0,0 +1,15 @@
/* Copyright (c) 2009-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 avian;
public class MethodAddendum extends Addendum {
public Object exceptionTable;
}

View File

@ -10,24 +10,10 @@
package avian; package avian;
import static avian.Stream.read1;
import static avian.Stream.read2;
import java.lang.reflect.Modifier;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.net.URL; import java.net.URL;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class SystemClassLoader extends ClassLoader { public class SystemClassLoader extends ClassLoader {
private static final int LinkFlag = 1 << 8;
public static native VMClass defineVMClass
(ClassLoader loader, byte[] b, int offset, int length);
private static native VMClass findVMClass(String name) private static native VMClass findVMClass(String name)
throws ClassNotFoundException; throws ClassNotFoundException;
@ -35,6 +21,8 @@ public class SystemClassLoader extends ClassLoader {
return getClass(findVMClass(name)); return getClass(findVMClass(name));
} }
public static native Class getClass(VMClass vmClass);
private static native VMClass findLoadedVMClass(String name); private static native VMClass findLoadedVMClass(String name);
protected Class reallyFindLoadedClass(String name){ protected Class reallyFindLoadedClass(String name){
@ -44,9 +32,6 @@ public class SystemClassLoader extends ClassLoader {
private static native boolean resourceExists(String name); private static native boolean resourceExists(String name);
private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec)
throws ClassNotFoundException;
protected URL findResource(String name) { protected URL findResource(String name) {
if (resourceExists(name)) { if (resourceExists(name)) {
try { try {
@ -55,261 +40,4 @@ public class SystemClassLoader extends ClassLoader {
} }
return null; return null;
} }
private static VMClass loadVMClass(ClassLoader loader,
byte[] nameBytes, int offset, int length)
{
byte[] spec = new byte[length + 1];
System.arraycopy(nameBytes, offset, spec, 0, length);
try {
VMClass c = resolveVMClass(loader, spec);
if (c == null) {
throw new NoClassDefFoundError();
}
return c;
} catch (ClassNotFoundException e) {
NoClassDefFoundError error = new NoClassDefFoundError
(new String(nameBytes, offset, length, false));
error.initCause(e);
throw error;
}
}
private static Object parseAnnotationValue(ClassLoader loader,
Object pool,
InputStream in)
throws IOException
{
switch (read1(in)) {
case 'Z':
return Boolean.valueOf(Singleton.getInt(pool, read2(in) - 1) != 0);
case 'B':
return Byte.valueOf((byte) Singleton.getInt(pool, read2(in) - 1));
case 'C':
return Character.valueOf((char) Singleton.getInt(pool, read2(in) - 1));
case 'S':
return Short.valueOf((short) Singleton.getInt(pool, read2(in) - 1));
case 'I':
return Integer.valueOf(Singleton.getInt(pool, read2(in) - 1));
case 'F':
return Float.valueOf
(Float.intBitsToFloat(Singleton.getInt(pool, read2(in) - 1)));
case 'J': {
return Long.valueOf(Singleton.getLong(pool, read2(in) - 1));
}
case 'D': {
return Double.valueOf
(Double.longBitsToDouble(Singleton.getLong(pool, read2(in) - 1)));
}
case 's': {
byte[] data = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return new String(data, 0, data.length - 1, false);
}
case 'e': {
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return Enum.valueOf
(getClass(loadVMClass(loader, typeName, 1, typeName.length - 3)),
new String(name, 0, name.length - 1, false));
}
case 'c':{
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
return getClass(loadVMClass(loader, name, 1, name.length - 3));
}
case '@':
return parseAnnotation(loader, pool, in);
case '[': {
Object[] array = new Object[read2(in)];
for (int i = 0; i < array.length; ++i) {
array[i] = parseAnnotationValue(loader, pool, in);
}
return array;
}
default: throw new AssertionError();
}
}
private static Object[] parseAnnotation(ClassLoader loader,
Object pool,
InputStream in)
throws IOException
{
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
Object[] annotation = new Object[(read2(in) + 1) * 2];
annotation[1] = getClass
(loadVMClass(loader, typeName, 1, typeName.length - 3));
for (int i = 2; i < annotation.length; i += 2) {
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
annotation[i] = new String(name, 0, name.length - 1, false);
annotation[i + 1] = parseAnnotationValue(loader, pool, in);
}
return annotation;
}
private static Object[] parseAnnotationTable(ClassLoader loader,
Object pool,
InputStream in)
throws IOException
{
Object[] table = new Object[read2(in)];
for (int i = 0; i < table.length; ++i) {
table[i] = parseAnnotation(loader, pool, in);
}
return table;
}
private static void parseAnnotationTable(ClassLoader loader,
Addendum addendum)
{
if (addendum != null && addendum.annotationTable instanceof byte[]) {
try {
addendum.annotationTable = parseAnnotationTable
(loader, addendum.pool, new ByteArrayInputStream
((byte[]) addendum.annotationTable));
} catch (IOException e) {
AssertionError error = new AssertionError();
error.initCause(e);
throw error;
}
addendum.pool = null;
}
}
private static int resolveSpec(ClassLoader loader, byte[] spec, int start) {
int result;
int end;
switch (spec[start]) {
case 'L':
++ start;
end = start;
while (spec[end] != ';') ++ end;
result = end + 1;
break;
case '[':
end = start + 1;
while (spec[end] == '[') ++ end;
switch (spec[end]) {
case 'L':
++ end;
while (spec[end] != ';') ++ end;
++ end;
break;
default:
++ end;
}
result = end;
break;
default:
return start + 1;
}
loadVMClass(loader, spec, start, end - start);
return result;
}
private static native void acquireClassLock();
private static native void releaseClassLock();
public static Class getClass(VMClass vmClass) {
if (vmClass.addendum == null) {
SystemClassLoader.acquireClassLock();
try {
if (vmClass.addendum == null) {
vmClass.addendum = new ClassAddendum();
}
} finally {
SystemClassLoader.releaseClassLock();
}
}
if (vmClass.addendum.class_ == null) {
SystemClassLoader.acquireClassLock();
try {
if (vmClass.addendum.class_ == null) {
vmClass.addendum.class_ = new Class(vmClass);
}
} finally {
SystemClassLoader.releaseClassLock();
}
}
return vmClass.addendum.class_;
}
public static native VMClass getVMClass(Object o);
public static void link(VMClass c, ClassLoader loader) {
acquireClassLock();
try {
if ((c.vmFlags & LinkFlag) == 0) {
if (c.super_ != null) {
link(c.super_, loader);
}
parseAnnotationTable(loader, c.addendum);
if (c.interfaceTable != null) {
int stride = ((c.flags & Modifier.INTERFACE) != 0 ? 1 : 2);
for (int i = 0; i < c.interfaceTable.length; i += stride) {
link((VMClass) c.interfaceTable[i], loader);
}
}
if (c.methodTable != null) {
for (int i = 0; i < c.methodTable.length; ++i) {
VMMethod m = c.methodTable[i];
for (int j = 1; j < m.spec.length;) {
j = resolveSpec(loader, m.spec, j);
}
parseAnnotationTable(loader, m.addendum);
}
}
if (c.fieldTable != null) {
for (int i = 0; i < c.fieldTable.length; ++i) {
VMField f = c.fieldTable[i];
resolveSpec(loader, f.spec, 0);
parseAnnotationTable(loader, f.addendum);
}
}
c.vmFlags |= LinkFlag;
}
} finally {
releaseClassLock();
}
}
public static void link(VMClass c) {
link(c, c.loader);
}
} }

View File

@ -17,6 +17,6 @@ public class VMField {
public short offset; public short offset;
public byte[] name; public byte[] name;
public byte[] spec; public byte[] spec;
public avian.Addendum addendum; public FieldAddendum addendum;
public VMClass class_; public VMClass class_;
} }

View File

@ -20,7 +20,7 @@ public class VMMethod {
public int nativeID; public int nativeID;
public byte[] name; public byte[] name;
public byte[] spec; public byte[] spec;
public avian.Addendum addendum; public MethodAddendum addendum;
public VMClass class_; public VMClass class_;
public Object code; public Object code;
} }

View File

@ -34,6 +34,10 @@ public class Handler extends URLStreamHandler {
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
return new ResourceInputStream(url.getFile()); return new ResourceInputStream(url.getFile());
} }
public void connect() {
// ignore
}
} }
private static class ResourceInputStream extends InputStream { private static class ResourceInputStream extends InputStream {

View File

@ -11,7 +11,6 @@
#include "math.h" #include "math.h"
#include "stdlib.h" #include "stdlib.h"
#include "time.h" #include "time.h"
#include "time.h"
#include "string.h" #include "string.h"
#include "stdio.h" #include "stdio.h"
#include "jni.h" #include "jni.h"

View File

@ -47,8 +47,6 @@ public final class Class <T>
this.vmClass = vmClass; this.vmClass = vmClass;
} }
public static native VMClass vmClass(Object o);
public String toString() { public String toString() {
return getName(); return getName();
} }
@ -71,23 +69,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 == primitiveClass('V')) { if (c == SystemClassLoader.primitiveClass('V')) {
c.name = "void\0".getBytes(); c.name = "void\0".getBytes();
} else if (c == primitiveClass('Z')) { } else if (c == SystemClassLoader.primitiveClass('Z')) {
c.name = "boolean\0".getBytes(); c.name = "boolean\0".getBytes();
} else if (c == primitiveClass('B')) { } else if (c == SystemClassLoader.primitiveClass('B')) {
c.name = "byte\0".getBytes(); c.name = "byte\0".getBytes();
} else if (c == primitiveClass('C')) { } else if (c == SystemClassLoader.primitiveClass('C')) {
c.name = "char\0".getBytes(); c.name = "char\0".getBytes();
} else if (c == primitiveClass('S')) { } else if (c == SystemClassLoader.primitiveClass('S')) {
c.name = "short\0".getBytes(); c.name = "short\0".getBytes();
} else if (c == primitiveClass('I')) { } else if (c == SystemClassLoader.primitiveClass('I')) {
c.name = "int\0".getBytes(); c.name = "int\0".getBytes();
} else if (c == primitiveClass('F')) { } else if (c == SystemClassLoader.primitiveClass('F')) {
c.name = "float\0".getBytes(); c.name = "float\0".getBytes();
} else if (c == primitiveClass('J')) { } else if (c == SystemClassLoader.primitiveClass('J')) {
c.name = "long\0".getBytes(); c.name = "long\0".getBytes();
} else if (c == primitiveClass('D')) { } else if (c == SystemClassLoader.primitiveClass('D')) {
c.name = "double\0".getBytes(); c.name = "double\0".getBytes();
} else { } else {
throw new AssertionError(); throw new AssertionError();
@ -154,15 +152,11 @@ public final class Class <T>
Class c = loader.loadClass(name); Class c = loader.loadClass(name);
SystemClassLoader.link(c.vmClass, loader); SystemClassLoader.link(c.vmClass, loader);
if (initialize) { if (initialize) {
initialize(c.vmClass); SystemClassLoader.initialize(c.vmClass);
} }
return c; return c;
} }
private static native VMClass primitiveClass(char name);
private static native void initialize(VMClass vmClass);
public static Class forCanonicalName(String name) { public static Class forCanonicalName(String name) {
return forCanonicalName(null, name); return forCanonicalName(null, name);
} }
@ -175,7 +169,8 @@ public final class Class <T>
return forName(name.substring(1, name.length() - 1), true, loader); return forName(name.substring(1, name.length() - 1), true, loader);
} else { } else {
if (name.length() == 1) { if (name.length() == 1) {
return SystemClassLoader.getClass(primitiveClass(name.charAt(0))); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass(name.charAt(0)));
} else { } else {
throw new ClassNotFoundException(name); throw new ClassNotFoundException(name);
} }
@ -189,21 +184,29 @@ 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(primitiveClass('Z')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('Z'));
} else if ("[B".equals(n)) { } else if ("[B".equals(n)) {
return SystemClassLoader.getClass(primitiveClass('B')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('B'));
} else if ("[S".equals(n)) { } else if ("[S".equals(n)) {
return SystemClassLoader.getClass(primitiveClass('S')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('S'));
} else if ("[C".equals(n)) { } else if ("[C".equals(n)) {
return SystemClassLoader.getClass(primitiveClass('C')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('C'));
} else if ("[I".equals(n)) { } else if ("[I".equals(n)) {
return SystemClassLoader.getClass(primitiveClass('I')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('I'));
} else if ("[F".equals(n)) { } else if ("[F".equals(n)) {
return SystemClassLoader.getClass(primitiveClass('F')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('F'));
} else if ("[J".equals(n)) { } else if ("[J".equals(n)) {
return SystemClassLoader.getClass(primitiveClass('J')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('J'));
} else if ("[D".equals(n)) { } else if ("[D".equals(n)) {
return SystemClassLoader.getClass(primitiveClass('D')); return SystemClassLoader.getClass
(SystemClassLoader.primitiveClass('D'));
} }
if (vmClass.staticTable == null) throw new AssertionError(); if (vmClass.staticTable == null) throw new AssertionError();
@ -213,10 +216,8 @@ public final class Class <T>
} }
} }
public static native boolean isAssignableFrom(VMClass a, VMClass b);
public boolean isAssignableFrom(Class c) { public boolean isAssignableFrom(Class c) {
return isAssignableFrom(vmClass, c.vmClass); return SystemClassLoader.isAssignableFrom(vmClass, c.vmClass);
} }
private static Field findField(VMClass vmClass, String name) { private static Field findField(VMClass vmClass, String name) {
@ -533,7 +534,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 && isAssignableFrom(c, SystemClassLoader.getVMClass(o)); return o != null && SystemClassLoader.isAssignableFrom
(c, SystemClassLoader.getVMClass(o));
} }
public boolean isInstance(Object o) { public boolean isInstance(Object o) {

View File

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

View File

@ -56,7 +56,7 @@ public class StackTraceElement {
} }
public String getClassName() { public String getClassName() {
return class_.replace('/', '.'); return class_;
} }
public String getMethodName() { public String getMethodName() {

View File

@ -12,13 +12,12 @@ package java.lang.ref;
public class ReferenceQueue<T> { public class ReferenceQueue<T> {
private Reference<? extends T> front; private Reference<? extends T> front;
private Reference<? extends T> rear;
public Reference<? extends T> poll() { public Reference<? extends T> poll() {
Reference<? extends T> r = front; Reference<? extends T> r = front;
if (front != null) { if (front != null) {
if (front == front.jNext) { if (front == front.jNext) {
front = rear = null; front = null;
} else { } else {
front = front.jNext; front = front.jNext;
} }
@ -27,12 +26,11 @@ public class ReferenceQueue<T> {
} }
void add(Reference<? extends T> r) { void add(Reference<? extends T> r) {
r.jNext = r;
if (front == null) { if (front == null) {
front = r; r.jNext = r;
} else { } else {
rear.jNext = r; r.jNext = front;
} }
rear = r; front = r;
} }
} }

View File

@ -204,7 +204,7 @@ public class Field<T> extends AccessibleObject {
} else { } else {
throw new IllegalArgumentException throw new IllegalArgumentException
("needed " + getType() + ", got " ("needed " + getType() + ", got "
+ Class.getName(Class.vmClass(target)) + + Class.getName(SystemClassLoader.vmClass(target)) +
" when setting " + Class.getName(vmField.class_) + "." + getName()); " when setting " + Class.getName(vmField.class_) + "." + getName());
} }
break; break;

191
makefile
View File

@ -1,4 +1,4 @@
MAKEFLAGS = -s #MAKEFLAGS = -s
name = avian name = avian
version = 0.3 version = 0.3
@ -39,11 +39,17 @@ endif
ifeq ($(continuations),true) ifeq ($(continuations),true)
options := $(options)-continuations options := $(options)-continuations
endif endif
classpath = avian
test-library-path = .
test-executable = $(executable)
ifdef gnu ifdef gnu
classpath = gnu
options := $(options)-gnu options := $(options)-gnu
gnu-sources = $(src)/gnu.cpp classapth-jar = $(gnu)/share/classpath/glibj.zip
gnu-jar = $(gnu)/share/classpath/glibj.zip classpath-libraries = \
gnu-libraries = \
$(gnu)/lib/classpath/libjavaio.a \ $(gnu)/lib/classpath/libjavaio.a \
$(gnu)/lib/classpath/libjavalang.a \ $(gnu)/lib/classpath/libjavalang.a \
$(gnu)/lib/classpath/libjavalangreflect.a \ $(gnu)/lib/classpath/libjavalangreflect.a \
@ -51,10 +57,20 @@ ifdef gnu
$(gnu)/lib/classpath/libjavanet.a \ $(gnu)/lib/classpath/libjavanet.a \
$(gnu)/lib/classpath/libjavanio.a \ $(gnu)/lib/classpath/libjavanio.a \
$(gnu)/lib/classpath/libjavautil.a $(gnu)/lib/classpath/libjavautil.a
gnu-object-dep = $(build)/gnu-object.dep classpath-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU
gnu-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU classpath-lflags = -lgmp
gnu-lflags = -lgmp endif
gnu-objects = $(shell find $(build)/gnu-objects -name "*.o") ifdef openjdk
classpath = openjdk
options := $(options)-openjdk
ifeq ($(arch),x86_64)
openjdk-lib-dir = $(openjdk)/jre/lib/amd64
else
openjdk-lib-dir = $(openjdk)/jre/lib
endif
classpath-jar = $(openjdk)/jre/lib/rt.jar
test-library-path = $(openjdk-lib-dir):$(native-build)
test-executable = $(executable-dynamic)
endif endif
root := $(shell (cd .. && pwd)) root := $(shell (cd .. && pwd))
@ -63,13 +79,16 @@ native-build = $(build)/$(platform)-$(arch)$(options)
classpath-build = $(build)/classpath classpath-build = $(build)/classpath
test-build = $(build)/test test-build = $(build)/test
src = src src = src
classpath = classpath classpath-src = classpath
test = test test = test
ifdef gnu ifneq ($(classpath),avian)
avian-classpath-build = $(build)/avian-classpath classpath-object-dep = $(build)/classpath-object.dep
classpath-objects = $(shell find $(build)/classpath-objects -name "*.o")
else else
avian-classpath-build = $(classpath-build) jni-sources := $(shell find $(classpath-src) -name '*.cpp')
jni-objects = \
$(call cpp-objects,$(jni-sources),$(classpath-src),$(native-build))
endif endif
input = List input = List
@ -112,14 +131,14 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \ common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \ "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
-DUSE_ATOMIC_OPERATIONS $(gnu-cflags) -DUSE_ATOMIC_OPERATIONS $(classpath-cflags)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
cflags = $(build-cflags) cflags = $(build-cflags)
common-lflags = -lm -lz $(gnu-lflags) common-lflags = -lm -lz $(classpath-lflags)
build-lflags = build-lflags =
@ -297,9 +316,6 @@ cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x)))
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x)))
java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x)))
jni-sources := $(shell find $(classpath) -name '*.cpp')
jni-objects = $(call cpp-objects,$(jni-sources),$(classpath),$(native-build))
generated-code = \ generated-code = \
$(native-build)/type-enums.cpp \ $(native-build)/type-enums.cpp \
$(native-build)/type-declarations.cpp \ $(native-build)/type-declarations.cpp \
@ -307,26 +323,7 @@ generated-code = \
$(native-build)/type-initializations.cpp \ $(native-build)/type-initializations.cpp \
$(native-build)/type-java-initializations.cpp $(native-build)/type-java-initializations.cpp
vm-depends = \ vm-depends := $(generated-code) $(wildcard $(src)/*.h)
$(generated-code) \
$(src)/allocator.h \
$(src)/common.h \
$(src)/system.h \
$(src)/heap.h \
$(src)/finder.h \
$(src)/processor.h \
$(src)/process.h \
$(src)/stream.h \
$(src)/constants.h \
$(src)/jnienv.h \
$(src)/machine.h \
$(src)/util.h \
$(src)/zone.h \
$(src)/assembler.h \
$(src)/compiler.h \
$(src)/$(asm).h \
$(src)/heapwalk.h \
$(src)/bootimage.h
vm-sources = \ vm-sources = \
$(src)/$(system).cpp \ $(src)/$(system).cpp \
@ -335,10 +332,10 @@ vm-sources = \
$(src)/util.cpp \ $(src)/util.cpp \
$(src)/heap.cpp \ $(src)/heap.cpp \
$(src)/$(process).cpp \ $(src)/$(process).cpp \
$(src)/classpath-$(classpath).cpp \
$(src)/builtin.cpp \ $(src)/builtin.cpp \
$(src)/jnienv.cpp \ $(src)/jnienv.cpp \
$(src)/process.cpp \ $(src)/process.cpp
$(gnu-sources)
vm-asm-sources = $(src)/$(asm).S vm-asm-sources = $(src)/$(asm).S
@ -428,48 +425,37 @@ converter = $(native-build)/binaryToObject
static-library = $(native-build)/lib$(name).a static-library = $(native-build)/lib$(name).a
executable = $(native-build)/$(name)${exe-suffix} executable = $(native-build)/$(name)${exe-suffix}
dynamic-library = $(native-build)/$(so-prefix)$(name)$(so-suffix) dynamic-library = $(native-build)/$(so-prefix)jvm$(so-suffix)
executable-dynamic = $(native-build)/$(name)-dynamic${exe-suffix} executable-dynamic = $(native-build)/$(name)-dynamic${exe-suffix}
classpath-sources := $(shell find $(classpath) -name '*.java') ifneq ($(classpath),avian)
classpath-sources := \
$(classpath-src)/avian/Continuations.java \
$(classpath-src)/avian/Callback.java \
$(classpath-src)/avian/CallbackReceiver.java \
$(classpath-src)/avian/IncompatibleContinuationException.java \
$(classpath-src)/avian/SystemClassLoader.java \
$(classpath-src)/avian/Machine.java \
$(classpath-src)/avian/Addendum.java \
$(classpath-src)/avian/ClassAddendum.java \
$(classpath-src)/avian/MethodAddendum.java \
$(classpath-src)/avian/FieldAddendum.java \
$(classpath-src)/avian/VMClass.java \
$(classpath-src)/avian/VMField.java \
$(classpath-src)/avian/VMMethod.java \
$(classpath-src)/avian/resource/Handler.java
else
classpath-sources := $(shell find $(classpath-src) -name '*.java')
endif
classpath-classes = \ classpath-classes = \
$(call java-classes,$(classpath-sources),$(classpath),$(classpath-build)) $(call java-classes,$(classpath-sources),$(classpath-src),$(classpath-build))
classpath-object = $(native-build)/classpath-jar.o classpath-object = $(native-build)/classpath-jar.o
classpath-dep = $(classpath-build).dep classpath-dep = $(classpath-build).dep
gnu-blacklist = \ vm-classes = \
java/lang/AbstractStringBuffer.class \
java/lang/reflect/Proxy.class
gnu-overrides = \
avian/*.class \ avian/*.class \
avian/resource/*.class \ avian/resource/*.class
java/lang/Class.class \
java/lang/Enum.class \
java/lang/InheritableThreadLocal.class \
java/lang/Object.class \
java/lang/StackTraceElement.class \
java/lang/String.class \
java/lang/String\$$*.class \
java/lang/StringBuffer.class \
java/lang/StringBuilder.class \
java/lang/StringBuilder\$$*.class \
java/lang/Thread.class \
java/lang/Thread\$$*.class \
java/lang/ThreadGroup.class \
java/lang/ThreadLocal.class \
java/lang/Throwable.class \
java/lang/ref/PhantomReference.class \
java/lang/ref/Reference.class \
java/lang/ref/ReferenceQueue.class \
java/lang/ref/SoftReference.class \
java/lang/ref/WeakReference.class \
java/lang/reflect/AccessibleObject.class \
java/lang/reflect/Constructor.class \
java/lang/reflect/Field.class \
java/lang/reflect/Method.class \
java/lang/reflect/Proxy.class \
java/lang/reflect/Proxy\$$*.class
test-sources = $(wildcard $(test)/*.java) test-sources = $(wildcard $(test)/*.java)
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build)) test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
@ -510,7 +496,7 @@ vg: build
.PHONY: test .PHONY: test
test: build test: build
/bin/sh $(test)/test.sh 2>/dev/null \ /bin/sh $(test)/test.sh 2>/dev/null \
$(executable) $(mode) "$(flags)" \ $(test-library-path) $(test-executable) $(mode) "$(flags)" \
$(call class-names,$(test-build),$(test-classes)) $(call class-names,$(test-build),$(test-classes))
.PHONY: tarball .PHONY: tarball
@ -549,27 +535,20 @@ $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep)
$(native-build)/type-generator.o: \ $(native-build)/type-generator.o: \
$(generator-headers) $(generator-headers)
$(classpath-build)/%.class: $(classpath)/%.java $(classpath-build)/%.class: $(classpath-src)/%.java
@echo $(<) @echo $(<)
$(classpath-dep): $(classpath-sources) $(gnu-jar) $(classpath-dep): $(classpath-sources) $(classpath-jar)
@echo "compiling classpath classes" @echo "compiling classpath classes"
@mkdir -p $(avian-classpath-build)
$(javac) -d $(avian-classpath-build) \
-bootclasspath $(avian-classpath-build) \
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
ifdef gnu
(wd=$$(pwd) && \
cd $(avian-classpath-build) && \
$(jar) c0f "$$($(native-path) "$${wd}/$(build)/overrides.jar")" \
$(gnu-overrides))
@mkdir -p $(classpath-build) @mkdir -p $(classpath-build)
ifneq ($(classpath),avian)
(wd=$$(pwd) && \ (wd=$$(pwd) && \
cd $(classpath-build) && \ cd $(classpath-build) && \
$(jar) xf $(gnu-jar) && \ $(jar) xf $(classpath-jar))
rm $(gnu-blacklist) && \
jar xf "$$($(native-path) "$${wd}/$(build)/overrides.jar")")
endif endif
$(javac) -d $(classpath-build) \
-bootclasspath $(classpath-build) \
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
@touch $(@) @touch $(@)
$(test-build)/%.class: $(test)/%.java $(test-build)/%.class: $(test)/%.java
@ -625,7 +604,7 @@ $(driver-object): $(driver-source)
$(driver-dynamic-object): $(driver-source) $(driver-dynamic-object): $(driver-source)
@echo "compiling $(@)" @echo "compiling $(@)"
@mkdir -p $(dir $(@)) @mkdir -p $(dir $(@))
$(cxx) $(cflags) -DBOOT_LIBRARY=\"$(so-prefix)$(name)$(so-suffix)\" \ $(cxx) $(cflags) -DBOOT_LIBRARY=\"$(so-prefix)jvm$(so-suffix)\" \
-c $(<) $(call output,$(@)) -c $(<) $(call output,$(@))
$(boot-object): $(boot-source) $(boot-object): $(boot-source)
@ -668,14 +647,14 @@ $(generator-objects): $(native-build)/%.o: $(src)/%.cpp
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \
-c $(<) -o $(@) -c $(<) -o $(@)
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp $(jni-objects): $(native-build)/%.o: $(classpath-src)/%.cpp
$(compile-object) $(compile-object)
$(static-library): $(gnu-object-dep) $(static-library): $(classpath-object-dep)
$(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects) $(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects)
@echo "creating $(@)" @echo "creating $(@)"
rm -rf $(@) rm -rf $(@)
$(ar) cru $(@) $(^) $(call gnu-objects) $(ar) cru $(@) $(^) $(call classpath-objects)
$(ranlib) $(@) $(ranlib) $(@)
$(bootimage-bin): $(bootimage-generator) $(bootimage-bin): $(bootimage-generator)
@ -687,13 +666,13 @@ $(bootimage-object): $(bootimage-bin) $(converter)
_binary_bootimage_bin_end $(platform) $(arch) $(pointer-size) \ _binary_bootimage_bin_end $(platform) $(arch) $(pointer-size) \
writable executable writable executable
$(gnu-object-dep): $(gnu-libraries) $(classpath-object-dep): $(classpath-libraries)
@mkdir -p $(build)/gnu-objects @mkdir -p $(build)/classpath-objects
(cd $(build)/gnu-objects && \ (cd $(build)/classpath-objects && \
for x in $(gnu-libraries); do ar x $${x}; done) for x in $(classpath-libraries); do ar x $${x}; done)
@touch $(@) @touch $(@)
$(executable): $(gnu-object-dep) $(executable): $(classpath-object-dep)
$(executable): \ $(executable): \
$(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \ $(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \
$(boot-object) $(vm-classpath-object) $(boot-object) $(vm-classpath-object)
@ -704,13 +683,13 @@ ifdef msvc
-MANIFESTFILE:$(@).manifest -MANIFESTFILE:$(@).manifest
$(mt) -manifest $(@).manifest -outputresource:"$(@);1" $(mt) -manifest $(@).manifest -outputresource:"$(@);1"
else else
$(dlltool) -z $(@).def $(^) $(call gnu-objects) $(dlltool) -z $(@).def $(^) $(call classpath-objects)
$(dlltool) -d $(@).def -e $(@).exp $(dlltool) -d $(@).def -e $(@).exp
$(ld) $(@).exp $(^) $(call gnu-objects) $(lflags) -o $(@) $(ld) $(@).exp $(^) $(call classpath-objects) $(lflags) -o $(@)
endif endif
else else
$(ld) $(^) $(call gnu-objects) $(rdynamic) $(lflags) $(bootimage-lflags) \ $(ld) $(^) $(call classpath-objects) $(rdynamic) $(lflags) \
-o $(@) $(bootimage-lflags) -o $(@)
endif endif
$(strip) $(strip-all) $(@) $(strip) $(strip-all) $(@)
@ -740,18 +719,18 @@ else
$(ld) $(^) $(rdynamic) $(lflags) -o $(@) $(ld) $(^) $(rdynamic) $(lflags) -o $(@)
endif endif
$(dynamic-library): $(gnu-object-dep) $(dynamic-library): $(classpath-object-dep)
$(dynamic-library): \ $(dynamic-library): \
$(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \ $(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \
$(boot-object) $(vm-classpath-object) $(gnu-libraries) $(boot-object) $(vm-classpath-object) $(classpath-libraries)
@echo "linking $(@)" @echo "linking $(@)"
ifdef msvc ifdef msvc
$(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \
-IMPLIB:$(native-build)/$(name).lib -MANIFESTFILE:$(@).manifest -IMPLIB:$(native-build)/$(name).lib -MANIFESTFILE:$(@).manifest
$(mt) -manifest $(@).manifest -outputresource:"$(@);2" $(mt) -manifest $(@).manifest -outputresource:"$(@);2"
else else
$(ld) $(^) $(call gnu-objects) $(shared) $(lflags) $(bootimage-lflags) \ $(ld) $(^) -Wl,--version-script=openjdk.ld \
-o $(@) $(call classpath-objects) $(shared) $(lflags) $(bootimage-lflags) -o $(@)
endif endif
$(strip) $(strip-all) $(@) $(strip) $(strip-all) $(@)

288
openjdk.ld Normal file
View File

@ -0,0 +1,288 @@
#
# @(#)mapfile-vers-product 1.19 08/02/12 10:56:37
#
#
# Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
#
# Define public interface.
SUNWprivate_1.1 {
global:
# JNI
JNI_CreateJavaVM;
JNI_GetCreatedJavaVMs;
JNI_GetDefaultJavaVMInitArgs;
# JVM
JVM_Accept;
JVM_ActiveProcessorCount;
JVM_AllocateNewArray;
JVM_AllocateNewObject;
JVM_ArrayCopy;
JVM_AssertionStatusDirectives;
JVM_Available;
JVM_Bind;
JVM_ClassDepth;
JVM_ClassLoaderDepth;
JVM_Clone;
JVM_Close;
JVM_CX8Field;
JVM_CompileClass;
JVM_CompileClasses;
JVM_CompilerCommand;
JVM_Connect;
JVM_ConstantPoolGetClassAt;
JVM_ConstantPoolGetClassAtIfLoaded;
JVM_ConstantPoolGetDoubleAt;
JVM_ConstantPoolGetFieldAt;
JVM_ConstantPoolGetFieldAtIfLoaded;
JVM_ConstantPoolGetFloatAt;
JVM_ConstantPoolGetIntAt;
JVM_ConstantPoolGetLongAt;
JVM_ConstantPoolGetMethodAt;
JVM_ConstantPoolGetMethodAtIfLoaded;
JVM_ConstantPoolGetMemberRefInfoAt;
JVM_ConstantPoolGetSize;
JVM_ConstantPoolGetStringAt;
JVM_ConstantPoolGetUTF8At;
JVM_CountStackFrames;
JVM_CurrentClassLoader;
JVM_CurrentLoadedClass;
JVM_CurrentThread;
JVM_CurrentTimeMillis;
JVM_DefineClass;
JVM_DefineClassWithSource;
JVM_DesiredAssertionStatus;
JVM_DisableCompiler;
JVM_DoPrivileged;
JVM_DTraceGetVersion;
JVM_DTraceActivate;
JVM_DTraceIsProbeEnabled;
JVM_DTraceIsSupported;
JVM_DTraceDispose;
JVM_DumpAllStacks;
JVM_DumpThreads;
JVM_EnableCompiler;
JVM_Exit;
JVM_FillInStackTrace;
JVM_FindClassFromClass;
JVM_FindClassFromClassLoader;
JVM_FindClassFromBootLoader;
JVM_FindLibraryEntry;
JVM_FindLoadedClass;
JVM_FindPrimitiveClass;
JVM_FindSignal;
JVM_FreeMemory;
JVM_GC;
JVM_GetAllThreads;
JVM_GetArrayElement;
JVM_GetArrayLength;
JVM_GetCPClassNameUTF;
JVM_GetCPFieldClassNameUTF;
JVM_GetCPFieldModifiers;
JVM_GetCPFieldNameUTF;
JVM_GetCPFieldSignatureUTF;
JVM_GetCPMethodClassNameUTF;
JVM_GetCPMethodModifiers;
JVM_GetCPMethodNameUTF;
JVM_GetCPMethodSignatureUTF;
JVM_GetCallerClass;
JVM_GetClassAccessFlags;
JVM_GetClassAnnotations;
JVM_GetClassCPEntriesCount;
JVM_GetClassCPTypes;
JVM_GetClassConstantPool;
JVM_GetClassContext;
JVM_GetClassDeclaredConstructors;
JVM_GetClassDeclaredFields;
JVM_GetClassDeclaredMethods;
JVM_GetClassFieldsCount;
JVM_GetClassInterfaces;
JVM_GetClassLoader;
JVM_GetClassMethodsCount;
JVM_GetClassModifiers;
JVM_GetClassName;
JVM_GetClassNameUTF;
JVM_GetClassSignature;
JVM_GetClassSigners;
JVM_GetComponentType;
JVM_GetDeclaredClasses;
JVM_GetDeclaringClass;
JVM_GetEnclosingMethodInfo;
JVM_GetFieldAnnotations;
JVM_GetFieldIxModifiers;
JVM_GetHostName;
JVM_GetInheritedAccessControlContext;
JVM_GetInterfaceVersion;
JVM_GetLastErrorString;
JVM_GetManagement;
JVM_GetMethodAnnotations;
JVM_GetMethodDefaultAnnotationValue;
JVM_GetMethodIxArgsSize;
JVM_GetMethodIxByteCode;
JVM_GetMethodIxByteCodeLength;
JVM_GetMethodIxExceptionIndexes;
JVM_GetMethodIxExceptionTableEntry;
JVM_GetMethodIxExceptionTableLength;
JVM_GetMethodIxExceptionsCount;
JVM_GetMethodIxLocalsCount;
JVM_GetMethodIxMaxStack;
JVM_GetMethodIxModifiers;
JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameterAnnotations;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetSockName;
JVM_GetSockOpt;
JVM_GetStackAccessControlContext;
JVM_GetStackTraceDepth;
JVM_GetStackTraceElement;
JVM_GetSystemPackage;
JVM_GetSystemPackages;
JVM_GetThreadStateNames;
JVM_GetThreadStateValues;
JVM_GetVersionInfo;
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InitializeCompiler;
JVM_InitializeSocketLibrary;
JVM_InternString;
JVM_Interrupt;
JVM_InvokeMethod;
JVM_IsArrayClass;
JVM_IsConstructorIx;
JVM_IsInterface;
JVM_IsInterrupted;
JVM_IsNaN;
JVM_IsPrimitiveClass;
JVM_IsSameClassPackage;
JVM_IsSilentCompiler;
JVM_IsSupportedJNIVersion;
JVM_IsThreadAlive;
JVM_LatestUserDefinedLoader;
JVM_Listen;
JVM_LoadClass0;
JVM_LoadLibrary;
JVM_Lseek;
JVM_MaxObjectInspectionAge;
JVM_MaxMemory;
JVM_MonitorNotify;
JVM_MonitorNotifyAll;
JVM_MonitorWait;
JVM_NanoTime;
JVM_NativePath;
JVM_NewArray;
JVM_NewInstanceFromConstructor;
JVM_NewMultiArray;
JVM_OnExit;
JVM_Open;
JVM_PrintStackTrace;
JVM_RaiseSignal;
JVM_RawMonitorCreate;
JVM_RawMonitorDestroy;
JVM_RawMonitorEnter;
JVM_RawMonitorExit;
JVM_Read;
JVM_Recv;
JVM_RecvFrom;
JVM_RegisterSignal;
JVM_ReleaseUTF;
JVM_ResolveClass;
JVM_ResumeThread;
JVM_Send;
JVM_SendTo;
JVM_SetArrayElement;
JVM_SetClassSigners;
JVM_SetLength;
JVM_SetPrimitiveArrayElement;
JVM_SetProtectionDomain;
JVM_SetSockOpt;
JVM_SetThreadPriority;
JVM_Sleep;
JVM_Socket;
JVM_SocketAvailable;
JVM_SocketClose;
JVM_SocketShutdown;
JVM_StartThread;
JVM_StopThread;
JVM_SuspendThread;
JVM_SupportsCX8;
JVM_Sync;
JVM_Timeout;
JVM_TotalMemory;
JVM_TraceInstructions;
JVM_TraceMethodCalls;
JVM_UnloadLibrary;
JVM_Write;
JVM_Yield;
JVM_handle_linux_signal;
# Old reflection routines
# These do not need to be present in the product build in JDK 1.4
# but their code has not been removed yet because there will not
# be a substantial code savings until JVM_InvokeMethod and
# JVM_NewInstanceFromConstructor can also be removed; see
# reflectionCompat.hpp.
JVM_GetClassConstructor;
JVM_GetClassConstructors;
JVM_GetClassField;
JVM_GetClassFields;
JVM_GetClassMethod;
JVM_GetClassMethods;
JVM_GetField;
JVM_GetPrimitiveField;
JVM_NewInstance;
JVM_SetField;
JVM_SetPrimitiveField;
# Needed for dropping VM into JDK 1.3.x, 1.4
_JVM_native_threads;
jdk_sem_init;
jdk_sem_post;
jdk_sem_wait;
jdk_pthread_sigmask;
jdk_waitpid;
# miscellaneous functions
jio_fprintf;
jio_printf;
jio_snprintf;
jio_vfprintf;
jio_vsnprintf;
fork1;
numa_warn;
numa_error;
# Needed because there is no JVM interface for this.
sysThreadAvailableStackWithSlack;
# This is for Forte Analyzer profiling support.
AsyncGetCallTrace;
};

View File

@ -39,135 +39,14 @@ search(Thread* t, object name, object (*op)(Thread*, object),
return reinterpret_cast<int64_t>(r); return reinterpret_cast<int64_t>(r);
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0; return 0;
} }
} }
void
enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
unsigned limit)
{
if (*index < limit) {
set(t, array, ArrayBody + (*index * BytesPerWord), x->javaThread);
++ (*index);
if (x->peer) enumerateThreads(t, x->peer, array, index, limit);
if (x->child) enumerateThreads(t, x->child, array, index, limit);
}
}
bool
compatibleArrayTypes(Thread* t, object a, object b)
{
return classArrayElementSize(t, a)
and classArrayElementSize(t, b)
and (a == b
or (not ((classVmFlags(t, a) & PrimitiveFlag)
or (classVmFlags(t, b) & PrimitiveFlag))));
}
void
runOnLoadIfFound(Thread* t, System::Library* library)
{
void* p = library->resolve("JNI_OnLoad");
if (p) {
jint (JNICALL * JNI_OnLoad)(Machine*, void*);
memcpy(&JNI_OnLoad, &p, sizeof(void*));
JNI_OnLoad(t->m, 0);
}
}
} // namespace } // namespace
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_toString
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
unsigned hash = objectHash(t, this_);
object s = makeString
(t, "%s@0x%x",
&byteArrayBody(t, className(t, objectClass(t, this_)), 0),
hash);
return reinterpret_cast<int64_t>(s);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_getVMClass
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(objectClass(t, o));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Object_wait
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
int64_t milliseconds; memcpy(&milliseconds, arguments + 1, 8);
vm::wait(t, this_, milliseconds);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Object_notify
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
notify(t, this_);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Object_notifyAll
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
notifyAll(t, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_hashCode
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
return objectHash(t, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_clone
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[0]);
PROTECT(t, o);
object class_ = objectClass(t, o);
unsigned size = baseSize(t, o, class_) * BytesPerWord;
object clone;
if (classArrayElementSize(t, class_)) {
clone = static_cast<object>(allocate(t, size, classObjectMask(t, class_)));
memcpy(clone, o, size);
// clear any object header flags:
setObjectClass(t, o, objectClass(t, o));
} else {
clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(o) + 1,
size - BytesPerWord);
}
return reinterpret_cast<int64_t>(clone);
}
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Avian_avian_SystemClassLoader_acquireClassLock Avian_avian_SystemClassLoader_acquireClassLock
(Thread* t, object, uintptr_t*) (Thread* t, object, uintptr_t*)
@ -195,8 +74,6 @@ Avian_avian_SystemClassLoader_defineVMClass
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
{ {
object loader = reinterpret_cast<object>(arguments[0]); object loader = reinterpret_cast<object>(arguments[0]);
PROTECT(t, loader);
object b = reinterpret_cast<object>(arguments[1]); object b = reinterpret_cast<object>(arguments[1]);
int offset = arguments[2]; int offset = arguments[2];
int length = arguments[3]; int length = arguments[3];
@ -204,20 +81,9 @@ Avian_avian_SystemClassLoader_defineVMClass
uint8_t* buffer = static_cast<uint8_t*> uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(length)); (t->m->heap->allocate(length));
memcpy(buffer, &byteArrayBody(t, b, offset), length); memcpy(buffer, &byteArrayBody(t, b, offset), length);
object c = parseClass(t, loader, buffer, length); object c = defineClass(t, loader, buffer, length);
t->m->heap->free(buffer, length); t->m->heap->free(buffer, length);
if (c) {
PROTECT(t, c);
if (getClassLoaderMap(t, loader) == 0) {
object map = makeHashMap(t, 0, 0);
set(t, loader, ClassLoaderMap, map);
}
hashMapInsert(t, getClassLoaderMap(t, loader), className(t, c), c,
byteArrayHash);
}
return reinterpret_cast<int64_t>(c); return reinterpret_cast<int64_t>(c);
} }
@ -260,62 +126,21 @@ Avian_avian_SystemClassLoader_resourceExists
stringChars(t, name, RUNTIME_ARRAY_BODY(n)); stringChars(t, name, RUNTIME_ARRAY_BODY(n));
return t->m->finder->exists(RUNTIME_ARRAY_BODY(n)); return t->m->finder->exists(RUNTIME_ARRAY_BODY(n));
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0; return 0;
} }
} }
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
Avian_java_io_ObjectInputStream_makeInstance Avian_avian_SystemClassLoader_primitiveClass
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
{ {
object c = reinterpret_cast<object>(arguments[0]); return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
return reinterpret_cast<int64_t>(make(t, c));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_primitiveClass
(Thread* t, object, uintptr_t* arguments)
{
char name = arguments[0];
switch (name) {
case 'B':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JbyteType));
case 'C':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JcharType));
case 'D':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JdoubleType));
case 'F':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JfloatType));
case 'I':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JintType));
case 'J':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JlongType));
case 'S':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JshortType));
case 'V':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JvoidType));
case 'Z':
return reinterpret_cast<int64_t>
(arrayBody(t, t->m->types, Machine::JbooleanType));
default:
t->exception = makeIllegalArgumentException(t);
return 0;
}
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_initialize Avian_avian_SystemClassLoader_initialize
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
{ {
object this_ = reinterpret_cast<object>(arguments[0]); object this_ = reinterpret_cast<object>(arguments[0]);
@ -324,7 +149,7 @@ Avian_java_lang_Class_initialize
} }
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_isAssignableFrom Avian_avian_SystemClassLoader_isAssignableFrom
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
{ {
object this_ = reinterpret_cast<object>(arguments[0]); object this_ = reinterpret_cast<object>(arguments[0]);
@ -333,392 +158,12 @@ Avian_java_lang_Class_isAssignableFrom
if (LIKELY(that)) { if (LIKELY(that)) {
return vm::isAssignableFrom(t, this_, that); return vm::isAssignableFrom(t, this_, that);
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0; return 0;
} }
} }
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Field_getPrimitive
(Thread* t, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int code = arguments[1];
int offset = arguments[2];
switch (code) {
case ByteField:
return cast<int8_t>(instance, offset);
case BooleanField:
return cast<uint8_t>(instance, offset);
case CharField:
return cast<uint16_t>(instance, offset);
case ShortField:
return cast<int16_t>(instance, offset);
case IntField:
return cast<int32_t>(instance, offset);
case LongField:
return cast<int64_t>(instance, offset);
case FloatField:
return cast<uint32_t>(instance, offset);
case DoubleField:
return cast<uint64_t>(instance, offset);
default:
abort(t);
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Field_getObject
(Thread*, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int offset = arguments[1];
return reinterpret_cast<int64_t>(cast<object>(instance, offset));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_reflect_Field_setPrimitive
(Thread* t, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int code = arguments[1];
int offset = arguments[2];
int64_t value; memcpy(&value, arguments + 3, 8);
switch (code) {
case ByteField:
cast<int8_t>(instance, offset) = static_cast<int8_t>(value);
break;
case BooleanField:
cast<uint8_t>(instance, offset) = static_cast<uint8_t>(value);
break;
case CharField:
cast<uint16_t>(instance, offset) = static_cast<uint16_t>(value);
break;
case ShortField:
cast<int16_t>(instance, offset) = static_cast<int16_t>(value);
break;
case IntField:
cast<int32_t>(instance, offset) = static_cast<int32_t>(value);
break;
case LongField:
cast<int64_t>(instance, offset) = static_cast<int64_t>(value);
break;
case FloatField:
cast<uint32_t>(instance, offset) = static_cast<uint32_t>(value);
break;
case DoubleField:
cast<uint64_t>(instance, offset) = static_cast<uint64_t>(value);
break;
default:
abort(t);
}
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_reflect_Field_setObject
(Thread* t, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int offset = arguments[1];
object value = reinterpret_cast<object>(arguments[2]);
set(t, instance, offset, value);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Constructor_make
(Thread* t, object, uintptr_t* arguments)
{
object c = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(make(t, c));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Method_getCaller
(Thread* t, object, uintptr_t*)
{
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t): t(t), method(0), count(0) { }
virtual bool visit(Processor::StackWalker* walker) {
if (count == 2) {
method = walker->method();
return false;
} else {
++ count;
return true;
}
}
Thread* t;
object method;
unsigned count;
} v(t);
t->m->processor->walkStack(t, &v);
return reinterpret_cast<int64_t>(v.method);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Method_invoke
(Thread* t, object, uintptr_t* arguments)
{
object method = reinterpret_cast<object>(arguments[0]);
object instance = reinterpret_cast<object>(arguments[1]);
object args = reinterpret_cast<object>(arguments[2]);
object v = t->m->processor->invokeArray(t, method, instance, args);
if (t->exception) {
t->exception = makeInvocationTargetException(t, t->exception);
}
return reinterpret_cast<int64_t>(v);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Array_getLength
(Thread* t, object, uintptr_t* arguments)
{
object array = reinterpret_cast<object>(arguments[0]);
if (LIKELY(array)) {
unsigned elementSize = classArrayElementSize(t, objectClass(t, array));
if (LIKELY(elementSize)) {
return cast<uintptr_t>(array, BytesPerWord);
} else {
t->exception = makeIllegalArgumentException(t);
}
} else {
t->exception = makeNullPointerException(t);
}
return 0;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Array_makeObjectArray
(Thread* t, object, uintptr_t* arguments)
{
object elementType = reinterpret_cast<object>(arguments[0]);
int length = arguments[1];
return reinterpret_cast<int64_t>
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Float_floatToRawIntBits
(Thread*, object, uintptr_t* arguments)
{
return static_cast<int32_t>(*arguments);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Float_intBitsToFloat
(Thread*, object, uintptr_t* arguments)
{
return static_cast<int32_t>(*arguments);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Double_doubleToRawLongBits
(Thread*, object, uintptr_t* arguments)
{
int64_t v; memcpy(&v, arguments, 8);
return v;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Double_longBitsToDouble
(Thread*, object, uintptr_t* arguments)
{
int64_t v; memcpy(&v, arguments, 8);
return v;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_String_intern
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(intern(t, this_));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_System_getVMProperty
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
object found = reinterpret_cast<object>(arguments[1]);
PROTECT(t, found);
unsigned length = stringLength(t, name);
RUNTIME_ARRAY(char, n, length + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
int64_t r = 0;
if (::strcmp(RUNTIME_ARRAY_BODY(n), "java.lang.classpath") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, "%s", t->m->finder->path()));
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "avian.version") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, AVIAN_VERSION));
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "file.encoding") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, "ASCII"));
} else {
const char* v = findProperty(t, RUNTIME_ARRAY_BODY(n));
if (v) {
r = reinterpret_cast<int64_t>(makeString(t, v));
}
}
if (r) {
booleanArrayBody(t, found, 0) = true;
}
return r;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_System_arraycopy
(Thread* t, object, uintptr_t* arguments)
{
object src = reinterpret_cast<object>(arguments[0]);
int32_t srcOffset = arguments[1];
object dst = reinterpret_cast<object>(arguments[2]);
int32_t dstOffset = arguments[3];
int32_t length = arguments[4];
if (LIKELY(src and dst)) {
if (LIKELY(compatibleArrayTypes
(t, objectClass(t, src), objectClass(t, dst))))
{
unsigned elementSize = classArrayElementSize(t, objectClass(t, src));
if (LIKELY(elementSize)) {
intptr_t sl = cast<uintptr_t>(src, BytesPerWord);
intptr_t dl = cast<uintptr_t>(dst, BytesPerWord);
if (LIKELY(length > 0)) {
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
dstOffset >= 0 and dstOffset + length <= dl))
{
uint8_t* sbody = &cast<uint8_t>(src, ArrayBody);
uint8_t* dbody = &cast<uint8_t>(dst, ArrayBody);
if (src == dst) {
memmove(dbody + (dstOffset * elementSize),
sbody + (srcOffset * elementSize),
length * elementSize);
} else {
memcpy(dbody + (dstOffset * elementSize),
sbody + (srcOffset * elementSize),
length * elementSize);
}
if (classObjectMask(t, objectClass(t, dst))) {
mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length);
}
return;
} else {
t->exception = makeIndexOutOfBoundsException(t);
return;
}
} else {
return;
}
}
}
} else {
t->exception = makeNullPointerException(t);
return;
}
t->exception = makeArrayStoreException(t);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_System_identityHashCode
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[0]);
if (LIKELY(o)) {
return objectHash(t, o);
} else {
t->exception = makeNullPointerException(t);
return 0;
}
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_load
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
bool mapName = arguments[1];
unsigned length = stringLength(t, name);
RUNTIME_ARRAY(char, n, length + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
ACQUIRE(t, t->m->classLock);
const char* builtins = findProperty(t, "avian.builtins");
if (mapName and builtins) {
const char* s = builtins;
while (*s) {
if (::strncmp(s, RUNTIME_ARRAY_BODY(n), length) == 0
and (s[length] == ',' or s[length] == 0))
{
// library is built in to this executable
if (not t->m->triedBuiltinOnLoad) {
t->m->triedBuiltinOnLoad = true;
runOnLoadIfFound(t, t->m->libraries);
}
return;
} else {
while (*s and *s != ',') ++ s;
if (*s) ++ s;
}
}
}
System::Library* last = t->m->libraries;
for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
if (lib->name()
and ::strcmp(lib->name(), RUNTIME_ARRAY_BODY(n)) == 0
and lib->mapName() == mapName)
{
// already loaded
return;
}
last = lib;
}
System::Library* lib;
if (LIKELY(t->m->system->success
(t->m->system->load(&lib, RUNTIME_ARRAY_BODY(n), mapName))))
{
last->setNext(lib);
runOnLoadIfFound(t, lib);
} else {
object message = makeString
(t, "library not found: %s", RUNTIME_ARRAY_BODY(n));
t->exception = makeUnsatisfiedLinkError(t, message);
}
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_gc
(Thread* t, object, uintptr_t*)
{
collect(t, Heap::MajorCollection);
}
#ifdef AVIAN_HEAPDUMP #ifdef AVIAN_HEAPDUMP
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
@ -753,193 +198,6 @@ Avian_java_lang_Runtime_exit
t->m->system->exit(arguments[1]); t->m->system->exit(arguments[1]);
} }
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Runtime_freeMemory
(Thread*, object, uintptr_t*)
{
// todo
return 0;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Runtime_totalMemory
(Thread*, object, uintptr_t*)
{
// todo
return 0;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_addShutdownHook
(Thread* t, object, uintptr_t* arguments)
{
object hook = reinterpret_cast<object>(arguments[1]);
PROTECT(t, hook);
ACQUIRE(t, t->m->shutdownLock);
t->m->shutdownHooks = makePair(t, hook, t->m->shutdownHooks);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Throwable_trace
(Thread* t, object, uintptr_t* arguments)
{
int32_t skipCount = arguments[0];
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t, int skipCount):
t(t), trace(0), skipCount(skipCount)
{ }
virtual bool visit(Processor::StackWalker* walker) {
if (skipCount == 0) {
object method = walker->method();
if (isAssignableFrom
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
methodClass(t, method))
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0))
== 0)
{
return true;
} else {
trace = makeTrace(t, walker);
return false;
}
} else {
-- skipCount;
return true;
}
}
Thread* t;
object trace;
unsigned skipCount;
} v(t, skipCount);
t->m->processor->walkStack(t, &v);
if (v.trace == 0) v.trace = makeArray(t, 0);
return reinterpret_cast<int64_t>(v.trace);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Throwable_resolveTrace
(Thread* t, object, uintptr_t* arguments)
{
object trace = reinterpret_cast<object>(*arguments);
PROTECT(t, trace);
unsigned length = arrayLength(t, trace);
object elementType = arrayBody
(t, t->m->types, Machine::StackTraceElementType);
object array = makeObjectArray
(t, classLoader(t, elementType), elementType, length);
PROTECT(t, array);
object e = 0;
PROTECT(t, e);
object class_ = 0;
PROTECT(t, class_);
object method = 0;
PROTECT(t, method);
for (unsigned i = 0; i < length; ++i) {
e = arrayBody(t, trace, i);
class_ = className(t, methodClass(t, traceElementMethod(t, e)));
class_ = makeString(t, class_, 0, byteArrayLength(t, class_) - 1, 0);
method = methodName(t, traceElementMethod(t, e));
method = makeString(t, method, 0, byteArrayLength(t, method) - 1, 0);
unsigned line = t->m->processor->lineNumber
(t, traceElementMethod(t, e), traceElementIp(t, e));
object file = classSourceFile(t, methodClass(t, traceElementMethod(t, e)));
file = file ? makeString(t, file, 0, byteArrayLength(t, file) - 1, 0) : 0;
object ste = makeStackTraceElement(t, class_, method, file, line);
set(t, array, ArrayBody + (i * BytesPerWord), ste);
}
return reinterpret_cast<int64_t>(array);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_currentThread
(Thread* t, object, uintptr_t*)
{
return reinterpret_cast<int64_t>(t->javaThread);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_doStart
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(startThread(t, reinterpret_cast<object>(*arguments)));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Thread_interrupt
(Thread* t, object, uintptr_t* arguments)
{
int64_t peer; memcpy(&peer, arguments, 8);
interrupt(t, reinterpret_cast<Thread*>(peer));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_getStackTrace
(Thread* t, object, uintptr_t* arguments)
{
int64_t peer; memcpy(&peer, arguments, 8);
if (reinterpret_cast<Thread*>(peer) == t) {
return reinterpret_cast<int64_t>(makeTrace(t));
} else {
return reinterpret_cast<int64_t>
(t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_activeCount
(Thread* t, object, uintptr_t*)
{
return t->m->liveCount;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_enumerate
(Thread* t, object, uintptr_t* arguments)
{
object array = reinterpret_cast<object>(*arguments);
ACQUIRE_RAW(t, t->m->stateLock);
unsigned count = min(t->m->liveCount, objectArrayLength(t, array));
unsigned index = 0;
enumerateThreads(t, t->m->rootThread, array, &index, count);
return count;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Thread_setDaemon
(Thread* t, object, uintptr_t* arguments)
{
object thread = reinterpret_cast<object>(arguments[0]);
bool daemon = arguments[1] != 0;
setDaemon(t, thread, daemon);
}
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)
@ -973,7 +231,8 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open
return reinterpret_cast<int64_t> return reinterpret_cast<int64_t>
(t->m->finder->find(RUNTIME_ARRAY_BODY(p))); (t->m->finder->find(RUNTIME_ARRAY_BODY(p)));
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0; return 0;
} }
} }

601
src/classpath-avian.cpp Normal file
View File

@ -0,0 +1,601 @@
/* 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. */
#include "machine.h"
#include "classpath-common.h"
using namespace vm;
namespace {
namespace local {
class MyClasspath : public Classpath {
public:
MyClasspath(Allocator* allocator):
allocator(allocator)
{ }
virtual object
makeJclass(Thread* t, object class_)
{
return vm::makeJclass(t, class_);
}
virtual object
makeString(Thread* t, object array, int32_t offset, int32_t length)
{
return vm::makeString(t, array, offset, length, 0);
}
virtual object
makeThread(Thread* t, Thread* parent)
{
object group;
if (parent) {
group = threadGroup(t, parent->javaThread);
} else {
group = makeThreadGroup(t, 0, 0, 0);
}
const unsigned NewState = 0;
const unsigned NormalPriority = 5;
return vm::makeThread
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, t->m->loader, 0, 0,
group);
}
virtual void
runThread(Thread* t)
{
object method = resolveMethod
(t, t->m->loader, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
if (t->exception == 0) {
t->m->processor->invoke(t, method, 0, t->javaThread);
}
}
virtual object
makeThrowable
(Thread* t, Machine::Type type, object message, object trace, object cause)
{
PROTECT(t, message);
PROTECT(t, cause);
if (trace == 0) {
trace = makeTrace(t);
}
object result = make(t, arrayBody(t, t->m->types, type));
set(t, result, ThrowableMessage, message);
set(t, result, ThrowableTrace, trace);
set(t, result, ThrowableCause, cause);
return result;
}
virtual void
dispose()
{
allocator->free(this, sizeof(*this));
}
Allocator* allocator;
};
void
enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
unsigned limit)
{
if (*index < limit) {
set(t, array, ArrayBody + (*index * BytesPerWord), x->javaThread);
++ (*index);
if (x->peer) enumerateThreads(t, x->peer, array, index, limit);
if (x->child) enumerateThreads(t, x->child, array, index, limit);
}
}
} // namespace local
} // namespace
namespace vm {
Classpath*
makeClasspath(System*, Allocator* allocator)
{
return new (allocator->allocate(sizeof(local::MyClasspath)))
local::MyClasspath(allocator);
}
} // namespace vm
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_toString
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
unsigned hash = objectHash(t, this_);
object s = makeString
(t, "%s@0x%x",
&byteArrayBody(t, className(t, objectClass(t, this_)), 0),
hash);
return reinterpret_cast<int64_t>(s);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_getVMClass
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(objectClass(t, o));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Object_wait
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
int64_t milliseconds; memcpy(&milliseconds, arguments + 1, 8);
vm::wait(t, this_, milliseconds);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Object_notify
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
notify(t, this_);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Object_notifyAll
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
notifyAll(t, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_hashCode
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
return objectHash(t, this_);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Object_clone
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(clone(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_io_ObjectInputStream_makeInstance
(Thread* t, object, uintptr_t* arguments)
{
object c = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(make(t, c));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Field_getPrimitive
(Thread* t, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int code = arguments[1];
int offset = arguments[2];
switch (code) {
case ByteField:
return cast<int8_t>(instance, offset);
case BooleanField:
return cast<uint8_t>(instance, offset);
case CharField:
return cast<uint16_t>(instance, offset);
case ShortField:
return cast<int16_t>(instance, offset);
case IntField:
return cast<int32_t>(instance, offset);
case LongField:
return cast<int64_t>(instance, offset);
case FloatField:
return cast<uint32_t>(instance, offset);
case DoubleField:
return cast<uint64_t>(instance, offset);
default:
abort(t);
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Field_getObject
(Thread*, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int offset = arguments[1];
return reinterpret_cast<int64_t>(cast<object>(instance, offset));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_reflect_Field_setPrimitive
(Thread* t, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int code = arguments[1];
int offset = arguments[2];
int64_t value; memcpy(&value, arguments + 3, 8);
switch (code) {
case ByteField:
cast<int8_t>(instance, offset) = static_cast<int8_t>(value);
break;
case BooleanField:
cast<uint8_t>(instance, offset) = static_cast<uint8_t>(value);
break;
case CharField:
cast<uint16_t>(instance, offset) = static_cast<uint16_t>(value);
break;
case ShortField:
cast<int16_t>(instance, offset) = static_cast<int16_t>(value);
break;
case IntField:
cast<int32_t>(instance, offset) = static_cast<int32_t>(value);
break;
case LongField:
cast<int64_t>(instance, offset) = static_cast<int64_t>(value);
break;
case FloatField:
cast<uint32_t>(instance, offset) = static_cast<uint32_t>(value);
break;
case DoubleField:
cast<uint64_t>(instance, offset) = static_cast<uint64_t>(value);
break;
default:
abort(t);
}
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_reflect_Field_setObject
(Thread* t, object, uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int offset = arguments[1];
object value = reinterpret_cast<object>(arguments[2]);
set(t, instance, offset, value);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Constructor_make
(Thread* t, object, uintptr_t* arguments)
{
object c = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(make(t, c));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Method_getCaller
(Thread* t, object, uintptr_t*)
{
return reinterpret_cast<int64_t>(getCaller(t, 2));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Method_invoke
(Thread* t, object, uintptr_t* arguments)
{
object method = reinterpret_cast<object>(arguments[0]);
object instance = reinterpret_cast<object>(arguments[1]);
object args = reinterpret_cast<object>(arguments[2]);
object v = t->m->processor->invokeArray(t, method, instance, args);
if (t->exception) {
t->exception = t->m->classpath->makeThrowable
(t, Machine::InvocationTargetExceptionType, 0, 0, t->exception);
}
return reinterpret_cast<int64_t>(v);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Array_getLength
(Thread* t, object, uintptr_t* arguments)
{
object array = reinterpret_cast<object>(arguments[0]);
if (LIKELY(array)) {
unsigned elementSize = classArrayElementSize(t, objectClass(t, array));
if (LIKELY(elementSize)) {
return cast<uintptr_t>(array, BytesPerWord);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType);
}
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
}
return 0;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_reflect_Array_makeObjectArray
(Thread* t, object, uintptr_t* arguments)
{
object elementType = reinterpret_cast<object>(arguments[0]);
int length = arguments[1];
return reinterpret_cast<int64_t>
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Float_floatToRawIntBits
(Thread*, object, uintptr_t* arguments)
{
return static_cast<int32_t>(*arguments);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Float_intBitsToFloat
(Thread*, object, uintptr_t* arguments)
{
return static_cast<int32_t>(*arguments);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Double_doubleToRawLongBits
(Thread*, object, uintptr_t* arguments)
{
int64_t v; memcpy(&v, arguments, 8);
return v;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Double_longBitsToDouble
(Thread*, object, uintptr_t* arguments)
{
int64_t v; memcpy(&v, arguments, 8);
return v;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_String_intern
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
return reinterpret_cast<int64_t>(intern(t, this_));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_System_getVMProperty
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
object found = reinterpret_cast<object>(arguments[1]);
PROTECT(t, found);
unsigned length = stringLength(t, name);
RUNTIME_ARRAY(char, n, length + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
int64_t r = 0;
if (::strcmp(RUNTIME_ARRAY_BODY(n), "java.lang.classpath") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, "%s", t->m->finder->path()));
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "avian.version") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, AVIAN_VERSION));
} else if (::strcmp(RUNTIME_ARRAY_BODY(n), "file.encoding") == 0) {
r = reinterpret_cast<int64_t>(makeString(t, "ASCII"));
} else {
const char* v = findProperty(t, RUNTIME_ARRAY_BODY(n));
if (v) {
r = reinterpret_cast<int64_t>(makeString(t, v));
}
}
if (r) {
booleanArrayBody(t, found, 0) = true;
}
return r;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_System_arraycopy
(Thread* t, object, uintptr_t* arguments)
{
arrayCopy(t, reinterpret_cast<object>(arguments[0]),
arguments[1],
reinterpret_cast<object>(arguments[2]),
arguments[3],
arguments[4]);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_System_identityHashCode
(Thread* t, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[0]);
if (LIKELY(o)) {
return objectHash(t, o);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0;
}
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_load
(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
bool mapName = arguments[1];
unsigned length = stringLength(t, name);
RUNTIME_ARRAY(char, n, length + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
loadLibrary(t, RUNTIME_ARRAY_BODY(n), mapName, true);
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_gc
(Thread* t, object, uintptr_t*)
{
collect(t, Heap::MajorCollection);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Runtime_freeMemory
(Thread*, object, uintptr_t*)
{
// todo
return 0;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Runtime_totalMemory
(Thread*, object, uintptr_t*)
{
// todo
return 0;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Runtime_addShutdownHook
(Thread* t, object, uintptr_t* arguments)
{
object hook = reinterpret_cast<object>(arguments[1]);
PROTECT(t, hook);
ACQUIRE(t, t->m->shutdownLock);
t->m->shutdownHooks = makePair(t, hook, t->m->shutdownHooks);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Throwable_trace
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>(getTrace(t, arguments[0]));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Throwable_resolveTrace
(Thread* t, object, uintptr_t* arguments)
{
object trace = reinterpret_cast<object>(*arguments);
PROTECT(t, trace);
unsigned length = arrayLength(t, trace);
object elementType = arrayBody
(t, t->m->types, Machine::StackTraceElementType);
object array = makeObjectArray
(t, classLoader(t, elementType), elementType, length);
PROTECT(t, array);
for (unsigned i = 0; i < length; ++i) {
object ste = makeStackTraceElement(t, arrayBody(t, trace, i));
set(t, array, ArrayBody + (i * BytesPerWord), ste);
}
return reinterpret_cast<int64_t>(array);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_currentThread
(Thread* t, object, uintptr_t*)
{
return reinterpret_cast<int64_t>(t->javaThread);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_doStart
(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(startThread(t, reinterpret_cast<object>(*arguments)));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Thread_interrupt
(Thread* t, object, uintptr_t* arguments)
{
int64_t peer; memcpy(&peer, arguments, 8);
interrupt(t, reinterpret_cast<Thread*>(peer));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_getStackTrace
(Thread* t, object, uintptr_t* arguments)
{
int64_t peer; memcpy(&peer, arguments, 8);
if (reinterpret_cast<Thread*>(peer) == t) {
return reinterpret_cast<int64_t>(makeTrace(t));
} else {
return reinterpret_cast<int64_t>
(t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_activeCount
(Thread* t, object, uintptr_t*)
{
return t->m->liveCount;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Thread_enumerate
(Thread* t, object, uintptr_t* arguments)
{
object array = reinterpret_cast<object>(*arguments);
ACQUIRE_RAW(t, t->m->stateLock);
unsigned count = min(t->m->liveCount, objectArrayLength(t, array));
unsigned index = 0;
local::enumerateThreads(t, t->m->rootThread, array, &index, count);
return count;
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Thread_setDaemon
(Thread* t, object, uintptr_t* arguments)
{
object thread = reinterpret_cast<object>(arguments[0]);
bool daemon = arguments[1] != 0;
setDaemon(t, thread, daemon);
}

271
src/classpath-common.h Normal file
View File

@ -0,0 +1,271 @@
/* 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. */
#ifndef CLASSPATH_COMMON_H
#define CLASSPATH_COMMON_H
namespace vm {
inline object
getCaller(Thread* t, unsigned target)
{
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t, unsigned target):
t(t), method(0), count(0), target(target)
{ }
virtual bool visit(Processor::StackWalker* walker) {
if (count == target) {
method = walker->method();
return false;
} else {
++ count;
return true;
}
}
Thread* t;
object method;
unsigned count;
unsigned target;
} v(t, target);
t->m->processor->walkStack(t, &v);
return v.method;
}
inline object
getTrace(Thread* t, unsigned skipCount)
{
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t, int skipCount):
t(t), trace(0), skipCount(skipCount)
{ }
virtual bool visit(Processor::StackWalker* walker) {
if (skipCount == 0) {
object method = walker->method();
if (isAssignableFrom
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
methodClass(t, method))
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0))
== 0)
{
return true;
} else {
trace = makeTrace(t, walker);
return false;
}
} else {
-- skipCount;
return true;
}
}
Thread* t;
object trace;
unsigned skipCount;
} v(t, skipCount);
t->m->processor->walkStack(t, &v);
if (v.trace == 0) v.trace = makeArray(t, 0);
return v.trace;
}
inline bool
compatibleArrayTypes(Thread* t, object a, object b)
{
return classArrayElementSize(t, a)
and classArrayElementSize(t, b)
and (a == b
or (not ((classVmFlags(t, a) & PrimitiveFlag)
or (classVmFlags(t, b) & PrimitiveFlag))));
}
inline void
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
int32_t dstOffset, int32_t length)
{
if (LIKELY(src and dst)) {
if (LIKELY(compatibleArrayTypes
(t, objectClass(t, src), objectClass(t, dst))))
{
unsigned elementSize = classArrayElementSize(t, objectClass(t, src));
if (LIKELY(elementSize)) {
intptr_t sl = cast<uintptr_t>(src, BytesPerWord);
intptr_t dl = cast<uintptr_t>(dst, BytesPerWord);
if (LIKELY(length > 0)) {
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
dstOffset >= 0 and dstOffset + length <= dl))
{
uint8_t* sbody = &cast<uint8_t>(src, ArrayBody);
uint8_t* dbody = &cast<uint8_t>(dst, ArrayBody);
if (src == dst) {
memmove(dbody + (dstOffset * elementSize),
sbody + (srcOffset * elementSize),
length * elementSize);
} else {
memcpy(dbody + (dstOffset * elementSize),
sbody + (srcOffset * elementSize),
length * elementSize);
}
if (classObjectMask(t, objectClass(t, dst))) {
mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length);
}
return;
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::IndexOutOfBoundsExceptionType);
return;
}
} else {
return;
}
}
}
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return;
}
t->exception = t->m->classpath->makeThrowable
(t, Machine::ArrayStoreExceptionType);
}
void
runOnLoadIfFound(Thread* t, System::Library* library)
{
void* p = library->resolve("JNI_OnLoad");
if (p) {
jint (JNICALL * JNI_OnLoad)(Machine*, void*);
memcpy(&JNI_OnLoad, &p, sizeof(void*));
JNI_OnLoad(t->m, 0);
}
}
System::Library*
loadLibrary(Thread* t, const char* name, bool mapName, bool runOnLoad)
{
ACQUIRE(t, t->m->classLock);
const char* builtins = findProperty(t, "avian.builtins");
if (mapName and builtins) {
const char* s = builtins;
while (*s) {
unsigned length = strlen(name);
if (::strncmp(s, name, length) == 0
and (s[length] == ',' or s[length] == 0))
{
// library is built in to this executable
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
t->m->triedBuiltinOnLoad = true;
runOnLoadIfFound(t, t->m->libraries);
}
return t->m->libraries;
} else {
while (*s and *s != ',') ++ s;
if (*s) ++ s;
}
}
}
System::Library* last = t->m->libraries;
for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
if (lib->name()
and ::strcmp(lib->name(), name) == 0
and lib->mapName() == mapName)
{
// already loaded
return lib;
}
last = lib;
}
System::Library* lib;
if (LIKELY(t->m->system->success(t->m->system->load(&lib, name, mapName)))) {
last->setNext(lib);
if (runOnLoad) {
runOnLoadIfFound(t, lib);
}
return lib;
} else {
object message = makeString(t, "library not found: %s", name);
t->exception = t->m->classpath->makeThrowable
(t, Machine::UnsatisfiedLinkErrorType, message);
return 0;
}
}
object
clone(Thread* t, object o)
{
PROTECT(t, o);
object class_ = objectClass(t, o);
unsigned size = baseSize(t, o, class_) * BytesPerWord;
object clone;
if (classArrayElementSize(t, class_)) {
clone = static_cast<object>(allocate(t, size, classObjectMask(t, class_)));
memcpy(clone, o, size);
// clear any object header flags:
setObjectClass(t, o, objectClass(t, o));
} else {
clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(o) + 1,
size - BytesPerWord);
}
return clone;
}
object
makeStackTraceElement(Thread* t, object e)
{
PROTECT(t, e);
object class_ = className(t, methodClass(t, traceElementMethod(t, e)));
PROTECT(t, class_);
RUNTIME_ARRAY(char, s, byteArrayLength(t, class_));
replace('/', '.', RUNTIME_ARRAY_BODY(s),
reinterpret_cast<char*>(&byteArrayBody(t, class_, 0)));
class_ = makeString(t, "%s", s);
object method = methodName(t, traceElementMethod(t, e));
PROTECT(t, method);
method = t->m->classpath->makeString
(t, method, 0, byteArrayLength(t, method) - 1);
unsigned line = t->m->processor->lineNumber
(t, traceElementMethod(t, e), traceElementIp(t, e));
object file = classSourceFile(t, methodClass(t, traceElementMethod(t, e)));
file = file ? t->m->classpath->makeString
(t, file, 0, byteArrayLength(t, file) - 1) : 0;
return makeStackTraceElement(t, class_, method, file, line);
}
} // namespace vm
#endif//CLASSPATH_COMMON_H

2096
src/classpath-openjdk.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -465,6 +465,16 @@ replace(char a, char b, char* c)
for (; *c; ++c) if (*c == a) *c = b; for (; *c; ++c) if (*c == a) *c = b;
} }
inline void
replace(char a, char b, char* dst, const char* src)
{
unsigned i = 0;
for (; src[i]; ++ i) {
dst[i] = src[i] == a ? b : src[i];
}
dst[i] = 0;
}
class Machine; class Machine;
class Thread; class Thread;

View File

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

View File

@ -40,7 +40,7 @@ namespace {
namespace local { namespace local {
const bool DebugCompile = false; const bool DebugCompile = true;
const bool DebugNatives = false; const bool DebugNatives = false;
const bool DebugCallTable = false; const bool DebugCallTable = false;
const bool DebugMethodTree = false; const bool DebugMethodTree = false;
@ -259,10 +259,10 @@ object
findMethod(Thread* t, object method, object instance) findMethod(Thread* t, object method, object instance)
{ {
if ((methodFlags(t, method) & ACC_STATIC) == 0) { if ((methodFlags(t, method) & ACC_STATIC) == 0) {
if (methodVirtual(t, method)) { if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
return findVirtualMethod(t, method, objectClass(t, instance));
} else if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
return findInterfaceMethod(t, method, objectClass(t, instance)); return findInterfaceMethod(t, method, objectClass(t, instance));
} else if (methodVirtual(t, method)) {
return findVirtualMethod(t, method, objectClass(t, instance));
} }
} }
return method; return method;
@ -2142,7 +2142,8 @@ findInterfaceMethodFromInstance(MyThread* t, object method, object instance)
return methodAddress(t, target); return methodAddress(t, target);
} }
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
unwind(t); unwind(t);
} }
} }
@ -2414,7 +2415,8 @@ makeBlankObjectArray(MyThread* t, object loader, object class_, int32_t length)
(makeObjectArray(t, loader, class_, length)); (makeObjectArray(t, loader, class_, length));
} else { } else {
object message = makeString(t, "%d", length); object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
unwind(t); unwind(t);
} }
} }
@ -2463,7 +2465,8 @@ makeBlankArray(MyThread* t, unsigned type, int32_t length)
return reinterpret_cast<uintptr_t>(constructor(t, length)); return reinterpret_cast<uintptr_t>(constructor(t, length));
} else { } else {
object message = makeString(t, "%d", length); object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
unwind(t); unwind(t);
} }
} }
@ -2497,7 +2500,8 @@ setMaybeNull(MyThread* t, object o, unsigned offset, object value)
if (LIKELY(o)) { if (LIKELY(o)) {
set(t, o, offset, value); set(t, o, offset, value);
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
unwind(t); unwind(t);
} }
} }
@ -2508,7 +2512,8 @@ acquireMonitorForObject(MyThread* t, object o)
if (LIKELY(o)) { if (LIKELY(o)) {
acquire(t, o); acquire(t, o);
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
unwind(t); unwind(t);
} }
} }
@ -2519,7 +2524,8 @@ releaseMonitorForObject(MyThread* t, object o)
if (LIKELY(o)) { if (LIKELY(o)) {
release(t, o); release(t, o);
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
unwind(t); unwind(t);
} }
} }
@ -2535,7 +2541,8 @@ makeMultidimensionalArray2(MyThread* t, object class_, uintptr_t* countStack,
RUNTIME_ARRAY_BODY(counts)[i] = countStack[dimensions - i - 1]; RUNTIME_ARRAY_BODY(counts)[i] = countStack[dimensions - i - 1];
if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) { if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) {
object message = makeString(t, "%d", RUNTIME_ARRAY_BODY(counts)[i]); object message = makeString(t, "%d", RUNTIME_ARRAY_BODY(counts)[i]);
t->exception = makeNegativeArraySizeException(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
return 0; return 0;
} }
} }
@ -2589,7 +2596,8 @@ throwArrayIndexOutOfBounds(MyThread* t)
{ {
if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) { if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) {
t->tracing = true; t->tracing = true;
t->exception = makeArrayIndexOutOfBoundsException(t, 0); t->exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType);
t->tracing = false; t->tracing = false;
} else { } else {
// not enough memory available for a new exception and stack trace // not enough memory available for a new exception and stack trace
@ -2606,7 +2614,8 @@ throw_(MyThread* t, object o)
if (LIKELY(o)) { if (LIKELY(o)) {
t->exception = o; t->exception = o;
} else { } else {
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
} }
// printTrace(t, t->exception); // printTrace(t, t->exception);
@ -2622,7 +2631,8 @@ checkCast(MyThread* t, object class_, object o)
(t, "%s as %s", (t, "%s as %s",
&byteArrayBody(t, className(t, objectClass(t, o)), 0), &byteArrayBody(t, className(t, objectClass(t, o)), 0),
&byteArrayBody(t, className(t, class_), 0)); &byteArrayBody(t, className(t, class_), 0));
t->exception = makeClassCastException(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::ClassCastExceptionType, message);
unwind(t); unwind(t);
} }
} }
@ -6125,34 +6135,32 @@ resolveNative(MyThread* t, object method)
initClass(t, methodClass(t, method)); initClass(t, methodClass(t, method));
if (LIKELY(t->exception == 0) if (LIKELY(t->exception == 0) and methodCode(t, method) == 0) {
and unresolved(t, methodCompiled(t, method))) object native = resolveNativeMethod(t, method);
{ if (UNLIKELY(native == 0)) {
void* function = resolveNativeMethod(t, method);
if (UNLIKELY(function == 0)) {
object message = makeString object message = makeString
(t, "%s.%s%s", (t, "%s.%s%s",
&byteArrayBody(t, className(t, methodClass(t, method)), 0), &byteArrayBody(t, className(t, methodClass(t, method)), 0),
&byteArrayBody(t, methodName(t, method), 0), &byteArrayBody(t, methodName(t, method), 0),
&byteArrayBody(t, methodSpec(t, method), 0)); &byteArrayBody(t, methodSpec(t, method), 0));
t->exception = makeUnsatisfiedLinkError(t, message);
t->exception = t->m->classpath->makeThrowable
(t, Machine::UnsatisfiedLinkErrorType, message);
return; return;
} }
// ensure other threads see updated methodVmFlags before // ensure other threads only see the methodCode field populated
// methodCompiled, since we don't want them using the slow calling // once the object it points do has been populated:
// convention on a function that expects the fast calling
// convention:
storeStoreMemoryBarrier(); storeStoreMemoryBarrier();
methodCompiled(t, method) = reinterpret_cast<uintptr_t>(function); set(t, method, MethodCode, native);
} }
} }
uint64_t uint64_t
invokeNativeFast(MyThread* t, object method) invokeNativeFast(MyThread* t, object method, void* function)
{ {
return reinterpret_cast<FastNativeFunction>(methodCompiled(t, method)) return reinterpret_cast<FastNativeFunction>(function)
(t, method, (t, method,
static_cast<uintptr_t*>(t->stack) static_cast<uintptr_t*>(t->stack)
+ t->arch->frameFooterSize() + t->arch->frameFooterSize()
@ -6160,7 +6168,7 @@ invokeNativeFast(MyThread* t, object method)
} }
uint64_t uint64_t
invokeNativeSlow(MyThread* t, object method) invokeNativeSlow(MyThread* t, object method, void* function)
{ {
PROTECT(t, method); PROTECT(t, method);
@ -6232,7 +6240,6 @@ invokeNativeSlow(MyThread* t, object method)
} }
} }
void* function = reinterpret_cast<void*>(methodCompiled(t, method));
unsigned returnCode = methodReturnCode(t, method); unsigned returnCode = methodReturnCode(t, method);
unsigned returnType = fieldType(t, returnCode); unsigned returnType = fieldType(t, returnCode);
uint64_t result; uint64_t result;
@ -6247,7 +6254,7 @@ invokeNativeSlow(MyThread* t, object method)
if (methodFlags(t, method) & ACC_STATIC) { if (methodFlags(t, method) & ACC_STATIC) {
acquire(t, methodClass(t, method)); acquire(t, methodClass(t, method));
} else { } else {
acquire(t, *reinterpret_cast<object*>(RUNTIME_ARRAY_BODY(args)[0])); acquire(t, *reinterpret_cast<object*>(RUNTIME_ARRAY_BODY(args)[1]));
} }
} }
@ -6268,7 +6275,7 @@ invokeNativeSlow(MyThread* t, object method)
if (methodFlags(t, method) & ACC_STATIC) { if (methodFlags(t, method) & ACC_STATIC) {
release(t, methodClass(t, method)); release(t, methodClass(t, method));
} else { } else {
release(t, *reinterpret_cast<object*>(RUNTIME_ARRAY_BODY(args)[0])); release(t, *reinterpret_cast<object*>(RUNTIME_ARRAY_BODY(args)[1]));
} }
} }
@ -6327,10 +6334,11 @@ invokeNativeSlow(MyThread* t, object method)
uint64_t uint64_t
invokeNative2(MyThread* t, object method) invokeNative2(MyThread* t, object method)
{ {
if (methodVmFlags(t, method) & FastNative) { object native = methodCode(t, method);
return invokeNativeFast(t, method); if (nativeFast(t, native)) {
return invokeNativeFast(t, method, nativeFunction(t, native));
} else { } else {
return invokeNativeSlow(t, method); return invokeNativeSlow(t, method, nativeFunction(t, native));
} }
} }
@ -6829,7 +6837,8 @@ callContinuation(MyThread* t, object continuation, object result,
action = Call; action = Call;
} }
} else { } else {
t->exception = makeIncompatibleContinuationException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::IncompatibleContinuationExceptionType);
action = Throw; action = Throw;
} }
} else { } else {
@ -7165,7 +7174,8 @@ class SegFaultHandler: public System::SignalHandler {
if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) { if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) {
t->tracing = true; t->tracing = true;
t->exception = makeNullPointerException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
t->tracing = false; t->tracing = false;
} else { } else {
// not enough memory available for a new NPE and stack trace // not enough memory available for a new NPE and stack trace
@ -7269,6 +7279,7 @@ class MyProcessor: public Processor {
t->init(); t->init();
if (false) { if (false) {
fprintf(stderr, "%d\n", difference(&(t->stack), t));
fprintf(stderr, "%d\n", difference(&(t->continuation), t)); fprintf(stderr, "%d\n", difference(&(t->continuation), t));
fprintf(stderr, "%d\n", difference(&(t->exception), t)); fprintf(stderr, "%d\n", difference(&(t->exception), t));
fprintf(stderr, "%d\n", difference(&(t->exceptionStackAdjustment), t)); fprintf(stderr, "%d\n", difference(&(t->exceptionStackAdjustment), t));
@ -7518,7 +7529,7 @@ class MyProcessor: public Processor {
assert(t, t->state == Thread::ActiveState assert(t, t->state == Thread::ActiveState
or t->state == Thread::ExclusiveState); or t->state == Thread::ExclusiveState);
unsigned size = parameterFootprint(t, methodSpec, false); unsigned size = parameterFootprint(t, methodSpec, this_ == 0);
RUNTIME_ARRAY(uintptr_t, array, size); RUNTIME_ARRAY(uintptr_t, array, size);
RUNTIME_ARRAY(bool, objectMask, size); RUNTIME_ARRAY(bool, objectMask, size);
ArgumentList list ArgumentList list
@ -7766,6 +7777,31 @@ 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 callTable;

View File

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

View File

@ -509,7 +509,9 @@ resolveNativeMethodData(Thread* t, object method)
&byteArrayBody(t, className(t, methodClass(t, method)), 0), &byteArrayBody(t, className(t, methodClass(t, method)), 0),
&byteArrayBody(t, methodName(t, method), 0), &byteArrayBody(t, methodName(t, method), 0),
&byteArrayBody(t, methodSpec(t, method), 0)); &byteArrayBody(t, methodSpec(t, method), 0));
t->exception = makeUnsatisfiedLinkError(t, message);
t->exception = t->m->classpath->makeThrowable
(t, Machine::UnsatisfiedLinkErrorType, message);
} }
} }
} }
@ -524,7 +526,8 @@ checkStack(Thread* t, object method)
+ codeMaxStack(t, methodCode(t, method)) + codeMaxStack(t, methodCode(t, method))
> Thread::StackSizeInWords / 2)) > Thread::StackSizeInWords / 2))
{ {
t->exception = makeStackOverflowError(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
} }
} }
@ -931,13 +934,15 @@ interpret(Thread* t)
{ {
pushObject(t, objectArrayBody(t, array, index)); pushObject(t, objectArrayBody(t, array, index));
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString
objectArrayLength(t, array)); (t, "%d not in [0,%d)", index, objectArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -953,13 +958,15 @@ interpret(Thread* t)
{ {
set(t, array, ArrayBody + (index * BytesPerWord), value); set(t, array, ArrayBody + (index * BytesPerWord), value);
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString
objectArrayLength(t, array)); (t, "%d not in [0,%d)", index, objectArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1002,7 +1009,8 @@ interpret(Thread* t)
class_, count)); class_, count));
} else { } else {
object message = makeString(t, "%d", count); object message = makeString(t, "%d", count);
exception = makeNegativeArraySizeException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1023,7 +1031,8 @@ interpret(Thread* t)
if (LIKELY(array)) { if (LIKELY(array)) {
pushInt(t, cast<uintptr_t>(array, BytesPerWord)); pushInt(t, cast<uintptr_t>(array, BytesPerWord));
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1051,7 +1060,8 @@ interpret(Thread* t)
case athrow: { case athrow: {
exception = popObject(t); exception = popObject(t);
if (UNLIKELY(exception == 0)) { if (UNLIKELY(exception == 0)) {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
} }
} goto throw_; } goto throw_;
@ -1071,7 +1081,8 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
booleanArrayLength(t, array)); booleanArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
@ -1083,12 +1094,15 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
byteArrayLength(t, array)); byteArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1110,7 +1124,8 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
booleanArrayLength(t, array)); booleanArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
@ -1121,12 +1136,14 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
byteArrayLength(t, array)); byteArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1147,11 +1164,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
charArrayLength(t, array)); charArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1169,11 +1188,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
charArrayLength(t, array)); charArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1191,7 +1212,8 @@ interpret(Thread* t)
&byteArrayBody &byteArrayBody
(t, className(t, objectClass(t, peekObject(t, sp - 1))), 0), (t, className(t, objectClass(t, peekObject(t, sp - 1))), 0),
&byteArrayBody(t, className(t, class_), 0)); &byteArrayBody(t, className(t, class_), 0));
exception = makeClassCastException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ClassCastExceptionType, message);
goto throw_; goto throw_;
} }
} }
@ -1228,11 +1250,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
doubleArrayLength(t, array)); doubleArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1250,11 +1274,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
doubleArrayLength(t, array)); doubleArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1428,11 +1454,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
floatArrayLength(t, array)); floatArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1450,11 +1478,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
floatArrayLength(t, array)); floatArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1566,7 +1596,8 @@ interpret(Thread* t)
} }
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1658,11 +1689,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
intArrayLength(t, array)); intArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1687,11 +1720,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
intArrayLength(t, array)); intArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1958,7 +1993,8 @@ interpret(Thread* t)
(t, method, objectClass(t, peekObject(t, sp - parameterFootprint))); (t, method, objectClass(t, peekObject(t, sp - parameterFootprint)));
goto invoke; goto invoke;
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -1983,7 +2019,8 @@ interpret(Thread* t)
goto invoke; goto invoke;
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2014,7 +2051,8 @@ interpret(Thread* t)
code = findVirtualMethod(t, method, class_); code = findVirtualMethod(t, method, class_);
goto invoke; goto invoke;
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2150,11 +2188,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
longArrayLength(t, array)); longArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2179,11 +2219,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
longArrayLength(t, array)); longArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2413,7 +2455,8 @@ interpret(Thread* t)
if (LIKELY(o)) { if (LIKELY(o)) {
acquire(t, o); acquire(t, o);
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2423,7 +2466,8 @@ interpret(Thread* t)
if (LIKELY(o)) { if (LIKELY(o)) {
release(t, o); release(t, o);
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2441,7 +2485,8 @@ interpret(Thread* t)
counts[i] = popInt(t); counts[i] = popInt(t);
if (UNLIKELY(counts[i] < 0)) { if (UNLIKELY(counts[i] < 0)) {
object message = makeString(t, "%d", counts[i]); object message = makeString(t, "%d", counts[i]);
exception = makeNegativeArraySizeException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_; goto throw_;
} }
} }
@ -2514,7 +2559,8 @@ interpret(Thread* t)
pushObject(t, array); pushObject(t, array);
} else { } else {
object message = makeString(t, "%d", count); object message = makeString(t, "%d", count);
exception = makeNegativeArraySizeException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2576,7 +2622,8 @@ interpret(Thread* t)
break; break;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
} }
} break; } break;
@ -2587,7 +2634,8 @@ interpret(Thread* t)
if (LIKELY(o)) { if (LIKELY(o)) {
cast<int64_t>(o, fieldOffset(t, field)) = value; cast<int64_t>(o, fieldOffset(t, field)) = value;
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
} }
} break; } break;
@ -2597,7 +2645,8 @@ interpret(Thread* t)
if (LIKELY(o)) { if (LIKELY(o)) {
set(t, o, fieldOffset(t, field), value); set(t, o, fieldOffset(t, field), value);
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
} }
} break; } break;
@ -2727,11 +2776,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
shortArrayLength(t, array)); shortArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -2749,11 +2800,13 @@ interpret(Thread* t)
} else { } else {
object message = makeString(t, "%d not in [0,%d)", index, object message = makeString(t, "%d not in [0,%d)", index,
shortArrayLength(t, array)); shortArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message); exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_; goto throw_;
} }
} else { } else {
exception = makeNullPointerException(t); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_; goto throw_;
} }
} goto loop; } goto loop;
@ -3195,7 +3248,8 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
> Thread::StackSizeInWords / 2)) > Thread::StackSizeInWords / 2))
{ {
t->exception = makeStackOverflowError(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
return 0; return 0;
} }
@ -3220,7 +3274,8 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
> Thread::StackSizeInWords / 2)) > Thread::StackSizeInWords / 2))
{ {
t->exception = makeStackOverflowError(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
return 0; return 0;
} }
@ -3244,7 +3299,8 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false) if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false)
> Thread::StackSizeInWords / 2)) > Thread::StackSizeInWords / 2))
{ {
t->exception = makeStackOverflowError(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
return 0; return 0;
} }

View File

@ -156,6 +156,49 @@ ReleaseStringChars(Thread* t, jstring s, const jchar* chars)
t->m->heap->free(chars, (stringLength(t, *s) + 1) * sizeof(jchar)); t->m->heap->free(chars, (stringLength(t, *s) + 1) * sizeof(jchar));
} }
void JNICALL
GetStringRegion(Thread* t, jstring s, jsize start, jsize length, jchar* dst)
{
ENTER(t, Thread::ActiveState);
stringChars(t, *s, start, length, dst);
}
const jchar* JNICALL
GetStringCritical(Thread* t, jstring s, jboolean* isCopy)
{
if ((t->criticalLevel ++) == 0) {
enter(t, Thread::ActiveState);
}
if (isCopy) {
*isCopy = true;
}
object data = stringData(t, *s);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
return GetStringChars(t, s, isCopy);
} else {
return &charArrayBody(t, data, stringOffset(t, *s));
}
}
void JNICALL
ReleaseStringCritical(Thread* t, jstring s, const jchar* chars)
{
if (objectClass(t, stringData(t, *s))
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
ReleaseStringChars(t, s, chars);
}
if ((-- t->criticalLevel) == 0) {
enter(t, Thread::IdleState);
}
}
jsize JNICALL jsize JNICALL
GetStringUTFLength(Thread* t, jstring s) GetStringUTFLength(Thread* t, jstring s)
{ {
@ -186,6 +229,15 @@ ReleaseStringUTFChars(Thread* t, jstring s, const char* chars)
t->m->heap->free(chars, stringLength(t, *s) + 1); t->m->heap->free(chars, stringLength(t, *s) + 1);
} }
void JNICALL
GetStringUTFRegion(Thread* t, jstring s, jsize start, jsize length, char* dst)
{
ENTER(t, Thread::ActiveState);
stringUTFChars
(t, *s, start, length, dst, stringUTFLength(t, *s, start, length));
}
jsize JNICALL jsize JNICALL
GetArrayLength(Thread* t, jarray array) GetArrayLength(Thread* t, jarray array)
{ {
@ -206,9 +258,8 @@ NewString(Thread* t, const jchar* chars, jsize size)
a = makeCharArray(t, size); a = makeCharArray(t, size);
memcpy(&charArrayBody(t, a, 0), chars, size * sizeof(jchar)); memcpy(&charArrayBody(t, a, 0), chars, size * sizeof(jchar));
} }
object s = makeString(t, a, 0, size, 0);
return makeLocalReference(t, s); return makeLocalReference(t, t->m->classpath->makeString(t, a, 0, size));
} }
jstring JNICALL jstring JNICALL
@ -218,15 +269,11 @@ NewStringUTF(Thread* t, const char* chars)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object a = 0; object array = parseUtf8(t, chars, strlen(chars));
unsigned size = strlen(chars);
if (size) {
a = makeByteArray(t, size);
memcpy(&byteArrayBody(t, a, 0), chars, size);
}
object s = makeString(t, a, 0, size, 0);
return makeLocalReference(t, s); return makeLocalReference
(t, t->m->classpath->makeString
(t, array, 0, cast<uintptr_t>(array, BytesPerWord) - 1));
} }
void void
@ -240,6 +287,19 @@ replace(int a, int b, const char* in, int8_t* out)
*out = 0; *out = 0;
} }
jclass JNICALL
DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer,
jsize length)
{
ENTER(t, Thread::ActiveState);
object c = defineClass
(t, loader ? *loader : t->m->loader,
reinterpret_cast<const uint8_t*>(buffer), length);
return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c));
}
jclass JNICALL jclass JNICALL
FindClass(Thread* t, const char* name) FindClass(Thread* t, const char* name)
{ {
@ -279,6 +339,20 @@ ThrowNew(Thread* t, jclass c, const char* message)
return 0; return 0;
} }
jint JNICALL
Throw(Thread* t, jthrowable throwable)
{
if (t->exception) {
return -1;
}
ENTER(t, Thread::ActiveState);
t->exception = *throwable;
return 0;
}
void JNICALL void JNICALL
DeleteLocalRef(Thread* t, jobject r) DeleteLocalRef(Thread* t, jobject r)
{ {
@ -329,6 +403,14 @@ IsInstanceOf(Thread* t, jobject o, jclass c)
return instanceOf(t, jclassVmClass(t, *c), *o); return instanceOf(t, jclassVmClass(t, *c), *o);
} }
jboolean JNICALL
IsAssignableFrom(Thread* t, jclass a, jclass b)
{
ENTER(t, Thread::ActiveState);
return isAssignableFrom(t, jclassVmClass(t, *a), jclassVmClass(t, *b));
}
object object
findMethod(Thread* t, jclass c, const char* name, const char* spec) findMethod(Thread* t, jclass c, const char* name, const char* spec)
{ {
@ -362,7 +444,10 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = findMethod(t, c, name, spec); object method = findMethod(t, c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) {
printTrace(t, t->exception);
return 0;
}
assert(t, (methodFlags(t, method) & ACC_STATIC) == 0); assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
@ -1116,7 +1201,7 @@ SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
set(t, classStaticTable(t, *c), field, (v ? *v : 0)); set(t, classStaticTable(t, jclassVmClass(t, *c)), field, (v ? *v : 0));
} }
void JNICALL void JNICALL
@ -1222,6 +1307,12 @@ DeleteGlobalRef(Thread* t, jobject r)
} }
} }
jint JNICALL
EnsureLocalCapacity(Thread*, jint)
{
return 0;
}
jthrowable JNICALL jthrowable JNICALL
ExceptionOccurred(Thread* t) ExceptionOccurred(Thread* t)
{ {
@ -1832,6 +1923,34 @@ ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint)
} }
} }
jint JNICALL
RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods,
jint methodCount)
{
ENTER(t, Thread::ActiveState);
for (int i = 0; i < methodCount; ++i) {
if (methods[i].function) {
object method = findMethod(t, c, methods[i].name, methods[i].signature);
if (UNLIKELY(t->exception)) return -1;
t->m->processor->registerNative(t, method, methods[i].function);
}
}
return 0;
}
jint JNICALL
UnregisterNatives(Thread* t, jclass c)
{
ENTER(t, Thread::ActiveState);
t->m->processor->unregisterNatives(t, *c);
return 0;
}
jint JNICALL jint JNICALL
MonitorEnter(Thread* t, jobject o) MonitorEnter(Thread* t, jobject o)
{ {
@ -1948,14 +2067,20 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->GetStringLength = local::GetStringLength; envTable->GetStringLength = local::GetStringLength;
envTable->GetStringChars = local::GetStringChars; envTable->GetStringChars = local::GetStringChars;
envTable->ReleaseStringChars = local::ReleaseStringChars; envTable->ReleaseStringChars = local::ReleaseStringChars;
envTable->GetStringRegion = local::GetStringRegion;
envTable->GetStringCritical = local::GetStringCritical;
envTable->ReleaseStringCritical = local::ReleaseStringCritical;
envTable->GetStringUTFLength = local::GetStringUTFLength; envTable->GetStringUTFLength = local::GetStringUTFLength;
envTable->GetStringUTFChars = local::GetStringUTFChars; envTable->GetStringUTFChars = local::GetStringUTFChars;
envTable->ReleaseStringUTFChars = local::ReleaseStringUTFChars; envTable->ReleaseStringUTFChars = local::ReleaseStringUTFChars;
envTable->GetStringUTFRegion = local::GetStringUTFRegion;
envTable->GetArrayLength = local::GetArrayLength; envTable->GetArrayLength = local::GetArrayLength;
envTable->NewString = local::NewString; envTable->NewString = local::NewString;
envTable->NewStringUTF = local::NewStringUTF; envTable->NewStringUTF = local::NewStringUTF;
envTable->DefineClass = local::DefineClass;
envTable->FindClass = local::FindClass; envTable->FindClass = local::FindClass;
envTable->ThrowNew = local::ThrowNew; envTable->ThrowNew = local::ThrowNew;
envTable->Throw = local::Throw;
envTable->ExceptionCheck = local::ExceptionCheck; envTable->ExceptionCheck = local::ExceptionCheck;
#ifdef AVIAN_GNU #ifdef AVIAN_GNU
envTable->NewDirectByteBuffer = vm::NewDirectByteBuffer; envTable->NewDirectByteBuffer = vm::NewDirectByteBuffer;
@ -1969,6 +2094,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->DeleteLocalRef = local::DeleteLocalRef; envTable->DeleteLocalRef = local::DeleteLocalRef;
envTable->GetObjectClass = local::GetObjectClass; envTable->GetObjectClass = local::GetObjectClass;
envTable->IsInstanceOf = local::IsInstanceOf; envTable->IsInstanceOf = local::IsInstanceOf;
envTable->IsAssignableFrom = local::IsAssignableFrom;
envTable->GetFieldID = local::GetFieldID; envTable->GetFieldID = local::GetFieldID;
envTable->GetMethodID = local::GetMethodID; envTable->GetMethodID = local::GetMethodID;
envTable->GetStaticMethodID = local::GetStaticMethodID; envTable->GetStaticMethodID = local::GetStaticMethodID;
@ -2054,6 +2180,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->NewGlobalRef = local::NewGlobalRef; envTable->NewGlobalRef = local::NewGlobalRef;
envTable->NewWeakGlobalRef = local::NewGlobalRef; envTable->NewWeakGlobalRef = local::NewGlobalRef;
envTable->DeleteGlobalRef = local::DeleteGlobalRef; envTable->DeleteGlobalRef = local::DeleteGlobalRef;
envTable->EnsureLocalCapacity = local::EnsureLocalCapacity;
envTable->ExceptionOccurred = local::ExceptionOccurred; envTable->ExceptionOccurred = local::ExceptionOccurred;
envTable->ExceptionDescribe = local::ExceptionDescribe; envTable->ExceptionDescribe = local::ExceptionDescribe;
envTable->ExceptionClear = local::ExceptionClear; envTable->ExceptionClear = local::ExceptionClear;
@ -2103,6 +2230,8 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->GetPrimitiveArrayCritical = local::GetPrimitiveArrayCritical; envTable->GetPrimitiveArrayCritical = local::GetPrimitiveArrayCritical;
envTable->ReleasePrimitiveArrayCritical envTable->ReleasePrimitiveArrayCritical
= local::ReleasePrimitiveArrayCritical; = local::ReleasePrimitiveArrayCritical;
envTable->RegisterNatives = local::RegisterNatives;
envTable->UnregisterNatives = local::UnregisterNatives;
envTable->MonitorEnter = local::MonitorEnter; envTable->MonitorEnter = local::MonitorEnter;
envTable->MonitorExit = local::MonitorExit; envTable->MonitorExit = local::MonitorExit;
envTable->GetJavaVM = local::GetJavaVM; envTable->GetJavaVM = local::GetJavaVM;
@ -2201,6 +2330,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
Heap* h = makeHeap(s, heapLimit); Heap* h = makeHeap(s, heapLimit);
Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary); Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary);
Processor* p = makeProcessor(s, h, true); Processor* p = makeProcessor(s, h, true);
Classpath* c = makeClasspath(s, h);
const char** properties = static_cast<const char**> const char** properties = static_cast<const char**>
(h->allocate(sizeof(const char*) * propertyCount)); (h->allocate(sizeof(const char*) * propertyCount));
@ -2212,11 +2342,14 @@ 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, properties, propertyCount); Machine(s, h, f, p, c, properties, propertyCount);
*t = p->makeThread(*m, 0, 0); *t = p->makeThread(*m, 0, 0);
enter(*t, Thread::ActiveState); enter(*t, Thread::ActiveState);
c->boot(*t);
enter(*t, Thread::IdleState); enter(*t, Thread::IdleState);
return 0; return 0;

View File

@ -196,10 +196,12 @@ turnOffTheLights(Thread* t)
System* s = m->system; System* s = m->system;
Heap* h = m->heap; Heap* h = m->heap;
Processor* p = m->processor; Processor* p = m->processor;
Classpath* c = m->classpath;
Finder* f = m->finder; Finder* f = m->finder;
m->dispose(); m->dispose();
h->disposeFixies(); h->disposeFixies();
c->dispose();
p->dispose(); p->dispose();
h->dispose(); h->dispose();
f->dispose(); f->dispose();
@ -227,23 +229,6 @@ killZombies(Thread* t, Thread* o)
} }
} }
object
makeJavaThread(Thread* t, Thread* parent)
{
object group;
if (parent) {
group = threadGroup(t, parent->javaThread);
} else {
group = makeThreadGroup(t, 0, 0, 0);
}
const unsigned NewState = 0;
const unsigned NormalPriority = 5;
return makeThread
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, t->m->loader, 0, 0, group);
}
unsigned unsigned
footprint(Thread* t) footprint(Thread* t)
{ {
@ -377,13 +362,12 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
object q = jreferenceQueue(t, *p); object q = jreferenceQueue(t, *p);
set(t, *p, JreferenceJNext, *p);
if (referenceQueueFront(t, q)) { if (referenceQueueFront(t, q)) {
set(t, referenceQueueRear(t, q), JreferenceJNext, *p); set(t, *p, JreferenceJNext, referenceQueueFront(t, q));
} else { } else {
set(t, q, ReferenceQueueFront, *p); set(t, *p, JreferenceJNext, *p);
} }
set(t, q, ReferenceQueueRear, *p); set(t, q, ReferenceQueueFront, *p);
jreferenceQueue(t, *p) = 0; jreferenceQueue(t, *p) = 0;
} }
@ -793,8 +777,8 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
parsePoolEntry(t, s, index, pool, si); parsePoolEntry(t, s, index, pool, si);
object value = singletonObject(t, pool, si); object value = singletonObject(t, pool, si);
value = makeString value = t->m->classpath->makeString
(t, value, 0, cast<uintptr_t>(value, BytesPerWord) - 1, 0); (t, value, 0, cast<uintptr_t>(value, BytesPerWord) - 1);
value = intern(t, value); value = intern(t, value);
set(t, pool, SingletonBody + (i * BytesPerWord), value); set(t, pool, SingletonBody + (i * BytesPerWord), value);
} }
@ -1046,7 +1030,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
object body = makeByteArray(t, length); object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)),
length); length);
addendum = makeAddendum(t, pool, body); addendum = makeFieldAddendum(t, pool, body);
} else { } else {
s.skip(length); s.skip(length);
} }
@ -1082,9 +1066,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
classVmFlags(t, class_) |= HasFinalMemberFlag; classVmFlags(t, class_) |= HasFinalMemberFlag;
} }
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord; while (memberOffset % fieldSize(t, code)) {
if (excess) { ++ memberOffset;
memberOffset += BytesPerWord - excess;
} }
fieldOffset(t, field) = memberOffset; fieldOffset(t, field) = memberOffset;
@ -1392,14 +1375,29 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
&byteArrayBody(t, name, 0)) == 0) &byteArrayBody(t, name, 0)) == 0)
{ {
code = parseCode(t, s, pool); code = parseCode(t, s, pool);
} else if (vm::strcmp(reinterpret_cast<const int8_t*>("Exceptions"),
&byteArrayBody(t, name, 0)) == 0)
{
if (addendum == 0) {
addendum = makeMethodAddendum(t, pool, 0, 0);
}
unsigned exceptionCount = s.read2();
object body = makeShortArray(t, exceptionCount);
for (unsigned i = 0; i < exceptionCount; ++i) {
shortArrayBody(t, body, i) = s.read2();
}
set(t, addendum, MethodAddendumExceptionTable, body);
} else if (vm::strcmp(reinterpret_cast<const int8_t*> } else if (vm::strcmp(reinterpret_cast<const int8_t*>
("RuntimeVisibleAnnotations"), ("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0) &byteArrayBody(t, name, 0)) == 0)
{ {
if (addendum == 0) {
addendum = makeMethodAddendum(t, pool, 0, 0);
}
object body = makeByteArray(t, length); object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)),
length); length);
addendum = makeAddendum(t, pool, body); set(t, addendum, AddendumAnnotationTable, body);
} else { } else {
s.skip(length); s.skip(length);
} }
@ -1549,7 +1547,6 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (abstractVirtuals) { if (abstractVirtuals) {
PROTECT(t, vtable); PROTECT(t, vtable);
PROTECT(t, abstractVirtuals);
unsigned oldLength = arrayLength(t, classMethodTable(t, class_)); unsigned oldLength = arrayLength(t, classMethodTable(t, class_));
object newMethodTable = makeArray object newMethodTable = makeArray
@ -1673,8 +1670,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
// verify that the classes have the same layout // verify that the classes have the same layout
expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_)); expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_));
expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType) expect(t, classFixedSize(t, bootstrapClass) >= classFixedSize(t, class_));
or classFixedSize(t, bootstrapClass) >= classFixedSize(t, class_));
expect(t, (classVmFlags(t, class_) & HasFinalizerFlag) == 0); expect(t, (classVmFlags(t, class_) & HasFinalizerFlag) == 0);
@ -2079,8 +2075,8 @@ class HeapClient: public Heap::Client {
namespace vm { namespace vm {
Machine::Machine(System* system, Heap* heap, Finder* finder, Machine::Machine(System* system, Heap* heap, Finder* finder,
Processor* processor, const char** properties, Processor* processor, Classpath* classpath,
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)))
@ -2088,6 +2084,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
heap(heap), heap(heap),
finder(finder), finder(finder),
processor(processor), processor(processor),
classpath(classpath),
rootThread(0), rootThread(0),
exclusive(0), exclusive(0),
finalizeThread(0), finalizeThread(0),
@ -2199,7 +2196,8 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
backupHeapIndex(0), backupHeapIndex(0),
useBackupHeap(false), useBackupHeap(false),
waiting(false), waiting(false),
tracing(false) tracing(false),
daemon(false)
#ifdef VM_STRESS #ifdef VM_STRESS
, stress(false) , stress(false)
#endif // VM_STRESS #endif // VM_STRESS
@ -2248,10 +2246,11 @@ Thread::init()
m->jniMethodTable = makeVector(this, 0, 0); m->jniMethodTable = makeVector(this, 0, 0);
m->nullPointerException = makeNullPointerException(this); m->nullPointerException = m->classpath->makeThrowable
(this, Machine::NullPointerExceptionType);
m->arrayIndexOutOfBoundsException m->arrayIndexOutOfBoundsException = m->classpath->makeThrowable
= makeArrayIndexOutOfBoundsException(this, 0); (this, Machine::IndexOutOfBoundsExceptionType);
m->localThread->set(this); m->localThread->set(this);
} else { } else {
@ -2262,7 +2261,7 @@ Thread::init()
expect(this, m->system->success(m->system->make(&lock))); expect(this, m->system->success(m->system->make(&lock)));
if (javaThread == 0) { if (javaThread == 0) {
this->javaThread = makeJavaThread(this, parent); this->javaThread = m->classpath->makeThread(this, parent);
} }
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this); threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
@ -2365,6 +2364,7 @@ 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)
@ -2408,6 +2408,24 @@ enter(Thread* t, Thread::State s)
} break; } break;
case Thread::IdleState: case Thread::IdleState:
// The java.lang.Thread implementation may or may not notify the
// VM when the daemon field in the Java object changes, so we sync
// up the native field whenever the thread transitions to idle:
if (t->daemon != threadDaemon(t, t->javaThread)) {
ACQUIRE_LOCK;
t->daemon = threadDaemon(t, t->javaThread);
if (t->daemon) {
++ t->m->daemonCount;
} else {
expect(t, t->m->daemonCount);
-- t->m->daemonCount;
}
t->m->stateLock->notifyAll(t->systemThread);
}
if (t->state == Thread::ActiveState) { if (t->state == Thread::ActiveState) {
// fast path // fast path
assert(t, t->m->activeCount > 0); assert(t, t->m->activeCount > 0);
@ -2420,6 +2438,7 @@ enter(Thread* t, Thread::State s)
t->m->stateLock->notifyAll(t->systemThread); t->m->stateLock->notifyAll(t->systemThread);
} }
break; break;
} else { } else {
// fall through to slow path // fall through to slow path
@ -2692,91 +2711,98 @@ makeString(Thread* t, const char* format, ...)
object s = ::makeByteArray(t, format, a); object s = ::makeByteArray(t, format, a);
va_end(a); va_end(a);
return makeString(t, s, 0, byteArrayLength(t, s) - 1, 0); return t->m->classpath->makeString(t, s, 0, byteArrayLength(t, s) - 1);
} }
int int
stringUTFLength(Thread* t, object string) { stringUTFLength(Thread* t, object string, unsigned start, unsigned length)
int length = 0; {
unsigned result = 0;
if (stringLength(t, string)) { if (length) {
object data = stringData(t, string); object data = stringData(t, string);
if (objectClass(t, data) if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType)) { == arrayBody(t, t->m->types, Machine::ByteArrayType))
length = stringLength(t, string); {
result = length;
} else { } else {
for (unsigned i = 0; i < stringLength(t, string); ++i) { for (unsigned i = 0; i < length; ++i) {
uint16_t c = charArrayBody(t, data, stringOffset(t, string) + i); uint16_t c = charArrayBody
if (!c) length += 1; // null char (was 2 bytes in Java) (t, data, stringOffset(t, string) + start + i);
else if (c < 0x80) length += 1; // ASCII char if (c == 0) result += 1; // null char (was 2 bytes in Java)
else if (c < 0x800) length += 2; // two-byte char else if (c < 0x80) result += 1; // ASCII char
else length += 3; // three-byte char else if (c < 0x800) result += 2; // two-byte char
else result += 3; // three-byte char
} }
} }
} }
return length; return result;
} }
void void
stringChars(Thread* t, object string, char* chars) stringChars(Thread* t, object string, unsigned start, unsigned length,
char* chars)
{ {
if (stringLength(t, string)) { if (length) {
object data = stringData(t, string); object data = stringData(t, string);
if (objectClass(t, data) if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType)) == arrayBody(t, t->m->types, Machine::ByteArrayType))
{ {
memcpy(chars, memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string)), &byteArrayBody(t, data, stringOffset(t, string) + start),
stringLength(t, string)); length);
} else { } else {
for (unsigned i = 0; i < stringLength(t, string); ++i) { for (unsigned i = 0; i < length; ++i) {
chars[i] = charArrayBody(t, data, stringOffset(t, string) + i); chars[i] = charArrayBody(t, data, stringOffset(t, string) + start + i);
} }
} }
} }
chars[stringLength(t, string)] = 0; chars[length] = 0;
} }
void void
stringChars(Thread* t, object string, uint16_t* chars) stringChars(Thread* t, object string, unsigned start, unsigned length,
uint16_t* chars)
{ {
if (stringLength(t, string)) { if (length) {
object data = stringData(t, string); object data = stringData(t, string);
if (objectClass(t, data) if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType)) == arrayBody(t, t->m->types, Machine::ByteArrayType))
{ {
for (unsigned i = 0; i < stringLength(t, string); ++i) { for (unsigned i = 0; i < length; ++i) {
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + i); chars[i] = byteArrayBody(t, data, stringOffset(t, string) + start + i);
} }
} else { } else {
memcpy(chars, memcpy(chars,
&charArrayBody(t, data, stringOffset(t, string)), &charArrayBody(t, data, stringOffset(t, string) + start),
stringLength(t, string) * sizeof(uint16_t)); length * sizeof(uint16_t));
} }
} }
chars[stringLength(t, string)] = 0; chars[length] = 0;
} }
void void
stringUTFChars(Thread* t, object string, char* chars, unsigned length UNUSED) stringUTFChars(Thread* t, object string, unsigned start, unsigned length,
char* chars, unsigned charsLength UNUSED)
{ {
assert(t, static_cast<unsigned>(stringUTFLength(t, string)) == length); assert(t, static_cast<unsigned>
(stringUTFLength(t, string, start, length)) == charsLength);
if (stringLength(t, string)) { if (length) {
object data = stringData(t, string); object data = stringData(t, string);
if (objectClass(t, data) if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType)) == arrayBody(t, t->m->types, Machine::ByteArrayType))
{ {
memcpy(chars, memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string)), &byteArrayBody(t, data, stringOffset(t, string) + start),
stringLength(t, string)); length);
chars[stringLength(t, string)] = 0; chars[length] = 0;
} else { } else {
int j = 0; int j = 0;
for (unsigned i = 0; i < stringLength(t, string); ++i) { for (unsigned i = 0; i < length; ++i) {
uint16_t c = charArrayBody(t, data, stringOffset(t, string) + i); uint16_t c = charArrayBody
(t, data, stringOffset(t, string) + start + i);
if(!c) { // null char if(!c) { // null char
chars[j++] = 0; chars[j++] = 0;
} else if (c < 0x80) { // ASCII char } else if (c < 0x80) { // ASCII char
@ -3118,7 +3144,8 @@ resolveSystemClass(Thread* t, object spec)
hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash); hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash);
} else if (t->exception == 0) { } else if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = makeClassNotFoundException(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::ClassNotFoundExceptionType, message);
} }
} }
@ -3191,7 +3218,8 @@ resolveClass(Thread* t, object loader, object spec)
byteArrayHash); byteArrayHash);
} else if (t->exception == 0) { } else if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = makeClassNotFoundException(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::ClassNotFoundExceptionType, message);
} }
return class_; return class_;
@ -3216,7 +3244,8 @@ resolveMethod(Thread* t, object class_, const char* methodName,
(t, "%s %s not found in %s", methodName, methodSpec, (t, "%s %s not found in %s", methodName, methodSpec,
&byteArrayBody(t, className(t, class_), 0)); &byteArrayBody(t, className(t, class_), 0));
t->exception = makeNoSuchMethodError(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::NoSuchMethodErrorType, message);
return 0; return 0;
} else { } else {
return method; return method;
@ -3246,7 +3275,8 @@ resolveField(Thread* t, object class_, const char* fieldName,
(t, "%s %s not found in %s", fieldName, fieldSpec, (t, "%s %s not found in %s", fieldName, fieldSpec,
&byteArrayBody(t, className(t, class_), 0)); &byteArrayBody(t, className(t, class_), 0));
t->exception = makeNoSuchFieldError(t, message); t->exception = t->m->classpath->makeThrowable
(t, Machine::NoSuchFieldErrorType, message);
return 0; return 0;
} else { } else {
return field; return field;
@ -3324,7 +3354,9 @@ preInitClass(Thread* t, object c)
} else if (classVmFlags(t, c) & InitErrorFlag) { } else if (classVmFlags(t, c) & InitErrorFlag) {
object message = makeString object message = makeString
(t, "%s", &byteArrayBody(t, className(t, c), 0)); (t, "%s", &byteArrayBody(t, className(t, c), 0));
t->exception = makeNoClassDefFoundError(t, message);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NoClassDefFoundErrorType, message);
} else { } else {
classVmFlags(t, c) |= InitFlag; classVmFlags(t, c) |= InitFlag;
return true; return true;
@ -3341,7 +3373,9 @@ postInitClass(Thread* t, object c)
ACQUIRE(t, t->m->classLock); ACQUIRE(t, t->m->classLock);
if (t->exception) { if (t->exception) {
t->exception = makeExceptionInInitializerError(t, t->exception); t->exception = t->m->classpath->makeThrowable
(t, Machine::ExceptionInInitializerErrorType, 0, 0, t->exception);
classVmFlags(t, c) |= NeedInitFlag | InitErrorFlag; classVmFlags(t, c) |= NeedInitFlag | InitErrorFlag;
classVmFlags(t, c) &= ~InitFlag; classVmFlags(t, c) &= ~InitFlag;
} else { } else {
@ -3412,7 +3446,7 @@ findInTable(Thread* t, object table, object name, object spec,
object object
findInHierarchy(Thread* t, object class_, object name, object spec, findInHierarchy(Thread* t, object class_, object name, object spec,
object (*find)(Thread*, object, object, object), object (*find)(Thread*, object, object, object),
object (*makeError)(Thread*, object)) Machine::Type errorType)
{ {
object originalClass = class_; object originalClass = class_;
@ -3440,7 +3474,7 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
&byteArrayBody(t, name, 0), &byteArrayBody(t, name, 0),
&byteArrayBody(t, spec, 0), &byteArrayBody(t, spec, 0),
&byteArrayBody(t, className(t, originalClass), 0)); &byteArrayBody(t, className(t, originalClass), 0));
t->exception = makeError(t, message); t->exception = t->m->classpath->makeThrowable(t, errorType, message);
} }
return o; return o;
@ -3596,7 +3630,7 @@ collect(Thread* t, Heap::CollectionType type)
if (m->objectsToFinalize and m->finalizeThread == 0) { if (m->objectsToFinalize and m->finalizeThread == 0) {
m->finalizeThread = m->processor->makeThread m->finalizeThread = m->processor->makeThread
(m, makeJavaThread(t, m->rootThread), m->rootThread); (m, t->m->classpath->makeThread(t, m->rootThread), m->rootThread);
if (not t->m->system->success if (not t->m->system->success
(m->system->start(&(m->finalizeThread->runnable)))) (m->system->start(&(m->finalizeThread->runnable))))
@ -3695,7 +3729,8 @@ void
printTrace(Thread* t, object exception) printTrace(Thread* t, object exception)
{ {
if (exception == 0) { if (exception == 0) {
exception = makeNullPointerException(t, 0, makeTrace(t), 0); exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
} }
for (object e = exception; e; e = throwableCause(t, e)) { for (object e = exception; e; e = throwableCause(t, e)) {
@ -3738,6 +3773,10 @@ printTrace(Thread* t, object exception)
fprintf(stderr, "(line %d)\n", line); fprintf(stderr, "(line %d)\n", line);
} }
} }
if (e == throwableCause(t, e)) {
break;
}
} }
} }
@ -3792,17 +3831,6 @@ makeTrace(Thread* t, Thread* target)
return v.trace ? v.trace : makeArray(t, 0); return v.trace ? v.trace : makeArray(t, 0);
} }
void
runJavaThread(Thread* t)
{
object method = resolveMethod
(t, t->m->loader, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
if (t->exception == 0) {
t->m->processor->invoke(t, method, 0, t->javaThread);
}
}
void void
runFinalizeThread(Thread* t) runFinalizeThread(Thread* t)
{ {
@ -3833,6 +3861,47 @@ runFinalizeThread(Thread* t)
} }
} }
object
parseUtf8(Thread* t, const char* data, unsigned length)
{
class Client: public Stream::Client {
public:
Client(Thread* t): t(t) { }
virtual void NO_RETURN handleError() {
vm::abort(t);
}
private:
Thread* t;
} client(t);
Stream s(&client, reinterpret_cast<const uint8_t*>(data), length);
return ::parseUtf8(t, s, length);
}
object
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length)
{
PROTECT(t, loader);
object c = parseClass(t, loader, buffer, length);
if (c) {
PROTECT(t, c);
if (getClassLoaderMap(t, loader) == 0) {
object map = makeHashMap(t, 0, 0);
set(t, loader, ClassLoaderMap, map);
}
hashMapInsert(t, getClassLoaderMap(t, loader), className(t, c), c,
byteArrayHash);
}
return c;
}
void void
noop() noop()
{ } { }
@ -3857,7 +3926,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 ", class_, method); fprintf(stderr, " at %s.%s (%x) ", class_, method, walker->ip());
switch (line) { switch (line) {
case NativeLine: case NativeLine:

View File

@ -97,7 +97,6 @@ const unsigned ContinuationFlag = 1 << 11;
const unsigned ClassInitFlag = 1 << 0; const unsigned ClassInitFlag = 1 << 0;
const unsigned CompiledFlag = 1 << 1; const unsigned CompiledFlag = 1 << 1;
const unsigned ConstructorFlag = 1 << 2; const unsigned ConstructorFlag = 1 << 2;
const unsigned FastNative = 1 << 3;
#ifndef JNI_VERSION_1_6 #ifndef JNI_VERSION_1_6
#define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_6 0x00010006
@ -1151,6 +1150,8 @@ class Reference {
unsigned count; unsigned count;
}; };
class Classpath;
class Machine { class Machine {
public: public:
enum Type { enum Type {
@ -1164,7 +1165,8 @@ class Machine {
}; };
Machine(System* system, Heap* heap, Finder* finder, Processor* processor, Machine(System* system, Heap* heap, Finder* finder, Processor* processor,
const char** properties, unsigned propertyCount); Classpath* classpath, const char** properties,
unsigned propertyCount);
~Machine() { ~Machine() {
dispose(); dispose();
@ -1178,6 +1180,7 @@ class Machine {
Heap* heap; Heap* heap;
Finder* finder; Finder* finder;
Processor* processor; Processor* processor;
Classpath* classpath;
Thread* rootThread; Thread* rootThread;
Thread* exclusive; Thread* exclusive;
Thread* finalizeThread; Thread* finalizeThread;
@ -1371,11 +1374,45 @@ class Thread {
bool useBackupHeap; bool useBackupHeap;
bool waiting; bool waiting;
bool tracing; bool tracing;
#ifdef VM_STRESS bool daemon;
bool stress; bool stress;
#endif // VM_STRESS
}; };
class Classpath {
public:
virtual object
makeJclass(Thread* t, object class_) = 0;
virtual object
makeString(Thread* t, object array, int32_t offset, int32_t length) = 0;
virtual object
makeThread(Thread* t, Thread* parent) = 0;
virtual void
runThread(Thread* t) = 0;
virtual object
makeThrowable
(Thread* t, Machine::Type type, object message = 0, object trace = 0,
object cause = 0) = 0;
virtual void
boot(Thread* t) = 0;
virtual void
dispose() = 0;
};
inline void
runJavaThread(Thread* t)
{
t->m->classpath->runThread(t);
}
Classpath*
makeClasspath(System* system, Allocator* allocator);
typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*); typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*);
inline object inline object
@ -1731,160 +1768,10 @@ makeTrace(Thread* t)
return makeTrace(t, t); return makeTrace(t, t);
} }
inline object
makeRuntimeException(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeRuntimeException(t, message, trace, 0);
}
inline object
makeIllegalStateException(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeIllegalStateException(t, message, trace, 0);
}
inline object
makeIllegalArgumentException(Thread* t)
{
return makeIllegalArgumentException(t, 0, makeTrace(t), 0);
}
inline object
makeIllegalMonitorStateException(Thread* t)
{
return makeIllegalMonitorStateException(t, 0, makeTrace(t), 0);
}
inline object
makeIndexOutOfBoundsException(Thread* t)
{
return makeIndexOutOfBoundsException(t, 0, makeTrace(t), 0);
}
inline object
makeArrayIndexOutOfBoundsException(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeArrayIndexOutOfBoundsException(t, message, trace, 0);
}
inline object
makeArrayStoreException(Thread* t)
{
return makeArrayStoreException(t, 0, makeTrace(t), 0);
}
inline object
makeNegativeArraySizeException(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeNegativeArraySizeException(t, message, trace, 0);
}
inline object
makeClassCastException(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeClassCastException(t, message, trace, 0);
}
inline object
makeClassNotFoundException(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeClassNotFoundException(t, message, trace, 0, 0);
}
inline object
makeNullPointerException(Thread* t)
{
return makeNullPointerException(t, 0, makeTrace(t), 0);
}
inline object
makeInvocationTargetException(Thread* t, object targetException)
{
PROTECT(t, targetException);
object trace = makeTrace(t);
return makeRuntimeException(t, 0, trace, targetException);
}
inline object
makeInterruptedException(Thread* t)
{
return makeInterruptedException(t, 0, makeTrace(t), 0);
}
inline object
makeIncompatibleContinuationException(Thread* t)
{
return makeIncompatibleContinuationException(t, 0, makeTrace(t), 0);
}
inline object
makeStackOverflowError(Thread* t)
{
return makeStackOverflowError(t, 0, makeTrace(t), 0);
}
inline object
makeNoSuchFieldError(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeNoSuchFieldError(t, message, trace, 0);
}
inline object
makeNoSuchMethodError(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeNoSuchMethodError(t, message, trace, 0);
}
inline object
makeNoClassDefFoundError(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeNoClassDefFoundError(t, message, trace, 0);
}
inline object
makeUnsatisfiedLinkError(Thread* t, object message)
{
PROTECT(t, message);
object trace = makeTrace(t);
return makeUnsatisfiedLinkError(t, message, trace, 0);
}
inline object
makeExceptionInInitializerError(Thread* t, object cause)
{
PROTECT(t, cause);
object trace = makeTrace(t);
return makeExceptionInInitializerError(t, 0, trace, cause, cause);
}
inline object
makeIncompatibleClassChangeError(Thread* t)
{
return makeIncompatibleClassChangeError(t, 0, makeTrace(t), 0);
}
inline object inline object
makeNew(Thread* t, object class_) makeNew(Thread* t, object class_)
{ {
assert(t, t->state == Thread::ActiveState); assert(t, t->state == Thread::NoState or t->state == Thread::ActiveState);
PROTECT(t, class_); PROTECT(t, class_);
unsigned sizeInBytes = pad(classFixedSize(t, class_)); unsigned sizeInBytes = pad(classFixedSize(t, class_));
@ -1917,16 +1804,43 @@ object
makeString(Thread* t, const char* format, ...); makeString(Thread* t, const char* format, ...);
int int
stringUTFLength(Thread* t, object string); stringUTFLength(Thread* t, object string, unsigned start, unsigned length);
inline int
stringUTFLength(Thread* t, object string)
{
return stringUTFLength(t, string, 0, stringLength(t, string));
}
void void
stringChars(Thread* t, object string, char* chars); stringChars(Thread* t, object string, unsigned start, unsigned length,
char* chars);
inline void
stringChars(Thread* t, object string, char* chars)
{
stringChars(t, string, 0, stringLength(t, string), chars);
}
void void
stringChars(Thread* t, object string, uint16_t* chars); stringChars(Thread* t, object string, unsigned start, unsigned length,
uint16_t* chars);
inline void
stringChars(Thread* t, object string, uint16_t* chars)
{
stringChars(t, string, 0, stringLength(t, string), chars);
}
void void
stringUTFChars(Thread* t, object string, char* chars, unsigned length); stringUTFChars(Thread* t, object string, unsigned start, unsigned length,
char* chars, unsigned charsLength);
inline void
stringUTFChars(Thread* t, object string, char* chars, unsigned charsLength)
{
stringUTFChars(t, string, 0, stringLength(t, string), chars, charsLength);
}
bool bool
isAssignableFrom(Thread* t, object a, object b); isAssignableFrom(Thread* t, object a, object b);
@ -2159,6 +2073,9 @@ emptyMethod(Thread* t, object method)
and (codeBody(t, methodCode(t, method), 0) == return_); and (codeBody(t, methodCode(t, method), 0) == return_);
} }
object
parseUtf8(Thread* t, const char* data, unsigned length);
object object
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length); parseClass(Thread* t, object loader, const uint8_t* data, unsigned length);
@ -2264,13 +2181,13 @@ findMethodInClass(Thread* t, object class_, object name, object spec)
object object
findInHierarchy(Thread* t, object class_, object name, object spec, findInHierarchy(Thread* t, object class_, object name, object spec,
object (*find)(Thread*, object, object, object), object (*find)(Thread*, object, object, object),
object (*makeError)(Thread*, object)); Machine::Type errorType);
inline object inline object
findMethod(Thread* t, object class_, object name, object spec) findMethod(Thread* t, object class_, object name, object spec)
{ {
return findInHierarchy return findInHierarchy
(t, class_, name, spec, findMethodInClass, makeNoSuchMethodError); (t, class_, name, spec, findMethodInClass, Machine::NoSuchMethodErrorType);
} }
inline object inline object
@ -2690,10 +2607,12 @@ wait(Thread* t, object o, int64_t milliseconds)
bool interrupted = monitorWait(t, m, milliseconds); bool interrupted = monitorWait(t, m, milliseconds);
if (interrupted) { if (interrupted) {
t->exception = makeInterruptedException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::InterruptedExceptionType);
} }
} else { } else {
t->exception = makeIllegalMonitorStateException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalMonitorStateExceptionType);
} }
if (DebugMonitors) { if (DebugMonitors) {
@ -2722,7 +2641,8 @@ notify(Thread* t, object o)
if (m and monitorOwner(t, m) == t) { if (m and monitorOwner(t, m) == t) {
monitorNotify(t, m); monitorNotify(t, m);
} else { } else {
t->exception = makeIllegalMonitorStateException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalMonitorStateExceptionType);
} }
} }
@ -2739,7 +2659,8 @@ notifyAll(Thread* t, object o)
if (m and monitorOwner(t, m) == t) { if (m and monitorOwner(t, m) == t) {
monitorNotifyAll(t, m); monitorNotifyAll(t, m);
} else { } else {
t->exception = makeIllegalMonitorStateException(t); t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalMonitorStateExceptionType);
} }
} }
@ -2756,6 +2677,7 @@ 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;
if (daemon) { if (daemon) {
++ t->m->daemonCount; ++ t->m->daemonCount;
@ -2947,7 +2869,7 @@ resolveClassInPool(Thread* t, object method, unsigned index)
inline object inline object
resolve(Thread* t, object loader, object method, unsigned index, resolve(Thread* t, object loader, object method, unsigned index,
object (*find)(vm::Thread*, object, object, object), object (*find)(vm::Thread*, object, object, object),
object (*makeError)(vm::Thread*, object)) 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) == arrayBody(t, t->m->types, Machine::ReferenceType))
@ -2962,7 +2884,7 @@ resolve(Thread* t, object loader, object method, unsigned index,
o = findInHierarchy o = findInHierarchy
(t, class_, referenceName(t, reference), referenceSpec(t, reference), (t, class_, referenceName(t, reference), referenceSpec(t, reference),
find, makeError); find, errorType);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)), set(t, codePool(t, methodCode(t, method)),
@ -2976,7 +2898,7 @@ inline object
resolveField(Thread* t, object loader, object method, unsigned index) resolveField(Thread* t, object loader, object method, unsigned index)
{ {
return resolve(t, loader, method, index, findFieldInClass, return resolve(t, loader, method, index, findFieldInClass,
makeNoSuchFieldError); Machine::NoSuchFieldErrorType);
} }
inline object inline object
@ -2990,7 +2912,7 @@ inline object
resolveMethod(Thread* t, object loader, object method, unsigned index) resolveMethod(Thread* t, object loader, object method, unsigned index)
{ {
return resolve(t, loader, method, index, findMethodInClass, return resolve(t, loader, method, index, findMethodInClass,
makeNoSuchMethodError); Machine::NoSuchMethodErrorType);
} }
inline object inline object
@ -3004,6 +2926,8 @@ inline object
getJClass(Thread* t, object c) getJClass(Thread* t, object c)
{ {
if (classAddendum(t, c) == 0) { if (classAddendum(t, c) == 0) {
PROTECT(t, c);
ACQUIRE(t, t->m->classLock); ACQUIRE(t, t->m->classLock);
object addendum = makeClassAddendum(t, 0, 0, 0, 0); object addendum = makeClassAddendum(t, 0, 0, 0, 0);
@ -3013,9 +2937,11 @@ getJClass(Thread* t, object c)
object jclass = classAddendumClass(t, classAddendum(t, c)); object jclass = classAddendumClass(t, classAddendum(t, c));
if (jclass == 0) { if (jclass == 0) {
PROTECT(t, c);
ACQUIRE(t, t->m->classLock); ACQUIRE(t, t->m->classLock);
jclass = makeJclass(t, c); jclass = t->m->classpath->makeJclass(t, c);
set(t, classAddendum(t, c), ClassAddendumClass, jclass); set(t, classAddendum(t, c), ClassAddendumClass, jclass);
} }
@ -3023,6 +2949,29 @@ getJClass(Thread* t, object c)
return jclass; return jclass;
} }
inline object
primitiveClass(Thread* t, char name)
{
switch (name) {
case 'B': return arrayBody(t, t->m->types, Machine::JbyteType);
case 'C': return arrayBody(t, t->m->types, Machine::JcharType);
case 'D': return arrayBody(t, t->m->types, Machine::JdoubleType);
case 'F': return arrayBody(t, t->m->types, Machine::JfloatType);
case 'I': return arrayBody(t, t->m->types, Machine::JintType);
case 'J': return arrayBody(t, t->m->types, Machine::JlongType);
case 'S': return arrayBody(t, t->m->types, Machine::JshortType);
case 'V': return arrayBody(t, t->m->types, Machine::JvoidType);
case 'Z': return arrayBody(t, t->m->types, Machine::JbooleanType);
default:
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalArgumentExceptionType);
return 0;
}
}
object
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length);
void void
dumpHeap(Thread* t, FILE* out); dumpHeap(Thread* t, FILE* out);

View File

@ -755,7 +755,7 @@ class MySystem: public System {
return 0; return 0;
} else { } else {
// fprintf(stderr, "dlerror: %s\n", dlerror()); fprintf(stderr, "dlerror: %s\n", dlerror());
return 1; return 1;
} }
} }

View File

@ -207,18 +207,17 @@ resolveNativeMethod(Thread* t, object method, const char* prefix,
namespace vm { namespace vm {
void* object
resolveNativeMethod(Thread* t, object method) resolveNativeMethod(Thread* t, object method)
{ {
void* p = ::resolveNativeMethod(t, method, "Avian_", 6, 3); void* p = ::resolveNativeMethod(t, method, "Avian_", 6, 3);
if (p) { if (p) {
methodVmFlags(t, method) |= FastNative; return makeNative(t, p, true);
return p;
} }
p = ::resolveNativeMethod(t, method, "Java_", 5, -1); p = ::resolveNativeMethod(t, method, "Java_", 5, -1);
if (p) { if (p) {
return p; return makeNative(t, p, false);
} }
return 0; return 0;

View File

@ -56,7 +56,7 @@ isSpecialMethod(Thread* t, object method, object class_)
and isSuperclass(t, methodClass(t, method), class_); and isSuperclass(t, methodClass(t, method), class_);
} }
void* object
resolveNativeMethod(Thread* t, object method); resolveNativeMethod(Thread* t, object method);
inline void inline void

View File

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

View File

@ -87,7 +87,7 @@ class System {
class Library { class Library {
public: public:
virtual void* resolve(const char* function) = 0; virtual void* resolve(const char* symbol) = 0;
virtual const char* name() = 0; virtual const char* name() = 0;
virtual bool mapName() = 0; virtual bool mapName() = 0;
virtual Library* next() = 0; virtual Library* next() = 0;

View File

@ -400,6 +400,8 @@ class Array : public Scalar {
o->typeName = typeName; o->typeName = typeName;
o->name = name; o->name = name;
o->elementSize = elementSize; o->elementSize = elementSize;
o->noassert = false;
o->nogc = false;
return o; return o;
} }
}; };
@ -455,7 +457,7 @@ memberTypeName(Object* o)
} }
} }
const char* const char*&
memberName(Object* o) memberName(Object* o)
{ {
switch (o->type) { switch (o->type) {
@ -987,8 +989,11 @@ class MemberIterator {
offset_ += padding_; offset_ += padding_;
// printf("size: %d; padding: %d; alignment: %d; offset: %d;\n", // fprintf(stderr,
// size_, padding_, alignment_, offset_); // "type: %s; member: %s; size: %d; padding: %d; alignment: %d;"
// " offset: %d;\n",
// typeName(type), memberName(member), size_, padding_, alignment_,
// offset_);
return member; return member;
} }
@ -1087,6 +1092,27 @@ parseArray(Object* t, Object* p, Object* declarations)
typeName, name, sizeOf(typeName, declarations)); typeName, name, sizeOf(typeName, declarations));
} }
Object*
parseMember(Object* t, Object* p, Object* declarations);
Object*
parseMember(Object* t, Object* p, Object* declarations, bool* isNew)
{
Object* member = parseMember(t, p, declarations);
for (MemberIterator it(t); it.hasMore();) {
Object* m = it.next();
if (equal(memberName(m), memberName(member))) {
if (not equal(memberTypeName(m), memberTypeName(member))) {
abort();
}
*isNew = false;
return m;
}
}
*isNew = true;
return member;
}
Object* Object*
parseMember(Object* t, Object* p, Object* declarations) parseMember(Object* t, Object* p, Object* declarations)
{ {
@ -1094,13 +1120,24 @@ parseMember(Object* t, Object* p, Object* declarations)
if (equal(spec, "array")) { if (equal(spec, "array")) {
return parseArray(t, cdr(p), declarations); return parseArray(t, cdr(p), declarations);
} else if (equal(spec, "noassert")) { } else if (equal(spec, "noassert")) {
Object* member = parseMember(t, cdr(p), declarations); bool isNew;
Object* member = parseMember(t, cdr(p), declarations, &isNew);
memberNoAssert(member) = true; memberNoAssert(member) = true;
return member; return isNew ? member : 0;
} else if (equal(spec, "nogc")) { } else if (equal(spec, "nogc")) {
Object* member = parseMember(t, cdr(p), declarations); bool isNew;
Object* member = parseMember(t, cdr(p), declarations, &isNew);
memberNoGC(member) = true; memberNoGC(member) = true;
return member; return isNew ? member : 0;
} else if (equal(spec, "require")) {
bool isNew;
Object* member = parseMember(t, cdr(p), declarations, &isNew);
return isNew ? member : 0;
} else if (equal(spec, "alias")) {
bool isNew;
Object* member = parseMember(t, cdr(cdr(p)), declarations, &isNew);
memberName(member) = string(car(cdr(p)));
return isNew ? member : 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))),
@ -1120,9 +1157,11 @@ parseSubdeclaration(Object* t, Object* p, Object* declarations)
assert(typeSuper(t)->type == Object::Type); assert(typeSuper(t)->type == Object::Type);
} else { } else {
Object* member = parseMember(t, p, declarations); Object* member = parseMember(t, p, declarations);
if (member) {
addMember(t, member); addMember(t, member);
} }
} }
}
bool bool
memberEqual(Object* a, Object* b) memberEqual(Object* a, Object* b)
@ -1311,14 +1350,6 @@ parseJavaClass(Object* type, Stream* s, Object* declarations)
Object* member = Scalar::make Object* member = Scalar::make
(type, 0, memberType, name, sizeOf(memberType, declarations)); (type, 0, memberType, name, sizeOf(memberType, declarations));
if (equal(typeJavaName(type), "java/lang/ref/Reference")
and (equal(name, "vmNext")
or equal(name, "target")
or equal(name, "queue")))
{
memberNoGC(member) = true;
}
addMember(type, member); addMember(type, member);
} }
} }
@ -1379,10 +1410,12 @@ parseType(Object::ObjectType type, Object* p, Object* declarations,
parseSubdeclaration(t, car(p), declarations); parseSubdeclaration(t, car(p), declarations);
} else { } else {
Object* member = parseMember(t, car(p), declarations); Object* member = parseMember(t, car(p), declarations);
if (member) {
assert(member->type == Object::Scalar); assert(member->type == Object::Scalar);
addMember(t, member); addMember(t, member);
} }
} }
}
if (not isJavaType) { if (not isJavaType) {
if (type == Object::Type and typeSuper(t)) { if (type == Object::Type and typeSuper(t)) {

View File

@ -3,7 +3,18 @@
(type class avian/VMClass (type class avian/VMClass
(array void* vtable)) (array void* vtable))
(type jclass java/lang/Class) (type jclass java/lang/Class
(require object vmClass))
(type jaccessibleObject java/lang/reflect/AccessibleObject)
(type jfield java/lang/reflect/Field)
(type jmethod java/lang/reflect/Method)
(type jconstructor java/lang/reflect/Constructor)
(type constantPool sun/reflect/ConstantPool)
(type singleton (type singleton
(array uintptr_t body)) (array uintptr_t body))
@ -22,6 +33,10 @@
(type classAddendum avian/ClassAddendum) (type classAddendum avian/ClassAddendum)
(type methodAddendum avian/MethodAddendum)
(type fieldAddendum avian/FieldAddendum)
(type nativeMethodData (type nativeMethodData
(void* function) (void* function)
(uint16_t argumentTableSize) (uint16_t argumentTableSize)
@ -30,6 +45,10 @@
(type pointer (type pointer
(void* value)) (void* value))
(type native
(void* function)
(uint8_t fast))
(pod exceptionHandler (pod exceptionHandler
(uint16_t start) (uint16_t start)
(uint16_t end) (uint16_t end)
@ -142,15 +161,23 @@
(type callbackReceiver avian/CallbackReceiver) (type callbackReceiver avian/CallbackReceiver)
(type string java/lang/String) (type string java/lang/String
(alias data object value)
(alias length uint32_t count)
(alias hashCode uint32_t hash))
(type thread java/lang/Thread) (type thread java/lang/Thread
(require object sleepLock)
(require uint8_t interrupted)
(alias peer uint64_t eetop))
(type threadGroup java/lang/ThreadGroup) (type threadGroup java/lang/ThreadGroup)
(type stackTraceElement java/lang/StackTraceElement) (type stackTraceElement java/lang/StackTraceElement)
(type throwable java/lang/Throwable) (type throwable java/lang/Throwable
(alias message object detailMessage)
(alias trace object backtrace))
(type exception java/lang/Exception) (type exception java/lang/Exception)
@ -184,6 +211,8 @@
(type virtualMachineError java/lang/VirtualMachineError) (type virtualMachineError java/lang/VirtualMachineError)
(type outOfMemoryError java/lang/OutOfMemoryError)
(type stackOverflowError java/lang/StackOverflowError) (type stackOverflowError java/lang/StackOverflowError)
(type linkageError java/lang/LinkageError) (type linkageError java/lang/LinkageError)
@ -221,9 +250,17 @@
(type double java/lang/Double) (type double java/lang/Double)
(type referenceQueue java/lang/ref/ReferenceQueue) (type referenceQueue java/lang/ref/ReferenceQueue
(alias front object head))
(type jreference java/lang/ref/Reference) (type jreference java/lang/ref/Reference
(alias target object referent)
(alias queue object queue)
(alias jNext object next)
(alias vmNext object discovered)
(nogc object target)
(nogc object queue)
(nogc object vmNext))
(type weakReference java/lang/ref/WeakReference) (type weakReference java/lang/ref/WeakReference)

View File

@ -4,6 +4,7 @@ log=build/log.txt
vg="nice valgrind --leak-check=full --num-callers=32 \ vg="nice valgrind --leak-check=full --num-callers=32 \
--freelist-vol=100000000 --error-exitcode=1" --freelist-vol=100000000 --error-exitcode=1"
library_path=${1}; shift
vm=${1}; shift vm=${1}; shift
mode=${1}; shift mode=${1}; shift
flags=${1}; shift flags=${1}; shift
@ -18,10 +19,11 @@ for test in ${tests}; do
case ${mode} in case ${mode} in
debug|debug-fast|fast|small ) debug|debug-fast|fast|small )
${vm} ${flags} ${test} >>${log} 2>&1;; LD_LIBRARY_PATH=${library_path} ${vm} ${flags} ${test} >>${log} 2>&1;;
stress* ) stress* )
${vg} ${vm} ${flags} ${test} >>${log} 2>&1;; LD_LIBRARY_PATH=${library_path} ${vg} ${vm} ${flags} ${test} \
>>${log} 2>&1;;
* ) * )
echo "unknown mode: ${mode}" >&2 echo "unknown mode: ${mode}" >&2