• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#! /bin/sh
2# Copyright (C) 2011 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# This script is used on host and device. It uses a common subset
17# shell dialect that should work on the host (e.g. bash), and
18# Android (e.g. mksh). Try to switch to bash if the shebang above
19# has launched a pessimal shell on host.
20if [ -z "$KSH_VERSION" -a -z "$BASH_VERSION" -a -n "$(which bash)" ]; then
21  exec bash -c ". $0" -- "$@"
22fi
23
24######################################
25# Functions
26######################################
27function find_libdir() {
28  # Get the actual file, $1 is the ART_BINARY_PATH and may be a symbolic link.
29  # Use realpath instead of readlink because Android does not have a readlink.
30  if [[ "$(realpath "$1")" == *dalvikvm64 ]]; then
31    echo "lib64"
32  else
33    echo "lib"
34  fi
35}
36
37function usage() {
38  cat 1>&2 <<EOF
39Usage: art [OPTIONS] [--] [ART_OPTIONS] CLASS
40
41Supported OPTIONS include:
42  --32                     Use the 32-bit Android Runtime.
43  --64                     Use the 64-bit Android Runtime.
44  -d                       Use the debug ART library (libartd.so).
45  --debug                  Equivalent to -d.
46  --gdb                    Launch the Android Runtime in gdb.
47  --gdbserver <comms>      Launch the Android Runtime in gdbserver using the
48                           supplied communication channel.
49  --help                   Display usage message.
50  --invoke-with <program>  Launch the Android Runtime in <program>.
51  --perf                   Launch the Android Runtime with perf recording.
52  --perf-report            Launch the Android Runtime with perf recording with
53                           report upon completion.
54  --profile                Run with profiling, then run using profile data.
55  --verbose                Run script verbosely.
56  --no-clean               Don't cleanup oat directories.
57  --no-compile             Don't invoke dex2oat before running.
58  --allow-default-jdwp     Don't automatically put in -XjdwpProvider:none.
59                           You probably do not want this.
60
61The ART_OPTIONS are passed directly to the Android Runtime.
62
63Example:
64  art --32 -cp my_classes.dex MainClass
65
66Common errors:
67  1) Not having core.art available (see $ANDROID_BUILD_TOP/art/Android.mk).
68     eg m -j32 build-art-host
69  2) Not having boot.art available (see $ANDROID_BUILD_TOP/build/make/core/dex_preopt_libart_boot.mk)
70     eg m -j32 out/target/product/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art
71EOF
72}
73
74function clean_android_data() {
75  if [ "$DELETE_ANDROID_DATA" = "yes" ]; then
76    rm -rf $ANDROID_DATA
77  fi
78}
79
80# Given 'VAR1=VAL VAR2=VAL2 ... cmd arg1 arg2 ... argN' run the 'cmd' with the args
81# with the modified environment {VAR1=VAL,VAL2=,...}.
82#
83# Also prints the command to be run if verbose mode is enabled.
84function verbose_run() {
85  if [ "$VERBOSE" = "yes" ]; then
86    echo "$@"
87  fi
88
89  env "$@"
90}
91
92# Parse a colon-separated list into an array (e.g. "foo.dex:bar.dex" -> (foo.dex bar.dex))
93PARSE_CLASSPATH_RESULT=()  # Return value will be here due to shell limitations.
94parse_classpath() {
95  local cp="$1"
96  local oldifs=$IFS
97
98  local cp_array
99  cp_array=()
100
101  IFS=":"
102  for part in $cp; do
103    cp_array+=("$part")
104  done
105  IFS=$oldifs
106
107  PARSE_CLASSPATH_RESULT=("${cp_array[@]}")
108}
109
110# Sets 'PARSE_CLASSPATH_RESULT' to an array of class path dex files.
111# e.g. (-cp foo/classes.dex:bar/classes.dex) -> (foo/classes.dex bar/classes.dex)
112find_cp_in_args() {
113  local found="false"
114  local index=0
115  local what
116
117  while [[ $# -gt 0 ]]; do
118    case "$1" in
119      -cp|-classpath)
120        parse_classpath "$2"
121        # Sets 'PARSE_CLASSPATH_RESULT' to an array of class path dex files.
122        # Subsequent parses will overwrite the preceding.
123        shift
124        ;;
125    esac
126    shift
127  done
128}
129
130# Delete the 'oat' directories relative to the classpath's dex files.
131# e.g. (foo/classes.dex bar/classes.dex) would delete (foo/oat bar/oat) directories.
132cleanup_oat_directory() {
133  local classpath
134  classpath=("$@")
135
136  local dirpath
137
138  for path in "${classpath[@]}"; do
139    dirpath="$(dirname "$path")"
140    [[ -d "$dirpath" ]] && verbose_run rm -rf "$dirpath/oat"
141  done
142}
143
144# Parse -cp <CP>, -classpath <CP>, and $CLASSPATH to find the dex files.
145# Each dex file's directory will have an 'oat' file directory, delete it.
146# Input: Command line arguments to the art script.
147# e.g. -cp foo/classes.dex:bar/classes.dex would delete (foo/oat bar/oat) directories.
148cleanup_oat_directory_for_classpath() {
149  if [ "$CLEAN_OAT_FILES" = "yes" ]; then
150    # First try: Use $CLASSPATH environment variable.
151    parse_classpath "$CLASSPATH"
152    # Second try: Look for latest -cp or -classpath arg which will take precedence.
153    find_cp_in_args "$@"
154
155    cleanup_oat_directory "${PARSE_CLASSPATH_RESULT[@]}"
156  fi
157}
158
159# Attempt to find $ANDROID_ROOT/framework/<isa>/core.art' without knowing what <isa> is.
160function check_if_boot_image_file_exists() {
161  local image_location_dir="$1"
162  local image_location_name="$2"
163
164  # Expand image_files to a list of existing image files on the disk.
165  # If no such files exist, it expands to single element 'dir/*/file' with a literal '*'.
166  local image_files
167  image_files=("$image_location_dir"/*/"$image_location_name") # avoid treating "*" as literal.
168
169  # Array always has at least 1 element. Test explicitly whether the file exists.
170  [[ -e "${image_files[0]}" ]]
171}
172
173# Automatically find the boot image location. It uses core.art by default.
174# On a real device, it might only have a boot.art, so use that instead when core.art does not exist.
175function detect_boot_image_location() {
176  local image_location_dir="$ANDROID_ROOT/framework"
177  local image_location_name="core.art"
178
179  # If there are no existing core.art, try to find boot.art.
180  # If there is no boot.art then leave it as-is, assumes -Ximage is explicitly used.
181  # Otherwise let dalvikvm give the error message about an invalid image file.
182  if ! check_if_boot_image_file_exists "$image_location_dir" "core.art" && \
183       check_if_boot_image_file_exists "$image_location_dir" "boot.art"; then
184    image_location_name="boot.art"
185  fi
186
187  local image_location="$image_location_dir/$image_location_name"
188  echo "$image_location"
189}
190
191function run_dex2oat() {
192  local class_loader_context=
193  for dex_file in "${DEX2OAT_CLASSPATH[@]}"
194  do
195    while [ -h "$dex_file" ]; do
196      # On Mac OS, readlink -f doesn't work.
197      dex_file="$(readlink "$dex_file")"
198    done
199    # Create oat file directory.
200    verbose_run mkdir -p $(dirname "$dex_file")/oat/$ISA
201    local oat_file=$(basename "$dex_file")
202    local oat_file=$(dirname "$dex_file")/oat/$ISA/${oat_file%.*}.odex
203    if [ "$GENERATE_APP_IMAGE" = "yes" ]; then
204      local art_file=$(basename "$dex_file")
205      local art_file=$(dirname "$dex_file")/oat/$ISA/${art_file%.*}.art
206      DEX2OAT_FLAGS+=("--app-image-file=$art_file")
207    fi
208
209    # When running dex2oat use the exact same context as when running dalvikvm.
210    # (see run_art function)
211    verbose_run ANDROID_DATA=$ANDROID_DATA                    \
212          ANDROID_ROOT=$ANDROID_ROOT                          \
213          ANDROID_I18N_ROOT=$ANDROID_I18N_ROOT                \
214          ANDROID_ART_ROOT=$ANDROID_ART_ROOT                  \
215          ANDROID_TZDATA_ROOT=$ANDROID_TZDATA_ROOT            \
216          LD_LIBRARY_PATH=$LD_LIBRARY_PATH                    \
217          PATH=$ANDROID_ROOT/bin:$PATH                        \
218          LD_USE_LOAD_BIAS=1                                  \
219          ANDROID_LOG_TAGS=$ANDROID_LOG_TAGS                  \
220          $DEX2OAT_BINARY_PATH                                \
221          --runtime-arg -Xnorelocate                          \
222          --boot-image=$DEX2OAT_BOOT_IMAGE                    \
223          --instruction-set=$ISA                              \
224          --class-loader-context="PCL[$class_loader_context]" \
225          "${DEX2OAT_FLAGS[@]}"                               \
226          --dex-file=$dex_file                                \
227          --oat-file=$oat_file
228    if [[ -n $class_loader_context ]]; then
229      class_loader_context+=":"
230    fi
231    class_loader_context+="$dex_file"
232  done
233}
234
235# Extract the dex2oat flags from the list of arguments.
236# -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array
237# -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH
238# -Ximage argument is stored in DEX2OAT_BOOT_IMAGE
239# -Xbootclasspath argument is stored in DEX2OAT_BCP
240# -Xbootclasspath-locations argument is stored in DEX2OAT_BCP_LOCS
241function extract_dex2oat_flags() {
242  while [ $# -gt 0 ]; do
243    case $1 in
244      -Xcompiler-option)
245        DEX2OAT_FLAGS+=("$2")
246
247        # Enable app images for profile filters
248        case $2 in
249          --compiler-filter=speed-profile)
250            GENERATE_APP_IMAGE="yes"
251            ;;
252          --compiler-filter=everything-profile)
253            GENERATE_APP_IMAGE="yes"
254            ;;
255        esac
256
257        shift
258        ;;
259      -Ximage:*)
260        DEX2OAT_BOOT_IMAGE=$1
261        # Remove '-Ximage:' from the argument.
262        DEX2OAT_BOOT_IMAGE=${DEX2OAT_BOOT_IMAGE##-Ximage:}
263        ;;
264      -Xbootclasspath:*)
265        DEX2OAT_BCP=$1
266        # Remove '-Xbootclasspath:' from the argument.
267        DEX2OAT_BCP=${DEX2OAT_BCP##-Xbootclasspath:}
268        ;;
269      -Xbootclasspath-locations:*)
270        DEX2OAT_BCP_LOCS=$1
271        # Remove '-Xbootclasspath-locations:' from the argument.
272        DEX2OAT_BCP_LOCS=${DEX2OAT_BCP_LOCS##-Xbootclasspath-locations:}
273        ;;
274      -cp)
275        # Reset any previously parsed classpath, just like dalvikvm
276        # only supports one -cp argument.
277        DEX2OAT_CLASSPATH=()
278        # TODO: support -classpath and CLASSPATH
279        local oifs=$IFS
280        IFS=':'
281        for classpath_elem in $2
282        do
283          DEX2OAT_CLASSPATH+=("$classpath_elem")
284        done
285        shift
286        IFS=$oifs
287        ;;
288    esac
289    shift
290  done
291}
292
293# Runs dalvikvm, returns its exit code.
294# (Oat directories are cleaned up in between runs)
295function run_art() {
296  local ret
297
298  # Run dalvikvm.
299  verbose_run ANDROID_DATA="$ANDROID_DATA"                  \
300              ANDROID_ROOT="$ANDROID_ROOT"                  \
301              ANDROID_I18N_ROOT="$ANDROID_I18N_ROOT"        \
302              ANDROID_ART_ROOT="$ANDROID_ART_ROOT"          \
303              ANDROID_TZDATA_ROOT="$ANDROID_TZDATA_ROOT"    \
304              LD_LIBRARY_PATH="$LD_LIBRARY_PATH"            \
305              PATH="$ANDROID_ROOT/bin:$PATH"                \
306              LD_USE_LOAD_BIAS=1                            \
307              ANDROID_LOG_TAGS="$ANDROID_LOG_TAGS"          \
308              $LAUNCH_WRAPPER $ART_BINARY_PATH $lib         \
309              -XXlib:"$LIBART"                              \
310              -Xnorelocate                                  \
311              -Ximage:"$DEFAULT_IMAGE_LOCATION"             \
312              "$@"
313  ret=$?
314
315  # Avoid polluting disk with 'oat' files after dalvikvm has finished.
316  cleanup_oat_directory_for_classpath "$@"
317
318  # Forward exit code of dalvikvm.
319  return $ret
320}
321
322######################################
323# Globals
324######################################
325ART_BINARY=dalvikvm
326DEX2OAT_BINARY=dex2oat
327DEX2OAT_SUFFIX=""
328DELETE_ANDROID_DATA="no"
329LAUNCH_WRAPPER=
330LIBART=libart.so
331JIT_PROFILE="no"
332ALLOW_DEFAULT_JDWP="no"
333VERBOSE="no"
334CLEAN_OAT_FILES="yes"
335RUN_DEX2OAT="yes"
336EXTRA_OPTIONS=()
337DEX2OAT_FLAGS=()
338DEX2OAT_CLASSPATH=()
339GENERATE_APP_IMAGE="no"
340
341# Parse arguments
342while [[ "$1" = "-"* ]]; do
343  case "$1" in
344  --)
345    # No more arguments for this script.
346    shift
347    break
348    ;;
349  --32)
350    ART_BINARY=dalvikvm32
351    DEX2OAT_SUFFIX=32
352    ;;
353  --64)
354    ART_BINARY=dalvikvm64
355    DEX2OAT_SUFFIX=64
356    ;;
357  -d)
358    ;& # Fallthrough
359  --debug)
360    LIBART="libartd.so"
361    DEX2OAT_BINARY="dex2oatd"
362    # Expect that debug mode wants all checks.
363    EXTRA_OPTIONS+=(-XX:SlowDebug=true)
364    ;;
365  --gdbserver)
366    LAUNCH_WRAPPER="gdbserver $2"
367    shift
368    ;;
369  --gdb)
370    LIBART="libartd.so"
371    LAUNCH_WRAPPER="gdb --args"
372    ;;
373  --help)
374    usage
375    exit 0
376    ;;
377  --invoke-with)
378    LAUNCH_WRAPPER=$2
379    shift
380    ;;
381  --perf)
382    PERF="record"
383    ;;
384  --perf-report)
385    PERF="report"
386    ;;
387  --profile)
388    JIT_PROFILE="yes"
389    ;;
390  --verbose)
391    VERBOSE="yes"
392    ;;
393  --no-clean)
394    CLEAN_OAT_FILES="no"
395    ;;
396  --no-compile)
397    CLEAN_OAT_FILES="no"
398    RUN_DEX2OAT="no"
399    ;;
400  --allow-default-jdwp)
401    ALLOW_DEFAULT_JDWP="yes"
402    ;;
403  --*)
404    echo "unknown option: $1" 1>&2
405    usage
406    exit 1
407    ;;
408  *)
409    break
410    ;;
411  esac
412  shift
413done
414
415if [ $# -eq 0 ]; then
416  usage
417  exit 1
418fi
419
420# Follow all sym links to get the program name.
421if [[ -n "$BASH_SOURCE" ]]; then
422  PROG_NAME="$BASH_SOURCE"
423else
424  PROG_NAME="$0"
425fi
426while [ -h "$PROG_NAME" ]; do
427  # On Mac OS, readlink -f doesn't work.
428  PROG_NAME="$(readlink "$PROG_NAME")"
429done
430
431PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
432ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
433
434# If ANDROID_I18N_ROOT is not set, try to detect whether we are running on
435# target or host and set that environment variable to the usual default value.
436if [ -z "$ANDROID_I18N_ROOT" ]; then
437  # This script is used on host and target (device). However, the (expected)
438  # default value `ANDROID_I18N_ROOT` is not the same on host and target:
439  # - on host, `ANDROID_I18N_ROOT` is expected to be
440  #   "$ANDROID_ROOT/com.android.i18n";
441  # - on target, `ANDROID_I18N_ROOT` is expected to be
442  #   "/apex/com.android.i18n".
443  #
444  # We use the presence/absence of the `$ANDROID_ROOT/../apex` directory to
445  # determine whether we are on target or host (this is brittle, but simple).
446  if [ -d "$ANDROID_ROOT/../apex" ]; then
447    # Target case.
448    ANDROID_I18N_ROOT="/apex/com.android.i18n"
449  else
450    # Host case.
451    ANDROID_I18N_ROOT="$ANDROID_ROOT/com.android.i18n"
452  fi
453fi
454
455# If ANDROID_ART_ROOT is not set, try to detect whether we are running on
456# target or host and set that environment variable to the usual default value.
457if [ -z "$ANDROID_ART_ROOT" ]; then
458  # This script is used on host and target (device). However, the (expected)
459  # default value `ANDROID_ART_ROOT` is not the same on host and target:
460  # - on host, `ANDROID_ART_ROOT` is expected to be
461  #   "$ANDROID_ROOT/com.android.art";
462  # - on target, `ANDROID_ART_ROOT` is expected to be
463  #   "/apex/com.android.art".
464  #
465  # We use the presence/absence of the `$ANDROID_ROOT/../apex` directory to
466  # determine whether we are on target or host (this is brittle, but simple).
467  if [ -d "$ANDROID_ROOT/../apex" ]; then
468    # Target case.
469    ANDROID_ART_ROOT="/apex/com.android.art"
470  else
471    # Host case.
472    ANDROID_ART_ROOT="$ANDROID_ROOT/com.android.art"
473  fi
474fi
475
476# If ANDROID_TZDATA_ROOT is not set, try to detect whether we are running on
477# target or host and set that environment variable to the usual default value.
478if [ -z "$ANDROID_TZDATA_ROOT" ]; then
479  # This script is used on host and target (device). However, the (expected)
480  # default value `ANDROID_TZDATA_ROOT` is not the same on host and target:
481  # - on host, `ANDROID_TZDATA_ROOT` is expected to be
482  #   "$ANDROID_ROOT/com.android.tzdata";
483  # - on target, `ANDROID_TZDATA_ROOT` is expected to be
484  #   "/apex/com.android.tzdata".
485  #
486  # We use the presence/absence of the `$ANDROID_ROOT/../apex` directory to
487  # determine whether we are on target or host (this is brittle, but simple).
488  if [ -d "$ANDROID_ROOT/../apex" ]; then
489    # Target case.
490    ANDROID_TZDATA_ROOT="/apex/com.android.tzdata"
491  else
492    # Host case.
493    ANDROID_TZDATA_ROOT="$ANDROID_ROOT/com.android.tzdata"
494  fi
495fi
496
497ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
498
499if [ ! -x "$ART_BINARY_PATH" ]; then
500  cat 1>&2 <<EOF
501Android Runtime not found: $ART_BINARY_PATH
502This script should be in the same directory as the Android Runtime ($ART_BINARY).
503EOF
504  exit 1
505fi
506
507DEX2OAT_BINARY_PATH=$ANDROID_ROOT/bin/$DEX2OAT_BINARY$DEX2OAT_SUFFIX
508
509if [ ! -x "$DEX2OAT_BINARY_PATH" ]; then
510  echo "Warning: Android Compiler not found: $DEX2OAT_BINARY_PATH"
511fi
512
513######################################
514# Main program
515######################################
516
517# If android logging is not explicitly set, only print warnings and errors.
518if [ -z "$ANDROID_LOG_TAGS" ]; then
519  ANDROID_LOG_TAGS='*:w'
520fi
521
522LIBDIR="$(find_libdir $ART_BINARY_PATH)"
523LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBDIR
524DEFAULT_IMAGE_LOCATION="$(detect_boot_image_location)"
525DEX2OAT_BOOT_IMAGE="$DEFAULT_IMAGE_LOCATION"
526ISA=$(LD_LIBRARY_PATH=$LD_LIBRARY_PATH $ART_BINARY_PATH -showversion | (read art version number isa && echo $isa))
527
528# Extract the dex2oat flags from the list of arguments.
529# -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array
530# -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH
531# -Ximage argument is stored in DEX2OAT_BOOT_IMAGE
532extract_dex2oat_flags "$@"
533
534# If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own,
535# and ensure we delete it at the end.
536if [ "$ANDROID_DATA" = "/data" ] || [ "$ANDROID_DATA" = "" ]; then
537  if [[ $PWD != / ]]; then
538    ANDROID_DATA="$PWD/android-data$$"
539  else
540    # Use /data/local/tmp when running this from adb shell, since it starts out in /
541    # by default.
542    ANDROID_DATA="$ANDROID_DATA/local/tmp/android-data$$"
543  fi
544  mkdir -p "$ANDROID_DATA"
545  DELETE_ANDROID_DATA="yes"
546fi
547
548if [[ "$DEX2OAT_BCP" = "" && "$DEX2OAT_BCP_LOCS" != "" ]]; then
549  echo "Cannot use -Xbootclasspath-locations without -Xbootclasspath"
550  exit 1
551fi
552
553# Create boot class path filename or location list.
554# It takes one optional argument which is the prefix to be inserted before each entry.
555function get_boot_class_path() {
556  # Note: This must start with the CORE_IMG_JARS in Android.common_path.mk
557  local modules="core-oj core-libart okhttp bouncycastle apache-xml core-icu4j conscrypt"
558  local prefix="$1"
559  local result=""
560  local separator=""
561  for module in ${modules}; do
562    case "$module" in
563      (conscrypt)  local apex="com.android.conscrypt";;
564      (core-icu4j) local apex="com.android.i18n";;
565      (*)          local apex="com.android.art";;
566    esac
567    result+="${separator}${prefix}/apex/${apex}/javalib/${module}.jar"
568    separator=":"
569  done
570  echo "$result"
571}
572
573# Create default boot class path if none was provided.
574if [[ "$DEX2OAT_BCP" = "" ]]; then
575  ANDROID_ROOT_MINUS_PWD="${ANDROID_ROOT#$PWD/}"  # For example: out/host/linux-x86
576  if [[ "$ANDROID_ROOT_MINUS_PWD" == */host/* ]]; then
577    DEX2OAT_BCP="$(get_boot_class_path $ANDROID_ROOT)"
578    DEX2OAT_BCP_LOCS="$(get_boot_class_path $ANDROID_ROOT_MINUS_PWD)"
579  elif [[ "$ANDROID_ROOT_MINUS_PWD" == */target/* ]]; then
580    DEX2OAT_BCP="$(get_boot_class_path $ANDROID_ROOT)"
581    DEX2OAT_BCP_LOCS="$(get_boot_class_path)"
582  else
583    echo "Can not determine whether are running on host or target"
584    exit 1
585  fi
586  if [ "$VERBOSE" = "yes" ]; then
587    echo ANDROID_ROOT=$ANDROID_ROOT
588    echo DEX2OAT_BOOT_IMAGE=$DEX2OAT_BOOT_IMAGE
589    echo DEX2OAT_BCP=$DEX2OAT_BCP
590    echo DEX2OAT_BCP_LOCS=$DEX2OAT_BCP_LOCS
591  fi
592fi
593
594if [ "$DEX2OAT_BCP" != "" ]; then
595  EXTRA_OPTIONS+=("-Xbootclasspath:$DEX2OAT_BCP")
596  DEX2OAT_FLAGS+=("--runtime-arg" "-Xbootclasspath:$DEX2OAT_BCP")
597  if [ "$DEX2OAT_BCP_LOCS" != "" ]; then
598    EXTRA_OPTIONS+=("-Xbootclasspath-locations:$DEX2OAT_BCP_LOCS")
599    DEX2OAT_FLAGS+=("--runtime-arg" \
600                    "-Xbootclasspath-locations:$DEX2OAT_BCP_LOCS")
601  fi
602fi
603
604if [ "$PERF" != "" ]; then
605  LAUNCH_WRAPPER="perf record -g --call-graph dwarf -F 10000 -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER"
606  DEX2OAT_FLAGS+=(--generate-debug-info)
607fi
608
609if [ "$ALLOW_DEFAULT_JDWP" = "no" ]; then
610  EXTRA_OPTIONS+=(-XjdwpProvider:none)
611fi
612
613# First cleanup any left-over 'oat' files from the last time dalvikvm was run.
614cleanup_oat_directory_for_classpath "$@"
615
616# Protect additional arguments in quotes to preserve whitespaces (used by
617# run-jdwp-test.sh when running on device), '$' (may be used as part of
618# classpath) and other special characters when evaluated.
619EXTRA_OPTIONS+=("$@")
620
621if [ "$JIT_PROFILE" = "yes" ]; then
622  # Create the profile. The runtime expects profiles to be created before
623  # execution.
624  PROFILE_PATH="$ANDROID_DATA/primary.prof"
625  touch "$PROFILE_PATH"
626
627  run_art -Xjitsaveprofilinginfo               \
628          -Xps-min-methods-to-save:1           \
629          -Xps-min-classes-to-save:1           \
630          -Xps-min-notification-before-wake:10 \
631          -Xps-profile-path:$PROFILE_PATH      \
632          -Xusejit:true                        \
633          ${EXTRA_OPTIONS[@]}                  \
634          &> "$ANDROID_DATA/profile_gen.log"
635  EXIT_STATUS=$?
636
637  if [ $EXIT_STATUS != 0 ]; then
638    echo "Profile run failed: " >&2
639    cat "$ANDROID_DATA/profile_gen.log" >&2
640    clean_android_data
641    exit $EXIT_STATUS
642  fi
643
644  # Wipe dalvik-cache so that a subsequent run_art must regenerate it.
645  # Leave $ANDROID_DATA intact since it contains our profile file.
646  rm -rf "$ANDROID_DATA/dalvik-cache"
647
648  # Append arguments so next invocation of run_art uses the profile.
649  DEX2OAT_FLAGS+=(--profile-file="$PROFILE_PATH")
650fi
651
652if [ -x "$DEX2OAT_BINARY_PATH" ]; then
653  if [ "$RUN_DEX2OAT" = "yes" ]; then
654    # Run dex2oat before launching ART to generate the oat files for the classpath.
655    run_dex2oat
656  fi
657fi
658
659# Do not continue if the dex2oat failed.
660EXIT_STATUS=$?
661if [ $EXIT_STATUS != 0 ]; then
662  echo "Failed dex2oat invocation" >&2
663  exit $EXIT_STATUS
664fi
665
666run_art "${EXTRA_OPTIONS[@]}"
667EXIT_STATUS=$?
668
669if [ "$PERF" != "" ]; then
670  if [ "$PERF" = report ]; then
671    perf report -i $ANDROID_DATA/perf.data
672  fi
673  echo "Perf data saved in: $ANDROID_DATA/perf.data"
674else
675  # Perf output is placed under $ANDROID_DATA so not cleaned when perf options used.
676  clean_android_data
677fi
678
679exit $EXIT_STATUS
680