Clean up verbose logging.

Change-Id: I6b01980e7145c4f8d25a5b50f620903f61a1b427
diff --git a/src/check_jni.cc b/src/check_jni.cc
index 2af35bb..89f0693 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -119,7 +119,7 @@
   if (!vm->trace.empty() && classNameStr.find(vm->trace) != std::string::npos) {
     return true;
   }
-  if (vm->log_third_party_jni) {
+  if (VLOG_IS_ON(third_party_jni)) {
     // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
     // like part of Android.
     StringPiece className(classNameStr);
@@ -385,7 +385,7 @@
     va_list ap;
 
     const Method* traceMethod = NULL;
-    if ((!vm_->trace.empty() || vm_->log_third_party_jni) && has_method_) {
+    if ((!vm_->trace.empty() || VLOG_IS_ON(third_party_jni)) && has_method_) {
       // We need to guard some of the invocation interface's calls: a bad caller might
       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
       Thread* self = Thread::Current();
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 04a368d8..dd8fc11 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -199,24 +199,21 @@
   DISALLOW_COPY_AND_ASSIGN(ObjectLock);
 };
 
-ClassLinker* ClassLinker::Create(bool verbose,
-                                 const std::string& boot_class_path,
-                                 InternTable* intern_table) {
+ClassLinker* ClassLinker::Create(const std::string& boot_class_path, InternTable* intern_table) {
   CHECK_NE(boot_class_path.size(), 0U);
-  UniquePtr<ClassLinker> class_linker(new ClassLinker(verbose, intern_table));
+  UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
   class_linker->Init(boot_class_path);
   return class_linker.release();
 }
 
-ClassLinker* ClassLinker::Create(bool verbose, InternTable* intern_table) {
-  UniquePtr<ClassLinker> class_linker(new ClassLinker(verbose, intern_table));
+ClassLinker* ClassLinker::Create(InternTable* intern_table) {
+  UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
   class_linker->InitFromImage();
   return class_linker.release();
 }
 
-ClassLinker::ClassLinker(bool verbose, InternTable* intern_table)
-    : verbose_(verbose),
-      dex_lock_("ClassLinker dex lock"),
+ClassLinker::ClassLinker(InternTable* intern_table)
+    : dex_lock_("ClassLinker dex lock"),
       classes_lock_("ClassLinker classes lock"),
       class_roots_(NULL),
       array_iftable_(NULL),
@@ -240,10 +237,7 @@
 }
 
 void ClassLinker::Init(const std::string& boot_class_path) {
-  const Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::InitFrom entering boot_class_path=" << boot_class_path;
-  }
+  VLOG(startup) << "ClassLinker::InitFrom entering boot_class_path=" << boot_class_path;
 
   CHECK(!init_done_);
 
@@ -475,16 +469,11 @@
 
   FinishInit();
 
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::InitFrom exiting";
-  }
+  VLOG(startup) << "ClassLinker::InitFrom exiting";
 }
 
 void ClassLinker::FinishInit() {
-  const Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::FinishInit entering";
-  }
+  VLOG(startup) << "ClassLinker::FinishInit entering";
 
   // Let the heap know some key offsets into java.lang.ref instances
   // Note: we hard code the field indexes here rather than using FindInstanceField
@@ -550,9 +539,7 @@
   // that Object, Class, and Object[] are setup
   init_done_ = true;
 
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::FinishInit exiting";
-  }
+  VLOG(startup) << "ClassLinker::FinishInit exiting";
 }
 
 void ClassLinker::RunRootClinits() {
@@ -617,9 +604,7 @@
 OatFile* ClassLinker::OpenOat(const Space* space) {
   MutexLock mu(dex_lock_);
   const Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::OpenOat entering";
-  }
+  VLOG(startup) << "ClassLinker::OpenOat entering";
   const ImageHeader& image_header = space->GetImageHeader();
   // Grab location but don't use Object::AsString as we haven't yet initialized the roots to
   // check the down cast
@@ -641,9 +626,7 @@
     return NULL;
   }
   oat_files_.push_back(oat_file);
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::OpenOat exiting";
-  }
+  VLOG(startup) << "ClassLinker::OpenOat exiting";
   return oat_file;
 }
 
@@ -732,9 +715,7 @@
 
 void ClassLinker::InitFromImage() {
   const Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::InitFromImage entering";
-  }
+  VLOG(startup) << "ClassLinker::InitFromImage entering";
   CHECK(!init_done_);
 
   const std::vector<Space*>& spaces = Heap::GetSpaces();
@@ -806,9 +787,7 @@
 
   FinishInit();
 
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "ClassLinker::InitFromImage exiting";
-  }
+  VLOG(startup) << "ClassLinker::InitFromImage exiting";
 }
 
 void ClassLinker::InitFromImageCallback(Object* obj, void* arg) {
@@ -1604,7 +1583,7 @@
 }
 
 bool ClassLinker::InsertClass(const std::string& descriptor, Class* klass, bool image_class) {
-  if (verbose_) {
+  if (VLOG_IS_ON(class_linker)) {
     DexCache* dex_cache = klass->GetDexCache();
     std::string source;
     if (dex_cache != NULL) {
@@ -1909,7 +1888,7 @@
       global_stats->class_init_time_ns += (t1 - t0);
       thread_stats->class_init_time_ns += (t1 - t0);
       klass->SetStatus(Class::kStatusInitialized);
-      if (verbose_) {
+      if (VLOG_IS_ON(class_linker)) {
         ClassHelper kh(klass);
         LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
       }
diff --git a/src/class_linker.h b/src/class_linker.h
index 089040f..5cd72b8 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -46,10 +46,10 @@
 class ClassLinker {
  public:
   // Creates the class linker by boot strapping from dex files.
-  static ClassLinker* Create(bool verbose, const std::string& boot_class_path, InternTable* intern_table);
+  static ClassLinker* Create(const std::string& boot_class_path, InternTable* intern_table);
 
   // Creates the class linker from one or more images.
-  static ClassLinker* Create(bool verbose, InternTable* intern_table);
+  static ClassLinker* Create(InternTable* intern_table);
 
   ~ClassLinker();
 
@@ -252,7 +252,7 @@
   pid_t GetDexLockOwner(); // For SignalCatcher.
 
  private:
-  explicit ClassLinker(bool verbose, InternTable*);
+  explicit ClassLinker(InternTable*);
 
   // Initialize class linker by bootstraping from dex files
   void Init(const std::string& boot_class_path);
@@ -365,8 +365,6 @@
   Method* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class);
   Method* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype);
 
-  const bool verbose_;
-
   std::vector<const DexFile*> boot_class_path_;
 
   std::vector<const DexFile*> dex_files_;
diff --git a/src/compiler.cc b/src/compiler.cc
index e437062..7ed953b 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -42,8 +42,7 @@
     : instruction_set_(instruction_set),
       jni_compiler_(instruction_set),
       image_(image),
-      image_classes_(image_classes),
-      verbose_(false) {
+      image_classes_(image_classes) {
   CHECK(!Runtime::Current()->IsStarted());
   if (!image_) {
     CHECK(image_classes_ == NULL);
diff --git a/src/compiler.h b/src/compiler.h
index 4e1be1d..f05f80b 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -45,14 +45,6 @@
     return image_;
   }
 
-  void SetVerbose(bool verbose) {
-    verbose_ = verbose;
-  }
-
-  bool IsVerbose() const {
-    return verbose_;
-  }
-
   // Stub to throw AbstractMethodError
   static ByteArray* CreateAbstractMethodErrorStub(InstructionSet instruction_set);
 
@@ -155,8 +147,6 @@
 
   const std::set<std::string>* image_classes_;
 
-  bool verbose_;
-
   DISALLOW_COPY_AND_ASSIGN(Compiler);
 };
 
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index ecc281b..75f5d7d 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -698,9 +698,7 @@
                                  const art::ClassLoader* class_loader,
                                  const art::DexFile& dex_file, art::InstructionSet insnSet)
 {
-    if (compiler.IsVerbose()) {
-        LOG(INFO) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
-    }
+    VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
     oatArenaReset();
 
     const u2* codePtr = code_item->insns_;
@@ -735,7 +733,7 @@
     if (!useMatch || match) {
         cUnit->disableOpt = compilerOptimizerDisableFlags;
         cUnit->enableDebug = compilerDebugFlags;
-        cUnit->printMe = compiler.IsVerbose() || (cUnit->enableDebug & (1 << kDebugVerbose));
+        cUnit->printMe = VLOG_IS_ON(compiler) || (cUnit->enableDebug & (1 << kDebugVerbose));
     }
 
     /* Assume non-throwing leaf */
@@ -919,10 +917,8 @@
                                                 cUnit->fpSpillMask, cUnit->mappingTable,
                                                 vmapTable);
 
-    if (compiler.IsVerbose()) {
-        LOG(INFO) << "Compiled " << PrettyMethod(method_idx, dex_file)
-                  << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0])) << " bytes)";
-    }
+    VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
+                   << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0])) << " bytes)";
 
     return result;
 }
@@ -933,9 +929,7 @@
     if (initialized)
         return;
     initialized = true;
-    if (compiler.IsVerbose()) {
-        LOG(INFO) << "Initializing compiler";
-    }
+    VLOG(compiler) << "Initializing compiler";
     if (!oatArchInit()) {
         LOG(FATAL) << "Failed to initialize oat";
     }
diff --git a/src/dalvik_system_Zygote.cc b/src/dalvik_system_Zygote.cc
index e3a2cdd..d74d3eb 100644
--- a/src/dalvik_system_Zygote.cc
+++ b/src/dalvik_system_Zygote.cc
@@ -219,7 +219,7 @@
   }
 
   if ((debug_flags & DEBUG_ENABLE_JNI_LOGGING) != 0) {
-    Runtime::Current()->GetJavaVM()->log_third_party_jni = true;
+    gLogVerbosity.third_party_jni = true;
     debug_flags &= ~DEBUG_ENABLE_JNI_LOGGING;
   }
 
diff --git a/src/debugger.cc b/src/debugger.cc
index eede552..b524359 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -281,7 +281,7 @@
  * "transport=dt_socket,address=8000,server=y,suspend=n"
  */
 bool Dbg::ParseJdwpOptions(const std::string& options) {
-  LOG(VERBOSE) << "ParseJdwpOptions: " << options;
+  VLOG(jdwp) << "ParseJdwpOptions: " << options;
 
   std::vector<std::string> pairs;
   Split(options, ',', pairs);
@@ -376,7 +376,7 @@
 
 void Dbg::Connected() {
   CHECK(!gDebuggerConnected);
-  LOG(VERBOSE) << "JDWP has attached";
+  VLOG(jdwp) << "JDWP has attached";
   gDebuggerConnected = true;
 }
 
@@ -971,7 +971,7 @@
     static void Callback(void* context, uint16_t slot, uint32_t startAddress, uint32_t endAddress, const char* name, const char* descriptor, const char* signature) {
       DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
 
-      LOG(VERBOSE) << StringPrintf("    %2d: %d(%d) '%s' '%s' '%s' slot=%d", pContext->variable_count, startAddress, endAddress - startAddress, name, descriptor, signature, slot);
+      VLOG(jdwp) << StringPrintf("    %2d: %d(%d) '%s' '%s' '%s' slot=%d", pContext->variable_count, startAddress, endAddress - startAddress, name, descriptor, signature, slot);
 
       slot = MangleSlot(slot, name);
 
@@ -1355,7 +1355,7 @@
     {
       CHECK_EQ(width, 1U);
       uint32_t intVal = f.GetVReg(m, reg);
-      LOG(VERBOSE) << "get boolean local " << reg << " = " << intVal;
+      VLOG(jdwp) << "get boolean local " << reg << " = " << intVal;
       JDWP::Set1(buf+1, intVal != 0);
     }
     break;
@@ -1363,7 +1363,7 @@
     {
       CHECK_EQ(width, 1U);
       uint32_t intVal = f.GetVReg(m, reg);
-      LOG(VERBOSE) << "get byte local " << reg << " = " << intVal;
+      VLOG(jdwp) << "get byte local " << reg << " = " << intVal;
       JDWP::Set1(buf+1, intVal);
     }
     break;
@@ -1372,7 +1372,7 @@
     {
       CHECK_EQ(width, 2U);
       uint32_t intVal = f.GetVReg(m, reg);
-      LOG(VERBOSE) << "get short/char local " << reg << " = " << intVal;
+      VLOG(jdwp) << "get short/char local " << reg << " = " << intVal;
       JDWP::Set2BE(buf+1, intVal);
     }
     break;
@@ -1381,7 +1381,7 @@
     {
       CHECK_EQ(width, 4U);
       uint32_t intVal = f.GetVReg(m, reg);
-      LOG(VERBOSE) << "get int/float local " << reg << " = " << intVal;
+      VLOG(jdwp) << "get int/float local " << reg << " = " << intVal;
       JDWP::Set4BE(buf+1, intVal);
     }
     break;
@@ -1389,7 +1389,7 @@
     {
       CHECK_EQ(width, sizeof(JDWP::ObjectId));
       Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
-      LOG(VERBOSE) << "get array local " << reg << " = " << o;
+      VLOG(jdwp) << "get array local " << reg << " = " << o;
       if (o != NULL && !Heap::IsHeapAddress(o)) {
         LOG(FATAL) << "Register " << reg << " expected to hold array: " << o;
       }
@@ -1400,7 +1400,7 @@
     {
       CHECK_EQ(width, sizeof(JDWP::ObjectId));
       Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
-      LOG(VERBOSE) << "get object local " << reg << " = " << o;
+      VLOG(jdwp) << "get object local " << reg << " = " << o;
       if (o != NULL && !Heap::IsHeapAddress(o)) {
         LOG(FATAL) << "Register " << reg << " expected to hold object: " << o;
       }
@@ -1415,7 +1415,7 @@
       uint32_t lo = f.GetVReg(m, reg);
       uint64_t hi = f.GetVReg(m, reg + 1);
       uint64_t longVal = (hi << 32) | lo;
-      LOG(VERBOSE) << "get double/long local " << hi << ":" << lo << " = " << longVal;
+      VLOG(jdwp) << "get double/long local " << hi << ":" << lo << " = " << longVal;
       JDWP::Set8BE(buf+1, longVal);
     }
     break;
@@ -1607,15 +1607,15 @@
      */
     ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
 
-    LOG(VERBOSE) << "    Transferring control to event thread";
+    VLOG(jdwp) << "    Transferring control to event thread";
     {
       MutexLock mu(req->lock_);
 
       if ((options & JDWP::INVOKE_SINGLE_THREADED) == 0) {
-        LOG(VERBOSE) << "      Resuming all threads";
+        VLOG(jdwp) << "      Resuming all threads";
         thread_list->ResumeAll(true);
       } else {
-        LOG(VERBOSE) << "      Resuming event thread only";
+        VLOG(jdwp) << "      Resuming event thread only";
         thread_list->Resume(targetThread, true);
       }
 
@@ -1624,7 +1624,7 @@
         req->cond_.Wait(req->lock_);
       }
     }
-    LOG(VERBOSE) << "    Control has returned from event thread";
+    VLOG(jdwp) << "    Control has returned from event thread";
 
     /* wait for thread to re-suspend itself */
     targetThread->WaitUntilSuspended();
@@ -1639,9 +1639,9 @@
    * so we want to resume the target thread once to keep the books straight.
    */
   if ((options & JDWP::INVOKE_SINGLE_THREADED) == 0) {
-    LOG(VERBOSE) << "      Suspending all threads";
+    VLOG(jdwp) << "      Suspending all threads";
     thread_list->SuspendAll(true);
-    LOG(VERBOSE) << "      Resuming event thread to balance the count";
+    VLOG(jdwp) << "      Resuming event thread to balance the count";
     thread_list->Resume(targetThread, true);
   }
 
@@ -1668,10 +1668,10 @@
 
   // Translate the method through the vtable, unless the debugger wants to suppress it.
   Method* m = pReq->method_;
-  LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m);
+  VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m);
   if ((pReq->options_ & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver_ != NULL) {
     m = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_);
-    LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m);
+    VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m);
   }
   CHECK(m != NULL);
 
