runtime.cc revision fc322c72d7a89a6f7a05c8bdc232d780aecd9232
16b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro// Copyright 2011 Google Inc. All Rights Reserved.
26b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro
3578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h"
47b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
5ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdio>
6ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdlib>
72ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <vector>
8ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
9578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h"
10578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "heap.h"
11fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro#include "scoped_ptr.h"
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h"
1361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
146b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art {
157b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
162ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::instance_ = NULL;
172ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
1861e019d291583029c01b61b93bea750f2b663c37Carl ShapiroRuntime::~Runtime() {
1961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // TODO: use a smart pointer instead.
2061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  delete class_linker_;
2169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Heap::Destroy();
2261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  delete thread_list_;
234acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
244acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  CHECK(instance_ == this);
254acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  instance_ = NULL;
2661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
2761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
28ffe6736397d17457188727510f0a2953f69a383aElliott Hughesvoid Runtime::Abort(const char* file, int line) {
29ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Get any pending output out of the way.
30ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  fflush(NULL);
31ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
32ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Many people have difficulty distinguish aborts from crashes,
33ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // so be explicit.
34ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  LogMessage(file, line, ERROR, -1).stream() << "Runtime aborting...";
35ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
36ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // TODO: if we support an abort hook, call it here.
37ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
38ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Perform any platform-specific pre-abort actions.
39ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  PlatformAbort(file, line);
40ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
41ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // If we call abort(3) on a device, all threads in the process
4269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // receive SIGABRT.  debuggerd dumps the stack trace of the main
4369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // thread, whether or not that was the thread that failed.  By
4469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // stuffing a value into a bogus address, we cause a segmentation
45ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // fault in the current thread, and get a useful log from debuggerd.
46ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // We can also trivially tell the difference between a VM crash and
47ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // a deliberate abort by looking at the fault address.
48ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  *reinterpret_cast<char*>(0xdeadd00d) = 38;
49ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  abort();
50ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
51ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // notreached
52ffe6736397d17457188727510f0a2953f69a383aElliott Hughes}
53ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
54fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapirovoid ParseClassPath(const char* class_path, std::vector<std::string>* vec) {
55fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  CHECK(vec != NULL);
56fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  scoped_ptr_malloc<char> tmp(strdup(class_path));
57fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  char* full = tmp.get();
58fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  char* p = full;
59fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  while (p) {
60fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    p = strpbrk(full, ":");
61fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    if (p != NULL) {
62fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro      p[0] = '\0';
63fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
64fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    if (full[0] != '\0') {
65fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro      vec->push_back(std::string(full));
66fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
67fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    if (p) {
68fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro      full = p + 1;
69fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
70fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
71fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
72fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
73fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro// TODO: move option processing elsewhere.
74fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiroconst char* FindBootClassPath(const Runtime::Options& options) {
75fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  const char* boot_class_path = getenv("BOOTCLASSPATH");
76fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  const char* flag = "-Xbootclasspath:";
77fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  for (size_t i = 0; i < options.size(); ++i) {
78fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    const StringPiece& option = options[i].first;
79fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    if (option.starts_with(flag)) {
80fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro      boot_class_path = option.substr(strlen(flag)).data();
81fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
82fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
83fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  if (boot_class_path == NULL) {
84fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    return "";
85fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  } else {
86fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    return boot_class_path;
87fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
88fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
89fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
90fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapirovoid CreateBootClassPath(const Runtime::Options& options,
91fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro                         std::vector<DexFile*>* boot_class_path) {
92fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  CHECK(boot_class_path != NULL);
93fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  const char* str = FindBootClassPath(options);
94fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  std::vector<std::string> parsed;
95fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  ParseClassPath(str, &parsed);
96fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  for (size_t i = 0; i < parsed.size(); ++i) {
97fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    DexFile* dex_file = DexFile::OpenFile(parsed[i].c_str());
98fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    if (dex_file != NULL) {
99fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro      boot_class_path->push_back(dex_file);
100fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
101fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
102fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
103fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
104fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro// TODO: do something with ignore_unrecognized when we parse the option
105fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro// strings for real.
1062ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
107fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  std::vector<DexFile*> boot_class_path;
108fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  CreateBootClassPath(options, &boot_class_path);
1092ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  return Runtime::Create(boot_class_path);
1102ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro}
1112ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
1122ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::Create(const std::vector<DexFile*>& boot_class_path) {
1132ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
1142ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  if (Runtime::instance_ != NULL) {
1152ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro    return NULL;
1162ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  }
11761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  scoped_ptr<Runtime> runtime(new Runtime());
118578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom  bool success = runtime->Init(boot_class_path);
11961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  if (!success) {
12061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro    return NULL;
12161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  } else {
1222ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro    return Runtime::instance_ = runtime.release();
12361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  }
12461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
12561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
1262ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapirobool Runtime::Init(const std::vector<DexFile*>& boot_class_path) {
12761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  thread_list_ = ThreadList::Create();
12869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Heap::Init(Heap::kStartupSize, Heap::kMaximumSize);
12961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  Thread::Init();
13061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  Thread* current_thread = Thread::Attach();
13161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  thread_list_->Register(current_thread);
132578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom  class_linker_ = ClassLinker::Create(boot_class_path);
1337b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro  return true;
1347b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
1357b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
1362ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapirobool Runtime::AttachCurrentThread(const char* name, JniEnvironment** penv) {
1372ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  return Thread::Attach() != NULL;
1382ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro}
1392ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
1402ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapirobool Runtime::AttachCurrentThreadAsDaemon(const char* name,
1412ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro                                          JniEnvironment** penv) {
1422ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  // TODO: do something different for daemon threads.
143b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  return Thread::Attach() != NULL;
14461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
14561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
146b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersbool Runtime::DetachCurrentThread() {
147b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  LOG(WARNING) << "Unimplemented: Runtime::DetachCurrentThread";
148b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  return true;
1497b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
1507b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
1516b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro}  // namespace art
152