Move to new art dalvikvm

Change-Id: Ib04bc9853b7084965fa0c9899c3e5f5ac42d4ce7
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 508ff1b..e84667d 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -137,9 +137,6 @@
 OATDUMP_SRC_FILES := \
 	src/oatdump.cc
 
-OATEXEC_SRC_FILES := \
-	src/oatexec.cc
-
 LIBART_COMMON_SRC_FILES := \
 	src/atomic.cc.arm \
 	src/barrier.cc \
diff --git a/build/Android.executable.mk b/build/Android.executable.mk
index ee968a7..83a1706 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -89,6 +89,8 @@
     LOCAL_SHARED_LIBRARIES += libstlport
   endif
 
+  LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/build/Android.executable.mk
+
   ifeq ($$(art_target_or_host),target)
     include $(BUILD_EXECUTABLE)
     ART_TARGET_EXECUTABLES := $(ART_TARGET_EXECUTABLES) $(TARGET_OUT_EXECUTABLES)/$$(LOCAL_MODULE)
@@ -102,12 +104,10 @@
 ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
   $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),target,ndebug))
   $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),target,ndebug))
-  $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),target,ndebug))
 endif
 ifeq ($(ART_BUILD_TARGET_DEBUG),true)
   $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),target,debug))
   $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),target,debug))
-  $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),target,debug))
 endif
 
 # We always build dex2oat and dependencies, even if the host build is otherwise disabled, since they are used to cross compile for the target.
@@ -120,9 +120,7 @@
 
 ifeq ($(ART_BUILD_HOST_NDEBUG),true)
   $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),host,ndebug))
-  $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),host,ndebug))
 endif
 ifeq ($(ART_BUILD_HOST_DEBUG),true)
   $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),host,debug))
-  $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),host,debug))
 endif
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 034e475..e2ee41a 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -65,7 +65,7 @@
 test-art-target-oat-$(1): $(ART_TEST_OUT)/oat-test-dex-$(1).jar test-art-target-sync
 	adb shell touch $(ART_TEST_DIR)/test-art-target-oat-$(1)
 	adb shell rm $(ART_TEST_DIR)/test-art-target-oat-$(1)
-	adb shell sh -c "oatexecd -Ximage:$(ART_TEST_DIR)/core.art -classpath $(ART_TEST_DIR)/oat-test-dex-$(1).jar -Djava.library.path=$(ART_TEST_DIR) $(1) $(2) && touch $(ART_TEST_DIR)/test-art-target-oat-$(1)"
+	adb shell sh -c "dalvikvm -XXlib:libartd.so -Ximage:$(ART_TEST_DIR)/core.art -classpath $(ART_TEST_DIR)/oat-test-dex-$(1).jar -Djava.library.path=$(ART_TEST_DIR) $(1) $(2) && touch $(ART_TEST_DIR)/test-art-target-oat-$(1)"
 	$(hide) (adb pull $(ART_TEST_DIR)/test-art-target-oat-$(1) /tmp/ && echo test-art-target-oat-$(1) PASSED) || (echo test-art-target-oat-$(1) FAILED && exit 1)
 	$(hide) rm /tmp/test-art-target-oat-$(1)
 
@@ -78,7 +78,7 @@
 	ANDROID_DATA=/tmp/android-data/test-art-host-oat-$(1) \
 	  ANDROID_ROOT=$(HOST_OUT) \
 	  LD_LIBRARY_PATH=$(HOST_OUT_SHARED_LIBRARIES) \
-	  oatexecd -Ximage:$(shell pwd)/$(HOST_CORE_IMG_OUT) -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
+	  dalvikvm -XXlib:libartd.so -Ximage:$(shell pwd)/$(HOST_CORE_IMG_OUT) -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
           && echo test-art-host-oat-$(1) PASSED || (echo test-art-host-oat-$(1) FAILED && exit 1)
 	$(hide) rm -r /tmp/android-data/test-art-host-oat-$(1)
 