@@ -1683,14 +1683,14 @@
   pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty());
   if (pReq->exception != 0) {
     Object* exc = self->GetException();
-    LOG(VERBOSE) << "  JDWP invocation returning with exception=" << exc << " " << PrettyTypeOf(exc);
+    VLOG(jdwp) << "  JDWP invocation returning with exception=" << exc << " " << PrettyTypeOf(exc);
     self->ClearException();
     pReq->result_value.j = 0;
   } else if (pReq->result_tag == JDWP::JT_OBJECT) {
     /* if no exception thrown, examine object result more closely */
     JDWP::JdwpTag new_tag = TagFromObject(pReq->result_value.l);
     if (new_tag != pReq->result_tag) {
-      LOG(VERBOSE) << "  JDWP promoted result from " << pReq->result_tag << " to " << new_tag;
+      VLOG(jdwp) << "  JDWP promoted result from " << pReq->result_tag << " to " << new_tag;
       pReq->result_tag = new_tag;
     }
 
@@ -1799,7 +1799,7 @@
   offset = env->GetIntField(chunk.get(), offset_fid);
   type = env->GetIntField(chunk.get(), type_fid);
 
-  LOG(VERBOSE) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length);
+  VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length);
   if (length == 0 || replyData.get() == NULL) {
     return false;
   }
@@ -1822,12 +1822,12 @@
   *pReplyBuf = reply;
   *pReplyLen = length + kChunkHdrLen;
 
-  LOG(VERBOSE) << StringPrintf("dvmHandleDdm returning type=%.4s buf=%p len=%d", (char*) reply, reply, length);
+  VLOG(jdwp) << StringPrintf("dvmHandleDdm returning type=%.4s buf=%p len=%d", (char*) reply, reply, length);
   return true;
 }
 
 void Dbg::DdmBroadcast(bool connect) {
-  LOG(VERBOSE) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "...";
+  VLOG(jdwp) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "...";
 
   Thread* self = Thread::Current();
   if (self->GetState() != Thread::kRunnable) {
@@ -1931,7 +1931,7 @@
 
 void Dbg::DdmSendChunkV(uint32_t type, const struct iovec* iov, int iov_count) {
   if (gJdwpState == NULL) {
-    LOG(VERBOSE) << "Debugger thread not active, ignoring DDM send: " << type;
+    VLOG(jdwp) << "Debugger thread not active, ignoring DDM send: " << type;
   } else {
     gJdwpState->DdmSendChunkV(type, iov, iov_count);
   }
diff --git a/src/heap.cc b/src/heap.cc
index 6b2ea71..07ed14f 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -19,10 +19,6 @@
 
 namespace art {
 
-bool Heap::is_verbose_heap_ = false;
-
-bool Heap::is_verbose_gc_ = false;
-
 std::vector<Space*> Heap::spaces_;
 
 Space* Heap::alloc_space_ = NULL;
@@ -60,14 +56,9 @@
 
 bool Heap::verify_objects_ = false;
 
-void Heap::Init(bool is_verbose_heap, bool is_verbose_gc,
-                size_t initial_size, size_t maximum_size, size_t growth_size,
+void Heap::Init(size_t initial_size, size_t maximum_size, size_t growth_size,
                 const std::vector<std::string>& image_file_names) {
-  is_verbose_heap_ = is_verbose_heap;
-  is_verbose_gc_ = is_verbose_gc;
-
-  const Runtime* runtime = Runtime::Current();
-  if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
+  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "Heap::Init entering";
   }
 
@@ -149,7 +140,7 @@
   // make it clear that you can't use locks during heap initialization.
   lock_ = new Mutex("Heap lock");
 
-  if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
+  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "Heap::Init exiting";
   }
 }
@@ -307,8 +298,7 @@
 }
 
 void Heap::RecordImageAllocations(Space* space) {
-  const Runtime* runtime = Runtime::Current();
-  if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
+  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "Heap::RecordImageAllocations entering";
   }
   DCHECK(!Runtime::Current()->IsStarted());
@@ -321,7 +311,7 @@
     live_bitmap_->Set(obj);
     current += RoundUp(obj->SizeOf(), kObjectAlignment);
   }
-  if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
+  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "Heap::RecordImageAllocations exiting";
   }
 }
@@ -388,10 +378,8 @@
     // OLD-TODO: may want to grow a little bit more so that the amount of
     //       free space is equal to the old free space + the
     //       utilization slop for the new allocation.
-    if (Heap::IsVerboseGc()) {
-      LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
-                << " for " << size << "-byte allocation";
-    }
+    VLOG(gc) << "Grow heap (frag case) to " << new_footprint / MB
+             << " for " << size << "-byte allocation";
     return ptr;
   }
 
@@ -402,10 +390,7 @@
   // cleared before throwing an OOME.
 
   // OLD-TODO: wait for the finalizers from the previous GC to finish
-  if (Heap::IsVerboseGc()) {
-    LOG(INFO) << "Forcing collection of SoftReferences for "
-              << size << "-byte allocation";
-  }
+  VLOG(gc) << "Forcing collection of SoftReferences for " << size << "-byte allocation";
   CollectGarbageInternal();
   ptr = space->AllocWithGrowth(size);
   if (ptr != NULL) {
@@ -546,14 +531,14 @@
 
   uint32_t duration = (t1 - t0)/1000/1000;
   bool gc_was_particularly_slow = (duration > 100); // TODO: crank this down for concurrent.
-  if (Heap::IsVerboseGc() || gc_was_particularly_slow) {
+  if (VLOG_IS_ON(gc) || gc_was_particularly_slow) {
     LOG(INFO) << "GC freed " << (is_small ? "<" : "") << kib_freed << "KiB, "
               << percentFree << "% free "
               << (num_bytes_allocated_/1024) << "KiB/" << (total/1024) << "KiB, "
               << "paused " << duration << "ms";
   }
   Dbg::GcDidFinish();
-  if (Heap::IsVerboseHeap()) {
+  if (VLOG_IS_ON(heap)) {
     timings.Dump();
   }
 }
@@ -590,13 +575,10 @@
 // value.
 // Old spaces will count against the ideal size.
 //
-void Heap::SetIdealFootprint(size_t max_allowed_footprint)
-{
+void Heap::SetIdealFootprint(size_t max_allowed_footprint) {
   if (max_allowed_footprint > Heap::growth_size_) {
-    if (Heap::IsVerboseGc()) {
-      LOG(INFO) << "Clamp target GC heap from " << max_allowed_footprint
-                << " to " << Heap::growth_size_;
-    }
+    VLOG(gc) << "Clamp target GC heap from " << max_allowed_footprint
+             << " to " << Heap::growth_size_;
     max_allowed_footprint = Heap::growth_size_;
   }
 
diff --git a/src/heap.h b/src/heap.h
index 8897405..6b056a2 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -47,20 +47,11 @@
   // Create a heap with the requested sizes. The possible empty
   // image_file_names names specify Spaces to load based on
   // ImageWriter output.
-  static void Init(bool is_verbose_heap, bool is_verbose_gc,
-                   size_t starting_size, size_t maximum_size, size_t growth_size,
+  static void Init(size_t starting_size, size_t maximum_size, size_t growth_size,
                    const std::vector<std::string>& image_file_names);
 
   static void Destroy();
 
-  static bool IsVerboseHeap() {
-    return is_verbose_heap_ || is_verbose_gc_ /* TODO: remove when pause times are down */;
-  }
-
-  static bool IsVerboseGc() {
-    return is_verbose_gc_;
-  }
-
   // Allocates and initializes storage for an object instance.
   static Object* AllocObject(Class* klass, size_t num_bytes);
 
@@ -225,10 +216,6 @@
 
   static Mutex* lock_;
 
-  static bool is_verbose_heap_;
-
-  static bool is_verbose_gc_;
-
   static std::vector<Space*> spaces_;
 
   // default Space for allocations
diff --git a/src/image_writer.h b/src/image_writer.h
index 4e95ee4..b6b02f4 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -16,6 +16,7 @@
 #include "object.h"
 #include "os.h"
 #include "space.h"
+#include "unordered_set.h"
 
 namespace art {
 
diff --git a/src/jdwp/jdwp_adb.cc b/src/jdwp/jdwp_adb.cc
index eb6eec2..eb49bce 100644
--- a/src/jdwp/jdwp_adb.cc
+++ b/src/jdwp/jdwp_adb.cc
@@ -121,7 +121,7 @@
 static bool startup(JdwpState* state, const JdwpOptions*) {
   JdwpNetState* netState;
 
-  LOG(VERBOSE) << "ADB transport startup";
+  VLOG(jdwp) << "ADB transport startup";
 
   state->netState = netState = new JdwpNetState;
   if (netState == NULL) {
@@ -248,14 +248,16 @@
         } while (ret < 0 && errno == EINTR);
 
         if (ret >= 0) {
-          LOG(VERBOSE) << StringPrintf("PID sent as '%.*s' to ADB", 4, buff);
+          VLOG(jdwp) << StringPrintf("PID sent as '%.*s' to ADB", 4, buff);
           break;
         }
 
         PLOG(ERROR) << "Weird, can't send JDWP process pid to ADB";
         return false;
       }
-      PLOG(VERBOSE) << "Can't connect to ADB control socket";
+      if (VLOG_IS_ON(jdwp)) {
+        PLOG(ERROR) << "Can't connect to ADB control socket";
+      }
 
       usleep( sleep_ms*1000 );
 
@@ -269,7 +271,7 @@
     }
   }
 
-  LOG(VERBOSE) << "trying to receive file descriptor from ADB";
+  VLOG(jdwp) << "trying to receive file descriptor from ADB";
   /* now we can receive a client file descriptor */
   netState->clientSock = receiveClientFd(netState);
   if (netState->shuttingDown) {
@@ -282,7 +284,7 @@
     }
     goto retry;
   } else {
-    LOG(VERBOSE) << "received file descriptor " << netState->clientSock << " from ADB";
+    VLOG(jdwp) << "received file descriptor " << netState->clientSock << " from ADB";
     netState->awaitingHandshake = 1;
     netState->inputCount = 0;
     return true;
@@ -308,7 +310,7 @@
     return;
   }
 
-  LOG(VERBOSE) << "+++ closed JDWP <-> ADB connection";
+  VLOG(jdwp) << "+++ closed JDWP <-> ADB connection";
 
   close(netState->clientSock);
   netState->clientSock = -1;
@@ -343,7 +345,7 @@
   }
 
   if (netState->wakeFds[1] >= 0) {
-    LOG(VERBOSE) << "+++ writing to wakePipe";
+    VLOG(jdwp) << "+++ writing to wakePipe";
     write(netState->wakeFds[1], "", 1);
   }
 }
@@ -462,7 +464,7 @@
     LOG(FATAL) << "reply?!";
   }
 
