blob: 15993ddaa20c6b41cd2d3f34d9f1a1782b1dd77d [file] [log] [blame]
Elliott Hughes40ef99e2011-08-11 17:44:34 -07001# 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
Nicolas Geoffray70a998c2014-12-04 17:05:22 +000015# 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
Orion Hodson9763f2e2017-03-28 08:27:23 +010019# Globals
Orion Hodson9763f2e2017-03-28 08:27:23 +010020ART_BINARY=dalvikvm
21DELETE_ANDROID_DATA="no"
22LAUNCH_WRAPPER=
23LIBART=libart.so
24JIT_PROFILE="no"
25VERBOSE="no"
Nicolas Geoffrayc0c07852017-08-08 09:44:15 +010026CLEAN_OAT_FILES="yes"
Vladimir Markoafd44ea2017-07-14 13:52:02 +010027EXTRA_OPTIONS=()
Orion Hodson9763f2e2017-03-28 08:27:23 +010028
Calin Juravle64f45cb2017-03-16 19:58:26 -070029# 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
Nicolas Geoffray9583fbc2014-02-28 15:21:07 +000039
Nicolas Geoffrayfc3c67a2014-07-02 14:57:53 +010040function find_libdir() {
Orion Hodson9763f2e2017-03-28 08:27:23 +010041 # Get the actual file, $1 is the ART_BINARY_PATH and may be a symbolic link.
Nicolas Geoffray70a998c2014-12-04 17:05:22 +000042 # Use realpath instead of readlink because Android does not have a readlink.
Orion Hodson9763f2e2017-03-28 08:27:23 +010043 if [[ "$(realpath "$1")" == *dalvikvm64 ]]; then
Nicolas Geoffrayfc3c67a2014-07-02 14:57:53 +010044 echo "lib64"
45 else
46 echo "lib"
47 fi
48}
49
Nicolas Geoffray49cda062017-04-21 13:08:25 +010050function replace_compiler_filter_with_quicken() {
51 ARGS_WITH_QUICKEN=("$@")
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +000052
53 found="false"
54 ((index=0))
55 while ((index <= $#)); do
Nicolas Geoffray49cda062017-04-21 13:08:25 +010056 what="${ARGS_WITH_QUICKEN[$index]}"
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +000057
58 case "$what" in
59 --compiler-filter=*)
Nicolas Geoffray49cda062017-04-21 13:08:25 +010060 ARGS_WITH_QUICKEN[$index]="--compiler-filter=quicken"
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +000061 found="true"
62 ;;
63 esac
64
65 ((index++))
66 shift
67 done
68 if [ "$found" != "true" ]; then
Nicolas Geoffray49cda062017-04-21 13:08:25 +010069 ARGS_WITH_QUICKEN=(-Xcompiler-option --compiler-filter=quicken "${ARGS_WITH_QUICKEN[@]}")
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +000070 fi
71}
72
Orion Hodson9763f2e2017-03-28 08:27:23 +010073function usage() {
74 cat 1>&2 <<EOF
75Usage: art [OPTIONS] [--] [ART_OPTIONS] CLASS
Nicolas Geoffrayf63a0a52014-09-02 15:24:25 +010076
Orion Hodson9763f2e2017-03-28 08:27:23 +010077Supported 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.
Nicolas Geoffrayc0c07852017-08-08 09:44:15 +010091 --no-clean Don't cleanup oat directories.
Orion Hodson9763f2e2017-03-28 08:27:23 +010092
93The ART_OPTIONS are passed directly to the Android Runtime.
94
95Example:
96 art --32 -cp my_classes.dex MainClass
97
98Common errors:
99 1) Not having core.art available (see $ANDROID_BUILD_TOP/art/Android.mk).
100 eg m -j32 build-art-host
101 2) Not having boot.art available (see $ANDROID_BUILD_TOP/build/make/core/dex_preopt_libart_boot.mk)
102 eg m -j32 out/target/product/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art
103EOF
104}
105
106function clean_android_data() {
107 if [ "$DELETE_ANDROID_DATA" = "yes" ]; then
108 rm -rf $ANDROID_DATA
Nicolas Geoffrayf63a0a52014-09-02 15:24:25 +0100109 fi
Orion Hodson9763f2e2017-03-28 08:27:23 +0100110}
111
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100112# Given 'VAR1=VAL VAR2=VAL2 ... cmd arg1 arg2 ... argN' run the 'cmd' with the args
113# with the modified environment {VAR1=VAL,VAL2=,...}.
114#
115# Also prints the command to be run if verbose mode is enabled.
Orion Hodson9763f2e2017-03-28 08:27:23 +0100116function verbose_run() {
117 if [ "$VERBOSE" = "yes" ]; then
118 echo "$@"
119 fi
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100120
121 env "$@"
Orion Hodson9763f2e2017-03-28 08:27:23 +0100122}
123
Nicolas Geoffray162a5702017-08-04 09:28:32 +0000124# Parse a colon-separated list into an array (e.g. "foo.dex:bar.dex" -> (foo.dex bar.dex))
125PARSE_CLASSPATH_RESULT=() # Return value will be here due to shell limitations.
126parse_classpath() {
127 local cp="$1"
128 local oldifs=$IFS
129
130 local cp_array
131 cp_array=()
132
133 IFS=":"
134 for part in $cp; do
135 cp_array+=("$part")
136 done
137 IFS=$oldifs
138
139 PARSE_CLASSPATH_RESULT=("${cp_array[@]}")
140}
141
142# Sets 'PARSE_CLASSPATH_RESULT' to an array of class path dex files.
143# e.g. (-cp foo/classes.dex:bar/classes.dex) -> (foo/classes.dex bar/classes.dex)
144find_cp_in_args() {
145 local found="false"
146 local index=0
147 local what
148
149 while [[ $# -gt 0 ]]; do
150 case "$1" in
151 -cp|-classpath)
152 parse_classpath "$2"
153 # Sets 'PARSE_CLASSPATH_RESULT' to an array of class path dex files.
154 # Subsequent parses will overwrite the preceding.
155 shift
156 ;;
157 esac
158 shift
159 done
160}
161
162# Delete the 'oat' directories relative to the classpath's dex files.
163# e.g. (foo/classes.dex bar/classes.dex) would delete (foo/oat bar/oat) directories.
164cleanup_oat_directory() {
165 local classpath
166 classpath=("$@")
167
168 local dirpath
169
170 for path in "${classpath[@]}"; do
171 dirpath="$(dirname "$path")"
172 [[ -d "$dirpath" ]] && verbose_run rm -rf "$dirpath/oat"
173 done
174}
175
176# Parse -cp <CP>, -classpath <CP>, and $CLASSPATH to find the dex files.
177# Each dex file's directory will have an 'oat' file directory, delete it.
178# Input: Command line arguments to the art script.
179# e.g. -cp foo/classes.dex:bar/classes.dex would delete (foo/oat bar/oat) directories.
180cleanup_oat_directory_for_classpath() {
Nicolas Geoffrayc0c07852017-08-08 09:44:15 +0100181 if [ "$CLEAN_OAT_FILES" = "yes" ]; then
182 # First try: Use $CLASSPATH environment variable.
183 parse_classpath "$CLASSPATH"
184 # Second try: Look for latest -cp or -classpath arg which will take precedence.
185 find_cp_in_args "$@"
Nicolas Geoffray162a5702017-08-04 09:28:32 +0000186
Nicolas Geoffrayc0c07852017-08-08 09:44:15 +0100187 cleanup_oat_directory "${PARSE_CLASSPATH_RESULT[@]}"
188 fi
Nicolas Geoffray162a5702017-08-04 09:28:32 +0000189}
190
Igor Murashkind54ac262017-07-26 11:16:23 -0700191# Attempt to find $ANDROID_ROOT/framework/<isa>/core.art' without knowing what <isa> is.
192function check_if_boot_image_file_exists() {
193 local image_location_dir="$1"
194 local image_location_name="$2"
195
196 # Expand image_files to a list of existing image files on the disk.
197 # If no such files exist, it expands to single element 'dir/*/file' with a literal '*'.
198 local image_files
199 image_files=("$image_location_dir"/*/"$image_location_name") # avoid treating "*" as literal.
200
201 # Array always has at least 1 element. Test explicitly whether the file exists.
202 [[ -e "${image_files[0]}" ]]
203}
204
Igor Murashkin7fef4eb2017-07-14 15:45:47 -0700205# Automatically find the boot image location. It uses core.art by default.
206# On a real device, it might only have a boot.art, so use that instead when core.art does not exist.
207function detect_boot_image_location() {
208 local image_location_dir="$ANDROID_ROOT/framework"
209 local image_location_name="core.art"
210
Igor Murashkind54ac262017-07-26 11:16:23 -0700211 # If there are no existing core.art, try to find boot.art.
212 # If there is no boot.art then leave it as-is, assumes -Ximage is explicitly used.
213 # Otherwise let dalvikvm give the error message about an invalid image file.
214 if ! check_if_boot_image_file_exists "$image_location_dir" "core.art" && \
215 check_if_boot_image_file_exists "$image_location_dir" "boot.art"; then
Igor Murashkin7fef4eb2017-07-14 15:45:47 -0700216 image_location_name="boot.art"
217 fi
218
219 local image_location="$image_location_dir/$image_location_name"
220 echo "$image_location"
221}
222
Nicolas Geoffray162a5702017-08-04 09:28:32 +0000223# Runs dalvikvm, returns its exit code.
224# (Oat directories are cleaned up in between runs)
Orion Hodson9763f2e2017-03-28 08:27:23 +0100225function run_art() {
Igor Murashkin7fef4eb2017-07-14 15:45:47 -0700226 local image_location="$(detect_boot_image_location)"
Nicolas Geoffray162a5702017-08-04 09:28:32 +0000227 local ret
Igor Murashkin7fef4eb2017-07-14 15:45:47 -0700228
Nicolas Geoffray162a5702017-08-04 09:28:32 +0000229 # First cleanup any left-over 'oat' files from the last time dalvikvm was run.
230 cleanup_oat_directory_for_classpath "$@"
231 # Run dalvikvm.
Orion Hodson9763f2e2017-03-28 08:27:23 +0100232 verbose_run ANDROID_DATA=$ANDROID_DATA \
233 ANDROID_ROOT=$ANDROID_ROOT \
234 LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
235 PATH=$ANDROID_ROOT/bin:$PATH \
236 LD_USE_LOAD_BIAS=1 \
237 $LAUNCH_WRAPPER $ART_BINARY_PATH $lib \
238 -XXlib:$LIBART \
239 -Xnorelocate \
Igor Murashkin7fef4eb2017-07-14 15:45:47 -0700240 -Ximage:"$image_location" \
Orion Hodson9763f2e2017-03-28 08:27:23 +0100241 "$@"
Nicolas Geoffray162a5702017-08-04 09:28:32 +0000242 ret=$?
243
244 # Avoid polluting disk with 'oat' files after dalvikvm has finished.
245 cleanup_oat_directory_for_classpath "$@"
246
247 # Forward exit code of dalvikvm.
248 return $ret
Orion Hodson9763f2e2017-03-28 08:27:23 +0100249}
250
251while [[ "$1" = "-"* ]]; do
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100252 case "$1" in
Orion Hodson9763f2e2017-03-28 08:27:23 +0100253 --)
254 # No more arguments for this script.
255 shift
256 break
257 ;;
258 --32)
259 ART_BINARY=dalvikvm32
260 ;;
261 --64)
262 ART_BINARY=dalvikvm64
263 ;;
264 --callgrind)
265 LAUNCH_WRAPPER="valgrind --tool=callgrind"
266 ;;
267 -d)
268 ;& # Fallthrough
269 --debug)
270 LIBART="libartd.so"
Andreas Gampe1c5b42f2017-06-15 18:20:45 -0700271 # Expect that debug mode wants all checks.
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100272 EXTRA_OPTIONS+=(-XX:SlowDebug=true)
Orion Hodson9763f2e2017-03-28 08:27:23 +0100273 ;;
274 --gdb)
275 LIBART="libartd.so"
276 LAUNCH_WRAPPER="gdb --args"
277 ;;
278 --help)
279 usage
280 exit 0
281 ;;
282 --invoke-with)
283 LAUNCH_WRAPPER=$2
284 shift
285 ;;
286 --perf)
287 PERF="record"
288 ;;
289 --perf-report)
290 PERF="report"
291 ;;
292 --profile)
293 JIT_PROFILE="yes"
294 ;;
295 --verbose)
296 VERBOSE="yes"
297 ;;
Nicolas Geoffrayc0c07852017-08-08 09:44:15 +0100298 --no-clean)
299 CLEAN_OAT_FILES="no"
300 ;;
Orion Hodson9763f2e2017-03-28 08:27:23 +0100301 --*)
302 echo "unknown option: $1" 1>&2
303 usage
304 exit 1
305 ;;
306 *)
307 break
308 ;;
309 esac
310 shift
Nicolas Geoffrayf63a0a52014-09-02 15:24:25 +0100311done
312
Orion Hodson9763f2e2017-03-28 08:27:23 +0100313if [ $# -eq 0 ]; then
314 usage
315 exit 1
316fi
317
Brian Carlstrom87bb26f2014-09-08 11:13:47 -0700318PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
319ANDROID_ROOT=$PROG_DIR/..
Orion Hodson9763f2e2017-03-28 08:27:23 +0100320ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
Brian Carlstrom87bb26f2014-09-08 11:13:47 -0700321
Orion Hodson9763f2e2017-03-28 08:27:23 +0100322if [ ! -x "$ART_BINARY_PATH" ]; then
323 cat 1>&2 <<EOF
324Android Runtime not found: $ART_BINARY_PATH
325This script should be in the same directory as the Android Runtime ($ART_BINARY).
326EOF
327 exit 1
328fi
329
330LIBDIR="$(find_libdir $ART_BINARY_PATH)"
331LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBDIR
Orion Hodson9763f2e2017-03-28 08:27:23 +0100332
Nicolas Geoffray70a998c2014-12-04 17:05:22 +0000333# If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own,
334# and ensure we delete it at the end.
335if [ "$ANDROID_DATA" = "/data" ] || [ "$ANDROID_DATA" = "" ]; then
Igor Murashkin7fef4eb2017-07-14 15:45:47 -0700336 if [[ $PWD != / ]]; then
337 ANDROID_DATA="$PWD/android-data$$"
338 else
339 # Use /data/local/tmp when running this from adb shell, since it starts out in /
340 # by default.
341 ANDROID_DATA="$ANDROID_DATA/local/tmp/android-data$$"
342 fi
Igor Murashkind54ac262017-07-26 11:16:23 -0700343 mkdir -p "$ANDROID_DATA"
Orion Hodson9763f2e2017-03-28 08:27:23 +0100344 DELETE_ANDROID_DATA="yes"
Nicolas Geoffray70a998c2014-12-04 17:05:22 +0000345fi
346
Orion Hodson9763f2e2017-03-28 08:27:23 +0100347if [ "$PERF" != "" ]; then
348 LAUNCH_WRAPPER="perf record -g -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER"
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100349 EXTRA_OPTIONS+=(-Xcompiler-option --generate-debug-info)
Nicolas Geoffraye099a612014-12-12 13:52:00 +0000350fi
351
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000352if [ "$JIT_PROFILE" = "yes" ]; then
353 # Create the profile. The runtime expects profiles to be created before
354 # execution.
355 PROFILE_PATH="$ANDROID_DATA/primary.prof"
Igor Murashkind54ac262017-07-26 11:16:23 -0700356 touch "$PROFILE_PATH"
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000357
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100358 # Replace the compiler filter with quicken so that we
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000359 # can capture the profile.
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100360 ARGS_WITH_QUICKEN=
361 replace_compiler_filter_with_quicken "$@"
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000362
363 run_art -Xjitsaveprofilinginfo \
364 -Xps-min-methods-to-save:1 \
365 -Xps-min-classes-to-save:1 \
366 -Xps-min-notification-before-wake:10 \
367 -Xps-profile-path:$PROFILE_PATH \
368 -Xusejit:true \
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100369 "${ARGS_WITH_QUICKEN[@]}" \
Igor Murashkin11942442017-07-20 11:08:34 -0700370 &> "$ANDROID_DATA/profile_gen.log"
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000371 EXIT_STATUS=$?
372
373 if [ $EXIT_STATUS != 0 ]; then
Igor Murashkind54ac262017-07-26 11:16:23 -0700374 echo "Profile run failed: " >&2
375 cat "$ANDROID_DATA/profile_gen.log" >&2
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000376 clean_android_data
377 exit $EXIT_STATUS
378 fi
379
Igor Murashkind54ac262017-07-26 11:16:23 -0700380 # Wipe dalvik-cache so that a subsequent run_art must regenerate it.
381 # Leave $ANDROID_DATA intact since it contains our profile file.
382 rm -rf "$ANDROID_DATA/dalvik-cache"
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000383
384 # Append arguments so next invocation of run_art uses the profile.
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100385 EXTRA_OPTIONS+=(-Xcompiler-option --profile-file="$PROFILE_PATH")
Nicolas Geoffray9d7baf42017-04-19 09:01:29 +0000386fi
387
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100388# Protect additional arguments in quotes to preserve whitespaces (used by
389# run-jdwp-test.sh when running on device), '$' (may be used as part of
390# classpath) and other special characters when evaluated.
391EXTRA_OPTIONS+=("$@")
Calin Juravle64f45cb2017-03-16 19:58:26 -0700392
Vladimir Markoafd44ea2017-07-14 13:52:02 +0100393run_art "${EXTRA_OPTIONS[@]}"
Orion Hodson9763f2e2017-03-28 08:27:23 +0100394EXIT_STATUS=$?
Calin Juravleaa980612014-10-20 15:58:57 +0100395
Orion Hodson9763f2e2017-03-28 08:27:23 +0100396if [ "$PERF" != "" ]; then
397 if [ "$PERF" = report ]; then
Calin Juravleaa980612014-10-20 15:58:57 +0100398 perf report -i $ANDROID_DATA/perf.data
399 fi
400 echo "Perf data saved in: $ANDROID_DATA/perf.data"
401else
Orion Hodson9763f2e2017-03-28 08:27:23 +0100402 # Perf output is placed under $ANDROID_DATA so not cleaned when perf options used.
403 clean_android_data
Calin Juravleaa980612014-10-20 15:58:57 +0100404fi
405
Nicolas Geoffray89c4e282014-03-24 09:33:30 +0000406exit $EXIT_STATUS