Merge "MIPS64: Implement isInfinite intrinsics."
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 3100b6d..5d8e3ba 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -16,9 +16,6 @@
 
 #include "compiler_driver.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <utils/Trace.h>
-
 #include <unordered_set>
 #include <vector>
 #include <unistd.h>
@@ -30,6 +27,7 @@
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "class_linker-inl.h"
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index f25d748..ea19059 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -32,9 +32,6 @@
 #include <sys/utsname.h>
 #endif
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <cutils/trace.h>
-
 #include "arch/instruction_set_features.h"
 #include "arch/mips/instruction_set_features_mips.h"
 #include "art_method-inl.h"
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index 44af3f7..f871543 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -23,6 +23,7 @@
 #include "mem_map.h"
 #include "mutex.h"
 #include "thread-inl.h"
+#include "systrace.h"
 
 namespace art {
 
@@ -261,6 +262,7 @@
 
 void ArenaPool::TrimMaps() {
   if (!use_malloc_) {
+    ScopedTrace trace(__PRETTY_FUNCTION__);
     // Doesn't work for malloc.
     MutexLock lock(Thread::Current(), lock_);
     for (auto* arena = free_arenas_; arena != nullptr; arena = arena->next_) {
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 6972b3e..620bf9c 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -19,12 +19,10 @@
 #include <errno.h>
 #include <sys/time.h>
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include "cutils/trace.h"
-
 #include "atomic.h"
 #include "base/logging.h"
 #include "base/time_utils.h"
+#include "base/systrace.h"
 #include "base/value_object.h"
 #include "mutex-inl.h"
 #include "runtime.h"
diff --git a/runtime/base/systrace.h b/runtime/base/systrace.h
new file mode 100644
index 0000000..3901f96
--- /dev/null
+++ b/runtime/base/systrace.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_RUNTIME_BASE_SYSTRACE_H_
+#define ART_RUNTIME_BASE_SYSTRACE_H_
+
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include <cutils/trace.h>
+#include <string>
+#include <utils/Trace.h>
+
+namespace art {
+
+class ScopedTrace {
+ public:
+  explicit ScopedTrace(const char* name) {
+    ATRACE_BEGIN(name);
+  }
+
+  explicit ScopedTrace(const std::string& name) : ScopedTrace(name.c_str()) {}
+
+  ~ScopedTrace() {
+    ATRACE_END();
+  }
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_BASE_SYSTRACE_H_
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index 1942e1d..9a0e0d0 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -15,15 +15,14 @@
  */
 
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
 #include <stdio.h>
-#include <cutils/trace.h>
 
 #include "timing_logger.h"
 
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/histogram-inl.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "thread-inl.h"
 
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 5f26b5d..a13a2e3 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -36,6 +36,7 @@
 #include "base/scoped_arena_containers.h"
 #include "base/scoped_flock.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "base/value_object.h"
@@ -1198,7 +1199,7 @@
     gc::space::ImageSpace* space,
     Handle<mirror::ClassLoader> class_loader,
     Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
-    bool added_class_table,
+    ClassTable::ClassSet* new_class_set,
     bool* out_forward_dex_cache_array,
     std::string* out_error_msg) {
   DCHECK(out_forward_dex_cache_array != nullptr);
@@ -1217,20 +1218,40 @@
   for (size_t i = 0; i < num_dex_caches; i++) {
     mirror::DexCache* const dex_cache = dex_caches->Get(i);
     const DexFile* const dex_file = dex_cache->GetDexFile();
-    // If the oat file expects the dex cache arrays to be in the BSS, then allocate there and
-    // copy over the arrays.
-    DCHECK(dex_file != nullptr);
-    const size_t num_strings = dex_file->NumStringIds();
-    const size_t num_types = dex_file->NumTypeIds();
-    const size_t num_methods = dex_file->NumMethodIds();
-    const size_t num_fields = dex_file->NumFieldIds();
-    CHECK_EQ(num_strings, dex_cache->NumStrings());
-    CHECK_EQ(num_types, dex_cache->NumResolvedTypes());
-    CHECK_EQ(num_methods, dex_cache->NumResolvedMethods());
-    CHECK_EQ(num_fields, dex_cache->NumResolvedFields());
     const OatFile::OatDexFile* oat_dex_file = dex_file->GetOatDexFile();
     if (oat_dex_file != nullptr && oat_dex_file->GetDexCacheArrays() != nullptr) {
       ++num_dex_caches_with_bss_arrays;
+    }
+  }
+  *out_forward_dex_cache_array = num_dex_caches_with_bss_arrays != 0;
+  if (*out_forward_dex_cache_array) {
+    if (num_dex_caches_with_bss_arrays != num_dex_caches) {
+      // Reject application image since we cannot forward only some of the dex cache arrays.
+      // TODO: We could get around this by having a dedicated forwarding slot. It should be an
+      // uncommon case.
+      *out_error_msg = StringPrintf("Dex caches in bss does not match total: %zu vs %zu",
+                                    num_dex_caches_with_bss_arrays,
+                                    num_dex_caches);
+      return false;
+    }
+  }
+  // Only add the classes to the class loader after the points where we can return false.
+  for (size_t i = 0; i < num_dex_caches; i++) {
+    mirror::DexCache* const dex_cache = dex_caches->Get(i);
+    const DexFile* const dex_file = dex_cache->GetDexFile();
+    const OatFile::OatDexFile* oat_dex_file = dex_file->GetOatDexFile();
+    if (oat_dex_file != nullptr && oat_dex_file->GetDexCacheArrays() != nullptr) {
+    // If the oat file expects the dex cache arrays to be in the BSS, then allocate there and
+      // copy over the arrays.
+      DCHECK(dex_file != nullptr);
+      const size_t num_strings = dex_file->NumStringIds();
+      const size_t num_types = dex_file->NumTypeIds();
+      const size_t num_methods = dex_file->NumMethodIds();
+      const size_t num_fields = dex_file->NumFieldIds();
+      CHECK_EQ(num_strings, dex_cache->NumStrings());
+      CHECK_EQ(num_types, dex_cache->NumResolvedTypes());
+      CHECK_EQ(num_methods, dex_cache->NumResolvedMethods());
+      CHECK_EQ(num_fields, dex_cache->NumResolvedFields());
       DexCacheArraysLayout layout(image_pointer_size_, dex_file);
       uint8_t* const raw_arrays = oat_dex_file->GetDexCacheArrays();
       // The space is not yet visible to the GC, we can avoid the read barriers and use std::copy_n.
@@ -1292,10 +1313,11 @@
       RegisterDexFileLocked(*dex_file, hs3.NewHandle(dex_cache));
     }
     GcRoot<mirror::Class>* const types = dex_cache->GetResolvedTypes();
-    if (!added_class_table) {
+    const size_t num_types = dex_cache->NumResolvedTypes();
+    if (new_class_set == nullptr) {
       for (int32_t j = 0; j < static_cast<int32_t>(num_types); j++) {
         // The image space is not yet added to the heap, avoid read barriers.
-        mirror::Class* klass = types[j].Read<kWithoutReadBarrier>();
+        mirror::Class* klass = types[j].Read();
         if (klass != nullptr) {
           DCHECK_NE(klass->GetStatus(), mirror::Class::kStatusError);
           // Update the class loader from the one in the image class loader to the one that loaded
@@ -1341,14 +1363,26 @@
     if (kIsDebugBuild) {
       for (int32_t j = 0; j < static_cast<int32_t>(num_types); j++) {
         // The image space is not yet added to the heap, avoid read barriers.
-        mirror::Class* klass = types[j].Read<kWithoutReadBarrier>();
+        mirror::Class* klass = types[j].Read();
         if (klass != nullptr) {
           DCHECK_NE(klass->GetStatus(), mirror::Class::kStatusError);
           if (kIsDebugBuild) {
-            DCHECK_EQ(table->LookupByDescriptor(klass), klass);
-            mirror::Class* super_class = klass->GetSuperClass();
-            if (super_class != nullptr && !heap->ObjectIsInBootImageSpace(super_class)) {
-              CHECK_EQ(table->LookupByDescriptor(super_class), super_class);
+            if (new_class_set != nullptr)   {
+              auto it = new_class_set->Find(GcRoot<mirror::Class>(klass));
+              DCHECK(it != new_class_set->end());
+              DCHECK_EQ(it->Read(), klass);
+              mirror::Class* super_class = klass->GetSuperClass();
+              if (super_class != nullptr && !heap->ObjectIsInBootImageSpace(super_class)) {
+                auto it2 = new_class_set->Find(GcRoot<mirror::Class>(super_class));
+                DCHECK(it2 != new_class_set->end());
+                DCHECK_EQ(it2->Read(), super_class);
+              }
+            } else {
+              DCHECK_EQ(table->LookupByDescriptor(klass), klass);
+              mirror::Class* super_class = klass->GetSuperClass();
+              if (super_class != nullptr && !heap->ObjectIsInBootImageSpace(super_class)) {
+                CHECK_EQ(table->LookupByDescriptor(super_class), super_class);
+              }
             }
           }
           if (kIsDebugBuild) {
@@ -1362,7 +1396,6 @@
                 DCHECK_EQ(code, oat_code) << PrettyMethod(&m);
               }
             }
-            VLOG(image) << "Virtual methods";
             for (ArtMethod& m : klass->GetVirtualMethods(sizeof(void*))) {
               const void* code = m.GetEntryPointFromQuickCompiledCode();
               const void* oat_code = m.IsInvokable() ? GetQuickOatCodeFor(&m) : code;
@@ -1378,17 +1411,7 @@
       }
     }
   }
-  *out_forward_dex_cache_array = num_dex_caches_with_bss_arrays != 0;
   if (*out_forward_dex_cache_array) {
-    if (num_dex_caches_with_bss_arrays != num_dex_caches) {
-      // Reject application image since we cannot forward only some of the dex cache arrays.
-      // TODO: We could get around this by having a dedicated forwarding slot. It should be an
-      // uncommon case.
-      *out_error_msg = StringPrintf("Dex caches in bss does not match total: %zu vs %zu",
-                                    num_dex_caches_with_bss_arrays,
-                                    num_dex_caches);
-      return false;
-    }
     FixupArtMethodArrayVisitor visitor(header);
     header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
         &visitor,
@@ -1396,17 +1419,11 @@
         sizeof(void*));
     Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
   }
-  if (kIsDebugBuild) {
-    ClassTable* const class_table = class_loader.Get()->GetClassTable();
-    VerifyClassInTableArtMethodVisitor visitor2(class_table);
-    header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
-        &visitor2,
-        space->Begin(),
-        sizeof(void*));
-  }
   return true;
 }
 
+// Update the class loader and resolved string dex cache array of classes. Should only be used on
+// classes in the image space.
 class UpdateClassLoaderAndResolvedStringsVisitor {
  public:
   UpdateClassLoaderAndResolvedStringsVisitor(gc::space::ImageSpace* space,
@@ -1644,43 +1661,46 @@
     methods.VisitPackedArtMethods(&visitor, space->Begin(), image_pointer_size_);
   }
 
-  const ImageSection& class_table_section = header.GetImageSection(ImageHeader::kSectionClassTable);
-  bool added_class_table = false;
-  if (app_image) {
-    GetOrCreateAllocatorForClassLoader(class_loader.Get());  // Make sure we have a linear alloc.
-  }
   ClassTable* class_table = nullptr;
   {
     WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
     class_table = InsertClassTableForClassLoader(class_loader.Get());
-    if (class_table_section.Size() > 0u) {
-      const uint64_t start_time2 = NanoTime();
-      class_table->ReadFromMemory(space->Begin() + class_table_section.Offset());
-      if (!app_image) {
-        dex_cache_boot_image_class_lookup_required_ = false;
-      }
-      VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
-      added_class_table = true;
+  }
+  // If we have a class table section, read it and use it for verification in
+  // UpdateAppImageClassLoadersAndDexCaches.
+  ClassTable::ClassSet temp_set;
+  const ImageSection& class_table_section = header.GetImageSection(ImageHeader::kSectionClassTable);
+  const bool added_class_table = class_table_section.Size() > 0u;
+  if (added_class_table) {
+    const uint64_t start_time2 = NanoTime();
+    size_t read_count = 0;
+    temp_set = ClassTable::ClassSet(space->Begin() + class_table_section.Offset(),
+                                    /*make copy*/false,
+                                    &read_count);
+    if (!app_image) {
+      dex_cache_boot_image_class_lookup_required_ = false;
     }
+    VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
   }
   if (app_image) {
     bool forward_dex_cache_arrays = false;
     if (!UpdateAppImageClassLoadersAndDexCaches(space,
                                                 class_loader,
                                                 dex_caches,
-                                                added_class_table,
+                                                added_class_table ? &temp_set : nullptr,
                                                 /*out*/&forward_dex_cache_arrays,
                                                 /*out*/error_msg)) {
       return false;
     }
+    // Update class loader and resolved strings. If added_class_table is false, the resolved
+    // strings were forwarded UpdateAppImageClassLoadersAndDexCaches.
+    UpdateClassLoaderAndResolvedStringsVisitor visitor(space,
+                                                       class_loader.Get(),
+                                                       forward_dex_cache_arrays);
     if (added_class_table) {
-      WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
-      // Update class loader and resolved strings. If added_class_table is false, the resolved
-      // strings were already updated in UpdateAppImageClassLoadersAndDexCaches.
-      UpdateClassLoaderAndResolvedStringsVisitor visitor(space,
-                                                         class_loader.Get(),
-                                                         forward_dex_cache_arrays);
-      class_table->Visit(visitor);
+      for (GcRoot<mirror::Class>& root : temp_set) {
+        visitor(root.Read());
+      }
     }
     // forward_dex_cache_arrays is true iff we copied all of the dex cache arrays into the .bss.
     // In this case, madvise away the dex cache arrays section of the image to reduce RAM usage and
@@ -1699,6 +1719,19 @@
       }
     }
   }
+  if (added_class_table) {
+    WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
+    class_table->AddClassSet(std::move(temp_set));
+  }
+  if (kIsDebugBuild && app_image) {
+    // This verification needs to happen after the classes have been added to the class loader.
+    // Since it ensures classes are in the class table.
+    VerifyClassInTableArtMethodVisitor visitor2(class_table);
+    header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
+        &visitor2,
+        space->Begin(),
+        sizeof(void*));
+  }
   VLOG(class_linker) << "Adding image space took " << PrettyDuration(NanoTime() - start_time);
   return true;
 }
@@ -7639,6 +7672,7 @@
 }
 
 std::set<DexCacheResolvedClasses> ClassLinker::GetResolvedClasses(bool ignore_boot_classes) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   ScopedObjectAccess soa(Thread::Current());
   ScopedAssertNoThreadSuspension ants(soa.Self(), __FUNCTION__);
   std::set<DexCacheResolvedClasses> ret;
@@ -7705,6 +7739,7 @@
 
 std::unordered_set<std::string> ClassLinker::GetClassDescriptorsForProfileKeys(
     const std::set<DexCacheResolvedClasses>& classes) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   std::unordered_set<std::string> ret;
   Thread* const self = Thread::Current();
   std::unordered_map<std::string, const DexFile*> location_to_dex_file;
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 0a75b27..492a228 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -1029,11 +1029,13 @@
       SHARED_REQUIRES(Locks::mutator_lock_)
       REQUIRES(!Locks::classlinker_classes_lock_);
 
+  // new_class_set is the set of classes that were read from the class table section in the image.
+  // If there was no class table section, it is null.
   bool UpdateAppImageClassLoadersAndDexCaches(
       gc::space::ImageSpace* space,
       Handle<mirror::ClassLoader> class_loader,
       Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
-      bool added_class_table,
+      ClassTable::ClassSet* new_class_set,
       bool* out_forward_dex_cache_array,
       std::string* out_error_msg)
       REQUIRES(!dex_lock_)
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index afb0556..d815b1a 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -168,8 +168,12 @@
 
 size_t ClassTable::ReadFromMemory(uint8_t* ptr) {
   size_t read_count = 0;
-  classes_.insert(classes_.begin(), ClassSet(ptr, /*make copy*/false, &read_count));
+  AddClassSet(ClassSet(ptr, /*make copy*/false, &read_count));
   return read_count;
 }
 
+void ClassTable::AddClassSet(ClassSet&& set) {
+  classes_.insert(classes_.begin(), std::move(set));
+}
+
 }  // namespace art
diff --git a/runtime/class_table.h b/runtime/class_table.h
index 5f2eb48..0e0e860 100644
--- a/runtime/class_table.h
+++ b/runtime/class_table.h
@@ -39,6 +39,34 @@
 // Each loader has a ClassTable
 class ClassTable {
  public:
+  class ClassDescriptorHashEquals {
+   public:
+    // uint32_t for cross compilation.
+    uint32_t operator()(const GcRoot<mirror::Class>& root) const NO_THREAD_SAFETY_ANALYSIS;
+    // Same class loader and descriptor.
+    bool operator()(const GcRoot<mirror::Class>& a, const GcRoot<mirror::Class>& b) const
+        NO_THREAD_SAFETY_ANALYSIS;;
+    // Same descriptor.
+    bool operator()(const GcRoot<mirror::Class>& a, const char* descriptor) const
+        NO_THREAD_SAFETY_ANALYSIS;
+    // uint32_t for cross compilation.
+    uint32_t operator()(const char* descriptor) const NO_THREAD_SAFETY_ANALYSIS;
+  };
+  class GcRootEmptyFn {
+   public:
+    void MakeEmpty(GcRoot<mirror::Class>& item) const {
+      item = GcRoot<mirror::Class>();
+    }
+    bool IsEmpty(const GcRoot<mirror::Class>& item) const {
+      return item.IsNull();
+    }
+  };
+  // hash set which hashes class descriptor, and compares descriptors and class loaders. Results
+  // should be compared for a matching Class descriptor and class loader.
+  typedef HashSet<GcRoot<mirror::Class>, GcRootEmptyFn, ClassDescriptorHashEquals,
+      ClassDescriptorHashEquals, TrackingAllocator<GcRoot<mirror::Class>, kAllocatorTagClassTable>>
+      ClassSet;
+
   ClassTable();
 
   // Used by image writer for checking.
@@ -112,35 +140,12 @@
       REQUIRES(Locks::classlinker_classes_lock_)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
- private:
-  class ClassDescriptorHashEquals {
-   public:
-    // uint32_t for cross compilation.
-    uint32_t operator()(const GcRoot<mirror::Class>& root) const NO_THREAD_SAFETY_ANALYSIS;
-    // Same class loader and descriptor.
-    bool operator()(const GcRoot<mirror::Class>& a, const GcRoot<mirror::Class>& b) const
-        NO_THREAD_SAFETY_ANALYSIS;;
-    // Same descriptor.
-    bool operator()(const GcRoot<mirror::Class>& a, const char* descriptor) const
-        NO_THREAD_SAFETY_ANALYSIS;
-    // uint32_t for cross compilation.
-    uint32_t operator()(const char* descriptor) const NO_THREAD_SAFETY_ANALYSIS;
-  };
-  class GcRootEmptyFn {
-   public:
-    void MakeEmpty(GcRoot<mirror::Class>& item) const {
-      item = GcRoot<mirror::Class>();
-    }
-    bool IsEmpty(const GcRoot<mirror::Class>& item) const {
-      return item.IsNull();
-    }
-  };
-  // hash set which hashes class descriptor, and compares descriptors and class loaders. Results
-  // should be compared for a matching Class descriptor and class loader.
-  typedef HashSet<GcRoot<mirror::Class>, GcRootEmptyFn, ClassDescriptorHashEquals,
-      ClassDescriptorHashEquals, TrackingAllocator<GcRoot<mirror::Class>, kAllocatorTagClassTable>>
-      ClassSet;
+  // Add a class set to the front of classes.
+  void AddClassSet(ClassSet&& set)
+      REQUIRES(Locks::classlinker_classes_lock_)
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
+ private:
   // TODO: shard lock to have one per class loader.
   // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot.
   std::vector<ClassSet> classes_ GUARDED_BY(Locks::classlinker_classes_lock_);
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 81a3e4b..4a0a6fc 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -34,6 +34,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/stringprintf.h"
+#include "base/systrace.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
 #include "dex_file_verifier.h"
@@ -116,6 +117,7 @@
 
 bool DexFile::Open(const char* filename, const char* location, std::string* error_msg,
                    std::vector<std::unique_ptr<const DexFile>>* dex_files) {
+  ScopedTrace trace(std::string("Open dex file ") + location);
   DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr";
   uint32_t magic;
   ScopedFd fd(OpenAndReadMagic(filename, &magic, error_msg));
@@ -201,6 +203,7 @@
                                              const OatDexFile* oat_dex_file,
                                              bool verify,
                                              std::string* error_msg) {
+  ScopedTrace trace(std::string("Open dex file from RAM ") + location);
   std::unique_ptr<const DexFile> dex_file = OpenMemory(base,
                                                        size,
                                                        location,
@@ -221,6 +224,7 @@
 
 std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, const char* location, bool verify,
                                                  std::string* error_msg) {
+  ScopedTrace trace(std::string("Open dex file ") + location);
   CHECK(location != nullptr);
   std::unique_ptr<MemMap> map;
   {
@@ -278,6 +282,7 @@
 
 bool DexFile::OpenZip(int fd, const std::string& location, std::string* error_msg,
                       std::vector<std::unique_ptr<const DexFile>>* dex_files) {
+  ScopedTrace trace("Dex file open Zip " + std::string(location));
   DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is nullptr";
   std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd, location.c_str(), error_msg));
   if (zip_archive.get() == nullptr) {
@@ -303,6 +308,7 @@
 std::unique_ptr<const DexFile> DexFile::Open(const ZipArchive& zip_archive, const char* entry_name,
                                              const std::string& location, std::string* error_msg,
                                              ZipOpenErrorCode* error_code) {
+  ScopedTrace trace("Dex file open from Zip Archive " + std::string(location));
   CHECK(!location.empty());
   std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg));
   if (zip_entry.get() == nullptr) {
@@ -348,6 +354,7 @@
 bool DexFile::OpenFromZip(const ZipArchive& zip_archive, const std::string& location,
                           std::string* error_msg,
                           std::vector<std::unique_ptr<const DexFile>>* dex_files) {
+  ScopedTrace trace("Dex file open from Zip " + std::string(location));
   DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr";
   ZipOpenErrorCode error_code;
   std::unique_ptr<const DexFile> dex_file(Open(zip_archive, kClassesDex, location, error_msg,
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index 1a7b1a3..121da37 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -17,6 +17,7 @@
 #include "card_table.h"
 
 #include "base/logging.h"
+#include "base/systrace.h"
 #include "card_table-inl.h"
 #include "gc/heap.h"
 #include "gc/space/space.h"
@@ -57,6 +58,7 @@
  */
 
 CardTable* CardTable::Create(const uint8_t* heap_begin, size_t heap_capacity) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   /* Set up the card table */
   size_t capacity = heap_capacity / kCardSize;
   /* Allocate an extra 256 bytes to allow fixed low-byte of base */
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index afd0a30..18c4adf 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -18,13 +18,11 @@
 
 #include "garbage_collector.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include "cutils/trace.h"
-
 #include "base/dumpable.h"
 #include "base/histogram-inl.h"
 #include "base/logging.h"
 #include "base/mutex-inl.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "gc/accounting/heap_bitmap.h"
 #include "gc/space/large_object_space.h"
@@ -81,7 +79,7 @@
 }
 
 void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) {
-  ATRACE_BEGIN(StringPrintf("%s %s GC", PrettyCause(gc_cause), GetName()).c_str());
+  ScopedTrace trace(StringPrintf("%s %s GC", PrettyCause(gc_cause), GetName()));
   Thread* self = Thread::Current();
   uint64_t start_time = NanoTime();
   Iteration* current_iteration = GetCurrentIteration();
@@ -107,7 +105,6 @@
     MutexLock mu(self, pause_histogram_lock_);
     pause_histogram_.AdjustAndAddValue(pause_time);
   }
-  ATRACE_END();
 }
 
 void GarbageCollector::SwapBitmaps() {
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 64c8e9a..6073fc8 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -22,13 +22,11 @@
 #include <climits>
 #include <vector>
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include "cutils/trace.h"
-
 #include "base/bounded_fifo.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/mutex-inl.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "gc/accounting/card_table-inl.h"
@@ -1137,17 +1135,15 @@
   }
 
   virtual void Run(Thread* thread) OVERRIDE NO_THREAD_SAFETY_ANALYSIS {
-    ATRACE_BEGIN("Marking thread roots");
+    ScopedTrace trace("Marking thread roots");
     // Note: self is not necessarily equal to thread since thread may be suspended.
     Thread* const self = Thread::Current();
     CHECK(thread == self || thread->IsSuspended() || thread->GetState() == kWaitingPerformingGc)
         << thread->GetState() << " thread " << thread << " self " << self;
     thread->VisitRoots(this);
-    ATRACE_END();
     if (revoke_ros_alloc_thread_local_buffers_at_checkpoint_) {
-      ATRACE_BEGIN("RevokeRosAllocThreadLocalBuffers");
+      ScopedTrace trace2("RevokeRosAllocThreadLocalBuffers");
       mark_sweep_->GetHeap()->RevokeRosAllocThreadLocalBuffers(thread);
-      ATRACE_END();
     }
     // If thread is a running mutator, then act on behalf of the garbage collector.
     // See the code in ThreadList::RunCheckpoint.
diff --git a/runtime/gc/collector/semi_space-inl.h b/runtime/gc/collector/semi_space-inl.h
index 12cf3db..e87b5ff 100644
--- a/runtime/gc/collector/semi_space-inl.h
+++ b/runtime/gc/collector/semi_space-inl.h
@@ -75,6 +75,7 @@
     }
     obj_ptr->Assign(forward_address);
   } else if (!collect_from_space_only_ && !immune_spaces_.IsInImmuneRegion(obj)) {
+    DCHECK(!to_space_->HasAddress(obj)) << "Tried to mark " << obj << " in to-space";
     BitmapSetSlowPathVisitor visitor(this);
     if (!mark_bitmap_->Set(obj, visitor)) {
       // This object was not previously marked.
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 2784693..f37daa5 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -619,7 +619,7 @@
 
 mirror::Object* SemiSpace::MarkObject(mirror::Object* root) {
   auto ref = StackReference<mirror::Object>::FromMirrorPtr(root);
-  MarkObject(&ref);
+  MarkObjectIfNotInToSpace(&ref);
   return ref.AsMirrorPtr();
 }
 
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index bebff0f..3480483 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -16,9 +16,6 @@
 
 #include "heap.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <cutils/trace.h>
-
 #include <limits>
 #include <memory>
 #include <unwind.h>  // For GC verification.
@@ -30,6 +27,7 @@
 #include "base/dumpable.h"
 #include "base/histogram-inl.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "common_throws.h"
 #include "cutils/sched_policy.h"
@@ -240,6 +238,7 @@
   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "Heap() entering";
   }
+  ScopedTrace trace(__FUNCTION__);
   Runtime* const runtime = Runtime::Current();
   // If we aren't the zygote, switch to the default non zygote allocator. This may update the
   // entrypoints.
@@ -274,14 +273,12 @@
     uint8_t* const original_requested_alloc_space_begin = requested_alloc_space_begin;
     for (size_t index = 0; index < image_file_names.size(); ++index) {
       std::string& image_name = image_file_names[index];
-      ATRACE_BEGIN("ImageSpace::Create");
       std::string error_msg;
       space::ImageSpace* boot_image_space = space::ImageSpace::CreateBootImage(
           image_name.c_str(),
           image_instruction_set,
           index > 0,
           &error_msg);
-      ATRACE_END();
       if (boot_image_space != nullptr) {
         AddSpace(boot_image_space);
         added_image_spaces.push_back(boot_image_space);
@@ -373,8 +370,8 @@
   }
   std::string error_str;
   std::unique_ptr<MemMap> non_moving_space_mem_map;
-  ATRACE_BEGIN("Create heap maps");
   if (separate_non_moving_space) {
+    ScopedTrace trace2("Create separate non moving space");
     // If we are the zygote, the non moving space becomes the zygote space when we run
     // PreZygoteFork the first time. In this case, call the map "zygote space" since we can't
     // rename the mem map later.
@@ -391,6 +388,7 @@
   }
   // Attempt to create 2 mem maps at or after the requested begin.
   if (foreground_collector_type_ != kCollectorTypeCC) {
+    ScopedTrace trace2("Create main mem map");
     if (separate_non_moving_space || !is_zygote) {
       main_mem_map_1.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[0],
                                                         request_begin,
@@ -409,14 +407,15 @@
   if (support_homogeneous_space_compaction ||
       background_collector_type_ == kCollectorTypeSS ||
       foreground_collector_type_ == kCollectorTypeSS) {
+    ScopedTrace trace2("Create main mem map 2");
     main_mem_map_2.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[1], main_mem_map_1->End(),
                                                       capacity_, &error_str));
     CHECK(main_mem_map_2.get() != nullptr) << error_str;
   }
-  ATRACE_END();
-  ATRACE_BEGIN("Create spaces");
+
   // Create the non moving space first so that bitmaps don't take up the address range.
   if (separate_non_moving_space) {
+    ScopedTrace trace2("Add non moving space");
     // Non moving space is always dlmalloc since we currently don't have support for multiple
     // active rosalloc spaces.
     const size_t size = non_moving_space_mem_map->Size();
@@ -504,9 +503,7 @@
   if (main_space_backup_.get() != nullptr) {
     RemoveSpace(main_space_backup_.get());
   }
-  ATRACE_END();
   // Allocate the card table.
-  ATRACE_BEGIN("Create card table");
   // We currently don't support dynamically resizing the card table.
   // Since we don't know where in the low_4gb the app image will be located, make the card table
   // cover the whole low_4gb. TODO: Extend the card table in AddSpace.
@@ -517,7 +514,6 @@
   card_table_.reset(accounting::CardTable::Create(reinterpret_cast<uint8_t*>(kMinHeapAddress),
                                                   4 * GB - kMinHeapAddress));
   CHECK(card_table_.get() != nullptr) << "Failed to create card table";
-  ATRACE_END();
   if (foreground_collector_type_ == kCollectorTypeCC && kUseTableLookupReadBarrier) {
     rb_table_.reset(new accounting::ReadBarrierTable());
     DCHECK(rb_table_->IsAllCleared());
@@ -1340,24 +1336,19 @@
 void Heap::Trim(Thread* self) {
   Runtime* const runtime = Runtime::Current();
   if (!CareAboutPauseTimes()) {
-    ATRACE_BEGIN("Deflating monitors");
     // Deflate the monitors, this can cause a pause but shouldn't matter since we don't care
     // about pauses.
-    {
-      ScopedSuspendAll ssa(__FUNCTION__);
-      uint64_t start_time = NanoTime();
-      size_t count = runtime->GetMonitorList()->DeflateMonitors();
-      VLOG(heap) << "Deflating " << count << " monitors took "
-          << PrettyDuration(NanoTime() - start_time);
-    }
-    ATRACE_END();
+    ScopedTrace trace("Deflating monitors");
+    ScopedSuspendAll ssa(__FUNCTION__);
+    uint64_t start_time = NanoTime();
+    size_t count = runtime->GetMonitorList()->DeflateMonitors();
+    VLOG(heap) << "Deflating " << count << " monitors took "
+        << PrettyDuration(NanoTime() - start_time);
   }
   TrimIndirectReferenceTables(self);
   TrimSpaces(self);
   // Trim arenas that may have been used by JIT or verifier.
-  ATRACE_BEGIN("Trimming arena maps");
   runtime->GetArenaPool()->TrimMaps();
-  ATRACE_END();
 }
 
 class TrimIndirectReferenceTableClosure : public Closure {
@@ -1365,9 +1356,7 @@
   explicit TrimIndirectReferenceTableClosure(Barrier* barrier) : barrier_(barrier) {
   }
   virtual void Run(Thread* thread) OVERRIDE NO_THREAD_SAFETY_ANALYSIS {
-    ATRACE_BEGIN("Trimming reference table");
     thread->GetJniEnv()->locals.Trim();
-    ATRACE_END();
     // If thread is a running mutator, then act on behalf of the trim thread.
     // See the code in ThreadList::RunCheckpoint.
     barrier_->Pass(Thread::Current());
@@ -1379,7 +1368,7 @@
 
 void Heap::TrimIndirectReferenceTables(Thread* self) {
   ScopedObjectAccess soa(self);
-  ATRACE_BEGIN(__FUNCTION__);
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   JavaVMExt* vm = soa.Vm();
   // Trim globals indirect reference table.
   vm->TrimGlobals();
@@ -1391,7 +1380,6 @@
   if (barrier_count != 0) {
     barrier.Increment(self, barrier_count);
   }
-  ATRACE_END();
 }
 
 void Heap::StartGC(Thread* self, GcCause cause, CollectorType collector_type) {
@@ -1410,7 +1398,7 @@
     // trimming.
     StartGC(self, kGcCauseTrim, kCollectorTypeHeapTrim);
   }
-  ATRACE_BEGIN(__FUNCTION__);
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   const uint64_t start_ns = NanoTime();
   // Trim the managed spaces.
   uint64_t total_alloc_space_allocated = 0;
@@ -1449,7 +1437,6 @@
   VLOG(heap) << "Heap trim of managed (duration=" << PrettyDuration(gc_heap_end_ns - start_ns)
       << ", advised=" << PrettySize(managed_reclaimed) << ") heap. Managed heap utilization of "
       << static_cast<int>(100 * managed_utilization) << "%.";
-  ATRACE_END();
 }
 
 bool Heap::IsValidObjectAddress(const mirror::Object* obj) const {
@@ -3434,11 +3421,10 @@
       running_collection_is_blocking_ = true;
       VLOG(gc) << "Waiting for a blocking GC " << cause;
     }
-    ATRACE_BEGIN("GC: Wait For Completion");
+    ScopedTrace trace("GC: Wait For Completion");
     // We must wait, change thread state then sleep on gc_complete_cond_;
     gc_complete_cond_->Wait(self);
     last_gc_type = last_gc_type_;
-    ATRACE_END();
   }
   uint64_t wait_time = NanoTime() - wait_start;
   total_wait_time_ += wait_time;
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 5aaf104..a4e5587 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -27,6 +27,7 @@
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/scoped_flock.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "gc/accounting/space_bitmap-inl.h"
@@ -471,6 +472,7 @@
                                         const InstructionSet image_isa,
                                         bool secondary_image,
                                         std::string* error_msg) {
+  ScopedTrace trace(__FUNCTION__);
   std::string system_filename;
   bool has_system = false;
   std::string cache_filename;
@@ -1167,7 +1169,7 @@
   CHECK(image_filename != nullptr);
   CHECK(image_location != nullptr);
 
-  TimingLogger logger(__FUNCTION__, true, false);
+  TimingLogger logger(__PRETTY_FUNCTION__, true, VLOG_IS_ON(image));
   VLOG(image) << "ImageSpace::Init entering image_filename=" << image_filename;
 
   std::unique_ptr<File> file;
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index fd4d0a1..203d3bc 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -17,9 +17,6 @@
 
 #include "rosalloc_space-inl.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include "cutils/trace.h"
-
 #include "base/time_utils.h"
 #include "gc/accounting/card_table.h"
 #include "gc/accounting/space_bitmap-inl.h"
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index a5b63b4..8e49492 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -16,6 +16,7 @@
 
 #include "indirect_reference_table-inl.h"
 
+#include "base/systrace.h"
 #include "jni_internal.h"
 #include "nth_caller_visitor.h"
 #include "reference_table.h"
@@ -261,6 +262,7 @@
 }
 
 void IndirectReferenceTable::Trim() {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   const size_t top_index = Capacity();
   auto* release_start = AlignUp(reinterpret_cast<uint8_t*>(&table_[top_index]), kPageSize);
   uint8_t* release_end = table_mem_map_->End();
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 191c0c7..a41fd45 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -16,15 +16,13 @@
 
 #include "jni_internal.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-
-#include <cutils/trace.h>
 #include <dlfcn.h>
 
 #include "art_method.h"
 #include "base/dumpable.h"
 #include "base/mutex.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "check_jni.h"
 #include "dex_file-inl.h"
 #include "fault_handler.h"
@@ -929,11 +927,10 @@
 // JNI Invocation interface.
 
 extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
-  ATRACE_BEGIN(__FUNCTION__);
+  ScopedTrace trace(__FUNCTION__);
   const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
   if (IsBadJniVersion(args->version)) {
     LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
-    ATRACE_END();
     return JNI_EVERSION;
   }
   RuntimeOptions options;
@@ -943,7 +940,6 @@
   }
   bool ignore_unrecognized = args->ignoreUnrecognized;
   if (!Runtime::Create(options, ignore_unrecognized)) {
-    ATRACE_END();
     return JNI_ERR;
   }
   Runtime* runtime = Runtime::Current();
@@ -952,12 +948,10 @@
     delete Thread::Current()->GetJniEnv();
     delete runtime->GetJavaVM();
     LOG(WARNING) << "CreateJavaVM failed";
-    ATRACE_END();
     return JNI_ERR;
   }
   *p_env = Thread::Current()->GetJniEnv();
   *p_vm = runtime->GetJavaVM();
-  ATRACE_END();
   return JNI_OK;
 }
 
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index e5be2a4..1545cb7 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -20,6 +20,7 @@
 
 #include "art_method-inl.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "debugger_interface.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
@@ -52,6 +53,7 @@
                                    size_t max_capacity,
                                    bool generate_debug_info,
                                    std::string* error_msg) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   CHECK_GE(max_capacity, initial_capacity);
 
   // Generating debug information is mostly for using the 'perf' tool, which does
@@ -255,6 +257,7 @@
 }
 
 void JitCodeCache::RemoveMethodsIn(Thread* self, const LinearAlloc& alloc) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   MutexLock mu(self, lock_);
   // We do not check if a code cache GC is in progress, as this method comes
   // with the classlinker_classes_lock_ held, and suspending ourselves could
@@ -452,6 +455,7 @@
       : code_cache_(code_cache), barrier_(barrier) {}
 
   void Run(Thread* thread) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+    ScopedTrace trace(__PRETTY_FUNCTION__);
     DCHECK(thread == Thread::Current() || thread->IsSuspended());
     MarkCodeVisitor visitor(thread, code_cache_);
     visitor.WalkStack();
@@ -552,6 +556,7 @@
 }
 
 void JitCodeCache::GarbageCollectCache(Thread* self) {
+  ScopedTrace trace(__FUNCTION__);
   if (!garbage_collect_code_) {
     MutexLock mu(self, lock_);
     IncreaseCodeCacheCapacity();
@@ -640,6 +645,7 @@
 }
 
 void JitCodeCache::RemoveUnmarkedCode(Thread* self) {
+  ScopedTrace trace(__FUNCTION__);
   MutexLock mu(self, lock_);
   ScopedCodeCacheWrite scc(code_map_.get());
   // Iterate over all compiled code and remove entries that are not marked.
@@ -661,6 +667,7 @@
 }
 
 void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) {
+  ScopedTrace trace(__FUNCTION__);
   {
     MutexLock mu(self, lock_);
     if (collect_profiling_info) {
@@ -737,6 +744,7 @@
 }
 
 bool JitCodeCache::CheckLiveCompiledCodeHasProfilingInfo() {
+  ScopedTrace trace(__FUNCTION__);
   // Check that methods we have compiled do have a ProfilingInfo object. We would
   // have memory leaks of compiled code otherwise.
   for (const auto& it : method_code_map_) {
@@ -867,6 +875,7 @@
 
 void JitCodeCache::GetCompiledArtMethods(const std::set<std::string>& dex_base_locations,
                                          std::vector<ArtMethod*>& methods) {
+  ScopedTrace trace(__FUNCTION__);
   MutexLock mu(Thread::Current(), lock_);
   for (auto it : method_code_map_) {
     if (ContainsElement(dex_base_locations, it.second->GetDexFile()->GetBaseLocation())) {
diff --git a/runtime/jit/offline_profiling_info.cc b/runtime/jit/offline_profiling_info.cc
index 67c9b5f..ecf34f5 100644
--- a/runtime/jit/offline_profiling_info.cc
+++ b/runtime/jit/offline_profiling_info.cc
@@ -26,6 +26,7 @@
 #include "base/mutex.h"
 #include "base/scoped_flock.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/unix_file/fd_file.h"
 #include "jit/profiling_info.h"
 #include "os.h"
@@ -57,6 +58,7 @@
     return true;
   }
 
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   ScopedFlock flock;
   std::string error;
   if (!flock.Init(filename.c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC, /* block */ false, &error)) {
@@ -132,6 +134,7 @@
  *    app.apk:classes5.dex,218490184,39,13,49,1
  **/
 bool ProfileCompilationInfo::Save(int fd) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   DCHECK_GE(fd, 0);
   // TODO(calin): Profile this and see how much memory it takes. If too much,
   // write to file directly.
@@ -298,6 +301,7 @@
 }
 
 bool ProfileCompilationInfo::Load(int fd) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   DCHECK_GE(fd, 0);
 
   std::string current_line;
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index ab26f6f..bd58157 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -17,6 +17,7 @@
 #include "profile_saver.h"
 
 #include "art_method-inl.h"
+#include "base/systrace.h"
 #include "scoped_thread_state_change.h"
 #include "oat_file_manager.h"
 
@@ -93,6 +94,7 @@
 }
 
 bool ProfileSaver::ProcessProfilingInfo() {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   uint64_t last_update_time_ns = jit_code_cache_->GetLastUpdateTimeNs();
   if (!first_profile_ && last_update_time_ns - code_cache_last_update_time_ns_
           < kMinimumTimeBetweenCodeCacheUpdatesNs) {
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 19c71f6..1ce5841 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -16,14 +16,12 @@
 
 #include "monitor.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-
-#include <cutils/trace.h>
 #include <vector>
 
 #include "art_method-inl.h"
 #include "base/mutex.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "class_linker.h"
 #include "dex_file-inl.h"
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index f912598..c389547 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -35,6 +35,7 @@
 #include "art_method-inl.h"
 #include "base/bit_vector.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/unix_file/fd_file.h"
 #include "elf_file.h"
 #include "elf_utils.h"
@@ -746,6 +747,7 @@
                                     bool executable,
                                     const char* abs_dex_location,
                                     std::string* error_msg) {
+  ScopedTrace trace("Open elf file " + location);
   std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable));
   bool success = oat_file->ElfFileOpen(file, oat_file_begin, writable, executable, error_msg);
   if (!success) {
@@ -768,6 +770,7 @@
 bool ElfOatFile::InitializeFromElfFile(ElfFile* elf_file,
                                        const char* abs_dex_location,
                                        std::string* error_msg) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   if (IsExecutable()) {
     *error_msg = "Cannot initialize from elf file in executable mode.";
     return false;
@@ -787,6 +790,7 @@
                       bool writable,
                       bool executable,
                       std::string* error_msg) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
   if (file == nullptr) {
     *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
@@ -804,6 +808,7 @@
                              bool writable,
                              bool executable,
                              std::string* error_msg) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   // TODO: rename requested_base to oat_data_begin
   elf_file_.reset(ElfFile::Open(file,
                                 writable,
@@ -864,6 +869,7 @@
                        bool executable,
                        const char* abs_dex_location,
                        std::string* error_msg) {
+  ScopedTrace trace("Open oat file " + location);
   CHECK(!filename.empty()) << location;
   CheckLocation(location);
   std::unique_ptr<OatFile> ret;
@@ -1072,6 +1078,7 @@
 }
 
 std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   return DexFile::Open(dex_file_pointer_,
                        FileSize(),
                        dex_file_location_,
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index ea26d58..9ae179f 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -16,14 +16,13 @@
 
 #include "oat_file_manager.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <cutils/trace.h>
 #include <memory>
 #include <queue>
 #include <vector>
 
 #include "base/logging.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "class_linker.h"
 #include "dex_file-inl.h"
 #include "gc/scoped_gc_critical_section.h"
@@ -299,6 +298,7 @@
     jobjectArray dex_elements,
     const OatFile** out_oat_file,
     std::vector<std::string>* error_msgs) {
+  ScopedTrace trace(__FUNCTION__);
   CHECK(dex_location != nullptr);
   CHECK(error_msgs != nullptr);
 
@@ -388,14 +388,15 @@
             ScopedSuspendAll ssa("Add image space");
             runtime->GetHeap()->AddSpace(image_space.get());
           }
-          ATRACE_BEGIN(StringPrintf("Adding image space for location %s", dex_location).c_str());
-          added_image_space = runtime->GetClassLinker()->AddImageSpace(image_space.get(),
-                                                                       h_loader,
-                                                                       dex_elements,
-                                                                       dex_location,
-                                                                       /*out*/&dex_files,
-                                                                       /*out*/&temp_error_msg);
-          ATRACE_END();
+          {
+            ScopedTrace trace2(StringPrintf("Adding image space for location %s", dex_location));
+            added_image_space = runtime->GetClassLinker()->AddImageSpace(image_space.get(),
+                                                                         h_loader,
+                                                                         dex_elements,
+                                                                         dex_location,
+                                                                         /*out*/&dex_files,
+                                                                         /*out*/&temp_error_msg);
+          }
           if (added_image_space) {
             // Successfully added image space to heap, release the map so that it does not get
             // freed.
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 8c813b4..bbb79af 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -23,8 +23,6 @@
 #include <sys/prctl.h>
 #endif
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <cutils/trace.h>
 #include <signal.h>
 #include <sys/syscall.h>
 #include "base/memory_tool.h"
@@ -58,6 +56,7 @@
 #include "base/arena_allocator.h"
 #include "base/dumpable.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker-inl.h"
 #include "compiler_callbacks.h"
@@ -215,7 +214,7 @@
 }
 
 Runtime::~Runtime() {
-  ATRACE_BEGIN("Runtime shutdown");
+  ScopedTrace trace("Runtime shutdown");
   if (is_native_bridge_loaded_) {
     UnloadNativeBridge();
   }
@@ -230,40 +229,34 @@
   Thread* self = Thread::Current();
   const bool attach_shutdown_thread = self == nullptr;
   if (attach_shutdown_thread) {
-    ATRACE_BEGIN("Attach shutdown thread");
     CHECK(AttachCurrentThread("Shutdown thread", false, nullptr, false));
-    ATRACE_END();
     self = Thread::Current();
   } else {
     LOG(WARNING) << "Current thread not detached in Runtime shutdown";
   }
 
   {
-    ATRACE_BEGIN("Wait for shutdown cond");
+    ScopedTrace trace2("Wait for shutdown cond");
     MutexLock mu(self, *Locks::runtime_shutdown_lock_);
     shutting_down_started_ = true;
     while (threads_being_born_ > 0) {
       shutdown_cond_->Wait(self);
     }
     shutting_down_ = true;
-    ATRACE_END();
   }
   // Shutdown and wait for the daemons.
   CHECK(self != nullptr);
   if (IsFinishedStarting()) {
-    ATRACE_BEGIN("Waiting for Daemons");
+    ScopedTrace trace2("Waiting for Daemons");
     self->ClearException();
     self->GetJniEnv()->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,
                                             WellKnownClasses::java_lang_Daemons_stop);
-    ATRACE_END();
   }
 
   Trace::Shutdown();
 
   if (attach_shutdown_thread) {
-    ATRACE_BEGIN("Detach shutdown thread");
     DetachCurrentThread();
-    ATRACE_END();
     self = nullptr;
   }
 
@@ -271,14 +264,13 @@
   heap_->WaitForGcToComplete(gc::kGcCauseBackground, self);
   heap_->DeleteThreadPool();
   if (jit_ != nullptr) {
-    ATRACE_BEGIN("Delete jit");
+    ScopedTrace trace2("Delete jit");
     VLOG(jit) << "Deleting jit thread pool";
     // Delete thread pool before the thread list since we don't want to wait forever on the
     // JIT compiler threads.
     jit_->DeleteThreadPool();
     // Similarly, stop the profile saver thread before deleting the thread list.
     jit_->StopProfileSaver();
-    ATRACE_END();
   }
 
   // Make sure our internal threads are dead before we start tearing down things they're using.
@@ -286,10 +278,10 @@
   delete signal_catcher_;
 
   // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
-  ATRACE_BEGIN("Delete thread list");
-  delete thread_list_;
-  ATRACE_END();
-
+  {
+    ScopedTrace trace2("Delete thread list");
+    delete thread_list_;
+  }
   // Delete the JIT after thread list to ensure that there is no remaining threads which could be
   // accessing the instrumentation when we delete it.
   if (jit_ != nullptr) {
@@ -300,7 +292,7 @@
   // Shutdown the fault manager if it was initialized.
   fault_manager.Shutdown();
 
-  ATRACE_BEGIN("Delete state");
+  ScopedTrace trace2("Delete state");
   delete monitor_list_;
   delete monitor_pool_;
   delete class_linker_;
@@ -318,12 +310,10 @@
   arena_pool_.reset();
   jit_arena_pool_.reset();
   MemMap::Shutdown();
-  ATRACE_END();
 
   // TODO: acquire a static mutex on Runtime to avoid racing.
   CHECK(instance_ == nullptr || instance_ == this);
   instance_ = nullptr;
-  ATRACE_END();
 }
 
 struct AbortState {
@@ -562,12 +552,14 @@
   // Use !IsAotCompiler so that we get test coverage, tests are never the zygote.
   if (!IsAotCompiler()) {
     ScopedObjectAccess soa(self);
-    ATRACE_BEGIN("AddImageStringsToTable");
-    GetInternTable()->AddImagesStringsToTable(heap_->GetBootImageSpaces());
-    ATRACE_END();
-    ATRACE_BEGIN("MoveImageClassesToClassTable");
-    GetClassLinker()->AddBootImageClassesToClassTable();
-    ATRACE_END();
+    {
+      ScopedTrace trace2("AddImageStringsToTable");
+      GetInternTable()->AddImagesStringsToTable(heap_->GetBootImageSpaces());
+    }
+    {
+      ScopedTrace trace2("MoveImageClassesToClassTable");
+      GetClassLinker()->AddBootImageClassesToClassTable();
+    }
   }
 
   // If we are the zygote then we need to wait until after forking to create the code cache
@@ -585,9 +577,10 @@
 
   // InitNativeMethods needs to be after started_ so that the classes
   // it touches will have methods linked to the oat file if necessary.
-  ATRACE_BEGIN("InitNativeMethods");
-  InitNativeMethods();
-  ATRACE_END();
+  {
+    ScopedTrace trace2("InitNativeMethods");
+    InitNativeMethods();
+  }
 
   // Initialize well known thread group values that may be accessed threads while attaching.
   InitThreadGroups(self);
@@ -613,9 +606,7 @@
                             GetInstructionSetString(kRuntimeISA));
   }
 
-  ATRACE_BEGIN("StartDaemonThreads");
   StartDaemonThreads();
-  ATRACE_END();
 
   {
     ScopedObjectAccess soa(self);
@@ -750,6 +741,7 @@
 }
 
 void Runtime::StartDaemonThreads() {
+  ScopedTrace trace(__FUNCTION__);
   VLOG(startup) << "Runtime::StartDaemonThreads entering";
 
   Thread* self = Thread::Current();
@@ -893,7 +885,7 @@
 
 bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
   RuntimeArgumentMap runtime_options(std::move(runtime_options_in));
-  ATRACE_BEGIN("Runtime::Init");
+  ScopedTrace trace(__FUNCTION__);
   CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
 
   MemMap::Init();
@@ -960,7 +952,6 @@
   is_low_memory_mode_ = runtime_options.Exists(Opt::LowMemoryMode);
 
   XGcOption xgc_option = runtime_options.GetOrDefault(Opt::GcOption);
-  ATRACE_BEGIN("CreateHeap");
   heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
                        runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
                        runtime_options.GetOrDefault(Opt::HeapMinFree),
@@ -991,11 +982,9 @@
                        xgc_option.gcstress_,
                        runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
                        runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));
-  ATRACE_END();
 
   if (!heap_->HasBootImageSpace() && !allow_dex_file_fallback_) {
     LOG(ERROR) << "Dex file fallback disabled, cannot continue without image.";
-    ATRACE_END();
     return false;
   }
 
@@ -1105,10 +1094,8 @@
   CHECK_GE(GetHeap()->GetContinuousSpaces().size(), 1U);
   class_linker_ = new ClassLinker(intern_table_);
   if (GetHeap()->HasBootImageSpace()) {
-    ATRACE_BEGIN("InitFromImage");
     std::string error_msg;
     bool result = class_linker_->InitFromBootImage(&error_msg);
-    ATRACE_END();
     if (!result) {
       LOG(ERROR) << "Could not initialize from image: " << error_msg;
       return false;
@@ -1251,8 +1238,6 @@
 
   VLOG(startup) << "Runtime::Init exiting";
 
-  ATRACE_END();
-
   return true;
 }
 
@@ -1468,10 +1453,12 @@
 
 bool Runtime::AttachCurrentThread(const char* thread_name, bool as_daemon, jobject thread_group,
                                   bool create_peer) {
+  ScopedTrace trace(__FUNCTION__);
   return Thread::Attach(thread_name, as_daemon, thread_group, create_peer) != nullptr;
 }
 
 void Runtime::DetachCurrentThread() {
+  ScopedTrace trace(__FUNCTION__);
   Thread* self = Thread::Current();
   if (self == nullptr) {
     LOG(FATAL) << "attempting to detach thread that is not attached";
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 2ee1605..6b8c0c2 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -14,11 +14,8 @@
  * limitations under the License.
  */
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-
 #include "thread.h"
 
-#include <cutils/trace.h>
 #include <pthread.h>
 #include <signal.h>
 #include <sys/resource.h>
@@ -39,6 +36,7 @@
 #include "base/mutex.h"
 #include "base/timing_logger.h"
 #include "base/to_str.h"
+#include "base/systrace.h"
 #include "class_linker-inl.h"
 #include "debugger.h"
 #include "dex_file-inl.h"
@@ -1119,9 +1117,8 @@
   bool found_checkpoint = false;
   for (uint32_t i = 0; i < kMaxCheckpoints; ++i) {
     if (checkpoints[i] != nullptr) {
-      ATRACE_BEGIN("Checkpoint function");
+      ScopedTrace trace("Run checkpoint function");
       checkpoints[i]->Run(this);
-      ATRACE_END();
       found_checkpoint = true;
     }
   }
@@ -1187,14 +1184,13 @@
 }
 
 void Thread::FullSuspendCheck() {
+  ScopedTrace trace(__FUNCTION__);
   VLOG(threads) << this << " self-suspending";
-  ATRACE_BEGIN("Full suspend check");
   // Make thread appear suspended to other threads, release mutator_lock_.
   tls32_.suspended_at_suspend_check = true;
   // Transition to suspended and back to runnable, re-acquire share on mutator_lock_.
   ScopedThreadSuspension(this, kSuspended);
   tls32_.suspended_at_suspend_check = false;
-  ATRACE_END();
   VLOG(threads) << this << " self-reviving";
 }
 
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 49d54fd..cf515b6 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -16,10 +16,7 @@
 
 #include "thread_list.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-
 #include <backtrace/BacktraceMap.h>
-#include <cutils/trace.h>
 #include <dirent.h>
 #include <ScopedLocalRef.h>
 #include <ScopedUtfChars.h>
@@ -30,6 +27,7 @@
 
 #include "base/histogram-inl.h"
 #include "base/mutex-inl.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "debugger.h"
@@ -69,38 +67,29 @@
 }
 
 ThreadList::~ThreadList() {
-  ATRACE_BEGIN(__FUNCTION__);
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   // Detach the current thread if necessary. If we failed to start, there might not be any threads.
   // We need to detach the current thread here in case there's another thread waiting to join with
   // us.
   bool contains = false;
+  Thread* self = Thread::Current();
   {
-    Thread* self = Thread::Current();
     MutexLock mu(self, *Locks::thread_list_lock_);
     contains = Contains(self);
   }
   if (contains) {
-    ATRACE_BEGIN("DetachCurrentThread");
     Runtime::Current()->DetachCurrentThread();
-    ATRACE_END();
   }
-  ATRACE_BEGIN("WaitForOtherNonDaemonThreadsToExit");
   WaitForOtherNonDaemonThreadsToExit();
-  ATRACE_END();
   // Disable GC and wait for GC to complete in case there are still daemon threads doing
   // allocations.
   gc::Heap* const heap = Runtime::Current()->GetHeap();
   heap->DisableGCForShutdown();
   // In case a GC is in progress, wait for it to finish.
-  ATRACE_BEGIN("WaitForGcToComplete");
   heap->WaitForGcToComplete(gc::kGcCauseBackground, Thread::Current());
-  ATRACE_END();
   // TODO: there's an unaddressed race here where a thread may attach during shutdown, see
   //       Thread::Init.
-  ATRACE_BEGIN("SuspendAllDaemonThreadsForShutdown");
   SuspendAllDaemonThreadsForShutdown();
-  ATRACE_END();
-  ATRACE_END();
 }
 
 bool ThreadList::Contains(Thread* thread) {
@@ -475,42 +464,42 @@
   } else {
     VLOG(threads) << "Thread[null] SuspendAll for " << cause << " starting...";
   }
-  ATRACE_BEGIN("Suspending mutator threads");
-  const uint64_t start_time = NanoTime();
+  {
+    ScopedTrace trace("Suspending mutator threads");
+    const uint64_t start_time = NanoTime();
 
-  SuspendAllInternal(self, self);
-  // All threads are known to have suspended (but a thread may still own the mutator lock)
-  // Make sure this thread grabs exclusive access to the mutator lock and its protected data.
+    SuspendAllInternal(self, self);
+    // All threads are known to have suspended (but a thread may still own the mutator lock)
+    // Make sure this thread grabs exclusive access to the mutator lock and its protected data.
 #if HAVE_TIMED_RWLOCK
-  while (true) {
-    if (Locks::mutator_lock_->ExclusiveLockWithTimeout(self, kThreadSuspendTimeoutMs, 0)) {
-      break;
-    } else if (!long_suspend_) {
-      // Reading long_suspend without the mutator lock is slightly racy, in some rare cases, this
-      // could result in a thread suspend timeout.
-      // Timeout if we wait more than kThreadSuspendTimeoutMs seconds.
-      UnsafeLogFatalForThreadSuspendAllTimeout();
+    while (true) {
+      if (Locks::mutator_lock_->ExclusiveLockWithTimeout(self, kThreadSuspendTimeoutMs, 0)) {
+        break;
+      } else if (!long_suspend_) {
+        // Reading long_suspend without the mutator lock is slightly racy, in some rare cases, this
+        // could result in a thread suspend timeout.
+        // Timeout if we wait more than kThreadSuspendTimeoutMs seconds.
+        UnsafeLogFatalForThreadSuspendAllTimeout();
+      }
     }
-  }
 #else
-  Locks::mutator_lock_->ExclusiveLock(self);
+    Locks::mutator_lock_->ExclusiveLock(self);
 #endif
 
-  long_suspend_ = long_suspend;
+    long_suspend_ = long_suspend;
 
-  const uint64_t end_time = NanoTime();
-  const uint64_t suspend_time = end_time - start_time;
-  suspend_all_historam_.AdjustAndAddValue(suspend_time);
-  if (suspend_time > kLongThreadSuspendThreshold) {
-    LOG(WARNING) << "Suspending all threads took: " << PrettyDuration(suspend_time);
+    const uint64_t end_time = NanoTime();
+    const uint64_t suspend_time = end_time - start_time;
+    suspend_all_historam_.AdjustAndAddValue(suspend_time);
+    if (suspend_time > kLongThreadSuspendThreshold) {
+      LOG(WARNING) << "Suspending all threads took: " << PrettyDuration(suspend_time);
+    }
+
+    if (kDebugLocking) {
+      // Debug check that all threads are suspended.
+      AssertThreadsAreSuspended(self, self);
+    }
   }
-
-  if (kDebugLocking) {
-    // Debug check that all threads are suspended.
-    AssertThreadsAreSuspended(self, self);
-  }
-
-  ATRACE_END();
   ATRACE_BEGIN((std::string("Mutator threads suspended for ") + cause).c_str());
 
   if (self != nullptr) {
@@ -640,7 +629,8 @@
   }
 
   ATRACE_END();
-  ATRACE_BEGIN("Resuming mutator threads");
+
+  ScopedTrace trace("Resuming mutator threads");
 
   if (kDebugLocking) {
     // Debug check that all threads are suspended.
@@ -672,7 +662,6 @@
     }
     Thread::resume_cond_->Broadcast(self);
   }
-  ATRACE_END();
 
   if (self != nullptr) {
     VLOG(threads) << *self << " ResumeAll complete";
@@ -1117,6 +1106,7 @@
 }
 
 void ThreadList::WaitForOtherNonDaemonThreadsToExit() {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   Thread* self = Thread::Current();
   Locks::mutator_lock_->AssertNotHeld(self);
   while (true) {
@@ -1148,6 +1138,7 @@
 }
 
 void ThreadList::SuspendAllDaemonThreadsForShutdown() {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
   Thread* self = Thread::Current();
   MutexLock mu(self, *Locks::thread_list_lock_);
   size_t daemons_left = 0;
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 6b82641..b879355 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -19,12 +19,10 @@
 #include <sys/uio.h>
 #include <unistd.h>
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include "cutils/trace.h"
-
 #include "art_method-inl.h"
 #include "base/casts.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
@@ -286,7 +284,7 @@
 
   while (true) {
     usleep(interval_us);
-    ATRACE_BEGIN("Profile sampling");
+    ScopedTrace trace("Profile sampling");
     Thread* self = Thread::Current();
     Trace* the_trace;
     {
@@ -301,7 +299,6 @@
       MutexLock mu(self, *Locks::thread_list_lock_);
       runtime->GetThreadList()->ForEach(GetSample, the_trace);
     }
-    ATRACE_END();
   }
 
   runtime->DetachCurrentThread();
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f71ebfe..4019656 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -16,9 +16,6 @@
 
 #include "method_verifier-inl.h"
 
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <cutils/trace.h>
-
 #include <iostream>
 
 #include "art_field-inl.h"
@@ -26,6 +23,7 @@
 #include "base/logging.h"
 #include "base/mutex-inl.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "base/time_utils.h"
 #include "class_linker.h"
 #include "compiler_callbacks.h"
@@ -272,6 +270,7 @@
                                                         bool log_hard_failures,
                                                         std::string* error) {
   DCHECK(class_def != nullptr);
+  ScopedTrace trace(__FUNCTION__);
 
   // A class must not be abstract and final.
   if ((class_def->access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
@@ -286,7 +285,6 @@
     // empty class, probably a marker interface
     return kNoFailure;
   }
-  ATRACE_BEGIN("VerifyClass");
   ClassDataItemIterator it(*dex_file, class_data);
   while (it.HasNextStaticField() || it.HasNextInstanceField()) {
     it.Next();
@@ -321,8 +319,6 @@
 
   data1.Merge(data2);
 
-  ATRACE_END();
-
   if (data1.kind == kNoFailure) {
     return kNoFailure;
   } else {