-  LOG(VERBOSE) << "----------";
+  VLOG(jdwp) << "----------";
 
   consumeBytes(netState, length);
   return true;
@@ -526,7 +528,7 @@
       }
 
       if (maxfd < 0) {
-        LOG(VERBOSE) << "+++ all fds are closed";
+        VLOG(jdwp) << "+++ all fds are closed";
         return false;
       }
 
@@ -580,7 +582,7 @@
           return true;
         } else if (readCount == 0) {
           /* EOF hit -- far end went away */
-          LOG(VERBOSE) << "+++ peer disconnected";
+          VLOG(jdwp) << "+++ peer disconnected";
           goto fail;
         } else {
           break;
@@ -619,7 +621,7 @@
 
     consumeBytes(netState, kMagicHandshakeLen);
     netState->awaitingHandshake = false;
-    LOG(VERBOSE) << "+++ handshake complete";
+    VLOG(jdwp) << "+++ handshake complete";
     return true;
   }
 
@@ -646,7 +648,7 @@
 
   if (netState->clientSock < 0) {
     /* can happen with some DDMS events */
-    LOG(VERBOSE) << "NOT sending request -- no debugger is attached";
+    VLOG(jdwp) << "NOT sending request -- no debugger is attached";
     return false;
   }
 
@@ -675,7 +677,7 @@
 
   if (netState->clientSock < 0) {
     /* can happen with some DDMS events */
-    LOG(VERBOSE) << "NOT sending request -- no debugger is attached";
+    VLOG(jdwp) << "NOT sending request -- no debugger is attached";
     return false;
   }
 
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index a405c9b..f3e98f5 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -331,7 +331,7 @@
 
     for (int i = 0; i < pEvent->modCount; i++) {
       if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
-        LOG(VERBOSE) << "##### Removing expired event";
+        VLOG(jdwp) << "##### Removing expired event";
         UnregisterEvent(pEvent);
         EventFree(pEvent);
         break;
@@ -507,7 +507,7 @@
  *  SP_ALL - suspend everybody except JDWP support thread
  */
 void JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspendPolicy) {
-  LOG(INFO) << "SuspendByPolicy(" << suspendPolicy << ")";
+  VLOG(jdwp) << "SuspendByPolicy(" << suspendPolicy << ")";
   if (suspendPolicy == SP_NONE) {
     return;
   }
@@ -550,7 +550,7 @@
     /* clear this before signaling */
     pReq->invoke_needed_ = false;
 
-    LOG(VERBOSE) << "invoke complete, signaling and self-suspending";
+    VLOG(jdwp) << "invoke complete, signaling and self-suspending";
     MutexLock mu(pReq->lock_);
     pReq->cond_.Signal();
   }
