Merge "Add dex file writer to dexlayout tool."
diff --git a/benchmark/Android.bp b/benchmark/Android.bp
index 014a2b3..e784508 100644
--- a/benchmark/Android.bp
+++ b/benchmark/Android.bp
@@ -44,3 +44,31 @@
         "-Wno-frame-larger-than=",
     ],
 }
+
+art_cc_library {
+    name: "libartbenchmark-micronative-host",
+    host_supported: true,
+    device_supported: false,
+    defaults: ["art_defaults", "art_debug_defaults"],
+    srcs: [
+        "jni_loader.cc",
+        "micro-native/micro_native.cc",
+    ],
+    shared_libs: [
+    ],
+    static_libs: [
+    ],
+    include_dirs: [
+        "libnativehelper/include/nativehelper"  // only for jni.h
+    ],
+    stl: "libc++_static",
+    clang: true,
+    target: {
+        host: {
+            host_ldlibs: ["-ldl", "-lpthread"],
+        },
+    },
+    cflags: [
+        "-Wno-frame-larger-than=",
+    ],
+}
diff --git a/benchmark/micro-native/micro_native.cc b/benchmark/micro-native/micro_native.cc
index 43c29e2..d366d9d 100644
--- a/benchmark/micro-native/micro_native.cc
+++ b/benchmark/micro-native/micro_native.cc
@@ -14,12 +14,26 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "NativeMethods"
+#include <stdio.h>
+#include <jni.h>
+
+#ifndef NATIVE_METHOD
+#define NATIVE_METHOD(className, functionName, signature) \
+    { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
+#endif
+#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
+
+#define GLUE4(a, b, c, d) a ## b ## c ## d
+#define GLUE4_(a, b, c, d) GLUE4(a, b, c, d)
 
 #define CLASS_NAME "benchmarks/MicroNative/java/NativeMethods"
+#define CLASS_INFIX benchmarks_MicroNative_java_NativeMethods
 
-#include "JNIHelp.h"
-#include "JniConstants.h"
+#define NAME_NORMAL_JNI_METHOD(name) GLUE4_(Java_, CLASS_INFIX, _, name)
+#define NAME_CRITICAL_JNI_METHOD(name) GLUE4_(JavaCritical_, CLASS_INFIX, _, name)
+
+#define DEFINE_NORMAL_JNI_METHOD(ret, name) extern "C" JNIEXPORT ret JNICALL GLUE4_(Java_, CLASS_INFIX, _, name)
+#define DEFINE_CRITICAL_JNI_METHOD(ret, name) extern "C" JNIEXPORT ret JNICALL GLUE4_(JavaCritical_, CLASS_INFIX, _, name)
 
 static void NativeMethods_emptyJniStaticSynchronizedMethod0(JNIEnv*, jclass) { }
 static void NativeMethods_emptyJniSynchronizedMethod0(JNIEnv*, jclass) { }
@@ -67,17 +81,66 @@
   NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6_Fast, "(IIIIII)V"),
 };
 
-static void NativeMethods_emptyJniStaticMethod0_Critical() { }
-static void NativeMethods_emptyJniStaticMethod6_Critical(int, int, int, int, int, int) { }
+// Have both a Java_ and a JavaCritical_ version of the same empty method.
+// The runtime automatically selects the right one when doing a dlsym-based native lookup.
+DEFINE_NORMAL_JNI_METHOD(void,   emptyJniStaticMethod0_1Critical)(JNIEnv*, jclass) { }
+DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod0_1Critical)() { }
+DEFINE_NORMAL_JNI_METHOD(void,   emptyJniStaticMethod6_1Critical)(JNIEnv*, jclass, int, int, int, int, int, int) { }
+DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod6_1Critical)(int, int, int, int, int, int) { }
 
 static JNINativeMethod gMethods_Critical[] = {
-  NATIVE_METHOD(NativeMethods, emptyJniStaticMethod0_Critical, "()V"),
-  NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6_Critical, "(IIIIII)V"),
+  // Don't use NATIVE_METHOD because the name is mangled differently.
+  { "emptyJniStaticMethod0_Critical", "()V",
+        reinterpret_cast<void*>(NAME_CRITICAL_JNI_METHOD(emptyJniStaticMethod0_1Critical)) },
+  { "emptyJniStaticMethod6_Critical", "(IIIIII)V",
+        reinterpret_cast<void*>(NAME_CRITICAL_JNI_METHOD(emptyJniStaticMethod6_1Critical)) }
 };
 
