blob: 18b001e7f07dcf8c9af15bd9ae3ee4ae4a4c4677 [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 Shapirofc322c72011-07-27 00:20:01 -070054void ParseClassPath(const char* class_path, std::vector<std::string>* vec) {
55 CHECK(vec != NULL);
56 scoped_ptr_malloc<char> tmp(strdup(class_path));
57 char* full = tmp.get();
58 char* p = full;
59 while (p) {
60 p = strpbrk(full, ":");
61 if (p != NULL) {
62 p[0] = '\0';
63 }
64 if (full[0] != '\0') {
65 vec->push_back(std::string(full));
66 }
67 if (p) {
68 full = p + 1;
69 }
70 }
71}
72
73// TODO: move option processing elsewhere.
74const char* FindBootClassPath(const Runtime::Options& options) {
75 const char* boot_class_path = getenv("BOOTCLASSPATH");
76 const char* flag = "-Xbootclasspath:";
77 for (size_t i = 0; i < options.size(); ++i) {
78 const StringPiece& option = options[i].first;
79 if (option.starts_with(flag)) {
80 boot_class_path = option.substr(strlen(flag)).data();
81 }
82 }
83 if (boot_class_path == NULL) {
84 return "";
85 } else {
86 return boot_class_path;
87 }
88}
89
90void CreateBootClassPath(const Runtime::Options& options,
91 std::vector<DexFile*>* boot_class_path) {
92 CHECK(boot_class_path != NULL);
93 const char* str = FindBootClassPath(options);
94 std::vector<std::string> parsed;
95 ParseClassPath(str, &parsed);
96 for (size_t i = 0; i < parsed.size(); ++i) {
97 DexFile* dex_file = DexFile::OpenFile(parsed[i].c_str());
98 if (dex_file != NULL) {
99 boot_class_path->push_back(dex_file);
100 }
101 }
102}
103
104// TODO: do something with ignore_unrecognized when we parse the option
105// strings for real.
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700106Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
Carl Shapirofc322c72011-07-27 00:20:01 -0700107 std::vector<DexFile*> boot_class_path;
108 CreateBootClassPath(options, &boot_class_path);
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700109 return Runtime::Create(boot_class_path);
110}
111
112Runtime* Runtime::Create(const std::vector<DexFile*>& boot_class_path) {
113 // TODO: acquire a static mutex on Runtime to avoid racing.
114 if (Runtime::instance_ != NULL) {
115 return NULL;
116 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700117 scoped_ptr<Runtime> runtime(new Runtime());
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700118 bool success = runtime->Init(boot_class_path);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700119 if (!success) {
120 return NULL;
121 } else {
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700122 return Runtime::instance_ = runtime.release();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700123 }
124}
125
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700126bool Runtime::Init(const std::vector<DexFile*>& boot_class_path) {
Carl Shapiro61e019d2011-07-14 16:53:09 -0700127 thread_list_ = ThreadList::Create();
Carl Shapiro69759ea2011-07-21 18:13:35 -0700128 Heap::Init(Heap::kStartupSize, Heap::kMaximumSize);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700129 Thread::Init();
130 Thread* current_thread = Thread::Attach();
131 thread_list_->Register(current_thread);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700132 class_linker_ = ClassLinker::Create(boot_class_path);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700133 return true;
134}
135
Carl Shapiro2ed144c2011-07-26 16:52:08 -0700136bool Runtime::AttachCurrentThread(const char* name, JniEnvironment** penv) {
137 return Thread::Attach() != NULL;
138}
139
140bool Runtime::AttachCurrentThreadAsDaemon(const char* name,
141 JniEnvironment** penv) {
142 // TODO: do something different for daemon threads.
Ian Rogersb033c752011-07-20 12:22:35 -0700143 return Thread::Attach() != NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -0700144}
145
Ian Rogersb033c752011-07-20 12:22:35 -0700146bool Runtime::DetachCurrentThread() {
147 LOG(WARNING) << "Unimplemented: Runtime::DetachCurrentThread";
148 return true;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700149}
150
151} // namespace art