A bit further along the track of multiple threads.

This also makes valgrind happy, and tsan mostly happy. (The heap, it turns out,
doesn't have a lock yet.)

The DexVerifier changes are just to make valgrind happy, and the code a little
less unidiomatic.

Change-Id: Ic5d436b4863b9d7088eb0b8fe9d32308919899d8
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 14f4883..b533a11 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -633,7 +633,7 @@
     } else {
       klass = AllocClass(SizeOfClass(dex_file, dex_class_def));
     }
-    if (!klass->IsLinked()) {
+    if (!klass->IsResolved()) {
       klass->SetDexCache(dex_cache);
       LoadClass(dex_file, dex_class_def, klass, class_loader);
       // Check for a pending exception during load
@@ -663,27 +663,27 @@
         }
         CHECK(klass->IsLoaded());
         // Link the class (if necessary)
-        CHECK(!klass->IsLinked());
+        CHECK(!klass->IsResolved());
         if (!LinkClass(klass)) {
           // Linking failed.
           // TODO: CHECK(self->IsExceptionPending());
           lock.NotifyAll();
           return NULL;
         }
-        CHECK(klass->IsLinked());
+        CHECK(klass->IsResolved());
       }
     }
   }
   // Link the class if it has not already been linked.
-  if (!klass->IsLinked() && !klass->IsErroneous()) {
+  if (!klass->IsResolved() && !klass->IsErroneous()) {
     ObjectLock lock(klass);
     // Check for circular dependencies between classes.
-    if (!klass->IsLinked() && klass->GetClinitThreadId() == self->GetTid()) {
+    if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
       self->ThrowNewException("Ljava/lang/ClassCircularityError;", NULL); // TODO: detail
       return NULL;
     }
     // Wait for the pending initialization to complete.
-    while (!klass->IsLinked() && !klass->IsErroneous()) {
+    while (!klass->IsResolved() && !klass->IsErroneous()) {
       lock.Wait();
     }
   }
@@ -692,7 +692,7 @@
     return NULL;
   }
   // Return the loaded class.  No exceptions should be pending.
-  CHECK(klass->IsLinked());
+  CHECK(klass->IsResolved());
   CHECK(!self->IsExceptionPending());
   return klass;
 }
@@ -1428,6 +1428,19 @@
   return klass;
 }
 