@@ -88,7 +88,7 @@
 	ANDROID_DATA=/tmp/android-data/test-art-host-interpreter-oat-$(1) \
 	  ANDROID_ROOT=$(HOST_OUT) \
 	  LD_LIBRARY_PATH=$(HOST_OUT_SHARED_LIBRARIES) \
-	  oatexecd -Ximage:$(shell pwd)/$(HOST_CORE_IMG_OUT) -Xint -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
+	  dalvikvm -XXlib:libartd.so -Ximage:$(shell pwd)/$(HOST_CORE_IMG_OUT) -Xint -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
           && echo test-art-host-interpreter-oat-$(1) PASSED || (echo test-art-host-interpreter-oat-$(1) FAILED && exit 1)
 	$(hide) rm -r /tmp/android-data/test-art-host-interpreter-oat-$(1)
 
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
new file mode 100644
index 0000000..869478d
--- /dev/null
+++ b/dalvikvm/Android.mk
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := dalvikvm
+LOCAL_MODULE_TAGS := optional
+LOCAL_CPP_EXTENSION := cc
+LOCAL_SRC_FILES := dalvikvm.cc
+LOCAL_CFLAGS := -Werror
+LOCAL_SHARED_LIBRARIES := libnativehelper libstlport libdl
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include external/stlport/libstlport.mk
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := dalvikvm
+LOCAL_MODULE_TAGS := optional
+LOCAL_CPP_EXTENSION := cc
+LOCAL_SRC_FILES := dalvikvm.cc
+LOCAL_CFLAGS := -Werror
+LOCAL_SHARED_LIBRARIES := libnativehelper
+LOCAL_LDFLAGS := -ldl
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/src/oatexec.cc b/dalvikvm/dalvikvm.cc
similarity index 77%
rename from src/oatexec.cc
rename to dalvikvm/dalvikvm.cc
index c05266c..8612683 100644
--- a/src/oatexec.cc
+++ b/dalvikvm/dalvikvm.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * copyright (C) 2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,20 +14,17 @@
  * limitations under the License.
  */
 
+#include <dlfcn.h>
 #include <signal.h>
 
-#include <algorithm>
 #include <cstdio>
 #include <cstring>
 #include <string>
 
-#include "base/logging.h"
 #include "jni.h"
-#include "modifiers.h"
 #include "ScopedLocalRef.h"
 #include "toStringArray.h"
 #include "UniquePtr.h"
-#include "well_known_classes.h"
 
 namespace art {
 
@@ -40,14 +37,19 @@
   }
   // We now have a Method instance.  We need to call its
   // getModifiers() method.
-  jmethodID mid = env->GetMethodID(WellKnownClasses::java_lang_reflect_AbstractMethod,
-                                   "getModifiers", "()I");
+  jclass method_class = env->FindClass("java/lang/reflect/Method");
+  if (method_class == NULL) {
+    fprintf(stderr, "Failed to find class java.lang.reflect.Method\n");
+    return false;
+  }
+  jmethodID mid = env->GetMethodID(method_class, "getModifiers", "()I");
   if (mid == NULL) {
     fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n");
     return false;
   }
   int modifiers = env->CallIntMethod(reflected.get(), mid);
