mirror of
https://github.com/corda/corda.git
synced 2025-01-22 12:28:11 +00:00
Merge branch 'master' of oss.readytalk.com:/var/local/git/avian
This commit is contained in:
commit
bf75e73aa9
@ -22,6 +22,8 @@ import java.lang.annotation.Annotation;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
import java.security.Permissions;
|
import java.security.Permissions;
|
||||||
import java.security.AllPermission;
|
import java.security.AllPermission;
|
||||||
@ -134,11 +136,15 @@ public final class Class <T> implements Type, GenericDeclaration {
|
|||||||
private native void initialize();
|
private native void initialize();
|
||||||
|
|
||||||
public static Class forCanonicalName(String name) {
|
public static Class forCanonicalName(String name) {
|
||||||
|
return forCanonicalName(null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class forCanonicalName(ClassLoader loader, String name) {
|
||||||
try {
|
try {
|
||||||
if (name.startsWith("[")) {
|
if (name.startsWith("[")) {
|
||||||
return forName(name);
|
return forName(name, true, loader);
|
||||||
} else if (name.startsWith("L")) {
|
} else if (name.startsWith("L")) {
|
||||||
return forName(name.substring(1, name.length() - 1));
|
return forName(name.substring(1, name.length() - 1), true, loader);
|
||||||
} else {
|
} else {
|
||||||
if (name.length() == 1) {
|
if (name.length() == 1) {
|
||||||
return primitiveClass(name.charAt(0));
|
return primitiveClass(name.charAt(0));
|
||||||
@ -444,7 +450,7 @@ public final class Class <T> implements Type, GenericDeclaration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isArray() {
|
public boolean isArray() {
|
||||||
return arrayElementSize != 0;
|
return this != Class.class && arrayElementSize != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInstance(Object o) {
|
public boolean isInstance(Object o) {
|
||||||
@ -484,7 +490,7 @@ public final class Class <T> implements Type, GenericDeclaration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Object[] getSigners() {
|
public Object[] getSigners() {
|
||||||
throw new UnsupportedOperationException();
|
return Static.signers.get(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Annotation[] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
@ -531,6 +537,12 @@ public final class Class <T> implements Type, GenericDeclaration {
|
|||||||
|
|
||||||
// for GNU Classpath compatibility:
|
// for GNU Classpath compatibility:
|
||||||
void setSigners(Object[] signers) {
|
void setSigners(Object[] signers) {
|
||||||
throw new UnsupportedOperationException();
|
if (signers != null && signers.length > 0) {
|
||||||
|
Static.signers.put(this, signers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Static {
|
||||||
|
public static final Map<Class,Object[]> signers = new HashMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,8 @@ public abstract class ClassLoader {
|
|||||||
return ClassLoader.class.getClassLoader();
|
return ClassLoader.class.getClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native Class defineClass(byte[] b, int offset, int length);
|
private static native Class defineClass
|
||||||
|
(ClassLoader loader, byte[] b, int offset, int length);
|
||||||
|
|
||||||
protected Class defineClass(String name, byte[] b, int offset, int length) {
|
protected Class defineClass(String name, byte[] b, int offset, int length) {
|
||||||
if (b == null) {
|
if (b == null) {
|
||||||
@ -44,7 +45,7 @@ public abstract class ClassLoader {
|
|||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return defineClass(b, offset, length);
|
return defineClass(this, b, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Class findClass(String name) throws ClassNotFoundException {
|
protected Class findClass(String name) throws ClassNotFoundException {
|
||||||
|
@ -357,9 +357,13 @@ public final class String
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int lastIndexOf(String s) {
|
public int lastIndexOf(String s) {
|
||||||
if (s.length == 0) return length;
|
return lastIndexOf(s, length - s.length);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = length - s.length; i >= 0; --i) {
|
public int lastIndexOf(String s, int lastIndex) {
|
||||||
|
if (s.length == 0) return lastIndex;
|
||||||
|
|
||||||
|
for (int i = Math.min(length - s.length, lastIndex); i >= 0; --i) {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (; j < s.length && i + j < length; ++j) {
|
for (; j < s.length && i + j < length; ++j) {
|
||||||
if (charAt(i + j) != s.charAt(j)) {
|
if (charAt(i + j) != s.charAt(j)) {
|
||||||
@ -521,44 +525,12 @@ public final class String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] split(String s) {
|
public String[] split(String regex) {
|
||||||
String[] array = new String[(length / s.length) + 1];
|
return split(regex, 0);
|
||||||
int index = 0;
|
|
||||||
int last = 0;
|
|
||||||
int position = 0;
|
|
||||||
for (int i = 0; i < length - s.length + 1;) {
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < s.length; ++j) {
|
|
||||||
if (charAt(i + j) != s.charAt(j)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j == s.length) {
|
public String[] split(String regex, int limit) {
|
||||||
if (i > 0) {
|
return Pattern.compile(regex).split(this, limit);
|
||||||
if (i > position) {
|
|
||||||
last = index;
|
|
||||||
}
|
|
||||||
array[index++] = substring(position, i);
|
|
||||||
}
|
|
||||||
i = position = i + s.length;
|
|
||||||
} else {
|
|
||||||
++ i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position < length) {
|
|
||||||
last = index;
|
|
||||||
array[index] = substring(position, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last + 1 < array.length) {
|
|
||||||
String[] a = new String[last + 1];
|
|
||||||
System.arraycopy(array, 0, a, 0, last + 1);
|
|
||||||
array = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence subSequence(int start, int end) {
|
public CharSequence subSequence(int start, int end) {
|
||||||
|
@ -38,7 +38,7 @@ public class Thread implements Runnable {
|
|||||||
|
|
||||||
public Thread(ThreadGroup group, Runnable task, String name, long stackSize)
|
public Thread(ThreadGroup group, Runnable task, String name, long stackSize)
|
||||||
{
|
{
|
||||||
this.group = group;
|
this.group = (group == null ? Thread.currentThread().group : group);
|
||||||
this.task = task;
|
this.task = task;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
@ -86,8 +86,11 @@ public class Thread implements Runnable {
|
|||||||
throw new IllegalStateException("thread already started");
|
throw new IllegalStateException("thread already started");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = (byte) State.RUNNABLE.ordinal();
|
||||||
|
|
||||||
peer = doStart();
|
peer = doStart();
|
||||||
if (peer == 0) {
|
if (peer == 0) {
|
||||||
|
state = (byte) State.NEW.ordinal();
|
||||||
throw new RuntimeException("unable to start native thread");
|
throw new RuntimeException("unable to start native thread");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,7 +98,6 @@ public class Thread implements Runnable {
|
|||||||
private native long doStart();
|
private native long doStart();
|
||||||
|
|
||||||
private static void run(Thread t) throws Throwable {
|
private static void run(Thread t) throws Throwable {
|
||||||
t.state = (byte) State.RUNNABLE.ordinal();
|
|
||||||
try {
|
try {
|
||||||
t.run();
|
t.run();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -53,7 +53,8 @@ public class Field<T> extends AccessibleObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class getType() {
|
public Class getType() {
|
||||||
return Class.forCanonicalName(new String(spec, 0, spec.length - 1, false));
|
return Class.forCanonicalName(class_.getClassLoader(),
|
||||||
|
new String(spec, 0, spec.length - 1, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(Object instance) throws IllegalAccessException {
|
public Object get(Object instance) throws IllegalAccessException {
|
||||||
|
@ -73,23 +73,26 @@ public class Method<T> extends AccessibleObject
|
|||||||
} else if (c == 'L') {
|
} else if (c == 'L') {
|
||||||
int start = i + 1;
|
int start = i + 1;
|
||||||
i = next(';', spec, start);
|
i = next(';', spec, start);
|
||||||
String name = spec.substring(start, i);
|
String name = spec.substring(start, i).replace('/', '.');
|
||||||
types[index++] = Class.forName(name);
|
types[index++] = Class.forName(name, true, class_.getClassLoader());
|
||||||
} else if (c == '[') {
|
} else if (c == '[') {
|
||||||
int start = i;
|
int start = i;
|
||||||
while (spec.charAt(i) == '[') ++i;
|
while (spec.charAt(i) == '[') ++i;
|
||||||
|
|
||||||
if (spec.charAt(i) == 'L') {
|
if (spec.charAt(i) == 'L') {
|
||||||
i = next(';', spec, i + 1);
|
i = next(';', spec, i + 1);
|
||||||
String name = spec.substring(start, i);
|
String name = spec.substring(start, i).replace('/', '.');
|
||||||
types[index++] = Class.forName(name);
|
types[index++] = Class.forName
|
||||||
|
(name, true, class_.getClassLoader());
|
||||||
} else {
|
} else {
|
||||||
String name = spec.substring(start, i + 1);
|
String name = spec.substring(start, i + 1);
|
||||||
types[index++] = Class.forCanonicalName(name);
|
types[index++] = Class.forCanonicalName
|
||||||
|
(class_.getClassLoader(), name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String name = spec.substring(i, i + 1);
|
String name = spec.substring(i, i + 1);
|
||||||
types[index++] = Class.forCanonicalName(name);
|
types[index++] = Class.forCanonicalName
|
||||||
|
(class_.getClassLoader(), name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
@ -103,6 +106,17 @@ public class Method<T> extends AccessibleObject
|
|||||||
throws InvocationTargetException, IllegalAccessException
|
throws InvocationTargetException, IllegalAccessException
|
||||||
{
|
{
|
||||||
if ((flags & Modifier.STATIC) != 0 || class_.isInstance(instance)) {
|
if ((flags & Modifier.STATIC) != 0 || class_.isInstance(instance)) {
|
||||||
|
if ((flags & Modifier.STATIC) != 0) {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments == null) {
|
||||||
|
if (parameterCount > 0) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
arguments = new Object[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (arguments.length == parameterCount) {
|
if (arguments.length == parameterCount) {
|
||||||
return invoke(this, instance, arguments);
|
return invoke(this, instance, arguments);
|
||||||
} else {
|
} else {
|
||||||
@ -121,7 +135,8 @@ public class Method<T> extends AccessibleObject
|
|||||||
for (int i = 0; i < spec.length - 1; ++i) {
|
for (int i = 0; i < spec.length - 1; ++i) {
|
||||||
if (spec[i] == ')') {
|
if (spec[i] == ')') {
|
||||||
return Class.forCanonicalName
|
return Class.forCanonicalName
|
||||||
(new String(spec, i + 1, spec.length - i - 2, false));
|
(class_.getClassLoader(),
|
||||||
|
new String(spec, i + 1, spec.length - i - 2, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
|
7
makefile
7
makefile
@ -375,14 +375,19 @@ gnu-overrides = \
|
|||||||
avian/*.class \
|
avian/*.class \
|
||||||
avian/resource/*.class \
|
avian/resource/*.class \
|
||||||
java/lang/Class.class \
|
java/lang/Class.class \
|
||||||
|
java/lang/Class\$$*.class \
|
||||||
java/lang/Enum.class \
|
java/lang/Enum.class \
|
||||||
java/lang/InheritableThreadLocal.class \
|
java/lang/InheritableThreadLocal.class \
|
||||||
java/lang/Object.class \
|
java/lang/Object.class \
|
||||||
java/lang/StackTraceElement.class \
|
java/lang/StackTraceElement.class \
|
||||||
java/lang/String*.class \
|
java/lang/String.class \
|
||||||
|
java/lang/String\$$*.class \
|
||||||
java/lang/StringBuffer.class \
|
java/lang/StringBuffer.class \
|
||||||
java/lang/StringBuilder.class \
|
java/lang/StringBuilder.class \
|
||||||
|
java/lang/StringBuilder\$$*.class \
|
||||||
java/lang/Thread.class \
|
java/lang/Thread.class \
|
||||||
|
java/lang/Thread\$$*.class \
|
||||||
|
java/lang/ThreadGroup.class \
|
||||||
java/lang/ThreadLocal.class \
|
java/lang/ThreadLocal.class \
|
||||||
java/lang/Throwable.class \
|
java/lang/Throwable.class \
|
||||||
java/lang/ref/PhantomReference.class \
|
java/lang/ref/PhantomReference.class \
|
||||||
|
@ -11,17 +11,12 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "processor.h"
|
#include "processor.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
inline void
|
|
||||||
replace(char a, char b, char* c)
|
|
||||||
{
|
|
||||||
for (; *c; ++c) if (*c == a) *c = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
search(Thread* t, object name, object (*op)(Thread*, object),
|
search(Thread* t, object name, object (*op)(Thread*, object),
|
||||||
bool replaceDots)
|
bool replaceDots)
|
||||||
@ -177,15 +172,30 @@ extern "C" JNIEXPORT int64_t JNICALL
|
|||||||
Avian_java_lang_ClassLoader_defineClass
|
Avian_java_lang_ClassLoader_defineClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object b = reinterpret_cast<object>(arguments[0]);
|
object loader = reinterpret_cast<object>(arguments[0]);
|
||||||
int offset = arguments[1];
|
PROTECT(t, loader);
|
||||||
int length = arguments[2];
|
|
||||||
|
object b = reinterpret_cast<object>(arguments[1]);
|
||||||
|
int offset = arguments[2];
|
||||||
|
int length = arguments[3];
|
||||||
|
|
||||||
uint8_t* buffer = static_cast<uint8_t*>
|
uint8_t* buffer = static_cast<uint8_t*>
|
||||||
(t->m->heap->allocate(length));
|
(t->m->heap->allocate(length));
|
||||||
memcpy(buffer, &byteArrayBody(t, b, offset), length);
|
memcpy(buffer, &byteArrayBody(t, b, offset), length);
|
||||||
object c = parseClass(t, buffer, length);
|
object c = parseClass(t, loader, buffer, length);
|
||||||
t->m->heap->free(buffer, length);
|
t->m->heap->free(buffer, length);
|
||||||
|
|
||||||
|
if (c) {
|
||||||
|
if (classLoaderMap(t, loader) == 0) {
|
||||||
|
PROTECT(t, c);
|
||||||
|
object map = makeHashMap(t, 0, 0);
|
||||||
|
set(t, loader, ClassLoaderMap, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashMapInsert(t, classLoaderMap(t, loader), className(t, c), c,
|
||||||
|
byteArrayHash);
|
||||||
|
}
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>(c);
|
return reinterpret_cast<int64_t>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +205,7 @@ Avian_avian_SystemClassLoader_findLoadedClass
|
|||||||
{
|
{
|
||||||
object name = reinterpret_cast<object>(arguments[1]);
|
object name = reinterpret_cast<object>(arguments[1]);
|
||||||
|
|
||||||
return search(t, name, findLoadedClass, true);
|
return search(t, name, findLoadedSystemClass, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
@ -204,7 +214,7 @@ Avian_avian_SystemClassLoader_findClass
|
|||||||
{
|
{
|
||||||
object name = reinterpret_cast<object>(arguments[1]);
|
object name = reinterpret_cast<object>(arguments[1]);
|
||||||
|
|
||||||
return search(t, name, resolveClass, true);
|
return search(t, name, resolveSystemClass, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
@ -465,7 +475,8 @@ Avian_java_lang_reflect_Array_makeObjectArray
|
|||||||
object elementType = reinterpret_cast<object>(arguments[0]);
|
object elementType = reinterpret_cast<object>(arguments[0]);
|
||||||
int length = arguments[1];
|
int length = arguments[1];
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>(makeObjectArray(t, elementType, length));
|
return reinterpret_cast<int64_t>
|
||||||
|
(makeObjectArray(t, classLoader(t, elementType), elementType, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
@ -767,8 +778,10 @@ Avian_java_lang_Throwable_resolveTrace
|
|||||||
PROTECT(t, trace);
|
PROTECT(t, trace);
|
||||||
|
|
||||||
unsigned length = arrayLength(t, trace);
|
unsigned length = arrayLength(t, trace);
|
||||||
|
object elementType = arrayBody
|
||||||
|
(t, t->m->types, Machine::StackTraceElementType);
|
||||||
object array = makeObjectArray
|
object array = makeObjectArray
|
||||||
(t, arrayBody(t, t->m->types, Machine::StackTraceElementType), length);
|
(t, classLoader(t, elementType), elementType, length);
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
object e = 0;
|
object e = 0;
|
||||||
|
12
src/common.h
12
src/common.h
@ -44,14 +44,12 @@
|
|||||||
# define ULD "u"
|
# define ULD "u"
|
||||||
# endif
|
# endif
|
||||||
#elif defined __x86_64__
|
#elif defined __x86_64__
|
||||||
|
# define LD "ld"
|
||||||
|
# define LX "lx"
|
||||||
# ifdef __MINGW32__
|
# ifdef __MINGW32__
|
||||||
# define LD "I64d"
|
|
||||||
# define LX "I64x"
|
|
||||||
# define LLD "I64d"
|
# define LLD "I64d"
|
||||||
# define ULD "I64x"
|
# define ULD "I64x"
|
||||||
# else
|
# else
|
||||||
# define LD "ld"
|
|
||||||
# define LX "lx"
|
|
||||||
# define LLD "ld"
|
# define LLD "ld"
|
||||||
# define ULD "lu"
|
# define ULD "lu"
|
||||||
# endif
|
# endif
|
||||||
@ -313,6 +311,12 @@ voidPointer(T function)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
replace(char a, char b, char* c)
|
||||||
|
{
|
||||||
|
for (; *c; ++c) if (*c == a) *c = b;
|
||||||
|
}
|
||||||
|
|
||||||
class Machine;
|
class Machine;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ resolveTarget(MyThread* t, void* stack, object method)
|
|||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
resolveClass(t, className(t, class_));
|
resolveSystemClass(t, className(t, class_));
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ resolveTarget(MyThread* t, object class_, unsigned index)
|
|||||||
if (classVmFlags(t, class_) & BootstrapFlag) {
|
if (classVmFlags(t, class_) & BootstrapFlag) {
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
resolveClass(t, className(t, class_));
|
resolveSystemClass(t, className(t, class_));
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2030,10 +2030,11 @@ longToFloat(int64_t a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
|
makeBlankObjectArray(MyThread* t, object loader, object class_, int32_t length)
|
||||||
{
|
{
|
||||||
if (length >= 0) {
|
if (length >= 0) {
|
||||||
return reinterpret_cast<uint64_t>(makeObjectArray(t, class_, length));
|
return reinterpret_cast<uint64_t>
|
||||||
|
(makeObjectArray(t, loader, class_, length));
|
||||||
} else {
|
} else {
|
||||||
object message = makeString(t, "%d", length);
|
object message = makeString(t, "%d", length);
|
||||||
t->exception = makeNegativeArraySizeException(t, message);
|
t->exception = makeNegativeArraySizeException(t, message);
|
||||||
@ -2226,6 +2227,9 @@ throw_(MyThread* t, object o)
|
|||||||
} else {
|
} else {
|
||||||
t->exception = makeNullPointerException(t);
|
t->exception = makeNullPointerException(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printTrace(t, t->exception);
|
||||||
|
|
||||||
unwind(t);
|
unwind(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2746,7 +2750,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case anewarray: {
|
case anewarray: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
object class_ = resolveClassInPool(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
Compiler::Operand* length = frame->popInt();
|
Compiler::Operand* length = frame->popInt();
|
||||||
@ -2757,7 +2761,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
0,
|
0,
|
||||||
frame->trace(0, 0),
|
frame->trace(0, 0),
|
||||||
BytesPerWord,
|
BytesPerWord,
|
||||||
3, c->register_(t->arch->thread()), frame->append(class_), length));
|
4, c->register_(t->arch->thread()),
|
||||||
|
frame->append(classLoader(t, methodClass(t, context->method))),
|
||||||
|
frame->append(class_), length));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case areturn: {
|
case areturn: {
|
||||||
@ -2810,7 +2816,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case checkcast: {
|
case checkcast: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
object class_ = resolveClassInPool(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
Compiler::Operand* instance = c->peek(1, 0);
|
Compiler::Operand* instance = c->peek(1, 0);
|
||||||
@ -3085,7 +3091,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case getstatic: {
|
case getstatic: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
Compiler::Operand* table;
|
Compiler::Operand* table;
|
||||||
@ -3452,7 +3458,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case instanceof: {
|
case instanceof: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
object class_ = resolveClassInPool(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
frame->pushInt
|
frame->pushInt
|
||||||
@ -3467,7 +3473,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
ip += 2;
|
ip += 2;
|
||||||
|
|
||||||
object target = resolveMethod(t, codePool(t, code), index - 1);
|
object target = resolveMethod(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
||||||
@ -3502,7 +3508,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case invokespecial: {
|
case invokespecial: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object target = resolveMethod(t, codePool(t, code), index - 1);
|
object target = resolveMethod(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
object class_ = methodClass(t, context->method);
|
object class_ = methodClass(t, context->method);
|
||||||
@ -3520,7 +3526,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case invokestatic: {
|
case invokestatic: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object target = resolveMethod(t, codePool(t, code), index - 1);
|
object target = resolveMethod(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
assert(t, methodFlags(t, target) & ACC_STATIC);
|
assert(t, methodFlags(t, target) & ACC_STATIC);
|
||||||
@ -3533,7 +3539,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case invokevirtual: {
|
case invokevirtual: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object target = resolveMethod(t, codePool(t, code), index - 1);
|
object target = resolveMethod(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
||||||
@ -3729,7 +3735,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
if (objectClass(t, v)
|
if (objectClass(t, v)
|
||||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
object class_ = resolveClassInPool(t, pool, index - 1);
|
object class_ = resolveClassInPool(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
frame->pushObject(frame->append(class_));
|
frame->pushObject(frame->append(class_));
|
||||||
@ -3807,6 +3813,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
int32_t pairCount = codeReadInt32(t, code, ip);
|
int32_t pairCount = codeReadInt32(t, code, ip);
|
||||||
|
|
||||||
|
if (pairCount) {
|
||||||
Compiler::Operand* start = 0;
|
Compiler::Operand* start = 0;
|
||||||
uint32_t ipTable[pairCount];
|
uint32_t ipTable[pairCount];
|
||||||
for (int32_t i = 0; i < pairCount; ++i) {
|
for (int32_t i = 0; i < pairCount; ++i) {
|
||||||
@ -3839,6 +3846,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
c->restoreState(state);
|
c->restoreState(state);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// a switch statement with no cases, apparently
|
||||||
|
c->jmp(default_);
|
||||||
|
}
|
||||||
|
|
||||||
ip = defaultIp;
|
ip = defaultIp;
|
||||||
} break;
|
} break;
|
||||||
@ -3934,7 +3945,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
uint8_t dimensions = codeBody(t, code, ip++);
|
uint8_t dimensions = codeBody(t, code, ip++);
|
||||||
|
|
||||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
object class_ = resolveClassInPool(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
@ -3958,7 +3969,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case new_: {
|
case new_: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
object class_ = resolveClassInPool(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
if (classVmFlags(t, class_) & (WeakReferenceFlag | HasFinalizerFlag)) {
|
if (classVmFlags(t, class_) & (WeakReferenceFlag | HasFinalizerFlag)) {
|
||||||
@ -4008,7 +4019,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case putstatic: {
|
case putstatic: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, context->method, index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
object staticTable = 0;
|
object staticTable = 0;
|
||||||
@ -4310,12 +4321,13 @@ logCompile(MyThread* t, const void* code, unsigned size, const char* class_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
translateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
|
translateExceptionHandlerTable(MyThread* t, Compiler* c, object method,
|
||||||
intptr_t start)
|
intptr_t start)
|
||||||
{
|
{
|
||||||
object oldTable = codeExceptionHandlerTable(t, code);
|
object oldTable = codeExceptionHandlerTable(t, methodCode(t, method));
|
||||||
|
|
||||||
if (oldTable) {
|
if (oldTable) {
|
||||||
PROTECT(t, code);
|
PROTECT(t, method);
|
||||||
PROTECT(t, oldTable);
|
PROTECT(t, oldTable);
|
||||||
|
|
||||||
unsigned length = exceptionHandlerTableLength(t, oldTable);
|
unsigned length = exceptionHandlerTableLength(t, oldTable);
|
||||||
@ -4344,7 +4356,7 @@ translateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
|
|||||||
object type;
|
object type;
|
||||||
if (exceptionHandlerCatchType(oldHandler)) {
|
if (exceptionHandlerCatchType(oldHandler)) {
|
||||||
type = resolveClassInPool
|
type = resolveClassInPool
|
||||||
(t, codePool(t, code), exceptionHandlerCatchType(oldHandler) - 1);
|
(t, method, exceptionHandlerCatchType(oldHandler) - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
} else {
|
} else {
|
||||||
type = 0;
|
type = 0;
|
||||||
@ -4353,7 +4365,7 @@ translateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
|
|||||||
set(t, newTable, ArrayBody + ((i + 1) * BytesPerWord), type);
|
set(t, newTable, ArrayBody + ((i + 1) * BytesPerWord), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(t, code, CodeExceptionHandlerTable, newTable);
|
set(t, methodCode(t, method), CodeExceptionHandlerTable, newTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4942,8 +4954,8 @@ finish(MyThread* t, Allocator* allocator, Context* context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
translateExceptionHandlerTable(t, c, methodCode(t, context->method),
|
translateExceptionHandlerTable
|
||||||
reinterpret_cast<intptr_t>(start));
|
(t, c, context->method, reinterpret_cast<intptr_t>(start));
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
translateLineNumberTable(t, c, methodCode(t, context->method),
|
translateLineNumberTable(t, c, methodCode(t, context->method),
|
||||||
@ -5825,6 +5837,8 @@ returnSpec(MyThread* t, object method)
|
|||||||
object
|
object
|
||||||
returnClass(MyThread* t, object method)
|
returnClass(MyThread* t, object method)
|
||||||
{
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
int8_t* spec = returnSpec(t, method);
|
int8_t* spec = returnSpec(t, method);
|
||||||
unsigned length = strlen(reinterpret_cast<char*>(spec));
|
unsigned length = strlen(reinterpret_cast<char*>(spec));
|
||||||
object name;
|
object name;
|
||||||
@ -5837,7 +5851,8 @@ returnClass(MyThread* t, object method)
|
|||||||
name = makeByteArray(t, length - 1);
|
name = makeByteArray(t, length - 1);
|
||||||
memcpy(&byteArrayBody(t, name, 0), spec + 1, length - 2);
|
memcpy(&byteArrayBody(t, name, 0), spec + 1, length - 2);
|
||||||
}
|
}
|
||||||
return resolveClass(t, name);
|
|
||||||
|
return resolveClass(t, classLoader(t, methodClass(t, method)), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -5959,7 +5974,7 @@ callContinuation(MyThread* t, object continuation, object result,
|
|||||||
PROTECT(t, nextContinuation);
|
PROTECT(t, nextContinuation);
|
||||||
|
|
||||||
object method = resolveMethod
|
object method = resolveMethod
|
||||||
(t, "avian/Continuations", "rewind",
|
(t, t->m->loader, "avian/Continuations", "rewind",
|
||||||
"(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;"
|
"(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;"
|
||||||
"Ljava/lang/Throwable;)V");
|
"Ljava/lang/Throwable;)V");
|
||||||
|
|
||||||
@ -6030,7 +6045,7 @@ callWithCurrentContinuation(MyThread* t, object receiver)
|
|||||||
|
|
||||||
if (receiveMethod(t) == 0) {
|
if (receiveMethod(t) == 0) {
|
||||||
object m = resolveMethod
|
object m = resolveMethod
|
||||||
(t, "avian/CallbackReceiver", "receive",
|
(t, t->m->loader, "avian/CallbackReceiver", "receive",
|
||||||
"(Lavian/Callback;)Ljava/lang/Object;");
|
"(Lavian/Callback;)Ljava/lang/Object;");
|
||||||
|
|
||||||
if (m) {
|
if (m) {
|
||||||
@ -6040,7 +6055,7 @@ callWithCurrentContinuation(MyThread* t, object receiver)
|
|||||||
(t, t->m->types, Machine::ContinuationType);
|
(t, t->m->types, Machine::ContinuationType);
|
||||||
|
|
||||||
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
|
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
|
||||||
resolveClass(t, vm::className(t, continuationClass));
|
resolveSystemClass(t, vm::className(t, continuationClass));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6078,7 +6093,7 @@ dynamicWind(MyThread* t, object before, object thunk, object after)
|
|||||||
|
|
||||||
if (windMethod(t) == 0) {
|
if (windMethod(t) == 0) {
|
||||||
object method = resolveMethod
|
object method = resolveMethod
|
||||||
(t, "avian/Continuations", "wind",
|
(t, t->m->loader, "avian/Continuations", "wind",
|
||||||
"(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;"
|
"(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;"
|
||||||
"Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;");
|
"Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;");
|
||||||
|
|
||||||
@ -6570,6 +6585,16 @@ class MyProcessor: public Processor {
|
|||||||
|
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
if (false) {
|
||||||
|
compile(static_cast<MyThread*>(t),
|
||||||
|
::codeAllocator(static_cast<MyThread*>(t)), 0,
|
||||||
|
resolveMethod(t, t->m->loader,
|
||||||
|
"java/beans/PropertyChangeSupport",
|
||||||
|
"firePropertyChange",
|
||||||
|
"(Ljava/beans/PropertyChangeEvent;)V"));
|
||||||
|
trap();
|
||||||
|
}
|
||||||
|
|
||||||
compile(static_cast<MyThread*>(t),
|
compile(static_cast<MyThread*>(t),
|
||||||
::codeAllocator(static_cast<MyThread*>(t)), 0, method);
|
::codeAllocator(static_cast<MyThread*>(t)), 0, method);
|
||||||
|
|
||||||
@ -6581,8 +6606,9 @@ class MyProcessor: public Processor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
invokeList(Thread* t, const char* className, const char* methodName,
|
invokeList(Thread* t, object loader, const char* className,
|
||||||
const char* methodSpec, object this_, va_list arguments)
|
const char* methodName, const char* methodSpec,
|
||||||
|
object this_, va_list arguments)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
@ -6595,7 +6621,8 @@ class MyProcessor: public Processor {
|
|||||||
ArgumentList list
|
ArgumentList list
|
||||||
(t, array, size, objectMask, this_, methodSpec, false, arguments);
|
(t, array, size, objectMask, this_, methodSpec, false, arguments);
|
||||||
|
|
||||||
object method = resolveMethod(t, className, methodName, methodSpec);
|
object method = resolveMethod
|
||||||
|
(t, loader, className, methodName, methodSpec);
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
@ -7064,7 +7091,7 @@ fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
|
|||||||
void
|
void
|
||||||
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
|
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
|
||||||
{
|
{
|
||||||
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
|
for (HashMapIterator it(t, classLoaderMap(t, t->m->loader)); it.hasMore();) {
|
||||||
object c = tripleSecond(t, it.next());
|
object c = tripleSecond(t, it.next());
|
||||||
|
|
||||||
if (classMethodTable(t, c)) {
|
if (classMethodTable(t, c)) {
|
||||||
@ -7194,7 +7221,9 @@ boot(MyThread* t, BootImage* image)
|
|||||||
|
|
||||||
syncInstructionCache(code, image->codeSize);
|
syncInstructionCache(code, image->codeSize);
|
||||||
|
|
||||||
t->m->classMap = makeClassMap(t, classTable, image->classCount, heap);
|
object classMap = makeClassMap(t, classTable, image->classCount, heap);
|
||||||
|
set(t, t->m->loader, ClassLoaderMap, classMap);
|
||||||
|
|
||||||
t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap);
|
t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap);
|
||||||
|
|
||||||
p->callTableSize = image->callCount;
|
p->callTableSize = image->callCount;
|
||||||
|
@ -256,7 +256,7 @@ class Read {
|
|||||||
value(0), event(0), eventNext(0)
|
value(0), event(0), eventNext(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual bool intersect(SiteMask* mask) = 0;
|
virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0;
|
||||||
|
|
||||||
virtual Value* successor() = 0;
|
virtual Value* successor() = 0;
|
||||||
|
|
||||||
@ -1939,7 +1939,7 @@ class SingleRead: public Read {
|
|||||||
next_(0), mask(mask), successor_(successor)
|
next_(0), mask(mask), successor_(successor)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual bool intersect(SiteMask* mask) {
|
virtual bool intersect(SiteMask* mask, unsigned) {
|
||||||
*mask = ::intersect(*mask, this->mask);
|
*mask = ::intersect(*mask, this->mask);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2002,13 +2002,19 @@ class MultiRead: public Read {
|
|||||||
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual bool intersect(SiteMask* mask) {
|
virtual bool intersect(SiteMask* mask, unsigned depth) {
|
||||||
|
if (depth > 0) {
|
||||||
|
// short-circuit recursion to avoid poor performance in
|
||||||
|
// deeply-nested branches
|
||||||
|
return reads != 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (not visited) {
|
if (not visited) {
|
||||||
visited = true;
|
visited = true;
|
||||||
for (Cell** cell = &reads; *cell;) {
|
for (Cell** cell = &reads; *cell;) {
|
||||||
Read* r = static_cast<Read*>((*cell)->value);
|
Read* r = static_cast<Read*>((*cell)->value);
|
||||||
bool valid = r->intersect(mask);
|
bool valid = r->intersect(mask, depth + 1);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
result = true;
|
result = true;
|
||||||
cell = &((*cell)->next);
|
cell = &((*cell)->next);
|
||||||
@ -2101,11 +2107,11 @@ class StubRead: public Read {
|
|||||||
next_(0), read(0), visited(false), valid_(true)
|
next_(0), read(0), visited(false), valid_(true)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual bool intersect(SiteMask* mask) {
|
virtual bool intersect(SiteMask* mask, unsigned depth) {
|
||||||
if (not visited) {
|
if (not visited) {
|
||||||
visited = true;
|
visited = true;
|
||||||
if (read) {
|
if (read) {
|
||||||
bool valid = read->intersect(mask);
|
bool valid = read->intersect(mask, depth);
|
||||||
if (not valid) {
|
if (not valid) {
|
||||||
read = 0;
|
read = 0;
|
||||||
}
|
}
|
||||||
@ -4319,20 +4325,32 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen,
|
|||||||
FrameIterator::Element el = it.next(c);
|
FrameIterator::Element el = it.next(c);
|
||||||
Value* v = el.value;
|
Value* v = el.value;
|
||||||
Read* r = live(v);
|
Read* r = live(v);
|
||||||
|
Site* s = sites[el.localIndex];
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
if (sites[el.localIndex]) {
|
if (s) {
|
||||||
if (DebugControl) {
|
if (DebugControl) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
sites[el.localIndex]->toString(c, buffer, 256);
|
s->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "resolve original %s for %p local %d frame %d\n",
|
fprintf(stderr, "resolve original %s for %p local %d frame %d\n",
|
||||||
buffer, el.value, el.localIndex, frameIndex(c, &el));
|
buffer, v, el.localIndex, frameIndex(c, &el));
|
||||||
}
|
}
|
||||||
|
|
||||||
acquireSite(c, frozen, sites[el.localIndex], v, r, true);
|
acquireSite(c, frozen, s, v, r, true);
|
||||||
} else {
|
} else {
|
||||||
complete = false;
|
complete = false;
|
||||||
}
|
}
|
||||||
|
} else if (s) {
|
||||||
|
if (DebugControl) {
|
||||||
|
char buffer[256];
|
||||||
|
s->toString(c, buffer, 256);
|
||||||
|
fprintf(stderr, "freeze original %s for %p local %d frame %d\n",
|
||||||
|
buffer, v, el.localIndex, frameIndex(c, &el));
|
||||||
|
}
|
||||||
|
|
||||||
|
addSite(c, v, s);
|
||||||
|
removeSite(c, v, s);
|
||||||
|
freeze(c, frozen, s, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4513,7 +4531,14 @@ setSites(Context* c, Event* e, Site** sites)
|
|||||||
if (sites[el.localIndex]) {
|
if (sites[el.localIndex]) {
|
||||||
if (live(el.value)) {
|
if (live(el.value)) {
|
||||||
setSites(c, el.value, sites[el.localIndex]);
|
setSites(c, el.value, sites[el.localIndex]);
|
||||||
|
} else if (DebugControl) {
|
||||||
|
char buffer[256]; sitesToString(c, sites[el.localIndex], buffer, 256);
|
||||||
|
fprintf(stderr, "skip sites %s for %p local %d frame %d\n",
|
||||||
|
buffer, el.value, el.localIndex, frameIndex(c, &el));
|
||||||
}
|
}
|
||||||
|
} else if (DebugControl) {
|
||||||
|
fprintf(stderr, "no sites for %p local %d frame %d\n",
|
||||||
|
el.value, el.localIndex, frameIndex(c, &el));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
72
src/gnu.cpp
72
src/gnu.cpp
@ -11,6 +11,7 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "processor.h"
|
#include "processor.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
|
|||||||
initSpec = "(I)V";
|
initSpec = "(I)V";
|
||||||
}
|
}
|
||||||
|
|
||||||
object pointerClass = resolveClass(t, pointerClassName);
|
object pointerClass = resolveClass(t, t->m->loader, pointerClassName);
|
||||||
if (UNLIKELY(pointerClass == 0)) return 0;
|
if (UNLIKELY(pointerClass == 0)) return 0;
|
||||||
PROTECT(t, pointerClass);
|
PROTECT(t, pointerClass);
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
|
|||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
object bufferClass = resolveClass
|
object bufferClass = resolveClass
|
||||||
(t, "java/nio/DirectByteBufferImpl$ReadWrite");
|
(t, t->m->loader, "java/nio/DirectByteBufferImpl$ReadWrite");
|
||||||
if (UNLIKELY(bufferClass == 0)) return 0;
|
if (UNLIKELY(bufferClass == 0)) return 0;
|
||||||
PROTECT(t, bufferClass);
|
PROTECT(t, bufferClass);
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ Avian_gnu_classpath_VMSystemProperties_preInit
|
|||||||
PROTECT(t, properties);
|
PROTECT(t, properties);
|
||||||
|
|
||||||
object method = resolveMethod
|
object method = resolveMethod
|
||||||
(t, "java/util/Properties", "setProperty",
|
(t, t->m->loader, "java/util/Properties", "setProperty",
|
||||||
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
|
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
|
||||||
|
|
||||||
if (UNLIKELY(t->exception)) {
|
if (UNLIKELY(t->exception)) {
|
||||||
@ -133,6 +134,9 @@ Avian_gnu_classpath_VMSystemProperties_preInit
|
|||||||
|
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "java.version", "1.5");
|
||||||
|
setProperty(t, method, properties, "java.specification.version", "1.5");
|
||||||
|
|
||||||
setProperty(t, method, properties, "java.vm.name", "Avian");
|
setProperty(t, method, properties, "java.vm.name", "Avian");
|
||||||
|
|
||||||
setProperty(t, method, properties, "java.protocol.handler.pkgs", "avian");
|
setProperty(t, method, properties, "java.protocol.handler.pkgs", "avian");
|
||||||
@ -212,7 +216,7 @@ Avian_gnu_classpath_VMStackWalker_getClassContext
|
|||||||
if (skipCount == 0) {
|
if (skipCount == 0) {
|
||||||
if (trace == 0) {
|
if (trace == 0) {
|
||||||
trace = makeObjectArray
|
trace = makeObjectArray
|
||||||
(t, arrayBody(t, t->m->types, Machine::ClassType),
|
(t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType),
|
||||||
walker->count());
|
walker->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +244,7 @@ Avian_gnu_classpath_VMStackWalker_getClassContext
|
|||||||
|
|
||||||
if (v.trace == 0) {
|
if (v.trace == 0) {
|
||||||
v.trace = makeObjectArray
|
v.trace = makeObjectArray
|
||||||
(t, arrayBody(t, t->m->types, Machine::ClassType), 0);
|
(t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>(v.trace);
|
return reinterpret_cast<int64_t>(v.trace);
|
||||||
@ -341,7 +345,7 @@ Avian_java_lang_VMRuntime_nativeLoad
|
|||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Class_primitiveClass
|
Avian_java_lang_Class_primitiveClass
|
||||||
(Thread* t, object, uintptr_t*);
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_lang_VMClassLoader_getPrimitiveClass
|
Avian_java_lang_VMClassLoader_getPrimitiveClass
|
||||||
@ -350,6 +354,26 @@ Avian_java_lang_VMClassLoader_getPrimitiveClass
|
|||||||
return Avian_java_lang_Class_primitiveClass(t, 0, arguments);
|
return Avian_java_lang_Class_primitiveClass(t, 0, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_ClassLoader_defineClass
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_defineClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
uintptr_t args[]
|
||||||
|
= { arguments[0], arguments[2], arguments[3], arguments[4] };
|
||||||
|
|
||||||
|
// object name = reinterpret_cast<object>(arguments[1]);
|
||||||
|
// char n[stringLength(t, name) + 1];
|
||||||
|
// stringChars(t, name, n);
|
||||||
|
// fprintf(stderr, "define class %s in %p\n", n,
|
||||||
|
// reinterpret_cast<void*>(arguments[0]));
|
||||||
|
|
||||||
|
return Avian_java_lang_ClassLoader_defineClass(t, 0, args);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_lang_System_identityHashCode
|
Avian_java_lang_System_identityHashCode
|
||||||
(Thread*, object, uintptr_t*);
|
(Thread*, object, uintptr_t*);
|
||||||
@ -396,18 +420,44 @@ Avian_java_lang_VMClassLoader_loadClass
|
|||||||
{
|
{
|
||||||
uintptr_t args[] = { 0, arguments[0] };
|
uintptr_t args[] = { 0, arguments[0] };
|
||||||
|
|
||||||
|
// object name = reinterpret_cast<object>(arguments[0]);
|
||||||
|
// char n[stringLength(t, name) + 1];
|
||||||
|
// stringChars(t, name, n);
|
||||||
|
// fprintf(stderr, "load bootstrap class %s in %p\n", n, t->m->loader);
|
||||||
|
|
||||||
return Avian_avian_SystemClassLoader_findClass(t, 0, args);
|
return Avian_avian_SystemClassLoader_findClass(t, 0, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Avian_avian_SystemClassLoader_findLoadedClass
|
Avian_java_lang_VMClassLoader_resolveClass
|
||||||
(Thread*, object, uintptr_t*);
|
(Thread*, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_lang_VMClassLoader_findLoadedClass
|
Avian_java_lang_VMClassLoader_findLoadedClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
uintptr_t args[] = { 0, arguments[1] };
|
object loader = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
return Avian_avian_SystemClassLoader_findLoadedClass(t, 0, args);
|
object map = classLoaderMap(t, loader);
|
||||||
|
if (map) {
|
||||||
|
PROTECT(t, loader);
|
||||||
|
|
||||||
|
object name = reinterpret_cast<object>(arguments[1]);
|
||||||
|
PROTECT(t, name);
|
||||||
|
|
||||||
|
object n = makeByteArray(t, stringLength(t, name) + 1);
|
||||||
|
char* s = reinterpret_cast<char*>(&byteArrayBody(t, n, 0));
|
||||||
|
stringChars(t, name, s);
|
||||||
|
|
||||||
|
replace('.', '/', s);
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>
|
||||||
|
(hashMapFind
|
||||||
|
(t, classLoaderMap(t, loader), n, byteArrayHash, byteArrayEqual));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,7 @@ FindClass(Thread* t, const char* name)
|
|||||||
object n = makeByteArray(t, strlen(name) + 1);
|
object n = makeByteArray(t, strlen(name) + 1);
|
||||||
replace('.', '/', name, &byteArrayBody(t, n, 0));
|
replace('.', '/', name, &byteArrayBody(t, n, 0));
|
||||||
|
|
||||||
return makeLocalReference(t, resolveClass(t, n));
|
return makeLocalReference(t, resolveClass(t, t->m->loader, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
jint JNICALL
|
jint JNICALL
|
||||||
@ -1213,7 +1213,7 @@ NewObjectArray(Thread* t, jsize length, jclass class_, jobject init)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object a = makeObjectArray(t, *class_, length);
|
object a = makeObjectArray(t, classLoader(t, *class_), *class_, length);
|
||||||
object value = (init ? *init : 0);
|
object value = (init ? *init : 0);
|
||||||
for (jsize i = 0; i < length; ++i) {
|
for (jsize i = 0; i < length; ++i) {
|
||||||
set(t, a, ArrayBody + (i * BytesPerWord), value);
|
set(t, a, ArrayBody + (i * BytesPerWord), value);
|
||||||
|
321
src/machine.cpp
321
src/machine.cpp
@ -857,7 +857,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
object name = singletonObject(t, pool, s.read2() - 1);
|
object name = singletonObject(t, pool, s.read2() - 1);
|
||||||
PROTECT(t, name);
|
PROTECT(t, name);
|
||||||
|
|
||||||
object interface = resolveClass(t, name);
|
object interface = resolveClass(t, classLoader(t, class_), name);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
PROTECT(t, interface);
|
PROTECT(t, interface);
|
||||||
@ -878,7 +878,8 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (HashMapIterator it(t, map); it.hasMore();) {
|
for (HashMapIterator it(t, map); it.hasMore();) {
|
||||||
object interface = resolveClass(t, tripleFirst(t, it.next()));
|
object interface = resolveClass
|
||||||
|
(t, classLoader(t, class_), tripleFirst(t, it.next()));
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
set(t, interfaceTable, ArrayBody + (i * BytesPerWord), interface);
|
set(t, interfaceTable, ArrayBody + (i * BytesPerWord), interface);
|
||||||
@ -1164,6 +1165,68 @@ scanMethodSpec(Thread* t, const char* s, unsigned* parameterCount,
|
|||||||
*returnCode = fieldCode(t, *it.returnSpec());
|
*returnCode = fieldCode(t, *it.returnSpec());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
addInterfaceMethods(Thread* t, object class_, object virtualMap,
|
||||||
|
unsigned* virtualCount, bool makeList)
|
||||||
|
{
|
||||||
|
object itable = classInterfaceTable(t, class_);
|
||||||
|
if (itable) {
|
||||||
|
PROTECT(t, class_);
|
||||||
|
PROTECT(t, virtualMap);
|
||||||
|
PROTECT(t, itable);
|
||||||
|
|
||||||
|
object list = 0;
|
||||||
|
PROTECT(t, list);
|
||||||
|
|
||||||
|
object method = 0;
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
object vtable = 0;
|
||||||
|
PROTECT(t, vtable);
|
||||||
|
|
||||||
|
unsigned stride = (classFlags(t, class_) & ACC_INTERFACE) ? 1 : 2;
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, itable); i += stride) {
|
||||||
|
vtable = classVirtualTable(t, arrayBody(t, itable, i));
|
||||||
|
if (vtable) {
|
||||||
|
for (unsigned j = 0; j < arrayLength(t, vtable); ++j) {
|
||||||
|
method = arrayBody(t, vtable, j);
|
||||||
|
object n = hashMapFindNode
|
||||||
|
(t, virtualMap, method, methodHash, methodEqual);
|
||||||
|
if (n == 0) {
|
||||||
|
method = makeMethod
|
||||||
|
(t,
|
||||||
|
methodVmFlags(t, method),
|
||||||
|
methodReturnCode(t, method),
|
||||||
|
methodParameterCount(t, method),
|
||||||
|
methodParameterFootprint(t, method),
|
||||||
|
methodFlags(t, method),
|
||||||
|
(*virtualCount)++,
|
||||||
|
0,
|
||||||
|
methodName(t, method),
|
||||||
|
methodSpec(t, method),
|
||||||
|
class_,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
hashMapInsert(t, virtualMap, method, method, methodHash);
|
||||||
|
|
||||||
|
if (makeList) {
|
||||||
|
if (list == 0) {
|
||||||
|
list = vm::makeList(t, 0, 0, 0);
|
||||||
|
}
|
||||||
|
listAppend(t, list, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
||||||
{
|
{
|
||||||
@ -1180,38 +1243,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
PROTECT(t, superVirtualTable);
|
PROTECT(t, superVirtualTable);
|
||||||
|
|
||||||
if (classFlags(t, class_) & ACC_INTERFACE) {
|
if (classFlags(t, class_) & ACC_INTERFACE) {
|
||||||
object itable = classInterfaceTable(t, class_);
|
addInterfaceMethods(t, class_, virtualMap, &virtualCount, false);
|
||||||
if (itable) {
|
|
||||||
PROTECT(t, itable);
|
|
||||||
for (unsigned i = 0; i < arrayLength(t, itable); ++i) {
|
|
||||||
object vtable = classVirtualTable(t, arrayBody(t, itable, i));
|
|
||||||
if (vtable) {
|
|
||||||
PROTECT(t, vtable);
|
|
||||||
for (unsigned j = 0; j < arrayLength(t, vtable); ++j) {
|
|
||||||
object method = arrayBody(t, vtable, j);
|
|
||||||
object n = hashMapFindNode
|
|
||||||
(t, virtualMap, method, methodHash, methodEqual);
|
|
||||||
if (n == 0) {
|
|
||||||
method = makeMethod
|
|
||||||
(t,
|
|
||||||
methodVmFlags(t, method),
|
|
||||||
methodReturnCode(t, method),
|
|
||||||
methodParameterCount(t, method),
|
|
||||||
methodParameterFootprint(t, method),
|
|
||||||
methodFlags(t, method),
|
|
||||||
virtualCount++,
|
|
||||||
0,
|
|
||||||
methodName(t, method),
|
|
||||||
methodSpec(t, method),
|
|
||||||
class_,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
hashMapInsert(t, virtualMap, method, method, methodHash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (classSuper(t, class_)) {
|
if (classSuper(t, class_)) {
|
||||||
superVirtualTable = classVirtualTable(t, classSuper(t, class_));
|
superVirtualTable = classVirtualTable(t, classSuper(t, class_));
|
||||||
@ -1325,6 +1357,15 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
set(t, class_, ClassMethodTable, methodTable);
|
set(t, class_, ClassMethodTable, methodTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object abstractVirtuals;
|
||||||
|
if (classFlags(t, class_) & ACC_INTERFACE) {
|
||||||
|
abstractVirtuals = 0;
|
||||||
|
} else {
|
||||||
|
abstractVirtuals = addInterfaceMethods
|
||||||
|
(t, class_, virtualMap, &virtualCount, true);
|
||||||
|
}
|
||||||
|
PROTECT(t, abstractVirtuals);
|
||||||
|
|
||||||
bool populateInterfaceVtables = false;
|
bool populateInterfaceVtables = false;
|
||||||
|
|
||||||
if (declaredVirtualCount == 0
|
if (declaredVirtualCount == 0
|
||||||
@ -1367,6 +1408,8 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
++ i;
|
++ i;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
populateInterfaceVtables = true;
|
||||||
|
|
||||||
if (superVirtualTable) {
|
if (superVirtualTable) {
|
||||||
for (; i < arrayLength(t, superVirtualTable); ++i) {
|
for (; i < arrayLength(t, superVirtualTable); ++i) {
|
||||||
object method = arrayBody(t, superVirtualTable, i);
|
object method = arrayBody(t, superVirtualTable, i);
|
||||||
@ -1380,15 +1423,40 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
set(t, vtable, ArrayBody + (i * BytesPerWord), pairFirst(t, p));
|
set(t, vtable, ArrayBody + (i * BytesPerWord), pairFirst(t, p));
|
||||||
++ i;
|
++ i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (abstractVirtuals) {
|
||||||
|
PROTECT(t, abstractVirtuals);
|
||||||
|
|
||||||
|
unsigned oldLength = arrayLength(t, classMethodTable(t, class_));
|
||||||
|
object newMethodTable = makeArray
|
||||||
|
(t, oldLength + listSize(t, abstractVirtuals));
|
||||||
|
|
||||||
|
memcpy(&arrayBody(t, newMethodTable, 0),
|
||||||
|
&arrayBody(t, classMethodTable(t, class_), 0),
|
||||||
|
oldLength * sizeof(object));
|
||||||
|
|
||||||
|
mark(t, newMethodTable, ArrayBody, oldLength);
|
||||||
|
|
||||||
|
unsigned mti = oldLength;
|
||||||
|
for (object p = listFront(t, abstractVirtuals);
|
||||||
|
p; p = pairSecond(t, p))
|
||||||
|
{
|
||||||
|
set(t, newMethodTable,
|
||||||
|
ArrayBody + ((mti++) * BytesPerWord), pairFirst(t, p));
|
||||||
|
|
||||||
|
set(t, vtable,
|
||||||
|
ArrayBody + ((i++) * BytesPerWord), pairFirst(t, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(t, arrayLength(t, newMethodTable) == mti);
|
||||||
|
|
||||||
|
set(t, class_, ClassMethodTable, newMethodTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t, arrayLength(t, vtable) == i);
|
assert(t, arrayLength(t, vtable) == i);
|
||||||
|
|
||||||
set(t, class_, ClassVirtualTable, vtable);
|
set(t, class_, ClassVirtualTable, vtable);
|
||||||
|
|
||||||
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
|
|
||||||
populateInterfaceVtables = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (populateInterfaceVtables) {
|
if (populateInterfaceVtables) {
|
||||||
@ -1406,9 +1474,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
object method = arrayBody(t, ivtable, j);
|
object method = arrayBody(t, ivtable, j);
|
||||||
method = hashMapFind
|
method = hashMapFind
|
||||||
(t, virtualMap, method, methodHash, methodEqual);
|
(t, virtualMap, method, methodHash, methodEqual);
|
||||||
|
assert(t, method);
|
||||||
// note that method may be null in the case of an abstract
|
|
||||||
// class
|
|
||||||
|
|
||||||
set(t, vtable, ArrayBody + (j * BytesPerWord), method);
|
set(t, vtable, ArrayBody + (j * BytesPerWord), method);
|
||||||
}
|
}
|
||||||
@ -1480,7 +1546,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeArrayClass(Thread* t, unsigned dimensions, object spec,
|
makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec,
|
||||||
object elementClass)
|
object elementClass)
|
||||||
{
|
{
|
||||||
// todo: arrays should implement Cloneable and Serializable
|
// todo: arrays should implement Cloneable and Serializable
|
||||||
@ -1502,7 +1568,7 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
elementClass,
|
elementClass,
|
||||||
t->m->loader,
|
loader,
|
||||||
arrayLength(t, vtable));
|
arrayLength(t, vtable));
|
||||||
|
|
||||||
t->m->processor->initVtable(t, c);
|
t->m->processor->initVtable(t, c);
|
||||||
@ -1511,7 +1577,7 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeArrayClass(Thread* t, object spec)
|
makeArrayClass(Thread* t, object loader, object spec)
|
||||||
{
|
{
|
||||||
PROTECT(t, spec);
|
PROTECT(t, spec);
|
||||||
|
|
||||||
@ -1551,11 +1617,28 @@ makeArrayClass(Thread* t, object spec)
|
|||||||
(t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
|
(t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
if (elementClass == 0) {
|
if (elementClass == 0) {
|
||||||
elementClass = resolveClass(t, elementSpec);
|
elementClass = resolveClass(t, loader, elementSpec);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeArrayClass(t, dimensions, spec, elementClass);
|
return makeArrayClass(t, loader, dimensions, spec, elementClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveArrayClass(Thread* t, object loader, object spec)
|
||||||
|
{
|
||||||
|
object c = hashMapFind
|
||||||
|
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
|
if (c) {
|
||||||
|
set(t, c, ClassVirtualTable,
|
||||||
|
classVirtualTable
|
||||||
|
(t, arrayBody(t, t->m->types, Machine::JobjectType)));
|
||||||
|
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
return makeArrayClass(t, loader, spec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1714,9 +1797,10 @@ boot(Thread* t)
|
|||||||
classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType))
|
classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType))
|
||||||
|= PrimitiveFlag;
|
|= PrimitiveFlag;
|
||||||
|
|
||||||
m->bootstrapClassMap = makeHashMap(t, 0, 0);
|
object classMap = makeHashMap(t, 0, 0);
|
||||||
|
set(t, t->m->loader, ClassLoaderMap, classMap);
|
||||||
|
|
||||||
m->classMap = makeHashMap(t, 0, 0);
|
m->bootstrapClassMap = makeHashMap(t, 0, 0);
|
||||||
|
|
||||||
m->stringMap = makeWeakHashMap(t, 0, 0);
|
m->stringMap = makeWeakHashMap(t, 0, 0);
|
||||||
|
|
||||||
@ -1846,7 +1930,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
|||||||
referenceLock(0),
|
referenceLock(0),
|
||||||
libraries(0),
|
libraries(0),
|
||||||
loader(0),
|
loader(0),
|
||||||
classMap(0),
|
loadClassMethod(0),
|
||||||
bootstrapClassMap(0),
|
bootstrapClassMap(0),
|
||||||
monitorMap(0),
|
monitorMap(0),
|
||||||
stringMap(0),
|
stringMap(0),
|
||||||
@ -1980,6 +2064,8 @@ Thread::init()
|
|||||||
|
|
||||||
m->localThread->set(this);
|
m->localThread->set(this);
|
||||||
} else {
|
} else {
|
||||||
|
assert(this, javaThread);
|
||||||
|
|
||||||
peer = parent->child;
|
peer = parent->child;
|
||||||
parent->child = this;
|
parent->child = this;
|
||||||
}
|
}
|
||||||
@ -1990,9 +2076,11 @@ Thread::init()
|
|||||||
const unsigned NewState = 0;
|
const unsigned NewState = 0;
|
||||||
const unsigned NormalPriority = 5;
|
const unsigned NormalPriority = 5;
|
||||||
|
|
||||||
|
object group = makeThreadGroup(this, 0, 0);
|
||||||
|
|
||||||
this->javaThread = makeThread
|
this->javaThread = makeThread
|
||||||
(this, reinterpret_cast<int64_t>(this), 0, 0, NewState, NormalPriority,
|
(this, reinterpret_cast<int64_t>(this), 0, 0, NewState, NormalPriority,
|
||||||
0, 0, 0, m->loader, 0, 0, 0);
|
0, 0, 0, m->loader, 0, 0, group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2296,6 +2384,8 @@ makeNewGeneral(Thread* t, object class_)
|
|||||||
{
|
{
|
||||||
assert(t, t->state == Thread::ActiveState);
|
assert(t, t->state == Thread::ActiveState);
|
||||||
|
|
||||||
|
PROTECT(t, class_);
|
||||||
|
|
||||||
object instance = makeNew(t, class_);
|
object instance = makeNew(t, class_);
|
||||||
PROTECT(t, instance);
|
PROTECT(t, instance);
|
||||||
|
|
||||||
@ -2378,7 +2468,7 @@ isAssignableFrom(Thread* t, object a, object b)
|
|||||||
|
|
||||||
if (classFlags(t, a) & ACC_INTERFACE) {
|
if (classFlags(t, a) & ACC_INTERFACE) {
|
||||||
if (classVmFlags(t, b) & BootstrapFlag) {
|
if (classVmFlags(t, b) & BootstrapFlag) {
|
||||||
resolveClass(t, className(t, b));
|
resolveSystemClass(t, className(t, b));
|
||||||
if (UNLIKELY(t->exception)) {
|
if (UNLIKELY(t->exception)) {
|
||||||
t->exception = 0;
|
t->exception = 0;
|
||||||
return false;
|
return false;
|
||||||
@ -2517,17 +2607,20 @@ primitiveSize(Thread* t, unsigned code)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
findLoadedClass(Thread* t, object spec)
|
findLoadedSystemClass(Thread* t, object spec)
|
||||||
{
|
{
|
||||||
PROTECT(t, spec);
|
PROTECT(t, spec);
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
return hashMapFind(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
|
return hashMapFind(t, classLoaderMap(t, t->m->loader), spec, byteArrayHash,
|
||||||
|
byteArrayEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
parseClass(Thread* t, const uint8_t* data, unsigned size)
|
parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
|
||||||
{
|
{
|
||||||
|
PROTECT(t, loader);
|
||||||
|
|
||||||
class Client : public Stream::Client {
|
class Client : public Stream::Client {
|
||||||
public:
|
public:
|
||||||
Client(Thread* t): t(t) { }
|
Client(Thread* t): t(t) { }
|
||||||
@ -2567,13 +2660,13 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
|||||||
0, // fields
|
0, // fields
|
||||||
0, // methods
|
0, // methods
|
||||||
0, // static table
|
0, // static table
|
||||||
t->m->loader,
|
loader,
|
||||||
0);// vtable length
|
0);// vtable length
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
unsigned super = s.read2();
|
unsigned super = s.read2();
|
||||||
if (super) {
|
if (super) {
|
||||||
object sc = resolveClass(t, singletonObject(t, pool, super - 1));
|
object sc = resolveClass(t, loader, singletonObject(t, pool, super - 1));
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
set(t, class_, ClassSuper, sc);
|
set(t, class_, ClassSuper, sc);
|
||||||
@ -2623,26 +2716,18 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveClass(Thread* t, object spec)
|
resolveSystemClass(Thread* t, object spec)
|
||||||
{
|
{
|
||||||
PROTECT(t, spec);
|
PROTECT(t, spec);
|
||||||
|
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
object class_ = hashMapFind
|
object class_ = hashMapFind
|
||||||
(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual);
|
(t, classLoaderMap(t, t->m->loader), spec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
if (class_ == 0) {
|
if (class_ == 0) {
|
||||||
if (byteArrayBody(t, spec, 0) == '[') {
|
if (byteArrayBody(t, spec, 0) == '[') {
|
||||||
class_ = hashMapFind
|
class_ = resolveArrayClass(t, t->m->loader, spec);
|
||||||
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
|
||||||
|
|
||||||
if (class_) {
|
|
||||||
set(t, class_, ClassVirtualTable,
|
|
||||||
classVirtualTable
|
|
||||||
(t, arrayBody(t, t->m->types, Machine::JobjectType)));
|
|
||||||
} else {
|
|
||||||
class_ = makeArrayClass(t, spec);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
char file[byteArrayLength(t, spec) + 6];
|
char file[byteArrayLength(t, spec) + 6];
|
||||||
memcpy(file, &byteArrayBody(t, spec, 0), byteArrayLength(t, spec) - 1);
|
memcpy(file, &byteArrayBody(t, spec, 0), byteArrayLength(t, spec) - 1);
|
||||||
@ -2656,7 +2741,8 @@ resolveClass(Thread* t, object spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse class file
|
// parse class file
|
||||||
class_ = parseClass(t, region->start(), region->length());
|
class_ = parseClass
|
||||||
|
(t, t->m->loader, region->start(), region->length());
|
||||||
region->dispose();
|
region->dispose();
|
||||||
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
@ -2667,7 +2753,8 @@ resolveClass(Thread* t, object spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object bootstrapClass = hashMapFind
|
object bootstrapClass = hashMapFind
|
||||||
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
(t, t->m->bootstrapClassMap, spec, byteArrayHash,
|
||||||
|
byteArrayEqual);
|
||||||
|
|
||||||
if (bootstrapClass) {
|
if (bootstrapClass) {
|
||||||
PROTECT(t, bootstrapClass);
|
PROTECT(t, bootstrapClass);
|
||||||
@ -2682,7 +2769,8 @@ resolveClass(Thread* t, object spec)
|
|||||||
if (class_) {
|
if (class_) {
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash);
|
hashMapInsert(t, classLoaderMap(t, t->m->loader), spec, class_,
|
||||||
|
byteArrayHash);
|
||||||
} else if (t->exception == 0) {
|
} else if (t->exception == 0) {
|
||||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||||
t->exception = makeClassNotFoundException(t, message);
|
t->exception = makeClassNotFoundException(t, message);
|
||||||
@ -2692,6 +2780,79 @@ resolveClass(Thread* t, object spec)
|
|||||||
return class_;
|
return class_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveClass(Thread* t, object loader, object spec)
|
||||||
|
{
|
||||||
|
if (loader == t->m->loader) {
|
||||||
|
return resolveSystemClass(t, spec);
|
||||||
|
} else {
|
||||||
|
PROTECT(t, loader);
|
||||||
|
PROTECT(t, spec);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
|
if (classLoaderMap(t, loader) == 0) {
|
||||||
|
object map = makeHashMap(t, 0, 0);
|
||||||
|
set(t, loader, ClassLoaderMap, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
object class_ = hashMapFind
|
||||||
|
(t, classLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
|
if (class_ == 0) {
|
||||||
|
if (byteArrayBody(t, spec, 0) == '[') {
|
||||||
|
class_ = resolveArrayClass(t, loader, spec);
|
||||||
|
} else {
|
||||||
|
if (t->m->loadClassMethod == 0) {
|
||||||
|
object m = resolveMethod
|
||||||
|
(t, t->m->loader, "java/lang/ClassLoader", "loadClass",
|
||||||
|
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||||
|
|
||||||
|
if (m) {
|
||||||
|
t->m->loadClassMethod = m;
|
||||||
|
|
||||||
|
object classLoaderClass = arrayBody
|
||||||
|
(t, t->m->types, Machine::ClassLoaderType);
|
||||||
|
|
||||||
|
if (classVmFlags(t, classLoaderClass) & BootstrapFlag) {
|
||||||
|
resolveSystemClass(t, vm::className(t, classLoaderClass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
object method = findMethod
|
||||||
|
(t, t->m->loadClassMethod, objectClass(t, loader));
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
object specString = makeString
|
||||||
|
(t, "%s", &byteArrayBody(t, spec, 0));
|
||||||
|
|
||||||
|
replace('/', '.', reinterpret_cast<char*>
|
||||||
|
(&byteArrayBody(t, stringData(t, specString), 0)));
|
||||||
|
|
||||||
|
class_ = t->m->processor->invoke(t, method, loader, specString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (class_) {
|
||||||
|
PROTECT(t, class_);
|
||||||
|
|
||||||
|
hashMapInsert(t, classLoaderMap(t, loader), spec, class_,
|
||||||
|
byteArrayHash);
|
||||||
|
} else if (t->exception == 0) {
|
||||||
|
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||||
|
t->exception = makeClassNotFoundException(t, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return class_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveMethod(Thread* t, object class_, const char* methodName,
|
resolveMethod(Thread* t, object class_, const char* methodName,
|
||||||
const char* methodSpec)
|
const char* methodSpec)
|
||||||
@ -2748,8 +2909,9 @@ resolveField(Thread* t, object class_, const char* fieldName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveObjectArrayClass(Thread* t, object elementSpec)
|
resolveObjectArrayClass(Thread* t, object loader, object elementSpec)
|
||||||
{
|
{
|
||||||
|
PROTECT(t, loader);
|
||||||
PROTECT(t, elementSpec);
|
PROTECT(t, elementSpec);
|
||||||
|
|
||||||
object spec;
|
object spec;
|
||||||
@ -2770,7 +2932,7 @@ resolveObjectArrayClass(Thread* t, object elementSpec)
|
|||||||
byteArrayBody(t, spec, byteArrayLength(t, elementSpec) + 2) = 0;
|
byteArrayBody(t, spec, byteArrayLength(t, elementSpec) + 2) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveClass(t, spec);
|
return resolveClass(t, loader, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -2860,9 +3022,10 @@ initClass(Thread* t, object c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeObjectArray(Thread* t, object elementClass, unsigned count)
|
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count)
|
||||||
{
|
{
|
||||||
object arrayClass = resolveObjectArrayClass(t, className(t, elementClass));
|
object arrayClass = resolveObjectArrayClass
|
||||||
|
(t, loader, className(t, elementClass));
|
||||||
PROTECT(t, arrayClass);
|
PROTECT(t, arrayClass);
|
||||||
|
|
||||||
object array = makeArray(t, count);
|
object array = makeArray(t, count);
|
||||||
@ -2926,10 +3089,6 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
|
|||||||
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
|
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
|
||||||
o = find(t, class_, name, spec);
|
o = find(t, class_, name, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o == 0 and find == findMethodInClass) {
|
|
||||||
o = findInInterfaces(t, originalClass, name, spec, find);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o == 0) {
|
if (o == 0) {
|
||||||
@ -3153,7 +3312,7 @@ void
|
|||||||
visitRoots(Machine* m, Heap::Visitor* v)
|
visitRoots(Machine* m, Heap::Visitor* v)
|
||||||
{
|
{
|
||||||
v->visit(&(m->loader));
|
v->visit(&(m->loader));
|
||||||
v->visit(&(m->classMap));
|
v->visit(&(m->loadClassMethod));
|
||||||
v->visit(&(m->bootstrapClassMap));
|
v->visit(&(m->bootstrapClassMap));
|
||||||
v->visit(&(m->monitorMap));
|
v->visit(&(m->monitorMap));
|
||||||
v->visit(&(m->stringMap));
|
v->visit(&(m->stringMap));
|
||||||
@ -3275,7 +3434,7 @@ void
|
|||||||
runJavaThread(Thread* t)
|
runJavaThread(Thread* t)
|
||||||
{
|
{
|
||||||
object method = resolveMethod
|
object method = resolveMethod
|
||||||
(t, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
|
(t, t->m->loader, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
|
||||||
|
|
||||||
if (t->exception == 0) {
|
if (t->exception == 0) {
|
||||||
t->m->processor->invoke(t, method, 0, t->javaThread);
|
t->m->processor->invoke(t, method, 0, t->javaThread);
|
||||||
|
@ -1188,7 +1188,7 @@ class Machine {
|
|||||||
System::Monitor* referenceLock;
|
System::Monitor* referenceLock;
|
||||||
System::Library* libraries;
|
System::Library* libraries;
|
||||||
object loader;
|
object loader;
|
||||||
object classMap;
|
object loadClassMethod;
|
||||||
object bootstrapClassMap;
|
object bootstrapClassMap;
|
||||||
object monitorMap;
|
object monitorMap;
|
||||||
object stringMap;
|
object stringMap;
|
||||||
@ -2070,7 +2070,7 @@ fieldSize(Thread* t, object field)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
findLoadedClass(Thread* t, object spec);
|
findLoadedSystemClass(Thread* t, object spec);
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
emptyMethod(Thread* t, object method)
|
emptyMethod(Thread* t, object method)
|
||||||
@ -2081,15 +2081,26 @@ emptyMethod(Thread* t, object method)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
parseClass(Thread* t, const uint8_t* data, unsigned length);
|
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length);
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveClass(Thread* t, object name);
|
resolveClass(Thread* t, object loader, object name);
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveClass(Thread* t, const char* name)
|
resolveClass(Thread* t, object loader, const char* name)
|
||||||
{
|
{
|
||||||
return resolveClass(t, makeByteArray(t, "%s", name));
|
PROTECT(t, loader);
|
||||||
|
object n = makeByteArray(t, "%s", name);
|
||||||
|
return resolveClass(t, loader, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveSystemClass(Thread* t, object name);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveSystemClass(Thread* t, const char* name)
|
||||||
|
{
|
||||||
|
return resolveSystemClass(t, makeByteArray(t, "%s", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
@ -2097,10 +2108,10 @@ resolveMethod(Thread* t, object class_, const char* methodName,
|
|||||||
const char* methodSpec);
|
const char* methodSpec);
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
resolveMethod(Thread* t, object loader, const char* className,
|
||||||
const char* methodSpec)
|
const char* methodName, const char* methodSpec)
|
||||||
{
|
{
|
||||||
object class_ = resolveClass(t, className);
|
object class_ = resolveClass(t, loader, className);
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
return resolveMethod(t, class_, methodName, methodSpec);
|
return resolveMethod(t, class_, methodName, methodSpec);
|
||||||
} else {
|
} else {
|
||||||
@ -2113,10 +2124,10 @@ resolveField(Thread* t, object class_, const char* fieldName,
|
|||||||
const char* fieldSpec);
|
const char* fieldSpec);
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveField(Thread* t, const char* className, const char* fieldName,
|
resolveField(Thread* t, object loader, const char* className,
|
||||||
const char* fieldSpec)
|
const char* fieldName, const char* fieldSpec)
|
||||||
{
|
{
|
||||||
object class_ = resolveClass(t, className);
|
object class_ = resolveClass(t, loader, className);
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
return resolveField(t, class_, fieldName, fieldSpec);
|
return resolveField(t, class_, fieldName, fieldSpec);
|
||||||
} else {
|
} else {
|
||||||
@ -2125,7 +2136,7 @@ resolveField(Thread* t, const char* className, const char* fieldName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveObjectArrayClass(Thread* t, object elementSpec);
|
resolveObjectArrayClass(Thread* t, object loader, object elementSpec);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
classNeedsInit(Thread* t, object c);
|
classNeedsInit(Thread* t, object c);
|
||||||
@ -2140,7 +2151,7 @@ void
|
|||||||
initClass(Thread* t, object c);
|
initClass(Thread* t, object c);
|
||||||
|
|
||||||
object
|
object
|
||||||
makeObjectArray(Thread* t, object elementClass, unsigned count);
|
makeObjectArray(Thread* t, object loader, object elementClass, unsigned count);
|
||||||
|
|
||||||
object
|
object
|
||||||
findInTable(Thread* t, object table, object name, object spec,
|
findInTable(Thread* t, object table, object name, object spec,
|
||||||
|
@ -501,11 +501,19 @@ void unsignedShiftRightR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveRR(Context* c, unsigned srcSize, Assembler::Register* src,
|
||||||
|
unsigned dstSize, Assembler::Register* dst);
|
||||||
|
|
||||||
void unsignedShiftRightC(Context* con, unsigned size, Const* a, Reg* b, Reg* t)
|
void unsignedShiftRightC(Context* con, unsigned size, Const* a, Reg* b, Reg* t)
|
||||||
{
|
{
|
||||||
int sh = getVal(a);
|
int sh = getVal(a);
|
||||||
if (size == 8) {
|
if (size == 8) {
|
||||||
if (sh < 32) {
|
if (sh == 32) {
|
||||||
|
Assembler::Register high(b->high);
|
||||||
|
moveRR(con, 4, &high, 4, t);
|
||||||
|
issue(con, li(H(t),0));
|
||||||
|
} else if (sh < 32) {
|
||||||
issue(con, srwi(R(t), R(b), sh));
|
issue(con, srwi(R(t), R(b), sh));
|
||||||
issue(con, rlwimi(R(t),H(b),32-sh,0,sh-1));
|
issue(con, rlwimi(R(t),H(b),32-sh,0,sh-1));
|
||||||
issue(con, rlwinm(H(t),H(b),32-sh,sh,31));
|
issue(con, rlwinm(H(t),H(b),32-sh,sh,31));
|
||||||
@ -596,10 +604,6 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* target)
|
|||||||
issue(c, bctr());
|
issue(c, bctr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
moveRR(Context* c, unsigned srcSize, Assembler::Register* src,
|
|
||||||
unsigned dstSize, Assembler::Register* dst);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
swapRR(Context* c, unsigned aSize, Assembler::Register* a,
|
swapRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||||
unsigned bSize, Assembler::Register* b)
|
unsigned bSize, Assembler::Register* b)
|
||||||
|
@ -203,14 +203,14 @@ namespace vm {
|
|||||||
void*
|
void*
|
||||||
resolveNativeMethod(Thread* t, object method)
|
resolveNativeMethod(Thread* t, object method)
|
||||||
{
|
{
|
||||||
void* p = ::resolveNativeMethod(t, method, "Java_", 5, -1);
|
void* p = ::resolveNativeMethod(t, method, "Avian_", 6, 3);
|
||||||
if (p) {
|
if (p) {
|
||||||
|
methodVmFlags(t, method) |= FastNative;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = ::resolveNativeMethod(t, method, "Avian_", 6, 3);
|
p = ::resolveNativeMethod(t, method, "Java_", 5, -1);
|
||||||
if (p) {
|
if (p) {
|
||||||
methodVmFlags(t, method) |= FastNative;
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +37,14 @@ codeReadInt32(Thread* t, object code, unsigned& ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveClassInObject(Thread* t, object container, unsigned classOffset)
|
resolveClassInObject(Thread* t, object loader, object container,
|
||||||
|
unsigned classOffset)
|
||||||
{
|
{
|
||||||
object o = cast<object>(container, classOffset);
|
object o = cast<object>(container, classOffset);
|
||||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
|
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
|
||||||
PROTECT(t, container);
|
PROTECT(t, container);
|
||||||
|
|
||||||
o = resolveClass(t, o);
|
o = resolveClass(t, loader, o);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
set(t, container, classOffset, o);
|
set(t, container, classOffset, o);
|
||||||
@ -52,34 +53,36 @@ resolveClassInObject(Thread* t, object container, unsigned classOffset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveClassInPool(Thread* t, object pool, unsigned index)
|
resolveClassInPool(Thread* t, object method, unsigned index)
|
||||||
{
|
{
|
||||||
object o = singletonObject(t, pool, index);
|
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
|
||||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
|
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) {
|
||||||
PROTECT(t, pool);
|
PROTECT(t, method);
|
||||||
|
|
||||||
o = resolveClass(t, o);
|
o = resolveClass(t, classLoader(t, methodClass(t, method)), o);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
set(t, pool, SingletonBody + (index * BytesPerWord), o);
|
set(t, codePool(t, methodCode(t, method)),
|
||||||
|
SingletonBody + (index * BytesPerWord), o);
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolve(Thread* t, object pool, unsigned index,
|
resolve(Thread* t, object method, unsigned index,
|
||||||
object (*find)(vm::Thread*, object, object, object),
|
object (*find)(vm::Thread*, object, object, object),
|
||||||
object (*makeError)(vm::Thread*, object))
|
object (*makeError)(vm::Thread*, object))
|
||||||
{
|
{
|
||||||
object o = singletonObject(t, pool, index);
|
object o = singletonObject(t, codePool(t, methodCode(t, method)), index);
|
||||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
|
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
|
||||||
{
|
{
|
||||||
PROTECT(t, pool);
|
PROTECT(t, method);
|
||||||
|
|
||||||
object reference = o;
|
object reference = o;
|
||||||
PROTECT(t, reference);
|
PROTECT(t, reference);
|
||||||
|
|
||||||
object class_ = resolveClassInObject(t, o, ReferenceClass);
|
object class_ = resolveClassInObject
|
||||||
|
(t, classLoader(t, methodClass(t, method)), o, ReferenceClass);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
o = findInHierarchy
|
o = findInHierarchy
|
||||||
@ -87,22 +90,23 @@ resolve(Thread* t, object pool, unsigned index,
|
|||||||
find, makeError);
|
find, makeError);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
set(t, pool, SingletonBody + (index * BytesPerWord), o);
|
set(t, codePool(t, methodCode(t, method)),
|
||||||
|
SingletonBody + (index * BytesPerWord), o);
|
||||||
}
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveField(Thread* t, object pool, unsigned index)
|
resolveField(Thread* t, object method, unsigned index)
|
||||||
{
|
{
|
||||||
return resolve(t, pool, index, findFieldInClass, makeNoSuchFieldError);
|
return resolve(t, method, index, findFieldInClass, makeNoSuchFieldError);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveMethod(Thread* t, object pool, unsigned index)
|
resolveMethod(Thread* t, object method, unsigned index)
|
||||||
{
|
{
|
||||||
return resolve(t, pool, index, findMethodInClass, makeNoSuchMethodError);
|
return resolve(t, method, index, findMethodInClass, makeNoSuchMethodError);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -162,7 +166,7 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
|
|||||||
&byteArrayBody(t, spec, 1),
|
&byteArrayBody(t, spec, 1),
|
||||||
byteArrayLength(t, spec) - 1);
|
byteArrayLength(t, spec) - 1);
|
||||||
|
|
||||||
object class_ = resolveClass(t, elementSpec);
|
object class_ = resolveSystemClass(t, elementSpec);
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
for (int32_t i = 0; i < counts[index]; ++i) {
|
for (int32_t i = 0; i < counts[index]; ++i) {
|
||||||
|
@ -101,8 +101,9 @@ class Processor {
|
|||||||
va_list arguments) = 0;
|
va_list arguments) = 0;
|
||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
invokeList(Thread* t, const char* className, const char* methodName,
|
invokeList(Thread* t, object loader, const char* className,
|
||||||
const char* methodSpec, object this_, va_list arguments) = 0;
|
const char* methodName, const char* methodSpec,
|
||||||
|
object this_, va_list arguments) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose(Thread* t) = 0;
|
dispose(Thread* t) = 0;
|
||||||
@ -160,13 +161,14 @@ class Processor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
invoke(Thread* t, const char* className, const char* methodName,
|
invoke(Thread* t, object loader, const char* className,
|
||||||
const char* methodSpec, object this_, ...)
|
const char* methodName, const char* methodSpec, object this_, ...)
|
||||||
{
|
{
|
||||||
va_list a;
|
va_list a;
|
||||||
va_start(a, this_);
|
va_start(a, this_);
|
||||||
|
|
||||||
object r = invokeList(t, className, methodName, methodSpec, this_, a);
|
object r = invokeList
|
||||||
|
(t, loader, className, methodName, methodSpec, this_, a);
|
||||||
|
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
(type singleton
|
(type singleton
|
||||||
(array uintptr_t body))
|
(array uintptr_t body))
|
||||||
|
|
||||||
(type classLoader java/lang/ClassLoader)
|
(type classLoader java/lang/ClassLoader
|
||||||
|
(object map))
|
||||||
|
|
||||||
(type systemClassLoader avian/SystemClassLoader)
|
(type systemClassLoader avian/SystemClassLoader)
|
||||||
|
|
||||||
@ -128,6 +129,8 @@
|
|||||||
|
|
||||||
(type thread java/lang/Thread)
|
(type thread java/lang/Thread)
|
||||||
|
|
||||||
|
(type threadGroup java/lang/ThreadGroup)
|
||||||
|
|
||||||
(type stackTraceElement java/lang/StackTraceElement)
|
(type stackTraceElement java/lang/StackTraceElement)
|
||||||
|
|
||||||
(type throwable java/lang/Throwable)
|
(type throwable java/lang/Throwable)
|
||||||
|
@ -39,6 +39,10 @@ public class Longs {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long unsignedShiftRight32(long x) {
|
||||||
|
return x >>> 32;
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
expect(((long) negativeOne()) == -1);
|
expect(((long) negativeOne()) == -1);
|
||||||
|
|
||||||
@ -211,6 +215,8 @@ public class Longs {
|
|||||||
buffer.putLong(231);
|
buffer.putLong(231);
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
expect(buffer.getLong() == 231);
|
expect(buffer.getLong() == 231);
|
||||||
|
|
||||||
|
expect(unsignedShiftRight32(231) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user