misc. bugfixes and tweaks

This commit is contained in:
Joel Dice 2007-07-28 10:10:13 -06:00
parent 363801af1c
commit 41bee5829e
12 changed files with 228 additions and 141 deletions

View File

@ -1,3 +1,6 @@
#include "sys/time.h"
#include "time.h"
#include "time.h"
#include "string.h"
#include "jni.h"
@ -19,3 +22,12 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring key)
return value;
}
extern "C" JNIEXPORT jlong JNICALL
Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass)
{
timeval tv = { 0, 0 };
gettimeofday(&tv, 0);
return (static_cast<jlong>(tv.tv_sec) * 1000) +
(static_cast<jlong>(tv.tv_usec) / 1000);
}

View File

@ -19,7 +19,6 @@ public final class Class <T> {
private Field[] fieldTable;
private Method[] methodTable;
private Object[] staticTable;
private Method initializer;
private Class() { }
@ -32,9 +31,11 @@ public final class Class <T> {
public native boolean isAssignableFrom(Class c);
private Field findField(String name) {
for (int i = 0; i < fieldTable.length; ++i) {
if (fieldTable[i].getName().equals(name)) {
return fieldTable[i];
if (fieldTable != null) {
for (int i = 0; i < fieldTable.length; ++i) {
if (fieldTable[i].getName().equals(name)) {
return fieldTable[i];
}
}
}
return null;
@ -73,11 +74,13 @@ public final class Class <T> {
}
private Method findMethod(String name, Class[] parameterTypes) {
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals(name)
&& match(parameterTypes, methodTable[i].getParameterTypes()))
{
return methodTable[i];
if (methodTable != null) {
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals(name)
&& match(parameterTypes, methodTable[i].getParameterTypes()))
{
return methodTable[i];
}
}
}
return null;
@ -125,12 +128,14 @@ public final class Class <T> {
private int countConstructors(boolean publicOnly) {
int count = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((! publicOnly)
|| ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0)
&& methodTable[i].getName().equals("<init>"))
{
++ count;
if (methodTable != null) {
for (int i = 0; i < methodTable.length; ++i) {
if (((! publicOnly)
|| ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0)
&& methodTable[i].getName().equals("<init>"))
{
++ count;
}
}
}
return count;
@ -138,10 +143,12 @@ public final class Class <T> {
public Constructor[] getDeclaredConstructors() {
Constructor[] array = new Constructor[countConstructors(false)];
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals("<init>")) {
array[index++] = new Constructor(methodTable[i]);
if (methodTable != null) {
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals("<init>")) {
array[index++] = new Constructor(methodTable[i]);
}
}
}
@ -150,12 +157,14 @@ public final class Class <T> {
public Constructor[] getConstructors() {
Constructor[] array = new Constructor[countConstructors(true)];
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& methodTable[i].getName().equals("<init>"))
{
array[index++] = new Constructor(methodTable[i]);
if (methodTable != null) {
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& methodTable[i].getName().equals("<init>"))
{
array[index++] = new Constructor(methodTable[i]);
}
}
}
@ -163,16 +172,22 @@ public final class Class <T> {
}
public Field[] getDeclaredFields() {
Field[] array = new Field[fieldTable.length];
System.arraycopy(fieldTable, 0, array, 0, fieldTable.length);
return array;
if (fieldTable != null) {
Field[] array = new Field[fieldTable.length];
System.arraycopy(fieldTable, 0, array, 0, fieldTable.length);
return array;
} else {
return new Field[0];
}
}
private int countPublicFields() {
int count = 0;
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
++ count;
if (fieldTable != null) {
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
++ count;
}
}
}
return count;
@ -180,9 +195,11 @@ public final class Class <T> {
public Field[] getFields() {
Field[] array = new Field[countPublicFields()];
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
array[i] = fieldTable[i];
if (fieldTable != null) {
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
array[i] = fieldTable[i];
}
}
}
return array;
@ -203,10 +220,12 @@ public final class Class <T> {
public Method[] getDeclaredMethods() {
Method[] array = new Method[countMethods(false)];
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (! methodTable[i].getName().startsWith("<")) {
array[index++] = methodTable[i];
if (methodTable != null) {
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (! methodTable[i].getName().startsWith("<")) {
array[index++] = methodTable[i];
}
}
}
@ -215,12 +234,14 @@ public final class Class <T> {
public Method[] getMethods() {
Method[] array = new Method[countMethods(true)];
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& (! methodTable[i].getName().startsWith("<")))
{
array[index++] = methodTable[i];
if (methodTable != null) {
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& (! methodTable[i].getName().startsWith("<")))
{
array[index++] = methodTable[i];
}
}
}
@ -228,11 +249,15 @@ public final class Class <T> {
}
public Class[] getInterfaces() {
Class[] array = new Class[interfaceTable.length / 2];
for (int i = 0; i < array.length; ++i) {
array[i] = (Class) interfaceTable[i * 2];
if (interfaceTable != null) {
Class[] array = new Class[interfaceTable.length / 2];
for (int i = 0; i < array.length; ++i) {
array[i] = (Class) interfaceTable[i * 2];
}
return array;
} else {
return new Class[0];
}
return array;
}
public ClassLoader getClassLoader() {

View File

@ -6,6 +6,7 @@ import java.util.WeakHashMap;
public class Thread implements Runnable {
private final Runnable task;
private Map<ThreadLocal, Object> locals;
private Object sleepLock;
private long peer;
public Thread(Runnable task) {
@ -17,7 +18,8 @@ public class Thread implements Runnable {
if (map != null) {
for (Map.Entry<ThreadLocal, Object> e: map.entrySet()) {
if (e.getKey() instanceof InheritableThreadLocal) {
locals().put(e.getKey(), e.getValue());
InheritableThreadLocal itl = (InheritableThreadLocal) e.getKey();
locals().put(itl, itl.childValue(e.getValue()));
}
}
}
@ -42,6 +44,13 @@ public class Thread implements Runnable {
public static native Thread currentThread();
public static native void sleep(long milliseconds)
throws InterruptedException;
public static void sleep(long milliseconds) throws InterruptedException {
Thread t = currentThread();
if (t.sleepLock == null) {
t.sleepLock = new Object();
}
synchronized (t.sleepLock) {
t.sleepLock.wait(milliseconds);
}
}
}

View File

@ -16,7 +16,7 @@ src = src
classpath = classpath
test = test
input = $(cls)/Reflection.class
input = $(cls)/Threads.class
cxx = g++
cc = gcc

View File

@ -73,12 +73,11 @@ Class_forName(Thread* t, jclass, jstring name)
return 0;
}
object clinit = classInitializer(t, c);
if (clinit) {
if (classVmFlags(t, c) & NeedInitFlag) {
PROTECT(t, c);
set(t, classInitializer(t, c), 0);
run(t, clinit, 0);
classVmFlags(t, c) &= ~NeedInitFlag;
run(t, classInitializer(t, c), 0);
}
return pushReference(t, c);
@ -105,9 +104,36 @@ Field_get(Thread* t, jobject this_, jobject instancep)
object field = *this_;
if (fieldFlags(t, field) & ACC_STATIC) {
return pushReference
(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)),
fieldOffset(t, field)));
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
fieldOffset(t, field));
switch (fieldCode(t, field)) {
case ByteField:
return pushReference(t, makeByte(t, intValue(t, v)));
case BooleanField:
return pushReference(t, makeBoolean(t, intValue(t, v)));
case CharField:
return pushReference(t, makeChar(t, intValue(t, v)));
case ShortField:
return pushReference(t, makeShort(t, intValue(t, v)));
case FloatField:
return pushReference(t, makeFloat(t, intValue(t, v)));
case DoubleField:
return pushReference(t, makeDouble(t, longValue(t, v)));
case IntField:
case LongField:
case ObjectField:
return pushReference(t, v);
default:
abort(t);
}
} else if (instancep) {
object instance = *instancep;
@ -169,9 +195,44 @@ Field_set(Thread* t, jobject this_, jobject instancep, jobject value)
object v = (value ? *value : 0);
if (fieldFlags(t, field) & ACC_STATIC) {
object* p = &arrayBody(t, classStaticTable(t, fieldClass(t, field)),
fieldOffset(t, field));
if (fieldCode(t, field) == ObjectField or v) {
set(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)),
fieldOffset(t, field)), v);
switch (fieldCode(t, field)) {
case ByteField:
set(t, *p, makeInt(t, byteValue(t, v)));
break;
case BooleanField:
set(t, *p, makeInt(t, booleanValue(t, v)));
break;
case CharField:
set(t, *p, makeInt(t, charValue(t, v)));
break;
case ShortField:
set(t, *p, makeInt(t, shortValue(t, v)));
break;
case FloatField:
set(t, *p, makeInt(t, floatValue(t, v)));
break;
case DoubleField:
set(t, *p, makeLong(t, longValue(t, v)));
break;
case IntField:
case LongField:
case ObjectField:
set(t, *p, v);
break;
default:
abort(t);
}
} else {
t->exception = makeNullPointerException(t);
}
@ -398,12 +459,6 @@ System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
t->exception = makeArrayStoreException(t);
}
jlong
System_currentTimeMillis(Thread* t, jclass)
{
return t->vm->system->now();
}
void
Runtime_loadLibrary(Thread* t, jobject, jstring name)
{
@ -516,15 +571,6 @@ Thread_currentThread(Thread* t, jclass)
return pushReference(t, t->javaThread);
}
void
Thread_sleep(Thread* t, jclass, jlong milliseconds)
{
if (milliseconds == 0) milliseconds = INT64_MAX;
ENTER(t, Thread::IdleState);
t->vm->system->sleep(milliseconds);
}
void
Thread_start(Thread* t, jobject this_)
{
@ -589,8 +635,6 @@ populateBuiltinMap(Thread* t, object map)
{ "Java_java_lang_System_arraycopy",
reinterpret_cast<void*>(::System_arraycopy) },
{ "Java_java_lang_System_currentTimeMillis",
reinterpret_cast<void*>(::System_currentTimeMillis) },
{ "Java_java_lang_Runtime_loadLibrary",
reinterpret_cast<void*>(::Runtime_loadLibrary) },
@ -603,8 +647,6 @@ populateBuiltinMap(Thread* t, object map)
reinterpret_cast<void*>(::Thread_start) },
{ "Java_java_lang_Thread_currentThread",
reinterpret_cast<void*>(::Thread_currentThread) },
{ "Java_java_lang_Thread_sleep",
reinterpret_cast<void*>(::Thread_sleep) },
{ "Java_java_lang_Throwable_resolveTrace",
reinterpret_cast<void*>(::Throwable_resolveTrace) },

View File

@ -939,7 +939,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (strcmp(reinterpret_cast<const int8_t*>("<clinit>"),
&byteArrayBody(t, methodName(t, method), 0)) == 0)
{
set(t, classInitializer(t, class_), method);
classVmFlags(t, class_) |= NeedInitFlag;
}
} else {
++ declaredVirtualCount;
@ -1096,8 +1096,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
0, // vtable
0, // fields
0, // methods
0, // static table
0); // initializer
0); // static table
PROTECT(t, class_);
unsigned super = s.read2();
@ -1107,7 +1106,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
set(t, classSuper(t, class_), sc);
classVmFlags(t, class_) |= classVmFlags(t, sc);
classVmFlags(t, class_)
|= (classVmFlags(t, sc) & (ReferenceFlag | WeakReferenceFlag));
}
parseInterfaceTable(t, s, class_, pool);
@ -1143,6 +1143,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
ENTER(t, Thread::ExclusiveState);
classFlags(t, bootstrapClass) = classFlags(t, class_);
classVmFlags(t, bootstrapClass) |= classVmFlags(t, class_);
set(t, classSuper(t, bootstrapClass), classSuper(t, class_));
set(t, classInterfaceTable(t, bootstrapClass),
@ -1151,7 +1152,6 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
set(t, classFieldTable(t, bootstrapClass), classFieldTable(t, class_));
set(t, classMethodTable(t, bootstrapClass), classMethodTable(t, class_));
set(t, classStaticTable(t, bootstrapClass), classStaticTable(t, class_));
set(t, classInitializer(t, bootstrapClass), classInitializer(t, class_));
object fieldTable = classFieldTable(t, class_);
if (fieldTable) {
@ -1186,7 +1186,6 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
classVirtualTable(t, arrayBody(t, t->vm->types, Machine::JobjectType)),
0,
0,
0,
0);
}
@ -1376,7 +1375,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
populateBuiltinMap(t, m->builtinMap);
t->javaThread = makeThread(t, 0, 0, reinterpret_cast<int64_t>(t));
t->javaThread = makeThread(t, 0, 0, 0, reinterpret_cast<int64_t>(t));
} else {
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
parent->child = this;
@ -1680,6 +1679,21 @@ instanceOf(Thread* t, object class_, object o)
}
}
object
classInitializer(Thread* t, object class_)
{
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, class_)); ++i) {
object o = arrayBody(t, classMethodTable(t, class_), i);
if (strcmp(reinterpret_cast<const int8_t*>("<clinit>"),
&byteArrayBody(t, methodName(t, o), 0)) == 0)
{
return o;
}
}
abort(t);
}
unsigned
parameterFootprint(const char* s)
{

View File

@ -22,7 +22,7 @@ namespace vm {
const bool Verbose = false;
const bool DebugRun = false;
const bool DebugStack = false;
const bool DebugMonitors = false;
const bool DebugMonitors = true;
const uintptr_t HashTakenMark = 1;
const uintptr_t ExtendedMark = 2;
@ -61,6 +61,7 @@ const int UnknownLine = -2;
const unsigned ReferenceFlag = 1 << 0;
const unsigned WeakReferenceFlag = 1 << 1;
const unsigned NeedInitFlag = 1 << 2;
class Thread;
@ -1487,6 +1488,9 @@ isAssignableFrom(Thread* t, object a, object b);
bool
instanceOf(Thread* t, object class_, object o);
object
classInitializer(Thread* t, object class_);
inline void
pushObject(Thread* t, object o)
{

View File

@ -76,13 +76,6 @@ popFrame(Thread* t)
}
}
inline void
setStatic(Thread* t, object field, object value)
{
set(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)),
fieldOffset(t, field)), value);
}
object
findInterfaceMethod(Thread* t, object method, object o)
{
@ -908,10 +901,9 @@ run(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
object clinit = classInitializer(t, fieldClass(t, field));
if (clinit) {
set(t, classInitializer(t, fieldClass(t, field)), 0);
code = clinit;
if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) {
classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag;
code = classInitializer(t, fieldClass(t, field));
ip -= 3;
goto invoke;
}
@ -1332,13 +1324,12 @@ run(Thread* t)
resolveClass(t, className(t, class_));
if (UNLIKELY(exception)) goto throw_;
object clinit = classInitializer(t, class_);
if (clinit) {
set(t, classInitializer(t, methodClass(t, method)), 0);
code = clinit;
if (classVmFlags(t, class_) & NeedInitFlag) {
classVmFlags(t, class_) &= ~NeedInitFlag;
code = classInitializer(t, class_);
ip -= 3;
goto invoke;
}
}
}
code = findMethod(t, method, class_);
@ -1361,10 +1352,9 @@ run(Thread* t)
object method = resolveMethod(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
object clinit = classInitializer(t, methodClass(t, method));
if (clinit) {
set(t, classInitializer(t, methodClass(t, method)), 0);
code = clinit;
if (classVmFlags(t, methodClass(t, method)) & NeedInitFlag) {
classVmFlags(t, methodClass(t, method)) &= ~NeedInitFlag;
code = classInitializer(t, methodClass(t, method));
ip -= 3;
goto invoke;
}
@ -1390,13 +1380,12 @@ run(Thread* t)
resolveClass(t, className(t, class_));
if (UNLIKELY(exception)) goto throw_;
object clinit = classInitializer(t, class_);
if (clinit) {
set(t, classInitializer(t, methodClass(t, method)), 0);
code = clinit;
if (classVmFlags(t, class_) & NeedInitFlag) {
classVmFlags(t, class_) &= ~NeedInitFlag;
code = classInitializer(t, class_);
ip -= 3;
goto invoke;
}
}
}
code = findMethod(t, method, class_);
@ -1774,10 +1763,9 @@ run(Thread* t)
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
object clinit = classInitializer(t, class_);
if (clinit) {
set(t, classInitializer(t, class_), 0);
code = clinit;
if (classVmFlags(t, class_) & NeedInitFlag) {
classVmFlags(t, class_) &= ~NeedInitFlag;
code = classInitializer(t, class_);
ip -= 3;
goto invoke;
}
@ -1922,10 +1910,9 @@ run(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
object clinit = classInitializer(t, fieldClass(t, field));
if (clinit) {
set(t, classInitializer(t, fieldClass(t, field)), 0);
code = clinit;
if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) {
classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag;
code = classInitializer(t, fieldClass(t, field));
ip -= 3;
goto invoke;
}

View File

@ -86,6 +86,15 @@ using namespace vm;
namespace {
int64_t
now()
{
timeval tv = { 0, 0 };
gettimeofday(&tv, 0);
return (static_cast<int64_t>(tv.tv_sec) * 1000) +
(static_cast<int64_t>(tv.tv_usec) / 1000);
}
void*
run(void* t)
{
@ -174,10 +183,10 @@ class MySystem: public System {
this->depth = 0;
this->context = 0;
if (time) {
int64_t then = s->now() + time;
int64_t then = now() + time;
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
int rv = pthread_cond_timedwait(&condition, &mutex, &ts);
assert(s, rv == 0);
assert(s, rv == 0 or rv == ETIMEDOUT);
} else {
int rv = pthread_cond_wait(&condition, &mutex);
assert(s, rv == 0);
@ -342,19 +351,6 @@ class MySystem: public System {
return 0;
}
virtual void sleep(int64_t milliseconds) {
timespec ts = { milliseconds / 1000, (milliseconds % 1000) * 1000 * 1000 };
nanosleep(&ts, 0);
}
virtual int64_t now() {
timeval tv = { 0, 0 };
gettimeofday(&tv, 0);
return (static_cast<int64_t>(tv.tv_sec) * 1000) +
(static_cast<int64_t>(tv.tv_usec) / 1000);
}
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
unsigned count, unsigned size, unsigned returnType)
{

View File

@ -60,8 +60,6 @@ class System: public Allocator {
virtual Status attach(Thread**) = 0;
virtual Status start(Runnable*) = 0;
virtual Status make(Monitor**) = 0;
virtual void sleep(int64_t milliseconds) = 0;
virtual int64_t now() = 0;
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
unsigned count, unsigned size,
unsigned returnType) = 0;

View File

@ -1488,7 +1488,7 @@ writeInitialization(Output* out, Object* type)
out->write(typeFixedSize(type));
out->write(", ");
out->write(typeArrayElementSize(type));
out->write(", mask, 0, super, 0, 0, 0, 0, 0, 0);\n");
out->write(", mask, 0, super, 0, 0, 0, 0, 0);\n");
out->write(" set(t, arrayBody(t, t->vm->types, Machine::");
out->write(capitalize(typeName(type)));

View File

@ -14,8 +14,7 @@
(object virtualTable)
(object fieldTable)
(object methodTable)
(object staticTable)
(object initializer))
(object staticTable))
(type accessibleObject java/lang/reflect/AccessibleObject
(extends jobject))
@ -128,6 +127,7 @@
(extends jobject)
(object task)
(object locals)
(object sleepLock)
(int64_t peer))
(type stackTraceElement java/lang/StackTraceElement