| # Copyright (C) 2011 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # This script is used on host and device. It uses a common subset |
| # shell dialect that should work on the host (e.g. bash), and |
| # Android (e.g. mksh). |
| |
| # Globals |
| ART_BINARY=dalvikvm |
| DEX2OAT_BINARY=dex2oat |
| DELETE_ANDROID_DATA="no" |
| LAUNCH_WRAPPER= |
| LIBART=libart.so |
| JIT_PROFILE="no" |
| VERBOSE="no" |
| |
| # Follow all sym links to get the program name. |
| if [ z"$BASH_SOURCE" != z ]; then |
| PROG_NAME="$BASH_SOURCE" |
| else |
| PROG_NAME="$0" |
| fi |
| while [ -h "$PROG_NAME" ]; do |
| # On Mac OS, readlink -f doesn't work. |
| PROG_NAME="$(readlink "$PROG_NAME")" |
| done |
| |
| function find_libdir() { |
| # Get the actual file, $1 is the ART_BINARY_PATH and may be a symbolic link. |
| # Use realpath instead of readlink because Android does not have a readlink. |
| if [[ "$(realpath "$1")" == *dalvikvm64 ]]; then |
| echo "lib64" |
| else |
| echo "lib" |
| fi |
| } |
| |
| function usage() { |
| cat 1>&2 <<EOF |
| Usage: art [OPTIONS] [--] [ART_OPTIONS] CLASS |
| |
| Supported OPTIONS include: |
| --32 Use the 32-bit Android Runtime. |
| --64 Use the 64-bit Android Runtime. |
| --callgrind Launch the Android Runtime in callgrind. |
| -d Use the debug ART library (libartd.so). |
| --debug Equivalent to -d. |
| --gdb Launch the Android Runtime in gdb. |
| --help Display usage message. |
| --invoke-with <program> Launch the Android Runtime in <program>. |
| --perf Launch the Android Runtime with perf recording. |
| --perf-report Launch the Android Runtime with perf recording with |
| report upon completion. |
| --profile Run with profiling, then run using profile data. |
| --verbose Run script verbosely. |
| |
| The ART_OPTIONS are passed directly to the Android Runtime. |
| Before calling ART, the script will invoke dex2oat on each element of the |
| classpath. '-Xcompiler-option' and '-Ximage' will be forwarded to dex2oat. |
| |
| Example: |
| art --32 -cp my_classes.dex MainClass |
| |
| Common errors: |
| 1) Not having core.art available (see $ANDROID_BUILD_TOP/art/Android.mk). |
| eg m -j32 build-art-host |
| 2) Not having boot.art available (see $ANDROID_BUILD_TOP/build/make/core/dex_preopt_libart_boot.mk) |
| eg m -j32 out/target/product/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art |
| EOF |
| } |
| |
| function clean_android_data() { |
| if [ "$DELETE_ANDROID_DATA" = "yes" ]; then |
| rm -rf $ANDROID_DATA |
| fi |
| } |
| |
| function verbose_run() { |
| if [ "$VERBOSE" = "yes" ]; then |
| echo "$@" |
| fi |
| eval "$@" |
| } |
| |
| function run_art() { |
| verbose_run ANDROID_DATA=$ANDROID_DATA \ |
| ANDROID_ROOT=$ANDROID_ROOT \ |
| LD_LIBRARY_PATH=$LD_LIBRARY_PATH \ |
| PATH=$ANDROID_ROOT/bin:$PATH \ |
| LD_USE_LOAD_BIAS=1 \ |
| $LAUNCH_WRAPPER $ART_BINARY_PATH $lib \ |
| -XXlib:$LIBART \ |
| -Xnorelocate \ |
| -Ximage:$DEFAULT_IMAGE \ |
| "$@" |
| } |
| |
| function run_dex2oat() { |
| for dex_file in "${DEX2OAT_CLASSPATH[@]}" |
| do |
| while [ -h "$dex_file" ]; do |
| # On Mac OS, readlink -f doesn't work. |
| dex_file="$(readlink "$dex_file")" |
| done |
| local dalvik_cache=$ANDROID_DATA/dalvik-cache/$ISA |
| # The oat file name if the absolute path of the dex file where '/' is |
| # replaced by '@'. The first '/' in the path is ignored and must be removed. |
| local oat_file=${dex_file//\//@} |
| local oat_file=${oat_file:1} |
| # When running dex2oat use the exact same context as when running dalvikvm. |
| # (see run_art function) |
| verbose_run ANDROID_DATA=$ANDROID_DATA \ |
| ANDROID_ROOT=$ANDROID_ROOT \ |
| LD_LIBRARY_PATH=$LD_LIBRARY_PATH \ |
| PATH=$ANDROID_ROOT/bin:$PATH \ |
| LD_USE_LOAD_BIAS=1 \ |
| $DEX2OAT_BINARY_PATH \ |
| --runtime-arg -Xnorelocate \ |
| --boot-image=$DEX2OAT_BOOTIMAGE \ |
| --instruction-set=$ISA \ |
| "${DEX2OAT_FLAGS[@]}" \ |
| --dex-file="$dex_file" \ |
| --oat-file="$dalvik_cache/$oat_file" |
| done |
| } |
| |
| # Extract the dex2oat flags from the list of arguments. |
| # -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array |
| # -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH |
| # -Ximage argument is stored in DEX2OAT_BOOTIMAGE |
| function extract_dex2oat_flags() { |
| while [ $# -gt 0 ]; do |
| case $1 in |
| -Xcompiler-option) |
| DEX2OAT_FLAGS+=("$2") |
| shift |
| ;; |
| -Ximage:*) |
| DEX2OAT_BOOTIMAGE=$1 |
| # Remove '-Ximage:' from the argument. |
| DEX2OAT_BOOTIMAGE=${DEX2OAT_BOOTIMAGE##-Ximage:} |
| ;; |
| -cp) |
| # TODO: support -classpath and CLASSPATH |
| local oifs=$IFS |
| IFS=':' |
| for classpath_elem in $2 |
| do |
| DEX2OAT_CLASSPATH+=("$classpath_elem") |
| done |
| shift |
| IFS=$oifs |
| ;; |
| esac |
| shift |
| done |
| } |
| |
| while [[ "$1" = "-"* ]]; do |
| case $1 in |
| --) |
| # No more arguments for this script. |
| shift |
| break |
| ;; |
| --32) |
| ART_BINARY=dalvikvm32 |
| ;; |
| --64) |
| ART_BINARY=dalvikvm64 |
| ;; |
| --callgrind) |
| LAUNCH_WRAPPER="valgrind --tool=callgrind" |
| ;; |
| -d) |
| ;& # Fallthrough |
| --debug) |
| LIBART="libartd.so" |
| DEX2OAT_BINARY="dex2oatd" |
| ;; |
| --gdb) |
| LIBART="libartd.so" |
| DEX2OAT_BINARY="dex2oatd" |
| LAUNCH_WRAPPER="gdb --args" |
| ;; |
| --help) |
| usage |
| exit 0 |
| ;; |
| --invoke-with) |
| LAUNCH_WRAPPER=$2 |
| shift |
| ;; |
| --perf) |
| PERF="record" |
| ;; |
| --perf-report) |
| PERF="report" |
| ;; |
| --profile) |
| JIT_PROFILE="yes" |
| ;; |
| --verbose) |
| VERBOSE="yes" |
| ;; |
| --*) |
| echo "unknown option: $1" 1>&2 |
| usage |
| exit 1 |
| ;; |
| *) |
| break |
| ;; |
| esac |
| shift |
| done |
| |
| if [ $# -eq 0 ]; then |
| usage |
| exit 1 |
| fi |
| |
| PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" |
| ANDROID_ROOT=$PROG_DIR/.. |
| ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY |
| DEX2OAT_BINARY_PATH=$ANDROID_ROOT/bin/$DEX2OAT_BINARY |
| |
| if [ ! -x "$DEX2OAT_BINARY_PATH" ]; then |
| cat 1>&2 <<EOF |
| Android Runtime not found: $DEX2OAT_BINARY_PATH |
| This script should be in the same directory as the Android Runtime ($DEX2OAT_BINARY). |
| EOF |
| exit 1 |
| fi |
| |
| if [ ! -x "$ART_BINARY_PATH" ]; then |
| cat 1>&2 <<EOF |
| Android Runtime not found: $ART_BINARY_PATH |
| This script should be in the same directory as the Android Runtime ($ART_BINARY). |
| EOF |
| exit 1 |
| fi |
| |
| LIBDIR="$(find_libdir $ART_BINARY_PATH)" |
| LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBDIR |
| EXTRA_OPTIONS="" |
| |
| DEFAULT_IMAGE=$ANDROID_ROOT/framework/core.art |
| DEX2OAT_FLAGS=() |
| DEX2OAT_CLASSPATH=() |
| DEX2OAT_BOOTIMAGE=$DEFAULT_IMAGE |
| ISA=$($ART_BINARY_PATH -showversion | (read art version number isa && echo $isa)) |
| |
| # Extract the dex2oat flags from the list of arguments. |
| # -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array |
| # -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH |
| # -Ximage argument is stored in DEX2OAT_BOOTIMAGE |
| extract_dex2oat_flags "$@" |
| |
| # If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own, |
| # and ensure we delete it at the end. |
| if [ "$ANDROID_DATA" = "/data" ] || [ "$ANDROID_DATA" = "" ]; then |
| ANDROID_DATA=$PWD/android-data$$ |
| mkdir -p "$ANDROID_DATA/dalvik-cache/$ISA" |
| DELETE_ANDROID_DATA="yes" |
| fi |
| |
| if [ "$PERF" != "" ]; then |
| LAUNCH_WRAPPER="perf record -g -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER" |
| EXTRA_OPTIONS="-Xcompiler-option --generate-debug-info" |
| fi |
| |
| # Protect additional arguments in quotes to preserve whitespaces when evaluated. |
| # This is for run-jdwp-test.sh which uses this script and has arguments with |
| # whitespaces when running on device. |
| while [ $# -gt 0 ]; do |
| EXTRA_OPTIONS="$EXTRA_OPTIONS \"$1\"" |
| shift |
| done |
| |
| if [ "$JIT_PROFILE" = "yes" ]; then |
| # Create the profile. The runtime expects profiles to be created before |
| # execution. |
| PROFILE_PATH="$ANDROID_DATA/primary.prof" |
| touch $PROFILE_PATH |
| |
| run_art -Xjitsaveprofilinginfo \ |
| -Xps-min-methods-to-save:1 \ |
| -Xps-min-classes-to-save:1 \ |
| -Xps-min-notification-before-wake:10 \ |
| -Xps-profile-path:$PROFILE_PATH \ |
| -Xusejit:true \ |
| $EXTRA_OPTIONS \ |
| "&>" "$ANDROID_DATA/profile_gen.log" |
| |
| DEX2OAT_FLAGS+=("--profile-file=$PROFILE_PATH") |
| |
| EXIT_STATUS=$? |
| |
| if [ $EXIT_STATUS != 0 ]; then |
| cat "$ANDROID_DATA/profile_gen.log" |
| clean_android_data |
| exit $EXIT_STATUS |
| fi |
| fi |
| |
| # Run dex2oat before launching ART to generate the oat files for the classpath. |
| run_dex2oat |
| |
| # Do not continue if the dex2oat failed. |
| EXIT_STATUS=$? |
| if [ $EXIT_STATUS != 0 ]; then |
| echo "Failed dex2oat invocation" >&2 |
| exit $EXIT_STATUS |
| fi |
| |
| # Launch ART using the additional arguments stored in EXTRA_OPTIONS. |
| run_art $EXTRA_OPTIONS |
| EXIT_STATUS=$? |
| |
| if [ "$PERF" != "" ]; then |
| if [ "$PERF" = report ]; then |
| perf report -i $ANDROID_DATA/perf.data |
| fi |
| echo "Perf data saved in: $ANDROID_DATA/perf.data" |
| else |
| # Perf output is placed under $ANDROID_DATA so not cleaned when perf options used. |
| clean_android_data |
| fi |
| |
| exit $EXIT_STATUS |