clean up bootstrap type generation to eliminate redundancy (broken)

This commit is contained in:
Joel Dice 2007-11-04 14:15:28 -07:00
parent bea4a73f54
commit 94e9bd0fd2
20 changed files with 755 additions and 571 deletions

View File

@ -0,0 +1,11 @@
package java.lang;
public class ArrayStoreException extends RuntimeException {
public ArrayStoreException(String message) {
super(message, null);
}
public ArrayStoreException() {
this(null);
}
}

View File

@ -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);
}

View File

@ -0,0 +1,11 @@
package java.lang;
public class ExceptionInInitializerError extends Error {
public ExceptionInInitializerError(String message) {
super(message);
}
public ExceptionInInitializerError() {
super();
}
}

View File

@ -0,0 +1,11 @@
package java.lang;
public class IllegalMonitorStateException extends RuntimeException {
public IllegalMonitorStateException(String message) {
super(message, null);
}
public IllegalMonitorStateException() {
this(null);
}
}

View File

@ -0,0 +1,11 @@
package java.lang;
public class NoSuchMethodError extends IncompatibleClassChangeError {
public NoSuchMethodError(String message) {
super(message);
}
public NoSuchMethodError() {
super();
}
}

View File

@ -0,0 +1,11 @@
package java.lang;
public class StackOverflowError extends Error {
public StackOverflowError(String message) {
super(message, null);
}
public StackOverflowError() {
this(null);
}
}

View File

@ -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) {

View File

@ -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() {

View File

@ -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;
}

View File

@ -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 $(@)"

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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*

View File

@ -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);
}

View File

@ -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)

View File

@ -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;