first step towards supporting Android class library on Windows

A majority of the tests are passing, but more work is needed to get
them all to pass.
This commit is contained in:
Joel Dice 2013-03-14 15:33:05 -06:00
parent 5d3dc707cb
commit d5504d8f58
3 changed files with 243 additions and 40 deletions

View File

@ -165,21 +165,47 @@ ifneq ($(android),)
-I$(build)/android-src/external/fdlibm \
-I$(build)/android-src \
-fno-exceptions \
-DHAVE_SYS_UIO_H \
-D_FILE_OFFSET_BITS=64 \
-g3 \
-Werror \
-fPIC
-Werror
luni-cpps := $(shell find $(luni-native) -name '*.cpp')
ifeq ($(platform),windows)
android-cflags += -D__STDC_CONSTANT_MACROS
ifneq ($(arch),i386)
android-cflags += -fPIC
endif
blacklist = $(luni-native)/java_io_Console.cpp \
$(luni-native)/java_lang_ProcessManager.cpp \
$(luni-native)/libcore_io_OsConstants.cpp \
$(luni-native)/libcore_io_Posix.cpp \
$(luni-native)/libcore_io_AsynchronousCloseMonitor.cpp \
$(luni-native)/libcore_net_RawSocket.cpp \
$(luni-native)/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp \
$(luni-native)/AsynchronousSocketCloseMonitor.cpp \
$(luni-native)/NetworkUtilities.cpp
luni-cpps := $(filter-out $(blacklist),$(luni-cpps))
icu-libs := $(android)/icu4c/lib/sicuin.a \
$(android)/icu4c/lib/sicuuc.a \
$(android)/icu4c/lib/sicudt.a
platform-lflags := -lgdi32
else
android-cflags += -fPIC -DHAVE_SYS_UIO_H
icu-libs := $(android)/icu4c/lib/icui18n.a \
$(android)/icu4c/lib/libicuuc.a \
$(android)/icu4c/lib/libicudat.a
endif
classpath-lflags := \
$(android)/icu4c/lib/libicui18n.a \
$(android)/icu4c/lib/libicuuc.a \
$(android)/icu4c/lib/libicudata.a \
$(icu-libs) \
$(android)/fdlibm/libfdm.a \
$(android)/expat/.libs/libexpat.a \
$(android)/openssl-upstream/libssl.a \
$(android)/openssl-upstream/libcrypto.a \
$(platform-lflags) \
-lstdc++
luni-cpps := $(shell find $(luni-native) -name '*.cpp')
classpath-objects = \
$(call cpp-objects,$(luni-cpps),$(luni-native),$(build))
luni-java = $(android)/libcore/luni/src/main/java
@ -198,6 +224,8 @@ ifneq ($(android),)
javahome-object = $(build)/javahome-jar.o
boot-javahome-object = $(build)/boot-javahome.o
build-javahome = $(android)/bionic/libc/zoneinfo
stub-sources = $(src)/android/stubs.cpp
stub-objects = $(call cpp-objects,$(stub-sources),$(src),$(build))
endif
ifeq ($(classpath),avian)
@ -1017,7 +1045,7 @@ target-asm = $(asm)
build-embed = $(build)/embed
build-embed-loader = $(build)/embed-loader
embed-loader-sources = $(src)/embedded-loader.cpp
embed-loader-sources = $(src)/embedded-loader.cpp $(stub-sources)
embed-loader-objects = $(call cpp-objects,$(embed-loader-sources),$(src),$(build-embed-loader))
embed-sources = $(src)/embed.cpp
@ -1091,14 +1119,12 @@ ifeq ($(continuations),true)
asmflags += -DAVIAN_CONTINUATIONS
endif
bootimage-generator-sources = $(src)/tools/bootimage-generator/main.cpp $(src)/util/arg-parser.cpp
bootimage-generator-sources = $(src)/tools/bootimage-generator/main.cpp $(src)/util/arg-parser.cpp $(stub-sources)
ifneq ($(lzma),)
bootimage-generator-sources += $(src)/lzma-encode.cpp
endif
ifneq ($(android),)
bootimage-generator-sources += $(src)/android/stubs.cpp
endif
bootimage-generator-objects = \
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(build))
bootimage-generator = $(build)/bootimage-generator
@ -1438,10 +1464,7 @@ $(classpath-dep): $(classpath-sources) $(classpath-jar-dep)
@touch $(@)
$(build)/android-src/%.cpp: $(luni-native)/%.cpp
if [ "$(luni-native)/libcore_icu_ICU.cpp" = "$(<)" ]; then \
sed 's/register_libcore_icu_ICU/hide_register_libcore_icu_ICU/' \
< $(<) > $(@).tmp && cat $(@).tmp $(src)/android/icu.cpp > $(@); else \
cp $(<) $(@); fi
cp $(<) $(@)
$(build)/%.o: $(build)/android-src/%.cpp $(build)/android.dep
@echo "compiling $(@)"
@ -1562,8 +1585,8 @@ $(embed-loader-o): $(embed-loader) $(converter)
$(converter) $(<) $(@) _binary_loader_start \
_binary_loader_end $(target-format) $(arch)
$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \
$(javahome-object) $(boot-javahome-object) $(lzma-decode-objects)
$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-object) \
$(heapwalk-objects) $(lzma-decode-objects)
ifdef ms_cl_compiler
$(ld) $(lflags) $(^) -out:$(@) \
-debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags)
@ -1701,7 +1724,7 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
$(javahome-object) $(boot-javahome-object) $(lzma-decode-objects)
unittest-executable-objects = $(unittest-objects) $(vm-objects) \
$(build)/util/arg-parser.o
$(build)/util/arg-parser.o $(stub-objects)
ifeq ($(process),interpret)
unittest-executable-objects += $(all-codegen-target-objects)
@ -1742,7 +1765,7 @@ define link-executable
@echo linking $(@)
$(dlltool) -z $(@).def $(^)
$(dlltool) -d $(@).def -e $(@).exp
$(ld) $(@).exp $(^) $(lflags) -o $(@)
$(ld) $(@).exp $(^) $(lflags) $(classpath-lflags) -o $(@)
endef
endif
endif

