diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 1e9acdef76..db9882e051 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -83,6 +83,16 @@ typedef char char_t; #endif // not PLATFORM_WINDOWS +#ifndef WINAPI_FAMILY +# ifndef WINAPI_PARTITION_DESKTOP +# define WINAPI_PARTITION_DESKTOP 1 +# endif + +# ifndef WINAPI_FAMILY_PARTITION +# define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#endif // WINAPI_FAMILY + inline void* operator new(size_t, void* p) throw() { return p; } typedef const char_t* string_t; @@ -214,6 +224,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) { #ifdef PLATFORM_WINDOWS +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) string_t chars = getChars(e, path); if (chars) { const unsigned BufferSize = MAX_PATH; @@ -228,6 +239,11 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) } return path; +# else + // WinRT has no concept of full paths + throwNewErrno(e, "java/io/IOException"); + return path; +# endif #else jstring result = path; string_t chars = getChars(e, path); @@ -256,11 +272,24 @@ Java_java_io_File_length(JNIEnv* e, jclass, jstring path) LARGE_INTEGER fileSize; string_t chars = getChars(e, path); + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE file = CreateFileW (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + #else + HANDLE file = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + #endif releaseChars(e, path, chars); if (file != INVALID_HANDLE_VALUE) + { + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) GetFileSizeEx(file, &fileSize); + #else + FILE_STANDARD_INFO info; + if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + fileSize = info.EndOfFile; + #endif + } else return 0; CloseHandle(file); return static_cast(fileSize.QuadPart); @@ -496,7 +525,11 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) releaseChars(e, path, chars); Directory* d = new (malloc(sizeof(Directory))) Directory; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data)); + #else + d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, NULL, 0); + #endif if (d->handle == INVALID_HANDLE_VALUE) { d->dispose(); d = 0; @@ -725,7 +758,11 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) ssize_t bytesRead = ::read(fd, dst + offset, length); +#else + auto bytesRead = ::read(fd, dst + offset, length); +#endif e->ReleasePrimitiveArrayCritical(buffer, dst, 0); if(bytesRead == -1) { @@ -737,7 +774,7 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, } extern "C" JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_close(JNIEnv*/* e*/, jclass, jlong peer) +Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer) { int fd = (int)peer; ::close(fd); diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 4cafd5e6cc..0414216194 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -62,6 +62,16 @@ #endif // not PLATFORM_WINDOWS +#ifndef WINAPI_FAMILY +# ifndef WINAPI_PARTITION_DESKTOP +# define WINAPI_PARTITION_DESKTOP 1 +# endif + +# ifndef WINAPI_FAMILY_PARTITION +# define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#endif // WINAPI_FAMILY + namespace { #ifdef PLATFORM_WINDOWS char* getErrorStr(DWORD err){ @@ -70,7 +80,8 @@ namespace { snprintf(errStr, 9, "%d", (int) err); return errStr; - // The better way to do this, if I could figure out how to convert LPTSTR to char* + //TODO: + // The better way to do this, if I could figure out how to convert LPTSTR to char* //char* errStr; //LPTSTR s; //if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -83,6 +94,7 @@ namespace { //return errStr; } +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void makePipe(JNIEnv* e, HANDLE p[2]) { SECURITY_ATTRIBUTES sa; @@ -95,6 +107,7 @@ namespace { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); } } +#endif int descriptor(JNIEnv* e, HANDLE h) { @@ -196,7 +209,7 @@ extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { - +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i){ jstring element = (jstring) e->GetObjectArrayElement(command, i); @@ -267,11 +280,15 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass, e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif } extern "C" JNIEXPORT jint JNICALL Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) DWORD exitCode; WaitForSingleObject(reinterpret_cast(pid), INFINITE); BOOL success = GetExitCodeProcess(reinterpret_cast(pid), &exitCode); @@ -283,14 +300,23 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) CloseHandle(reinterpret_cast(tid)); return exitCode; +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); + return -1; +#endif } extern "C" JNIEXPORT void JNICALL -Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid) { +Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TerminateProcess(reinterpret_cast(pid), 1); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif } Locale getLocale() { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) const char* lang = ""; const char* reg = ""; unsigned langid = GetUserDefaultUILanguage(); @@ -362,8 +388,11 @@ Locale getLocale() { default: lang = "en"; } - Locale locale(lang, reg); - return locale; + return Locale(lang, reg); +#else + //TODO: CultureInfo.CurrentCulture + return Locale("en", "US"); +#endif } #else extern "C" JNIEXPORT void JNICALL @@ -531,8 +560,15 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, } else if (strcmp(chars, "file.separator") == 0) { r = e->NewStringUTF("\\"); } else if (strcmp(chars, "os.name") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) r = e->NewStringUTF("Windows"); +# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + r = e->NewStringUTF("Windows Phone"); +# else + r = e->NewStringUTF("Windows RT"); +# endif } else if (strcmp(chars, "os.version") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) unsigned size = 32; RUNTIME_ARRAY(char, buffer, size); OSVERSIONINFO OSversion; @@ -540,6 +576,10 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, ::GetVersionEx(&OSversion); snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%i.%i", (int)OSversion.dwMajorVersion, (int)OSversion.dwMinorVersion); r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer)); +# else + // Currently there is no alternative on WinRT/WP8 + r = e->NewStringUTF("8.0"); +# endif } else if (strcmp(chars, "os.arch") == 0) { #ifdef ARCH_x86_32 r = e->NewStringUTF("x86"); @@ -551,15 +591,28 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = e->NewStringUTF("arm"); #endif } else if (strcmp(chars, "java.io.tmpdir") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TCHAR buffer[MAX_PATH]; GetTempPath(MAX_PATH, buffer); r = e->NewStringUTF(buffer); +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.Storage.ApplicationData.Current.TemporaryFolder + r = 0; +# endif } else if (strcmp(chars, "user.dir") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TCHAR buffer[MAX_PATH]; GetCurrentDirectory(MAX_PATH, buffer); r = e->NewStringUTF(buffer); +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.ApplicationModel.Package.Current.InstalledLocation + r = 0; +# endif } else if (strcmp(chars, "user.home") == 0) { # ifdef _MSC_VER +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) WCHAR buffer[MAX_PATH]; size_t needed; if (_wgetenv_s(&needed, buffer, MAX_PATH, L"USERPROFILE") == 0) { @@ -567,6 +620,11 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, } else { r = 0; } +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.Storage.KnownFolders.DocumentsLibrary; + r = 0; +# endif # else LPWSTR home = _wgetenv(L"USERPROFILE"); r = e->NewString(reinterpret_cast(home), lstrlenW(home)); @@ -654,6 +712,9 @@ namespace { #elif defined __APPLE__ # include # define environ (*_NSGetEnviron()) +#elif defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +// WinRT/WP8 does not provide alternative for environment variables +char* environ[] = { 0 }; #else extern char** environ; #endif diff --git a/makefile b/makefile index 9b4ffb954a..28ef8be401 100755 --- a/makefile +++ b/makefile @@ -51,7 +51,7 @@ ifeq ($(continuations),true) endif root := $(shell (cd .. && pwd)) -build = build/$(platform)-$(arch)$(options) +build = $(build-prefix)build/$(platform)-$(arch)$(options) classpath-build = $(build)/classpath test-build = $(build)/test src = src @@ -59,6 +59,8 @@ classpath-src = classpath test = test win32 ?= $(root)/win32 win64 ?= $(root)/win64 +winrt ?= $(root)/winrt +wp8 ?= $(root)/wp8 classpath = avian @@ -183,6 +185,18 @@ strip-all = --strip-all rdynamic = -rdynamic +cflags_debug = -O0 -g3 +cflags_debug_fast = -O0 -g3 +cflags_stress = -O0 -g3 +cflags_stress_major = -O0 -g3 +ifeq ($(use-clang),true) + cflags_fast = -O4 -g3 + cflags_small = -Oz -g3 +else + cflags_fast = -O3 -g3 + cflags_small = -Os -g3 +endif + # note that we suppress the non-virtual-dtor warning because we never # use the delete operator, which means we don't need virtual # destructors: @@ -198,7 +212,7 @@ common-cflags = $(warnings) -fno-rtti -fno-exceptions -I$(classpath-src) \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags) -asmflags = $(target-cflags) +asmflags = $(target-cflags) -I$(src) ifneq (,$(filter i386 x86_64,$(arch))) ifeq ($(use-frame-pointer),true) @@ -237,6 +251,18 @@ pointer-size = 8 so-prefix = lib so-suffix = .so +static-prefix = lib +static-suffix = .a + +output = -o $(1) +asm-output = -o $(1) +asm-input = -c $(1) +asm-format = S +as = $(cc) +ld = $(cxx) +build-ld = $(build-cc) + +static = -static shared = -shared no-error = -Wno-error @@ -244,6 +270,8 @@ no-error = -Wno-error openjdk-extra-cflags = -fvisibility=hidden bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) +bootimage-symbols = _binary_bootimage_bin_start:_binary_bootimage_bin_end +codeimage-symbols = _binary_codeimage_bin_start:_binary_codeimage_bin_end developer-dir := $(shell if test -d /Developer; then echo /Developer; \ else echo /Applications/Xcode.app/Contents/Developer; fi) @@ -354,41 +382,68 @@ ifeq ($(platform),freebsd) cflags = $(build-cflags) endif ifeq ($(platform),android) - asm = arm - pointer-size = 4 - no-psabi = -Wno-psabi - use-lto = false - ifeq ($(build-platform),cygwin) + ifeq ($(build-platform),cygwin) ndk = "$$(cygpath -u "$(ANDROID_NDK)")" else ndk = $(ANDROID_NDK) endif + ifeq ($(android-version),) + android-version = 5 + endif + + ifeq ($(android-toolchain),) + android-toolchain = 4.7 + endif + + ifeq ($(arch),arm) + android-toolchain-name = arm-linux-androideabi + android-toolchain-prefix = arm-linux-androideabi- + endif + ifeq ($(arch),i386) + android-toolchain-name = x86 + android-toolchain-prefix = i686-linux-android- + endif + + ifeq ($(android-arm-arch),) + android-arm-arch = armv5 + endif + + options := $(options)-api$(android-version)-$(android-toolchain)-$(android-arm-arch) + build-cflags = $(common-cflags) -I$(src) - #build-lflags = -lz -lpthread -ldl + build-lflags = -lz -lpthread ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) build-system = windows build-cxx = i686-w64-mingw32-g++ build-cc = i686-w64-mingw32-gcc - sysroot = "$$(cygpath -w "$(ndk)/platforms/android-5/arch-arm")" + sysroot = "$$(cygpath -w "$(ndk)/platforms/android-$(android-version)/arch-arm")" build-cflags += "-I$(JAVA_HOME)/include/win32" else toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-* - sysroot = $(ndk)/platforms/android-5/arch-arm + sysroot = $(ndk)/platforms/android-$(android-version)/arch-arm build-cflags += "-I$(JAVA_HOME)/include/linux" + build-lflags += -ldl endif - toolchain = $(ndk)/toolchains/arm-linux-androideabi-4.7/prebuilt/$(toolchain-host-platform) - cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 -marm $(no-psabi) - lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -ldl + toolchain = $(ndk)/toolchains/$(android-toolchain-name)-$(android-toolchain)/prebuilt/$(toolchain-host-platform) + cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 $(no-psabi) + lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -llog + target-format = elf use-lto = false - cxx = $(toolchain)/bin/arm-linux-androideabi-g++ --sysroot="$(sysroot)" - cc = $(toolchain)/bin/arm-linux-androideabi-gcc --sysroot="$(sysroot)" - as = $(toolchain)/bin/arm-linux-androideabi-as --sysroot="$(sysroot)" - ar = $(toolchain)/bin/arm-linux-androideabi-ar - ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib - strip = $(toolchain)/bin/arm-linux-androideabi-strip + ifeq ($(arch),arm) + cflags += -marm -march=$(android-arm-arch) -ftree-vectorize -ffast-math -mfloat-abi=softfp + endif + ifeq ($(arch),i386) + endif + + cxx = $(toolchain)/bin/$(android-toolchain-prefix)g++ --sysroot="$(sysroot)" + cc = $(toolchain)/bin/$(android-toolchain-prefix)gcc --sysroot="$(sysroot)" + as = $(cxx) + ar = $(toolchain)/bin/$(android-toolchain-prefix)ar + ranlib = $(toolchain)/bin/$(android-toolchain-prefix)ranlib + strip = $(toolchain)/bin/$(android-toolchain-prefix)strip endif ifeq ($(platform),darwin) @@ -475,7 +530,9 @@ ifeq ($(platform),darwin) endif ifeq ($(platform),windows) - target-format = pe + ifeq ($(target-format),) + target-format = pe + endif inc = "$(win32)/include" lib = "$(win32)/lib" @@ -488,7 +545,8 @@ ifeq ($(platform),windows) so-suffix = .dll exe-suffix = .exe - lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mwindows -mconsole + lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mconsole + bootimage-generator-lflags = -static-libstdc++ -static-libgcc cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 ifeq (,$(filter mingw32 cygwin,$(build-platform))) @@ -539,39 +597,197 @@ ifeq ($(platform),windows) embed-loader-o = $(build-embed)/embed-loader.o endif +ifeq ($(platform),wp8) + ifeq ($(shell uname -s | grep -i -c WOW64),1) + programFiles = Program Files (x86) + else + programFiles = Program Files + endif + ifeq ($(MSVS_ROOT),) + # Environment variable MSVS_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0" + MSVS_ROOT = C:\$(programFiles)\Microsoft Visual Studio 11.0 + endif + ifeq ($(MSVC_ROOT),) + # Environment variable MSVC_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0\VC" + MSVC_ROOT = $(MSVS_ROOT)\VC + endif + ifeq ($(WP80_SDK),) + # Environment variable WP8_SDK not found. It should be something like + # "C:\Program Files[ (x86)]\Microsoft Visual Studio 11.0\VC\WPSDK\WP80" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_SDK = C:\$(programFiles)\Microsoft Visual Studio 11.0\VC\WPSDK\WP80 + endif + ifeq ($(WP80_KIT),) + # Environment variable WP8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Phone Kits\8.0" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_KIT = C:\$(programFiles)\Windows Phone Kits\8.0 + endif + ifeq ($(WIN8_KIT),) + # Environment variable WIN8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Kits\8.0" + WIN8_KIT = C:\$(programFiles)\Windows Kits\8.0 + endif + ifeq ($(build-platform),cygwin) + windows-path = cygpath -w + else + windows-path = $(native-path) + endif + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + target-format = pe + ms_cl_compiler = wp8 + use-lto = false + supports_avian_executable = false + process = interpret + ifneq ($(process),compile) + options := -$(process) + endif + bootimage = true + ifeq ($(bootimage),true) + options := $(options)-bootimage + endif + system = windows + build-system = windows + static-prefix = + static-suffix = .lib + so-prefix = + so-suffix = .dll + exe-suffix = .exe + + ifeq ($(arch),arm) + wp8_arch = \x86_arm + vc_arch = \arm + w8kit_arch = arm + deps_arch = ARM + as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" + asmflags = -machine ARM -32 + asm-output = -o $(1) + asm-input = $(1) + machine_type = ARM + bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end + codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end + endif + ifeq ($(arch),i386) + wp8_arch = + vc_arch = + w8kit_arch = x86 + deps_arch = x86 + as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" + asmflags += -nologo + asm-output = $(output) + machine_type = X86 + endif + + PATH := $(shell cygpath -u "$(MSVS_ROOT)\Common7\IDE"):$(shell cygpath -u "$(WP80_SDK)\bin$(wp8_arch)"):$(shell cygpath -u "$(WP80_SDK)\bin"):${PATH} + + build-cflags = $(common-cflags) -I$(src) -I$(inc) -mthreads + build-lflags = -lz -lpthread + + cflags = -nologo \ + -I"$(WP80_SDK)\include" -I"$(WP80_KIT)\Include" -I"$(WP80_KIT)\Include\minwin" -I"$(WP80_KIT)\Include\mincore" \ + -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP \ + -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ + -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" \ + -Fd$(build)/$(name).pdb -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ + -I"$(build)" \ + -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ + -DTARGET_BYTES_PER_WORD=$(pointer-size) + + common-lflags = $(classpath-lflags) + + arflags = -MACHINE:$(machine_type) + lflags = $(common-lflags) -nologo \ + -MACHINE:$(machine_type) \ + -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ + ws2_32.lib \ + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\ThreadEmulation.lib")" + + cc = $(cxx) + asm-format = masm + shared = -dll + ar = "$$(cygpath -u "$(WP80_SDK)\bin\lib.exe")" + arflags += -nologo + ifeq ($(build-platform),cygwin) + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + dlltool = i686-w64-mingw32-dlltool + ranlib = + strip = + endif + output = -Fo$(1) + + cflags_debug = -Od -Zi -MDd + cflags_debug_fast = -Od -Zi -MDd + cflags_stress = -O0 -g3 -MD + cflags_stress_major = -O0 -g3 -MD + cflags_fast = -O2 -Zi -MD + cflags_small = -O1s -Zi -MD + # -GL [whole program optimization] in 'fast' and 'small' breaks compilation for some reason + + ifeq ($(mode),debug) + cflags += + lflags += + endif + ifeq ($(mode),debug-fast) + cflags += -DNDEBUG + lflags += + endif + ifeq ($(mode),stress_major) + cflags += + lflags += + endif + ifeq ($(mode),fast) + cflags += + lflags += + endif + # -LTCG is needed only if -GL is used + ifeq ($(mode),fast) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + ifeq ($(mode),small) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + + strip = : +endif + ifeq ($(mode),debug) - optimization-cflags = -O0 -g3 - converter-cflags += -O0 -g3 + optimization-cflags = $(cflags_debug) + converter-cflags += $(cflags_debug) strip = : endif ifeq ($(mode),debug-fast) - optimization-cflags = -O0 -g3 -DNDEBUG + optimization-cflags = $(cflags_debug_fast) -DNDEBUG strip = : endif ifeq ($(mode),stress) - optimization-cflags = -O0 -g3 -DVM_STRESS + optimization-cflags = $(cflags_stress) -DVM_STRESS strip = : endif ifeq ($(mode),stress-major) - optimization-cflags = -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR + optimization-cflags = $(cflags_stress_major) -DVM_STRESS -DVM_STRESS_MAJOR strip = : endif ifeq ($(mode),fast) - ifeq ($(use-clang),true) - optimization-cflags = -O4 -g3 -DNDEBUG - else - optimization-cflags = -O3 -g3 -DNDEBUG - endif + optimization-cflags = $(cflags_fast) -DNDEBUG ifeq ($(use-lto),) use-lto = true endif endif ifeq ($(mode),small) - ifeq ($(use-clang),true) - optimization-cflags = -Oz -g3 -DNDEBUG - else - optimization-cflags = -Os -g3 -DNDEBUG - endif + optimization-cflags = $(cflags_small) -DNDEBUG ifeq ($(use-lto),) use-lto = true endif @@ -596,6 +812,7 @@ endif cflags += $(optimization-cflags) +ifndef ms_cl_compiler ifneq ($(platform),darwin) ifeq ($(arch),i386) # this is necessary to support __sync_bool_compare_and_swap: @@ -603,16 +820,9 @@ ifeq ($(arch),i386) lflags += -march=i586 endif endif - -output = -o $(1) -as := $(cc) -ld := $(cc) -build-ld := $(build-cc) - -static = -static +endif ifdef msvc - static = no-error = windows-path = $(native-path) windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") @@ -621,6 +831,7 @@ ifdef msvc cc = $(cxx) ld = "$(msvc)/BIN/link.exe" mt = "mt.exe" + manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ @@ -629,7 +840,7 @@ ifdef msvc -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ -DTARGET_BYTES_PER_WORD=$(pointer-size) - ifneq ($(lzma),) + ifneq ($(lzma),) cflags += -I$(shell $(windows-path) "$(lzma)") endif @@ -656,9 +867,11 @@ ifdef msvc strip = : endif +build-cflags += -DAVIAN_HOST_TARGET + c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) -asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x))) +asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.$(asm-format),$(3)/%-asm.o,$(x))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) generated-code = \ @@ -684,7 +897,7 @@ vm-sources = \ $(src)/jnienv.cpp \ $(src)/process.cpp -vm-asm-sources = $(src)/$(asm).S +vm-asm-sources = $(src)/$(asm).$(asm-format) target-asm = $(asm) @@ -702,8 +915,9 @@ ifeq ($(process),compile) $(src)/compiler.cpp \ $(src)/$(target-asm).cpp - vm-asm-sources += $(src)/compile-$(asm).S + vm-asm-sources += $(src)/compile-$(asm).$(asm-format) endif +cflags += -DAVIAN_PROCESS_$(process) vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(build)) vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build)) @@ -835,7 +1049,7 @@ converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) converter = $(build)/binaryToObject/binaryToObject -static-library = $(build)/lib$(name).a +static-library = $(build)/$(static-prefix)$(name)${static-suffix} executable = $(build)/$(name)${exe-suffix} dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) executable-dynamic = $(build)/$(name)-dynamic${exe-suffix} @@ -945,9 +1159,15 @@ test-flags = -Djava.library.path=$(build) -cp $(build)/test test-args = $(test-flags) $(input) .PHONY: build +ifneq ($(supports_avian_executable),false) build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ $(test-extra-dep) $(embed) +else +build: $(static-library) $(dynamic-library) $(lzma-loader) \ + $(lzma-encoder) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(embed) +endif $(test-dep): $(classpath-dep) @@ -992,7 +1212,7 @@ clean: @echo "removing build" rm -rf build -$(build)/compile-x86-asm.o: $(src)/continuations-x86.S +$(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) @@ -1043,7 +1263,7 @@ endef define compile-asm-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(as) -I$(src) $(asmflags) -c $(<) -o $(@) + $(as) $(asmflags) $(call asm-output,$(@)) $(call asm-input,$(<)) endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) @@ -1054,10 +1274,12 @@ $(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) $(test-library): $(test-cpp-objects) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(test-build)/$(name).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);2" + -IMPLIB:$(test-build)/$(name).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif else $(ld) $(^) $(shared) $(lflags) -o $(@) endif @@ -1065,10 +1287,12 @@ endif ifdef embed $(embed): $(embed-objects) $(embed-loader-o) @echo "building $(embed)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(cxx) $(^) $(lflags) $(static) $(call output,$(@)) endif @@ -1086,10 +1310,12 @@ $(embed-loader-o): $(embed-loader) $(converter) $(embed-loader): $(embed-loader-objects) $(static-library) @mkdir -p $(dir $(@)) cd $(dir $(@)) && $(ar) x ../../../$(static-library) -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(dir $(@))/*.o $(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@))) @@ -1109,7 +1335,7 @@ $(build)/%.o: $(lzma)/C/%.c @mkdir -p $(dir $(@)) $(cxx) $(cflags) $(no-error) -c $$($(windows-path) $(<)) $(call output,$(@)) -$(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S +$(vm-asm-objects): $(build)/%-asm.o: $(src)/%.$(asm-format) $(compile-asm-object) $(bootimage-generator-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) @@ -1196,14 +1422,18 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) @echo "creating $(@)" rm -rf $(@) +ifdef ms_cl_compiler + $(ar) $(arflags) $(^) -out:$(@) +else $(ar) cru $(@) $(^) $(ranlib) $(@) +endif -$(bootimage-object) $(codeimage-object): $(bootimage-generator) \ - $(build)/classpath.jar +$(bootimage-object) $(codeimage-object): $(bootimage-generator) + @echo "generating bootimage and codeimage binaries using $(<)" $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ - -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ - -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end + -bootimage-symbols $(bootimage-symbols) \ + -codeimage-symbols $(codeimage-symbols) executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ @@ -1212,10 +1442,12 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(executable): $(executable-objects) @echo "linking $(@)" ifeq ($(platform),windows) -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(executable-objects) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(@).def $(executable-objects) $(dlltool) -d $(@).def -e $(@).exp @@ -1229,6 +1461,7 @@ endif $(bootimage-generator): $(bootimage-generator-objects) echo arch=$(arch) platform=$(platform) $(MAKE) mode=$(mode) \ + build-prefix=$(build)/host/ \ arch=$(build-arch) \ target-arch=$(arch) \ platform=$(bootimage-platform) \ @@ -1247,17 +1480,19 @@ $(build-bootimage-generator): \ $(lzma-decode-objects) $(lzma-encode-objects) @echo "linking $(@)" ifeq ($(platform),windows) -ifdef msvc - $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb -IMPLIB:$(@).lib \ - -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" +ifdef ms_cl_compiler + $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(@).def $(^) $(dlltool) -d $(@).def -e $(@).exp - $(ld) $(@).exp $(^) $(lflags) -o $(@) + $(ld) $(@).exp $(^) $(bootimage-generator-lflags) $(lflags) -o $(@) endif else - $(ld) $(^) $(rdynamic) $(lflags) -o $(@) + $(ld) $(^) $(rdynamic) $(bootimage-generator-lflags) $(lflags) -o $(@) endif $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ @@ -1265,10 +1500,12 @@ $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(classpath-libraries) $(javahome-object) $(boot-javahome-object) \ $(lzma-decode-objects) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);2" + -IMPLIB:$(build)/$(name).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif else $(ld) $(^) $(version-script-flag) $(soname-flag) \ $(shared) $(lflags) $(bootimage-lflags) \ @@ -1280,11 +1517,13 @@ endif # Ubuntu 11.10 which may be fixable without disabling LTO. $(executable-dynamic): $(driver-dynamic-objects) $(dynamic-library) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) -LIBPATH:$(build) -DEFAULTLIB:$(name) \ - -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) -out:$(@) \ - -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) \ + -out:$(@) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) -o $(@) endif diff --git a/src/arm.h b/src/arm.h index 7e7a4d61dd..adfd92b4ad 100644 --- a/src/arm.h +++ b/src/arm.h @@ -71,33 +71,53 @@ namespace vm { inline void trap() { +#ifdef _MSC_VER + __debugbreak(); +#else asm("bkpt"); +#endif } +#ifndef _MSC_VER inline void memoryBarrier() { asm("nop"); } +#endif inline void storeStoreMemoryBarrier() { +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else memoryBarrier(); +#endif } inline void storeLoadMemoryBarrier() { +#ifdef _MSC_VER + MemoryBarrier(); +#else memoryBarrier(); +#endif } inline void loadMemoryBarrier() { +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else memoryBarrier(); +#endif } +#if defined(AVIAN_PROCESS_compile) + #if defined(__ANDROID__) // http://code.google.com/p/android/issues/detail?id=1803 extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__))); @@ -116,6 +136,8 @@ syncInstructionCache(const void* start, unsigned size) #endif } +#endif // AVIAN_PROCESS_compile + #ifndef __APPLE__ typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); # define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) @@ -160,7 +182,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, unsigned vfpIndex = 0; unsigned vfpBackfillIndex UNUSED = 0; - uintptr_t stack[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding + uintptr_t* stack = new uintptr_t[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding unsigned stackIndex = 0; unsigned ai = 0; @@ -250,10 +272,12 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, } unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2); - return vmNativeCall + auto retVal = vmNativeCall (function, stackSize, stack, stackIndex * BytesPerWord, (gprIndex ? gprTable : 0), (vfpIndex ? vfpTable : 0), returnType); + delete[] stack; + return retVal; } } // namespace vm diff --git a/src/arm.masm b/src/arm.masm new file mode 100644 index 0000000000..8fc09eb875 --- /dev/null +++ b/src/arm.masm @@ -0,0 +1,77 @@ + AREA text, CODE, ARM + + EXPORT vmNativeCall [FUNC] +vmNativeCall + ; arguments: + ; r0 -> r4 : function + ; r1 -> r5 : stackTotal + ; r2 : memoryTable + ; r3 : memoryCount + ; [sp, #0] -> r6 : gprTable + + mov ip, sp ; save stack frame + stmfd sp!, {r4-r6, lr} ; save clobbered non-volatile regs + + ; mv args into non-volatile regs + mov r4, r0 + mov r5, r1 + ldr r6, [ip] + + ; setup stack arguments if necessary + sub sp, sp, r5 ; allocate stack + mov ip, sp +loop + tst r3, r3 + ldrne r0, [r2], #4 + strne r0, [ip], #4 + subne r3, r3, #4 + bne loop + + ; setup argument registers if necessary + tst r6, r6 + ldmneia r6, {r0-r3} + + blx r4 ; call function + add sp, sp, r5 ; deallocate stack + + ldmfd sp!, {r4-r6, pc} ; restore non-volatile regs and return + + EXPORT vmJump [FUNC] +vmJump + mov lr, r0 + ldr r0, [sp] + ldr r1, [sp, #4] + mov sp, r2 + mov r8, r3 + bx lr + +CHECKPOINT_THREAD EQU 4 +CHECKPOINT_STACK EQU 24 + + EXPORT vmRun [FUNC] +vmRun + ; r0: function + ; r1: arguments + ; r2: checkpoint + stmfd sp!, {r4-r11, lr} + ; align stack + sub sp, sp, #12 + + str sp, [r2, #CHECKPOINT_STACK] + + mov r12, r0 + ldr r0, [r2, #CHECKPOINT_THREAD] + + blx r12 + + EXPORT vmRun_returnAddress [FUNC] +vmRun_returnAddress + add sp, sp, #12 + ldmfd sp!, {r4-r11, lr} + bx lr + + EXPORT vmTrap [FUNC] +vmTrap + bkpt 3 + + END \ No newline at end of file diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 8d5d5fc444..186e491447 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -17,13 +17,17 @@ namespace { -#define IMAGE_SIZEOF_SHORT_NAME 8 +// --- winnt.h ---- +#define IMAGE_SIZEOF_SHORT_NAME 8 -#define IMAGE_FILE_RELOCS_STRIPPED 1 -#define IMAGE_FILE_LINE_NUMS_STRIPPED 4 -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_32BIT_MACHINE 256 +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) +#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. #define IMAGE_SCN_ALIGN_1BYTES 0x100000 #define IMAGE_SCN_ALIGN_2BYTES 0x200000 @@ -73,6 +77,7 @@ struct IMAGE_SYMBOL { uint8_t StorageClass; uint8_t NumberOfAuxSymbols; } __attribute__((packed)); +// --- winnt.h ---- inline unsigned pad(unsigned n) @@ -82,7 +87,7 @@ pad(unsigned n) using namespace avian::tools; -template +template class WindowsPlatform : public Platform { public: @@ -202,12 +207,15 @@ public: int machine; int machineMask; - if (BytesPerWord == 8) { + if (Architecture == PlatformInfo::x86_64) { machine = IMAGE_FILE_MACHINE_AMD64; machineMask = 0; - } else { // if (BytesPerWord == 8) + } else if (Architecture == PlatformInfo::x86) { machine = IMAGE_FILE_MACHINE_I386; machineMask = IMAGE_FILE_32BIT_MACHINE; + } else if (Architecture == PlatformInfo::Arm) { + machine = IMAGE_FILE_MACHINE_ARMNT; + machineMask = IMAGE_FILE_32BIT_MACHINE; } int sectionMask; @@ -269,10 +277,11 @@ public: } WindowsPlatform(): - Platform(PlatformInfo(PlatformInfo::Pe, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {} + Platform(PlatformInfo(PlatformInfo::Pe, Architecture)) {} }; -WindowsPlatform<4> windows32Platform; -WindowsPlatform<8> windows64Platform; +WindowsPlatform<4, PlatformInfo::x86> windows32Platform; +WindowsPlatform<8, PlatformInfo::x86_64> windows64Platform; +WindowsPlatform<4, PlatformInfo::Arm> windowsRtPlatform; // Windows Phone 8 and Windows RT } // namespace diff --git a/src/bootimage.cpp b/src/bootimage.cpp index f82e73f9f5..ec04196ca0 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -342,7 +342,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, unsigned count = s.read2() - 1; if (count) { - Type types[count + 2]; + Type* types = new Type[count + 2]; types[0] = Type_object; types[1] = Type_intptr_t; @@ -410,6 +410,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, (t, typeMaps, hashMapFind (t, root(t, Machine::PoolMap), c, objectHash, objectEqual), array, objectHash); + + delete[] types; + types = 0; } } @@ -420,7 +423,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object fields = allFields(t, typeMaps, c, &count, &array); PROTECT(t, fields); - Field memberFields[count + 1]; + Field* memberFields = new Field[count + 1]; unsigned memberIndex; unsigned buildMemberOffset; @@ -454,7 +457,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, const unsigned StaticHeader = 3; - Field staticFields[count + StaticHeader]; + Field* staticFields = new Field[count + StaticHeader]; init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -586,6 +589,12 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, hashMapInsert (t, typeMaps, classStaticTable(t, c), array, objectHash); } + + delete[] memberFields; + memberFields = 0; + + delete[] staticFields; + staticFields = 0; } } } @@ -1334,7 +1343,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp } ++ count; - Field fields[count]; + Field* fields = new Field[count]; init(new (fields) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -1462,6 +1471,9 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp hashMapInsert (t, typeMaps, vm::type(t, static_cast(i)), array, objectHash); + + delete[] fields; + fields = 0; } constants = makeCodeImage @@ -1646,10 +1658,10 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp Platform* platform = Platform::getPlatform(PlatformInfo((PlatformInfo::Format)AVIAN_TARGET_FORMAT, (PlatformInfo::Architecture)AVIAN_TARGET_ARCH)); - // if(!platform) { - // fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); - // return false; - // } + if(!platform) { + fprintf(stderr, "unsupported platform: target-format = %d / target-arch = %d\n", AVIAN_TARGET_FORMAT, AVIAN_TARGET_ARCH); + abort(); + } SymbolInfo bootimageSymbols[] = { SymbolInfo(0, bootimageStart), @@ -1768,7 +1780,7 @@ bool ArgParser::parse(int ac, const char** av) { } bool found = false; for(Arg* arg = first; arg; arg = arg->next) { - if(strcmp(arg->name, &av[i][1]) == 0) { + if(::strcmp(arg->name, &av[i][1]) == 0) { found = true; if (arg->desc == 0) { arg->value = "true"; @@ -1905,20 +1917,26 @@ public: exit(1); } +# if AVIAN_TARGET_FORMAT != AVIAN_FORMAT_PE +# define SYMBOL_PREFIX "_" +# else +# define SYMBOL_PREFIX +# endif + if(!bootimageStart) { - bootimageStart = strdup("_binary_bootimage_bin_start"); + bootimageStart = strdup(SYMBOL_PREFIX"binary_bootimage_bin_start"); } if(!bootimageEnd) { - bootimageEnd = strdup("_binary_bootimage_bin_end"); + bootimageEnd = strdup(SYMBOL_PREFIX"binary_bootimage_bin_end"); } if(!codeimageStart) { - codeimageStart = strdup("_binary_codeimage_bin_start"); + codeimageStart = strdup(SYMBOL_PREFIX"binary_codeimage_bin_start"); } if(!codeimageEnd) { - codeimageEnd = strdup("_binary_codeimage_bin_end"); + codeimageEnd = strdup(SYMBOL_PREFIX"binary_codeimage_bin_end"); } } diff --git a/src/common.h b/src/common.h index adab2f587f..c99f23410e 100644 --- a/src/common.h +++ b/src/common.h @@ -94,7 +94,13 @@ typedef int64_t intptr_t; typedef uint64_t uintptr_t; # define UINT64_C(x) x##L # define ARCH_x86_64 -@ define BYTES_PER_WORD 8 +# define BYTES_PER_WORD 8 +# elif defined _M_ARM_FP +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +# define UINT64_C(x) x##LL +# define ARCH_arm +# define BYTES_PER_WORD 4 # else # error "unsupported architecture" # endif diff --git a/src/interpret.cpp b/src/interpret.cpp index 4a324fd084..9399e96657 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -18,7 +18,7 @@ using namespace vm; -namespace { +namespace local { const unsigned FrameBaseOffset = 0; const unsigned FrameNextOffset = 1; @@ -2321,7 +2321,7 @@ interpret3(Thread* t, const int base) object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); PROTECT(t, class_); - int32_t counts[dimensions]; + int32_t* counts = new int32_t[dimensions]; for (int i = dimensions - 1; i >= 0; --i) { counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { @@ -2338,6 +2338,9 @@ interpret3(Thread* t, const int base) populateMultiArray(t, array, counts, 0, dimensions); pushObject(t, array); + + delete[] counts; + counts = 0; } goto loop; case new_: { @@ -3100,7 +3103,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3124,7 +3127,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3148,7 +3151,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, indirectObjects, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3174,7 +3177,7 @@ class MyProcessor: public Processor { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object getStackTrace(vm::Thread* t, vm::Thread*) { @@ -3254,8 +3257,8 @@ namespace vm { Processor* makeProcessor(System* system, Allocator* allocator, bool) { - return new (allocator->allocate(sizeof(MyProcessor))) - MyProcessor(system, allocator); + return new (allocator->allocate(sizeof(local::MyProcessor))) + local::MyProcessor(system, allocator); } } // namespace vm diff --git a/src/machine.h b/src/machine.h index 2924a13fb7..420a0192cb 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1325,6 +1325,9 @@ checkDaemon(Thread* t); object& root(Thread* t, Machine::Root root); +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) +# define vmRun vmRun_ +#endif extern "C" uint64_t vmRun(uint64_t (*function)(Thread*, uintptr_t*), uintptr_t* arguments, void* checkpoint); diff --git a/src/system.h b/src/system.h index c36aefacd9..14a29c7272 100644 --- a/src/system.h +++ b/src/system.h @@ -97,11 +97,13 @@ class System { virtual void disposeAll() = 0; }; +#if defined(AVIAN_PROCESS_compile) class SignalHandler { public: virtual bool handleSignal(void** ip, void** frame, void** stack, void** thread) = 0; }; +#endif class MonitorResource { public: @@ -121,17 +123,21 @@ class System { virtual bool success(Status) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0; virtual void free(const void* p) = 0; +#if defined(AVIAN_PROCESS_compile) virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0; virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0; +#endif virtual Status attach(Runnable*) = 0; virtual Status start(Runnable*) = 0; virtual Status make(Mutex**) = 0; virtual Status make(Monitor**) = 0; virtual Status make(Local**) = 0; +#if defined(AVIAN_PROCESS_compile) virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleDivideByZero(SignalHandler* handler) = 0; virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor) = 0; +#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0; diff --git a/src/windows.cpp b/src/windows.cpp index 532b66e161..2d8c4c16c4 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -26,6 +26,71 @@ #include "arch.h" #include "system.h" +#if defined(WINAPI_FAMILY) + +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#define WaitForSingleObject(hHandle, dwMilliseconds) \ + WaitForSingleObjectEx((hHandle), (dwMilliseconds), FALSE) + +#define CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) \ + CreateEventEx((lpEventAttributes), (lpName), ((bManualReset)?CREATE_EVENT_MANUAL_RESET:0)|((bInitialState)?CREATE_EVENT_INITIAL_SET:0), EVENT_MODIFY_STATE) + +#define CreateMutex(lpEventAttributes, bInitialOwner, lpName) \ + CreateMutexEx((lpEventAttributes), (lpName), (bInitialOwner)?CREATE_MUTEX_INITIAL_OWNER:0, MUTEX_MODIFY_STATE) + +#include "thread-emulation.h" + +#endif + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) +// Headers in Windows Phone 8 DevKit contain severe error, so let's define needed functions on our own +extern "C" +{ +WINBASEAPI +_Ret_maybenull_ +HANDLE +WINAPI +CreateFileMappingFromApp( + _In_ HANDLE hFile, + _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, + _In_ ULONG PageProtection, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name + ); + +WINBASEAPI +_Ret_maybenull_ __out_data_source(FILE) +PVOID +WINAPI +MapViewOfFileFromApp( + _In_ HANDLE hFileMappingObject, + _In_ ULONG DesiredAccess, + _In_ ULONG64 FileOffset, + _In_ SIZE_T NumberOfBytesToMap + ); + +WINBASEAPI +BOOL +WINAPI +UnmapViewOfFile( + _In_ LPCVOID lpBaseAddress + ); +} +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + +#else + +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif + +#endif + #define ACQUIRE(s, x) MutexResource MAKE_NAME(mutexResource_) (s, x) using namespace vm; @@ -49,16 +114,20 @@ class MutexResource { HANDLE m; }; +#if defined(AVIAN_PROCESS_compile) const unsigned SegFaultIndex = 0; const unsigned DivideByZeroIndex = 1; const unsigned HandlerCount = 2; +#endif class MySystem; MySystem* system; +#if defined(AVIAN_PROCESS_compile) LONG CALLBACK handleException(LPEXCEPTION_POINTERS e); +#endif DWORD WINAPI run(void* r) @@ -559,18 +628,22 @@ class MySystem: public System { }; MySystem(const char* crashDumpDirectory): +#if defined(AVIAN_PROCESS_compile) oldHandler(0), +#endif crashDumpDirectory(crashDumpDirectory) { expect(this, system == 0); system = this; +#if defined(AVIAN_PROCESS_compile) memset(handlers, 0, sizeof(handlers)); +#endif mutex = CreateMutex(0, false, 0); assert(this, mutex); } - +#if defined(AVIAN_PROCESS_compile) bool findHandler() { for (unsigned i = 0; i < HandlerCount; ++i) { if (handlers[i]) return true; @@ -578,6 +651,7 @@ class MySystem: public System { return false; } + //TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx int registerHandler(System::SignalHandler* handler, int index) { if (handler) { handlers[index] = handler; @@ -609,7 +683,7 @@ class MySystem: public System { return 1; } } - +#endif virtual void* tryAllocate(unsigned sizeInBytes) { return malloc(sizeInBytes); } @@ -618,6 +692,7 @@ class MySystem: public System { if (p) ::free(const_cast(p)); } + #if defined(AVIAN_PROCESS_compile) virtual void* tryAllocateExecutable(unsigned sizeInBytes) { return VirtualAlloc (0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); @@ -627,6 +702,7 @@ class MySystem: public System { int r UNUSED = VirtualFree(const_cast(p), 0, MEM_RELEASE); assert(this, r); } + #endif virtual bool success(Status s) { return s == 0; @@ -666,6 +742,7 @@ class MySystem: public System { return 0; } +#if defined(AVIAN_PROCESS_compile) virtual Status handleSegFault(SignalHandler* handler) { return registerHandler(handler, SegFaultIndex); } @@ -710,6 +787,7 @@ class MySystem: public System { return (success ? 0 : 1); } +#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) @@ -719,15 +797,39 @@ class MySystem: public System { virtual Status map(System::Region** region, const char* name) { Status status = 1; - +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE file = CreateFile(name, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); +#else + size_t nameLen = strlen(name); + wchar_t* wideName = new wchar_t[nameLen + 1]; + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); + HANDLE file = CreateFile2(wideName, GENERIC_READ, FILE_SHARE_READ, + OPEN_EXISTING, 0); + delete[] wideName; +#endif if (file != INVALID_HANDLE_VALUE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) unsigned size = GetFileSize(file, 0); +#else + FILE_STANDARD_INFO info; + unsigned size = INVALID_FILE_SIZE; + if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + size = info.EndOfFile.QuadPart; +#endif if (size != INVALID_FILE_SIZE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0); +#else + HANDLE mapping = CreateFileMappingFromApp(file, 0, PAGE_READONLY, size, 0); +#endif if (mapping) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); +#else + void* data = MapViewOfFileFromApp(mapping, FILE_MAP_READ, 0, 0); +#endif if (data) { *region = new (allocate(this, sizeof(Region))) Region(this, static_cast(data), size, file, mapping); @@ -757,7 +859,12 @@ class MySystem: public System { memcpy(RUNTIME_ARRAY_BODY(buffer) + length, "\\*", 3); Directory* d = new (allocate(this, sizeof(Directory))) Directory(this); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) d->handle = FindFirstFile(RUNTIME_ARRAY_BODY(buffer), &(d->data)); +#else + d->handle = FindFirstFileEx(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, 0, 0); +#endif if (d->handle == INVALID_HANDLE_VALUE) { d->dispose(); } else { @@ -797,6 +904,7 @@ class MySystem: public System { } virtual const char* toAbsolutePath(Allocator* allocator, const char* name) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) if (strncmp(name, "//", 2) == 0 or strncmp(name, "\\\\", 2) == 0 or strncmp(name + 1, ":/", 2) == 0 @@ -808,6 +916,11 @@ class MySystem: public System { GetCurrentDirectory(MAX_PATH, buffer); return append(allocator, buffer, "\\", name); } +#else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.ApplicationModel.Package.Current.InstalledLocation + return name; +#endif } virtual Status load(System::Library** lib, @@ -816,9 +929,23 @@ class MySystem: public System { HMODULE handle; unsigned nameLength = (name ? strlen(name) : 0); if (name) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) handle = LoadLibrary(name); +#else + size_t nameLen = strlen(name); + wchar_t* wideName = new wchar_t[nameLen + 1]; + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); + handle = LoadPackagedLibrary(wideName, 0); + delete[] wideName; +#endif } else { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) handle = GetModuleHandle(0); +#else + // Most of WinRT/WP8 applications can not host native object files inside main executable + assert(this, false); +#endif } if (handle) { @@ -866,7 +993,11 @@ class MySystem: public System { } virtual void yield() { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) SwitchToThread(); +#else + YieldProcessor(); +#endif } virtual void exit(int code) { @@ -886,11 +1017,15 @@ class MySystem: public System { } HANDLE mutex; +#if defined(AVIAN_PROCESS_compile) SignalHandler* handlers[HandlerCount]; LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; +#endif const char* crashDumpDirectory; }; +#if defined(AVIAN_PROCESS_compile) + #pragma pack(push,4) struct MINIDUMP_EXCEPTION_INFORMATION { DWORD thread; @@ -1005,6 +1140,8 @@ handleException(LPEXCEPTION_POINTERS e) return EXCEPTION_CONTINUE_SEARCH; } +#endif + } // namespace namespace vm { diff --git a/src/x86.masm b/src/x86.masm new file mode 100644 index 0000000000..715669f8c1 --- /dev/null +++ b/src/x86.masm @@ -0,0 +1,166 @@ +comment # + Copyright (c) 2008-2011, 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. +# + +.586 +.MODEL FLAT, C + +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +CHECKPOINT_THREAD equ 4 +CHECKPOINT_STACK equ 24 +CHECKPOINT_BASE equ 28 + +_TEXT SEGMENT + +public C detectFeature +detectFeature: + push ebp + mov ebp,esp + push edx + push ecx + push ebx + push esi + push edi + mov esi,ds:dword ptr[12+ebp] + mov edi,ds:dword ptr[8+ebp] + mov eax,1 + cpuid + and edx,esi + and ecx,edi + or ecx,edx + test ecx,ecx + je LNOSSE + mov eax,1 + jmp LSSEEND + +LNOSSE: + mov eax,0 + +LSSEEND: + pop edi + pop esi + pop ebx + pop ecx + pop edx + mov esp,ebp + pop ebp + ret + +public C vmNativeCall +vmNativeCall: + push ebp + mov ebp,esp + mov ecx,ds:dword ptr[16+ebp] + sub esp,ecx + mov ecx,0 + jmp Ltest + +Lloop: + mov eax,ecx + mov edx,ecx + add edx,esp + add eax,ds:dword ptr[12+ebp] + mov eax,ds:dword ptr[eax] + mov ds:dword ptr[edx],eax + add ecx,4 + +Ltest: + cmp ecx,ds:dword ptr[16+ebp] + jb Lloop + call dword ptr[8+ebp] + mov ecx,ds:dword ptr[20+ebp] + +Lvoid: + cmp ecx,offset VOID_TYPE + jne Lint64 + jmp Lexit + +Lint64: + cmp ecx,offset INT64_TYPE + jne Lfloat + jmp Lexit + +Lfloat: + cmp ecx,offset FLOAT_TYPE + jne Ldouble + fstp ds:dword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + jmp Lexit + +Ldouble: + cmp ecx,offset DOUBLE_TYPE + jne Lexit + fstp ds:dword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + mov edx,ds:dword ptr[12+ebp] + +Lexit: + mov esp,ebp + pop ebp + ret + +public C vmJump +vmJump: + mov esi,ds:dword ptr[4+esp] + mov ebp,ds:dword ptr[8+esp] + mov ebx,ds:dword ptr[16+esp] + mov eax,ds:dword ptr[20+esp] + mov edx,ds:dword ptr[24+esp] + mov esp,ds:dword ptr[12+esp] + jmp esi + +VMRUN_FRAME_SIZE equ 24 + +public C vmRun_ +vmRun_: + ; 8(%ebp): function + ; 12(%ebp): arguments + ; 16(%ebp): checkpoint + push ebp + mov ebp,esp + sub esp,offset VMRUN_FRAME_SIZE + + mov ds:dword ptr[8+esp],ebx + mov ds:dword ptr[12+esp],esi + mov ds:dword ptr[16+esp],edi + + mov eax,ds:dword ptr[12+ebp] + mov ds:dword ptr[4+esp],eax + + mov ecx,ds:dword ptr[16+ebp] + mov eax,ds:dword ptr[CHECKPOINT_THREAD+ecx] + mov ds:dword ptr[0+esp],eax + + mov ds:dword ptr[CHECKPOINT_STACK+ecx],esp + + call dword ptr[8+ebp] + +public C vmRun_returnAddress +vmRun_returnAddress: + + mov ebx,ds:dword ptr[8+esp] + mov esi,ds:dword ptr[12+esp] + mov edi,ds:dword ptr[16+esp] + + add esp,offset VMRUN_FRAME_SIZE + pop ebp + ret + +_TEXT ENDS +END \ No newline at end of file