Initialize runtime constituents on runtime construction.

Change-Id: I63fff272b64bd29a7f828dac48aed91833af1eee
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 5b50113..e2ab39a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -19,6 +19,13 @@
 
 namespace art {
 
+ClassLinker* ClassLinker::Create() {
+  scoped_ptr<ClassLinker> class_linker(new ClassLinker);
+  class_linker->Init();
+  // TODO: check for failure during initialization
+  return class_linker.release();
+}
+
 void ClassLinker::Init() {
   // Allocate and partially initialize the Object and Class classes.
   // Initialization will be completed when the definitions are loaded.
diff --git a/src/class_linker.h b/src/class_linker.h
index 3796dc2..00271a5 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -15,11 +15,10 @@
 
 class ClassLinker {
  public:
-  ClassLinker() {}
-  ~ClassLinker() {}
-
   // Initializes the class linker.
-  void Init();
+  static ClassLinker* Create();
+
+  ~ClassLinker() {}
 
   // Finds a class by its descriptor name.
   Class* FindClass(const char* descriptor,
@@ -49,6 +48,10 @@
   void AppendToClassPath(DexFile* dex_file);
 
  private:
+  ClassLinker() {}
+
+  void Init();
+
   Class* CreatePrimitiveClass(JType type, const char* descriptor);
 
   void LoadInterfaces(const RawDexFile::ClassDef& class_def, Class *klass);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 5cd8a6f..f44192a 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -12,14 +12,13 @@
   scoped_ptr<DexFile> dex(DexFile::OpenBase64(kMyClassDex));
   ASSERT_TRUE(dex != NULL);
 
-  ClassLinker linker;
-  linker.Init();
-  linker.AppendToClassPath(dex.get());
+  scoped_ptr<ClassLinker> linker(ClassLinker::Create());
+  linker->AppendToClassPath(dex.get());
 
   scoped_ptr<Class> klass(Heap::AllocClass(dex.get()));
-  bool result1 = linker.LoadClass("NoSuchClass", klass.get());
+  bool result1 = linker->LoadClass("NoSuchClass", klass.get());
   EXPECT_FALSE(result1);
-  bool result2 = linker.LoadClass("LNoSuchClass;", klass.get());
+  bool result2 = linker->LoadClass("LNoSuchClass;", klass.get());
   EXPECT_FALSE(result2);
 }
 
@@ -27,12 +26,11 @@
   scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex));
   ASSERT_TRUE(dex != NULL);
 
-  ClassLinker linker;
-  linker.Init();
-  linker.AppendToClassPath(dex.get());
+  scoped_ptr<ClassLinker> linker(ClassLinker::Create());
+  linker->AppendToClassPath(dex.get());
 
   scoped_ptr<Class> klass(Heap::AllocClass(dex.get()));
-  bool result = linker.LoadClass("LNested;", klass.get());
+  bool result = linker->LoadClass("LNested;", klass.get());
   ASSERT_TRUE(result);
 
   uint32_t vmeth = klass->NumVirtualMethods();
@@ -46,11 +44,10 @@
   scoped_ptr<DexFile> dex(DexFile::OpenBase64(kMyClassDex));
   ASSERT_TRUE(dex != NULL);
 
-  ClassLinker linker;
-  linker.Init();
-  linker.AppendToClassPath(dex.get());
+  scoped_ptr<ClassLinker> linker(ClassLinker::Create());
+  linker->AppendToClassPath(dex.get());
 
-  Class* JavaLangObject = linker.FindClass("Ljava/lang/Object;", NULL, dex.get());
+  Class* JavaLangObject = linker->FindClass("Ljava/lang/Object;", NULL, dex.get());
   ASSERT_TRUE(JavaLangObject != NULL);
   EXPECT_TRUE(JavaLangObject->GetClass() != NULL);
   ASSERT_TRUE(JavaLangObject->GetDescriptor() == "Ljava/lang/Object;");
@@ -70,7 +67,7 @@
   EXPECT_EQ((size_t) 0, JavaLangObject->NumInstanceFields());
   EXPECT_EQ((size_t) 0, JavaLangObject->NumStaticFields());
 
-  Class* MyClass = linker.FindClass("LMyClass;", NULL, dex.get());
+  Class* MyClass = linker->FindClass("LMyClass;", NULL, dex.get());
   ASSERT_TRUE(MyClass != NULL);
   EXPECT_TRUE(MyClass->GetClass() != NULL);
   ASSERT_TRUE(MyClass->GetDescriptor() == "LMyClass;");
diff --git a/src/heap.h b/src/heap.h
index 7b31ebc..7c679eb 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -11,6 +11,14 @@
 
 class Heap {
  public:
+  static Heap* Create() {
+    Heap* new_heap = new Heap();
+    // TODO: should return NULL if the heap could not be created.
+    return new_heap;
+  }
+
+  ~Heap() {}
+
   static Class* AllocClass(DexFile* dex_file) {
     byte* raw = new byte[sizeof(Class)]();
     Class* klass = reinterpret_cast<Class*>(raw);
@@ -38,6 +46,11 @@
     string->count_ = count;
     return string;
   }
+
+ private:
+  Heap() {}
+
+  DISALLOW_COPY_AND_ASSIGN(Heap);
 };
 
 }  // namespace art
