#!/bin/sh
#
# Run the code in test.jar using the host-mode virtual machine. The jar should
# contain a top-level class named Main to run.

msg() {
    if [ "$QUIET" = "n" ]; then
        echo "$@"
    fi
}

DEBUGGER="n"
PREBUILD="n"
GDB="n"
ISA="x86"
INTERPRETER="n"
VERIFY="y"
RELOCATE="y"
OPTIMIZE="y"
INVOKE_WITH=""
DEV_MODE="n"
QUIET="n"
FLAGS=""
COMPILER_FLAGS=""
BUILD_BOOT_OPT=""
SECONDARY_DEX=""
exe="${ANDROID_HOST_OUT}/bin/dalvikvm32"
main="Main"
DEX_VERIFY=""
DEX2OAT_SWAP="n"

while true; do
    if [ "x$1" = "x--quiet" ]; then
        QUIET="y"
        shift
    elif [ "x$1" = "x--prebuild" ]; then
        PREBUILD="y"
        shift
    elif [ "x$1" = "x--lib" ]; then
        shift
        if [ "x$1" = "x" ]; then
            echo "$0 missing argument to --lib" 1>&2
            exit 1
        fi
        LIB="$1"
        if [ `uname` = "Darwin" ]; then
            LIB=${LIB/%so/dylib}
        fi
        shift
    elif [ "x$1" = "x--boot" ]; then
        shift
        option="$1"
        BOOT_OPT="$option"
        BUILD_BOOT_OPT="--boot-image=${option#-Ximage:}"
        shift
    elif [ "x$1" = "x--debug" ]; then
        DEBUGGER="y"
        shift
    elif [ "x$1" = "x--gdb" ]; then
        GDB="y"
        DEV_MODE="y"
        shift
    elif [ "x$1" = "x--invoke-with" ]; then
        shift
        if [ "x$1" = "x" ]; then
            echo "$0 missing argument to --invoke-with" 1>&2
            exit 1
        fi
        if [ "x$INVOKE_WITH" = "x" ]; then
            INVOKE_WITH="$1"
        else
            INVOKE_WITH="$INVOKE_WITH $1"
        fi
        shift
    elif [ "x$1" = "x--dev" ]; then
        DEV_MODE="y"
        shift
    elif [ "x$1" = "x--interpreter" ]; then
        INTERPRETER="y"
        shift
    elif [ "x$1" = "x--64" ]; then
        ISA="x86_64"
        exe="${ANDROID_HOST_OUT}/bin/dalvikvm64"
        shift
    elif [ "x$1" = "x--no-verify" ]; then
        VERIFY="n"
        shift
    elif [ "x$1" = "x--no-optimize" ]; then
        OPTIMIZE="n"
        shift
    elif [ "x$1" = "x--no-relocate" ]; then
        RELOCATE="n"
        shift
    elif [ "x$1" = "x--relocate" ]; then
        RELOCATE="y"
        shift
    elif [ "x$1" = "x--secondary" ]; then
        SECONDARY_DEX=":$DEX_LOCATION/$TEST_NAME-ex.jar"
        shift
    elif [ "x$1" = "x-Xcompiler-option" ]; then
        shift
        option="$1"
        FLAGS="${FLAGS} -Xcompiler-option $option"
        COMPILER_FLAGS="${COMPILER_FLAGS} $option"
        shift
    elif [ "x$1" = "x--runtime-option" ]; then
        shift
        option="$1"
        FLAGS="${FLAGS} $option"
        shift
    elif [ "x$1" = "x--dex2oat-swap" ]; then
        DEX2OAT_SWAP="y"
        shift
    elif [ "x$1" = "x--" ]; then
        shift
        break
    elif expr "x$1" : "x--" >/dev/null 2>&1; then
        echo "unknown $0 option: $1" 1>&2
        exit 1
    else
        break
    fi
done

if [ "x$1" = "x" ] ; then
  main="Main"
else
  main="$1"
fi

msg "------------------------------"

