mirror of
https://github.com/corda/corda.git
synced 2025-02-09 12:21:22 +00:00
Merge branch 'master' of https://github.com/ReadyTalk/avian
This commit is contained in:
commit
bd2ebfce07
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ build
|
||||
bin
|
||||
/lib
|
||||
/distrib
|
||||
*.pdb
|
||||
|
2
.travis.yml
Normal file
2
.travis.yml
Normal file
@ -0,0 +1,2 @@
|
||||
language: cpp
|
||||
script: ./test/ci.sh
|
804
README.md
Normal file
804
README.md
Normal 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
75
android.pro
Normal 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
|
@ -14,4 +14,6 @@ public class ClassAddendum extends Addendum {
|
||||
public Object[] interfaceTable;
|
||||
public Object[] innerClassTable;
|
||||
public Object[] methodTable;
|
||||
public Object enclosingClass;
|
||||
public Object enclosingMethod;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
61
classpath/avian/Traces.java
Normal file
61
classpath/avian/Traces.java
Normal 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();
|
||||
}
|
||||
}
|
@ -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;
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
16
classpath/java/io/Closeable.java
Normal file
16
classpath/java/io/Closeable.java
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
16
classpath/java/io/Flushable.java
Normal file
16
classpath/java/io/Flushable.java
Normal 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;
|
||||
}
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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() { }
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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"),
|
||||
|
44
classpath/java/math/BigInteger.java
Normal file
44
classpath/java/math/BigInteger.java
Normal 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);
|
||||
}
|
||||
}
|
71
classpath/java/math/MathContext.java
Normal file
71
classpath/java/math/MathContext.java
Normal 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();
|
||||
}
|
||||
}
|
36
classpath/java/math/RoundingMode.java
Normal file
36
classpath/java/math/RoundingMode.java
Normal 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];
|
||||
}
|
||||
}
|
@ -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)) {
|
||||
|
57
classpath/java/net/URLClassLoader.java
Normal file
57
classpath/java/net/URLClassLoader.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
40
classpath/java/nio/ByteOrder.java
Normal file
40
classpath/java/nio/ByteOrder.java
Normal 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;
|
||||
}
|
||||
}
|
27
classpath/java/util/jar/Attributes.java
Normal file
27
classpath/java/util/jar/Attributes.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
47
include/avian/util/abort.h
Normal file
47
include/avian/util/abort.h
Normal 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
|
46
include/avian/util/arg-parser.h
Normal file
46
include/avian/util/arg-parser.h
Normal 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
56
include/avian/util/math.h
Normal 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
|
40
include/avian/util/runtime-array.h
Normal file
40
include/avian/util/runtime-array.h
Normal 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
|
@ -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
|
63
include/avian/util/string.h
Normal file
63
include/avian/util/string.h
Normal 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
|
137
include/avian/vm/codegen/architecture.h
Normal file
137
include/avian/vm/codegen/architecture.h
Normal 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
|
113
include/avian/vm/codegen/assembler.h
Normal file
113
include/avian/vm/codegen/assembler.h
Normal 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
|
@ -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
|
62
include/avian/vm/codegen/lir-ops.inc.cpp
Normal file
62
include/avian/vm/codegen/lir-ops.inc.cpp
Normal 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)
|
174
include/avian/vm/codegen/lir.h
Normal file
174
include/avian/vm/codegen/lir.h
Normal 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
|
159
include/avian/vm/codegen/promise.h
Normal file
159
include/avian/vm/codegen/promise.h
Normal 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
|
73
include/avian/vm/codegen/registers.h
Normal file
73
include/avian/vm/codegen/registers.h
Normal 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
|
32
include/avian/vm/codegen/targets.h
Normal file
32
include/avian/vm/codegen/targets.h
Normal 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
|
@ -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;
|
@ -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);
|
@ -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 += \
|
||||
|
65
openjdk.pro
65
openjdk.pro
@ -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;
|
||||
}
|
||||
|
727
readme.txt
727
readme.txt
@ -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
6
src/android/stubs.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
struct JavaVM;
|
||||
|
||||
extern "C" int JNI_OnLoad(JavaVM*, void*)
|
||||
{
|
||||
return 0;
|
||||
}
|
20
src/arm.S
20
src/arm.S
@ -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
|
||||
|
3013
src/arm.cpp
3013
src/arm.cpp
File diff suppressed because it is too large
Load Diff
89
src/arm.masm
Normal file
89
src/arm.masm
Normal 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
|
478
src/assembler.h
478
src/assembler.h
@ -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
|
@ -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) {
|
@ -11,7 +11,7 @@
|
||||
#ifndef ALLOCATOR_H
|
||||
#define ALLOCATOR_H
|
||||
|
||||
#include "common.h"
|
||||
#include "avian/common.h"
|
||||
|
||||
namespace vm {
|
||||
|
@ -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,
|
@ -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);
|
||||
}
|
@ -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 {
|
||||
|
677
src/avian/classpath-common.h
Normal file
677
src/avian/classpath-common.h
Normal 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
|
@ -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
|
@ -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
|
@ -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 {
|
||||
|
@ -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
69
src/avian/java-common.h
Normal 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
35
src/avian/jnienv.h
Normal 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
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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"
|
@ -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 {
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user