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) {