runtime.cc revision 2692b573a56cd63a3c8c8aa1636e3766b6d8c9c4
16b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro// Copyright 2011 Google Inc. All Rights Reserved.
26b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro
3578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h"
47b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
5dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom#include <signal.h>
6dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom
7ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdio>
8ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdlib>
98a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom#include <limits>
102ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <vector>
11ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h"
13aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "class_loader.h"
143bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "debugger.h"
15578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "heap.h"
16e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "image.h"
17cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes#include "intern_table.h"
18c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h"
1932d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes#include "monitor.h"
20e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_file.h"
21726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes#include "ScopedLocalRef.h"
22e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#include "signal_catcher.h"
23e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "space.h"
24578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h"
258daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h"
263bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "UniquePtr.h"
2761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
2890a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes// TODO: this drags in cutil/log.h, which conflicts with our logging.h.
2990a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "JniConstants.h"
3090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes
316b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art {
327b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
332ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::instance_ = NULL;
342ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
35dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesRuntime::Runtime()
364dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    : is_zygote_(false),
370a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom      default_stack_size_(Thread::kDefaultStackSize),
38c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes      monitor_list_(NULL),
39dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      thread_list_(NULL),
40dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      intern_table_(NULL),
41dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      class_linker_(NULL),
42dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      signal_catcher_(NULL),
43dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      java_vm_(NULL),
44161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom      jni_stub_array_(NULL),
45e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      abstract_method_error_stub_array_(NULL),
46dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      started_(false),
47dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      vfprintf_(NULL),
48dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      exit_(NULL),
499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      abort_(NULL),
502692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao      stats_enabled_(false),
512692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao      tracer_(NULL) {
524f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
534f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    resolution_stub_array_[i] = NULL;
544f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
554f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
564f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    callee_save_method_[i] = NULL;
574f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
58dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
59dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
6061e019d291583029c01b61b93bea750f2b663c37Carl ShapiroRuntime::~Runtime() {
61d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  Dbg::StopJdwp();
62d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
635fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // Make sure our internal threads are dead before we start tearing down things they're using.
645fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  delete signal_catcher_;
65038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // TODO: GC thread.
665fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes
67038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
6893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes  delete thread_list_;
69c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes  delete monitor_list_;
7093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes
7161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  delete class_linker_;
7269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Heap::Destroy();
73cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  delete intern_table_;
74c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes  delete java_vm_;
75c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  Thread::Shutdown();
764acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
774a289ed61242964b921434de7d375f46480472a1Brian Carlstrom  CHECK(instance_ == NULL || instance_ == this);
784acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  instance_ = NULL;
7961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
8061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
81cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughesstatic bool gAborting = false;
82cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes
83e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughesstruct AbortState {
84e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  void Dump(std::ostream& os) {
85cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes    if (gAborting) {
86cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes      os << "Runtime aborting --- recursively, so no thread-specific detail!\n";
87cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes      return;
88cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes    }
89cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes    gAborting = true;
90e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    os << "Runtime aborting...\n";
91e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    Thread* self = Thread::Current();
92e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    if (self == NULL) {
93e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes      os << "(Aborting thread was not attached to runtime!)\n";
94e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    } else {
95e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes      self->Dump(os, true);
96e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    }
97e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  }
98e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes};
99e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes
100ffe6736397d17457188727510f0a2953f69a383aElliott Hughesvoid Runtime::Abort(const char* file, int line) {
101ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Get any pending output out of the way.
102ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  fflush(NULL);
103ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
104ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Many people have difficulty distinguish aborts from crashes,
105ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // so be explicit.
106e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  AbortState state;
107e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  LOG(ERROR) << Dumpable<AbortState>(state);
108ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
109ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Perform any platform-specific pre-abort actions.
110ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  PlatformAbort(file, line);
111ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
1126ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  // use abort hook if we have one
1136ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) {
1146ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    Runtime::Current()->abort_();
1156ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    // notreached
1166ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
1176ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
118ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // If we call abort(3) on a device, all threads in the process
11969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // receive SIGABRT.  debuggerd dumps the stack trace of the main
12069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // thread, whether or not that was the thread that failed.  By
12169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // stuffing a value into a bogus address, we cause a segmentation
122ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // fault in the current thread, and get a useful log from debuggerd.
123ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // We can also trivially tell the difference between a VM crash and
124ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // a deliberate abort by looking at the fault address.
125ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  *reinterpret_cast<char*>(0xdeadd00d) = 38;
126ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  abort();
127ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // notreached
128ffe6736397d17457188727510f0a2953f69a383aElliott Hughes}
129ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
130bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid Runtime::CallExitHook(jint status) {
131bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (exit_ != NULL) {
132bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative);
133bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    exit_(status);
134bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    LOG(WARNING) << "Exit hook returned instead of exiting!";
135bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
136bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
137bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1388a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
1398a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// memory sizes.  [kK] indicates kilobytes, [mM] megabytes, and
1408a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// [gG] gigabytes.
1418a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1428a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "s" should point just past the "-Xm?" part of the string.
1438a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "div" specifies a divisor, e.g. 1024 if the value must be a multiple
1448a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// of 1024.
1458a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1468a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// The spec says the -Xmx and -Xms options must be multiples of 1024.  It
1478a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// doesn't say anything about -Xss.
1488a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1498a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Returns 0 (a useless size) if "s" is malformed or specifies a low or
1508a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// non-evenly-divisible value.
1518a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
152c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughessize_t ParseMemoryOption(const char* s, size_t div) {
1538a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // strtoul accepts a leading [+-], which we don't want,
1548a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // so make sure our string starts with a decimal digit.
1558a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  if (isdigit(*s)) {
156c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughes    const char* s2;
157c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughes    size_t val = strtoul(s, (char**)&s2, 10);
1588a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (s2 != s) {
1598a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // s2 should be pointing just after the number.
1608a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // If this is the end of the string, the user
1618a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // has specified a number of bytes.  Otherwise,
1628a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // there should be exactly one more character
1638a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // that specifies a multiplier.
1648a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (*s2 != '\0') {
165f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // The remainder of the string is either a single multiplier
166f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // character, or nothing to indicate that the value is in
167f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // bytes.
168f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        char c = *s2++;
169f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (*s2 == '\0') {
170f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          size_t mul;
171f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (c == '\0') {
172f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = 1;
173f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'k' || c == 'K') {
174f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = KB;
175f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'm' || c == 'M') {
176f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = MB;
177f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'g' || c == 'G') {
178f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = GB;
1798a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          } else {
180f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Unknown multiplier character.
1818a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom            return 0;
1828a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          }
183f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
184f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (val <= std::numeric_limits<size_t>::max() / mul) {
185f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val *= mul;
186f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else {
187f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Clamp to a multiple of 1024.
188f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val = std::numeric_limits<size_t>::max() & ~(1024-1);
189f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          }
190f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        } else {
191f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          // There's more than one character after the numeric part.
192f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          return 0;
193f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
1948a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
1958a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // The man page says that a -Xm value must be a multiple of 1024.
1968a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (val % div == 0) {
1978a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom        return val;
1988a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
199fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
200fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
2018a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  return 0;
202fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
203fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
204bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughessize_t ParseIntegerOrDie(const StringPiece& s) {
205bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  StringPiece::size_type colon = s.find(':');
206bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  if (colon == StringPiece::npos) {
207bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    LOG(FATAL) << "Missing integer: " << s;
208bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  }
209bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  const char* begin = &s.data()[colon + 1];
210bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  char* end;
211bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  size_t result = strtoul(begin, &end, 10);
212bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  if (begin == end || *end != '\0') {
213bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    LOG(FATAL) << "Failed to parse integer in: " << s;
214bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  }
215bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  return result;
216bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes}
217bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes
2180af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesvoid LoadJniLibrary(JavaVMExt* vm, const char* name) {
2190af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  // TODO: OS_SHARED_LIB_FORMAT_STR
2200af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  std::string mapped_name(StringPrintf("lib%s.so", name));
2217577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  std::string reason;
2227577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  if (!vm->LoadNativeLibrary(mapped_name, NULL, reason)) {
2230af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": "
2240af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes               << reason;
2250af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  }
2260af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes}
2270af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
2286ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian CarlstromRuntime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
22990a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> parsed(new ParsedOptions());
2305de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom  bool compiler = false;
23158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  const char* boot_class_path = getenv("BOOTCLASSPATH");
23258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (boot_class_path != NULL) {
23358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    parsed->boot_class_path_ = getenv("BOOTCLASSPATH");
23458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
23558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  const char* class_path = getenv("CLASSPATH");
23658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (class_path != NULL) {
23758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    parsed->class_path_ = getenv("CLASSPATH");
23858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
239515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#ifdef NDEBUG
2405174fe6e4e931c423e910366ff22ce0838567940Elliott Hughes  // -Xcheck:jni is off by default for regular builds...
241515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  parsed->check_jni_ = false;
242515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#else
243515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  // ...but on by default in debug builds.
244515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  parsed->check_jni_ = true;
245515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#endif
24685d1545e985ac689db4bad7849880e843707c862Elliott Hughes
2476ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_initial_size_ = Heap::kInitialSize;
2486ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_maximum_size_ = Heap::kMaximumSize;
249c11607024d2e7a52ca690b8339306cab040e6653jeffhao  parsed->heap_growth_limit_ = 0;  // 0 means no growth limit
250f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom  parsed->stack_size_ = Thread::kDefaultStackSize;
251f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
2529ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  parsed->is_zygote_ = false;
2539ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
254bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  parsed->jni_globals_max_ = 0;
255fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes  parsed->lock_profiling_threshold_ = 0;
256fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes  parsed->hook_is_sensitive_thread_ = NULL;
257fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes
2586ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_vfprintf_ = vfprintf;
2596ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_exit_ = exit;
2606ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_abort_ = abort;
2618a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
2628a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  for (size_t i = 0; i < options.size(); ++i) {
2638a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    const StringPiece& option = options[i].first;
2640796af03edc06d92bb8d631f1c0c23befdae2315Brian Carlstrom    if (true && options[0].first == "-Xzygote") {
26558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      LOG(INFO) << "option[" << i << "]=" << option;
26658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    }
2678a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (option.starts_with("-Xbootclasspath:")) {
26858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:")).data();
26969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option == "-classpath" || option == "-cp") {
27069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      // TODO: support -Djava.class.path
27169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      i++;
27269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      if (i == options.size()) {
27369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        // TODO: usage
27469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Missing required class path value for " << option;
27569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        return NULL;
27669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      }
27769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      const StringPiece& value = options[i].first;
27858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->class_path_ = value.data();
27969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option.starts_with("-Ximage:")) {
28069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      parsed->images_.push_back(option.substr(strlen("-Ximage:")).data());
281515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes    } else if (option.starts_with("-Xcheck:jni")) {
282515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes      parsed->check_jni_ = true;
2833bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes    } else if (option.starts_with("-Xrunjdwp:") || option.starts_with("-agentlib:jdwp=")) {
284955724179c6c739524f610023287f56b24dc31deElliott Hughes      std::string tail(option.substr(option[1] == 'X' ? 10 : 15).ToString());
2853bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes      if (tail == "help" || !Dbg::ParseJdwpOptions(tail)) {
2863bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes        LOG(FATAL) << "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n"
2873bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes                   << "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n";
2883bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes        return NULL;
2893bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes      }
2908a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option.starts_with("-Xms")) {
291f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).data(), 1024);
292f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
293f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
294f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
295f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2964a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
29769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
298f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
299f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
300f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_initial_size_ = size;
3018a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option.starts_with("-Xmx")) {
302f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).data(), 1024);
303f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
304f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
305f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
306f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
3074a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
30869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
309f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
310f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
311f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_maximum_size_ = size;
312c11607024d2e7a52ca690b8339306cab040e6653jeffhao    } else if (option.starts_with("-XX:HeapGrowthLimit=")) {
313c11607024d2e7a52ca690b8339306cab040e6653jeffhao      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapGrowthLimit=")).data(), 1024);
314c11607024d2e7a52ca690b8339306cab040e6653jeffhao      if (size == 0) {
315c11607024d2e7a52ca690b8339306cab040e6653jeffhao        if (ignore_unrecognized) {
316c11607024d2e7a52ca690b8339306cab040e6653jeffhao          continue;
317c11607024d2e7a52ca690b8339306cab040e6653jeffhao        }
318c11607024d2e7a52ca690b8339306cab040e6653jeffhao        // TODO: usage
319c11607024d2e7a52ca690b8339306cab040e6653jeffhao        LOG(FATAL) << "Failed to parse " << option;
320c11607024d2e7a52ca690b8339306cab040e6653jeffhao        return NULL;
321c11607024d2e7a52ca690b8339306cab040e6653jeffhao      }
322c11607024d2e7a52ca690b8339306cab040e6653jeffhao      parsed->heap_growth_limit_ = size;
323f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom    } else if (option.starts_with("-Xss")) {
324f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).data(), 1);
325f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
326f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
327f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
328f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
3294a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
33069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
331f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
332f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
333f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->stack_size_ = size;
3346ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option.starts_with("-D")) {
3356ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->properties_.push_back(option.substr(strlen("-D")).data());
336a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    } else if (option.starts_with("-Xjnitrace:")) {
337a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:")).data();
3385de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom    } else if (option == "compiler") {
3395de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom      compiler = true;
3409ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes    } else if (option == "-Xzygote") {
3419ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes      parsed->is_zygote_ = true;
3426ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option.starts_with("-verbose:")) {
3430af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      std::vector<std::string> verbose_options;
34434023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes      Split(option.substr(strlen("-verbose:")).data(), ',', verbose_options);
3450af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      for (size_t i = 0; i < verbose_options.size(); ++i) {
3464dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        if (verbose_options[i] == "class") {
3474dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.class_linker = true;
3484dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "compiler") {
3494dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.compiler = true;
3504dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "heap") {
3514dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.heap = true;
3524dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "gc") {
3534dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.gc = true;
3544dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "jdwp") {
3554dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.jdwp = true;
3564dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "jni") {
3574dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.jni = true;
3584dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "monitor") {
3594dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.monitor = true;
3604dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "startup") {
3614dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.startup = true;
3624dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "third-party-jni") {
3634dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.third_party_jni = true;
3644dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "threads") {
3654dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.threads = true;
3664dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else {
3674dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i];
3684dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        }
3690af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      }
370bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    } else if (option.starts_with("-Xjnigreflimit:")) {
371bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes      parsed->jni_globals_max_ = ParseIntegerOrDie(option);
372fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes    } else if (option.starts_with("-Xlockprofthreshold:")) {
373bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes      parsed->lock_profiling_threshold_ = ParseIntegerOrDie(option);
37494ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes    } else if (option.starts_with("-Xstacktracefile:")) {
3757c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom// always show stack traces in debug builds
3767c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom#ifdef NDEBUG
37794ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes      parsed->stack_trace_file_ = option.substr(strlen("-Xstacktracefile:")).data();
3787c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom#endif
379fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes    } else if (option == "sensitiveThread") {
380fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes      parsed->hook_is_sensitive_thread_ = reinterpret_cast<bool (*)()>(options[i].second);
3816ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "vfprintf") {
3826ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_vfprintf_ = reinterpret_cast<int (*)(FILE *, const char*, va_list)>(options[i].second);
3836ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "exit") {
3846ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second);
3856ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "abort") {
3866ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second);
38758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option == "host-prefix") {
38858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second);
3898a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else {
3908a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (!ignore_unrecognized) {
3916ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom        // TODO: print usage via vfprintf
39227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        LOG(ERROR) << "Unrecognized option " << option;
39327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        // TODO: this should exit, but for now tolerate unknown options
39427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        //return NULL;
3958a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
3968a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    }
3978a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  }
3988a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
3995de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom  if (!compiler && parsed->images_.empty()) {
40029e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom    parsed->images_.push_back("/system/framework/boot.art");
4015de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom  }
402c11607024d2e7a52ca690b8339306cab040e6653jeffhao  if (parsed->heap_growth_limit_ == 0) {
403c11607024d2e7a52ca690b8339306cab040e6653jeffhao    parsed->heap_growth_limit_ = parsed->heap_maximum_size_;
404c11607024d2e7a52ca690b8339306cab040e6653jeffhao  }
4055de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom
406cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  LOG(INFO) << "Build type: "
407cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes#ifndef NDEBUG
408cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes            << "debug"
409cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes#else
410cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes            << "optimized"
411cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes#endif
412cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes            << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off");
41385d1545e985ac689db4bad7849880e843707c862Elliott Hughes
41469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return parsed.release();
4158a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom}
4168a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
4178a436595d36c1e4935984fcac249d7d877e00383Brian CarlstromRuntime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
4182ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
4192ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  if (Runtime::instance_ != NULL) {
4202ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro    return NULL;
4212ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  }
422dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  instance_ = new Runtime;
423dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  if (!instance_->Init(options, ignore_unrecognized)) {
424dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    delete instance_;
425dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    instance_ = NULL;
42661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  }
42769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return instance_;
42869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
4290af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
430aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromvoid CreateSystemClassLoader() {
431aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (ClassLoader::UseCompileTimeClassPath()) {
432aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return;
433aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
434aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
435aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  Thread* self = Thread::Current();
436aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
437aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  // Must be in the kNative state for calling native methods.
438aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK_EQ(self->GetState(), Thread::kNative);
439aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
440aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  JNIEnv* env = self->GetJniEnv();
441df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader"));
442df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(ClassLoader_class.get() != NULL);
443df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(),
444df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                          "getSystemClassLoader",
445df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                          "()Ljava/lang/ClassLoader;");
446df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(getSystemClassLoader != NULL);
447df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(),
448df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                                        getSystemClassLoader));
449df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(class_loader.get() != NULL);
450df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom
451df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get()));
4521b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson
4531b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  ScopedLocalRef<jclass> Thread_class(env, env->FindClass("java/lang/Thread"));
4541b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  CHECK(Thread_class.get() != NULL);
4551b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  jfieldID contextClassLoader = env->GetFieldID(Thread_class.get(),
4561b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson                                                "contextClassLoader",
4571b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson                                                "Ljava/lang/ClassLoader;");
4581b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  CHECK(contextClassLoader != NULL);
4591b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  ScopedLocalRef<jobject> self_jobject(env, AddLocalReference<jobject>(env, self->GetPeer()));
4601b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  env->SetObjectField(self_jobject.get(), contextClassLoader, class_loader.get());
461aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
462aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
46369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromvoid Runtime::Start() {
4644dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Start entering";
46558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
46658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  CHECK(host_prefix_.empty()) << host_prefix_;
46758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
468f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom  // Restore main thread state to kNative as expected by native code
469f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom  Thread::Current()->SetState(Thread::kNative);
470f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom
4715d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  started_ = true;
4725d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom
473ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // InitNativeMethods needs to be after started_ so that the classes
474ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // it touches will have methods linked to the oat file if necessary.
475ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  InitNativeMethods();
476ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
4779a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson  Thread::FinishStartup();
4789a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson
479d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  if (!is_zygote_) {
480d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes    DidForkFromZygote();
481d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  }
4829ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
48385d1545e985ac689db4bad7849880e843707c862Elliott Hughes  StartDaemonThreads();
4840a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom
485aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CreateSystemClassLoader();
486aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
487726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  Thread::Current()->GetJniEnv()->locals.AssertEmpty();
488726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes
4894dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Start exiting";
49085d1545e985ac689db4bad7849880e843707c862Elliott Hughes}
49185d1545e985ac689db4bad7849880e843707c862Elliott Hughes
492caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::DidForkFromZygote() {
493caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  is_zygote_ = false;
494d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
495caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  StartSignalCatcher();
496d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
497d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
498d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // this will pause the runtime, so we probably want this to come last.
499d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  Dbg::StartJdwp();
500caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom}
501caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom
502caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::StartSignalCatcher() {
503caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  if (!is_zygote_) {
50494ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes    signal_catcher_ = new SignalCatcher(stack_trace_file_);
505caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  }
506caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom}
507caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom
50885d1545e985ac689db4bad7849880e843707c862Elliott Hughesvoid Runtime::StartDaemonThreads() {
5094dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::StartDaemonThreads entering";
51085d1545e985ac689db4bad7849880e843707c862Elliott Hughes
511719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  Thread* self = Thread::Current();
512aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
513aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  // Must be in the kNative state for calling native methods.
514aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK_EQ(self->GetState(), Thread::kNative);
515aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
516719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  JNIEnv* env = self->GetJniEnv();
517726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Daemons"));
518726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  CHECK(c.get() != NULL);
519726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V");
520719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  CHECK(mid != NULL);
521726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  env->CallStaticVoidMethod(c.get(), mid);
5229ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
5234dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::StartDaemonThreads exiting";
52461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
52561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
52658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrombool Runtime::IsStarted() const {
527dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  return started_;
528dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
529dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
5300af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesbool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
531c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
5326ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
53390a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
53490a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  if (options.get() == NULL) {
535e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to parse options";
5366ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    return false;
5376ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
5384dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Init -verbose:startup enabled";
5397ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
540bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  SetJniGlobalsMax(options->jni_globals_max_);
5414dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
54232d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes
54358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  host_prefix_ = options->host_prefix_;
54458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  boot_class_path_ = options->boot_class_path_;
54558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  class_path_ = options->class_path_;
5467ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  properties_ = options->properties_;
5477ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
5489ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  is_zygote_ = options->is_zygote_;
5499ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
5500af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  vfprintf_ = options->hook_vfprintf_;
5510af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  exit_ = options->hook_exit_;
5520af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  abort_ = options->hook_abort_;
5536ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
554be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  default_stack_size_ = options->stack_size_;
55594ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes  stack_trace_file_ = options->stack_trace_file_;
5566ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
557c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes  monitor_list_ = new MonitorList;
5584dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  thread_list_ = new ThreadList;
559cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  intern_table_ = new InternTable;
560cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
5614dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  Heap::Init(options->heap_initial_size_,
5626b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom             options->heap_maximum_size_,
563c11607024d2e7a52ca690b8339306cab040e6653jeffhao             options->heap_growth_limit_,
5646b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom             options->images_);
5656ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
566c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  BlockSignals();
567c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
568a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  java_vm_ = new JavaVMExt(this, options.get());
569515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes
570be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  Thread::Startup();
571d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
5725fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // ClassLinker needs an attached thread, but we can't fully attach a thread
5735fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // without creating objects.
5745fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  Thread::Attach(this, "main", false);
5756ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
576f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom  // Set us to runnable so tools using a runtime can allocate and GC by default
577f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom  Thread::Current()->SetState(Thread::kRunnable);
578f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom
57958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  CHECK_GE(Heap::GetSpaces().size(), 1U);
58058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace())
5814dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes                   ? ClassLinker::Create(intern_table_)
5824dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes                   : ClassLinker::Create(options->boot_class_path_, intern_table_));
5836ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
5844dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Init exiting";
5857b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro  return true;
5867b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
5877b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
588038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Runtime::InitNativeMethods() {
5894dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::InitNativeMethods entering";
590ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread* self = Thread::Current();
591ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  JNIEnv* env = self->GetJniEnv();
592ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
593418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Must be in the kNative state for calling native methods (JNI_OnLoad code).
594aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK_EQ(self->GetState(), Thread::kNative);
595ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
596418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // First set up JniConstants, which is used by both the runtime's built-in native
597418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // methods and libcore.
598fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes  JniConstants::init(env);
599fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes
600418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up the native methods provided by the runtime itself.
601ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  RegisterRuntimeNativeMethods(env);
602ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
603418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad.
604418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's
605418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // the library that implements System.loadLibrary!
606ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  LoadJniLibrary(instance_->GetJavaVM(), "javacore");
6074dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::InitNativeMethods exiting";
608ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
609ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
610ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesvoid Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
611ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
612f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  REGISTER(register_dalvik_system_DexFile);
6139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  REGISTER(register_dalvik_system_VMDebug);
6147ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  REGISTER(register_dalvik_system_VMRuntime);
6158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_dalvik_system_VMStack);
61601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  REGISTER(register_dalvik_system_Zygote);
617d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes  REGISTER(register_java_lang_Class);
618bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Object);
619bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Runtime);
620bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_String);
621bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_System);
6228daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_java_lang_Thread);
6231240dade91d6c4bbf4e367ca608fcdc15348da45Elliott Hughes  REGISTER(register_java_lang_Throwable);
62464bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  REGISTER(register_java_lang_VMClassLoader);
6255b8e4c810a97c9dc417142b8c6e07871ae15c797Brian Carlstrom  REGISTER(register_java_lang_reflect_Array);
6262a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes  REGISTER(register_java_lang_reflect_Constructor);
627f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Field);
628f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Method);
62995caa791e560da97363c0c0d22bfda4a7e7377c3Jesse Wilson  REGISTER(register_java_lang_reflect_Proxy);
630bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_util_concurrent_atomic_AtomicLong);
631395520eaa47eca25b92e86188accf3095d60af49Brian Carlstrom  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
632f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal);
6335ee7a8b56dee896245e0f4ae5215f8b7376c1787Elliott Hughes  REGISTER(register_sun_misc_Unsafe);
634ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#undef REGISTER
635ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
636ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
6378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesvoid Runtime::Dump(std::ostream& os) {
638e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  // TODO: dump other runtime statistics?
639cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  GetClassLinker()->DumpForSigQuit(os);
640cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  GetInternTable()->DumpForSigQuit(os);
64142ee14279065352a4b9a3e8028d02c567e847d05Elliott Hughes  os << "\n";
6428daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
6438daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  thread_list_->Dump(os);
644e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes}
645e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
64621a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughesvoid Runtime::DumpLockHolders(std::ostream& os) {
64721a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t heap_lock_owner = Heap::GetLockOwner();
64821a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t thread_list_lock_owner = GetThreadList()->GetLockOwner();
64921a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t classes_lock_owner = GetClassLinker()->GetClassesLockOwner();
65021a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t dex_lock_owner = GetClassLinker()->GetDexLockOwner();
65121a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  if ((heap_lock_owner | thread_list_lock_owner | classes_lock_owner | dex_lock_owner) != 0) {
65221a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes    os << "Heap lock owner tid: " << heap_lock_owner << "\n"
65321a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ThreadList lock owner tid: " << thread_list_lock_owner << "\n"
65421a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ClassLinker classes lock owner tid: " << classes_lock_owner << "\n"
65521a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ClassLinker dex lock owner tid: " << dex_lock_owner << "\n";
65621a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  }
65721a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes}
65821a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes
6599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::SetStatsEnabled(bool new_state) {
6609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (new_state == true) {
6619d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    GetStats()->Clear(~0);
6629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // TODO: wouldn't it make more sense to clear _all_ threads' stats?
6639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    Thread::Current()->GetStats()->Clear(~0);
6649d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
6659d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  stats_enabled_ = new_state;
6669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
6679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
6689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::ResetStats(int kinds) {
6699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  GetStats()->Clear(kinds & 0xffff);
6709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  // TODO: wouldn't it make more sense to clear _all_ threads' stats?
6719d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  Thread::Current()->GetStats()->Clear(kinds >> 16);
6729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
6739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
6749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott HughesRuntimeStats* Runtime::GetStats() {
6759d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return &stats_;
6769d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
6779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
6789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesint32_t Runtime::GetStat(int kind) {
6799d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  RuntimeStats* stats;
6809d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (kind < (1<<16)) {
6819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = GetStats();
6829d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  } else {
6839d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = Thread::Current()->GetStats();
6849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    kind >>= 16;
6859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
6869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  switch (kind) {
6879d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_OBJECTS:
6889d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_objects;
6899d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_BYTES:
6909d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_bytes;
6919d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_OBJECTS:
6929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_objects;
6939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_BYTES:
6949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_bytes;
6959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_GC_INVOCATIONS:
6969d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->gc_for_alloc_count;
6979d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_COUNT:
6989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->class_init_count;
6999d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_TIME:
7009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // Convert ns to us, reduce to 32 bits.
7019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return (int) (stats->class_init_time_ns / 1000);
7029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_OBJECTS:
7039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_BYTES:
7049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_OBJECTS:
7059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_BYTES:
7069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return 0;  // backward compatibility
7079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  default:
7089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    CHECK(false);
7099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return -1; // unreachable
7109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
7119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
7129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
713c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Runtime::BlockSignals() {
714c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  sigset_t sigset;
715c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigemptyset(&sigset) == -1) {
716c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(FATAL) << "sigemptyset failed";
717c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
718c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGPIPE) == -1) {
719c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGPIPE failed";
720c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
721c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGQUIT is used to dump the runtime's state (including stack traces).
722c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGQUIT) == -1) {
723c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGQUIT failed";
724c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
725c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGUSR1 is used to initiate a heap dump.
726c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGUSR1) == -1) {
727c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGUSR1 failed";
728c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
729c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0);
730c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
731c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
7325fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughesvoid Runtime::AttachCurrentThread(const char* name, bool as_daemon) {
7335fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  Thread::Attach(instance_, name, as_daemon);
73461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
73561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
736d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Runtime::DetachCurrentThread() {
737038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // TODO: check we're not calling DetachCurrentThread from a call stack that
738038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // includes managed frames. (It's only valid if the stack is all-native.)
73902b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes  thread_list_->Unregister();
7407b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
7417b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
742e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
743bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  Dbg::VisitRoots(visitor, arg);
744e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  class_linker_->VisitRoots(visitor, arg);
745e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  intern_table_->VisitRoots(visitor, arg);
746e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  java_vm_->VisitRoots(visitor, arg);
747e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  thread_list_->VisitRoots(visitor, arg);
748e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  visitor(jni_stub_array_, arg);
749e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  visitor(abstract_method_error_stub_array_, arg);
7504f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
7514f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    visitor(resolution_stub_array_[i], arg);
7524f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
7534f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
7544f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    visitor(callee_save_method_[i], arg);
7554f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
756e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
757e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
758169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogersbool Runtime::HasJniDlsymLookupStub() const {
759e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return jni_stub_array_ != NULL;
760e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
761e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
762169c9a7f46776b235d0a37d5e0ff27682deffe06Ian RogersByteArray* Runtime::GetJniDlsymLookupStub() const {
763e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(jni_stub_array_ != NULL);
764e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return jni_stub_array_;
765e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
766e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
767169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogersvoid Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) {
768aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK(jni_stub_array != NULL)  << " jni_stub_array=" << jni_stub_array;
769aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array)
770aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array;
771e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  jni_stub_array_ = jni_stub_array;
772e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
773e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
774e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool Runtime::HasAbstractMethodErrorStubArray() const {
775e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return abstract_method_error_stub_array_ != NULL;
776e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
777e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
778e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromByteArray* Runtime::GetAbstractMethodErrorStubArray() const {
779e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array_ != NULL);
780e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return abstract_method_error_stub_array_;
781e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
782e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
783e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) {
784e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array != NULL);
785e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array);
786e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  abstract_method_error_stub_array_ = abstract_method_error_stub_array;
787e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
788e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
7891cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers
7901cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersRuntime::TrampolineType Runtime::GetTrampolineType(Method* method) {
7911cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  if (method == NULL) {
7921cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kUnknownMethod;
7931cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  } else if (method->IsStatic()) {
7941cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kStaticMethod;
7951cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  } else {
7961cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kInstanceMethod;
7971cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  }
7981cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers}
7991cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers
8001cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersbool Runtime::HasResolutionStubArray(TrampolineType type) const {
8011cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  return resolution_stub_array_[type] != NULL;
802ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
803ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
8041cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersByteArray* Runtime::GetResolutionStubArray(TrampolineType type) const {
8051cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  CHECK(HasResolutionStubArray(type));
8064f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType));
8071cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  return resolution_stub_array_[type];
808ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
809ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
8101cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersvoid Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type) {
811ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  CHECK(resolution_stub_array != NULL);
8121cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array);
8131cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  resolution_stub_array_[type] = resolution_stub_array;
814ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
815ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
816ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian CarlstromMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) {
817ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  Class* method_class = Method::GetMethodClass();
81840381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
819ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetDeclaringClass(method_class);
8206d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  // TODO: use a special method for callee saves
8216d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  method->SetMethodIndex(DexFile::kDexNoIndex16);
8223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  method->SetCode(NULL);
823ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
8244f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6)  | (1 << art::arm::R7) |
8254f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                          (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
8264f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
8274f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9);
8284f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills :0) |
8294f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                           (type == kSaveAll ? all_spills :0) | (1 << art::arm::LR);
8304f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_all_spills = (1 << art::arm::S0)  | (1 << art::arm::S1)  | (1 << art::arm::S2) |
8314f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S3)  | (1 << art::arm::S4)  | (1 << art::arm::S5) |
8324f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S6)  | (1 << art::arm::S7)  | (1 << art::arm::S8) |
8334f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S9)  | (1 << art::arm::S10) | (1 << art::arm::S11) |
8344f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) |
8354f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) |
8364f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) |
8374f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) |
8384f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) |
8394f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) |
8404f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S30) | (1 << art::arm::S31);
8414f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0;
8424f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
8434f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                                 __builtin_popcount(fp_spills) /* fprs */ +
8444f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                                 1 /* Method* */) * kPointerSize, kStackAlignment);
84515fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetFrameSizeInBytes(frame_size);
8464f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetCoreSpillMask(core_spills);
8474f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetFpSpillMask(fp_spills);
848ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  } else if (instruction_set == kX86) {
849ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFrameSizeInBytes(32);
8504f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetCoreSpillMask((1 << art::x86::EBX) | (1 << art::x86::EBP) | (1 << art::x86::ESI) |
851ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::x86::EDI));
852ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFpSpillMask(0);
853ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  } else {
854ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    UNIMPLEMENTED(FATAL);
855ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  }
85640381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  return method.get();
857ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers}
858ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers
8594f0d07c783afef89703dce32c94440fc8621a29bIan Rogersbool Runtime::HasCalleeSaveMethod(CalleeSaveType type) const {
8604f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  return callee_save_method_[type] != NULL;
861e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
862410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
863e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom// Returns a special method that describes all callee saves being spilled to the stack.
8644f0d07c783afef89703dce32c94440fc8621a29bIan RogersMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type) const {
8654f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  CHECK(HasCalleeSaveMethod(type));
8664f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  return callee_save_method_[type];
8671f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom}
8681f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom
8694f0d07c783afef89703dce32c94440fc8621a29bIan Rogersvoid Runtime::SetCalleeSaveMethod(Method* method, CalleeSaveType type) {
8704f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
8714f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  callee_save_method_[type] = method;
872e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
873e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
8742692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Runtime::EnableMethodTracing(Trace* tracer) {
8752692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  CHECK(!IsMethodTracingActive());
8762692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  tracer_ = tracer;
8772692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
8782692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
8792692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Runtime::DisableMethodTracing() {
8802692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  CHECK(IsMethodTracingActive());
8812692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  delete tracer_;
8822692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  tracer_ = NULL;
8832692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
8842692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
8852692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaobool Runtime::IsMethodTracingActive() const {
8862692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  return (tracer_ != NULL);
8872692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
8882692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
8892692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaoTrace* Runtime::GetTracer() const {
8902692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  CHECK(IsMethodTracingActive());
8912692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  return tracer_;
8922692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
8932692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
8946b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro}  // namespace art
895