Home | History | Annotate | Download | only in tools
      1 # Copyright (C) 2011 The Android Open Source Project
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 
     15 # This script is used on host and device. It uses a common subset
     16 # shell dialect that should work on the host (e.g. bash), and
     17 # Android (e.g. mksh).
     18 
     19 # Globals
     20 ARCHS={arm,arm64,mips,mips64,x86,x86_64}
     21 ART_BINARY=dalvikvm
     22 DELETE_ANDROID_DATA="no"
     23 LAUNCH_WRAPPER=
     24 LIBART=libart.so
     25 JIT_PROFILE="no"
     26 VERBOSE="no"
     27 
     28 # Follow all sym links to get the program name.
     29 if [ z"$BASH_SOURCE" != z ]; then
     30   PROG_NAME="$BASH_SOURCE"
     31 else
     32   PROG_NAME="$0"
     33 fi
     34 while [ -h "$PROG_NAME" ]; do
     35   # On Mac OS, readlink -f doesn't work.
     36   PROG_NAME="$(readlink "$PROG_NAME")"
     37 done
     38 
     39 function find_libdir() {
     40   # Get the actual file, $1 is the ART_BINARY_PATH and may be a symbolic link.
     41   # Use realpath instead of readlink because Android does not have a readlink.
     42   if [[ "$(realpath "$1")" == *dalvikvm64 ]]; then
     43     echo "lib64"
     44   else
     45     echo "lib"
     46   fi
     47 }
     48 
     49 function replace_compiler_filter_with_quicken() {
     50   ARGS_WITH_QUICKEN=("$@")
     51 
     52   found="false"
     53   ((index=0))
     54   while ((index <= $#)); do
     55     what="${ARGS_WITH_QUICKEN[$index]}"
     56 
     57     case "$what" in
     58       --compiler-filter=*)
     59         ARGS_WITH_QUICKEN[$index]="--compiler-filter=quicken"
     60         found="true"
     61         ;;
     62     esac
     63 
     64     ((index++))
     65     shift
     66   done
     67   if [ "$found" != "true" ]; then
     68     ARGS_WITH_QUICKEN=(-Xcompiler-option --compiler-filter=quicken "${ARGS_WITH_QUICKEN[@]}")
     69   fi
     70 }
     71 
     72 function usage() {
     73   cat 1>&2 <<EOF
     74 Usage: art [OPTIONS] [--] [ART_OPTIONS] CLASS
     75 
     76 Supported OPTIONS include:
     77   --32                     Use the 32-bit Android Runtime.
     78   --64                     Use the 64-bit Android Runtime.
     79   --callgrind              Launch the Android Runtime in callgrind.
     80   -d                       Use the debug ART library (libartd.so).
     81   --debug                  Equivalent to -d.
     82   --gdb                    Launch the Android Runtime in gdb.
     83   --help                   Display usage message.
     84   --invoke-with <program>  Launch the Android Runtime in <program>.
     85   --perf                   Launch the Android Runtime with perf recording.
     86   --perf-report            Launch the Android Runtime with perf recording with
     87                            report upon completion.
     88   --profile                Run with profiling, then run using profile data.
     89   --verbose                Run script verbosely.
     90 
     91 The ART_OPTIONS are passed directly to the Android Runtime.
     92 
     93 Example:
     94   art --32 -cp my_classes.dex MainClass
     95 
     96 Common errors:
     97   1) Not having core.art available (see $ANDROID_BUILD_TOP/art/Android.mk).
     98      eg m -j32 build-art-host
     99   2) Not having boot.art available (see $ANDROID_BUILD_TOP/build/make/core/dex_preopt_libart_boot.mk)
    100      eg m -j32 out/target/product/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art
    101 EOF
    102 }
    103 
    104 function clean_android_data() {
    105   if [ "$DELETE_ANDROID_DATA" = "yes" ]; then
    106     rm -rf $ANDROID_DATA
    107   fi
    108 }
    109 
    110 function verbose_run() {
    111   if [ "$VERBOSE" = "yes" ]; then
    112     echo "$@"
    113   fi
    114   eval "$@"
    115 }
    116 
    117 function run_art() {
    118   verbose_run ANDROID_DATA=$ANDROID_DATA               \
    119               ANDROID_ROOT=$ANDROID_ROOT               \
    120               LD_LIBRARY_PATH=$LD_LIBRARY_PATH         \
    121               PATH=$ANDROID_ROOT/bin:$PATH             \
    122               LD_USE_LOAD_BIAS=1                       \
    123               $LAUNCH_WRAPPER $ART_BINARY_PATH $lib    \
    124               -XXlib:$LIBART                           \
    125               -Xnorelocate                             \
    126               -Ximage:$ANDROID_ROOT/framework/core.art \
    127               "$@"
    128 }
    129 
    130 while [[ "$1" = "-"* ]]; do
    131   case $1 in
    132   --)
    133     # No more arguments for this script.
    134     shift
    135     break
    136     ;;
    137   --32)
    138     ART_BINARY=dalvikvm32
    139     ;;
    140   --64)
    141     ART_BINARY=dalvikvm64
    142     ;;
    143   --callgrind)
    144     LAUNCH_WRAPPER="valgrind --tool=callgrind"
    145     ;;
    146   -d)
    147     ;& # Fallthrough
    148   --debug)
    149     LIBART="libartd.so"
    150     ;;
    151   --gdb)
    152     LIBART="libartd.so"
    153     LAUNCH_WRAPPER="gdb --args"
    154     ;;
    155   --help)
    156     usage
    157     exit 0
    158     ;;
    159   --invoke-with)
    160     LAUNCH_WRAPPER=$2
    161     shift
    162     ;;
    163   --perf)
    164     PERF="record"
    165     ;;
    166   --perf-report)
    167     PERF="report"
    168     ;;
    169   --profile)
    170     JIT_PROFILE="yes"
    171     ;;
    172   --verbose)
    173     VERBOSE="yes"
    174     ;;
    175   --*)
    176     echo "unknown option: $1" 1>&2
    177     usage
    178     exit 1
    179     ;;
    180   *)
    181     break
    182     ;;
    183   esac
    184   shift
    185 done
    186 
    187 if [ $# -eq 0 ]; then
    188   usage
    189   exit 1
    190 fi
    191 
    192 PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
    193 ANDROID_ROOT=$PROG_DIR/..
    194 ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
    195 
    196 if [ ! -x "$ART_BINARY_PATH" ]; then
    197   cat 1>&2 <<EOF
    198 Android Runtime not found: $ART_BINARY_PATH
    199 This script should be in the same directory as the Android Runtime ($ART_BINARY).
    200 EOF
    201   exit 1
    202 fi
    203 
    204 LIBDIR="$(find_libdir $ART_BINARY_PATH)"
    205 LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBDIR
    206 EXTRA_OPTIONS=""
    207 
    208 # If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own,
    209 # and ensure we delete it at the end.
    210 if [ "$ANDROID_DATA" = "/data" ] || [ "$ANDROID_DATA" = "" ]; then
    211   ANDROID_DATA=$PWD/android-data$$
    212   mkdir -p $ANDROID_DATA/dalvik-cache/$ARCHS
    213   DELETE_ANDROID_DATA="yes"
    214 fi
    215 
    216 if [ "$PERF" != "" ]; then
    217   LAUNCH_WRAPPER="perf record -g -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER"
    218   EXTRA_OPTIONS="-Xcompiler-option --generate-debug-info"
    219 fi
    220 
    221 if [ "$JIT_PROFILE" = "yes" ]; then
    222   # Create the profile. The runtime expects profiles to be created before
    223   # execution.
    224   PROFILE_PATH="$ANDROID_DATA/primary.prof"
    225   touch $PROFILE_PATH
    226 
    227   # Replace the compiler filter with quicken so that we
    228   # can capture the profile.
    229   ARGS_WITH_QUICKEN=
    230   replace_compiler_filter_with_quicken "$@"
    231 
    232   run_art -Xjitsaveprofilinginfo               \
    233           -Xps-min-methods-to-save:1           \
    234           -Xps-min-classes-to-save:1           \
    235           -Xps-min-notification-before-wake:10 \
    236           -Xps-profile-path:$PROFILE_PATH      \
    237           -Xusejit:true                        \
    238           "${ARGS_WITH_QUICKEN[@]}"            \
    239           "&>" "$ANDROID_DATA/profile_gen.log"
    240   EXIT_STATUS=$?
    241 
    242   if [ $EXIT_STATUS != 0 ]; then
    243     cat "$ANDROID_DATA/profile_gen.log"
    244     clean_android_data
    245     exit $EXIT_STATUS
    246   fi
    247 
    248   # Wipe dalvik-cache to prepare it for the next invocation.
    249   rm -rf $ANDROID_DATA/dalvik-cache/$ARCHS/*
    250 
    251   # Append arguments so next invocation of run_art uses the profile.
    252   EXTRA_OPTIONS="$EXTRA_OPTIONS -Xcompiler-option --profile-file=$PROFILE_PATH"
    253 fi
    254 
    255 # Protect additional arguments in quotes to preserve whitespaces when evaluated.
    256 # This is for run-jdwp-test.sh which uses this script and has arguments with
    257 # whitespaces when running on device.
    258 while [ $# -gt 0 ]; do
    259   EXTRA_OPTIONS="$EXTRA_OPTIONS \"$1\""
    260   shift
    261 done
    262 
    263 run_art $EXTRA_OPTIONS
    264 EXIT_STATUS=$?
    265 
    266 if [ "$PERF" != "" ]; then
    267   if [ "$PERF" = report ]; then
    268     perf report -i $ANDROID_DATA/perf.data
    269   fi
    270   echo "Perf data saved in: $ANDROID_DATA/perf.data"
    271 else
    272   # Perf output is placed under $ANDROID_DATA so not cleaned when perf options used.
    273   clean_android_data
    274 fi
    275 
    276 exit $EXIT_STATUS
    277