mirror of
https://github.com/corda/corda.git
synced 2024-12-28 16:58:55 +00:00
bugfixes
This commit is contained in:
parent
e5bea7a455
commit
f71c77298c
@ -22,7 +22,7 @@ public class TestThreads implements Runnable {
|
||||
try {
|
||||
System.out.println("I'm running in a seperate thread!");
|
||||
|
||||
final int arrayCount = 64;
|
||||
final int arrayCount = 8;
|
||||
final int arraySize = 4;
|
||||
System.out.println("Allocating and discarding " + arrayCount +
|
||||
" arrays of " + arraySize + "MB each");
|
||||
|
19
classpath/java/lang/ArrayIndexOutOfBoundsException.java
Normal file
19
classpath/java/lang/ArrayIndexOutOfBoundsException.java
Normal file
@ -0,0 +1,19 @@
|
||||
package java.lang;
|
||||
|
||||
public class ArrayIndexOutOfBoundsException extends RuntimeException {
|
||||
public ArrayIndexOutOfBoundsException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ArrayIndexOutOfBoundsException(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
public ArrayIndexOutOfBoundsException(Throwable cause) {
|
||||
this(null, cause);
|
||||
}
|
||||
|
||||
public ArrayIndexOutOfBoundsException() {
|
||||
this(null, null);
|
||||
}
|
||||
}
|
@ -19,9 +19,9 @@ public class Object {
|
||||
|
||||
public native String toString();
|
||||
|
||||
public native final void wait();
|
||||
public final void wait() {
|
||||
wait(0);
|
||||
}
|
||||
|
||||
public native final void wait(long timeout);
|
||||
|
||||
public native final void wait(long timeout, int nanos);
|
||||
}
|
||||
|
@ -6,6 +6,20 @@ public final class String {
|
||||
private int length;
|
||||
private int hash;
|
||||
|
||||
public String(char[] data, int offset, int length, boolean copy) {
|
||||
if (copy) {
|
||||
char[] c = new char[length];
|
||||
System.arraycopy(data, offset, c, 0, length);
|
||||
|
||||
this.data = c;
|
||||
this.length = length;
|
||||
} else {
|
||||
this.data = data;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
@ -14,8 +28,23 @@ public final class String {
|
||||
return valueOf((long) v);
|
||||
}
|
||||
|
||||
public native void getChars(int offset, int length,
|
||||
char[] dst, int dstLength);
|
||||
public void getChars(int srcOffset, int srcLength,
|
||||
char[] dst, int dstOffset)
|
||||
{
|
||||
if (srcOffset + srcLength > length) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
if (data instanceof char[]) {
|
||||
char[] src = (char[]) data;
|
||||
System.arraycopy(src, offset + srcOffset, dst, dstOffset, srcLength);
|
||||
} else {
|
||||
byte[] src = (byte[]) data;
|
||||
for (int i = 0; i < srcLength; ++i) {
|
||||
dst[i + dstOffset] = (char) src[i + offset + srcOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String valueOf(long v) {
|
||||
if (v == 0) {
|
||||
@ -35,7 +64,7 @@ public final class String {
|
||||
array[--index] = '-';
|
||||
}
|
||||
|
||||
return vm.Strings.wrap(array, index, Max - index);
|
||||
return new String(array, index, Max - index, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class StringBuilder {
|
||||
index -= c.value.length();
|
||||
c.value.getChars(0, c.value.length(), array, index);
|
||||
}
|
||||
return vm.Strings.wrap(array, 0, array.length);
|
||||
return new String(array, 0, array.length, false);
|
||||
}
|
||||
|
||||
private static class Cell {
|
||||
|
@ -1,16 +1,34 @@
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "jni.h"
|
||||
|
||||
#undef JNIEXPORT
|
||||
#define JNIEXPORT __attribute__ ((visibility("default")))
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_lang_System_00024Output_println(JNIEnv* e, jobject, jstring s)
|
||||
Java_java_lang_System_00024Output_print(JNIEnv* e, jobject, jstring s)
|
||||
{
|
||||
jboolean isCopy;
|
||||
const char* chars = e->GetStringUTFChars(s, &isCopy);
|
||||
if (chars) {
|
||||
printf("%s\n", chars);
|
||||
printf("%s", chars);
|
||||
}
|
||||
e->ReleaseStringUTFChars(s, chars);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jstring JNICALL
|
||||
Java_java_lang_System_getProperty(JNIEnv* e, jstring key)
|
||||
{
|
||||
jstring value = 0;
|
||||
|
||||
jboolean isCopy;
|
||||
const char* chars = e->GetStringUTFChars(key, &isCopy);
|
||||
if (chars) {
|
||||
if (strcmp(chars, "line.separator") == 0) {
|
||||
value = e->NewStringUTF("\n");
|
||||
}
|
||||
}
|
||||
e->ReleaseStringUTFChars(key, chars);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -8,14 +8,17 @@ public abstract class System {
|
||||
loadLibrary("natives");
|
||||
}
|
||||
|
||||
public static native void arraycopy(Object src, int srcOffset, Object dst,
|
||||
int dstOffset, int length);
|
||||
|
||||
public static native void loadLibrary(String name);
|
||||
|
||||
public static native String getProperty(String name);
|
||||
|
||||
public static class Output {
|
||||
public native void print(String s);
|
||||
public synchronized native void print(String s);
|
||||
|
||||
public void println(String s) {
|
||||
public synchronized void println(String s) {
|
||||
print(s);
|
||||
print(getProperty("line.separator"));
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
package vm;
|
||||
|
||||
public abstract class Strings {
|
||||
public static native String wrap(char[] array, int offset, int length);
|
||||
}
|
@ -5,6 +5,35 @@
|
||||
namespace vm {
|
||||
namespace builtin {
|
||||
|
||||
jstring
|
||||
toString(Thread* t, jobject this_)
|
||||
{
|
||||
object s = makeString
|
||||
(t, "%s@%p",
|
||||
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
||||
*this_);
|
||||
|
||||
return pushReference(t, s);
|
||||
}
|
||||
|
||||
void
|
||||
wait(Thread* t, jobject this_, jlong milliseconds)
|
||||
{
|
||||
vm::wait(t, *this_, milliseconds);
|
||||
}
|
||||
|
||||
void
|
||||
notify(Thread* t, jobject this_)
|
||||
{
|
||||
vm::notify(t, *this_);
|
||||
}
|
||||
|
||||
void
|
||||
notifyAll(Thread* t, jobject this_)
|
||||
{
|
||||
vm::notifyAll(t, *this_);
|
||||
}
|
||||
|
||||
void
|
||||
loadLibrary(Thread* t, jstring nameString)
|
||||
{
|
||||
@ -30,15 +59,53 @@ loadLibrary(Thread* t, jstring nameString)
|
||||
}
|
||||
}
|
||||
|
||||
jstring
|
||||
toString(Thread* t, jobject this_)
|
||||
void
|
||||
arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset,
|
||||
jint length)
|
||||
{
|
||||
object s = makeString
|
||||
(t, "%s@%p",
|
||||
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
||||
*this_);
|
||||
if (LIKELY(src and dst)) {
|
||||
object s = *src;
|
||||
object d = *dst;
|
||||
|
||||
return pushReference(t, s);
|
||||
if (LIKELY(objectClass(t, s) == objectClass(t, d))) {
|
||||
unsigned elementSize = classArrayElementSize(t, objectClass(t, s));
|
||||
|
||||
if (LIKELY(elementSize)) {
|
||||
unsigned offset = 0;
|
||||
|
||||
if (objectClass(t, s)
|
||||
== arrayBody(t, t->vm->types, Machine::ObjectArrayType))
|
||||
{
|
||||
if (LIKELY(objectArrayElementClass(t, s)
|
||||
== objectArrayElementClass(t, d)))
|
||||
{
|
||||
offset = 1;
|
||||
} else {
|
||||
t->exception = makeArrayStoreException(t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t sl = cast<uint32_t>(s, offset * BytesPerWord);
|
||||
int32_t dl = cast<uint32_t>(d, offset * BytesPerWord);
|
||||
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
|
||||
dstOffset >= 0 and dstOffset + length < dl))
|
||||
{
|
||||
uint8_t* sbody = &cast<uint8_t>(s, (offset * BytesPerWord) + 4);
|
||||
uint8_t* dbody = &cast<uint8_t>(s, (offset * BytesPerWord) + 4);
|
||||
memcpy(sbody + (srcOffset * elementSize),
|
||||
dbody + (dstOffset * elementSize),
|
||||
length * elementSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
return;
|
||||
}
|
||||
|
||||
t->exception = makeArrayStoreException(t);
|
||||
}
|
||||
|
||||
jarray
|
||||
@ -100,7 +167,6 @@ start(Thread* t, jobject this_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
populate(Thread* t, object map)
|
||||
{
|
||||
@ -110,8 +176,16 @@ populate(Thread* t, object map)
|
||||
} builtins[] = {
|
||||
{ "Java_java_lang_Object_toString",
|
||||
reinterpret_cast<void*>(toString) },
|
||||
{ "Java_java_lang_Object_wait",
|
||||
reinterpret_cast<void*>(wait) },
|
||||
{ "Java_java_lang_Object_notify",
|
||||
reinterpret_cast<void*>(notify) },
|
||||
{ "Java_java_lang_Object_notifyAll",
|
||||
reinterpret_cast<void*>(notifyAll) },
|
||||
{ "Java_java_lang_System_loadLibrary",
|
||||
reinterpret_cast<void*>(loadLibrary) },
|
||||
{ "Java_java_lang_System_arraycopy",
|
||||
reinterpret_cast<void*>(arraycopy) },
|
||||
{ "Java_java_lang_Throwable_trace",
|
||||
reinterpret_cast<void*>(trace) },
|
||||
{ "Java_java_lang_Thread_start",
|
||||
|
@ -235,18 +235,19 @@ enum Constant {
|
||||
CONSTANT_Utf8 = 1
|
||||
};
|
||||
|
||||
const unsigned ACC_PUBLIC = 1 << 0;
|
||||
const unsigned ACC_PRIVATE = 1 << 1;
|
||||
const unsigned ACC_PROTECTED = 1 << 2;
|
||||
const unsigned ACC_STATIC = 1 << 3;
|
||||
const unsigned ACC_FINAL = 1 << 4;
|
||||
const unsigned ACC_SUPER = 1 << 5;
|
||||
const unsigned ACC_VOLATILE = 1 << 6;
|
||||
const unsigned ACC_TRANSIENT = 1 << 7;
|
||||
const unsigned ACC_NATIVE = 1 << 8;
|
||||
const unsigned ACC_INTERFACE = 1 << 9;
|
||||
const unsigned ACC_ABSTRACT = 1 << 10;
|
||||
const unsigned ACC_STRICT = 1 << 11;
|
||||
const unsigned ACC_PUBLIC = 1 << 0;
|
||||
const unsigned ACC_PRIVATE = 1 << 1;
|
||||
const unsigned ACC_PROTECTED = 1 << 2;
|
||||
const unsigned ACC_STATIC = 1 << 3;
|
||||
const unsigned ACC_FINAL = 1 << 4;
|
||||
const unsigned ACC_SUPER = 1 << 5;
|
||||
const unsigned ACC_SYNCHRONIZED = ACC_SUPER;
|
||||
const unsigned ACC_VOLATILE = 1 << 6;
|
||||
const unsigned ACC_TRANSIENT = 1 << 7;
|
||||
const unsigned ACC_NATIVE = 1 << 8;
|
||||
const unsigned ACC_INTERFACE = 1 << 9;
|
||||
const unsigned ACC_ABSTRACT = 1 << 10;
|
||||
const unsigned ACC_STRICT = 1 << 11;
|
||||
|
||||
} // namespace vm
|
||||
|
||||
|
@ -36,6 +36,14 @@ ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
|
||||
t->vm->system->free(chars);
|
||||
}
|
||||
|
||||
jstring
|
||||
NewStringUTF(Thread* t, const char* chars)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeString(t, "%s", chars));
|
||||
}
|
||||
|
||||
void
|
||||
populate(JNIEnvVTable* table)
|
||||
{
|
||||
@ -44,6 +52,7 @@ populate(JNIEnvVTable* table)
|
||||
table->GetStringUTFLength = GetStringUTFLength;
|
||||
table->GetStringUTFChars = GetStringUTFChars;
|
||||
table->ReleaseStringUTFChars = ReleaseStringUTFChars;
|
||||
table->NewStringUTF = NewStringUTF;
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
107
src/machine.cpp
107
src/machine.cpp
@ -6,45 +6,6 @@ using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
visitRoots(Thread* t, Heap::Visitor* v)
|
||||
{
|
||||
if (t->state != Thread::ZombieState) {
|
||||
t->heapIndex = 0;
|
||||
|
||||
v->visit(&(t->javaThread));
|
||||
v->visit(&(t->code));
|
||||
v->visit(&(t->exception));
|
||||
|
||||
for (unsigned i = 0; i < t->sp; ++i) {
|
||||
if (t->stack[i * 2] == ObjectTag) {
|
||||
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
||||
}
|
||||
}
|
||||
|
||||
for (Thread::Protector* p = t->protector; p; p = p->next) {
|
||||
v->visit(p->p);
|
||||
}
|
||||
}
|
||||
|
||||
for (Thread* c = t->child; c; c = c->peer) {
|
||||
visitRoots(c, v);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
postCollect(Thread* t)
|
||||
{
|
||||
if (t->large) {
|
||||
t->vm->system->free(t->large);
|
||||
t->large = 0;
|
||||
}
|
||||
|
||||
for (Thread* c = t->child; c; c = c->peer) {
|
||||
postCollect(c);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
find(Thread* t, Thread* o)
|
||||
{
|
||||
@ -140,6 +101,45 @@ killZombies(Thread* t, Thread* o)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
visitRoots(Thread* t, Heap::Visitor* v)
|
||||
{
|
||||
if (t->state != Thread::ZombieState) {
|
||||
t->heapIndex = 0;
|
||||
|
||||
v->visit(&(t->javaThread));
|
||||
v->visit(&(t->code));
|
||||
v->visit(&(t->exception));
|
||||
|
||||
for (unsigned i = 0; i < t->sp; ++i) {
|
||||
if (t->stack[i * 2] == ObjectTag) {
|
||||
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
||||
}
|
||||
}
|
||||
|
||||
for (Thread::Protector* p = t->protector; p; p = p->next) {
|
||||
v->visit(p->p);
|
||||
}
|
||||
}
|
||||
|
||||
for (Thread* c = t->child; c; c = c->peer) {
|
||||
visitRoots(c, v);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
postCollect(Thread* t)
|
||||
{
|
||||
if (t->large) {
|
||||
t->vm->system->free(t->large);
|
||||
t->large = 0;
|
||||
}
|
||||
|
||||
for (Thread* c = t->child; c; c = c->peer) {
|
||||
postCollect(c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
collect(Thread* t, Heap::CollectionType type)
|
||||
{
|
||||
@ -174,13 +174,8 @@ collect(Thread* t, Heap::CollectionType type)
|
||||
}
|
||||
}
|
||||
|
||||
for (object* f = &(m->finalizers); *f; f = &finalizerNext(t, *f)) {
|
||||
v->visit(f);
|
||||
}
|
||||
|
||||
for (object* f = &(m->doomed); *f; f = &finalizerNext(t, *f)) {
|
||||
v->visit(f);
|
||||
}
|
||||
v->visit(&(m->finalizers));
|
||||
v->visit(&(m->doomed));
|
||||
|
||||
for (object p = m->weakReferences; p;) {
|
||||
object o = jreferenceTarget(t, p);
|
||||
@ -193,8 +188,8 @@ collect(Thread* t, Heap::CollectionType type)
|
||||
}
|
||||
|
||||
object last = p;
|
||||
p = weakReferenceNext(t, p);
|
||||
weakReferenceNext(t, last) = 0;
|
||||
p = jreferenceNext(t, p);
|
||||
jreferenceNext(t, last) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,13 +228,16 @@ collect(Thread* t, Heap::CollectionType type)
|
||||
memcpy(dst, o, n * BytesPerWord);
|
||||
|
||||
if (hashTaken(t, o)) {
|
||||
extendedWord(t, dst, base) = takeHash(t, o);
|
||||
cast<uintptr_t>(dst, 0) &= PointerMask;
|
||||
cast<uintptr_t>(dst, 0) |= ExtendedMark;
|
||||
extendedWord(t, dst, base) = takeHash(t, o);
|
||||
}
|
||||
|
||||
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
||||
weakReferenceNext(t, dst) = m->weakReferences;
|
||||
fprintf(stderr, "weak reference to %p at %p\n",
|
||||
jreferenceTarget(t, dst),
|
||||
&jreferenceTarget(t, dst));
|
||||
jreferenceNext(t, dst) = m->weakReferences;
|
||||
m->weakReferences = dst;
|
||||
}
|
||||
}
|
||||
@ -255,7 +253,6 @@ collect(Thread* t, Heap::CollectionType type)
|
||||
// fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n",
|
||||
// p, class_, objectMask, intArrayLength(t, objectMask));
|
||||
|
||||
unsigned vmFlags = classVmFlags(t, class_);
|
||||
unsigned fixedSize = classFixedSize(t, class_);
|
||||
unsigned arrayElementSize = classArrayElementSize(t, class_);
|
||||
unsigned arrayLength
|
||||
@ -275,9 +272,7 @@ collect(Thread* t, Heap::CollectionType type)
|
||||
= divide(arrayElementSize, BytesPerWord);
|
||||
|
||||
for (unsigned i = 0; i < fixedSizeInWords; ++i) {
|
||||
if ((i != 1 or (vmFlags & WeakReferenceFlag) == 0)
|
||||
and mask[wordOf(i)] & (static_cast<uintptr_t>(1) << bitOf(i)))
|
||||
{
|
||||
if (mask[wordOf(i)] & (static_cast<uintptr_t>(1) << bitOf(i))) {
|
||||
if (not w->visit(i)) {
|
||||
return;
|
||||
}
|
||||
@ -322,7 +317,7 @@ collect(Thread* t, Heap::CollectionType type)
|
||||
|
||||
postCollect(m->rootThread);
|
||||
|
||||
for (object f = m->doomed; f; f = tripleThird(t, f)) {
|
||||
for (object f = m->doomed; f; f = finalizerNext(t, f)) {
|
||||
reinterpret_cast<void (*)(Thread*, object)>(finalizerFinalize(t, f))
|
||||
(t, finalizerTarget(t, f));
|
||||
}
|
||||
@ -451,6 +446,8 @@ Thread::Thread(Machine* m, Allocator* allocator, object javaThread,
|
||||
|
||||
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
||||
set(t, cast<object>(intArrayClass, 0), classClass);
|
||||
set(t, classSuper(t, intArrayClass),
|
||||
arrayBody(t, m->types, Machine::JobjectType));
|
||||
|
||||
m->unsafe = false;
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace vm {
|
||||
const bool Verbose = false;
|
||||
const bool Debug = false;
|
||||
const bool DebugRun = true;
|
||||
const bool DebugStack = false;
|
||||
const bool DebugStack = true;
|
||||
|
||||
const uintptr_t HashTakenMark = 1;
|
||||
const uintptr_t ExtendedMark = 2;
|
||||
@ -1311,6 +1311,12 @@ makeIllegalStateException(Thread* t, object message)
|
||||
return makeIllegalStateException(t, message, trace, 0);
|
||||
}
|
||||
|
||||
inline object
|
||||
makeIllegalMonitorStateException(Thread* t)
|
||||
{
|
||||
return makeIllegalMonitorStateException(t, 0, makeTrace(t), 0);
|
||||
}
|
||||
|
||||
inline object
|
||||
makeArrayIndexOutOfBoundsException(Thread* t, object message)
|
||||
{
|
||||
@ -1320,11 +1326,17 @@ makeArrayIndexOutOfBoundsException(Thread* t, object message)
|
||||
}
|
||||
|
||||
inline object
|
||||
makeNegativeArrayStoreException(Thread* t, object message)
|
||||
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 makeNegativeArrayStoreException(t, message, trace, 0);
|
||||
return makeNegativeArraySizeException(t, message, trace, 0);
|
||||
}
|
||||
|
||||
inline object
|
||||
@ -1535,7 +1547,7 @@ pokeLong(Thread* t, unsigned index, uint64_t value)
|
||||
}
|
||||
|
||||
pokeInt(t, index, value >> 32);
|
||||
pokeInt(t, index + 2, value & 0xFF);
|
||||
pokeInt(t, index + 1, value & 0xFF);
|
||||
}
|
||||
|
||||
inline object*
|
||||
@ -1807,6 +1819,56 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
||||
System::Monitor*
|
||||
objectMonitor(Thread* t, object o);
|
||||
|
||||
inline void
|
||||
acquire(Thread* t, object o)
|
||||
{
|
||||
System::Monitor* m = objectMonitor(t, o);
|
||||
if (not m->tryAcquire(t)) {
|
||||
ENTER(t, Thread::IdleState);
|
||||
m->acquire(t);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
release(Thread* t, object o)
|
||||
{
|
||||
objectMonitor(t, o)->release(t);
|
||||
}
|
||||
|
||||
inline void
|
||||
wait(Thread* t, object o, int64_t milliseconds)
|
||||
{
|
||||
System::Monitor* m = objectMonitor(t, o);
|
||||
if (m->owner() == t) {
|
||||
ENTER(t, Thread::IdleState);
|
||||
m->wait(t, milliseconds);
|
||||
} else {
|
||||
t->exception = makeIllegalMonitorStateException(t);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
notify(Thread* t, object o)
|
||||
{
|
||||
System::Monitor* m = objectMonitor(t, o);
|
||||
if (m->owner() == t) {
|
||||
m->notify(t);
|
||||
} else {
|
||||
t->exception = makeIllegalMonitorStateException(t);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
notifyAll(Thread* t, object o)
|
||||
{
|
||||
System::Monitor* m = objectMonitor(t, o);
|
||||
if (m->owner() == t) {
|
||||
m->notifyAll(t);
|
||||
} else {
|
||||
t->exception = makeIllegalMonitorStateException(t);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exit(Thread* t);
|
||||
|
||||
|
@ -227,6 +227,10 @@ class System: public vm::System {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void* owner() {
|
||||
return context;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
pthread_mutex_destroy(&mutex);
|
||||
pthread_cond_destroy(&condition);
|
||||
|
113
src/run.cpp
113
src/run.cpp
@ -42,11 +42,30 @@ pushFrame(Thread* t, object method)
|
||||
|
||||
pokeInt(t, frame + FrameBaseOffset, base);
|
||||
pokeObject(t, frame + FrameMethodOffset, method);
|
||||
pokeInt(t, t->frame + FrameIpOffset, 0);
|
||||
|
||||
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
||||
if (methodFlags(t, method) & ACC_STATIC) {
|
||||
acquire(t, methodClass(t, method));
|
||||
} else {
|
||||
acquire(t, peekObject(t, base));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
popFrame(Thread* t)
|
||||
{
|
||||
object method = frameMethod(t, t->frame);
|
||||
|
||||
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
||||
if (methodFlags(t, method) & ACC_STATIC) {
|
||||
release(t, methodClass(t, method));
|
||||
} else {
|
||||
release(t, peekObject(t, frameBase(t, t->frame)));
|
||||
}
|
||||
}
|
||||
|
||||
t->sp = frameBase(t, t->frame);
|
||||
t->frame = frameNext(t, t->frame);
|
||||
if (t->frame >= 0) {
|
||||
@ -1214,10 +1233,20 @@ resolveClass(Thread* t, object spec)
|
||||
|
||||
hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash);
|
||||
} else {
|
||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
t->exception = makeClassNotFoundException(t, message);
|
||||
class_ = hashMapFind
|
||||
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||
|
||||
if (class_ == 0) {
|
||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
t->exception = makeClassNotFoundException(t, message);
|
||||
}
|
||||
}
|
||||
|
||||
if (class_) {
|
||||
hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash);
|
||||
}
|
||||
}
|
||||
|
||||
return class_;
|
||||
}
|
||||
|
||||
@ -1452,6 +1481,12 @@ invokeNative(Thread* t, object method)
|
||||
enter(t, Thread::IdleState);
|
||||
}
|
||||
|
||||
if (DebugRun) {
|
||||
fprintf(stderr, "invoke native method %s.%s\n",
|
||||
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
||||
&byteArrayBody(t, methodName(t, method), 0));
|
||||
}
|
||||
|
||||
uint64_t result = t->vm->system->call
|
||||
(function,
|
||||
args,
|
||||
@ -1460,6 +1495,14 @@ invokeNative(Thread* t, object method)
|
||||
size,
|
||||
returnType);
|
||||
|
||||
if (DebugRun) {
|
||||
fprintf(stderr, "return from native method %s.%s\n",
|
||||
&byteArrayBody
|
||||
(t, className(t, methodClass(t, frameMethod(t, t->frame))), 0),
|
||||
&byteArrayBody
|
||||
(t, methodName(t, frameMethod(t, t->frame)), 0));
|
||||
}
|
||||
|
||||
if (not builtin) {
|
||||
enter(t, oldState);
|
||||
}
|
||||
@ -1477,15 +1520,26 @@ invokeNative(Thread* t, object method)
|
||||
case ShortField:
|
||||
case FloatField:
|
||||
case IntField:
|
||||
if (DebugRun) {
|
||||
fprintf(stderr, "result: " LLD "\n", result);
|
||||
}
|
||||
pushInt(t, result);
|
||||
break;
|
||||
|
||||
case LongField:
|
||||
case DoubleField:
|
||||
if (DebugRun) {
|
||||
fprintf(stderr, "result: " LLD "\n", result);
|
||||
}
|
||||
pushLong(t, result);
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
if (DebugRun) {
|
||||
fprintf(stderr, "result: %p at %p\n", result == 0 ? 0 :
|
||||
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)),
|
||||
reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
||||
}
|
||||
pushObject(t, result == 0 ? 0 :
|
||||
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
||||
break;
|
||||
@ -1622,28 +1676,19 @@ run(Thread* t)
|
||||
pushObject(t, array);
|
||||
} else {
|
||||
object message = makeString(t, "%d", count);
|
||||
exception = makeNegativeArrayStoreException(t, message);
|
||||
exception = makeNegativeArraySizeException(t, message);
|
||||
goto throw_;
|
||||
}
|
||||
} goto loop;
|
||||
|
||||
case areturn:
|
||||
case ireturn:
|
||||
case lreturn: {
|
||||
case areturn: {
|
||||
object result = popObject(t);
|
||||
popFrame(t);
|
||||
if (frame >= 0) {
|
||||
pushObject(t, result);
|
||||
goto loop;
|
||||
} else {
|
||||
switch (instruction) {
|
||||
case areturn:
|
||||
return popObject(t);
|
||||
|
||||
case ireturn:
|
||||
return makeInt(t, popInt(t));
|
||||
|
||||
case lreturn:
|
||||
return makeLong(t, popLong(t));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} goto loop;
|
||||
|
||||
@ -1655,14 +1700,14 @@ run(Thread* t)
|
||||
{
|
||||
pushInt(t, objectArrayLength(t, array));
|
||||
} else {
|
||||
// for all other array types, the length follow the class pointer.
|
||||
// for all other array types, the length follows the class pointer.
|
||||
pushInt(t, cast<uint32_t>(array, BytesPerWord));
|
||||
}
|
||||
} else {
|
||||
exception = makeNullPointerException(t);
|
||||
goto throw_;
|
||||
}
|
||||
} abort(t);
|
||||
} goto loop;
|
||||
|
||||
case astore: {
|
||||
setLocalObject(t, codeBody(t, code, ip++), popObject(t));
|
||||
@ -2168,7 +2213,7 @@ run(Thread* t)
|
||||
int32_t b = popInt(t);
|
||||
int32_t a = popInt(t);
|
||||
|
||||
if (a < b) {
|
||||
if (a <= b) {
|
||||
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
||||
}
|
||||
} goto loop;
|
||||
@ -2405,6 +2450,17 @@ run(Thread* t)
|
||||
pushInt(t, a % b);
|
||||
} goto loop;
|
||||
|
||||
case ireturn: {
|
||||
int32_t result = popInt(t);
|
||||
popFrame(t);
|
||||
if (frame >= 0) {
|
||||
pushInt(t, result);
|
||||
goto loop;
|
||||
} else {
|
||||
return makeInt(t, result);
|
||||
}
|
||||
} goto loop;
|
||||
|
||||
case ishl: {
|
||||
int32_t b = popInt(t);
|
||||
int32_t a = popInt(t);
|
||||
@ -2480,7 +2536,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case l2i: {
|
||||
pushLong(t, static_cast<int32_t>(popLong(t)));
|
||||
pushInt(t, static_cast<int32_t>(popLong(t)));
|
||||
} goto loop;
|
||||
|
||||
case ladd: {
|
||||
@ -2649,6 +2705,17 @@ run(Thread* t)
|
||||
pushLong(t, a % b);
|
||||
} goto loop;
|
||||
|
||||
case lreturn: {
|
||||
int64_t result = popLong(t);
|
||||
popFrame(t);
|
||||
if (frame >= 0) {
|
||||
pushLong(t, result);
|
||||
goto loop;
|
||||
} else {
|
||||
return makeLong(t, result);
|
||||
}
|
||||
} goto loop;
|
||||
|
||||
case lshl: {
|
||||
int64_t b = popLong(t);
|
||||
int64_t a = popLong(t);
|
||||
@ -2707,7 +2774,7 @@ run(Thread* t)
|
||||
case monitorenter: {
|
||||
object o = popObject(t);
|
||||
if (LIKELY(o)) {
|
||||
objectMonitor(t, o)->acquire(t);
|
||||
acquire(t, o);
|
||||
} else {
|
||||
exception = makeNullPointerException(t);
|
||||
goto throw_;
|
||||
@ -2717,7 +2784,7 @@ run(Thread* t)
|
||||
case monitorexit: {
|
||||
object o = popObject(t);
|
||||
if (LIKELY(o)) {
|
||||
objectMonitor(t, o)->release(t);
|
||||
release(t, o);
|
||||
} else {
|
||||
exception = makeNullPointerException(t);
|
||||
goto throw_;
|
||||
@ -2790,7 +2857,7 @@ run(Thread* t)
|
||||
pushObject(t, array);
|
||||
} else {
|
||||
object message = makeString(t, "%d", count);
|
||||
exception = makeNegativeArrayStoreException(t, message);
|
||||
exception = makeNegativeArraySizeException(t, message);
|
||||
goto throw_;
|
||||
}
|
||||
} goto loop;
|
||||
|
@ -40,6 +40,7 @@ class System: public Allocator {
|
||||
virtual void wait(void* context, int64_t time) = 0;
|
||||
virtual void notify(void* context) = 0;
|
||||
virtual void notifyAll(void* context) = 0;
|
||||
virtual void* owner() = 0;
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
|
@ -1475,23 +1475,11 @@ writeInitialization(Output* out, Object* type)
|
||||
out->write(" object mask = 0;\n");
|
||||
}
|
||||
|
||||
if (typeJavaName(type)) {
|
||||
if (typeObjectMask(type) != 1) {
|
||||
out->write(" PROTECT(t, mask);\n");
|
||||
}
|
||||
out->write(" object name = ::makeByteArray(t, \"");
|
||||
out->write(typeJavaName(type));
|
||||
out->write("\");\n");
|
||||
|
||||
if (typeSuper(type)) {
|
||||
out->write(" object super = arrayBody(t, t->vm->types, Machine::");
|
||||
out->write(capitalize(typeName(typeSuper(type))));
|
||||
out->write("Type);\n");
|
||||
} else {
|
||||
out->write(" object super = 0;\n");
|
||||
}
|
||||
if (typeJavaName(type) and typeSuper(type)) {
|
||||
out->write(" object super = arrayBody(t, t->vm->types, Machine::");
|
||||
out->write(capitalize(typeName(typeSuper(type))));
|
||||
out->write("Type);\n");
|
||||
} else {
|
||||
out->write(" object name = 0;\n");
|
||||
out->write(" object super = 0;\n");
|
||||
}
|
||||
|
||||
@ -1500,17 +1488,12 @@ writeInitialization(Output* out, Object* type)
|
||||
out->write(typeFixedSize(type));
|
||||
out->write(", ");
|
||||
out->write(typeArrayElementSize(type));
|
||||
out->write(", mask, name, super, 0, 0, 0, 0, 0, 0);\n");
|
||||
out->write(", mask, 0, super, 0, 0, 0, 0, 0, 0);\n");
|
||||
|
||||
out->write(" set(t, arrayBody(t, t->vm->types, Machine::");
|
||||
out->write(capitalize(typeName(type)));
|
||||
out->write("Type), class_);\n");
|
||||
|
||||
if (typeJavaName(type)) {
|
||||
out->write(" hashMapInsert(t, t->vm->bootstrapClassMap, ");
|
||||
out->write("className(t, class_), class_, byteArrayHash);\n");
|
||||
}
|
||||
|
||||
out->write("}\n\n");
|
||||
}
|
||||
|
||||
@ -1549,10 +1532,38 @@ writeInitializations(Output* out, Object* declarations)
|
||||
|
||||
for (Object* p = declarations; p; p = cdr(p)) {
|
||||
Object* o = car(p);
|
||||
if (o->type == Object::Type and typeJavaName(o) == 0) {
|
||||
if (o->type == Object::Type and equal(typeName(o), "intArray")) {
|
||||
writeInitialization(out, o);
|
||||
}
|
||||
}
|
||||
|
||||
for (Object* p = declarations; p; p = cdr(p)) {
|
||||
Object* o = car(p);
|
||||
if (o->type == Object::Type and not equal(typeName(o), "intArray")) {
|
||||
writeInitialization(out, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeJavaInitialization(Output* out, Object* type)
|
||||
{
|
||||
out->write("{\n");
|
||||
|
||||
out->write(" object name = ::makeByteArray(t, \"");
|
||||
out->write(typeJavaName(type));
|
||||
out->write("\");\n");
|
||||
|
||||
out->write(" object class_ = arrayBody(t, t->vm->types, Machine::");
|
||||
out->write(capitalize(typeName(type)));
|
||||
out->write("Type);\n");
|
||||
|
||||
out->write(" set(t, className(t, class_), name);\n");
|
||||
|
||||
out->write(" hashMapInsert(t, t->vm->bootstrapClassMap, ");
|
||||
out->write("name, class_, byteArrayHash);\n");
|
||||
|
||||
out->write("}\n\n");
|
||||
}
|
||||
|
||||
void
|
||||
@ -1561,7 +1572,7 @@ writeJavaInitializations(Output* out, Object* declarations)
|
||||
for (Object* p = declarations; p; p = cdr(p)) {
|
||||
Object* o = car(p);
|
||||
if (o->type == Object::Type and typeJavaName(o)) {
|
||||
writeInitialization(out, o);
|
||||
writeJavaInitialization(out, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1570,7 +1581,8 @@ void
|
||||
usageAndExit(const char* command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s {enums,declarations,constructors,initializations}\n",
|
||||
"usage: %s {enums,declarations,constructors,initializations,"
|
||||
"java-initializations}\n",
|
||||
command);
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
(type intArray
|
||||
(array int32_t body))
|
||||
|
||||
(type class
|
||||
(uint16_t flags)
|
||||
(uint16_t vmFlags)
|
||||
@ -108,31 +105,6 @@
|
||||
(type array
|
||||
(noassert array object body))
|
||||
|
||||
(type objectArray
|
||||
(object elementClass)
|
||||
(array object body))
|
||||
|
||||
(type byteArray
|
||||
(array int8_t body))
|
||||
|
||||
(type booleanArray
|
||||
(array int8_t body))
|
||||
|
||||
(type shortArray
|
||||
(array int16_t body))
|
||||
|
||||
(type charArray
|
||||
(array uint16_t body))
|
||||
|
||||
(type longArray
|
||||
(array int64_t body))
|
||||
|
||||
(type floatArray
|
||||
(array uint32_t body))
|
||||
|
||||
(type doubleArray
|
||||
(array uint64_t body))
|
||||
|
||||
|
||||
(type jobject java/lang/Object)
|
||||
|
||||
@ -166,11 +138,17 @@
|
||||
(type illegalStateException java/lang/IllegalStateException
|
||||
(extends runtimeException))
|
||||
|
||||
(type illegalMonitorStateException java/lang/IllegalMonitorStateException
|
||||
(extends runtimeException))
|
||||
|
||||
(type arrayIndexOutOfBoundsException
|
||||
java/lang/ArrayIndexOutOfBoundsException
|
||||
(extends runtimeException))
|
||||
|
||||
(type negativeArrayStoreException java/lang/NegativeArrayStoreException
|
||||
(type arrayStoreException java/lang/arrayStoreException
|
||||
(extends runtimeException))
|
||||
|
||||
(type negativeArraySizeException java/lang/NegativeArraySizeException
|
||||
(extends runtimeException))
|
||||
|
||||
(type classCastException java/lang/ClassCastException
|
||||
@ -228,8 +206,45 @@
|
||||
|
||||
(type jreference java/lang/ref/Reference
|
||||
(extends jobject)
|
||||
(object target))
|
||||
(void* target)
|
||||
(void* next))
|
||||
|
||||
(type weakReference java/lang/ref/WeakReference
|
||||
(extends jreference)
|
||||
(object next))
|
||||
(extends jreference))
|
||||
|
||||
(type objectArray [
|
||||
(extends jobject)
|
||||
(object elementClass)
|
||||
(array object body))
|
||||
|
||||
(type byteArray [B
|
||||
(extends jobject)
|
||||
(array int8_t body))
|
||||
|
||||
(type booleanArray [Z
|
||||
(extends jobject)
|
||||
(array int8_t body))
|
||||
|
||||
(type shortArray [S
|
||||
(extends jobject)
|
||||
(array int16_t body))
|
||||
|
||||
(type charArray [C
|
||||
(extends jobject)
|
||||
(array uint16_t body))
|
||||
|
||||
(type intArray [I
|
||||
(extends jobject)
|
||||
(array int32_t body))
|
||||
|
||||
(type longArray [J
|
||||
(extends jobject)
|
||||
(array int64_t body))
|
||||
|
||||
(type floatArray [F
|
||||
(extends jobject)
|
||||
(array uint32_t body))
|
||||
|
||||
(type doubleArray [D
|
||||
(extends jobject)
|
||||
(array uint64_t body))
|
||||
|
Loading…
Reference in New Issue
Block a user