export ANDROID_PRINTF_LOG=brief
if [ "$DEV_MODE" = "y" ]; then
    export ANDROID_LOG_TAGS='*:d'
else
    export ANDROID_LOG_TAGS='*:s'
fi
export ANDROID_DATA="$DEX_LOCATION"
export ANDROID_ROOT="${ANDROID_HOST_OUT}"
export LD_LIBRARY_PATH="${ANDROID_ROOT}/lib"
export DYLD_LIBRARY_PATH="${ANDROID_ROOT}/lib"

if [ "$DEX2OAT_SWAP" = "y" ]; then
  COMPILER_FLAGS="${COMPILER_FLAGS} --swap-file=$ANDROID_DATA/dex2oat.swap"
fi

if [ "$DEBUGGER" = "y" ]; then
    PORT=8000
    msg "Waiting for jdb to connect:"
    msg "    jdb -attach localhost:$PORT"
    DEBUGGER_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
fi

if [ "$GDB" = "y" ]; then
    if [ `uname` = "Darwin" ]; then
        gdb=lldb
        gdbargs="-- $exe"
        exe=
    else
        gdb=gdb
        gdbargs="--args $exe"
        # Enable for Emacs "M-x gdb" support. TODO: allow extra gdb arguments on command line.
        # gdbargs="--annotate=3 $gdbargs"
    fi
fi

if [ "$INTERPRETER" = "y" ]; then
    INT_OPTS="-Xint"
    if [ "$VERIFY" = "y" ] ; then
      COMPILER_FLAGS="${COMPILER_FLAGS} --compiler-filter=interpret-only"
    else
      COMPILER_FLAGS="${COMPILER_FLAGS} --compiler-filter=verify-none"
      DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
    fi
fi

if [ "$RELOCATE" = "y" ]; then
  FLAGS="${FLAGS} -Xrelocate"
  COMPILER_FLAGS="${COMPILER_FLAGS} --runtime-arg -Xnorelocate --include-patch-information"
  # Run test sets a fairly draconian ulimit that we will likely blow right over
  # since we are relocating. Get the total size of the /system/framework directory
  # in 512 byte blocks and set it as the ulimit. This should be more than enough
  # room.
  if [ ! `uname` = "Darwin" ]; then  # TODO: Darwin doesn't support "du -B..."
    ulimit -S $(du -c -B512 ${ANDROID_ROOT}/framework | tail -1 | cut -f1) || exit 1
  fi
else
  FLAGS="${FLAGS} -Xnorelocate"
  COMPILER_FLAGS="${COMPILER_FLAGS} --runtime-arg -Xnorelocate --no-include-patch-information"
fi

mkdir_cmd="mkdir -p ${DEX_LOCATION}/dalvik-cache/$ISA"
if [ "$PREBUILD" = "y" ]; then
  prebuild_cmd="${ANDROID_HOST_OUT}/bin/dex2oatd $COMPILER_FLAGS --instruction-set=$ISA $BUILD_BOOT_OPT --dex-file=$DEX_LOCATION/$TEST_NAME.jar --oat-file=$DEX_LOCATION/dalvik-cache/$ISA/$(echo $DEX_LOCATION/$TEST_NAME.jar/classes.dex | cut -d/ -f 2- | sed "s:/:@:g")"
else
  prebuild_cmd="true"
fi

JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
cmdline="$INVOKE_WITH $gdb $exe $gdbargs -XXlib:$LIB $DEX_VERIFY $JNI_OPTS $FLAGS $INT_OPTS $DEBUGGER_OPTS $BOOT_OPT -cp $DEX_LOCATION/$TEST_NAME.jar$SECONDARY_DEX $main"
if [ "$DEV_MODE" = "y" ]; then
  if [ "$PREBUILD" = "y" ]; then
    echo "$mkdir_cmd && $prebuild_cmd && $cmdline"
  elif [ "$RELOCATE" = "y" ]; then
    echo "$mkdir_cmd && $cmdline"
  else
    echo $cmdline
  fi
fi

cd $ANDROID_BUILD_TOP
$mkdir_cmd && $prebuild_cmd && $cmdline "$@"