-  if ((modifiers & kAccPublic) == 0) {
+  static const int PUBLIC = 0x0001;  // java.lang.reflect.Modifiers.PUBLIC
+  if ((modifiers & PUBLIC) == 0) {
     return false;
   }
   return true;
@@ -102,8 +104,7 @@
 
 // Parse arguments.  Most of it just gets passed through to the runtime.
 // The JNI spec defines a handful of standard arguments.
-static int oatexec(int argc, char** argv) {
-  InitLogging(argv);
+static int dalvikvm(int argc, char** argv) {
   setvbuf(stdout, NULL, _IONBF, 0);
 
   // Skip over argv[0].
@@ -123,12 +124,19 @@
   //
   // [Do we need to catch & handle "-jar" here?]
   bool need_extra = false;
+  const char* lib = "libdvm.so";
+  const char* debug = NULL;
   const char* what = NULL;
   int curr_opt, arg_idx;
   for (curr_opt = arg_idx = 0; arg_idx < argc; arg_idx++) {
     if (argv[arg_idx][0] != '-' && !need_extra) {
       break;
     }
+    if (strncmp(argv[arg_idx], "-XXlib:", strlen("-XXlib:")) == 0) {
+      lib = argv[arg_idx] + strlen("-XXlib:");
+      continue;
+    }
+
     options[curr_opt++].optionString = argv[arg_idx];
 
     // Some options require an additional argument.
@@ -152,7 +160,30 @@
 
   // insert additional internal options here
 
-  DCHECK_LE(curr_opt, option_count);
+  if (curr_opt >= option_count) {
+    fprintf(stderr, "curr_opt(%d) >= option_count(%d)\n", curr_opt, option_count);
+    abort();
+    return EXIT_FAILURE;
+  }
+
+  // Find the JNI_CreateJavaVM implementation.
+  std::string library(lib);
+  if (debug != NULL) {
+    library += debug;
+  }
+  void* handle = dlopen(library.c_str(), RTLD_NOW);
+  if (handle == NULL) {
+    fprintf(stderr, "Failed to dlopen library %s: %s\n", library.c_str(), dlerror());
+    return EXIT_FAILURE;
+  }
+  const char* symbol = "JNI_CreateJavaVM";
+  void* sym = dlsym(handle, symbol);
+  if (handle == NULL) {
+    fprintf(stderr, "Failed to find symbol %s: %s\n", symbol, dlerror());
+    return EXIT_FAILURE;
+  }
+  typedef int (*Fn)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
+  Fn JNI_CreateJavaVM = reinterpret_cast<Fn>(sym);
 
   JavaVMInitArgs init_args;
   init_args.version = JNI_VERSION_1_6;
@@ -164,7 +195,7 @@
   JavaVM* vm = NULL;
   JNIEnv* env = NULL;
   if (JNI_CreateJavaVM(&vm, &env, &init_args) != JNI_OK) {
-    fprintf(stderr, "runtime failed to initialize (check log for details)\n");
+    fprintf(stderr, "Failed to initialize runtime (check log for details)\n");
     return EXIT_FAILURE;
   }
 
@@ -190,5 +221,5 @@
 } // namespace art
 
 int main(int argc, char** argv) {
-  return art::oatexec(argc, argv);
+  return art::dalvikvm(argc, argv);
 }
diff --git a/src/base/logging.cc b/src/base/logging.cc
index a19580c..2c6b6a8 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -28,9 +28,9 @@
 unsigned int gAborting = 0;
 
 static LogSeverity gMinimumLogSeverity = INFO;
-static std::string* gCmdLine;
-static std::string* gProgramInvocationName;
-static std::string* gProgramInvocationShortName;
+static std::string* gCmdLine = NULL;
+static std::string* gProgramInvocationName = NULL;
+static std::string* gProgramInvocationShortName = NULL;
 
 const char* GetCmdLine() {
   return (gCmdLine != NULL) ? gCmdLine->c_str() : NULL;
@@ -53,21 +53,28 @@
 // and a letter indicating the minimum priority level we're expected to log.
 // This can be used to reveal or conceal logs with specific tags.
 void InitLogging(char* argv[]) {
+  if (gCmdLine != NULL) {
+    return;
+  }
   // TODO: Move this to a more obvious InitART...
   Locks::Init();
 
   // Stash the command line for later use. We can use /proc/self/cmdline on Linux to recover this,
   // but we don't have that luxury on the Mac, and there are a couple of argv[0] variants that are
   // commonly used.
-  gCmdLine = new std::string(argv[0]);
-  for (size_t i = 1; argv[i] != NULL; ++i) {
-    gCmdLine->append(" ");
-    gCmdLine->append(argv[i]);
+  if (argv != NULL) {
+    gCmdLine = new std::string(argv[0]);
+    for (size_t i = 1; argv[i] != NULL; ++i) {
+      gCmdLine->append(" ");
+      gCmdLine->append(argv[i]);
+    }
+    gProgramInvocationName = new std::string(argv[0]);
+    const char* last_slash = strrchr(argv[0], '/');
+    gProgramInvocationShortName = new std::string((last_slash != NULL) ? last_slash + 1 : argv[0]);
+  } else {
+    // TODO: fall back to /proc/self/cmdline when argv is NULL on Linux
+    gCmdLine = new std::string("<unset>");
   }
-  gProgramInvocationName = new std::string(argv[0]);
-  const char* last_slash = strrchr(argv[0], '/');
-  gProgramInvocationShortName = new std::string((last_slash != NULL) ? last_slash + 1 : argv[0]);
-
   const char* tags = getenv("ANDROID_LOG_TAGS");
   if (tags == NULL) {
     return;
diff --git a/src/runtime.cc b/src/runtime.cc
index 45d2988..186f208 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -607,7 +607,7 @@
   if (Runtime::instance_ != NULL) {
     return false;
   }
-  Locks::Init();
+  InitLogging(NULL); // Calls Locks::Init() as a side effect.
   instance_ = new Runtime;
   if (!instance_->Init(options, ignore_unrecognized)) {
     delete instance_;
diff --git a/test/etc/host-run-test-jar b/test/etc/host-run-test-jar
index f8f393f..357fb5a 100755
--- a/test/etc/host-run-test-jar
+++ b/test/etc/host-run-test-jar
@@ -9,7 +9,8 @@
     fi
 }
 
-DEBUG="n"
+LIB="libartd.so"
+DEBUGGER="n"
 GDB="n"
 INTERPRETER="n"
 VERIFY="y"
@@ -17,17 +18,19 @@
 INVOKE_WITH=""
 DEV_MODE="n"
 QUIET="n"
-OATEXEC="oatexecd"
 
 while true; do
     if [ "x$1" = "x--quiet" ]; then
         QUIET="y"
         shift
+    elif [ "x$1" = "x-lib" ]; then
+        shift
+        LIB="$1"
     elif [ "x$1" = "x-O" ]; then
-        OATEXEC="oatexec"
+        LIB="libart.so"
         shift
     elif [ "x$1" = "x--debug" ]; then
-        DEBUG="y"
+        DEBUGGER="y"
         shift
     elif [ "x$1" = "x--gdb" ]; then
         GDB="y"
@@ -81,13 +84,13 @@
 export DYLD_LIBRARY_PATH="${ANDROID_ROOT}/lib"
 unset ANDROID_PRODUCT_OUT # avoid defaulting dex2oat --host-prefix to target output
 
-exe="${ANDROID_ROOT}/bin/${OATEXEC}"
+exe="${ANDROID_ROOT}/bin/dalvikvm"
 
-if [ "$DEBUG" = "y" ]; then
+if [ "$DEBUGGER" = "y" ]; then
     PORT=8000
     msg "Waiting for jdb to connect:"
     msg "    jdb -attach localhost:$PORT"
-    DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
+    DEBUGGER_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
 fi
 
 if [ "$GDB" = "y" ]; then
@@ -104,6 +107,6 @@
 JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
 
 cd $ANDROID_BUILD_TOP
-$INVOKE_WITH $gdb $exe $gdbargs -Ximage:$ANDROID_ROOT/framework/core.art \
-    $JNI_OPTS $INT_OPTS $DEBUG_OPTS \
+$INVOKE_WITH $gdb $exe $gdbargs -XXlib:$LIB -Ximage:$ANDROID_ROOT/framework/core.art \
+    $JNI_OPTS $INT_OPTS $DEBUGGER_OPTS \
     -cp $DEX_LOCATION/$TEST_NAME.jar Main "$@"
diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar
index 1e653e2..cc28592 100755
--- a/test/etc/push-and-run-test-jar
+++ b/test/etc/push-and-run-test-jar
@@ -9,9 +9,9 @@
     fi
 }
 
-OATEXEC="oatexecd"
+LIB="libartd.so"
 GDB="n"
-DEBUG="n"
+DEBUGGER="n"
 INTERPRETER="n"
 VERIFY="y"
 OPTIMIZE="y"
@@ -24,11 +24,14 @@
     if [ "x$1" = "x--quiet" ]; then
         QUIET="y"
         shift
+    elif [ "x$1" = "x-lib" ]; then
+        shift
+        LIB="$1"
     elif [ "x$1" = "x-O" ]; then
-        OATEXEC="oatexec"
+        LIB="libart.so"
         shift
     elif [ "x$1" = "x--debug" ]; then
-        DEBUG="y"
+        DEBUGGER="y"
         shift
     elif [ "x$1" = "x--gdb" ]; then
         GDB="y"
@@ -105,16 +108,16 @@
   adb push $TEST_NAME-ex.jar $DEX_LOCATION >/dev/null 2>&1
 fi
 
-if [ "$DEBUG" = "y" ]; then
+if [ "$DEBUGGER" = "y" ]; then
   # Use this instead for ddms and connect by running 'ddms':
-  # DEBUG_OPTS="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
+  # DEBUGGER_OPTS="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
   # TODO: add a separate --ddms option?
 
   PORT=12345
   msg "Waiting for jdb to connect:"
   msg "    adb forward tcp:$PORT tcp:$PORT"
   msg "    jdb -attach localhost:$PORT"
-  DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
+  DEBUGGER_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
 fi
 
 if [ "$GDB" = "y" ]; then
@@ -129,7 +132,7 @@
 JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
 
 cmdline="cd $DEX_LOCATION && mkdir dalvik-cache && export ANDROID_DATA=$DEX_LOCATION && export DEX_LOCATION=$DEX_LOCATION && \
-    $INVOKE_WITH $gdb $OATEXEC $gdbargs $ZYGOTE $JNI_OPTS $INT_OPTS $DEBUG_OPTS -Ximage:/data/art-test/core.art -cp $DEX_LOCATION/$TEST_NAME.jar Main"
+    $INVOKE_WITH $gdb dalvikvm $gdbargs -XXlib:$LIB $ZYGOTE $JNI_OPTS $INT_OPTS $DEBUGGER_OPTS -Ximage:/data/art-test/core.art -cp $DEX_LOCATION/$TEST_NAME.jar Main"
 if [ "$DEV_MODE" = "y" ]; then
   echo $cmdline "$@"
 fi
diff --git a/test/run-test b/test/run-test
index b4db141..4744f19 100755
--- a/test/run-test
+++ b/test/run-test
@@ -172,7 +172,7 @@
         echo '  Omitting the test name or specifying "-" will use the' \
              "current directory."
         echo "  Runtime Options:"
-        echo "    -O             Run oatexec rather than oatexecd (off by default)."
+        echo "    -O             Run non-debug rather than debug build (off by default)."
         echo "    --debug        Wait for a debugger to attach."
         echo "    --gdb          Run under gdb; incompatible with some tests."
         echo "    --build-only   Build test files only (off by default)."
diff --git a/tools/art b/tools/art
index 4d5fc1f..0a6c941 100755
--- a/tools/art
+++ b/tools/art
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-oatexec=oatexec
+lib=-XXlib:libart.so
 invoke_with=
 
 while true; do
@@ -23,7 +23,7 @@
     invoke_with="$1"
     shift
   elif [ "$1" = "-d" ]; then
-    oatexec="oatexecd"
+    lib="-XXlib:libartd.so"
     shift
   elif expr "$1" : "--" >/dev/null 2>&1; then
     echo "unknown option: $1" 1>&2
@@ -39,7 +39,7 @@
 ANDROID_DATA=/tmp/android-data \
   ANDROID_ROOT=$ANDROID_HOST_OUT \
   LD_LIBRARY_PATH=$ANDROID_HOST_OUT/lib \
-  exec $invoke_with $ANDROID_HOST_OUT/bin/$oatexec \
+  exec $invoke_with $ANDROID_HOST_OUT/bin/dalvikvm $lib \
     -Xbootclasspath:$ANDROID_HOST_OUT/core-hostdex.jar \
     -Ximage:$ANDROID_HOST_OUT/framework/core.art \
      "$@"