+void jniRegisterNativeMethods(JNIEnv* env,
+                              const char* className,
+                              const JNINativeMethod* methods,
+                              int numMethods) {
+    jclass c = env->FindClass(className);
+    if (c == nullptr) {
+        char* tmp;
+        const char* msg;
+        if (asprintf(&tmp,
+                     "Native registration unable to find class '%s'; aborting...",
+                     className) == -1) {
+            // Allocation failed, print default warning.
+            msg = "Native registration unable to find class; aborting...";
+        } else {
+            msg = tmp;
+        }
+        env->FatalError(msg);
+    }
+
+    if (env->RegisterNatives(c, methods, numMethods) < 0) {
+        char* tmp;
+        const char* msg;
+        if (asprintf(&tmp, "RegisterNatives failed for '%s'; aborting...", className) == -1) {
+            // Allocation failed, print default warning.
+            msg = "RegisterNatives failed; aborting...";
+        } else {
+            msg = tmp;
+        }
+        env->FatalError(msg);
+    }
+}
+
 void register_micro_native_methods(JNIEnv* env) {
   jniRegisterNativeMethods(env, CLASS_NAME, gMethods_NormalOnly, NELEM(gMethods_NormalOnly));
   jniRegisterNativeMethods(env, CLASS_NAME, gMethods, NELEM(gMethods));
   jniRegisterNativeMethods(env, CLASS_NAME, gMethods_Fast, NELEM(gMethods_Fast));
-  jniRegisterNativeMethods(env, CLASS_NAME, gMethods_Critical, NELEM(gMethods_Critical));
+
+  if (env->FindClass("dalvik/annotation/optimization/CriticalNative") != nullptr) {
+    // Only register them explicitly if the annotation is present.
+    jniRegisterNativeMethods(env, CLASS_NAME, gMethods_Critical, NELEM(gMethods_Critical));
+  } else {
+    if (env->ExceptionCheck()) {
+      // It will throw NoClassDefFoundError
+      env->ExceptionClear();
+    }
+  }
+  // else let them be registered implicitly.
 }
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 5d44cc1..1ddf961 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -990,6 +990,8 @@
       }
     }
 
+    char_backing_storage_.reserve((dex_locations_.size() - 1) * 2);
+
     // Now create the other names. Use a counted loop to skip the first one.
     for (size_t i = 1; i < dex_locations_.size(); ++i) {
       // TODO: Make everything properly std::string.
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index 17873b5..d09e66f 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -27,7 +27,7 @@
 
 // Headers for LogMessage::LogLine.
 #ifdef ART_TARGET_ANDROID
-#include "cutils/log.h"
+#include <android/log.h>
 #include <android/set_abort_message.h>
 #else
 #include <sys/types.h>
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index 3649111..a968343 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -191,86 +191,6 @@
   }
 }
 
-template<size_t kAlignment>
-void SpaceBitmap<kAlignment>::WalkInstanceFields(SpaceBitmap<kAlignment>* visited,
-                                                 ObjectCallback* callback, mirror::Object* obj,
-                                                 mirror::Class* klass, void* arg)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  // Visit fields of parent classes first.
-  mirror::Class* super = klass->GetSuperClass();
-  if (super != nullptr) {
-    WalkInstanceFields(visited, callback, obj, super, arg);
-  }
-  // Walk instance fields
-  for (ArtField& field : klass->GetIFields()) {
-    if (!field.IsPrimitiveType()) {
-      mirror::Object* value = field.GetObj(obj);
-      if (value != nullptr) {
-        WalkFieldsInOrder(visited, callback, value, arg);
-      }
-    }
-  }
-}
-
-template<size_t kAlignment>
-void SpaceBitmap<kAlignment>::WalkFieldsInOrder(SpaceBitmap<kAlignment>* visited,
-                                                ObjectCallback* callback, mirror::Object* obj,
-                                                void* arg) {
-  if (visited->Test(obj)) {
-    return;
-  }
-  // visit the object itself
-  (*callback)(obj, arg);
-  visited->Set(obj);
-  // Walk instance fields of all objects
-  mirror::Class* klass = obj->GetClass();
-  WalkInstanceFields(visited, callback, obj, klass, arg);
-  // Walk static fields of a Class
-  if (obj->IsClass()) {
-    for (ArtField& field : klass->GetSFields()) {
-      if (!field.IsPrimitiveType()) {
-        mirror::Object* value = field.GetObj(nullptr);
-        if (value != nullptr) {
-          WalkFieldsInOrder(visited, callback, value, arg);
-        }
-      }
-    }
-  } else if (obj->IsObjectArray()) {
-    // Walk elements of an object array
-    mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>();
-    int32_t length = obj_array->GetLength();
-    for (int32_t i = 0; i < length; i++) {
-      mirror::Object* value = obj_array->Get(i);
-      if (value != nullptr) {
-        WalkFieldsInOrder(visited, callback, value, arg);
-      }
-    }
-  }
-}
-
-template<size_t kAlignment>
-void SpaceBitmap<kAlignment>::InOrderWalk(ObjectCallback* callback, void* arg) {
-  std::unique_ptr<SpaceBitmap<kAlignment>> visited(
-      Create("bitmap for in-order walk", reinterpret_cast<uint8_t*>(heap_begin_),
-             IndexToOffset(bitmap_size_ / sizeof(intptr_t))));
-  CHECK(bitmap_begin_ != nullptr);
-  CHECK(callback != nullptr);
-  uintptr_t end = Size() / sizeof(intptr_t);
-  for (uintptr_t i = 0; i < end; ++i) {
-    // Need uint for unsigned shift.
-    uintptr_t w = bitmap_begin_[i].LoadRelaxed();
-    if (UNLIKELY(w != 0)) {
-      uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;
-      while (w != 0) {
-        const size_t shift = CTZ(w);
-        mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
-        WalkFieldsInOrder(visited.get(), callback, obj, arg);
-        w ^= (static_cast<uintptr_t>(1)) << shift;
-      }
-    }
-  }
-}
-
 template class SpaceBitmap<kObjectAlignment>;
 template class SpaceBitmap<kPageSize>;
 
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 576f9c7..296663a 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -133,11 +133,6 @@
   void Walk(ObjectCallback* callback, void* arg)
       REQUIRES_SHARED(Locks::heap_bitmap_lock_);
 
