runtime.cc revision 5d40f182181488eb39ccd19ffd306bb1fb9740c9
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
1090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "UniquePtr.h"
11578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h"
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "heap.h"
13cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes#include "intern_table.h"
14c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h"
15e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#include "signal_catcher.h"
16578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h"
178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h"
1861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
1990a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes// TODO: this drags in cutil/log.h, which conflicts with our logging.h.
2090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "JniConstants.h"
2190a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes
226b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art {
237b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
242ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::instance_ = NULL;
252ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
26dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesRuntime::Runtime()
27be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes    : default_stack_size_(Thread::kDefaultStackSize),
28dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      thread_list_(NULL),
29dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      intern_table_(NULL),
30dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      class_linker_(NULL),
31dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      signal_catcher_(NULL),
32dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      java_vm_(NULL),
33161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom      jni_stub_array_(NULL),
34ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers      callee_save_method_(NULL),
35dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      started_(false),
36dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      vfprintf_(NULL),
37dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      exit_(NULL),
389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      abort_(NULL),
399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      stats_enabled_(false) {
40dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
41dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
4261e019d291583029c01b61b93bea750f2b663c37Carl ShapiroRuntime::~Runtime() {
435fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // Make sure our internal threads are dead before we start tearing down things they're using.
445fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  delete signal_catcher_;
45038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // TODO: GC thread.
465fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes
47038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
4893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes  delete thread_list_;
4993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes
5061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  delete class_linker_;
5169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Heap::Destroy();
52cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  delete intern_table_;
53c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes  delete java_vm_;
54c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  Thread::Shutdown();
554acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
564a289ed61242964b921434de7d375f46480472a1Brian Carlstrom  CHECK(instance_ == NULL || instance_ == this);
574acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  instance_ = NULL;
5861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
5961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
60ffe6736397d17457188727510f0a2953f69a383aElliott Hughesvoid Runtime::Abort(const char* file, int line) {
61ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Get any pending output out of the way.
62ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  fflush(NULL);
63ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
64ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Many people have difficulty distinguish aborts from crashes,
65ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // so be explicit.
66ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  LogMessage(file, line, ERROR, -1).stream() << "Runtime aborting...";
67ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
68ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Perform any platform-specific pre-abort actions.
69ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  PlatformAbort(file, line);
70ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
716ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  // use abort hook if we have one
726ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) {
736ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    Runtime::Current()->abort_();
746ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    // notreached
756ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
766ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
77ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // If we call abort(3) on a device, all threads in the process
7869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // receive SIGABRT.  debuggerd dumps the stack trace of the main
7969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // thread, whether or not that was the thread that failed.  By
8069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // stuffing a value into a bogus address, we cause a segmentation
81ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // fault in the current thread, and get a useful log from debuggerd.
82ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // We can also trivially tell the difference between a VM crash and
83ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // a deliberate abort by looking at the fault address.
84ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  *reinterpret_cast<char*>(0xdeadd00d) = 38;
85ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  abort();
86ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // notreached
87ffe6736397d17457188727510f0a2953f69a383aElliott Hughes}
88ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
89bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid Runtime::CallExitHook(jint status) {
90bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (exit_ != NULL) {
91bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative);
92bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    exit_(status);
93bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    LOG(WARNING) << "Exit hook returned instead of exiting!";
94bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
95bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
96bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
978a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
988a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// memory sizes.  [kK] indicates kilobytes, [mM] megabytes, and
998a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// [gG] gigabytes.
1008a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1018a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "s" should point just past the "-Xm?" part of the string.
1028a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "div" specifies a divisor, e.g. 1024 if the value must be a multiple
1038a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// of 1024.
1048a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1058a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// The spec says the -Xmx and -Xms options must be multiples of 1024.  It
1068a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// doesn't say anything about -Xss.
1078a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1088a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Returns 0 (a useless size) if "s" is malformed or specifies a low or
1098a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// non-evenly-divisible value.
1108a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
1118a436595d36c1e4935984fcac249d7d877e00383Brian Carlstromsize_t ParseMemoryOption(const char *s, size_t div) {
1128a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // strtoul accepts a leading [+-], which we don't want,
1138a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // so make sure our string starts with a decimal digit.
1148a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  if (isdigit(*s)) {
1158a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    const char *s2;
1168a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    size_t val = strtoul(s, (char **)&s2, 10);
1178a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (s2 != s) {
1188a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // s2 should be pointing just after the number.
1198a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // If this is the end of the string, the user
1208a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // has specified a number of bytes.  Otherwise,
1218a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // there should be exactly one more character
1228a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // that specifies a multiplier.
1238a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (*s2 != '\0') {
124f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // The remainder of the string is either a single multiplier
125f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // character, or nothing to indicate that the value is in
126f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // bytes.
127f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        char c = *s2++;
128f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (*s2 == '\0') {
129f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          size_t mul;
130f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (c == '\0') {
131f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = 1;
132f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'k' || c == 'K') {
133f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = KB;
134f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'm' || c == 'M') {
135f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = MB;
136f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'g' || c == 'G') {
137f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = GB;
1388a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          } else {
139f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Unknown multiplier character.
1408a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom            return 0;
1418a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          }
142f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
143f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (val <= std::numeric_limits<size_t>::max() / mul) {
144f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val *= mul;
145f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else {
146f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Clamp to a multiple of 1024.
147f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val = std::numeric_limits<size_t>::max() & ~(1024-1);
148f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          }
149f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        } else {
150f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          // There's more than one character after the numeric part.
151f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          return 0;
152f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
1538a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
1548a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // The man page says that a -Xm value must be a multiple of 1024.
1558a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (val % div == 0) {
1568a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom        return val;
1578a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
158fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
159fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
1608a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  return 0;
161fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
162fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
1630af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesvoid LoadJniLibrary(JavaVMExt* vm, const char* name) {
1640af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  // TODO: OS_SHARED_LIB_FORMAT_STR
1650af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  std::string mapped_name(StringPrintf("lib%s.so", name));
1667577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  std::string reason;
1677577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  if (!vm->LoadNativeLibrary(mapped_name, NULL, reason)) {
1680af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": "
1690af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes               << reason;
1700af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  }
1710af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes}
1720af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
1737ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughesvoid CreateClassPath(const std::string& class_path,
17469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom                     std::vector<const DexFile*>& class_path_vector) {
175fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  std::vector<std::string> parsed;
1767ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  Split(class_path, ':', parsed);
177fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  for (size_t i = 0; i < parsed.size(); ++i) {
178161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom    const DexFile* dex_file = DexFile::Open(parsed[i], "");
179fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    if (dex_file != NULL) {
18069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      class_path_vector.push_back(dex_file);
181fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
182fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
183fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
184fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
1856ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian CarlstromRuntime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
18690a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> parsed(new ParsedOptions());
1876ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->boot_image_ = NULL;
188515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#ifdef NDEBUG
1895174fe6e4e931c423e910366ff22ce0838567940Elliott Hughes  // -Xcheck:jni is off by default for regular builds...
190515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  parsed->check_jni_ = false;
191515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#else
192515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  // ...but on by default in debug builds.
193515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  parsed->check_jni_ = true;
194515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#endif
19585d1545e985ac689db4bad7849880e843707c862Elliott Hughes
1966ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_initial_size_ = Heap::kInitialSize;
1976ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->heap_maximum_size_ = Heap::kMaximumSize;
198f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom  parsed->stack_size_ = Thread::kDefaultStackSize;
199f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
2006ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_vfprintf_ = vfprintf;
2016ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_exit_ = exit;
2026ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_abort_ = abort;
2038a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
2048a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  for (size_t i = 0; i < options.size(); ++i) {
2058a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    const StringPiece& option = options[i].first;
2068a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (option.starts_with("-Xbootclasspath:")) {
2077ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes      parsed->boot_class_path_string_ = option.substr(strlen("-Xbootclasspath:")).data();
2088a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option == "bootclasspath") {
2097ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes      UNIMPLEMENTED(WARNING) << "what should VMRuntime.getBootClassPath return here?";
210f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      const void* dex_vector = options[i].second;
2119ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom      const std::vector<const DexFile*>* v
2129ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom          = reinterpret_cast<const std::vector<const DexFile*>*>(dex_vector);
213f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (v == NULL) {
214f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
215f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
216f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
217f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // TODO: usage
21869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
219f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
220f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
221f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->boot_class_path_ = *v;
22278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else if (option == "classpath") {
22378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      const void* dex_vector = options[i].second;
22478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      const std::vector<const DexFile*>* v
22578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          = reinterpret_cast<const std::vector<const DexFile*>*>(dex_vector);
22678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      if (v == NULL) {
22778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        if (ignore_unrecognized) {
22878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          continue;
22978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        }
23078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        // TODO: usage
23178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
23278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        return NULL;
23378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
23478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      parsed->class_path_ = *v;
23569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option == "-classpath" || option == "-cp") {
23669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      // TODO: support -Djava.class.path
23769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      i++;
23869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      if (i == options.size()) {
23969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        // TODO: usage
24069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Missing required class path value for " << option;
24169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        return NULL;
24269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      }
24369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      const StringPiece& value = options[i].first;
2447ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes      parsed->class_path_string_ = value.data();
2458a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option.starts_with("-Xbootimage:")) {
24669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      // TODO: remove when intern_addr_ is removed, just use -Ximage:
2476ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->boot_image_ = option.substr(strlen("-Xbootimage:")).data();
24869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option.starts_with("-Ximage:")) {
24969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      parsed->images_.push_back(option.substr(strlen("-Ximage:")).data());
250515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes    } else if (option.starts_with("-Xcheck:jni")) {
251515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes      parsed->check_jni_ = true;
2528a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option.starts_with("-Xms")) {
253f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).data(), 1024);
254f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
255f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
256f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
257f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2584a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
25969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
260f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
261f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
262f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_initial_size_ = size;
2638a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else if (option.starts_with("-Xmx")) {
264f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).data(), 1024);
265f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
266f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
267f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
268f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2694a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
27069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
271f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
272f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
273f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_maximum_size_ = size;
274f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom    } else if (option.starts_with("-Xss")) {
275f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).data(), 1);
276f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
277f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
278f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
279f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2804a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
28169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
282f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
283f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
284f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->stack_size_ = size;
2856ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option.starts_with("-D")) {
2866ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->properties_.push_back(option.substr(strlen("-D")).data());
287a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    } else if (option.starts_with("-Xjnitrace:")) {
288a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:")).data();
2896ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option.starts_with("-verbose:")) {
2900af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      std::vector<std::string> verbose_options;
29134023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes      Split(option.substr(strlen("-verbose:")).data(), ',', verbose_options);
2920af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      for (size_t i = 0; i < verbose_options.size(); ++i) {
2930af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes        parsed->verbose_.insert(verbose_options[i]);
2940af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      }
2956ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "vfprintf") {
2966ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_vfprintf_ = reinterpret_cast<int (*)(FILE *, const char*, va_list)>(options[i].second);
2976ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "exit") {
2986ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second);
2996ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "abort") {
3006ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom      parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second);
3018a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else {
3028a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (!ignore_unrecognized) {
3036ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom        // TODO: print usage via vfprintf
30427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        LOG(ERROR) << "Unrecognized option " << option;
30527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        // TODO: this should exit, but for now tolerate unknown options
30627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        //return NULL;
3078a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
3088a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    }
3098a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  }
3108a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
3117ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  // Consider it an error if both bootclasspath and -Xbootclasspath: are supplied.
31278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  // TODO: remove bootclasspath and classpath which are mostly just used by tests?
3137ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  if (!parsed->boot_class_path_.empty() && !parsed->boot_class_path_string_.empty()) {
31469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    // TODO: usage
31569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options.";
31669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    return NULL;
3178a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  }
31878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (!parsed->class_path_.empty() && !parsed->class_path_string_.empty()) {
31978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    // TODO: usage
32078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options.";
32178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return NULL;
32278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
32369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  if (parsed->boot_class_path_.empty()) {
3247ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes    if (parsed->boot_class_path_string_ == NULL) {
3257ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes      const char* BOOTCLASSPATH = getenv("BOOTCLASSPATH");
32627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      if (BOOTCLASSPATH != NULL) {
32727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        parsed->boot_class_path_string_ = BOOTCLASSPATH;
32827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      }
32969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    }
3307ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes    CreateClassPath(parsed->boot_class_path_string_, parsed->boot_class_path_);
3318a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  }
3322ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
33378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (parsed->class_path_.empty()) {
33478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (parsed->class_path_string_ == NULL) {
33578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      const char* CLASSPATH = getenv("CLASSPATH");
33678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      if (CLASSPATH != NULL) {
33778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        parsed->class_path_string_ = CLASSPATH;
33878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
33969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    }
34078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    CreateClassPath(parsed->class_path_string_, parsed->class_path_);
34169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
34269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
34385d1545e985ac689db4bad7849880e843707c862Elliott Hughes  LOG(INFO) << "CheckJNI is " << (parsed->check_jni_ ? "on" : "off");
34485d1545e985ac689db4bad7849880e843707c862Elliott Hughes
34569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return parsed.release();
3468a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom}
3478a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
3488a436595d36c1e4935984fcac249d7d877e00383Brian CarlstromRuntime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
3492ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
3502ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  if (Runtime::instance_ != NULL) {
3512ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro    return NULL;
3522ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  }
353dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  instance_ = new Runtime;
354dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  if (!instance_->Init(options, ignore_unrecognized)) {
355dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    delete instance_;
356dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    instance_ = NULL;
35761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  }
35869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return instance_;
35969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
3600af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
36169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromvoid Runtime::Start() {
362038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  InitNativeMethods();
36385d1545e985ac689db4bad7849880e843707c862Elliott Hughes
364038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  Thread::FinishStartup();
36585d1545e985ac689db4bad7849880e843707c862Elliott Hughes
3662a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes  class_linker_->RunRootClinits();
367f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom
3685d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  // Class::AllocObject asserts that all objects allocated better be
3695d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  // initialized after Runtime::IsStarted is true, so this needs to
3705d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  // come after ClassLinker::RunRootClinits.
3715d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  started_ = true;
3725d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom
37385d1545e985ac689db4bad7849880e843707c862Elliott Hughes  StartDaemonThreads();
37485d1545e985ac689db4bad7849880e843707c862Elliott Hughes}
37585d1545e985ac689db4bad7849880e843707c862Elliott Hughes
37685d1545e985ac689db4bad7849880e843707c862Elliott Hughesvoid Runtime::StartDaemonThreads() {
37785d1545e985ac689db4bad7849880e843707c862Elliott Hughes  signal_catcher_ = new SignalCatcher;
37885d1545e985ac689db4bad7849880e843707c862Elliott Hughes
379719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  Thread* self = Thread::Current();
380719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  JNIEnv* env = self->GetJniEnv();
381719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  jclass c = env->FindClass("java/lang/Daemons");
38285d1545e985ac689db4bad7849880e843707c862Elliott Hughes  CHECK(c != NULL);
383719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  jmethodID mid = env->GetStaticMethodID(c, "start", "()V");
384719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  CHECK(mid != NULL);
385719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  env->CallStaticVoidMethod(c, mid);
38661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
38761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
388dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughesbool Runtime::IsStarted() {
389dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  return started_;
390dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
391dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
3920af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesbool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
393c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
3946ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
39590a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
39690a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  if (options.get() == NULL) {
39769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    LOG(WARNING) << "Failed to parse options";
3986ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    return false;
3996ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
4007ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
4017ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  boot_class_path_ = options->boot_class_path_string_;
4027ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  class_path_ = options->class_path_string_;
4037ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  properties_ = options->properties_;
4047ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
4050af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  vfprintf_ = options->hook_vfprintf_;
4060af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  exit_ = options->hook_exit_;
4070af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  abort_ = options->hook_abort_;
4086ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
409be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  default_stack_size_ = options->stack_size_;
4106ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
41114357e842b611279d467b64d450c569af33a6936Elliott Hughes  thread_list_ = new ThreadList(options->IsVerbose("thread"));
412cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  intern_table_ = new InternTable;
413cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
414be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  Heap::Init(options->heap_initial_size_, options->heap_maximum_size_,
415be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes      options->boot_image_, options->images_);
4166ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
417c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  BlockSignals();
418c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
419a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  java_vm_ = new JavaVMExt(this, options.get());
420515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes
421be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  Thread::Startup();
422d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
4235fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // ClassLinker needs an attached thread, but we can't fully attach a thread
4245fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // without creating objects.
4255fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  Thread::Attach(this, "main", false);
4266ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
42769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  class_linker_ = ClassLinker::Create(options->boot_class_path_,
42869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom                                      options->class_path_,
42969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom                                      intern_table_,
43069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom                                      Heap::GetBootSpace());
4316ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
4327b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro  return true;
4337b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
4347b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
435038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Runtime::InitNativeMethods() {
436ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread* self = Thread::Current();
437ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  JNIEnv* env = self->GetJniEnv();
438ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
439418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Must be in the kNative state for calling native methods (JNI_OnLoad code).
440ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  ScopedThreadStateChange tsc(self, Thread::kNative);
441ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
442418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // First set up JniConstants, which is used by both the runtime's built-in native
443418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // methods and libcore.
444fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes  JniConstants::init(env);
445fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes
446418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up the native methods provided by the runtime itself.
447ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  RegisterRuntimeNativeMethods(env);
448ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
449418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad.
450418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's
451418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // the library that implements System.loadLibrary!
452ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  LoadJniLibrary(instance_->GetJavaVM(), "javacore");
453ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
454ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
455ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesvoid Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
456ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
457f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  REGISTER(register_dalvik_system_DexFile);
4589d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  REGISTER(register_dalvik_system_VMDebug);
4597ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  REGISTER(register_dalvik_system_VMRuntime);
4608daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_dalvik_system_VMStack);
46101158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  REGISTER(register_dalvik_system_Zygote);
462d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes  REGISTER(register_java_lang_Class);
463bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Object);
464bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Runtime);
465bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_String);
466bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_System);
4678daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_java_lang_Thread);
4681240dade91d6c4bbf4e367ca608fcdc15348da45Elliott Hughes  REGISTER(register_java_lang_Throwable);
46964bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  REGISTER(register_java_lang_VMClassLoader);
470ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  //REGISTER(register_java_lang_reflect_AccessibleObject);
4715b8e4c810a97c9dc417142b8c6e07871ae15c797Brian Carlstrom  REGISTER(register_java_lang_reflect_Array);
4722a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes  REGISTER(register_java_lang_reflect_Constructor);
473f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Field);
474f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Method);
475ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  //REGISTER(register_java_lang_reflect_Proxy);
476bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_util_concurrent_atomic_AtomicLong);
477395520eaa47eca25b92e86188accf3095d60af49Brian Carlstrom  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
478ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  //REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal);
4795ee7a8b56dee896245e0f4ae5215f8b7376c1787Elliott Hughes  REGISTER(register_sun_misc_Unsafe);
480ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#undef REGISTER
481ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
482ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
4838daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesvoid Runtime::Dump(std::ostream& os) {
484e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  // TODO: dump other runtime statistics?
485e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  os << "Loaded classes: " << class_linker_->NumLoadedClasses() << "\n";
486cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  os << "Intern table size: " << GetInternTable()->Size() << "\n";
487e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  // LOGV("VM stats: meth=%d ifld=%d sfld=%d linear=%d",
488e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.numDeclaredMethods,
489e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.numDeclaredInstFields,
490e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.numDeclaredStaticFields,
491e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  //    gDvm.pBootLoaderAlloc->curOffset);
492e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  // LOGI("GC precise methods: %d", dvmPointerSetGetCount(gDvm.preciseMethods));
49342ee14279065352a4b9a3e8028d02c567e847d05Elliott Hughes  os << "\n";
4948daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
4958daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  thread_list_->Dump(os);
496e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes}
497e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
4989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::SetStatsEnabled(bool new_state) {
4999d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (new_state == true) {
5009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    GetStats()->Clear(~0);
5019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // TODO: wouldn't it make more sense to clear _all_ threads' stats?
5029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    Thread::Current()->GetStats()->Clear(~0);
5039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
5049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  stats_enabled_ = new_state;
5059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::ResetStats(int kinds) {
5089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  GetStats()->Clear(kinds & 0xffff);
5099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  // TODO: wouldn't it make more sense to clear _all_ threads' stats?
5109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  Thread::Current()->GetStats()->Clear(kinds >> 16);
5119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott HughesRuntimeStats* Runtime::GetStats() {
5149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return &stats_;
5159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5179d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesint32_t Runtime::GetStat(int kind) {
5189d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  RuntimeStats* stats;
5199d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (kind < (1<<16)) {
5209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = GetStats();
5219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  } else {
5229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = Thread::Current()->GetStats();
5239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    kind >>= 16;
5249d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
5259d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  switch (kind) {
5269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_OBJECTS:
5279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_objects;
5289d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_BYTES:
5299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_bytes;
5309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_OBJECTS:
5319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_objects;
5329d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_BYTES:
5339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_bytes;
5349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_GC_INVOCATIONS:
5359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->gc_for_alloc_count;
5369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_COUNT:
5379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->class_init_count;
5389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_TIME:
5399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // Convert ns to us, reduce to 32 bits.
5409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return (int) (stats->class_init_time_ns / 1000);
5419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_OBJECTS:
5429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_BYTES:
5439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_OBJECTS:
5449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_BYTES:
5459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return 0;  // backward compatibility
5469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  default:
5479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    CHECK(false);
5489d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return -1; // unreachable
5499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
5509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
552c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Runtime::BlockSignals() {
553c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  sigset_t sigset;
554c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigemptyset(&sigset) == -1) {
555c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(FATAL) << "sigemptyset failed";
556c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
557c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGPIPE) == -1) {
558c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGPIPE failed";
559c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
560c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGQUIT is used to dump the runtime's state (including stack traces).
561c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGQUIT) == -1) {
562c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGQUIT failed";
563c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
564c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGUSR1 is used to initiate a heap dump.
565c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (sigaddset(&sigset, SIGUSR1) == -1) {
566c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(ERROR) << "sigaddset SIGUSR1 failed";
567c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
568c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0);
569c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
570c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
5715fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughesvoid Runtime::AttachCurrentThread(const char* name, bool as_daemon) {
5725fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  Thread::Attach(instance_, name, as_daemon);
57361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
57461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
575d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Runtime::DetachCurrentThread() {
576038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // TODO: check we're not calling DetachCurrentThread from a call stack that
577038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // includes managed frames. (It's only valid if the stack is all-native.)
57802b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes  thread_list_->Unregister();
5797b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
5807b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
581ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian RogersMethod* Runtime::CreateCalleeSaveMethod(InstructionSet insns) {
582ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  Class* method_class = Method::GetMethodClass();
583ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  Method* method = down_cast<Method*>(method_class->AllocObject());
584ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetDeclaringClass(method_class);
585ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetName(intern_table_->InternStrong("$$$callee_save_method$$$"));
586ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetSignature(intern_table_->InternStrong("()V"));
587ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetCode(NULL, insns, NULL);
588ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  if ((insns == kThumb2) || (insns == kArm)) {
58915fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    size_t frame_size = (12 /* gprs */ + 32 /* fprs */ + 4 /* data */) * kPointerSize;
59015fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetFrameSizeInBytes(frame_size);
59115fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetReturnPcOffsetInBytes(frame_size - kPointerSize);
592ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetCoreSpillMask((1 << art::arm::R1) |
593ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R2) |
594ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R3) |
595ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R4) |
596ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R5) |
597ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R6) |
598ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R7) |
599ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R8) |
600ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R9) |
601ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R10) |
602ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::R11) |
603ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::arm::LR));
60415fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetFpSpillMask((1 << art::arm::S0) |
60515fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S1) |
60615fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S2) |
60715fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S3) |
60815fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S4) |
60915fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S5) |
61015fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S6) |
61115fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S7) |
61215fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S8) |
61315fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S9) |
61415fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S10) |
61515fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S11) |
61615fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S12) |
61715fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S13) |
61815fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S14) |
61915fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S15) |
62015fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S16) |
62115fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S17) |
62215fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S18) |
62315fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S19) |
62415fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S20) |
62515fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S21) |
62615fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S22) |
62715fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S23) |
62815fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S24) |
62915fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S25) |
63015fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S26) |
63115fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S27) |
63215fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S28) |
63315fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S29) |
63415fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S30) |
63515fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers                           (1 << art::arm::S31));
636ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  } else if (insns == kX86) {
637ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFrameSizeInBytes(32);
638ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetReturnPcOffsetInBytes(28);
639ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetCoreSpillMask((1 << art::x86::EBX) |
640ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::x86::EBP) |
641ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::x86::ESI) |
642ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers                             (1 << art::x86::EDI));
643ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFpSpillMask(0);
644ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  } else {
645ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    UNIMPLEMENTED(FATAL);
646ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  }
647ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  return method;
648ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers}
649ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers
650410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughesvoid Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
651410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  class_linker_->VisitRoots(visitor, arg);
652410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  intern_table_->VisitRoots(visitor, arg);
653410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  java_vm_->VisitRoots(visitor, arg);
654410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  thread_list_->VisitRoots(visitor, arg);
655161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  visitor(jni_stub_array_, arg);
656ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  visitor(callee_save_method_, arg);
657410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
658410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  //(*visitor)(&gDvm.outOfMemoryObj, 0, ROOT_VM_INTERNAL, arg);
659410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  //(*visitor)(&gDvm.internalErrorObj, 0, ROOT_VM_INTERNAL, arg);
660410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  //(*visitor)(&gDvm.noClassDefFoundErrorObj, 0, ROOT_VM_INTERNAL, arg);
661410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  UNIMPLEMENTED(WARNING) << "some roots not marked";
6621f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom}
6631f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom
6646b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro}  // namespace art
665