@@ -589,13 +589,13 @@
    * go to sleep indefinitely.
    */
   while (eventThreadId != 0) {
-    LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", eventThreadId, threadId);
+    VLOG(jdwp) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", eventThreadId, threadId);
     waited = true;
     event_thread_cond_.Wait(event_thread_lock_);
   }
 
   if (waited || threadId != 0) {
-    LOG(VERBOSE) << StringPrintf("event token grabbed (0x%llx)", threadId);
+    VLOG(jdwp) << StringPrintf("event token grabbed (0x%llx)", threadId);
   }
   if (threadId != 0) {
     eventThreadId = threadId;
@@ -614,7 +614,7 @@
   MutexLock mu(event_thread_lock_);
 
   CHECK_NE(eventThreadId, 0U);
-  LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", eventThreadId);
+  VLOG(jdwp) << StringPrintf("cleared event token (0x%llx)", eventThreadId);
 
   eventThreadId = 0;
 
@@ -674,8 +674,8 @@
   {
     MutexLock mu(event_lock_); // probably don't need this here
 
-    LOG(VERBOSE) << "EVENT: " << EK_VM_START;
-    LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
+    VLOG(jdwp) << "EVENT: " << EK_VM_START;
+    VLOG(jdwp) << "  suspendPolicy=" << suspendPolicy;
 
     expandBufAdd1(pReq, suspendPolicy);
     expandBufAdd4BE(pReq, 1);
@@ -745,7 +745,7 @@
    * this is mostly paranoia.)
    */
   if (basket.threadId == debugThreadId) {
-    LOG(VERBOSE) << "Ignoring location event in JDWP thread";
+    VLOG(jdwp) << "Ignoring location event in JDWP thread";
     return false;
   }
 
@@ -759,7 +759,7 @@
    * method invocation to complete.
    */
   if (InvokeInProgress()) {
-    LOG(VERBOSE) << "Not checking breakpoints during invoke (" << basket.className << ")";
+    VLOG(jdwp) << "Not checking breakpoints during invoke (" << basket.className << ")";
     return false;
   }
 
@@ -783,12 +783,12 @@
       FindMatchingEvents(EK_METHOD_EXIT, &basket, matchList, &matchCount);
     }
     if (matchCount != 0) {
-      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
+      VLOG(jdwp) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
                    << basket.className << "." << Dbg::GetMethodName(pLoc->classId, pLoc->methodId)
                    << " thread=" << (void*) basket.threadId << " code=" << (void*) pLoc->idx << ")";
 
       suspendPolicy = scanSuspendPolicy(matchList, matchCount);
-      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
+      VLOG(jdwp) << "  suspendPolicy=" << suspendPolicy;
 
       pReq = eventPrep();
       expandBufAdd1(pReq, suspendPolicy);
@@ -857,11 +857,11 @@
     }
 
     if (matchCount != 0) {
-      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
+      VLOG(jdwp) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
                    << "thread=" << (void*) basket.threadId << ")";
 
       suspendPolicy = scanSuspendPolicy(matchList, matchCount);
-      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
+      VLOG(jdwp) << "  suspendPolicy=" << suspendPolicy;
 
       pReq = eventPrep();
       expandBufAdd1(pReq, suspendPolicy);
@@ -898,7 +898,7 @@
  * Skips the usual "event token" stuff.
  */
 bool JdwpState::PostVMDeath() {
-  LOG(VERBOSE) << "EVENT: " << EK_VM_DEATH;
+  VLOG(jdwp) << "EVENT: " << EK_VM_DEATH;
 
   ExpandBuf* pReq = eventPrep();
   expandBufAdd1(pReq, SP_NONE);
@@ -938,7 +938,7 @@
 
   /* don't try to post an exception caused by the debugger */
   if (InvokeInProgress()) {
-    LOG(VERBOSE) << "Not posting exception hit during invoke (" << basket.className << ")";
+    VLOG(jdwp) << "Not posting exception hit during invoke (" << basket.className << ")";
     return false;
   }
 
@@ -950,19 +950,19 @@
     MutexLock mu(event_lock_);
     FindMatchingEvents(EK_EXCEPTION, &basket, matchList, &matchCount);
     if (matchCount != 0) {
-      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total)"
+      VLOG(jdwp) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total)"
                    << " thread=" << (void*) basket.threadId
                    << " exceptId=" << (void*) exceptionId
                    << " caught=" << basket.caught << ")";
-      LOG(VERBOSE) << "  throw: " << *pThrowLoc;
+      VLOG(jdwp) << "  throw: " << *pThrowLoc;
       if (pCatchLoc->classId == 0) {
-        LOG(VERBOSE) << "  catch: (not caught)";
+        VLOG(jdwp) << "  catch: (not caught)";
       } else {
-        LOG(VERBOSE) << "  catch: " << *pCatchLoc;
+        VLOG(jdwp) << "  catch: " << *pCatchLoc;
       }
 
       suspendPolicy = scanSuspendPolicy(matchList, matchCount);
-      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
+      VLOG(jdwp) << "  suspendPolicy=" << suspendPolicy;
 
       pReq = eventPrep();
       expandBufAdd1(pReq, suspendPolicy);
@@ -1018,7 +1018,7 @@
 
   /* suppress class prep caused by debugger */
   if (InvokeInProgress()) {
-    LOG(VERBOSE) << "Not posting class prep caused by invoke (" << basket.className << ")";
+    VLOG(jdwp) << "Not posting class prep caused by invoke (" << basket.className << ")";
     return false;
   }
 
@@ -1030,11 +1030,11 @@
     MutexLock mu(event_lock_);
     FindMatchingEvents(EK_CLASS_PREPARE, &basket, matchList, &matchCount);
     if (matchCount != 0) {
-      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
+      VLOG(jdwp) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
                    << "thread=" << (void*) basket.threadId << ") " << signature;
 
       suspendPolicy = scanSuspendPolicy(matchList, matchCount);
-      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
+      VLOG(jdwp) << "  suspendPolicy=" << suspendPolicy;
 
       if (basket.threadId == debugThreadId) {
         /*
@@ -1042,7 +1042,7 @@
          * should set threadId to null and if any threads were supposed
          * to be suspended then we suspend all other threads.
          */
-        LOG(VERBOSE) << "  NOTE: class prepare in debugger thread!";
+        VLOG(jdwp) << "  NOTE: class prepare in debugger thread!";
         basket.threadId = 0;
         if (suspendPolicy == SP_EVENT_THREAD) {
           suspendPolicy = SP_ALL;
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 9f23af1..1b2ac43 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -108,9 +108,9 @@
 
   uint32_t numArgs = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("    --> threadId=%llx objectId=%llx", threadId, objectId);
-  LOG(VERBOSE) << StringPrintf("        classId=%llx methodId=%x %s.%s", classId, methodId, Dbg::GetClassDescriptor(classId).c_str(), Dbg::GetMethodName(classId, methodId).c_str());
-  LOG(VERBOSE) << StringPrintf("        %d args:", numArgs);
+  VLOG(jdwp) << StringPrintf("    --> threadId=%llx objectId=%llx", threadId, objectId);
+  VLOG(jdwp) << StringPrintf("        classId=%llx methodId=%x %s.%s", classId, methodId, Dbg::GetClassDescriptor(classId).c_str(), Dbg::GetMethodName(classId, methodId).c_str());
+  VLOG(jdwp) << StringPrintf("        %d args:", numArgs);
 
   uint64_t* argArray = NULL;
   if (numArgs > 0) {
@@ -122,12 +122,12 @@
     size_t width = Dbg::GetTagWidth(typeTag);
     uint64_t value = jdwpReadValue(&buf, width);
 
-    LOG(VERBOSE) << StringPrintf("          '%c'(%d): 0x%llx", typeTag, width, value);
+    VLOG(jdwp) << StringPrintf("          '%c'(%d): 0x%llx", typeTag, width, value);
     argArray[i] = value;
   }
 
   uint32_t options = Read4BE(&buf);  /* enum InvokeOptions bit flags */
-  LOG(VERBOSE) << StringPrintf("        options=0x%04x%s%s", options, (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "", (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
+  VLOG(jdwp) << StringPrintf("        options=0x%04x%s%s", options, (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "", (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
 
   JDWP::JdwpTag resultTag;
   uint64_t resultValue;
@@ -152,14 +152,14 @@
     expandBufAdd1(pReply, JT_OBJECT);
     expandBufAddObjectId(pReply, exceptObjId);
 
-    LOG(VERBOSE) << StringPrintf("  --> returned '%c' 0x%llx (except=%08llx)", resultTag, resultValue, exceptObjId);
+    VLOG(jdwp) << StringPrintf("  --> returned '%c' 0x%llx (except=%08llx)", resultTag, resultValue, exceptObjId);
 
     /* show detailed debug output */
     if (resultTag == JT_STRING && exceptObjId == 0) {
       if (resultValue != 0) {
-        LOG(VERBOSE) << "      string '" << Dbg::StringToUtf8(resultValue) << "'";
+        VLOG(jdwp) << "      string '" << Dbg::StringToUtf8(resultValue) << "'";
       } else {
-        LOG(VERBOSE) << "      string (null)";
+        VLOG(jdwp) << "      string (null)";
       }
     }
   }
@@ -195,7 +195,7 @@
  */
 static JdwpError handleVM_ClassesBySignature(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   std::string classDescriptor(ReadNewUtf8String(&buf));
-  LOG(VERBOSE) << "  Req for class by signature '" << classDescriptor << "'";
+  VLOG(jdwp) << "  Req for class by signature '" << classDescriptor << "'";
 
   std::vector<RefTypeId> ids;
   Dbg::FindLoadedClassBySignature(classDescriptor, ids);
@@ -324,7 +324,7 @@
  */
 static JdwpError handleVM_CreateString(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   std::string str(ReadNewUtf8String(&buf));
-  LOG(VERBOSE) << "  Req to create string '" << str << "'";
+  VLOG(jdwp) << "  Req to create string '" << str << "'";
   ObjectId stringId = Dbg::CreateString(str);
   if (stringId == 0) {
     return ERR_OUT_OF_MEMORY;
@@ -451,7 +451,7 @@
 static JdwpError handleRT_Signature(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for signature of refTypeId=0x%llx", refTypeId);
+  VLOG(jdwp) << StringPrintf("  Req for signature of refTypeId=0x%llx", refTypeId);
   std::string signature;
   if (!Dbg::GetSignature(refTypeId, signature)) {
     return ERR_INVALID_CLASS;
@@ -480,7 +480,7 @@
   ReadRefTypeId(&buf); // We don't need this, but we need to skip over it in the request.
   uint32_t numFields = Read4BE(&buf);
 
-  LOG(VERBOSE) << "  RT_GetValues " << numFields << ":";
+  VLOG(jdwp) << "  RT_GetValues " << numFields << ":";
 
   expandBufAdd4BE(pReply, numFields);
   for (uint32_t i = 0; i < numFields; i++) {
@@ -523,7 +523,7 @@
  */
 static JdwpError handleRT_Interfaces(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  LOG(VERBOSE) << StringPrintf("  Req for interfaces in %llx (%s)", refTypeId, Dbg::GetClassDescriptor(refTypeId).c_str());
+  VLOG(jdwp) << StringPrintf("  Req for interfaces in %llx (%s)", refTypeId, Dbg::GetClassDescriptor(refTypeId).c_str());
   return Dbg::OutputDeclaredInterfaces(refTypeId, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
@@ -536,7 +536,7 @@
   if (!Dbg::GetClassObject(refTypeId, classObjectId)) {
     return ERR_INVALID_CLASS;
   }
-  LOG(VERBOSE) << StringPrintf("  RefTypeId %llx -> ObjectId %llx", refTypeId, classObjectId);
+  VLOG(jdwp) << StringPrintf("  RefTypeId %llx -> ObjectId %llx", refTypeId, classObjectId);
   expandBufAddObjectId(pReply, classObjectId);
   return ERR_NONE;
 }
@@ -559,7 +559,7 @@
 
   RefTypeId refTypeId = ReadRefTypeId(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for signature of refTypeId=0x%llx", refTypeId);
+  VLOG(jdwp) << StringPrintf("  Req for signature of refTypeId=0x%llx", refTypeId);
   std::string signature;
   if (Dbg::GetSignature(refTypeId, signature)) {
     expandBufAddUtf8String(pReply, signature);
@@ -596,14 +596,14 @@
  */
 static JdwpError handleRT_FieldsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  LOG(VERBOSE) << "  Req for fields in " << Describe(refTypeId);
+  VLOG(jdwp) << "  Req for fields in " << Describe(refTypeId);
   return Dbg::OutputDeclaredFields(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
 // Obsolete equivalent of FieldsWithGeneric, without the generic type information.
 static JdwpError handleRT_Fields(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  LOG(VERBOSE) << "  Req for fields in " << Describe(refTypeId);
+  VLOG(jdwp) << "  Req for fields in " << Describe(refTypeId);
   return Dbg::OutputDeclaredFields(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
@@ -613,14 +613,14 @@
  */
 static JdwpError handleRT_MethodsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  LOG(VERBOSE) << "  Req for methods in " << Describe(refTypeId);
+  VLOG(jdwp) << "  Req for methods in " << Describe(refTypeId);
   return Dbg::OutputDeclaredMethods(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
 // Obsolete equivalent of MethodsWithGeneric, without the generic type information.
 static JdwpError handleRT_Methods(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  LOG(VERBOSE) << "  Req for methods in " << Describe(refTypeId);
+  VLOG(jdwp) << "  Req for methods in " << Describe(refTypeId);
   return Dbg::OutputDeclaredMethods(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
@@ -644,7 +644,7 @@
   RefTypeId classId = ReadRefTypeId(&buf);
   uint32_t values = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req to set %d values in classId=%llx", values, classId);
+  VLOG(jdwp) << StringPrintf("  Req to set %d values in classId=%llx", values, classId);
 
   for (uint32_t i = 0; i < values; i++) {
     FieldId fieldId = ReadFieldId(&buf);
@@ -652,7 +652,7 @@
     size_t width = Dbg::GetTagWidth(fieldTag);
     uint64_t value = jdwpReadValue(&buf, width);
 
-    LOG(VERBOSE) << StringPrintf("    --> field=%x tag=%c -> %lld", fieldId, fieldTag, value);
+    VLOG(jdwp) << StringPrintf("    --> field=%x tag=%c -> %lld", fieldId, fieldTag, value);
     Dbg::SetStaticFieldValue(fieldId, value, width);
   }
 
@@ -685,7 +685,7 @@
   ObjectId threadId = ReadObjectId(&buf);
   MethodId methodId = ReadMethodId(&buf);
 
-  LOG(VERBOSE) << "Creating instance of " << Dbg::GetClassDescriptor(classId);
+  VLOG(jdwp) << "Creating instance of " << Dbg::GetClassDescriptor(classId);
   ObjectId objectId;
   if (!Dbg::CreateObject(classId, objectId)) {
     return ERR_INVALID_CLASS;
@@ -703,7 +703,7 @@
   RefTypeId arrayTypeId = ReadRefTypeId(&buf);
   uint32_t length = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("Creating array %s[%u]", Dbg::GetClassDescriptor(arrayTypeId).c_str(), length);
+  VLOG(jdwp) << StringPrintf("Creating array %s[%u]", Dbg::GetClassDescriptor(arrayTypeId).c_str(), length);
   ObjectId objectId;
   if (!Dbg::CreateArrayObject(arrayTypeId, length, objectId)) {
     return ERR_INVALID_CLASS;
@@ -723,7 +723,7 @@
   RefTypeId refTypeId = ReadRefTypeId(&buf);
   MethodId methodId = ReadMethodId(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for line table in %s.%s", Dbg::GetClassDescriptor(refTypeId).c_str(), Dbg::GetMethodName(refTypeId,methodId).c_str());
+  VLOG(jdwp) << StringPrintf("  Req for line table in %s.%s", Dbg::GetClassDescriptor(refTypeId).c_str(), Dbg::GetMethodName(refTypeId,methodId).c_str());
 
   Dbg::OutputLineTable(refTypeId, methodId, pReply);
 
@@ -737,7 +737,7 @@
   RefTypeId classId = ReadRefTypeId(&buf);
   MethodId methodId = ReadMethodId(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for LocalVarTab in class=%s method=%s", Dbg::GetClassDescriptor(classId).c_str(), Dbg::GetMethodName(classId, methodId).c_str());
+  VLOG(jdwp) << StringPrintf("  Req for LocalVarTab in class=%s method=%s", Dbg::GetClassDescriptor(classId).c_str(), Dbg::GetMethodName(classId, methodId).c_str());
 
   /*
    * We could return ERR_ABSENT_INFORMATION here if the DEX file was
@@ -759,7 +759,7 @@
  */
 static JdwpError handleOR_ReferenceType(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   ObjectId objectId = ReadObjectId(&buf);
-  LOG(VERBOSE) << StringPrintf("  Req for type of objectId=0x%llx", objectId);
+  VLOG(jdwp) << StringPrintf("  Req for type of objectId=0x%llx", objectId);
 
   JDWP::JdwpTypeTag refTypeTag;
   RefTypeId typeId;
@@ -778,7 +778,7 @@
   ObjectId objectId = ReadObjectId(&buf);
   uint32_t numFields = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for %d fields from objectId=0x%llx", numFields, objectId);
+  VLOG(jdwp) << StringPrintf("  Req for %d fields from objectId=0x%llx", numFields, objectId);
 
   expandBufAdd4BE(pReply, numFields);
 
@@ -797,7 +797,7 @@
   ObjectId objectId = ReadObjectId(&buf);
   uint32_t numFields = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req to set %d fields in objectId=0x%llx", numFields, objectId);
+  VLOG(jdwp) << StringPrintf("  Req to set %d fields in objectId=0x%llx", numFields, objectId);
 
   for (uint32_t i = 0; i < numFields; i++) {
     FieldId fieldId = ReadFieldId(&buf);
@@ -806,7 +806,7 @@
     size_t width = Dbg::GetTagWidth(fieldTag);
     uint64_t value = jdwpReadValue(&buf, width);
 
-    LOG(VERBOSE) << StringPrintf("    --> fieldId=%x tag='%c'(%d) value=%lld", fieldId, fieldTag, width, value);
+    VLOG(jdwp) << StringPrintf("    --> fieldId=%x tag='%c'(%d) value=%lld", fieldId, fieldTag, width, value);
 
     Dbg::SetFieldValue(objectId, fieldId, value, width);
   }
@@ -857,7 +857,7 @@
   ObjectId objectId;
 
   objectId = ReadObjectId(&buf);
-  LOG(VERBOSE) << StringPrintf("  Req IsCollected(0x%llx)", objectId);
+  VLOG(jdwp) << StringPrintf("  Req IsCollected(0x%llx)", objectId);
 
   // TODO: currently returning false; must integrate with GC
   expandBufAdd1(pReply, 0);
@@ -872,7 +872,7 @@
   ObjectId stringObject = ReadObjectId(&buf);
   std::string str(Dbg::StringToUtf8(stringObject));
 
-  LOG(VERBOSE) << StringPrintf("  Req for str %llx --> '%s'", stringObject, PrintableString(str).c_str());
+  VLOG(jdwp) << StringPrintf("  Req for str %llx --> '%s'", stringObject, PrintableString(str).c_str());
 
   expandBufAddUtf8String(pReply, str);
 
@@ -885,12 +885,12 @@
 static JdwpError handleTR_Name(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   ObjectId threadId = ReadObjectId(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for name of thread 0x%llx", threadId);
+  VLOG(jdwp) << StringPrintf("  Req for name of thread 0x%llx", threadId);
   std::string name;
   if (!Dbg::GetThreadName(threadId, name)) {
     return ERR_INVALID_THREAD;
   }
-  LOG(VERBOSE) << StringPrintf("  Name of thread 0x%llx is \"%s\"", threadId, name.c_str());
+  VLOG(jdwp) << StringPrintf("  Name of thread 0x%llx is \"%s\"", threadId, name.c_str());
   expandBufAddUtf8String(pReply, name);
 
   return ERR_NONE;
@@ -909,7 +909,7 @@
     LOG(INFO) << "  Warning: ignoring request to suspend self";
     return ERR_THREAD_NOT_SUSPENDED;
   }
-  LOG(VERBOSE) << StringPrintf("  Req to suspend thread 0x%llx", threadId);
+  VLOG(jdwp) << StringPrintf("  Req to suspend thread 0x%llx", threadId);
   Dbg::SuspendThread(threadId);
   return ERR_NONE;
 }
@@ -924,7 +924,7 @@
     LOG(INFO) << "  Warning: ignoring request to resume self";
     return ERR_NONE;
   }
-  LOG(VERBOSE) << StringPrintf("  Req to resume thread 0x%llx", threadId);
+  VLOG(jdwp) << StringPrintf("  Req to resume thread 0x%llx", threadId);
   Dbg::ResumeThread(threadId);
   return ERR_NONE;
 }
@@ -935,7 +935,7 @@
 static JdwpError handleTR_Status(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   ObjectId threadId = ReadObjectId(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for status of thread 0x%llx", threadId);
+  VLOG(jdwp) << StringPrintf("  Req for status of thread 0x%llx", threadId);
 
   JDWP::JdwpThreadStatus threadStatus;
   JDWP::JdwpSuspendStatus suspendStatus;
@@ -943,7 +943,7 @@
     return ERR_INVALID_THREAD;
   }
 
-  LOG(VERBOSE) << "    --> " << threadStatus << ", " << suspendStatus;
+  VLOG(jdwp) << "    --> " << threadStatus << ", " << suspendStatus;
 
   expandBufAdd4BE(pReply, threadStatus);
   expandBufAdd4BE(pReply, suspendStatus);
@@ -985,7 +985,7 @@
 
   size_t frameCount = Dbg::GetThreadFrameCount(threadId);
 
-  LOG(VERBOSE) << StringPrintf("  Request for frames: threadId=%llx start=%d length=%d [count=%d]", threadId, startFrame, length, frameCount);
+  VLOG(jdwp) << StringPrintf("  Request for frames: threadId=%llx start=%d length=%d [count=%d]", threadId, startFrame, length, frameCount);
   if (frameCount <= 0) {
     return ERR_THREAD_NOT_SUSPENDED;    /* == 0 means 100% native */
   }
@@ -1007,7 +1007,7 @@
     expandBufAdd8BE(pReply, frameId);
     AddLocation(pReply, &loc);
 
-    LOG(VERBOSE) << StringPrintf("    Frame %d: id=%llx loc={type=%d cls=%llx mth=%x loc=%llx}", i, frameId, loc.typeTag, loc.classId, loc.methodId, loc.idx);
+    VLOG(jdwp) << StringPrintf("    Frame %d: id=%llx loc={type=%d cls=%llx mth=%x loc=%llx}", i, frameId, loc.typeTag, loc.classId, loc.methodId, loc.idx);
   }
 
   return ERR_NONE;
@@ -1072,7 +1072,7 @@
  */
 static JdwpError handleTGR_Name(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   ObjectId threadGroupId = ReadObjectId(&buf);
-  LOG(VERBOSE) << StringPrintf("  Req for name of threadGroupId=0x%llx", threadGroupId);
+  VLOG(jdwp) << StringPrintf("  Req for name of threadGroupId=0x%llx", threadGroupId);
 
   expandBufAddUtf8String(pReply, Dbg::GetThreadGroupName(threadGroupId));
 
@@ -1098,7 +1098,7 @@
  */
 static JdwpError handleTGR_Children(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   ObjectId threadGroupId = ReadObjectId(&buf);
-  LOG(VERBOSE) << StringPrintf("  Req for threads in threadGroupId=0x%llx", threadGroupId);
+  VLOG(jdwp) << StringPrintf("  Req for threads in threadGroupId=0x%llx", threadGroupId);
 
   ObjectId* pThreadIds;
   uint32_t threadCount;
@@ -1131,11 +1131,11 @@
  */
 static JdwpError handleAR_Length(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   ObjectId arrayId = ReadObjectId(&buf);
-  LOG(VERBOSE) << StringPrintf("  Req for length of array 0x%llx", arrayId);
+  VLOG(jdwp) << StringPrintf("  Req for length of array 0x%llx", arrayId);
 
   uint32_t arrayLength = Dbg::GetArrayLength(arrayId);
 
-  LOG(VERBOSE) << StringPrintf("    --> %d", arrayLength);
+  VLOG(jdwp) << StringPrintf("    --> %d", arrayLength);
 
   expandBufAdd4BE(pReply, arrayLength);
 
@@ -1151,7 +1151,7 @@
   uint32_t length = Read4BE(&buf);
 
   uint8_t tag = Dbg::GetArrayElementTag(arrayId);
-  LOG(VERBOSE) << StringPrintf("  Req for array values 0x%llx first=%d len=%d (elem tag=%c)", arrayId, firstIndex, length, tag);
+  VLOG(jdwp) << StringPrintf("  Req for array values 0x%llx first=%d len=%d (elem tag=%c)", arrayId, firstIndex, length, tag);
 
   expandBufAdd1(pReply, tag);
   expandBufAdd4BE(pReply, length);
@@ -1171,7 +1171,7 @@
   uint32_t firstIndex = Read4BE(&buf);
   uint32_t values = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req to set array values 0x%llx first=%d count=%d", arrayId, firstIndex, values);
+  VLOG(jdwp) << StringPrintf("  Req to set array values 0x%llx first=%d count=%d", arrayId, firstIndex, values);
 
   if (!Dbg::SetArrayElements(arrayId, firstIndex, values, buf)) {
     return ERR_INVALID_LENGTH;
@@ -1244,7 +1244,7 @@
   uint8_t suspendPolicy = Read1(&buf);
   uint32_t modifierCount = Read4BE(&buf);
 
-  LOG(VERBOSE) << "  Set(kind=" << JdwpEventKind(eventKind)
+  VLOG(jdwp) << "  Set(kind=" << JdwpEventKind(eventKind)
                << " suspend=" << JdwpSuspendPolicy(suspendPolicy)
                << " mods=" << modifierCount << ")";
 
@@ -1268,7 +1268,7 @@
     case MK_COUNT:          /* report once, when "--count" reaches 0 */
       {
         uint32_t count = Read4BE(&buf);
-        LOG(VERBOSE) << "    Count: " << count;
+        VLOG(jdwp) << "    Count: " << count;
         if (count == 0) {
           return ERR_INVALID_COUNT;
         }
@@ -1278,28 +1278,28 @@
     case MK_CONDITIONAL:    /* conditional on expression) */
       {
         uint32_t exprId = Read4BE(&buf);
-        LOG(VERBOSE) << "    Conditional: " << exprId;
+        VLOG(jdwp) << "    Conditional: " << exprId;
         pEvent->mods[idx].conditional.exprId = exprId;
       }
       break;
     case MK_THREAD_ONLY:    /* only report events in specified thread */
       {
         ObjectId threadId = ReadObjectId(&buf);
-        LOG(VERBOSE) << StringPrintf("    ThreadOnly: %llx", threadId);
+        VLOG(jdwp) << StringPrintf("    ThreadOnly: %llx", threadId);
         pEvent->mods[idx].threadOnly.threadId = threadId;
       }
       break;
     case MK_CLASS_ONLY:     /* for ClassPrepare, MethodEntry */
       {
         RefTypeId clazzId = ReadRefTypeId(&buf);
-        LOG(VERBOSE) << StringPrintf("    ClassOnly: %llx (%s)", clazzId, Dbg::GetClassDescriptor(clazzId).c_str());
+        VLOG(jdwp) << StringPrintf("    ClassOnly: %llx (%s)", clazzId, Dbg::GetClassDescriptor(clazzId).c_str());
         pEvent->mods[idx].classOnly.refTypeId = clazzId;
       }
       break;
     case MK_CLASS_MATCH:    /* restrict events to matching classes */
       {
         std::string pattern(ReadNewUtf8String(&buf));
-        LOG(VERBOSE) << StringPrintf("    ClassMatch: '%s'", pattern.c_str());
+        VLOG(jdwp) << StringPrintf("    ClassMatch: '%s'", pattern.c_str());
         /* pattern is "java.foo.*", we want "java/foo/ *" */
         pEvent->mods[idx].classMatch.classPattern = dvmDotToSlash(pattern.c_str());
       }
@@ -1307,7 +1307,7 @@
     case MK_CLASS_EXCLUDE:  /* restrict events to non-matching classes */
       {
         std::string pattern(ReadNewUtf8String(&buf));
-        LOG(VERBOSE) << StringPrintf("    ClassExclude: '%s'", pattern.c_str());
+        VLOG(jdwp) << StringPrintf("    ClassExclude: '%s'", pattern.c_str());
         pEvent->mods[idx].classExclude.classPattern = dvmDotToSlash(pattern.c_str());
       }
       break;
@@ -1316,7 +1316,7 @@
         JdwpLocation loc;
 
         jdwpReadLocation(&buf, &loc);
-        LOG(VERBOSE) << StringPrintf("    LocationOnly: typeTag=%d classId=%llx methodId=%x idx=%llx",
+        VLOG(jdwp) << StringPrintf("    LocationOnly: typeTag=%d classId=%llx methodId=%x idx=%llx",
         loc.typeTag, loc.classId, loc.methodId, loc.idx);
         pEvent->mods[idx].locationOnly.loc = loc;
       }
@@ -1329,7 +1329,7 @@
         exceptionOrNull = ReadRefTypeId(&buf);
         caught = Read1(&buf);
         uncaught = Read1(&buf);
-        LOG(VERBOSE) << StringPrintf("    ExceptionOnly: type=%llx(%s) caught=%d uncaught=%d",
+        VLOG(jdwp) << StringPrintf("    ExceptionOnly: type=%llx(%s) caught=%d uncaught=%d",
             exceptionOrNull, (exceptionOrNull == 0) ? "null" : Dbg::GetClassDescriptor(exceptionOrNull).c_str(), caught, uncaught);
 
         pEvent->mods[idx].exceptionOnly.refTypeId = exceptionOrNull;
@@ -1341,7 +1341,7 @@
       {
         RefTypeId declaring = ReadRefTypeId(&buf);
         FieldId fieldId = ReadFieldId(&buf);
-        LOG(VERBOSE) << StringPrintf("    FieldOnly: %llx %x", declaring, fieldId);
+        VLOG(jdwp) << StringPrintf("    FieldOnly: %llx %x", declaring, fieldId);
         pEvent->mods[idx].fieldOnly.refTypeId = declaring;
         pEvent->mods[idx].fieldOnly.fieldId = fieldId;
       }
@@ -1354,7 +1354,7 @@
         threadId = ReadObjectId(&buf);
         size = Read4BE(&buf);
         depth = Read4BE(&buf);
-        LOG(VERBOSE) << StringPrintf("    Step: thread=%llx", threadId)
+        VLOG(jdwp) << StringPrintf("    Step: thread=%llx", threadId)
                      << " size=" << JdwpStepSize(size) << " depth=" << JdwpStepDepth(depth);
 
         pEvent->mods[idx].step.threadId = threadId;
@@ -1365,7 +1365,7 @@
     case MK_INSTANCE_ONLY:  /* report events related to a specific obj */
       {
         ObjectId instance = ReadObjectId(&buf);
-        LOG(VERBOSE) << StringPrintf("    InstanceOnly: %llx", instance);
+        VLOG(jdwp) << StringPrintf("    InstanceOnly: %llx", instance);
         pEvent->mods[idx].instanceOnly.objectId = instance;
       }
       break;
@@ -1391,7 +1391,7 @@
 
   pEvent->requestId = requestId;
 
-  LOG(VERBOSE) << StringPrintf("    --> event requestId=%#x", requestId);
+  VLOG(jdwp) << StringPrintf("    --> event requestId=%#x", requestId);
 
   /* add it to the list */
   JdwpError err = state->RegisterEvent(pEvent);
@@ -1412,7 +1412,7 @@
   eventKind = Read1(&buf);
   uint32_t requestId = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req to clear eventKind=%d requestId=%#x", eventKind, requestId);
+  VLOG(jdwp) << StringPrintf("  Req to clear eventKind=%d requestId=%#x", eventKind, requestId);
 
   state->UnregisterEventById(requestId);
 
@@ -1427,14 +1427,14 @@
   FrameId frameId = ReadFrameId(&buf);
   uint32_t slots = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for %d slots in threadId=%llx frameId=%llx", slots, threadId, frameId);
+  VLOG(jdwp) << StringPrintf("  Req for %d slots in threadId=%llx frameId=%llx", slots, threadId, frameId);
 
   expandBufAdd4BE(pReply, slots);     /* "int values" */
   for (uint32_t i = 0; i < slots; i++) {
     uint32_t slot = Read4BE(&buf);
     JDWP::JdwpTag reqSigByte = ReadTag(&buf);
 
-    LOG(VERBOSE) << StringPrintf("    --> slot %d '%c'", slot, reqSigByte);
+    VLOG(jdwp) << StringPrintf("    --> slot %d '%c'", slot, reqSigByte);
 
     size_t width = Dbg::GetTagWidth(reqSigByte);
     uint8_t* ptr = expandBufAddSpace(pReply, width+1);
@@ -1452,7 +1452,7 @@
   FrameId frameId = ReadFrameId(&buf);
   uint32_t slots = Read4BE(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req to set %d slots in threadId=%llx frameId=%llx", slots, threadId, frameId);
+  VLOG(jdwp) << StringPrintf("  Req to set %d slots in threadId=%llx frameId=%llx", slots, threadId, frameId);
 
   for (uint32_t i = 0; i < slots; i++) {
     uint32_t slot = Read4BE(&buf);
@@ -1460,7 +1460,7 @@
     size_t width = Dbg::GetTagWidth(sigByte);
     uint64_t value = jdwpReadValue(&buf, width);
 
-    LOG(VERBOSE) << StringPrintf("    --> slot %d '%c' %llx", slot, sigByte, value);
+    VLOG(jdwp) << StringPrintf("    --> slot %d '%c' %llx", slot, sigByte, value);
     Dbg::SetLocalValue(threadId, frameId, slot, sigByte, value, width);
   }
 
@@ -1480,7 +1480,7 @@
   }
 
   uint8_t objectTag = Dbg::GetObjectTag(objectId);
-  LOG(VERBOSE) << StringPrintf("  Req for 'this' in frame=%llx --> %llx '%c'", frameId, objectId, (char)objectTag);
+  VLOG(jdwp) << StringPrintf("  Req for 'this' in frame=%llx --> %llx '%c'", frameId, objectId, (char)objectTag);
 
   expandBufAdd1(pReply, objectTag);
   expandBufAddObjectId(pReply, objectId);
@@ -1498,7 +1498,7 @@
 static JdwpError handleCOR_ReflectedType(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId classObjectId = ReadRefTypeId(&buf);
 
-  LOG(VERBOSE) << StringPrintf("  Req for refTypeId for class=%llx (%s)", classObjectId, Dbg::GetClassDescriptor(classObjectId).c_str());
+  VLOG(jdwp) << StringPrintf("  Req for refTypeId for class=%llx (%s)", classObjectId, Dbg::GetClassDescriptor(classObjectId).c_str());
 
   bool is_interface;
   if (!Dbg::IsInterface(classObjectId, is_interface)) {
@@ -1518,7 +1518,7 @@
   uint8_t* replyBuf = NULL;
   int replyLen = -1;
 
-  LOG(VERBOSE) << StringPrintf("  Handling DDM packet (%.4s)", buf);
+  VLOG(jdwp) << StringPrintf("  Handling DDM packet (%.4s)", buf);
 
   /*
    * On first DDM packet, notify all handlers that DDM is running.
@@ -1755,7 +1755,7 @@
   size_t i;
   for (i = 0; i < arraysize(gHandlerMap); i++) {
     if (gHandlerMap[i].cmdSet == pHeader->cmdSet && gHandlerMap[i].cmd == pHeader->cmd && gHandlerMap[i].func != NULL) {
-      LOG(VERBOSE) << DescribeCommand(pHeader, dataLen);
+      VLOG(jdwp) << DescribeCommand(pHeader, dataLen);
       result = (*gHandlerMap[i].func)(this, buf, dataLen, pReply);
       break;
     }
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index ad0610d..608ad04 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -271,7 +271,7 @@
   Runtime* runtime = Runtime::Current();
   runtime->AttachCurrentThread("JDWP", true);
 
-  LOG(VERBOSE) << "JDWP: thread running";
+  VLOG(jdwp) << "JDWP: thread running";
 
   /*
    * Finish initializing, then notify the creating thread that
@@ -379,7 +379,7 @@
   /* back to running, for thread shutdown */
   Dbg::ThreadRunning();
 
-  LOG(VERBOSE) << "JDWP: thread detaching and exiting...";
+  VLOG(jdwp) << "JDWP: thread detaching and exiting...";
   runtime->DetachCurrentThread();
 }
 
@@ -423,7 +423,7 @@
 
   /* initializing or in the middle of something? */
   if (last == 0) {
-    LOG(VERBOSE) << "+++ last=busy";
+    VLOG(jdwp) << "+++ last=busy";
     return 0;
   }
 
@@ -431,7 +431,7 @@
   int64_t now = MilliTime();
   CHECK_GT(now, last);
 
-  LOG(VERBOSE) << "+++ debugger interval=" << (now - last);
+  VLOG(jdwp) << "+++ debugger interval=" << (now - last);
   return now - last;
 }
 
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index b832133..d28c1da 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -222,7 +222,7 @@
 
   /* if we might be sitting in select, kick us loose */
   if (netState->wakePipe[1] >= 0) {
-    LOG(VERBOSE) << "+++ writing to wakePipe";
+    VLOG(jdwp) << "+++ writing to wakePipe";
     (void) write(netState->wakePipe[1], "", 1);
   }
 }
@@ -353,7 +353,9 @@
       // When we call shutdown() on the socket, accept() returns with
       // EINVAL.  Don't gripe about it.
       if (errno == EINVAL) {
-        PLOG(VERBOSE) << "accept failed";
+        if (VLOG_IS_ON(jdwp)) {
+          PLOG(ERROR) << "accept failed";
+        }
       } else {
         PLOG(ERROR) << "accept failed";
         return false;
@@ -363,13 +365,13 @@
 
   netState->remoteAddr = addr.addrInet.sin_addr;
   netState->remotePort = ntohs(addr.addrInet.sin_port);
-  LOG(VERBOSE) << "+++ accepted connection from " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
+  VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
 
   netState->clientSock = sock;
   netState->awaitingHandshake = true;
   netState->inputCount = 0;
 
-  LOG(VERBOSE) << "Setting TCP_NODELAY on accepted socket";
+  VLOG(jdwp) << "Setting TCP_NODELAY on accepted socket";
   setNoDelay(netState->clientSock);
 
   if (pipe(netState->wakePipe) < 0) {
@@ -476,7 +478,7 @@
     return;
   }
 
-  LOG(VERBOSE) << "+++ closed connection to " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
+  VLOG(jdwp) << "+++ closed connection to " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
 
   close(netState->clientSock);
   netState->clientSock = -1;
@@ -543,7 +545,7 @@
 
   dataLen = length - (buf - packetBuf);
 
-  LOG(VERBOSE) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
+  VLOG(jdwp) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
       reply ? "reply" : "req", dataLen, id, flags, cmdSet, cmd);
   if (dataLen > 0) {
     HexDump(buf, dataLen);
@@ -608,7 +610,7 @@
     DCHECK(false);
   }
 
-  LOG(VERBOSE) << "----------";
+  VLOG(jdwp) << "----------";
 
   consumeBytes(netState, length);
   return true;
@@ -653,7 +655,7 @@
       }
 
       if (maxfd < 0) {
-        LOG(VERBOSE) << "+++ all fds are closed";
+        VLOG(jdwp) << "+++ all fds are closed";
         return false;
       }
 
@@ -769,7 +771,7 @@
 
     consumeBytes(netState, kMagicHandshakeLen);
     netState->awaitingHandshake = false;
-    LOG(VERBOSE) << "+++ handshake complete";
+    VLOG(jdwp) << "+++ handshake complete";
     return true;
   }
 
@@ -797,7 +799,7 @@
   /*dumpPacket(expandBufGetBuffer(pReq));*/
   if (netState->clientSock < 0) {
     /* can happen with some DDMS events */
-    LOG(VERBOSE) << "NOT sending request -- no debugger is attached";
+    VLOG(jdwp) << "NOT sending request -- no debugger is attached";
     return false;
   }
 
@@ -825,7 +827,7 @@
 
   if (netState->clientSock < 0) {
     /* can happen with some DDMS events */
-    LOG(VERBOSE) << "NOT sending request -- no debugger is attached";
+    VLOG(jdwp) << "NOT sending request -- no debugger is attached";
     return false;
   }
 
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 7e145a8..9ace57a 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -573,19 +573,15 @@
 
     MutexLock mu(jni_on_load_lock_);
     while (jni_on_load_result_ == kPending) {
-      if (vm->verbose_jni) {
-        LOG(INFO) << "[" << *self << " waiting for \"" << path_ << "\" "
-                  << "JNI_OnLoad...]";
-      }
+      VLOG(jni) << "[" << *self << " waiting for \"" << path_ << "\" "
+                << "JNI_OnLoad...]";
       ScopedThreadStateChange tsc(self, Thread::kVmWait);
       jni_on_load_cond_.Wait(jni_on_load_lock_);
     }
 
     bool okay = (jni_on_load_result_ == kOkay);
-    if (vm->verbose_jni) {
-      LOG(INFO) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
-                << (okay ? "succeeded" : "failed") << "]";
-    }
+    VLOG(jni) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
+              << (okay ? "succeeded" : "failed") << "]";
     return okay;
   }
 
@@ -665,10 +661,8 @@
         fn = library->FindSymbol(jni_long_name);
       }
       if (fn != NULL) {
-        if (Runtime::Current()->GetJavaVM()->verbose_jni) {
-          LOG(INFO) << "[Found native code for " << PrettyMethod(m)
-                    << " in \"" << library->GetPath() << "\"]";
-        }
+        VLOG(jni) << "[Found native code for " << PrettyMethod(m)
+                  << " in \"" << library->GetPath() << "\"]";
         return fn;
       }
     }
@@ -2237,9 +2231,7 @@
         return JNI_ERR;
       }
 
-      if (ts.Vm()->verbose_jni) {
-        LOG(INFO) << "[Registering JNI native method " << PrettyMethod(m) << "]";
-      }
+      VLOG(jni) << "[Registering JNI native method " << PrettyMethod(m) << "]";
 
       m->RegisterNative(methods[i].fnPtr);
     }
@@ -2250,9 +2242,7 @@
     ScopedJniThreadState ts(env);
     Class* c = Decode<Class*>(ts, java_class);
 
-    if (ts.Vm()->verbose_jni) {
-      LOG(INFO) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
-    }
+    VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
 
     for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
       Method* m = c->GetDirectMethod(i);
@@ -2752,8 +2742,6 @@
       check_jni_abort_hook(NULL),
       check_jni(false),
       force_copy(false), // TODO: add a way to enable this
-      verbose_jni(options->IsVerbose("jni")),
-      log_third_party_jni(options->IsVerbose("third-party-jni")),
       trace(options->jni_trace_),
       work_around_app_jni_bugs(false), // TODO: add a way to enable this
       pins_lock("JNI pin table lock"),
@@ -2818,10 +2806,8 @@
       LOG(WARNING) << detail;
       return false;
     }
-    if (verbose_jni) {
-      LOG(INFO) << "[Shared library \"" << path << "\" already loaded in "
-                << "ClassLoader " << class_loader << "]";
-    }
+    VLOG(jni) << "[Shared library \"" << path << "\" already loaded in "
+              << "ClassLoader " << class_loader << "]";
     if (!library->CheckOnLoadResult(this)) {
       StringAppendF(&detail, "JNI_OnLoad failed on a previous attempt "
           "to load \"%s\"", path.c_str());
@@ -2864,9 +2850,7 @@
     handle = dlopen(path.c_str(), RTLD_LAZY);
   }
 
-  if (verbose_jni) {
-    LOG(INFO) << "[Call to dlopen(\"" << path << "\") returned " << handle << "]";
-  }
+  VLOG(jni) << "[Call to dlopen(\"" << path << "\") returned " << handle << "]";
 
   if (handle == NULL) {
     detail = dlerror();
@@ -2887,16 +2871,12 @@
     libraries->Put(path, library);
   }
 
-  if (verbose_jni) {
-    LOG(INFO) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
-  }
+  VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
 
   bool result = true;
   void* sym = dlsym(handle, "JNI_OnLoad");
   if (sym == NULL) {
-    if (verbose_jni) {
-      LOG(INFO) << "[No JNI_OnLoad found in \"" << path << "\"]";
-    }
+    VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]";
   } else {
     // Call JNI_OnLoad.  We have to override the current class
     // loader, which will always be "null" since the stuff at the
@@ -2910,9 +2890,7 @@
     int version = 0;
     {
       ScopedThreadStateChange tsc(self, Thread::kNative);
-      if (verbose_jni) {
-        LOG(INFO) << "[Calling JNI_OnLoad in \"" << path << "\"]";
-      }
+      VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]";
       version = (*jni_on_load)(this, NULL);
     }
 
@@ -2931,10 +2909,8 @@
       // unregister them, but that doesn't seem worthwhile.
       result = false;
     } else {
-      if (verbose_jni) {
-        LOG(INFO) << "[Returned " << (result ? "successfully" : "failure")
-                  << " from JNI_OnLoad in \"" << path << "\"]";
-      }
+      VLOG(jni) << "[Returned " << (result ? "successfully" : "failure")
+                << " from JNI_OnLoad in \"" << path << "\"]";
     }
   }
 
diff --git a/src/jni_internal.h b/src/jni_internal.h
index f39740b..dacc310 100644
--- a/src/jni_internal.h
+++ b/src/jni_internal.h
@@ -98,8 +98,6 @@
   bool force_copy;
 
   // Extra diagnostics.
-  bool verbose_jni;
-  bool log_third_party_jni;
   std::string trace;
 
   // Used to provide compatibility for apps that assumed direct references.
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index a9c9a41..d59fb3d 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -19,7 +19,7 @@
     vm_ = Runtime::Current()->GetJavaVM();
 
     // Turn on -verbose:jni for the JNI tests.
-    vm_->verbose_jni = true;
+    gLogVerbosity.jni = true;
 
     env_ = Thread::Current()->GetJniEnv();
 
diff --git a/src/logging.cc b/src/logging.cc
index 34e5e8d..4f1ae55 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -22,6 +22,8 @@
 
 namespace art {
 
+LogVerbosity gLogVerbosity;
+
 art::Mutex& GetLoggingLock() {
   static art::Mutex lock("LogMessage lock");
   return lock;
diff --git a/src/logging.h b/src/logging.h
index b653931..51d4496 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -121,6 +121,9 @@
 
 #define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
 
+#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
+#define VLOG(module) if (VLOG_IS_ON(module)) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
+
 //
 // Implementation details beyond this point.
 //
@@ -197,6 +200,23 @@
   return os;
 }
 
+// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
+// and the "-verbose:" command line argument.
+struct LogVerbosity {
+  bool class_linker; // Enabled with "-verbose:class".
+  bool compiler;
+  bool heap;
+  bool gc;
+  bool jdwp;
+  bool jni;
+  bool monitor;
+  bool startup;
+  bool third_party_jni; // Enabled with "-verbose:third-party-jni".
+  bool threads;
+};
+
+extern LogVerbosity gLogVerbosity;
+
 }  // namespace art
 
 #endif  // ART_SRC_LOGGING_H_
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index d44796c..9078340 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -565,9 +565,7 @@
 
 MarkSweep::~MarkSweep() {
 #ifndef NDEBUG
-  if (Heap::IsVerboseHeap()) {
-    LOG(INFO) << "MarkSweep scanned classes=" << class_count_ << " arrays=" << array_count_ << " other=" << other_count_;
-  }
+  VLOG(heap) << "MarkSweep scanned classes=" << class_count_ << " arrays=" << array_count_ << " other=" << other_count_;
 #endif
   delete mark_stack_;
   mark_bitmap_->Clear();
diff --git a/src/monitor.cc b/src/monitor.cc
index 8d04e2d..caaa116 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -96,13 +96,8 @@
 #define LW_LOCK_COUNT(x) (((x) >> LW_LOCK_COUNT_SHIFT) & LW_LOCK_COUNT_MASK)
 
 bool (*Monitor::is_sensitive_thread_hook_)() = NULL;
-bool Monitor::is_verbose_ = false;
 uint32_t Monitor::lock_profiling_threshold_ = 0;
 
-bool Monitor::IsVerbose() {
-  return is_verbose_;
-}
-
 bool Monitor::IsSensitiveThread() {
   if (is_sensitive_thread_hook_ != NULL) {
     return (*is_sensitive_thread_hook_)();
@@ -110,8 +105,7 @@
   return false;
 }
 
-void Monitor::Init(bool is_verbose, uint32_t lock_profiling_threshold, bool (*is_sensitive_thread_hook)()) {
-  is_verbose_ = is_verbose;
+void Monitor::Init(uint32_t lock_profiling_threshold, bool (*is_sensitive_thread_hook)()) {
   lock_profiling_threshold_ = lock_profiling_threshold;
   is_sensitive_thread_hook_ = is_sensitive_thread_hook;
 }
@@ -515,10 +509,8 @@
 
   // Allocate and acquire a new monitor.
   Monitor* m = new Monitor(obj);
-  if (is_verbose_) {
-    LOG(INFO) << "monitor: thread " << self->GetThinLockId()
-              << " created monitor " << m << " for object " << obj;
-  }
+  VLOG(monitor) << "monitor: thread " << self->GetThinLockId()
+                << " created monitor " << m << " for object " << obj;
   Runtime::Current()->GetMonitorList()->Add(m);
   m->Lock(self);
   // Propagate the lock state.
@@ -575,10 +567,8 @@
         goto retry;
       }
     } else {
-      if (is_verbose_) {
-        LOG(INFO) << StringPrintf("monitor: thread %d spin on lock %p (a %s) owned by %d",
-            threadId, thinp, PrettyTypeOf(obj).c_str(), LW_LOCK_OWNER(thin));
-      }
+      VLOG(monitor) << StringPrintf("monitor: thread %d spin on lock %p (a %s) owned by %d",
+          threadId, thinp, PrettyTypeOf(obj).c_str(), LW_LOCK_OWNER(thin));
       // The lock is owned by another thread. Notify the VM that we are about to wait.
       self->monitor_enter_object_ = obj;
       Thread::State oldStatus = self->SetState(Thread::kBlocked);
@@ -617,33 +607,25 @@
         } else {
           // The thin lock was inflated by another thread. Let the VM know we are no longer
           // waiting and try again.
-          if (is_verbose_) {
-            LOG(INFO) << "monitor: thread " << threadId
-                      << " found lock " << (void*) thinp << " surprise-fattened by another thread";
-          }
+          VLOG(monitor) << "monitor: thread " << threadId
+                        << " found lock " << (void*) thinp << " surprise-fattened by another thread";
           self->monitor_enter_object_ = NULL;
           self->SetState(oldStatus);
           goto retry;
         }
       }
-      if (is_verbose_) {
-        LOG(INFO) << StringPrintf("monitor: thread %d spin on lock %p done", threadId, thinp);
-      }
+      VLOG(monitor) << StringPrintf("monitor: thread %d spin on lock %p done", threadId, thinp);
       // We have acquired the thin lock. Let the VM know that we are no longer waiting.
       self->monitor_enter_object_ = NULL;
       self->SetState(oldStatus);
       // Fatten the lock.
       Inflate(self, obj);
-      if (is_verbose_) {
-        LOG(INFO) << StringPrintf("monitor: thread %d fattened lock %p", threadId, thinp);
-      }
+      VLOG(monitor) << StringPrintf("monitor: thread %d fattened lock %p", threadId, thinp);
     }
   } else {
     // The lock is a fat lock.
-    if (is_verbose_) {
-      LOG(INFO) << StringPrintf("monitor: thread %d locking fat lock %p (%p) %p on a %s",
+    VLOG(monitor) << StringPrintf("monitor: thread %d locking fat lock %p (%p) %p on a %s",
           threadId, thinp, LW_MONITOR(*thinp), (void*)*thinp, PrettyTypeOf(obj).c_str());
-    }
     DCHECK(LW_MONITOR(*thinp) != NULL);
     LW_MONITOR(*thinp)->Lock(self);
   }
@@ -729,9 +711,7 @@
      * any other thread gets a chance.
      */
     Inflate(self, obj);
-    if (is_verbose_) {
-      LOG(INFO) << StringPrintf("monitor: thread %d fattened lock %p by wait()", self->GetThinLockId(), thinp);
-    }
+    VLOG(monitor) << StringPrintf("monitor: thread %d fattened lock %p by wait()", self->GetThinLockId(), thinp);
   }
   LW_MONITOR(*thinp)->Wait(self, ms, ns, interruptShouldThrow);
 }
@@ -863,9 +843,7 @@
   while (it != list_.end()) {
     Monitor* m = *it;
     if (!is_marked(m->GetObject(), arg)) {
-      if (Monitor::IsVerbose()) {
-        LOG(INFO) << "freeing monitor " << m << " belonging to unmarked object " << m->GetObject();
-      }
+      VLOG(monitor) << "freeing monitor " << m << " belonging to unmarked object " << m->GetObject();
       delete m;
       it = list_.erase(it);
     } else {
diff --git a/src/monitor.h b/src/monitor.h
index 9b79f8e..0a8c795 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -63,9 +63,8 @@
  public:
   ~Monitor();
 
-  static bool IsVerbose();
   static bool IsSensitiveThread();
-  static void Init(bool is_verbose, uint32_t lock_profiling_threshold, bool (*is_sensitive_thread_hook)());
+  static void Init(uint32_t lock_profiling_threshold, bool (*is_sensitive_thread_hook)());
 
   static uint32_t GetThinLockId(uint32_t raw_lock_word);
 
@@ -103,7 +102,6 @@
                          const char*& source_file, uint32_t& line_number) const;
 
   static bool (*is_sensitive_thread_hook_)();
-  static bool is_verbose_;
   static uint32_t lock_profiling_threshold_;
 
   // Which thread currently owns the lock?
diff --git a/src/runtime.cc b/src/runtime.cc
index b41ebde..1304787 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -31,8 +31,7 @@
 Runtime* Runtime::instance_ = NULL;
 
 Runtime::Runtime()
-    : verbose_startup_(false),
-      is_zygote_(false),
+    : is_zygote_(false),
       default_stack_size_(Thread::kDefaultStackSize),
       monitor_list_(NULL),
       thread_list_(NULL),
@@ -341,7 +340,29 @@
       std::vector<std::string> verbose_options;
       Split(option.substr(strlen("-verbose:")).data(), ',', verbose_options);
       for (size_t i = 0; i < verbose_options.size(); ++i) {
-        parsed->verbose_.insert(verbose_options[i]);
+        if (verbose_options[i] == "class") {
+          gLogVerbosity.class_linker = true;
+        } else if (verbose_options[i] == "compiler") {
+          gLogVerbosity.compiler = true;
+        } else if (verbose_options[i] == "heap") {
+          gLogVerbosity.heap = true;
+        } else if (verbose_options[i] == "gc") {
+          gLogVerbosity.gc = true;
+        } else if (verbose_options[i] == "jdwp") {
+          gLogVerbosity.jdwp = true;
+        } else if (verbose_options[i] == "jni") {
+          gLogVerbosity.jni = true;
+        } else if (verbose_options[i] == "monitor") {
+          gLogVerbosity.monitor = true;
+        } else if (verbose_options[i] == "startup") {
+          gLogVerbosity.startup = true;
+        } else if (verbose_options[i] == "third-party-jni") {
+          gLogVerbosity.third_party_jni = true;
+        } else if (verbose_options[i] == "threads") {
+          gLogVerbosity.threads = true;
+        } else {
+          LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i];
+        }
       }
     } else if (option.starts_with("-Xjnigreflimit:")) {
       parsed->jni_globals_max_ = ParseIntegerOrDie(option);
@@ -437,9 +458,7 @@
 }
 
 void Runtime::Start() {
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::Start entering";
-  }
+  VLOG(startup) << "Runtime::Start entering";
 
   CHECK(host_prefix_.empty()) << host_prefix_;
 
@@ -464,9 +483,7 @@
 
   Thread::Current()->GetJniEnv()->locals.AssertEmpty();
 
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::Start exiting";
-  }
+  VLOG(startup) << "Runtime::Start exiting";
 }
 
 void Runtime::DidForkFromZygote() {
@@ -486,9 +503,7 @@
 }
 
 void Runtime::StartDaemonThreads() {
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::StartDaemonThreads entering";
-  }
+  VLOG(startup) << "Runtime::StartDaemonThreads entering";
 
   Thread* self = Thread::Current();
 
@@ -502,9 +517,7 @@
   CHECK(mid != NULL);
   env->CallStaticVoidMethod(c.get(), mid);
 
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::StartDaemonThreads exiting";
-  }
+  VLOG(startup) << "Runtime::StartDaemonThreads exiting";
 }
 
 bool Runtime::IsStarted() const {
@@ -519,13 +532,10 @@
     LOG(ERROR) << "Failed to parse options";
     return false;
   }
-  verbose_startup_ = options->IsVerbose("startup");
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::Init -verbose:startup enabled";
-  }
+  VLOG(startup) << "Runtime::Init -verbose:startup enabled";
 
   SetJniGlobalsMax(options->jni_globals_max_);
-  Monitor::Init(options->IsVerbose("monitor"), options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
+  Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
 
   host_prefix_ = options->host_prefix_;
   boot_class_path_ = options->boot_class_path_;
@@ -542,12 +552,10 @@
   stack_trace_file_ = options->stack_trace_file_;
 
   monitor_list_ = new MonitorList;
-  thread_list_ = new ThreadList(options->IsVerbose("thread"));
+  thread_list_ = new ThreadList;
   intern_table_ = new InternTable;
 
-  Heap::Init(options->IsVerbose("heap"),
-             options->IsVerbose("gc"),
-             options->heap_initial_size_,
+  Heap::Init(options->heap_initial_size_,
              options->heap_maximum_size_,
              options->heap_growth_limit_,
              options->images_);
@@ -566,21 +574,16 @@
   Thread::Current()->SetState(Thread::kRunnable);
 
   CHECK_GE(Heap::GetSpaces().size(), 1U);
-  bool verbose_class = options->IsVerbose("class");
   class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace())
-                   ? ClassLinker::Create(verbose_class, intern_table_)
-                   : ClassLinker::Create(verbose_class, options->boot_class_path_, intern_table_));
+                   ? ClassLinker::Create(intern_table_)
+                   : ClassLinker::Create(options->boot_class_path_, intern_table_));
 
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::Init exiting";
-  }
+  VLOG(startup) << "Runtime::Init exiting";
   return true;
 }
 
 void Runtime::InitNativeMethods() {
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::InitNativeMethods entering";
-  }
+  VLOG(startup) << "Runtime::InitNativeMethods entering";
   Thread* self = Thread::Current();
   JNIEnv* env = self->GetJniEnv();
 
@@ -598,9 +601,7 @@
   // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's
   // the library that implements System.loadLibrary!
   LoadJniLibrary(instance_->GetJavaVM(), "javacore");
-  if (IsVerboseStartup()) {
-    LOG(INFO) << "Runtime::InitNativeMethods exiting";
-  }
+  VLOG(startup) << "Runtime::InitNativeMethods exiting";
 }
 
 void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
diff --git a/src/runtime.h b/src/runtime.h
index 80534c2..b5e6954 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -18,7 +18,6 @@
 #include "macros.h"
 #include "runtime_stats.h"
 #include "stringpiece.h"
-#include "unordered_set.h"
 
 namespace art {
 
@@ -64,13 +63,8 @@
     jint (*hook_vfprintf_)(FILE* stream, const char* format, va_list ap);
     void (*hook_exit_)(jint status);
     void (*hook_abort_)();
-    std::tr1::unordered_set<std::string> verbose_;
     std::vector<std::string> properties_;
 
-    bool IsVerbose(const std::string& key) const {
-      return verbose_.find(key) != verbose_.end();
-    }
-
    private:
     ParsedOptions() {}
   };
@@ -78,10 +72,6 @@
   // Creates and initializes a new runtime.
   static Runtime* Create(const Options& options, bool ignore_unrecognized);
 
-  bool IsVerboseStartup() const {
-    return verbose_startup_;
-  }
-
   bool IsZygote() const {
     return is_zygote_;
   }
@@ -227,7 +217,6 @@
   void StartDaemonThreads();
   void StartSignalCatcher();
 
-  bool verbose_startup_;
   bool is_zygote_;
 
   // The host prefix is used during cross compilation. It is removed
diff --git a/src/runtime_test.cc b/src/runtime_test.cc
index ce03571..213897f 100644
--- a/src/runtime_test.cc
+++ b/src/runtime_test.cc
@@ -58,10 +58,16 @@
   EXPECT_TRUE(test_vfprintf == parsed->hook_vfprintf_);
   EXPECT_TRUE(test_exit == parsed->hook_exit_);
   EXPECT_TRUE(test_abort == parsed->hook_abort_);
-  ASSERT_EQ(3U, parsed->verbose_.size());
-  EXPECT_TRUE(parsed->verbose_.find("gc") != parsed->verbose_.end());
-  EXPECT_TRUE(parsed->verbose_.find("class") != parsed->verbose_.end());
-  EXPECT_TRUE(parsed->verbose_.find("jni") != parsed->verbose_.end());
+  EXPECT_TRUE(VLOG_IS_ON(class_linker));
+  EXPECT_FALSE(VLOG_IS_ON(compiler));
+  EXPECT_FALSE(VLOG_IS_ON(heap));
+  EXPECT_TRUE(VLOG_IS_ON(gc));
+  EXPECT_FALSE(VLOG_IS_ON(jdwp));
+  EXPECT_TRUE(VLOG_IS_ON(jni));
+  EXPECT_FALSE(VLOG_IS_ON(monitor));
+  EXPECT_FALSE(VLOG_IS_ON(startup));
+  EXPECT_FALSE(VLOG_IS_ON(third_party_jni));
+  EXPECT_FALSE(VLOG_IS_ON(threads));
   ASSERT_EQ(2U, parsed->properties_.size());
   EXPECT_EQ("foo=bar", parsed->properties_[0]);
   EXPECT_EQ("baz=qux", parsed->properties_[1]);
diff --git a/src/space.cc b/src/space.cc
index 6421188..14731f1 100644
--- a/src/space.cc
+++ b/src/space.cc
@@ -57,14 +57,11 @@
 }
 
 bool Space::Init(size_t initial_size, size_t maximum_size, size_t growth_size, byte* requested_base) {
-  const Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "Space::Init entering " << name_
-              << " initial_size=" << initial_size
-              << " maximum_size=" << maximum_size
-              << " growth_size=" << growth_size
-              << " requested_base=" << reinterpret_cast<void*>(requested_base);
-  }
+  VLOG(startup) << "Space::Init entering " << name_
+                << " initial_size=" << initial_size
+                << " maximum_size=" << maximum_size
+                << " growth_size=" << growth_size
+                << " requested_base=" << reinterpret_cast<void*>(requested_base);
   if (initial_size > growth_size) {
     LOG(ERROR) << "Failed to create space with initial size > growth size ("
                << initial_size << ">" << growth_size << "): " << name_;
@@ -92,9 +89,7 @@
     LOG(WARNING) << "Failed to create mspace for space: " << name_;
     return false;
   }
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "Space::Init exiting";
-  }
+  VLOG(startup) << "Space::Init exiting";
   return true;
 }
 
@@ -106,10 +101,8 @@
 
 bool Space::InitFromImage(const std::string& image_file_name) {
   Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "Space::InitFromImage entering"
-              << " image_file_name=" << image_file_name;
-  }
+  VLOG(startup) << "Space::InitFromImage entering"
+                << " image_file_name=" << image_file_name;
   UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false));
   if (file.get() == NULL) {
     LOG(WARNING) << "Failed to open " << image_file_name;
@@ -161,9 +154,7 @@
 
   InitFromMemMap(map.release());
   growth_limit_ = limit_;
-  if (runtime->IsVerboseStartup()) {
-    LOG(INFO) << "Space::InitFromImage exiting";
-  }
+  VLOG(startup) << "Space::InitFromImage exiting";
   return true;
 }
 
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 03998b6..9f7f08e 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -60,16 +60,13 @@
   Runtime::Current()->GetThreadList()->thread_list_lock_.Unlock();
 }
 
-ThreadList::ThreadList(bool verbose)
-    : verbose_(verbose),
-      thread_list_lock_("thread list lock"),
+ThreadList::ThreadList()
+    : thread_list_lock_("thread list lock"),
       thread_start_cond_("thread_start_cond_"),
       thread_exit_cond_("thread_exit_cond_"),
       thread_suspend_count_lock_("thread suspend count lock"),
       thread_suspend_count_cond_("thread_suspend_count_cond_") {
-  if (verbose_) {
-    LOG(INFO) << "default stack size " << Runtime::Current()->GetDefaultStackSize() / KB << "kb";
-  }
+  VLOG(threads) << "Default stack size: " << Runtime::Current()->GetDefaultStackSize() / KB << "KiB";
 }
 
 ThreadList::~ThreadList() {
@@ -125,9 +122,7 @@
     return;
   }
 
-  if (verbose_) {
-    LOG(INFO) << *thread << " self-suspending";
-  }
+  VLOG(threads) << *thread << " self-suspending";
   {
     ScopedThreadStateChange tsc(thread, Thread::kSuspended);
     while (thread->suspend_count_ != 0) {
@@ -140,17 +135,13 @@
     }
     CHECK_EQ(thread->suspend_count_, 0);
   }
-  if (verbose_) {
-    LOG(INFO) << *thread << " self-reviving";
-  }
+  VLOG(threads) << *thread << " self-reviving";
 }
 
 void ThreadList::SuspendAll(bool for_debugger) {
   Thread* self = Thread::Current();
 
-  if (verbose_) {
-    LOG(INFO) << *self << " SuspendAll starting..." << (for_debugger ? " (debugger)" : "");
-  }
+  VLOG(threads) << *self << " SuspendAll starting..." << (for_debugger ? " (debugger)" : "");
 
   CHECK_EQ(self->GetState(), Thread::kRunnable);
   ScopedThreadListLock thread_list_lock;
@@ -164,9 +155,7 @@
       if (thread == self || (for_debugger && thread == debug_thread)) {
         continue;
       }
-      if (verbose_) {
-        LOG(INFO) << "requesting thread suspend: " << *thread;
-      }
+      VLOG(threads) << "requesting thread suspend: " << *thread;
       ModifySuspendCount(thread, +1, for_debugger);
     }
   }
@@ -191,14 +180,10 @@
       continue;
     }
     thread->WaitUntilSuspended();
