blob: a02b09c9bebfd8f788e8dd16d9db93e77f81b590 [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
Elliott Hughes40ef99e2011-08-11 17:44:34 -070092DexFile* Open(const std::string& filename) {
93 if (filename.size() < 4) {
94 LOG(WARNING) << "Ignoring short classpath entry '" << filename << "'";
95 return NULL;
96 }
97 std::string suffix(filename.substr(filename.size() - 4));
98 if (suffix == ".zip" || suffix == ".jar" || suffix == ".apk") {
99 return DexFile::OpenZip(filename);
100 } else {
101 return DexFile::OpenFile(filename);
102 }
103}
104
Carl Shapirofc322c72011-07-27 00:20:01 -0700105void CreateBootClassPath(const Runtime::Options& options,
106 std::vector<DexFile*>* boot_class_path) {
107 CHECK(boot_class_path != NULL);
108 const char* str = FindBootClassPath(options);
109 std::vector<std::string> parsed;
110 ParseClassPath(str, &parsed);
111 for (size_t i = 0; i < parsed.size(); ++i) {
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700112 DexFile* dex_file = Open(parsed[i]);
Carl Shapirofc322c72011-07-27 00:20:01 -0700113 if (dex_file != NULL) {
114 boot_class_path->push_back(dex_file);
115 }
116 }
117}
118
119// TODO: do something with ignore_unrecognized when we parse the option
120// strings for real.
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700121Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
Carl Shapirofc322c72011-07-27 00:20:01 -0700122 std::vector<DexFile*> boot_class_path;
123 CreateBootClassPath(options, &boot_class_path);
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700124 return Runtime::Create(boot_class_path);
125}
126
127Runtime* Runtime::Create(const std::vector<DexFile*>& boot_class_path) {
128 // TODO: acquire a static mutex on Runtime to avoid racing.
129 if (Runtime::instance_ != NULL) {
130 return NULL;
131 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700132 scoped_ptr<Runtime> runtime(new Runtime());
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700133 bool success = runtime->Init(boot_class_path);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700134 if (!success) {
135 return NULL;
136 } else {
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700137 return Runtime::instance_ = runtime.release();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700138 }
139}
140
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700141bool Runtime::Init(const std::vector<DexFile*>& boot_class_path) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700142 CHECK_EQ(kPageSize, sysconf(_SC_PAGE_SIZE));
Carl Shapiro61e019d2011-07-14 16:53:09 -0700143 thread_list_ = ThreadList::Create();
Carl Shapiro69759ea2011-07-21 18:13:35 -0700144 Heap::Init(Heap::kStartupSize, Heap::kMaximumSize);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700145 Thread::Init();
146 Thread* current_thread = Thread::Attach();
147 thread_list_->Register(current_thread);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700148 class_linker_ = ClassLinker::Create(boot_class_path);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700149 return true;
150}
151
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700152bool Runtime::AttachCurrentThread(const char* name, JNIEnv** penv) {
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700153 return Thread::Attach() != NULL;
154}
155
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700156bool Runtime::AttachCurrentThreadAsDaemon(const char* name, JNIEnv** penv) {
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700157 // TODO: do something different for daemon threads.
Ian Rogersb033c752011-07-20 12:22:35 -0700158 return Thread::Attach() != NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -0700159}
160
Ian Rogersb033c752011-07-20 12:22:35 -0700161bool Runtime::DetachCurrentThread() {
162 LOG(WARNING) << "Unimplemented: Runtime::DetachCurrentThread";
163 return true;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700164}
165
166} // namespace art