diff --git a/src/object_test.cc b/src/object_test.cc
index 49dda32..c49c4fd 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -33,12 +33,11 @@
   scoped_ptr<DexFile> dex_file(DexFile::OpenBase64(kProtoCompareDex));
   ASSERT_TRUE(dex_file != NULL);
 
-  ClassLinker linker;
-  linker.Init();
-  linker.AppendToClassPath(dex_file.get());
+  scoped_ptr<ClassLinker> linker(ClassLinker::Create());
+  linker->AppendToClassPath(dex_file.get());
 
   scoped_ptr<Class> klass(Heap::AllocClass(dex_file.get()));
-  bool result = linker.LoadClass("LProtoCompare;", klass.get());
+  bool result = linker->LoadClass("LProtoCompare;", klass.get());
   ASSERT_TRUE(result);
 
   ASSERT_EQ(4U, klass->NumVirtualMethods());
@@ -91,18 +90,16 @@
   ASSERT_TRUE(dex_file1 != NULL);
   scoped_ptr<DexFile> dex_file2(DexFile::OpenBase64(kProtoCompare2Dex));
   ASSERT_TRUE(dex_file2 != NULL);
-  ClassLinker linker1;
-  linker1.Init();
-  linker1.AppendToClassPath(dex_file1.get());
-  ClassLinker linker2;
-  linker2.Init();
-  linker2.AppendToClassPath(dex_file2.get());
+  scoped_ptr<ClassLinker> linker1(ClassLinker::Create());
+  linker1->AppendToClassPath(dex_file1.get());
+  scoped_ptr<ClassLinker> linker2(ClassLinker::Create());
+  linker2->AppendToClassPath(dex_file2.get());
 
   scoped_ptr<Class> klass1(Heap::AllocClass(dex_file1.get()));
-  bool result1 = linker1.LoadClass("LProtoCompare;", klass1.get());
+  bool result1 = linker1->LoadClass("LProtoCompare;", klass1.get());
   ASSERT_TRUE(result1);
   scoped_ptr<Class> klass2(Heap::AllocClass(dex_file2.get()));
-  bool result2 = linker2.LoadClass("LProtoCompare2;", klass2.get());
+  bool result2 = linker2->LoadClass("LProtoCompare2;", klass2.get());
   ASSERT_TRUE(result2);
 
   Method* m1_1 = klass1->GetVirtualMethod(0);
diff --git a/src/runtime.cc b/src/runtime.cc
index f627a46..e1ad32d 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2,13 +2,47 @@
 
 #include "src/runtime.h"
 
