auto import //branches/master/...@140412
diff --git a/vm/alloc/Alloc.h b/vm/alloc/Alloc.h
index 0489db7..8bf4520 100644
--- a/vm/alloc/Alloc.h
+++ b/vm/alloc/Alloc.h
@@ -133,7 +133,7 @@
     }
 #ifdef WITH_EXTRA_OBJECT_VALIDATION
     if (!dvmIsValidObject(obj)) {
-        //abort();
+        //dvmAbort();
         dvmThrowException("Ljava/lang/InternalError;",
             "VM detected invalid object ptr");
         return false;
@@ -142,7 +142,7 @@
 #ifndef NDEBUG
     /* check for heap corruption */
     if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
-        abort();
+        dvmAbort();
         dvmThrowException("Ljava/lang/InternalError;",
             "VM detected invalid object class ptr");
         return false;
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index 9ddc8be..6f3c7c1 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -174,6 +174,7 @@
         if (self != NULL) {
             oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
         } else {
+            LOGI("ODD: waiting on heap lock, no self\n");
             oldStatus = -1; // shut up gcc
         }
 
@@ -831,6 +832,8 @@
     if (gcHeap->hprofDumpOnGc) {
         char nameBuf[128];
 
+        gcHeap->hprofResult = -1;
+
         if (gcHeap->hprofFileName == NULL) {
             /* no filename was provided; invent one */
             sprintf(nameBuf, "/data/misc/heap-dump-tm%d-pid%d.hprof",
@@ -860,7 +863,10 @@
 
     /* Set up the marking context.
      */
-    dvmHeapBeginMarkStep();
+    if (!dvmHeapBeginMarkStep()) {
+        LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting\n");
+        dvmAbort();
+    }
 
     /* Mark the set of objects that are strongly reachable from the roots.
      */
@@ -982,7 +988,8 @@
     if (gcHeap->hprofContext != NULL) {
         hprofFinishHeapDump(gcHeap->hprofContext);
 //TODO: write a HEAP_SUMMARY record
-        hprofShutdown(gcHeap->hprofContext);
+        if (hprofShutdown(gcHeap->hprofContext))
+            gcHeap->hprofResult = 0;    /* indicate success */
         gcHeap->hprofContext = NULL;
     }
 #endif
@@ -1046,16 +1053,23 @@
  * Perform garbage collection, writing heap information to the specified file.
  *
  * If "fileName" is NULL, a suitable name will be generated automatically.
+ *
+ * Returns 0 on success, or an error code on failure.
  */
-void hprofDumpHeap(const char* fileName)
+int hprofDumpHeap(const char* fileName)
 {
+    int result;
+
     dvmLockMutex(&gDvm.gcHeapLock);
 
     gDvm.gcHeap->hprofDumpOnGc = true;
     gDvm.gcHeap->hprofFileName = fileName;
     dvmCollectGarbageInternal(false);
+    result = gDvm.gcHeap->hprofResult;
 
     dvmUnlockMutex(&gDvm.gcHeapLock);
+
+    return result;
 }
 
 void dvmHeapSetHprofGcScanState(hprof_heap_tag_t state, u4 threadSerialNumber)
diff --git a/vm/alloc/HeapInternal.h b/vm/alloc/HeapInternal.h
index 7851983..fafb87a 100644
--- a/vm/alloc/HeapInternal.h
+++ b/vm/alloc/HeapInternal.h
@@ -189,6 +189,7 @@
     bool            hprofDumpOnGc;
     const char*     hprofFileName;
     hprof_context_t *hprofContext;
+    int             hprofResult;
 #endif
 };
 
diff --git a/vm/alloc/HeapWorker.c b/vm/alloc/HeapWorker.c
index 0244cca..b4a2d0e 100644
--- a/vm/alloc/HeapWorker.c
+++ b/vm/alloc/HeapWorker.c
@@ -111,7 +111,7 @@
 }
 
 /* Make sure that the HeapWorker thread hasn't spent an inordinate
- * amount of time inside interpreted a finalizer.
+ * amount of time inside a finalizer.
  *
  * Aborts the VM if the thread appears to be wedged.
  *
@@ -132,12 +132,16 @@
         u8 nowCpu = dvmGetOtherThreadCpuTimeUsec(gDvm.heapWorkerHandle);
         u8 deltaCpu = nowCpu - heapWorkerInterpCpuStartTime;
 
-        if (delta > HEAP_WORKER_WATCHDOG_TIMEOUT && gDvm.debuggerActive) {
+        if (delta > HEAP_WORKER_WATCHDOG_TIMEOUT &&
+            (gDvm.debuggerActive || gDvm.nativeDebuggerActive))
+        {
             /*
              * Debugger suspension can block the thread indefinitely.  For
              * best results we should reset this explicitly whenever the
-             * HeapWorker thread is resumed.  Ignoring the yelp isn't
-             * quite right but will do for a quick fix.
+             * HeapWorker thread is resumed.  Unfortunately this is also
+             * affected by native debuggers, and we have no visibility
+             * into how they're manipulating us.  So, we ignore the
+             * watchdog and just reset the timer.
              */
             LOGI("Debugger is attached -- suppressing HeapWorker watchdog\n");
             heapWorkerInterpStartTime = now;        /* reset timer */
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.c
index a0601d7..0905bce 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.c
@@ -22,6 +22,7 @@
 #include <limits.h>     // for ULONG_MAX
 #include <sys/mman.h>   // for madvise(), mmap()
 #include <cutils/ashmem.h>
+#include <errno.h>
 
 #define GC_DEBUG_PARANOID   2
 #define GC_DEBUG_BASIC      1
@@ -92,7 +93,7 @@
 {
     const Object **limit;
     size_t size;
-    int fd;
+    int fd, err;
 
     /* Create a stack big enough for the worst possible case,
      * where the heap is perfectly full of the smallest object.
@@ -104,14 +105,17 @@
     size = ALIGN_UP_TO_PAGE_SIZE(size);
     fd = ashmem_create_region("dalvik-heap-markstack", size);
     if (fd < 0) {
-        LOGE_GC("Could not create %d-byte ashmem mark stack\n", size);
+        LOGE_GC("Could not create %d-byte ashmem mark stack: %s\n",
+            size, strerror(errno));
         return false;
     }
     limit = (const Object **)mmap(NULL, size, PROT_READ | PROT_WRITE,
             MAP_PRIVATE, fd, 0);
+    err = errno;
     close(fd);
     if (limit == MAP_FAILED) {
-        LOGE_GC("Could not mmap %d-byte ashmem mark stack\n", size);
+        LOGE_GC("Could not mmap %d-byte ashmem mark stack: %s\n",
+            size, strerror(err));
         return false;
     }