runtime.cc revision 6c1c69eea21cce39dd043d89368a684d250c9abe
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
166b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro
17578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h"
187b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
19dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom#include <signal.h>
20dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom
21ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdio>
22ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdlib>
238a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom#include <limits>
242ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <vector>
25b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa#include <fstream>
26ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
27578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h"
28aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "class_loader.h"
290f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes#include "constants_arm.h"
300f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes#include "constants_x86.h"
313bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "debugger.h"
32578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "heap.h"
33e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "image.h"
34cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes#include "intern_table.h"
35c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h"
3632d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes#include "monitor.h"
37e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_file.h"
38726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes#include "ScopedLocalRef.h"
39e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#include "signal_catcher.h"
40457005c557b8762475db3220ce5a747d629f975bElliott Hughes#include "signal_set.h"
41e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "space.h"
42578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h"
438daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h"
44b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao#include "trace.h"
453bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "UniquePtr.h"
46776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#include "verifier/method_verifier.h"
4761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
4890a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes// TODO: this drags in cutil/log.h, which conflicts with our logging.h.
4990a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "JniConstants.h"
5090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes
516b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art {
527b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
532ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::instance_ = NULL;
542ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
55dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesRuntime::Runtime()
56d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    : is_compiler_(false),
57d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      is_zygote_(false),
580a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom      default_stack_size_(Thread::kDefaultStackSize),
59b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      heap_(NULL),
60c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes      monitor_list_(NULL),
61dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      thread_list_(NULL),
62dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      intern_table_(NULL),
63dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      class_linker_(NULL),
64dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      signal_catcher_(NULL),
65dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      java_vm_(NULL),
66161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom      jni_stub_array_(NULL),
67e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      abstract_method_error_stub_array_(NULL),
681984651929744dd603fd082e23eacd877b9bc177Ian Rogers      resolution_method_(NULL),
697c3757fb51450d0669883c82375040ece051e189Ian Rogers      system_class_loader_(NULL),
706b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes      shutting_down_(false),
71dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      started_(false),
72dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      vfprintf_(NULL),
73dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      exit_(NULL),
749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      abort_(NULL),
752692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao      stats_enabled_(false),
76776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers      method_trace_(0),
77776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers      method_trace_file_size_(0),
78b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      tracer_(NULL),
79b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      use_compile_time_class_path_(false) {
804f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
814f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    resolution_stub_array_[i] = NULL;
824f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
834f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
844f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    callee_save_method_[i] = NULL;
854f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
86dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
87dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
8861e019d291583029c01b61b93bea750f2b663c37Carl ShapiroRuntime::~Runtime() {
896b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes  shutting_down_ = true;
906b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes
91b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  if (IsMethodTracingActive()) {
92b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    Trace::Shutdown();
93b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  }
94b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
955fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // Make sure our internal threads are dead before we start tearing down things they're using.
96e52e49b32f5cf862a414da63e5dbd2eb04ad758eElliott Hughes  Dbg::StopJdwp();
975fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  delete signal_catcher_;
985fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes
99038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
10093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes  delete thread_list_;
101c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes  delete monitor_list_;
10293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes
10361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  delete class_linker_;
104b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  delete heap_;
105dd361c9eab3284e76e2d07c2e7d371b0f5269942Logan Chien#if defined(ART_USE_LLVM_COMPILER)
106776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers  verifier::MethodVerifier::DeleteInferredRegCategoryMaps();
107dd361c9eab3284e76e2d07c2e7d371b0f5269942Logan Chien#endif
108776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers  verifier::MethodVerifier::DeleteGcMaps();
109cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  delete intern_table_;
110c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes  delete java_vm_;
111c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  Thread::Shutdown();
1124acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
1134a289ed61242964b921434de7d375f46480472a1Brian Carlstrom  CHECK(instance_ == NULL || instance_ == this);
1144acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  instance_ = NULL;
11561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
11661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
117cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughesstatic bool gAborting = false;
118cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes
119e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughesstruct AbortState {
120e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  void Dump(std::ostream& os) {
121cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes    if (gAborting) {
122cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes      os << "Runtime aborting --- recursively, so no thread-specific detail!\n";
123cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes      return;
124cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes    }
125cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes    gAborting = true;
126e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    os << "Runtime aborting...\n";
1276c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes    if (Runtime::Current() == NULL) {
1286c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes      os << "(Runtime does not yet exist!)\n";
1296c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes      return;
1306c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes    }
131e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    Thread* self = Thread::Current();
132e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    if (self == NULL) {
133e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes      os << "(Aborting thread was not attached to runtime!)\n";
134e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    } else {
135899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes      self->Dump(os);
136899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes      if (self->IsExceptionPending()) {
137899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes        os << "Pending " << PrettyTypeOf(self->GetException()) << " on thread:\n"
138899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes           << self->GetException()->Dump();
139899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes      }
140e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    }
141e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  }
142e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes};
143e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes
144b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughesstatic Mutex& GetAbortLock() {
145b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  static Mutex abort_lock("abort lock");
146b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  return abort_lock;
147b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes}
148b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
1498593fdbacf97261f790ca53ea0ec416f57c987a7Elliott Hughesvoid Runtime::Abort() {
150131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes  // Ensure that we don't have multiple threads trying to abort at once,
151131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes  // which would result in significantly worse diagnostics.
152b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  MutexLock mu(GetAbortLock());
153131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes
154ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Get any pending output out of the way.
155ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  fflush(NULL);
156ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
157ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Many people have difficulty distinguish aborts from crashes,
158ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // so be explicit.
159e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  AbortState state;
1609ee5f9ccba015beb3ae376ed08b3363bd9df6422Elliott Hughes  LOG(INTERNAL_FATAL) << Dumpable<AbortState>(state);
161ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
1628593fdbacf97261f790ca53ea0ec416f57c987a7Elliott Hughes  // Call the abort hook if we have one.
1636ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) {
1646c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes    LOG(INTERNAL_FATAL) << "Calling abort hook...";
1656ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    Runtime::Current()->abort_();
1666ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    // notreached
1676c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes    LOG(INTERNAL_FATAL) << "Unexpectedly returned from abort hook!";
1686ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
1696ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
1706c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes  // TODO: finish merging patches to fix abort(3) in bionic, then lose this!
1716c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes  // Bionic doesn't implement POSIX semantics for abort(3) in a multi-threaded
1726c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes  // process, so if we call abort(3) on a device, all threads in the process
17369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // receive SIGABRT.  debuggerd dumps the stack trace of the main
17469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // thread, whether or not that was the thread that failed.  By
17569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // stuffing a value into a bogus address, we cause a segmentation
176ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // fault in the current thread, and get a useful log from debuggerd.
17781ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // We can also trivially tell the difference between a crash and
178ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // a deliberate abort by looking at the fault address.
179ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  *reinterpret_cast<char*>(0xdeadd00d) = 38;
180ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  abort();
181ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // notreached
182ffe6736397d17457188727510f0a2953f69a383aElliott Hughes}
183ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
184bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid Runtime::CallExitHook(jint status) {
185bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (exit_ != NULL) {
18634e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes    ScopedThreadStateChange tsc(Thread::Current(), kNative);
187bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    exit_(status);
188bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    LOG(WARNING) << "Exit hook returned instead of exiting!";
189bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
190bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
191bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1928a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
1938a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// memory sizes.  [kK] indicates kilobytes, [mM] megabytes, and
1948a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// [gG] gigabytes.
1958a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1968a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "s" should point just past the "-Xm?" part of the string.
1978a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "div" specifies a divisor, e.g. 1024 if the value must be a multiple
1988a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// of 1024.
1998a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
2008a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// The spec says the -Xmx and -Xms options must be multiples of 1024.  It
2018a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// doesn't say anything about -Xss.
2028a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
2038a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Returns 0 (a useless size) if "s" is malformed or specifies a low or
2048a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// non-evenly-divisible value.
2058a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
206c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughessize_t ParseMemoryOption(const char* s, size_t div) {
2078a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // strtoul accepts a leading [+-], which we don't want,
2088a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // so make sure our string starts with a decimal digit.
2098a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  if (isdigit(*s)) {
210398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes    char* s2;
211398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes    size_t val = strtoul(s, &s2, 10);
2128a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (s2 != s) {
2138a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // s2 should be pointing just after the number.
2148a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // If this is the end of the string, the user
2158a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // has specified a number of bytes.  Otherwise,
2168a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // there should be exactly one more character
2178a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // that specifies a multiplier.
2188a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (*s2 != '\0') {
219f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // The remainder of the string is either a single multiplier
220f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // character, or nothing to indicate that the value is in
221f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // bytes.
222f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        char c = *s2++;
223f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (*s2 == '\0') {
224f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          size_t mul;
225f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (c == '\0') {
226f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = 1;
227f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'k' || c == 'K') {
228f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = KB;
229f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'm' || c == 'M') {
230f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = MB;
231f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'g' || c == 'G') {
232f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = GB;
2338a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          } else {
234f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Unknown multiplier character.
2358a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom            return 0;
2368a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          }
237f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
238f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (val <= std::numeric_limits<size_t>::max() / mul) {
239f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val *= mul;
240f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else {
241f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Clamp to a multiple of 1024.
242f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val = std::numeric_limits<size_t>::max() & ~(1024-1);
243f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          }
244f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        } else {
245f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          // There's more than one character after the numeric part.
246f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          return 0;
247f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2488a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
2498a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // The man page says that a -Xm value must be a multiple of 1024.
2508a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (val % div == 0) {
2518a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom        return val;
2528a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
253fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
254fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
2558a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  return 0;
256fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
257fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
258f1a5adc87760f938b01df26d906295063546b259Elliott Hughessize_t ParseIntegerOrDie(const std::string& s) {
259f1a5adc87760f938b01df26d906295063546b259Elliott Hughes  std::string::size_type colon = s.find(':');
260f1a5adc87760f938b01df26d906295063546b259Elliott Hughes  if (colon == std::string::npos) {
261bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    LOG(FATAL) << "Missing integer: " << s;
262bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  }
263f1a5adc87760f938b01df26d906295063546b259Elliott Hughes  const char* begin = &s[colon + 1];
264bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  char* end;
265bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  size_t result = strtoul(begin, &end, 10);
266bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  if (begin == end || *end != '\0') {
267bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    LOG(FATAL) << "Failed to parse integer in: " << s;
268bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  }
269bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  return result;
270bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes}
271bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes
2720af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesvoid LoadJniLibrary(JavaVMExt* vm, const char* name) {
2736cc332ef80edf56221676e33ea16bb4022130344Elliott Hughes  std::string mapped_name(StringPrintf(OS_SHARED_LIB_FORMAT_STR, name));
2747577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  std::string reason;
2757577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  if (!vm->LoadNativeLibrary(mapped_name, NULL, reason)) {
2760af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": "
2770af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes               << reason;
2780af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  }
2790af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes}
2800af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
2816ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian CarlstromRuntime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
28290a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> parsed(new ParsedOptions());
283a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  const char* boot_class_path_string = getenv("BOOTCLASSPATH");
284a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  if (boot_class_path_string != NULL) {
285a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    parsed->boot_class_path_string_ = boot_class_path_string;
28658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
287a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  const char* class_path_string = getenv("CLASSPATH");
288a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  if (class_path_string != NULL) {
289a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    parsed->class_path_string_ = class_path_string;
29058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
29167d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes  // -Xcheck:jni is off by default for regular builds but on by default in debug builds.
29267d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes  parsed->check_jni_ = kIsDebugBuild;
29385d1545e985ac689db4bad7849880e843707c862Elliott Hughes
2946ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_initial_size_ = Heap::kInitialSize;
2956ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_maximum_size_ = Heap::kMaximumSize;
296c11607024d2e7a52ca690b8339306cab040e6653jeffhao  parsed->heap_growth_limit_ = 0;  // 0 means no growth limit
297f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom  parsed->stack_size_ = Thread::kDefaultStackSize;
298f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
299d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  parsed->is_compiler_ = false;
3009ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  parsed->is_zygote_ = false;
3019ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
302bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  parsed->jni_globals_max_ = 0;
303fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes  parsed->lock_profiling_threshold_ = 0;
304fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes  parsed->hook_is_sensitive_thread_ = NULL;
305fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes
3066ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_vfprintf_ = vfprintf;
3076ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_exit_ = exit;
3086c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes  parsed->hook_abort_ = NULL; // We don't call abort(3) by default; see Runtime::Abort.
3096c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes#if defined(__APPLE__)
3106c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes  parsed->hook_abort_ = abort; // On the Mac, abort(3) gives better results; see Runtime::InitPlatformSignalHandlers.
3116c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes#endif
3128a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
313b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.class_linker = true; // TODO: don't check this in!
314b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.compiler = true; // TODO: don't check this in!
315b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.heap = true; // TODO: don't check this in!
316b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.gc = true; // TODO: don't check this in!
317b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.jdwp = true; // TODO: don't check this in!
318b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.jni = true; // TODO: don't check this in!
319b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.monitor = true; // TODO: don't check this in!
320b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.startup = true; // TODO: don't check this in!
321b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.third_party_jni = true; // TODO: don't check this in!
322b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes//  gLogVerbosity.threads = true; // TODO: don't check this in!
323b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
324b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  parsed->method_trace_ = false;
325b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  parsed->method_trace_file_ = "/data/method-trace-file.bin";
326b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  parsed->method_trace_file_size_ = 10 * MB;
327b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
3288a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  for (size_t i = 0; i < options.size(); ++i) {
329f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    const std::string option(options[i].first);
3300796af03edc06d92bb8d631f1c0c23befdae2315Brian Carlstrom    if (true && options[0].first == "-Xzygote") {
33158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      LOG(INFO) << "option[" << i << "]=" << option;
33258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    }
333f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    if (StartsWith(option, "-Xbootclasspath:")) {
334a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->boot_class_path_string_ = option.substr(strlen("-Xbootclasspath:")).data();
33569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option == "-classpath" || option == "-cp") {
33669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      // TODO: support -Djava.class.path
33769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      i++;
33869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      if (i == options.size()) {
33969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        // TODO: usage
34069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Missing required class path value for " << option;
34169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        return NULL;
34269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      }
343a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      const StringPiece& value = options[i].first;
344a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->class_path_string_ = value.data();
345a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    } else if (option == "bootclasspath") {
346a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->boot_class_path_
347a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom          = reinterpret_cast<const std::vector<const DexFile*>*>(options[i].second);
348f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Ximage:")) {
349a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->image_ = option.substr(strlen("-Ximage:")).data();
350f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xcheck:jni")) {
351515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes      parsed->check_jni_ = true;
352f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xrunjdwp:") || StartsWith(option, "-agentlib:jdwp=")) {
353f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      std::string tail(option.substr(option[1] == 'X' ? 10 : 15));
3543bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes      if (tail == "help" || !Dbg::ParseJdwpOptions(tail)) {
3553bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes        LOG(FATAL) << "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n"
3563bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes                   << "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n";
3573bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes        return NULL;
3583bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes      }
359f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xms")) {
360f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).c_str(), 1024);
361f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
362f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
363f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
364f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
3654a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
36669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
367f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
368f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
369f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_initial_size_ = size;
370f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xmx")) {
371f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).c_str(), 1024);
372f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
373f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
374f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
375f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
3764a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
37769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
378f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
379f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
380f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_maximum_size_ = size;
381f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-XX:HeapGrowthLimit=")) {
382f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapGrowthLimit=")).c_str(), 1024);
383c11607024d2e7a52ca690b8339306cab040e6653jeffhao      if (size == 0) {
384c11607024d2e7a52ca690b8339306cab040e6653jeffhao        if (ignore_unrecognized) {
385c11607024d2e7a52ca690b8339306cab040e6653jeffhao          continue;
386c11607024d2e7a52ca690b8339306cab040e6653jeffhao        }
387c11607024d2e7a52ca690b8339306cab040e6653jeffhao        // TODO: usage
388c11607024d2e7a52ca690b8339306cab040e6653jeffhao        LOG(FATAL) << "Failed to parse " << option;
389c11607024d2e7a52ca690b8339306cab040e6653jeffhao        return NULL;
390c11607024d2e7a52ca690b8339306cab040e6653jeffhao      }
391c11607024d2e7a52ca690b8339306cab040e6653jeffhao      parsed->heap_growth_limit_ = size;
392f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xss")) {
393f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).c_str(), 1);
394f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
395f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
396f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
397f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
3984a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
39969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
400f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
401f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
402f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->stack_size_ = size;
403f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-D")) {
404f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      parsed->properties_.push_back(option.substr(strlen("-D")));
405f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xjnitrace:")) {
406f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:"));
4075de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom    } else if (option == "compiler") {
408d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      parsed->is_compiler_ = true;
4099ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes    } else if (option == "-Xzygote") {
4109ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes      parsed->is_zygote_ = true;
411f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-verbose:")) {
4120af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      std::vector<std::string> verbose_options;
413f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      Split(option.substr(strlen("-verbose:")), ',', verbose_options);
4140af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      for (size_t i = 0; i < verbose_options.size(); ++i) {
4154dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        if (verbose_options[i] == "class") {
4164dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.class_linker = true;
4174dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "compiler") {
4184dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.compiler = true;
4194dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "heap") {
4204dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.heap = true;
4214dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "gc") {
4224dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.gc = true;
4234dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "jdwp") {
4244dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.jdwp = true;
4254dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "jni") {
4264dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.jni = true;
4274dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "monitor") {
4284dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.monitor = true;
4294dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "startup") {
4304dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.startup = true;
4314dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "third-party-jni") {
4324dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.third_party_jni = true;
4334dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "threads") {
4344dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.threads = true;
435b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa        } else if (StartsWith(verbose_options[i], "log-to=")) {
436b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa          std::string log_file_name(verbose_options[i].substr(strlen("log-to=")));
437b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa          std::ofstream* log_file = new std::ofstream(log_file_name.c_str());
438b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa          if (log_file->is_open() && log_file->good()) {
439b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa            gLogVerbosity.SetLoggingStream(log_file);
440b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa          } else {
441b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa            LOG(ERROR) << "Fail to open log file: \"" << log_file_name << "\","
442b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa                       << " use default logging stream.";
443b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60TDYa          }
4444dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else {
4454dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i];
4464dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        }
4470af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      }
448f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xjnigreflimit:")) {
449bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes      parsed->jni_globals_max_ = ParseIntegerOrDie(option);
450f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xlockprofthreshold:")) {
451bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes      parsed->lock_profiling_threshold_ = ParseIntegerOrDie(option);
452f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xstacktracefile:")) {
45367d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes      if (kIsDebugBuild) {
45467d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes        // Ignore the zygote and always show stack traces in debug builds.
45567d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes      } else {
45667d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes        parsed->stack_trace_file_ = option.substr(strlen("-Xstacktracefile:"));
45767d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes      }
458fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes    } else if (option == "sensitiveThread") {
459fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes      parsed->hook_is_sensitive_thread_ = reinterpret_cast<bool (*)()>(options[i].second);
4606ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "vfprintf") {
4616ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_vfprintf_ = reinterpret_cast<int (*)(FILE *, const char*, va_list)>(options[i].second);
4626ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "exit") {
4636ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second);
4646ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "abort") {
4656ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second);
46658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option == "host-prefix") {
46758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second);
468b3e66dfcd069db8818cd902d787ff1d7bbca45f2Elliott Hughes    } else if (option == "-Xgenregmap" || option == "-Xgc:precise") {
469b3e66dfcd069db8818cd902d787ff1d7bbca45f2Elliott Hughes      // We silently ignore these for backwards compatibility.
470b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    } else if (option == "-Xmethod-trace") {
471b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      parsed->method_trace_ = true;
472b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    } else if (StartsWith(option, "-Xmethod-trace-file:")) {
473b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      parsed->method_trace_file_ = option.substr(strlen("-Xmethod-trace-file:"));
474b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    } else if (StartsWith(option, "-Xmethod-trace-file-size:")) {
475b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      parsed->method_trace_file_size_ = ParseIntegerOrDie(option);
4768a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else {
4778a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (!ignore_unrecognized) {
4786ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom        // TODO: print usage via vfprintf
47927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        LOG(ERROR) << "Unrecognized option " << option;
48027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        // TODO: this should exit, but for now tolerate unknown options
48127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        //return NULL;
4828a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
4838a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    }
4848a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  }
4858a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
486223f20fa939c386c695977263780dea2195093dbBrian Carlstrom  if (!parsed->is_compiler_ && parsed->image_.empty()) {
487223f20fa939c386c695977263780dea2195093dbBrian Carlstrom    parsed->image_ += GetAndroidRoot();
488223f20fa939c386c695977263780dea2195093dbBrian Carlstrom    parsed->image_ += "/framework/boot.art";
4895de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom  }
490c11607024d2e7a52ca690b8339306cab040e6653jeffhao  if (parsed->heap_growth_limit_ == 0) {
491c11607024d2e7a52ca690b8339306cab040e6653jeffhao    parsed->heap_growth_limit_ = parsed->heap_maximum_size_;
492c11607024d2e7a52ca690b8339306cab040e6653jeffhao  }
4935de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom
494cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  LOG(INFO) << "Build type: "
49567d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes            << (kIsDebugBuild ? "debug" : "optimized")
496cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes            << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off");
49785d1545e985ac689db4bad7849880e843707c862Elliott Hughes
49869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return parsed.release();
4998a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom}
5008a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
5018a436595d36c1e4935984fcac249d7d877e00383Brian CarlstromRuntime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
5022ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
5032ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  if (Runtime::instance_ != NULL) {
5042ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro    return NULL;
5052ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  }
506dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  instance_ = new Runtime;
507dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  if (!instance_->Init(options, ignore_unrecognized)) {
508dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    delete instance_;
509dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    instance_ = NULL;
51061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  }
51169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return instance_;
51269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
5130af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
514aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromvoid CreateSystemClassLoader() {
515b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (Runtime::Current()->UseCompileTimeClassPath()) {
516aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return;
517aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
518aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
519aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  Thread* self = Thread::Current();
520aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
521aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  // Must be in the kNative state for calling native methods.
52234e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes  CHECK_EQ(self->GetState(), kNative);
523aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
524aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  JNIEnv* env = self->GetJniEnv();
525df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader"));
526df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(ClassLoader_class.get() != NULL);
527df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(),
528df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                          "getSystemClassLoader",
529df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                          "()Ljava/lang/ClassLoader;");
530df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(getSystemClassLoader != NULL);
531df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(),
532df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                                        getSystemClassLoader));
533df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(class_loader.get() != NULL);
534df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom
535df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get()));
5361b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson
5371b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  ScopedLocalRef<jclass> Thread_class(env, env->FindClass("java/lang/Thread"));
5381b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  CHECK(Thread_class.get() != NULL);
5391b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  jfieldID contextClassLoader = env->GetFieldID(Thread_class.get(),
5401b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson                                                "contextClassLoader",
5411b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson                                                "Ljava/lang/ClassLoader;");
5421b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  CHECK(contextClassLoader != NULL);
5431b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  ScopedLocalRef<jobject> self_jobject(env, AddLocalReference<jobject>(env, self->GetPeer()));
5441b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  env->SetObjectField(self_jobject.get(), contextClassLoader, class_loader.get());
545aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
546aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
54769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromvoid Runtime::Start() {
5484dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Start entering";
54958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
55058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  CHECK(host_prefix_.empty()) << host_prefix_;
55158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
5520c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien  // Relocate the OatFiles (ELF images)
5530c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien  class_linker_->RelocateExecutable();
5540c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien
555f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom  // Restore main thread state to kNative as expected by native code
55634e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes  Thread::Current()->SetState(kNative);
557f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom
5585d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  started_ = true;
5595d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom
560ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // InitNativeMethods needs to be after started_ so that the classes
561ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // it touches will have methods linked to the oat file if necessary.
562ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  InitNativeMethods();
563ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
5649a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson  Thread::FinishStartup();
5659a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson
566d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  if (!is_zygote_) {
567d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes    DidForkFromZygote();
568d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  }
5699ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
57085d1545e985ac689db4bad7849880e843707c862Elliott Hughes  StartDaemonThreads();
5710a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom
572aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CreateSystemClassLoader();
573aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
574726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  Thread::Current()->GetJniEnv()->locals.AssertEmpty();
575726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes
5764dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Start exiting";
57785d1545e985ac689db4bad7849880e843707c862Elliott Hughes}
57885d1545e985ac689db4bad7849880e843707c862Elliott Hughes
579caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::DidForkFromZygote() {
580caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  is_zygote_ = false;
581d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
582caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  StartSignalCatcher();
583d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
584d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
585d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // this will pause the runtime, so we probably want this to come last.
586d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  Dbg::StartJdwp();
587caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom}
588caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom
589caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::StartSignalCatcher() {
590caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  if (!is_zygote_) {
59194ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes    signal_catcher_ = new SignalCatcher(stack_trace_file_);
592caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  }
593caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom}
594caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom
59585d1545e985ac689db4bad7849880e843707c862Elliott Hughesvoid Runtime::StartDaemonThreads() {
5964dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::StartDaemonThreads entering";
59785d1545e985ac689db4bad7849880e843707c862Elliott Hughes
598719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  Thread* self = Thread::Current();
599aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
600aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  // Must be in the kNative state for calling native methods.
60134e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes  CHECK_EQ(self->GetState(), kNative);
602aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
603719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  JNIEnv* env = self->GetJniEnv();
604726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Daemons"));
605726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  CHECK(c.get() != NULL);
606726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V");
607719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  CHECK(mid != NULL);
608726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  env->CallStaticVoidMethod(c.get(), mid);
6098cf5bc0ab8742df107f0f4fc8ec0e991b6568f11Elliott Hughes  CHECK(!env->ExceptionCheck());
6109ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
6114dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::StartDaemonThreads exiting";
61261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
61361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
6146b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughesbool Runtime::IsShuttingDown() const {
6156b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes  return shutting_down_;
6166b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes}
6176b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes
61858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrombool Runtime::IsStarted() const {
619dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  return started_;
620dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
621dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
6220af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesbool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
623c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
6246ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
62590a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
62690a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  if (options.get() == NULL) {
627e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to parse options";
6286ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    return false;
6296ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
6304dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Init -verbose:startup enabled";
6317ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
632bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  SetJniGlobalsMax(options->jni_globals_max_);
6334dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
63432d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes
63558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  host_prefix_ = options->host_prefix_;
636a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  boot_class_path_string_ = options->boot_class_path_string_;
637a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  class_path_string_ = options->class_path_string_;
6387ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  properties_ = options->properties_;
6397ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
640d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  is_compiler_ = options->is_compiler_;
6419ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  is_zygote_ = options->is_zygote_;
6429ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
6430af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  vfprintf_ = options->hook_vfprintf_;
6440af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  exit_ = options->hook_exit_;
6450af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  abort_ = options->hook_abort_;
6466ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
647be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  default_stack_size_ = options->stack_size_;
64894ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes  stack_trace_file_ = options->stack_trace_file_;
6496ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
650c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes  monitor_list_ = new MonitorList;
6514dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  thread_list_ = new ThreadList;
652cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  intern_table_ = new InternTable;
653cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
654776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers  verifier::MethodVerifier::InitGcMaps();
655b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
656dd361c9eab3284e76e2d07c2e7d371b0f5269942Logan Chien#if defined(ART_USE_LLVM_COMPILER)
657776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers  verifier::MethodVerifier::InitInferredRegCategoryMaps();
658dd361c9eab3284e76e2d07c2e7d371b0f5269942Logan Chien#endif
659dd361c9eab3284e76e2d07c2e7d371b0f5269942Logan Chien
660b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  heap_ = new Heap(options->heap_initial_size_,
661b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes                   options->heap_growth_limit_,
662b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes                   options->heap_maximum_size_,
663b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes                   options->image_);
6646ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
665c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  BlockSignals();
666457005c557b8762475db3220ce5a747d629f975bElliott Hughes  InitPlatformSignalHandlers();
667c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
668a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  java_vm_ = new JavaVMExt(this, options.get());
669515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes
670be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  Thread::Startup();
671d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
6725fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // ClassLinker needs an attached thread, but we can't fully attach a thread
673462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes  // without creating objects. We can't supply a thread group yet; it will be fixed later.
674462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes  Thread::Attach("main", false, NULL);
6756ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
676f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom  // Set us to runnable so tools using a runtime can allocate and GC by default
67734e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes  Thread::Current()->SetState(kRunnable);
678f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom
679141d62275f207bf68c55f583fb206fe586d857cfIan Rogers  // Now we're attached, we can take the heap lock and validate the heap.
680141d62275f207bf68c55f583fb206fe586d857cfIan Rogers  GetHeap()->EnableObjectValidation();
681141d62275f207bf68c55f583fb206fe586d857cfIan Rogers
682b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CHECK_GE(GetHeap()->GetSpaces().size(), 1U);
683b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (GetHeap()->GetSpaces()[0]->IsImageSpace()) {
684a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    class_linker_ = ClassLinker::CreateFromImage(intern_table_);
685a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  } else {
686a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    CHECK(options->boot_class_path_ != NULL);
687a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    CHECK_NE(options->boot_class_path_->size(), 0U);
688a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    class_linker_ = ClassLinker::CreateFromCompiler(*options->boot_class_path_, intern_table_);
689a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  }
690a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  CHECK(class_linker_ != NULL);
6916ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
692b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  method_trace_ = options->method_trace_;
693b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  method_trace_file_ = options->method_trace_file_;
694b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  method_trace_file_size_ = options->method_trace_file_size_;
695b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
696b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  if (options->method_trace_) {
697b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0, false);
698b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  }
699b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
7004dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Init exiting";
7017b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro  return true;
7027b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
7037b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
704038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Runtime::InitNativeMethods() {
7054dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::InitNativeMethods entering";
706ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread* self = Thread::Current();
707ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  JNIEnv* env = self->GetJniEnv();
708ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
709418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Must be in the kNative state for calling native methods (JNI_OnLoad code).
71034e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes  CHECK_EQ(self->GetState(), kNative);
711ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
712418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // First set up JniConstants, which is used by both the runtime's built-in native
713418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // methods and libcore.
714fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes  JniConstants::init(env);
715fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes
716418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up the native methods provided by the runtime itself.
717ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  RegisterRuntimeNativeMethods(env);
718ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
719418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad.
720418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's
721418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // the library that implements System.loadLibrary!
722ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  LoadJniLibrary(instance_->GetJavaVM(), "javacore");
7234dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::InitNativeMethods exiting";
724ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
725ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
726ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesvoid Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
727ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
7285167c97a4f672ba821453418e3943988fabbfc43Ian Rogers  // Register Throwable first so that registration of other native methods can throw exceptions
7295167c97a4f672ba821453418e3943988fabbfc43Ian Rogers  REGISTER(register_java_lang_Throwable);
730f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  REGISTER(register_dalvik_system_DexFile);
7319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  REGISTER(register_dalvik_system_VMDebug);
7327ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  REGISTER(register_dalvik_system_VMRuntime);
7338daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_dalvik_system_VMStack);
73401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  REGISTER(register_dalvik_system_Zygote);
735d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes  REGISTER(register_java_lang_Class);
736bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Object);
737bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Runtime);
738bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_String);
739bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_System);
7408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_java_lang_Thread);
74164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  REGISTER(register_java_lang_VMClassLoader);
7425b8e4c810a97c9dc417142b8c6e07871ae15c797Brian Carlstrom  REGISTER(register_java_lang_reflect_Array);
7432a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes  REGISTER(register_java_lang_reflect_Constructor);
744f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Field);
745f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Method);
74695caa791e560da97363c0c0d22bfda4a7e7377c3Jesse Wilson  REGISTER(register_java_lang_reflect_Proxy);
747bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_util_concurrent_atomic_AtomicLong);
748395520eaa47eca25b92e86188accf3095d60af49Brian Carlstrom  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
749f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal);
7505ee7a8b56dee896245e0f4ae5215f8b7376c1787Elliott Hughes  REGISTER(register_sun_misc_Unsafe);
751ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#undef REGISTER
752ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
753ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
754c967f78cd29b6019f7cfca40a02e9b677112da70Elliott Hughesvoid Runtime::DumpForSigQuit(std::ostream& os) {
755cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  GetClassLinker()->DumpForSigQuit(os);
756cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  GetInternTable()->DumpForSigQuit(os);
757c967f78cd29b6019f7cfca40a02e9b677112da70Elliott Hughes  GetHeap()->DumpForSigQuit(os);
75842ee14279065352a4b9a3e8028d02c567e847d05Elliott Hughes  os << "\n";
7598daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
760c967f78cd29b6019f7cfca40a02e9b677112da70Elliott Hughes  thread_list_->DumpForSigQuit(os);
761e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes}
762e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
76321a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughesvoid Runtime::DumpLockHolders(std::ostream& os) {
764b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  pid_t heap_lock_owner = GetHeap()->GetLockOwner();
76521a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t thread_list_lock_owner = GetThreadList()->GetLockOwner();
76621a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t classes_lock_owner = GetClassLinker()->GetClassesLockOwner();
76721a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t dex_lock_owner = GetClassLinker()->GetDexLockOwner();
76821a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  if ((heap_lock_owner | thread_list_lock_owner | classes_lock_owner | dex_lock_owner) != 0) {
76921a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes    os << "Heap lock owner tid: " << heap_lock_owner << "\n"
77021a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ThreadList lock owner tid: " << thread_list_lock_owner << "\n"
77121a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ClassLinker classes lock owner tid: " << classes_lock_owner << "\n"
77221a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ClassLinker dex lock owner tid: " << dex_lock_owner << "\n";
77321a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  }
77421a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes}
77521a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes
7769d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::SetStatsEnabled(bool new_state) {
7779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (new_state == true) {
7789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    GetStats()->Clear(~0);
7799d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // TODO: wouldn't it make more sense to clear _all_ threads' stats?
7809d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    Thread::Current()->GetStats()->Clear(~0);
7819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
7829d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  stats_enabled_ = new_state;
7839d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
7849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
7859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::ResetStats(int kinds) {
7869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  GetStats()->Clear(kinds & 0xffff);
7879d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  // TODO: wouldn't it make more sense to clear _all_ threads' stats?
7889d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  Thread::Current()->GetStats()->Clear(kinds >> 16);
7899d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
7909d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
7919d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott HughesRuntimeStats* Runtime::GetStats() {
7929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return &stats_;
7939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
7949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
7959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesint32_t Runtime::GetStat(int kind) {
7969d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  RuntimeStats* stats;
7979d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (kind < (1<<16)) {
7989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = GetStats();
7999d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  } else {
8009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = Thread::Current()->GetStats();
8019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    kind >>= 16;
8029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
8039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  switch (kind) {
8049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_OBJECTS:
8059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_objects;
8069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_BYTES:
8079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_bytes;
8089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_OBJECTS:
8099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_objects;
8109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_BYTES:
8119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_bytes;
8129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_GC_INVOCATIONS:
8139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->gc_for_alloc_count;
8149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_COUNT:
8159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->class_init_count;
8169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_TIME:
8179d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // Convert ns to us, reduce to 32 bits.
818398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes    return static_cast<int>(stats->class_init_time_ns / 1000);
8199d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_OBJECTS:
8209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_BYTES:
8219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_OBJECTS:
8229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_BYTES:
8239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return 0;  // backward compatibility
8249d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  default:
8257b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes    LOG(FATAL) << "Unknown statistic " << kind;
8269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return -1; // unreachable
8279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
8289d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
8299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
830c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Runtime::BlockSignals() {
831457005c557b8762475db3220ce5a747d629f975bElliott Hughes  SignalSet signals;
832457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Add(SIGPIPE);
833c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGQUIT is used to dump the runtime's state (including stack traces).
834457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Add(SIGQUIT);
8350879504b6ac72f6d93dcccf9e1b7e1769a73b230Elliott Hughes  // SIGUSR1 is used to initiate a GC.
836457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Add(SIGUSR1);
837457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Block();
838c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
839c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
840462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughesvoid Runtime::AttachCurrentThread(const char* thread_name, bool as_daemon, Object* thread_group) {
841462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes  Thread::Attach(thread_name, as_daemon, thread_group);
84222869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes  if (thread_name == NULL) {
84322869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes    LOG(WARNING) << *Thread::Current() << " attached without supplying a name";
84422869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes  }
84561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
84661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
847d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Runtime::DetachCurrentThread() {
84822869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes  if (Thread::Current()->GetTopOfStack().GetSP() != NULL) {
84922869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes    LOG(FATAL) << *Thread::Current() << " attempting to detach while still running code";
85022869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes  }
85102b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes  thread_list_->Unregister();
8527b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
8537b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
854e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
855bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  Dbg::VisitRoots(visitor, arg);
856e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  class_linker_->VisitRoots(visitor, arg);
857e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  intern_table_->VisitRoots(visitor, arg);
858e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  java_vm_->VisitRoots(visitor, arg);
859e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  thread_list_->VisitRoots(visitor, arg);
860e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  visitor(jni_stub_array_, arg);
861e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  visitor(abstract_method_error_stub_array_, arg);
8624f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
8634f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    visitor(resolution_stub_array_[i], arg);
8644f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
8651984651929744dd603fd082e23eacd877b9bc177Ian Rogers  visitor(resolution_method_, arg);
8664f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
8674f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    visitor(callee_save_method_[i], arg);
8684f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
869e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
870e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
871169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogersbool Runtime::HasJniDlsymLookupStub() const {
872e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return jni_stub_array_ != NULL;
873e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
874e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
875169c9a7f46776b235d0a37d5e0ff27682deffe06Ian RogersByteArray* Runtime::GetJniDlsymLookupStub() const {
876e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(jni_stub_array_ != NULL);
877e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return jni_stub_array_;
878e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
879e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
880169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogersvoid Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) {
881aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK(jni_stub_array != NULL)  << " jni_stub_array=" << jni_stub_array;
882aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array)
883aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array;
884e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  jni_stub_array_ = jni_stub_array;
885e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
886e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
887e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool Runtime::HasAbstractMethodErrorStubArray() const {
888e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return abstract_method_error_stub_array_ != NULL;
889e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
890e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
891e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromByteArray* Runtime::GetAbstractMethodErrorStubArray() const {
892e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array_ != NULL);
893e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return abstract_method_error_stub_array_;
894e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
895e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
896e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) {
897e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array != NULL);
898e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array);
899e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  abstract_method_error_stub_array_ = abstract_method_error_stub_array;
900e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
901e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
9021cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers
9031cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersRuntime::TrampolineType Runtime::GetTrampolineType(Method* method) {
9041cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  if (method == NULL) {
9051cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kUnknownMethod;
9061cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  } else if (method->IsStatic()) {
9071cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kStaticMethod;
9081cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  } else {
909fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers    return Runtime::kUnknownMethod;
9101cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  }
9111cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers}
9121cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers
9131cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersbool Runtime::HasResolutionStubArray(TrampolineType type) const {
9141cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  return resolution_stub_array_[type] != NULL;
915ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
916ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
9171cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersByteArray* Runtime::GetResolutionStubArray(TrampolineType type) const {
9181cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  CHECK(HasResolutionStubArray(type));
9194f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType));
9201cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  return resolution_stub_array_[type];
921ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
922ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
9231cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersvoid Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type) {
924ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  CHECK(resolution_stub_array != NULL);
9251cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array);
9261cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  resolution_stub_array_[type] = resolution_stub_array;
927ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
928ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
9291984651929744dd603fd082e23eacd877b9bc177Ian RogersMethod* Runtime::CreateResolutionMethod() {
9301984651929744dd603fd082e23eacd877b9bc177Ian Rogers  Class* method_class = Method::GetMethodClass();
9311984651929744dd603fd082e23eacd877b9bc177Ian Rogers  SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
9321984651929744dd603fd082e23eacd877b9bc177Ian Rogers  method->SetDeclaringClass(method_class);
9331984651929744dd603fd082e23eacd877b9bc177Ian Rogers  // TODO: use a special method for resolution method saves
9341984651929744dd603fd082e23eacd877b9bc177Ian Rogers  method->SetDexMethodIndex(DexFile::kDexNoIndex16);
9351984651929744dd603fd082e23eacd877b9bc177Ian Rogers  ByteArray* unknown_resolution_stub = GetResolutionStubArray(kUnknownMethod);
9361984651929744dd603fd082e23eacd877b9bc177Ian Rogers  CHECK(unknown_resolution_stub != NULL);
9371984651929744dd603fd082e23eacd877b9bc177Ian Rogers  method->SetCode(unknown_resolution_stub->GetData());
9381984651929744dd603fd082e23eacd877b9bc177Ian Rogers  return method.get();
9391984651929744dd603fd082e23eacd877b9bc177Ian Rogers}
9401984651929744dd603fd082e23eacd877b9bc177Ian Rogers
9411984651929744dd603fd082e23eacd877b9bc177Ian Rogersbool Runtime::HasResolutionMethod() const {
9421984651929744dd603fd082e23eacd877b9bc177Ian Rogers  return resolution_method_ != NULL;
9431984651929744dd603fd082e23eacd877b9bc177Ian Rogers}
9441984651929744dd603fd082e23eacd877b9bc177Ian Rogers
9451984651929744dd603fd082e23eacd877b9bc177Ian Rogers// Returns a special method that calls into a trampoline for runtime method resolution
9461984651929744dd603fd082e23eacd877b9bc177Ian RogersMethod* Runtime::GetResolutionMethod() const {
9471984651929744dd603fd082e23eacd877b9bc177Ian Rogers  CHECK(HasResolutionMethod());
9481984651929744dd603fd082e23eacd877b9bc177Ian Rogers  return resolution_method_;
9491984651929744dd603fd082e23eacd877b9bc177Ian Rogers}
9501984651929744dd603fd082e23eacd877b9bc177Ian Rogers
9511984651929744dd603fd082e23eacd877b9bc177Ian Rogersvoid Runtime::SetResolutionMethod(Method* method) {
9521984651929744dd603fd082e23eacd877b9bc177Ian Rogers  resolution_method_ = method;
9531984651929744dd603fd082e23eacd877b9bc177Ian Rogers}
9541984651929744dd603fd082e23eacd877b9bc177Ian Rogers
955ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian CarlstromMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) {
956ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  Class* method_class = Method::GetMethodClass();
95740381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
958ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetDeclaringClass(method_class);
9596d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  // TODO: use a special method for callee saves
9601984651929744dd603fd082e23eacd877b9bc177Ian Rogers  method->SetDexMethodIndex(DexFile::kDexNoIndex16);
9613320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  method->SetCode(NULL);
962ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
9634f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6)  | (1 << art::arm::R7) |
9644f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                          (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
9654f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
9664f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9);
9674f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills :0) |
9684f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                           (type == kSaveAll ? all_spills :0) | (1 << art::arm::LR);
9694f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_all_spills = (1 << art::arm::S0)  | (1 << art::arm::S1)  | (1 << art::arm::S2) |
9704f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S3)  | (1 << art::arm::S4)  | (1 << art::arm::S5) |
9714f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S6)  | (1 << art::arm::S7)  | (1 << art::arm::S8) |
9724f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S9)  | (1 << art::arm::S10) | (1 << art::arm::S11) |
9734f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) |
9744f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) |
9754f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) |
9764f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) |
9774f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) |
9784f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) |
9794f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S30) | (1 << art::arm::S31);
9804f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0;
9814f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
9824f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                                 __builtin_popcount(fp_spills) /* fprs */ +
9834f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                                 1 /* Method* */) * kPointerSize, kStackAlignment);
98415fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetFrameSizeInBytes(frame_size);
9854f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetCoreSpillMask(core_spills);
9864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetFpSpillMask(fp_spills);
987ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  } else if (instruction_set == kX86) {
9887caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    uint32_t ref_spills = (1 << art::x86::EBP) | (1 << art::x86::ESI) | (1 << art::x86::EDI);
9897caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    uint32_t arg_spills = (1 << art::x86::ECX) | (1 << art::x86::EDX) | (1 << art::x86::EBX);
9907caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
9917caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers                         (1 << art::x86::kNumberOfCpuRegisters);  // fake return address callee save
9927caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
9937caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers                                 1 /* Method* */) * kPointerSize, kStackAlignment);
9947caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    method->SetFrameSizeInBytes(frame_size);
9957caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    method->SetCoreSpillMask(core_spills);
996ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFpSpillMask(0);
997ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  } else {
998ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    UNIMPLEMENTED(FATAL);
999ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  }
100040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  return method.get();
1001ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers}
1002ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers
10034f0d07c783afef89703dce32c94440fc8621a29bIan Rogersbool Runtime::HasCalleeSaveMethod(CalleeSaveType type) const {
10044f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  return callee_save_method_[type] != NULL;
1005e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1006410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
1007e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom// Returns a special method that describes all callee saves being spilled to the stack.
10084f0d07c783afef89703dce32c94440fc8621a29bIan RogersMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type) const {
10094f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  CHECK(HasCalleeSaveMethod(type));
10104f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  return callee_save_method_[type];
10111f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom}
10121f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom
10134f0d07c783afef89703dce32c94440fc8621a29bIan Rogersvoid Runtime::SetCalleeSaveMethod(Method* method, CalleeSaveType type) {
10144f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
10154f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  callee_save_method_[type] = method;
1016e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1017e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
10182692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Runtime::EnableMethodTracing(Trace* tracer) {
10192692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  CHECK(!IsMethodTracingActive());
10202692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  tracer_ = tracer;
10212692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
10222692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
10232692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Runtime::DisableMethodTracing() {
10242692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  CHECK(IsMethodTracingActive());
10252692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  delete tracer_;
10262692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  tracer_ = NULL;
10272692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
10282692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
10292692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaobool Runtime::IsMethodTracingActive() const {
10302692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  return (tracer_ != NULL);
10312692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
10322692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
10332692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaoTrace* Runtime::GetTracer() const {
10342692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  CHECK(IsMethodTracingActive());
10352692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  return tracer_;
10362692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
10372692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
1038b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughesconst std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(const ClassLoader* class_loader) {
1039b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (class_loader == NULL) {
1040b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    return GetClassLinker()->GetBootClassPath();
1041b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  }
1042b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CHECK(UseCompileTimeClassPath());
1043b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CompileTimeClassPaths::const_iterator it = compile_time_class_paths_.find(class_loader);
1044b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CHECK(it != compile_time_class_paths_.end());
1045b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  return it->second;
1046b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes}
1047b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
1048b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughesvoid Runtime::SetCompileTimeClassPath(const ClassLoader* class_loader, std::vector<const DexFile*>& class_path) {
1049b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CHECK(!IsStarted());
1050b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  use_compile_time_class_path_ = true;
1051a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  compile_time_class_paths_.Put(class_loader, class_path);
1052b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes}
1053b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
10546b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro}  // namespace art
1055