runtime.cc revision f1a5adc87760f938b01df26d906295063546b259
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 166b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro 17578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h" 187b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro 19dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom#include <signal.h> 20dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom 21ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdio> 22ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdlib> 238a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom#include <limits> 242ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <vector> 25ffe6736397d17457188727510f0a2953f69a383aElliott Hughes 26578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h" 27aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "class_loader.h" 283bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "debugger.h" 294d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes#include "dex_verifier.h" 30578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "heap.h" 31e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "image.h" 32cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes#include "intern_table.h" 33c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h" 3432d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes#include "monitor.h" 35e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_file.h" 36726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes#include "ScopedLocalRef.h" 37e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#include "signal_catcher.h" 38e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "space.h" 39578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h" 413bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "UniquePtr.h" 4261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 4390a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes// TODO: this drags in cutil/log.h, which conflicts with our logging.h. 4490a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "JniConstants.h" 4590a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes 466b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art { 477b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro 482ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::instance_ = NULL; 492ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 50131aef8c94292cc530da2fd91ee98d1432352959Elliott HughesMutex Runtime::abort_lock_("abort lock"); 51131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes 52dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesRuntime::Runtime() 53d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes : is_compiler_(false), 54d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes is_zygote_(false), 550a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom default_stack_size_(Thread::kDefaultStackSize), 56c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes monitor_list_(NULL), 57dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes thread_list_(NULL), 58dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes intern_table_(NULL), 59dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes class_linker_(NULL), 60dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes signal_catcher_(NULL), 61dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes java_vm_(NULL), 62161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom jni_stub_array_(NULL), 63e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom abstract_method_error_stub_array_(NULL), 646b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes shutting_down_(false), 65dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes started_(false), 66dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes vfprintf_(NULL), 67dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes exit_(NULL), 689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes abort_(NULL), 692692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao stats_enabled_(false), 702692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao tracer_(NULL) { 714f0d07c783afef89703dce32c94440fc8621a29bIan Rogers for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) { 724f0d07c783afef89703dce32c94440fc8621a29bIan Rogers resolution_stub_array_[i] = NULL; 734f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 744f0d07c783afef89703dce32c94440fc8621a29bIan Rogers for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 754f0d07c783afef89703dce32c94440fc8621a29bIan Rogers callee_save_method_[i] = NULL; 764f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 77dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes} 78dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes 7961e019d291583029c01b61b93bea750f2b663c37Carl ShapiroRuntime::~Runtime() { 806b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes shutting_down_ = true; 816b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes 82d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes Dbg::StopJdwp(); 83d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes 845fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes // Make sure our internal threads are dead before we start tearing down things they're using. 855fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes delete signal_catcher_; 86038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // TODO: GC thread. 875fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 88038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended. 8993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes delete thread_list_; 90c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes delete monitor_list_; 9193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 9261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro delete class_linker_; 9369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro Heap::Destroy(); 944d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes verifier::DexVerifier::DeleteGcMaps(); 95cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes delete intern_table_; 96c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes delete java_vm_; 97c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes Thread::Shutdown(); 984acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro // TODO: acquire a static mutex on Runtime to avoid racing. 994a289ed61242964b921434de7d375f46480472a1Brian Carlstrom CHECK(instance_ == NULL || instance_ == this); 1004acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro instance_ = NULL; 10161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 10261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 103cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughesstatic bool gAborting = false; 104cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes 105e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughesstruct AbortState { 106e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes void Dump(std::ostream& os) { 107cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes if (gAborting) { 108cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes os << "Runtime aborting --- recursively, so no thread-specific detail!\n"; 109cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes return; 110cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes } 111cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes gAborting = true; 112e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes os << "Runtime aborting...\n"; 1136c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes if (Runtime::Current() == NULL) { 1146c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes os << "(Runtime does not yet exist!)\n"; 1156c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes return; 1166c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes } 117e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes Thread* self = Thread::Current(); 118e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes if (self == NULL) { 119e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes os << "(Aborting thread was not attached to runtime!)\n"; 120e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes } else { 121899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes self->Dump(os); 122899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes if (self->IsExceptionPending()) { 123899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes os << "Pending " << PrettyTypeOf(self->GetException()) << " on thread:\n" 124899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes << self->GetException()->Dump(); 125899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes } 126e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes } 127e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes } 128e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes}; 129e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes 130ffe6736397d17457188727510f0a2953f69a383aElliott Hughesvoid Runtime::Abort(const char* file, int line) { 131131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes // Ensure that we don't have multiple threads trying to abort at once, 132131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes // which would result in significantly worse diagnostics. 133131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes MutexLock mu(abort_lock_); 134131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes 135ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // Get any pending output out of the way. 136ffe6736397d17457188727510f0a2953f69a383aElliott Hughes fflush(NULL); 137ffe6736397d17457188727510f0a2953f69a383aElliott Hughes 138ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // Many people have difficulty distinguish aborts from crashes, 139ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // so be explicit. 140e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes AbortState state; 1419ee5f9ccba015beb3ae376ed08b3363bd9df6422Elliott Hughes LOG(INTERNAL_FATAL) << Dumpable<AbortState>(state); 142ffe6736397d17457188727510f0a2953f69a383aElliott Hughes 143ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // Perform any platform-specific pre-abort actions. 144ffe6736397d17457188727510f0a2953f69a383aElliott Hughes PlatformAbort(file, line); 145ffe6736397d17457188727510f0a2953f69a383aElliott Hughes 1466ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom // use abort hook if we have one 1476ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) { 1486ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom Runtime::Current()->abort_(); 1496ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom // notreached 1506ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom } 1516ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom 152ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // If we call abort(3) on a device, all threads in the process 15369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // receive SIGABRT. debuggerd dumps the stack trace of the main 15469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // thread, whether or not that was the thread that failed. By 15569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // stuffing a value into a bogus address, we cause a segmentation 156ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // fault in the current thread, and get a useful log from debuggerd. 157ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // We can also trivially tell the difference between a VM crash and 158ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // a deliberate abort by looking at the fault address. 159ffe6736397d17457188727510f0a2953f69a383aElliott Hughes *reinterpret_cast<char*>(0xdeadd00d) = 38; 160ffe6736397d17457188727510f0a2953f69a383aElliott Hughes abort(); 161ffe6736397d17457188727510f0a2953f69a383aElliott Hughes // notreached 162ffe6736397d17457188727510f0a2953f69a383aElliott Hughes} 163ffe6736397d17457188727510f0a2953f69a383aElliott Hughes 164bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid Runtime::CallExitHook(jint status) { 165bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes if (exit_ != NULL) { 166bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative); 167bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes exit_(status); 168bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes LOG(WARNING) << "Exit hook returned instead of exiting!"; 169bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes } 170bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes} 171bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes 1728a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify 1738a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// memory sizes. [kK] indicates kilobytes, [mM] megabytes, and 1748a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// [gG] gigabytes. 1758a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// 1768a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "s" should point just past the "-Xm?" part of the string. 1778a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "div" specifies a divisor, e.g. 1024 if the value must be a multiple 1788a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// of 1024. 1798a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// 1808a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// The spec says the -Xmx and -Xms options must be multiples of 1024. It 1818a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// doesn't say anything about -Xss. 1828a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// 1838a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Returns 0 (a useless size) if "s" is malformed or specifies a low or 1848a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// non-evenly-divisible value. 1858a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// 186c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughessize_t ParseMemoryOption(const char* s, size_t div) { 1878a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // strtoul accepts a leading [+-], which we don't want, 1888a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // so make sure our string starts with a decimal digit. 1898a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom if (isdigit(*s)) { 190c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughes const char* s2; 191c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughes size_t val = strtoul(s, (char**)&s2, 10); 1928a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom if (s2 != s) { 1938a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // s2 should be pointing just after the number. 1948a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // If this is the end of the string, the user 1958a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // has specified a number of bytes. Otherwise, 1968a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // there should be exactly one more character 1978a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // that specifies a multiplier. 1988a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom if (*s2 != '\0') { 199f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom // The remainder of the string is either a single multiplier 200f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom // character, or nothing to indicate that the value is in 201f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom // bytes. 202f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom char c = *s2++; 203f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (*s2 == '\0') { 204f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom size_t mul; 205f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (c == '\0') { 206f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom mul = 1; 207f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } else if (c == 'k' || c == 'K') { 208f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom mul = KB; 209f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } else if (c == 'm' || c == 'M') { 210f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom mul = MB; 211f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } else if (c == 'g' || c == 'G') { 212f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom mul = GB; 2138a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } else { 214f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom // Unknown multiplier character. 2158a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom return 0; 2168a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } 217f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom 218f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (val <= std::numeric_limits<size_t>::max() / mul) { 219f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom val *= mul; 220f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } else { 221f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom // Clamp to a multiple of 1024. 222f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom val = std::numeric_limits<size_t>::max() & ~(1024-1); 223f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 224f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } else { 225f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom // There's more than one character after the numeric part. 226f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom return 0; 227f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 2288a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } 2298a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom // The man page says that a -Xm value must be a multiple of 1024. 2308a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom if (val % div == 0) { 2318a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom return val; 2328a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } 233fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro } 234fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro } 2358a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom return 0; 236fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro} 237fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro 238f1a5adc87760f938b01df26d906295063546b259Elliott Hughessize_t ParseIntegerOrDie(const std::string& s) { 239f1a5adc87760f938b01df26d906295063546b259Elliott Hughes std::string::size_type colon = s.find(':'); 240f1a5adc87760f938b01df26d906295063546b259Elliott Hughes if (colon == std::string::npos) { 241bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes LOG(FATAL) << "Missing integer: " << s; 242bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes } 243f1a5adc87760f938b01df26d906295063546b259Elliott Hughes const char* begin = &s[colon + 1]; 244bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes char* end; 245bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes size_t result = strtoul(begin, &end, 10); 246bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes if (begin == end || *end != '\0') { 247bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes LOG(FATAL) << "Failed to parse integer in: " << s; 248bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes } 249bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes return result; 250bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes} 251bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes 2520af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesvoid LoadJniLibrary(JavaVMExt* vm, const char* name) { 2536cc332ef80edf56221676e33ea16bb4022130344Elliott Hughes std::string mapped_name(StringPrintf(OS_SHARED_LIB_FORMAT_STR, name)); 2547577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes std::string reason; 2557577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes if (!vm->LoadNativeLibrary(mapped_name, NULL, reason)) { 2560af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": " 2570af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes << reason; 2580af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes } 2590af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes} 2600af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes 2616ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian CarlstromRuntime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) { 26290a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes UniquePtr<ParsedOptions> parsed(new ParsedOptions()); 26358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom const char* boot_class_path = getenv("BOOTCLASSPATH"); 26458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom if (boot_class_path != NULL) { 2654f6b57a5676477882eb06240f3db62483006147dIan Rogers parsed->boot_class_path_ = boot_class_path; 26658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } 26758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom const char* class_path = getenv("CLASSPATH"); 26858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom if (class_path != NULL) { 2694f6b57a5676477882eb06240f3db62483006147dIan Rogers parsed->class_path_ = class_path; 27058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } 271515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#ifdef NDEBUG 2725174fe6e4e931c423e910366ff22ce0838567940Elliott Hughes // -Xcheck:jni is off by default for regular builds... 273515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes parsed->check_jni_ = false; 274515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#else 275515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes // ...but on by default in debug builds. 276515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes parsed->check_jni_ = true; 277515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes#endif 27885d1545e985ac689db4bad7849880e843707c862Elliott Hughes 2796ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->heap_initial_size_ = Heap::kInitialSize; 2806ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->heap_maximum_size_ = Heap::kMaximumSize; 281c11607024d2e7a52ca690b8339306cab040e6653jeffhao parsed->heap_growth_limit_ = 0; // 0 means no growth limit 282f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom parsed->stack_size_ = Thread::kDefaultStackSize; 283f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom 284d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes parsed->is_compiler_ = false; 2859ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes parsed->is_zygote_ = false; 2869ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes 287bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes parsed->jni_globals_max_ = 0; 288fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes parsed->lock_profiling_threshold_ = 0; 289fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes parsed->hook_is_sensitive_thread_ = NULL; 290fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes 2916ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->hook_vfprintf_ = vfprintf; 2926ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->hook_exit_ = exit; 2936ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->hook_abort_ = abort; 2948a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom 2958a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom for (size_t i = 0; i < options.size(); ++i) { 296f1a5adc87760f938b01df26d906295063546b259Elliott Hughes const std::string option(options[i].first); 2970796af03edc06d92bb8d631f1c0c23befdae2315Brian Carlstrom if (true && options[0].first == "-Xzygote") { 29858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom LOG(INFO) << "option[" << i << "]=" << option; 29958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } 300f1a5adc87760f938b01df26d906295063546b259Elliott Hughes if (StartsWith(option, "-Xbootclasspath:")) { 301f1a5adc87760f938b01df26d906295063546b259Elliott Hughes parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:")); 30269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom } else if (option == "-classpath" || option == "-cp") { 30369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom // TODO: support -Djava.class.path 30469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom i++; 30569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom if (i == options.size()) { 30669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom // TODO: usage 30769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom LOG(FATAL) << "Missing required class path value for " << option; 30869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom return NULL; 30969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom } 310f1a5adc87760f938b01df26d906295063546b259Elliott Hughes parsed->class_path_ = options[i].first; 311f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Ximage:")) { 312f1a5adc87760f938b01df26d906295063546b259Elliott Hughes parsed->image_ = option.substr(strlen("-Ximage:")); 313f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xcheck:jni")) { 314515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes parsed->check_jni_ = true; 315f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xrunjdwp:") || StartsWith(option, "-agentlib:jdwp=")) { 316f1a5adc87760f938b01df26d906295063546b259Elliott Hughes std::string tail(option.substr(option[1] == 'X' ? 10 : 15)); 3173bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (tail == "help" || !Dbg::ParseJdwpOptions(tail)) { 3183bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(FATAL) << "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n" 3193bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes << "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n"; 3203bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return NULL; 3213bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 322f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xms")) { 323f1a5adc87760f938b01df26d906295063546b259Elliott Hughes size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).c_str(), 1024); 324f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (size == 0) { 325f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (ignore_unrecognized) { 326f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom continue; 327f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 3284a289ed61242964b921434de7d375f46480472a1Brian Carlstrom // TODO: usage 32969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom LOG(FATAL) << "Failed to parse " << option; 330f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom return NULL; 331f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 332f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom parsed->heap_initial_size_ = size; 333f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xmx")) { 334f1a5adc87760f938b01df26d906295063546b259Elliott Hughes size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).c_str(), 1024); 335f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (size == 0) { 336f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (ignore_unrecognized) { 337f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom continue; 338f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 3394a289ed61242964b921434de7d375f46480472a1Brian Carlstrom // TODO: usage 34069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom LOG(FATAL) << "Failed to parse " << option; 341f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom return NULL; 342f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 343f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom parsed->heap_maximum_size_ = size; 344f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-XX:HeapGrowthLimit=")) { 345f1a5adc87760f938b01df26d906295063546b259Elliott Hughes size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapGrowthLimit=")).c_str(), 1024); 346c11607024d2e7a52ca690b8339306cab040e6653jeffhao if (size == 0) { 347c11607024d2e7a52ca690b8339306cab040e6653jeffhao if (ignore_unrecognized) { 348c11607024d2e7a52ca690b8339306cab040e6653jeffhao continue; 349c11607024d2e7a52ca690b8339306cab040e6653jeffhao } 350c11607024d2e7a52ca690b8339306cab040e6653jeffhao // TODO: usage 351c11607024d2e7a52ca690b8339306cab040e6653jeffhao LOG(FATAL) << "Failed to parse " << option; 352c11607024d2e7a52ca690b8339306cab040e6653jeffhao return NULL; 353c11607024d2e7a52ca690b8339306cab040e6653jeffhao } 354c11607024d2e7a52ca690b8339306cab040e6653jeffhao parsed->heap_growth_limit_ = size; 355f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xss")) { 356f1a5adc87760f938b01df26d906295063546b259Elliott Hughes size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).c_str(), 1); 357f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (size == 0) { 358f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom if (ignore_unrecognized) { 359f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom continue; 360f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 3614a289ed61242964b921434de7d375f46480472a1Brian Carlstrom // TODO: usage 36269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom LOG(FATAL) << "Failed to parse " << option; 363f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom return NULL; 364f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom } 365f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom parsed->stack_size_ = size; 366f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-D")) { 367f1a5adc87760f938b01df26d906295063546b259Elliott Hughes parsed->properties_.push_back(option.substr(strlen("-D"))); 368f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xjnitrace:")) { 369f1a5adc87760f938b01df26d906295063546b259Elliott Hughes parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:")); 3705de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom } else if (option == "compiler") { 371d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes parsed->is_compiler_ = true; 3729ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes } else if (option == "-Xzygote") { 3739ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes parsed->is_zygote_ = true; 374f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-verbose:")) { 3750af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes std::vector<std::string> verbose_options; 376f1a5adc87760f938b01df26d906295063546b259Elliott Hughes Split(option.substr(strlen("-verbose:")), ',', verbose_options); 3770af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes for (size_t i = 0; i < verbose_options.size(); ++i) { 3784dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes if (verbose_options[i] == "class") { 3794dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.class_linker = true; 3804dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "compiler") { 3814dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.compiler = true; 3824dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "heap") { 3834dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.heap = true; 3844dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "gc") { 3854dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.gc = true; 3864dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "jdwp") { 3874dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.jdwp = true; 3884dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "jni") { 3894dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.jni = true; 3904dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "monitor") { 3914dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.monitor = true; 3924dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "startup") { 3934dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.startup = true; 3944dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "third-party-jni") { 3954dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.third_party_jni = true; 3964dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else if (verbose_options[i] == "threads") { 3974dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes gLogVerbosity.threads = true; 3984dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } else { 3994dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i]; 4004dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } 4010af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes } 402f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xjnigreflimit:")) { 403bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes parsed->jni_globals_max_ = ParseIntegerOrDie(option); 404f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xlockprofthreshold:")) { 405bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes parsed->lock_profiling_threshold_ = ParseIntegerOrDie(option); 406f1a5adc87760f938b01df26d906295063546b259Elliott Hughes } else if (StartsWith(option, "-Xstacktracefile:")) { 4077c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom// always show stack traces in debug builds 4087c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom#ifdef NDEBUG 409f1a5adc87760f938b01df26d906295063546b259Elliott Hughes parsed->stack_trace_file_ = option.substr(strlen("-Xstacktracefile:")); 4107c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom#endif 411fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes } else if (option == "sensitiveThread") { 412fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes parsed->hook_is_sensitive_thread_ = reinterpret_cast<bool (*)()>(options[i].second); 4136ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom } else if (option == "vfprintf") { 4146ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->hook_vfprintf_ = reinterpret_cast<int (*)(FILE *, const char*, va_list)>(options[i].second); 4156ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom } else if (option == "exit") { 4166ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second); 4176ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom } else if (option == "abort") { 4186ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second); 41958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } else if (option == "host-prefix") { 42058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second); 421b3e66dfcd069db8818cd902d787ff1d7bbca45f2Elliott Hughes } else if (option == "-Xgenregmap" || option == "-Xgc:precise") { 422b3e66dfcd069db8818cd902d787ff1d7bbca45f2Elliott Hughes // We silently ignore these for backwards compatibility. 4238a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } else { 4248a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom if (!ignore_unrecognized) { 4256ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom // TODO: print usage via vfprintf 42627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom LOG(ERROR) << "Unrecognized option " << option; 42727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // TODO: this should exit, but for now tolerate unknown options 42827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom //return NULL; 4298a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } 4308a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } 4318a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom } 4328a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom 433223f20fa939c386c695977263780dea2195093dbBrian Carlstrom if (!parsed->is_compiler_ && parsed->image_.empty()) { 434223f20fa939c386c695977263780dea2195093dbBrian Carlstrom parsed->image_ += GetAndroidRoot(); 435223f20fa939c386c695977263780dea2195093dbBrian Carlstrom parsed->image_ += "/framework/boot.art"; 4365de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom } 437c11607024d2e7a52ca690b8339306cab040e6653jeffhao if (parsed->heap_growth_limit_ == 0) { 438c11607024d2e7a52ca690b8339306cab040e6653jeffhao parsed->heap_growth_limit_ = parsed->heap_maximum_size_; 439c11607024d2e7a52ca690b8339306cab040e6653jeffhao } 4405de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom 441cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes LOG(INFO) << "Build type: " 442cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes#ifndef NDEBUG 443cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes << "debug" 444cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes#else 445cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes << "optimized" 446cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes#endif 447cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off"); 44885d1545e985ac689db4bad7849880e843707c862Elliott Hughes 44969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom return parsed.release(); 4508a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom} 4518a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom 4528a436595d36c1e4935984fcac249d7d877e00383Brian CarlstromRuntime* Runtime::Create(const Options& options, bool ignore_unrecognized) { 4532ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // TODO: acquire a static mutex on Runtime to avoid racing. 4542ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (Runtime::instance_ != NULL) { 4552ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return NULL; 4562ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 457dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes instance_ = new Runtime; 458dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes if (!instance_->Init(options, ignore_unrecognized)) { 459dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes delete instance_; 460dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes instance_ = NULL; 46161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro } 46269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom return instance_; 46369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom} 4640af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes 465aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromvoid CreateSystemClassLoader() { 466aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom if (ClassLoader::UseCompileTimeClassPath()) { 467aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return; 468aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 469aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 470aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom Thread* self = Thread::Current(); 471aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 472aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom // Must be in the kNative state for calling native methods. 473aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK_EQ(self->GetState(), Thread::kNative); 474aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 475aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom JNIEnv* env = self->GetJniEnv(); 476df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader")); 477df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom CHECK(ClassLoader_class.get() != NULL); 478df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(), 479df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom "getSystemClassLoader", 480df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom "()Ljava/lang/ClassLoader;"); 481df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom CHECK(getSystemClassLoader != NULL); 482df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(), 483df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom getSystemClassLoader)); 484df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom CHECK(class_loader.get() != NULL); 485df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom 486df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get())); 4871b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson 4881b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson ScopedLocalRef<jclass> Thread_class(env, env->FindClass("java/lang/Thread")); 4891b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson CHECK(Thread_class.get() != NULL); 4901b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson jfieldID contextClassLoader = env->GetFieldID(Thread_class.get(), 4911b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson "contextClassLoader", 4921b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson "Ljava/lang/ClassLoader;"); 4931b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson CHECK(contextClassLoader != NULL); 4941b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson ScopedLocalRef<jobject> self_jobject(env, AddLocalReference<jobject>(env, self->GetPeer())); 4951b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson env->SetObjectField(self_jobject.get(), contextClassLoader, class_loader.get()); 496aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 497aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 49869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromvoid Runtime::Start() { 4994dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::Start entering"; 50058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom 50158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom CHECK(host_prefix_.empty()) << host_prefix_; 50258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom 503f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom // Restore main thread state to kNative as expected by native code 504f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom Thread::Current()->SetState(Thread::kNative); 505f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom 5065d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom started_ = true; 5075d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom 508ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom // InitNativeMethods needs to be after started_ so that the classes 509ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom // it touches will have methods linked to the oat file if necessary. 510ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom InitNativeMethods(); 511ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 5129a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson Thread::FinishStartup(); 5139a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson 514d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes if (!is_zygote_) { 515d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes DidForkFromZygote(); 516d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes } 5179ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes 51885d1545e985ac689db4bad7849880e843707c862Elliott Hughes StartDaemonThreads(); 5190a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom 520aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CreateSystemClassLoader(); 521aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 522726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes Thread::Current()->GetJniEnv()->locals.AssertEmpty(); 523726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes 5244dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::Start exiting"; 52585d1545e985ac689db4bad7849880e843707c862Elliott Hughes} 52685d1545e985ac689db4bad7849880e843707c862Elliott Hughes 527caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::DidForkFromZygote() { 528caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom is_zygote_ = false; 529d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes 530caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom StartSignalCatcher(); 531d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes 532d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // Start the JDWP thread. If the command-line debugger flags specified "suspend=y", 533d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // this will pause the runtime, so we probably want this to come last. 534d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes Dbg::StartJdwp(); 535caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom} 536caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom 537caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::StartSignalCatcher() { 538caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom if (!is_zygote_) { 53994ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes signal_catcher_ = new SignalCatcher(stack_trace_file_); 540caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom } 541caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom} 542caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom 54385d1545e985ac689db4bad7849880e843707c862Elliott Hughesvoid Runtime::StartDaemonThreads() { 5444dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::StartDaemonThreads entering"; 54585d1545e985ac689db4bad7849880e843707c862Elliott Hughes 546719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes Thread* self = Thread::Current(); 547aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 548aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom // Must be in the kNative state for calling native methods. 549aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK_EQ(self->GetState(), Thread::kNative); 550aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 551719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes JNIEnv* env = self->GetJniEnv(); 552726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Daemons")); 553726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes CHECK(c.get() != NULL); 554726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V"); 555719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes CHECK(mid != NULL); 556726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes env->CallStaticVoidMethod(c.get(), mid); 5578cf5bc0ab8742df107f0f4fc8ec0e991b6568f11Elliott Hughes CHECK(!env->ExceptionCheck()); 5589ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes 5594dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::StartDaemonThreads exiting"; 56061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 56161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 5626b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughesbool Runtime::IsShuttingDown() const { 5636b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes return shutting_down_; 5646b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes} 5656b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes 56658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrombool Runtime::IsStarted() const { 567dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes return started_; 568dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes} 569dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes 5700af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesbool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { 571c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize); 5726ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom 57390a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized)); 57490a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes if (options.get() == NULL) { 575e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to parse options"; 5766ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom return false; 5776ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom } 5784dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::Init -verbose:startup enabled"; 5797ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes 580bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes SetJniGlobalsMax(options->jni_globals_max_); 5814dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_); 58232d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes 58358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom host_prefix_ = options->host_prefix_; 58458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom boot_class_path_ = options->boot_class_path_; 58558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom class_path_ = options->class_path_; 5867ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes properties_ = options->properties_; 5877ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes 588d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes is_compiler_ = options->is_compiler_; 5899ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes is_zygote_ = options->is_zygote_; 5909ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes 5910af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes vfprintf_ = options->hook_vfprintf_; 5920af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes exit_ = options->hook_exit_; 5930af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes abort_ = options->hook_abort_; 5946ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom 595be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes default_stack_size_ = options->stack_size_; 59694ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes stack_trace_file_ = options->stack_trace_file_; 5976ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom 598c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes monitor_list_ = new MonitorList; 5994dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes thread_list_ = new ThreadList; 600cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes intern_table_ = new InternTable; 601cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 6024dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes Heap::Init(options->heap_initial_size_, 603c11607024d2e7a52ca690b8339306cab040e6653jeffhao options->heap_growth_limit_, 60430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers options->heap_maximum_size_, 605223f20fa939c386c695977263780dea2195093dbBrian Carlstrom options->image_); 6066ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom 607c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes BlockSignals(); 608c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 609a09576416788b916095739e43a16917e7948f3a4Elliott Hughes java_vm_ = new JavaVMExt(this, options.get()); 610515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes 611be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes Thread::Startup(); 612d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 6135fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes // ClassLinker needs an attached thread, but we can't fully attach a thread 6145fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes // without creating objects. 6155fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes Thread::Attach(this, "main", false); 6166ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom 617f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom // Set us to runnable so tools using a runtime can allocate and GC by default 618f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom Thread::Current()->SetState(Thread::kRunnable); 619f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom 62058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom CHECK_GE(Heap::GetSpaces().size(), 1U); 62158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace()) 6224dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes ? ClassLinker::Create(intern_table_) 6234dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes : ClassLinker::Create(options->boot_class_path_, intern_table_)); 6246ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom 6254dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::Init exiting"; 6267b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro return true; 6277b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro} 6287b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro 629038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Runtime::InitNativeMethods() { 6304dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::InitNativeMethods entering"; 631ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes Thread* self = Thread::Current(); 632ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes JNIEnv* env = self->GetJniEnv(); 633ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes 634418d20fc407052d4152157f61e7453359f902383Elliott Hughes // Must be in the kNative state for calling native methods (JNI_OnLoad code). 635aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK_EQ(self->GetState(), Thread::kNative); 636ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes 637418d20fc407052d4152157f61e7453359f902383Elliott Hughes // First set up JniConstants, which is used by both the runtime's built-in native 638418d20fc407052d4152157f61e7453359f902383Elliott Hughes // methods and libcore. 639fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes JniConstants::init(env); 640fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes 641418d20fc407052d4152157f61e7453359f902383Elliott Hughes // Then set up the native methods provided by the runtime itself. 642ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes RegisterRuntimeNativeMethods(env); 643ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes 644418d20fc407052d4152157f61e7453359f902383Elliott Hughes // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad. 645418d20fc407052d4152157f61e7453359f902383Elliott Hughes // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's 646418d20fc407052d4152157f61e7453359f902383Elliott Hughes // the library that implements System.loadLibrary! 647ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes LoadJniLibrary(instance_->GetJavaVM(), "javacore"); 6484dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(startup) << "Runtime::InitNativeMethods exiting"; 649ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes} 650ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes 651ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesvoid Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { 652ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#define REGISTER(FN) extern void FN(JNIEnv*); FN(env) 6535167c97a4f672ba821453418e3943988fabbfc43Ian Rogers // Register Throwable first so that registration of other native methods can throw exceptions 6545167c97a4f672ba821453418e3943988fabbfc43Ian Rogers REGISTER(register_java_lang_Throwable); 655f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom REGISTER(register_dalvik_system_DexFile); 6569d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes REGISTER(register_dalvik_system_VMDebug); 6577ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes REGISTER(register_dalvik_system_VMRuntime); 6588daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes REGISTER(register_dalvik_system_VMStack); 65901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes REGISTER(register_dalvik_system_Zygote); 660d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes REGISTER(register_java_lang_Class); 661bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes REGISTER(register_java_lang_Object); 662bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes REGISTER(register_java_lang_Runtime); 663bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes REGISTER(register_java_lang_String); 664bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes REGISTER(register_java_lang_System); 6658daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes REGISTER(register_java_lang_Thread); 66664bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes REGISTER(register_java_lang_VMClassLoader); 6675b8e4c810a97c9dc417142b8c6e07871ae15c797Brian Carlstrom REGISTER(register_java_lang_reflect_Array); 6682a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes REGISTER(register_java_lang_reflect_Constructor); 669f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom REGISTER(register_java_lang_reflect_Field); 670f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom REGISTER(register_java_lang_reflect_Method); 67195caa791e560da97363c0c0d22bfda4a7e7377c3Jesse Wilson REGISTER(register_java_lang_reflect_Proxy); 672bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes REGISTER(register_java_util_concurrent_atomic_AtomicLong); 673395520eaa47eca25b92e86188accf3095d60af49Brian Carlstrom REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer); 674f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal); 6755ee7a8b56dee896245e0f4ae5215f8b7376c1787Elliott Hughes REGISTER(register_sun_misc_Unsafe); 676ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#undef REGISTER 677ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes} 678ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes 6798daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesvoid Runtime::Dump(std::ostream& os) { 680e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes // TODO: dump other runtime statistics? 681cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes GetClassLinker()->DumpForSigQuit(os); 682cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes GetInternTable()->DumpForSigQuit(os); 68342ee14279065352a4b9a3e8028d02c567e847d05Elliott Hughes os << "\n"; 6848daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 6858daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes thread_list_->Dump(os); 686e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes} 687e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 68821a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughesvoid Runtime::DumpLockHolders(std::ostream& os) { 68921a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes pid_t heap_lock_owner = Heap::GetLockOwner(); 69021a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes pid_t thread_list_lock_owner = GetThreadList()->GetLockOwner(); 69121a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes pid_t classes_lock_owner = GetClassLinker()->GetClassesLockOwner(); 69221a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes pid_t dex_lock_owner = GetClassLinker()->GetDexLockOwner(); 69321a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes if ((heap_lock_owner | thread_list_lock_owner | classes_lock_owner | dex_lock_owner) != 0) { 69421a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes os << "Heap lock owner tid: " << heap_lock_owner << "\n" 69521a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes << "ThreadList lock owner tid: " << thread_list_lock_owner << "\n" 69621a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes << "ClassLinker classes lock owner tid: " << classes_lock_owner << "\n" 69721a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes << "ClassLinker dex lock owner tid: " << dex_lock_owner << "\n"; 69821a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes } 69921a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes} 70021a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes 7019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::SetStatsEnabled(bool new_state) { 7029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes if (new_state == true) { 7039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes GetStats()->Clear(~0); 7049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes // TODO: wouldn't it make more sense to clear _all_ threads' stats? 7059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes Thread::Current()->GetStats()->Clear(~0); 7069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes } 7079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes stats_enabled_ = new_state; 7089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes} 7099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 7109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::ResetStats(int kinds) { 7119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes GetStats()->Clear(kinds & 0xffff); 7129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes // TODO: wouldn't it make more sense to clear _all_ threads' stats? 7139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes Thread::Current()->GetStats()->Clear(kinds >> 16); 7149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes} 7159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 7169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott HughesRuntimeStats* Runtime::GetStats() { 7179d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return &stats_; 7189d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes} 7199d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 7209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesint32_t Runtime::GetStat(int kind) { 7219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes RuntimeStats* stats; 7229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes if (kind < (1<<16)) { 7239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes stats = GetStats(); 7249d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes } else { 7259d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes stats = Thread::Current()->GetStats(); 7269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes kind >>= 16; 7279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes } 7289d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes switch (kind) { 7299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_ALLOCATED_OBJECTS: 7309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return stats->allocated_objects; 7319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_ALLOCATED_BYTES: 7329d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return stats->allocated_bytes; 7339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_FREED_OBJECTS: 7349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return stats->freed_objects; 7359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_FREED_BYTES: 7369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return stats->freed_bytes; 7379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_GC_INVOCATIONS: 7389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return stats->gc_for_alloc_count; 7399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_CLASS_INIT_COUNT: 7409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return stats->class_init_count; 7419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_CLASS_INIT_TIME: 7429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes // Convert ns to us, reduce to 32 bits. 7439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return (int) (stats->class_init_time_ns / 1000); 7449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_EXT_ALLOCATED_OBJECTS: 7459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_EXT_ALLOCATED_BYTES: 7469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_EXT_FREED_OBJECTS: 7479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes case KIND_EXT_FREED_BYTES: 7489d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return 0; // backward compatibility 7499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes default: 7509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes CHECK(false); 7519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes return -1; // unreachable 7529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes } 7539d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes} 7549d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 755c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Runtime::BlockSignals() { 756c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes sigset_t sigset; 757c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (sigemptyset(&sigset) == -1) { 758c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(FATAL) << "sigemptyset failed"; 759c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 760c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (sigaddset(&sigset, SIGPIPE) == -1) { 761c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(ERROR) << "sigaddset SIGPIPE failed"; 762c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 763c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes // SIGQUIT is used to dump the runtime's state (including stack traces). 764c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (sigaddset(&sigset, SIGQUIT) == -1) { 765c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(ERROR) << "sigaddset SIGQUIT failed"; 766c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 767c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes // SIGUSR1 is used to initiate a heap dump. 768c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (sigaddset(&sigset, SIGUSR1) == -1) { 769c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(ERROR) << "sigaddset SIGUSR1 failed"; 770c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 771c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0); 772c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 773c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 7745fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughesvoid Runtime::AttachCurrentThread(const char* name, bool as_daemon) { 7755fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes Thread::Attach(instance_, name, as_daemon); 77661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 77761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 778d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Runtime::DetachCurrentThread() { 779038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // TODO: check we're not calling DetachCurrentThread from a call stack that 780038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // includes managed frames. (It's only valid if the stack is all-native.) 78102b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes thread_list_->Unregister(); 7827b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro} 7837b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro 784e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { 785bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes Dbg::VisitRoots(visitor, arg); 786e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_linker_->VisitRoots(visitor, arg); 787e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom intern_table_->VisitRoots(visitor, arg); 788e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom java_vm_->VisitRoots(visitor, arg); 789e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom thread_list_->VisitRoots(visitor, arg); 790e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom visitor(jni_stub_array_, arg); 791e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom visitor(abstract_method_error_stub_array_, arg); 7924f0d07c783afef89703dce32c94440fc8621a29bIan Rogers for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) { 7934f0d07c783afef89703dce32c94440fc8621a29bIan Rogers visitor(resolution_stub_array_[i], arg); 7944f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 7954f0d07c783afef89703dce32c94440fc8621a29bIan Rogers for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 7964f0d07c783afef89703dce32c94440fc8621a29bIan Rogers visitor(callee_save_method_[i], arg); 7974f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 798e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 799e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 800169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogersbool Runtime::HasJniDlsymLookupStub() const { 801e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return jni_stub_array_ != NULL; 802e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 803e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 804169c9a7f46776b235d0a37d5e0ff27682deffe06Ian RogersByteArray* Runtime::GetJniDlsymLookupStub() const { 805e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(jni_stub_array_ != NULL); 806e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return jni_stub_array_; 807e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 808e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 809169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogersvoid Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) { 810aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK(jni_stub_array != NULL) << " jni_stub_array=" << jni_stub_array; 811aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array) 812aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array; 813e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom jni_stub_array_ = jni_stub_array; 814e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 815e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 816e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool Runtime::HasAbstractMethodErrorStubArray() const { 817e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return abstract_method_error_stub_array_ != NULL; 818e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 819e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 820e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromByteArray* Runtime::GetAbstractMethodErrorStubArray() const { 821e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(abstract_method_error_stub_array_ != NULL); 822e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return abstract_method_error_stub_array_; 823e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 824e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 825e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) { 826e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(abstract_method_error_stub_array != NULL); 827e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array); 828e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom abstract_method_error_stub_array_ = abstract_method_error_stub_array; 829e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 830e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 8311cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers 8321cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersRuntime::TrampolineType Runtime::GetTrampolineType(Method* method) { 8331cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers if (method == NULL) { 8341cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers return Runtime::kUnknownMethod; 8351cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers } else if (method->IsStatic()) { 8361cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers return Runtime::kStaticMethod; 8371cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers } else { 8381cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers return Runtime::kInstanceMethod; 8391cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers } 8401cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers} 8411cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers 8421cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersbool Runtime::HasResolutionStubArray(TrampolineType type) const { 8431cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers return resolution_stub_array_[type] != NULL; 844ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 845ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 8461cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersByteArray* Runtime::GetResolutionStubArray(TrampolineType type) const { 8471cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers CHECK(HasResolutionStubArray(type)); 8484f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType)); 8491cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers return resolution_stub_array_[type]; 850ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 851ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 8521cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogersvoid Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type) { 853ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers CHECK(resolution_stub_array != NULL); 8541cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array); 8551cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers resolution_stub_array_[type] = resolution_stub_array; 856ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 857ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 858ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian CarlstromMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) { 859ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers Class* method_class = Method::GetMethodClass(); 86040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject())); 861ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers method->SetDeclaringClass(method_class); 8626d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers // TODO: use a special method for callee saves 8636d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers method->SetMethodIndex(DexFile::kDexNoIndex16); 8643320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetCode(NULL); 865ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if ((instruction_set == kThumb2) || (instruction_set == kArm)) { 8664f0d07c783afef89703dce32c94440fc8621a29bIan Rogers uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) | 8674f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11); 8684f0d07c783afef89703dce32c94440fc8621a29bIan Rogers uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3); 8694f0d07c783afef89703dce32c94440fc8621a29bIan Rogers uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9); 8704f0d07c783afef89703dce32c94440fc8621a29bIan Rogers uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills :0) | 8714f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (type == kSaveAll ? all_spills :0) | (1 << art::arm::LR); 8724f0d07c783afef89703dce32c94440fc8621a29bIan Rogers uint32_t fp_all_spills = (1 << art::arm::S0) | (1 << art::arm::S1) | (1 << art::arm::S2) | 8734f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S3) | (1 << art::arm::S4) | (1 << art::arm::S5) | 8744f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S6) | (1 << art::arm::S7) | (1 << art::arm::S8) | 8754f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S9) | (1 << art::arm::S10) | (1 << art::arm::S11) | 8764f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) | 8774f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) | 8784f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) | 8794f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) | 8804f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) | 8814f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) | 8824f0d07c783afef89703dce32c94440fc8621a29bIan Rogers (1 << art::arm::S30) | (1 << art::arm::S31); 8834f0d07c783afef89703dce32c94440fc8621a29bIan Rogers uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0; 8844f0d07c783afef89703dce32c94440fc8621a29bIan Rogers size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ + 8854f0d07c783afef89703dce32c94440fc8621a29bIan Rogers __builtin_popcount(fp_spills) /* fprs */ + 8864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 1 /* Method* */) * kPointerSize, kStackAlignment); 88715fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers method->SetFrameSizeInBytes(frame_size); 8884f0d07c783afef89703dce32c94440fc8621a29bIan Rogers method->SetCoreSpillMask(core_spills); 8894f0d07c783afef89703dce32c94440fc8621a29bIan Rogers method->SetFpSpillMask(fp_spills); 890ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } else if (instruction_set == kX86) { 891ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers method->SetFrameSizeInBytes(32); 8924f0d07c783afef89703dce32c94440fc8621a29bIan Rogers method->SetCoreSpillMask((1 << art::x86::EBX) | (1 << art::x86::EBP) | (1 << art::x86::ESI) | 893ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers (1 << art::x86::EDI)); 894ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers method->SetFpSpillMask(0); 895ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers } else { 896ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers UNIMPLEMENTED(FATAL); 897ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers } 89840381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom return method.get(); 899ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers} 900ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers 9014f0d07c783afef89703dce32c94440fc8621a29bIan Rogersbool Runtime::HasCalleeSaveMethod(CalleeSaveType type) const { 9024f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return callee_save_method_[type] != NULL; 903e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 904410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 905e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom// Returns a special method that describes all callee saves being spilled to the stack. 9064f0d07c783afef89703dce32c94440fc8621a29bIan RogersMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type) const { 9074f0d07c783afef89703dce32c94440fc8621a29bIan Rogers CHECK(HasCalleeSaveMethod(type)); 9084f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return callee_save_method_[type]; 9091f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom} 9101f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom 9114f0d07c783afef89703dce32c94440fc8621a29bIan Rogersvoid Runtime::SetCalleeSaveMethod(Method* method, CalleeSaveType type) { 9124f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType)); 9134f0d07c783afef89703dce32c94440fc8621a29bIan Rogers callee_save_method_[type] = method; 914e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 915e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 9162692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Runtime::EnableMethodTracing(Trace* tracer) { 9172692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao CHECK(!IsMethodTracingActive()); 9182692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao tracer_ = tracer; 9192692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 9202692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 9212692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Runtime::DisableMethodTracing() { 9222692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao CHECK(IsMethodTracingActive()); 9232692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao delete tracer_; 9242692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao tracer_ = NULL; 9252692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 9262692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 9272692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaobool Runtime::IsMethodTracingActive() const { 9282692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao return (tracer_ != NULL); 9292692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 9302692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 9312692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaoTrace* Runtime::GetTracer() const { 9322692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao CHECK(IsMethodTracingActive()); 9332692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao return tracer_; 9342692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 9352692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 9366b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro} // namespace art 937