runtime.cc revision 9ca7a1fdd0daa546b790adb6a24dbc13c22df76a
16b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro// Copyright 2011 Google Inc. All Rights Reserved.
26b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro
3578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h"
47b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
5ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdio>
6ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdlib>
78a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom#include <limits>
82ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <vector>
9ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
10aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "ScopedLocalRef.h"
1190a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "UniquePtr.h"
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h"
13aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "class_loader.h"
14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "heap.h"
15e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "image.h"
16cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes#include "intern_table.h"
17c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h"
18e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_file.h"
19726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes#include "ScopedLocalRef.h"
20e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#include "signal_catcher.h"
21e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "space.h"
22578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h"
238daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h"
2461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
2590a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes// TODO: this drags in cutil/log.h, which conflicts with our logging.h.
2690a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "JniConstants.h"
2790a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes
286b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art {
297b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
302ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::instance_ = NULL;
312ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
32dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesRuntime::Runtime()
330a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom    : verbose_startup_(false),
349ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes      is_zygote_(false),
350a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom      default_stack_size_(Thread::kDefaultStackSize),
36dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      thread_list_(NULL),
37dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      intern_table_(NULL),
38dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      class_linker_(NULL),
39dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      signal_catcher_(NULL),
40dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      java_vm_(NULL),
41161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom      jni_stub_array_(NULL),
42e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      abstract_method_error_stub_array_(NULL),
43dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      started_(false),
44dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      vfprintf_(NULL),
45dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      exit_(NULL),
469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      abort_(NULL),
479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      stats_enabled_(false) {
484f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
494f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    resolution_stub_array_[i] = NULL;
504f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
514f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
524f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    callee_save_method_[i] = NULL;
534f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
54dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
55dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
5661e019d291583029c01b61b93bea750f2b663c37Carl ShapiroRuntime::~Runtime() {
575fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // Make sure our internal threads are dead before we start tearing down things they're using.
585fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  delete signal_catcher_;
59038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // TODO: GC thread.
605fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes
61038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
6293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes  delete thread_list_;
6393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes
6461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  delete class_linker_;
6569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Heap::Destroy();
66cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  delete intern_table_;
67c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes  delete java_vm_;
68c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  Thread::Shutdown();
694acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
704a289ed61242964b921434de7d375f46480472a1Brian Carlstrom  CHECK(instance_ == NULL || instance_ == this);
714acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  instance_ = NULL;
7261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
7361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
74ffe6736397d17457188727510f0a2953f69a383aElliott Hughesvoid Runtime::Abort(const char* file, int line) {
75ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Get any pending output out of the way.
76ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  fflush(NULL);
77ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
78ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Many people have difficulty distinguish aborts from crashes,
79ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // so be explicit.
80ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  LogMessage(file, line, ERROR, -1).stream() << "Runtime aborting...";
81ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
82ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Perform any platform-specific pre-abort actions.
83ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  PlatformAbort(file, line);
84ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
856ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  // use abort hook if we have one
866ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) {
876ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    Runtime::Current()->abort_();
886ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    // notreached
896ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
906ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
91ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // If we call abort(3) on a device, all threads in the process
9269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // receive SIGABRT.  debuggerd dumps the stack trace of the main
9369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // thread, whether or not that was the thread that failed.  By
9469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // stuffing a value into a bogus address, we cause a segmentation
95ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // fault in the current thread, and get a useful log from debuggerd.
96ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // We can also trivially tell the difference between a VM crash and
97ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // a deliberate abort by looking at the fault address.
98ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  *reinterpret_cast<char*>(0xdeadd00d) = 38;
99ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  abort();
100ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // notreached
101ffe6736397d17457188727510f0a2953f69a383aElliott Hughes}
102ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
103bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid Runtime::CallExitHook(jint status) {
104bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (exit_ != NULL) {
105bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative);
106bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    exit_(status);
107bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    LOG(WARNING) << "Exit hook returned instead of exiting!";
108bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
109bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
110bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1118a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
1128a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// memory sizes.  [kK] indicates kilobytes, [mM] megabytes, and
1138a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// [gG] gigabytes.
1148a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1158a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "s" should point just past the "-Xm?" part of the string.
1168a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "div" specifies a divisor, e.g. 1024 if the value must be a multiple
1178a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// of 1024.
1188a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1198a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// The spec says the -Xmx and -Xms options must be multiples of 1024.  It
1208a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// doesn't say anything about -Xss.
1218a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1228a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Returns 0 (a useless size) if "s" is malformed or specifies a low or
1238a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// non-evenly-divisible value.
1248a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1258a436595d36c1e4935984fcac249d7d877e00383Brian Carlstromsize_t ParseMemoryOption(const char *s, size_t div) {
1268a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // strtoul accepts a leading [+-], which we don't want,
1278a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // so make sure our string starts with a decimal digit.
1288a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  if (isdigit(*s)) {
1298a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    const char *s2;
1308a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    size_t val = strtoul(s, (char **)&s2, 10);
1318a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (s2 != s) {
1328a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // s2 should be pointing just after the number.
1338a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // If this is the end of the string, the user
1348a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // has specified a number of bytes.  Otherwise,
1358a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // there should be exactly one more character
1368a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // that specifies a multiplier.
1378a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (*s2 != '\0') {
138f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // The remainder of the string is either a single multiplier
139f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // character, or nothing to indicate that the value is in
140f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // bytes.
141f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        char c = *s2++;
142f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (*s2 == '\0') {
143f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          size_t mul;
144f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (c == '\0') {
145f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = 1;
146f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'k' || c == 'K') {
147f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = KB;
148f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'm' || c == 'M') {
149f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = MB;
150f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'g' || c == 'G') {
151f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = GB;
1528a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          } else {
153f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Unknown multiplier character.
1548a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom            return 0;
1558a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          }
156f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
157f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (val <= std::numeric_limits<size_t>::max() / mul) {
158f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val *= mul;
159f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else {
160f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Clamp to a multiple of 1024.
161f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val = std::numeric_limits<size_t>::max() & ~(1024-1);
162f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          }
163f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        } else {
164f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          // There's more than one character after the numeric part.
165f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          return 0;
166f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
1678a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
1688a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // The man page says that a -Xm value must be a multiple of 1024.
1698a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (val % div == 0) {
1708a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom        return val;
1718a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
172fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
173fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
1748a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  return 0;
175fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
176fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
1770af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesvoid LoadJniLibrary(JavaVMExt* vm, const char* name) {
1780af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  // TODO: OS_SHARED_LIB_FORMAT_STR
1790af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  std::string mapped_name(StringPrintf("lib%s.so", name));
1807577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  std::string reason;
1817577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  if (!vm->LoadNativeLibrary(mapped_name, NULL, reason)) {
1820af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": "
1830af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes               << reason;
1840af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  }
1850af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes}
1860af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
1876ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian CarlstromRuntime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
18890a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> parsed(new ParsedOptions());
18958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  const char* boot_class_path = getenv("BOOTCLASSPATH");
19058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (boot_class_path != NULL) {
19158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    parsed->boot_class_path_ = getenv("BOOTCLASSPATH");
19258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
19358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  const char* class_path = getenv("CLASSPATH");
19458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (class_path != NULL) {
19558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    parsed->class_path_ = getenv("CLASSPATH");
19658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
197515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#ifdef NDEBUG
1985174fe6e4e931c423e910366ff22ce0838567940Elliott Hughes  // -Xcheck:jni is off by default for regular builds...
199515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  parsed->check_jni_ = false;
200515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#else
201515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  // ...but on by default in debug builds.
202515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  parsed->check_jni_ = true;
203515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#endif
20485d1545e985ac689db4bad7849880e843707c862Elliott Hughes
2056ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_initial_size_ = Heap::kInitialSize;
2066ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_maximum_size_ = Heap::kMaximumSize;
207f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom  parsed->stack_size_ = Thread::kDefaultStackSize;
208f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
2099ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  parsed->is_zygote_ = false;
2109ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
2116ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_vfprintf_ = vfprintf;
2126ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_exit_ = exit;
2136ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_abort_ = abort;
2148a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
2158a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  for (size_t i = 0; i < options.size(); ++i) {
2168a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    const StringPiece& option = options[i].first;
21758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    if (false) {
21858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      LOG(INFO) << "option[" << i << "]=" << option;
21958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    }
2208a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (option.starts_with("-Xbootclasspath:")) {
22158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:")).data();
22269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option == "-classpath" || option == "-cp") {
22369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      // TODO: support -Djava.class.path
22469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      i++;
22569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      if (i == options.size()) {
22669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        // TODO: usage
22769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Missing required class path value for " << option;
22869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        return NULL;
22969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      }
23069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      const StringPiece& value = options[i].first;
23158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->class_path_ = value.data();
23269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option.starts_with("-Ximage:")) {
23369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      parsed->images_.push_back(option.substr(strlen("-Ximage:")).data());
234515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes    } else if (option.starts_with("-Xcheck:jni")) {
235515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes      parsed->check_jni_ = true;
2368a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option.starts_with("-Xms")) {
237f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).data(), 1024);
238f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
239f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
240f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
241f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2424a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
24369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
244f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
245f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
246f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_initial_size_ = size;
2478a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option.starts_with("-Xmx")) {
248f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).data(), 1024);
249f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
250f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
251f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
252f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2534a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
25469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
255f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
256f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
257f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_maximum_size_ = size;
258f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom    } else if (option.starts_with("-Xss")) {
259f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).data(), 1);
260f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
261f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
262f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
263f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2644a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
26569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
266f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
267f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
268f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->stack_size_ = size;
2696ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option.starts_with("-D")) {
2706ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->properties_.push_back(option.substr(strlen("-D")).data());
271a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    } else if (option.starts_with("-Xjnitrace:")) {
272a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:")).data();
2739ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes    } else if (option == "-Xzygote") {
2749ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes      parsed->is_zygote_ = true;
2756ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option.starts_with("-verbose:")) {
2760af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      std::vector<std::string> verbose_options;
27734023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes      Split(option.substr(strlen("-verbose:")).data(), ',', verbose_options);
2780af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      for (size_t i = 0; i < verbose_options.size(); ++i) {
2790af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes        parsed->verbose_.insert(verbose_options[i]);
2800af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      }
2816ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "vfprintf") {
2826ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_vfprintf_ = reinterpret_cast<int (*)(FILE *, const char*, va_list)>(options[i].second);
2836ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "exit") {
2846ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second);
2856ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "abort") {
2866ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second);
28758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option == "host-prefix") {
28858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second);
2898a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else {
2908a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (!ignore_unrecognized) {
2916ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom        // TODO: print usage via vfprintf
29227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        LOG(ERROR) << "Unrecognized option " << option;
29327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        // TODO: this should exit, but for now tolerate unknown options
29427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        //return NULL;
2958a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
2968a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    }
2978a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  }
2988a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
29985d1545e985ac689db4bad7849880e843707c862Elliott Hughes  LOG(INFO) << "CheckJNI is " << (parsed->check_jni_ ? "on" : "off");
30085d1545e985ac689db4bad7849880e843707c862Elliott Hughes
30169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return parsed.release();
3028a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom}
3038a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
3048a436595d36c1e4935984fcac249d7d877e00383Brian CarlstromRuntime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
3052ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
3062ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  if (Runtime::instance_ != NULL) {
3072ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro    return NULL;
3082ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  }
309dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  instance_ = new Runtime;
310dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  if (!instance_->Init(options, ignore_unrecognized)) {
311dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    delete instance_;
312dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    instance_ = NULL;
31361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  }
31469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return instance_;
31569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
3160af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
317aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromvoid CreateSystemClassLoader() {
318aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (ClassLoader::UseCompileTimeClassPath()) {
319aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return;
320aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
321aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
322aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  Thread* self = Thread::Current();
323aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
324aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  // Must be in the kNative state for calling native methods.
325aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK_EQ(self->GetState(), Thread::kNative);
326aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
327aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  JNIEnv* env = self->GetJniEnv();
328df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader"));
329df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(ClassLoader_class.get() != NULL);
330df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(),
331df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                          "getSystemClassLoader",
332df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                          "()Ljava/lang/ClassLoader;");
333df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(getSystemClassLoader != NULL);
334df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(),
335df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom                                                                        getSystemClassLoader));
336df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(class_loader.get() != NULL);
337df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom
338df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get()));
339aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
340aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
34169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromvoid Runtime::Start() {
3420a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  if (IsVerboseStartup()) {
3430a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom    LOG(INFO) << "Runtime::Start entering";
3440a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  }
34558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
34658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  CHECK(host_prefix_.empty()) << host_prefix_;
34758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
348038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  InitNativeMethods();
34985d1545e985ac689db4bad7849880e843707c862Elliott Hughes
350038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  Thread::FinishStartup();
35185d1545e985ac689db4bad7849880e843707c862Elliott Hughes
3522a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes  class_linker_->RunRootClinits();
353f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom
3545d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  // Class::AllocObject asserts that all objects allocated better be
3555d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  // initialized after Runtime::IsStarted is true, so this needs to
3565d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  // come after ClassLinker::RunRootClinits.
3575d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  started_ = true;
3585d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom
3599ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  if (!is_zygote_) {
3609ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes    signal_catcher_ = new SignalCatcher;
3619ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  }
3629ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
36385d1545e985ac689db4bad7849880e843707c862Elliott Hughes  StartDaemonThreads();
3640a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom
365aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CreateSystemClassLoader();
366aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
367726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  Thread::Current()->GetJniEnv()->locals.AssertEmpty();
368726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes
3690a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  if (IsVerboseStartup()) {
3700a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom    LOG(INFO) << "Runtime::Start exiting";
3710a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  }
37285d1545e985ac689db4bad7849880e843707c862Elliott Hughes}
37385d1545e985ac689db4bad7849880e843707c862Elliott Hughes
37485d1545e985ac689db4bad7849880e843707c862Elliott Hughesvoid Runtime::StartDaemonThreads() {
3759ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  if (IsVerboseStartup()) {
3769ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes    LOG(INFO) << "Runtime::StartDaemonThreads entering";
3779ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  }
37885d1545e985ac689db4bad7849880e843707c862Elliott Hughes
379719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  Thread* self = Thread::Current();
380aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
381aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  // Must be in the kNative state for calling native methods.
382aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK_EQ(self->GetState(), Thread::kNative);
383aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
384719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  JNIEnv* env = self->GetJniEnv();
385726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Daemons"));
386726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  CHECK(c.get() != NULL);
387726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V");
388719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  CHECK(mid != NULL);
389726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes  env->CallStaticVoidMethod(c.get(), mid);
3909ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
3919ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  if (IsVerboseStartup()) {
3929ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes    LOG(INFO) << "Runtime::StartDaemonThreads exiting";
3939ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  }
39461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
39561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
39658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrombool Runtime::IsStarted() const {
397dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  return started_;
398dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
399dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
4000af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesbool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
401c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
4026ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
40390a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
40490a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  if (options.get() == NULL) {
405e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to parse options";
4066ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    return false;
4076ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
4080a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  verbose_startup_ = options->IsVerbose("startup");
4090a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  if (IsVerboseStartup()) {
4100a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom    LOG(INFO) << "Runtime::Init -verbose:startup enabled";
4110a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  }
4127ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
41358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  host_prefix_ = options->host_prefix_;
41458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  boot_class_path_ = options->boot_class_path_;
41558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  class_path_ = options->class_path_;
4167ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  properties_ = options->properties_;
4177ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
4189ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  is_zygote_ = options->is_zygote_;
4199ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
4200af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  vfprintf_ = options->hook_vfprintf_;
4210af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  exit_ = options->hook_exit_;
4220af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  abort_ = options->hook_abort_;
4236ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
424be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  default_stack_size_ = options->stack_size_;
4256ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
42614357e842b611279d467b64d450c569af33a6936Elliott Hughes  thread_list_ = new ThreadList(options->IsVerbose("thread"));
427cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  intern_table_ = new InternTable;
428cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
42958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  Heap::Init(options->heap_initial_size_, options->heap_maximum_size_, options->images_);
4306ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
431c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  BlockSignals();
432c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
433a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  java_vm_ = new JavaVMExt(this, options.get());
434515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes
435be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  Thread::Startup();
436d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
4375fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // ClassLinker needs an attached thread, but we can't fully attach a thread
4385fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // without creating objects.
4395fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  Thread::Attach(this, "main", false);
4406ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
44158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  CHECK_GE(Heap::GetSpaces().size(), 1U);
44258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace())
44358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom                   ? ClassLinker::Create(intern_table_)
44458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom                   : ClassLinker::Create(options->boot_class_path_, intern_table_));
4456ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
4460a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  if (IsVerboseStartup()) {
4470a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom    LOG(INFO) << "Runtime::Init exiting";
4480a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  }
4497b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro  return true;
4507b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
4517b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
452038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Runtime::InitNativeMethods() {
4530a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  if (IsVerboseStartup()) {
4540a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom    LOG(INFO) << "Runtime::InitNativeMethods entering";
4550a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  }
456ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread* self = Thread::Current();
457ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  JNIEnv* env = self->GetJniEnv();
458ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
459418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Must be in the kNative state for calling native methods (JNI_OnLoad code).
460aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK_EQ(self->GetState(), Thread::kNative);
461ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
462418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // First set up JniConstants, which is used by both the runtime's built-in native
463418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // methods and libcore.
464fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes  JniConstants::init(env);
465fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes
466418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up the native methods provided by the runtime itself.
467ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  RegisterRuntimeNativeMethods(env);
468ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
469418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad.
470418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's
471418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // the library that implements System.loadLibrary!
472ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  LoadJniLibrary(instance_->GetJavaVM(), "javacore");
4730a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  if (IsVerboseStartup()) {
4740a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom    LOG(INFO) << "Runtime::InitNativeMethods exiting";
4750a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom  }
476ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
477ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
478ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesvoid Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
479ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
480f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  REGISTER(register_dalvik_system_DexFile);
4819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  REGISTER(register_dalvik_system_VMDebug);
4827ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  REGISTER(register_dalvik_system_VMRuntime);
4838daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_dalvik_system_VMStack);
48401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  REGISTER(register_dalvik_system_Zygote);
485d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes  REGISTER(register_java_lang_Class);
486bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Object);
487bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Runtime);
488bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_String);
489bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_System);
4908daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_java_lang_Thread);
4911240dade91d6c4bbf4e367ca608fcdc15348da45Elliott Hughes  REGISTER(register_java_lang_Throwable);
49264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  REGISTER(register_java_lang_VMClassLoader);
4935b8e4c810a97c9dc417142b8c6e07871ae15c797Brian Carlstrom  REGISTER(register_java_lang_reflect_Array);
4942a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes  REGISTER(register_java_lang_reflect_Constructor);
495f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Field);
496f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Method);
497ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  //REGISTER(register_java_lang_reflect_Proxy);
498bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_util_concurrent_atomic_AtomicLong);
499395520eaa47eca25b92e86188accf3095d60af49Brian Carlstrom  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
500ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  //REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal);
5015ee7a8b56dee896245e0f4ae5215f8b7376c1787Elliott Hughes  REGISTER(register_sun_misc_Unsafe);
502ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#undef REGISTER
503ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
504ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
5058daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesvoid Runtime::Dump(std::ostream& os) {
506e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  // TODO: dump other runtime statistics?
507e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  os << "Loaded classes: " << class_linker_->NumLoadedClasses() << "\n";
508cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  os << "Intern table size: " << GetInternTable()->Size() << "\n";
509e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  // LOGV("VM stats: meth=%d ifld=%d sfld=%d linear=%d",
510e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.numDeclaredMethods,
511e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.numDeclaredInstFields,
512e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.numDeclaredStaticFields,
513e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.pBootLoaderAlloc->curOffset);
514e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  // LOGI("GC precise methods: %d", dvmPointerSetGetCount(gDvm.preciseMethods));
51542ee14279065352a4b9a3e8028d02c567e847d05Elliott Hughes  os << "\n";
5168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
5178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  thread_list_->Dump(os);
518e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes}
519e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
5209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::SetStatsEnabled(bool new_state) {
5219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (new_state == true) {
5229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    GetStats()->Clear(~0);
5239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // TODO: wouldn't it make more sense to clear _all_ threads' stats?
5249d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    Thread::Current()->GetStats()->Clear(~0);
5259d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
5269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  stats_enabled_ = new_state;
5279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5289d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::ResetStats(int kinds) {
5309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  GetStats()->Clear(kinds & 0xffff);
5319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  // TODO: wouldn't it make more sense to clear _all_ threads' stats?
5329d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  Thread::Current()->GetStats()->Clear(kinds >> 16);
5339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott HughesRuntimeStats* Runtime::GetStats() {
5369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return &stats_;
5379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesint32_t Runtime::GetStat(int kind) {
5409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  RuntimeStats* stats;
5419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (kind < (1<<16)) {
5429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = GetStats();
5439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  } else {
5449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = Thread::Current()->GetStats();
5459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    kind >>= 16;
5469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
5479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  switch (kind) {
5489d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_OBJECTS:
5499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_objects;
5509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_BYTES:
5519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_bytes;
5529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_OBJECTS:
5539d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_objects;
5549d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_BYTES:
5559d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_bytes;
5569d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_GC_INVOCATIONS:
5579d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->gc_for_alloc_count;
5589d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_COUNT:
5599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->class_init_count;
5609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_TIME:
5619d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // Convert ns to us, reduce to 32 bits.
5629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return (int) (stats->class_init_time_ns / 1000);
5639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_OBJECTS:
5649d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_BYTES:
5659d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_OBJECTS:
5669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_BYTES:
5679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return 0;  // backward compatibility
5689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  default:
5699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    CHECK(false);
5709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return -1; // unreachable
5719d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
5729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
574c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Runtime::BlockSignals() {
575c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  sigset_t sigset;
576c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigemptyset(&sigset) == -1) {
577c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(FATAL) << "sigemptyset failed";
578c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
579c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGPIPE) == -1) {
580c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGPIPE failed";
581c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
582c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGQUIT is used to dump the runtime's state (including stack traces).
583c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGQUIT) == -1) {
584c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGQUIT failed";
585c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
586c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGUSR1 is used to initiate a heap dump.
587c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGUSR1) == -1) {
588c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGUSR1 failed";
589c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
590c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0);
591c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
592c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
5935fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughesvoid Runtime::AttachCurrentThread(const char* name, bool as_daemon) {
5945fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  Thread::Attach(instance_, name, as_daemon);
59561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
59661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
597d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Runtime::DetachCurrentThread() {
598038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // TODO: check we're not calling DetachCurrentThread from a call stack that
599038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // includes managed frames. (It's only valid if the stack is all-native.)
60002b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes  thread_list_->Unregister();
6017b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
6027b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
603e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
604e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  class_linker_->VisitRoots(visitor, arg);
605e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  intern_table_->VisitRoots(visitor, arg);
606e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  java_vm_->VisitRoots(visitor, arg);
607e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  thread_list_->VisitRoots(visitor, arg);
608e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  visitor(jni_stub_array_, arg);
609e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  visitor(abstract_method_error_stub_array_, arg);
6104f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
6114f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    visitor(resolution_stub_array_[i], arg);
6124f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
6134f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
6144f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    visitor(callee_save_method_[i], arg);
6154f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
616e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
617e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  //(*visitor)(&gDvm.outOfMemoryObj, 0, ROOT_VM_INTERNAL, arg);
618e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  //(*visitor)(&gDvm.internalErrorObj, 0, ROOT_VM_INTERNAL, arg);
619e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  //(*visitor)(&gDvm.noClassDefFoundErrorObj, 0, ROOT_VM_INTERNAL, arg);
620e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  UNIMPLEMENTED(WARNING) << "some roots not marked";
621e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
622e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
623e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool Runtime::HasJniStubArray() const {
624e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return jni_stub_array_ != NULL;
625e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
626e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
627e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromByteArray* Runtime::GetJniStubArray() const {
628e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(jni_stub_array_ != NULL);
629e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return jni_stub_array_;
630e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
631e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
632e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::SetJniStubArray(ByteArray* jni_stub_array) {
633aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK(jni_stub_array != NULL)  << " jni_stub_array=" << jni_stub_array;
634aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array)
635aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array;
636e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  jni_stub_array_ = jni_stub_array;
637e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
638e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
639e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool Runtime::HasAbstractMethodErrorStubArray() const {
640e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return abstract_method_error_stub_array_ != NULL;
641e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
642e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
643e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromByteArray* Runtime::GetAbstractMethodErrorStubArray() const {
644e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array_ != NULL);
645e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return abstract_method_error_stub_array_;
646e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
647e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
648e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) {
649e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array != NULL);
650e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array);
651e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  abstract_method_error_stub_array_ = abstract_method_error_stub_array;
652e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
653e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
6541cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers
6551cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersRuntime::TrampolineType Runtime::GetTrampolineType(Method* method) {
6561cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  if (method == NULL) {
6571cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kUnknownMethod;
6581cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  } else if (method->IsStatic()) {
6591cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kStaticMethod;
6601cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  } else {
6611cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return Runtime::kInstanceMethod;
6621cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  }
6631cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers}
6641cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers
6651cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersbool Runtime::HasResolutionStubArray(TrampolineType type) const {
6661cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  return resolution_stub_array_[type] != NULL;
667ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
668ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
6691cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersByteArray* Runtime::GetResolutionStubArray(TrampolineType type) const {
6701cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  CHECK(HasResolutionStubArray(type));
6714f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType));
6721cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  return resolution_stub_array_[type];
673ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
674ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
6751cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersvoid Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type) {
676ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  CHECK(resolution_stub_array != NULL);
6771cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array);
6781cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  resolution_stub_array_[type] = resolution_stub_array;
679ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
680ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
6814f0d07c783afef89703dce32c94440fc8621a29bIan RogersMethod* Runtime::CreateCalleeSaveMethod(InstructionSet insns, CalleeSaveType type) {
682ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  Class* method_class = Method::GetMethodClass();
683ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  Method* method = down_cast<Method*>(method_class->AllocObject());
684ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetDeclaringClass(method_class);
6854f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  const char* name;
6864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  if (type == kSaveAll) {
6874f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    name = "$$$callee_save_method$$$";
6884f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  } else if (type == kRefsOnly) {
6894f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    name = "$$$refs_only_callee_save_method$$$";
6904f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  } else {
6914f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    DCHECK(type == kRefsAndArgs);
6924f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    name = "$$$refs_and_args_callee_save_method$$$";
6934f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
6944f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  method->SetName(intern_table_->InternStrong(name));
695ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetSignature(intern_table_->InternStrong("()V"));
6963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  method->SetCode(NULL);
697ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  if ((insns == kThumb2) || (insns == kArm)) {
6984f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6)  | (1 << art::arm::R7) |
6994f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                          (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
7004f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
7014f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9);
7024f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills :0) |
7034f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                           (type == kSaveAll ? all_spills :0) | (1 << art::arm::LR);
7044f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_all_spills = (1 << art::arm::S0)  | (1 << art::arm::S1)  | (1 << art::arm::S2) |
7054f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S3)  | (1 << art::arm::S4)  | (1 << art::arm::S5) |
7064f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S6)  | (1 << art::arm::S7)  | (1 << art::arm::S8) |
7074f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S9)  | (1 << art::arm::S10) | (1 << art::arm::S11) |
7084f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) |
7094f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) |
7104f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) |
7114f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) |
7124f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) |
7134f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) |
7144f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S30) | (1 << art::arm::S31);
7154f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0;
7164f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
7174f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                                 __builtin_popcount(fp_spills) /* fprs */ +
7184f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                                 1 /* Method* */) * kPointerSize, kStackAlignment);
71915fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetFrameSizeInBytes(frame_size);
72015fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetReturnPcOffsetInBytes(frame_size - kPointerSize);
7214f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetCoreSpillMask(core_spills);
7224f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetFpSpillMask(fp_spills);
723ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  } else if (insns == kX86) {
724ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFrameSizeInBytes(32);
725ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetReturnPcOffsetInBytes(28);
7264f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetCoreSpillMask((1 << art::x86::EBX) | (1 << art::x86::EBP) | (1 << art::x86::ESI) |
727ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::x86::EDI));
728ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFpSpillMask(0);
729ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  } else {
730ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    UNIMPLEMENTED(FATAL);
731ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  }
732ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  return method;
733ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers}
734ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers
7354f0d07c783afef89703dce32c94440fc8621a29bIan Rogersbool Runtime::HasCalleeSaveMethod(CalleeSaveType type) const {
7364f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  return callee_save_method_[type] != NULL;
737e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
738410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
739e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom// Returns a special method that describes all callee saves being spilled to the stack.
7404f0d07c783afef89703dce32c94440fc8621a29bIan RogersMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type) const {
7414f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  CHECK(HasCalleeSaveMethod(type));
7424f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  return callee_save_method_[type];
7431f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom}
7441f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom
7454f0d07c783afef89703dce32c94440fc8621a29bIan Rogersvoid Runtime::SetCalleeSaveMethod(Method* method, CalleeSaveType type) {
7464f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
7474f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  callee_save_method_[type] = method;
748e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
749e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
7506b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro}  // namespace art
751