From d0a6096eb0452480a8612b4cb8a61379d1dc7936 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 5 Nov 2010 13:18:28 -0600 Subject: [PATCH] add support for accessing embedded JARs as if they were directories This allows OpenJDK to access time zone data which is normally found under java.home, but which we must embed in the executable itself to create a self-contained build. The VM intercepts various file operations, looking for paths which start with a prefix specified by the avian.embed.prefix property and redirecting those operations to an embedded JAR. For example, if avian.embed.prefix is "/avian-embedded", and code calls File.exists() with a path of "/avian-embedded/javahomeJar/foo.txt", the VM looks for a function named javahomeJar via dlsym, calls the function to find the memory region containing the embeded JAR, and finally consults the JAR to see if the file "foo.txt" exists. --- makefile | 53 ++-- src/boot.cpp | 30 +++ src/builtin.cpp | 5 +- src/classpath-avian.cpp | 2 +- src/classpath-openjdk.cpp | 510 +++++++++++++++++++++++++++++++------- src/compile.cpp | 2 +- src/finder.cpp | 269 +++++++++++++------- src/finder.h | 10 +- src/jnienv.cpp | 12 +- src/machine.cpp | 21 +- src/machine.h | 9 +- src/posix.cpp | 8 +- src/system.h | 2 +- src/type-generator.cpp | 26 +- src/types.def | 9 + src/util.cpp | 21 +- src/util.h | 3 + test/Misc.java | 2 + 18 files changed, 773 insertions(+), 221 deletions(-) diff --git a/makefile b/makefile index edaecb7ff8..5214d37f0e 100644 --- a/makefile +++ b/makefile @@ -52,25 +52,29 @@ classpath = avian test-executable = $(executable) boot-classpath = $(classpath-build) -java-home = /avian-embedded +embed-prefix = /avian-embedded ifdef openjdk ifdef openjdk-src include openjdk-src.mk options := $(options)-openjdk-src classpath-objects = $(openjdk-objects) - classpath-cflags = -DAVIAN_OPENJDK_SRC + classpath-cflags = -DAVIAN_OPENJDK_SRC -DBOOT_JAVAHOME openjdk-jar-dep = $(build)/openjdk-jar.dep classpath-jar-dep = $(openjdk-jar-dep) + javahome = $(embed-prefix)/javahomeJar + javahome-files = lib/zi + javahome-object = $(build)/javahome-jar.o else options := $(options)-openjdk test-executable = $(executable-dynamic) library-path = LD_LIBRARY_PATH=$(build) - java-home = $(openjdk)/jre + javahome = $(openjdk)/jre endif classpath = openjdk boot-classpath := $(boot-classpath):$(openjdk)/jre/lib/rt.jar + build-javahome = $(openjdk)/jre endif ifeq ($(classpath),avian) @@ -120,7 +124,8 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \ common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \ "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) $(classpath-cflags) \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ - -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(java-home)\" + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread @@ -593,12 +598,6 @@ $(driver-dynamic-object): $(driver-source) $(boot-object): $(boot-source) $(compile-object) -$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) - @echo "creating $(@)" - (wd=$$(pwd) && \ - cd $(classpath-build) && \ - $(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .) - $(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp $(build-cxx) -c $(^) -o $(@) @@ -620,11 +619,28 @@ $(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp $(converter): $(converter-objects) $(build-cxx) $(^) -o $(@) +$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) + @echo "creating $(@)" + (wd=$$(pwd) && \ + cd $(classpath-build) && \ + $(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .) + $(classpath-object): $(build)/classpath.jar $(converter) @echo "creating $(@)" $(converter) $(<) $(@) _binary_classpath_jar_start \ _binary_classpath_jar_end $(platform) $(arch) +$(build)/javahome.jar: $(foreach x,$(javahome-files),$(build-javahome)/$(x)) + @echo "creating $(@)" + (wd=$$(pwd) && \ + cd $(build-javahome) && \ + $(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $(javahome-files)) + +$(javahome-object): $(build)/javahome.jar $(converter) + @echo "creating $(@)" + $(converter) $(<) $(@) _binary_javahome_jar_start \ + _binary_javahome_jar_end $(platform) $(arch) + $(generator-objects): $(generator-depends) $(generator-objects): $(build)/%-build.o: $(src)/%.cpp @echo "compiling $(@)" @@ -651,7 +667,8 @@ $(bootimage-object): $(bootimage-bin) $(converter) writable executable executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ - $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) + $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \ + $(javahome-object) $(executable): $(executable-objects) @echo "linking $(@)" @@ -696,18 +713,16 @@ else $(ld) $(^) $(rdynamic) $(lflags) -o $(@) endif -dynamic-library-objects = $(vm-objects) $(dynamic-object) \ - $(classpath-objects) $(vm-heapwalk-objects) $(boot-object) \ - $(vm-classpath-object) $(classpath-libraries) - -$(dynamic-library): $(dynamic-library-objects) +$(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ + $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \ + $(classpath-libraries) $(javahome-object) @echo "linking $(@)" ifdef msvc - $(ld) $(shared) $(lflags) $(dynamic-library-objects) -out:$(@) \ - -PDB:$(@).pdb -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest + $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ + -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest $(mt) -manifest $(@).manifest -outputresource:"$(@);2" else - $(ld) $(dynamic-library-objects) -Wl,--version-script=openjdk.ld \ + $(ld) $(^) -Wl,--version-script=openjdk.ld \ $(shared) $(lflags) $(bootimage-lflags) -o $(@) endif $(strip) $(strip-all) $(@) diff --git a/src/boot.cpp b/src/boot.cpp index 186cf4745f..f6a1cd8d20 100644 --- a/src/boot.cpp +++ b/src/boot.cpp @@ -52,6 +52,8 @@ extern "C" { } +#undef SYMBOL + #endif//BOOT_IMAGE #ifdef BOOT_CLASSPATH @@ -76,4 +78,32 @@ extern "C" { } +#undef SYMBOL + #endif//BOOT_CLASSPATH + +#ifdef BOOT_JAVAHOME + +#if (defined __MINGW32__) || (defined _MSC_VER) +# define SYMBOL(x) binary_javahome_jar_##x +#else +# define SYMBOL(x) _binary_javahome_jar_##x +#endif + +extern "C" { + + extern const uint8_t SYMBOL(start)[]; + extern const uint8_t SYMBOL(end)[]; + + EXPORT const uint8_t* + javahomeJar(unsigned* size) + { + *size = SYMBOL(end) - SYMBOL(start); + return SYMBOL(start); + } + +} + +#undef SYMBOL + +#endif//BOOT_JAVAHOME diff --git a/src/builtin.cpp b/src/builtin.cpp index f113bd5ead..75de37c759 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -85,8 +85,9 @@ Avian_avian_SystemClassLoader_resourceExists RUNTIME_ARRAY(char, n, stringLength(t, name) + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); - bool r = static_cast(systemClassLoaderFinder(t, loader))->exists - (RUNTIME_ARRAY_BODY(n)); + unsigned length; + bool r = static_cast(systemClassLoaderFinder(t, loader))->stat + (RUNTIME_ARRAY_BODY(n), &length) == System::TypeFile; // fprintf(stderr, "resource %s exists? %d\n", n, r); diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 13bbf44f41..aacfb7e9d5 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -128,7 +128,7 @@ enumerateThreads(Thread* t, Thread* x, object array, unsigned* index, namespace vm { Classpath* -makeClasspath(System*, Allocator* allocator, const char*) +makeClasspath(System*, Allocator* allocator, const char*, const char*) { return new (allocator->allocate(sizeof(local::MyClasspath))) local::MyClasspath(allocator); diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index c6f6949380..f3eb91ec59 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -88,6 +88,7 @@ namespace local { const unsigned InterfaceVersion = 4; const unsigned PageSize = 4 * 1024; +const int VirtualFileBase = 1000000000; Machine* globalMachine; @@ -145,7 +146,6 @@ makeClassNameString(Thread* t, object name) return makeString(t, "%s", s); } -#ifdef AVIAN_OPENJDK_SRC // only safe to call during bootstrap when there's only one thread // running: void @@ -171,51 +171,20 @@ intercept(Thread* t, object c, const char* name, const char* spec, } } -const char* -zipLibrary(Thread*); - int64_t JNICALL getFileAttributes -(Thread* t, object method, uintptr_t* arguments) -{ - const unsigned Exists = 1; - const unsigned Regular = 2; +(Thread* t, object method, uintptr_t* arguments); - object file = reinterpret_cast(arguments[1]); - - object pathField = findFieldInClass2 - (t, objectClass(t, file), "path", "Ljava/lang/String;"); - - if (pathField) { - object path = cast(file, fieldOffset(t, pathField)); - - RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); - stringChars(t, path, RUNTIME_ARRAY_BODY(p)); - - if (strcmp(zipLibrary(t), p) == 0) { - return Exists | Regular; - } else { - object r = t->m->processor->invoke - (t, nativeInterceptOriginal(t, methodCode(t, method)), - reinterpret_cast(arguments[0]), file); - return (r ? intValue(t, r) : 0); - } - } else { - object message = makeString - (t, "path Ljava/lang/String; not found in %s", - &byteArrayBody(t, className(t, objectClass(t, file)), 0)); - t->exception = t->m->classpath->makeThrowable - (t, Machine::RuntimeExceptionType, message); - return 0; - } -} -#endif // AVIAN_OPENJDK_SRC +int64_t JNICALL +getLength +(Thread* t, object method, uintptr_t* arguments); class MyClasspath : public Classpath { public: static const unsigned BufferSize = 1024; - MyClasspath(System* s, Allocator* allocator, const char* javaHome): + MyClasspath(System* s, Allocator* allocator, const char* javaHome, + const char* embedPrefix): allocator(allocator) { class StringBuilder { @@ -285,6 +254,11 @@ class MyClasspath : public Classpath { sb.append(LIBRARY_PREFIX); sb.append("zip"); sb.append(LIBRARY_SUFFIX); + sb.append('\0'); + + this->embedPrefix = sb.pointer; + sb.append(embedPrefix); + this->embedPrefixLength = sb.pointer - this->embedPrefix; } virtual object @@ -377,13 +351,32 @@ class MyClasspath : public Classpath { globalMachine = t->m; #ifdef AVIAN_OPENJDK_SRC - { object c = resolveClass + { object ufsClass = resolveClass (t, root(t, Machine::BootLoader), "java/io/UnixFileSystem"); - if (c) { - intercept(t, c, "getBooleanAttributes0", "(Ljava/io/File;)I", - voidPointer(getFileAttributes)); + if (ufsClass) { + PROTECT(t, ufsClass); + + object fileClass = resolveClass + (t, root(t, Machine::BootLoader), "java/io/File"); + + if (fileClass) { + object pathField = findFieldInClass2 + (t, fileClass, "path", "Ljava/lang/String;"); + + if (pathField) { + this->pathField = fieldOffset(t, pathField); + + intercept(t, ufsClass, "getBooleanAttributes0", + "(Ljava/io/File;)I", voidPointer(getFileAttributes)); + + intercept(t, ufsClass, "getLength", "(Ljava/io/File;)J", + voidPointer(getLength)); + } + } } + + if (UNLIKELY(t->exception)) return; } #else // not AVIAN_OPENJDK_SRC if (loadLibrary(t, libraryPath, "java", true, true) == 0) { @@ -437,7 +430,7 @@ class MyClasspath : public Classpath { virtual void dispose() - { + { allocator->free(this, sizeof(*this)); } @@ -446,33 +439,202 @@ class MyClasspath : public Classpath { const char* classpath; const char* libraryPath; const char* zipLibrary; + const char* embedPrefix; + unsigned embedPrefixLength; + unsigned pathField; char buffer[BufferSize]; }; -struct JVM_ExceptionTableEntryType{ - jint start_pc; - jint end_pc; - jint handler_pc; - jint catchType; +struct JVM_ExceptionTableEntryType { + jint start_pc; + jint end_pc; + jint handler_pc; + jint catchType; }; struct jvm_version_info { - unsigned int jvm_version; - unsigned int update_version: 8; - unsigned int special_update_version: 8; - unsigned int reserved1: 16; - unsigned int reserved2; - unsigned int is_attach_supported: 1; - unsigned int is_kernel_jvm: 1; - unsigned int: 30; - unsigned int: 32; - unsigned int: 32; + unsigned jvm_version; + unsigned update_version: 8; + unsigned special_update_version: 8; + unsigned reserved1: 16; + unsigned reserved2; + unsigned is_attach_supported: 1; + unsigned is_kernel_jvm: 1; + unsigned: 30; + unsigned: 32; + unsigned: 32; }; -const char* -zipLibrary(Thread* t) +Finder* +getFinder(Thread* t, const char* name, unsigned nameLength) { - return static_cast(t->m->classpath)->zipLibrary; + ACQUIRE(t, t->m->referenceLock); + + for (object p = root(t, Machine::VirtualFileFinders); + p; p = finderNext(t, p)) + { + if (byteArrayLength(t, finderName(t, p)) == nameLength + and strncmp(reinterpret_cast + (&byteArrayBody(t, finderName(t, p), 0)), + name, nameLength)) + { + return static_cast(finderFinder(t, p)); + } + } + + object n = makeByteArray(t, nameLength + 1); + memcpy(&byteArrayBody(t, n, 0), name, nameLength); + + void* p = t->m->libraries->resolve + (reinterpret_cast(&byteArrayBody(t, n, 0))); + if (p) { + uint8_t* (*function)(unsigned*); + memcpy(&function, &p, BytesPerWord); + + unsigned size; + uint8_t* data = function(&size); + if (data) { + Finder* f = makeFinder(t->m->system, t->m->heap, data, size); + object finder = makeFinder + (t, f, n, root(t, Machine::VirtualFileFinders)); + + setRoot(t, Machine::VirtualFileFinders, finder); + + return f; + } + } + + return 0; +} + +class EmbeddedFile { + public: + EmbeddedFile(MyClasspath* cp, const char* path, unsigned pathLength) { + if (strncmp(cp->embedPrefix, path, cp->embedPrefixLength) == 0) { + const char* p = path + cp->embedPrefixLength; + while (*p == '/') ++ p; + + this->jar = p; + + if (*p == 0) { + this->jarLength = 0; + this->path = 0; + this->pathLength = 0; + return; + } + + while (*p and *p != '/') ++p; + + this->jarLength = p - this->jar; + + while (*p == '/') ++p; + + this->path = p; + this->pathLength = pathLength - (p - path); + } else { + this->jar = 0; + this->jarLength =0; + this->path = 0; + this->pathLength = 0; + } + } + + const char* jar; + const char* path; + unsigned jarLength; + unsigned pathLength; +}; + +int64_t JNICALL +getFileAttributes +(Thread* t, object method, uintptr_t* arguments) +{ + const unsigned Exists = 1; + const unsigned Regular = 2; + const unsigned Directory = 4; + + MyClasspath* cp = static_cast(t->m->classpath); + + object file = reinterpret_cast(arguments[1]); + object path = cast(file, cp->pathField); + + RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + + if (strcmp(cp->zipLibrary, RUNTIME_ARRAY_BODY(p)) == 0) { + return Exists | Regular; + } else { + EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path)); + if (ef.jar) { + if (ef.jarLength == 0) { + return Exists | Directory; + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder) { + if (ef.pathLength == 0) { + return Exists | Directory; + } + + unsigned length; + System::FileType type = finder->stat(ef.path, &length, true); + switch (type) { + case System::TypeUnknown: return Exists; + case System::TypeDoesNotExist: return 0; + case System::TypeFile: return Exists | Regular; + case System::TypeDirectory: return Exists | Directory; + default: abort(t); + } + } else { + return 0; + } + } else { + object r = t->m->processor->invoke + (t, nativeInterceptOriginal(t, methodCode(t, method)), + reinterpret_cast(arguments[0]), file); + + return (r ? intValue(t, r) : 0); + } + } +} + +int64_t JNICALL +getLength +(Thread* t, object method, uintptr_t* arguments) +{ + MyClasspath* cp = static_cast(t->m->classpath); + + object file = reinterpret_cast(arguments[1]); + object path = cast(file, cp->pathField); + + RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + + EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path)); + if (ef.jar) { + if (ef.jarLength == 0) { + return 0; + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder) { + if (ef.pathLength == 0) { + return 0; + } + + unsigned fileLength; + finder->stat(ef.path, &fileLength); + return fileLength; + } + + return 0; + } else { + object r = t->m->processor->invoke + (t, nativeInterceptOriginal(t, methodCode(t, method)), + reinterpret_cast(arguments[0]), file); + + return (r ? longValue(t, r) : 0); + } } unsigned @@ -735,10 +897,11 @@ interruptLock(Thread* t, object thread) namespace vm { Classpath* -makeClasspath(System* s, Allocator* allocator, const char* javaHome) +makeClasspath(System* s, Allocator* allocator, const char* javaHome, + const char* embedPrefix) { return new (allocator->allocate(sizeof(local::MyClasspath))) - local::MyClasspath(s, allocator, javaHome); + local::MyClasspath(s, allocator, javaHome, embedPrefix); } } // namespace vm @@ -1308,7 +1471,9 @@ JVM_LoadLibrary(const char* name) Thread* t = static_cast(local::globalMachine->localThread->get()); #ifdef AVIAN_OPENJDK_SRC - if (strcmp(local::zipLibrary(t), name) == 0) { + if (strcmp(static_cast(t->m->classpath)->zipLibrary, + name) == 0) + { return t->m->libraries; } #endif // AVIAN_OPENJDK_SRC @@ -2475,21 +2640,126 @@ JVM_NativePath(char* path) } extern "C" JNIEXPORT jint JNICALL -JVM_Open(const char* name, jint flags, jint mode) +JVM_Open(const char* path, jint flags, jint mode) { - return OPEN(name, flags, mode); + Thread* t = static_cast(local::globalMachine->localThread->get()); + local::MyClasspath* cp = static_cast(t->m->classpath); + + local::EmbeddedFile ef(cp, path, strlen(path)); + if (ef.jar) { + if (flags != O_RDONLY) { + errno = EACCES; + return -1; + } + + if (ef.jarLength == 0 or ef.pathLength == 0) { + errno = ENOENT; + return -1; + } + + Finder* finder = local::getFinder(t, ef.jar, ef.jarLength); + if (finder == 0) { + errno = ENOENT; + return -1; + } + + System::Region* r = finder->find(ef.path); + if (r == 0) { + errno = ENOENT; + return -1; + } + + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->m->referenceLock); + + int index = -1; + unsigned oldLength = root(t, Machine::VirtualFiles) + ? arrayLength(t, root(t, Machine::VirtualFiles)) : 0; + + for (unsigned i = 0; i < oldLength; ++i) { + if (arrayBody(t, root(t, Machine::VirtualFiles), i) == 0) { + index = i; + break; + } + } + + if (index == -1) { + object newArray = growArray(t, root(t, Machine::VirtualFiles)); + setRoot(t, Machine::VirtualFiles, newArray); + index = oldLength; + } + + object region = makeRegion(t, r, 0); + set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord), + region); + + return index + local::VirtualFileBase; + } else { + int r = OPEN(path, flags, mode); + expect(t, r < local::VirtualFileBase); + return r; + } } extern "C" JNIEXPORT jint JNICALL JVM_Close(jint fd) { - return CLOSE(fd); + if (fd >= local::VirtualFileBase) { + Thread* t = static_cast(local::globalMachine->localThread->get()); + unsigned index = fd - local::VirtualFileBase; + + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->m->referenceLock); + + object region = arrayBody(t, root(t, Machine::VirtualFiles), index); + if (region) { + static_cast(regionRegion(t, region))->dispose(); + } + + set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord), + 0); + + return 0; + } else { + return CLOSE(fd); + } } extern "C" JNIEXPORT jint JNICALL JVM_Read(jint fd, char* dst, jint length) { - return READ(fd, dst, length); + if (fd >= local::VirtualFileBase) { + Thread* t = static_cast(local::globalMachine->localThread->get()); + unsigned index = fd - local::VirtualFileBase; + + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->m->referenceLock); + + object region = arrayBody(t, root(t, Machine::VirtualFiles), index); + if (region) { + System::Region* r = static_cast + (regionRegion(t, region)); + + int available = r->length() - regionPosition(t, region); + if (length > available) { + length = available; + } + + memcpy(dst, r->start(), length); + + regionPosition(t, region) += length; + + return length; + } else { + errno = EINVAL; + return -1; + } + } else { + return READ(fd, dst, length); + } } extern "C" JNIEXPORT jint JNICALL @@ -2501,34 +2771,94 @@ JVM_Write(jint fd, char* src, jint length) extern "C" JNIEXPORT jint JNICALL JVM_Available(jint fd, jlong* result) { - struct stat buffer; - int n; - if (FSTAT(fd, &buffer) >= 0 - and (S_ISCHR(buffer.st_mode) - or S_ISFIFO(buffer.st_mode) - or S_ISSOCK(buffer.st_mode)) - and ioctl(fd, FIONREAD, &n) >= 0) - { - *result = n; + if (fd >= local::VirtualFileBase) { + Thread* t = static_cast(local::globalMachine->localThread->get()); + unsigned index = fd - local::VirtualFileBase; + + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->m->referenceLock); + + object region = arrayBody(t, root(t, Machine::VirtualFiles), index); + if (region) { + return static_cast(regionRegion(t, region))->length() + - regionPosition(t, region); + } else { + return 0; + } + } else { + struct stat buffer; + int n; + if (FSTAT(fd, &buffer) >= 0 + and (S_ISCHR(buffer.st_mode) + or S_ISFIFO(buffer.st_mode) + or S_ISSOCK(buffer.st_mode)) + and ioctl(fd, FIONREAD, &n) >= 0) + { + *result = n; + return 1; + } + + int current = LSEEK(fd, 0, SEEK_CUR); + if (current == -1) return 0; + + int end = LSEEK(fd, 0, SEEK_END); + if (end == -1) return 0; + + if (LSEEK(fd, current, SEEK_SET) == -1) return 0; + + *result = end - current; return 1; } - - int current = LSEEK(fd, 0, SEEK_CUR); - if (current == -1) return 0; - - int end = LSEEK(fd, 0, SEEK_END); - if (end == -1) return 0; - - if (LSEEK(fd, current, SEEK_SET) == -1) return 0; - - *result = end - current; - return 1; } extern "C" JNIEXPORT jlong JNICALL -JVM_Lseek(jint fd, jlong offset, jint start) +JVM_Lseek(jint fd, jlong offset, jint seek) { - return LSEEK(fd, offset, start); + if (fd >= local::VirtualFileBase) { + Thread* t = static_cast(local::globalMachine->localThread->get()); + unsigned index = fd - local::VirtualFileBase; + + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->m->referenceLock); + + object region = arrayBody(t, root(t, Machine::VirtualFiles), index); + if (region) { + System::Region* r = static_cast + (regionRegion(t, region)); + + switch (seek) { + case SEEK_SET: + break; + + case SEEK_CUR: + offset += regionPosition(t, region); + break; + + case SEEK_END: + offset += r->length(); + break; + + default: + errno = EINVAL; + return -1; + } + + if (offset >= 0 and offset <= static_cast(r->length())) { + regionPosition(t, region) = offset; + return offset; + } else { + errno = EINVAL; + return -1; + } + } else { + errno = EINVAL; + return -1; + } + } else { + return LSEEK(fd, offset, seek); + } } extern "C" JNIEXPORT jint JNICALL diff --git a/src/compile.cpp b/src/compile.cpp index 280cb3f2fc..b9858a1b71 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -7156,7 +7156,7 @@ class SegFaultHandler: public System::SignalHandler { t->exception = root(t, Machine::NullPointerException); } -// printTrace(t, t->exception); + printTrace(t, t->exception); object continuation; findUnwindTarget(t, ip, base, stack, &continuation); diff --git a/src/finder.cpp b/src/finder.cpp index 4e0fa64166..17e9078243 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -20,12 +20,12 @@ namespace { const bool DebugFind = false; const char* -append(System* s, const char* a, const char* b, const char* c) +append(Allocator* allocator, const char* a, const char* b, const char* c) { unsigned al = strlen(a); unsigned bl = strlen(b); unsigned cl = strlen(c); - char* p = static_cast(allocate(s, (al + bl + cl) + 1)); + char* p = static_cast(allocator->allocate((al + bl + cl) + 1)); memcpy(p, a, al); memcpy(p + al, b, bl); memcpy(p + al + bl, c, cl + 1); @@ -33,10 +33,10 @@ append(System* s, const char* a, const char* b, const char* c) } const char* -copy(System* s, const char* a) +copy(Allocator* allocator, const char* a) { unsigned al = strlen(a); - char* p = static_cast(allocate(s, al + 1)); + char* p = static_cast(allocator->allocate(al + 1)); memcpy(p, a, al + 1); return p; } @@ -63,7 +63,8 @@ class Element { virtual Iterator* iterator() = 0; virtual System::Region* find(const char* name) = 0; - virtual bool exists(const char* name) = 0; + virtual System::FileType stat(const char* name, unsigned* length, + bool tryDirectory) = 0; virtual void dispose() = 0; Element* next; @@ -73,8 +74,9 @@ class DirectoryElement: public Element { public: class Iterator: public Element::Iterator { public: - Iterator(System* s, const char* name, unsigned skip): - s(s), name(name), skip(skip), directory(0), last(0), it(0) + Iterator(System* s, Allocator* allocator, const char* name, unsigned skip): + s(s), allocator(allocator), name(name), skip(skip), directory(0), + last(0), it(0) { if (not s->success(s->open(&directory, name))) { directory = 0; @@ -93,15 +95,17 @@ class DirectoryElement: public Element { } if (last) { - s->free(last); + allocator->free(last, strlen(last) + 1); } if (directory) { for (const char* v = directory->next(); v; v = directory->next()) { if (v[0] != '.') { - last = append(s, name, "/", v); - if (s->identify(last) == System::TypeDirectory) { - it = new (allocate(s, sizeof(Iterator))) Iterator(s, last, skip); + last = append(allocator, name, "/", v); + unsigned length; + if (s->stat(last, &length) == System::TypeDirectory) { + it = new (allocator->allocate(sizeof(Iterator))) + Iterator(s, allocator, last, skip); it->name = last; } const char* result = last + skip; @@ -116,10 +120,11 @@ class DirectoryElement: public Element { virtual void dispose() { directory->dispose(); - s->free(this); + allocator->free(this, sizeof(*this)); } System* s; + Allocator* allocator; const char* name; unsigned skip; System::Directory* directory; @@ -127,20 +132,20 @@ class DirectoryElement: public Element { Iterator* it; }; - DirectoryElement(System* s, const char* name): - s(s), name(name) + DirectoryElement(System* s, Allocator* allocator, const char* name): + s(s), allocator(allocator), name(name) { } virtual Element::Iterator* iterator() { - return new (allocate(s, sizeof(Iterator))) - Iterator(s, name, strlen(name) + 1); + return new (allocator->allocate(sizeof(Iterator))) + Iterator(s, allocator, name, strlen(name) + 1); } virtual System::Region* find(const char* name) { - const char* file = append(s, this->name, "/", name); + const char* file = append(allocator, this->name, "/", name); System::Region* region; System::Status status = s->map(®ion, file); - s->free(file); + allocator->free(file, strlen(file) + 1); if (s->success(status)) { if (DebugFind) { @@ -155,26 +160,29 @@ class DirectoryElement: public Element { } } - virtual bool exists(const char* name) { - const char* file = append(s, this->name, "/", name); - System::FileType type = s->identify(file); - s->free(file); - return type != System::TypeDoesNotExist; + virtual System::FileType stat(const char* name, unsigned* length, bool) { + const char* file = append(allocator, this->name, "/", name); + System::FileType type = s->stat(file, length); + allocator->free(file, strlen(file) + 1); + return type; } virtual void dispose() { - s->free(name); - s->free(this); + allocator->free(name, strlen(name) + 1); + allocator->free(this, sizeof(*this)); } System* s; + Allocator* allocator; const char* name; }; class PointerRegion: public System::Region { public: - PointerRegion(System* s, const uint8_t* start, size_t length): + PointerRegion(System* s, Allocator* allocator, const uint8_t* start, + size_t length): s(s), + allocator(allocator), start_(start), length_(length) { } @@ -188,18 +196,20 @@ class PointerRegion: public System::Region { } virtual void dispose() { - s->free(this); + allocator->free(this, sizeof(*this)); } System* s; + Allocator* allocator; const uint8_t* start_; size_t length_; }; class DataRegion: public System::Region { public: - DataRegion(System* s, size_t length): + DataRegion(System* s, Allocator* allocator, size_t length): s(s), + allocator(allocator), length_(length) { } @@ -212,10 +222,11 @@ class DataRegion: public System::Region { } virtual void dispose() { - s->free(this); + allocator->free(this, sizeof(*this)); } System* s; + Allocator* allocator; size_t length_; uint8_t data[0]; }; @@ -241,11 +252,12 @@ class JarIndex { Node* next; }; - JarIndex(System* s, unsigned capacity): + JarIndex(System* s, Allocator* allocator, unsigned capacity): s(s), + allocator(allocator), capacity(capacity), position(0), - nodes(static_cast(allocate(s, sizeof(Node) * capacity))) + nodes(static_cast(allocator->allocate(sizeof(Node) * capacity))) { memset(table, 0, sizeof(Node*) * capacity); } @@ -322,14 +334,16 @@ class JarIndex { commentFieldLength(p); } - static JarIndex* make(System* s, unsigned capacity) { + static JarIndex* make(System* s, Allocator* allocator, unsigned capacity) { return new - (allocate(s, sizeof(JarIndex) + (sizeof(Node*) * capacity))) - JarIndex(s, capacity); + (allocator->allocate(sizeof(JarIndex) + (sizeof(Node*) * capacity))) + JarIndex(s, allocator, capacity); } - static JarIndex* open(System* s, System::Region* region) { - JarIndex* index = make(s, 32); + static JarIndex* open(System* s, Allocator* allocator, + System::Region* region) + { + JarIndex* index = make(s, allocator, 32); const uint8_t* start = region->start(); const uint8_t* end = start + region->length(); @@ -362,7 +376,7 @@ class JarIndex { table[i] = new (nodes + (position++)) Node(hash, entry, table[i]); return this; } else { - JarIndex* index = make(s, capacity * 2); + JarIndex* index = make(s, allocator, capacity * 2); for (unsigned i = 0; i < capacity; ++i) { index->add(nodes[i].hash, nodes[i].entry); } @@ -390,15 +404,15 @@ class JarIndex { const uint8_t* p = n->entry; switch (compressionMethod(p)) { case Stored: { - return new (allocate(s, sizeof(PointerRegion))) - PointerRegion(s, fileData(start + localHeaderOffset(p)), + return new (allocator->allocate(sizeof(PointerRegion))) + PointerRegion(s, allocator, fileData(start + localHeaderOffset(p)), compressedSize(p)); } break; case Deflated: { DataRegion* region = new - (allocate(s, sizeof(DataRegion) + uncompressedSize(p))) - DataRegion(s, uncompressedSize(p)); + (allocator->allocate(sizeof(DataRegion) + uncompressedSize(p))) + DataRegion(s, allocator, uncompressedSize(p)); z_stream zStream; memset(&zStream, 0, sizeof(z_stream)); @@ -428,16 +442,41 @@ class JarIndex { return 0; } - bool exists(const char* name) { - return findNode(name) != 0; + System::FileType stat(const char* name, unsigned* length, bool tryDirectory) + { + Node* node = findNode(name); + if (node) { + *length = uncompressedSize(node->entry); + return System::TypeFile; + } else if (tryDirectory) { + *length = 0; + + // try again with '/' appended + unsigned length = strlen(name); + RUNTIME_ARRAY(char, n, length + 2); + memcpy(RUNTIME_ARRAY_BODY(n), name, length); + RUNTIME_ARRAY_BODY(n)[length] = '/'; + RUNTIME_ARRAY_BODY(n)[length + 1] = 0; + + node = findNode(n); + if (node) { + return System::TypeDirectory; + } else { + return System::TypeDoesNotExist; + } + } else { + *length = 0; + return System::TypeDoesNotExist; + } } void dispose() { - s->free(nodes); - s->free(this); + allocator->free(nodes, sizeof(Node) * capacity); + allocator->free(this, sizeof(*this) + (sizeof(Node*) * capacity)); } System* s; + Allocator* allocator; unsigned capacity; unsigned position; @@ -449,7 +488,9 @@ class JarElement: public Element { public: class Iterator: public Element::Iterator { public: - Iterator(System* s, JarIndex* index): s(s), index(index), position(0) { } + Iterator(System* s, Allocator* allocator, JarIndex* index): + s(s), allocator(allocator), index(index), position(0) + { } virtual const char* next(unsigned* size) { if (position < index->position) { @@ -462,22 +503,34 @@ class JarElement: public Element { } virtual void dispose() { - s->free(this); + allocator->free(this, sizeof(*this)); } System* s; + Allocator* allocator; JarIndex* index; unsigned position; }; - JarElement(System* s, const char* name): - s(s), name(name), region(0), index(0) + JarElement(System* s, Allocator* allocator, const char* name): + s(s), allocator(allocator), name(name), region(0), index(0) + { } + + JarElement(System* s, Allocator* allocator, const uint8_t* jarData, + unsigned jarLength): + s(s), + allocator(allocator), + name(0), + region(new (allocator->allocate(sizeof(PointerRegion))) + PointerRegion(s, allocator, jarData, jarLength)), + index(JarIndex::open(s, allocator, region)) { } virtual Element::Iterator* iterator() { init(); - return new (allocate(s, sizeof(Iterator))) Iterator(s, index); + return new (allocator->allocate(sizeof(Iterator))) + Iterator(s, allocator, index); } virtual void init() { @@ -485,7 +538,7 @@ class JarElement: public Element { System::Region* r; if (s->success(s->map(&r, name))) { region = r; - index = JarIndex::open(s, r); + index = JarIndex::open(s, allocator, r); } } } @@ -506,26 +559,34 @@ class JarElement: public Element { return r; } - virtual bool exists(const char* name) { + virtual System::FileType stat(const char* name, unsigned* length, + bool tryDirectory) + { init(); while (*name == '/') name++; - return (index ? index->exists(name) : 0); + return (index ? index->stat(name, length, tryDirectory) + : System::TypeDoesNotExist); } virtual void dispose() { - s->free(name); + dispose(sizeof(*this)); + } + + virtual void dispose(unsigned size) { + allocator->free(name, strlen(name) + 1); if (index) { index->dispose(); } if (region) { region->dispose(); } - s->free(this); + allocator->free(this, size); } System* s; + Allocator* allocator; const char* name; System::Region* region; JarIndex* index; @@ -533,9 +594,10 @@ class JarElement: public Element { class BuiltinElement: public JarElement { public: - BuiltinElement(System* s, const char* name, const char* libraryName): - JarElement(s, name), - libraryName(libraryName ? copy(s, libraryName) : 0) + BuiltinElement(System* s, Allocator* allocator, const char* name, + const char* libraryName): + JarElement(s, allocator, name), + libraryName(libraryName ? copy(allocator, libraryName) : 0) { } virtual void init() { @@ -549,9 +611,9 @@ class BuiltinElement: public JarElement { unsigned size; uint8_t* data = function(&size); if (data) { - region = new (allocate(s, sizeof(PointerRegion))) - PointerRegion(s, data, size); - index = JarIndex::open(s, region); + region = new (allocator->allocate(sizeof(PointerRegion))) + PointerRegion(s, allocator, data, size); + index = JarIndex::open(s, allocator, region); } } } @@ -560,8 +622,10 @@ class BuiltinElement: public JarElement { virtual void dispose() { library->disposeAll(); - s->free(libraryName); - JarElement::dispose(); + if (libraryName) { + allocator->free(libraryName, strlen(libraryName) + 1); + } + JarElement::dispose(sizeof(*this)); } System::Library* library; @@ -569,7 +633,8 @@ class BuiltinElement: public JarElement { }; Element* -parsePath(System* s, const char* path, const char* bootLibrary) +parsePath(System* s, Allocator* allocator, const char* path, + const char* bootLibrary) { Element* first = 0; Element* prev = 0; @@ -578,29 +643,31 @@ parsePath(System* s, const char* path, const char* bootLibrary) Element* e; if (*token.s == '[' and token.s[token.length - 1] == ']') { - char* name = static_cast(allocate(s, token.length - 1)); + char* name = static_cast(allocator->allocate(token.length - 1)); memcpy(name, token.s + 1, token.length - 1); name[token.length - 2] = 0; - e = new (allocate(s, sizeof(BuiltinElement))) - BuiltinElement(s, name, bootLibrary); + e = new (allocator->allocate(sizeof(BuiltinElement))) + BuiltinElement(s, allocator, name, bootLibrary); } else { - char* name = static_cast(allocate(s, token.length + 1)); + char* name = static_cast(allocator->allocate(token.length + 1)); memcpy(name, token.s, token.length); name[token.length] = 0; - switch (s->identify(name)) { + unsigned length; + switch (s->stat(name, &length)) { case System::TypeFile: { - e = new (allocate(s, sizeof(JarElement))) JarElement(s, name); + e = new (allocator->allocate(sizeof(JarElement))) + JarElement(s, allocator, name); } break; case System::TypeDirectory: { - e = new (allocate(s, sizeof(DirectoryElement))) - DirectoryElement(s, name); + e = new (allocator->allocate(sizeof(DirectoryElement))) + DirectoryElement(s, allocator, name); } break; default: { - s->free(name); + allocator->free(name, strlen(name) + 1); e = 0; } break; } @@ -621,8 +688,9 @@ parsePath(System* s, const char* path, const char* bootLibrary) class MyIterator: public Finder::IteratorImp { public: - MyIterator(System* s, Element* path): - s(s), e(path ? path->next : 0), it(path ? path->iterator() : 0) + MyIterator(System* s, Allocator* allocator, Element* path): + s(s), allocator(allocator), e(path ? path->next : 0), + it(path ? path->iterator() : 0) { } virtual const char* next(unsigned* size) { @@ -645,25 +713,37 @@ class MyIterator: public Finder::IteratorImp { virtual void dispose() { if (it) it->dispose(); - s->free(this); + allocator->free(this, sizeof(*this)); } System* s; + Allocator* allocator; Element* e; Element::Iterator* it; }; class MyFinder: public Finder { public: - MyFinder(System* system, const char* path, const char* bootLibrary): + MyFinder(System* system, Allocator* allocator, const char* path, + const char* bootLibrary): system(system), - path_(parsePath(system, path, bootLibrary)), - pathString(copy(system, path)) + allocator(allocator), + path_(parsePath(system, allocator, path, bootLibrary)), + pathString(copy(allocator, path)) + { } + + MyFinder(System* system, Allocator* allocator, const uint8_t* jarData, + unsigned jarLength): + system(system), + allocator(allocator), + path_(new (allocator->allocate(sizeof(JarElement))) + JarElement(system, allocator, jarData, jarLength)), + pathString(0) { } virtual IteratorImp* iterator() { - return new (allocate(system, sizeof(MyIterator))) - MyIterator(system, path_); + return new (allocator->allocate(sizeof(MyIterator))) + MyIterator(system, allocator, path_); } virtual System::Region* find(const char* name) { @@ -677,14 +757,17 @@ class MyFinder: public Finder { return 0; } - virtual bool exists(const char* name) { + virtual System::FileType stat(const char* name, unsigned* length, + bool tryDirectory) + { for (Element* e = path_; e; e = e->next) { - if (e->exists(name)) { - return true; + System::FileType type = e->stat(name, length, tryDirectory); + if (type != System::TypeDoesNotExist) { + return type; } } - return false; + return System::TypeDoesNotExist; } virtual const char* path() { @@ -697,11 +780,12 @@ class MyFinder: public Finder { e = e->next; t->dispose(); } - system->free(pathString); - system->free(this); + allocator->free(pathString, strlen(pathString) + 1); + allocator->free(this, sizeof(*this)); } System* system; + Allocator* allocator; Element* path_; const char* pathString; }; @@ -711,9 +795,16 @@ class MyFinder: public Finder { namespace vm { Finder* -makeFinder(System* s, const char* path, const char* bootLibrary) +makeFinder(System* s, Allocator* a, const char* path, const char* bootLibrary) { - return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path, bootLibrary); + return new (a->allocate(sizeof(MyFinder))) MyFinder(s, a, path, bootLibrary); +} + +Finder* +makeFinder(System* s, Allocator* a, const uint8_t* jarData, unsigned jarLength) +{ + return new (a->allocate(sizeof(MyFinder))) + MyFinder(s, a, jarData, jarLength); } } // namespace vm diff --git a/src/finder.h b/src/finder.h index 4cd1256baf..203abb49e3 100644 --- a/src/finder.h +++ b/src/finder.h @@ -60,13 +60,19 @@ class Finder { virtual IteratorImp* iterator() = 0; virtual System::Region* find(const char* name) = 0; - virtual bool exists(const char* name) = 0; + virtual System::FileType stat(const char* name, + unsigned* length, + bool tryDirectory = false) = 0; virtual const char* path() = 0; virtual void dispose() = 0; }; Finder* -makeFinder(System* s, const char* path, const char* bootLibrary); +makeFinder(System* s, Allocator* a, const char* path, const char* bootLibrary); + +Finder* +makeFinder(System* s, Allocator* a, const uint8_t* jarData, + unsigned jarLength); } // namespace vm diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 680992c4df..44cbb0cb91 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -2228,6 +2228,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) #define BOOTSTRAP_PROPERTY "avian.bootstrap" #define CRASHDIR_PROPERTY "avian.crash.dir" +#define EMBED_PREFIX_PROPERTY "avian.embed.prefix" #define CLASSPATH_PROPERTY "java.class.path" #define JAVA_HOME_PROPERTY "java.home" #define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" @@ -2250,6 +2251,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) const char* bootLibrary = 0; const char* classpath = 0; const char* javaHome = AVIAN_JAVA_HOME; + const char* embedPrefix = AVIAN_EMBED_PREFIX; const char* bootClasspathPrepend = ""; const char* bootClasspath = 0; const char* bootClasspathAppend = ""; @@ -2293,6 +2295,10 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) sizeof(JAVA_HOME_PROPERTY)) == 0) { javaHome = p + sizeof(JAVA_HOME_PROPERTY); + } else if (strncmp(p, EMBED_PREFIX_PROPERTY "=", + sizeof(EMBED_PREFIX_PROPERTY)) == 0) + { + embedPrefix = p + sizeof(EMBED_PREFIX_PROPERTY); } ++ propertyCount; @@ -2305,7 +2311,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) System* s = makeSystem(crashDumpDirectory); Heap* h = makeHeap(s, heapLimit); - Classpath* c = makeClasspath(s, h, javaHome); + Classpath* c = makeClasspath(s, h, javaHome, embedPrefix); if (bootClasspath == 0) { bootClasspath = c->bootClasspath(); @@ -2325,8 +2331,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0); Finder* bf = makeFinder - (s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary); - Finder* af = makeFinder(s, classpath, bootLibrary); + (s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary); + Finder* af = makeFinder(s, h, classpath, bootLibrary); Processor* p = makeProcessor(s, h, true); const char** properties = static_cast diff --git a/src/machine.cpp b/src/machine.cpp index 184649e0e5..9d3ab655fb 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -193,6 +193,23 @@ turnOffTheLights(Thread* t) } } + if (root(t, Machine::VirtualFiles)) { + for (unsigned i = 0; i < arrayLength(t, root(t, Machine::VirtualFiles)); + ++i) + { + object region = arrayBody(t, root(t, Machine::VirtualFiles), i); + if (region) { + static_cast(regionRegion(t, region))->dispose(); + } + } + } + + for (object p = root(t, Machine::VirtualFileFinders); + p; p = finderNext(t, p)) + { + static_cast(finderFinder(t, p))->dispose(); + } + Machine* m = t->m; disposeAll(t, t->m->rootThread); @@ -204,13 +221,13 @@ turnOffTheLights(Thread* t) Finder* bf = m->bootFinder; Finder* af = m->appFinder; + c->dispose(); m->dispose(); h->disposeFixies(); - c->dispose(); p->dispose(); - h->dispose(); bf->dispose(); af->dispose(); + h->dispose(); s->dispose(); } diff --git a/src/machine.h b/src/machine.h index 1955adadb8..15782d5240 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1198,10 +1198,12 @@ class Machine { ShutdownHooks, ObjectsToFinalize, NullPointerException, - ArrayIndexOutOfBoundsException + ArrayIndexOutOfBoundsException, + VirtualFileFinders, + VirtualFiles }; - static const unsigned RootCount = ArrayIndexOutOfBoundsException + 1; + static const unsigned RootCount = VirtualFiles + 1; Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, @@ -1446,7 +1448,8 @@ runJavaThread(Thread* t) } Classpath* -makeClasspath(System* system, Allocator* allocator, const char* javaHome); +makeClasspath(System* system, Allocator* allocator, const char* javaHome, + const char* embedPrefix); typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*); diff --git a/src/posix.cpp b/src/posix.cpp index 47ef06fe34..1c3e0c6d09 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -698,18 +698,22 @@ class MySystem: public System { return status; } - virtual FileType identify(const char* name) { + virtual FileType stat(const char* name, unsigned* length) { struct stat s; - int r = stat(name, &s); + int r = ::stat(name, &s); if (r == 0) { if (S_ISREG(s.st_mode)) { + *length = s.st_size; return TypeFile; } else if (S_ISDIR(s.st_mode)) { + *length = 0; return TypeDirectory; } else { + *length = 0; return TypeUnknown; } } else { + *length = 0; return TypeDoesNotExist; } } diff --git a/src/system.h b/src/system.h index 1cdddb3afe..5cf7211ab9 100644 --- a/src/system.h +++ b/src/system.h @@ -132,7 +132,7 @@ class System { unsigned count, unsigned size, unsigned returnType) = 0; virtual Status map(Region**, const char* name) = 0; - virtual FileType identify(const char* name) = 0; + virtual FileType stat(const char* name, unsigned* length) = 0; virtual Status open(Directory**, const char* name) = 0; virtual const char* libraryPrefix() = 0; virtual const char* librarySuffix() = 0; diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 1480fb92a4..c2eeb76684 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -2213,7 +2213,31 @@ main(int ac, char** av) } System* system = makeSystem(0); - Finder* finder = makeFinder(system, av[1], 0); + + class MyAllocator: public Allocator { + public: + MyAllocator(System* s): s(s) { } + + virtual void* tryAllocate(unsigned size) { + return s->tryAllocate(size); + } + + virtual void* allocate(unsigned size) { + void* p = tryAllocate(size); + if (p == 0) { + abort(s); + } + return p; + } + + virtual void free(const void* p, unsigned) { + s->free(p); + } + + System* s; + } allocator(system); + + Finder* finder = makeFinder(system, &allocator, av[1], 0); FILE* inStream = ::fopen(av[2], "rb"); if (inStream == 0) { diff --git a/src/types.def b/src/types.def index 158483115a..1cb88bcf86 100644 --- a/src/types.def +++ b/src/types.def @@ -48,6 +48,15 @@ (extends native) (object original)) +(type finder + (void* finder) + (object name) + (object next)) + +(type region + (void* region) + (unsigned position)) + (pod exceptionHandler (uint16_t start) (uint16_t end) diff --git a/src/util.cpp b/src/util.cpp index 0745f98f72..0e9bd6d4b7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -529,11 +529,6 @@ vectorAppend(Thread* t, object vector, object value) vectorSize(t, vector) * BytesPerWord); } - memset(&vectorBody(t, newVector, vectorSize(t, vector) + 1), - 0, - (vectorLength(t, newVector) - vectorSize(t, vector) - 1) - * BytesPerWord); - vector = newVector; } @@ -542,6 +537,22 @@ vectorAppend(Thread* t, object vector, object value) return vector; } +object +growArray(Thread* t, object array) +{ + PROTECT(t, array); + + object newArray = makeArray + (t, array == 0 ? 16 : (arrayLength(t, array) * 2)); + + if (array) { + memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0), + arrayLength(t, array)); + } + + return newArray; +} + object treeQuery(Thread* t, object tree, intptr_t key, object sentinal, intptr_t (*compare)(Thread* t, intptr_t key, object b)) diff --git a/src/util.h b/src/util.h index bf895f6bae..ecd9a54a6b 100644 --- a/src/util.h +++ b/src/util.h @@ -84,6 +84,9 @@ listAppend(Thread* t, object list, object value); object vectorAppend(Thread* t, object vector, object value); +object +growArray(Thread* t, object array); + object treeQuery(Thread* t, object tree, intptr_t key, object sentinal, intptr_t (*compare)(Thread* t, intptr_t key, object b)); diff --git a/test/Misc.java b/test/Misc.java index 2bdc3396ca..c1a5a016d4 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -204,5 +204,7 @@ public class Misc { } while (x != 1); } } + + System.out.println(java.util.Calendar.getInstance().toString()); } }