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