This commit is contained in:
Mike Jensen 2013-04-29 11:45:32 -06:00
commit bd2ebfce07
240 changed files with 31223 additions and 21054 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ build
bin
/lib
/distrib
*.pdb

2
.travis.yml Normal file
View File

@ -0,0 +1,2 @@
language: cpp
script: ./test/ci.sh

804
README.md Normal file
View File

@ -0,0 +1,804 @@
Avian - A lightweight Java Virtual Machine (JVM)
================================================
[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian)
Quick Start
-----------
#### on Linux:
$ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed
$ make
$ build/linux-i386/avian -cp build/linux-i386/test Hello
#### on Mac OS X:
$ export JAVA_HOME=/Library/Java/Home
$ make
$ build/darwin-i386/avian -cp build/darwin-i386/test Hello
#### on Windows (MSYS):
$ git clone git@github.com:ReadyTalk/win32.git ../win32
$ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07"
$ make
$ build/windows-i386/avian -cp build/windows-i386/test Hello
#### on Windows (Cygwin):
$ git clone git@github.com:ReadyTalk/win32.git ../win32
$ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07"
$ make
$ build/windows-i386/avian -cp build/windows-i386/test Hello
#### on FreeBSD:
$ export JAVA_HOME=/usr/local/openjdk7 # or wherever you have the JDK installed
$ gmake
$ build/freebsd-x86_64/avian -cp build/freebsd-x86_64/test Hello
Adjust JAVA_HOME according to your system, but be sure to use forward
slashes in the path.
Introduction
------------
Avian is a lightweight virtual machine and class library designed to
provide a useful subset of Java's features, suitable for building
self-contained applications. More information is available at the
project [web site](http://oss.readytalk.com/avian).
If you have any trouble building, running, or embedding Avian, please
post a message to our [discussion group](http://groups.google.com/group/avian).
That's also the place for any other questions, comments, or
suggestions you might have.
Supported Platforms
-------------------
Avian can currently target the following platforms:
* Linux (i386, x86_64, ARM, and 32-bit PowerPC)
* Windows (i386 and x86_64)
* Mac OS X (i386, x86_64 and 32-bit PowerPC)
* Apple iOS (i386 and ARM)
* FreeBSD (i386, x86_64)
Building
--------
Build requirements include:
* GNU make 3.80 or later
* GCC 3.4 or later (4.5.1 or later for Windows/x86_64)
or LLVM Clang 3.1 or later (see use-clang option below)
* JDK 1.5 or later
* MinGW 3.4 or later (only if compiling for Windows)
* zlib 1.2.3 or later
Earlier versions of some of these packages may also work but have not
been tested.
The build is directed by a single makefile and may be influenced via
certain flags described below, all of which are optional.
$ make \
platform={linux,windows,darwin,freebsd} \
arch={i386,x86_64,powerpc,arm} \
process={compile,interpret} \
mode={debug,debug-fast,fast,small} \
lzma=<lzma source directory> \
ios={true,false} \
bootimage={true,false} \
heapdump={true,false} \
tails={true,false} \
continuations={true,false} \
use-clang={true,false} \
openjdk=<openjdk installation directory> \
openjdk-src=<openjdk source directory> \
android=<android source directory>
* `platform` - the target platform
* _default:_ output of $(uname -s | tr [:upper:] [:lower:]),
normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows)
* `arch` - the target architecture
* _default:_ output of $(uname -m), normalized in some cases
(e.g. i686 -> i386)
* `process` - choice between pure interpreter or JIT compiler
* _default:_ compile
* `mode` - which set of compilation flags to use to determine
optimization level, debug symbols, and whether to enable
assertions
* _default:_ fast
* `lzma` - if set, support use of LZMA to compress embedded JARs and
boot images. The value of this option should be a directory
containing a recent LZMA SDK (available [here](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of
the SDK has been tested, but other versions might work.
* _default:_ not set
* `ios` - if true, cross-compile for iOS on OS X. Note that
non-jailbroken iOS devices do not allow JIT compilation, so only
process=interpret or bootimage=true builds will run on such
devices. See [here](https://github.com/ReadyTalk/hello-ios) for an
example of an Xcode project for iOS which uses Avian.
* _default:_ false
* `bootimage` - if true, create a boot image containing the pre-parsed
class library and ahead-of-time compiled methods. This option is
only valid for process=compile builds. Note that you may need to
specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems
where "uname -m" prints "i386".
* _default:_ false
* `heapdump` - if true, implement avian.Machine.dumpHeap(String),
which, when called, will generate a snapshot of the heap in a
simple, ad-hoc format for memory profiling purposes. See
heapdump.cpp for details.
* _default:_ false
* `tails` - if true, optimize each tail call by replacing the caller's
stack frame with the callee's. This convention ensures proper
tail recursion, suitable for languages such as Scheme. This
option is only valid for process=compile builds.
* _default:_ false
* `continuations` - if true, support continuations via the
avian.Continuations methods callWithCurrentContinuation and
dynamicWind. See Continuations.java for details. This option is
only valid for process=compile builds.
* _default:_ false
* `use-clang` - if true, use LLVM's clang instead of GCC to build.
Note that this does not currently affect cross compiles, only
native builds.
* _default:_ false
* `openjdk` - if set, use the OpenJDK class library instead of the
default Avian class library. See "Building with the OpenJDK Class
Library" below for details.
* _default:_ not set
* `openjdk-src` - if this and the openjdk option above are both set,
build an embeddable VM using the OpenJDK class library. The JNI
components of the OpenJDK class library will be built from the
sources found under the specified directory. See "Building with
the OpenJDK Class Library" below for details.
* _default:_ not set
* `android` - if set, use the Android class library instead of the
default Avian class library. See "Building with the Android Class
Library" below for details.
* _default:_ not set
These flags determine the name of the directory used for the build.
The name always starts with _${platform}-${arch}_, and each non-default
build option is appended to the name. For example, a debug build with
bootimage enabled on Linux/i386 would be built in
_build/linux-i386-debug-bootimage_. This allows you to build with
several different sets of options independently and even
simultaneously without doing a clean build each time.
If you are compiling for Windows, you may either cross-compile using
MinGW or build natively on Windows under MSYS or Cygwin.
#### Installing MSYS:
__1.__ Download and install the current MinGW and MSYS packages from
mingw.org, selecting the C and C++ compilers when prompted. Use the
post-install script to create the filesystem link to the compiler.
__2.__ Download GNU Make 3.81 from the MSYS download page
(make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into
_e.g. c:/msys/1.0_.
#### Installing Cygwin:
__1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), installing the base
system and these packages: make, gcc-mingw-g++,
mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git.
You may also find our win32 repository useful: (run this from the
directory containing the avian directory)
$ git clone git@github.com:ReadyTalk/win32.git
This gives you the Windows JNI headers, zlib headers and library, and
a few other useful libraries like OpenSSL, libjpeg, and libpng.
There's also a win64 repository for 64-bit builds:
$ git clone git@github.com:ReadyTalk/win64.git
Building with the Microsoft Visual C++ Compiler
-----------------------------------------------
You can also build using the MSVC compiler, which makes debugging with
tools like WinDbg and Visual Studio much easier. Note that you will
still need to have GCC installed - MSVC is only used to compile the
C++ portions of the VM, while the assembly code and helper tools are
built using GCC.
The MSVC build has been tested with Visual Studio Express Edition
versions 8, 9, and 10. Other versions may also work.
To build with MSVC, install Cygwin as described above and set the
following environment variables:
$ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem"
$ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;"
$ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC"
$ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;"
$ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;"
Adjust these definitions as necessary according to your MSVC
installation.
Finally, build with the msvc flag set to the MSVC tool directory:
$ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC"
Building with the OpenJDK Class Library
---------------------------------------
By default, Avian uses its own lightweight class library. However,
that library only contains a relatively small subset of the classes
and methods included in the JRE. If your application requires
features beyond that subset, you may want to tell Avian to use
OpenJDK's class library instead. To do so, specify the directory
where OpenJDK is installed, e.g.:
$ make openjdk=/usr/lib/jvm/java-7-openjdk
This will build Avian as a conventional JVM (e.g. libjvm.so) which
loads its boot class library and native libraries (e.g. libjava.so)
from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. Note that you must
use an absolute path here, or else the result will not work when run
from other directories. In this configuration, OpenJDK needs to
remain installed for Avian to work, and you can run applications like
this:
$ build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \
com.example.MyApplication
Alternatively, you can enable a stand-alone build using OpenJDK by
specifying the location of the OpenJDK source code, e.g.:
$ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \
openjdk-src=$(pwd)/../jdk7/jdk/src
You must ensure that the path specified for openjdk-src does not have
any spaces in it; make gets confused when dependency paths include
spaces, and we haven't found away around that except to avoid paths
with spaces entirely.
The result of such a build is a self-contained binary which does not
depend on external libraries, jars, or other files. In this case, the
specified paths are used only at build time; anything needed at
runtime is embedded in the binary. Thus, the process of running an
application is simplified:
$ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \
com.example.MyApplication
Note that the resulting binary will be very large due to the size of
OpenJDK's class library. This can be mitigated using UPX, preferably
an LZMA-enabled version:
$ upx --lzma --best build/linux-x86_64-openjdk-src/avian
You can reduce the size futher for embedded builds by using ProGuard
and the supplied openjdk.pro configuration file (see "Embedding with
ProGuard and a Boot Image" below). Note that you'll still need to use
vm.pro in that case -- openjdk.pro just adds additional constraints
specific to the OpenJDK port. Also see app.mk in
_git://oss.readytalk.com/avian-swt-examples.git_ for an example of using
Avian, OpenJDK, ProGuard, and UPX in concert.
Here are some examples of how to install OpenJDK and build Avian with
it on various OSes:
#### Debian-based Linux:
_Conventional build:_
$ apt-get install openjdk-7-jdk
$ make openjdk=/usr/lib/jvm/java-7-openjdk test
_Stand-alone build:_
$ apt-get install openjdk-7-jdk
$ apt-get source openjdk-7-jdk
$ apt-get build-dep openjdk-7-jdk
$ (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage)
$ make openjdk=/usr/lib/jvm/java-7-openjdk \
openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \
test
####Mac OS X:
_Prerequisite:_ Build OpenJDK 7 according to [this site](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port).
_Conventional build:_
$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test
_Stand-alone build:_
$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \
openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test
####Windows (Cygwin):
_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). Alternatively, use https://github.com/alexkasko/openjdk-unofficial-builds.
_Conventional build:_
$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test
_Stand-alone build:_
$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \
openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test
Currently, only OpenJDK 7 is supported. Later versions might work,
but have not yet been tested.
Building with the Android Class Library
---------------------------------------
As an alternative to both the Avian and OpenJDK class libaries, you
can also build with the Android class library on some platforms
(currently Linux works and OS X mostly works). To build this way, do
the following, starting from the Avian directory:
cd ..
mkdir -p android/system android/external
cd android
git clone https://android.googlesource.com/platform/bionic
git clone https://android.googlesource.com/platform/system/core \
system/core
git clone https://android.googlesource.com/platform/external/expat \
external/expat
git clone https://android.googlesource.com/platform/external/fdlibm \
external/fdlibm
git clone https://android.googlesource.com/platform/external/icu4c \
external/icu4c
git clone https://android.googlesource.com/platform/libnativehelper
git clone https://android.googlesource.com/platform/external/openssl \
external/openssl
git clone https://android.googlesource.com/platform/external/zlib \
external/zlib
git clone git://git.openssl.org/openssl.git openssl-upstream
git clone https://github.com/dicej/android-libcore64 libcore
(cd external/expat && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure \
--enable-static && make)
(cd external/fdlibm && (mv makefile.in Makefile.in || true) \
&& CFLAGS=-fPIC bash configure && make)
(cd external/icu4c && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure \
--enable-static && make)
NB: use 'CC="gcc -fPIC" ./Configure darwin64-x86_64-cc' when building
for x86_64 OS X instead of 'CC="gcc -fPIC" ./config':
(cd openssl-upstream && git checkout OpenSSL_1_0_1e \
&& (for x in ../external/openssl/patches/*.patch; \
do patch -p1 < $x; done) \
&& CC="gcc -fPIC" ./config && make)
cd ../avian
make android=$(pwd)/../android test
Note that we use https://github.com/dicej/android-libcore64 above
instead of the upstream
https://android.googlesource.com/platform/libcore repository, since
the former has patches to provide better support for non-Linux platforms.
Also note that we use the upstream OpenSSL repository and apply the
Android patches to it. This is because it is not clear how to build
the Android fork of OpenSSL directly without checking out and building
the entire platform. As of this writing, the patches apply cleanly
against OpenSSL 1.0.1e, so that's the tag we check out, but this may
change in the future when the Android fork rebases against a new
OpenSSL version.
Installing
----------
Installing Avian is as simple as copying the executable to the desired
directory:
$ cp build/${platform}-${arch}/avian ~/bin/
Embedding
---------
The following series of commands illustrates how to produce a
stand-alone executable out of a Java application using Avian.
Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or
"i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands
below (e.g. x86_64-w64-mingw32-gcc).
__1.__ Build Avian, create a new directory, and populate it with the
VM object files and bootstrap classpath jar.
$ make
$ mkdir hello
$ cd hello
$ ar x ../build/${platform}-${arch}/libavian.a
$ cp ../build/${platform}-${arch}/classpath.jar boot.jar
__2.__ Build the Java code and add it to the jar.
$ cat >Hello.java <<EOF
public class Hello {
public static void main(String[] args) {
System.out.println("hello, world!");
}
}
EOF
$ javac -bootclasspath boot.jar Hello.java
$ jar u0f boot.jar Hello.class
__3.__ Make an object file out of the jar.
$ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \
boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch}
If you've built Avian using the `lzma` option, you may optionally
compress the jar before generating the object:
../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma
&& ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \
boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \
${platform} ${arch}
Note that you'll need to specify "-Xbootclasspath:[lzma:bootJar]"
instead of "-Xbootclasspath:[bootJar]" in the next step if you've used
LZMA to compress the jar.
__4.__ Write a driver which starts the VM and runs the desired main
method. Note the bootJar function, which will be called by the VM to
get a handle to the embedded jar. We tell the VM about this jar by
setting the boot classpath to "[bootJar]".
$ cat >embedded-jar-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"
#if (defined __MINGW32__) || (defined _MSC_VER)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __attribute__ ((visibility("default"))) \
__attribute__ ((used))
#endif
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define SYMBOL(x) binary_boot_jar_##x
#else
# define SYMBOL(x) _binary_boot_jar_##x
#endif
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
EXPORT const uint8_t*
bootJar(unsigned* size)
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
} // extern "C"
int
main(int ac, const char** av)
{
JavaVMInitArgs vmArgs;
vmArgs.version = JNI_VERSION_1_2;
vmArgs.nOptions = 1;
vmArgs.ignoreUnrecognized = JNI_TRUE;
JavaVMOption options[vmArgs.nOptions];
vmArgs.options = options;
options[0].optionString = const_cast<char*>("-Xbootclasspath:[bootJar]");
JavaVM* vm;
void* env;
JNI_CreateJavaVM(&vm, &env, &vmArgs);
JNIEnv* e = static_cast<JNIEnv*>(env);
jclass c = e->FindClass("Hello");
if (not e->ExceptionCheck()) {
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
if (not e->ExceptionCheck()) {
jclass stringClass = e->FindClass("java/lang/String");
if (not e->ExceptionCheck()) {
jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
if (not e->ExceptionCheck()) {
for (int i = 1; i < ac; ++i) {
e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
}
e->CallStaticVoidMethod(c, m, a);
}
}
}
}
int exitCode = 0;
if (e->ExceptionCheck()) {
exitCode = -1;
e->ExceptionDescribe();
}
vm->DestroyJavaVM();
return exitCode;
}
EOF
__on Linux:__
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
-D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o
__on Mac OS X:__
$ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \
-o main.o
__on Windows:__
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \
-D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o
__5.__ Link the objects produced above to produce the final
executable, and optionally strip its symbols.
__on Linux:__
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello
__on Mac OS X:__
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation
$ strip -S -x hello
__on Windows:__
$ dlltool -z hello.def *.o
$ dlltool -d hello.def -e hello.exp
$ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \
-mwindows -mconsole -o hello.exe
$ strip --strip-all hello.exe
Embedding with ProGuard and a Boot Image
----------------------------------------
The following illustrates how to embed an application as above, except
this time we preprocess the code using ProGuard and build a boot image
from it for quicker startup. The pros and cons of using ProGuard are
as follow:
* Pros: ProGuard will eliminate unused code, optimize the rest, and
obfuscate it as well for maximum space savings
* Cons: increased build time, especially for large applications, and
extra effort needed to configure it for applications which rely
heavily on reflection and/or calls to Java from native code
For boot image builds:
* Pros: the boot image build pre-parses all the classes and compiles
all the methods, obviating the need for JIT compilation at runtime.
This also makes garbage collection faster, since the pre-parsed
classes are never visited.
* Cons: the pre-parsed classes and AOT-compiled methods take up more
space in the executable than the equivalent class files. In
practice, this can make the executable 30-50% larger. Also, AOT
compilation does not yet yield significantly faster or smaller code
than JIT compilation. Finally, floating point code may be slower
on 32-bit x86 since the compiler cannot assume SSE2 support will be
available at runtime, and the x87 FPU is not supported except via
out-of-line helper functions.
Note you can use ProGuard without using a boot image and vice-versa,
as desired.
The following instructions assume we are building for Linux/i386.
Please refer to the previous example for guidance on other platforms.
__1.__ Build Avian, create a new directory, and populate it with the
VM object files.
$ make bootimage=true
$ mkdir hello
$ cd hello
$ ar x ../build/linux-i386-bootimage/libavian.a
__2.__ Create a stage1 directory and extract the contents of the
class library jar into it.
$ mkdir stage1
$ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar)
__3.__ Build the Java code and add it to stage1.
$ cat >Hello.java <<EOF
public class Hello {
public static void main(String[] args) {
System.out.println("hello, world!");
}
}
EOF
$ javac -bootclasspath stage1 -d stage1 Hello.java
__4.__ Create a ProGuard configuration file specifying Hello.main as
the entry point.
$ cat >hello.pro <<EOF
-keep class Hello {
public static void main(java.lang.String[]);
}
EOF
__5.__ Run ProGuard with stage1 as input and stage2 as output.
$ java -jar ../../proguard4.6/lib/proguard.jar \
-dontusemixedcaseclassnames -injars stage1 -outjars stage2 \
@../vm.pro @hello.pro
(note: The -dontusemixedcaseclassnames option is only needed when
building on systems with case-insensitive filesystems such as Windows
and OS X. Also, you'll need to add -ignorewarnings if you use the
OpenJDK class library since the openjdk-src build does not include all
the JARs from OpenJDK, and thus ProGuard will not be able to resolve
all referenced classes. If you actually plan to use such classes at
runtime, you'll need to add them to stage1 before running ProGuard.
Finally, you'll need to add @../openjdk.pro to the above command when
using the OpenJDK library.)
__6.__ Build the boot and code images.
$ ../build/linux-i386-bootimage/bootimage-generator
-cp stage2 \
-bootimage bootimage-bin.o \
-codeimage codeimage-bin.o
Note that you can override the default names for the start and end
symbols in the boot/code image by also passing:
-bootimage-symbols my_bootimage_start:my_bootimage_end \
-codeimage-symbols my_codeimage_start:my_codeimage_end
__7.__ Write a driver which starts the VM and runs the desired main
method. Note the bootimageBin function, which will be called by the
VM to get a handle to the embedded boot image. We tell the VM about
this function via the "avian.bootimage" property.
Note also that this example includes no resources besides class files.
If our application loaded resources such as images and properties
files via the classloader, we would also need to embed the jar file
containing them. See the previous example for instructions.
$ cat >bootimage-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"
#if (defined __MINGW32__) || (defined _MSC_VER)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __attribute__ ((visibility("default")))
#endif
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define BOOTIMAGE_BIN(x) binary_bootimage_bin_##x
# define CODEIMAGE_BIN(x) binary_codeimage_bin_##x
#else
# define BOOTIMAGE_BIN(x) _binary_bootimage_bin_##x
# define CODEIMAGE_BIN(x) _binary_codeimage_bin_##x
#endif
extern "C" {
extern const uint8_t BOOTIMAGE_BIN(start)[];
extern const uint8_t BOOTIMAGE_BIN(end)[];
EXPORT const uint8_t*
bootimageBin(unsigned* size)
{
*size = BOOTIMAGE_BIN(end) - BOOTIMAGE_BIN(start);
return BOOTIMAGE_BIN(start);
}
extern const uint8_t CODEIMAGE_BIN(start)[];
extern const uint8_t CODEIMAGE_BIN(end)[];
EXPORT const uint8_t*
codeimageBin(unsigned* size)
{
*size = CODEIMAGE_BIN(end) - CODEIMAGE_BIN(start);
return CODEIMAGE_BIN(start);
}
} // extern "C"
int
main(int ac, const char** av)
{
JavaVMInitArgs vmArgs;
vmArgs.version = JNI_VERSION_1_2;
vmArgs.nOptions = 2;
vmArgs.ignoreUnrecognized = JNI_TRUE;
JavaVMOption options[vmArgs.nOptions];
vmArgs.options = options;
options[0].optionString
= const_cast<char*>("-Davian.bootimage=bootimageBin");
options[1].optionString
= const_cast<char*>("-Davian.codeimage=codeimageBin");
JavaVM* vm;
void* env;
JNI_CreateJavaVM(&vm, &env, &vmArgs);
JNIEnv* e = static_cast<JNIEnv*>(env);
jclass c = e->FindClass("Hello");
if (not e->ExceptionCheck()) {
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
if (not e->ExceptionCheck()) {
jclass stringClass = e->FindClass("java/lang/String");
if (not e->ExceptionCheck()) {
jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
if (not e->ExceptionCheck()) {
for (int i = 1; i < ac; ++i) {
e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
}
e->CallStaticVoidMethod(c, m, a);
}
}
}
}
int exitCode = 0;
if (e->ExceptionCheck()) {
exitCode = -1;
e->ExceptionDescribe();
}
vm->DestroyJavaVM();
return exitCode;
}
EOF
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
-D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o
__8.__ Link the objects produced above to produce the final
executable, and optionally strip its symbols.
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello
Trademarks
----------
Oracle and Java are registered trademarks of Oracle and/or its
affiliates. Other names may be trademarks of their respective owners.
The Avian project is not affiliated with Oracle.

75
android.pro Normal file
View File

@ -0,0 +1,75 @@
# these are referenced in JniConstants.cpp:
-keep class java.text.Bidi$Run
-keep class java.math.BigDecimal
-keep class java.lang.Boolean
-keep class java.lang.Byte
-keep class java.nio.charset.CharsetICU {
CharsetICU(java.lang.String, java.lang.String, java.lang.String[]);
}
-keep class java.lang.reflect.Constructor
-keep class java.util.zip.Deflater
-keep class java.lang.Double
-keep class libcore.io.ErrnoException
-keep class java.lang.reflect.Field
-keep class libcore.icu.NativeDecimalFormat$FieldPositionIterator {
void setData(int[]);
}
-keep class java.io.FileDescriptor
-keep class libcore.io.GaiException
-keep class java.net.Inet6Address
-keep class java.net.InetAddress
-keep class java.net.InetSocketAddress
-keep class java.util.zip.Inflater
-keep class java.lang.Integer
-keep class libcore.icu.LocaleData
-keep class java.lang.Long
-keep class java.lang.reflect.Method
-keep class libcore.util.MutableInt
-keep class libcore.util.MutableLong
-keep class java.text.ParsePosition
-keep class java.util.regex.PatternSyntaxException
-keep class java.lang.RealToString
-keep class java.net.Socket
-keep class java.net.SocketImpl
-keep class java.lang.String
-keep class libcore.io.StructAddrinfo
-keep class libcore.io.StructFlock
-keep class libcore.io.StructGroupReq
-keep class libcore.io.StructLinger
-keep class libcore.io.StructPasswd
-keep class libcore.io.StructPollfd
-keep class libcore.io.StructStat {
StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long);
}
-keep class libcore.io.StructStatFs
-keep class libcore.io.StructTimeval
-keep class libcore.io.StructUtsname {
StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
}
# referenced from libcore native code
-keep class libcore.icu.LocaleData {
<fields>;
}
# called from the VM
-keep class java.lang.Thread {
Thread(java.lang.ThreadGroup, java.lang.String, int, boolean);
}
-keep class avian.Classes {
java.lang.Class forName(java.lang.String, boolean, java.lang.ClassLoader);
int findField(avian.VMClass, java.lang.String);
int findMethod(avian.VMClass, java.lang.String, java.lang.Class[]);
java.lang.annotation.Annotation getAnnotation(java.lang.ClassLoader, java.lang.Object[]);
}
-keep class java.lang.VMThread {
VMThread(java.lang.Thread);
}
# loaded reflectively to handle embedded resources:
-keep class avian.avianvmresource.Handler

View File

@ -14,4 +14,6 @@ public class ClassAddendum extends Addendum {
public Object[] interfaceTable;
public Object[] innerClassTable;
public Object[] methodTable;
public Object enclosingClass;
public Object enclosingMethod;
}

View File

@ -16,6 +16,8 @@ import static avian.Stream.read2;
import java.lang.reflect.Modifier;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.lang.annotation.Annotation;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@ -262,6 +264,159 @@ public class Classes {
link(c, c.loader);
}
public static Class forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
{
if (loader == null) {
loader = Class.class.getClassLoader();
}
Class c = loader.loadClass(name);
VMClass vmc = SystemClassLoader.vmClass(c);
Classes.link(vmc, loader);
if (initialize) {
Classes.initialize(vmc);
}
return c;
}
public static Class forCanonicalName(String name) {
return forCanonicalName(null, name);
}
public static Class forCanonicalName(ClassLoader loader, String name) {
try {
if (name.startsWith("[")) {
return forName(name, true, loader);
} else if (name.startsWith("L")) {
return forName(name.substring(1, name.length() - 1), true, loader);
} else {
if (name.length() == 1) {
return SystemClassLoader.getClass
(Classes.primitiveClass(name.charAt(0)));
} else {
throw new ClassNotFoundException(name);
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private static int next(char c, String s, int start) {
for (int i = start; i < s.length(); ++i) {
if (s.charAt(i) == c) return i;
}
throw new RuntimeException();
}
public static Class[] getParameterTypes(VMMethod vmMethod) {
int count = vmMethod.parameterCount;
Class[] types = new Class[count];
int index = 0;
String spec = new String
(vmMethod.spec, 1, vmMethod.spec.length - 2);
try {
for (int i = 0; i < spec.length(); ++i) {
char c = spec.charAt(i);
if (c == ')') {
break;
} else if (c == 'L') {
int start = i + 1;
i = next(';', spec, start);
String name = spec.substring(start, i).replace('/', '.');
types[index++] = Class.forName(name, true, vmMethod.class_.loader);
} else if (c == '[') {
int start = i;
while (spec.charAt(i) == '[') ++i;
if (spec.charAt(i) == 'L') {
i = next(';', spec, i + 1);
String name = spec.substring(start, i).replace('/', '.');
types[index++] = Class.forName
(name, true, vmMethod.class_.loader);
} else {
String name = spec.substring(start, i + 1);
types[index++] = forCanonicalName(vmMethod.class_.loader, name);
}
} else {
String name = spec.substring(i, i + 1);
types[index++] = forCanonicalName(vmMethod.class_.loader, name);
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return types;
}
public static int findField(VMClass vmClass, String name) {
if (vmClass.fieldTable != null) {
Classes.link(vmClass);
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (toString(vmClass.fieldTable[i].name).equals(name)) {
return i;
}
}
}
return -1;
}
public static String toString(byte[] array) {
return new String(array, 0, array.length - 1);
}
public static boolean match(Class[] a, Class[] b) {
if (a.length == b.length) {
for (int i = 0; i < a.length; ++i) {
if (! a[i].isAssignableFrom(b[i])) {
return false;
}
}
return true;
} else {
return false;
}
}
public static int findMethod(VMClass vmClass, String name,
Class[] parameterTypes)
{
if (vmClass.methodTable != null) {
Classes.link(vmClass);
if (parameterTypes == null) {
parameterTypes = new Class[0];
}
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (toString(vmClass.methodTable[i].name).equals(name)
&& match(parameterTypes,
getParameterTypes(vmClass.methodTable[i])))
{
return i;
}
}
}
return -1;
}
public static Annotation getAnnotation(ClassLoader loader, Object[] a) {
if (a[0] == null) {
a[0] = Proxy.newProxyInstance
(loader, new Class[] { (Class) a[1] },
new AnnotationInvocationHandler(a));
}
return (Annotation) a[0];
}
public static native Method makeMethod(Class c, int slot);
private static native void acquireClassLock();
private static native void releaseClassLock();

View File

@ -45,20 +45,4 @@ public class OpenJDK {
}
return array;
}
public static Class getDeclaringClass(VMClass c) {
try {
String name = new String
(replace('/', '.', c.name, 0, c.name.length - 1), 0,
c.name.length - 1);
int index = name.lastIndexOf("$");
if (index == -1) {
return null;
} else {
return c.loader.loadClass(name.substring(0, index));
}
} catch (ClassNotFoundException e) {
return null;
}
}
}

View File

@ -252,7 +252,7 @@ public class PersistentSet <T> implements Iterable <T> {
}
ancestors.next = new Cell(n, ancestors.next);
sibling = ancestors.value.right;
sibling = ancestors.value.right = new Node(ancestors.value.right);
}
if (! (sibling.left.red || sibling.right.red)) {
@ -303,7 +303,7 @@ public class PersistentSet <T> implements Iterable <T> {
}
ancestors.next = new Cell(n, ancestors.next);
sibling = ancestors.value.left;
sibling = ancestors.value.left = new Node(ancestors.value.left);
}
if (! (sibling.right.red || sibling.left.red)) {

View File

@ -28,6 +28,8 @@ public class SystemClassLoader extends ClassLoader {
public static native Class getClass(VMClass vmClass);
public static native VMClass vmClass(Class jClass);
private native VMClass findLoadedVMClass(String name);
protected Class reallyFindLoadedClass(String name){
@ -35,6 +37,30 @@ public class SystemClassLoader extends ClassLoader {
return c == null ? null : getClass(c);
}
protected Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
if (c == null) {
ClassLoader parent = getParent();
if (parent != null) {
try {
c = parent.loadClass(name);
} catch (ClassNotFoundException ok) { }
}
if (c == null) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
private native String resourceURLPrefix(String name);
protected URL findResource(String name) {

View File

@ -0,0 +1,61 @@
package avian;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class Traces {
private static final String Newline = System.getProperty("line.separator");
private static String traceAllThreads() {
StringBuilder buffer = new StringBuilder();
Thread[] threads = new Thread[Thread.activeCount()];
int count = Thread.enumerate(threads);
for (int i = 0; i < count; ++i) {
traceThread(threads[i], buffer);
}
return buffer.toString();
}
private static String traceThread(Thread thread) {
StringBuilder buffer = new StringBuilder();
traceThread(thread, buffer);
return buffer.toString();
}
private static void traceThread(Thread thread, StringBuilder buffer) {
buffer.append(thread).append(Newline);
for (StackTraceElement e: thread.getStackTrace()) {
buffer.append("\tat ").append(e).append(Newline);
}
}
public static void startTraceListener(final String host, final int port) {
Thread t = new Thread(new Runnable() {
public void run() {
try {
ServerSocketChannel server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(host, port));
while (true) {
SocketChannel c = server.accept();
try {
c.write(ByteBuffer.wrap(traceAllThreads().getBytes()));
} finally {
c.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
}
}

View File

@ -8,7 +8,7 @@
There is NO WARRANTY for this software. See license.txt for
details. */
package avian.avian_vm_resource;
package avian.avianvmresource;
import java.net.URL;
import java.net.URLStreamHandler;

View File

@ -55,6 +55,15 @@
typedef wchar_t char_t;
#if defined(WINAPI_FAMILY)
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#include "avian-interop.h"
#define SKIP_OPERATOR_NEW
#endif
#endif
#else // not PLATFORM_WINDOWS
# include <dirent.h>
@ -83,7 +92,19 @@ 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
#if !defined(SKIP_OPERATOR_NEW)
inline void* operator new(size_t, void* p) throw() { return p; }
#endif
typedef const char_t* string_t;
@ -155,69 +176,9 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
}
}
#ifdef PLATFORM_WINDOWS
class Mapping {
public:
Mapping(uint8_t* start, size_t length, HANDLE mapping, HANDLE file):
start(start),
length(length),
mapping(mapping),
file(file)
{ }
uint8_t* start;
size_t length;
HANDLE mapping;
HANDLE file;
};
inline Mapping*
map(JNIEnv* e, string_t path)
{
Mapping* result = 0;
HANDLE file = CreateFileW(path, FILE_READ_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
if (file != INVALID_HANDLE_VALUE) {
unsigned size = GetFileSize(file, 0);
if (size != INVALID_FILE_SIZE) {
HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0);
if (mapping) {
void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
if (data) {
void* p = allocate(e, sizeof(Mapping));
if (not e->ExceptionCheck()) {
result = new (p)
Mapping(static_cast<uint8_t*>(data), size, file, mapping);
}
}
if (result == 0) {
CloseHandle(mapping);
}
}
}
if (result == 0) {
CloseHandle(file);
}
}
if (result == 0 and not e->ExceptionCheck()) {
throwNew(e, "java/io/IOException", "%d", GetLastError());
}
return result;
}
inline void
unmap(JNIEnv*, Mapping* mapping)
{
UnmapViewOfFile(mapping->start);
CloseHandle(mapping->mapping);
CloseHandle(mapping->file);
free(mapping);
}
class Directory {
public:
Directory(): handle(0), findNext(false) { }
@ -250,51 +211,9 @@ class Directory {
#else // not PLATFORM_WINDOWS
class Mapping {
public:
Mapping(uint8_t* start, size_t length):
start(start),
length(length)
{ }
uint8_t* start;
size_t length;
};
inline Mapping*
map(JNIEnv* e, string_t path)
{
Mapping* result = 0;
int fd = open(path, O_RDONLY);
if (fd != -1) {
struct stat s;
int r = fstat(fd, &s);
if (r != -1) {
void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data) {
void* p = allocate(e, sizeof(Mapping));
if (not e->ExceptionCheck()) {
result = new (p) Mapping(static_cast<uint8_t*>(data), s.st_size);
}
}
}
close(fd);
}
if (result == 0 and not e->ExceptionCheck()) {
throwNewErrno(e, "java/io/IOException");
}
return result;
}
inline void
unmap(JNIEnv*, Mapping* mapping)
{
munmap(mapping->start, mapping->length);
free(mapping);
}
#endif // not PLATFORM_WINDOWS
} // namespace
inline string_t getChars(JNIEnv* e, jstring path) {
@ -316,6 +235,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;
@ -330,6 +250,19 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
}
return path;
# else
string_t chars = getChars(e, path);
if(chars) {
std::wstring partialPath = chars;
releaseChars(e, path, chars);
std::wstring fullPath = AvianInterop::GetFullPath(partialPath);
return e->NewString
(reinterpret_cast<const jchar*>(fullPath.c_str()), fullPath.length());
}
return path;
# endif
#else
jstring result = path;
string_t chars = getChars(e, path);
@ -353,20 +286,41 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
extern "C" JNIEXPORT jlong JNICALL
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
{
#ifdef PLATFORM_WINDOWS
LARGE_INTEGER fileSize;
// Option: without opening file
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
string_t chars = getChars(e, path);
HANDLE file = CreateFileW
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
releaseChars(e, path, chars);
if (file != INVALID_HANDLE_VALUE)
GetFileSizeEx(file, &fileSize);
else return 0;
CloseHandle(file);
return static_cast<jlong>(fileSize.QuadPart);
if(chars) {
LARGE_INTEGER fileSize;
#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)
return 0;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
if(!GetFileSizeEx(file, &fileSize))
{
CloseHandle(file);
return 0;
}
#else
FILE_STANDARD_INFO info;
if(!GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info)))
{
CloseHandle(file);
return 0;
}
fileSize = info.EndOfFile;
#endif
CloseHandle(file);
return static_cast<jlong>(fileSize.QuadPart);
}
#else
string_t chars = getChars(e, path);
@ -598,7 +552,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;
@ -610,6 +568,62 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
}
}
extern "C" JNIEXPORT jlong JNICALL
Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
{
string_t chars = getChars(e, path);
if (chars) {
#ifdef PLATFORM_WINDOWS
// Option: without opening file
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
HANDLE hFile = CreateFileW
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
#else
HANDLE hFile = CreateFile2
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#endif
releaseChars(e, path, chars);
if (hFile == INVALID_HANDLE_VALUE)
return 0;
LARGE_INTEGER fileDate, filetimeToUnixEpochAdjustment;
filetimeToUnixEpochAdjustment.QuadPart = 11644473600000L * 10000L;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
FILETIME fileLastWriteTime;
if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime))
{
CloseHandle(hFile);
return 0;
}
fileDate.HighPart = fileLastWriteTime.dwHighDateTime;
fileDate.LowPart = fileLastWriteTime.dwLowDateTime;
#else
FILE_BASIC_INFO fileInfo;
if (!GetFileInformationByHandleEx(hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo)))
{
CloseHandle(hFile);
return 0;
}
fileDate = fileInfo.ChangeTime;
#endif
CloseHandle(hFile);
fileDate.QuadPart -= filetimeToUnixEpochAdjustment.QuadPart;
return fileDate.QuadPart / 10000000L;
#else
struct stat fileStat;
if (stat(chars, &fileStat) == -1) {
releaseChars(e, path, chars);
return 0;
}
return (static_cast<jlong>(st.st_mtim.tv_sec) * 1000) +
(static_cast<jlong>(st.st_mtim.tv_nsec) / (1000*1000));
#endif
}
return 0;
}
extern "C" JNIEXPORT jstring JNICALL
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
{
@ -759,13 +773,13 @@ Java_java_io_FileOutputStream_write__I_3BII
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
{
jbyte* data = static_cast<jbyte*>(malloc(length));
if (data == 0) {
throwNew(e, "java/lang/OutOfMemoryError", 0);
return;
}
e->GetByteArrayRegion(b, offset, length, data);
if (not e->ExceptionCheck()) {
doWrite(e, fd, data, length);
}
@ -785,35 +799,104 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
{
string_t chars = getChars(e, path);
if (chars) {
Mapping* mapping = map(e, chars);
jlong peer = 0;
jlong length = 0;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#if defined(PLATFORM_WINDOWS)
int fd = ::_wopen(chars, O_RDONLY | OPEN_MASK);
#else
int fd = ::open((const char*)chars, O_RDONLY | OPEN_MASK);
#endif
releaseChars(e, path, chars);
if (fd == -1) {
throwNewErrno(e, "java/io/IOException");
return;
}
struct ::stat fileStats;
if(::fstat(fd, &fileStats) == -1) {
::close(fd);
throwNewErrno(e, "java/io/IOException");
return;
}
peer = fd;
length = fileStats.st_size;
#else
HANDLE hFile = CreateFile2
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
if (hFile == INVALID_HANDLE_VALUE) {
throwNewErrno(e, "java/io/IOException");
return;
}
FILE_STANDARD_INFO info;
if(!GetFileInformationByHandleEx(hFile, FileStandardInfo, &info, sizeof(info))) {
CloseHandle(hFile);
throwNewErrno(e, "java/io/IOException");
return;
}
peer = (jlong)hFile;
length = info.EndOfFile.QuadPart;
#endif
jlong peer = reinterpret_cast<jlong>(mapping);
e->SetLongArrayRegion(result, 0, 1, &peer);
jlong length = (mapping ? mapping->length : 0);
e->SetLongArrayRegion(result, 1, 1, &length);
releaseChars(e, path, chars);
}
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_RandomAccessFile_copy(JNIEnv* e, jclass, jlong peer,
extern "C" JNIEXPORT jint JNICALL
Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
jlong position, jbyteArray buffer,
int offset, int length)
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
int fd = (int)peer;
if(::lseek(fd, position, SEEK_SET) == -1) {
throwNewErrno(e, "java/io/IOException");
return -1;
}
uint8_t* dst = reinterpret_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, 0));
memcpy(dst + offset,
reinterpret_cast<Mapping*>(peer)->start + position,
length);
int64_t bytesRead = ::read(fd, dst + offset, length);
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
if(bytesRead == -1) {
throwNewErrno(e, "java/io/IOException");
return -1;
}
#else
HANDLE hFile = (HANDLE)peer;
LARGE_INTEGER lPos;
lPos.QuadPart = position;
if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
throwNewErrno(e, "java/io/IOException");
return -1;
}
uint8_t* dst = reinterpret_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, 0));
DWORD bytesRead = 0;
if(!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) {
throwNewErrno(e, "java/io/IOException");
return -1;
}
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
#endif
return (jint)bytesRead;
}
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)
{
unmap(e, reinterpret_cast<Mapping*>(peer));
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
int fd = (int)peer;
::close(fd);
#else
HANDLE hFile = (HANDLE)peer;
CloseHandle(hFile);
#endif
}

