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