+#include "src/class_linker.h"
+#include "src/heap.h"
+#include "src/thread.h"
+
 namespace art {
 
-bool Runtime::Startup() {
+Runtime::~Runtime() {
+  // TODO: use a smart pointer instead.
+  delete class_linker_;
+  delete heap_;
+  delete thread_list_;
+}
+
+Runtime* Runtime::Create() {
+  scoped_ptr<Runtime> runtime(new Runtime());
+  bool success = runtime->Init();
+  if (!success) {
+    return NULL;
+  } else {
+    return runtime.release();
+  }
+}
+
+bool Runtime::Init() {
+  thread_list_ = ThreadList::Create();
+  heap_ = Heap::Create();
+  Thread::Init();
+  Thread* current_thread = Thread::Attach();
+  thread_list_->Register(current_thread);
+  class_linker_ = ClassLinker::Create();
   return true;
 }
 
-void Runtime::Shutdown() {
+bool AttachCurrentThread() {
+  LOG(FATAL) << "Unimplemented";
+  return false;
+}
+
+bool DetachCurrentThread() {
+  LOG(FATAL) << "Unimplemented";
+  return false;
 }
 
 }  // namespace art
diff --git a/src/runtime.h b/src/runtime.h
index 495ab1c..76f7676 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -3,23 +3,45 @@
 #ifndef ART_SRC_RUNTIME_H_
 #define ART_SRC_RUNTIME_H_
 
-#include "src/thread.h"
+#include "src/globals.h"
+#include "src/macros.h"
+#include "src/stringpiece.h"
 
 namespace art {
 
+class ClassLinker;
+class Heap;
+class ThreadList;
+
 class Runtime {
  public:
-  static bool Startup();
-  static void Shutdown();
+  // Creates and initializes a new runtime.
+  static Runtime* Create();
 
-  static void Compile(const char* filename);
+  // Compiles a dex file.
+  static void Compile(const StringPiece& filename);
 
-  void SetThreadList(ThreadList* thread_list) {
-    thread_list_ = thread_list;
-  }
+  // Attaches the current native thread to the runtime.
+  bool AttachCurrentThread();
+
+  // Detaches the current native thread from the runtime.
+  bool DetachCurrentThread();
+
+  ~Runtime();
 
  private:
+  Runtime() : class_linker_(NULL), heap_(NULL), thread_list_(NULL) {}
+
+  // Initializes a new uninitialized runtime.
+  bool Init();
+
+  ClassLinker* class_linker_;
+
+  Heap* heap_;
+
   ThreadList* thread_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(Runtime);
 };
 
 }  // namespace art
diff --git a/src/thread.cc b/src/thread.cc
index abd45db..9320fcf 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -6,8 +6,10 @@
 #include <list>
 #include <errno.h>
 #include <pthread.h>
+#include <sys/mman.h>
 
 #include "src/runtime.h"
+#include "src/utils.h"
 
 namespace art {
 
@@ -44,11 +46,60 @@
   SetOwner(Thread::Current());
 }
 
-Thread* Thread::Create(const char* name) {
+void* ThreadStart(void *arg) {
   LOG(FATAL) << "Unimplemented";
   return NULL;
 }
 
+Thread* Thread::Create(size_t stack_size) {
+  int prot = PROT_READ | PROT_WRITE;
+  // TODO: require the stack size to be page aligned?
+  size_t length = RoundUp(stack_size, 0x1000);
+  void* stack_limit = mmap(NULL, length, prot, MAP_PRIVATE, -1, 0);
+  if (stack_limit == MAP_FAILED) {
+    LOG(FATAL) << "mmap";
+    return false;
+  }
+
+  Thread* new_thread = new Thread;
+  new_thread->stack_limit_ = static_cast<byte*>(stack_limit);
+  new_thread->stack_base_ = new_thread->stack_limit_ + length;
+
+  pthread_attr_t attr;
+  int result = pthread_attr_init(&attr);
+  CHECK_EQ(result, 0);
+
+  result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  CHECK_EQ(result, 0);
+
+  pthread_t handle;
+  result = pthread_create(&handle, &attr, ThreadStart, new_thread);
+  CHECK_EQ(result, 0);
+
+  result = pthread_attr_destroy(&attr);
+  CHECK_EQ(result, 0);
+
+  return new_thread;
+}
+
+Thread* Thread::Attach() {
+  Thread* thread = new Thread;
+
+  thread->stack_limit_ = reinterpret_cast<byte*>(-1);  // TODO: getrlimit
+  uintptr_t addr = reinterpret_cast<uintptr_t>(&thread);  // TODO: ask pthreads
+  uintptr_t stack_base = RoundUp(addr, 4096);
+  thread->stack_base_ = reinterpret_cast<byte*>(stack_base);
+  // TODO: set the stack size
+
+  thread->handle_ = pthread_self();
+
+  thread->state_ = kRunnable;
+
+  int result = pthread_setspecific(Thread::pthread_key_self_, thread);
+  CHECK_EQ(result, 0);
+  return thread;
+}
+
 static void ThreadExitCheck(void* arg) {
   LG << "Thread exit check";
 }
@@ -71,6 +122,10 @@
   return true;
 }
 
+ThreadList* ThreadList::Create() {
+  return new ThreadList;
+}
+
 ThreadList::ThreadList() {
   lock_ = Mutex::Create("ThreadList::Lock");
 }
@@ -96,9 +151,4 @@
   list_.remove(thread);
 }
 
-void ThreadList::Init(Runtime* runtime) {
-  ThreadList* thread_list = new ThreadList();
-  runtime->SetThreadList(thread_list);
-}
-
 }  // namespace
