mirror of
https://github.com/corda/corda.git
synced 2025-02-10 21:01:27 +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
|
bin
|
||||||
/lib
|
/lib
|
||||||
/distrib
|
/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[] interfaceTable;
|
||||||
public Object[] innerClassTable;
|
public Object[] innerClassTable;
|
||||||
public Object[] methodTable;
|
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.Modifier;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -262,6 +264,159 @@ public class Classes {
|
|||||||
link(c, c.loader);
|
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 acquireClassLock();
|
||||||
|
|
||||||
private static native void releaseClassLock();
|
private static native void releaseClassLock();
|
||||||
|
@ -45,20 +45,4 @@ public class OpenJDK {
|
|||||||
}
|
}
|
||||||
return array;
|
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);
|
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)) {
|
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);
|
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)) {
|
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 Class getClass(VMClass vmClass);
|
||||||
|
|
||||||
|
public static native VMClass vmClass(Class jClass);
|
||||||
|
|
||||||
private native VMClass findLoadedVMClass(String name);
|
private native VMClass findLoadedVMClass(String name);
|
||||||
|
|
||||||
protected Class reallyFindLoadedClass(String name){
|
protected Class reallyFindLoadedClass(String name){
|
||||||
@ -35,6 +37,30 @@ public class SystemClassLoader extends ClassLoader {
|
|||||||
return c == null ? null : getClass(c);
|
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);
|
private native String resourceURLPrefix(String name);
|
||||||
|
|
||||||
protected URL findResource(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
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
package avian.avian_vm_resource;
|
package avian.avianvmresource;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLStreamHandler;
|
import java.net.URLStreamHandler;
|
@ -55,6 +55,15 @@
|
|||||||
|
|
||||||
typedef wchar_t char_t;
|
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
|
#else // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
@ -83,7 +92,19 @@ typedef char char_t;
|
|||||||
|
|
||||||
#endif // not PLATFORM_WINDOWS
|
#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; }
|
inline void* operator new(size_t, void* p) throw() { return p; }
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef const char_t* string_t;
|
typedef const char_t* string_t;
|
||||||
|
|
||||||
@ -155,69 +176,9 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#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 {
|
class Directory {
|
||||||
public:
|
public:
|
||||||
Directory(): handle(0), findNext(false) { }
|
Directory(): handle(0), findNext(false) { }
|
||||||
@ -250,51 +211,9 @@ class Directory {
|
|||||||
|
|
||||||
#else // not PLATFORM_WINDOWS
|
#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
|
#endif // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
inline string_t getChars(JNIEnv* e, jstring path) {
|
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)
|
Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
const unsigned BufferSize = MAX_PATH;
|
const unsigned BufferSize = MAX_PATH;
|
||||||
@ -330,6 +250,19 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 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
|
#else
|
||||||
jstring result = path;
|
jstring result = path;
|
||||||
string_t chars = getChars(e, 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
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
// Option: without opening file
|
||||||
LARGE_INTEGER fileSize;
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
|
if(chars) {
|
||||||
|
LARGE_INTEGER fileSize;
|
||||||
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
HANDLE file = CreateFileW
|
HANDLE file = CreateFileW
|
||||||
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
(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);
|
releaseChars(e, path, chars);
|
||||||
if (file != INVALID_HANDLE_VALUE)
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
GetFileSizeEx(file, &fileSize);
|
return 0;
|
||||||
else 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);
|
CloseHandle(file);
|
||||||
return static_cast<jlong>(fileSize.QuadPart);
|
return static_cast<jlong>(fileSize.QuadPart);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
@ -598,7 +552,11 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
|||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
|
|
||||||
Directory* d = new (malloc(sizeof(Directory))) Directory;
|
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));
|
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) {
|
if (d->handle == INVALID_HANDLE_VALUE) {
|
||||||
d->dispose();
|
d->dispose();
|
||||||
d = 0;
|
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
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
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)
|
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
|
||||||
{
|
{
|
||||||
jbyte* data = static_cast<jbyte*>(malloc(length));
|
jbyte* data = static_cast<jbyte*>(malloc(length));
|
||||||
|
|
||||||
if (data == 0) {
|
if (data == 0) {
|
||||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->GetByteArrayRegion(b, offset, length, data);
|
e->GetByteArrayRegion(b, offset, length, data);
|
||||||
|
|
||||||
if (not e->ExceptionCheck()) {
|
if (not e->ExceptionCheck()) {
|
||||||
doWrite(e, fd, data, length);
|
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);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
Mapping* mapping = map(e, chars);
|
jlong peer = 0;
|
||||||
|
jlong length = 0;
|
||||||
jlong peer = reinterpret_cast<jlong>(mapping);
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
e->SetLongArrayRegion(result, 0, 1, &peer);
|
#if defined(PLATFORM_WINDOWS)
|
||||||
|
int fd = ::_wopen(chars, O_RDONLY | OPEN_MASK);
|
||||||
jlong length = (mapping ? mapping->length : 0);
|
#else
|
||||||
e->SetLongArrayRegion(result, 1, 1, &length);
|
int fd = ::open((const char*)chars, O_RDONLY | OPEN_MASK);
|
||||||
|
#endif
|
||||||
releaseChars(e, path, chars);
|
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
|
||||||
|
|
||||||
|
e->SetLongArrayRegion(result, 0, 1, &peer);
|
||||||
|
e->SetLongArrayRegion(result, 1, 1, &length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_RandomAccessFile_copy(JNIEnv* e, jclass, jlong peer,
|
Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
||||||
jlong position, jbyteArray buffer,
|
jlong position, jbyteArray buffer,
|
||||||
int offset, int length)
|
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*>
|
uint8_t* dst = reinterpret_cast<uint8_t*>
|
||||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||||
|
|
||||||
memcpy(dst + offset,
|
int64_t bytesRead = ::read(fd, dst + offset, length);
|
||||||
reinterpret_cast<Mapping*>(peer)->start + position,
|
|
||||||
length);
|
|
||||||
|
|
||||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
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
|
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 "signal.h"
|
||||||
# include "sys/time.h"
|
# include "sys/time.h"
|
||||||
# include "sys/types.h"
|
# include "sys/types.h"
|
||||||
|
# ifndef __ANDROID__
|
||||||
# include "sys/sysctl.h"
|
# include "sys/sysctl.h"
|
||||||
|
# endif
|
||||||
# include "sys/utsname.h"
|
# include "sys/utsname.h"
|
||||||
# include "sys/wait.h"
|
# include "sys/wait.h"
|
||||||
|
|
||||||
#endif // not PLATFORM_WINDOWS
|
#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 {
|
namespace {
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
char* getErrorStr(DWORD err){
|
|
||||||
// The poor man's error string, just print the error code
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
char * errStr = (char*) malloc(9 * sizeof(char));
|
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);
|
snprintf(errStr, 9, "%d", (int) err);
|
||||||
return errStr;
|
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;
|
|
||||||
}
|
}
|
||||||
|
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])
|
void makePipe(JNIEnv* e, HANDLE p[2])
|
||||||
{
|
{
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
@ -93,6 +124,7 @@ namespace {
|
|||||||
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int descriptor(JNIEnv* e, HANDLE h)
|
int descriptor(JNIEnv* e, HANDLE h)
|
||||||
{
|
{
|
||||||
@ -194,7 +226,7 @@ extern "C" JNIEXPORT void JNICALL
|
|||||||
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
||||||
jobjectArray command, jlongArray process)
|
jobjectArray command, jlongArray process)
|
||||||
{
|
{
|
||||||
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (int i = 0; i < e->GetArrayLength(command); ++i){
|
for (int i = 0; i < e->GetArrayLength(command); ++i){
|
||||||
jstring element = (jstring) e->GetObjectArrayElement(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);
|
e->SetLongArrayRegion(process, 0, 1, &pid);
|
||||||
jlong tid = reinterpret_cast<jlong>(pi.hThread);
|
jlong tid = reinterpret_cast<jlong>(pi.hThread);
|
||||||
e->SetLongArrayRegion(process, 1, 1, &tid);
|
e->SetLongArrayRegion(process, 1, 1, &tid);
|
||||||
|
#else
|
||||||
|
throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
|
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
|
||||||
{
|
{
|
||||||
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
DWORD exitCode;
|
DWORD exitCode;
|
||||||
WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE);
|
WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE);
|
||||||
BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode);
|
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));
|
CloseHandle(reinterpret_cast<HANDLE>(tid));
|
||||||
|
|
||||||
return exitCode;
|
return exitCode;
|
||||||
|
#else
|
||||||
|
throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8"));
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
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);
|
TerminateProcess(reinterpret_cast<HANDLE>(pid), 1);
|
||||||
|
#else
|
||||||
|
throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Locale getLocale() {
|
Locale getLocale() {
|
||||||
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
const char* lang = "";
|
const char* lang = "";
|
||||||
const char* reg = "";
|
const char* reg = "";
|
||||||
unsigned langid = GetUserDefaultUILanguage();
|
unsigned langid = GetUserDefaultUILanguage();
|
||||||
@ -360,8 +405,23 @@ Locale getLocale() {
|
|||||||
default: lang = "en";
|
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);
|
Locale locale(lang, reg);
|
||||||
|
free(cultureName);
|
||||||
return locale;
|
return locale;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
extern "C" JNIEXPORT void JNICALL
|
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) {
|
} else if (strcmp(chars, "file.separator") == 0) {
|
||||||
r = e->NewStringUTF("\\");
|
r = e->NewStringUTF("\\");
|
||||||
} else if (strcmp(chars, "os.name") == 0) {
|
} else if (strcmp(chars, "os.name") == 0) {
|
||||||
|
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
r = e->NewStringUTF("Windows");
|
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) {
|
} else if (strcmp(chars, "os.version") == 0) {
|
||||||
|
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
unsigned size = 32;
|
unsigned size = 32;
|
||||||
RUNTIME_ARRAY(char, buffer, size);
|
RUNTIME_ARRAY(char, buffer, size);
|
||||||
OSVERSIONINFO OSversion;
|
OSVERSIONINFO OSversion;
|
||||||
@ -538,6 +605,10 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name,
|
|||||||
::GetVersionEx(&OSversion);
|
::GetVersionEx(&OSversion);
|
||||||
snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%i.%i", (int)OSversion.dwMajorVersion, (int)OSversion.dwMinorVersion);
|
snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%i.%i", (int)OSversion.dwMajorVersion, (int)OSversion.dwMinorVersion);
|
||||||
r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer));
|
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) {
|
} else if (strcmp(chars, "os.arch") == 0) {
|
||||||
#ifdef ARCH_x86_32
|
#ifdef ARCH_x86_32
|
||||||
r = e->NewStringUTF("x86");
|
r = e->NewStringUTF("x86");
|
||||||
@ -549,15 +620,26 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name,
|
|||||||
r = e->NewStringUTF("arm");
|
r = e->NewStringUTF("arm");
|
||||||
#endif
|
#endif
|
||||||
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
||||||
|
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
TCHAR buffer[MAX_PATH];
|
TCHAR buffer[MAX_PATH];
|
||||||
GetTempPath(MAX_PATH, buffer);
|
GetTempPath(MAX_PATH, buffer);
|
||||||
r = e->NewStringUTF(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) {
|
} else if (strcmp(chars, "user.dir") == 0) {
|
||||||
|
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
TCHAR buffer[MAX_PATH];
|
TCHAR buffer[MAX_PATH];
|
||||||
GetCurrentDirectory(MAX_PATH, buffer);
|
GetCurrentDirectory(MAX_PATH, buffer);
|
||||||
r = e->NewStringUTF(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) {
|
} else if (strcmp(chars, "user.home") == 0) {
|
||||||
# ifdef _MSC_VER
|
# ifdef _MSC_VER
|
||||||
|
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
WCHAR buffer[MAX_PATH];
|
WCHAR buffer[MAX_PATH];
|
||||||
size_t needed;
|
size_t needed;
|
||||||
if (_wgetenv_s(&needed, buffer, MAX_PATH, L"USERPROFILE") == 0) {
|
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 {
|
} else {
|
||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
# else
|
||||||
|
std::wstring userHome = AvianInterop::GetDocumentsLibraryLocation();
|
||||||
|
r = e->NewString((const jchar*)userHome.c_str(), userHome.length());
|
||||||
|
# endif
|
||||||
# else
|
# else
|
||||||
LPWSTR home = _wgetenv(L"USERPROFILE");
|
LPWSTR home = _wgetenv(L"USERPROFILE");
|
||||||
r = e->NewString(reinterpret_cast<jchar*>(home), lstrlenW(home));
|
r = e->NewString(reinterpret_cast<jchar*>(home), lstrlenW(home));
|
||||||
@ -652,6 +738,9 @@ namespace {
|
|||||||
#elif defined __APPLE__
|
#elif defined __APPLE__
|
||||||
# include <crt_externs.h>
|
# include <crt_externs.h>
|
||||||
# define environ (*_NSGetEnviron())
|
# 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
|
#else
|
||||||
extern char** environ;
|
extern char** environ;
|
||||||
#endif
|
#endif
|
||||||
@ -785,6 +874,54 @@ Java_java_lang_Math_cos(JNIEnv*, jclass, jdouble val)
|
|||||||
return cos(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
|
extern "C" JNIEXPORT jdouble JNICALL
|
||||||
Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val)
|
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);
|
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
|
extern "C" JNIEXPORT jdouble JNICALL
|
||||||
Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val)
|
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
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -262,19 +262,33 @@ setTcpNoDelay(JNIEnv* e, int d, bool on)
|
|||||||
void
|
void
|
||||||
doBind(JNIEnv* e, int s, sockaddr_in* address)
|
doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||||
{
|
{
|
||||||
int opt = 1;
|
{ int opt = 1;
|
||||||
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||||
reinterpret_cast<char*>(&opt), sizeof(int));
|
reinterpret_cast<char*>(&opt), sizeof(int));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = ::bind(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
#ifdef SO_NOSIGPIPE
|
||||||
|
{ int opt = 1;
|
||||||
|
int r = ::setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE,
|
||||||
|
reinterpret_cast<char*>(&opt), sizeof(int));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ int r = ::bind
|
||||||
|
(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||||
|
if (r != 0) {
|
||||||
|
throwIOException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -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 "stdlib.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "zlib-custom.h"
|
#include "avian/zlib-custom.h"
|
||||||
|
|
||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "jni-util.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
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
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;
|
public static final String separator = FileSeparator;
|
||||||
|
|
||||||
|
private static final String PathSeparator
|
||||||
|
= System.getProperty("path.separator");
|
||||||
|
|
||||||
|
public static final String pathSeparator = PathSeparator;
|
||||||
|
|
||||||
// static {
|
// static {
|
||||||
// System.loadLibrary("natives");
|
// 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 openDir(String path);
|
||||||
|
|
||||||
|
private static native long lastModified(String path);
|
||||||
|
|
||||||
private static native String readDir(long handle);
|
private static native String readDir(long handle);
|
||||||
|
|
||||||
private static native long closeDir(long handle);
|
private static native long closeDir(long handle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static class Pair {
|
private static class Pair {
|
||||||
public final String value;
|
public final String value;
|
||||||
public final Pair next;
|
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;
|
package java.io;
|
||||||
|
|
||||||
public abstract class InputStream {
|
public abstract class InputStream implements Closeable {
|
||||||
public abstract int read() throws IOException;
|
public abstract int read() throws IOException;
|
||||||
|
|
||||||
public int read(byte[] buffer) throws IOException {
|
public int read(byte[] buffer) throws IOException {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
public abstract class OutputStream {
|
public abstract class OutputStream implements Closeable, Flushable {
|
||||||
public abstract void write(int c) throws IOException;
|
public abstract void write(int c) throws IOException;
|
||||||
|
|
||||||
public void write(byte[] buffer) throws IOException {
|
public void write(byte[] buffer) throws IOException {
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
|
import java.lang.IllegalArgumentException;
|
||||||
|
|
||||||
public class RandomAccessFile {
|
public class RandomAccessFile {
|
||||||
private long peer;
|
private long peer;
|
||||||
private File file;
|
private File file;
|
||||||
@ -56,26 +58,68 @@ public class RandomAccessFile {
|
|||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readFully(byte[] buffer, int offset, int length)
|
public int skipBytes(int count) throws IOException {
|
||||||
throws IOException
|
if (position + count > length()) throw new IOException();
|
||||||
{
|
this.position = position + count;
|
||||||
if (peer == 0) throw new IOException();
|
return count;
|
||||||
|
|
||||||
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 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();
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
int bytesRead = readBytes(peer, position, b, off, len);
|
||||||
copy(peer, position, buffer, offset, length);
|
position += bytesRead;
|
||||||
|
return bytesRead;
|
||||||
position += length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native void copy(long peer, long position, byte[] buffer,
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
int offset, int length);
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
public abstract class Reader {
|
public abstract class Reader implements Closeable {
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
char[] buffer = new char[1];
|
char[] buffer = new char[1];
|
||||||
int c = read(buffer);
|
int c = read(buffer);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
public abstract class Writer {
|
public abstract class Writer implements Closeable, Flushable {
|
||||||
public void write(int c) throws IOException {
|
public void write(int c) throws IOException {
|
||||||
char[] buffer = new char[] { (char) c };
|
char[] buffer = new char[] { (char) c };
|
||||||
write(buffer);
|
write(buffer);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public final class Boolean implements Comparable<Boolean> {
|
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 FALSE = new Boolean(false);
|
||||||
public static final Boolean TRUE = new Boolean(true);
|
public static final Boolean TRUE = new Boolean(true);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public final class Byte extends Number implements Comparable<Byte> {
|
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;
|
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 MIN_RADIX = 2;
|
||||||
public static final int MAX_RADIX = 36;
|
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;
|
private final char value;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ import java.security.AllPermission;
|
|||||||
|
|
||||||
public final class Class <T> implements Type, AnnotatedElement {
|
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;
|
public final VMClass vmClass;
|
||||||
|
|
||||||
@ -144,38 +145,7 @@ public final class Class <T> implements Type, AnnotatedElement {
|
|||||||
ClassLoader loader)
|
ClassLoader loader)
|
||||||
throws ClassNotFoundException
|
throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
if (loader == null) {
|
return Classes.forName(name, initialize, loader);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getComponentType() {
|
public Class getComponentType() {
|
||||||
@ -210,84 +180,36 @@ public final class Class <T> implements Type, AnnotatedElement {
|
|||||||
return Classes.isAssignableFrom(vmClass, c.vmClass);
|
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 {
|
public Field getDeclaredField(String name) throws NoSuchFieldException {
|
||||||
Field f = findField(vmClass, name);
|
int index = Classes.findField(vmClass, name);
|
||||||
if (f == null) {
|
if (index < 0) {
|
||||||
throw new NoSuchFieldException(name);
|
throw new NoSuchFieldException(name);
|
||||||
} else {
|
} else {
|
||||||
return f;
|
return new Field(vmClass.fieldTable[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Field getField(String name) throws NoSuchFieldException {
|
public Field getField(String name) throws NoSuchFieldException {
|
||||||
for (VMClass c = vmClass; c != null; c = c.super_) {
|
for (VMClass c = vmClass; c != null; c = c.super_) {
|
||||||
Field f = findField(c, name);
|
int index = Classes.findField(c, name);
|
||||||
if (f != null) {
|
if (index >= 0) {
|
||||||
return f;
|
return new Field(vmClass.fieldTable[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new NoSuchFieldException(name);
|
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)
|
public Method getDeclaredMethod(String name, Class ... parameterTypes)
|
||||||
throws NoSuchMethodException
|
throws NoSuchMethodException
|
||||||
{
|
{
|
||||||
if (name.startsWith("<")) {
|
if (name.startsWith("<")) {
|
||||||
throw new NoSuchMethodException(name);
|
throw new NoSuchMethodException(name);
|
||||||
}
|
}
|
||||||
Method m = findMethod(vmClass, name, parameterTypes);
|
int index = Classes.findMethod(vmClass, name, parameterTypes);
|
||||||
if (m == null) {
|
if (index < 0) {
|
||||||
throw new NoSuchMethodException(name);
|
throw new NoSuchMethodException(name);
|
||||||
} else {
|
} 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);
|
throw new NoSuchMethodException(name);
|
||||||
}
|
}
|
||||||
for (VMClass c = vmClass; c != null; c = c.super_) {
|
for (VMClass c = vmClass; c != null; c = c.super_) {
|
||||||
Method m = findMethod(c, name, parameterTypes);
|
int index = Classes.findMethod(c, name, parameterTypes);
|
||||||
if (m != null) {
|
if (index >= 0) {
|
||||||
return m;
|
return new Method(vmClass.methodTable[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new NoSuchMethodException(name);
|
throw new NoSuchMethodException(name);
|
||||||
@ -309,11 +231,11 @@ public final class Class <T> implements Type, AnnotatedElement {
|
|||||||
public Constructor getConstructor(Class ... parameterTypes)
|
public Constructor getConstructor(Class ... parameterTypes)
|
||||||
throws NoSuchMethodException
|
throws NoSuchMethodException
|
||||||
{
|
{
|
||||||
Method m = findMethod(vmClass, "<init>", parameterTypes);
|
int index = Classes.findMethod(vmClass, "<init>", parameterTypes);
|
||||||
if (m == null) {
|
if (index < 0) {
|
||||||
throw new NoSuchMethodException();
|
throw new NoSuchMethodException();
|
||||||
} else {
|
} 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();
|
Constructor[] constructors = getDeclaredConstructors();
|
||||||
|
|
||||||
for (int i = 0; i < constructors.length; ++i) {
|
for (int i = 0; i < constructors.length; ++i) {
|
||||||
if (match(parameterTypes, constructors[i].getParameterTypes())) {
|
if (Classes.match(parameterTypes, constructors[i].getParameterTypes())) {
|
||||||
c = constructors[i];
|
c = constructors[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,6 +477,10 @@ public final class Class <T> implements Type, AnnotatedElement {
|
|||||||
return (vmClass.vmFlags & PrimitiveFlag) != 0;
|
return (vmClass.vmFlags & PrimitiveFlag) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnum() {
|
||||||
|
return getSuperclass() == Enum.class && (vmClass.flags & EnumFlag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public URL getResource(String path) {
|
public URL getResource(String path) {
|
||||||
if (! path.startsWith("/")) {
|
if (! path.startsWith("/")) {
|
||||||
String name = new String
|
String name = new String
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public final class Double extends Number {
|
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 NEGATIVE_INFINITY = -1.0 / 0.0;
|
||||||
public static final double POSITIVE_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) {
|
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 {
|
try {
|
||||||
Method method = enumType.getMethod("values");
|
Method method = enumType.getMethod("values");
|
||||||
@ -41,10 +43,11 @@ public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} 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() {
|
public int ordinal() {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public final class Float extends Number {
|
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 EXP_BIT_MASK = 0x7F800000;
|
||||||
private static final int SIGNIF_BIT_MASK = 0x007FFFFF;
|
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
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -11,7 +11,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public final class Integer extends Number implements Comparable<Integer> {
|
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 MIN_VALUE = 0x80000000;
|
||||||
public static final int MAX_VALUE = 0x7FFFFFFF;
|
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);
|
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) {
|
public static String toBinaryString(int v) {
|
||||||
return Long.toString(((long) v) & 0xFFFFFFFFL, 2);
|
return Long.toString(((long) v) & 0xFFFFFFFFL, 2);
|
||||||
}
|
}
|
||||||
@ -90,6 +94,27 @@ public final class Integer extends Number implements Comparable<Integer> {
|
|||||||
return (double) value;
|
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) {
|
public static int parseInt(String s) {
|
||||||
return parseInt(s, 10);
|
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
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
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 MIN_VALUE = -9223372036854775808l;
|
||||||
public static final long MAX_VALUE = 9223372036854775807l;
|
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;
|
private final long value;
|
||||||
|
|
||||||
@ -94,6 +94,14 @@ public final class Long extends Number implements Comparable<Long> {
|
|||||||
return toString(v, 16);
|
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() {
|
public byte byteValue() {
|
||||||
return (byte) value;
|
return (byte) value;
|
||||||
}
|
}
|
||||||
@ -118,6 +126,12 @@ public final class Long extends Number implements Comparable<Long> {
|
|||||||
return (double) value;
|
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) {
|
private static long pow(long a, long b) {
|
||||||
long c = 1;
|
long c = 1;
|
||||||
for (int i = 0; i < b; ++i) c *= a;
|
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 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 acos(double v);
|
||||||
|
|
||||||
public static native double asin(double v);
|
public static native double asin(double v);
|
||||||
|
@ -17,9 +17,9 @@ public class Package {
|
|||||||
private final String implementationTitle;
|
private final String implementationTitle;
|
||||||
private final String implementationVendor;
|
private final String implementationVendor;
|
||||||
private final String implementationVersion;
|
private final String implementationVersion;
|
||||||
private final String specementationTitle;
|
private final String specificationTitle;
|
||||||
private final String specementationVendor;
|
private final String specificationVendor;
|
||||||
private final String specementationVersion;
|
private final String specificationVersion;
|
||||||
private final URL sealed;
|
private final URL sealed;
|
||||||
private final ClassLoader loader;
|
private final ClassLoader loader;
|
||||||
|
|
||||||
@ -27,9 +27,9 @@ public class Package {
|
|||||||
String implementationTitle,
|
String implementationTitle,
|
||||||
String implementationVendor,
|
String implementationVendor,
|
||||||
String implementationVersion,
|
String implementationVersion,
|
||||||
String specementationTitle,
|
String specificationTitle,
|
||||||
String specementationVendor,
|
String specificationVendor,
|
||||||
String specementationVersion,
|
String specificationVersion,
|
||||||
URL sealed,
|
URL sealed,
|
||||||
ClassLoader loader)
|
ClassLoader loader)
|
||||||
{
|
{
|
||||||
@ -37,9 +37,9 @@ public class Package {
|
|||||||
this.implementationTitle = implementationTitle;
|
this.implementationTitle = implementationTitle;
|
||||||
this.implementationVendor = implementationVendor;
|
this.implementationVendor = implementationVendor;
|
||||||
this.implementationVersion = implementationVersion;
|
this.implementationVersion = implementationVersion;
|
||||||
this.specementationTitle = specementationTitle;
|
this.specificationTitle = specificationTitle;
|
||||||
this.specementationVendor = specementationVendor;
|
this.specificationVendor = specificationVendor;
|
||||||
this.specementationVersion = specementationVersion;
|
this.specificationVersion = specificationVersion;
|
||||||
this.sealed = sealed;
|
this.sealed = sealed;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
}
|
}
|
||||||
@ -47,4 +47,36 @@ public class Package {
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
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;
|
package java.lang;
|
||||||
|
|
||||||
public final class Short extends Number implements Comparable<Short> {
|
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;
|
public static final short MAX_VALUE = 32767;
|
||||||
|
|
||||||
private final short value;
|
private final short value;
|
||||||
|
@ -127,6 +127,11 @@ public final class String
|
|||||||
} else {
|
} else {
|
||||||
c = Utf8.decode((byte[])data, offset, length);
|
c = Utf8.decode((byte[])data, offset, length);
|
||||||
if(c instanceof char[]) length = ((char[])c).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;
|
this.data = c;
|
||||||
|
@ -151,8 +151,8 @@ public class Thread implements Runnable {
|
|||||||
|
|
||||||
private static native boolean interrupted(long peer);
|
private static native boolean interrupted(long peer);
|
||||||
|
|
||||||
public static boolean isInterrupted() {
|
public boolean isInterrupted() {
|
||||||
return currentThread().interrupted;
|
return interrupted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sleep(long milliseconds) throws InterruptedException {
|
public static void sleep(long milliseconds) throws InterruptedException {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public final class Void {
|
public final class Void {
|
||||||
public static final Class TYPE = Class.forCanonicalName("V");
|
public static final Class TYPE = avian.Classes.forCanonicalName("V");
|
||||||
|
|
||||||
private Void() { }
|
private Void() { }
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public class Field<T> extends AccessibleObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class getType() {
|
public Class getType() {
|
||||||
return Class.forCanonicalName
|
return Classes.forCanonicalName
|
||||||
(vmField.class_.loader,
|
(vmField.class_.loader,
|
||||||
new String(vmField.spec, 0, vmField.spec.length - 1, false));
|
new String(vmField.spec, 0, vmField.spec.length - 1, false));
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
public class InvocationTargetException extends Exception {
|
public class InvocationTargetException extends Exception {
|
||||||
|
private Throwable target; // for compatibility with OpenJDK
|
||||||
|
|
||||||
public InvocationTargetException(Throwable targetException, String message) {
|
public InvocationTargetException(Throwable targetException, String message) {
|
||||||
super(message, targetException);
|
super(message, targetException);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ package java.lang.reflect;
|
|||||||
import avian.VMMethod;
|
import avian.VMMethod;
|
||||||
import avian.AnnotationInvocationHandler;
|
import avian.AnnotationInvocationHandler;
|
||||||
import avian.SystemClassLoader;
|
import avian.SystemClassLoader;
|
||||||
|
import avian.Classes;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
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);
|
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() {
|
public Class[] getParameterTypes() {
|
||||||
return getParameterTypes(vmMethod);
|
return Classes.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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object invoke(Object instance, Object ... arguments)
|
public Object invoke(Object instance, Object ... arguments)
|
||||||
@ -151,7 +99,7 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
public Class getReturnType() {
|
public Class getReturnType() {
|
||||||
for (int i = 0; i < vmMethod.spec.length - 1; ++i) {
|
for (int i = 0; i < vmMethod.spec.length - 1; ++i) {
|
||||||
if (vmMethod.spec[i] == ')') {
|
if (vmMethod.spec[i] == ')') {
|
||||||
return Class.forCanonicalName
|
return Classes.forCanonicalName
|
||||||
(vmMethod.class_.loader,
|
(vmMethod.class_.loader,
|
||||||
new String
|
new String
|
||||||
(vmMethod.spec, i + 1, vmMethod.spec.length - i - 2, false));
|
(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();
|
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_) {
|
public <T extends Annotation> T getAnnotation(Class<T> class_) {
|
||||||
if (vmMethod.hasAnnotations()) {
|
if (vmMethod.hasAnnotations()) {
|
||||||
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
||||||
for (int i = 0; i < table.length; ++i) {
|
for (int i = 0; i < table.length; ++i) {
|
||||||
Object[] a = (Object[]) table[i];
|
Object[] a = (Object[]) table[i];
|
||||||
if (a[1] == class_) {
|
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;
|
Object[] table = (Object[]) vmMethod.addendum.annotationTable;
|
||||||
Annotation[] array = new Annotation[table.length];
|
Annotation[] array = new Annotation[table.length];
|
||||||
for (int i = 0; i < table.length; ++i) {
|
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;
|
return array;
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,6 +16,9 @@ import static avian.Stream.write4;
|
|||||||
import static avian.Stream.set4;
|
import static avian.Stream.set4;
|
||||||
import static avian.Assembler.*;
|
import static avian.Assembler.*;
|
||||||
|
|
||||||
|
import avian.SystemClassLoader;
|
||||||
|
import avian.Classes;
|
||||||
|
|
||||||
import avian.ConstantPool;
|
import avian.ConstantPool;
|
||||||
import avian.ConstantPool.PoolEntry;
|
import avian.ConstantPool.PoolEntry;
|
||||||
|
|
||||||
@ -87,26 +90,15 @@ public class Proxy {
|
|||||||
|
|
||||||
write1(out, aload_0);
|
write1(out, aload_0);
|
||||||
|
|
||||||
write1(out, new_);
|
|
||||||
write2(out, ConstantPool.addClass(pool, "java/lang/reflect/Method") + 1);
|
|
||||||
write1(out, dup);
|
|
||||||
write1(out, ldc_w);
|
write1(out, ldc_w);
|
||||||
write2(out, ConstantPool.addClass(pool, className) + 1);
|
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);
|
write1(out, ldc_w);
|
||||||
write2(out, ConstantPool.addInteger(pool, index) + 1);
|
write2(out, ConstantPool.addInteger(pool, index) + 1);
|
||||||
write1(out, aaload);
|
write1(out, invokestatic);
|
||||||
write1(out, invokespecial);
|
|
||||||
write2(out, ConstantPool.addMethodRef
|
write2(out, ConstantPool.addMethodRef
|
||||||
(pool, "java/lang/reflect/Method",
|
(pool, "avian/Classes",
|
||||||
"<init>", "(Lavian/VMMethod;)V") + 1);
|
"makeMethod", "(Ljava/lang/Class;I)Ljava/lang/reflect/Method;")
|
||||||
|
+ 1);
|
||||||
|
|
||||||
write1(out, ldc_w);
|
write1(out, ldc_w);
|
||||||
write2(out, ConstantPool.addInteger(pool, parameterCount) + 1);
|
write2(out, ConstantPool.addInteger(pool, parameterCount) + 1);
|
||||||
@ -363,10 +355,11 @@ public class Proxy {
|
|||||||
|
|
||||||
Map<String,avian.VMMethod> virtualMap = new HashMap();
|
Map<String,avian.VMMethod> virtualMap = new HashMap();
|
||||||
for (Class c: interfaces) {
|
for (Class c: interfaces) {
|
||||||
avian.VMMethod[] ivtable = c.vmClass.virtualTable;
|
avian.VMMethod[] ivtable = SystemClassLoader.vmClass(c).virtualTable;
|
||||||
if (ivtable != null) {
|
if (ivtable != null) {
|
||||||
for (avian.VMMethod m: ivtable) {
|
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()) {
|
for (avian.VMMethod m: virtualMap.values()) {
|
||||||
methodTable[i] = new MethodData
|
methodTable[i] = new MethodData
|
||||||
(0,
|
(0,
|
||||||
ConstantPool.addUtf8(pool, Method.getName(m)),
|
ConstantPool.addUtf8(pool, Classes.toString(m.name)),
|
||||||
ConstantPool.addUtf8(pool, Method.getSpec(m)),
|
ConstantPool.addUtf8(pool, Classes.toString(m.spec)),
|
||||||
makeInvokeCode(pool, name, m.spec, m.parameterCount,
|
makeInvokeCode(pool, name, m.spec, m.parameterCount,
|
||||||
m.parameterFootprint, i));
|
m.parameterFootprint, i));
|
||||||
++ i;
|
++ i;
|
||||||
}
|
}
|
||||||
|
|
||||||
methodTable[i++] = new MethodData
|
methodTable[i++] = new MethodData
|
||||||
(0,
|
(Modifier.PUBLIC,
|
||||||
ConstantPool.addUtf8(pool, "<init>"),
|
ConstantPool.addUtf8(pool, "<init>"),
|
||||||
ConstantPool.addUtf8
|
ConstantPool.addUtf8
|
||||||
(pool, "(Ljava/lang/reflect/InvocationHandler;)V"),
|
(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)) {
|
if ("http".equals(protocol) || "https".equals(protocol)) {
|
||||||
return new avian.http.Handler();
|
return new avian.http.Handler();
|
||||||
} else if ("avian_vm_resource".equals(protocol)) {
|
} else if ("avianvmresource".equals(protocol)) {
|
||||||
return new avian.avian_vm_resource.Handler();
|
return new avian.avianvmresource.Handler();
|
||||||
} else if ("file".equals(protocol)) {
|
} else if ("file".equals(protocol)) {
|
||||||
return new avian.file.Handler();
|
return new avian.file.Handler();
|
||||||
} else if ("jar".equals(protocol)) {
|
} 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;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasArray() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] array() {
|
public byte[] array() {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
@ -49,9 +53,10 @@ class ArrayByteBuffer extends ByteBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer put(ByteBuffer src) {
|
public ByteBuffer put(ByteBuffer src) {
|
||||||
checkPut(position, src.remaining());
|
int length = src.remaining();
|
||||||
src.get(array, arrayOffset + position, src.remaining());
|
checkPut(position, length);
|
||||||
position += src.remaining();
|
src.get(array, arrayOffset + position, length);
|
||||||
|
position += length;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +53,15 @@ public abstract class ByteBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compact() {
|
public ByteBuffer compact() {
|
||||||
|
int remaining = remaining();
|
||||||
|
|
||||||
if (position != 0) {
|
if (position != 0) {
|
||||||
ByteBuffer b = slice();
|
ByteBuffer b = slice();
|
||||||
position = 0;
|
position = 0;
|
||||||
put(b);
|
put(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
position = remaining();
|
position = remaining;
|
||||||
limit(capacity());
|
limit(capacity());
|
||||||
|
|
||||||
return this;
|
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 "stdlib.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
|
#include <avian/util/runtime-array.h>
|
||||||
|
|
||||||
#undef JNIEXPORT
|
#undef JNIEXPORT
|
||||||
|
|
||||||
#if (defined __MINGW32__) || (defined _MSC_VER)
|
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
@ -121,30 +123,5 @@ allocate(JNIEnv* e, unsigned size)
|
|||||||
}
|
}
|
||||||
return p;
|
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
|
#endif//JNI_UTIL
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package sun.misc;
|
package sun.misc;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
public final class Unsafe {
|
public final class Unsafe {
|
||||||
private void Unsafe() { }
|
private void Unsafe() { }
|
||||||
|
|
||||||
@ -50,10 +52,15 @@ public final class Unsafe {
|
|||||||
|
|
||||||
public native int arrayBaseOffset(Class arrayClass);
|
public native int arrayBaseOffset(Class arrayClass);
|
||||||
|
|
||||||
|
public native long objectFieldOffset(Field field);
|
||||||
|
|
||||||
public native void copyMemory(Object srcBase, long srcOffset,
|
public native void copyMemory(Object srcBase, long srcOffset,
|
||||||
Object destBase, long destOffset,
|
Object destBase, long destOffset,
|
||||||
long count);
|
long count);
|
||||||
|
|
||||||
|
public native boolean compareAndSwapInt(Object o, long offset, int old,
|
||||||
|
int new_);
|
||||||
|
|
||||||
public void copyMemory(long src, long dst, long count) {
|
public void copyMemory(long src, long dst, long count) {
|
||||||
copyMemory(null, src, null, dst, count);
|
copyMemory(null, src, null, dst, count);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@
|
|||||||
#define AVIAN_TOOLS_H_
|
#define AVIAN_TOOLS_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "environment.h"
|
|
||||||
|
#include <avian/util/string.h>
|
||||||
|
|
||||||
|
#include "avian/environment.h"
|
||||||
|
|
||||||
namespace avian {
|
namespace avian {
|
||||||
|
|
||||||
@ -38,24 +41,12 @@ public:
|
|||||||
virtual void write(uint8_t byte);
|
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 {
|
class SymbolInfo {
|
||||||
public:
|
public:
|
||||||
unsigned addr;
|
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),
|
addr(addr),
|
||||||
name(name) {}
|
name(name) {}
|
||||||
|
|
||||||
@ -78,7 +69,7 @@ public:
|
|||||||
|
|
||||||
class StringTable : public Buffer {
|
class StringTable : public Buffer {
|
||||||
public:
|
public:
|
||||||
unsigned add(String str);
|
unsigned add(util::String str);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
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
|
#ifndef STREAM_H
|
||||||
#define STREAM_H
|
#define STREAM_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
class Stream {
|
class AbstractStream {
|
||||||
public:
|
public:
|
||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
virtual void handleError() = 0;
|
virtual void handleError() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Stream(Client* client, const uint8_t* data, unsigned size):
|
AbstractStream(Client* client, unsigned size):
|
||||||
client(client), data(data), size(size), position_(0)
|
client(client), size(size), position_(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned position() {
|
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_) {
|
if (size > this->size - position_) {
|
||||||
memset(data, 0, size);
|
memset(dst, 0, size);
|
||||||
|
|
||||||
client->handleError();
|
client->handleError();
|
||||||
} else {
|
} else {
|
||||||
memcpy(data, this->data + position_, size);
|
copy(dst, position_, size);
|
||||||
position_ += size;
|
position_ += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,13 +85,29 @@ class Stream {
|
|||||||
return read8();
|
return read8();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void copy(uint8_t* dst, unsigned offset, unsigned size) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Client* client;
|
Client* client;
|
||||||
const uint8_t* data;
|
|
||||||
unsigned size;
|
unsigned size;
|
||||||
unsigned position_;
|
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
|
} // namespace vm
|
||||||
|
|
||||||
#endif//STREAM_H
|
#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
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#ifndef COMPILER_H
|
#ifndef AVIAN_CODEGEN_COMPILER_H
|
||||||
#define COMPILER_H
|
#define AVIAN_CODEGEN_COMPILER_H
|
||||||
|
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "zone.h"
|
#include "avian/zone.h"
|
||||||
#include "assembler.h"
|
#include "assembler.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace avian {
|
||||||
|
namespace codegen {
|
||||||
|
|
||||||
class TraceHandler {
|
class TraceHandler {
|
||||||
public:
|
public:
|
||||||
@ -26,10 +27,10 @@ class Compiler {
|
|||||||
public:
|
public:
|
||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0;
|
virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0;
|
||||||
virtual intptr_t getThunk(BinaryOperation op, unsigned size,
|
virtual intptr_t getThunk(lir::BinaryOperation op, unsigned size,
|
||||||
unsigned resultSize) = 0;
|
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;
|
unsigned resultSize, bool* threadParameter) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -200,9 +201,10 @@ class Compiler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Compiler*
|
Compiler*
|
||||||
makeCompiler(System* system, Assembler* assembler, Zone* zone,
|
makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
||||||
Compiler::Client* client);
|
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
|
#ifndef HEAP_H
|
||||||
#define HEAP_H
|
#define HEAP_H
|
||||||
|
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "allocator.h"
|
#include "avian/allocator.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
@ -59,13 +59,16 @@ class Heap: public Allocator {
|
|||||||
|
|
||||||
virtual void setClient(Client* client) = 0;
|
virtual void setClient(Client* client) = 0;
|
||||||
virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) = 0;
|
virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) = 0;
|
||||||
virtual bool limitExceeded() = 0;
|
virtual unsigned limit() = 0;
|
||||||
virtual void collect(CollectionType type, unsigned footprint) = 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,
|
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,
|
||||||
bool objectMask, unsigned* totalInBytes) = 0;
|
bool objectMask) = 0;
|
||||||
virtual void* allocateImmortalFixed(Allocator* allocator,
|
virtual void* allocateImmortalFixed(Allocator* allocator,
|
||||||
unsigned sizeInWords, bool objectMask,
|
unsigned sizeInWords,
|
||||||
unsigned* totalInBytes) = 0;
|
bool objectMask) = 0;
|
||||||
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
|
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
|
||||||
virtual void pad(void* p) = 0;
|
virtual void pad(void* p) = 0;
|
||||||
virtual void* follow(void* p) = 0;
|
virtual void* follow(void* p) = 0;
|
@ -11,12 +11,13 @@
|
|||||||
#ifndef SYSTEM_H
|
#ifndef SYSTEM_H
|
||||||
#define SYSTEM_H
|
#define SYSTEM_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
#include "allocator.h"
|
#include "avian/allocator.h"
|
||||||
|
#include <avian/util/abort.h>
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
class System {
|
class System : public avian::util::Aborter {
|
||||||
public:
|
public:
|
||||||
typedef intptr_t Status;
|
typedef intptr_t Status;
|
||||||
|
|
||||||
@ -121,8 +122,10 @@ class System {
|
|||||||
virtual bool success(Status) = 0;
|
virtual bool success(Status) = 0;
|
||||||
virtual void* tryAllocate(unsigned sizeInBytes) = 0;
|
virtual void* tryAllocate(unsigned sizeInBytes) = 0;
|
||||||
virtual void free(const void* p) = 0;
|
virtual void free(const void* p) = 0;
|
||||||
|
#if !defined(AVIAN_AOT_ONLY)
|
||||||
virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0;
|
virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0;
|
||||||
virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0;
|
virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0;
|
||||||
|
#endif
|
||||||
virtual Status attach(Runnable*) = 0;
|
virtual Status attach(Runnable*) = 0;
|
||||||
virtual Status start(Runnable*) = 0;
|
virtual Status start(Runnable*) = 0;
|
||||||
virtual Status make(Mutex**) = 0;
|
virtual Status make(Mutex**) = 0;
|
||||||
@ -148,7 +151,6 @@ class System {
|
|||||||
virtual int64_t now() = 0;
|
virtual int64_t now() = 0;
|
||||||
virtual void yield() = 0;
|
virtual void yield() = 0;
|
||||||
virtual void exit(int code) = 0;
|
virtual void exit(int code) = 0;
|
||||||
virtual void abort() = 0;
|
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -163,11 +165,8 @@ allocate(System* s, unsigned size)
|
|||||||
#define ACQUIRE_MONITOR(t, m) \
|
#define ACQUIRE_MONITOR(t, m) \
|
||||||
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)
|
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)
|
||||||
|
|
||||||
inline void NO_RETURN
|
inline avian::util::Aborter* getAborter(System* s) {
|
||||||
abort(System* s)
|
return s;
|
||||||
{
|
|
||||||
s->abort(); // this should not return
|
|
||||||
::abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void NO_RETURN
|
inline void NO_RETURN
|
||||||
@ -176,28 +175,22 @@ sysAbort(System* s)
|
|||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
// #ifdef NDEBUG
|
||||||
expect(System* s, bool v)
|
|
||||||
{
|
|
||||||
if (UNLIKELY(not v)) abort(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NDEBUG
|
// # define assert(a, b)
|
||||||
|
// # define vm_assert(a, b)
|
||||||
|
|
||||||
# define assert(a, b)
|
// #else // not NDEBUG
|
||||||
# define vm_assert(a, b)
|
|
||||||
|
|
||||||
#else // not NDEBUG
|
// inline void
|
||||||
|
// assert(System* s, bool v)
|
||||||
|
// {
|
||||||
|
// expect(s, v);
|
||||||
|
// }
|
||||||
|
|
||||||
inline void
|
// # define vm_assert(a, b) vm::assert(a, b)
|
||||||
assert(System* s, bool v)
|
|
||||||
{
|
|
||||||
expect(s, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
# define vm_assert(a, b) vm::assert(a, b)
|
// #endif // not NDEBUG
|
||||||
|
|
||||||
#endif // not NDEBUG
|
|
||||||
|
|
||||||
JNIEXPORT System*
|
JNIEXPORT System*
|
||||||
makeSystem(const char* crashDumpDirectory);
|
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/NetworkInterface_winXP.c \
|
||||||
$(openjdk-src)/windows/native/java/net/SocketInputStream.c \
|
$(openjdk-src)/windows/native/java/net/SocketInputStream.c \
|
||||||
$(openjdk-src)/windows/native/java/net/SocketOutputStream.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/WindowsPreferences.c \
|
||||||
$(openjdk-src)/windows/native/java/util/logging.c \
|
$(openjdk-src)/windows/native/java/util/logging.c \
|
||||||
$(openjdk-src)/windows/native/java/util/TimeZone_md.c \
|
$(openjdk-src)/windows/native/java/util/TimeZone_md.c \
|
||||||
@ -216,6 +218,9 @@ ifeq ($(platform),windows)
|
|||||||
|
|
||||||
openjdk-headers-classes += \
|
openjdk-headers-classes += \
|
||||||
java.net.DualStackPlainSocketImpl \
|
java.net.DualStackPlainSocketImpl \
|
||||||
|
java.net.SocketImpl \
|
||||||
|
java.net.TwoStacksPlainDatagramSocketImpl \
|
||||||
|
java.net.TwoStacksPlainSocketImpl \
|
||||||
java.lang.ProcessImpl \
|
java.lang.ProcessImpl \
|
||||||
sun.io.Win32ErrorMode \
|
sun.io.Win32ErrorMode \
|
||||||
sun.nio.ch.WindowsSelectorImpl \
|
sun.nio.ch.WindowsSelectorImpl \
|
||||||
@ -327,7 +332,8 @@ else
|
|||||||
$(src)/openjdk/my_java_props_macosx.c
|
$(src)/openjdk/my_java_props_macosx.c
|
||||||
else
|
else
|
||||||
openjdk-sources += \
|
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
|
endif
|
||||||
|
|
||||||
openjdk-cflags += \
|
openjdk-cflags += \
|
||||||
|
65
openjdk.pro
65
openjdk.pro
@ -14,6 +14,10 @@
|
|||||||
public static void setProperties(java.util.Properties);
|
public static void setProperties(java.util.Properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-keep class sun.misc.Launcher {
|
||||||
|
public static sun.misc.Launcher getLauncher();
|
||||||
|
}
|
||||||
|
|
||||||
-keep class java.lang.ClassLoader {
|
-keep class java.lang.ClassLoader {
|
||||||
private static java.lang.ClassLoader scl;
|
private static java.lang.ClassLoader scl;
|
||||||
private static boolean sclSet;
|
private static boolean sclSet;
|
||||||
@ -42,7 +46,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
-keep class avian.OpenJDK {
|
-keep class avian.OpenJDK {
|
||||||
public static java.security.ProtectionDomain getProtectionDomain();
|
<methods>;
|
||||||
}
|
}
|
||||||
|
|
||||||
-keepclassmembers public class java.security.PrivilegedAction {
|
-keepclassmembers public class java.security.PrivilegedAction {
|
||||||
@ -132,11 +136,30 @@
|
|||||||
public InetSocketAddress(java.net.InetAddress, int);
|
public InetSocketAddress(java.net.InetAddress, int);
|
||||||
}
|
}
|
||||||
-keep class java.net.ServerSocket
|
-keep class java.net.ServerSocket
|
||||||
|
-keep class java.net.SocketTimeoutException
|
||||||
|
|
||||||
-keepclassmembers class java.net.PlainSocketImpl {
|
-keepclassmembers class java.net.PlainSocketImpl {
|
||||||
<fields>;
|
<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 {
|
-keepclassmembers class java.io.FileInputStream {
|
||||||
private java.io.FileDescriptor fd;
|
private java.io.FileDescriptor fd;
|
||||||
}
|
}
|
||||||
@ -208,7 +231,7 @@
|
|||||||
-keep class sun.nio.cs.UTF_8
|
-keep class sun.nio.cs.UTF_8
|
||||||
|
|
||||||
# loaded reflectively to handle embedded resources:
|
# loaded reflectively to handle embedded resources:
|
||||||
-keep class avian.resource.Handler
|
-keep class avian.avianvmresource.Handler
|
||||||
|
|
||||||
# refered to symbolically in MethodAccessorGenerator:
|
# refered to symbolically in MethodAccessorGenerator:
|
||||||
-keep class sun.reflect.MethodAccessorImpl {
|
-keep class sun.reflect.MethodAccessorImpl {
|
||||||
@ -244,3 +267,41 @@
|
|||||||
-keep class sun.nio.fs.UnixException {
|
-keep class sun.nio.fs.UnixException {
|
||||||
UnixException(int);
|
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
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#include "types.h"
|
#include "avian/types.h"
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
@ -56,16 +56,25 @@ LOCAL(loop):
|
|||||||
|
|
||||||
// setup argument registers if necessary
|
// setup argument registers if necessary
|
||||||
tst r6, r6
|
tst r6, r6
|
||||||
|
#if (defined __APPLE__) && (defined __clang_major__) && (__clang_major__ >= 4)
|
||||||
|
ldmiane r6, {r0-r3}
|
||||||
|
#else
|
||||||
ldmneia r6, {r0-r3}
|
ldmneia r6, {r0-r3}
|
||||||
#if defined(__VFP_FP__) && (! defined(__SOFTFP__)) && (! defined(__QNX__))
|
#endif
|
||||||
|
#if defined(__ARM_PCS_VFP)
|
||||||
// and VFP registers
|
// and VFP registers
|
||||||
vldmia r7, {d0-d7}
|
vldmia r7, {d0-d7}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||||
|
mov lr, pc
|
||||||
|
bx r4
|
||||||
|
#else
|
||||||
blx r4 // call function
|
blx r4 // call function
|
||||||
|
#endif
|
||||||
add sp, sp, r5 // deallocate stack
|
add sp, sp, r5 // deallocate stack
|
||||||
|
|
||||||
#if defined(__VFP_FP__) && (! defined(__SOFTFP__)) && (! defined(__QNX__))
|
#if defined(__ARM_PCS_VFP)
|
||||||
cmp r8,#FLOAT_TYPE
|
cmp r8,#FLOAT_TYPE
|
||||||
bne LOCAL(double)
|
bne LOCAL(double)
|
||||||
fmrs r0,s0
|
fmrs r0,s0
|
||||||
@ -108,7 +117,12 @@ GLOBAL(vmRun):
|
|||||||
mov r12, r0
|
mov r12, r0
|
||||||
ldr r0, [r2, #CHECKPOINT_THREAD]
|
ldr r0, [r2, #CHECKPOINT_THREAD]
|
||||||
|
|
||||||
|
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||||
|
mov lr, pc
|
||||||
|
bx r12
|
||||||
|
#else
|
||||||
blx r12
|
blx r12
|
||||||
|
#endif
|
||||||
|
|
||||||
.globl GLOBAL(vmRun_returnAddress)
|
.globl GLOBAL(vmRun_returnAddress)
|
||||||
.align 2
|
.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
|
#ifndef VECTOR_H
|
||||||
#define VECTOR_H
|
#define VECTOR_H
|
||||||
|
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "target.h"
|
#include "avian/target.h"
|
||||||
|
|
||||||
|
#include <avian/util/math.h>
|
||||||
|
|
||||||
|
#undef max
|
||||||
|
#undef min
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
@ -51,8 +56,8 @@ class Vector {
|
|||||||
if (position + space > capacity) {
|
if (position + space > capacity) {
|
||||||
assert(s, minimumCapacity >= 0);
|
assert(s, minimumCapacity >= 0);
|
||||||
|
|
||||||
unsigned newCapacity = max
|
unsigned newCapacity = avian::util::max
|
||||||
(position + space, max(minimumCapacity, capacity * 2));
|
(position + space, avian::util::max(minimumCapacity, capacity * 2));
|
||||||
uint8_t* newData = static_cast<uint8_t*>
|
uint8_t* newData = static_cast<uint8_t*>
|
||||||
(allocator->allocate(newCapacity));
|
(allocator->allocate(newCapacity));
|
||||||
if (data) {
|
if (data) {
|
@ -11,7 +11,7 @@
|
|||||||
#ifndef ALLOCATOR_H
|
#ifndef ALLOCATOR_H
|
||||||
#define ALLOCATOR_H
|
#define ALLOCATOR_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
@ -19,7 +19,7 @@
|
|||||||
# undef interface
|
# undef interface
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
|
|
||||||
extern "C" void NO_RETURN
|
extern "C" void NO_RETURN
|
||||||
vmJump(void* address, void* frame, void* stack, void* thread,
|
vmJump(void* address, void* frame, void* stack, void* thread,
|
@ -11,8 +11,9 @@
|
|||||||
#ifndef ARM_H
|
#ifndef ARM_H
|
||||||
#define ARM_H
|
#define ARM_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "avian/types.h"
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
|
#include <avian/util/runtime-array.h>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# include "libkern/OSAtomic.h"
|
# include "libkern/OSAtomic.h"
|
||||||
@ -71,33 +72,57 @@ namespace vm {
|
|||||||
inline void
|
inline void
|
||||||
trap()
|
trap()
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
__debugbreak();
|
||||||
|
#else
|
||||||
asm("bkpt");
|
asm("bkpt");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
inline void
|
inline void
|
||||||
memoryBarrier()
|
memoryBarrier()
|
||||||
{
|
{
|
||||||
asm("nop");
|
asm("nop");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
storeStoreMemoryBarrier()
|
storeStoreMemoryBarrier()
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
_ReadWriteBarrier();
|
||||||
|
#else
|
||||||
memoryBarrier();
|
memoryBarrier();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
storeLoadMemoryBarrier()
|
storeLoadMemoryBarrier()
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
MemoryBarrier();
|
||||||
|
#else
|
||||||
memoryBarrier();
|
memoryBarrier();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
loadMemoryBarrier()
|
loadMemoryBarrier()
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
_ReadWriteBarrier();
|
||||||
|
#else
|
||||||
memoryBarrier();
|
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
|
inline void
|
||||||
syncInstructionCache(const void* start, unsigned size)
|
syncInstructionCache(const void* start, unsigned size)
|
||||||
{
|
{
|
||||||
@ -112,6 +137,8 @@ syncInstructionCache(const void* start, unsigned size)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // AVIAN_AOT_ONLY
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
|
typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
|
||||||
# define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
|
# define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
|
||||||
@ -156,14 +183,14 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
unsigned vfpIndex = 0;
|
unsigned vfpIndex = 0;
|
||||||
unsigned vfpBackfillIndex UNUSED = 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 stackIndex = 0;
|
||||||
|
|
||||||
unsigned ai = 0;
|
unsigned ai = 0;
|
||||||
for (unsigned ati = 0; ati < argumentCount; ++ ati) {
|
for (unsigned ati = 0; ati < argumentCount; ++ ati) {
|
||||||
switch (argumentTypes[ati]) {
|
switch (argumentTypes[ati]) {
|
||||||
case DOUBLE_TYPE:
|
case DOUBLE_TYPE:
|
||||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) && !defined(__QNX__)
|
#if defined(__ARM_PCS_VFP)
|
||||||
{
|
{
|
||||||
if (vfpIndex + Alignment <= VfpCount) {
|
if (vfpIndex + Alignment <= VfpCount) {
|
||||||
if (vfpIndex % Alignment) {
|
if (vfpIndex % Alignment) {
|
||||||
@ -179,7 +206,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
++ stackIndex;
|
++ stackIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(stack + stackIndex, arguments + ai, 8);
|
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
|
||||||
stackIndex += 8 / BytesPerWord;
|
stackIndex += 8 / BytesPerWord;
|
||||||
}
|
}
|
||||||
ai += 8 / BytesPerWord;
|
ai += 8 / BytesPerWord;
|
||||||
@ -192,7 +219,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
} else if (vfpIndex < VfpCount) {
|
} else if (vfpIndex < VfpCount) {
|
||||||
vfpTable[vfpIndex++] = arguments[ai];
|
vfpTable[vfpIndex++] = arguments[ai];
|
||||||
} else {
|
} else {
|
||||||
stack[stackIndex++] = arguments[ai];
|
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
||||||
}
|
}
|
||||||
++ ai;
|
++ ai;
|
||||||
break;
|
break;
|
||||||
@ -204,7 +231,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
and gprIndex + Alignment == GprCount)
|
and gprIndex + Alignment == GprCount)
|
||||||
{
|
{
|
||||||
gprTable[gprIndex++] = arguments[ai];
|
gprTable[gprIndex++] = arguments[ai];
|
||||||
stack[stackIndex++] = arguments[ai + 1];
|
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1];
|
||||||
} else {
|
} else {
|
||||||
if (gprIndex % Alignment) {
|
if (gprIndex % Alignment) {
|
||||||
++gprIndex;
|
++gprIndex;
|
||||||
@ -219,7 +246,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
++stackIndex;
|
++stackIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(stack + stackIndex, arguments + ai, 8);
|
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
|
||||||
stackIndex += 8 / BytesPerWord;
|
stackIndex += 8 / BytesPerWord;
|
||||||
}
|
}
|
||||||
ai += 8 / BytesPerWord;
|
ai += 8 / BytesPerWord;
|
||||||
@ -229,7 +256,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
if (gprIndex < GprCount) {
|
if (gprIndex < GprCount) {
|
||||||
gprTable[gprIndex++] = arguments[ai];
|
gprTable[gprIndex++] = arguments[ai];
|
||||||
} else {
|
} else {
|
||||||
stack[stackIndex++] = arguments[ai];
|
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
||||||
}
|
}
|
||||||
++ ai;
|
++ ai;
|
||||||
} break;
|
} break;
|
||||||
@ -247,7 +274,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
|
|
||||||
unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2);
|
unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2);
|
||||||
return vmNativeCall
|
return vmNativeCall
|
||||||
(function, stackSize, stack, stackIndex * BytesPerWord,
|
(function, stackSize, RUNTIME_ARRAY_BODY(stack), stackIndex * BytesPerWord,
|
||||||
(gprIndex ? gprTable : 0),
|
(gprIndex ? gprTable : 0),
|
||||||
(vfpIndex ? vfpTable : 0), returnType);
|
(vfpIndex ? vfpTable : 0), returnType);
|
||||||
}
|
}
|
@ -11,9 +11,12 @@
|
|||||||
#ifndef BOOTIMAGE_H
|
#ifndef BOOTIMAGE_H
|
||||||
#define BOOTIMAGE_H
|
#define BOOTIMAGE_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
#include "target.h"
|
#include "java-common.h"
|
||||||
#include "machine.h"
|
#include "avian/target.h"
|
||||||
|
#include "avian/machine.h"
|
||||||
|
|
||||||
|
#include <avian/util/math.h>
|
||||||
|
|
||||||
namespace vm {
|
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
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#ifndef COMMON_H
|
#ifndef AVIAN_COMMON_H
|
||||||
#define COMMON_H
|
#define AVIAN_COMMON_H
|
||||||
|
|
||||||
#ifndef __STDC_CONSTANT_MACROS
|
#ifndef __STDC_CONSTANT_MACROS
|
||||||
# define __STDC_CONSTANT_MACROS
|
# define __STDC_CONSTANT_MACROS
|
||||||
@ -20,25 +20,25 @@
|
|||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "types.h"
|
#include "avian/types.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
#include "float.h"
|
#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:
|
// don't complain about using 'this' in member initializers:
|
||||||
# pragma warning(disable:4355)
|
# 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 strncasecmp _strnicmp
|
||||||
|
|
||||||
#define FP_NAN 0
|
#define FP_NAN 0
|
||||||
@ -58,11 +58,6 @@ inline int fpclassify(double d) {
|
|||||||
return FP_UNDEF;
|
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) {
|
inline int signbit(double d) {
|
||||||
return _copysign(1.0, d) < 0;
|
return _copysign(1.0, d) < 0;
|
||||||
}
|
}
|
||||||
@ -86,15 +81,18 @@ inline int signbit(double d) {
|
|||||||
# ifdef _M_IX86
|
# ifdef _M_IX86
|
||||||
typedef int32_t intptr_t;
|
typedef int32_t intptr_t;
|
||||||
typedef uint32_t uintptr_t;
|
typedef uint32_t uintptr_t;
|
||||||
# define UINT64_C(x) x##LL
|
|
||||||
# define ARCH_x86_32
|
# define ARCH_x86_32
|
||||||
# define BYTES_PER_WORD 4
|
# define BYTES_PER_WORD 4
|
||||||
# elif defined _M_X64
|
# elif defined _M_X64
|
||||||
typedef int64_t intptr_t;
|
typedef int64_t intptr_t;
|
||||||
typedef uint64_t uintptr_t;
|
typedef uint64_t uintptr_t;
|
||||||
# define UINT64_C(x) x##L
|
|
||||||
# define ARCH_x86_64
|
# 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
|
# else
|
||||||
# error "unsupported architecture"
|
# error "unsupported architecture"
|
||||||
# endif
|
# endif
|
||||||
@ -107,7 +105,7 @@ typedef intptr_t intptr_alias_t;
|
|||||||
|
|
||||||
#else // not _MSC_VER
|
#else // not _MSC_VER
|
||||||
|
|
||||||
# include "stdint.h"
|
# include <stdint.h>
|
||||||
|
|
||||||
# define BYTES_PER_WORD __SIZEOF_POINTER__
|
# define BYTES_PER_WORD __SIZEOF_POINTER__
|
||||||
|
|
||||||
@ -214,6 +212,9 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
|
|||||||
type name; \
|
type name; \
|
||||||
} MAKE_NAME(resource_)(name);
|
} MAKE_NAME(resource_)(name);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning( disable : 4291 )
|
||||||
|
#endif
|
||||||
inline void* operator new(size_t, void* p) throw() { return p; }
|
inline void* operator new(size_t, void* p) throw() { return p; }
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
@ -226,23 +227,6 @@ alias(void* p, unsigned offset)
|
|||||||
|
|
||||||
#ifdef _MSC_VER
|
#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
|
inline int
|
||||||
vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
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
|
#else // not _MSC_VER
|
||||||
|
|
||||||
# define RUNTIME_ARRAY(type, name, size) type name[size];
|
|
||||||
# define RUNTIME_ARRAY_BODY(name) name
|
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
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;
|
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
|
inline unsigned
|
||||||
pad(unsigned n, unsigned alignment)
|
pad(unsigned n, unsigned alignment)
|
||||||
{
|
{
|
||||||
@ -349,35 +312,17 @@ padWord(uintptr_t n)
|
|||||||
return padWord(n, BytesPerWord);
|
return padWord(n, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline bool fitsInInt8(int64_t v) {
|
||||||
ceiling(unsigned n, unsigned d)
|
return v == static_cast<int8_t>(v);
|
||||||
{
|
|
||||||
return (n + d - 1) / d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool fitsInInt16(int64_t v) {
|
||||||
powerOfTwo(unsigned n)
|
return v == static_cast<int16_t>(v);
|
||||||
{
|
|
||||||
for (; n > 2; n >>= 1) if (n & 1) return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline bool fitsInInt32(int64_t v) {
|
||||||
nextPowerOfTwo(unsigned n)
|
return v == static_cast<int32_t>(v);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline unsigned
|
inline unsigned
|
||||||
wordOf(unsigned i)
|
wordOf(unsigned i)
|
||||||
@ -476,14 +421,14 @@ getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T&
|
inline T&
|
||||||
cast(void* p, unsigned offset)
|
fieldAtOffset(void* p, unsigned offset)
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T*
|
inline T*
|
||||||
mask(T* p)
|
maskAlignedPointer(T* p)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
|
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
|
||||||
}
|
}
|
||||||
@ -524,6 +469,12 @@ hash(const uint16_t* s, unsigned length)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
write4(uint8_t* dst, uint32_t v)
|
||||||
|
{
|
||||||
|
memcpy(dst, &v, 4);
|
||||||
|
}
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
floatToBits(float f)
|
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
|
} // 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
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
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
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#ifndef JNIENV_H
|
#ifndef EMBED_H
|
||||||
#define JNIENV_H
|
#define EMBED_H
|
||||||
|
|
||||||
#include "machine.h"
|
#define RESID_MAIN_CLASS 100
|
||||||
|
#define RESID_BOOT_JAR L"BOOT.JAR"
|
||||||
|
|
||||||
namespace vm {
|
#endif
|
||||||
|
|
||||||
void
|
|
||||||
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
|
|
||||||
|
|
||||||
} // namespace vm
|
|
||||||
|
|
||||||
#endif//JNIENV_H
|
|
@ -11,9 +11,9 @@
|
|||||||
#ifndef FINDER_H
|
#ifndef FINDER_H
|
||||||
#define FINDER_H
|
#define FINDER_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "allocator.h"
|
#include "avian/allocator.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
@ -11,7 +11,8 @@
|
|||||||
#ifndef HEAPWALK_H
|
#ifndef HEAPWALK_H
|
||||||
#define HEAPWALK_H
|
#define HEAPWALK_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
|
#include "java-common.h"
|
||||||
|
|
||||||
namespace vm {
|
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
|
#ifndef LZMA_UTIL_H
|
||||||
#define LZMA_UTIL_H
|
#define LZMA_UTIL_H
|
||||||
|
|
||||||
#include "lzma.h"
|
#include "avian/lzma.h"
|
||||||
#include "C/Types.h"
|
#include "C/Types.h"
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "allocator.h"
|
#include "avian/allocator.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
@ -11,8 +11,8 @@
|
|||||||
#ifndef LZMA_H
|
#ifndef LZMA_H
|
||||||
#define LZMA_H
|
#define LZMA_H
|
||||||
|
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "allocator.h"
|
#include "avian/allocator.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
@ -11,13 +11,16 @@
|
|||||||
#ifndef MACHINE_H
|
#ifndef MACHINE_H
|
||||||
#define MACHINE_H
|
#define MACHINE_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
#include "system.h"
|
#include "java-common.h"
|
||||||
#include "heap.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "finder.h"
|
#include <avian/vm/heap/heap.h>
|
||||||
#include "processor.h"
|
#include "avian/finder.h"
|
||||||
#include "constants.h"
|
#include "avian/processor.h"
|
||||||
#include "arch.h"
|
#include "avian/constants.h"
|
||||||
|
#include "avian/arch.h"
|
||||||
|
|
||||||
|
using namespace avian::util;
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
# define JNICALL __stdcall
|
# define JNICALL __stdcall
|
||||||
@ -101,6 +104,8 @@ const bool DebugStack = false;
|
|||||||
const bool DebugMonitors = false;
|
const bool DebugMonitors = false;
|
||||||
const bool DebugReferences = false;
|
const bool DebugReferences = false;
|
||||||
|
|
||||||
|
const bool AbortOnOutOfMemoryError = false;
|
||||||
|
|
||||||
const uintptr_t HashTakenMark = 1;
|
const uintptr_t HashTakenMark = 1;
|
||||||
const uintptr_t ExtendedMark = 2;
|
const uintptr_t ExtendedMark = 2;
|
||||||
const uintptr_t FixedMark = 3;
|
const uintptr_t FixedMark = 3;
|
||||||
@ -1206,6 +1211,7 @@ class Machine {
|
|||||||
BootLoader,
|
BootLoader,
|
||||||
AppLoader,
|
AppLoader,
|
||||||
BootstrapClassMap,
|
BootstrapClassMap,
|
||||||
|
PackageMap,
|
||||||
FindLoadedClassMethod,
|
FindLoadedClassMethod,
|
||||||
LoadClassMethod,
|
LoadClassMethod,
|
||||||
MonitorMap,
|
MonitorMap,
|
||||||
@ -1226,10 +1232,12 @@ class Machine {
|
|||||||
OutOfMemoryError,
|
OutOfMemoryError,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
VirtualFileFinders,
|
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,
|
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
|
||||||
Processor* processor, Classpath* classpath, const char** properties,
|
Processor* processor, Classpath* classpath, const char** properties,
|
||||||
@ -1535,6 +1543,18 @@ class Classpath {
|
|||||||
virtual object
|
virtual object
|
||||||
makeThread(Thread* t, Thread* parent) = 0;
|
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
|
virtual void
|
||||||
clearInterrupted(Thread* t) = 0;
|
clearInterrupted(Thread* t) = 0;
|
||||||
|
|
||||||
@ -1544,12 +1564,37 @@ class Classpath {
|
|||||||
virtual void
|
virtual void
|
||||||
resolveNative(Thread* t, object method) = 0;
|
resolveNative(Thread* t, object method) = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
interceptMethods(Thread* t) = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
preBoot(Thread* t) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
boot(Thread* t) = 0;
|
boot(Thread* t) = 0;
|
||||||
|
|
||||||
virtual const char*
|
virtual const char*
|
||||||
bootClasspath() = 0;
|
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
|
virtual void
|
||||||
dispose() = 0;
|
dispose() = 0;
|
||||||
};
|
};
|
||||||
@ -1582,7 +1627,8 @@ class ThreadRuntimeArray: public Thread::Resource {
|
|||||||
|
|
||||||
#else // not _MSC_VER
|
#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
|
#endif // not _MSC_VER
|
||||||
|
|
||||||
@ -1595,7 +1641,7 @@ typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*);
|
|||||||
inline object
|
inline object
|
||||||
objectClass(Thread*, object o)
|
objectClass(Thread*, object o)
|
||||||
{
|
{
|
||||||
return mask(cast<object>(o, 0));
|
return maskAlignedPointer(fieldAtOffset<object>(o, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
@ -1656,7 +1702,7 @@ release(Thread* t, Reference* r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
collect(Thread* t, Heap::CollectionType type);
|
collect(Thread* t, Heap::CollectionType type, int pendingAllocation = 0);
|
||||||
|
|
||||||
void
|
void
|
||||||
shutDown(Thread* t);
|
shutDown(Thread* t);
|
||||||
@ -1742,24 +1788,8 @@ class RawMonitorResource: public Thread::Resource {
|
|||||||
System::Monitor* m;
|
System::Monitor* m;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void NO_RETURN
|
inline Aborter* getAborter(Thread* t) {
|
||||||
abort(Thread* t)
|
return t->m->system;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FixedAllocator: public Allocator {
|
class FixedAllocator: public Allocator {
|
||||||
@ -1768,8 +1798,8 @@ class FixedAllocator: public Allocator {
|
|||||||
s(s), base(base), offset(0), capacity(capacity)
|
s(s), base(base), offset(0), capacity(capacity)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void* tryAllocate(unsigned) {
|
virtual void* tryAllocate(unsigned size) {
|
||||||
abort(s);
|
return allocate(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* allocate(unsigned size, unsigned padAlignment) {
|
void* allocate(unsigned size, unsigned padAlignment) {
|
||||||
@ -1802,7 +1832,7 @@ class FixedAllocator: public Allocator {
|
|||||||
inline bool
|
inline bool
|
||||||
ensure(Thread* t, unsigned sizeInBytes)
|
ensure(Thread* t, unsigned sizeInBytes)
|
||||||
{
|
{
|
||||||
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
if (t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord)
|
||||||
> ThreadHeapSizeInWords)
|
> ThreadHeapSizeInWords)
|
||||||
{
|
{
|
||||||
if (sizeInBytes <= ThreadBackupHeapSizeInBytes) {
|
if (sizeInBytes <= ThreadBackupHeapSizeInBytes) {
|
||||||
@ -1829,11 +1859,11 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
|||||||
inline object
|
inline object
|
||||||
allocateSmall(Thread* t, unsigned sizeInBytes)
|
allocateSmall(Thread* t, unsigned sizeInBytes)
|
||||||
{
|
{
|
||||||
assert(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
assert(t, t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord)
|
||||||
<= ThreadHeapSizeInWords);
|
<= ThreadHeapSizeInWords);
|
||||||
|
|
||||||
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
||||||
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
t->heapIndex += ceilingDivide(sizeInBytes, BytesPerWord);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1842,7 +1872,7 @@ allocate(Thread* t, unsigned sizeInBytes, bool objectMask)
|
|||||||
{
|
{
|
||||||
stress(t);
|
stress(t);
|
||||||
|
|
||||||
if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
if (UNLIKELY(t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord)
|
||||||
> ThreadHeapSizeInWords
|
> ThreadHeapSizeInWords
|
||||||
or t->m->exclusive))
|
or t->m->exclusive))
|
||||||
{
|
{
|
||||||
@ -1867,18 +1897,18 @@ mark(Thread* t, object o, unsigned offset)
|
|||||||
inline void
|
inline void
|
||||||
set(Thread* t, object target, unsigned offset, object value)
|
set(Thread* t, object target, unsigned offset, object value)
|
||||||
{
|
{
|
||||||
cast<object>(target, offset) = value;
|
fieldAtOffset<object>(target, offset) = value;
|
||||||
mark(t, target, offset);
|
mark(t, target, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
setObjectClass(Thread*, object o, object value)
|
setObjectClass(Thread*, object o, object value)
|
||||||
{
|
{
|
||||||
cast<object>(o, 0)
|
fieldAtOffset<object>(o, 0)
|
||||||
= reinterpret_cast<object>
|
= reinterpret_cast<object>
|
||||||
(reinterpret_cast<intptr_alias_t>(value)
|
(reinterpret_cast<intptr_alias_t>(value)
|
||||||
| (reinterpret_cast<intptr_alias_t>
|
| (reinterpret_cast<intptr_alias_t>
|
||||||
(cast<object>(o, 0)) & (~PointerMask)));
|
(fieldAtOffset<object>(o, 0)) & (~PointerMask)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char*
|
inline const char*
|
||||||
@ -1965,6 +1995,7 @@ addThread(Thread* t, Thread* p)
|
|||||||
ACQUIRE_RAW(t, t->m->stateLock);
|
ACQUIRE_RAW(t, t->m->stateLock);
|
||||||
|
|
||||||
assert(t, p->state == Thread::NoState);
|
assert(t, p->state == Thread::NoState);
|
||||||
|
expect(t, t->state == Thread::ActiveState || t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
p->state = Thread::IdleState;
|
p->state = Thread::IdleState;
|
||||||
++ t->m->threadCount;
|
++ t->m->threadCount;
|
||||||
@ -2133,9 +2164,9 @@ baseSize(Thread* t, object o, object class_)
|
|||||||
{
|
{
|
||||||
assert(t, classFixedSize(t, class_) >= BytesPerWord);
|
assert(t, classFixedSize(t, class_) >= BytesPerWord);
|
||||||
|
|
||||||
return ceiling(classFixedSize(t, class_), BytesPerWord)
|
return ceilingDivide(classFixedSize(t, class_), BytesPerWord)
|
||||||
+ ceiling(classArrayElementSize(t, class_)
|
+ ceilingDivide(classArrayElementSize(t, class_)
|
||||||
* cast<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord),
|
* fieldAtOffset<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord),
|
||||||
BytesPerWord);
|
BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2274,7 +2305,7 @@ inline uintptr_t&
|
|||||||
extendedWord(Thread* t UNUSED, object o, unsigned baseSize)
|
extendedWord(Thread* t UNUSED, object o, unsigned baseSize)
|
||||||
{
|
{
|
||||||
assert(t, objectExtended(t, o));
|
assert(t, objectExtended(t, o));
|
||||||
return cast<uintptr_t>(o, baseSize * BytesPerWord);
|
return fieldAtOffset<uintptr_t>(o, baseSize * BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
@ -2509,6 +2540,9 @@ emptyMethod(Thread* t, object method)
|
|||||||
object
|
object
|
||||||
parseUtf8(Thread* t, const char* data, unsigned length);
|
parseUtf8(Thread* t, const char* data, unsigned length);
|
||||||
|
|
||||||
|
object
|
||||||
|
parseUtf8(Thread* t, object array);
|
||||||
|
|
||||||
object
|
object
|
||||||
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length,
|
parseClass(Thread* t, object loader, const uint8_t* data, unsigned length,
|
||||||
Machine::Type throwType = Machine::NoClassDefFoundErrorType);
|
Machine::Type throwType = Machine::NoClassDefFoundErrorType);
|
||||||
@ -2663,6 +2697,19 @@ makeThrowable(Thread* t, Machine::Type type, const char* format, ...)
|
|||||||
void
|
void
|
||||||
popResources(Thread* t);
|
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
|
inline void NO_RETURN
|
||||||
throw_(Thread* t, object e)
|
throw_(Thread* t, object e)
|
||||||
{
|
{
|
||||||
@ -2673,6 +2720,28 @@ throw_(Thread* t, object e)
|
|||||||
|
|
||||||
t->exception = 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);
|
// printTrace(t, e);
|
||||||
|
|
||||||
popResources(t);
|
popResources(t);
|
||||||
@ -2773,7 +2842,7 @@ objectArrayLength(Thread* t UNUSED, object array)
|
|||||||
{
|
{
|
||||||
assert(t, classFixedSize(t, objectClass(t, array)) == BytesPerWord * 2);
|
assert(t, classFixedSize(t, objectClass(t, array)) == BytesPerWord * 2);
|
||||||
assert(t, classArrayElementSize(t, objectClass(t, array)) == BytesPerWord);
|
assert(t, classArrayElementSize(t, objectClass(t, array)) == BytesPerWord);
|
||||||
return cast<uintptr_t>(array, BytesPerWord);
|
return fieldAtOffset<uintptr_t>(array, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object&
|
inline object&
|
||||||
@ -2784,7 +2853,7 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index)
|
|||||||
assert(t, classObjectMask(t, objectClass(t, array))
|
assert(t, classObjectMask(t, objectClass(t, array))
|
||||||
== classObjectMask(t, arrayBody
|
== classObjectMask(t, arrayBody
|
||||||
(t, t->m->types, Machine::ArrayType)));
|
(t, t->m->types, Machine::ArrayType)));
|
||||||
return cast<object>(array, ArrayBody + (index * BytesPerWord));
|
return fieldAtOffset<object>(array, ArrayBody + (index * BytesPerWord));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
@ -2820,7 +2889,7 @@ inline bool
|
|||||||
atomicCompareAndSwapObject(Thread* t, object target, unsigned offset,
|
atomicCompareAndSwapObject(Thread* t, object target, unsigned offset,
|
||||||
object old, object new_)
|
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>(old),
|
||||||
reinterpret_cast<uintptr_t>(new_)))
|
reinterpret_cast<uintptr_t>(new_)))
|
||||||
{
|
{
|
||||||
@ -3330,7 +3399,7 @@ inline unsigned
|
|||||||
singletonMaskSize(unsigned count, unsigned bitsPerWord)
|
singletonMaskSize(unsigned count, unsigned bitsPerWord)
|
||||||
{
|
{
|
||||||
if (count) {
|
if (count) {
|
||||||
return ceiling(count + 2, bitsPerWord);
|
return ceilingDivide(count + 2, bitsPerWord);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3346,7 +3415,7 @@ singletonMaskSize(Thread* t, object singleton)
|
|||||||
{
|
{
|
||||||
unsigned length = singletonLength(t, singleton);
|
unsigned length = singletonLength(t, singleton);
|
||||||
if (length) {
|
if (length) {
|
||||||
return ceiling(length + 2, BitsPerWord + 1);
|
return ceilingDivide(length + 2, BitsPerWord + 1);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3429,7 +3498,7 @@ singletonBit(Thread* t, object singleton, unsigned start, unsigned index)
|
|||||||
inline unsigned
|
inline unsigned
|
||||||
poolMaskSize(unsigned count, unsigned bitsPerWord)
|
poolMaskSize(unsigned count, unsigned bitsPerWord)
|
||||||
{
|
{
|
||||||
return ceiling(count, bitsPerWord);
|
return ceilingDivide(count, bitsPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
@ -3441,7 +3510,7 @@ poolMaskSize(unsigned count)
|
|||||||
inline unsigned
|
inline unsigned
|
||||||
poolMaskSize(Thread* t, object pool)
|
poolMaskSize(Thread* t, object pool)
|
||||||
{
|
{
|
||||||
return ceiling(singletonCount(t, pool), BitsPerWord + 1);
|
return ceilingDivide(singletonCount(t, pool), BitsPerWord + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
@ -3454,7 +3523,7 @@ inline object
|
|||||||
resolveClassInObject(Thread* t, object loader, object container,
|
resolveClassInObject(Thread* t, object loader, object container,
|
||||||
unsigned classOffset, bool throw_ = true)
|
unsigned classOffset, bool throw_ = true)
|
||||||
{
|
{
|
||||||
object o = cast<object>(container, classOffset);
|
object o = fieldAtOffset<object>(container, classOffset);
|
||||||
|
|
||||||
loadMemoryBarrier();
|
loadMemoryBarrier();
|
||||||
|
|
||||||
@ -3801,14 +3870,11 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
|
|||||||
unsigned index, unsigned dimensions);
|
unsigned index, unsigned dimensions);
|
||||||
|
|
||||||
object
|
object
|
||||||
getCaller(Thread* t, unsigned target);
|
getCaller(Thread* t, unsigned target, bool skipMethodInvoke = false);
|
||||||
|
|
||||||
object
|
object
|
||||||
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length);
|
defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length);
|
||||||
|
|
||||||
void
|
|
||||||
dumpHeap(Thread* t, FILE* out);
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
methodClone(Thread* t, object method)
|
methodClone(Thread* t, object method)
|
||||||
{
|
{
|
||||||
@ -3893,9 +3959,6 @@ errorLog(Thread* t)
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
JNIEXPORT void
|
|
||||||
vmPrintTrace(vm::Thread* t);
|
|
||||||
|
|
||||||
JNIEXPORT void*
|
JNIEXPORT void*
|
||||||
vmAddressFromLine(vm::Thread* t, vm::object m, unsigned line);
|
vmAddressFromLine(vm::Thread* t, vm::object m, unsigned line);
|
||||||
|
|
@ -11,8 +11,8 @@
|
|||||||
#ifndef POWERPC_H
|
#ifndef POWERPC_H
|
||||||
#define POWERPC_H
|
#define POWERPC_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "avian/types.h"
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# include "mach/mach_types.h"
|
# include "mach/mach_types.h"
|
@ -11,10 +11,10 @@
|
|||||||
#ifndef PROCESS_H
|
#ifndef PROCESS_H
|
||||||
#define PROCESS_H
|
#define PROCESS_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "machine.h"
|
#include "avian/machine.h"
|
||||||
#include "constants.h"
|
#include "avian/constants.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
@ -11,13 +11,18 @@
|
|||||||
#ifndef PROCESSOR_H
|
#ifndef PROCESSOR_H
|
||||||
#define PROCESSOR_H
|
#define PROCESSOR_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "avian/common.h"
|
||||||
#include "system.h"
|
#include <avian/vm/system/system.h>
|
||||||
#include "heap.h"
|
#include <avian/vm/heap/heap.h>
|
||||||
#include "bootimage.h"
|
#include "bootimage.h"
|
||||||
#include "heapwalk.h"
|
#include "avian/heapwalk.h"
|
||||||
#include "zone.h"
|
#include "avian/zone.h"
|
||||||
#include "assembler.h"
|
|
||||||
|
namespace avian {
|
||||||
|
namespace codegen {
|
||||||
|
class DelayedPromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
@ -142,7 +147,7 @@ class Processor {
|
|||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
|
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
|
||||||
DelayedPromise** addresses, object method,
|
avian::codegen::DelayedPromise** addresses, object method,
|
||||||
OffsetResolver* resolver) = 0;
|
OffsetResolver* resolver) = 0;
|
||||||
|
|
||||||
virtual void
|
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