-    if (verbose_) {
-      LOG(INFO) << "thread suspended: " << *thread;
-    }
+    VLOG(threads) << "thread suspended: " << *thread;
   }
 
-  if (verbose_) {
-    LOG(INFO) << *self << " SuspendAll complete";
-  }
+  VLOG(threads) << *self << " SuspendAll complete";
 }
 
 void ThreadList::Suspend(Thread* thread, bool for_debugger) {
@@ -207,9 +192,7 @@
 
   // TODO: add another thread_suspend_lock_ to avoid GC/debugger races.
 
-  if (verbose_) {
-    LOG(INFO) << "Suspend(" << *thread << ") starting..." << (for_debugger ? " (debugger)" : "");
-  }
+  VLOG(threads) << "Suspend(" << *thread << ") starting..." << (for_debugger ? " (debugger)" : "");
 
   if (!Contains(thread)) {
     return;
@@ -222,9 +205,7 @@
 
   thread->WaitUntilSuspended();
 
-  if (verbose_) {
-    LOG(INFO) << "Suspend(" << *thread << ") complete";
-  }
+  VLOG(threads) << "Suspend(" << *thread << ") complete";
 }
 
 void ThreadList::SuspendSelfForDebugger() {
@@ -244,9 +225,7 @@
   // Suspend ourselves.
   CHECK_GT(self->suspend_count_, 0);
   self->SetState(Thread::kSuspended);
-  if (verbose_) {
-    LOG(INFO) << *self << " self-suspending (dbg)";
-  }
+  VLOG(threads) << *self << " self-suspending (dbg)";
 
   // Tell JDWP that we've completed suspension. The JDWP thread can't
   // tell us to resume before we're fully asleep because we hold the
@@ -266,17 +245,13 @@
   }
   CHECK_EQ(self->suspend_count_, 0);
   self->SetState(Thread::kRunnable);
-  if (verbose_) {
-    LOG(INFO) << *self << " self-reviving (dbg)";
-  }
+  VLOG(threads) << *self << " self-reviving (dbg)";
 }
 
 void ThreadList::ResumeAll(bool for_debugger) {
   Thread* self = Thread::Current();
 
-  if (verbose_) {
-    LOG(INFO) << *self << " ResumeAll starting" << (for_debugger ? " (debugger)" : "");
-  }
+  VLOG(threads) << *self << " ResumeAll starting" << (for_debugger ? " (debugger)" : "");
 
   // Decrement the suspend counts for all threads.  No need for atomic
   // writes, since nobody should be moving until we decrement the count.
@@ -297,16 +272,12 @@
   // Broadcast a notification to all suspended threads, some or all of
   // which may choose to wake up.  No need to wait for them.
   {
-    if (verbose_) {
-      LOG(INFO) << *self << " ResumeAll waking others";
-    }
+    VLOG(threads) << *self << " ResumeAll waking others";
     MutexLock mu(thread_suspend_count_lock_);
     thread_suspend_count_cond_.Broadcast();
   }
 
-  if (verbose_) {
-    LOG(INFO) << *self << " ResumeAll complete";
-  }
+  VLOG(threads) << *self << " ResumeAll complete";
 }
 
 void ThreadList::Resume(Thread* thread, bool for_debugger) {
@@ -316,9 +287,7 @@
     thread_list_lock_.AssertHeld();
   }
 
