mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
rework OpenJDK build to derive classpath and library path from environment
We now consult the JAVA_HOME environment variable to determine where to find the system library JARs and SOs. Ultimately, we'll want to support self-contained build, but this allows Avian to behave like a conventional libjvm.so.
This commit is contained in:
parent
88942a9672
commit
17f495eb27
86
makefile
86
makefile
@ -40,26 +40,20 @@ ifeq ($(continuations),true)
|
|||||||
options := $(options)-continuations
|
options := $(options)-continuations
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
root := $(shell (cd .. && pwd))
|
||||||
|
build = build/$(platform)-$(arch)$(options)
|
||||||
|
classpath-build = $(build)/classpath
|
||||||
|
test-build = $(build)/test
|
||||||
|
src = src
|
||||||
|
classpath-src = classpath
|
||||||
|
test = test
|
||||||
|
|
||||||
classpath = avian
|
classpath = avian
|
||||||
|
|
||||||
test-library-path = .
|
|
||||||
test-executable = $(executable)
|
test-executable = $(executable)
|
||||||
|
generator-classpath = $(classpath-build)
|
||||||
|
boot-classpath = $(classpath-build)
|
||||||
|
|
||||||
ifdef gnu
|
|
||||||
classpath = gnu
|
|
||||||
options := $(options)-gnu
|
|
||||||
classapth-jar = $(gnu)/share/classpath/glibj.zip
|
|
||||||
classpath-libraries = \
|
|
||||||
$(gnu)/lib/classpath/libjavaio.a \
|
|
||||||
$(gnu)/lib/classpath/libjavalang.a \
|
|
||||||
$(gnu)/lib/classpath/libjavalangreflect.a \
|
|
||||||
$(gnu)/lib/classpath/libjavamath.a \
|
|
||||||
$(gnu)/lib/classpath/libjavanet.a \
|
|
||||||
$(gnu)/lib/classpath/libjavanio.a \
|
|
||||||
$(gnu)/lib/classpath/libjavautil.a
|
|
||||||
classpath-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU
|
|
||||||
classpath-lflags = -lgmp
|
|
||||||
endif
|
|
||||||
ifdef openjdk
|
ifdef openjdk
|
||||||
classpath = openjdk
|
classpath = openjdk
|
||||||
options := $(options)-openjdk
|
options := $(options)-openjdk
|
||||||
@ -68,19 +62,12 @@ ifdef openjdk
|
|||||||
else
|
else
|
||||||
openjdk-lib-dir = $(openjdk)/jre/lib
|
openjdk-lib-dir = $(openjdk)/jre/lib
|
||||||
endif
|
endif
|
||||||
classpath-jar = $(openjdk)/jre/lib/rt.jar
|
classpath-cflags = -DAVIAN_OPENJDK_JAVA_HOME=\"$(openjdk)\"
|
||||||
test-library-path = $(openjdk-lib-dir):$(build)
|
|
||||||
test-executable = $(executable-dynamic)
|
test-executable = $(executable-dynamic)
|
||||||
|
generator-classpath := $(generator-classpath):$(openjdk)/jre/lib/rt.jar
|
||||||
|
boot-classpath := $(boot-classpath):$(openjdk)/jre/lib/rt.jar
|
||||||
endif
|
endif
|
||||||
|
|
||||||
root := $(shell (cd .. && pwd))
|
|
||||||
build = build/$(platform)-$(arch)$(options)
|
|
||||||
classpath-build = $(build)/classpath
|
|
||||||
test-build = $(build)/test
|
|
||||||
src = src
|
|
||||||
classpath-src = classpath
|
|
||||||
test = test
|
|
||||||
|
|
||||||
ifneq ($(classpath),avian)
|
ifneq ($(classpath),avian)
|
||||||
classpath-object-dep = $(build)/classpath-object.dep
|
classpath-object-dep = $(build)/classpath-object.dep
|
||||||
classpath-objects = $(shell find $(build)/classpath-objects -name "*.o")
|
classpath-objects = $(shell find $(build)/classpath-objects -name "*.o")
|
||||||
@ -138,7 +125,7 @@ cflags = $(build-cflags)
|
|||||||
|
|
||||||
common-lflags = -lm -lz $(classpath-lflags)
|
common-lflags = -lm -lz $(classpath-lflags)
|
||||||
|
|
||||||
build-lflags =
|
build-lflags = -lz -lpthread -ldl
|
||||||
|
|
||||||
lflags = $(common-lflags) -lpthread -ldl
|
lflags = $(common-lflags) -lpthread -ldl
|
||||||
|
|
||||||
@ -401,10 +388,15 @@ driver-dynamic-object = $(build)/main-dynamic.o
|
|||||||
boot-source = $(src)/boot.cpp
|
boot-source = $(src)/boot.cpp
|
||||||
boot-object = $(build)/boot.o
|
boot-object = $(build)/boot.o
|
||||||
|
|
||||||
generator-headers = $(src)/constants.h
|
generator-depends := $(wildcard $(src)/*.h)
|
||||||
generator-sources = $(src)/type-generator.cpp
|
generator-sources = \
|
||||||
|
$(src)/type-generator.cpp \
|
||||||
|
$(src)/$(system).cpp \
|
||||||
|
$(src)/finder.cpp
|
||||||
|
generator-cpp-objects = \
|
||||||
|
$(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%-build.o,$(x)))
|
||||||
generator-objects = \
|
generator-objects = \
|
||||||
$(call cpp-objects,$(generator-sources),$(src),$(build))
|
$(call generator-cpp-objects,$(generator-sources),$(src),$(build))
|
||||||
generator = $(build)/generator
|
generator = $(build)/generator
|
||||||
|
|
||||||
converter-objects = \
|
converter-objects = \
|
||||||
@ -467,9 +459,9 @@ test-extra-dep = $(test-build)-extra.dep
|
|||||||
class-name = $(patsubst $(1)/%.class,%,$(2))
|
class-name = $(patsubst $(1)/%.class,%,$(2))
|
||||||
class-names = $(foreach x,$(2),$(call class-name,$(1),$(x)))
|
class-names = $(foreach x,$(2),$(call class-name,$(1),$(x)))
|
||||||
|
|
||||||
flags = -cp $(test-build)
|
test-flags = -cp $(build)/test
|
||||||
|
|
||||||
args = $(flags) $(input)
|
test-args = $(test-flags) $(input)
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(static-library) $(executable) $(dynamic-library) \
|
build: $(static-library) $(executable) $(dynamic-library) \
|
||||||
@ -481,20 +473,20 @@ $(test-extra-dep): $(classpath-dep)
|
|||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: build
|
run: build
|
||||||
$(executable) $(args)
|
LD_LIBRARY_PATH=$(build) $(test-executable) $(test-args)
|
||||||
|
|
||||||
.PHONY: debug
|
.PHONY: debug
|
||||||
debug: build
|
debug: build
|
||||||
gdb --args $(executable) $(args)
|
LD_LIBRARY_PATH=$(build) gdb --args $(test-executable) $(test-args)
|
||||||
|
|
||||||
.PHONY: vg
|
.PHONY: vg
|
||||||
vg: build
|
vg: build
|
||||||
$(vg) $(executable) $(args)
|
LD_LIBRARY_PATH=$(build) $(vg) $(test-executable) $(test-args)
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: build
|
test: build
|
||||||
/bin/sh $(test)/test.sh 2>/dev/null \
|
/bin/sh $(test)/test.sh 2>/dev/null \
|
||||||
$(test-library-path) $(test-executable) $(mode) "$(flags)" \
|
$(build) $(test-executable) $(mode) "$(test-flags)" \
|
||||||
$(call class-names,$(test-build),$(test-classes))
|
$(call class-names,$(test-build),$(test-classes))
|
||||||
|
|
||||||
.PHONY: tarball
|
.PHONY: tarball
|
||||||
@ -523,24 +515,15 @@ gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:')
|
|||||||
$(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep)
|
$(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep)
|
||||||
@echo "generating $(@)"
|
@echo "generating $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(generator) $(classpath-build) $(call gen-arg,$(@)) < $(<) > $(@)
|
$(generator) $(generator-classpath) $(<) $(@) $(call gen-arg,$(@))
|
||||||
|
|
||||||
$(build)/type-generator.o: \
|
|
||||||
$(generator-headers)
|
|
||||||
|
|
||||||
$(classpath-build)/%.class: $(classpath-src)/%.java
|
$(classpath-build)/%.class: $(classpath-src)/%.java
|
||||||
@echo $(<)
|
@echo $(<)
|
||||||
|
|
||||||
$(classpath-dep): $(classpath-sources) $(classpath-jar)
|
$(classpath-dep): $(classpath-sources)
|
||||||
@echo "compiling classpath classes"
|
@echo "compiling classpath classes"
|
||||||
@mkdir -p $(classpath-build)
|
@mkdir -p $(classpath-build)
|
||||||
ifneq ($(classpath),avian)
|
$(javac) -d $(classpath-build) -bootclasspath $(boot-classpath) \
|
||||||
(wd=$$(pwd) && \
|
|
||||||
cd $(classpath-build) && \
|
|
||||||
$(jar) xf $(classpath-jar))
|
|
||||||
endif
|
|
||||||
$(javac) -d $(classpath-build) \
|
|
||||||
-bootclasspath $(classpath-build) \
|
|
||||||
$(shell $(MAKE) -s --no-print-directory build=$(build) \
|
$(shell $(MAKE) -s --no-print-directory build=$(build) \
|
||||||
$(classpath-classes))
|
$(classpath-classes))
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
@ -553,7 +536,7 @@ $(test-dep): $(test-sources)
|
|||||||
@mkdir -p $(test-build)
|
@mkdir -p $(test-build)
|
||||||
files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-classes))"; \
|
files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-classes))"; \
|
||||||
if test -n "$${files}"; then \
|
if test -n "$${files}"; then \
|
||||||
$(javac) -d $(test-build) -bootclasspath $(classpath-build) $${files}; \
|
$(javac) -d $(test-build) -bootclasspath $(boot-classpath) $${files}; \
|
||||||
fi
|
fi
|
||||||
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(test-build) \
|
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(test-build) \
|
||||||
test/Subroutine.java
|
test/Subroutine.java
|
||||||
@ -564,7 +547,7 @@ $(test-extra-dep): $(test-extra-sources)
|
|||||||
@mkdir -p $(test-build)
|
@mkdir -p $(test-build)
|
||||||
files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-extra-classes))"; \
|
files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-extra-classes))"; \
|
||||||
if test -n "$${files}"; then \
|
if test -n "$${files}"; then \
|
||||||
$(javac) -d $(test-build) -bootclasspath $(classpath-build) $${files}; \
|
$(javac) -d $(test-build) -bootclasspath $(boot-classpath) $${files}; \
|
||||||
fi
|
fi
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
@ -635,7 +618,8 @@ $(classpath-object): $(build)/classpath.jar $(converter)
|
|||||||
$(converter) $(<) $(@) _binary_classpath_jar_start \
|
$(converter) $(<) $(@) _binary_classpath_jar_start \
|
||||||
_binary_classpath_jar_end $(platform) $(arch)
|
_binary_classpath_jar_end $(platform) $(arch)
|
||||||
|
|
||||||
$(generator-objects): $(build)/%.o: $(src)/%.cpp
|
$(generator-objects): $(generator-depends)
|
||||||
|
$(generator-objects): $(build)/%-build.o: $(src)/%.cpp
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \
|
$(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \
|
||||||
|
@ -92,6 +92,12 @@ class MyClasspath : public Classpath {
|
|||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char*
|
||||||
|
bootClasspath()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose()
|
dispose()
|
||||||
{
|
{
|
||||||
@ -473,7 +479,7 @@ Avian_java_lang_Runtime_load
|
|||||||
RUNTIME_ARRAY(char, n, length + 1);
|
RUNTIME_ARRAY(char, n, length + 1);
|
||||||
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
loadLibrary(t, RUNTIME_ARRAY_BODY(n), mapName, true);
|
loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), mapName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
#ifndef CLASSPATH_COMMON_H
|
#ifndef CLASSPATH_COMMON_H
|
||||||
#define CLASSPATH_COMMON_H
|
#define CLASSPATH_COMMON_H
|
||||||
|
|
||||||
|
#include "tokenizer.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
inline object
|
object
|
||||||
getCaller(Thread* t, unsigned target)
|
getCaller(Thread* t, unsigned target)
|
||||||
{
|
{
|
||||||
class Visitor: public Processor::StackVisitor {
|
class Visitor: public Processor::StackVisitor {
|
||||||
@ -43,7 +45,7 @@ getCaller(Thread* t, unsigned target)
|
|||||||
return v.method;
|
return v.method;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
object
|
||||||
getTrace(Thread* t, unsigned skipCount)
|
getTrace(Thread* t, unsigned skipCount)
|
||||||
{
|
{
|
||||||
class Visitor: public Processor::StackVisitor {
|
class Visitor: public Processor::StackVisitor {
|
||||||
@ -84,7 +86,7 @@ getTrace(Thread* t, unsigned skipCount)
|
|||||||
return v.trace;
|
return v.trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
bool
|
||||||
compatibleArrayTypes(Thread* t, object a, object b)
|
compatibleArrayTypes(Thread* t, object a, object b)
|
||||||
{
|
{
|
||||||
return classArrayElementSize(t, a)
|
return classArrayElementSize(t, a)
|
||||||
@ -94,7 +96,7 @@ compatibleArrayTypes(Thread* t, object a, object b)
|
|||||||
or (classVmFlags(t, b) & PrimitiveFlag))));
|
or (classVmFlags(t, b) & PrimitiveFlag))));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
void
|
||||||
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
||||||
int32_t dstOffset, int32_t length)
|
int32_t dstOffset, int32_t length)
|
||||||
{
|
{
|
||||||
@ -160,17 +162,42 @@ runOnLoadIfFound(Thread* t, System::Library* library)
|
|||||||
}
|
}
|
||||||
|
|
||||||
System::Library*
|
System::Library*
|
||||||
loadLibrary(Thread* t, const char* name, bool mapName, bool runOnLoad)
|
loadLibrary(Thread* t, const char* name)
|
||||||
{
|
{
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
|
System::Library* last = t->m->libraries;
|
||||||
|
for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
|
||||||
|
if (lib->name() and ::strcmp(lib->name(), name) == 0) {
|
||||||
|
// already loaded
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
last = lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
System::Library* lib;
|
||||||
|
if (LIKELY(t->m->system->success(t->m->system->load(&lib, name)))) {
|
||||||
|
last->setNext(lib);
|
||||||
|
return lib;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System::Library*
|
||||||
|
loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||||
|
bool runOnLoad)
|
||||||
|
{
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
|
unsigned nameLength = strlen(name);
|
||||||
|
if (mapName) {
|
||||||
const char* builtins = findProperty(t, "avian.builtins");
|
const char* builtins = findProperty(t, "avian.builtins");
|
||||||
if (mapName and builtins) {
|
if (builtins) {
|
||||||
const char* s = builtins;
|
const char* s = builtins;
|
||||||
while (*s) {
|
while (*s) {
|
||||||
unsigned length = strlen(name);
|
if (::strncmp(s, name, nameLength) == 0
|
||||||
if (::strncmp(s, name, length) == 0
|
and (s[nameLength] == ',' or s[nameLength] == 0))
|
||||||
and (s[length] == ',' or s[length] == 0))
|
|
||||||
{
|
{
|
||||||
// library is built in to this executable
|
// library is built in to this executable
|
||||||
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
|
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
|
||||||
@ -185,31 +212,55 @@ loadLibrary(Thread* t, const char* name, bool mapName, bool runOnLoad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Library* last = t->m->libraries;
|
const char* prefix = t->m->system->libraryPrefix();
|
||||||
for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
|
const char* suffix = t->m->system->librarySuffix();
|
||||||
if (lib->name()
|
unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix);
|
||||||
and ::strcmp(lib->name(), name) == 0
|
|
||||||
and lib->mapName() == mapName)
|
char* mappedName = static_cast<char*>
|
||||||
{
|
(t->m->heap->allocate(mappedNameLength + 1));
|
||||||
// already loaded
|
|
||||||
return lib;
|
snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix);
|
||||||
}
|
|
||||||
last = lib;
|
name = mappedName;
|
||||||
|
nameLength = mappedNameLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Library* lib;
|
System::Library* lib = 0;
|
||||||
if (LIKELY(t->m->system->success(t->m->system->load(&lib, name, mapName)))) {
|
for (Tokenizer tokenizer(path, t->m->system->pathSeparator());
|
||||||
last->setNext(lib);
|
tokenizer.hasMore();)
|
||||||
|
{
|
||||||
|
Tokenizer::Token token(tokenizer.next());
|
||||||
|
|
||||||
|
unsigned fullNameLength = token.length + 1 + nameLength;
|
||||||
|
RUNTIME_ARRAY(char, fullName, fullNameLength + 1);
|
||||||
|
|
||||||
|
snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1,
|
||||||
|
"%*s%c%s", token.length, token.s, t->m->system->fileSeparator(),
|
||||||
|
name);
|
||||||
|
|
||||||
|
lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName));
|
||||||
|
if (lib) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lib == 0) {
|
||||||
|
lib = loadLibrary(t, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lib) {
|
||||||
if (runOnLoad) {
|
if (runOnLoad) {
|
||||||
runOnLoadIfFound(t, lib);
|
runOnLoadIfFound(t, lib);
|
||||||
}
|
}
|
||||||
return lib;
|
|
||||||
} else {
|
} else {
|
||||||
object message = makeString(t, "library not found: %s", name);
|
object message = makeString(t, "library not found: %s", name);
|
||||||
t->exception = t->m->classpath->makeThrowable
|
t->exception = t->m->classpath->makeThrowable
|
||||||
(t, Machine::UnsatisfiedLinkErrorType, message);
|
(t, Machine::UnsatisfiedLinkErrorType, message);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mapName) {
|
||||||
|
t->m->heap->free(name, nameLength + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
|
@ -139,10 +139,74 @@ makeClassNameString(Thread* t, object name)
|
|||||||
|
|
||||||
class MyClasspath : public Classpath {
|
class MyClasspath : public Classpath {
|
||||||
public:
|
public:
|
||||||
MyClasspath(Allocator* allocator):
|
static const unsigned BufferSize = 256;
|
||||||
|
|
||||||
|
MyClasspath(System* s, Allocator* allocator):
|
||||||
allocator(allocator)
|
allocator(allocator)
|
||||||
|
{
|
||||||
|
const char* javaHome = getenv("JAVA_HOME");
|
||||||
|
if (javaHome == 0) {
|
||||||
|
javaHome = AVIAN_OPENJDK_JAVA_HOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringBuilder {
|
||||||
|
public:
|
||||||
|
StringBuilder(System* s, char* pointer, unsigned remaining):
|
||||||
|
s(s), pointer(pointer), remaining(remaining)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
void append(const char* append) {
|
||||||
|
unsigned length = strlen(append);
|
||||||
|
assert(s, remaining > length);
|
||||||
|
|
||||||
|
strncpy(pointer, append, remaining);
|
||||||
|
|
||||||
|
remaining -= length;
|
||||||
|
pointer += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(char c) {
|
||||||
|
assert(s, remaining > 1);
|
||||||
|
|
||||||
|
pointer[0] = c;
|
||||||
|
pointer[1] = 0;
|
||||||
|
|
||||||
|
-- remaining;
|
||||||
|
++ pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
System* s;
|
||||||
|
char* pointer;
|
||||||
|
unsigned remaining;
|
||||||
|
} sb(s, buffer, BufferSize);
|
||||||
|
|
||||||
|
this->javaHome = sb.pointer;
|
||||||
|
sb.append(javaHome);
|
||||||
|
sb.append('\0');
|
||||||
|
|
||||||
|
this->classpath = sb.pointer;
|
||||||
|
sb.append(javaHome);
|
||||||
|
sb.append("/jre/lib/rt.jar");
|
||||||
|
sb.append(s->pathSeparator());
|
||||||
|
sb.append(javaHome);
|
||||||
|
sb.append("/jre/lib/jsse.jar");
|
||||||
|
sb.append(s->pathSeparator());
|
||||||
|
sb.append(javaHome);
|
||||||
|
sb.append("/jre/lib/jce.jar");
|
||||||
|
sb.append(s->pathSeparator());
|
||||||
|
sb.append(javaHome);
|
||||||
|
sb.append("/jre/lib/resources.jar");
|
||||||
|
sb.append('\0');
|
||||||
|
|
||||||
|
this->libraryPath = sb.pointer;
|
||||||
|
sb.append(javaHome);
|
||||||
|
#ifdef ARCH_x86_64
|
||||||
|
sb.append("/jre/lib/amd64");
|
||||||
|
#else
|
||||||
|
sb.append("/jre/lib");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
makeJclass(Thread* t, object class_)
|
makeJclass(Thread* t, object class_)
|
||||||
{
|
{
|
||||||
@ -232,7 +296,7 @@ class MyClasspath : public Classpath {
|
|||||||
{
|
{
|
||||||
globalMachine = t->m;
|
globalMachine = t->m;
|
||||||
|
|
||||||
if (loadLibrary(t, "java", true, true) == 0) {
|
if (loadLibrary(t, libraryPath, "java", true, true) == 0) {
|
||||||
abort(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +335,12 @@ class MyClasspath : public Classpath {
|
|||||||
fieldOffset(t, sclSet)) = true;
|
fieldOffset(t, sclSet)) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char*
|
||||||
|
bootClasspath()
|
||||||
|
{
|
||||||
|
return classpath;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose()
|
dispose()
|
||||||
{
|
{
|
||||||
@ -278,6 +348,10 @@ class MyClasspath : public Classpath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Allocator* allocator;
|
Allocator* allocator;
|
||||||
|
const char* javaHome;
|
||||||
|
const char* classpath;
|
||||||
|
const char* libraryPath;
|
||||||
|
char buffer[BufferSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JVM_ExceptionTableEntryType{
|
struct JVM_ExceptionTableEntryType{
|
||||||
@ -560,10 +634,10 @@ interruptLock(Thread* t, object thread)
|
|||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Classpath*
|
Classpath*
|
||||||
makeClasspath(System*, Allocator* allocator)
|
makeClasspath(System* s, Allocator* allocator)
|
||||||
{
|
{
|
||||||
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
||||||
local::MyClasspath(allocator);
|
local::MyClasspath(s, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
@ -1028,18 +1102,20 @@ JVM_InitProperties(Thread* t, jobject properties)
|
|||||||
local::setProperty(t, method, *properties, "os.name", "Linux");
|
local::setProperty(t, method, *properties, "os.name", "Linux");
|
||||||
# endif
|
# endif
|
||||||
local::setProperty(t, method, *properties, "java.io.tmpdir", "/tmp");
|
local::setProperty(t, method, *properties, "java.io.tmpdir", "/tmp");
|
||||||
local::setProperty(t, method, *properties, "java.home", "/tmp");
|
|
||||||
local::setProperty(t, method, *properties, "user.home", getenv("HOME"));
|
local::setProperty(t, method, *properties, "user.home", getenv("HOME"));
|
||||||
local::setProperty(t, method, *properties, "user.dir", getenv("PWD"));
|
local::setProperty(t, method, *properties, "user.dir", getenv("PWD"));
|
||||||
|
|
||||||
// todo: set this to something sane:
|
|
||||||
local::setProperty(t, method, *properties, "sun.boot.library.path",
|
|
||||||
getenv("LD_LIBRARY_PATH"));
|
|
||||||
|
|
||||||
local::setProperty(t, method, *properties, "java.protocol.handler.pkgs",
|
local::setProperty(t, method, *properties, "java.protocol.handler.pkgs",
|
||||||
"avian");
|
"avian");
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
local::setProperty
|
||||||
|
(t, method, *properties, "java.home",
|
||||||
|
static_cast<local::MyClasspath*>(t->m->classpath)->javaHome);
|
||||||
|
|
||||||
|
local::setProperty
|
||||||
|
(t, method, *properties, "sun.boot.library.path",
|
||||||
|
static_cast<local::MyClasspath*>(t->m->classpath)->libraryPath);
|
||||||
|
|
||||||
local::setProperty(t, method, *properties, "file.encoding", "ASCII");
|
local::setProperty(t, method, *properties, "file.encoding", "ASCII");
|
||||||
#ifdef ARCH_x86_32
|
#ifdef ARCH_x86_32
|
||||||
local::setProperty(t, method, *properties, "os.arch", "x86");
|
local::setProperty(t, method, *properties, "os.arch", "x86");
|
||||||
@ -1132,7 +1208,9 @@ JVM_LoadLibrary(const char* name)
|
|||||||
|
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return loadLibrary(t, name, false, false);
|
return loadLibrary
|
||||||
|
(t, static_cast<local::MyClasspath*>(t->m->classpath)->libraryPath, name,
|
||||||
|
false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "zlib-custom.h"
|
#include "zlib-custom.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "tokenizer.h"
|
||||||
#include "finder.h"
|
#include "finder.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
@ -19,8 +20,7 @@ namespace {
|
|||||||
const bool DebugFind = false;
|
const bool DebugFind = false;
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
append(System* s, const char* a, const char* b,
|
append(System* s, const char* a, const char* b, const char* c)
|
||||||
const char* c)
|
|
||||||
{
|
{
|
||||||
unsigned al = strlen(a);
|
unsigned al = strlen(a);
|
||||||
unsigned bl = strlen(b);
|
unsigned bl = strlen(b);
|
||||||
@ -148,6 +148,9 @@ class DirectoryElement: public Element {
|
|||||||
}
|
}
|
||||||
return region;
|
return region;
|
||||||
} else {
|
} else {
|
||||||
|
if (DebugFind) {
|
||||||
|
fprintf(stderr, "%s not found in %s\n", name, this->name);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,8 +496,12 @@ class JarElement: public Element {
|
|||||||
while (*name == '/') name++;
|
while (*name == '/') name++;
|
||||||
|
|
||||||
System::Region* r = (index ? index->find(name, region->start()) : 0);
|
System::Region* r = (index ? index->find(name, region->start()) : 0);
|
||||||
if (DebugFind and r) {
|
if (DebugFind) {
|
||||||
|
if (r) {
|
||||||
fprintf(stderr, "found %s in %s\n", name, this->name);
|
fprintf(stderr, "found %s in %s\n", name, this->name);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s not found in %s\n", name, this->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -533,7 +540,7 @@ class BuiltinElement: public JarElement {
|
|||||||
|
|
||||||
virtual void init() {
|
virtual void init() {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
if (s->success(s->load(&library, libraryName, false))) {
|
if (s->success(s->load(&library, libraryName))) {
|
||||||
void* p = library->resolve(name);
|
void* p = library->resolve(name);
|
||||||
if (p) {
|
if (p) {
|
||||||
uint8_t* (*function)(unsigned*);
|
uint8_t* (*function)(unsigned*);
|
||||||
@ -564,33 +571,6 @@ class BuiltinElement: public JarElement {
|
|||||||
Element*
|
Element*
|
||||||
parsePath(System* s, const char* path, const char* bootLibrary)
|
parsePath(System* s, const char* path, const char* bootLibrary)
|
||||||
{
|
{
|
||||||
class Tokenizer {
|
|
||||||
public:
|
|
||||||
class Token {
|
|
||||||
public:
|
|
||||||
Token(const char* s, unsigned length): s(s), length(length) { }
|
|
||||||
|
|
||||||
const char* s;
|
|
||||||
unsigned length;
|
|
||||||
};
|
|
||||||
|
|
||||||
Tokenizer(const char* s, char delimiter): s(s), delimiter(delimiter) { }
|
|
||||||
|
|
||||||
bool hasMore() {
|
|
||||||
while (*s == delimiter) ++s;
|
|
||||||
return *s;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token next() {
|
|
||||||
const char* p = s;
|
|
||||||
while (*s and *s != delimiter) ++s;
|
|
||||||
return Token(p, s - p);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* s;
|
|
||||||
char delimiter;
|
|
||||||
};
|
|
||||||
|
|
||||||
Element* first = 0;
|
Element* first = 0;
|
||||||
Element* prev = 0;
|
Element* prev = 0;
|
||||||
for (Tokenizer t(path, s->pathSeparator()); t.hasMore();) {
|
for (Tokenizer t(path, s->pathSeparator()); t.hasMore();) {
|
||||||
|
@ -2306,26 +2306,31 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
|||||||
|
|
||||||
if (classpath == 0) classpath = ".";
|
if (classpath == 0) classpath = ".";
|
||||||
|
|
||||||
|
System* s = makeSystem(crashDumpDirectory);
|
||||||
|
Heap* h = makeHeap(s, heapLimit);
|
||||||
|
Classpath* c = makeClasspath(s, h);
|
||||||
|
const char* classpathBootClasspath = c->bootClasspath();
|
||||||
|
|
||||||
unsigned bcppl = strlen(bootClasspathPrepend);
|
unsigned bcppl = strlen(bootClasspathPrepend);
|
||||||
unsigned bcpl = strlen(bootClasspath);
|
unsigned bcpl = strlen(bootClasspath);
|
||||||
|
unsigned cbcpl = strlen(classpathBootClasspath);
|
||||||
unsigned bcpal = strlen(bootClasspathAppend);
|
unsigned bcpal = strlen(bootClasspathAppend);
|
||||||
|
|
||||||
unsigned bootClasspathBufferSize = bcppl + bcpl + bcpal + 3;
|
unsigned bootClasspathBufferSize = bcppl + bcpl + cbcpl + bcpal + 3;
|
||||||
RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize);
|
RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize);
|
||||||
char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer);
|
char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer);
|
||||||
local::append
|
local::append(&bootClasspathPointer, bootClasspathPrepend, bcppl,
|
||||||
(&bootClasspathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR);
|
bcpl + cbcpl + bcpal ? PATH_SEPARATOR : 0);
|
||||||
local::append(&bootClasspathPointer, bootClasspath, bcpl,
|
local::append(&bootClasspathPointer, bootClasspath, bcpl,
|
||||||
|
cbcpl + bcpal ? PATH_SEPARATOR : 0);
|
||||||
|
local::append(&bootClasspathPointer, classpathBootClasspath, cbcpl,
|
||||||
bcpal ? PATH_SEPARATOR : 0);
|
bcpal ? PATH_SEPARATOR : 0);
|
||||||
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
|
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
|
||||||
|
|
||||||
System* s = makeSystem(crashDumpDirectory);
|
|
||||||
Heap* h = makeHeap(s, heapLimit);
|
|
||||||
Finder* bf = makeFinder
|
Finder* bf = makeFinder
|
||||||
(s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
(s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
||||||
Finder* af = makeFinder(s, classpath, bootLibrary);
|
Finder* af = makeFinder(s, classpath, bootLibrary);
|
||||||
Processor* p = makeProcessor(s, h, true);
|
Processor* p = makeProcessor(s, h, true);
|
||||||
Classpath* c = makeClasspath(s, h);
|
|
||||||
|
|
||||||
const char** properties = static_cast<const char**>
|
const char** properties = static_cast<const char**>
|
||||||
(h->allocate(sizeof(const char*) * propertyCount));
|
(h->allocate(sizeof(const char*) * propertyCount));
|
||||||
|
@ -2166,7 +2166,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder,
|
|||||||
not system->success(system->make(&referenceLock)) or
|
not system->success(system->make(&referenceLock)) or
|
||||||
not system->success(system->make(&shutdownLock)) or
|
not system->success(system->make(&shutdownLock)) or
|
||||||
not system->success
|
not system->success
|
||||||
(system->load(&libraries, findProperty(this, "avian.bootstrap"), false)))
|
(system->load(&libraries, findProperty(this, "avian.bootstrap"))))
|
||||||
{
|
{
|
||||||
system->abort();
|
system->abort();
|
||||||
}
|
}
|
||||||
|
@ -1432,6 +1432,9 @@ class Classpath {
|
|||||||
virtual void
|
virtual void
|
||||||
boot(Thread* t) = 0;
|
boot(Thread* t) = 0;
|
||||||
|
|
||||||
|
virtual const char*
|
||||||
|
bootClasspath() = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose() = 0;
|
dispose() = 0;
|
||||||
};
|
};
|
||||||
|
@ -469,13 +469,12 @@ class MySystem: public System {
|
|||||||
class Library: public System::Library {
|
class Library: public System::Library {
|
||||||
public:
|
public:
|
||||||
Library(System* s, void* p, const char* name, unsigned nameLength,
|
Library(System* s, void* p, const char* name, unsigned nameLength,
|
||||||
bool mapName, bool isMain):
|
bool isMain):
|
||||||
s(s),
|
s(s),
|
||||||
p(p),
|
p(p),
|
||||||
mainExecutable(isMain),
|
mainExecutable(isMain),
|
||||||
name_(name),
|
name_(name),
|
||||||
nameLength(nameLength),
|
nameLength(nameLength),
|
||||||
mapName_(mapName),
|
|
||||||
next_(0)
|
next_(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -487,10 +486,6 @@ class MySystem: public System {
|
|||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool mapName() {
|
|
||||||
return mapName_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual System::Library* next() {
|
virtual System::Library* next() {
|
||||||
return next_;
|
return next_;
|
||||||
}
|
}
|
||||||
@ -504,7 +499,7 @@ class MySystem: public System {
|
|||||||
fprintf(stderr, "close %p\n", p);
|
fprintf(stderr, "close %p\n", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mainExecutable) dlclose(p);
|
if (not mainExecutable) dlclose(p);
|
||||||
|
|
||||||
if (next_) {
|
if (next_) {
|
||||||
next_->disposeAll();
|
next_->disposeAll();
|
||||||
@ -522,7 +517,6 @@ class MySystem: public System {
|
|||||||
bool mainExecutable;
|
bool mainExecutable;
|
||||||
const char* name_;
|
const char* name_;
|
||||||
unsigned nameLength;
|
unsigned nameLength;
|
||||||
bool mapName_;
|
|
||||||
System::Library* next_;
|
System::Library* next_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -716,27 +710,23 @@ class MySystem: public System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char* libraryPrefix() {
|
||||||
|
return "lib";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* librarySuffix() {
|
||||||
|
return SO_SUFFIX;
|
||||||
|
}
|
||||||
|
|
||||||
virtual Status load(System::Library** lib,
|
virtual Status load(System::Library** lib,
|
||||||
const char* name,
|
const char* name)
|
||||||
bool mapName)
|
|
||||||
{
|
{
|
||||||
void* p;
|
|
||||||
bool alreadyAllocated = false;
|
|
||||||
bool isMain = false;
|
|
||||||
unsigned nameLength = (name ? strlen(name) : 0);
|
unsigned nameLength = (name ? strlen(name) : 0);
|
||||||
if (mapName and name) {
|
bool isMain = name == 0;
|
||||||
unsigned size = nameLength + 3 + sizeof(SO_SUFFIX);
|
if (isMain) {
|
||||||
char buffer[size];
|
|
||||||
vm::snprintf(buffer, size, "lib%s" SO_SUFFIX, name);
|
|
||||||
p = dlopen(buffer, RTLD_LAZY | RTLD_LOCAL);
|
|
||||||
} else {
|
|
||||||
if (!name) {
|
|
||||||
pathOfExecutable(this, &name, &nameLength);
|
pathOfExecutable(this, &name, &nameLength);
|
||||||
alreadyAllocated = true;
|
|
||||||
isMain = true;
|
|
||||||
}
|
|
||||||
p = dlopen(name, RTLD_LAZY | RTLD_LOCAL);
|
|
||||||
}
|
}
|
||||||
|
void* p = dlopen(name, RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
@ -747,7 +737,7 @@ class MySystem: public System {
|
|||||||
if (name) {
|
if (name) {
|
||||||
n = static_cast<char*>(allocate(this, nameLength + 1));
|
n = static_cast<char*>(allocate(this, nameLength + 1));
|
||||||
memcpy(n, name, nameLength + 1);
|
memcpy(n, name, nameLength + 1);
|
||||||
if (alreadyAllocated) {
|
if (isMain) {
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -755,11 +745,13 @@ class MySystem: public System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*lib = new (allocate(this, sizeof(Library)))
|
*lib = new (allocate(this, sizeof(Library)))
|
||||||
Library(this, p, n, nameLength, mapName, isMain);
|
Library(this, p, n, nameLength, isMain);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
if (Verbose) {
|
||||||
fprintf(stderr, "dlerror: %s\n", dlerror());
|
fprintf(stderr, "dlerror: %s\n", dlerror());
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -768,6 +760,10 @@ class MySystem: public System {
|
|||||||
return ':';
|
return ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual char fileSeparator() {
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
virtual int64_t now() {
|
virtual int64_t now() {
|
||||||
timeval tv = { 0, 0 };
|
timeval tv = { 0, 0 };
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
|
@ -89,7 +89,6 @@ class System {
|
|||||||
public:
|
public:
|
||||||
virtual void* resolve(const char* symbol) = 0;
|
virtual void* resolve(const char* symbol) = 0;
|
||||||
virtual const char* name() = 0;
|
virtual const char* name() = 0;
|
||||||
virtual bool mapName() = 0;
|
|
||||||
virtual Library* next() = 0;
|
virtual Library* next() = 0;
|
||||||
virtual void setNext(Library* lib) = 0;
|
virtual void setNext(Library* lib) = 0;
|
||||||
virtual void disposeAll() = 0;
|
virtual void disposeAll() = 0;
|
||||||
@ -135,8 +134,11 @@ class System {
|
|||||||
virtual Status map(Region**, const char* name) = 0;
|
virtual Status map(Region**, const char* name) = 0;
|
||||||
virtual FileType identify(const char* name) = 0;
|
virtual FileType identify(const char* name) = 0;
|
||||||
virtual Status open(Directory**, const char* name) = 0;
|
virtual Status open(Directory**, const char* name) = 0;
|
||||||
virtual Status load(Library**, const char* name, bool mapName) = 0;
|
virtual const char* libraryPrefix() = 0;
|
||||||
|
virtual const char* librarySuffix() = 0;
|
||||||
|
virtual Status load(Library**, const char* name) = 0;
|
||||||
virtual char pathSeparator() = 0;
|
virtual char pathSeparator() = 0;
|
||||||
|
virtual char fileSeparator() = 0;
|
||||||
virtual int64_t now() = 0;
|
virtual int64_t now() = 0;
|
||||||
virtual void exit(int code) = 0;
|
virtual void exit(int code) = 0;
|
||||||
virtual void abort() = 0;
|
virtual void abort() = 0;
|
||||||
|
45
src/tokenizer.h
Normal file
45
src/tokenizer.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* Copyright (c) 2010, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#ifndef TOKENIZER_H
|
||||||
|
#define TOKENIZER_H
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
|
||||||
|
class Tokenizer {
|
||||||
|
public:
|
||||||
|
class Token {
|
||||||
|
public:
|
||||||
|
Token(const char* s, unsigned length): s(s), length(length) { }
|
||||||
|
|
||||||
|
const char* s;
|
||||||
|
unsigned length;
|
||||||
|
};
|
||||||
|
|
||||||
|
Tokenizer(const char* s, char delimiter): s(s), delimiter(delimiter) { }
|
||||||
|
|
||||||
|
bool hasMore() {
|
||||||
|
while (*s == delimiter) ++s;
|
||||||
|
return *s != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token next() {
|
||||||
|
const char* p = s;
|
||||||
|
while (*s and *s != delimiter) ++s;
|
||||||
|
return Token(p, s - p);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* s;
|
||||||
|
char delimiter;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif//TOKENIZER_H
|
@ -12,9 +12,13 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "assert.h"
|
#include "errno.h"
|
||||||
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "finder.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
#define UNREACHABLE abort()
|
#define UNREACHABLE abort()
|
||||||
|
|
||||||
@ -28,6 +32,8 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
namespace local {
|
||||||
|
|
||||||
#ifndef POINTER_SIZE
|
#ifndef POINTER_SIZE
|
||||||
# define POINTER_SIZE sizeof(void*)
|
# define POINTER_SIZE sizeof(void*)
|
||||||
#endif
|
#endif
|
||||||
@ -177,7 +183,7 @@ class Output {
|
|||||||
void write(int i) {
|
void write(int i) {
|
||||||
static const int Size = 32;
|
static const int Size = 32;
|
||||||
char s[Size];
|
char s[Size];
|
||||||
int c UNUSED = snprintf(s, Size, "%d", i);
|
int c UNUSED = ::snprintf(s, Size, "%d", i);
|
||||||
assert(c > 0 and c < Size);
|
assert(c > 0 and c < Size);
|
||||||
write(s);
|
write(s);
|
||||||
}
|
}
|
||||||
@ -213,63 +219,6 @@ class FileOutput : public Output {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
class Object {
|
||||||
public:
|
public:
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -1384,8 +1333,8 @@ parseJavaClass(Object* type, Stream* s, Object* declarations)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
parseType(Object::ObjectType type, Object* p, Object* declarations,
|
parseType(Finder* finder, Object::ObjectType type, Object* p,
|
||||||
const char* javaClassDirectory)
|
Object* declarations)
|
||||||
{
|
{
|
||||||
const char* name = string(car(p));
|
const char* name = string(car(p));
|
||||||
|
|
||||||
@ -1400,9 +1349,16 @@ parseType(Object::ObjectType type, Object* p, Object* declarations,
|
|||||||
bool isJavaType = javaName and *javaName != '[';
|
bool isJavaType = javaName and *javaName != '[';
|
||||||
|
|
||||||
if (isJavaType) {
|
if (isJavaType) {
|
||||||
const char* file = append(javaClassDirectory, "/", javaName, ".class");
|
class Client: public Stream::Client {
|
||||||
Stream s(fopen(file, "rb"), true);
|
public:
|
||||||
|
virtual void NO_RETURN handleError() {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} client;
|
||||||
|
System::Region* region = finder->find(append(javaName, ".class"));
|
||||||
|
Stream s(&client, region->start(), region->length());
|
||||||
parseJavaClass(t, &s, declarations);
|
parseJavaClass(t, &s, declarations);
|
||||||
|
region->dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = cdr(p); p; p = cdr(p)) {
|
for (p = cdr(p); p; p = cdr(p)) {
|
||||||
@ -1429,14 +1385,13 @@ parseType(Object::ObjectType type, Object* p, Object* declarations,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
parseDeclaration(Object* p, Object* declarations,
|
parseDeclaration(Finder* finder, Object* p, Object* declarations)
|
||||||
const char* javaClassDirectory)
|
|
||||||
{
|
{
|
||||||
const char* spec = string(car(p));
|
const char* spec = string(car(p));
|
||||||
if (equal(spec, "type")) {
|
if (equal(spec, "type")) {
|
||||||
return parseType(Object::Type, cdr(p), declarations, javaClassDirectory);
|
return parseType(finder, Object::Type, cdr(p), declarations);
|
||||||
} else if (equal(spec, "pod")) {
|
} else if (equal(spec, "pod")) {
|
||||||
return parseType(Object::Pod, cdr(p), declarations, javaClassDirectory);
|
return parseType(finder, Object::Pod, cdr(p), declarations);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "unexpected declaration spec: %s\n", spec);
|
fprintf(stderr, "unexpected declaration spec: %s\n", spec);
|
||||||
abort();
|
abort();
|
||||||
@ -1444,7 +1399,7 @@ parseDeclaration(Object* p, Object* declarations,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
parse(Input* in, const char* javaClassDirectory)
|
parse(Finder* finder, Input* in)
|
||||||
{
|
{
|
||||||
Object* eos = Singleton::make(Object::Eos);
|
Object* eos = Singleton::make(Object::Eos);
|
||||||
List declarations;
|
List declarations;
|
||||||
@ -1452,7 +1407,7 @@ parse(Input* in, const char* javaClassDirectory)
|
|||||||
Object* o;
|
Object* o;
|
||||||
while ((o = read(in, eos, 0)) != eos) {
|
while ((o = read(in, eos, 0)) != eos) {
|
||||||
declarations.append
|
declarations.append
|
||||||
(parseDeclaration(o, declarations.first, javaClassDirectory));
|
(parseDeclaration(finder, o, declarations.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
return declarations.first;
|
return declarations.first;
|
||||||
@ -1522,7 +1477,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
|
|
||||||
if (not unsafe) {
|
if (not unsafe) {
|
||||||
out->write("const unsigned ");
|
out->write("const unsigned ");
|
||||||
out->write(capitalize(::typeName(memberOwner(member))));
|
out->write(capitalize(local::typeName(memberOwner(member))));
|
||||||
out->write(capitalize(memberName(member)));
|
out->write(capitalize(memberName(member)));
|
||||||
out->write(" = ");
|
out->write(" = ");
|
||||||
writeOffset(out, offset);
|
writeOffset(out, offset);
|
||||||
@ -1547,7 +1502,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
writeAccessorName(out, member, unsafe);
|
writeAccessorName(out, member, unsafe);
|
||||||
if (memberOwner(member)->type == Object::Pod) {
|
if (memberOwner(member)->type == Object::Pod) {
|
||||||
out->write("(");
|
out->write("(");
|
||||||
out->write(capitalize(::typeName(memberOwner(member))));
|
out->write(capitalize(local::typeName(memberOwner(member))));
|
||||||
out->write("*");
|
out->write("*");
|
||||||
} else {
|
} else {
|
||||||
out->write("(Thread* t UNUSED, object");
|
out->write("(Thread* t UNUSED, object");
|
||||||
@ -1563,13 +1518,13 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
out->write(" assert(t, t->m->unsafe or ");
|
out->write(" assert(t, t->m->unsafe or ");
|
||||||
out->write("instanceOf(t, arrayBodyUnsafe");
|
out->write("instanceOf(t, arrayBodyUnsafe");
|
||||||
out->write("(t, t->m->types, Machine::");
|
out->write("(t, t->m->types, Machine::");
|
||||||
out->write(capitalize(::typeName(memberOwner(member))));
|
out->write(capitalize(local::typeName(memberOwner(member))));
|
||||||
out->write("Type)");
|
out->write("Type)");
|
||||||
out->write(", o));\n");
|
out->write(", o));\n");
|
||||||
|
|
||||||
if (member->type != Object::Scalar) {
|
if (member->type != Object::Scalar) {
|
||||||
out->write(" assert(t, i < ");
|
out->write(" assert(t, i < ");
|
||||||
out->write(::typeName(memberOwner(member)));
|
out->write(local::typeName(memberOwner(member)));
|
||||||
out->write("Length(t, o));\n");
|
out->write("Length(t, o));\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1599,7 +1554,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
out->write("[");
|
out->write("[");
|
||||||
}
|
}
|
||||||
|
|
||||||
out->write(capitalize(::typeName(memberOwner(member))));
|
out->write(capitalize(local::typeName(memberOwner(member))));
|
||||||
out->write(capitalize(memberName(member)));
|
out->write(capitalize(memberName(member)));
|
||||||
|
|
||||||
if (member->type != Object::Scalar) {
|
if (member->type != Object::Scalar) {
|
||||||
@ -2221,62 +2176,83 @@ void
|
|||||||
usageAndExit(const char* command)
|
usageAndExit(const char* command)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s <java class directory> "
|
"usage: %s <classpath> <input file> <output file> "
|
||||||
"{enums,declarations,constructors,initializations,"
|
"{enums,declarations,constructors,initializations,"
|
||||||
"java-initializations}\n",
|
"java-initializations}\n",
|
||||||
command);
|
command);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace local
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
extern "C" uint64_t
|
||||||
|
vmNativeCall(void*, void*, unsigned, unsigned)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
vmJump(void*, void*, void*, void*, uintptr_t, uintptr_t)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int ac, char** av)
|
main(int ac, char** av)
|
||||||
{
|
{
|
||||||
if ((ac != 2 and ac != 3)
|
if (ac != 5
|
||||||
or (ac == 3
|
or not (local::equal(av[4], "enums")
|
||||||
and not equal(av[2], "enums")
|
or local::equal(av[4], "declarations")
|
||||||
and not equal(av[2], "declarations")
|
or local::equal(av[4], "constructors")
|
||||||
and not equal(av[2], "constructors")
|
or local::equal(av[4], "initializations")
|
||||||
and not equal(av[2], "initializations")
|
or local::equal(av[4], "java-initializations")))
|
||||||
and not equal(av[2], "java-initializations")))
|
|
||||||
{
|
{
|
||||||
usageAndExit(av[0]);
|
local::usageAndExit(av[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInput in(0, stdin, false);
|
System* system = makeSystem(0);
|
||||||
|
Finder* finder = makeFinder(system, av[1], 0);
|
||||||
|
|
||||||
Object* declarations = parse(&in, av[1]);
|
FILE* inStream = ::fopen(av[2], "rb");
|
||||||
|
if (inStream == 0) {
|
||||||
FileOutput out(0, stdout, false);
|
fprintf(stderr, "unable to open %s: %s\n", av[2], strerror(errno));
|
||||||
|
return -1;
|
||||||
if (ac == 2 or equal(av[2], "enums")) {
|
|
||||||
writeEnums(&out, declarations);
|
|
||||||
}
|
}
|
||||||
|
local::FileInput in(0, inStream, false);
|
||||||
|
|
||||||
if (ac == 2 or equal(av[2], "declarations")) {
|
local::Object* declarations = local::parse(finder, &in);
|
||||||
|
|
||||||
|
finder->dispose();
|
||||||
|
system->dispose();
|
||||||
|
|
||||||
|
FILE* outStream = ::fopen(av[3], "wb");
|
||||||
|
if (outStream == 0) {
|
||||||
|
fprintf(stderr, "unable to open %s: %s\n", av[3], strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
local::FileOutput out(0, outStream, false);
|
||||||
|
|
||||||
|
if (local::equal(av[4], "enums")) {
|
||||||
|
local::writeEnums(&out, declarations);
|
||||||
|
} else if (local::equal(av[4], "declarations")) {
|
||||||
out.write("const unsigned TypeCount = ");
|
out.write("const unsigned TypeCount = ");
|
||||||
out.Output::write(typeCount(declarations));
|
out.Output::write(local::typeCount(declarations));
|
||||||
out.write(";\n\n");
|
out.write(";\n\n");
|
||||||
|
|
||||||
writePods(&out, declarations);
|
local::writePods(&out, declarations);
|
||||||
writeAccessors(&out, declarations);
|
local::writeAccessors(&out, declarations);
|
||||||
writeSizes(&out, declarations);
|
local::writeSizes(&out, declarations);
|
||||||
writeInitializerDeclarations(&out, declarations);
|
local::writeInitializerDeclarations(&out, declarations);
|
||||||
writeConstructorDeclarations(&out, declarations);
|
local::writeConstructorDeclarations(&out, declarations);
|
||||||
}
|
} else if (local::equal(av[4], "constructors")) {
|
||||||
|
local::writeInitializers(&out, declarations);
|
||||||
if (ac == 2 or equal(av[2], "constructors")) {
|
local::writeConstructors(&out, declarations);
|
||||||
writeInitializers(&out, declarations);
|
} else if (local::equal(av[4], "initializations")) {
|
||||||
writeConstructors(&out, declarations);
|
local::writeInitializations(&out, declarations);
|
||||||
}
|
} else if (local::equal(av[4], "java-initializations")) {
|
||||||
|
local::writeJavaInitializations(&out, declarations);
|
||||||
if (ac == 2 or equal(av[2], "initializations")) {
|
|
||||||
writeInitializations(&out, declarations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ac == 2 or equal(av[2], "java-initializations")) {
|
|
||||||
writeJavaInitializations(&out, declarations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user