| # 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 |
| ARCHS={arm,arm64,mips,mips64,x86,x86_64} |
| ART_BINARY=dalvikvm |
| 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 replace_compiler_filter_with_interepret_only() { |
| ARGS_WITH_INTERPRET_ONLY=("$@") |
| |
| found="false" |
| ((index=0)) |
| while ((index <= $#)); do |
| what="${ARGS_WITH_INTERPRET_ONLY[$index]}" |
| |
| case "$what" in |
| --compiler-filter=*) |
| ARGS_WITH_INTERPRET_ONLY[$index]="--compiler-filter=interpret-only" |
| found="true" |
| ;; |
| esac |
| |
| ((index++)) |
| shift |
| done |
| if [ "$found" != "true" ]; then |
| ARGS_WITH_INTERPRET_ONLY=(-Xcompiler-option --compiler-filter=interpret-only "${ARGS_WITH_INTERPRET_ONLY[@]}") |
| 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. |
| |
| 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:$ANDROID_ROOT/framework/core.art \ |
| "$@" |
| } |
| |
| 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" |
| ;; |
| --gdb) |
| LIBART="libartd.so" |
| 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 |
| |
| 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="" |
| |
| # 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/$ARCHS |
| 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 |
| |
| 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 |
| |
| # Replace the compiler filter with interpret-only so that we |
| # can capture the profile. |
| ARGS_WITH_INTERPRET_ONLY= |
| replace_compiler_filter_with_interepret_only "$@" |
| |
| 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 \ |
| "${ARGS_WITH_INTERPRET_ONLY[@]}" \ |
| "&>" "$ANDROID_DATA/profile_gen.log" |
| EXIT_STATUS=$? |
| |
| if [ $EXIT_STATUS != 0 ]; then |
| cat "$ANDROID_DATA/profile_gen.log" |
| clean_android_data |
| exit $EXIT_STATUS |
| fi |
| |
| # Wipe dalvik-cache to prepare it for the next invocation. |
| rm -rf $ANDROID_DATA/dalvik-cache/$ARCHS/* |
| |
| # Append arguments so next invocation of run_art uses the profile. |
| EXTRA_OPTIONS="$EXTRA_OPTIONS -Xcompiler-option --profile-file=$PROFILE_PATH" |
| 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 |
| |
| 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 |