diff --git a/src/thread.h b/src/thread.h
index 6cc2135..55c1b11 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -10,9 +10,11 @@
 #include "src/globals.h"
 #include "src/logging.h"
 #include "src/macros.h"
+#include "src/runtime.h"
 
 namespace art {
 
+class Heap;
 class Object;
 class Runtime;
 class Thread;
@@ -72,7 +74,13 @@
     kTerminated,
   };
 
-  static Thread* Create(const char* name);
+  static const size_t kDefaultStackSize = 64 * KB;
+
+  // Creates a new thread.
+  static Thread* Create(size_t stack_size);
+
+  // Creates a new thread from the calling thread.
+  static Thread* Attach();
 
   static Thread* Current() {
     static Thread self;
@@ -115,10 +123,6 @@
 
   static bool Init();
 
-  Thread* next_;
-
-  Thread* prev_;
-
   State GetState() {
     return state_;
   }
@@ -137,10 +141,13 @@
 
   pid_t native_id_;
 
-  pthread_t native_handle_;
+  pthread_t handle_;
 
   Object* exception_;
 
+  byte* stack_base_;
+  byte* stack_limit_;
+
   static pthread_key_t pthread_key_self_;
 
   DISALLOW_COPY_AND_ASSIGN(Thread);
@@ -148,21 +155,18 @@
 
 class ThreadList {
  public:
-  static const int kMaxThreadId = 0xFFFF;
-  static const int kMainThreadId = 1;
+  static const int kMaxId = 0xFFFF;
+  static const int kInvalidId = 0;
+  static const int kMainId = 1;
 
-  void Init(Runtime* runtime);
+  static ThreadList* Create();
+
+  ~ThreadList();
 
   void Register(Thread* thread);
 
   void Unregister(Thread* thread);
 
-  void SuspendAll();
-
-  void ResumeAll();
-
-  ~ThreadList();
-
   void Lock() {
     lock_->Lock();
   }
@@ -206,11 +210,6 @@
     thread_list_->Unlock();
   }
 
-  // Allocates
-  int AllocThreadId();
-
-  void FreeThreadId(int thread_id);
-
  private:
   ThreadList* thread_list_;
 
diff --git a/src/utils.h b/src/utils.h
index bf8896d..cbf0cff 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -59,6 +59,17 @@
   return static_cast<int32_t>(value >> 32);
 }
 
+template<typename T>
+static inline T RoundDown(T x, int n) {
+  CHECK(IsPowerOfTwo(n));
+  return (x & -n);
+}
+
+template<typename T>
+static inline T RoundUp(T x, int n) {
+  return RoundDown(x + n - 1, n);
+}
+
 // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
 // figure 3-3, page 48, where the function is called clp2.
 static inline uint32_t RoundUpToPowerOfTwo(uint32_t x) {