blob: 5857c3aa1231805d306f09d77a057e7defcb2bd6 [file] [log] [blame]
Carl Shapiro1fb86202011-06-27 17:43:13 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "runtime.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -07004
Elliott Hughesffe67362011-07-17 12:09:27 -07005#include <cstdio>
6#include <cstdlib>
Carl Shapiro2ed144c2011-07-26 16:52:08 -07007#include <vector>
Elliott Hughesffe67362011-07-17 12:09:27 -07008
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07009#include "class_linker.h"
10#include "heap.h"
Carl Shapirofc322c72011-07-27 00:20:01 -070011#include "scoped_ptr.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070012#include "thread.h"
Carl Shapiro61e019d2011-07-14 16:53:09 -070013
Carl Shapiro1fb86202011-06-27 17:43:13 -070014namespace art {
15
Carl Shapiro2ed144c2011-07-26 16:52:08 -070016Runtime* Runtime::instance_ = NULL;
17
Carl Shapiro61e019d2011-07-14 16:53:09 -070018Runtime::~Runtime() {
19 // TODO: use a smart pointer instead.
20 delete class_linker_;
Carl Shapiro69759ea2011-07-21 18:13:35 -070021 Heap::Destroy();
Carl Shapiro61e019d2011-07-14 16:53:09 -070022 delete thread_list_;
Carl Shapiro4acf4642011-07-26 18:54:13 -070023 // TODO: acquire a static mutex on Runtime to avoid racing.
24 CHECK(instance_ == this);
25 instance_ = NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -070026}
27
Elliott Hughesffe67362011-07-17 12:09:27 -070028void Runtime::Abort(const char* file, int line) {
29 // Get any pending output out of the way.
30 fflush(NULL);
31
32 // Many people have difficulty distinguish aborts from crashes,
33 // so be explicit.
34 LogMessage(file, line, ERROR, -1).stream() << "Runtime aborting...";
35
36 // TODO: if we support an abort hook, call it here.
37
38 // Perform any platform-specific pre-abort actions.
39 PlatformAbort(file, line);
40
41 // If we call abort(3) on a device, all threads in the process
Carl Shapiro69759ea2011-07-21 18:13:35 -070042 // receive SIGABRT. debuggerd dumps the stack trace of the main
43 // thread, whether or not that was the thread that failed. By
44 // stuffing a value into a bogus address, we cause a segmentation
Elliott Hughesffe67362011-07-17 12:09:27 -070045 // fault in the current thread, and get a useful log from debuggerd.
46 // We can also trivially tell the difference between a VM crash and
47 // a deliberate abort by looking at the fault address.
48 *reinterpret_cast<char*>(0xdeadd00d) = 38;
49 abort();
50
51 // notreached
52}
53
Carl Shapirod3c15752011-07-27 16:27:22 -070054// Splits a colon delimited list of pathname elements into a vector of
55// strings. Empty strings will be omitted.
Carl Shapirofc322c72011-07-27 00:20:01 -070056void ParseClassPath(const char* class_path, std::vector<std::string>* vec) {
57 CHECK(vec != NULL);
58 scoped_ptr_malloc<char> tmp(strdup(class_path));
59 char* full = tmp.get();
60 char* p = full;
Carl Shapirod3c15752011-07-27 16:27:22 -070061 while (p != NULL) {
Carl Shapirofc322c72011-07-27 00:20:01 -070062 p = strpbrk(full, ":");
63 if (p != NULL) {
64 p[0] = '\0';
65 }
66 if (full[0] != '\0') {
67 vec->push_back(std::string(full));
68 }
Carl Shapirod3c15752011-07-27 16:27:22 -070069 if (p != NULL) {
Carl Shapirofc322c72011-07-27 00:20:01 -070070 full = p + 1;
71 }
72 }
73}
74
75// TODO: move option processing elsewhere.
76const char* FindBootClassPath(const Runtime::Options& options) {
77 const char* boot_class_path = getenv("BOOTCLASSPATH");
78 const char* flag = "-Xbootclasspath:";
79 for (size_t i = 0; i < options.size(); ++i) {
80 const StringPiece& option = options[i].first;
81 if (option.starts_with(flag)) {
82 boot_class_path = option.substr(strlen(flag)).data();
83 }
84 }
85 if (boot_class_path == NULL) {
86 return "";
87 } else {
88 return boot_class_path;
89 }
90}
91
92void CreateBootClassPath(const Runtime::Options& options,
93 std::vector<DexFile*>* boot_class_path) {
94 CHECK(boot_class_path != NULL);
95 const char* str = FindBootClassPath(options);
96 std::vector<std::string> parsed;
97 ParseClassPath(str, &parsed);
98 for (size_t i = 0; i < parsed.size(); ++i) {
99 DexFile* dex_file = DexFile::OpenFile(parsed[i].c_str());
100 if (dex_file != NULL) {
101 boot_class_path->push_back(dex_file);
102 }
103 }
104}
105
106// TODO: do something with ignore_unrecognized when we parse the option
107// strings for real.
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700108Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
Carl Shapirofc322c72011-07-27 00:20:01 -0700109 std::vector<DexFile*> boot_class_path;
110 CreateBootClassPath(options, &boot_class_path);
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700111 return Runtime::Create(boot_class_path);
112}
113
114Runtime* Runtime::Create(const std::vector<DexFile*>& boot_class_path) {
115 // TODO: acquire a static mutex on Runtime to avoid racing.
116 if (Runtime::instance_ != NULL) {
117 return NULL;
118 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700119 scoped_ptr<Runtime> runtime(new Runtime());
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700120 bool success = runtime->Init(boot_class_path);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700121 if (!success) {
122 return NULL;
123 } else {
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700124 return Runtime::instance_ = runtime.release();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700125 }
126}
127
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700128bool Runtime::Init(const std::vector<DexFile*>& boot_class_path) {
Carl Shapiro61e019d2011-07-14 16:53:09 -0700129 thread_list_ = ThreadList::Create();
Carl Shapiro69759ea2011-07-21 18:13:35 -0700130 Heap::Init(Heap::kStartupSize, Heap::kMaximumSize);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700131 Thread::Init();
132 Thread* current_thread = Thread::Attach();
133 thread_list_->Register(current_thread);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700134 class_linker_ = ClassLinker::Create(boot_class_path);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700135 return true;
136}
137
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700138bool Runtime::AttachCurrentThread(const char* name, JniEnvironment** penv) {
139 return Thread::Attach() != NULL;
140}
141
142bool Runtime::AttachCurrentThreadAsDaemon(const char* name,
143 JniEnvironment** penv) {
144 // TODO: do something different for daemon threads.
Ian Rogersb033c752011-07-20 12:22:35 -0700145 return Thread::Attach() != NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -0700146}
147
Ian Rogersb033c752011-07-20 12:22:35 -0700148bool Runtime::DetachCurrentThread() {
149 LOG(WARNING) << "Unimplemented: Runtime::DetachCurrentThread";
150 return true;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700151}
152
153} // namespace art