View File

@ -1,12 +0,0 @@
void
register_libcore_icu_ICU(JNIEnv* e)
{
UErrorCode status = U_ZERO_ERROR;
udata_setFileAccess(UDATA_NO_FILES, &status);
if (status != U_ZERO_ERROR) abort();
u_init(&status);
if (status != U_ZERO_ERROR) abort();
jniRegisterNativeMethods(e, "libcore/icu/ICU", gMethods, NELEM(gMethods));
}

View File

@ -24,6 +24,18 @@ namespace {
namespace local {
void*
getDirectBufferAddress(Thread* t, object b)
{
PROTECT(t, b);
object field = resolveField
(t, objectClass(t, b), "effectiveDirectAddress", "J");
return reinterpret_cast<void*>
(fieldAtOffset<int64_t>(b, fieldOffset(t, field)));
}
void JNICALL
loadLibrary(Thread* t, object, uintptr_t* arguments)
{
@ -140,6 +152,28 @@ initVmThread(Thread* t, object thread)
}
}
void JNICALL
createThread(Thread* t, object method, uintptr_t* arguments)
{
object thread = reinterpret_cast<object>(arguments[0]);
PROTECT(t, thread);
object group = reinterpret_cast<object>(arguments[1]);
PROTECT(t, group);
object name = reinterpret_cast<object>(arguments[2]);
PROTECT(t, name);
int64_t stackSize; memcpy(&stackSize, arguments + 3, 8);
initVmThread(t, thread);
t->m->processor->invoke
(t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
thread, group, name, stackSize);
}
object
translateStackTrace(Thread* t, object raw)
{
@ -163,7 +197,8 @@ translateStackTrace(Thread* t, object raw)
class MyClasspath : public Classpath {
public:
MyClasspath(Allocator* allocator):
allocator(allocator)
allocator(allocator),
tzdata(0)
{ }
virtual object
@ -329,7 +364,11 @@ class MyClasspath : public Classpath {
{
// Android's System.initSystemProperties throws an NPE if
// LD_LIBRARY_PATH is not set as of this writing:
#ifdef PLATFORM_WINDOWS
_wputenv(L"LD_LIBRARY_PATH=dummy");
#else
setenv("LD_LIBRARY_PATH", "", false);
#endif
{ object c = resolveClass
(t, root(t, Machine::BootLoader), "java/lang/Runtime", false);
@ -375,6 +414,19 @@ class MyClasspath : public Classpath {
intercept(t, c, "close", "()V", voidPointer(closeMemoryMappedFile));
}
}
{ object c = resolveClass
(t, root(t, Machine::BootLoader), "java/lang/Thread", false);
if (c) {
PROTECT(t, c);
intercept(t, c, "create",
"(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;"
"Ljava/lang/String;J)V",
voidPointer(createThread));
}
}
JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0);
}
@ -419,13 +471,7 @@ class MyClasspath : public Classpath {
virtual void*
getDirectBufferAddress(Thread* t, object b)
{
PROTECT(t, b);
object field = resolveField
(t, objectClass(t, b), "effectiveDirectAddress", "J");
return reinterpret_cast<void*>
(fieldAtOffset<int64_t>(b, fieldOffset(t, field)));
return local::getDirectBufferAddress(t, b);
}
virtual int64_t
@ -599,11 +645,21 @@ jniThrowIOException(JNIEnv* e, const char* message)
extern "C" const char*
jniStrError(int error, char* buffer, size_t length)
{
#ifdef PLATFORM_WINDOWS
const char* s = strerror(error);
if (strlen(s) < length) {
strncpy(buffer, s, length);
return buffer;
} else {
return 0;
}
#else
if (static_cast<int>(strerror_r(error, buffer, length)) == 0) {
return buffer;
} else {
return 0;
}
#endif
}
extern "C" int
@ -1676,3 +1732,139 @@ Avian_java_lang_System_mapLibraryName
RUNTIME_ARRAY_BODY(originalChars),
t->m->system->librarySuffix()));
}
#ifdef PLATFORM_WINDOWS
# include <io.h>
void register_java_io_Console(_JNIEnv*) { }
void register_java_lang_ProcessManager(_JNIEnv*) { }
void register_libcore_io_OsConstants(_JNIEnv*) { }
void register_libcore_io_AsynchronousCloseMonitor(_JNIEnv*) { }
void register_libcore_io_Posix(_JNIEnv*) { }
void register_libcore_net_RawSocket(_JNIEnv*) { }
void register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(_JNIEnv*) { }
extern "C" JNIEXPORT void JNICALL
Avian_libcore_io_OsConstants_initConstants
(Thread* t, object method, uintptr_t*)
{
object c = methodClass(t, method);
PROTECT(t, c);
object table = classStaticTable(t, c);
PROTECT(t, table);
object field = resolveField(t, c, "STDIN_FILENO", "I");
fieldAtOffset<jint>(table, fieldOffset(t, field)) = 0;
field = resolveField(t, c, "STDOUT_FILENO", "I");
fieldAtOffset<jint>(table, fieldOffset(t, field)) = 1;
field = resolveField(t, c, "STDERR_FILENO", "I");
fieldAtOffset<jint>(table, fieldOffset(t, field)) = 2;
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_libcore_io_Posix_getenv(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[1]);
THREAD_RUNTIME_ARRAY(t, uint16_t, chars, stringLength(t, name) + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(chars));
wchar_t* value = _wgetenv
(reinterpret_cast<wchar_t*>(RUNTIME_ARRAY_BODY(chars)));
if (value) {
unsigned size = wcslen(value);
object a = makeCharArray(t, size);
if (size) {
memcpy(&charArrayBody(t, a, 0), value, size * sizeof(jchar));
}
return reinterpret_cast<uintptr_t>
(t->m->classpath->makeString(t, a, 0, size));
} else {
return 0;
}
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_libcore_io_Posix_uname(Thread* t, object, uintptr_t*)
{
object c = resolveClass
(t, root(t, Machine::BootLoader), "libcore/io/StructUtsname");
PROTECT(t, c);
object instance = makeNew(t, c);
PROTECT(t, instance);
#ifdef ARCH_x86_32
object arch = makeString(t, "x86");
#elif defined ARCH_x86_64
object arch = makeString(t, "x86_64");
#elif defined ARCH_powerpc
object arch = makeString(t, "ppc");
#elif defined ARCH_arm
object arch = makeString(t, "arm");
#else
object arch = makeString(t, "unknown");
#endif
set(t, instance, fieldOffset
(t, resolveField(t, c, "machine", "Ljava/lang/String;")), arch);
object platform = makeString(t, "Windows");
set(t, instance, fieldOffset
(t, resolveField(t, c, "sysname", "Ljava/lang/String;")), platform);
object version = makeString(t, "unknown");
set(t, instance, fieldOffset
(t, resolveField(t, c, "release", "Ljava/lang/String;")), version);
return reinterpret_cast<uintptr_t>(instance);
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_libcore_io_Posix_writeBytes(Thread* t, object, uintptr_t* arguments)
{
object fd = reinterpret_cast<object>(arguments[1]);
PROTECT(t, fd);
object buffer = reinterpret_cast<object>(arguments[2]);
PROTECT(t, buffer);
int offset = arguments[3];
int count = arguments[4];
int d = jniGetFDFromFileDescriptor(t, &fd);
int r;
if (objectClass(t, buffer) == type(t, Machine::ByteArrayType)) {
void* tmp = t->m->heap->allocate(count);
memcpy(tmp, &byteArrayBody(t, buffer, offset), count);
{ ENTER(t, Thread::IdleState);
r = _write(d, tmp, count);
}
t->m->heap->free(tmp, count);
} else {
void* p = local::getDirectBufferAddress(t, buffer);
{ ENTER(t, Thread::IdleState);
r = _write(d, p, count);
}
}
if (r < 0) {
THREAD_RUNTIME_ARRAY(t, char, message, 256);
throwNew(t, Machine::RuntimeExceptionType, "writeBytes %d: %s", d,
jniStrError(errno, RUNTIME_ARRAY_BODY(message), 0));
} else {
return r;
}
}
#endif