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 20ARCHS={arm,arm64,mips,mips64,x86,x86_64} 21ART_BINARY=dalvikvm 22DELETE_ANDROID_DATA="no" 23LAUNCH_WRAPPER= 24LIBART=libart.so 25JIT_PROFILE="no" 26VERBOSE="no" 27EXTRA_OPTIONS=() 28 29# Follow all sym links to get the program name. 30if [ z"$BASH_SOURCE" != z ]; then 31 PROG_NAME="$BASH_SOURCE" 32else 33 PROG_NAME="$0" 34fi 35while [ -h "$PROG_NAME" ]; do 36 # On Mac OS, readlink -f doesn't work. 37 PROG_NAME="$(readlink "$PROG_NAME")" 38done 39 40function find_libdir() { 41 # Get the actual file, $1 is the ART_BINARY_PATH and may be a symbolic link. 42 # Use realpath instead of readlink because Android does not have a readlink. 43 if [[ "$(realpath "$1")" == *dalvikvm64 ]]; then 44 echo "lib64" 45 else 46 echo "lib" 47 fi 48} 49 50function replace_compiler_filter_with_quicken() { 51 ARGS_WITH_QUICKEN=("$@") 52 53 found="false" 54 ((index=0)) 55 while ((index <= $#)); do 56 what="${ARGS_WITH_QUICKEN[$index]}" 57 58 case "$what" in 59 --compiler-filter=*) 60 ARGS_WITH_QUICKEN[$index]="--compiler-filter=quicken" 61 found="true" 62 ;; 63 esac 64 65 ((index++)) 66 shift 67 done 68 if [ "$found" != "true" ]; then 69 ARGS_WITH_QUICKEN=(-Xcompiler-option --compiler-filter=quicken "${ARGS_WITH_QUICKEN[@]}") 70 fi 71} 72 73function usage() { 74 cat 1>&2 <<EOF 75Usage: art [OPTIONS] [--] [ART_OPTIONS] CLASS 76 77Supported OPTIONS include: 78 --32 Use the 32-bit Android Runtime. 79 --64 Use the 64-bit Android Runtime. 80 --callgrind Launch the Android Runtime in callgrind. 81 -d Use the debug ART library (libartd.so). 82 --debug Equivalent to -d. 83 --gdb Launch the Android Runtime in gdb. 84 --help Display usage message. 85 --invoke-with <program> Launch the Android Runtime in <program>. 86 --perf Launch the Android Runtime with perf recording. 87 --perf-report Launch the Android Runtime with perf recording with 88 report upon completion. 89 --profile Run with profiling, then run using profile data. 90 --verbose Run script verbosely. 91 92The ART_OPTIONS are passed directly to the Android Runtime. 93 94Example: 95 art --32 -cp my_classes.dex MainClass 96 97Common errors: 98 1) Not having core.art available (see $ANDROID_BUILD_TOP/art/Android.mk). 99 eg m -j32 build-art-host 100 2) Not having boot.art available (see $ANDROID_BUILD_TOP/build/make/core/dex_preopt_libart_boot.mk) 101 eg m -j32 out/target/product/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art 102EOF 103} 104 105function clean_android_data() { 106 if [ "$DELETE_ANDROID_DATA" = "yes" ]; then 107 rm -rf $ANDROID_DATA 108 fi 109} 110 111# Given 'VAR1=VAL VAR2=VAL2 ... cmd arg1 arg2 ... argN' run the 'cmd' with the args 112# with the modified environment {VAR1=VAL,VAL2=,...}. 113# 114# Also prints the command to be run if verbose mode is enabled. 115function verbose_run() { 116 if [ "$VERBOSE" = "yes" ]; then 117 echo "$@" 118 fi 119 120 env "$@" 121} 122 123# Automatically find the boot image location. It uses core.art by default. 124# On a real device, it might only have a boot.art, so use that instead when core.art does not exist. 125function detect_boot_image_location() { 126 local image_location_dir="$ANDROID_ROOT/framework" 127 local image_location_name="core.art" 128 129 local maybe_arch 130 local core_image_exists="false" 131 132 # Parse ARCHS={a,b,c,d} syntax. 133 local array 134 IFS=, read -a array <<< "${ARCHS:1:(-1)}"; 135 for maybe_arch in "${array[@]}"; do 136 if [[ -e "$image_location_dir/$maybe_arch/$image_location_name" ]]; then 137 core_image_exists="true" 138 break 139 fi 140 done 141 142 if [[ "$core_image_exists" == "false" ]]; then 143 image_location_name="boot.art" 144 fi 145 146 local image_location="$image_location_dir/$image_location_name" 147 echo "$image_location" 148} 149 150function run_art() { 151 local image_location="$(detect_boot_image_location)" 152 153 verbose_run ANDROID_DATA=$ANDROID_DATA \ 154 ANDROID_ROOT=$ANDROID_ROOT \ 155 LD_LIBRARY_PATH=$LD_LIBRARY_PATH \ 156 PATH=$ANDROID_ROOT/bin:$PATH \ 157 LD_USE_LOAD_BIAS=1 \ 158 $LAUNCH_WRAPPER $ART_BINARY_PATH $lib \ 159 -XXlib:$LIBART \ 160 -Xnorelocate \ 161 -Ximage:"$image_location" \ 162 "$@" 163} 164 165while [[ "$1" = "-"* ]]; do 166 case "$1" in 167 --) 168 # No more arguments for this script. 169 shift 170 break 171 ;; 172 --32) 173 ART_BINARY=dalvikvm32 174 ;; 175 --64) 176 ART_BINARY=dalvikvm64 177 ;; 178 --callgrind) 179 LAUNCH_WRAPPER="valgrind --tool=callgrind" 180 ;; 181 -d) 182 ;& # Fallthrough 183 --debug) 184 LIBART="libartd.so" 185 # Expect that debug mode wants all checks. 186 EXTRA_OPTIONS+=(-XX:SlowDebug=true) 187 ;; 188 --gdb) 189 LIBART="libartd.so" 190 LAUNCH_WRAPPER="gdb --args" 191 ;; 192 --help) 193 usage 194 exit 0 195 ;; 196 --invoke-with) 197 LAUNCH_WRAPPER=$2 198 shift 199 ;; 200 --perf) 201 PERF="record" 202 ;; 203 --perf-report) 204 PERF="report" 205 ;; 206 --profile) 207 JIT_PROFILE="yes" 208 ;; 209 --verbose) 210 VERBOSE="yes" 211 ;; 212 --*) 213 echo "unknown option: $1" 1>&2 214 usage 215 exit 1 216 ;; 217 *) 218 break 219 ;; 220 esac 221 shift 222done 223 224if [ $# -eq 0 ]; then 225 usage 226 exit 1 227fi 228 229PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" 230ANDROID_ROOT=$PROG_DIR/.. 231ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY 232 233if [ ! -x "$ART_BINARY_PATH" ]; then 234 cat 1>&2 <<EOF 235Android Runtime not found: $ART_BINARY_PATH 236This script should be in the same directory as the Android Runtime ($ART_BINARY). 237EOF 238 exit 1 239fi 240 241LIBDIR="$(find_libdir $ART_BINARY_PATH)" 242LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBDIR 243 244# If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own, 245# and ensure we delete it at the end. 246if [ "$ANDROID_DATA" = "/data" ] || [ "$ANDROID_DATA" = "" ]; then 247 if [[ $PWD != / ]]; then 248 ANDROID_DATA="$PWD/android-data$$" 249 else 250 # Use /data/local/tmp when running this from adb shell, since it starts out in / 251 # by default. 252 ANDROID_DATA="$ANDROID_DATA/local/tmp/android-data$$" 253 fi 254 mkdir -p $ANDROID_DATA/dalvik-cache/$ARCHS 255 DELETE_ANDROID_DATA="yes" 256fi 257 258if [ "$PERF" != "" ]; then 259 LAUNCH_WRAPPER="perf record -g -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER" 260 EXTRA_OPTIONS+=(-Xcompiler-option --generate-debug-info) 261fi 262 263if [ "$JIT_PROFILE" = "yes" ]; then 264 # Create the profile. The runtime expects profiles to be created before 265 # execution. 266 PROFILE_PATH="$ANDROID_DATA/primary.prof" 267 touch $PROFILE_PATH 268 269 # Replace the compiler filter with quicken so that we 270 # can capture the profile. 271 ARGS_WITH_QUICKEN= 272 replace_compiler_filter_with_quicken "$@" 273 274 run_art -Xjitsaveprofilinginfo \ 275 -Xps-min-methods-to-save:1 \ 276 -Xps-min-classes-to-save:1 \ 277 -Xps-min-notification-before-wake:10 \ 278 -Xps-profile-path:$PROFILE_PATH \ 279 -Xusejit:true \ 280 "${ARGS_WITH_QUICKEN[@]}" \ 281 "&>" "$ANDROID_DATA/profile_gen.log" 282 EXIT_STATUS=$? 283 284 if [ $EXIT_STATUS != 0 ]; then 285 cat "$ANDROID_DATA/profile_gen.log" 286 clean_android_data 287 exit $EXIT_STATUS 288 fi 289 290 # Wipe dalvik-cache to prepare it for the next invocation. 291 rm -rf $ANDROID_DATA/dalvik-cache/$ARCHS/* 292 293 # Append arguments so next invocation of run_art uses the profile. 294 EXTRA_OPTIONS+=(-Xcompiler-option --profile-file="$PROFILE_PATH") 295fi 296 297# Protect additional arguments in quotes to preserve whitespaces (used by 298# run-jdwp-test.sh when running on device), '$' (may be used as part of 299# classpath) and other special characters when evaluated. 300EXTRA_OPTIONS+=("$@") 301 302run_art "${EXTRA_OPTIONS[@]}" 303EXIT_STATUS=$? 304 305if [ "$PERF" != "" ]; then 306 if [ "$PERF" = report ]; then 307 perf report -i $ANDROID_DATA/perf.data 308 fi 309 echo "Perf data saved in: $ANDROID_DATA/perf.data" 310else 311 # Perf output is placed under $ANDROID_DATA so not cleaned when perf options used. 312 clean_android_data 313fi 314 315exit $EXIT_STATUS 316