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

@ -12,5 +12,5 @@ package avian;
public class Addendum {
public Object pool;
public Object annotationTable;
public Object annotationTable;
}

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;
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.MalformedURLException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
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)
throws ClassNotFoundException;
@ -35,6 +21,8 @@ public class SystemClassLoader extends ClassLoader {
return getClass(findVMClass(name));
}
public static native Class getClass(VMClass vmClass);
private static native VMClass findLoadedVMClass(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 VMClass resolveVMClass(ClassLoader loader, byte[] spec)
throws ClassNotFoundException;
protected URL findResource(String name) {
if (resourceExists(name)) {
try {
@ -55,261 +40,4 @@ public class SystemClassLoader extends ClassLoader {
}
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 byte[] name;
public byte[] spec;
public avian.Addendum addendum;
public FieldAddendum addendum;
public VMClass class_;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

203
makefile
View File

@ -1,4 +1,4 @@
MAKEFLAGS = -s
#MAKEFLAGS = -s
name = avian
version = 0.3
@ -39,11 +39,17 @@ endif
ifeq ($(continuations),true)
options := $(options)-continuations
endif
classpath = avian
test-library-path = .
test-executable = $(executable)
ifdef gnu
classpath = gnu
options := $(options)-gnu
gnu-sources = $(src)/gnu.cpp
gnu-jar = $(gnu)/share/classpath/glibj.zip
gnu-libraries = \
classapth-jar = $(gnu)/share/classpath/glibj.zip
classpath-libraries = \
$(gnu)/lib/classpath/libjavaio.a \
$(gnu)/lib/classpath/libjavalang.a \
$(gnu)/lib/classpath/libjavalangreflect.a \
@ -51,10 +57,20 @@ ifdef gnu
$(gnu)/lib/classpath/libjavanet.a \
$(gnu)/lib/classpath/libjavanio.a \
$(gnu)/lib/classpath/libjavautil.a
gnu-object-dep = $(build)/gnu-object.dep
gnu-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU
gnu-lflags = -lgmp
gnu-objects = $(shell find $(build)/gnu-objects -name "*.o")
classpath-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU
classpath-lflags = -lgmp
endif
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
root := $(shell (cd .. && pwd))
@ -63,13 +79,16 @@ native-build = $(build)/$(platform)-$(arch)$(options)
classpath-build = $(build)/classpath
test-build = $(build)/test
src = src
classpath = classpath
classpath-src = classpath
test = test
ifdef gnu
avian-classpath-build = $(build)/avian-classpath
ifneq ($(classpath),avian)
classpath-object-dep = $(build)/classpath-object.dep
classpath-objects = $(shell find $(build)/classpath-objects -name "*.o")
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
input = List
@ -79,12 +98,12 @@ build-cc = gcc
mflag =
ifneq ($(platform),darwin)
ifeq ($(arch),i386)
mflag = -m32
endif
ifeq ($(arch),x86_64)
mflag = -m64
endif
ifeq ($(arch),i386)
mflag = -m32
endif
ifeq ($(arch),x86_64)
mflag = -m64
endif
endif
cxx = $(build-cxx) $(mflag)
@ -112,14 +131,14 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
-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 \
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
cflags = $(build-cflags)
common-lflags = -lm -lz $(gnu-lflags)
common-lflags = -lm -lz $(classpath-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)))
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 = \
$(native-build)/type-enums.cpp \
$(native-build)/type-declarations.cpp \
@ -307,26 +323,7 @@ generated-code = \
$(native-build)/type-initializations.cpp \
$(native-build)/type-java-initializations.cpp
vm-depends = \
$(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-depends := $(generated-code) $(wildcard $(src)/*.h)
vm-sources = \
$(src)/$(system).cpp \
@ -335,10 +332,10 @@ vm-sources = \
$(src)/util.cpp \
$(src)/heap.cpp \
$(src)/$(process).cpp \
$(src)/classpath-$(classpath).cpp \
$(src)/builtin.cpp \
$(src)/jnienv.cpp \
$(src)/process.cpp \
$(gnu-sources)
$(src)/process.cpp
vm-asm-sources = $(src)/$(asm).S
@ -428,48 +425,37 @@ converter = $(native-build)/binaryToObject
static-library = $(native-build)/lib$(name).a
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}
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 = \
$(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-dep = $(classpath-build).dep
gnu-blacklist = \
java/lang/AbstractStringBuffer.class \
java/lang/reflect/Proxy.class
gnu-overrides = \
vm-classes = \
avian/*.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
avian/resource/*.class
test-sources = $(wildcard $(test)/*.java)
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
@ -510,7 +496,7 @@ vg: build
.PHONY: test
test: build
/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))
.PHONY: tarball
@ -549,27 +535,20 @@ $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep)
$(native-build)/type-generator.o: \
$(generator-headers)
$(classpath-build)/%.class: $(classpath)/%.java
$(classpath-build)/%.class: $(classpath-src)/%.java
@echo $(<)
$(classpath-dep): $(classpath-sources) $(gnu-jar)
$(classpath-dep): $(classpath-sources) $(classpath-jar)
@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)
ifneq ($(classpath),avian)
(wd=$$(pwd) && \
cd $(classpath-build) && \
$(jar) xf $(gnu-jar) && \
rm $(gnu-blacklist) && \
jar xf "$$($(native-path) "$${wd}/$(build)/overrides.jar")")
$(jar) xf $(classpath-jar))
endif
$(javac) -d $(classpath-build) \
-bootclasspath $(classpath-build) \
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
@touch $(@)
$(test-build)/%.class: $(test)/%.java
@ -625,7 +604,7 @@ $(driver-object): $(driver-source)
$(driver-dynamic-object): $(driver-source)
@echo "compiling $(@)"
@mkdir -p $(dir $(@))
$(cxx) $(cflags) -DBOOT_LIBRARY=\"$(so-prefix)$(name)$(so-suffix)\" \
$(cxx) $(cflags) -DBOOT_LIBRARY=\"$(so-prefix)jvm$(so-suffix)\" \
-c $(<) $(call output,$(@))
$(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) \
-c $(<) -o $(@)
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
$(jni-objects): $(native-build)/%.o: $(classpath-src)/%.cpp
$(compile-object)
$(static-library): $(gnu-object-dep)
$(static-library): $(classpath-object-dep)
$(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects)
@echo "creating $(@)"
rm -rf $(@)
$(ar) cru $(@) $(^) $(call gnu-objects)
$(ar) cru $(@) $(^) $(call classpath-objects)
$(ranlib) $(@)
$(bootimage-bin): $(bootimage-generator)
@ -687,13 +666,13 @@ $(bootimage-object): $(bootimage-bin) $(converter)
_binary_bootimage_bin_end $(platform) $(arch) $(pointer-size) \
writable executable
$(gnu-object-dep): $(gnu-libraries)
@mkdir -p $(build)/gnu-objects
(cd $(build)/gnu-objects && \
for x in $(gnu-libraries); do ar x $${x}; done)
$(classpath-object-dep): $(classpath-libraries)
@mkdir -p $(build)/classpath-objects
(cd $(build)/classpath-objects && \
for x in $(classpath-libraries); do ar x $${x}; done)
@touch $(@)
$(executable): $(gnu-object-dep)
$(executable): $(classpath-object-dep)
$(executable): \
$(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \
$(boot-object) $(vm-classpath-object)
@ -704,13 +683,13 @@ ifdef msvc
-MANIFESTFILE:$(@).manifest
$(mt) -manifest $(@).manifest -outputresource:"$(@);1"
else
$(dlltool) -z $(@).def $(^) $(call gnu-objects)
$(dlltool) -z $(@).def $(^) $(call classpath-objects)
$(dlltool) -d $(@).def -e $(@).exp
$(ld) $(@).exp $(^) $(call gnu-objects) $(lflags) -o $(@)
$(ld) $(@).exp $(^) $(call classpath-objects) $(lflags) -o $(@)
endif
else
$(ld) $(^) $(call gnu-objects) $(rdynamic) $(lflags) $(bootimage-lflags) \
-o $(@)
$(ld) $(^) $(call classpath-objects) $(rdynamic) $(lflags) \
$(bootimage-lflags) -o $(@)
endif
$(strip) $(strip-all) $(@)
@ -740,18 +719,18 @@ else
$(ld) $(^) $(rdynamic) $(lflags) -o $(@)
endif
$(dynamic-library): $(gnu-object-dep)
$(dynamic-library): $(classpath-object-dep)
$(dynamic-library): \
$(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 $(@)"
ifdef msvc
$(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \
-IMPLIB:$(native-build)/$(name).lib -MANIFESTFILE:$(@).manifest
$(mt) -manifest $(@).manifest -outputresource:"$(@);2"
else
$(ld) $(^) $(call gnu-objects) $(shared) $(lflags) $(bootimage-lflags) \
-o $(@)
$(ld) $(^) -Wl,--version-script=openjdk.ld \
$(call classpath-objects) $(shared) $(lflags) $(bootimage-lflags) -o $(@)
endif
$(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);
} else {
t->exception = makeNullPointerException(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
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
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
Avian_avian_SystemClassLoader_acquireClassLock
(Thread* t, object, uintptr_t*)
@ -195,8 +74,6 @@ Avian_avian_SystemClassLoader_defineVMClass
(Thread* t, object, uintptr_t* arguments)
{
object loader = reinterpret_cast<object>(arguments[0]);
PROTECT(t, loader);
object b = reinterpret_cast<object>(arguments[1]);
int offset = arguments[2];
int length = arguments[3];
@ -204,20 +81,9 @@ Avian_avian_SystemClassLoader_defineVMClass
uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(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);
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);
}
@ -260,62 +126,21 @@ Avian_avian_SystemClassLoader_resourceExists
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
return t->m->finder->exists(RUNTIME_ARRAY_BODY(n));
} else {
t->exception = makeNullPointerException(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
return 0;
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_io_ObjectInputStream_makeInstance
Avian_avian_SystemClassLoader_primitiveClass
(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_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;
}
return reinterpret_cast<int64_t>(primitiveClass(t, arguments[0]));
}
extern "C" JNIEXPORT void JNICALL
Avian_java_lang_Class_initialize
Avian_avian_SystemClassLoader_initialize
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
@ -324,7 +149,7 @@ Avian_java_lang_Class_initialize
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_java_lang_Class_isAssignableFrom
Avian_avian_SystemClassLoader_isAssignableFrom
(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
@ -333,392 +158,12 @@ Avian_java_lang_Class_isAssignableFrom
if (LIKELY(that)) {
return vm::isAssignableFrom(t, this_, that);
} else {
t->exception = makeNullPointerException(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
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
extern "C" JNIEXPORT void JNICALL
@ -753,193 +198,6 @@ Avian_java_lang_Runtime_exit
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
Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength
(Thread* t, object, uintptr_t* arguments)
@ -973,7 +231,8 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open
return reinterpret_cast<int64_t>
(t->m->finder->find(RUNTIME_ARRAY_BODY(p)));
} else {
t->exception = makeNullPointerException(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
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;
}
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 Thread;

View File

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

View File

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

View File

@ -10,11 +10,11 @@
#ifdef __x86_64__
#define THREAD_CONTINUATION 2224
#define THREAD_CONTINUATION 2232
#define THREAD_EXCEPTION 80
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2232
#define THREAD_EXCEPTION_OFFSET 2240
#define THREAD_EXCEPTION_HANDLER 2248
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2240
#define THREAD_EXCEPTION_OFFSET 2248
#define THREAD_EXCEPTION_HANDLER 2256
#define CONTINUATION_NEXT 8
#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, methodName(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))
> Thread::StackSizeInWords / 2))
{
t->exception = makeStackOverflowError(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
}
}
@ -680,15 +683,15 @@ invokeNativeSlow(Thread* t, object method)
&byteArrayBody(t, methodName(t, method), 0));
}
// if (strcmp(reinterpret_cast<const char*>
// (&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
// "org/eclipse/swt/internal/C") == 0
// and strcmp(reinterpret_cast<const char*>
// (&byteArrayBody(t, methodName(t, method), 0)),
// "memmove") == 0)
// {
// asm("int3");
// }
// if (strcmp(reinterpret_cast<const char*>
// (&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
// "org/eclipse/swt/internal/C") == 0
// and strcmp(reinterpret_cast<const char*>
// (&byteArrayBody(t, methodName(t, method), 0)),
// "memmove") == 0)
// {
// asm("int3");
// }
{ ENTER(t, Thread::IdleState);
@ -931,13 +934,15 @@ interpret(Thread* t)
{
pushObject(t, objectArrayBody(t, array, index));
} else {
object message = makeString(t, "%d not in [0,%d)", index,
objectArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
object message = makeString
(t, "%d not in [0,%d)", index, objectArrayLength(t, array));
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -953,13 +958,15 @@ interpret(Thread* t)
{
set(t, array, ArrayBody + (index * BytesPerWord), value);
} else {
object message = makeString(t, "%d not in [0,%d)", index,
objectArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
object message = makeString
(t, "%d not in [0,%d)", index, objectArrayLength(t, array));
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1002,7 +1009,8 @@ interpret(Thread* t)
class_, count));
} else {
object message = makeString(t, "%d", count);
exception = makeNegativeArraySizeException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_;
}
} goto loop;
@ -1023,7 +1031,8 @@ interpret(Thread* t)
if (LIKELY(array)) {
pushInt(t, cast<uintptr_t>(array, BytesPerWord));
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1051,7 +1060,8 @@ interpret(Thread* t)
case athrow: {
exception = popObject(t);
if (UNLIKELY(exception == 0)) {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
}
} goto throw_;
@ -1071,7 +1081,8 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
booleanArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
@ -1083,12 +1094,15 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
byteArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1110,7 +1124,8 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
booleanArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
@ -1121,12 +1136,14 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
byteArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1147,11 +1164,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
charArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1169,11 +1188,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
charArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1191,7 +1212,8 @@ interpret(Thread* t)
&byteArrayBody
(t, className(t, objectClass(t, peekObject(t, sp - 1))), 0),
&byteArrayBody(t, className(t, class_), 0));
exception = makeClassCastException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ClassCastExceptionType, message);
goto throw_;
}
}
@ -1228,11 +1250,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
doubleArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1250,11 +1274,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
doubleArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1428,11 +1454,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
floatArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1450,11 +1478,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
floatArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1566,7 +1596,8 @@ interpret(Thread* t)
}
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1658,11 +1689,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
intArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1687,11 +1720,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
intArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1958,7 +1993,8 @@ interpret(Thread* t)
(t, method, objectClass(t, peekObject(t, sp - parameterFootprint)));
goto invoke;
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -1983,7 +2019,8 @@ interpret(Thread* t)
goto invoke;
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2014,7 +2051,8 @@ interpret(Thread* t)
code = findVirtualMethod(t, method, class_);
goto invoke;
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2150,11 +2188,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
longArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2179,11 +2219,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
longArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2413,7 +2455,8 @@ interpret(Thread* t)
if (LIKELY(o)) {
acquire(t, o);
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2423,7 +2466,8 @@ interpret(Thread* t)
if (LIKELY(o)) {
release(t, o);
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2441,7 +2485,8 @@ interpret(Thread* t)
counts[i] = popInt(t);
if (UNLIKELY(counts[i] < 0)) {
object message = makeString(t, "%d", counts[i]);
exception = makeNegativeArraySizeException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_;
}
}
@ -2514,7 +2559,8 @@ interpret(Thread* t)
pushObject(t, array);
} else {
object message = makeString(t, "%d", count);
exception = makeNegativeArraySizeException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::NegativeArraySizeExceptionType, message);
goto throw_;
}
} goto loop;
@ -2576,7 +2622,8 @@ interpret(Thread* t)
break;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
}
} break;
@ -2587,7 +2634,8 @@ interpret(Thread* t)
if (LIKELY(o)) {
cast<int64_t>(o, fieldOffset(t, field)) = value;
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
}
} break;
@ -2597,7 +2645,8 @@ interpret(Thread* t)
if (LIKELY(o)) {
set(t, o, fieldOffset(t, field), value);
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
}
} break;
@ -2727,11 +2776,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
shortArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -2749,11 +2800,13 @@ interpret(Thread* t)
} else {
object message = makeString(t, "%d not in [0,%d)", index,
shortArrayLength(t, array));
exception = makeArrayIndexOutOfBoundsException(t, message);
exception = t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType, message);
goto throw_;
}
} else {
exception = makeNullPointerException(t);
exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
goto throw_;
}
} goto loop;
@ -3195,7 +3248,8 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
> Thread::StackSizeInWords / 2))
{
t->exception = makeStackOverflowError(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
return 0;
}
@ -3220,7 +3274,8 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
> Thread::StackSizeInWords / 2))
{
t->exception = makeStackOverflowError(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
return 0;
}
@ -3244,7 +3299,8 @@ class MyProcessor: public Processor {
if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false)
> Thread::StackSizeInWords / 2))
{
t->exception = makeStackOverflowError(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::StackOverflowErrorType);
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));
}
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
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);
}
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
GetArrayLength(Thread* t, jarray array)
{
@ -206,9 +258,8 @@ NewString(Thread* t, const jchar* chars, jsize size)
a = makeCharArray(t, size);
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
@ -218,15 +269,11 @@ NewStringUTF(Thread* t, const char* chars)
ENTER(t, Thread::ActiveState);
object a = 0;
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);
object array = parseUtf8(t, chars, strlen(chars));
return makeLocalReference(t, s);
return makeLocalReference
(t, t->m->classpath->makeString
(t, array, 0, cast<uintptr_t>(array, BytesPerWord) - 1));
}
void
@ -240,6 +287,19 @@ replace(int a, int b, const char* in, int8_t* out)
*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
FindClass(Thread* t, const char* name)
{
@ -279,6 +339,20 @@ ThrowNew(Thread* t, jclass c, const char* message)
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
DeleteLocalRef(Thread* t, jobject r)
{
@ -329,6 +403,14 @@ IsInstanceOf(Thread* t, jobject o, jclass c)
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
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);
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);
@ -1116,7 +1201,7 @@ SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v)
{
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
@ -1222,6 +1307,12 @@ DeleteGlobalRef(Thread* t, jobject r)
}
}
jint JNICALL
EnsureLocalCapacity(Thread*, jint)
{
return 0;
}
jthrowable JNICALL
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
MonitorEnter(Thread* t, jobject o)
{
@ -1948,14 +2067,20 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->GetStringLength = local::GetStringLength;
envTable->GetStringChars = local::GetStringChars;
envTable->ReleaseStringChars = local::ReleaseStringChars;
envTable->GetStringRegion = local::GetStringRegion;
envTable->GetStringCritical = local::GetStringCritical;
envTable->ReleaseStringCritical = local::ReleaseStringCritical;
envTable->GetStringUTFLength = local::GetStringUTFLength;
envTable->GetStringUTFChars = local::GetStringUTFChars;
envTable->ReleaseStringUTFChars = local::ReleaseStringUTFChars;
envTable->GetStringUTFRegion = local::GetStringUTFRegion;
envTable->GetArrayLength = local::GetArrayLength;
envTable->NewString = local::NewString;
envTable->NewStringUTF = local::NewStringUTF;
envTable->DefineClass = local::DefineClass;
envTable->FindClass = local::FindClass;
envTable->ThrowNew = local::ThrowNew;
envTable->Throw = local::Throw;
envTable->ExceptionCheck = local::ExceptionCheck;
#ifdef AVIAN_GNU
envTable->NewDirectByteBuffer = vm::NewDirectByteBuffer;
@ -1969,6 +2094,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->DeleteLocalRef = local::DeleteLocalRef;
envTable->GetObjectClass = local::GetObjectClass;
envTable->IsInstanceOf = local::IsInstanceOf;
envTable->IsAssignableFrom = local::IsAssignableFrom;
envTable->GetFieldID = local::GetFieldID;
envTable->GetMethodID = local::GetMethodID;
envTable->GetStaticMethodID = local::GetStaticMethodID;
@ -2054,6 +2180,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->NewGlobalRef = local::NewGlobalRef;
envTable->NewWeakGlobalRef = local::NewGlobalRef;
envTable->DeleteGlobalRef = local::DeleteGlobalRef;
envTable->EnsureLocalCapacity = local::EnsureLocalCapacity;
envTable->ExceptionOccurred = local::ExceptionOccurred;
envTable->ExceptionDescribe = local::ExceptionDescribe;
envTable->ExceptionClear = local::ExceptionClear;
@ -2103,6 +2230,8 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
envTable->GetPrimitiveArrayCritical = local::GetPrimitiveArrayCritical;
envTable->ReleasePrimitiveArrayCritical
= local::ReleasePrimitiveArrayCritical;
envTable->RegisterNatives = local::RegisterNatives;
envTable->UnregisterNatives = local::UnregisterNatives;
envTable->MonitorEnter = local::MonitorEnter;
envTable->MonitorExit = local::MonitorExit;
envTable->GetJavaVM = local::GetJavaVM;
@ -2201,6 +2330,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
Heap* h = makeHeap(s, heapLimit);
Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary);
Processor* p = makeProcessor(s, h, true);
Classpath* c = makeClasspath(s, h);
const char** properties = static_cast<const char**>
(h->allocate(sizeof(const char*) * propertyCount));
@ -2212,11 +2342,14 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
}
*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);
enter(*t, Thread::ActiveState);
c->boot(*t);
enter(*t, Thread::IdleState);
return 0;

View File

@ -196,10 +196,12 @@ turnOffTheLights(Thread* t)
System* s = m->system;
Heap* h = m->heap;
Processor* p = m->processor;
Classpath* c = m->classpath;
Finder* f = m->finder;
m->dispose();
h->disposeFixies();
c->dispose();
p->dispose();
h->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
footprint(Thread* t)
{
@ -377,13 +362,12 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
object q = jreferenceQueue(t, *p);
set(t, *p, JreferenceJNext, *p);
if (referenceQueueFront(t, q)) {
set(t, referenceQueueRear(t, q), JreferenceJNext, *p);
set(t, *p, JreferenceJNext, referenceQueueFront(t, q));
} 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;
}
@ -793,8 +777,8 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
parsePoolEntry(t, s, index, pool, si);
object value = singletonObject(t, pool, si);
value = makeString
(t, value, 0, cast<uintptr_t>(value, BytesPerWord) - 1, 0);
value = t->m->classpath->makeString
(t, value, 0, cast<uintptr_t>(value, BytesPerWord) - 1);
value = intern(t, 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);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)),
length);
addendum = makeAddendum(t, pool, body);
addendum = makeFieldAddendum(t, pool, body);
} else {
s.skip(length);
}
@ -1082,9 +1066,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
classVmFlags(t, class_) |= HasFinalMemberFlag;
}
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord;
if (excess) {
memberOffset += BytesPerWord - excess;
while (memberOffset % fieldSize(t, code)) {
++ memberOffset;
}
fieldOffset(t, field) = memberOffset;
@ -1392,14 +1375,29 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
&byteArrayBody(t, name, 0)) == 0)
{
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*>
("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0)
{
if (addendum == 0) {
addendum = makeMethodAddendum(t, pool, 0, 0);
}
object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)),
length);
addendum = makeAddendum(t, pool, body);
set(t, addendum, AddendumAnnotationTable, body);
} else {
s.skip(length);
}
@ -1549,7 +1547,6 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (abstractVirtuals) {
PROTECT(t, vtable);
PROTECT(t, abstractVirtuals);
unsigned oldLength = arrayLength(t, classMethodTable(t, class_));
object newMethodTable = makeArray
@ -1673,8 +1670,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
// verify that the classes have the same layout
expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_));
expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType)
or classFixedSize(t, bootstrapClass) >= classFixedSize(t, class_));
expect(t, classFixedSize(t, bootstrapClass) >= classFixedSize(t, class_));
expect(t, (classVmFlags(t, class_) & HasFinalizerFlag) == 0);
@ -2079,8 +2075,8 @@ class HeapClient: public Heap::Client {
namespace vm {
Machine::Machine(System* system, Heap* heap, Finder* finder,
Processor* processor, const char** properties,
unsigned propertyCount):
Processor* processor, Classpath* classpath,
const char** properties, unsigned propertyCount):
vtable(&javaVMVTable),
system(system),
heapClient(new (heap->allocate(sizeof(HeapClient)))
@ -2088,6 +2084,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
heap(heap),
finder(finder),
processor(processor),
classpath(classpath),
rootThread(0),
exclusive(0),
finalizeThread(0),
@ -2199,7 +2196,8 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
backupHeapIndex(0),
useBackupHeap(false),
waiting(false),
tracing(false)
tracing(false),
daemon(false)
#ifdef VM_STRESS
, stress(false)
#endif // VM_STRESS
@ -2248,10 +2246,11 @@ Thread::init()
m->jniMethodTable = makeVector(this, 0, 0);
m->nullPointerException = makeNullPointerException(this);
m->nullPointerException = m->classpath->makeThrowable
(this, Machine::NullPointerExceptionType);
m->arrayIndexOutOfBoundsException
= makeArrayIndexOutOfBoundsException(this, 0);
m->arrayIndexOutOfBoundsException = m->classpath->makeThrowable
(this, Machine::IndexOutOfBoundsExceptionType);
m->localThread->set(this);
} else {
@ -2262,7 +2261,7 @@ Thread::init()
expect(this, m->system->success(m->system->make(&lock)));
if (javaThread == 0) {
this->javaThread = makeJavaThread(this, parent);
this->javaThread = m->classpath->makeThread(this, parent);
}
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
@ -2365,6 +2364,7 @@ enter(Thread* t, Thread::State s)
return;
}
#ifdef USE_ATOMIC_OPERATIONS
# define INCREMENT atomicIncrement
# define ACQUIRE_LOCK ACQUIRE_RAW(t, t->m->stateLock)
@ -2408,6 +2408,24 @@ enter(Thread* t, Thread::State s)
} break;
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) {
// fast path
assert(t, t->m->activeCount > 0);
@ -2420,6 +2438,7 @@ enter(Thread* t, Thread::State s)
t->m->stateLock->notifyAll(t->systemThread);
}
break;
} else {
// fall through to slow path
@ -2692,91 +2711,98 @@ makeString(Thread* t, const char* format, ...)
object s = ::makeByteArray(t, format, 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
stringUTFLength(Thread* t, object string) {
int length = 0;
stringUTFLength(Thread* t, object string, unsigned start, unsigned length)
{
unsigned result = 0;
if (stringLength(t, string)) {
if (length) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType)) {
length = stringLength(t, string);
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
result = length;
} else {
for (unsigned i = 0; i < stringLength(t, string); ++i) {
uint16_t c = charArrayBody(t, data, stringOffset(t, string) + i);
if (!c) length += 1; // null char (was 2 bytes in Java)
else if (c < 0x80) length += 1; // ASCII char
else if (c < 0x800) length += 2; // two-byte char
else length += 3; // three-byte char
for (unsigned i = 0; i < length; ++i) {
uint16_t c = charArrayBody
(t, data, stringOffset(t, string) + start + i);
if (c == 0) result += 1; // null char (was 2 bytes in Java)
else if (c < 0x80) result += 1; // ASCII char
else if (c < 0x800) result += 2; // two-byte char
else result += 3; // three-byte char
}
}
}
return length;
return result;
}
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);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string));
&byteArrayBody(t, data, stringOffset(t, string) + start),
length);
} else {
for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = charArrayBody(t, data, stringOffset(t, string) + i);
for (unsigned i = 0; i < length; ++i) {
chars[i] = charArrayBody(t, data, stringOffset(t, string) + start + i);
}
}
}
chars[stringLength(t, string)] = 0;
chars[length] = 0;
}
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);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
for (unsigned i = 0; i < stringLength(t, string); ++i) {
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + i);
for (unsigned i = 0; i < length; ++i) {
chars[i] = byteArrayBody(t, data, stringOffset(t, string) + start + i);
}
} else {
memcpy(chars,
&charArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string) * sizeof(uint16_t));
&charArrayBody(t, data, stringOffset(t, string) + start),
length * sizeof(uint16_t));
}
}
chars[stringLength(t, string)] = 0;
chars[length] = 0;
}
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);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string));
chars[stringLength(t, string)] = 0;
&byteArrayBody(t, data, stringOffset(t, string) + start),
length);
chars[length] = 0;
} else {
int j = 0;
for (unsigned i = 0; i < stringLength(t, string); ++i) {
uint16_t c = charArrayBody(t, data, stringOffset(t, string) + i);
for (unsigned i = 0; i < length; ++i) {
uint16_t c = charArrayBody
(t, data, stringOffset(t, string) + start + i);
if(!c) { // null char
chars[j++] = 0;
} else if (c < 0x80) { // ASCII char
@ -3118,7 +3144,8 @@ resolveSystemClass(Thread* t, object spec)
hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash);
} else if (t->exception == 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);
} else if (t->exception == 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_;
@ -3216,7 +3244,8 @@ resolveMethod(Thread* t, object class_, const char* methodName,
(t, "%s %s not found in %s", methodName, methodSpec,
&byteArrayBody(t, className(t, class_), 0));
t->exception = makeNoSuchMethodError(t, message);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NoSuchMethodErrorType, message);
return 0;
} else {
return method;
@ -3246,7 +3275,8 @@ resolveField(Thread* t, object class_, const char* fieldName,
(t, "%s %s not found in %s", fieldName, fieldSpec,
&byteArrayBody(t, className(t, class_), 0));
t->exception = makeNoSuchFieldError(t, message);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NoSuchFieldErrorType, message);
return 0;
} else {
return field;
@ -3324,7 +3354,9 @@ preInitClass(Thread* t, object c)
} else if (classVmFlags(t, c) & InitErrorFlag) {
object message = makeString
(t, "%s", &byteArrayBody(t, className(t, c), 0));
t->exception = makeNoClassDefFoundError(t, message);
t->exception = t->m->classpath->makeThrowable
(t, Machine::NoClassDefFoundErrorType, message);
} else {
classVmFlags(t, c) |= InitFlag;
return true;
@ -3341,7 +3373,9 @@ postInitClass(Thread* t, object c)
ACQUIRE(t, t->m->classLock);
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) &= ~InitFlag;
} else {
@ -3412,7 +3446,7 @@ findInTable(Thread* t, object table, object name, object spec,
object
findInHierarchy(Thread* t, object class_, object name, object spec,
object (*find)(Thread*, object, object, object),
object (*makeError)(Thread*, object))
Machine::Type errorType)
{
object originalClass = class_;
@ -3440,7 +3474,7 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
&byteArrayBody(t, name, 0),
&byteArrayBody(t, spec, 0),
&byteArrayBody(t, className(t, originalClass), 0));
t->exception = makeError(t, message);
t->exception = t->m->classpath->makeThrowable(t, errorType, message);
}
return o;
@ -3596,7 +3630,7 @@ collect(Thread* t, Heap::CollectionType type)
if (m->objectsToFinalize and m->finalizeThread == 0) {
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
(m->system->start(&(m->finalizeThread->runnable))))
@ -3695,7 +3729,8 @@ void
printTrace(Thread* t, object exception)
{
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)) {
@ -3738,6 +3773,10 @@ printTrace(Thread* t, object exception)
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);
}
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
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
noop()
{ }
@ -3857,7 +3926,7 @@ vmPrintTrace(Thread* t)
int line = t->m->processor->lineNumber
(t, walker->method(), walker->ip());
fprintf(stderr, " at %s.%s ", class_, method);
fprintf(stderr, " at %s.%s (%x) ", class_, method, walker->ip());
switch (line) {
case NativeLine:

View File

@ -97,7 +97,6 @@ const unsigned ContinuationFlag = 1 << 11;
const unsigned ClassInitFlag = 1 << 0;
const unsigned CompiledFlag = 1 << 1;
const unsigned ConstructorFlag = 1 << 2;
const unsigned FastNative = 1 << 3;
#ifndef JNI_VERSION_1_6
#define JNI_VERSION_1_6 0x00010006
@ -1151,6 +1150,8 @@ class Reference {
unsigned count;
};
class Classpath;
class Machine {
public:
enum Type {
@ -1164,7 +1165,8 @@ class Machine {
};
Machine(System* system, Heap* heap, Finder* finder, Processor* processor,
const char** properties, unsigned propertyCount);
Classpath* classpath, const char** properties,
unsigned propertyCount);
~Machine() {
dispose();
@ -1178,6 +1180,7 @@ class Machine {
Heap* heap;
Finder* finder;
Processor* processor;
Classpath* classpath;
Thread* rootThread;
Thread* exclusive;
Thread* finalizeThread;
@ -1371,11 +1374,45 @@ class Thread {
bool useBackupHeap;
bool waiting;
bool tracing;
#ifdef VM_STRESS
bool daemon;
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*);
inline object
@ -1731,160 +1768,10 @@ makeTrace(Thread* 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
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_);
unsigned sizeInBytes = pad(classFixedSize(t, class_));
@ -1917,16 +1804,43 @@ object
makeString(Thread* t, const char* format, ...);
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
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
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
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
isAssignableFrom(Thread* t, object a, object b);
@ -2159,6 +2073,9 @@ emptyMethod(Thread* t, object method)
and (codeBody(t, methodCode(t, method), 0) == return_);
}
object
parseUtf8(Thread* t, const char* data, unsigned length);
object
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
findInHierarchy(Thread* t, object class_, object name, object spec,
object (*find)(Thread*, object, object, object),
object (*makeError)(Thread*, object));
Machine::Type errorType);
inline object
findMethod(Thread* t, object class_, object name, object spec)
{
return findInHierarchy
(t, class_, name, spec, findMethodInClass, makeNoSuchMethodError);
(t, class_, name, spec, findMethodInClass, Machine::NoSuchMethodErrorType);
}
inline object
@ -2690,10 +2607,12 @@ wait(Thread* t, object o, int64_t milliseconds)
bool interrupted = monitorWait(t, m, milliseconds);
if (interrupted) {
t->exception = makeInterruptedException(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::InterruptedExceptionType);
}
} else {
t->exception = makeIllegalMonitorStateException(t);
t->exception = t->m->classpath->makeThrowable
(t, Machine::IllegalMonitorStateExceptionType);
}
if (DebugMonitors) {
@ -2722,7 +2641,8 @@ notify(Thread* t, object o)
if (m and monitorOwner(t, m) == t) {
monitorNotify(t, m);
} 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) {
monitorNotifyAll(t, m);
} 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) {
threadDaemon(t, thread) = daemon;
t->daemon = daemon;
if (daemon) {
++ t->m->daemonCount;
@ -2947,7 +2869,7 @@ resolveClassInPool(Thread* t, object method, unsigned index)
inline object
resolve(Thread* t, object loader, object method, unsigned index,
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);
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
(t, class_, referenceName(t, reference), referenceSpec(t, reference),
find, makeError);
find, errorType);
if (UNLIKELY(t->exception)) return 0;
set(t, codePool(t, methodCode(t, method)),
@ -2976,7 +2898,7 @@ inline object
resolveField(Thread* t, object loader, object method, unsigned index)
{
return resolve(t, loader, method, index, findFieldInClass,
makeNoSuchFieldError);
Machine::NoSuchFieldErrorType);
}
inline object
@ -2990,7 +2912,7 @@ inline object
resolveMethod(Thread* t, object loader, object method, unsigned index)
{
return resolve(t, loader, method, index, findMethodInClass,
makeNoSuchMethodError);
Machine::NoSuchMethodErrorType);
}
inline object
@ -3004,6 +2926,8 @@ inline object
getJClass(Thread* t, object c)
{
if (classAddendum(t, c) == 0) {
PROTECT(t, c);
ACQUIRE(t, t->m->classLock);
object addendum = makeClassAddendum(t, 0, 0, 0, 0);
@ -3013,9 +2937,11 @@ getJClass(Thread* t, object c)
object jclass = classAddendumClass(t, classAddendum(t, c));
if (jclass == 0) {
PROTECT(t, c);
ACQUIRE(t, t->m->classLock);
jclass = makeJclass(t, c);
jclass = t->m->classpath->makeJclass(t, c);
set(t, classAddendum(t, c), ClassAddendumClass, jclass);
}
@ -3023,6 +2949,29 @@ getJClass(Thread* t, object c)
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
dumpHeap(Thread* t, FILE* out);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -400,6 +400,8 @@ class Array : public Scalar {
o->typeName = typeName;
o->name = name;
o->elementSize = elementSize;
o->noassert = false;
o->nogc = false;
return o;
}
};
@ -455,7 +457,7 @@ memberTypeName(Object* o)
}
}
const char*
const char*&
memberName(Object* o)
{
switch (o->type) {
@ -987,8 +989,11 @@ class MemberIterator {
offset_ += padding_;
// printf("size: %d; padding: %d; alignment: %d; offset: %d;\n",
// size_, padding_, alignment_, offset_);
// fprintf(stderr,
// "type: %s; member: %s; size: %d; padding: %d; alignment: %d;"
// " offset: %d;\n",
// typeName(type), memberName(member), size_, padding_, alignment_,
// offset_);
return member;
}
@ -1087,6 +1092,27 @@ parseArray(Object* t, Object* p, Object* 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*
parseMember(Object* t, Object* p, Object* declarations)
{
@ -1094,13 +1120,24 @@ parseMember(Object* t, Object* p, Object* declarations)
if (equal(spec, "array")) {
return parseArray(t, cdr(p), declarations);
} 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;
return member;
return isNew ? member : 0;
} 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;
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 {
return Scalar::make(t, declaration(spec, declarations), spec,
string(car(cdr(p))),
@ -1120,7 +1157,9 @@ parseSubdeclaration(Object* t, Object* p, Object* declarations)
assert(typeSuper(t)->type == Object::Type);
} else {
Object* member = parseMember(t, p, declarations);
addMember(t, member);
if (member) {
addMember(t, member);
}
}
}
@ -1311,14 +1350,6 @@ parseJavaClass(Object* type, Stream* s, Object* declarations)
Object* member = Scalar::make
(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);
}
}
@ -1379,8 +1410,10 @@ parseType(Object::ObjectType type, Object* p, Object* declarations,
parseSubdeclaration(t, car(p), declarations);
} else {
Object* member = parseMember(t, car(p), declarations);
assert(member->type == Object::Scalar);
addMember(t, member);
if (member) {
assert(member->type == Object::Scalar);
addMember(t, member);
}
}
}

View File

@ -3,7 +3,18 @@
(type class avian/VMClass
(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
(array uintptr_t body))
@ -22,6 +33,10 @@
(type classAddendum avian/ClassAddendum)
(type methodAddendum avian/MethodAddendum)
(type fieldAddendum avian/FieldAddendum)
(type nativeMethodData
(void* function)
(uint16_t argumentTableSize)
@ -30,6 +45,10 @@
(type pointer
(void* value))
(type native
(void* function)
(uint8_t fast))
(pod exceptionHandler
(uint16_t start)
(uint16_t end)
@ -142,15 +161,23 @@
(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 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)
@ -184,6 +211,8 @@
(type virtualMachineError java/lang/VirtualMachineError)
(type outOfMemoryError java/lang/OutOfMemoryError)
(type stackOverflowError java/lang/StackOverflowError)
(type linkageError java/lang/LinkageError)
@ -221,9 +250,17 @@
(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)

View File

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