diff --git a/makefile b/makefile
index 01d78bb444..17a577ff08 100644
--- a/makefile
+++ b/makefile
@@ -1,7 +1,5 @@
#MAKEFLAGS = -s
-input = $(cls)/Hello.class
-
build-arch = $(shell uname -m)
ifeq ($(build-arch),i586)
build-arch = i386
@@ -24,12 +22,16 @@ process = interpret
mode = debug
-bld = build/$(platform)/$(arch)/$(mode)
-cls = build/classes
+build = build
+native-build = $(build)/$(platform)/$(arch)/$(mode)
+classpath-build = $(build)/classpath
+test-build = $(build)/test
src = src
classpath = classpath
test = test
+input = $(test-build)/Hello.class
+
build-cxx = g++
build-cc = gcc
@@ -44,6 +46,7 @@ vg = nice valgrind --suppressions=valgrind.supp --undef-value-errors=no \
--num-callers=32 --db-attach=yes --freelist-vol=100000000
db = gdb --args
javac = javac
+zip = zip
strip = :
show-size = :
@@ -54,8 +57,8 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter \
-Winit-self -Wconversion
common-cflags = $(warnings) -fno-rtti -fno-exceptions \
- -I$(JAVA_HOME)/include -idirafter $(src) -I$(bld) -D__STDC_LIMIT_MACROS \
- -D_JNI_IMPLEMENTATION_
+ -I$(JAVA_HOME)/include -idirafter $(src) -I$(native-build) \
+ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_
system = posix
asm = x86
@@ -116,18 +119,18 @@ endif
cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x)))
asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x)))
-java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(cls)/%.class,$(x)))
+java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x)))
jni-sources = $(shell find $(classpath) -name '*.cpp')
-jni-objects = $(call cpp-objects,$(jni-sources),$(classpath),$(bld))
+jni-objects = $(call cpp-objects,$(jni-sources),$(classpath),$(native-build))
jni-cflags = $(cflags)
generated-code = \
- $(bld)/type-enums.cpp \
- $(bld)/type-declarations.cpp \
- $(bld)/type-constructors.cpp \
- $(bld)/type-initializations.cpp \
- $(bld)/type-java-initializations.cpp
+ $(native-build)/type-enums.cpp \
+ $(native-build)/type-declarations.cpp \
+ $(native-build)/type-constructors.cpp \
+ $(native-build)/type-initializations.cpp \
+ $(native-build)/type-java-initializations.cpp
interpreter-depends = \
$(generated-code) \
@@ -158,63 +161,67 @@ ifeq ($(process),compile)
endif
interpreter-cpp-objects = \
- $(call cpp-objects,$(interpreter-sources),$(src),$(bld))
+ $(call cpp-objects,$(interpreter-sources),$(src),$(native-build))
interpreter-asm-objects = \
- $(call asm-objects,$(interpreter-asm-sources),$(src),$(bld))
+ $(call asm-objects,$(interpreter-asm-sources),$(src),$(native-build))
interpreter-objects = \
$(interpreter-cpp-objects) \
$(interpreter-asm-objects)
driver-sources = $(src)/main.cpp
-driver-objects = $(call cpp-objects,$(driver-sources),$(src),$(bld))
+driver-objects = $(call cpp-objects,$(driver-sources),$(src),$(native-build))
generator-headers = \
$(src)/input.h \
$(src)/output.h
-generator-sources = \
- $(src)/type-generator.cpp
-generator-objects = $(call cpp-objects,$(generator-sources),$(src),$(bld))
-generator-executable = $(bld)/generator
+generator-sources = $(src)/type-generator.cpp
+generator-objects = \
+ $(call cpp-objects,$(generator-sources),$(src),$(native-build))
+generator = $(native-build)/generator
-archive = $(bld)/libvm.a
-executable = $(bld)/vm
+bin2c-sources = $(src)/bin2c.cpp
+bin2c-objects = $(call cpp-objects,$(bin2c-sources),$(src),$(native-build))
+bin2c = $(native-build)/bin2c
+
+archive = $(native-build)/libvm.a
+interpreter = $(native-build)/vm
classpath-sources = $(shell find $(classpath) -name '*.java')
-classpath-classes = $(call java-classes,$(classpath-sources),$(classpath))
-
-classpath-objects = $(classpath-classes)
+classpath-classes = \
+ $(call java-classes,$(classpath-sources),$(classpath),$(classpath-build))
+classpath-object = $(native-build)/classpath.o
test-sources = $(shell find $(test) -name '*.java')
-test-classes = $(call java-classes,$(test-sources),$(test))
+test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
-class-name = $(patsubst $(cls)/%.class,%,$(1))
+class-name = $(patsubst $(1)/%.class,%,$(2))
class-names = $(foreach x,$(1),$(call class-name,$(x)))
-flags = -cp $(cls)
-args = $(flags) $(call class-name,$(input))
+flags = -cp $(test-build)
+args = $(flags) $(call class-name,$(test-build),$(input))
.PHONY: build
-build: $(executable) $(classpath-objects) $(test-classes)
+build: $(interpreter) $(classpath-classes) $(test-classes)
$(input): $(classpath-classes)
.PHONY: run
run: build
- $(executable) $(args)
+ $(interpreter) $(args)
.PHONY: debug
debug: build
- gdb --args $(executable) $(args)
+ gdb --args $(interpreter) $(args)
.PHONY: vg
vg: build
- $(vg) $(executable) $(args)
+ $(vg) $(interpreter) $(args)
.PHONY: test
test: build
/bin/bash $(test)/test.sh 2>/dev/null \
- $(executable) $(mode) "$(flags)" $(call class-names,$(test-classes))
+ $(interpreter) $(mode) "$(flags)" $(call class-names,$(test-classes))
.PHONY: clean
clean:
@@ -223,31 +230,39 @@ clean:
.PHONY: clean-native
clean-native:
- @echo "removing $(bld)"
- rm -rf $(bld)
+ @echo "removing $(native-build)"
+ rm -rf $(native-build)
-gen-arg = $(shell echo $(1) | sed -e 's:$(bld)/type-\(.*\)\.cpp:\1:')
-$(generated-code): %.cpp: $(src)/types.def $(generator-executable)
+gen-arg = $(shell echo $(1) | sed -e 's:$(native-build)/type-\(.*\)\.cpp:\1:')
+$(generated-code): %.cpp: $(src)/types.def $(generator)
@echo "generating $(@)"
@mkdir -p -m 1777 $(dir $(@))
- $(generator-executable) $(call gen-arg,$(@)) < $(<) > $(@)
+ $(generator) $(call gen-arg,$(@)) < $(<) > $(@)
-$(bld)/type-generator.o: \
+$(native-build)/type-generator.o: \
$(generator-headers)
define compile-class
@echo "compiling $(@)"
@mkdir -p -m 1777 $(dir $(@))
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
- -d $(cls) $(<)
+ -d $(1) $(<)
@touch $(@)
endef
-$(cls)/%.class: $(classpath)/%.java
- $(compile-class)
+$(classpath-build)/%.class: $(classpath)/%.java
+ @echo "compiling $(@)"
+ @mkdir -p -m 1777 $(dir $(@))
+ $(javac) -bootclasspath $(classpath) -classpath $(classpath) \
+ -d $(classpath-build) $(<)
+ @touch $(@)
-$(cls)/%.class: $(test)/%.java
- $(compile-class)
+$(test-build)/%.class: $(test)/%.java
+ @echo "compiling $(@)"
+ @mkdir -p -m 1777 $(dir $(@))
+ $(javac) -bootclasspath $(classpath) -classpath $(classpath) \
+ -d $(test-build) $(<)
+ @touch $(@)
define compile-object
@echo "compiling $(@)"
@@ -255,46 +270,66 @@ define compile-object
$(cxx) $(cflags) -c $(<) -o $(@)
endef
-$(interpreter-cpp-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends)
+$(interpreter-cpp-objects): \
+ $(native-build)/%.o: $(src)/%.cpp $(interpreter-depends)
$(compile-object)
-$(interpreter-asm-objects): $(bld)/%-asm.o: $(src)/%.S
+$(interpreter-asm-objects): $(native-build)/%-asm.o: $(src)/%.S
$(compile-object)
-$(driver-objects): $(bld)/%.o: $(src)/%.cpp
+$(driver-objects): $(native-build)/%.o: $(src)/%.cpp
$(compile-object)
-$(generator-objects): $(bld)/%.o: $(src)/%.cpp
+$(bin2c-objects): $(native-build)/%.o: $(src)/%.cpp
+ $(compile-object)
+
+$(build)/classpath.zip: $(classpath-classes)
+ echo $(classpath-classes)
+ wd=$$(pwd); \
+ cd $(classpath-build); \
+ $(zip) -q -0 $${wd}/$(@) $$(find -name '*.class'); \
+ cd -
+
+$(build)/classpath.c: $(build)/classpath.zip $(bin2c)
+ $(bin2c) $(<) vmClasspath >$(@)
+
+$(classpath-object): $(build)/classpath.c
+ $(cxx) $(cflags) -c $(<) -o $(@)
+
+$(generator-objects): $(native-build)/%.o: $(src)/%.cpp
@echo "compiling $(@)"
@mkdir -p -m 1777 $(dir $(@))
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) $(cflags) -c $(<) -o $(@)
-$(jni-objects): $(bld)/%.o: $(classpath)/%.cpp
+$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
@echo "compiling $(@)"
@mkdir -p -m 1777 $(dir $(@))
$(cxx) $(jni-cflags) -c $(<) -o $(@)
+$(archive): $(interpreter-objects) $(jni-objects) $(classpath-object)
ifeq ($(platform),windows)
-$(archive): $(interpreter-objects) $(jni-objects)
@echo "creating $(@)"
$(dlltool) -z $(@).def $(^)
$(dlltool) -k -d $(@).def -e $(@).exp
$(ar) cru $(@) $(@).exp $(^)
$(ranlib) $(@)
else
-$(archive): $(interpreter-objects) $(jni-objects)
@echo "creating $(@)"
$(ar) cru $(@) $(^)
$(ranlib) $(@)
endif
-$(executable): $(archive) $(driver-objects)
+$(interpreter): $(archive) $(driver-objects)
@echo "linking $(@)"
$(cc) $(begin-merge-archive) $(^) $(end-merge-archive) \
$(lflags) $(rdynamic) -o $(@)
@$(strip) --strip-all $(@)
@$(show-size) $(@)
-$(generator-executable): $(generator-objects)
+$(generator): $(generator-objects)
+ @echo "linking $(@)"
+ $(build-cc) $(^) -o $(@)
+
+$(bin2c): $(bin2c-objects)
@echo "linking $(@)"
$(build-cc) $(^) -o $(@)
diff --git a/src/bin2c.cpp b/src/bin2c.cpp
new file mode 100644
index 0000000000..970b90b0db
--- /dev/null
+++ b/src/bin2c.cpp
@@ -0,0 +1,62 @@
+#include "stdio.h"
+#include "stdint.h"
+#include "stdlib.h"
+
+namespace {
+
+void
+writeCode(FILE* in, FILE* out, const char* procedure)
+{
+ fprintf(out, "#ifdef __MINGW32__\n");
+ fprintf(out, "# define EXPORT __declspec(dllexport)\n");
+ fprintf(out, "#else\n");
+ fprintf(out, "# define EXPORT __attribute__"
+ "((visibility(\"default\")))\n");
+ fprintf(out, "#endif\n\n");
+
+ fprintf(out, "namespace { const unsigned char data[] = {\n");
+
+ const unsigned size = 4096;
+ uint8_t buffer[size];
+ while (not feof(in)) {
+ unsigned c = fread(buffer, 1, size, in);
+ for (unsigned i = 0; i < c; ++i) {
+ fprintf(out, "0x%x,", buffer[i]);
+ }
+ }
+
+ fprintf(out, "}; }\n\n");
+
+ fprintf(out, "extern \"C\" EXPORT const unsigned char*\n");
+ fprintf(out, "%s(unsigned* size)\n", procedure);
+ fprintf(out, "{\n");
+ fprintf(out, " *size = sizeof(data);\n");
+ fprintf(out, " return data;\n");
+ fprintf(out, "}\n");
+}
+
+void
+usageAndExit(const char* name)
+{
+ fprintf(stderr, "usage: %s \n", name);
+ exit(-1);
+}
+
+} // namespace
+
+int
+main(int ac, const char** av)
+{
+ if (ac != 3) {
+ usageAndExit(av[0]);
+ }
+
+ FILE* in = fopen(av[1], "rb");
+ if (in) {
+ writeCode(in, stdout, av[2]);
+ fclose(in);
+ } else {
+ fprintf(stderr, "trouble opening %s\n", av[1]);
+ exit(-1);
+ }
+}
diff --git a/src/compile.cpp b/src/compile.cpp
index 0f84841d04..d3b6582911 100644
--- a/src/compile.cpp
+++ b/src/compile.cpp
@@ -4881,7 +4881,10 @@ class MyProcessor: public Processor {
virtual Thread*
makeThread(Machine* m, object javaThread, Thread* parent)
{
- return new (s->allocate(sizeof(MyThread))) MyThread(m, javaThread, parent);
+ MyThread* t = new (s->allocate(sizeof(Thread)))
+ MyThread(m, javaThread, parent);
+ t->init();
+ return t;
}
virtual void*
diff --git a/src/finder.cpp b/src/finder.cpp
index c742006da0..0510c0d52d 100644
--- a/src/finder.cpp
+++ b/src/finder.cpp
@@ -325,13 +325,13 @@ class JarIndex {
class JarElement: public Element {
public:
JarElement(System* s, const char* name):
- s(s), name(name), region(0), index(0)
+ s(s), name(name), index(0)
{ }
- void init() {
+ virtual void init() {
if (index == 0) {
System::Region* r;
- if (s->success(s->map(&r, this->name))) {
+ if (s->success(s->map(&r, name))) {
region = r;
index = JarIndex::open(s, r);
}
@@ -358,6 +358,8 @@ class JarElement: public Element {
s->free(name);
if (index) {
index->dispose();
+ }
+ if (region) {
region->dispose();
}
s->free(this);
@@ -369,6 +371,35 @@ class JarElement: public Element {
JarIndex* index;
};
+class BuiltinElement: public JarElement {
+ public:
+ BuiltinElement(System* s, const char* name):
+ JarElement(s, name)
+ { }
+
+ virtual void init() {
+ if (index == 0) {
+ System::Library* library;
+ if (s->success(s->load(&library, 0, false, 0))) {
+ void* p = library->resolve(name);
+ if (p) {
+ uint8_t* (*function)(unsigned*);
+ memcpy(&function, &p, BytesPerWord);
+
+ unsigned size;
+ uint8_t* data = function(&size);
+ if (data) {
+ region = new (s->allocate(sizeof(PointerRegion)))
+ PointerRegion(s, data, size);
+ index = JarIndex::open(s, region);
+ }
+ }
+ library->dispose();
+ }
+ }
+ }
+};
+
Element*
parsePath(System* s, const char* path)
{
@@ -403,26 +434,34 @@ parsePath(System* s, const char* path)
Element* prev = 0;
for (Tokenizer t(path, s->pathSeparator()); t.hasMore();) {
Tokenizer::Token token(t.next());
- char* name = static_cast(s->allocate(token.length + 1));
- memcpy(name, token.s, token.length);
- name[token.length] = 0;
Element* e;
- switch (s->identify(name)) {
- case System::File: {
- e = new (s->allocate(sizeof(JarElement)))
- JarElement(s, name);
- } break;
+ if (*token.s == '[' and token.s[token.length - 1] == ']') {
+ char* name = static_cast(s->allocate(token.length - 1));
+ memcpy(name, token.s + 1, token.length - 1);
+ name[token.length - 2] = 0;
+
+ e = new (s->allocate(sizeof(BuiltinElement))) BuiltinElement(s, name);
+ } else {
+ char* name = static_cast(s->allocate(token.length + 1));
+ memcpy(name, token.s, token.length);
+ name[token.length] = 0;
- case System::Directory: {
- e = new (s->allocate(sizeof(DirectoryElement)))
- DirectoryElement(s, name);
- } break;
+ switch (s->identify(name)) {
+ case System::File: {
+ e = new (s->allocate(sizeof(JarElement))) JarElement(s, name);
+ } break;
- default: {
- s->free(name);
- e = 0;
- } break;
+ case System::Directory: {
+ e = new (s->allocate(sizeof(DirectoryElement)))
+ DirectoryElement(s, name);
+ } break;
+
+ default: {
+ s->free(name);
+ e = 0;
+ } break;
+ }
}
if (e) {
diff --git a/src/interpret.cpp b/src/interpret.cpp
index 4aa2b747e5..50ed9f9677 100644
--- a/src/interpret.cpp
+++ b/src/interpret.cpp
@@ -2870,7 +2870,10 @@ class MyProcessor: public Processor {
virtual vm::Thread*
makeThread(Machine* m, object javaThread, vm::Thread* parent)
{
- return new (s->allocate(sizeof(Thread))) Thread(m, javaThread, parent);
+ Thread* t = new (s->allocate(sizeof(Thread)))
+ Thread(m, javaThread, parent);
+ t->init();
+ return t;
}
virtual void*
diff --git a/src/jnienv.cpp b/src/jnienv.cpp
index 4084800e82..0c1c20530b 100644
--- a/src/jnienv.cpp
+++ b/src/jnienv.cpp
@@ -1842,6 +1842,7 @@ JNI_GetDefaultJavaVMInitArgs(void* args)
}
#define BUILTINS_PROPERTY "vm.builtins"
+#define BUILTIN_CLASSPATH "[vmClasspath]"
extern "C" JNIEXPORT jint JNICALL
JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
@@ -1849,7 +1850,13 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
JDK1_1InitArgs* a = static_cast(args);
System* s = makeSystem(a->maxHeapSize);
- Finder* f = makeFinder(s, a->classpath);
+
+ unsigned size = sizeof(BUILTIN_CLASSPATH) + 1 + strlen(a->classpath);
+ char classpath[size];
+ snprintf(classpath, size, "%s%c%s",
+ BUILTIN_CLASSPATH, s->pathSeparator(), a->classpath);
+
+ Finder* f = makeFinder(s, classpath);
Heap* h = makeHeap(s);
Processor* p = makeProcessor(s);
diff --git a/src/machine.cpp b/src/machine.cpp
index e004be98c0..4afc085dd5 100644
--- a/src/machine.cpp
+++ b/src/machine.cpp
@@ -1394,7 +1394,6 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
weakReferences(0),
tenuredWeakReferences(0),
unsafe(false),
- active(false),
heapPoolIndex(0)
{
populateJNITables(&javaVMVTable, &jniEnvVTable);
@@ -1451,6 +1450,10 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
#ifdef VM_STRESS
, stress(false)
#endif // VM_STRESS
+{ }
+
+void
+Thread::init()
{
if (parent == 0) {
assert(this, m->rootThread == 0);
@@ -1458,7 +1461,6 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
m->rootThread = this;
m->unsafe = true;
- m->active = false;
if (not m->system->success(m->system->attach(&runnable))) {
abort(this);
@@ -1554,7 +1556,6 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
if (parent == 0) {
enter(this, Thread::IdleState);
- m->active = true;
}
}
diff --git a/src/machine.h b/src/machine.h
index 21c2f16b9b..4b0840ea2a 100644
--- a/src/machine.h
+++ b/src/machine.h
@@ -1148,7 +1148,6 @@ class Machine {
object weakReferences;
object tenuredWeakReferences;
bool unsafe;
- bool active;
JavaVMVTable javaVMVTable;
JNIEnvVTable jniEnvVTable;
uintptr_t* heapPool[HeapPoolSize];
@@ -1242,6 +1241,7 @@ class Thread {
Thread(Machine* m, object javaThread, Thread* parent);
+ void init();
void exit();
void dispose();
diff --git a/src/main.cpp b/src/main.cpp
index fe78006bc2..db062ae8df 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,5 @@
#include "stdlib.h"
+#include "stdio.h"
#include "string.h"
#include "jni.h"
diff --git a/src/type-generator.cpp b/src/type-generator.cpp
index 045157aa75..df16cd50df 100644
--- a/src/type-generator.cpp
+++ b/src/type-generator.cpp
@@ -1426,7 +1426,13 @@ writeConstructors(Output* out, Object* declarations)
out->write(" PROTECT(t, e);\n");
out->write("#endif\n");
out->write(" resolveClass(t, className(t, class__));\n");
- out->write(" assert(t, t->exception == e);\n");
+
+ if (equal("classNotFoundException", typeName(o))) {
+ out->write(" t->exception = 0;\n");
+ } else {
+ out->write(" assert(t, t->exception == e);\n");
+ }
+
out->write(" }\n");
}