View File

@ -54,33 +54,64 @@
# include "signal.h"
# include "sys/time.h"
# include "sys/types.h"
# ifndef __ANDROID__
# include "sys/sysctl.h"
# endif
# include "sys/utsname.h"
# include "sys/wait.h"
#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
#else
# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# include "avian-interop.h"
# endif
#endif // WINAPI_FAMILY
namespace {
#ifdef PLATFORM_WINDOWS
char* getErrorStr(DWORD err){
// The poor man's error string, just print the error code
char * errStr = (char*) malloc(9 * sizeof(char));
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*
//char* errStr;
//LPTSTR s;
//if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
// FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, &s, 0, NULL) == 0)
//{
// errStr.Format("Unknown error occurred (%08x)", err);
//} else {
// errStr = s;
//}
//return errStr;
}
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
char* getErrorStr(DWORD err) {
LPSTR errorStr = 0;
if(!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, (LPSTR)&errorStr, 0, 0))
{
char* errStr = (char*) malloc(9 * sizeof(char));
snprintf(errStr, 9, "%d", (int) err);
return errStr;
}
char* errStr = strdup(errorStr);
LocalFree(errorStr);
return errStr;
}
#else
char* getErrorStr(DWORD err) {
LPSTR errorStr = (LPSTR)malloc(4096); //NOTE: something constant
if(!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, errorStr, 0, 0))
{
free(errorStr);
char* errStr = (char*) malloc(9 * sizeof(char));
snprintf(errStr, 9, "%d", (int) err);
return errStr;
}
char* errStr = strdup(errorStr);
free(errorStr);
return errStr;
}
#endif
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
void makePipe(JNIEnv* e, HANDLE p[2])
{
SECURITY_ATTRIBUTES sa;
@ -93,6 +124,7 @@ namespace {
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
}
}
#endif
int descriptor(JNIEnv* e, HANDLE h)
{
@ -194,7 +226,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);
@ -265,11 +297,15 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
e->SetLongArrayRegion(process, 0, 1, &pid);
jlong tid = reinterpret_cast<jlong>(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<HANDLE>(pid), INFINITE);
BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode);
@ -281,14 +317,23 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
CloseHandle(reinterpret_cast<HANDLE>(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<HANDLE>(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();
@ -360,8 +405,23 @@ Locale getLocale() {
default: lang = "en";
}
return Locale(lang, reg);
#else
std::wstring culture = AvianInterop::GetCurrentUICulture();
char* cultureName = strdup(std::string(culture.begin(), culture.end()).c_str());
char* delimiter = strchr(cultureName, '-');
if(!delimiter)
{
free(cultureName);
return Locale("en", "US");
}
const char* lang = cultureName;
const char* reg = delimiter + 1;
*delimiter = 0;
Locale locale(lang, reg);
free(cultureName);
return locale;
#endif
}
#else
extern "C" JNIEXPORT void JNICALL
@ -529,8 +589,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;
@ -538,6 +605,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");
@ -549,15 +620,26 @@ 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
std::wstring tmpDir = AvianInterop::GetTemporaryFolder();
r = e->NewString((const jchar*)tmpDir.c_str(), tmpDir.length());
# 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
std::wstring userDir = AvianInterop::GetInstalledLocation();
r = e->NewString((const jchar*)userDir.c_str(), userDir.length());
# 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) {
@ -565,6 +647,10 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name,
} else {
r = 0;
}
# else
std::wstring userHome = AvianInterop::GetDocumentsLibraryLocation();
r = e->NewString((const jchar*)userHome.c_str(), userHome.length());
# endif
# else
LPWSTR home = _wgetenv(L"USERPROFILE");
r = e->NewString(reinterpret_cast<jchar*>(home), lstrlenW(home));
@ -652,6 +738,9 @@ namespace {
#elif defined __APPLE__
# include <crt_externs.h>
# 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
@ -785,6 +874,54 @@ Java_java_lang_Math_cos(JNIEnv*, jclass, jdouble val)
return cos(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_tan(JNIEnv*, jclass, jdouble val)
{
return tan(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_asin(JNIEnv*, jclass, jdouble val)
{
return asin(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_acos(JNIEnv*, jclass, jdouble val)
{
return acos(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_atan(JNIEnv*, jclass, jdouble val)
{
return atan(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_atan2(JNIEnv*, jclass, jdouble y, jdouble x)
{
return atan2(y, x);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_sinh(JNIEnv*, jclass, jdouble val)
{
return sinh(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_cosh(JNIEnv*, jclass, jdouble val)
{
return cosh(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_tanh(JNIEnv*, jclass, jdouble val)
{
return tanh(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val)
{
@ -797,6 +934,12 @@ Java_java_lang_Math_pow(JNIEnv*, jclass, jdouble val, jdouble exp)
return pow(val, exp);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_log(JNIEnv*, jclass, jdouble val)
{
return log(val);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val)
{

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2011, Avian Contributors
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
@ -262,18 +262,32 @@ setTcpNoDelay(JNIEnv* e, int d, bool on)
void
doBind(JNIEnv* e, int s, sockaddr_in* address)
{
int opt = 1;
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char*>(&opt), sizeof(int));
if (r != 0) {
throwIOException(e);
return;
{ int opt = 1;
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char*>(&opt), sizeof(int));
if (r != 0) {
throwIOException(e);
return;
}
}
r = ::bind(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
if (r != 0) {
throwIOException(e);
return;
#ifdef SO_NOSIGPIPE
{ int opt = 1;
int r = ::setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE,
reinterpret_cast<char*>(&opt), sizeof(int));
if (r != 0) {
throwIOException(e);
return;
}
}
#endif
{ int r = ::bind
(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
if (r != 0) {
throwIOException(e);
return;
}
}
}
@ -1015,3 +1029,15 @@ Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv *, jclass)
{
union {
uint32_t i;
char c[4];
} u = {0x01020304};
if (u.c[0] == 1)
return JNI_TRUE;
return JNI_FALSE;
}

View File

@ -10,7 +10,7 @@
#include "stdlib.h"
#include "string.h"
#include "zlib-custom.h"
#include "avian/zlib-custom.h"
#include "jni.h"
#include "jni-util.h"

View File

@ -0,0 +1,16 @@
/* Copyright (c) 2012, 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. */
package java.io;
public interface Closeable {
void close()
throws IOException;
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2012, Avian Contributors
/* Copyright (c) 2008-2013, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
@ -16,6 +16,11 @@ public class File implements Serializable {
public static final String separator = FileSeparator;
private static final String PathSeparator
= System.getProperty("path.separator");
public static final String pathSeparator = PathSeparator;
// static {
// System.loadLibrary("natives");
// }
@ -289,12 +294,19 @@ public class File implements Serializable {
}
}
public long lastModified() {
return lastModified(path);
}
private static native long openDir(String path);
private static native long lastModified(String path);
private static native String readDir(long handle);
private static native long closeDir(long handle);
private static class Pair {
public final String value;
public final Pair next;

View File

@ -0,0 +1,16 @@
/* Copyright (c) 2012, 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. */
package java.io;
public interface Flushable {
void flush()
throws IOException;
}

View File

@ -10,7 +10,7 @@
package java.io;
public abstract class InputStream {
public abstract class InputStream implements Closeable {
public abstract int read() throws IOException;
public int read(byte[] buffer) throws IOException {

View File

@ -10,7 +10,7 @@
package java.io;
public abstract class OutputStream {
public abstract class OutputStream implements Closeable, Flushable {
public abstract void write(int c) throws IOException;
public void write(byte[] buffer) throws IOException {

View File

@ -10,6 +10,8 @@
package java.io;
import java.lang.IllegalArgumentException;
public class RandomAccessFile {
private long peer;
private File file;
@ -56,26 +58,68 @@ public class RandomAccessFile {
this.position = position;
}
public void readFully(byte[] buffer, int offset, int length)
throws IOException
{
if (peer == 0) throw new IOException();
if (length == 0) return;
if (position + length > this.length) {
if (position + length > length()) throw new EOFException();
}
if (offset < 0 || offset + length > buffer.length)
public int skipBytes(int count) throws IOException {
if (position + count > length()) throw new IOException();
this.position = position + count;
return count;
}
public int read(byte b[], int off, int len) throws IOException {
if(b == null)
throw new IllegalArgumentException();
if (peer == 0)
throw new IOException();
if(len == 0)
return 0;
if (position + len > this.length)
throw new EOFException();
if (off < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
copy(peer, position, buffer, offset, length);
position += length;
int bytesRead = readBytes(peer, position, b, off, len);
position += bytesRead;
return bytesRead;
}
public int read(byte b[]) throws IOException {
if(b == null)
throw new IllegalArgumentException();
if (peer == 0)
throw new IOException();
if(b.length == 0)
return 0;
if (position + b.length > this.length)
throw new EOFException();
int bytesRead = readBytes(peer, position, b, 0, b.length);
position += bytesRead;
return bytesRead;
}
private static native void copy(long peer, long position, byte[] buffer,
public void readFully(byte b[], int off, int len) throws IOException {
if(b == null)
throw new IllegalArgumentException();
if (peer == 0)
throw new IOException();
if(len == 0)
return;
if (position + len > this.length)
throw new EOFException();
if (off < 0 || off + len > b.length)
throw new ArrayIndexOutOfBoundsException();
int n = 0;
do {
int count = readBytes(peer, position, b, off + n, len - n);
position += count;
if (count == 0)
throw new EOFException();
n += count;
} while (n < len);
}
public void readFully(byte b[]) throws IOException {
readFully(b, 0, b.length);
}
private static native int readBytes(long peer, long position, byte[] buffer,
int offset, int length);
public void close() throws IOException {

View File

@ -10,7 +10,7 @@
package java.io;
public abstract class Reader {
public abstract class Reader implements Closeable {
public int read() throws IOException {
char[] buffer = new char[1];
int c = read(buffer);

View File

@ -10,7 +10,7 @@
package java.io;
public abstract class Writer {
public abstract class Writer implements Closeable, Flushable {
public void write(int c) throws IOException {
char[] buffer = new char[] { (char) c };
write(buffer);

View File

@ -11,7 +11,7 @@
package java.lang;
public final class Boolean implements Comparable<Boolean> {
public static final Class TYPE = Class.forCanonicalName("Z");
public static final Class TYPE = avian.Classes.forCanonicalName("Z");
public static final Boolean FALSE = new Boolean(false);
public static final Boolean TRUE = new Boolean(true);

View File

@ -11,7 +11,7 @@
package java.lang;
public final class Byte extends Number implements Comparable<Byte> {
public static final Class TYPE = Class.forCanonicalName("B");
public static final Class TYPE = avian.Classes.forCanonicalName("B");
private final byte value;

View File

@ -14,7 +14,7 @@ public final class Character implements Comparable<Character> {
public static final int MIN_RADIX = 2;
public static final int MAX_RADIX = 36;
public static final Class TYPE = Class.forCanonicalName("C");
public static final Class TYPE = avian.Classes.forCanonicalName("C");
private final char value;

View File

@ -37,7 +37,8 @@ import java.security.Permissions;
import java.security.AllPermission;
public final class Class <T> implements Type, AnnotatedElement {
private static final int PrimitiveFlag = 1 << 5;
private static final int PrimitiveFlag = 1 << 5;
private static final int EnumFlag = 1 << 14;
public final VMClass vmClass;
@ -144,38 +145,7 @@ public final class Class <T> implements Type, AnnotatedElement {
ClassLoader loader)
throws ClassNotFoundException
{
if (loader == null) {
loader = Class.class.vmClass.loader;
}
Class c = loader.loadClass(name);
Classes.link(c.vmClass, loader);
if (initialize) {
Classes.initialize(c.vmClass);
}
return c;
}
public static Class forCanonicalName(String name) {
return forCanonicalName(null, name);
}
public static Class forCanonicalName(ClassLoader loader, String name) {
try {
if (name.startsWith("[")) {
return forName(name, true, loader);
} else if (name.startsWith("L")) {
return forName(name.substring(1, name.length() - 1), true, loader);
} else {
if (name.length() == 1) {
return SystemClassLoader.getClass
(Classes.primitiveClass(name.charAt(0)));
} else {
throw new ClassNotFoundException(name);
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return Classes.forName(name, initialize, loader);
}
public Class getComponentType() {
@ -210,84 +180,36 @@ public final class Class <T> implements Type, AnnotatedElement {
return Classes.isAssignableFrom(vmClass, c.vmClass);
}
private static Field findField(VMClass vmClass, String name) {
if (vmClass.fieldTable != null) {
Classes.link(vmClass);
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (Field.getName(vmClass.fieldTable[i]).equals(name)) {
return new Field(vmClass.fieldTable[i]);
}
}
}
return null;
}
public Field getDeclaredField(String name) throws NoSuchFieldException {
Field f = findField(vmClass, name);
if (f == null) {
int index = Classes.findField(vmClass, name);
if (index < 0) {
throw new NoSuchFieldException(name);
} else {
return f;
return new Field(vmClass.fieldTable[index]);
}
}
public Field getField(String name) throws NoSuchFieldException {
for (VMClass c = vmClass; c != null; c = c.super_) {
Field f = findField(c, name);
if (f != null) {
return f;
int index = Classes.findField(c, name);
if (index >= 0) {
return new Field(vmClass.fieldTable[index]);
}
}
throw new NoSuchFieldException(name);
}
private static boolean match(Class[] a, Class[] b) {
if (a.length == b.length) {
for (int i = 0; i < a.length; ++i) {
if (! a[i].isAssignableFrom(b[i])) {
return false;
}
}
return true;
} else {
return false;
}
}
private static Method findMethod(VMClass vmClass, String name,
Class[] parameterTypes)
{
if (vmClass.methodTable != null) {
Classes.link(vmClass);
if (parameterTypes == null) {
parameterTypes = new Class[0];
}
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (Method.getName(vmClass.methodTable[i]).equals(name)
&& match(parameterTypes,
Method.getParameterTypes(vmClass.methodTable[i])))
{
return new Method(vmClass.methodTable[i]);
}
}
}
return null;
}
public Method getDeclaredMethod(String name, Class ... parameterTypes)
throws NoSuchMethodException
{
if (name.startsWith("<")) {
throw new NoSuchMethodException(name);
}
Method m = findMethod(vmClass, name, parameterTypes);
if (m == null) {
int index = Classes.findMethod(vmClass, name, parameterTypes);
if (index < 0) {
throw new NoSuchMethodException(name);
} else {
return m;
return new Method(vmClass.methodTable[index]);
}
}
@ -298,9 +220,9 @@ public final class Class <T> implements Type, AnnotatedElement {
throw new NoSuchMethodException(name);
}
for (VMClass c = vmClass; c != null; c = c.super_) {
Method m = findMethod(c, name, parameterTypes);
if (m != null) {
return m;
int index = Classes.findMethod(c, name, parameterTypes);
if (index >= 0) {
return new Method(vmClass.methodTable[index]);
}
}
throw new NoSuchMethodException(name);
@ -309,11 +231,11 @@ public final class Class <T> implements Type, AnnotatedElement {
public Constructor getConstructor(Class ... parameterTypes)
throws NoSuchMethodException
{
Method m = findMethod(vmClass, "<init>", parameterTypes);
if (m == null) {
int index = Classes.findMethod(vmClass, "<init>", parameterTypes);
if (index < 0) {
throw new NoSuchMethodException();
} else {
return new Constructor(m);
return new Constructor(new Method(vmClass.methodTable[index]));
}
}
@ -324,7 +246,7 @@ public final class Class <T> implements Type, AnnotatedElement {
Constructor[] constructors = getDeclaredConstructors();
for (int i = 0; i < constructors.length; ++i) {
if (match(parameterTypes, constructors[i].getParameterTypes())) {
if (Classes.match(parameterTypes, constructors[i].getParameterTypes())) {
c = constructors[i];
}
}
@ -555,6 +477,10 @@ public final class Class <T> implements Type, AnnotatedElement {
return (vmClass.vmFlags & PrimitiveFlag) != 0;
}
public boolean isEnum() {
return getSuperclass() == Enum.class && (vmClass.flags & EnumFlag) != 0;
}
public URL getResource(String path) {
if (! path.startsWith("/")) {
String name = new String
@ -626,7 +552,7 @@ public final class Class <T> implements Type, AnnotatedElement {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
Classes.link(c, c.loader);
Object[] table = (Object[]) c.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];

View File

@ -11,7 +11,7 @@
package java.lang;
public final class Double extends Number {
public static final Class TYPE = Class.forCanonicalName("D");
public static final Class TYPE = avian.Classes.forCanonicalName("D");
public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
public static final double POSITIVE_INFINITY = 1.0 / 0.0;

View File

@ -30,7 +30,9 @@ public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
if (name == null) throw new NullPointerException();
if (name == null) throw new NullPointerException("name");
if (!enumType.isEnum())
throw new IllegalArgumentException(enumType.getCanonicalName() + " is not an enum.");
try {
Method method = enumType.getMethod("values");
@ -41,10 +43,11 @@ public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
}
}
} catch (Exception ex) {
throw new RuntimeException(ex);
// Cannot happen
throw new Error(ex);
}
throw new IllegalArgumentException(name);
throw new IllegalArgumentException(enumType.getCanonicalName() + "." + name + " is not an enum constant.");
}
public int ordinal() {

View File

@ -11,7 +11,7 @@
package java.lang;
public final class Float extends Number {
public static final Class TYPE = Class.forCanonicalName("F");
public static final Class TYPE = avian.Classes.forCanonicalName("F");
private static final int EXP_BIT_MASK = 0x7F800000;
private static final int SIGNIF_BIT_MASK = 0x007FFFFF;

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2008, Avian Contributors
/* Copyright (c) 2008-2013, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
@ -11,7 +11,7 @@
package java.lang;
public final class Integer extends Number implements Comparable<Integer> {
public static final Class TYPE = Class.forCanonicalName("I");
public static final Class TYPE = avian.Classes.forCanonicalName("I");
public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7FFFFFFF;
@ -62,6 +62,10 @@ public final class Integer extends Number implements Comparable<Integer> {
return Long.toString(((long) v) & 0xFFFFFFFFL, 16);
}
public static String toOctalString(int v) {
return Long.toString(((long) v) & 0xFFFFFFFFL, 8);
}
public static String toBinaryString(int v) {
return Long.toString(((long) v) & 0xFFFFFFFFL, 2);
}
@ -90,6 +94,27 @@ public final class Integer extends Number implements Comparable<Integer> {
return (double) value;
}
public static int signum(int v) {
if (v == 0) return 0;
else if (v > 0) return 1;
else return -1;
}
// See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
public static int bitCount(int v) {
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
public static int reverseBytes(int v) {
int byte3 = v >>> 24;
int byte2 = (v >>> 8) & 0xFF00;
int byte1 = (v << 8) & 0xFF00;
int byte0 = v << 24;
return (byte0 | byte1 | byte2 | byte3);
}
public static int parseInt(String s) {
return parseInt(s, 10);
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2010, Avian Contributors
/* Copyright (c) 2008-2013, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
@ -14,7 +14,7 @@ public final class Long extends Number implements Comparable<Long> {
public static final long MIN_VALUE = -9223372036854775808l;
public static final long MAX_VALUE = 9223372036854775807l;
public static final Class TYPE = Class.forCanonicalName("J");
public static final Class TYPE = avian.Classes.forCanonicalName("J");
private final long value;
@ -94,6 +94,14 @@ public final class Long extends Number implements Comparable<Long> {
return toString(v, 16);
}
public static String toOctalString(long v) {
return toString(v, 8);
}
public static String toBinaryString(long v) {
return toString(v, 2);
}
public byte byteValue() {
return (byte) value;
}
@ -118,6 +126,12 @@ public final class Long extends Number implements Comparable<Long> {
return (double) value;
}
public static int signum(long v) {
if (v == 0) return 0;
else if (v > 0) return 1;
else return -1;
}
private static long pow(long a, long b) {
long c = 1;
for (int i = 0; i < b; ++i) c *= a;

View File

@ -93,6 +93,12 @@ public final class Math {
public static native double tan(double v);
public static native double cosh(double v);
public static native double sinh(double v);
public static native double tanh(double v);
public static native double acos(double v);
public static native double asin(double v);

View File

@ -17,34 +17,66 @@ public class Package {
private final String implementationTitle;
private final String implementationVendor;
private final String implementationVersion;
private final String specementationTitle;
private final String specementationVendor;
private final String specementationVersion;
private final String specificationTitle;
private final String specificationVendor;
private final String specificationVersion;
private final URL sealed;
private final ClassLoader loader;
Package(String name,
String implementationTitle,
String implementationVendor,
String implementationVersion,
String specementationTitle,
String specementationVendor,
String specementationVersion,
URL sealed,
String implementationTitle,
String implementationVendor,
String implementationVersion,
String specificationTitle,
String specificationVendor,
String specificationVersion,
URL sealed,
ClassLoader loader)
{
this.name = name;
this.implementationTitle = implementationTitle;
this.implementationVendor = implementationVendor;
this.name = name;
this.implementationTitle = implementationTitle;
this.implementationVendor = implementationVendor;
this.implementationVersion = implementationVersion;
this.specementationTitle = specementationTitle;
this.specementationVendor = specementationVendor;
this.specementationVersion = specementationVersion;
this.sealed = sealed;
this.loader = loader;
this.specificationTitle = specificationTitle;
this.specificationVendor = specificationVendor;
this.specificationVersion = specificationVersion;
this.sealed = sealed;
this.loader = loader;
}
public String getName() {
return name;
}
public String getImplementationTitle() {
return implementationTitle;
}
public String getImplementationVendor() {
return implementationVendor;
}
public String getImplementationVersion() {
return implementationVersion;
}
public String getSpecificationTitle() {
return specificationTitle;
}
public String getSpecificationVendor() {
return specificationVendor;
}
public String getSpecificationVersion() {
return specificationVersion;
}
public boolean isSealed() {
return sealed != null;
}
public boolean isSealed(URL url) {
return sealed.equals(url);
}
}

View File

@ -11,7 +11,7 @@
package java.lang;
public final class Short extends Number implements Comparable<Short> {
public static final Class TYPE = Class.forCanonicalName("S");
public static final Class TYPE = avian.Classes.forCanonicalName("S");
public static final short MAX_VALUE = 32767;
private final short value;

View File

@ -127,6 +127,11 @@ public final class String
} else {
c = Utf8.decode((byte[])data, offset, length);
if(c instanceof char[]) length = ((char[])c).length;
if (c == null) {
throw new RuntimeException
("unable to parse \"" + new String(data, offset, length, false)
+ "\"");
}
}
this.data = c;

View File

@ -151,8 +151,8 @@ public class Thread implements Runnable {
private static native boolean interrupted(long peer);
public static boolean isInterrupted() {
return currentThread().interrupted;
public boolean isInterrupted() {
return interrupted;
}
public static void sleep(long milliseconds) throws InterruptedException {

View File

@ -11,7 +11,7 @@
package java.lang;
public final class Void {
public static final Class TYPE = Class.forCanonicalName("V");
public static final Class TYPE = avian.Classes.forCanonicalName("V");
private Void() { }
}

View File

@ -61,7 +61,7 @@ public class Field<T> extends AccessibleObject {
}
public Class getType() {
return Class.forCanonicalName
return Classes.forCanonicalName
(vmField.class_.loader,
new String(vmField.spec, 0, vmField.spec.length - 1, false));
}

View File

@ -11,6 +11,8 @@
package java.lang.reflect;
public class InvocationTargetException extends Exception {
private Throwable target; // for compatibility with OpenJDK
public InvocationTargetException(Throwable targetException, String message) {
super(message, targetException);
}

View File

@ -13,6 +13,7 @@ package java.lang.reflect;
import avian.VMMethod;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import avian.Classes;
import java.lang.annotation.Annotation;
@ -58,61 +59,8 @@ public class Method<T> extends AccessibleObject implements Member {
return new String(vmMethod.spec, 0, vmMethod.spec.length - 1, false);
}
private static int next(char c, String s, int start) {
for (int i = start; i < s.length(); ++i) {
if (s.charAt(i) == c) return i;
}
throw new RuntimeException();
}
public Class[] getParameterTypes() {
return getParameterTypes(vmMethod);
}
public static Class[] getParameterTypes(VMMethod vmMethod) {
int count = vmMethod.parameterCount;
Class[] types = new Class[count];
int index = 0;
String spec = new String
(vmMethod.spec, 1, vmMethod.spec.length - 1, false);
try {
for (int i = 0; i < spec.length(); ++i) {
char c = spec.charAt(i);
if (c == ')') {
break;
} else if (c == 'L') {
int start = i + 1;
i = next(';', spec, start);
String name = spec.substring(start, i).replace('/', '.');
types[index++] = Class.forName(name, true, vmMethod.class_.loader);
} else if (c == '[') {
int start = i;
while (spec.charAt(i) == '[') ++i;
if (spec.charAt(i) == 'L') {
i = next(';', spec, i + 1);
String name = spec.substring(start, i).replace('/', '.');
types[index++] = Class.forName
(name, true, vmMethod.class_.loader);
} else {
String name = spec.substring(start, i + 1);
types[index++] = Class.forCanonicalName
(vmMethod.class_.loader, name);
}
} else {
String name = spec.substring(i, i + 1);
types[index++] = Class.forCanonicalName
(vmMethod.class_.loader, name);
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return types;
return Classes.getParameterTypes(vmMethod);
}
public Object invoke(Object instance, Object ... arguments)
@ -151,7 +99,7 @@ public class Method<T> extends AccessibleObject implements Member {
public Class getReturnType() {
for (int i = 0; i < vmMethod.spec.length - 1; ++i) {
if (vmMethod.spec[i] == ')') {
return Class.forCanonicalName
return Classes.forCanonicalName
(vmMethod.class_.loader,
new String
(vmMethod.spec, i + 1, vmMethod.spec.length - i - 2, false));
@ -160,22 +108,13 @@ public class Method<T> extends AccessibleObject implements Member {
throw new RuntimeException();
}
private Annotation getAnnotation(Object[] a) {
if (a[0] == null) {
a[0] = Proxy.newProxyInstance
(vmMethod.class_.loader, new Class[] { (Class) a[1] },
new AnnotationInvocationHandler(a));
}
return (Annotation) a[0];
}
public <T extends Annotation> T getAnnotation(Class<T> class_) {
if (vmMethod.hasAnnotations()) {
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
return (T) getAnnotation(a);
return (T) Classes.getAnnotation(vmMethod.class_.loader, a);
}
}
}
@ -187,7 +126,8 @@ public class Method<T> extends AccessibleObject implements Member {
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);
array[i] = Classes.getAnnotation
(vmMethod.class_.loader, (Object[]) table[i]);
}
return array;
} else {

View File

@ -16,6 +16,9 @@ import static avian.Stream.write4;
import static avian.Stream.set4;
import static avian.Assembler.*;
import avian.SystemClassLoader;
import avian.Classes;
import avian.ConstantPool;
import avian.ConstantPool.PoolEntry;
@ -87,26 +90,15 @@ public class Proxy {
write1(out, aload_0);
write1(out, new_);
write2(out, ConstantPool.addClass(pool, "java/lang/reflect/Method") + 1);
write1(out, dup);
write1(out, ldc_w);
write2(out, ConstantPool.addClass(pool, className) + 1);
write1(out, getfield);
write2(out, ConstantPool.addFieldRef
(pool, "java/lang/Class",
"vmClass", "Lavian/VMClass;") + 1);
write1(out, getfield);
write2(out, ConstantPool.addFieldRef
(pool, "avian/VMClass",
"methodTable", "[Lavian/VMMethod;") + 1);
write1(out, ldc_w);
write2(out, ConstantPool.addInteger(pool, index) + 1);
write1(out, aaload);
write1(out, invokespecial);
write1(out, invokestatic);
write2(out, ConstantPool.addMethodRef
(pool, "java/lang/reflect/Method",
"<init>", "(Lavian/VMMethod;)V") + 1);
(pool, "avian/Classes",
"makeMethod", "(Ljava/lang/Class;I)Ljava/lang/reflect/Method;")
+ 1);
write1(out, ldc_w);
write2(out, ConstantPool.addInteger(pool, parameterCount) + 1);
@ -363,10 +355,11 @@ public class Proxy {
Map<String,avian.VMMethod> virtualMap = new HashMap();
for (Class c: interfaces) {
avian.VMMethod[] ivtable = c.vmClass.virtualTable;
avian.VMMethod[] ivtable = SystemClassLoader.vmClass(c).virtualTable;
if (ivtable != null) {
for (avian.VMMethod m: ivtable) {
virtualMap.put(Method.getName(m) + Method.getSpec(m), m);
virtualMap.put
(Classes.toString(m.name) + Classes.toString(m.spec), m);
}
}
}
@ -376,15 +369,15 @@ public class Proxy {
for (avian.VMMethod m: virtualMap.values()) {
methodTable[i] = new MethodData
(0,
ConstantPool.addUtf8(pool, Method.getName(m)),
ConstantPool.addUtf8(pool, Method.getSpec(m)),
ConstantPool.addUtf8(pool, Classes.toString(m.name)),
ConstantPool.addUtf8(pool, Classes.toString(m.spec)),
makeInvokeCode(pool, name, m.spec, m.parameterCount,
m.parameterFootprint, i));
++ i;
}
methodTable[i++] = new MethodData
(0,
(Modifier.PUBLIC,
ConstantPool.addUtf8(pool, "<init>"),
ConstantPool.addUtf8
(pool, "(Ljava/lang/reflect/InvocationHandler;)V"),

View File

@ -0,0 +1,44 @@
/* Copyright (c) 2013, 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. */
package java.math;
import java.io.Serializable;
public class BigInteger implements Serializable {
private int sign;
private int[] value;
private BigInteger(int sign, long value) {
this.sign = sign;
int upperBits = (int) (value >>> 32);
if (upperBits == 0)
// Array with one element
this.value = new int[] { (int) value };
else
// Array with two elements
this.value = new int[] { (int) value, upperBits };
}
public static final BigInteger ZERO = new BigInteger(0, 0);
public static final BigInteger ONE = new BigInteger(1, 1);
public static final BigInteger TEN = new BigInteger(1, 10);
public static BigInteger valueOf(long num) {
int signum = Long.signum(num);
if (signum == 0)
return BigInteger.ZERO;
else if (signum > 0)
return new BigInteger(signum, num);
else
return new BigInteger(signum, -num);
}
}

View File

@ -0,0 +1,71 @@
/* Copyright (c) 2013, 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. */
package java.math;
import java.io.Serializable;
public final class MathContext implements Serializable {
public static final MathContext DECIMAL32 = new MathContext( 7, RoundingMode.HALF_EVEN);
public static final MathContext DECIMAL64 = new MathContext(16, RoundingMode.HALF_EVEN);
public static final MathContext DECIMAL128 = new MathContext(34, RoundingMode.HALF_EVEN);
public static final MathContext UNLIMITED = new MathContext(0, RoundingMode.HALF_UP);
private int precision;
private RoundingMode roundingMode;
public MathContext(int precision, RoundingMode roundingMode) {
if (precision < 0)
throw new IllegalArgumentException();
if (roundingMode == null)
throw new NullPointerException();
this.precision = precision;
this.roundingMode = roundingMode;
}
public MathContext(int precision) {
this(precision, RoundingMode.HALF_UP);
}
public int getPrecision() {
return precision;
}
public RoundingMode getRoundingMode() {
return roundingMode;
}
@Override
public boolean equals(Object that) {
return
(that instanceof MathContext) &&
(precision == ((MathContext) that).getPrecision()) &&
(roundingMode == ((MathContext) that).getRoundingMode());
}
@Override
public int hashCode() {
return
roundingMode.ordinal() |
(precision << 4);
}
private final static String precisionString = "precision=";
private final static String roundingModeString = " roundingMode=";
@Override
public String toString() {
StringBuilder sb = new StringBuilder(48);
sb.append(precisionString).append(precision);
sb.append(roundingModeString).append(roundingMode);
return sb.toString();
}
}

View File

@ -0,0 +1,36 @@
/* Copyright (c) 2013, 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. */
package java.math;
public enum RoundingMode {
UP (0),
DOWN (1),
CEILING (2),
FLOOR (3),
HALF_UP (4),
HALF_DOWN (5),
HALF_EVEN (6),
UNNECESSARY(7);
RoundingMode(int rm) {
roundingMode = rm;
}
private final int roundingMode;
public static RoundingMode valueOf(int roundingMode) {
final RoundingMode[] values = values();
if (roundingMode < 0 || roundingMode >= values.length)
throw new IllegalArgumentException();
return values[roundingMode];
}
}

View File

@ -83,8 +83,8 @@ public final class URL {
{
if ("http".equals(protocol) || "https".equals(protocol)) {
return new avian.http.Handler();
} else if ("avian_vm_resource".equals(protocol)) {
return new avian.avian_vm_resource.Handler();
} else if ("avianvmresource".equals(protocol)) {
return new avian.avianvmresource.Handler();
} else if ("file".equals(protocol)) {
return new avian.file.Handler();
} else if ("jar".equals(protocol)) {

View File

@ -0,0 +1,57 @@
package java.net;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
public class URLClassLoader extends ClassLoader {
private final File jarFile;
public URLClassLoader(URL[] urls, ClassLoader parent) {
super(parent);
if(urls.length != 1) {
throw new UnsupportedOperationException();
}
if(!urls[0].getProtocol().equals("file")) {
throw new UnsupportedOperationException(urls[0].getProtocol());
}
this.jarFile = new File(urls[0].getFile());
}
protected Class findClass(String name) throws ClassNotFoundException {
try {
InputStream stream = getResourceAsStream(name.replace(".", "/") + ".class");
if(stream == null) {
throw new ClassNotFoundException("couldn't find class " + name);
}
byte[] buf = new byte[2048];
ByteArrayOutputStream mem = new ByteArrayOutputStream();
try {
int size;
while((size = stream.read(buf, 0, buf.length)) > 0) {
mem.write(buf, 0, size);
}
byte[] data = mem.toByteArray();
return defineClass(name, data, 0, data.length);
} finally {
stream.close();
}
} catch(IOException e) {
throw new ClassNotFoundException("couldn't find class " + name, e);
}
}
public URL getResource(String path) {
try {
return new URL("jar:file:" + jarFile.getAbsolutePath() + "!/" + path);
} catch(MalformedURLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -31,6 +31,10 @@ class ArrayByteBuffer extends ByteBuffer {
return b;
}
public boolean hasArray() {
return true;
}
public byte[] array() {
return array;
}
@ -49,9 +53,10 @@ class ArrayByteBuffer extends ByteBuffer {
}
public ByteBuffer put(ByteBuffer src) {
checkPut(position, src.remaining());
src.get(array, arrayOffset + position, src.remaining());
position += src.remaining();
int length = src.remaining();
checkPut(position, length);
src.get(array, arrayOffset + position, length);
position += length;
return this;
}

View File

@ -53,13 +53,15 @@ public abstract class ByteBuffer
}
public ByteBuffer compact() {
int remaining = remaining();
if (position != 0) {
ByteBuffer b = slice();
position = 0;
put(b);
}
position = remaining();
position = remaining;
limit(capacity());
return this;

View File

@ -0,0 +1,40 @@
/* Copyright (c) 2012, 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. */
package java.nio;
public final class ByteOrder {
public static final ByteOrder BIG_ENDIAN = new ByteOrder("BIG_ENDIAN");
public static final ByteOrder LITTLE_ENDIAN = new ByteOrder("LITTLE_ENDIAN");
private static final ByteOrder NATIVE;
private static native boolean isNativeBigEndian();
static {
if (isNativeBigEndian())
NATIVE = BIG_ENDIAN;
else
NATIVE = LITTLE_ENDIAN;
}
private String name;
private ByteOrder(String name) {
this.name = name;
}
public String toString() {
return name;
}
public static ByteOrder nativeOrder() {
return NATIVE;
}
}

View File

@ -0,0 +1,27 @@
/* Copyright (c) 2013, 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. */
package java.util.jar;
public class Attributes {
public static class Name {
private final String name;
private static final int MAX_NAME_LENGTH = 70;
public Name(String s) {
int len = s.length();
if (len == 0 || len > MAX_NAME_LENGTH)
throw new IllegalArgumentException();
name = s;
}
}
}

View File

@ -15,6 +15,8 @@
#include "stdlib.h"
#include "string.h"
#include <avian/util/runtime-array.h>
#undef JNIEXPORT
#if (defined __MINGW32__) || (defined _MSC_VER)
@ -121,30 +123,5 @@ allocate(JNIEnv* e, unsigned size)
}
return p;
}
#ifdef _MSC_VER
template <class T>
class RuntimeArray {
public:
RuntimeArray(unsigned size):
body(static_cast<T*>(malloc(size * sizeof(T))))
{ }
~RuntimeArray() {
free(body);
}
T* body;
};
# define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
# define RUNTIME_ARRAY_BODY(name) name.body
#else // not _MSC_VER
# define RUNTIME_ARRAY(type, name, size) type name[size];
# define RUNTIME_ARRAY_BODY(name) name
#endif // not _MSC_VER
#endif//JNI_UTIL

View File

@ -1,5 +1,7 @@
package sun.misc;
import java.lang.reflect.Field;
public final class Unsafe {
private void Unsafe() { }
@ -50,10 +52,15 @@ public final class Unsafe {
public native int arrayBaseOffset(Class arrayClass);
public native long objectFieldOffset(Field field);
public native void copyMemory(Object srcBase, long srcOffset,
Object destBase, long destOffset,
long count);
public native boolean compareAndSwapInt(Object o, long offset, int old,
int new_);
public void copyMemory(long src, long dst, long count) {
copyMemory(null, src, null, dst, count);
}

View File

@ -12,7 +12,10 @@
#define AVIAN_TOOLS_H_
#include <stdlib.h>
#include "environment.h"
#include <avian/util/string.h>
#include "avian/environment.h"
namespace avian {
@ -38,24 +41,12 @@ public:
virtual void write(uint8_t byte);
};
class String {
public:
const char* text;
size_t length;
String(const char* text);
inline String(const char* text, size_t length):
text(text),
length(length) {}
};
class SymbolInfo {
public:
unsigned addr;
String name;
util::String name;
inline SymbolInfo(uint64_t addr, const String& name):
inline SymbolInfo(uint64_t addr, const util::String& name):
addr(addr),
name(name) {}
@ -78,7 +69,7 @@ public:
class StringTable : public Buffer {
public:
unsigned add(String str);
unsigned add(util::String str);
};
template<class T>

View File

@ -0,0 +1,47 @@
/* Copyright (c) 2008-2012, 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 AVIAN_UTIL_ABORT_H
#define AVIAN_UTIL_ABORT_H
namespace avian {
namespace util {
class Aborter {
public:
virtual void NO_RETURN abort() = 0;
};
template<class T>
inline void NO_RETURN abort(T t) {
getAborter(t)->abort();
::abort();
}
template<class T>
inline void expect(T t, bool v) {
if(UNLIKELY(!v)) {
abort(t);
}
}
#ifdef NDEBUG
#define assert(t, v)
#else
template<class T>
inline void assert(T t, bool v) {
expect(t, v);
}
#endif
} // namespace util
} // namespace avian
#endif // AVIAN_UTIL_ABORT_H

View File

@ -0,0 +1,46 @@
/* 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. */
#ifndef AVIAN_UTIL_ARG_PARSER_H
#define AVIAN_UTIL_ARG_PARSER_H
namespace avian {
namespace util {
class Arg;
class ArgParser {
public:
Arg* first;
Arg** last;
ArgParser();
bool parse(int ac, const char* const* av);
void printUsage(const char* exe);
};
class Arg {
public:
Arg* next;
bool required;
const char* name;
const char* desc;
const char* value;
Arg(ArgParser& parser, bool required, const char* name, const char* desc);
};
} // namespace avian
} // namespace util
#endif // AVIAN_UTIL_ARG_PARSER_H

56
include/avian/util/math.h Normal file
View File

@ -0,0 +1,56 @@
/* Copyright (c) 2008-2012, 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 AVIAN_UTIL_MATH_H
#define AVIAN_UTIL_MATH_H
#undef max
#undef min
namespace avian {
namespace util {
inline unsigned max(unsigned a, unsigned b) {
return (a > b ? a : b);
}
inline unsigned min(unsigned a, unsigned b) {
return (a < b ? a : b);
}
inline unsigned avg(unsigned a, unsigned b) {
return (a + b) / 2;
}
inline unsigned ceilingDivide(unsigned n, unsigned d) {
return (n + d - 1) / d;
}
inline bool powerOfTwo(unsigned n) {
for (; n > 2; n >>= 1) if (n & 1) return false;
return true;
}
inline unsigned nextPowerOfTwo(unsigned n) {
unsigned r = 1;
while (r < n) r <<= 1;
return r;
}
inline unsigned log(unsigned n) {
unsigned r = 0;
for (unsigned i = 1; i < n; ++r) i <<= 1;
return r;
}
} // namespace util
} // namespace avian
#endif // AVIAN_UTIL_MATH_H

View File

@ -0,0 +1,40 @@
/* Copyright (c) 2008-2012, 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 AVIAN_UTIL_RUNTIME_ARRAY_H
#define AVIAN_UTIL_RUNTIME_ARRAY_H
#ifdef _MSC_VER
template <class T>
class RuntimeArray {
public:
RuntimeArray(unsigned size):
body(static_cast<T*>(malloc(size * sizeof(T))))
{ }
~RuntimeArray() {
free(body);
}
T* body;
};
# define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
# define RUNTIME_ARRAY_BODY(name) name.body
#else // not _MSC_VER
# define RUNTIME_ARRAY(type, name, size) type name##_body[size];
# define RUNTIME_ARRAY_BODY(name) name##_body
#endif
#endif // AVIAN_UTIL_RUNTIME_ARRAY_H

View File

@ -11,19 +11,19 @@
#ifndef STREAM_H
#define STREAM_H
#include "common.h"
#include "avian/common.h"
namespace vm {
class Stream {
class AbstractStream {
public:
class Client {
public:
virtual void handleError() = 0;
};
Stream(Client* client, const uint8_t* data, unsigned size):
client(client), data(data), size(size), position_(0)
AbstractStream(Client* client, unsigned size):
client(client), size(size), position_(0)
{ }
unsigned position() {
@ -42,13 +42,13 @@ class Stream {
}
}
void read(uint8_t* data, unsigned size) {
void read(uint8_t* dst, unsigned size) {
if (size > this->size - position_) {
memset(data, 0, size);
memset(dst, 0, size);
client->handleError();
} else {
memcpy(data, this->data + position_, size);
copy(dst, position_, size);
position_ += size;
}
}
@ -85,13 +85,29 @@ class Stream {
return read8();
}
protected:
virtual void copy(uint8_t* dst, unsigned offset, unsigned size) = 0;
private:
Client* client;
const uint8_t* data;
unsigned size;
unsigned position_;
};
class Stream: public AbstractStream {
public:
Stream(Client* client, const uint8_t* data, unsigned size):
AbstractStream(client, size), data(data)
{ }
private:
virtual void copy(uint8_t* dst, unsigned offset, unsigned size) {
memcpy(dst, data + offset, size);
}
const uint8_t* data;
};
} // namespace vm
#endif//STREAM_H

View File

@ -0,0 +1,63 @@
/* Copyright (c) 2010-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. */
#ifndef AVIAN_UTIL_STRING_H
#define AVIAN_UTIL_STRING_H
#include <string.h>
namespace avian {
namespace util {
class String {
public:
const char* text;
size_t length;
String(const char* text):
text(text),
length(strlen(text)) {}
inline String(const char* text, size_t length):
text(text),
length(length) {}
};
class Tokenizer {
public:
Tokenizer(const char* s, char delimiter):
s(s), limit(0), delimiter(delimiter)
{ }
Tokenizer(String str, char delimiter):
s(str.text), limit(str.text + str.length), delimiter(delimiter)
{ }
bool hasMore() {
while (s != limit and *s == delimiter) ++s;
return s != limit and *s != 0;
}
String next() {
const char* p = s;
while (s != limit and *s and *s != delimiter) ++s;
return String(p, s - p);
}
const char* s;
const char* limit;
char delimiter;
};
} // namespace util
} // namespace avain
#endif//AVIAN_UTIL_STRING_H

View File

@ -0,0 +1,137 @@
/* Copyright (c) 2008-2012, 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 AVIAN_CODEGEN_ARCHITECTURE_H
#define AVIAN_CODEGEN_ARCHITECTURE_H
namespace vm {
class Allocator;
class Zone;
}
namespace avian {
namespace codegen {
class Assembler;
class RegisterFile;
class OperandMask {
public:
uint8_t typeMask;
uint64_t registerMask;
OperandMask(uint8_t typeMask, uint64_t registerMask):
typeMask(typeMask),
registerMask(registerMask)
{ }
OperandMask():
typeMask(~0),
registerMask(~static_cast<uint64_t>(0))
{ }
};
class Architecture {
public:
virtual unsigned floatRegisterSize() = 0;
virtual const RegisterFile* registerFile() = 0;
virtual int scratch() = 0;
virtual int stack() = 0;
virtual int thread() = 0;
virtual int returnLow() = 0;
virtual int returnHigh() = 0;
virtual int virtualCallTarget() = 0;
virtual int virtualCallIndex() = 0;
virtual bool bigEndian() = 0;
virtual uintptr_t maximumImmediateJump() = 0;
virtual bool alwaysCondensed(lir::BinaryOperation op) = 0;
virtual bool alwaysCondensed(lir::TernaryOperation op) = 0;
virtual bool reserved(int register_) = 0;
virtual unsigned frameFootprint(unsigned footprint) = 0;
virtual unsigned argumentFootprint(unsigned footprint) = 0;
virtual bool argumentAlignment() = 0;
virtual bool argumentRegisterAlignment() = 0;
virtual unsigned argumentRegisterCount() = 0;
virtual int argumentRegister(unsigned index) = 0;
virtual bool hasLinkRegister() = 0;
virtual unsigned stackAlignmentInWords() = 0;
virtual bool matchCall(void* returnAddress, void* target) = 0;
virtual void updateCall(lir::UnaryOperation op, void* returnAddress,
void* newTarget) = 0;
virtual void setConstant(void* dst, uint64_t constant) = 0;
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
void* link, bool mostRecent,
unsigned targetParameterFootprint, void** ip,
void** stack) = 0;
virtual void* frameIp(void* stack) = 0;
virtual unsigned frameHeaderSize() = 0;
virtual unsigned frameReturnAddressSize() = 0;
virtual unsigned frameFooterSize() = 0;
virtual int returnAddressOffset() = 0;
virtual int framePointerOffset() = 0;
virtual void plan
(lir::UnaryOperation op,
unsigned aSize, OperandMask& aMask,
bool* thunk) = 0;
virtual void planSource
(lir::BinaryOperation op,
unsigned aSize, OperandMask& aMask,
unsigned bSize, bool* thunk) = 0;
virtual void planDestination
(lir::BinaryOperation op,
unsigned aSize, const OperandMask& aMask,
unsigned bSize, OperandMask& bMask) = 0;
virtual void planMove
(unsigned size, OperandMask& src,
OperandMask& tmp,
const OperandMask& dst) = 0;
virtual void planSource
(lir::TernaryOperation op,
unsigned aSize, OperandMask& aMask,
unsigned bSize, OperandMask& bMask,
unsigned cSize, bool* thunk) = 0;
virtual void planDestination
(lir::TernaryOperation op,
unsigned aSize, const OperandMask& aMask,
unsigned bSize, const OperandMask& bMask,
unsigned cSize, OperandMask& cMask) = 0;
virtual Assembler* makeAssembler(vm::Allocator*, vm::Zone*) = 0;
virtual void acquire() = 0;
virtual void release() = 0;
};
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_ARCHITECTURE_H

View File

@ -0,0 +1,113 @@
/* Copyright (c) 2008-2012, 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 AVIAN_CODEGEN_ASSEMBLER_H
#define AVIAN_CODEGEN_ASSEMBLER_H
#include <avian/vm/system/system.h>
#include "avian/zone.h"
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/promise.h>
namespace avian {
namespace codegen {
class Architecture;
class OperandInfo {
public:
const unsigned size;
const lir::OperandType type;
lir::Operand* const operand;
inline OperandInfo(unsigned size, lir::OperandType type, lir::Operand* operand):
size(size),
type(type),
operand(operand)
{ }
};
#ifdef AVIAN_TAILS
const bool TailCalls = true;
#else
const bool TailCalls = false;
#endif
#if (defined AVIAN_USE_FRAME_POINTER) || (defined ARCH_powerpc)
const bool UseFramePointer = true;
#else
const bool UseFramePointer = false;
#endif
class Assembler {
public:
class Client {
public:
virtual int acquireTemporary
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
virtual void releaseTemporary(int r) = 0;
virtual void save(int r) = 0;
};
class Block {
public:
virtual unsigned resolve(unsigned start, Block* next) = 0;
};
virtual void setClient(Client* client) = 0;
virtual Architecture* arch() = 0;
virtual void checkStackOverflow(uintptr_t handler,
unsigned stackLimitOffsetFromThread) = 0;
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) = 0;
virtual void pushFrame(unsigned argumentCount, ...) = 0;
virtual void allocateFrame(unsigned footprint) = 0;
virtual void adjustFrame(unsigned difference) = 0;
virtual void popFrame(unsigned footprint) = 0;
virtual void popFrameForTailCall(unsigned footprint, int offset,
int returnAddressSurrogate,
int framePointerSurrogate) = 0;
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
unsigned argumentFootprint)
= 0;
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
unsigned stackOffsetFromThread)
= 0;
virtual void apply(lir::Operation op) = 0;
virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0;
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0;
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) = 0;
virtual void setDestination(uint8_t* dst) = 0;
virtual void write() = 0;
virtual Promise* offset(bool forTrace = false) = 0;
virtual Block* endBlock(bool startNew) = 0;
virtual void endEvent() = 0;
virtual unsigned length() = 0;
virtual unsigned footerSize() = 0;
virtual void dispose() = 0;
};
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_H

View File

@ -8,14 +8,15 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef COMPILER_H
#define COMPILER_H
#ifndef AVIAN_CODEGEN_COMPILER_H
#define AVIAN_CODEGEN_COMPILER_H
#include "system.h"
#include "zone.h"
#include <avian/vm/system/system.h>
#include "avian/zone.h"
#include "assembler.h"
namespace vm {
namespace avian {
namespace codegen {
class TraceHandler {
public:
@ -26,10 +27,10 @@ class Compiler {
public:
class Client {
public:
virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(BinaryOperation op, unsigned size,
virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(lir::BinaryOperation op, unsigned size,
unsigned resultSize) = 0;
virtual intptr_t getThunk(TernaryOperation op, unsigned size,
virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size,
unsigned resultSize, bool* threadParameter) = 0;
};
@ -200,9 +201,10 @@ class Compiler {
};
Compiler*
makeCompiler(System* system, Assembler* assembler, Zone* zone,
makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
Compiler::Client* client);
} // namespace vm
} // namespace codegen
} // namespace avian
#endif//COMPILER_H
#endif // AVIAN_CODEGEN_COMPILER_H

View File

@ -0,0 +1,62 @@
LIR_OP_0(Return)
LIR_OP_0(LoadBarrier)
LIR_OP_0(StoreStoreBarrier)
LIR_OP_0(StoreLoadBarrier)
LIR_OP_0(Trap)
LIR_OP_1(Call)
LIR_OP_1(LongCall)
LIR_OP_1(AlignedLongCall)
LIR_OP_1(AlignedCall)
LIR_OP_1(Jump)
LIR_OP_1(LongJump)
LIR_OP_1(AlignedLongJump)
LIR_OP_1(AlignedJump)
LIR_OP_2(Move)
LIR_OP_2(MoveLow)
LIR_OP_2(MoveHigh)
LIR_OP_2(MoveZ)
LIR_OP_2(Negate)
LIR_OP_2(FloatNegate)
LIR_OP_2(Float2Float)
LIR_OP_2(Float2Int)
LIR_OP_2(Int2Float)
LIR_OP_2(FloatSquareRoot)
LIR_OP_2(FloatAbsolute)
LIR_OP_2(Absolute)
LIR_OP_3(Add)
LIR_OP_3(Subtract)
LIR_OP_3(Multiply)
LIR_OP_3(Divide)
LIR_OP_3(Remainder)
LIR_OP_3(ShiftLeft)
LIR_OP_3(ShiftRight)
LIR_OP_3(UnsignedShiftRight)
LIR_OP_3(And)
LIR_OP_3(Or)
LIR_OP_3(Xor)
LIR_OP_3(FloatAdd)
LIR_OP_3(FloatSubtract)
LIR_OP_3(FloatMultiply)
LIR_OP_3(FloatDivide)
LIR_OP_3(FloatRemainder)
LIR_OP_3(FloatMax)
LIR_OP_3(FloatMin)
LIR_OP_3(JumpIfLess)
LIR_OP_3(JumpIfGreater)
LIR_OP_3(JumpIfLessOrEqual)
LIR_OP_3(JumpIfGreaterOrEqual)
LIR_OP_3(JumpIfEqual)
LIR_OP_3(JumpIfNotEqual)
LIR_OP_3(JumpIfFloatEqual)
LIR_OP_3(JumpIfFloatNotEqual)
LIR_OP_3(JumpIfFloatLess)
LIR_OP_3(JumpIfFloatGreater)
LIR_OP_3(JumpIfFloatLessOrEqual)
LIR_OP_3(JumpIfFloatGreaterOrEqual)
LIR_OP_3(JumpIfFloatLessOrUnordered)
LIR_OP_3(JumpIfFloatGreaterOrUnordered)
LIR_OP_3(JumpIfFloatLessOrEqualOrUnordered)
LIR_OP_3(JumpIfFloatGreaterOrEqualOrUnordered)

View File

@ -0,0 +1,174 @@
/* Copyright (c) 2008-2012, 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 AVIAN_CODEGEN_LIR_H
#define AVIAN_CODEGEN_LIR_H
namespace avian {
namespace codegen {
class Promise;
namespace lir {
enum Operation {
#define LIR_OP_0(x) x,
#define LIR_OP_1(x)
#define LIR_OP_2(x)
#define LIR_OP_3(x)
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
};
const unsigned OperationCount = Trap + 1;
enum UnaryOperation {
#define LIR_OP_0(x)
#define LIR_OP_1(x) x,
#define LIR_OP_2(x)
#define LIR_OP_3(x)
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoUnaryOperation = -1
};
const unsigned UnaryOperationCount = AlignedJump + 1;
enum BinaryOperation {
#define LIR_OP_0(x)
#define LIR_OP_1(x)
#define LIR_OP_2(x) x,
#define LIR_OP_3(x)
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoBinaryOperation = -1
};
const unsigned BinaryOperationCount = Absolute + 1;
enum TernaryOperation {
#define LIR_OP_0(x)
#define LIR_OP_1(x)
#define LIR_OP_2(x)
#define LIR_OP_3(x) x,
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoTernaryOperation = -1
};
const unsigned TernaryOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
const unsigned BranchOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin;
enum OperandType {
ConstantOperand,
AddressOperand,
RegisterOperand,
MemoryOperand
};
enum ValueType {
ValueGeneral,
ValueFloat
};
const unsigned OperandTypeCount = MemoryOperand + 1;
const int NoRegister = -1;
inline bool isBranch(lir::TernaryOperation op) {
return op > FloatMin;
}
inline bool isFloatBranch(lir::TernaryOperation op) {
return op > JumpIfNotEqual;
}
class Operand { };
class Constant: public Operand {
public:
Constant(Promise* value): value(value) { }
Promise* value;
};
class Address: public Operand {
public:
Address(Promise* address): address(address) { }
Promise* address;
};
class Register: public Operand {
public:
Register(int low, int high = NoRegister): low(low), high(high) { }
int low;
int high;
};
class Memory: public Operand {
public:
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
base(base), offset(offset), index(index), scale(scale)
{ }
int base;
int offset;
int index;
unsigned scale;
};
class Instr {
public:
enum Opcode {
#define LIR_OP_0(x) OP_##x,
#define LIR_OP_1(x) OP_##x,
#define LIR_OP_2(x) OP_##x,
#define LIR_OP_3(x) OP_##x,
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
};
static const char* opcodeName(Opcode op);
static Opcode opcodeFromNullary(Operation op);
static Opcode opcodeFromUnary(UnaryOperation op);
static Opcode opcodeFromBinary(BinaryOperation op);
static Opcode opcodeFromTernary(TernaryOperation op);
};
} // namespace lir
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_LIR_H

View File

@ -0,0 +1,159 @@
/* Copyright (c) 2008-2012, 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 AVIAN_CODEGEN_PROMISE_H
#define AVIAN_CODEGEN_PROMISE_H
#include "avian/allocator.h"
namespace avian {
namespace codegen {
class Promise {
public:
class Listener {
public:
virtual bool resolve(int64_t value, void** location) = 0;
Listener* next;
};
virtual int64_t value() = 0;
virtual bool resolved() = 0;
virtual Listener* listen(unsigned) { return 0; }
};
class ResolvedPromise: public Promise {
public:
ResolvedPromise(int64_t value): value_(value) { }
virtual int64_t value() {
return value_;
}
virtual bool resolved() {
return true;
}
int64_t value_;
};
class ShiftMaskPromise: public Promise {
public:
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
base(base), shift(shift), mask(mask)
{ }
virtual int64_t value() {
return (base->value() >> shift) & mask;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
unsigned shift;
int64_t mask;
};
class CombinedPromise: public Promise {
public:
CombinedPromise(Promise* low, Promise* high):
low(low), high(high)
{ }
virtual int64_t value() {
return low->value() | (high->value() << 32);
}
virtual bool resolved() {
return low->resolved() and high->resolved();
}
Promise* low;
Promise* high;
};
class OffsetPromise: public Promise {
public:
OffsetPromise(Promise* base, int64_t offset):
base(base), offset(offset)
{ }
virtual int64_t value() {
return base->value() + offset;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
int64_t offset;
};
class ListenPromise: public Promise {
public:
ListenPromise(vm::System* s, vm::Allocator* allocator):
s(s), allocator(allocator), listener(0)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
vm::System* s;
vm::Allocator* allocator;
Listener* listener;
Promise* promise;
};
class DelayedPromise: public ListenPromise {
public:
DelayedPromise(vm::System* s, vm::Allocator* allocator, Promise* basis,
DelayedPromise* next):
ListenPromise(s, allocator), basis(basis), next(next)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
Promise* basis;
DelayedPromise* next;
};
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_PROMISE_H

View File

@ -0,0 +1,73 @@
/* Copyright (c) 2008-2012, 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 AVIAN_CODEGEN_REGISTERS_H
#define AVIAN_CODEGEN_REGISTERS_H
#include "avian/common.h"
namespace avian {
namespace codegen {
class RegisterMask {
public:
uint32_t mask;
uint8_t start;
uint8_t limit;
static unsigned maskStart(uint32_t mask);
static unsigned maskLimit(uint32_t mask);
inline RegisterMask(uint32_t mask):
mask(mask),
start(maskStart(mask)),
limit(maskLimit(mask))
{ }
};
class RegisterFile {
public:
RegisterMask allRegisters;
RegisterMask generalRegisters;
RegisterMask floatRegisters;
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask):
allRegisters(generalRegisterMask | floatRegisterMask),
generalRegisters(generalRegisterMask),
floatRegisters(floatRegisterMask)
{ }
};
class RegisterIterator {
public:
int index;
const RegisterMask& mask;
inline RegisterIterator(const RegisterMask& mask):
index(mask.start),
mask(mask) {}
inline bool hasNext() {
return index < mask.limit;
}
inline int next() {
int r = index;
do {
index++;
} while(index < mask.limit && !(mask.mask & (1 << index)));
return r;
}
};
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_REGISTERS_H

View File

@ -0,0 +1,32 @@
/* Copyright (c) 2008-2012, 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 AVIAN_CODEGEN_TARGETS_H
#define AVIAN_CODEGEN_TARGETS_H
namespace vm {
class System;
}
namespace avian {
namespace codegen {
class Architecture;
Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures);
Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures);
Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures);
Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures);
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_TARGETS_H

View File

@ -11,8 +11,8 @@
#ifndef HEAP_H
#define HEAP_H
#include "system.h"
#include "allocator.h"
#include <avian/vm/system/system.h>
#include "avian/allocator.h"
namespace vm {
@ -59,13 +59,16 @@ class Heap: public Allocator {
virtual void setClient(Client* client) = 0;
virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) = 0;
virtual bool limitExceeded() = 0;
virtual void collect(CollectionType type, unsigned footprint) = 0;
virtual unsigned limit() = 0;
virtual bool limitExceeded(int pendingAllocation = 0) = 0;
virtual void collect(CollectionType type, unsigned footprint,
int pendingAllocation) = 0;
virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0;
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,
bool objectMask, unsigned* totalInBytes) = 0;
bool objectMask) = 0;
virtual void* allocateImmortalFixed(Allocator* allocator,
unsigned sizeInWords, bool objectMask,
unsigned* totalInBytes) = 0;
unsigned sizeInWords,
bool objectMask) = 0;
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
virtual void pad(void* p) = 0;
virtual void* follow(void* p) = 0;

View File

@ -11,12 +11,13 @@
#ifndef SYSTEM_H
#define SYSTEM_H
#include "common.h"
#include "allocator.h"
#include "avian/common.h"
#include "avian/allocator.h"
#include <avian/util/abort.h>
namespace vm {
class System {
class System : public avian::util::Aborter {
public:
typedef intptr_t Status;
@ -121,8 +122,10 @@ class System {
virtual bool success(Status) = 0;
virtual void* tryAllocate(unsigned sizeInBytes) = 0;
virtual void free(const void* p) = 0;
#if !defined(AVIAN_AOT_ONLY)
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;
@ -148,7 +151,6 @@ class System {
virtual int64_t now() = 0;
virtual void yield() = 0;
virtual void exit(int code) = 0;
virtual void abort() = 0;
virtual void dispose() = 0;
};
@ -163,11 +165,8 @@ allocate(System* s, unsigned size)
#define ACQUIRE_MONITOR(t, m) \
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)
inline void NO_RETURN
abort(System* s)
{
s->abort(); // this should not return
::abort();
inline avian::util::Aborter* getAborter(System* s) {
return s;
}
inline void NO_RETURN
@ -176,28 +175,22 @@ sysAbort(System* s)
abort(s);
}
inline void
expect(System* s, bool v)
{
if (UNLIKELY(not v)) abort(s);
}
// #ifdef NDEBUG
#ifdef NDEBUG
// # define assert(a, b)
// # define vm_assert(a, b)
# define assert(a, b)
# define vm_assert(a, b)
// #else // not NDEBUG
#else // not NDEBUG
// inline void
// assert(System* s, bool v)
// {
// expect(s, v);
// }
inline void
assert(System* s, bool v)
{
expect(s, v);
}
// # define vm_assert(a, b) vm::assert(a, b)
# define vm_assert(a, b) vm::assert(a, b)
#endif // not NDEBUG
// #endif // not NDEBUG
JNIEXPORT System*
makeSystem(const char* crashDumpDirectory);

994
makefile

File diff suppressed because it is too large Load Diff

View File

@ -196,6 +196,8 @@ ifeq ($(platform),windows)
$(openjdk-src)/windows/native/java/net/NetworkInterface_winXP.c \
$(openjdk-src)/windows/native/java/net/SocketInputStream.c \
$(openjdk-src)/windows/native/java/net/SocketOutputStream.c \
$(openjdk-src)/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c \
$(openjdk-src)/windows/native/java/net/TwoStacksPlainSocketImpl.c \
$(openjdk-src)/windows/native/java/util/WindowsPreferences.c \
$(openjdk-src)/windows/native/java/util/logging.c \
$(openjdk-src)/windows/native/java/util/TimeZone_md.c \
@ -216,6 +218,9 @@ ifeq ($(platform),windows)
openjdk-headers-classes += \
java.net.DualStackPlainSocketImpl \
java.net.SocketImpl \
java.net.TwoStacksPlainDatagramSocketImpl \
java.net.TwoStacksPlainSocketImpl \
java.lang.ProcessImpl \
sun.io.Win32ErrorMode \
sun.nio.ch.WindowsSelectorImpl \
@ -327,7 +332,8 @@ else
$(src)/openjdk/my_java_props_macosx.c
else
openjdk-sources += \
$(openjdk-src)/solaris/native/java/lang/java_props_macosx.c
$(openjdk-src)/solaris/native/java/lang/java_props_macosx.c \
$(openjdk-src)/macosx/native/sun/nio/ch/KQueueArrayWrapper.c
endif
openjdk-cflags += \

View File

@ -14,6 +14,10 @@
public static void setProperties(java.util.Properties);
}
-keep class sun.misc.Launcher {
public static sun.misc.Launcher getLauncher();
}
-keep class java.lang.ClassLoader {
private static java.lang.ClassLoader scl;
private static boolean sclSet;
@ -42,7 +46,7 @@
}
-keep class avian.OpenJDK {
public static java.security.ProtectionDomain getProtectionDomain();
<methods>;
}
-keepclassmembers public class java.security.PrivilegedAction {
@ -132,11 +136,30 @@
public InetSocketAddress(java.net.InetAddress, int);
}
-keep class java.net.ServerSocket
-keep class java.net.SocketTimeoutException
-keepclassmembers class java.net.PlainSocketImpl {
<fields>;
}
-keepclassmembers class java.net.TwoStacksPlainSocketImpl {
*** fd1;
*** lastfd;
}
-keepclassmembers class java.net.AbstractPlainSocketImpl {
*** timeout;
*** trafficClass;
}
-keepclassmembers class java.net.SocketImpl {
*** serverSocket;
*** fd;
*** address;
*** port;
*** localport;
}
-keepclassmembers class java.io.FileInputStream {
private java.io.FileDescriptor fd;
}
@ -208,7 +231,7 @@
-keep class sun.nio.cs.UTF_8
# loaded reflectively to handle embedded resources:
-keep class avian.resource.Handler
-keep class avian.avianvmresource.Handler
# refered to symbolically in MethodAccessorGenerator:
-keep class sun.reflect.MethodAccessorImpl {
@ -244,3 +267,41 @@
-keep class sun.nio.fs.UnixException {
UnixException(int);
}
-keep class sun.net.www.protocol.jar.Handler
# These concurrent classes refer to certain members reflectively in their static initializers
-keepclassmembers class java.util.concurrent.ConcurrentHashMap$HashEntry {
*** next;
}
-keepclassmembers class java.util.concurrent.CopyOnWriteArrayList {
*** lock;
}
-keepclassmembers class java.util.concurrent.CountDownLatch {
*** allocationSpinLock;
}
-keepclassmembers class java.util.concurrent.PriorityBlockingQueue {
*** allocationSpinLock;
}
-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack {
*** head;
}
-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue {
*** head;
*** tail;
}
-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue$Node {
*** item;
*** next;
}
-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack$SNode {
*** match;
*** next;
}

View File

@ -1,727 +0,0 @@
Quick Start
-----------
on Linux:
$ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed
$ make
$ build/linux-i386/avian -cp build/linux-i386/test Hello
on Mac OS X:
$ export JAVA_HOME=/Library/Java/Home
$ make
$ build/darwin-i386/avian -cp build/darwin-i386/test Hello
on Windows (MSYS):
$ git clone git://oss.readytalk.com/win32.git ../win32
$ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07"
$ make
$ build/windows-i386/avian -cp build/windows-i386/test Hello
on Windows (Cygwin):
$ git clone git://oss.readytalk.com/win32.git ../win32
$ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07"
$ make
$ build/windows-i386/avian -cp build/windows-i386/test Hello
Adjust JAVA_HOME according to your system, but be sure to use forward
slashes in the path.
Introduction
------------
Avian is a lightweight virtual machine and class library designed to
provide a useful subset of Java's features, suitable for building
self-contained applications. More information is available at the
project web site:
http://oss.readytalk.com/avian
If you have any trouble building, running, or embedding Avian, please
post a message to our discussion group:
http://groups.google.com/group/avian
That's also the place for any other questions, comments, or
suggestions you might have.
Supported Platforms
-------------------
Avian can currently target the following platforms:
Linux (i386, x86_64, ARM, and 32-bit PowerPC)
Windows (i386 and x86_64)
Mac OS X (i386, x86_64 and 32-bit PowerPC)
Apple iOS (i386 and ARM)
Building
--------
Build requirements include:
* GNU make 3.80 or later
* GCC 3.4 or later (4.5.1 or later for Windows/x86_64)
or LLVM Clang 3.1 or later (see use-clang option below)
* JDK 1.5 or later
* MinGW 3.4 or later (only if compiling for Windows)
* zlib 1.2.3 or later
Earlier versions of some of these packages may also work but have not
been tested.
The build is directed by a single makefile and may be influenced via
certain flags described below, all of which are optional.
$ make \
platform={linux,windows,darwin} \
arch={i386,x86_64,powerpc,arm} \
process={compile,interpret} \
mode={debug,debug-fast,fast,small} \
lzma=<lzma source directory> \
ios={true,false} \
bootimage={true,false} \
heapdump={true,false} \
tails={true,false} \
continuations={true,false} \
use-clang={true,false} \
openjdk=<openjdk installation directory> \
openjdk-src=<openjdk source directory>
* platform - the target platform
default: output of $(uname -s | tr [:upper:] [:lower:]),
normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows)
* arch - the target architecture
default: output of $(uname -m), normalized in some cases
(e.g. i686 -> i386)
* process - choice between pure interpreter or JIT compiler
default: compile
* mode - which set of compilation flags to use to determine
optimization level, debug symbols, and whether to enable
assertions
default: fast
* lzma - if set, support use of LZMA to compress embedded JARs and
boot images. The value of this option should be a directory
containing a recent LZMA SDK (available at
http://www.7-zip.org/sdk.html). Currently, only version 9.20 of
the SDK has been tested, but other versions might work.
default: not set
* ios - if true, cross-compile for iOS on OS X. Note that
non-jailbroken iOS devices do not allow JIT compilation, so only
process=interpret or bootimage=true builds will run on such
devices. See https://github.com/ReadyTalk/hello-ios for an
example of an Xcode project for iOS which uses Avian.
default: false
* bootimage - if true, create a boot image containing the pre-parsed
class library and ahead-of-time compiled methods. This option is
only valid for process=compile builds. Note that you may need to
specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems
where "uname -m" prints "i386".
default: false
* heapdump - if true, implement avian.Machine.dumpHeap(String),
which, when called, will generate a snapshot of the heap in a
simple, ad-hoc format for memory profiling purposes. See
heapdump.cpp for details.
default: false
* tails - if true, optimize each tail call by replacing the caller's
stack frame with the callee's. This convention ensures proper
tail recursion, suitable for languages such as Scheme. This
option is only valid for process=compile builds.
default: false
* continuations - if true, support continuations via the
avian.Continuations methods callWithCurrentContinuation and
dynamicWind. See Continuations.java for details. This option is
only valid for process=compile builds.
default: false
* use-clang - if true, use LLVM's clang instead of GCC to build.
Note that this does not currently affect cross compiles, only
native builds.
default: false
* openjdk - if set, use OpenJDK class library instead of the default
Avian class library. See "Building with the OpenJDK Class
Library" below for details.
default: not set
* openjdk-src - if this and the openjdk option above are both set,
build an embeddable VM using the OpenJDK class library. The JNI
components of the OpenJDK class library will be built from the
sources found under the specified directory. See "Building with
the OpenJDK Class Library" below for details.
default: not set
These flags determine the name of the directory used for the build.
The name always starts with ${platform}-${arch}, and each non-default
build option is appended to the name. For example, a debug build with
bootimage enabled on Linux/i386 would be built in
build/linux-i386-debug-bootimage. This allows you to build with
several different sets of options independently and even
simultaneously without doing a clean build each time.
If you are compiling for Windows, you may either cross-compile using
MinGW or build natively on Windows under MSYS or Cygwin.
Installing MSYS:
1. Download and install the current MinGW and MSYS packages from
mingw.org, selecting the C and C++ compilers when prompted. Use the
post-install script to create the filesystem link to the compiler.
2. Download GNU Make 3.81 from the MSYS download page
(make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into
e.g. c:/msys/1.0.
Installing Cygwin:
1. Download and run setup.exe from cygwin.com, installing the base
system and these packages: make, gcc-mingw-g++,
mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git.
You may also find our win32 repository useful: (run this from the
directory containing the avian directory)
$ git clone git://oss.readytalk.com/win32.git
This gives you the Windows JNI headers, zlib headers and library, and
a few other useful libraries like OpenSSL, libjpeg, and libpng.
There's also a win64 repository for 64-bit builds:
$ git clone git://oss.readytalk.com/win64.git
Building with the Microsoft Visual C++ Compiler
-----------------------------------------------
You can also build using the MSVC compiler, which makes debugging with
tools like WinDbg and Visual Studio much easier. Note that you will
still need to have GCC installed - MSVC is only used to compile the
C++ portions of the VM, while the assembly code and helper tools are
built using GCC.
The MSVC build has been tested with Visual Studio Express Edition
versions 8, 9, and 10. Other versions may also work.
To build with MSVC, install Cygwin as described above and set the
following environment variables:
$ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem"
$ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;"
$ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC"
$ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;"
$ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;"
Adjust these definitions as necessary according to your MSVC
installation.
Finally, build with the msvc flag set to the MSVC tool directory:
$ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC"
Building with the OpenJDK Class Library
---------------------------------------
By default, Avian uses its own lightweight class library. However,
that library only contains a relatively small subset of the classes
and methods included in the JRE. If your application requires
features beyond that subset, you may want to tell Avian to use
OpenJDK's class library instead. To do so, specify the directory
where OpenJDK is installed, e.g.:
$ make openjdk=/usr/lib/jvm/java-7-openjdk
This will build Avian as a conventional JVM (e.g. libjvm.so) which
loads its boot class library and native libraries (e.g. libjava.so)
from /usr/lib/jvm/java-7-openjdk/jre at runtime. To run an
application in this configuration, you'll need to make sure the VM is
in your library search path. For example:
$ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \
build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \
com.example.MyApplication
Alternatively, you can enable a stand-alone build using OpenJDK by
specifying the location of the OpenJDK source code, e.g.:
$ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \
openjdk-src=$(pwd)/../jdk7/jdk/src
You must ensure that the path specified for openjdk-src does not have
any spaces in it; make gets confused when dependency paths include
spaces, and we haven't found away around that except to avoid paths
with spaces entirely.
The result of such a build is a self-contained binary which does not
depend on external libraries, jars, or other files. In this case, the
specified paths are used only at build time; anything needed at
runtime is embedded in the binary. Thus, the process of running an
application is simplified:
$ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \
com.example.MyApplication
Note that the resulting binary will be very large due to the size of
OpenJDK's class library. This can be mitigated using UPX, preferably
an LZMA-enabled version:
$ upx --lzma --best build/linux-x86_64-openjdk-src/avian
You can reduce the size futher for embedded builds by using ProGuard
and the supplied openjdk.pro configuration file (see "Embedding with
ProGuard and a Boot Image" below). Note that you'll still need to use
vm.pro in that case -- openjdk.pro just adds additional constraints
specific to the OpenJDK port. Also see app.mk in
git://oss.readytalk.com/avian-swt-examples.git for an example of using
Avian, OpenJDK, ProGuard, and UPX in concert.
Here are some examples of how to install OpenJDK and build Avian with
it on various OSes:
Debian-based Linux:
# conventional build:
apt-get install openjdk-7-jdk
make openjdk=/usr/lib/jvm/java-7-openjdk test
# stand-alone build:
apt-get install openjdk-7-jdk
apt-get source openjdk-7-jdk
apt-get build-dep openjdk-7-jdk
(cd openjdk-7-7~b147-2.0 && dpkg-buildpackage)
make openjdk=/usr/lib/jvm/java-7-openjdk \
openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \
test
Mac OS X:
# Prerequisite: build OpenJDK 7 according to
# https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port
# conventional build:
make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test
# stand-alone build:
make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \
openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test
Windows (Cygwin):
# Prerequisite: build OpenJDK 7 according to
# http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction
# conventional build:
make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test
# stand-alone build:
make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \
openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test
Currently, only OpenJDK 7 is supported. Later versions might work,
but have not yet been tested.
Installing
----------
Installing Avian is as simple as copying the executable to the desired
directory:
$ cp build/${platform}-${arch}/avian ~/bin/
Embedding
---------
The following series of commands illustrates how to produce a
stand-alone executable out of a Java application using Avian.
Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or
"i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands
below (e.g. x86_64-w64-mingw32-gcc).
Step 1: Build Avian, create a new directory, and populate it with the
VM object files and bootstrap classpath jar.
$ make
$ mkdir hello
$ cd hello
$ ar x ../build/${platform}-${arch}/libavian.a
$ cp ../build/${platform}-${arch}/classpath.jar boot.jar
Step 2: Build the Java code and add it to the jar.
$ cat >Hello.java <<EOF
public class Hello {
public static void main(String[] args) {
System.out.println("hello, world!");
}
}
EOF
$ javac -bootclasspath boot.jar Hello.java
$ jar u0f boot.jar Hello.class
Step 3: Make an object file out of the jar.
$ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \
boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch}
If you've built Avian using the lzma option, you may optionally
compress the jar before generating the object:
$ ../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma
&& ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \
boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \
${platform} ${arch}
Note that you'll need to specify "-Xbootclasspath:[lzma:bootJar]"
instead of "-Xbootclasspath:[bootJar]" in the next step if you've used
LZMA to compress the jar.
Step 4: Write a driver which starts the VM and runs the desired main
method. Note the bootJar function, which will be called by the VM to
get a handle to the embedded jar. We tell the VM about this jar by
setting the boot classpath to "[bootJar]".
$ cat >embedded-jar-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"
#if (defined __MINGW32__) || (defined _MSC_VER)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __attribute__ ((visibility("default"))) \
__attribute__ ((used))
#endif
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define SYMBOL(x) binary_boot_jar_##x
#else
# define SYMBOL(x) _binary_boot_jar_##x
#endif
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
EXPORT const uint8_t*
bootJar(unsigned* size)
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
} // extern "C"
int
main(int ac, const char** av)
{
JavaVMInitArgs vmArgs;
vmArgs.version = JNI_VERSION_1_2;
vmArgs.nOptions = 1;
vmArgs.ignoreUnrecognized = JNI_TRUE;
JavaVMOption options[vmArgs.nOptions];
vmArgs.options = options;
options[0].optionString = const_cast<char*>("-Xbootclasspath:[bootJar]");
JavaVM* vm;
void* env;
JNI_CreateJavaVM(&vm, &env, &vmArgs);
JNIEnv* e = static_cast<JNIEnv*>(env);
jclass c = e->FindClass("Hello");
if (not e->ExceptionCheck()) {
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
if (not e->ExceptionCheck()) {
jclass stringClass = e->FindClass("java/lang/String");
if (not e->ExceptionCheck()) {
jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
if (not e->ExceptionCheck()) {
for (int i = 1; i < ac; ++i) {
e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
}
e->CallStaticVoidMethod(c, m, a);
}
}
}
}
int exitCode = 0;
if (e->ExceptionCheck()) {
exitCode = -1;
e->ExceptionDescribe();
}
vm->DestroyJavaVM();
return exitCode;
}
EOF
on Linux:
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
-D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o
on Mac OS X:
$ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \
-o main.o
on Windows:
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \
-D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o
Step 5: Link the objects produced above to produce the final
executable, and optionally strip its symbols.
on Linux:
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello
on Mac OS X:
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation
$ strip -S -x hello
on Windows:
$ dlltool -z hello.def *.o
$ dlltool -d hello.def -e hello.exp
$ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \
-mwindows -mconsole -o hello.exe
$ strip --strip-all hello.exe
Embedding with ProGuard and a Boot Image
----------------------------------------
The following illustrates how to embed an application as above, except
this time we preprocess the code using ProGuard and build a boot image
from it for quicker startup. The pros and cons of using ProGuard are
as follow:
* Pros: ProGuard will eliminate unused code, optimize the rest, and
obfuscate it as well for maximum space savings
* Cons: increased build time, especially for large applications, and
extra effort needed to configure it for applications which rely
heavily on reflection and/or calls to Java from native code
For boot image builds:
* Pros: the boot image build pre-parses all the classes and compiles
all the methods, obviating the need for JIT compilation at runtime.
This also makes garbage collection faster, since the pre-parsed
classes are never visited.
* Cons: the pre-parsed classes and AOT-compiled methods take up more
space in the executable than the equivalent class files. In
practice, this can make the executable 30-50% larger. Also, AOT
compilation does not yet yield significantly faster or smaller code
than JIT compilation. Finally, floating point code may be slower
on 32-bit x86 since the compiler cannot assume SSE2 support will be
available at runtime, and the x87 FPU is not supported except via
out-of-line helper functions.
Note you can use ProGuard without using a boot image and vice-versa,
as desired.
The following instructions assume we are building for Linux/i386.
Please refer to the previous example for guidance on other platforms.
Step 1: Build Avian, create a new directory, and populate it with the
VM object files.
$ make bootimage=true
$ mkdir hello
$ cd hello
$ ar x ../build/linux-i386-bootimage/libavian.a
Step 2: Create a stage1 directory and extract the contents of the
class library jar into it.
$ mkdir stage1
$ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar)
Step 3: Build the Java code and add it to stage1.
$ cat >Hello.java <<EOF
public class Hello {
public static void main(String[] args) {
System.out.println("hello, world!");
}
}
EOF
$ javac -bootclasspath stage1 -d stage1 Hello.java
Step 4: Create a ProGuard configuration file specifying Hello.main as
the entry point.
$ cat >hello.pro <<EOF
-keep class Hello {
public static void main(java.lang.String[]);
}
EOF
Step 5: Run ProGuard with stage1 as input and stage2 as output.
$ java -jar ../../proguard4.6/lib/proguard.jar \
-dontusemixedcaseclassnames -injars stage1 -outjars stage2 \
@../vm.pro @hello.pro
(note: The -dontusemixedcaseclassnames option is only needed when
building on systems with case-insensitive filesystems such as Windows
and OS X. Also, you'll need to add -ignorewarnings if you use the
OpenJDK class library since the openjdk-src build does not include all
the JARs from OpenJDK, and thus ProGuard will not be able to resolve
all referenced classes. If you actually plan to use such classes at
runtime, you'll need to add them to stage1 before running ProGuard.
Finally, you'll need to add @../openjdk.pro to the above command when
using the OpenJDK library.)
Step 6: Build the boot and code images.
$ ../build/linux-i386-bootimage/bootimage-generator
-cp stage2 \
-bootimage bootimage-bin.o \
-codeimage codeimage-bin.o
Note that you can override the default names for the start and end
symbols in the boot/code image by also passing:
-bootimage-symbols my_bootimage_start:my_bootimage_end \
-codeimage-symbols my_codeimage_start:my_codeimage_end
Step 7: Write a driver which starts the VM and runs the desired main
method. Note the bootimageBin function, which will be called by the
VM to get a handle to the embedded boot image. We tell the VM about
this function via the "avian.bootimage" property.
Note also that this example includes no resources besides class files.
If our application loaded resources such as images and properties
files via the classloader, we would also need to embed the jar file
containing them. See the previous example for instructions.
$ cat >bootimage-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"
#if (defined __MINGW32__) || (defined _MSC_VER)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __attribute__ ((visibility("default")))
#endif
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define BOOTIMAGE_BIN(x) binary_bootimage_bin_##x
# define CODEIMAGE_BIN(x) binary_codeimage_bin_##x
#else
# define BOOTIMAGE_BIN(x) _binary_bootimage_bin_##x
# define CODEIMAGE_BIN(x) _binary_codeimage_bin_##x
#endif
extern "C" {
extern const uint8_t BOOTIMAGE_BIN(start)[];
extern const uint8_t BOOTIMAGE_BIN(end)[];
EXPORT const uint8_t*
bootimageBin(unsigned* size)
{
*size = BOOTIMAGE_BIN(end) - BOOTIMAGE_BIN(start);
return BOOTIMAGE_BIN(start);
}
extern const uint8_t CODEIMAGE_BIN(start)[];
extern const uint8_t CODEIMAGE_BIN(end)[];
EXPORT const uint8_t*
codeimageBin(unsigned* size)
{
*size = CODEIMAGE_BIN(end) - CODEIMAGE_BIN(start);
return CODEIMAGE_BIN(start);
}
} // extern "C"
int
main(int ac, const char** av)
{
JavaVMInitArgs vmArgs;
vmArgs.version = JNI_VERSION_1_2;
vmArgs.nOptions = 2;
vmArgs.ignoreUnrecognized = JNI_TRUE;
JavaVMOption options[vmArgs.nOptions];
vmArgs.options = options;
options[0].optionString
= const_cast<char*>("-Davian.bootimage=bootimageBin");
options[1].optionString
= const_cast<char*>("-Davian.codeimage=codeimageBin");
JavaVM* vm;
void* env;
JNI_CreateJavaVM(&vm, &env, &vmArgs);
JNIEnv* e = static_cast<JNIEnv*>(env);
jclass c = e->FindClass("Hello");
if (not e->ExceptionCheck()) {
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
if (not e->ExceptionCheck()) {
jclass stringClass = e->FindClass("java/lang/String");
if (not e->ExceptionCheck()) {
jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
if (not e->ExceptionCheck()) {
for (int i = 1; i < ac; ++i) {
e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
}
e->CallStaticVoidMethod(c, m, a);
}
}
}
}
int exitCode = 0;
if (e->ExceptionCheck()) {
exitCode = -1;
e->ExceptionDescribe();
}
vm->DestroyJavaVM();
return exitCode;
}
EOF
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
-D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o
Step 8: Link the objects produced above to produce the final
executable, and optionally strip its symbols.
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello
Trademarks
----------
Oracle and Java are registered trademarks of Oracle and/or its
affiliates. Other names may be trademarks of their respective owners.
The Avian project is not affiliated with Oracle.

6
src/android/stubs.cpp Normal file
View File

@ -0,0 +1,6 @@
struct JavaVM;
extern "C" int JNI_OnLoad(JavaVM*, void*)
{
return 0;
}

View File

@ -9,7 +9,7 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include "types.h"
#include "avian/types.h"
.text
@ -56,16 +56,25 @@ LOCAL(loop):
// setup argument registers if necessary
tst r6, r6
#if (defined __APPLE__) && (defined __clang_major__) && (__clang_major__ >= 4)
ldmiane r6, {r0-r3}
#else
ldmneia r6, {r0-r3}
#if defined(__VFP_FP__) && (! defined(__SOFTFP__)) && (! defined(__QNX__))
#endif
#if defined(__ARM_PCS_VFP)
// and VFP registers
vldmia r7, {d0-d7}
#endif
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
mov lr, pc
bx r4
#else
blx r4 // call function
#endif
add sp, sp, r5 // deallocate stack
#if defined(__VFP_FP__) && (! defined(__SOFTFP__)) && (! defined(__QNX__))
#if defined(__ARM_PCS_VFP)
cmp r8,#FLOAT_TYPE
bne LOCAL(double)
fmrs r0,s0
@ -108,7 +117,12 @@ GLOBAL(vmRun):
mov r12, r0
ldr r0, [r2, #CHECKPOINT_THREAD]
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
mov lr, pc
bx r12
#else
blx r12
#endif
.globl GLOBAL(vmRun_returnAddress)
.align 2

File diff suppressed because it is too large Load Diff

89
src/arm.masm Normal file
View File

@ -0,0 +1,89 @@
; 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.
;
; ORIGIN: https://github.com/gkvas/avian/tree/wince
AREA text, CODE, ARM
EXPORT vmNativeCall
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
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
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
vmRun_returnAddress
add sp, sp, #12
ldmfd sp!, {r4-r11, lr}
bx lr
EXPORT vmTrap
vmTrap
bkpt 3
END

View File

@ -1,478 +0,0 @@
/* Copyright (c) 2008-2012, 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 ASSEMBLER_H
#define ASSEMBLER_H
#include "system.h"
#include "zone.h"
namespace vm {
#ifdef AVIAN_TAILS
const bool TailCalls = true;
#else
const bool TailCalls = false;
#endif
#if (defined AVIAN_USE_FRAME_POINTER) || (defined ARCH_powerpc)
const bool UseFramePointer = true;
#else
const bool UseFramePointer = false;
#endif
enum Operation {
Return,
LoadBarrier,
StoreStoreBarrier,
StoreLoadBarrier,
Trap
};
const unsigned OperationCount = Trap + 1;
enum UnaryOperation {
Call,
LongCall,
AlignedLongCall,
AlignedCall,
Jump,
LongJump,
AlignedLongJump,
AlignedJump,
NoUnaryOperation = -1
};
const unsigned UnaryOperationCount = AlignedJump + 1;
enum BinaryOperation {
Move,
MoveLow,
MoveHigh,
MoveZ,
Negate,
FloatNegate,
Float2Float,
Float2Int,
Int2Float,
FloatSquareRoot,
FloatAbsolute,
Absolute,
NoBinaryOperation = -1
};
const unsigned BinaryOperationCount = Absolute + 1;
enum TernaryOperation {
Add,
Subtract,
Multiply,
Divide,
Remainder,
ShiftLeft,
ShiftRight,
UnsignedShiftRight,
And,
Or,
Xor,
FloatAdd,
FloatSubtract,
FloatMultiply,
FloatDivide,
FloatRemainder,
FloatMax,
FloatMin,
JumpIfLess,
JumpIfGreater,
JumpIfLessOrEqual,
JumpIfGreaterOrEqual,
JumpIfEqual,
JumpIfNotEqual,
JumpIfFloatEqual,
JumpIfFloatNotEqual,
JumpIfFloatLess,
JumpIfFloatGreater,
JumpIfFloatLessOrEqual,
JumpIfFloatGreaterOrEqual,
JumpIfFloatLessOrUnordered,
JumpIfFloatGreaterOrUnordered,
JumpIfFloatLessOrEqualOrUnordered,
JumpIfFloatGreaterOrEqualOrUnordered,
NoTernaryOperation = -1
};
const unsigned TernaryOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
const unsigned BranchOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin;
enum OperandType {
ConstantOperand,
AddressOperand,
RegisterOperand,
MemoryOperand
};
enum ValueType {
ValueGeneral,
ValueFloat
};
const unsigned OperandTypeCount = MemoryOperand + 1;
const int NoRegister = -1;
class Promise {
public:
class Listener {
public:
virtual bool resolve(int64_t value, void** location) = 0;
Listener* next;
};
virtual int64_t value() = 0;
virtual bool resolved() = 0;
virtual Listener* listen(unsigned) { return 0; }
};
class ResolvedPromise: public Promise {
public:
ResolvedPromise(int64_t value): value_(value) { }
virtual int64_t value() {
return value_;
}
virtual bool resolved() {
return true;
}
int64_t value_;
};
class ShiftMaskPromise: public Promise {
public:
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
base(base), shift(shift), mask(mask)
{ }
virtual int64_t value() {
return (base->value() >> shift) & mask;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
unsigned shift;
int64_t mask;
};
class CombinedPromise: public Promise {
public:
CombinedPromise(Promise* low, Promise* high):
low(low), high(high)
{ }
virtual int64_t value() {
return low->value() | (high->value() << 32);
}
virtual bool resolved() {
return low->resolved() and high->resolved();
}
Promise* low;
Promise* high;
};
class OffsetPromise: public Promise {
public:
OffsetPromise(Promise* base, int64_t offset):
base(base), offset(offset)
{ }
virtual int64_t value() {
return base->value() + offset;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
int64_t offset;
};
class ListenPromise: public Promise {
public:
ListenPromise(System* s, Allocator* allocator):
s(s), allocator(allocator), listener(0)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
System* s;
Allocator* allocator;
Listener* listener;
Promise* promise;
};
class DelayedPromise: public ListenPromise {
public:
DelayedPromise(System* s, Allocator* allocator, Promise* basis,
DelayedPromise* next):
ListenPromise(s, allocator), basis(basis), next(next)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
Promise* basis;
DelayedPromise* next;
};
class Assembler {
public:
class Operand { };
class Constant: public Operand {
public:
Constant(Promise* value): value(value) { }
Promise* value;
};
class Address: public Operand {
public:
Address(Promise* address): address(address) { }
Promise* address;
};
class Register: public Operand {
public:
Register(int low, int high = NoRegister): low(low), high(high) { }
int low;
int high;
};
class Memory: public Operand {
public:
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
base(base), offset(offset), index(index), scale(scale)
{ }
int base;
int offset;
int index;
unsigned scale;
};
class Client {
public:
virtual int acquireTemporary
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
virtual void releaseTemporary(int r) = 0;
virtual void save(int r) = 0;
};
class Block {
public:
virtual unsigned resolve(unsigned start, Block* next) = 0;
};
class Architecture {
public:
virtual unsigned floatRegisterSize() = 0;
virtual uint32_t generalRegisterMask() = 0;
virtual uint32_t floatRegisterMask() = 0;
virtual int scratch() = 0;
virtual int stack() = 0;
virtual int thread() = 0;
virtual int returnLow() = 0;
virtual int returnHigh() = 0;
virtual int virtualCallTarget() = 0;
virtual int virtualCallIndex() = 0;
virtual bool bigEndian() = 0;
virtual uintptr_t maximumImmediateJump() = 0;
virtual bool alwaysCondensed(BinaryOperation op) = 0;
virtual bool alwaysCondensed(TernaryOperation op) = 0;
virtual bool reserved(int register_) = 0;
virtual unsigned frameFootprint(unsigned footprint) = 0;
virtual unsigned argumentFootprint(unsigned footprint) = 0;
virtual bool argumentAlignment() = 0;
virtual bool argumentRegisterAlignment() = 0;
virtual unsigned argumentRegisterCount() = 0;
virtual int argumentRegister(unsigned index) = 0;
virtual bool hasLinkRegister() = 0;
virtual unsigned stackAlignmentInWords() = 0;
virtual bool matchCall(void* returnAddress, void* target) = 0;
virtual void updateCall(UnaryOperation op, void* returnAddress,
void* newTarget) = 0;
virtual void setConstant(void* dst, uint64_t constant) = 0;
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
void* link, bool mostRecent,
unsigned targetParameterFootprint, void** ip,
void** stack) = 0;
virtual void* frameIp(void* stack) = 0;
virtual unsigned frameHeaderSize() = 0;
virtual unsigned frameReturnAddressSize() = 0;
virtual unsigned frameFooterSize() = 0;
virtual int returnAddressOffset() = 0;
virtual int framePointerOffset() = 0;
virtual void plan
(UnaryOperation op,
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
bool* thunk) = 0;
virtual void planSource
(BinaryOperation op,
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
unsigned bSize, bool* thunk) = 0;
virtual void planDestination
(BinaryOperation op,
unsigned aSize, uint8_t aTypeMask, uint64_t aRegisterMask,
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask) = 0;
virtual void planMove
(unsigned size, uint8_t* srcTypeMask, uint64_t* srcRegisterMask,
uint8_t* tmpTypeMask, uint64_t* tmpRegisterMask,
uint8_t dstTypeMask, uint64_t dstRegisterMask) = 0;
virtual void planSource
(TernaryOperation op,
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
unsigned cSize, bool* thunk) = 0;
virtual void planDestination
(TernaryOperation op,
unsigned aSize, uint8_t aTypeMask, uint64_t aRegisterMask,
unsigned bSize, uint8_t bTypeMask, uint64_t bRegisterMask,
unsigned cSize, uint8_t* cTypeMask, uint64_t* cRegisterMask) = 0;
virtual void acquire() = 0;
virtual void release() = 0;
};
virtual void setClient(Client* client) = 0;
virtual Architecture* arch() = 0;
virtual void checkStackOverflow(uintptr_t handler,
unsigned stackLimitOffsetFromThread) = 0;
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) = 0;
virtual void pushFrame(unsigned argumentCount, ...) = 0;
virtual void allocateFrame(unsigned footprint) = 0;
virtual void adjustFrame(unsigned difference) = 0;
virtual void popFrame(unsigned footprint) = 0;
virtual void popFrameForTailCall(unsigned footprint, int offset,
int returnAddressSurrogate,
int framePointerSurrogate) = 0;
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
unsigned argumentFootprint)
= 0;
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
unsigned stackOffsetFromThread)
= 0;
virtual void apply(Operation op) = 0;
virtual void apply(UnaryOperation op,
unsigned aSize, OperandType aType, Operand* aOperand) = 0;
virtual void apply(BinaryOperation op,
unsigned aSize, OperandType aType, Operand* aOperand,
unsigned bSize, OperandType bType, Operand* bOperand) = 0;
virtual void apply(TernaryOperation op,
unsigned aSize, OperandType aType, Operand* aOperand,
unsigned bSize, OperandType bType, Operand* bOperand,
unsigned cSize, OperandType cType, Operand* cOperand) = 0;
virtual void setDestination(uint8_t* dst) = 0;
virtual void write() = 0;
virtual Promise* offset(bool forTrace = false) = 0;
virtual Block* endBlock(bool startNew) = 0;
virtual void endEvent() = 0;
virtual unsigned length() = 0;
virtual unsigned footerSize() = 0;
virtual void dispose() = 0;
};
Assembler::Architecture*
makeArchitecture(System* system, bool useNativeFeatures);
Assembler*
makeAssembler(System* system, Allocator* allocator, Zone* zone,
Assembler::Architecture* architecture);
} // namespace vm
#endif//ASSEMBLER_H

View File

@ -11,8 +11,13 @@
#ifndef VECTOR_H
#define VECTOR_H
#include "system.h"
#include "target.h"
#include <avian/vm/system/system.h>
#include "avian/target.h"
#include <avian/util/math.h>
#undef max
#undef min
namespace vm {
@ -51,8 +56,8 @@ class Vector {
if (position + space > capacity) {
assert(s, minimumCapacity >= 0);
unsigned newCapacity = max
(position + space, max(minimumCapacity, capacity * 2));
unsigned newCapacity = avian::util::max
(position + space, avian::util::max(minimumCapacity, capacity * 2));
uint8_t* newData = static_cast<uint8_t*>
(allocator->allocate(newCapacity));
if (data) {

View File

@ -11,7 +11,7 @@
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include "common.h"
#include "avian/common.h"
namespace vm {

View File

@ -19,7 +19,7 @@
# undef interface
#endif
#include "common.h"
#include "avian/common.h"
extern "C" void NO_RETURN
vmJump(void* address, void* frame, void* stack, void* thread,

View File

@ -11,8 +11,9 @@
#ifndef ARM_H
#define ARM_H
#include "types.h"
#include "common.h"
#include "avian/types.h"
#include "avian/common.h"
#include <avian/util/runtime-array.h>
#ifdef __APPLE__
# include "libkern/OSAtomic.h"
@ -71,33 +72,57 @@ 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_AOT_ONLY)
#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__)));
#endif
inline void
syncInstructionCache(const void* start, unsigned size)
{
@ -112,6 +137,8 @@ syncInstructionCache(const void* start, unsigned size)
#endif
}
#endif // AVIAN_AOT_ONLY
#ifndef __APPLE__
typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
# define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
@ -156,14 +183,14 @@ 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
RUNTIME_ARRAY(uintptr_t, stack, (argumentCount * 8) / BytesPerWord); // is > argumentSize to account for padding
unsigned stackIndex = 0;
unsigned ai = 0;
for (unsigned ati = 0; ati < argumentCount; ++ ati) {
switch (argumentTypes[ati]) {
case DOUBLE_TYPE:
#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) && !defined(__QNX__)
#if defined(__ARM_PCS_VFP)
{
if (vfpIndex + Alignment <= VfpCount) {
if (vfpIndex % Alignment) {
@ -179,7 +206,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
++ stackIndex;
}
memcpy(stack + stackIndex, arguments + ai, 8);
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
stackIndex += 8 / BytesPerWord;
}
ai += 8 / BytesPerWord;
@ -192,7 +219,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
} else if (vfpIndex < VfpCount) {
vfpTable[vfpIndex++] = arguments[ai];
} else {
stack[stackIndex++] = arguments[ai];
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
}
++ ai;
break;
@ -204,7 +231,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
and gprIndex + Alignment == GprCount)
{
gprTable[gprIndex++] = arguments[ai];
stack[stackIndex++] = arguments[ai + 1];
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1];
} else {
if (gprIndex % Alignment) {
++gprIndex;
@ -219,7 +246,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
++stackIndex;
}
memcpy(stack + stackIndex, arguments + ai, 8);
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
stackIndex += 8 / BytesPerWord;
}
ai += 8 / BytesPerWord;
@ -229,7 +256,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
if (gprIndex < GprCount) {
gprTable[gprIndex++] = arguments[ai];
} else {
stack[stackIndex++] = arguments[ai];
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
}
++ ai;
} break;
@ -247,7 +274,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2);
return vmNativeCall
(function, stackSize, stack, stackIndex * BytesPerWord,
(function, stackSize, RUNTIME_ARRAY_BODY(stack), stackIndex * BytesPerWord,
(gprIndex ? gprTable : 0),
(vfpIndex ? vfpTable : 0), returnType);
}

View File

@ -11,9 +11,12 @@
#ifndef BOOTIMAGE_H
#define BOOTIMAGE_H
#include "common.h"
#include "target.h"
#include "machine.h"
#include "avian/common.h"
#include "java-common.h"
#include "avian/target.h"
#include "avian/machine.h"
#include <avian/util/math.h>
namespace vm {

View File

@ -0,0 +1,677 @@
/* Copyright (c) 2010-2012, 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 CLASSPATH_COMMON_H
#define CLASSPATH_COMMON_H
#include <avian/util/string.h>
#include <avian/util/runtime-array.h>
using namespace avian::util;
namespace vm {
object
getTrace(Thread* t, unsigned skipCount)
{
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t, int skipCount):
t(t), trace(0), skipCount(skipCount)
{ }
virtual bool visit(Processor::StackWalker* walker) {
if (skipCount == 0) {
object method = walker->method();
if (isAssignableFrom
(t, type(t, Machine::ThrowableType), methodClass(t, method))
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0))
== 0)
{
return true;
} else {
trace = makeTrace(t, walker);
return false;
}
} else {
-- skipCount;
return true;
}
}
Thread* t;
object trace;
unsigned skipCount;
} v(t, skipCount);
t->m->processor->walkStack(t, &v);
if (v.trace == 0) v.trace = makeObjectArray(t, 0);
return v.trace;
}
bool
compatibleArrayTypes(Thread* t, object a, object b)
{
return classArrayElementSize(t, a)
and classArrayElementSize(t, b)
and (a == b
or (not ((classVmFlags(t, a) & PrimitiveFlag)
or (classVmFlags(t, b) & PrimitiveFlag))));
}
void
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
int32_t dstOffset, int32_t length)
{
if (LIKELY(src and dst)) {
if (LIKELY(compatibleArrayTypes
(t, objectClass(t, src), objectClass(t, dst))))
{
unsigned elementSize = classArrayElementSize(t, objectClass(t, src));
if (LIKELY(elementSize)) {
intptr_t sl = fieldAtOffset<uintptr_t>(src, BytesPerWord);
intptr_t dl = fieldAtOffset<uintptr_t>(dst, BytesPerWord);
if (LIKELY(length > 0)) {
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
dstOffset >= 0 and dstOffset + length <= dl))
{
uint8_t* sbody = &fieldAtOffset<uint8_t>(src, ArrayBody);
uint8_t* dbody = &fieldAtOffset<uint8_t>(dst, ArrayBody);
if (src == dst) {
memmove(dbody + (dstOffset * elementSize),
sbody + (srcOffset * elementSize),
length * elementSize);
} else {
memcpy(dbody + (dstOffset * elementSize),
sbody + (srcOffset * elementSize),
length * elementSize);
}
if (classObjectMask(t, objectClass(t, dst))) {
mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length);
}
return;
} else {
throwNew(t, Machine::IndexOutOfBoundsExceptionType);
}
} else {
return;
}
}
}
} else {
throwNew(t, Machine::NullPointerExceptionType);
return;
}
throwNew(t, Machine::ArrayStoreExceptionType);
}
void
runOnLoadIfFound(Thread* t, System::Library* library)
{
void* p = library->resolve("JNI_OnLoad");
#ifdef PLATFORM_WINDOWS
if (p == 0) {
p = library->resolve("_JNI_OnLoad@8");
if (p == 0) {
p = library->resolve("JNI_OnLoad@8");
}
}
#endif
if (p) {
jint (JNICALL * JNI_OnLoad)(Machine*, void*);
memcpy(&JNI_OnLoad, &p, sizeof(void*));
JNI_OnLoad(t->m, 0);
}
}
System::Library*
loadLibrary(Thread* t, const char* name)
{
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 (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, bool throw_ = true)
{
ACQUIRE(t, t->m->classLock);
char* mappedName;
unsigned nameLength = strlen(name);
if (mapName) {
const char* builtins = findProperty(t, "avian.builtins");
if (builtins) {
const char* s = builtins;
while (*s) {
if (::strncmp(s, name, nameLength) == 0
and (s[nameLength] == ',' or s[nameLength] == 0))
{
// library is built in to this executable
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
t->m->triedBuiltinOnLoad = true;
// todo: release the classLock before calling this to
// avoid the possibility of deadlock:
runOnLoadIfFound(t, t->m->libraries);
}
return t->m->libraries;
} else {
while (*s and *s != ',') ++ s;
if (*s) ++ s;
}
}
}
const char* prefix = t->m->system->libraryPrefix();
const char* suffix = t->m->system->librarySuffix();
unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix);
mappedName = static_cast<char*>
(t->m->heap->allocate(mappedNameLength + 1));
snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix);
name = mappedName;
nameLength = mappedNameLength;
} else {
mappedName = 0;
}
THREAD_RESOURCE2
(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
t->m->heap->free(mappedName, nameLength + 1);
});
System::Library* lib = 0;
for (Tokenizer tokenizer(path, t->m->system->pathSeparator());
tokenizer.hasMore();)
{
String token(tokenizer.next());
unsigned fullNameLength = token.length + 1 + nameLength;
THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1);
snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1,
"%.*s/%s", token.length, token.text, name);
lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName));
if (lib) break;
}
if (lib == 0) {
lib = loadLibrary(t, name);
}
if (lib) {
if (runOnLoad) {
runOnLoadIfFound(t, lib);
}
} else if (throw_) {
throwNew(t, Machine::UnsatisfiedLinkErrorType, "library not found: %s",
name);
}
return lib;
}
object
clone(Thread* t, object o)
{
PROTECT(t, o);
object class_ = objectClass(t, o);
unsigned size = baseSize(t, o, class_) * BytesPerWord;
object clone;
if (classArrayElementSize(t, class_)) {
clone = static_cast<object>(allocate(t, size, classObjectMask(t, class_)));
memcpy(clone, o, size);
// clear any object header flags:
setObjectClass(t, o, objectClass(t, o));
} else if (instanceOf(t, type(t, Machine::CloneableType), o)) {
clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(o) + 1,
size - BytesPerWord);
} else {
throwNew(t, Machine::CloneNotSupportedExceptionType, "%s",
&byteArrayBody(t, className(t, objectClass(t, o)), 0));
}
return clone;
}
object
makeStackTraceElement(Thread* t, object e)
{
PROTECT(t, e);
object class_ = className(t, methodClass(t, traceElementMethod(t, e)));
PROTECT(t, class_);
THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, class_));
replace('/', '.', RUNTIME_ARRAY_BODY(s),
reinterpret_cast<char*>(&byteArrayBody(t, class_, 0)));
class_ = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
object method = methodName(t, traceElementMethod(t, e));
PROTECT(t, method);
method = t->m->classpath->makeString
(t, method, 0, byteArrayLength(t, method) - 1);
unsigned line = t->m->processor->lineNumber
(t, traceElementMethod(t, e), traceElementIp(t, e));
object file = classSourceFile(t, methodClass(t, traceElementMethod(t, e)));
file = file ? t->m->classpath->makeString
(t, file, 0, byteArrayLength(t, file) - 1) : 0;
return makeStackTraceElement(t, class_, method, file, line);
}
object
translateInvokeResult(Thread* t, unsigned returnCode, object o)
{
switch (returnCode) {
case ByteField:
return makeByte(t, intValue(t, o));
case BooleanField:
return makeBoolean(t, intValue(t, o) != 0);
case CharField:
return makeChar(t, intValue(t, o));
case ShortField:
return makeShort(t, intValue(t, o));
case FloatField:
return makeFloat(t, intValue(t, o));
case IntField:
case LongField:
case ObjectField:
case VoidField:
return o;
case DoubleField:
return makeDouble(t, longValue(t, o));
default:
abort(t);
}
}
object
resolveClassBySpec(Thread* t, object loader, const char* spec,
unsigned specLength)
{
switch (*spec) {
case 'L': {
THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1);
memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2);
RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0;
return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s));
}
case '[': {
THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1);
memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength);
RUNTIME_ARRAY_BODY(s)[specLength] = 0;
return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s));
}
default:
return primitiveClass(t, *spec);
}
}
object
resolveJType(Thread* t, object loader, const char* spec, unsigned specLength)
{
return getJClass(t, resolveClassBySpec(t, loader, spec, specLength));
}
object
resolveParameterTypes(Thread* t, object loader, object spec,
unsigned* parameterCount, unsigned* returnTypeSpec)
{
PROTECT(t, loader);
PROTECT(t, spec);
object list = 0;
PROTECT(t, list);
unsigned offset = 1;
unsigned count = 0;
while (byteArrayBody(t, spec, offset) != ')') {
switch (byteArrayBody(t, spec, offset)) {
case 'L': {
unsigned start = offset;
++ offset;
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
++ offset;
object type = resolveClassBySpec
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
offset - start);
list = makePair(t, type, list);
++ count;
} break;
case '[': {
unsigned start = offset;
while (byteArrayBody(t, spec, offset) == '[') ++ offset;
switch (byteArrayBody(t, spec, offset)) {
case 'L':
++ offset;
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
++ offset;
break;
default:
++ offset;
break;
}
object type = resolveClassBySpec
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
offset - start);
list = makePair(t, type, list);
++ count;
} break;
default:
list = makePair
(t, primitiveClass(t, byteArrayBody(t, spec, offset)), list);
++ offset;
++ count;
break;
}
}
*parameterCount = count;
*returnTypeSpec = offset + 1;
return list;
}
object
resolveParameterJTypes(Thread* t, object loader, object spec,
unsigned* parameterCount, unsigned* returnTypeSpec)
{
object list = resolveParameterTypes
(t, loader, spec, parameterCount, returnTypeSpec);
PROTECT(t, list);
object array = makeObjectArray
(t, type(t, Machine::JclassType), *parameterCount);
PROTECT(t, array);
for (int i = *parameterCount - 1; i >= 0; --i) {
object c = getJClass(t, pairFirst(t, list));
set(t, array, ArrayBody + (i * BytesPerWord), c);
list = pairSecond(t, list);
}
return array;
}
object
resolveExceptionJTypes(Thread* t, object loader, object addendum)
{
if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) {
return makeObjectArray(t, type(t, Machine::JclassType), 0);
}
PROTECT(t, loader);
PROTECT(t, addendum);
object array = makeObjectArray
(t, type(t, Machine::JclassType),
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
PROTECT(t, array);
for (unsigned i = 0; i < shortArrayLength
(t, methodAddendumExceptionTable(t, addendum)); ++i)
{
uint16_t index = shortArrayBody
(t, methodAddendumExceptionTable(t, addendum), i) - 1;
object o = singletonObject(t, addendumPool(t, addendum), index);
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
o = resolveClass(t, loader, referenceName(t, o));
set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord),
o);
}
o = getJClass(t, o);
set(t, array, ArrayBody + (i * BytesPerWord), o);
}
return array;
}
object
invoke(Thread* t, object method, object instance, object args)
{
PROTECT(t, method);
PROTECT(t, instance);
PROTECT(t, args);
if (methodFlags(t, method) & ACC_STATIC) {
instance = 0;
}
if ((args == 0 ? 0 : objectArrayLength(t, args))
!= methodParameterCount(t, method))
{
throwNew(t, Machine::IllegalArgumentExceptionType);
}
if (methodParameterCount(t, method)) {
PROTECT(t, method);
unsigned specLength = byteArrayLength(t, methodSpec(t, method));
THREAD_RUNTIME_ARRAY(t, char, spec, specLength);
memcpy(RUNTIME_ARRAY_BODY(spec),
&byteArrayBody(t, methodSpec(t, method), 0), specLength);
unsigned i = 0;
for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) {
object type;
bool objectType = false;
const char* p = it.next();
switch (*p) {
case 'Z': type = vm::type(t, Machine::BooleanType); break;
case 'B': type = vm::type(t, Machine::ByteType); break;
case 'S': type = vm::type(t, Machine::ShortType); break;
case 'C': type = vm::type(t, Machine::CharType); break;
case 'I': type = vm::type(t, Machine::IntType); break;
case 'F': type = vm::type(t, Machine::FloatType); break;
case 'J': type = vm::type(t, Machine::LongType); break;
case 'D': type = vm::type(t, Machine::DoubleType); break;
case 'L':
case '[': {
objectType = true;
unsigned nameLength;
if (*p == 'L') {
++ p;
nameLength = it.s - p;
} else {
nameLength = (it.s - p) + 1;
}
THREAD_RUNTIME_ARRAY(t, char, name, nameLength);
memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1);
RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0;
type = resolveClass
(t, classLoader(t, methodClass(t, method)),
RUNTIME_ARRAY_BODY(name));
} break;
default:
abort();
}
object arg = objectArrayBody(t, args, i++);
if ((arg == 0 and (not objectType))
or (arg and (not instanceOf(t, type, arg))))
{
// fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast<const int8_t*>("<null>"), &byteArrayBody(t, className(t, type), 0));
throwNew(t, Machine::IllegalArgumentExceptionType);
}
}
}
unsigned returnCode = methodReturnCode(t, method);
THREAD_RESOURCE0(t, {
if (t->exception) {
object exception = t->exception;
t->exception = makeThrowable
(t, Machine::InvocationTargetExceptionType, 0, 0, exception);
set(t, t->exception, InvocationTargetExceptionTarget,
throwableCause(t, t->exception));
}
});
object result;
if (args) {
result = t->m->processor->invokeArray(t, method, instance, args);
} else {
result = t->m->processor->invoke(t, method, instance);
}
return translateInvokeResult(t, returnCode, result);
}
// only safe to call during bootstrap when there's only one thread
// running:
void
intercept(Thread* t, object c, const char* name, const char* spec,
void* function, bool updateRuntimeData)
{
object m = findMethodOrNull(t, c, name, spec);
if (m) {
PROTECT(t, m);
object clone;
if (updateRuntimeData) {
clone = methodClone(t, m);
// make clone private to prevent vtable updates at compilation
// time. Otherwise, our interception might be bypassed by calls
// through the vtable.
methodFlags(t, clone) |= ACC_PRIVATE;
}
methodFlags(t, m) |= ACC_NATIVE;
if (updateRuntimeData) {
object native = makeNativeIntercept(t, function, true, clone);
PROTECT(t, native);
object runtimeData = getMethodRuntimeData(t, m);
set(t, runtimeData, MethodRuntimeDataNative, native);
}
} else {
// If we can't find the method, just ignore it, since ProGuard may
// have stripped it out as unused. Otherwise, the code below can
// be uncommented for debugging purposes.
// fprintf(stderr, "unable to find %s%s in %s\n",
// name, spec, &byteArrayBody(t, className(t, c), 0));
// abort(t);
}
}
Finder*
getFinder(Thread* t, const char* name, unsigned nameLength)
{
ACQUIRE(t, t->m->referenceLock);
for (object p = root(t, Machine::VirtualFileFinders);
p; p = finderNext(t, p))
{
if (byteArrayLength(t, finderName(t, p)) == nameLength
and strncmp(reinterpret_cast<const char*>
(&byteArrayBody(t, finderName(t, p), 0)),
name, nameLength))
{
return static_cast<Finder*>(finderFinder(t, p));
}
}
object n = makeByteArray(t, nameLength + 1);
memcpy(&byteArrayBody(t, n, 0), name, nameLength);
void* p = t->m->libraries->resolve
(reinterpret_cast<const char*>(&byteArrayBody(t, n, 0)));
if (p) {
uint8_t* (*function)(unsigned*);
memcpy(&function, &p, BytesPerWord);
unsigned size;
uint8_t* data = function(&size);
if (data) {
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
object finder = makeFinder
(t, f, n, root(t, Machine::VirtualFileFinders));
setRoot(t, Machine::VirtualFileFinders, finder);
return f;
}
}
return 0;
}
} // namespace vm
#endif//CLASSPATH_COMMON_H

View File

@ -8,8 +8,8 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef COMMON_H
#define COMMON_H
#ifndef AVIAN_COMMON_H
#define AVIAN_COMMON_H
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
@ -20,25 +20,25 @@
#include "stddef.h"
#include "string.h"
#include "stdio.h"
#include "types.h"
#include "avian/types.h"
#include "math.h"
#ifdef _MSC_VER
#include "float.h"
#include <stdint.h>
#ifdef powerpc
# undef powerpc
#endif
#ifdef linux
# undef linux
#endif
// don't complain about using 'this' in member initializers:
# pragma warning(disable:4355)
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define strncasecmp _strnicmp
#define FP_NAN 0
@ -58,11 +58,6 @@ inline int fpclassify(double d) {
return FP_UNDEF;
}
#define INT32_MIN ((int32_t) _I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t) _I64_MIN)
#define INT64_MAX _I64_MAX
inline int signbit(double d) {
return _copysign(1.0, d) < 0;
}
@ -86,15 +81,18 @@ inline int signbit(double d) {
# ifdef _M_IX86
typedef int32_t intptr_t;
typedef uint32_t uintptr_t;
# define UINT64_C(x) x##LL
# define ARCH_x86_32
# define BYTES_PER_WORD 4
# elif defined _M_X64
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 ARCH_arm
# define BYTES_PER_WORD 4
# else
# error "unsupported architecture"
# endif
@ -107,7 +105,7 @@ typedef intptr_t intptr_alias_t;
#else // not _MSC_VER
# include "stdint.h"
# include <stdint.h>
# define BYTES_PER_WORD __SIZEOF_POINTER__
@ -214,6 +212,9 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
type name; \
} MAKE_NAME(resource_)(name);
#ifdef _MSC_VER
# pragma warning( disable : 4291 )
#endif
inline void* operator new(size_t, void* p) throw() { return p; }
namespace vm {
@ -226,23 +227,6 @@ alias(void* p, unsigned offset)
#ifdef _MSC_VER
template <class T>
class RuntimeArray {
public:
RuntimeArray(unsigned size):
body(static_cast<T*>(malloc(size * sizeof(T))))
{ }
~RuntimeArray() {
free(body);
}
T* body;
};
# define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
# define RUNTIME_ARRAY_BODY(name) name.body
inline int
vsnprintf(char* dst, size_t size, const char* format, va_list a)
{
@ -272,9 +256,6 @@ fopen(const char* name, const char* mode)
#else // not _MSC_VER
# define RUNTIME_ARRAY(type, name, size) type name[size];
# define RUNTIME_ARRAY_BODY(name) name
inline int
vsnprintf(char* dst, size_t size, const char* format, va_list a)
{
@ -307,24 +288,6 @@ const uintptr_t PointerMask
const unsigned LikelyPageSizeInBytes = 4 * 1024;
inline unsigned
max(unsigned a, unsigned b)
{
return (a > b ? a : b);
}
inline unsigned
min(unsigned a, unsigned b)
{
return (a < b ? a : b);
}
inline unsigned
avg(unsigned a, unsigned b)
{
return (a + b) / 2;
}
inline unsigned
pad(unsigned n, unsigned alignment)
{
@ -349,35 +312,17 @@ padWord(uintptr_t n)
return padWord(n, BytesPerWord);
}
inline unsigned
ceiling(unsigned n, unsigned d)
{
return (n + d - 1) / d;
inline bool fitsInInt8(int64_t v) {
return v == static_cast<int8_t>(v);
}
inline bool
powerOfTwo(unsigned n)
{
for (; n > 2; n >>= 1) if (n & 1) return false;
return true;
inline bool fitsInInt16(int64_t v) {
return v == static_cast<int16_t>(v);
}
inline unsigned
nextPowerOfTwo(unsigned n)
{
unsigned r = 1;
while (r < n) r <<= 1;
return r;
inline bool fitsInInt32(int64_t v) {
return v == static_cast<int32_t>(v);
}
inline unsigned
log(unsigned n)
{
unsigned r = 0;
for (unsigned i = 1; i < n; ++r) i <<= 1;
return r;
}
template <class T>
inline unsigned
wordOf(unsigned i)
@ -476,14 +421,14 @@ getBits(T* map, unsigned bitsPerRecord, unsigned index)
template <class T>
inline T&
cast(void* p, unsigned offset)
fieldAtOffset(void* p, unsigned offset)
{
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
}
template <class T>
inline T*
mask(T* p)
maskAlignedPointer(T* p)
{
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
}
@ -524,6 +469,12 @@ hash(const uint16_t* s, unsigned length)
return h;
}
inline void
write4(uint8_t* dst, uint32_t v)
{
memcpy(dst, &v, 4);
}
inline uint32_t
floatToBits(float f)
{
@ -593,57 +544,6 @@ equal(const void* a, unsigned al, const void* b, unsigned bl)
}
}
class Machine;
class Thread;
struct Object { };
typedef Object* object;
typedef uint8_t jboolean;
typedef int8_t jbyte;
typedef uint16_t jchar;
typedef int16_t jshort;
typedef int32_t jint;
typedef int64_t jlong;
typedef float jfloat;
typedef double jdouble;
typedef jint jsize;
typedef object* jobject;
typedef jobject jclass;
typedef jobject jthrowable;
typedef jobject jstring;
typedef jobject jweak;
typedef jobject jarray;
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jarray jobjectArray;
typedef uintptr_t jfieldID;
typedef uintptr_t jmethodID;
union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
};
} // namespace vm
#endif//COMMON_H
#endif // AVIAN_COMMON_H

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2008, Avian Contributors
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
@ -8,16 +8,10 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef JNIENV_H
#define JNIENV_H
#ifndef EMBED_H
#define EMBED_H
#include "machine.h"
#define RESID_MAIN_CLASS 100
#define RESID_BOOT_JAR L"BOOT.JAR"
namespace vm {
void
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
} // namespace vm
#endif//JNIENV_H
#endif

View File

@ -11,9 +11,9 @@
#ifndef FINDER_H
#define FINDER_H
#include "common.h"
#include "system.h"
#include "allocator.h"
#include "avian/common.h"
#include <avian/vm/system/system.h>
#include "avian/allocator.h"
namespace vm {

View File

@ -11,7 +11,8 @@
#ifndef HEAPWALK_H
#define HEAPWALK_H
#include "common.h"
#include "avian/common.h"
#include "java-common.h"
namespace vm {

69
src/avian/java-common.h Normal file
View File

@ -0,0 +1,69 @@
/* Copyright (c) 2008-2012, 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 JAVA_COMMON_H
#define JAVA_COMMON_H
namespace vm {
class Machine;
class Thread;
struct Object { };
typedef Object* object;
typedef uint8_t jboolean;
typedef int8_t jbyte;
typedef uint16_t jchar;
typedef int16_t jshort;
typedef int32_t jint;
typedef int64_t jlong;
typedef float jfloat;
typedef double jdouble;
typedef jint jsize;
typedef object* jobject;
typedef jobject jclass;
typedef jobject jthrowable;
typedef jobject jstring;
typedef jobject jweak;
typedef jobject jarray;
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jarray jobjectArray;
typedef uintptr_t jfieldID;
typedef uintptr_t jmethodID;
union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
};
} // namespace vm
#endif // JAVA_COMMON_H

35
src/avian/jnienv.h Normal file
View File

@ -0,0 +1,35 @@
/* Copyright (c) 2008, 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 JNIENV_H
#define JNIENV_H
#include "avian/machine.h"
#define BOOTSTRAP_PROPERTY "avian.bootstrap"
#define JAVA_COMMAND_PROPERTY "sun.java.command"
#define JAVA_LAUNCHER_PROPERTY "sun.java.launcher"
#define CRASHDIR_PROPERTY "avian.crash.dir"
#define EMBED_PREFIX_PROPERTY "avian.embed.prefix"
#define CLASSPATH_PROPERTY "java.class.path"
#define JAVA_HOME_PROPERTY "java.home"
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
#define BOOTCLASSPATH_OPTION "bootclasspath"
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a"
namespace vm {
void
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
} // namespace vm
#endif//JNIENV_H

View File

@ -11,10 +11,10 @@
#ifndef LZMA_UTIL_H
#define LZMA_UTIL_H
#include "lzma.h"
#include "avian/lzma.h"
#include "C/Types.h"
#include "system.h"
#include "allocator.h"
#include <avian/vm/system/system.h>
#include "avian/allocator.h"
namespace vm {

View File

@ -11,8 +11,8 @@
#ifndef LZMA_H
#define LZMA_H
#include "system.h"
#include "allocator.h"
#include <avian/vm/system/system.h>
#include "avian/allocator.h"
namespace vm {

View File

@ -11,13 +11,16 @@
#ifndef MACHINE_H
#define MACHINE_H
#include "common.h"
#include "system.h"
#include "heap.h"
#include "finder.h"
#include "processor.h"
#include "constants.h"
#include "arch.h"
#include "avian/common.h"
#include "java-common.h"
#include <avian/vm/system/system.h>
#include <avian/vm/heap/heap.h>
#include "avian/finder.h"
#include "avian/processor.h"
#include "avian/constants.h"
#include "avian/arch.h"
using namespace avian::util;
#ifdef PLATFORM_WINDOWS
# define JNICALL __stdcall
@ -101,6 +104,8 @@ const bool DebugStack = false;
const bool DebugMonitors = false;
const bool DebugReferences = false;
const bool AbortOnOutOfMemoryError = false;
const uintptr_t HashTakenMark = 1;
const uintptr_t ExtendedMark = 2;
const uintptr_t FixedMark = 3;
@ -1206,6 +1211,7 @@ class Machine {
BootLoader,
AppLoader,
BootstrapClassMap,
PackageMap,
FindLoadedClassMethod,
LoadClassMethod,
MonitorMap,
@ -1226,10 +1232,12 @@ class Machine {
OutOfMemoryError,
Shutdown,
VirtualFileFinders,
VirtualFiles
VirtualFiles,
ArrayInterfaceTable,
ThreadTerminated
};
static const unsigned RootCount = VirtualFiles + 1;
static const unsigned RootCount = ThreadTerminated + 1;
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
Processor* processor, Classpath* classpath, const char** properties,
@ -1535,6 +1543,18 @@ class Classpath {
virtual object
makeThread(Thread* t, Thread* parent) = 0;
virtual object
makeJMethod(Thread* t, object vmMethod) = 0;
virtual object
getVMMethod(Thread* t, object jmethod) = 0;
virtual object
makeJField(Thread* t, object vmField) = 0;
virtual object
getVMField(Thread* t, object jfield) = 0;
virtual void
clearInterrupted(Thread* t) = 0;
@ -1544,12 +1564,37 @@ class Classpath {
virtual void
resolveNative(Thread* t, object method) = 0;
virtual void
interceptMethods(Thread* t) = 0;
virtual void
preBoot(Thread* t) = 0;
virtual void
boot(Thread* t) = 0;
virtual const char*
bootClasspath() = 0;
virtual void
updatePackageMap(Thread* t, object class_) = 0;
virtual object
makeDirectByteBuffer(Thread* t, void* p, jlong capacity) = 0;
virtual void*
getDirectBufferAddress(Thread* t, object buffer) = 0;
virtual int64_t
getDirectBufferCapacity(Thread* t, object buffer) = 0;
virtual bool
canTailCall(Thread* t, object caller, object calleeClassName,
object calleeMethodName, object calleeMethodSpec) = 0;
virtual void
shutDown(Thread* t) = 0;
virtual void
dispose() = 0;
};
@ -1582,7 +1627,8 @@ class ThreadRuntimeArray: public Thread::Resource {
#else // not _MSC_VER
# define THREAD_RUNTIME_ARRAY(thread, type, name, size) type name[size];
# define THREAD_RUNTIME_ARRAY(thread, type, name, size) \
type name##_body[size];
#endif // not _MSC_VER
@ -1595,7 +1641,7 @@ typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*);
inline object
objectClass(Thread*, object o)
{
return mask(cast<object>(o, 0));
return maskAlignedPointer(fieldAtOffset<object>(o, 0));
}
inline unsigned
@ -1656,7 +1702,7 @@ release(Thread* t, Reference* r)
}
void
collect(Thread* t, Heap::CollectionType type);
collect(Thread* t, Heap::CollectionType type, int pendingAllocation = 0);
void
shutDown(Thread* t);
@ -1742,24 +1788,8 @@ class RawMonitorResource: public Thread::Resource {
System::Monitor* m;
};
inline void NO_RETURN
abort(Thread* t)
{
abort(t->m->system);
}
#ifndef NDEBUG
inline void
assert(Thread* t, bool v)
{
assert(t->m->system, v);
}
#endif // not NDEBUG
inline void
expect(Thread* t, bool v)
{
expect(t->m->system, v);
inline Aborter* getAborter(Thread* t) {
return t->m->system;
}
class FixedAllocator: public Allocator {
@ -1768,8 +1798,8 @@ class FixedAllocator: public Allocator {
s(s), base(base), offset(0), capacity(capacity)
{ }
virtual void* tryAllocate(unsigned) {
abort(s);
virtual void* tryAllocate(unsigned size) {
return allocate(size);
}
void* allocate(unsigned size, unsigned padAlignment) {
@ -1802,7 +1832,7 @@ class FixedAllocator: public Allocator {
inline bool
ensure(Thread* t, unsigned sizeInBytes)
{
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
if (t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord)
> ThreadHeapSizeInWords)
{
if (sizeInBytes <= ThreadBackupHeapSizeInBytes) {
@ -1829,11 +1859,11 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
inline object
allocateSmall(Thread* t, unsigned sizeInBytes)
{
assert(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
assert(t, t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord)
<= ThreadHeapSizeInWords);
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
t->heapIndex += ceilingDivide(sizeInBytes, BytesPerWord);
return o;
}
@ -1842,7 +1872,7 @@ allocate(Thread* t, unsigned sizeInBytes, bool objectMask)
{
stress(t);
if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
if (UNLIKELY(t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord)
> ThreadHeapSizeInWords
or t->m->exclusive))
{
@ -1867,18 +1897,18 @@ mark(Thread* t, object o, unsigned offset)
inline void
set(Thread* t, object target, unsigned offset, object value)
{
cast<object>(target, offset) = value;
fieldAtOffset<object>(target, offset) = value;
mark(t, target, offset);
}
inline void
setObjectClass(Thread*, object o, object value)
{
cast<object>(o, 0)
fieldAtOffset<object>(o, 0)
= reinterpret_cast<object>
(reinterpret_cast<intptr_alias_t>(value)
| (reinterpret_cast<intptr_alias_t>
(cast<object>(o, 0)) & (~PointerMask)));
(fieldAtOffset<object>(o, 0)) & (~PointerMask)));
}
inline const char*
@ -1965,6 +1995,7 @@ addThread(Thread* t, Thread* p)
ACQUIRE_RAW(t, t->m->stateLock);
assert(t, p->state == Thread::NoState);
expect(t, t->state == Thread::ActiveState || t->state == Thread::ExclusiveState);
p->state = Thread::IdleState;
++ t->m->threadCount;
@ -2133,9 +2164,9 @@ baseSize(Thread* t, object o, object class_)
{
assert(t, classFixedSize(t, class_) >= BytesPerWord);
return ceiling(classFixedSize(t, class_), BytesPerWord)
+ ceiling(classArrayElementSize(t, class_)
* cast<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord),
return ceilingDivide(classFixedSize(t, class_), BytesPerWord)
+ ceilingDivide(classArrayElementSize(t, class_)
* fieldAtOffset<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord),
BytesPerWord);
}
@ -2274,7 +2305,7 @@ inline uintptr_t&
extendedWord(Thread* t UNUSED, object o, unsigned baseSize)
{
assert(t, objectExtended(t, o));
return cast<uintptr_t>(o, baseSize * BytesPerWord);
return fieldAtOffset<uintptr_t>(o, baseSize * BytesPerWord);
}
inline unsigned
@ -2509,6 +2540,9 @@ emptyMethod(Thread* t, object method)
object
parseUtf8(Thread* t, const char* data, unsigned length);
object
parseUtf8(Thread* t, object array);
object
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length,
Machine::Type throwType = Machine::NoClassDefFoundErrorType);
@ -2663,6 +2697,19 @@ makeThrowable(Thread* t, Machine::Type type, const char* format, ...)
void
popResources(Thread* t);
} // namespace vm
JNIEXPORT void
vmPrintTrace(vm::Thread* t);
JNIEXPORT void
vmfPrintTrace(vm::Thread* t, FILE* out);
namespace vm {
void
dumpHeap(Thread* t, FILE* out);
inline void NO_RETURN
throw_(Thread* t, object e)
{
@ -2673,6 +2720,28 @@ throw_(Thread* t, object e)
t->exception = e;
if (objectClass(t, e) == type(t, Machine::OutOfMemoryErrorType)) {
#ifdef AVIAN_HEAPDUMP
if (not t->m->dumpedHeapOnOOM) {
t->m->dumpedHeapOnOOM = true;
const char* path = findProperty(t, "avian.heap.dump");
if (path) {
FILE* out = vm::fopen(path, "wb");
if (out) {
dumpHeap(t, out);
fclose(out);
}
}
}
#endif//AVIAN_HEAPDUMP
if (AbortOnOutOfMemoryError) {
fprintf(stderr, "OutOfMemoryError\n");
vmPrintTrace(t);
abort();
}
}
// printTrace(t, e);
popResources(t);
@ -2773,7 +2842,7 @@ objectArrayLength(Thread* t UNUSED, object array)
{
assert(t, classFixedSize(t, objectClass(t, array)) == BytesPerWord * 2);
assert(t, classArrayElementSize(t, objectClass(t, array)) == BytesPerWord);
return cast<uintptr_t>(array, BytesPerWord);
return fieldAtOffset<uintptr_t>(array, BytesPerWord);
}
inline object&
@ -2784,7 +2853,7 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index)
assert(t, classObjectMask(t, objectClass(t, array))
== classObjectMask(t, arrayBody
(t, t->m->types, Machine::ArrayType)));
return cast<object>(array, ArrayBody + (index * BytesPerWord));
return fieldAtOffset<object>(array, ArrayBody + (index * BytesPerWord));
}
unsigned
@ -2820,7 +2889,7 @@ inline bool
atomicCompareAndSwapObject(Thread* t, object target, unsigned offset,
object old, object new_)
{
if (atomicCompareAndSwap(&cast<uintptr_t>(target, offset),
if (atomicCompareAndSwap(&fieldAtOffset<uintptr_t>(target, offset),
reinterpret_cast<uintptr_t>(old),
reinterpret_cast<uintptr_t>(new_)))
{
@ -3330,7 +3399,7 @@ inline unsigned
singletonMaskSize(unsigned count, unsigned bitsPerWord)
{
if (count) {
return ceiling(count + 2, bitsPerWord);
return ceilingDivide(count + 2, bitsPerWord);
}
return 0;
}
@ -3346,7 +3415,7 @@ singletonMaskSize(Thread* t, object singleton)
{
unsigned length = singletonLength(t, singleton);
if (length) {
return ceiling(length + 2, BitsPerWord + 1);
return ceilingDivide(length + 2, BitsPerWord + 1);
}
return 0;
}
@ -3429,7 +3498,7 @@ singletonBit(Thread* t, object singleton, unsigned start, unsigned index)
inline unsigned
poolMaskSize(unsigned count, unsigned bitsPerWord)
{
return ceiling(count, bitsPerWord);
return ceilingDivide(count, bitsPerWord);
}
inline unsigned
@ -3441,7 +3510,7 @@ poolMaskSize(unsigned count)
inline unsigned
poolMaskSize(Thread* t, object pool)
{
return ceiling(singletonCount(t, pool), BitsPerWord + 1);
return ceilingDivide(singletonCount(t, pool), BitsPerWord + 1);
}
inline unsigned
@ -3454,7 +3523,7 @@ inline object
resolveClassInObject(Thread* t, object loader, object container,
unsigned classOffset, bool throw_ = true)
{
object o = cast<object>(container, classOffset);
object o = fieldAtOffset<object>(container, classOffset);
loadMemoryBarrier();
@ -3801,14 +3870,11 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
unsigned index, unsigned dimensions);
object
getCaller(Thread* t, unsigned target);
getCaller(Thread* t, unsigned target, bool skipMethodInvoke = false);
object
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length);
void
dumpHeap(Thread* t, FILE* out);
inline object
methodClone(Thread* t, object method)
{
@ -3893,9 +3959,6 @@ errorLog(Thread* t)
} // namespace vm
JNIEXPORT void
vmPrintTrace(vm::Thread* t);
JNIEXPORT void*
vmAddressFromLine(vm::Thread* t, vm::object m, unsigned line);

View File

@ -11,8 +11,8 @@
#ifndef POWERPC_H
#define POWERPC_H
#include "types.h"
#include "common.h"
#include "avian/types.h"
#include "avian/common.h"
#ifdef __APPLE__
# include "mach/mach_types.h"

View File

@ -11,10 +11,10 @@
#ifndef PROCESS_H
#define PROCESS_H
#include "common.h"
#include "system.h"
#include "machine.h"
#include "constants.h"
#include "avian/common.h"
#include <avian/vm/system/system.h>
#include "avian/machine.h"
#include "avian/constants.h"
namespace vm {

View File

@ -11,13 +11,18 @@
#ifndef PROCESSOR_H
#define PROCESSOR_H
#include "common.h"
#include "system.h"
#include "heap.h"
#include "avian/common.h"
#include <avian/vm/system/system.h>
#include <avian/vm/heap/heap.h>
#include "bootimage.h"
#include "heapwalk.h"
#include "zone.h"
#include "assembler.h"
#include "avian/heapwalk.h"
#include "avian/zone.h"
namespace avian {
namespace codegen {
class DelayedPromise;
}
}
namespace vm {
@ -142,7 +147,7 @@ class Processor {
virtual void
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
DelayedPromise** addresses, object method,
avian::codegen::DelayedPromise** addresses, object method,
OffsetResolver* resolver) = 0;
virtual void

Some files were not shown because too many files have changed in this diff Show More