-  // Visits set bits with an in order traversal.  The callback is not permitted to change the bitmap
-  // bits or max during the traversal.
-  void InOrderWalk(ObjectCallback* callback, void* arg)
-      REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
   // Walk through the bitmaps in increasing address order, and find the object pointers that
   // correspond to garbage objects.  Call <callback> zero or more times with lists of these object
   // pointers. The callback is not permitted to increase the max of either bitmap.
@@ -202,15 +197,6 @@
   template<bool kSetBit>
   bool Modify(const mirror::Object* obj);
 
-  // For an unvisited object, visit it then all its children found via fields.
-  static void WalkFieldsInOrder(SpaceBitmap* visited, ObjectCallback* callback, mirror::Object* obj,
-                                void* arg) REQUIRES_SHARED(Locks::mutator_lock_);
-  // Walk instance fields of the given Class. Separate function to allow recursion on the super
-  // class.
-  static void WalkInstanceFields(SpaceBitmap<kAlignment>* visited, ObjectCallback* callback,
-                                 mirror::Object* obj, mirror::Class* klass, void* arg)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Backing storage for bitmap.
   std::unique_ptr<MemMap> mem_map_;
 
diff --git a/runtime/monitor_android.cc b/runtime/monitor_android.cc
index 671cb60..0d1839b 100644
--- a/runtime/monitor_android.cc
+++ b/runtime/monitor_android.cc
@@ -21,7 +21,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "cutils/log.h"
+#include <android/log.h>
 
 #define EVENT_LOG_TAG_dvm_lock_sample 20003
 
diff --git a/tools/jfuzz/run_dex_fuzz_test.py b/tools/jfuzz/run_dex_fuzz_test.py
index 56cdf02..50c4f20 100755
--- a/tools/jfuzz/run_dex_fuzz_test.py
+++ b/tools/jfuzz/run_dex_fuzz_test.py
@@ -26,6 +26,7 @@
         os.path.realpath(__file__))))
 
 from common.common import FatalError
+from common.common import GetEnvVariableOrError
 from common.common import GetJackClassPath
 from common.common import RetCode
 from common.common import RunCommand
@@ -54,6 +55,7 @@
     self._results_dir = None
     self._dexfuzz_dir = None
     self._inputs_dir = None
+    self._dexfuzz_env = None
 
   def __enter__(self):
     """On entry, enters new temp directory after saving current directory.
@@ -68,7 +70,14 @@
     if self._results_dir is None or self._dexfuzz_dir is None or \
         self._inputs_dir is None:
       raise FatalError('Cannot obtain temp directory')
+    self._dexfuzz_env = os.environ.copy()
+    self._dexfuzz_env['ANDROID_DATA'] = self._dexfuzz_dir
+    top = GetEnvVariableOrError('ANDROID_BUILD_TOP')
+    self._dexfuzz_env['PATH'] = (top + '/art/tools/bisection_search:' +
+                                 self._dexfuzz_env['PATH'])
     os.chdir(self._dexfuzz_dir)
+    os.mkdir('divergent_programs')
+    os.mkdir('bisection_outputs')
     return self
 
   def __exit__(self, etype, evalue, etraceback):
@@ -110,15 +119,15 @@
   def RunDexFuzz(self):
     """Starts the DexFuzz testing."""
     os.chdir(self._dexfuzz_dir)
-    os.environ['ANDROID_DATA'] = self._dexfuzz_dir
     dexfuzz_args = ['--inputs=' + self._inputs_dir, '--execute',
                     '--execute-class=Test', '--repeat=' + str(self._num_tests),
-                    '--dump-output', '--interpreter', '--optimizing']
+                    '--dump-output', '--interpreter', '--optimizing',
+                    '--bisection-search']
     if self._device is not None:
       dexfuzz_args += ['--device=' + self._device, '--allarm']
     else:
       dexfuzz_args += ['--host']  # Assume host otherwise.
-    check_call(['dexfuzz'] + dexfuzz_args)
+    check_call(['dexfuzz'] + dexfuzz_args, env=self._dexfuzz_env)
     # TODO: summarize findings.