• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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