-  if (verbose_) {
-    LOG(INFO) << "Resume(" << *thread << ") starting..." << (for_debugger ? " (debugger)" : "");
-  }
+  VLOG(threads) << "Resume(" << *thread << ") starting..." << (for_debugger ? " (debugger)" : "");
 
   {
     MutexLock mu(thread_suspend_count_lock_);
@@ -329,16 +298,12 @@
   }
 
   {
-    if (verbose_) {
-      LOG(INFO) << "Resume(" << *thread << ") waking others";
-    }
+    VLOG(threads) << "Resume(" << *thread << ") waking others";
     MutexLock mu(thread_suspend_count_lock_);
     thread_suspend_count_cond_.Broadcast();
   }
 
-  if (verbose_) {
-    LOG(INFO) << "Resume(" << *thread << ") complete";
-  }
+  VLOG(threads) << "Resume(" << *thread << ") complete";
 }
 
 void ThreadList::RunWhileSuspended(Thread* thread, void (*callback)(void*), void* arg) {
@@ -356,9 +321,7 @@
 void ThreadList::UndoDebuggerSuspensions() {
   Thread* self = Thread::Current();
 
-  if (verbose_) {
-    LOG(INFO) << *self << " UndoDebuggerSuspensions starting";
-  }
+  VLOG(threads) << *self << " UndoDebuggerSuspensions starting";
 
   {
     ScopedThreadListLock thread_list_lock;
@@ -377,17 +340,13 @@
     thread_suspend_count_cond_.Broadcast();
   }
 
-  if (verbose_) {
-    LOG(INFO) << "UndoDebuggerSuspensions(" << *self << ") complete";
-  }
+  VLOG(threads) << "UndoDebuggerSuspensions(" << *self << ") complete";
 }
 
 void ThreadList::Register() {
   Thread* self = Thread::Current();
 
-  if (verbose_) {
-    LOG(INFO) << "ThreadList::Register() " << *self << "\n" << Dumpable<Thread>(*self);
-  }
+  VLOG(threads) << "ThreadList::Register() " << *self << "\n" << Dumpable<Thread>(*self);
 
   ScopedThreadListLock thread_list_lock;
   CHECK(!Contains(self));
@@ -397,9 +356,7 @@
 void ThreadList::Unregister() {
   Thread* self = Thread::Current();
 
-  if (verbose_) {
-    LOG(INFO) << "ThreadList::Unregister() " << *self;
-  }
+  VLOG(threads) << "ThreadList::Unregister() " << *self;
 
   if (self->GetPeer() != NULL) {
       self->SetState(Thread::kRunnable);
@@ -464,9 +421,7 @@
 
   {
     ScopedThreadListLock thread_list_lock;
-    if (verbose_) {
-      LOG(INFO) << *self << " waiting for child " << *child << " to be in thread list...";
-    }
+    VLOG(threads) << *self << " waiting for child " << *child << " to be in thread list...";
 
     // We wait for the child to tell us that it's in the thread list.
     while (child->GetState() != Thread::kStarting) {
@@ -480,9 +435,7 @@
 
   // Tell the child that it's safe: it will see any future suspend request.
   ScopedThreadListLock thread_list_lock;
-  if (verbose_) {
-    LOG(INFO) << *self << " telling child " << *child << " it's safe to proceed...";
-  }
+  VLOG(threads) << *self << " telling child " << *child << " it's safe to proceed...";
   child->SetState(Thread::kVmWait);
   thread_start_cond_.Broadcast();
 }
@@ -495,26 +448,20 @@
     ScopedThreadListLock thread_list_lock;
 
     // Tell our parent that we're in the thread list.
-    if (verbose_) {
-      LOG(INFO) << *self << " telling parent that we're now in thread list...";
-    }
+    VLOG(threads) << *self << " telling parent that we're now in thread list...";
     self->SetState(Thread::kStarting);
     thread_start_cond_.Broadcast();
 
     // Wait until our parent tells us there's no suspend still pending
     // from before we were on the thread list.
-    if (verbose_) {
-      LOG(INFO) << *self << " waiting for parent's go-ahead...";
-    }
+    VLOG(threads) << *self << " waiting for parent's go-ahead...";
     while (self->GetState() != Thread::kVmWait) {
       thread_start_cond_.Wait(thread_list_lock_);
     }
   }
 
   // Enter the runnable state. We know that any pending suspend will affect us now.
-  if (verbose_) {
-    LOG(INFO) << *self << " entering runnable state...";
-  }
+  VLOG(threads) << *self << " entering runnable state...";
   // Lock and unlock the heap lock. This ensures that if there was a GC in progress when we
   // started, we wait until it's over. Which means that if there's now another GC pending, our
   // suspend count is non-zero, so switching to the runnable state will suspend us.
diff --git a/src/thread_list.h b/src/thread_list.h
index d93ec3b..5da9877 100644
--- a/src/thread_list.h
+++ b/src/thread_list.h
@@ -28,7 +28,7 @@
   static const uint32_t kInvalidId = 0;
   static const uint32_t kMainId = 1;
 
-  explicit ThreadList(bool verbose);
+  explicit ThreadList();
   ~ThreadList();
 
   void Dump(std::ostream& os);
@@ -68,8 +68,6 @@
 
   static void ModifySuspendCount(Thread* thread, int delta, bool for_debugger);
 
-  bool verbose_;
-
   mutable Mutex thread_list_lock_;
   std::bitset<kMaxThreadId> allocated_ids_;
   std::list<Thread*> list_;