mirror of
https://github.com/corda/corda.git
synced 2025-01-01 02:36:44 +00:00
clean up bootstrap type generation to eliminate redundancy (broken)
This commit is contained in:
parent
bea4a73f54
commit
94e9bd0fd2
11
classpath/java/lang/ArrayStoreException.java
Normal file
11
classpath/java/lang/ArrayStoreException.java
Normal file
@ -0,0 +1,11 @@
|
||||
package java.lang;
|
||||
|
||||
public class ArrayStoreException extends RuntimeException {
|
||||
public ArrayStoreException(String message) {
|
||||
super(message, null);
|
||||
}
|
||||
|
||||
public ArrayStoreException() {
|
||||
this(null);
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ public final class Boolean implements Comparable<Boolean> {
|
||||
}
|
||||
|
||||
public static Boolean valueOf(String s) {
|
||||
Boolean.TRUE.booleanValue();
|
||||
return ("true".equals(s) ? Boolean.TRUE : Boolean.FALSE);
|
||||
}
|
||||
|
||||
|
11
classpath/java/lang/ExceptionInInitializerError.java
Normal file
11
classpath/java/lang/ExceptionInInitializerError.java
Normal file
@ -0,0 +1,11 @@
|
||||
package java.lang;
|
||||
|
||||
public class ExceptionInInitializerError extends Error {
|
||||
public ExceptionInInitializerError(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ExceptionInInitializerError() {
|
||||
super();
|
||||
}
|
||||
}
|
11
classpath/java/lang/IllegalMonitorStateException.java
Normal file
11
classpath/java/lang/IllegalMonitorStateException.java
Normal file
@ -0,0 +1,11 @@
|
||||
package java.lang;
|
||||
|
||||
public class IllegalMonitorStateException extends RuntimeException {
|
||||
public IllegalMonitorStateException(String message) {
|
||||
super(message, null);
|
||||
}
|
||||
|
||||
public IllegalMonitorStateException() {
|
||||
this(null);
|
||||
}
|
||||
}
|
11
classpath/java/lang/NoSuchMethodError.java
Normal file
11
classpath/java/lang/NoSuchMethodError.java
Normal file
@ -0,0 +1,11 @@
|
||||
package java.lang;
|
||||
|
||||
public class NoSuchMethodError extends IncompatibleClassChangeError {
|
||||
public NoSuchMethodError(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public NoSuchMethodError() {
|
||||
super();
|
||||
}
|
||||
}
|
11
classpath/java/lang/StackOverflowError.java
Normal file
11
classpath/java/lang/StackOverflowError.java
Normal file
@ -0,0 +1,11 @@
|
||||
package java.lang;
|
||||
|
||||
public class StackOverflowError extends Error {
|
||||
public StackOverflowError(String message) {
|
||||
super(message, null);
|
||||
}
|
||||
|
||||
public StackOverflowError() {
|
||||
this(null);
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ public final class String implements Comparable<String> {
|
||||
private Object data;
|
||||
private int offset;
|
||||
private int length;
|
||||
private int hash;
|
||||
private int hashCode;
|
||||
|
||||
public String(char[] data, int offset, int length, boolean copy) {
|
||||
this((Object) data, offset, length, copy);
|
||||
@ -70,12 +70,12 @@ public final class String implements Comparable<String> {
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
if (hash == 0) {
|
||||
if (hashCode == 0) {
|
||||
int h = 0;
|
||||
for (int i = 0; i < length; ++i) h = (h * 31) + charAt(i);
|
||||
hash = h;
|
||||
hashCode = h;
|
||||
}
|
||||
return hash;
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
|
@ -4,7 +4,8 @@ public abstract class Reference<T> {
|
||||
private Object vmNext;
|
||||
private T target;
|
||||
private ReferenceQueue<? super T> queue;
|
||||
Reference next;
|
||||
|
||||
Reference jNext;
|
||||
|
||||
protected Reference(T target, ReferenceQueue<? super T> queue) {
|
||||
this.target = target;
|
||||
@ -20,7 +21,7 @@ public abstract class Reference<T> {
|
||||
}
|
||||
|
||||
public boolean isEnqueued() {
|
||||
return next != null;
|
||||
return jNext != null;
|
||||
}
|
||||
|
||||
public boolean enqueue() {
|
||||
|
@ -7,21 +7,21 @@ public class ReferenceQueue<T> {
|
||||
public Reference<? extends T> poll() {
|
||||
Reference<? extends T> r = front;
|
||||
if (front != null) {
|
||||
if (front == front.next) {
|
||||
if (front == front.jNext) {
|
||||
front = rear = null;
|
||||
} else {
|
||||
front = front.next;
|
||||
front = front.jNext;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void add(Reference<? extends T> r) {
|
||||
r.next = r;
|
||||
r.jNext = r;
|
||||
if (front == null) {
|
||||
front = r;
|
||||
} else {
|
||||
rear.next = r;
|
||||
rear.jNext = r;
|
||||
}
|
||||
rear = r;
|
||||
}
|
||||
|
13
makefile
13
makefile
@ -28,7 +28,7 @@ src = src
|
||||
classpath = classpath
|
||||
test = test
|
||||
|
||||
input = $(test-build)/Hello.class
|
||||
input = $(test-build)/Reflection.class
|
||||
|
||||
build-cxx = g++
|
||||
build-cc = gcc
|
||||
@ -174,9 +174,7 @@ driver-sources = $(src)/main.cpp
|
||||
|
||||
driver-object = $(call cpp-objects,$(driver-sources),$(src),$(native-build))
|
||||
|
||||
generator-headers = \
|
||||
$(src)/input.h \
|
||||
$(src)/output.h
|
||||
generator-headers = $(src)/constants.h
|
||||
generator-sources = $(src)/type-generator.cpp
|
||||
generator-objects = \
|
||||
$(call cpp-objects,$(generator-sources),$(src),$(native-build))
|
||||
@ -239,10 +237,10 @@ clean-native:
|
||||
rm -rf $(native-build)
|
||||
|
||||
gen-arg = $(shell echo $(1) | sed -e 's:$(native-build)/type-\(.*\)\.cpp:\1:')
|
||||
$(generated-code): %.cpp: $(src)/types.def $(generator)
|
||||
$(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep)
|
||||
@echo "generating $(@)"
|
||||
@mkdir -p $(dir $(@))
|
||||
$(generator) $(call gen-arg,$(@)) < $(<) > $(@)
|
||||
$(generator) $(classpath-build) $(call gen-arg,$(@)) < $(<) > $(@)
|
||||
|
||||
$(native-build)/type-generator.o: \
|
||||
$(generator-headers)
|
||||
@ -297,7 +295,8 @@ $(classpath-object): $(build)/classpath.jar
|
||||
$(generator-objects): $(native-build)/%.o: $(src)/%.cpp
|
||||
@echo "compiling $(@)"
|
||||
@mkdir -p $(dir $(@))
|
||||
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) $(build-cflags) -c $(<) -o $(@)
|
||||
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \
|
||||
-c $(<) -o $(@)
|
||||
|
||||
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
|
||||
@echo "compiling $(@)"
|
||||
|
134
src/input.h
134
src/input.h
@ -1,134 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
// input //////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Input {
|
||||
public:
|
||||
virtual ~Input() { }
|
||||
|
||||
virtual void dispose() = 0;
|
||||
|
||||
virtual int peek() = 0;
|
||||
|
||||
virtual int read() = 0;
|
||||
|
||||
virtual unsigned line() = 0;
|
||||
|
||||
virtual unsigned column() = 0;
|
||||
|
||||
void skipSpace() {
|
||||
bool quit = false;
|
||||
while (not quit) {
|
||||
int c = peek();
|
||||
switch (c) {
|
||||
case ' ': case '\t': case '\n':
|
||||
read();
|
||||
break;
|
||||
|
||||
default: quit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// file input /////////////////////////////////////////////////////////////////
|
||||
|
||||
class FileInput : public Input {
|
||||
public:
|
||||
const char* file;
|
||||
FILE* stream;
|
||||
unsigned line_;
|
||||
unsigned column_;
|
||||
bool close;
|
||||
|
||||
FileInput(const char* file, FILE* stream = 0, bool close = true):
|
||||
file(file), stream(stream), line_(1), column_(1), close(close)
|
||||
{ }
|
||||
|
||||
virtual ~FileInput() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (stream and close) {
|
||||
fclose(stream);
|
||||
stream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual int peek() {
|
||||
int c = getc(stream);
|
||||
ungetc(c, stream);
|
||||
return c;
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
int c = getc(stream);
|
||||
if (c == '\n') {
|
||||
++ line_;
|
||||
column_ = 1;
|
||||
} else {
|
||||
++ column_;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
virtual unsigned line() {
|
||||
return line_;
|
||||
}
|
||||
|
||||
virtual unsigned column() {
|
||||
return column_;
|
||||
}
|
||||
};
|
||||
|
||||
// string input ///////////////////////////////////////////////////////////////
|
||||
|
||||
class StringInput : public Input {
|
||||
public:
|
||||
const char* string;
|
||||
unsigned position;
|
||||
unsigned limit;
|
||||
unsigned line_;
|
||||
unsigned column_;
|
||||
|
||||
StringInput(const char* string);
|
||||
|
||||
virtual ~StringInput() { }
|
||||
|
||||
virtual void dispose() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
virtual int peek() {
|
||||
if (position == limit) return -1;
|
||||
return string[position];
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
int c = peek();
|
||||
if (c >= 0) {
|
||||
if (c == '\n') {
|
||||
++ line_;
|
||||
column_ = 1;
|
||||
} else {
|
||||
++ column_;
|
||||
}
|
||||
++ position;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
virtual unsigned line() {
|
||||
return line_;
|
||||
}
|
||||
|
||||
virtual unsigned column() {
|
||||
return column_;
|
||||
}
|
||||
};
|
||||
|
||||
#endif//INPUT_H
|
@ -2569,6 +2569,12 @@ interpret(Thread* t)
|
||||
|
||||
case wide: goto wide;
|
||||
|
||||
case impdep1: {
|
||||
// this means we're invoking a virtual method on an instance of a
|
||||
// bootstrap class, so we need to load the real class.
|
||||
abort(t);
|
||||
} break;
|
||||
|
||||
default: abort(t);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,9 @@ namespace {
|
||||
const uintptr_t InterfaceMethodID
|
||||
= (static_cast<uintptr_t>(1) << (BitsPerWord - 1));
|
||||
|
||||
const uintptr_t NonVirtualMethodID
|
||||
= (static_cast<uintptr_t>(1) << (BitsPerWord - 2));
|
||||
|
||||
jint JNICALL
|
||||
DestroyJavaVM(Machine* m)
|
||||
{
|
||||
@ -228,6 +231,8 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
= vectorAppend(t, t->m->jniInterfaceTable, method);
|
||||
|
||||
return (vectorSize(t, t->m->jniInterfaceTable) - 1) | InterfaceMethodID;
|
||||
} else if (methodFlags(t, method) & ACC_PRIVATE) {
|
||||
return methodOffset(t, method) | NonVirtualMethodID;
|
||||
} else {
|
||||
return methodOffset(t, method) + 1;
|
||||
}
|
||||
@ -249,6 +254,9 @@ getMethod(Thread* t, object o, jmethodID m)
|
||||
{
|
||||
if (m & InterfaceMethodID) {
|
||||
return vectorBody(t, t->m->jniInterfaceTable, m & (~InterfaceMethodID));
|
||||
} else if (m & NonVirtualMethodID) {
|
||||
return arrayBody(t, classMethodTable(t, objectClass(t, o)),
|
||||
m & (~NonVirtualMethodID));
|
||||
} else {
|
||||
return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m - 1);
|
||||
}
|
||||
@ -1890,5 +1898,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
|
||||
*t = p->makeThread(*m, 0, 0);
|
||||
|
||||
enter(*t, Thread::ActiveState);
|
||||
enter(*t, Thread::IdleState);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
109
src/machine.cpp
109
src/machine.cpp
@ -250,9 +250,9 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
|
||||
|
||||
object q = jreferenceQueue(t, *p);
|
||||
|
||||
set(t, *p, JreferenceJnext, *p);
|
||||
set(t, *p, JreferenceJNext, *p);
|
||||
if (referenceQueueFront(t, q)) {
|
||||
set(t, referenceQueueRear(t, q), JreferenceJnext, *p);
|
||||
set(t, referenceQueueRear(t, q), JreferenceJNext, *p);
|
||||
} else {
|
||||
set(t, q, ReferenceQueueFront, *p);
|
||||
}
|
||||
@ -261,7 +261,7 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
|
||||
jreferenceQueue(t, *p) = 0;
|
||||
}
|
||||
|
||||
*p = jreferenceNext(t, *p);
|
||||
*p = jreferenceVmNext(t, *p);
|
||||
}
|
||||
|
||||
void
|
||||
@ -278,7 +278,7 @@ referenceUnreachable(Thread* t, Heap::Visitor* v, object* p)
|
||||
// queue is reachable - add the reference
|
||||
referenceTargetUnreachable(t, v, p);
|
||||
} else {
|
||||
*p = jreferenceNext(t, *p);
|
||||
*p = jreferenceVmNext(t, *p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,11 +373,11 @@ postVisit(Thread* t, Heap::Visitor* v)
|
||||
}
|
||||
|
||||
object reference = *p;
|
||||
*p = jreferenceNext(t, reference);
|
||||
jreferenceNext(t, reference) = firstNewTenuredWeakReference;
|
||||
*p = jreferenceVmNext(t, reference);
|
||||
jreferenceVmNext(t, reference) = firstNewTenuredWeakReference;
|
||||
firstNewTenuredWeakReference = reference;
|
||||
} else {
|
||||
p = &jreferenceNext(t, *p);
|
||||
p = &jreferenceVmNext(t, *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -408,7 +408,7 @@ postVisit(Thread* t, Heap::Visitor* v)
|
||||
} else {
|
||||
// both reference and target are reachable
|
||||
referenceTargetReachable(t, v, p);
|
||||
p = &jreferenceNext(t, *p);
|
||||
p = &jreferenceVmNext(t, *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -419,7 +419,7 @@ postVisit(Thread* t, Heap::Visitor* v)
|
||||
}
|
||||
|
||||
if (lastNewTenuredWeakReference) {
|
||||
jreferenceNext(t, lastNewTenuredWeakReference) = m->tenuredWeakReferences;
|
||||
jreferenceVmNext(t, lastNewTenuredWeakReference) = m->tenuredWeakReferences;
|
||||
m->tenuredWeakReferences = firstNewTenuredWeakReference;
|
||||
}
|
||||
}
|
||||
@ -1224,7 +1224,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
||||
compiled);
|
||||
PROTECT(t, method);
|
||||
|
||||
if (flags & ACC_STATIC) {
|
||||
if (flags & (ACC_STATIC | ACC_PRIVATE)) {
|
||||
methodOffset(t, method) = i;
|
||||
|
||||
if (strcmp(reinterpret_cast<const int8_t*>("<clinit>"),
|
||||
@ -1377,9 +1377,8 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
|
||||
|
||||
ENTER(t, Thread::ExclusiveState);
|
||||
|
||||
classVmFlags(t, bootstrapClass) = classVmFlags(t, class_);
|
||||
classFlags(t, bootstrapClass) = classFlags(t, class_);
|
||||
classVmFlags(t, bootstrapClass)
|
||||
|= (classVmFlags(t, class_) & ~BootstrapFlag);
|
||||
|
||||
set(t, bootstrapClass, ClassSuper, classSuper(t, class_));
|
||||
set(t, bootstrapClass, ClassInterfaceTable, classInterfaceTable(t, class_));
|
||||
@ -1515,6 +1514,48 @@ invoke(Thread* t, const char* className, int argc, const char** argv)
|
||||
(t, className, "main", "([Ljava/lang/String;)V", 0, args);
|
||||
}
|
||||
|
||||
void
|
||||
bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
|
||||
unsigned fixedSize, unsigned arrayElementSize)
|
||||
{
|
||||
object mask;
|
||||
if (objectMask) {
|
||||
mask = makeIntArray(t, 1, false);
|
||||
intArrayBody(t, mask, 0) = objectMask;
|
||||
} else {
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
object super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
|
||||
|
||||
object class_ = makeClass(t, 0, 0, 0, fixedSize, arrayElementSize, mask, 0,
|
||||
super, 0, 0, 0, 0, 0, t->m->loader);
|
||||
|
||||
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
|
||||
}
|
||||
|
||||
void
|
||||
bootJavaClass(Thread* t, Machine::Type type, const char* name,
|
||||
unsigned vtableLength, object bootMethod)
|
||||
{
|
||||
PROTECT(t, bootMethod);
|
||||
|
||||
object n = makeByteArray(t, name);
|
||||
object class_ = arrayBody(t, t->m->types, type);
|
||||
PROTECT(t, class_);
|
||||
|
||||
set(t, class_, ClassName, n);
|
||||
|
||||
object vtable = makeArray(t, vtableLength, false);
|
||||
for (unsigned i = 0; i < vtableLength; ++ i) {
|
||||
arrayBody(t, vtable, i) = bootMethod;
|
||||
}
|
||||
|
||||
set(t, class_, ClassVirtualTable, vtable);
|
||||
|
||||
hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash);
|
||||
}
|
||||
|
||||
class HeapClient: public Heap::Client {
|
||||
public:
|
||||
HeapClient(Machine* m): m(m) { }
|
||||
@ -1729,6 +1770,10 @@ Thread::init()
|
||||
t->m->loader = allocate(t, sizeof(void*) * 3, true);
|
||||
memset(t->m->loader, 0, sizeof(void*) * 2);
|
||||
|
||||
t->m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
|
||||
arrayLength(t, t->m->types) = TypeCount;
|
||||
memset(&arrayBody(t, t->m->types, 0), 0, TypeCount * BytesPerWord);
|
||||
|
||||
#include "type-initializations.cpp"
|
||||
|
||||
object arrayClass = arrayBody(t, t->m->types, Machine::ArrayType);
|
||||
@ -1781,8 +1826,9 @@ Thread::init()
|
||||
|
||||
m->bootstrapClassMap = makeHashMap(this, 0, 0);
|
||||
|
||||
object loaderMap = makeHashMap(this, 0, 0);
|
||||
set(t, m->loader, SystemClassLoaderMap, loaderMap);
|
||||
{ object loaderMap = makeHashMap(this, 0, 0);
|
||||
set(t, m->loader, SystemClassLoaderMap, loaderMap);
|
||||
}
|
||||
|
||||
m->monitorMap = makeWeakHashMap(this, 0, 0);
|
||||
m->stringMap = makeWeakHashMap(this, 0, 0);
|
||||
@ -1791,19 +1837,14 @@ Thread::init()
|
||||
|
||||
m->localThread->set(this);
|
||||
|
||||
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1, false);
|
||||
codeBody(t, bootCode, 0) = impdep1;
|
||||
object bootMethod = makeMethod
|
||||
(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode, 0);
|
||||
PROTECT(t, bootMethod);
|
||||
|
||||
#include "type-java-initializations.cpp"
|
||||
|
||||
enter(t, Thread::ActiveState);
|
||||
|
||||
resolveClass
|
||||
(t, className(t, arrayBody(t, m->types,
|
||||
Machine::SystemClassLoaderType)));
|
||||
resolveClass
|
||||
(t, className(t, arrayBody(t, m->types, Machine::ClassType)));
|
||||
resolveClass
|
||||
(t, className(t, arrayBody(t, m->types, Machine::IntArrayType)));
|
||||
resolveClass
|
||||
(t, className(t, arrayBody(t, m->types, Machine::ByteArrayType)));
|
||||
}
|
||||
} else {
|
||||
parent->child = this;
|
||||
}
|
||||
@ -1814,10 +1855,6 @@ Thread::init()
|
||||
this->javaThread = makeThread
|
||||
(this, reinterpret_cast<int64_t>(this), 0, 0, 0, 0, m->loader);
|
||||
}
|
||||
|
||||
if (parent == 0) {
|
||||
enter(this, Thread::IdleState);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -2072,7 +2109,7 @@ stringChars(Thread* t, object string, char* chars)
|
||||
&byteArrayBody(t, data, stringOffset(t, string)),
|
||||
stringLength(t, string));
|
||||
} else {
|
||||
for (int i = 0; i < stringLength(t, string); ++i) {
|
||||
for (unsigned i = 0; i < stringLength(t, string); ++i) {
|
||||
chars[i] = charArrayBody(t, data, stringOffset(t, string) + i);
|
||||
}
|
||||
}
|
||||
@ -2235,7 +2272,7 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
||||
|
||||
object r = makeWeakReference(t, 0, 0, 0, 0);
|
||||
jreferenceTarget(t, r) = key;
|
||||
jreferenceNext(t, r) = t->m->weakReferences;
|
||||
jreferenceVmNext(t, r) = t->m->weakReferences;
|
||||
key = t->m->weakReferences = r;
|
||||
}
|
||||
|
||||
@ -2810,7 +2847,7 @@ printTrace(Thread* t, object exception)
|
||||
exception = makeNullPointerException(t, 0, makeTrace(t), 0);
|
||||
}
|
||||
|
||||
for (object e = exception; e; e = throwableCauseUnsafe(t, e)) {
|
||||
for (object e = exception; e; e = throwableCause(t, e)) {
|
||||
if (e != exception) {
|
||||
fprintf(stderr, "caused by: ");
|
||||
}
|
||||
@ -2818,8 +2855,8 @@ printTrace(Thread* t, object exception)
|
||||
fprintf(stderr, "%s", &byteArrayBody
|
||||
(t, className(t, objectClass(t, e)), 0));
|
||||
|
||||
if (throwableMessageUnsafe(t, e)) {
|
||||
object m = throwableMessageUnsafe(t, e);
|
||||
if (throwableMessage(t, e)) {
|
||||
object m = throwableMessage(t, e);
|
||||
char message[stringLength(t, m) + 1];
|
||||
stringChars(t, m, message);
|
||||
fprintf(stderr, ": %s\n", message);
|
||||
@ -2827,7 +2864,7 @@ printTrace(Thread* t, object exception)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
object trace = throwableTraceUnsafe(t, e);
|
||||
object trace = throwableTrace(t, e);
|
||||
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
|
||||
object e = arrayBody(t, trace, i);
|
||||
const int8_t* class_ = &byteArrayBody
|
||||
|
@ -61,8 +61,7 @@ const unsigned WeakReferenceFlag = 1 << 1;
|
||||
const unsigned NeedInitFlag = 1 << 2;
|
||||
const unsigned InitFlag = 1 << 3;
|
||||
const unsigned PrimitiveFlag = 1 << 4;
|
||||
const unsigned BootstrapFlag = 1 << 5;
|
||||
const unsigned SingletonFlag = 1 << 6;
|
||||
const unsigned SingletonFlag = 1 << 5;
|
||||
|
||||
// method flags:
|
||||
const unsigned ClassInitFlag = 1 << 0;
|
||||
@ -1471,6 +1470,9 @@ setObjectClass(Thread* t, object o, object value)
|
||||
object&
|
||||
arrayBodyUnsafe(Thread*, object, unsigned);
|
||||
|
||||
bool
|
||||
instanceOf(Thread* t, object class_, object o);
|
||||
|
||||
#include "type-declarations.cpp"
|
||||
|
||||
inline bool
|
||||
@ -1654,7 +1656,7 @@ makeNewWeakReference(Thread* t, object class_)
|
||||
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
jreferenceNextUnsafe(t, instance) = t->m->weakReferences;
|
||||
jreferenceVmNext(t, instance) = t->m->weakReferences;
|
||||
t->m->weakReferences = instance;
|
||||
|
||||
return instance;
|
||||
@ -1682,9 +1684,6 @@ stringChars(Thread* t, object string, char* chars);
|
||||
bool
|
||||
isAssignableFrom(Thread* t, object a, object b);
|
||||
|
||||
bool
|
||||
instanceOf(Thread* t, object class_, object o);
|
||||
|
||||
object
|
||||
classInitializer(Thread* t, object class_);
|
||||
|
||||
@ -1799,7 +1798,7 @@ stringEqual(Thread* t, object a, object b)
|
||||
if (a == b) {
|
||||
return true;
|
||||
} else if (stringLength(t, a) == stringLength(t, b)) {
|
||||
for (int i = 0; i < stringLength(t, a); ++i) {
|
||||
for (unsigned i = 0; i < stringLength(t, a); ++i) {
|
||||
if (stringCharAt(t, a, i) != stringCharAt(t, b, i)) {
|
||||
return false;
|
||||
}
|
||||
|
60
src/output.h
60
src/output.h
@ -1,60 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef OUTPUT_H
|
||||
#define OUTPUT_H
|
||||
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
// output /////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Output {
|
||||
public:
|
||||
virtual ~Output() { }
|
||||
|
||||
virtual void dispose() = 0;
|
||||
|
||||
virtual void write(const char* s) = 0;
|
||||
|
||||
void write(int i) {
|
||||
static const int Size = 32;
|
||||
char s[Size];
|
||||
int c UNUSED = snprintf(s, Size, "%d", i);
|
||||
assert(c > 0 and c < Size);
|
||||
write(s);
|
||||
}
|
||||
};
|
||||
|
||||
// file output ////////////////////////////////////////////////////////////////
|
||||
|
||||
class FileOutput : public Output {
|
||||
public:
|
||||
const char* file;
|
||||
FILE* stream;
|
||||
bool close;
|
||||
|
||||
FileOutput(const char* file, FILE* stream = 0, bool close = true):
|
||||
file(file), stream(stream), close(close)
|
||||
{ }
|
||||
|
||||
virtual ~FileOutput() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (stream and close) {
|
||||
fclose(stream);
|
||||
stream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void write(const char* s) {
|
||||
fputs(s, stream);
|
||||
}
|
||||
|
||||
const char* filename() {
|
||||
return file;
|
||||
}
|
||||
};
|
||||
|
||||
#endif//OUTPUT_H
|
@ -127,8 +127,7 @@ findMethod(Thread* t, object method, object class_)
|
||||
inline bool
|
||||
methodVirtual(Thread* t, object method)
|
||||
{
|
||||
return (methodFlags(t, method) & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE))
|
||||
== 0;
|
||||
return (methodFlags(t, method) & (ACC_STATIC | ACC_PRIVATE)) == 0;
|
||||
}
|
||||
|
||||
inline void*
|
||||
|
@ -1,17 +1,21 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
#include "assert.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "constants.h"
|
||||
|
||||
#define UNREACHABLE abort()
|
||||
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
inline void operator delete(void*) { abort(); }
|
||||
|
||||
extern "C" void __cxa_pure_virtual(void) { abort(); }
|
||||
|
||||
using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifndef POINTER_SIZE
|
||||
@ -74,11 +78,194 @@ take(unsigned n, const char* c)
|
||||
return r;
|
||||
}
|
||||
|
||||
class Input {
|
||||
public:
|
||||
virtual ~Input() { }
|
||||
|
||||
virtual void dispose() = 0;
|
||||
|
||||
virtual int peek() = 0;
|
||||
|
||||
virtual int read() = 0;
|
||||
|
||||
virtual unsigned line() = 0;
|
||||
|
||||
virtual unsigned column() = 0;
|
||||
|
||||
void skipSpace() {
|
||||
bool quit = false;
|
||||
while (not quit) {
|
||||
int c = peek();
|
||||
switch (c) {
|
||||
case ' ': case '\t': case '\n':
|
||||
read();
|
||||
break;
|
||||
|
||||
default: quit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class FileInput : public Input {
|
||||
public:
|
||||
const char* file;
|
||||
FILE* stream;
|
||||
unsigned line_;
|
||||
unsigned column_;
|
||||
bool close;
|
||||
|
||||
FileInput(const char* file, FILE* stream = 0, bool close = true):
|
||||
file(file), stream(stream), line_(1), column_(1), close(close)
|
||||
{ }
|
||||
|
||||
virtual ~FileInput() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (stream and close) {
|
||||
fclose(stream);
|
||||
stream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual int peek() {
|
||||
int c = getc(stream);
|
||||
ungetc(c, stream);
|
||||
return c;
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
int c = getc(stream);
|
||||
if (c == '\n') {
|
||||
++ line_;
|
||||
column_ = 1;
|
||||
} else {
|
||||
++ column_;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
virtual unsigned line() {
|
||||
return line_;
|
||||
}
|
||||
|
||||
virtual unsigned column() {
|
||||
return column_;
|
||||
}
|
||||
};
|
||||
|
||||
class Output {
|
||||
public:
|
||||
virtual ~Output() { }
|
||||
|
||||
virtual void dispose() = 0;
|
||||
|
||||
virtual void write(const char* s) = 0;
|
||||
|
||||
void write(int i) {
|
||||
static const int Size = 32;
|
||||
char s[Size];
|
||||
int c UNUSED = snprintf(s, Size, "%d", i);
|
||||
assert(c > 0 and c < Size);
|
||||
write(s);
|
||||
}
|
||||
};
|
||||
|
||||
class FileOutput : public Output {
|
||||
public:
|
||||
const char* file;
|
||||
FILE* stream;
|
||||
bool close;
|
||||
|
||||
FileOutput(const char* file, FILE* stream = 0, bool close = true):
|
||||
file(file), stream(stream), close(close)
|
||||
{ }
|
||||
|
||||
virtual ~FileOutput() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (stream and close) {
|
||||
fclose(stream);
|
||||
stream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void write(const char* s) {
|
||||
fputs(s, stream);
|
||||
}
|
||||
|
||||
const char* filename() {
|
||||
return file;
|
||||
}
|
||||
};
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
Stream(FILE* stream, bool close):
|
||||
stream(stream), close(close)
|
||||
{
|
||||
assert(stream);
|
||||
}
|
||||
|
||||
~Stream() {
|
||||
if (close) fclose(stream);
|
||||
}
|
||||
|
||||
void skip(unsigned size) {
|
||||
fseek(stream, size, SEEK_CUR);
|
||||
}
|
||||
|
||||
void read(uint8_t* data, unsigned size) {
|
||||
fread(data, 1, size, stream);
|
||||
}
|
||||
|
||||
uint8_t read1() {
|
||||
uint8_t v;
|
||||
read(&v, 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
uint16_t read2() {
|
||||
uint16_t a = read1();
|
||||
uint16_t b = read1();
|
||||
return (a << 8) | b;
|
||||
}
|
||||
|
||||
uint32_t read4() {
|
||||
uint32_t a = read2();
|
||||
uint32_t b = read2();
|
||||
return (a << 16) | b;
|
||||
}
|
||||
|
||||
uint64_t read8() {
|
||||
uint64_t a = read4();
|
||||
uint64_t b = read4();
|
||||
return (a << 32) | b;
|
||||
}
|
||||
|
||||
uint32_t readFloat() {
|
||||
return read4();
|
||||
}
|
||||
|
||||
uint64_t readDouble() {
|
||||
return read8();
|
||||
}
|
||||
|
||||
private:
|
||||
FILE* stream;
|
||||
bool close;
|
||||
};
|
||||
|
||||
class Object {
|
||||
public:
|
||||
typedef enum {
|
||||
Scalar,
|
||||
Array,
|
||||
Method,
|
||||
Pod,
|
||||
Type,
|
||||
Pair,
|
||||
@ -118,6 +305,13 @@ car(Object* o)
|
||||
return static_cast<Pair*>(o)->car;
|
||||
}
|
||||
|
||||
void
|
||||
setCar(Object* o, Object* v)
|
||||
{
|
||||
assert(o->type == Object::Pair);
|
||||
static_cast<Pair*>(o)->car = v;
|
||||
}
|
||||
|
||||
Object*&
|
||||
cdr(Object* o)
|
||||
{
|
||||
@ -336,13 +530,54 @@ memberHide(Object* o)
|
||||
}
|
||||
}
|
||||
|
||||
class Method : public Object {
|
||||
public:
|
||||
Object* owner;
|
||||
const char* name;
|
||||
const char* spec;
|
||||
|
||||
static Method* make(Object* owner, const char* name, const char* spec)
|
||||
{
|
||||
Method* o = allocate<Method>();
|
||||
o->type = Object::Method;
|
||||
o->owner = owner;
|
||||
o->name = name;
|
||||
o->spec = spec;
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
const char*
|
||||
methodName(Object* o)
|
||||
{
|
||||
switch (o->type) {
|
||||
case Object::Method:
|
||||
return static_cast<Method*>(o)->name;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
methodSpec(Object* o)
|
||||
{
|
||||
switch (o->type) {
|
||||
case Object::Method:
|
||||
return static_cast<Method*>(o)->spec;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
class Type : public Object {
|
||||
public:
|
||||
const char* name;
|
||||
const char* javaName;
|
||||
Object* super;
|
||||
List members;
|
||||
List subtypes;
|
||||
List methods;
|
||||
bool hideConstructor;
|
||||
|
||||
static Type* make(Object::ObjectType type, const char* name,
|
||||
@ -354,7 +589,7 @@ class Type : public Object {
|
||||
o->javaName = javaName;
|
||||
o->super = 0;
|
||||
o->members.first = o->members.last = 0;
|
||||
o->subtypes.first = o->subtypes.last = 0;
|
||||
o->methods.first = o->methods.last = 0;
|
||||
o->hideConstructor = false;
|
||||
return o;
|
||||
}
|
||||
@ -396,6 +631,18 @@ typeMembers(Object* o)
|
||||
}
|
||||
}
|
||||
|
||||
Object*
|
||||
typeMethods(Object* o)
|
||||
{
|
||||
switch (o->type) {
|
||||
case Object::Type:
|
||||
return static_cast<Type*>(o)->methods.first;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addMember(Object* o, Object* member)
|
||||
{
|
||||
@ -414,11 +661,20 @@ addMember(Object* o, Object* member)
|
||||
}
|
||||
|
||||
void
|
||||
addSubtype(Object* o, Object* subtype)
|
||||
addMethod(Object* o, Object* method)
|
||||
{
|
||||
switch (o->type) {
|
||||
case Object::Type:
|
||||
static_cast<Type*>(o)->subtypes.append(subtype);
|
||||
for (Object* p = typeMethods(o); p; p = cdr(p)) {
|
||||
Object* m = car(p);
|
||||
if (equal(methodName(m), methodName(method))
|
||||
and equal(methodSpec(m), methodSpec(method)))
|
||||
{
|
||||
setCar(p, method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
static_cast<Type*>(o)->methods.append(method);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -426,18 +682,6 @@ addSubtype(Object* o, Object* subtype)
|
||||
}
|
||||
}
|
||||
|
||||
Object*
|
||||
typeSubtypes(Object* o)
|
||||
{
|
||||
switch (o->type) {
|
||||
case Object::Type:
|
||||
return static_cast<Type*>(o)->subtypes.first;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
Object*&
|
||||
typeSuper(Object* o)
|
||||
{
|
||||
@ -642,6 +886,25 @@ declaration(const char* name, Object* declarations)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Object*
|
||||
javaDeclaration(const char* name, Object* declarations)
|
||||
{
|
||||
for (Object* p = declarations; p; p = cdr(p)) {
|
||||
Object* o = car(p);
|
||||
switch (o->type) {
|
||||
case Object::Type:
|
||||
if (typeJavaName(o) and equal(name, typeJavaName(o))) return o;
|
||||
break;
|
||||
|
||||
case Object::Pod:
|
||||
break;
|
||||
|
||||
default: UNREACHABLE;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Object*
|
||||
derivationChain(Object* o)
|
||||
{
|
||||
@ -868,7 +1131,6 @@ parseSubdeclaration(Object* t, Object* p, Object* declarations)
|
||||
typeSuper(t) = declaration(string(car(cdr(p))), declarations);
|
||||
assert(typeSuper(t));
|
||||
assert(typeSuper(t)->type == Object::Type);
|
||||
addSubtype(typeSuper(t), t);
|
||||
} else {
|
||||
Object* member = parseMember(t, p, declarations);
|
||||
addMember(t, member);
|
||||
@ -923,23 +1185,185 @@ specEqual(Object* a, Object* b)
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
append(const char* a, const char* b, const char* c, const char* d)
|
||||
{
|
||||
unsigned al = strlen(a);
|
||||
unsigned bl = strlen(b);
|
||||
unsigned cl = strlen(c);
|
||||
unsigned dl = strlen(d);
|
||||
char* p = static_cast<char*>(malloc(al + bl + cl + dl + 1));
|
||||
memcpy(p, a, al);
|
||||
memcpy(p + al, b, bl);
|
||||
memcpy(p + al + bl, c, cl);
|
||||
memcpy(p + al + bl + cl, d, dl + 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
const char*
|
||||
append(const char* a, const char* b)
|
||||
{
|
||||
assert(a and b);
|
||||
unsigned aLength = strlen(a);
|
||||
unsigned bLength = strlen(b);
|
||||
assert(aLength + bLength);
|
||||
char* r = static_cast<char*>(malloc(aLength + bLength + 1));
|
||||
assert(r);
|
||||
|
||||
memcpy(r, a, aLength);
|
||||
memcpy(r + aLength, b, bLength + 1);
|
||||
return r;
|
||||
return append(a, b, "", "");
|
||||
}
|
||||
|
||||
const char*
|
||||
fieldType(const char* spec)
|
||||
{
|
||||
switch (*spec) {
|
||||
case 'B':
|
||||
case 'Z':
|
||||
return "uint8_t";
|
||||
case 'C':
|
||||
case 'S':
|
||||
return "uint16_t";
|
||||
case 'D':
|
||||
case 'J':
|
||||
return "uint64_t";
|
||||
case 'F':
|
||||
case 'I':
|
||||
return "uint32_t";
|
||||
case 'L':
|
||||
case '[':
|
||||
return "object";
|
||||
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parseJavaClass(Object* type, Stream* s, Object* declarations)
|
||||
{
|
||||
uint32_t magic = s->read4();
|
||||
assert(magic == 0xCAFEBABE);
|
||||
s->read2(); // minor version
|
||||
s->read2(); // major version
|
||||
|
||||
unsigned poolCount = s->read2() - 1;
|
||||
uintptr_t pool[poolCount];
|
||||
for (unsigned i = 0; i < poolCount; ++i) {
|
||||
unsigned c = s->read1();
|
||||
|
||||
switch (c) {
|
||||
case CONSTANT_Integer:
|
||||
case CONSTANT_Float:
|
||||
pool[i] = s->read4();
|
||||
break;
|
||||
|
||||
case CONSTANT_Long:
|
||||
case CONSTANT_Double:
|
||||
pool[i++] = s->read4();
|
||||
pool[i] = s->read4();
|
||||
break;
|
||||
|
||||
case CONSTANT_Utf8: {
|
||||
unsigned length = s->read2();
|
||||
uint8_t* p = static_cast<uint8_t*>(malloc(length + 1));
|
||||
s->read(p, length);
|
||||
p[length] = 0;
|
||||
pool[i] = reinterpret_cast<uintptr_t>(p);
|
||||
} break;
|
||||
|
||||
case CONSTANT_Class:
|
||||
case CONSTANT_String:
|
||||
pool[i] = s->read2();
|
||||
break;
|
||||
|
||||
case CONSTANT_NameAndType:
|
||||
pool[i] = s->read4();
|
||||
break;
|
||||
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
pool[i] = s->read4();
|
||||
break;
|
||||
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
s->read2(); // flags
|
||||
s->read2(); // name
|
||||
|
||||
unsigned superIndex = s->read2();
|
||||
if (superIndex) {
|
||||
const char* name = reinterpret_cast<const char*>
|
||||
(pool[pool[superIndex - 1] - 1]);
|
||||
typeSuper(type) = javaDeclaration(name, declarations);
|
||||
assert(typeSuper(type));
|
||||
}
|
||||
|
||||
unsigned interfaceCount = s->read2();
|
||||
s->skip(interfaceCount * 2);
|
||||
|
||||
unsigned fieldCount = s->read2();
|
||||
for (unsigned i = 0; i < fieldCount; ++i) {
|
||||
unsigned flags = s->read2();
|
||||
unsigned nameIndex = s->read2();
|
||||
unsigned specIndex = s->read2();
|
||||
|
||||
unsigned attributeCount = s->read2();
|
||||
for (unsigned j = 0; j < attributeCount; ++j) {
|
||||
s->read2();
|
||||
s->skip(s->read4());
|
||||
}
|
||||
|
||||
if ((flags & ACC_STATIC) == 0) {
|
||||
char* name = reinterpret_cast<char*>(pool[nameIndex - 1]);
|
||||
unsigned nameLength = strlen(name);
|
||||
if (nameLength > 0 and name[nameLength - 1] == '_') {
|
||||
name[nameLength - 1] = 0;
|
||||
}
|
||||
|
||||
const char* spec = reinterpret_cast<const char*>(pool[specIndex - 1]);
|
||||
const char* memberType = fieldType(spec);
|
||||
|
||||
Object* member = Scalar::make
|
||||
(type, 0, memberType, name, sizeOf(memberType, declarations));
|
||||
|
||||
if (equal(typeJavaName(type), "java/lang/ref/Reference")
|
||||
and (equal(name, "vmNext")
|
||||
or equal(name, "target")
|
||||
or equal(name, "queue")))
|
||||
{
|
||||
memberNoGC(member) = true;
|
||||
}
|
||||
|
||||
addMember(type, member);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeSuper(type)) {
|
||||
for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) {
|
||||
addMethod(type, car(p));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned methodCount = s->read2();
|
||||
for (unsigned i = 0; i < methodCount; ++i) {
|
||||
unsigned flags = s->read2();
|
||||
unsigned nameIndex = s->read2();
|
||||
unsigned specIndex = s->read2();
|
||||
|
||||
unsigned attributeCount = s->read2();
|
||||
for (unsigned j = 0; j < attributeCount; ++j) {
|
||||
s->read2();
|
||||
s->skip(s->read4());
|
||||
}
|
||||
|
||||
if ((flags & (ACC_STATIC | ACC_PRIVATE)) == 0) {
|
||||
const char* name = reinterpret_cast<const char*>(pool[nameIndex - 1]);
|
||||
const char* spec = reinterpret_cast<const char*>(pool[specIndex - 1]);
|
||||
|
||||
Object* method = Method::make(type, name, spec);
|
||||
addMethod(type, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object*
|
||||
parseType(Object::ObjectType type, Object* p, Object* declarations)
|
||||
parseType(Object::ObjectType type, Object* p, Object* declarations,
|
||||
const char* javaClassDirectory)
|
||||
{
|
||||
const char* name = string(car(p));
|
||||
|
||||
@ -951,13 +1375,27 @@ parseType(Object::ObjectType type, Object* p, Object* declarations)
|
||||
|
||||
Type* t = Type::make(type, name, javaName);
|
||||
|
||||
for (p = cdr(p); p; p = cdr(p)) {
|
||||
if (type == Object::Type) {
|
||||
parseSubdeclaration(t, car(p), declarations);
|
||||
} else {
|
||||
Object* member = parseMember(t, car(p), declarations);
|
||||
assert(member->type == Object::Scalar);
|
||||
addMember(t, member);
|
||||
if (javaName and *javaName != '[') {
|
||||
assert(cdr(p) == 0);
|
||||
|
||||
const char* file = append(javaClassDirectory, "/", javaName, ".class");
|
||||
Stream s(fopen(file, "rb"), true);
|
||||
parseJavaClass(t, &s, declarations);
|
||||
} else {
|
||||
for (p = cdr(p); p; p = cdr(p)) {
|
||||
if (type == Object::Type) {
|
||||
parseSubdeclaration(t, car(p), declarations);
|
||||
} else {
|
||||
Object* member = parseMember(t, car(p), declarations);
|
||||
assert(member->type == Object::Scalar);
|
||||
addMember(t, member);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Object::Type and typeSuper(t)) {
|
||||
for (Object* p = typeMethods(typeSuper(t)); p; p = cdr(p)) {
|
||||
addMethod(t, car(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -965,13 +1403,14 @@ parseType(Object::ObjectType type, Object* p, Object* declarations)
|
||||
}
|
||||
|
||||
Object*
|
||||
parseDeclaration(Object* p, Object* declarations)
|
||||
parseDeclaration(Object* p, Object* declarations,
|
||||
const char* javaClassDirectory)
|
||||
{
|
||||
const char* spec = string(car(p));
|
||||
if (equal(spec, "type")) {
|
||||
return parseType(Object::Type, cdr(p), declarations);
|
||||
return parseType(Object::Type, cdr(p), declarations, javaClassDirectory);
|
||||
} else if (equal(spec, "pod")) {
|
||||
return parseType(Object::Pod, cdr(p), declarations);
|
||||
return parseType(Object::Pod, cdr(p), declarations, javaClassDirectory);
|
||||
} else {
|
||||
fprintf(stderr, "unexpected declaration spec: %s\n", spec);
|
||||
abort();
|
||||
@ -979,14 +1418,15 @@ parseDeclaration(Object* p, Object* declarations)
|
||||
}
|
||||
|
||||
Object*
|
||||
parse(Input* in)
|
||||
parse(Input* in, const char* javaClassDirectory)
|
||||
{
|
||||
Object* eos = Singleton::make(Object::Eos);
|
||||
List declarations;
|
||||
|
||||
Object* o;
|
||||
while ((o = read(in, eos, 0)) != eos) {
|
||||
declarations.append(parseDeclaration(o, declarations.first));
|
||||
declarations.append
|
||||
(parseDeclaration(o, declarations.first, javaClassDirectory));
|
||||
}
|
||||
|
||||
return declarations.first;
|
||||
@ -1052,19 +1492,6 @@ writeOffset(Output* out, Object* offset, bool allocationStyle = false)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeSubtypeAssertions(Output* out, Object* o)
|
||||
{
|
||||
for (Object* p = typeSubtypes(o); p; p = cdr(p)) {
|
||||
Object* st = car(p);
|
||||
out->write(" or objectClass(t, o) == arrayBodyUnsafe");
|
||||
out->write("(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(st)));
|
||||
out->write("Type)");
|
||||
writeSubtypeAssertions(out, st);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
||||
{
|
||||
@ -1110,16 +1537,13 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
||||
out->write(") {\n");
|
||||
|
||||
if (memberOwner(member)->type == Object::Type) {
|
||||
if (unsafe) {
|
||||
out->write(" assert(t, true);");
|
||||
} else {
|
||||
if (not unsafe) {
|
||||
out->write(" assert(t, t->m->unsafe or ");
|
||||
out->write("objectClass(t, o) == arrayBodyUnsafe");
|
||||
out->write("instanceOf(t, arrayBodyUnsafe");
|
||||
out->write("(t, t->m->types, Machine::");
|
||||
out->write(capitalize(::typeName(memberOwner(member))));
|
||||
out->write("Type)");
|
||||
writeSubtypeAssertions(out, memberOwner(member));
|
||||
out->write(");\n");
|
||||
out->write(", o));\n");
|
||||
|
||||
if (member->type != Object::Scalar) {
|
||||
out->write(" assert(t, i < ");
|
||||
@ -1506,32 +1930,6 @@ writeConstructors(Output* out, Object* declarations)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeJavaName(o)
|
||||
and not equal("class", typeName(o))
|
||||
and startsWith("java/", typeJavaName(o)))
|
||||
{
|
||||
out->write(" object class__ ");
|
||||
out->write("= arrayBody(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(o)));
|
||||
out->write("Type);\n");
|
||||
|
||||
out->write(" if (classVmFlags(t, class__) & BootstrapFlag) {\n");
|
||||
out->write(" classVmFlags(t, class__) &= ~BootstrapFlag;\n");
|
||||
out->write("#ifndef NDEBUG\n");
|
||||
out->write(" object e = t->exception;\n");
|
||||
out->write(" PROTECT(t, e);\n");
|
||||
out->write("#endif\n");
|
||||
out->write(" resolveClass(t, className(t, class__));\n");
|
||||
|
||||
if (equal("classNotFoundException", typeName(o))) {
|
||||
out->write(" t->exception = 0;\n");
|
||||
} else {
|
||||
out->write(" assert(t, t->exception == e);\n");
|
||||
}
|
||||
|
||||
out->write(" }\n");
|
||||
}
|
||||
|
||||
out->write(" object o = allocate(t, ");
|
||||
writeOffset(out, typeOffset(o), true);
|
||||
if (hasObjectMask) {
|
||||
@ -1593,6 +1991,14 @@ memberCount(Object* o)
|
||||
return c;
|
||||
}
|
||||
|
||||
unsigned
|
||||
methodCount(Object* o)
|
||||
{
|
||||
unsigned c = 0;
|
||||
for (Object* p = typeMethods(o); p; p = cdr(p)) ++c;
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
set(uint32_t* mask, unsigned index)
|
||||
{
|
||||
@ -1665,49 +2071,31 @@ typeObjectMask(Object* type)
|
||||
void
|
||||
writeInitialization(Output* out, Object* type)
|
||||
{
|
||||
out->write("{\n");
|
||||
out->write("bootClass(t, Machine::");
|
||||
out->write(capitalize(typeName(type)));
|
||||
out->write("Type, ");
|
||||
|
||||
if (typeSuper(type)) {
|
||||
out->write("Machine::");
|
||||
out->write(capitalize(typeName(typeSuper(type))));
|
||||
out->write("Type");
|
||||
} else {
|
||||
out->write("-1");
|
||||
}
|
||||
out->write(", ");
|
||||
|
||||
if (typeObjectMask(type) != 1) {
|
||||
out->write(" object mask = makeIntArray(t, 1, false);\n");
|
||||
|
||||
out->write(" intArrayBody(t, mask, 0) = ");
|
||||
out->write(typeObjectMask(type));
|
||||
out->write(";\n");
|
||||
} else {
|
||||
out->write(" object mask = 0;\n");
|
||||
out->write("0");
|
||||
}
|
||||
out->write(", ");
|
||||
|
||||
if (typeJavaName(type) and typeSuper(type)) {
|
||||
out->write(" object super = arrayBody(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(typeSuper(type))));
|
||||
out->write("Type);\n");
|
||||
} else {
|
||||
out->write(" object super = 0;\n");
|
||||
}
|
||||
|
||||
out->write(" object class_ = makeClass");
|
||||
out->write("(t, 0, ");
|
||||
|
||||
if (typeJavaName(type)
|
||||
and not equal("class", typeName(type))
|
||||
and startsWith("java/", typeJavaName(type)))
|
||||
{
|
||||
out->write("BootstrapFlag");
|
||||
} else {
|
||||
out->write("0");
|
||||
}
|
||||
|
||||
out->write(", 0, ");
|
||||
out->write(typeFixedSize(type));
|
||||
out->write(", ");
|
||||
|
||||
out->write(typeArrayElementSize(type));
|
||||
out->write(", mask, 0, super, 0, 0, 0, 0, 0, t->m->loader);\n");
|
||||
|
||||
out->write(" set(t, t->m->types, ArrayBody + (Machine::");
|
||||
out->write(capitalize(typeName(type)));
|
||||
out->write("Type * BytesPerWord), class_);\n");
|
||||
|
||||
out->write("}\n\n");
|
||||
out->write(");\n");
|
||||
}
|
||||
|
||||
unsigned
|
||||
@ -1751,18 +2139,6 @@ reorder(Object* declarations)
|
||||
void
|
||||
writeInitializations(Output* out, Object* declarations)
|
||||
{
|
||||
unsigned count = typeCount(declarations);
|
||||
|
||||
out->write("t->m->types = allocate(t, pad((");
|
||||
out->write(count);
|
||||
out->write(" * BytesPerWord) + (BytesPerWord * 2)), true);\n");
|
||||
out->write("arrayLength(t, t->m->types) = ");
|
||||
out->write(count);
|
||||
out->write(";\n");
|
||||
out->write("memset(&arrayBody(t, t->m->types, 0), 0, ");
|
||||
out->write(count);
|
||||
out->write(" * BytesPerWord);\n\n");
|
||||
|
||||
declarations = reorder(declarations);
|
||||
|
||||
for (Object* p = declarations; p; p = cdr(p)) {
|
||||
@ -1776,22 +2152,15 @@ writeInitializations(Output* out, Object* declarations)
|
||||
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->m->types, Machine::");
|
||||
out->write("bootJavaClass(t, Machine::");
|
||||
out->write(capitalize(typeName(type)));
|
||||
out->write("Type);\n");
|
||||
out->write("Type, \"");
|
||||
|
||||
out->write(" set(t, class_, ClassName, name);\n");
|
||||
out->write(typeJavaName(type));
|
||||
out->write("\", ");
|
||||
|
||||
out->write(" hashMapInsert(t, t->m->bootstrapClassMap, ");
|
||||
out->write("name, class_, byteArrayHash);\n");
|
||||
|
||||
out->write("}\n\n");
|
||||
out->write(methodCount(type));
|
||||
out->write(", bootMethod);\n");
|
||||
}
|
||||
|
||||
void
|
||||
@ -1809,7 +2178,8 @@ void
|
||||
usageAndExit(const char* command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s {enums,declarations,constructors,initializations,"
|
||||
"usage: %s <java class directory> "
|
||||
"{enums,declarations,constructors,initializations,"
|
||||
"java-initializations}\n",
|
||||
command);
|
||||
exit(-1);
|
||||
@ -1820,44 +2190,48 @@ usageAndExit(const char* command)
|
||||
int
|
||||
main(int ac, char** av)
|
||||
{
|
||||
if ((ac != 1 and ac != 2)
|
||||
or (ac == 2
|
||||
and not equal(av[1], "enums")
|
||||
and not equal(av[1], "declarations")
|
||||
and not equal(av[1], "constructors")
|
||||
and not equal(av[1], "initializations")
|
||||
and not equal(av[1], "java-initializations")))
|
||||
if ((ac != 2 and ac != 3)
|
||||
or (ac == 3
|
||||
and not equal(av[2], "enums")
|
||||
and not equal(av[2], "declarations")
|
||||
and not equal(av[2], "constructors")
|
||||
and not equal(av[2], "initializations")
|
||||
and not equal(av[2], "java-initializations")))
|
||||
{
|
||||
usageAndExit(av[0]);
|
||||
}
|
||||
|
||||
FileInput in(0, stdin, false);
|
||||
|
||||
Object* declarations = parse(&in);
|
||||
Object* declarations = parse(&in, av[1]);
|
||||
|
||||
FileOutput out(0, stdout, false);
|
||||
|
||||
if (ac == 1 or equal(av[1], "enums")) {
|
||||
if (ac == 2 or equal(av[2], "enums")) {
|
||||
writeEnums(&out, declarations);
|
||||
}
|
||||
|
||||
if (ac == 1 or equal(av[1], "declarations")) {
|
||||
if (ac == 2 or equal(av[2], "declarations")) {
|
||||
out.write("const unsigned TypeCount = ");
|
||||
out.Output::write(typeCount(declarations));
|
||||
out.write(";\n\n");
|
||||
|
||||
writePods(&out, declarations);
|
||||
writeAccessors(&out, declarations);
|
||||
writeInitializerDeclarations(&out, declarations);
|
||||
writeConstructorDeclarations(&out, declarations);
|
||||
}
|
||||
|
||||
if (ac == 1 or equal(av[1], "constructors")) {
|
||||
if (ac == 2 or equal(av[2], "constructors")) {
|
||||
writeInitializers(&out, declarations);
|
||||
writeConstructors(&out, declarations);
|
||||
}
|
||||
|
||||
if (ac == 1 or equal(av[1], "initializations")) {
|
||||
if (ac == 2 or equal(av[2], "initializations")) {
|
||||
writeInitializations(&out, declarations);
|
||||
}
|
||||
|
||||
if (ac == 1 or equal(av[1], "java-initializations")) {
|
||||
if (ac == 2 or equal(av[2], "java-initializations")) {
|
||||
writeJavaInitializations(&out, declarations);
|
||||
}
|
||||
|
||||
|
196
src/types.def
196
src/types.def
@ -1,45 +1,17 @@
|
||||
(type jobject java/lang/Object)
|
||||
|
||||
(type class java/lang/Class
|
||||
(extends jobject)
|
||||
(uint16_t flags)
|
||||
(uint8_t vmFlags)
|
||||
(uint8_t arrayDimensions)
|
||||
(uint16_t fixedSize)
|
||||
(uint16_t arrayElementSize)
|
||||
(object objectMask)
|
||||
(object name)
|
||||
(object super)
|
||||
(object interfaceTable)
|
||||
(object virtualTable)
|
||||
(object fieldTable)
|
||||
(object methodTable)
|
||||
(object staticTable)
|
||||
(object loader))
|
||||
(type class java/lang/Class)
|
||||
|
||||
(type singleton
|
||||
(array uintptr_t body))
|
||||
|
||||
(type classLoader java/lang/ClassLoader
|
||||
(extends jobject)
|
||||
(object parent))
|
||||
(type classLoader java/lang/ClassLoader)
|
||||
|
||||
(type systemClassLoader java/lang/SystemClassLoader
|
||||
(extends classLoader)
|
||||
(object map))
|
||||
(type systemClassLoader java/lang/SystemClassLoader)
|
||||
|
||||
(type accessibleObject java/lang/reflect/AccessibleObject
|
||||
(extends jobject))
|
||||
(type accessibleObject java/lang/reflect/AccessibleObject)
|
||||
|
||||
(type field java/lang/reflect/Field
|
||||
(extends accessibleObject)
|
||||
(uint8_t vmFlags)
|
||||
(uint8_t code)
|
||||
(uint16_t flags)
|
||||
(uint16_t offset)
|
||||
(object name)
|
||||
(object spec)
|
||||
(object class))
|
||||
(type field java/lang/reflect/Field)
|
||||
|
||||
(pod compiled
|
||||
(uint16_t maxLocals)
|
||||
@ -51,19 +23,7 @@
|
||||
(uint32_t stackMapTableLength)
|
||||
(uint8_t[0] body))
|
||||
|
||||
(type method java/lang/reflect/Method
|
||||
(extends accessibleObject)
|
||||
(uint8_t vmFlags)
|
||||
(uint8_t returnCode)
|
||||
(uint8_t parameterCount)
|
||||
(uint8_t parameterFootprint)
|
||||
(uint16_t flags)
|
||||
(uint16_t offset)
|
||||
(object name)
|
||||
(object spec)
|
||||
(object class)
|
||||
(object code)
|
||||
(object compiled))
|
||||
(type method java/lang/reflect/Method)
|
||||
|
||||
(type nativeMethodData
|
||||
(void* function)
|
||||
@ -154,148 +114,82 @@
|
||||
(type array
|
||||
(noassert array object body))
|
||||
|
||||
(type string java/lang/String
|
||||
(extends jobject)
|
||||
(object data)
|
||||
(int32_t offset)
|
||||
(int32_t length)
|
||||
(int32_t hashCode))
|
||||
(type string java/lang/String)
|
||||
|
||||
(type thread java/lang/Thread
|
||||
(extends jobject)
|
||||
(int64_t peer)
|
||||
(object task)
|
||||
(object locals)
|
||||
(uint8_t interrupted)
|
||||
(object sleepLock)
|
||||
(object classLoader))
|
||||
(type thread java/lang/Thread)
|
||||
|
||||
(type stackTraceElement java/lang/StackTraceElement
|
||||
(extends jobject)
|
||||
(object class)
|
||||
(object method)
|
||||
(object file)
|
||||
(int32_t line))
|
||||
(type stackTraceElement java/lang/StackTraceElement)
|
||||
|
||||
(type throwable java/lang/Throwable
|
||||
(extends jobject)
|
||||
(noassert object message)
|
||||
(noassert object trace)
|
||||
(noassert object cause))
|
||||
(type throwable java/lang/Throwable)
|
||||
|
||||
(type exception java/lang/Exception
|
||||
(extends throwable))
|
||||
(type exception java/lang/Exception)
|
||||
|
||||
(type runtimeException java/lang/RuntimeException
|
||||
(extends exception))
|
||||
(type runtimeException java/lang/RuntimeException)
|
||||
|
||||
(type nullPointerException java/lang/NullPointerException
|
||||
(extends runtimeException))
|
||||
(type nullPointerException java/lang/NullPointerException)
|
||||
|
||||
(type illegalStateException java/lang/IllegalStateException
|
||||
(extends runtimeException))
|
||||
(type illegalStateException java/lang/IllegalStateException)
|
||||
|
||||
(type illegalArgumentException java/lang/IllegalArgumentException
|
||||
(extends runtimeException))
|
||||
(type illegalArgumentException java/lang/IllegalArgumentException)
|
||||
|
||||
(type illegalMonitorStateException java/lang/IllegalMonitorStateException
|
||||
(extends runtimeException))
|
||||
(type illegalMonitorStateException java/lang/IllegalMonitorStateException)
|
||||
|
||||
(type arrayIndexOutOfBoundsException
|
||||
java/lang/ArrayIndexOutOfBoundsException
|
||||
(extends runtimeException))
|
||||
java/lang/ArrayIndexOutOfBoundsException)
|
||||
|
||||
(type arrayStoreException java/lang/ArrayStoreException
|
||||
(extends runtimeException))
|
||||
(type arrayStoreException java/lang/ArrayStoreException)
|
||||
|
||||
(type negativeArraySizeException java/lang/NegativeArraySizeException
|
||||
(extends runtimeException))
|
||||
(type negativeArraySizeException java/lang/NegativeArraySizeException)
|
||||
|
||||
(type classCastException java/lang/ClassCastException
|
||||
(extends runtimeException))
|
||||
(type classCastException java/lang/ClassCastException)
|
||||
|
||||
(type classNotFoundException java/lang/ClassNotFoundException
|
||||
(extends exception))
|
||||
(type classNotFoundException java/lang/ClassNotFoundException)
|
||||
|
||||
(type invocationTargetException java/lang/InvocationTargetException
|
||||
(extends exception))
|
||||
(type invocationTargetException java/lang/reflect/InvocationTargetException)
|
||||
|
||||
(type interruptedException java/lang/InterruptedException
|
||||
(extends exception))
|
||||
(type interruptedException java/lang/InterruptedException)
|
||||
|
||||
(type error java/lang/Error
|
||||
(extends throwable))
|
||||
(type error java/lang/Error)
|
||||
|
||||
(type stackOverflowError java/lang/StackOverflowError
|
||||
(extends error))
|
||||
(type stackOverflowError java/lang/StackOverflowError)
|
||||
|
||||
(type noSuchFieldError java/lang/NoSuchFieldError
|
||||
(extends error))
|
||||
(type linkageError java/lang/LinkageError)
|
||||
|
||||
(type noSuchMethodError java/lang/NoSuchMethodError
|
||||
(extends error))
|
||||
(type incompatibleClassChangeError java/lang/IncompatibleClassChangeError)
|
||||
|
||||
(type linkageError java/lang/LinkageError
|
||||
(extends error))
|
||||
(type noSuchFieldError java/lang/NoSuchFieldError)
|
||||
|
||||
(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError
|
||||
(extends linkageError))
|
||||
(type noSuchMethodError java/lang/NoSuchMethodError)
|
||||
|
||||
(type exceptionInInitializerError java/lang/ExceptionInInitializerError
|
||||
(extends error))
|
||||
(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError)
|
||||
|
||||
(type number java/lang/Number
|
||||
(extends jobject))
|
||||
(type exceptionInInitializerError java/lang/ExceptionInInitializerError)
|
||||
|
||||
(type byte java/lang/Byte
|
||||
(extends number)
|
||||
(int8_t value))
|
||||
(type number java/lang/Number)
|
||||
|
||||
(type boolean java/lang/Boolean
|
||||
(extends jobject)
|
||||
(uint8_t value))
|
||||
(type byte java/lang/Byte)
|
||||
|
||||
(type short java/lang/Short
|
||||
(extends number)
|
||||
(int16_t value))
|
||||
(type boolean java/lang/Boolean)
|
||||
|
||||
(type char java/lang/Character
|
||||
(extends jobject)
|
||||
(uint16_t value))
|
||||
(type short java/lang/Short)
|
||||
|
||||
(type int java/lang/Integer
|
||||
(extends number)
|
||||
(int32_t value))
|
||||
(type char java/lang/Character)
|
||||
|
||||
(type long java/lang/Long
|
||||
(extends number)
|
||||
(int64_t value))
|
||||
(type int java/lang/Integer)
|
||||
|
||||
(type float java/lang/Float
|
||||
(extends number)
|
||||
(uint32_t value))
|
||||
(type long java/lang/Long)
|
||||
|
||||
(type double java/lang/Double
|
||||
(extends number)
|
||||
(uint64_t value))
|
||||
(type float java/lang/Float)
|
||||
|
||||
(type referenceQueue java/lang/ref/ReferenceQueue
|
||||
(extends jobject)
|
||||
(object front)
|
||||
(object rear))
|
||||
(type double java/lang/Double)
|
||||
|
||||
(type jreference java/lang/ref/Reference
|
||||
(extends jobject)
|
||||
(noassert nogc object next)
|
||||
(nogc object target)
|
||||
(nogc object queue)
|
||||
(object jnext))
|
||||
(type referenceQueue java/lang/ref/ReferenceQueue)
|
||||
|
||||
(type weakReference java/lang/ref/WeakReference
|
||||
(extends jreference))
|
||||
(type jreference java/lang/ref/Reference)
|
||||
|
||||
(type phantomReference java/lang/ref/PhantomReference
|
||||
(extends jreference))
|
||||
(type weakReference java/lang/ref/WeakReference)
|
||||
|
||||
(type phantomReference java/lang/ref/PhantomReference)
|
||||
|
||||
(type byteArray [B
|
||||
(extends jobject)
|
||||
|
@ -15,6 +15,8 @@ public class Misc {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
boolean v = Boolean.valueOf("true");
|
||||
|
||||
int a = 2;
|
||||
int b = 2;
|
||||
int c = a + b;
|
||||
|
Loading…
Reference in New Issue
Block a user