Use static thread safety analysis when available, and fix the bugs GCC finds.

It's impossible to express the Heap locking and the ThreadList locking with
GCC, but Clang is supposed to be able to do it. This patch does what's possible
for now.

Change-Id: Ib64a890c9d27c6ce255d5003cb755c2ef1beba95
diff --git a/src/heap.h b/src/heap.h
index e205f7a..96a9ee6 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -42,7 +42,7 @@
 class SpaceTest;
 class Thread;
 
-class Heap {
+class LOCKABLE Heap {
   friend class ScopedHeapLock;
  public:
   static const size_t kInitialSize = 2 * MB;
@@ -236,13 +236,14 @@
   void DumpForSigQuit(std::ostream& os);
 
   void Trim();
+
  private:
   // Allocates uninitialized storage.
   Object* AllocateLocked(size_t num_bytes);
   Object* AllocateLocked(AllocSpace* space, size_t num_bytes);
 
-  void Lock();
-  void Unlock();
+  void Lock() EXCLUSIVE_LOCK_FUNCTION();
+  void Unlock() UNLOCK_FUNCTION();
 
   // Pushes a list of cleared references out to the managed heap.
   void EnqueueClearedReferences(Object** cleared_references);
@@ -253,7 +254,8 @@
   void RecordAllocationLocked(AllocSpace* space, const Object* object);
   void RecordImageAllocations(Space* space);
 
-  void CollectGarbageInternal(bool concurrent, bool clear_soft_references);
+  // TODO: can we teach GCC to understand the weird locking in here?
+  void CollectGarbageInternal(bool concurrent, bool clear_soft_references) NO_THREAD_SAFETY_ANALYSIS;
 
   // Given the current contents of the alloc space, increase the allowed heap footprint to match
   // the target utilization ratio.  This should only be called immediately after a full garbage