+void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
+    Class* c, std::map<int, Field*>& field_map) {
+  const ClassLoader* cl = c->GetClassLoader();
+  const byte* class_data = dex_file.GetClassData(dex_class_def);
+  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
+  uint32_t last_idx = 0;
+  for (size_t i = 0; i < header.static_fields_size_; ++i) {
+    DexFile::Field dex_field;
+    dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
+    field_map[i] = ResolveField(dex_file, dex_field.field_idx_, c->GetDexCache(), cl, true);
+  }
+}
+
 void ClassLinker::InitializeStaticFields(Class* klass) {
   size_t num_static_fields = klass->NumStaticFields();
   if (num_static_fields == 0) {
@@ -1442,6 +1455,11 @@
   const DexFile& dex_file = FindDexFile(dex_cache);
   const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
   CHECK(dex_class_def != NULL);
+
+  // We reordered the fields, so we need to be able to map the field indexes to the right fields.
+  std::map<int, Field*> field_map;
+  ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
+
   const byte* addr = dex_file.GetEncodedArray(*dex_class_def);
   if (addr == NULL) {
     // All this class' static fields have default values.
@@ -1449,7 +1467,7 @@
   }
   size_t array_size = DecodeUnsignedLeb128(&addr);
   for (size_t i = 0; i < array_size; ++i) {
-    Field* field = klass->GetStaticField(i);
+    Field* field = field_map[i];
     JValue value;
     DexFile::ValueType type = dex_file.ReadEncodedValue(&addr, &value);
     switch (type) {
@@ -1573,7 +1591,7 @@
 #ifndef NDEBUG
   // Ensure super classes are fully resolved prior to resolving fields..
   while (super != NULL) {
-    CHECK(super->IsLinked());
+    CHECK(super->IsResolved());
     super = super->GetSuperClass();
   }
 #endif
@@ -1818,7 +1836,7 @@
   return success;
 }
 
-bool ClassLinker::LinkFields(Class *klass, bool instance) {
+bool ClassLinker::LinkFields(Class* klass, bool instance) {
   size_t num_fields =
       instance ? klass->NumInstanceFields() : klass->NumStaticFields();
 
@@ -1833,7 +1851,7 @@
   if (instance) {
     Class* super_class = klass->GetSuperClass();
     if (super_class != NULL) {
-      CHECK(super_class->IsLinked());
+      CHECK(super_class->IsResolved());
       field_offset = MemberOffset(super_class->GetObjectSize());
       if (field_offset.Uint32Value() == 0u) {
         field_offset = OFFSET_OF_OBJECT_MEMBER(DataObject, fields_);
diff --git a/src/class_linker.h b/src/class_linker.h
index 4f4ffc7..fe375c2 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -185,6 +185,9 @@
   void AppendToBootClassPath(const DexFile& dex_file);
   void AppendToBootClassPath(const DexFile& dex_file, DexCache* dex_cache);
 
+  void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
+      Class* c, std::map<int, Field*>& field_map);
+
   size_t SizeOfClass(const DexFile& dex_file,
                      const DexFile::ClassDef& dex_class_def);
 
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 71cb22e..607382b 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -40,7 +40,7 @@
     EXPECT_TRUE(primitive->GetStatus() == Class::kStatusInitialized);
     EXPECT_FALSE(primitive->IsErroneous());
     EXPECT_TRUE(primitive->IsVerified());
-    EXPECT_TRUE(primitive->IsLinked());
+    EXPECT_TRUE(primitive->IsResolved());
     EXPECT_FALSE(primitive->IsArrayInstance());
     EXPECT_FALSE(primitive->IsArrayClass());
     EXPECT_EQ(0, primitive->GetArrayRank());
@@ -81,7 +81,7 @@
     EXPECT_TRUE(array->GetStatus() == Class::kStatusInitialized);
     EXPECT_FALSE(array->IsErroneous());
     EXPECT_TRUE(array->IsVerified());
-    EXPECT_TRUE(array->IsLinked());
+    EXPECT_TRUE(array->IsResolved());
     EXPECT_FALSE(array->IsArrayInstance());
     EXPECT_TRUE(array->IsArrayClass());
     EXPECT_LE(1, array->GetArrayRank());
@@ -138,10 +138,9 @@
       EXPECT_TRUE(klass->GetSuperClass() != NULL);
     }
     EXPECT_TRUE(klass->GetDexCache() != NULL);
-    EXPECT_EQ(Class::kStatusResolved, klass->GetStatus());
+    EXPECT_TRUE(klass->IsResolved());
     EXPECT_FALSE(klass->IsErroneous());
-    EXPECT_FALSE(klass->IsVerified());
-    EXPECT_TRUE(klass->IsLinked());
+    EXPECT_TRUE(klass->IsResolved());
     EXPECT_TRUE(klass->IsLoaded());
     EXPECT_FALSE(klass->IsArrayClass());
     EXPECT_EQ(0, klass->GetArrayRank());
@@ -309,8 +308,8 @@
   EXPECT_FALSE(JavaLangObject->HasSuperClass());
   EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
   EXPECT_FALSE(JavaLangObject->IsErroneous());
-  EXPECT_FALSE(JavaLangObject->IsVerified());
-  EXPECT_TRUE(JavaLangObject->IsLinked());
+  EXPECT_TRUE(JavaLangObject->IsVerified());
+  EXPECT_TRUE(JavaLangObject->IsResolved());
   EXPECT_FALSE(JavaLangObject->IsArrayInstance());
   EXPECT_FALSE(JavaLangObject->IsArrayClass());
   EXPECT_EQ(0, JavaLangObject->GetArrayRank());
@@ -339,7 +338,7 @@
   EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
   EXPECT_FALSE(MyClass->IsErroneous());
   EXPECT_FALSE(MyClass->IsVerified());
-  EXPECT_TRUE(MyClass->IsLinked());
+  EXPECT_TRUE(MyClass->IsResolved());
   EXPECT_FALSE(MyClass->IsArrayInstance());
   EXPECT_FALSE(MyClass->IsArrayClass());
   EXPECT_EQ(0, JavaLangObject->GetArrayRank());
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index df9d7cb..0a93109 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -12,7 +12,6 @@
 #include "logging.h"
 #include "runtime.h"
 #include "stringpiece.h"
-#include "UniquePtr.h"
 
 namespace art {
 
@@ -125,7 +124,7 @@
   const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
-  const DexFile::CodeItem *code_item =
+  const DexFile::CodeItem* code_item =
       dex_file.GetCodeItem(method->GetCodeItemOffset());
 
   /*
@@ -158,8 +157,7 @@
   /*
    * Allocate and initialize an array to hold instruction data.
    */
-  UniquePtr<InsnFlags> insn_flags(new InsnFlags[code_item->insns_size_]());
-  vdata.insn_flags_ = insn_flags.get();
+  vdata.insn_flags_.reset(new InsnFlags[code_item->insns_size_]());
 
   /*
    * Run through the instructions and see if the width checks out.
@@ -194,7 +192,7 @@
 
 bool DexVerifier::VerifyInstructions(VerifierData* vdata) {
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  InsnFlags* insn_flags = vdata->insn_flags_;
+  InsnFlags* insn_flags = vdata->insn_flags_.get();
   const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
   const Instruction* inst = Instruction::At(ptr);
 
@@ -227,7 +225,7 @@
     const Instruction* inst, uint32_t code_offset) {
   const DexFile* dex_file = vdata->dex_file_;
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  InsnFlags* insn_flags = vdata->insn_flags_;
+  InsnFlags* insn_flags = vdata->insn_flags_.get();
   Instruction::DecodedInstruction dec_insn(inst);
   bool result = true;
 
@@ -330,14 +328,13 @@
     return false;
   }
 
-  vdata->register_lines_ = reg_table.register_lines_;
+  vdata->register_lines_ = reg_table.register_lines_.get();
 
   /* Allocate a map to hold the classes of uninitialized instances. */
-  UniquePtr<UninitInstanceMap> uninit_map(CreateUninitInstanceMap(vdata));
-  vdata->uninit_map_ = uninit_map.get();
+  vdata->uninit_map_.reset(CreateUninitInstanceMap(vdata));
 
   /* Initialize register types of method arguments. */
-  if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_)) {
+  if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_.get())) {
     LOG(ERROR) << "VFY: bad signature '"
                << method->GetSignature()->ToModifiedUtf8() << "' for "
                << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
@@ -359,7 +356,7 @@
 bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
   const uint16_t* insns = vdata->code_item_->insns_;
   uint32_t insns_size = vdata->code_item_->insns_size_;
-  InsnFlags* insn_flags = vdata->insn_flags_;
+  InsnFlags* insn_flags = vdata->insn_flags_.get();
   const byte* ptr = reinterpret_cast<const byte*>(insns);
   const Instruction* inst = Instruction::At(ptr);
   size_t new_instance_count = 0;
@@ -392,7 +389,7 @@
 
 bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  InsnFlags* insn_flags = vdata->insn_flags_;
+  InsnFlags* insn_flags = vdata->insn_flags_.get();
   uint32_t insns_size = code_item->insns_size_;
   uint32_t tries_size = code_item->tries_size_;
 
@@ -821,7 +818,7 @@
 bool DexVerifier::InitRegisterTable(VerifierData* vdata,
     RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  InsnFlags* insn_flags = vdata->insn_flags_;
+  InsnFlags* insn_flags = vdata->insn_flags_.get();
   uint16_t registers_size = code_item->registers_size_;
   uint32_t insns_size = code_item->insns_size_;
   uint32_t i;
@@ -832,7 +829,7 @@
    * indirection.
    */
   reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
-  reg_table->register_lines_ = new RegisterLine[insns_size]();
+  reg_table->register_lines_.reset(new RegisterLine[insns_size]());
 
   assert(insns_size > 0);
 
@@ -1050,7 +1047,7 @@
   Method* method = vdata->method_;
   const DexFile* dex_file = vdata->dex_file_;
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  UninitInstanceMap* uninit_map = vdata->uninit_map_;
+  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
 
   int arg_start = code_item->registers_size_ - code_item->ins_size_;
   int expected_args = code_item->ins_size_;   /* long/double count as two */
@@ -1243,7 +1240,7 @@
     RegisterTable* reg_table) {
   const Method* method = vdata->method_;
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  InsnFlags* insn_flags = vdata->insn_flags_;
+  InsnFlags* insn_flags = vdata->insn_flags_.get();
   const uint16_t* insns = code_item->insns_;
   uint32_t insns_size = code_item->insns_size_;
   size_t insn_idx, start_guess;
@@ -1296,7 +1293,7 @@
        * a full table) and make sure it actually matches.
        */
       RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
-      if (register_line->reg_types_ != NULL && CompareLineToTable(reg_table,
+      if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
           insn_idx, &reg_table->work_line_) != 0) {
         Class* klass = method->GetDeclaringClass();
         LOG(ERROR) << "HUH? work_line diverged in "
@@ -1378,9 +1375,9 @@
   const Method* method = vdata->method_;
   Class* klass = method->GetDeclaringClass();
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  InsnFlags* insn_flags = vdata->insn_flags_;
+  InsnFlags* insn_flags = vdata->insn_flags_.get();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  UninitInstanceMap* uninit_map = vdata->uninit_map_;
+  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
   const uint16_t* insns = code_item->insns_ + insn_idx;
   uint32_t insns_size = code_item->insns_size_;
   uint32_t registers_size = code_item->registers_size_;
@@ -1437,7 +1434,7 @@
         reg_table->insn_reg_count_plus_);
   } else {
 #ifndef NDEBUG
-    memset(reg_table->saved_line_.reg_types_, 0xdd,
+    memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
         reg_table->insn_reg_count_plus_ * sizeof(RegType));
 #endif
   }
@@ -1681,7 +1678,7 @@
        * we skip them here); if we can't, then the code path could be
        * "live" so we still need to check it.
        */
-      if (work_line->monitor_entries_ != NULL)
+      if (work_line->monitor_entries_.get() != NULL)
         opcode_flag &= ~Instruction::kThrow;
       HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
       break;
@@ -3450,7 +3447,7 @@
     if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
       return false;
 
-    if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_ != NULL) {
+    if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
       /*
        * Merge registers into what we have for the next instruction,
        * and set the "changed" flag if needed.
@@ -3732,7 +3729,7 @@
     return;
   }
 
-  if (work_line->monitor_entries_ == NULL) {
+  if (work_line->monitor_entries_.get() == NULL) {
     return;
   }
 
@@ -3760,7 +3757,7 @@
     return;
   }
 
-  if (work_line->monitor_entries_ == NULL) {
+  if (work_line->monitor_entries_.get() == NULL) {
     return;
   }
 
@@ -3801,7 +3798,7 @@
     int field_idx, VerifyError* failure) {
   Method* method = vdata->method_;
   const DexFile* dex_file = vdata->dex_file_;
-  UninitInstanceMap* uninit_map = vdata->uninit_map_;
+  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
   const ClassLoader* class_loader =
@@ -4013,7 +4010,7 @@
 
 void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
     RegType new_type) {
-  RegType* insn_regs = register_line->reg_types_;
+  RegType* insn_regs = register_line->reg_types_.get();
 
   switch (new_type) {
     case kRegTypeUnknown:
@@ -4077,13 +4074,13 @@
   /*
    * Clear the monitor entry bits for this register.
    */
-  if (register_line->monitor_entries_ != NULL)
+  if (register_line->monitor_entries_.get() != NULL)
     register_line->monitor_entries_[vdst] = 0;
 }
 
 void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
     RegType check_type, VerifyError* failure) {
-  const RegType* insn_regs = register_line->reg_types_;
+  const RegType* insn_regs = register_line->reg_types_.get();
   RegType src_type = insn_regs[vsrc];
 
   switch (check_type) {
@@ -4189,7 +4186,7 @@
 void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
     int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
     VerifyError* failure) {
-  RegType* insn_regs = register_line->reg_types_;
+  RegType* insn_regs = register_line->reg_types_.get();
   Class* klass = GetUninitInstance(uninit_map,
       RegTypeToUninitIndex(uninit_type));
 
@@ -4216,12 +4213,12 @@
 
 void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
     int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
-  RegType* insn_regs = register_line->reg_types_;
+  RegType* insn_regs = register_line->reg_types_.get();
 
   for (int i = 0; i < insn_reg_count; i++) {
     if (insn_regs[i] == uninit_type) {
       insn_regs[i] = kRegTypeConflict;
-      if (register_line->monitor_entries_ != NULL)
+      if (register_line->monitor_entries_.get() != NULL)
         register_line->monitor_entries_[i] = 0;
     }
   }
@@ -4237,7 +4234,7 @@
                << " cat=" << (int) cat;
   } else {
     SetRegisterType(register_line, vdst, type);
-    if (cat == kTypeCategoryRef && register_line->monitor_entries_ != NULL) {
+    if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
       register_line->monitor_entries_[vdst] =
           register_line->monitor_entries_[vsrc];
     }
@@ -4489,7 +4486,7 @@
     RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
   const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
   assert(work_line != NULL);
-  const RegType* work_regs = work_line->reg_types_;
+  const RegType* work_regs = work_line->reg_types_.get();
 
   if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
     /*
@@ -4504,9 +4501,9 @@
   } else {
     /* Merge registers, set Changed only if different */
     RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
-    RegType* target_regs = target_line->reg_types_;
-    MonitorEntries* work_mon_ents = work_line->monitor_entries_;
-    MonitorEntries* target_mon_ents = target_line->monitor_entries_;
+    RegType* target_regs = target_line->reg_types_.get();
+    MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
+    MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
     bool changed = false;
     unsigned int idx;
 
@@ -4520,7 +4517,7 @@
                    << std::hex << next_insn << std::dec;
         return false;
       }
-      if (memcmp(target_line->monitor_stack_, work_line->monitor_stack_,
+      if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
                  target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
          LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
                     << next_insn << std::dec;
@@ -4667,7 +4664,7 @@
 
 bool DexVerifier::CheckConstructorReturn(const Method* method,
     const RegisterLine* register_line, const int insn_reg_count) {
-  const RegType* insn_regs = register_line->reg_types_;
+  const RegType* insn_regs = register_line->reg_types_.get();
 
   if (!IsInitMethod(method))
     return true;
@@ -4955,7 +4952,7 @@
   Method* method = vdata->method_;
   const DexFile* dex_file = vdata->dex_file_;
   const DexFile::CodeItem* code_item = vdata->code_item_;
-  UninitInstanceMap* uninit_map = vdata->uninit_map_;
+  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
   const ClassLoader* class_loader =
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index b6fbd46..c89dfaf 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -7,6 +7,7 @@
 #include "dex_instruction.h"
 #include "macros.h"
 #include "object.h"
+#include "UniquePtr.h"
 
 namespace art {
 
@@ -235,32 +236,21 @@
    * to the GC).
    */
   struct RegisterLine {
-    RegType*        reg_types_;
-    MonitorEntries* monitor_entries_;
-    uint32_t*       monitor_stack_;
-    uint32_t        monitor_stack_top_;
+    UniquePtr<RegType[]> reg_types_;
+    UniquePtr<MonitorEntries[]> monitor_entries_;
+    UniquePtr<uint32_t[]> monitor_stack_;
+    uint32_t monitor_stack_top_;
 
-    /* Default constructor. */
-    RegisterLine() {
-      reg_types_ = NULL;
-      monitor_entries_ = NULL;
-      monitor_stack_ = NULL;
-      monitor_stack_top_ = 0;
-    }
-
-    /* Default destructor. */
-    ~RegisterLine() {
-      delete reg_types_;
-      delete monitor_entries_;
-      delete monitor_stack_;
+    RegisterLine()
+        : reg_types_(NULL), monitor_entries_(NULL), monitor_stack_(NULL), monitor_stack_top_(0) {
     }
 
     /* Allocate space for the fields. */
     void Alloc(size_t size, bool track_monitors) {
-      reg_types_ = new RegType[size]();
+      reg_types_.reset(new RegType[size]());
       if (track_monitors) {
-        monitor_entries_ = new MonitorEntries[size];
-        monitor_stack_ = new uint32_t[kMaxMonitorStackDepth];
+        monitor_entries_.reset(new MonitorEntries[size]);
+        monitor_stack_.reset(new uint32_t[kMaxMonitorStackDepth]);
       }
     }
   };
@@ -272,7 +262,7 @@
      * set the pointers for certain addresses, based on instruction widths
      * and what we're trying to accomplish.
      */
-    RegisterLine* register_lines_;
+    UniquePtr<RegisterLine[]> register_lines_;
 
     /*
      * Number of registers we track for each instruction.  This is equal
@@ -286,15 +276,7 @@
     /* Storage for a register line we're saving for later. */
     RegisterLine saved_line_;
 
-    /* Default constructor. */
-    RegisterTable() {
-      register_lines_ = NULL;
-      insn_reg_count_plus_ = 0;
-    }
-
-    /* Default destructor. */
-    ~RegisterTable() {
-      delete [] register_lines_;
+    RegisterTable() : register_lines_(NULL), insn_reg_count_plus_(0) {
     }
   };
 
@@ -313,17 +295,11 @@
    */
   struct UninitInstanceMap {
     int num_entries_;
-    UninitInstanceMapEntry* map_;
+    UniquePtr<UninitInstanceMapEntry[]> map_;
 
-    /* Basic constructor */
-    UninitInstanceMap(int num_entries) {
-      num_entries_ = num_entries;
-      map_ = new UninitInstanceMapEntry[num_entries]();
-    }
-
-    /* Default destructor */
-    ~UninitInstanceMap() {
-      delete map_;
+    UninitInstanceMap(int num_entries)
+        : num_entries_(num_entries),
+          map_(new UninitInstanceMapEntry[num_entries]()) {
     }
   };
   #define kUninitThisArgAddr  (-1)
@@ -341,13 +317,13 @@
     const DexFile::CodeItem* code_item_;
 
     /* Instruction widths and flags, one entry per code unit. */
-    InsnFlags* insn_flags_;
+    UniquePtr<InsnFlags[]> insn_flags_;
 
     /*
      * Uninitialized instance map, used for tracking the movement of
      * objects that have been allocated but not initialized.
      */
-    UninitInstanceMap* uninit_map_;
+    UniquePtr<UninitInstanceMap> uninit_map_;
 
     /*
      * Array of RegisterLine structs, one entry per code unit.  We only need
@@ -361,7 +337,6 @@
     size_t new_instance_count_;
     size_t monitor_enter_count_;
 
-    /* Basic constructor. */
     VerifierData(Method* method, const DexFile* dex_file,
         const DexFile::CodeItem* code_item)
         : method_(method), dex_file_(dex_file), code_item_(code_item),
@@ -461,9 +436,9 @@
   }
 
   /* Get the class object at the specified index. */
-  static inline Class* GetUninitInstance(const UninitInstanceMap* uninit_map,
-      int idx) {
-    assert(idx >= 0 && idx < uninit_map->num_entries_);
+  static inline Class* GetUninitInstance(const UninitInstanceMap* uninit_map, int idx) {
+    DCHECK_GE(idx, 0);
+    DCHECK_LT(idx, uninit_map->num_entries_);
     return uninit_map->map_[idx].klass_;
   }
 
@@ -483,7 +458,7 @@
    * (does not expect uninit ref types or "zero").
    */
   static Class* RegTypeInitializedReferenceToClass(RegType type) {
-    assert(RegTypeIsReference(type) && type != kRegTypeZero);
+    DCHECK(RegTypeIsReference(type) && type != kRegTypeZero);
     if ((type & 0x01) == 0) {
       return (Class*) type;
     } else {
@@ -494,16 +469,16 @@
 
   /* Extract the index into the uninitialized instance map table. */
   static inline int RegTypeToUninitIndex(RegType type) {
-    assert(RegTypeIsUninitReference(type));
+    DCHECK(RegTypeIsUninitReference(type));
     return (type & ~kRegTypeUninitMask) >> kRegTypeUninitShift;
   }
 
   /* Convert the reference "type" to a Class pointer. */
   static Class* RegTypeReferenceToClass(RegType type,
       const UninitInstanceMap* uninit_map) {
-    assert(RegTypeIsReference(type) && type != kRegTypeZero);
+    DCHECK(RegTypeIsReference(type) && type != kRegTypeZero);
     if (RegTypeIsUninitReference(type)) {
-      assert(uninit_map != NULL);
+      DCHECK(uninit_map != NULL);
       return GetUninitInstance(uninit_map, RegTypeToUninitIndex(type));
     } else {
         return (Class*) type;
@@ -755,15 +730,15 @@
   /* Copy a register line. */
   static inline void CopyRegisterLine(RegisterLine* dst,
       const RegisterLine* src, size_t num_regs) {
-    memcpy(dst->reg_types_, src->reg_types_, num_regs * sizeof(RegType));
+    memcpy(dst->reg_types_.get(), src->reg_types_.get(), num_regs * sizeof(RegType));
 
-    assert((src->monitor_entries_ == NULL && dst->monitor_entries_ == NULL) ||
-           (src->monitor_entries_ != NULL && dst->monitor_entries_ != NULL));
-    if (dst->monitor_entries_ != NULL) {
-      assert(dst->monitor_stack_ != NULL);
-      memcpy(dst->monitor_entries_, src->monitor_entries_,
+    DCHECK((src->monitor_entries_.get() == NULL && dst->monitor_entries_.get() == NULL) ||
+        (src->monitor_entries_.get() != NULL && dst->monitor_entries_.get() != NULL));
+    if (dst->monitor_entries_.get() != NULL) {
+      DCHECK(dst->monitor_stack_.get() != NULL);
+      memcpy(dst->monitor_entries_.get(), src->monitor_entries_.get(),
           num_regs * sizeof(MonitorEntries));
-      memcpy(dst->monitor_stack_, src->monitor_stack_,
+      memcpy(dst->monitor_stack_.get(), src->monitor_stack_.get(),
           kMaxMonitorStackDepth * sizeof(uint32_t));
       dst->monitor_stack_top_ = src->monitor_stack_top_;
     }
@@ -773,7 +748,7 @@
   static inline void CopyLineToTable(RegisterTable* reg_table, int insn_idx,
       const RegisterLine* src) {
     RegisterLine* dst = GetRegisterLine(reg_table, insn_idx);
-    assert(dst->reg_types_ != NULL);
+    DCHECK(dst->reg_types_.get() != NULL);
     CopyRegisterLine(dst, src, reg_table->insn_reg_count_plus_);
   }
 
@@ -781,7 +756,7 @@
   static inline void CopyLineFromTable(RegisterLine* dst,
       const RegisterTable* reg_table, int insn_idx) {
     RegisterLine* src = GetRegisterLine(reg_table, insn_idx);
-    assert(src->reg_types_ != NULL);
+    DCHECK(src->reg_types_.get() != NULL);
     CopyRegisterLine(dst, src, reg_table->insn_reg_count_plus_);
   }
 
@@ -795,12 +770,12 @@
   static inline int CompareLineToTable(const RegisterTable* reg_table,
       int insn_idx, const RegisterLine* line2) {
     const RegisterLine* line1 = GetRegisterLine(reg_table, insn_idx);
-    if (line1->monitor_entries_ != NULL) {
+    if (line1->monitor_entries_.get() != NULL) {
       int result;
 
-      if (line2->monitor_entries_ == NULL)
+      if (line2->monitor_entries_.get() == NULL)
         return 1;
-      result = memcmp(line1->monitor_entries_, line2->monitor_entries_,
+      result = memcmp(line1->monitor_entries_.get(), line2->monitor_entries_.get(),
           reg_table->insn_reg_count_plus_ * sizeof(MonitorEntries));
       if (result != 0) {
         LOG(ERROR) << "monitor_entries_ mismatch";
@@ -811,14 +786,14 @@
         LOG(ERROR) << "monitor_stack_top_ mismatch";
         return result;
       }
-      result = memcmp(line1->monitor_stack_, line2->monitor_stack_,
+      result = memcmp(line1->monitor_stack_.get(), line2->monitor_stack_.get(),
             line1->monitor_stack_top_);
       if (result != 0) {
         LOG(ERROR) << "monitor_stack_ mismatch";
         return result;
       }
     }
-    return memcmp(line1->reg_types_, line2->reg_types_,
+    return memcmp(line1->reg_types_.get(), line2->reg_types_.get(),
         reg_table->insn_reg_count_plus_ * sizeof(RegType));
   }
 #endif
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 8e24e47..2ea6f76 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -442,7 +442,8 @@
   CHECK_GE(args.version, JNI_VERSION_1_2);
 
   Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->runtime;
-  runtime->AttachCurrentThread(args.name, p_env, as_daemon);
+  runtime->AttachCurrentThread(args.name, as_daemon);
+  *p_env = Thread::Current()->GetJniEnv();
   return JNI_OK;
 }
 
@@ -618,11 +619,17 @@
 
   static jclass FindClass(JNIEnv* env, const char* name) {
     ScopedJniThreadState ts(env);
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    Runtime* runtime = Runtime::Current();
+    ClassLinker* class_linker = runtime->GetClassLinker();
     std::string descriptor(NormalizeJniClassDescriptor(name));
-    // TODO: need to get the appropriate ClassLoader.
-    const ClassLoader* cl = ts.Self()->GetClassLoaderOverride();
-    Class* c = class_linker->FindClass(descriptor, cl);
+    Class* c = NULL;
+    if (runtime->IsStarted()) {
+      // TODO: need to get the appropriate ClassLoader.
+      const ClassLoader* cl = ts.Self()->GetClassLoaderOverride();
+      c = class_linker->FindClass(descriptor, cl);
+    } else {
+      c = class_linker->FindSystemClass(descriptor);
+    }
     return AddLocalReference<jclass>(env, c);
   }
 
diff --git a/src/logging.cc b/src/logging.cc
index c59a099..03788c3 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -17,26 +17,43 @@
 #include "logging.h"
 
 #include "runtime.h"
+#include "thread.h"
 #include "utils.h"
 
+namespace {
+
+art::Mutex* GetLoggingLock() {
+  static art::Mutex* lock = art::Mutex::Create("LogMessage lock");
+  return lock;
+}
+
+}
+
 LogMessage::~LogMessage() {
+  // Finish constructing the message.
   if (errno_ != -1) {
     buffer_ << ": " << strerror(errno_);
   }
   std::string msg(buffer_.str());
-  if (msg.find('\n') == std::string::npos) {
-    LogLine(msg.c_str());
-  } else {
-    msg += '\n';
-    size_t i = 0;
-    while (i < msg.size()) {
-      size_t nl = msg.find('\n', i);
-      msg[nl] = '\0';
-      LogLine(&msg[i]);
-      i = nl + 1;
+
+  // Do the actual logging with the lock held.
+  {
+    art::MutexLock mu(GetLoggingLock());
+    if (msg.find('\n') == std::string::npos) {
+      LogLine(msg.c_str());
+    } else {
+      msg += '\n';
+      size_t i = 0;
+      while (i < msg.size()) {
+        size_t nl = msg.find('\n', i);
+        msg[nl] = '\0';
+        LogLine(&msg[i]);
+        i = nl + 1;
+      }
     }
   }
 
+  // Abort if necessary.
   if (severity_ == FATAL) {
     art::Runtime::Abort(file_, line_number_);
   }
diff --git a/src/object.cc b/src/object.cc
index d7b6024..7c27ec7 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -196,7 +196,7 @@
 }
 
 void Field::SetInt(Object* object, int32_t i) const {
-  DCHECK(GetType()->IsPrimitiveInt());
+  DCHECK(GetType()->IsPrimitiveInt()) << PrettyField(this);
   Set32(object, i);
 }
 
@@ -273,7 +273,7 @@
 }
 
 Class* Method::GetReturnType() const {
-  DCHECK(GetDeclaringClass()->IsLinked());
+  DCHECK(GetDeclaringClass()->IsResolved());
   // Short-cut
   Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx());
   if (result == NULL) {
diff --git a/src/object.h b/src/object.h
index c0e725c..23ce3c4 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1275,7 +1275,7 @@
   }
 
   // Returns true if the class has been linked.
-  bool IsLinked() const {
+  bool IsResolved() const {
     return GetStatus() >= kStatusResolved;
   }
 
@@ -1630,7 +1630,7 @@
   }
 
   Method* GetVirtualMethod(uint32_t i) const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     return GetVirtualMethods()->Get(i);
   }
 
@@ -1647,7 +1647,7 @@
   }
 
   ObjectArray<Method>* GetVTable() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     return GetFieldObject<ObjectArray<Method>*>(
         OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
   }
@@ -1745,7 +1745,7 @@
   }
 
   size_t GetIFTableCount() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     DCHECK(sizeof(size_t) == sizeof(int32_t));
     return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, iftable_count_), false);
   }
@@ -1757,7 +1757,7 @@
   }
 
   InterfaceEntry* GetIFTable() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     return GetFieldPtr<InterfaceEntry*>(
         OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
   }
@@ -1768,7 +1768,7 @@
   }
 
   size_t GetIfviPoolCount() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     CHECK(sizeof(size_t) == sizeof(int32_t));
     return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_count_), false);
   }
@@ -1780,7 +1780,7 @@
   }
 
   uint32_t* GetIfviPool() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     return GetFieldPtr<uint32_t*>(
         OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_), false);
   }
@@ -1820,7 +1820,7 @@
 
   // Returns the number of instance fields containing reference types.
   size_t NumReferenceInstanceFields() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     DCHECK(sizeof(size_t) == sizeof(int32_t));
     return GetField32(
         OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
@@ -1840,7 +1840,7 @@
   }
 
   uint32_t GetReferenceInstanceOffsets() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     return GetField32(
         OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
   }
@@ -1854,7 +1854,7 @@
 
   // Returns the number of static fields containing reference types.
   size_t NumReferenceStaticFields() const {
-    DCHECK(IsLinked());
+    DCHECK(IsResolved());
     DCHECK(sizeof(size_t) == sizeof(int32_t));
     return GetField32(
         OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
@@ -2208,7 +2208,7 @@
 }
 
 inline uint32_t Method::GetReturnTypeIdx() const {
-  DCHECK(GetDeclaringClass()->IsLinked());
+  DCHECK(GetDeclaringClass()->IsResolved());
   return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
                     false);
 }
@@ -2527,7 +2527,7 @@
 }
 
 inline MemberOffset Field::GetOffset() const {
-  DCHECK(GetDeclaringClass()->IsLinked());
+  DCHECK(GetDeclaringClass()->IsResolved());
   return MemberOffset(
       GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
 }
@@ -2595,7 +2595,7 @@
 }
 
 inline uint16_t Method::GetMethodIndex() const {
-  DCHECK(GetDeclaringClass()->IsLinked());
+  DCHECK(GetDeclaringClass()->IsResolved());
   return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false);
 }
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 2acf2ec..c7ae9c1 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -36,10 +36,11 @@
 }
 
 Runtime::~Runtime() {
-  // TODO: use smart pointers instead. (we'll need the pimpl idiom.)
+  // Make sure our internal threads are dead before we start tearing down things they're using.
+  delete signal_catcher_;
+
   delete class_linker_;
   Heap::Destroy();
-  delete signal_catcher_;
   delete thread_list_;
   delete intern_table_;
   delete java_vm_;
@@ -336,6 +337,11 @@
 
 void Runtime::Start() {
   started_ = true;
+
+  // Finish attaching the main thread.
+  Thread* main_thread = Thread::Current();
+  main_thread->CreatePeer("main", false);
+
   instance_->InitLibraries();
   instance_->signal_catcher_ = new SignalCatcher;
 }
@@ -378,7 +384,9 @@
     return false;
   }
 
-  thread_list_->Register(Thread::Attach(this, "main", false));
+  // ClassLinker needs an attached thread, but we can't fully attach a thread
+  // without creating objects.
+  Thread::Attach(this, "main", false);
 
   class_linker_ = ClassLinker::Create(options->boot_class_path_,
                                       options->class_path_,
@@ -466,9 +474,8 @@
   CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0);
 }
 
-void Runtime::AttachCurrentThread(const char* name, JNIEnv** penv, bool as_daemon) {
-  Thread* t = Thread::Attach(instance_, name, as_daemon);
-  thread_list_->Register(t);
+void Runtime::AttachCurrentThread(const char* name, bool as_daemon) {
+  Thread::Attach(instance_, name, as_daemon);
 }
 
 void Runtime::DetachCurrentThread() {
diff --git a/src/runtime.h b/src/runtime.h
index db86a96..96513e6 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -85,7 +85,7 @@
   static void Abort(const char* file, int line);
 
   // Attaches the current native thread to the runtime.
-  void AttachCurrentThread(const char* name, JNIEnv** jni_env, bool as_daemon);
+  void AttachCurrentThread(const char* name, bool as_daemon);
 
   void CallExitHook(jint status);
 
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index e2e2360..1552180 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -29,11 +29,12 @@
 
 namespace art {
 
-bool SignalCatcher::halt_ = false;
-
 SignalCatcher::SignalCatcher() {
+  lock_ = Mutex::Create("SignalCatcher lock");
+  SetHaltFlag(false);
+
   // Create a raw pthread; its start routine will attach to the runtime.
-  errno = pthread_create(&thread_, NULL, &Run, NULL);
+  errno = pthread_create(&thread_, NULL, &Run, this);
   if (errno != 0) {
     PLOG(FATAL) << "pthread_create failed for signal catcher thread";
   }
@@ -42,11 +43,21 @@
 SignalCatcher::~SignalCatcher() {
   // Since we know the thread is just sitting around waiting for signals
   // to arrive, send it one.
-  halt_ = true;
+  SetHaltFlag(true);
   pthread_kill(thread_, SIGQUIT);
   pthread_join(thread_, NULL);
 }
 
+void SignalCatcher::SetHaltFlag(bool new_value) {
+  MutexLock mu(lock_);
+  halt_ = new_value;
+}
+
+bool SignalCatcher::ShouldHalt() {
+  MutexLock mu(lock_);
+  return halt_;
+}
+
 void SignalCatcher::HandleSigQuit() {
   // TODO: suspend all threads
 
@@ -100,8 +111,11 @@
   return signal_number;
 }
 
-void* SignalCatcher::Run(void*) {
-  Runtime::Current()->AttachCurrentThread("Signal Catcher", NULL, true);
+void* SignalCatcher::Run(void* arg) {
+  SignalCatcher* signal_catcher = reinterpret_cast<SignalCatcher*>(arg);
+  CHECK(signal_catcher != NULL);
+
+  Runtime::Current()->AttachCurrentThread("Signal Catcher", true);
   Thread* self = Thread::Current();
   CHECK(self != NULL);
 
@@ -113,7 +127,7 @@
 
   while (true) {
     int signal_number = WaitForSignal(self, mask);
-    if (halt_) {
+    if (signal_catcher->ShouldHalt()) {
       Runtime::Current()->DetachCurrentThread();
       return NULL;
     }
diff --git a/src/signal_catcher.h b/src/signal_catcher.h
index a31b9f1..8d91a94 100644
--- a/src/signal_catcher.h
+++ b/src/signal_catcher.h
@@ -21,6 +21,7 @@
 
 namespace art {
 
+class Mutex;
 class Runtime;
 class Thread;
 
@@ -40,7 +41,11 @@
   static void* Run(void* arg);
   static void HandleSigUsr1();
 
-  static bool halt_;
+  void SetHaltFlag(bool new_value);
+  bool ShouldHalt();
+
+  Mutex* lock_;
+  bool halt_;
   pthread_t thread_;
 };
 
diff --git a/src/thread.cc b/src/thread.cc
index 7d909c9..3081d91 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -205,10 +205,26 @@
 }
 
 void Mutex::Unlock() {
-  DCHECK(HaveLock());
+#ifndef NDEBUG
+  Thread* self = Thread::Current();
+  std::stringstream os;
+  os << "owner=";
+  if (owner_ != NULL) {
+    os << *owner_;
+  } else {
+    os << "NULL";
+  }
+  os << " self=";
+  if (self != NULL) {
+    os << *self;
+  } else {
+    os << "NULL";
+  }
+  DCHECK(HaveLock()) << os.str();
+#endif
+  SetOwner(NULL);
   int result = pthread_mutex_unlock(&lock_impl_);
   CHECK_EQ(result, 0);
-  SetOwner(NULL);
 }
 
 bool Mutex::HaveLock() {
@@ -244,7 +260,6 @@
   size_t stack_size = runtime->GetStackSize();
 
   Thread* new_thread = new Thread;
-  new_thread->InitCpu();
 
   pthread_attr_t attr;
   errno = pthread_attr_init(&attr);
@@ -279,25 +294,52 @@
 }
 
 Thread* Thread::Attach(const Runtime* runtime, const char* name, bool as_daemon) {
-  Thread* thread = new Thread;
-  thread->InitCpu();
+  Thread* self = new Thread;
 
-  thread->tid_ = ::art::GetTid();
-  thread->handle_ = pthread_self();
-  thread->is_daemon_ = as_daemon;
+  self->tid_ = ::art::GetTid();
+  self->handle_ = pthread_self();
+  self->is_daemon_ = as_daemon;
 
-  thread->state_ = kRunnable;
+  self->state_ = kRunnable;
 
   SetThreadName(name);
 
-  errno = pthread_setspecific(Thread::pthread_key_self_, thread);
+  errno = pthread_setspecific(Thread::pthread_key_self_, self);
   if (errno != 0) {
     PLOG(FATAL) << "pthread_setspecific failed";
   }
 
-  thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM());
+  self->jni_env_ = new JNIEnvExt(self, runtime->GetJavaVM());
 
-  return thread;
+  runtime->GetThreadList()->Register(self);
+
+  // If we're the main thread, ClassLinker won't be created until after we're attached,
+  // so that thread needs a two-stage attach. Regular threads don't need this hack.
+  if (self->thin_lock_id_ != ThreadList::kMainId) {
+    self->CreatePeer(name, as_daemon);
+  }
+
+  return self;
+}
+
+void Thread::CreatePeer(const char* name, bool as_daemon) {
+  ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative);
+
+  JNIEnv* env = jni_env_;
+
+  jobject thread_group = NULL;
+  jobject thread_name = env->NewStringUTF(name);
+  jint thread_priority = 123;
+  jboolean thread_is_daemon = as_daemon;
+
+  jclass c = env->FindClass("java/lang/Thread");
+  LOG(INFO) << "java/lang/Thread=" << (void*)c;
+  jmethodID mid = env->GetMethodID(c, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
+  LOG(INFO) << "java/lang/Thread.<init>=" << (void*)mid;
+  jobject o = env->NewObject(c, mid, thread_group, thread_name, thread_priority, thread_is_daemon);
+  LOG(INFO) << "Created new java.lang.Thread " << (void*) o << " decoded=" << (void*) DecodeJObject(o);
+
+  peer_ = DecodeJObject(o);
 }
 
 void Thread::Dump(std::ostream& os) const {
@@ -494,6 +536,7 @@
       exception_(NULL),
       suspend_count_(0),
       class_loader_override_(NULL) {
+  InitCpu();
   {
     ThreadListLock mu;
     thin_lock_id_ = Runtime::Current()->GetThreadList()->AllocThreadId();
diff --git a/src/thread.h b/src/thread.h
index b255d6b..df162b9 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -448,6 +448,9 @@
   ~Thread();
   friend class ThreadList;  // For ~Thread.
 
+  void CreatePeer(const char* name, bool as_daemon);
+  friend class Runtime; // For CreatePeer.
+
   void DumpState(std::ostream& os) const;
   void DumpStack(std::ostream& os) const;
 
@@ -528,9 +531,9 @@
 
 class ThreadList {
  public:
-  static const int kMaxThreadId = 0xFFFF;
-  static const int kInvalidId = 0;
-  static const int kMainId = 1;
+  static const uint32_t kMaxThreadId = 0xFFFF;
+  static const uint32_t kInvalidId = 0;
+  static const uint32_t kMainId = 1;
 
   static ThreadList* Create();