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
19bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
20bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom#include <sys/mount.h>
21bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom#include <linux/fs.h>
22bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom
23dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom#include <signal.h>
24d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes#include <sys/syscall.h>
25dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom
26ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdio>
27ffe6736397d17457188727510f0a2953f69a383aElliott Hughes#include <cstdlib>
288a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom#include <limits>
292ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <vector>
30ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
31166db04e259ca51838c311891598664deeed85adIan Rogers#include "arch/arm/registers_arm.h"
32166db04e259ca51838c311891598664deeed85adIan Rogers#include "arch/mips/registers_mips.h"
33166db04e259ca51838c311891598664deeed85adIan Rogers#include "arch/x86/registers_x86.h"
342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "atomic.h"
35578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h"
363bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "debugger.h"
371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h"
381d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/heap.h"
391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h"
40e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "image.h"
41725a957985171d712d5c048cc3d00ff14968784bjeffhao#include "instrumentation.h"
42cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes#include "intern_table.h"
435d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao#include "invoke_arg_array_builder.h"
44c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h"
45ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h"
46ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array.h"
4862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "mirror/class-inl.h"
492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h"
5132d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes#include "monitor.h"
52e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_file.h"
53726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes#include "ScopedLocalRef.h"
5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
55e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#include "signal_catcher.h"
56457005c557b8762475db3220ce5a747d629f975bElliott Hughes#include "signal_set.h"
571f5393447b9f45be7918042d9ee7b521376de866Ian Rogers#include "sirt_ref.h"
58578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h"
598daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h"
60b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao#include "trace.h"
613bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include "UniquePtr.h"
62776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#include "verifier/method_verifier.h"
63eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "well_known_classes.h"
6461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
657934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom#include "JniConstants.h"  // Last to avoid LOG redefinition in ics-mr1-plus-art.
6690a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes
676b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art {
687b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
692ed144c2b49ae1da6c464d7a1be0062870530802Carl ShapiroRuntime* Runtime::instance_ = NULL;
702ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro
71dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesRuntime::Runtime()
72d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    : is_compiler_(false),
73d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      is_zygote_(false),
74069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier      is_concurrent_gc_enabled_(true),
758718359763aa3dcd0033a2d2e67e0cb145fb9c53Anwar Ghuloum      is_explicit_gc_disabled_(false),
766cf23884730574ca364b357e823259f4993e6908Elliott Hughes      default_stack_size_(0),
77b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      heap_(NULL),
78c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes      monitor_list_(NULL),
79dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      thread_list_(NULL),
80dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      intern_table_(NULL),
81dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      class_linker_(NULL),
82dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      signal_catcher_(NULL),
83dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      java_vm_(NULL),
84225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes      pre_allocated_OutOfMemoryError_(NULL),
851984651929744dd603fd082e23eacd877b9bc177Ian Rogers      resolution_method_(NULL),
86120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers      threads_being_born_(0),
87c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      shutdown_cond_(new ConditionVariable("Runtime shutdown", *Locks::runtime_shutdown_lock_)),
886b3557571e798b60df995f978fa01c0ca1980dfdElliott Hughes      shutting_down_(false),
89120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers      shutting_down_started_(false),
90dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      started_(false),
917664f5cd118b355a5fe0c7536cb48ac991ed2b62Mathieu Chartier      finished_starting_(false),
92dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      vfprintf_(NULL),
93dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes      exit_(NULL),
949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      abort_(NULL),
952692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao      stats_enabled_(false),
96776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers      method_trace_(0),
97776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers      method_trace_file_size_(0),
9862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      instrumentation_(),
99365c10235438607541fa2259a5fec48061b90bd8Ian Rogers      use_compile_time_class_path_(false),
100365c10235438607541fa2259a5fec48061b90bd8Ian Rogers      main_thread_group_(NULL),
101ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom      system_thread_group_(NULL),
102ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom      system_class_loader_(NULL) {
1034f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
104225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes    callee_save_methods_[i] = NULL;
1054f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
106dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes}
107dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
10861e019d291583029c01b61b93bea750f2b663c37Carl ShapiroRuntime::~Runtime() {
109120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  Thread* self = Thread::Current();
110120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  {
111120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
112120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    shutting_down_started_ = true;
113120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    while (threads_being_born_ > 0) {
114c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers      shutdown_cond_->Wait(self);
115120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    }
116120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers    shutting_down_ = true;
117120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  }
11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Trace::Shutdown();
119b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
120a6399035ee2af012e2ac898ee7a753a2f83b35abMathieu Chartier  // Make sure to let the GC complete if it is running.
121120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  heap_->WaitForConcurrentGcToComplete(self);
12235883cc623fdf475a4ead1dafcba9e9becc1ed11Mathieu Chartier  heap_->DeleteThreadPool();
123a6399035ee2af012e2ac898ee7a753a2f83b35abMathieu Chartier
1245fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  // Make sure our internal threads are dead before we start tearing down things they're using.
125e52e49b32f5cf862a414da63e5dbd2eb04ad758eElliott Hughes  Dbg::StopJdwp();
1265fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes  delete signal_catcher_;
1275fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes
128038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes  // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
12993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes  delete thread_list_;
130c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes  delete monitor_list_;
13161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  delete class_linker_;
132b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  delete heap_;
133cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  delete intern_table_;
134c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes  delete java_vm_;
135c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  Thread::Shutdown();
1367c6169de901fd0a39c8e0c078874dc25207f5b59Elliott Hughes  QuasiAtomic::Shutdown();
1374d4adb1dae07bb7421e863732ab789413a3b43f0Sebastien Hertz  verifier::MethodVerifier::Shutdown();
1384acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
1394a289ed61242964b921434de7d375f46480472a1Brian Carlstrom  CHECK(instance_ == NULL || instance_ == this);
1404acf4646fbbd6c1893cec5bb700d3c7cd09e4a26Carl Shapiro  instance_ = NULL;
14161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
14261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
143e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughesstruct AbortState {
144e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  void Dump(std::ostream& os) {
145f08e473519dc5c7ccb85eb2b333f9d0aff23a329Ian Rogers    if (gAborting > 1) {
146cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes      os << "Runtime aborting --- recursively, so no thread-specific detail!\n";
147cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes      return;
148cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes    }
149f08e473519dc5c7ccb85eb2b333f9d0aff23a329Ian Rogers    gAborting++;
150e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    os << "Runtime aborting...\n";
1516c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes    if (Runtime::Current() == NULL) {
1526c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes      os << "(Runtime does not yet exist!)\n";
1536c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes      return;
1546c7d244058b74cdd61533968dd6cddd7003d2671Elliott Hughes    }
155e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    Thread* self = Thread::Current();
156e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    if (self == NULL) {
157e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes      os << "(Aborting thread was not attached to runtime!)\n";
158e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    } else {
15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      // TODO: we're aborting and the ScopedObjectAccess may attempt to acquire the mutator_lock_
16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      //       which may block indefinitely if there's a misbehaving thread holding it exclusively.
16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      //       The code below should be made robust to this.
16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      ScopedObjectAccess soa(self);
1632f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers      os << "Aborting thread:\n";
164899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes      self->Dump(os);
165899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes      if (self->IsExceptionPending()) {
16662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        ThrowLocation throw_location;
16762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        mirror::Throwable* exception = self->GetException(&throw_location);
16862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        os << "Pending exception " << PrettyTypeOf(exception)
169bc939663ccfbe0c648dd6a3670041510aca82420Ian Rogers            << " thrown by '" << throw_location.Dump() << "'\n"
17062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers            << exception->Dump();
171899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes      }
172e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes    }
1732f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers    DumpAllThreads(os, self);
1742f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers  }
1752f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers
1762f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers  void DumpAllThreads(std::ostream& os, Thread* self) NO_THREAD_SAFETY_ANALYSIS {
1772f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers    bool tll_already_held = Locks::thread_list_lock_->IsExclusiveHeld(self);
1782f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers    bool ml_already_held = Locks::mutator_lock_->IsSharedHeld(self);
179fbd229147c62d8e8787e27e7c9db3b387ffe39efIan Rogers    if (!tll_already_held || !ml_already_held) {
180fbd229147c62d8e8787e27e7c9db3b387ffe39efIan Rogers      os << "Dumping all threads without appropriate locks held:"
181fbd229147c62d8e8787e27e7c9db3b387ffe39efIan Rogers          << (!tll_already_held ? " thread list lock" : "")
1822fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers          << (!ml_already_held ? " mutator lock" : "")
1832fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers          << "\n";
1842f7f9b6a3f0f6f334f0314b10d1dc696e5a9afa4Ian Rogers    }
185fbd229147c62d8e8787e27e7c9db3b387ffe39efIan Rogers    os << "All threads:\n";
186fbd229147c62d8e8787e27e7c9db3b387ffe39efIan Rogers    Runtime::Current()->GetThreadList()->DumpLocked(os);
187e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  }
188e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes};
189e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes
1908593fdbacf97261f790ca53ea0ec416f57c987a7Elliott Hughesvoid Runtime::Abort() {
191f08e473519dc5c7ccb85eb2b333f9d0aff23a329Ian Rogers  gAborting++;  // set before taking any locks
19281b8871007101f42e2baabf213e1312004073eb0Brian Carlstrom
193131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes  // Ensure that we don't have multiple threads trying to abort at once,
194131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes  // which would result in significantly worse diagnostics.
19550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  MutexLock mu(Thread::Current(), *Locks::abort_lock_);
196131aef8c94292cc530da2fd91ee98d1432352959Elliott Hughes
197ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Get any pending output out of the way.
198ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  fflush(NULL);
199ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
200ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // Many people have difficulty distinguish aborts from crashes,
201ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // so be explicit.
202e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes  AbortState state;
2039ee5f9ccba015beb3ae376ed08b3363bd9df6422Elliott Hughes  LOG(INTERNAL_FATAL) << Dumpable<AbortState>(state);
204ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
2058593fdbacf97261f790ca53ea0ec416f57c987a7Elliott Hughes  // Call the abort hook if we have one.
2066ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) {
2076c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes    LOG(INTERNAL_FATAL) << "Calling abort hook...";
2086ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    Runtime::Current()->abort_();
2096ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    // notreached
2106c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes    LOG(INTERNAL_FATAL) << "Unexpectedly returned from abort hook!";
2116ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
2126ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
213dd623dbcb6e5c42c32382c136f16e000ab053216Elliott Hughes#if defined(__GLIBC__)
214d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes  // TODO: we ought to be able to use pthread_kill(3) here (or abort(3),
215d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes  // which POSIX defines in terms of raise(3), which POSIX defines in terms
216d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes  // of pthread_kill(3)). On Linux, though, libcorkscrew can't unwind through
217d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes  // libpthread, which means the stacks we dump would be useless. Calling
218d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes  // tgkill(2) directly avoids that.
219d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes  syscall(__NR_tgkill, getpid(), GetTid(), SIGABRT);
220dd623dbcb6e5c42c32382c136f16e000ab053216Elliott Hughes  // TODO: LLVM installs it's own SIGABRT handler so exit to be safe... Can we disable that in LLVM?
221dd623dbcb6e5c42c32382c136f16e000ab053216Elliott Hughes  // If not, we could use sigaction(3) before calling tgkill(2) and lose this call to exit(3).
222700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  exit(1);
223dd623dbcb6e5c42c32382c136f16e000ab053216Elliott Hughes#else
224dd623dbcb6e5c42c32382c136f16e000ab053216Elliott Hughes  abort();
225d06a6c7c40180c2c906d6981dd461ede2187bd99Elliott Hughes#endif
226ffe6736397d17457188727510f0a2953f69a383aElliott Hughes  // notreached
227ffe6736397d17457188727510f0a2953f69a383aElliott Hughes}
228ffe6736397d17457188727510f0a2953f69a383aElliott Hughes
229cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartierbool Runtime::PreZygoteFork() {
230cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  heap_->PreZygoteFork();
231cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  return true;
232cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier}
233cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
234bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid Runtime::CallExitHook(jint status) {
235bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (exit_ != NULL) {
23634e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes    ScopedThreadStateChange tsc(Thread::Current(), kNative);
237bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    exit_(status);
238bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    LOG(WARNING) << "Exit hook returned instead of exiting!";
239bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
240bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
241bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
2428a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
2438a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// memory sizes.  [kK] indicates kilobytes, [mM] megabytes, and
2448a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// [gG] gigabytes.
2458a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
2468a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "s" should point just past the "-Xm?" part of the string.
2478a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// "div" specifies a divisor, e.g. 1024 if the value must be a multiple
2488a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// of 1024.
2498a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
2508a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// The spec says the -Xmx and -Xms options must be multiples of 1024.  It
2518a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// doesn't say anything about -Xss.
2528a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
2538a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// Returns 0 (a useless size) if "s" is malformed or specifies a low or
2548a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom// non-evenly-divisible value.
2558a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom//
256c1f143de3d0370a17a4561eb83bf10a5d7908aa3Elliott Hughessize_t ParseMemoryOption(const char* s, size_t div) {
2578a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // strtoul accepts a leading [+-], which we don't want,
2588a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  // so make sure our string starts with a decimal digit.
2598a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  if (isdigit(*s)) {
260398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes    char* s2;
261398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes    size_t val = strtoul(s, &s2, 10);
2628a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    if (s2 != s) {
2638a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // s2 should be pointing just after the number.
2648a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // If this is the end of the string, the user
2658a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // has specified a number of bytes.  Otherwise,
2668a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // there should be exactly one more character
2678a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // that specifies a multiplier.
2688a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (*s2 != '\0') {
269f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // The remainder of the string is either a single multiplier
270f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // character, or nothing to indicate that the value is in
271f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        // bytes.
272f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        char c = *s2++;
273f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (*s2 == '\0') {
274f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          size_t mul;
275f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (c == '\0') {
276f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = 1;
277f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'k' || c == 'K') {
278f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = KB;
279f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'm' || c == 'M') {
280f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = MB;
281f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else if (c == 'g' || c == 'G') {
282f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            mul = GB;
2838a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          } else {
284f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Unknown multiplier character.
2858a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom            return 0;
2868a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom          }
287f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
288f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          if (val <= std::numeric_limits<size_t>::max() / mul) {
289f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val *= mul;
290f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          } else {
291f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            // Clamp to a multiple of 1024.
292f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom            val = std::numeric_limits<size_t>::max() & ~(1024-1);
293f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          }
294f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        } else {
295f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          // There's more than one character after the numeric part.
296f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          return 0;
297f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
2988a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
2998a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      // The man page says that a -Xm value must be a multiple of 1024.
3008a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (val % div == 0) {
3018a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom        return val;
3028a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
303fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro    }
304fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro  }
3058a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  return 0;
306fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro}
307fc322c72d7a89a6f7a05c8bdc232d780aecd9232Carl Shapiro
308f1a5adc87760f938b01df26d906295063546b259Elliott Hughessize_t ParseIntegerOrDie(const std::string& s) {
309f1a5adc87760f938b01df26d906295063546b259Elliott Hughes  std::string::size_type colon = s.find(':');
310f1a5adc87760f938b01df26d906295063546b259Elliott Hughes  if (colon == std::string::npos) {
311bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    LOG(FATAL) << "Missing integer: " << s;
312bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  }
313f1a5adc87760f938b01df26d906295063546b259Elliott Hughes  const char* begin = &s[colon + 1];
314bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  char* end;
315bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  size_t result = strtoul(begin, &end, 10);
316bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  if (begin == end || *end != '\0') {
317bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    LOG(FATAL) << "Failed to parse integer in: " << s;
318bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  }
319bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes  return result;
320bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes}
321bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes
3226ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian CarlstromRuntime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
32390a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> parsed(new ParsedOptions());
324a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  const char* boot_class_path_string = getenv("BOOTCLASSPATH");
325a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  if (boot_class_path_string != NULL) {
326a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    parsed->boot_class_path_string_ = boot_class_path_string;
32758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
328a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  const char* class_path_string = getenv("CLASSPATH");
329a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  if (class_path_string != NULL) {
330a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    parsed->class_path_string_ = class_path_string;
33158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
33267d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes  // -Xcheck:jni is off by default for regular builds but on by default in debug builds.
33367d920071fe4a0aa8b8bc339e93b18276238c320Elliott Hughes  parsed->check_jni_ = kIsDebugBuild;
33485d1545e985ac689db4bad7849880e843707c862Elliott Hughes
3351d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  parsed->heap_initial_size_ = gc::Heap::kDefaultInitialSize;
3361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  parsed->heap_maximum_size_ = gc::Heap::kDefaultMaximumSize;
3371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  parsed->heap_min_free_ = gc::Heap::kDefaultMinFree;
3381d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  parsed->heap_max_free_ = gc::Heap::kDefaultMaxFree;
3391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  parsed->heap_target_utilization_ = gc::Heap::kDefaultTargetUtilization;
3406cf23884730574ca364b357e823259f4993e6908Elliott Hughes  parsed->heap_growth_limit_ = 0;  // 0 means no growth limit.
34163a54345598861030178e033ffbd72c0e231a4c9Mathieu Chartier  // Default to number of processors minus one since the main GC thread also does work.
3422775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  parsed->parallel_gc_threads_ = sysconf(_SC_NPROCESSORS_CONF) - 1;
3432775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  // Only the main GC thread, no workers.
3442775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  parsed->conc_gc_threads_ = 0;
3457934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  parsed->stack_size_ = 0;  // 0 means default.
346e0a53e99e2a01f8668d6616c3cec7e2f5a711286Mathieu Chartier  parsed->low_memory_mode_ = false;
347f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom
348d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  parsed->is_compiler_ = false;
3499ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  parsed->is_zygote_ = false;
35050ffee20ced9c0c7ac68889c86be8844cf120cf2Ian Rogers  parsed->interpreter_only_ = false;
351069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier  parsed->is_concurrent_gc_enabled_ = true;
3528718359763aa3dcd0033a2d2e67e0cb145fb9c53Anwar Ghuloum  parsed->is_explicit_gc_disabled_ = false;
3539ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
3542775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  parsed->long_pause_log_threshold_ = gc::Heap::kDefaultLongPauseLogThreshold;
3552775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  parsed->long_gc_log_threshold_ = gc::Heap::kDefaultLongGCLogThreshold;
3562775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  parsed->ignore_max_footprint_ = false;
3572775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier
358fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes  parsed->lock_profiling_threshold_ = 0;
359fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes  parsed->hook_is_sensitive_thread_ = NULL;
360fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes
3616ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_vfprintf_ = vfprintf;
3626ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  parsed->hook_exit_ = exit;
3637934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  parsed->hook_abort_ = NULL;  // We don't call abort(3) by default; see Runtime::Abort.
3648a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
365a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  parsed->compiler_filter_ = Runtime::kDefaultCompilerFilter;
366a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  parsed->huge_method_threshold_ = Runtime::kDefaultHugeMethodThreshold;
367a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  parsed->large_method_threshold_ = Runtime::kDefaultLargeMethodThreshold;
368a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  parsed->small_method_threshold_ = Runtime::kDefaultSmallMethodThreshold;
369a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  parsed->tiny_method_threshold_ = Runtime::kDefaultTinyMethodThreshold;
370a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  parsed->num_dex_methods_threshold_ = Runtime::kDefaultNumDexMethodsThreshold;
3718447d84d847d4562d7a7bce62768c27e7d20a9aaAnwar Ghuloum
3727467ee05012e1fd9834df74663c1ebda46f5636bDragos Sbirlea  parsed->sea_ir_mode_ = false;
3737934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.class_linker = true;  // TODO: don't check this in!
3747934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.compiler = true;  // TODO: don't check this in!
37575a43f10f55e2aa550de51e969cc1e60d583b632Anwar Ghuloum//  gLogVerbosity.verifier = true;  // TODO: don't check this in!
3767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.heap = true;  // TODO: don't check this in!
3777934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.gc = true;  // TODO: don't check this in!
3787934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.jdwp = true;  // TODO: don't check this in!
3797934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.jni = true;  // TODO: don't check this in!
3807934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.monitor = true;  // TODO: don't check this in!
3817934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.startup = true;  // TODO: don't check this in!
3827934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.third_party_jni = true;  // TODO: don't check this in!
3837934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom//  gLogVerbosity.threads = true;  // TODO: don't check this in!
384b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
385b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  parsed->method_trace_ = false;
386b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  parsed->method_trace_file_ = "/data/method-trace-file.bin";
387b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  parsed->method_trace_file_size_ = 10 * MB;
388b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
3898a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  for (size_t i = 0; i < options.size(); ++i) {
390f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    const std::string option(options[i].first);
3910796af03edc06d92bb8d631f1c0c23befdae2315Brian Carlstrom    if (true && options[0].first == "-Xzygote") {
39258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      LOG(INFO) << "option[" << i << "]=" << option;
39358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    }
394f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    if (StartsWith(option, "-Xbootclasspath:")) {
395a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->boot_class_path_string_ = option.substr(strlen("-Xbootclasspath:")).data();
39669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option == "-classpath" || option == "-cp") {
39769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      // TODO: support -Djava.class.path
39869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      i++;
39969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      if (i == options.size()) {
40069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        // TODO: usage
40169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Missing required class path value for " << option;
40269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        return NULL;
40369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      }
404a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      const StringPiece& value = options[i].first;
405a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->class_path_string_ = value.data();
406a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    } else if (option == "bootclasspath") {
407a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->boot_class_path_
408a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom          = reinterpret_cast<const std::vector<const DexFile*>*>(options[i].second);
409f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Ximage:")) {
410a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      parsed->image_ = option.substr(strlen("-Ximage:")).data();
411f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xcheck:jni")) {
412515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes      parsed->check_jni_ = true;
413f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xrunjdwp:") || StartsWith(option, "-agentlib:jdwp=")) {
414f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      std::string tail(option.substr(option[1] == 'X' ? 10 : 15));
4153bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes      if (tail == "help" || !Dbg::ParseJdwpOptions(tail)) {
4163bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes        LOG(FATAL) << "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n"
4173bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes                   << "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n";
4183bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes        return NULL;
4193bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes      }
420f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xms")) {
421f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).c_str(), 1024);
422f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
423f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
424f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
425f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
4264a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
42769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
428f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
429f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
430f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_initial_size_ = size;
431f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xmx")) {
432f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).c_str(), 1024);
433f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
434f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
435f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
436f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
4374a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
43869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
439f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
440f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
441f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->heap_maximum_size_ = size;
442f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-XX:HeapGrowthLimit=")) {
443f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapGrowthLimit=")).c_str(), 1024);
444c11607024d2e7a52ca690b8339306cab040e6653jeffhao      if (size == 0) {
445c11607024d2e7a52ca690b8339306cab040e6653jeffhao        if (ignore_unrecognized) {
446c11607024d2e7a52ca690b8339306cab040e6653jeffhao          continue;
447c11607024d2e7a52ca690b8339306cab040e6653jeffhao        }
448c11607024d2e7a52ca690b8339306cab040e6653jeffhao        // TODO: usage
449c11607024d2e7a52ca690b8339306cab040e6653jeffhao        LOG(FATAL) << "Failed to parse " << option;
450c11607024d2e7a52ca690b8339306cab040e6653jeffhao        return NULL;
451c11607024d2e7a52ca690b8339306cab040e6653jeffhao      }
452c11607024d2e7a52ca690b8339306cab040e6653jeffhao      parsed->heap_growth_limit_ = size;
4530051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier    } else if (StartsWith(option, "-XX:HeapMinFree=")) {
4540051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapMinFree=")).c_str(), 1024);
4550051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      if (size == 0) {
4560051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        if (ignore_unrecognized) {
4570051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier          continue;
4580051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        }
4590051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        // TODO: usage
4600051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        LOG(FATAL) << "Failed to parse " << option;
4610051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        return NULL;
4620051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      }
4630051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      parsed->heap_min_free_ = size;
4640051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier    } else if (StartsWith(option, "-XX:HeapMaxFree=")) {
4650051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapMaxFree=")).c_str(), 1024);
4660051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      if (size == 0) {
4670051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        if (ignore_unrecognized) {
4680051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier          continue;
4690051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        }
4700051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        // TODO: usage
4710051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        LOG(FATAL) << "Failed to parse " << option;
4720051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        return NULL;
4730051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      }
4740051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      parsed->heap_max_free_ = size;
4750051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier    } else if (StartsWith(option, "-XX:HeapTargetUtilization=")) {
4760051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      std::istringstream iss(option.substr(strlen("-XX:HeapTargetUtilization=")));
4770051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      double value;
4780051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      iss >> value;
4790051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
480bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom      const bool sane_val = iss.eof() && (value >= 0.1) && (value <= 0.9);
4810051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      if (!sane_val) {
4820051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        if (ignore_unrecognized) {
4830051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier          continue;
4840051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        }
4850051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        LOG(FATAL) << "Invalid option '" << option << "'";
4860051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier        return NULL;
4870051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      }
4880051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier      parsed->heap_target_utilization_ = value;
4892775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    } else if (StartsWith(option, "-XX:ParallelGCThreads=")) {
4902775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier      parsed->parallel_gc_threads_ =
4912775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier          ParseMemoryOption(option.substr(strlen("-XX:ParallelGCThreads=")).c_str(), 1024);
4922775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    } else if (StartsWith(option, "-XX:ConcGCThreads=")) {
4932775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier      parsed->conc_gc_threads_ =
4942775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier          ParseMemoryOption(option.substr(strlen("-XX:ConcGCThreads=")).c_str(), 1024);
495f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xss")) {
496f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).c_str(), 1);
497f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      if (size == 0) {
498f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        if (ignore_unrecognized) {
499f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom          continue;
500f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        }
5014a289ed61242964b921434de7d375f46480472a1Brian Carlstrom        // TODO: usage
50269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        LOG(FATAL) << "Failed to parse " << option;
503f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom        return NULL;
504f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      }
505f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom      parsed->stack_size_ = size;
5062775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    } else if (option == "-XX:LongPauseLogThreshold") {
5072775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier      parsed->long_pause_log_threshold_ =
5082775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier          ParseMemoryOption(option.substr(strlen("-XX:LongPauseLogThreshold=")).c_str(), 1024);
5092775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    } else if (option == "-XX:LongGCLogThreshold") {
5102775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier          parsed->long_gc_log_threshold_ =
5112775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier              ParseMemoryOption(option.substr(strlen("-XX:LongGCLogThreshold")).c_str(), 1024);
5122775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    } else if (option == "-XX:IgnoreMaxFootprint") {
5132775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier      parsed->ignore_max_footprint_ = true;
514e0a53e99e2a01f8668d6616c3cec7e2f5a711286Mathieu Chartier    } else if (option == "-XX:LowMemoryMode") {
515e0a53e99e2a01f8668d6616c3cec7e2f5a711286Mathieu Chartier      parsed->low_memory_mode_ = true;
516f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-D")) {
517f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      parsed->properties_.push_back(option.substr(strlen("-D")));
518f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xjnitrace:")) {
519f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:"));
5205de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom    } else if (option == "compiler") {
521d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      parsed->is_compiler_ = true;
5229ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes    } else if (option == "-Xzygote") {
5239ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes      parsed->is_zygote_ = true;
52450ffee20ced9c0c7ac68889c86be8844cf120cf2Ian Rogers    } else if (option == "-Xint") {
52550ffee20ced9c0c7ac68889c86be8844cf120cf2Ian Rogers      parsed->interpreter_only_ = true;
526069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier    } else if (StartsWith(option, "-Xgc:")) {
527069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier      std::vector<std::string> gc_options;
528069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier      Split(option.substr(strlen("-Xgc:")), ',', gc_options);
529069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier      for (size_t i = 0; i < gc_options.size(); ++i) {
530069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier        if (gc_options[i] == "noconcurrent") {
531069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier          parsed->is_concurrent_gc_enabled_ = false;
532069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier        } else if (gc_options[i] == "concurrent") {
533069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier          parsed->is_concurrent_gc_enabled_ = true;
534069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier        } else {
535069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier          LOG(WARNING) << "Ignoring unknown -Xgc option: " << gc_options[i];
536069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier        }
537069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier      }
5388718359763aa3dcd0033a2d2e67e0cb145fb9c53Anwar Ghuloum    } else if (option == "-XX:+DisableExplicitGC") {
5398718359763aa3dcd0033a2d2e67e0cb145fb9c53Anwar Ghuloum      parsed->is_explicit_gc_disabled_ = true;
540f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-verbose:")) {
5410af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      std::vector<std::string> verbose_options;
542f1a5adc87760f938b01df26d906295063546b259Elliott Hughes      Split(option.substr(strlen("-verbose:")), ',', verbose_options);
5430af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      for (size_t i = 0; i < verbose_options.size(); ++i) {
5444dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        if (verbose_options[i] == "class") {
5454dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.class_linker = true;
54675a43f10f55e2aa550de51e969cc1e60d583b632Anwar Ghuloum        } else if (verbose_options[i] == "verifier") {
54775a43f10f55e2aa550de51e969cc1e60d583b632Anwar Ghuloum          gLogVerbosity.verifier = true;
5484dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "compiler") {
5494dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.compiler = true;
5504dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "heap") {
5514dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.heap = true;
5524dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "gc") {
5534dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.gc = true;
5544dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "jdwp") {
5554dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.jdwp = true;
5564dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "jni") {
5574dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.jni = true;
5584dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "monitor") {
5594dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.monitor = true;
5604dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "startup") {
5614dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.startup = true;
5624dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "third-party-jni") {
5634dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.third_party_jni = true;
5644dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else if (verbose_options[i] == "threads") {
5654dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          gLogVerbosity.threads = true;
5664dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        } else {
5674dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes          LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i];
5684dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        }
5690af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      }
570f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xjnigreflimit:")) {
5712010a6004fb083eb4109c21886fce6ee65abda33Elliott Hughes      // Silently ignored for backwards compatibility.
572f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xlockprofthreshold:")) {
573bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes      parsed->lock_profiling_threshold_ = ParseIntegerOrDie(option);
574f1a5adc87760f938b01df26d906295063546b259Elliott Hughes    } else if (StartsWith(option, "-Xstacktracefile:")) {
575206c20d6b1e27d8eca843498fdde1ddd5b9daa39Elliott Hughes      parsed->stack_trace_file_ = option.substr(strlen("-Xstacktracefile:"));
576fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes    } else if (option == "sensitiveThread") {
5771b09b094a85e03f6ef5f687f58bb91c433273ba1Ian Rogers      parsed->hook_is_sensitive_thread_ = reinterpret_cast<bool (*)()>(const_cast<void*>(options[i].second));
5786ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "vfprintf") {
5791b09b094a85e03f6ef5f687f58bb91c433273ba1Ian Rogers      parsed->hook_vfprintf_ =
5801b09b094a85e03f6ef5f687f58bb91c433273ba1Ian Rogers          reinterpret_cast<int (*)(FILE *, const char*, va_list)>(const_cast<void*>(options[i].second));
5816ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "exit") {
5821b09b094a85e03f6ef5f687f58bb91c433273ba1Ian Rogers      parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(const_cast<void*>(options[i].second));
5836ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    } else if (option == "abort") {
5841b09b094a85e03f6ef5f687f58bb91c433273ba1Ian Rogers      parsed->hook_abort_ = reinterpret_cast<void(*)()>(const_cast<void*>(options[i].second));
58558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option == "host-prefix") {
58658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second);
587b3e66dfcd069db8818cd902d787ff1d7bbca45f2Elliott Hughes    } else if (option == "-Xgenregmap" || option == "-Xgc:precise") {
588b3e66dfcd069db8818cd902d787ff1d7bbca45f2Elliott Hughes      // We silently ignore these for backwards compatibility.
589b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    } else if (option == "-Xmethod-trace") {
590b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      parsed->method_trace_ = true;
591b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    } else if (StartsWith(option, "-Xmethod-trace-file:")) {
592b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      parsed->method_trace_file_ = option.substr(strlen("-Xmethod-trace-file:"));
593b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao    } else if (StartsWith(option, "-Xmethod-trace-file-size:")) {
594b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      parsed->method_trace_file_size_ = ParseIntegerOrDie(option);
595e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    } else if (option == "-Xprofile:threadcpuclock") {
596e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes      Trace::SetDefaultClockSource(kProfilerClockSourceThreadCpu);
597e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    } else if (option == "-Xprofile:wallclock") {
598e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes      Trace::SetDefaultClockSource(kProfilerClockSourceWall);
599e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    } else if (option == "-Xprofile:dualclock") {
600e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes      Trace::SetDefaultClockSource(kProfilerClockSourceDual);
601a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (option == "-compiler-filter:interpret-only") {
602a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->compiler_filter_ = kInterpretOnly;
603a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (option == "-compiler-filter:space") {
604a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->compiler_filter_ = kSpace;
605a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (option == "-compiler-filter:balanced") {
606a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->compiler_filter_ = kBalanced;
607a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (option == "-compiler-filter:speed") {
608a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->compiler_filter_ = kSpeed;
609fe9ca4028f379688ecba6132ac3738171176b3e4buzbee    } else if (option == "-compiler-filter:everything") {
610fe9ca4028f379688ecba6132ac3738171176b3e4buzbee      parsed->compiler_filter_ = kEverything;
6112ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom    } else if (option == "-sea_ir") {
6127467ee05012e1fd9834df74663c1ebda46f5636bDragos Sbirlea      parsed->sea_ir_mode_ = true;
613a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (StartsWith(option, "-huge-method-max:")) {
614a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->huge_method_threshold_ = ParseIntegerOrDie(option);
615a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (StartsWith(option, "-large-method-max:")) {
616a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->large_method_threshold_ = ParseIntegerOrDie(option);
617a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (StartsWith(option, "-small-method-max:")) {
618a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->small_method_threshold_ = ParseIntegerOrDie(option);
619a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (StartsWith(option, "-tiny-method-max:")) {
620a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->tiny_method_threshold_ = ParseIntegerOrDie(option);
621a024a0686c3b0fea13f362bff70d65981e5febc5buzbee    } else if (StartsWith(option, "-num-dex-methods-max:")) {
622a024a0686c3b0fea13f362bff70d65981e5febc5buzbee      parsed->num_dex_methods_threshold_ = ParseIntegerOrDie(option);
6238a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    } else {
6248a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      if (!ignore_unrecognized) {
6256ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom        // TODO: print usage via vfprintf
62627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        LOG(ERROR) << "Unrecognized option " << option;
62727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        // TODO: this should exit, but for now tolerate unknown options
6287934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        // return NULL;
6298a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom      }
6308a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom    }
6318a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom  }
6328a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
633fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  // If a reference to the dalvik core.jar snuck in, replace it with
634fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  // the art specific version. This can happen with on device
635fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  // boot.art/boot.oat generation by GenerateImage which relies on the
636fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  // value of BOOTCLASSPATH.
637fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  std::string core_jar("/core.jar");
638fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  size_t core_jar_pos = parsed->boot_class_path_string_.find(core_jar);
639fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  if (core_jar_pos != std::string::npos) {
640fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom    parsed->boot_class_path_string_.replace(core_jar_pos, core_jar.size(), "/core-libart.jar");
641fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom  }
642fb67b724df2e3288c8573e8d72b6b6d06aff26caBrian Carlstrom
643223f20fa939c386c695977263780dea2195093dbBrian Carlstrom  if (!parsed->is_compiler_ && parsed->image_.empty()) {
644223f20fa939c386c695977263780dea2195093dbBrian Carlstrom    parsed->image_ += GetAndroidRoot();
645223f20fa939c386c695977263780dea2195093dbBrian Carlstrom    parsed->image_ += "/framework/boot.art";
6465de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom  }
647c11607024d2e7a52ca690b8339306cab040e6653jeffhao  if (parsed->heap_growth_limit_ == 0) {
648c11607024d2e7a52ca690b8339306cab040e6653jeffhao    parsed->heap_growth_limit_ = parsed->heap_maximum_size_;
649c11607024d2e7a52ca690b8339306cab040e6653jeffhao  }
6505de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom
65169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return parsed.release();
6528a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom}
6538a436595d36c1e4935984fcac249d7d877e00383Brian Carlstrom
65400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersbool Runtime::Create(const Options& options, bool ignore_unrecognized) {
6552ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  // TODO: acquire a static mutex on Runtime to avoid racing.
6562ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  if (Runtime::instance_ != NULL) {
65700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return false;
6582ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro  }
6597934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  InitLogging(NULL);  // Calls Locks::Init() as a side effect.
660dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  instance_ = new Runtime;
661dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  if (!instance_->Init(options, ignore_unrecognized)) {
662dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    delete instance_;
663dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    instance_ = NULL;
66400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return false;
66561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  }
66600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return true;
66769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
6680af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
669ce88853ab316c70ef7b598978a3609611db60552Brian Carlstromjobject CreateSystemClassLoader() {
670b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (Runtime::Current()->UseCompileTimeClassPath()) {
671ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom    return NULL;
672aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
673aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
67400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
675aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
6762dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* class_loader_class =
6772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader);
678365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(class_loader_class, true, true));
679aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
680ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::ArtMethod* getSystemClassLoader =
6812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;");
682df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  CHECK(getSystemClassLoader != NULL);
683df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom
6845d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao  JValue result;
6855d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao  ArgArray arg_array(NULL, 0);
6866474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao  InvokeWithArgArray(soa, getSystemClassLoader, &arg_array, &result, 'L');
6875d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao  mirror::ClassLoader* class_loader = down_cast<mirror::ClassLoader*>(result.GetL());
688365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  CHECK(class_loader != NULL);
689365c10235438607541fa2259a5fec48061b90bd8Ian Rogers
690ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom  JNIEnv* env = soa.Self()->GetJniEnv();
691ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom  ScopedLocalRef<jobject> system_class_loader(env, soa.AddLocalReference<jobject>(class_loader));
692ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom  CHECK(system_class_loader.get() != NULL);
693ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom
69400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  soa.Self()->SetClassLoaderOverride(class_loader);
6951b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson
6962dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
697365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(thread_class, true, true));
698365c10235438607541fa2259a5fec48061b90bd8Ian Rogers
699ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::ArtField* contextClassLoader = thread_class->FindDeclaredInstanceField("contextClassLoader",
700ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                                                                 "Ljava/lang/ClassLoader;");
7011b2b2f26c4202020d54cc7a5b9c342e6bca5b680Jesse Wilson  CHECK(contextClassLoader != NULL);
702365c10235438607541fa2259a5fec48061b90bd8Ian Rogers
703cfaa455374aae0a08c8cb28b5bb306b17866d652Ian Rogers  contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader);
704ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom
705ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom  return env->NewGlobalRef(system_class_loader.get());
706aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
707aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
708bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrombool Runtime::Start() {
7094dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Start entering";
71058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
71158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  CHECK(host_prefix_.empty()) << host_prefix_;
71258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
71300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Restore main thread state to kNative as expected by native code.
714a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  Thread* self = Thread::Current();
71500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  self->TransitionFromRunnableToSuspended(kNative);
71600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
7175d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom  started_ = true;
7185d40f182181488eb39ccd19ffd306bb1fb9740c9Brian Carlstrom
719ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // InitNativeMethods needs to be after started_ so that the classes
720ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // it touches will have methods linked to the oat file if necessary.
721ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  InitNativeMethods();
722ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
723365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  // Initialize well known thread group values that may be accessed threads while attaching.
724365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  InitThreadGroups(self);
725365c10235438607541fa2259a5fec48061b90bd8Ian Rogers
7269a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson  Thread::FinishStartup();
7279a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson
728bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  if (is_zygote_) {
729bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    if (!InitZygote()) {
730bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom      return false;
731bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    }
732bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  } else {
733d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes    DidForkFromZygote();
734d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  }
7359ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
73685d1545e985ac689db4bad7849880e843707c862Elliott Hughes  StartDaemonThreads();
7370a5b14de5115f51e0ed2dd6c3fcc5b84bbce690eBrian Carlstrom
738ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom  system_class_loader_ = CreateSystemClassLoader();
739aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
740225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes  self->GetJniEnv()->locals.AssertEmpty();
741726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes
7424dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Start exiting";
7437664f5cd118b355a5fe0c7536cb48ac991ed2b62Mathieu Chartier
7447664f5cd118b355a5fe0c7536cb48ac991ed2b62Mathieu Chartier  finished_starting_ = true;
745bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom
746bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  return true;
74785d1545e985ac689db4bad7849880e843707c862Elliott Hughes}
74885d1545e985ac689db4bad7849880e843707c862Elliott Hughes
749120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogersvoid Runtime::EndThreadBirth() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_) {
750120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  DCHECK_GT(threads_being_born_, 0U);
751120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  threads_being_born_--;
752120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  if (shutting_down_started_ && threads_being_born_ == 0) {
753c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    shutdown_cond_->Broadcast(Thread::Current());
754120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  }
755120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers}
756120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers
757bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom// Do zygote-mode-only initialization.
758bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrombool Runtime::InitZygote() {
759bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // zygote goes into its own process group
760b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom  setpgid(0, 0);
761bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom
762bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // See storage config details at http://source.android.com/tech/storage/
763bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // Create private mount namespace shared by all children
764bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  if (unshare(CLONE_NEWNS) == -1) {
765bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    PLOG(WARNING) << "Failed to unshare()";
766bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    return false;
767bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  }
768bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom
769bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // Mark rootfs as being a slave so that changes from default
770bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // namespace only flow into our children.
771bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
772bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    PLOG(WARNING) << "Failed to mount() rootfs as MS_SLAVE";
773bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    return false;
774bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  }
775bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom
776bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // Create a staging tmpfs that is shared by our children; they will
777bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // bind mount storage into their respective private namespaces, which
778bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  // are isolated from each other.
779bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  const char* target_base = getenv("EMULATED_STORAGE_TARGET");
780bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  if (target_base != NULL) {
781bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
78252cd1e8f2f0622a174f883e24151ab873170787fJeff Sharkey              "uid=0,gid=1028,mode=0751") == -1) {
783bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom      LOG(WARNING) << "Failed to mount tmpfs to " << target_base;
784bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom      return false;
785bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom    }
786bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  }
787bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom
788bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom  return true;
789bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom}
790bd86bccf1b47f1151842152ee52cf5d46d6b34abBrian Carlstrom
791caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::DidForkFromZygote() {
792caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  is_zygote_ = false;
793d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
79402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  // Create the thread pool.
79502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  heap_->CreateThreadPool();
79602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
797caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  StartSignalCatcher();
798d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes
799d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
800d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  // this will pause the runtime, so we probably want this to come last.
801d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes  Dbg::StartJdwp();
802caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom}
803caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom
804caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Runtime::StartSignalCatcher() {
805caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  if (!is_zygote_) {
80694ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes    signal_catcher_ = new SignalCatcher(stack_trace_file_);
807caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom  }
808caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom}
809caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom
81085d1545e985ac689db4bad7849880e843707c862Elliott Hughesvoid Runtime::StartDaemonThreads() {
8114dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::StartDaemonThreads entering";
81285d1545e985ac689db4bad7849880e843707c862Elliott Hughes
813719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  Thread* self = Thread::Current();
814aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
815aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  // Must be in the kNative state for calling native methods.
81650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  CHECK_EQ(self->GetState(), kNative);
817aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
818719b323e6a290a075239ac8f4b664e23fd3190f4Elliott Hughes  JNIEnv* env = self->GetJniEnv();
8192fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,
8202fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers                            WellKnownClasses::java_lang_Daemons_start);
8212fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (env->ExceptionCheck()) {
8222fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    env->ExceptionDescribe();
8232fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    LOG(FATAL) << "Error starting java.lang.Daemons";
8242fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
8259ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
8264dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::StartDaemonThreads exiting";
82761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
82861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
8290af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughesbool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
830c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
8316ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
83290a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
83390a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  if (options.get() == NULL) {
834e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to parse options";
8356ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom    return false;
8366ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom  }
8374dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Init -verbose:startup enabled";
8387ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
8397c6169de901fd0a39c8e0c078874dc25207f5b59Elliott Hughes  QuasiAtomic::Startup();
8407c6169de901fd0a39c8e0c078874dc25207f5b59Elliott Hughes
8414dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
84232d6e1e5654433d7eadede89e1c770b2c839aee9Elliott Hughes
84358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  host_prefix_ = options->host_prefix_;
844a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  boot_class_path_string_ = options->boot_class_path_string_;
845a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  class_path_string_ = options->class_path_string_;
8467ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  properties_ = options->properties_;
8477ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes
848d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  is_compiler_ = options->is_compiler_;
8499ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes  is_zygote_ = options->is_zygote_;
850069387a60cb2b72e116cc38b32e14403f092df8fMathieu Chartier  is_concurrent_gc_enabled_ = options->is_concurrent_gc_enabled_;
8518718359763aa3dcd0033a2d2e67e0cb145fb9c53Anwar Ghuloum  is_explicit_gc_disabled_ = options->is_explicit_gc_disabled_;
8529ca7a1fdd0daa546b790adb6a24dbc13c22df76aElliott Hughes
853a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  compiler_filter_ = options->compiler_filter_;
854a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  huge_method_threshold_ = options->huge_method_threshold_;
855a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  large_method_threshold_ = options->large_method_threshold_;
856a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  small_method_threshold_ = options->small_method_threshold_;
857a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  tiny_method_threshold_ = options->tiny_method_threshold_;
858a024a0686c3b0fea13f362bff70d65981e5febc5buzbee  num_dex_methods_threshold_ = options->num_dex_methods_threshold_;
8598447d84d847d4562d7a7bce62768c27e7d20a9aaAnwar Ghuloum
8607467ee05012e1fd9834df74663c1ebda46f5636bDragos Sbirlea  sea_ir_mode_ = options->sea_ir_mode_;
8610af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  vfprintf_ = options->hook_vfprintf_;
8620af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  exit_ = options->hook_exit_;
8630af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes  abort_ = options->hook_abort_;
8646ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
865be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  default_stack_size_ = options->stack_size_;
86694ce37a3919a0bdb8855a3d3264a50df1dbc41beElliott Hughes  stack_trace_file_ = options->stack_trace_file_;
8676ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
868c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes  monitor_list_ = new MonitorList;
8694dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  thread_list_ = new ThreadList;
870cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  intern_table_ = new InternTable;
871cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
872dd361c9eab3284e76e2d07c2e7d371b0f5269942Logan Chien
87362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (options->interpreter_only_) {
87462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    GetInstrumentation()->ForceInterpretOnly();
87562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
87662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
8771d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  heap_ = new gc::Heap(options->heap_initial_size_,
8781d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       options->heap_growth_limit_,
8791d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       options->heap_min_free_,
8801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       options->heap_max_free_,
8811d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       options->heap_target_utilization_,
8821d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       options->heap_maximum_size_,
8831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       options->image_,
88463a54345598861030178e033ffbd72c0e231a4c9Mathieu Chartier                       options->is_concurrent_gc_enabled_,
8852775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier                       options->parallel_gc_threads_,
8862775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier                       options->conc_gc_threads_,
8872775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier                       options->low_memory_mode_,
8882775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier                       options->long_pause_log_threshold_,
8892775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier                       options->long_gc_log_threshold_,
8902775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier                       options->ignore_max_footprint_);
8916ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
892c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  BlockSignals();
893457005c557b8762475db3220ce5a747d629f975bElliott Hughes  InitPlatformSignalHandlers();
894c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
895a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  java_vm_ = new JavaVMExt(this, options.get());
896515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes
897be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes  Thread::Startup();
898d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
899664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier  // ClassLinker needs an attached thread, but we can't fully attach a thread without creating
900664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier  // objects. We can't supply a thread group yet; it will be fixed later. Since we are the main
901664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier  // thread, we do not get a java peer.
902664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier  Thread* self = Thread::Attach("main", false, NULL, false);
903664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier  CHECK_EQ(self->thin_lock_id_, ThreadList::kMainId);
904120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  CHECK(self != NULL);
9056ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
906f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom  // Set us to runnable so tools using a runtime can allocate and GC by default
907120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  self->TransitionFromSuspendedToRunnable();
908f28bc5b6df6edb4b22aeca360ff102a95f3155e1Brian Carlstrom
909a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  // Now we're attached, we can take the heap locks and validate the heap.
910141d62275f207bf68c55f583fb206fe586d857cfIan Rogers  GetHeap()->EnableObjectValidation();
911141d62275f207bf68c55f583fb206fe586d857cfIan Rogers
9121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  CHECK_GE(GetHeap()->GetContinuousSpaces().size(), 1U);
9131d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  if (GetHeap()->GetContinuousSpaces()[0]->IsImageSpace()) {
914a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    class_linker_ = ClassLinker::CreateFromImage(intern_table_);
915a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  } else {
916a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    CHECK(options->boot_class_path_ != NULL);
917a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    CHECK_NE(options->boot_class_path_->size(), 0U);
918a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    class_linker_ = ClassLinker::CreateFromCompiler(*options->boot_class_path_, intern_table_);
919a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  }
920a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  CHECK(class_linker_ != NULL);
92151a5fb78d1b03b5235c2ae45414235282182bb86Sameer Abu Asal  verifier::MethodVerifier::Init();
9226ea095ad30bf13cc00b4fee7afbbe4731a349c83Brian Carlstrom
923b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  method_trace_ = options->method_trace_;
924b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  method_trace_file_ = options->method_trace_file_;
925b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  method_trace_file_size_ = options->method_trace_file_size_;
926b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
927b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  if (options->method_trace_) {
92823009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao    Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0,
92923009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                 false, false, 0);
930b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  }
931b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
932a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  // Pre-allocate an OutOfMemoryError for the double-OOME case.
933a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  self->ThrowNewException(ThrowLocation(), "Ljava/lang/OutOfMemoryError;",
934a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers                          "OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available");
935a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  pre_allocated_OutOfMemoryError_ = self->GetException(NULL);
936a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  self->ClearException();
937a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers
9384dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::Init exiting";
9397b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro  return true;
9407b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
9417b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
942038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Runtime::InitNativeMethods() {
9434dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::InitNativeMethods entering";
944ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread* self = Thread::Current();
945ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  JNIEnv* env = self->GetJniEnv();
946ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
947418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Must be in the kNative state for calling native methods (JNI_OnLoad code).
94850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  CHECK_EQ(self->GetState(), kNative);
949ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
950418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // First set up JniConstants, which is used by both the runtime's built-in native
951418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // methods and libcore.
952fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes  JniConstants::init(env);
953eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  WellKnownClasses::Init(env);
954fea966e51e65f2040e1510a2e39d407baad29b2cElliott Hughes
955418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up the native methods provided by the runtime itself.
956ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  RegisterRuntimeNativeMethods(env);
957ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
958418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad.
959418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's
960418d20fc407052d4152157f61e7453359f902383Elliott Hughes  // the library that implements System.loadLibrary!
96100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  {
96200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    std::string mapped_name(StringPrintf(OS_SHARED_LIB_FORMAT_STR, "javacore"));
96300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    std::string reason;
96400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromSuspendedToRunnable();
96500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (!instance_->java_vm_->LoadNativeLibrary(mapped_name, NULL, reason)) {
96600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": " << reason;
96700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
96800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromRunnableToSuspended(kNative);
96900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
970ef28b14268ed0f9db0c7bbd571aa514354a360bdIan Rogers
971ef28b14268ed0f9db0c7bbd571aa514354a360bdIan Rogers  // Initialize well known classes that may invoke runtime native methods.
972ef28b14268ed0f9db0c7bbd571aa514354a360bdIan Rogers  WellKnownClasses::LateInit(env);
973ef28b14268ed0f9db0c7bbd571aa514354a360bdIan Rogers
9744dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(startup) << "Runtime::InitNativeMethods exiting";
975ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
976ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
977365c10235438607541fa2259a5fec48061b90bd8Ian Rogersvoid Runtime::InitThreadGroups(Thread* self) {
978365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  JNIEnvExt* env = self->GetJniEnv();
979365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  ScopedJniEnvLocalRefState env_state(env);
980365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  main_thread_group_ =
981365c10235438607541fa2259a5fec48061b90bd8Ian Rogers      env->NewGlobalRef(env->GetStaticObjectField(WellKnownClasses::java_lang_ThreadGroup,
982365c10235438607541fa2259a5fec48061b90bd8Ian Rogers                                                  WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup));
983034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom  CHECK(main_thread_group_ != NULL || IsCompiler());
984365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  system_thread_group_ =
985365c10235438607541fa2259a5fec48061b90bd8Ian Rogers      env->NewGlobalRef(env->GetStaticObjectField(WellKnownClasses::java_lang_ThreadGroup,
986365c10235438607541fa2259a5fec48061b90bd8Ian Rogers                                                  WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup));
987034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom  CHECK(system_thread_group_ != NULL || IsCompiler());
988034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom}
989034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom
990034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstromjobject Runtime::GetMainThreadGroup() const {
991034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom  CHECK(main_thread_group_ != NULL || IsCompiler());
992034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom  return main_thread_group_;
993034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom}
994034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom
995034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstromjobject Runtime::GetSystemThreadGroup() const {
996034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom  CHECK(system_thread_group_ != NULL || IsCompiler());
997034f76b91225bea769d6185d7dad5e243af4ffa0Brian Carlstrom  return system_thread_group_;
998365c10235438607541fa2259a5fec48061b90bd8Ian Rogers}
999365c10235438607541fa2259a5fec48061b90bd8Ian Rogers
1000ce88853ab316c70ef7b598978a3609611db60552Brian Carlstromjobject Runtime::GetSystemClassLoader() const {
1001ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom  CHECK(system_class_loader_ != NULL || IsCompiler());
1002ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom  return system_class_loader_;
1003ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom}
1004ce88853ab316c70ef7b598978a3609611db60552Brian Carlstrom
1005ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesvoid Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
1006ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
10075167c97a4f672ba821453418e3943988fabbfc43Ian Rogers  // Register Throwable first so that registration of other native methods can throw exceptions
10085167c97a4f672ba821453418e3943988fabbfc43Ian Rogers  REGISTER(register_java_lang_Throwable);
1009f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  REGISTER(register_dalvik_system_DexFile);
10109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  REGISTER(register_dalvik_system_VMDebug);
10117ede61eceed2f8da14a4fff05c57c748c160d57fElliott Hughes  REGISTER(register_dalvik_system_VMRuntime);
10128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_dalvik_system_VMStack);
101301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  REGISTER(register_dalvik_system_Zygote);
1014d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes  REGISTER(register_java_lang_Class);
1015ee39a10e45a6a0880e8b829525c40d6055818560Ian Rogers  REGISTER(register_java_lang_DexCache);
1016bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Object);
1017bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_Runtime);
1018bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_String);
1019bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_lang_System);
10208daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  REGISTER(register_java_lang_Thread);
102164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  REGISTER(register_java_lang_VMClassLoader);
10225b8e4c810a97c9dc417142b8c6e07871ae15c797Brian Carlstrom  REGISTER(register_java_lang_reflect_Array);
10232a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes  REGISTER(register_java_lang_reflect_Constructor);
1024f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Field);
1025f867b6f706818c886087f61b89d1e8f5fc4653cfBrian Carlstrom  REGISTER(register_java_lang_reflect_Method);
102695caa791e560da97363c0c0d22bfda4a7e7377c3Jesse Wilson  REGISTER(register_java_lang_reflect_Proxy);
1027bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  REGISTER(register_java_util_concurrent_atomic_AtomicLong);
1028395520eaa47eca25b92e86188accf3095d60af49Brian Carlstrom  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
1029f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal);
10305ee7a8b56dee896245e0f4ae5215f8b7376c1787Elliott Hughes  REGISTER(register_sun_misc_Unsafe);
1031ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes#undef REGISTER
1032ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes}
1033ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
1034c967f78cd29b6019f7cfca40a02e9b677112da70Elliott Hughesvoid Runtime::DumpForSigQuit(std::ostream& os) {
1035cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  GetClassLinker()->DumpForSigQuit(os);
1036cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes  GetInternTable()->DumpForSigQuit(os);
1037ae80b493748c5b6ffe310a91c651e7043f4b2daeElliott Hughes  GetJavaVM()->DumpForSigQuit(os);
1038c967f78cd29b6019f7cfca40a02e9b677112da70Elliott Hughes  GetHeap()->DumpForSigQuit(os);
103942ee14279065352a4b9a3e8028d02c567e847d05Elliott Hughes  os << "\n";
10408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
1041c967f78cd29b6019f7cfca40a02e9b677112da70Elliott Hughes  thread_list_->DumpForSigQuit(os);
104256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  BaseMutex::DumpAll(os);
1043e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes}
1044e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
104521a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughesvoid Runtime::DumpLockHolders(std::ostream& os) {
1046b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  uint64_t mutator_lock_owner = Locks::mutator_lock_->GetExclusiveOwnerTid();
104721a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t thread_list_lock_owner = GetThreadList()->GetLockOwner();
104821a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t classes_lock_owner = GetClassLinker()->GetClassesLockOwner();
104921a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  pid_t dex_lock_owner = GetClassLinker()->GetDexLockOwner();
105000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if ((thread_list_lock_owner | classes_lock_owner | dex_lock_owner) != 0) {
105100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    os << "Mutator lock exclusive owner tid: " << mutator_lock_owner << "\n"
105221a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ThreadList lock owner tid: " << thread_list_lock_owner << "\n"
105321a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ClassLinker classes lock owner tid: " << classes_lock_owner << "\n"
105421a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes       << "ClassLinker dex lock owner tid: " << dex_lock_owner << "\n";
105521a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes  }
105621a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes}
105721a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes
10589d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::SetStatsEnabled(bool new_state) {
10599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (new_state == true) {
10609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    GetStats()->Clear(~0);
10619d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // TODO: wouldn't it make more sense to clear _all_ threads' stats?
10629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    Thread::Current()->GetStats()->Clear(~0);
10639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
10649d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  stats_enabled_ = new_state;
10659d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
10669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
10679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid Runtime::ResetStats(int kinds) {
10689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  GetStats()->Clear(kinds & 0xffff);
10699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  // TODO: wouldn't it make more sense to clear _all_ threads' stats?
10709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  Thread::Current()->GetStats()->Clear(kinds >> 16);
10719d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
10729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
10739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesint32_t Runtime::GetStat(int kind) {
10749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  RuntimeStats* stats;
10759d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (kind < (1<<16)) {
10769d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = GetStats();
10779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  } else {
10789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    stats = Thread::Current()->GetStats();
10799d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    kind >>= 16;
10809d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
10819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  switch (kind) {
10829d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_OBJECTS:
10839d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_objects;
10849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_ALLOCATED_BYTES:
10859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->allocated_bytes;
10869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_OBJECTS:
10879d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_objects;
10889d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_FREED_BYTES:
10899d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->freed_bytes;
10909d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_GC_INVOCATIONS:
10919d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->gc_for_alloc_count;
10929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_COUNT:
10939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return stats->class_init_count;
10949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_CLASS_INIT_TIME:
10959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // Convert ns to us, reduce to 32 bits.
1096398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes    return static_cast<int>(stats->class_init_time_ns / 1000);
10979d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_OBJECTS:
10989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_ALLOCATED_BYTES:
10999d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_OBJECTS:
11009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  case KIND_EXT_FREED_BYTES:
11019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return 0;  // backward compatibility
11029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  default:
11037b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes    LOG(FATAL) << "Unknown statistic " << kind;
11047934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    return -1;  // unreachable
11059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
11069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
11079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1108c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Runtime::BlockSignals() {
1109457005c557b8762475db3220ce5a747d629f975bElliott Hughes  SignalSet signals;
1110457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Add(SIGPIPE);
1111c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // SIGQUIT is used to dump the runtime's state (including stack traces).
1112457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Add(SIGQUIT);
11130879504b6ac72f6d93dcccf9e1b7e1769a73b230Elliott Hughes  // SIGUSR1 is used to initiate a GC.
1114457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Add(SIGUSR1);
1115457005c557b8762475db3220ce5a747d629f975bElliott Hughes  signals.Block();
1116c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
1117c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
1118664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartierbool Runtime::AttachCurrentThread(const char* thread_name, bool as_daemon, jobject thread_group,
1119664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier                                  bool create_peer) {
1120664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier  bool success = Thread::Attach(thread_name, as_daemon, thread_group, create_peer) != NULL;
112122869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes  if (thread_name == NULL) {
112222869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes    LOG(WARNING) << *Thread::Current() << " attached without supplying a name";
112322869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes  }
1124120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers  return success;
112561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
112661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
1127d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Runtime::DetachCurrentThread() {
11284d5714378c3433ba7e351cbf6a6713fb49c31784Brian Carlstrom  Thread* self = Thread::Current();
11294d5714378c3433ba7e351cbf6a6713fb49c31784Brian Carlstrom  if (self == NULL) {
11304d5714378c3433ba7e351cbf6a6713fb49c31784Brian Carlstrom    LOG(FATAL) << "attempting to detach thread that is not attached";
11314d5714378c3433ba7e351cbf6a6713fb49c31784Brian Carlstrom  }
11320399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  if (self->HasManagedStack()) {
113322869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes    LOG(FATAL) << *Thread::Current() << " attempting to detach while still running code";
113422869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes  }
113500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  thread_list_->Unregister(self);
11367b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro}
11377b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro
1138a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryError() const {
1139a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  if (pre_allocated_OutOfMemoryError_ == NULL) {
1140a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers    LOG(ERROR) << "Failed to return pre-allocated OOME";
1141a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  }
1142a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers  return pre_allocated_OutOfMemoryError_;
1143a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers}
1144a436fde2762664a3ecdda5eefcadd20b2e104f59Ian Rogers
11451d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid Runtime::VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_dirty,
11461d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                   bool clean_dirty) {
1147c4621985bdfc2b27494087e5dee65a6d0cc5a632Mathieu Chartier  intern_table_->VisitRoots(visitor, arg, only_dirty, clean_dirty);
1148c4621985bdfc2b27494087e5dee65a6d0cc5a632Mathieu Chartier  class_linker_->VisitRoots(visitor, arg, only_dirty, clean_dirty);
11499ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartier}
11509ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartier
11512dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid Runtime::VisitNonThreadRoots(RootVisitor* visitor, void* arg) {
1152e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  java_vm_->VisitRoots(visitor, arg);
1153225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes  if (pre_allocated_OutOfMemoryError_ != NULL) {
1154225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes    visitor(pre_allocated_OutOfMemoryError_, arg);
1155225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes  }
11561984651929744dd603fd082e23eacd877b9bc177Ian Rogers  visitor(resolution_method_, arg);
11574f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
1158225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes    visitor(callee_save_methods_[i], arg);
11594f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  }
1160e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1161e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
11622dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid Runtime::VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) {
1163858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier  thread_list_->VisitRoots(visitor, arg);
1164858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier  VisitNonThreadRoots(visitor, arg);
1165858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier}
1166858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier
11671d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid Runtime::VisitRoots(RootVisitor* visitor, void* arg, bool only_dirty, bool clean_dirty) {
11681d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  VisitConcurrentRoots(visitor, arg, only_dirty, clean_dirty);
11699ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartier  VisitNonConcurrentRoots(visitor, arg);
11709ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartier}
11719ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartier
1172ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrommirror::ArtMethod* Runtime::CreateResolutionMethod() {
1173ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::Class* method_class = mirror::ArtMethod::GetJavaLangReflectArtMethod();
117450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self = Thread::Current();
1175ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  SirtRef<mirror::ArtMethod>
1176ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      method(self, down_cast<mirror::ArtMethod*>(method_class->AllocObject(self)));
11771984651929744dd603fd082e23eacd877b9bc177Ian Rogers  method->SetDeclaringClass(method_class);
11781984651929744dd603fd082e23eacd877b9bc177Ian Rogers  // TODO: use a special method for resolution method saves
1179ee39a10e45a6a0880e8b829525c40d6055818560Ian Rogers  method->SetDexMethodIndex(DexFile::kDexNoIndex);
118058df32711162823647356afe25ae2cde04133563Jeff Hao  // When compiling, the code pointer will get set later when the image is loaded.
11810aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  Runtime* r = Runtime::Current();
11820aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  ClassLinker* cl = r->GetClassLinker();
11830aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  method->SetEntryPointFromCompiledCode(r->IsCompiler() ? NULL : GetResolutionTrampoline(cl));
11841984651929744dd603fd082e23eacd877b9bc177Ian Rogers  return method.get();
11851984651929744dd603fd082e23eacd877b9bc177Ian Rogers}
11861984651929744dd603fd082e23eacd877b9bc177Ian Rogers
1187ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrommirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set,
11882dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                                                        CalleeSaveType type) {
1189ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::Class* method_class = mirror::ArtMethod::GetJavaLangReflectArtMethod();
119050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self = Thread::Current();
1191ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  SirtRef<mirror::ArtMethod>
1192ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      method(self, down_cast<mirror::ArtMethod*>(method_class->AllocObject(self)));
1193ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  method->SetDeclaringClass(method_class);
11946d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  // TODO: use a special method for callee saves
1195ee39a10e45a6a0880e8b829525c40d6055818560Ian Rogers  method->SetDexMethodIndex(DexFile::kDexNoIndex);
1196aa4a793d7175ceeb1efa215c2af5e52e42b22f0aJeff Hao  method->SetEntryPointFromCompiledCode(NULL);
1197ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
11984f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6)  | (1 << art::arm::R7) |
11994f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                          (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
12004f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
12014f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9);
1202fa147e22a73c6df166b08a2f71f9c9b52b09d17cjeffhao    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
1203fa147e22a73c6df166b08a2f71f9c9b52b09d17cjeffhao                           (type == kSaveAll ? all_spills : 0) | (1 << art::arm::LR);
12044f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_all_spills = (1 << art::arm::S0)  | (1 << art::arm::S1)  | (1 << art::arm::S2) |
12054f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S3)  | (1 << art::arm::S4)  | (1 << art::arm::S5) |
12064f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S6)  | (1 << art::arm::S7)  | (1 << art::arm::S8) |
12074f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S9)  | (1 << art::arm::S10) | (1 << art::arm::S11) |
12084f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) |
12094f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) |
12104f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) |
12114f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) |
12124f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) |
12134f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) |
12144f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                             (1 << art::arm::S30) | (1 << art::arm::S31);
12154f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0;
12164f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
12174f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                                 __builtin_popcount(fp_spills) /* fprs */ +
12187fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao                                 1 /* Method* */) * kPointerSize, kStackAlignment);
12197fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    method->SetFrameSizeInBytes(frame_size);
12207fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    method->SetCoreSpillMask(core_spills);
12217fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    method->SetFpSpillMask(fp_spills);
12227fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao  } else if (instruction_set == kMips) {
12237fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    uint32_t ref_spills = (1 << art::mips::S2) | (1 << art::mips::S3) | (1 << art::mips::S4) |
12247fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao                          (1 << art::mips::S5) | (1 << art::mips::S6) | (1 << art::mips::S7) |
12251f3bc2f0f9366594379249027622ab63673b0d3bJeff Hao                          (1 << art::mips::GP) | (1 << art::mips::FP);
12267fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    uint32_t arg_spills = (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3);
1227fa147e22a73c6df166b08a2f71f9c9b52b09d17cjeffhao    uint32_t all_spills = (1 << art::mips::S0) | (1 << art::mips::S1);
12287fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
1229fa147e22a73c6df166b08a2f71f9c9b52b09d17cjeffhao                           (type == kSaveAll ? all_spills : 0) | (1 << art::mips::RA);
12307fbee0731b14b5bf392a4254f5cd84685ab517dajeffhao    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
12311f3bc2f0f9366594379249027622ab63673b0d3bJeff Hao                                (type == kRefsAndArgs ? 0 : 3) + 1 /* Method* */) *
12321f3bc2f0f9366594379249027622ab63673b0d3bJeff Hao                                kPointerSize, kStackAlignment);
123315fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers    method->SetFrameSizeInBytes(frame_size);
12344f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    method->SetCoreSpillMask(core_spills);
12350703060875166106af3d490c6c264611aea67ec8jeffhao    method->SetFpSpillMask(0);
1236ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  } else if (instruction_set == kX86) {
12377caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    uint32_t ref_spills = (1 << art::x86::EBP) | (1 << art::x86::ESI) | (1 << art::x86::EDI);
12387caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    uint32_t arg_spills = (1 << art::x86::ECX) | (1 << art::x86::EDX) | (1 << art::x86::EBX);
12397caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
12407caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers                         (1 << art::x86::kNumberOfCpuRegisters);  // fake return address callee save
12417caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
12427caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers                                 1 /* Method* */) * kPointerSize, kStackAlignment);
12437caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    method->SetFrameSizeInBytes(frame_size);
12447caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    method->SetCoreSpillMask(core_spills);
1245ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    method->SetFpSpillMask(0);
1246ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  } else {
1247ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers    UNIMPLEMENTED(FATAL);
1248ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers  }
124940381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  return method.get();
1250ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers}
1251ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers
1252c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartiervoid Runtime::DisallowNewSystemWeaks() {
1253c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  monitor_list_->DisallowNewMonitors();
1254c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  intern_table_->DisallowNewInterns();
1255c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  java_vm_->DisallowNewWeakGlobals();
1256c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier}
1257c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier
1258c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartiervoid Runtime::AllowNewSystemWeaks() {
1259c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  monitor_list_->AllowNewMonitors();
1260c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  intern_table_->AllowNewInterns();
1261c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  java_vm_->AllowNewWeakGlobals();
1262c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier}
1263c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier
1264ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid Runtime::SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type) {
12654f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
1266225f5a1df25241babd16cdba54056b9e2cd166a2Elliott Hughes  callee_save_methods_[type] = method;
1267e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1268e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
126900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersconst std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(jobject class_loader) {
1270b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (class_loader == NULL) {
1271b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    return GetClassLinker()->GetBootClassPath();
1272b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  }
1273b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CHECK(UseCompileTimeClassPath());
1274b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CompileTimeClassPaths::const_iterator it = compile_time_class_paths_.find(class_loader);
1275b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CHECK(it != compile_time_class_paths_.end());
1276b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  return it->second;
1277b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes}
1278b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
127900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid Runtime::SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path) {
1280b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  CHECK(!IsStarted());
1281b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  use_compile_time_class_path_ = true;
1282a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  compile_time_class_paths_.Put(class_loader, class_path);
1283b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes}
1284b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
12856b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro}  // namespace art
1286