runtime.cc revision f1a5adc87760f938b01df26d906295063546b259
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "runtime.h"
18
19#include <signal.h>
20
21#include <cstdio>
22#include <cstdlib>
23#include <limits>
24#include <vector>
25
26#include "class_linker.h"
27#include "class_loader.h"
28#include "debugger.h"
29#include "dex_verifier.h"
30#include "heap.h"
31#include "image.h"
32#include "intern_table.h"
33#include "jni_internal.h"
34#include "monitor.h"
35#include "oat_file.h"
36#include "ScopedLocalRef.h"
37#include "signal_catcher.h"
38#include "space.h"
39#include "thread.h"
40#include "thread_list.h"
41#include "UniquePtr.h"
42
43// TODO: this drags in cutil/log.h, which conflicts with our logging.h.
44#include "JniConstants.h"
45
46namespace art {
47
48Runtime* Runtime::instance_ = NULL;
49
50Mutex Runtime::abort_lock_("abort lock");
51
52Runtime::Runtime()
53    : is_compiler_(false),
54      is_zygote_(false),
55      default_stack_size_(Thread::kDefaultStackSize),
56      monitor_list_(NULL),
57      thread_list_(NULL),
58      intern_table_(NULL),
59      class_linker_(NULL),
60      signal_catcher_(NULL),
61      java_vm_(NULL),
62      jni_stub_array_(NULL),
63      abstract_method_error_stub_array_(NULL),
64      shutting_down_(false),
65      started_(false),
66      vfprintf_(NULL),
67      exit_(NULL),
68      abort_(NULL),
69      stats_enabled_(false),
70      tracer_(NULL) {
71  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
72    resolution_stub_array_[i] = NULL;
73  }
74  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
75    callee_save_method_[i] = NULL;
76  }
77}
78
79Runtime::~Runtime() {
80  shutting_down_ = true;
81
82  Dbg::StopJdwp();
83
84  // Make sure our internal threads are dead before we start tearing down things they're using.
85  delete signal_catcher_;
86  // TODO: GC thread.
87
88  // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
89  delete thread_list_;
90  delete monitor_list_;
91
92  delete class_linker_;
93  Heap::Destroy();
94  verifier::DexVerifier::DeleteGcMaps();
95  delete intern_table_;
96  delete java_vm_;
97  Thread::Shutdown();
98  // TODO: acquire a static mutex on Runtime to avoid racing.
99  CHECK(instance_ == NULL || instance_ == this);
100  instance_ = NULL;
101}
102
103static bool gAborting = false;
104
105struct AbortState {
106  void Dump(std::ostream& os) {
107    if (gAborting) {
108      os << "Runtime aborting --- recursively, so no thread-specific detail!\n";
109      return;
110    }
111    gAborting = true;
112    os << "Runtime aborting...\n";
113    if (Runtime::Current() == NULL) {
114      os << "(Runtime does not yet exist!)\n";
115      return;
116    }
117    Thread* self = Thread::Current();
118    if (self == NULL) {
119      os << "(Aborting thread was not attached to runtime!)\n";
120    } else {
121      self->Dump(os);
122      if (self->IsExceptionPending()) {
123        os << "Pending " << PrettyTypeOf(self->GetException()) << " on thread:\n"
124           << self->GetException()->Dump();
125      }
126    }
127  }
128};
129
130void Runtime::Abort(const char* file, int line) {
131  // Ensure that we don't have multiple threads trying to abort at once,
132  // which would result in significantly worse diagnostics.
133  MutexLock mu(abort_lock_);
134
135  // Get any pending output out of the way.
136  fflush(NULL);
137
138  // Many people have difficulty distinguish aborts from crashes,
139  // so be explicit.
140  AbortState state;
141  LOG(INTERNAL_FATAL) << Dumpable<AbortState>(state);
142
143  // Perform any platform-specific pre-abort actions.
144  PlatformAbort(file, line);
145
146  // use abort hook if we have one
147  if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) {
148    Runtime::Current()->abort_();
149    // notreached
150  }
151
152  // If we call abort(3) on a device, all threads in the process
153  // receive SIGABRT.  debuggerd dumps the stack trace of the main
154  // thread, whether or not that was the thread that failed.  By
155  // stuffing a value into a bogus address, we cause a segmentation
156  // fault in the current thread, and get a useful log from debuggerd.
157  // We can also trivially tell the difference between a VM crash and
158  // a deliberate abort by looking at the fault address.
159  *reinterpret_cast<char*>(0xdeadd00d) = 38;
160  abort();
161  // notreached
162}
163
164void Runtime::CallExitHook(jint status) {
165  if (exit_ != NULL) {
166    ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative);
167    exit_(status);
168    LOG(WARNING) << "Exit hook returned instead of exiting!";
169  }
170}
171
172// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
173// memory sizes.  [kK] indicates kilobytes, [mM] megabytes, and
174// [gG] gigabytes.
175//
176// "s" should point just past the "-Xm?" part of the string.
177// "div" specifies a divisor, e.g. 1024 if the value must be a multiple
178// of 1024.
179//
180// The spec says the -Xmx and -Xms options must be multiples of 1024.  It
181// doesn't say anything about -Xss.
182//
183// Returns 0 (a useless size) if "s" is malformed or specifies a low or
184// non-evenly-divisible value.
185//
186size_t ParseMemoryOption(const char* s, size_t div) {
187  // strtoul accepts a leading [+-], which we don't want,
188  // so make sure our string starts with a decimal digit.
189  if (isdigit(*s)) {
190    const char* s2;
191    size_t val = strtoul(s, (char**)&s2, 10);
192    if (s2 != s) {
193      // s2 should be pointing just after the number.
194      // If this is the end of the string, the user
195      // has specified a number of bytes.  Otherwise,
196      // there should be exactly one more character
197      // that specifies a multiplier.
198      if (*s2 != '\0') {
199        // The remainder of the string is either a single multiplier
200        // character, or nothing to indicate that the value is in
201        // bytes.
202        char c = *s2++;
203        if (*s2 == '\0') {
204          size_t mul;
205          if (c == '\0') {
206            mul = 1;
207          } else if (c == 'k' || c == 'K') {
208            mul = KB;
209          } else if (c == 'm' || c == 'M') {
210            mul = MB;
211          } else if (c == 'g' || c == 'G') {
212            mul = GB;
213          } else {
214            // Unknown multiplier character.
215            return 0;
216          }
217
218          if (val <= std::numeric_limits<size_t>::max() / mul) {
219            val *= mul;
220          } else {
221            // Clamp to a multiple of 1024.
222            val = std::numeric_limits<size_t>::max() & ~(1024-1);
223          }
224        } else {
225          // There's more than one character after the numeric part.
226          return 0;
227        }
228      }
229      // The man page says that a -Xm value must be a multiple of 1024.
230      if (val % div == 0) {
231        return val;
232      }
233    }
234  }
235  return 0;
236}
237
238size_t ParseIntegerOrDie(const std::string& s) {
239  std::string::size_type colon = s.find(':');
240  if (colon == std::string::npos) {
241    LOG(FATAL) << "Missing integer: " << s;
242  }
243  const char* begin = &s[colon + 1];
244  char* end;
245  size_t result = strtoul(begin, &end, 10);
246  if (begin == end || *end != '\0') {
247    LOG(FATAL) << "Failed to parse integer in: " << s;
248  }
249  return result;
250}
251
252void LoadJniLibrary(JavaVMExt* vm, const char* name) {
253  std::string mapped_name(StringPrintf(OS_SHARED_LIB_FORMAT_STR, name));
254  std::string reason;
255  if (!vm->LoadNativeLibrary(mapped_name, NULL, reason)) {
256    LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": "
257               << reason;
258  }
259}
260
261Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
262  UniquePtr<ParsedOptions> parsed(new ParsedOptions());
263  const char* boot_class_path = getenv("BOOTCLASSPATH");
264  if (boot_class_path != NULL) {
265    parsed->boot_class_path_ = boot_class_path;
266  }
267  const char* class_path = getenv("CLASSPATH");
268  if (class_path != NULL) {
269    parsed->class_path_ = class_path;
270  }
271#ifdef NDEBUG
272  // -Xcheck:jni is off by default for regular builds...
273  parsed->check_jni_ = false;
274#else
275  // ...but on by default in debug builds.
276  parsed->check_jni_ = true;
277#endif
278
279  parsed->heap_initial_size_ = Heap::kInitialSize;
280  parsed->heap_maximum_size_ = Heap::kMaximumSize;
281  parsed->heap_growth_limit_ = 0;  // 0 means no growth limit
282  parsed->stack_size_ = Thread::kDefaultStackSize;
283
284  parsed->is_compiler_ = false;
285  parsed->is_zygote_ = false;
286
287  parsed->jni_globals_max_ = 0;
288  parsed->lock_profiling_threshold_ = 0;
289  parsed->hook_is_sensitive_thread_ = NULL;
290
291  parsed->hook_vfprintf_ = vfprintf;
292  parsed->hook_exit_ = exit;
293  parsed->hook_abort_ = abort;
294
295  for (size_t i = 0; i < options.size(); ++i) {
296    const std::string option(options[i].first);
297    if (true && options[0].first == "-Xzygote") {
298      LOG(INFO) << "option[" << i << "]=" << option;
299    }
300    if (StartsWith(option, "-Xbootclasspath:")) {
301      parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:"));
302    } else if (option == "-classpath" || option == "-cp") {
303      // TODO: support -Djava.class.path
304      i++;
305      if (i == options.size()) {
306        // TODO: usage
307        LOG(FATAL) << "Missing required class path value for " << option;
308        return NULL;
309      }
310      parsed->class_path_ = options[i].first;
311    } else if (StartsWith(option, "-Ximage:")) {
312      parsed->image_ = option.substr(strlen("-Ximage:"));
313    } else if (StartsWith(option, "-Xcheck:jni")) {
314      parsed->check_jni_ = true;
315    } else if (StartsWith(option, "-Xrunjdwp:") || StartsWith(option, "-agentlib:jdwp=")) {
316      std::string tail(option.substr(option[1] == 'X' ? 10 : 15));
317      if (tail == "help" || !Dbg::ParseJdwpOptions(tail)) {
318        LOG(FATAL) << "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n"
319                   << "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n";
320        return NULL;
321      }
322    } else if (StartsWith(option, "-Xms")) {
323      size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).c_str(), 1024);
324      if (size == 0) {
325        if (ignore_unrecognized) {
326          continue;
327        }
328        // TODO: usage
329        LOG(FATAL) << "Failed to parse " << option;
330        return NULL;
331      }
332      parsed->heap_initial_size_ = size;
333    } else if (StartsWith(option, "-Xmx")) {
334      size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).c_str(), 1024);
335      if (size == 0) {
336        if (ignore_unrecognized) {
337          continue;
338        }
339        // TODO: usage
340        LOG(FATAL) << "Failed to parse " << option;
341        return NULL;
342      }
343      parsed->heap_maximum_size_ = size;
344    } else if (StartsWith(option, "-XX:HeapGrowthLimit=")) {
345      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapGrowthLimit=")).c_str(), 1024);
346      if (size == 0) {
347        if (ignore_unrecognized) {
348          continue;
349        }
350        // TODO: usage
351        LOG(FATAL) << "Failed to parse " << option;
352        return NULL;
353      }
354      parsed->heap_growth_limit_ = size;
355    } else if (StartsWith(option, "-Xss")) {
356      size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).c_str(), 1);
357      if (size == 0) {
358        if (ignore_unrecognized) {
359          continue;
360        }
361        // TODO: usage
362        LOG(FATAL) << "Failed to parse " << option;
363        return NULL;
364      }
365      parsed->stack_size_ = size;
366    } else if (StartsWith(option, "-D")) {
367      parsed->properties_.push_back(option.substr(strlen("-D")));
368    } else if (StartsWith(option, "-Xjnitrace:")) {
369      parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:"));
370    } else if (option == "compiler") {
371      parsed->is_compiler_ = true;
372    } else if (option == "-Xzygote") {
373      parsed->is_zygote_ = true;
374    } else if (StartsWith(option, "-verbose:")) {
375      std::vector<std::string> verbose_options;
376      Split(option.substr(strlen("-verbose:")), ',', verbose_options);
377      for (size_t i = 0; i < verbose_options.size(); ++i) {
378        if (verbose_options[i] == "class") {
379          gLogVerbosity.class_linker = true;
380        } else if (verbose_options[i] == "compiler") {
381          gLogVerbosity.compiler = true;
382        } else if (verbose_options[i] == "heap") {
383          gLogVerbosity.heap = true;
384        } else if (verbose_options[i] == "gc") {
385          gLogVerbosity.gc = true;
386        } else if (verbose_options[i] == "jdwp") {
387          gLogVerbosity.jdwp = true;
388        } else if (verbose_options[i] == "jni") {
389          gLogVerbosity.jni = true;
390        } else if (verbose_options[i] == "monitor") {
391          gLogVerbosity.monitor = true;
392        } else if (verbose_options[i] == "startup") {
393          gLogVerbosity.startup = true;
394        } else if (verbose_options[i] == "third-party-jni") {
395          gLogVerbosity.third_party_jni = true;
396        } else if (verbose_options[i] == "threads") {
397          gLogVerbosity.threads = true;
398        } else {
399          LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i];
400        }
401      }
402    } else if (StartsWith(option, "-Xjnigreflimit:")) {
403      parsed->jni_globals_max_ = ParseIntegerOrDie(option);
404    } else if (StartsWith(option, "-Xlockprofthreshold:")) {
405      parsed->lock_profiling_threshold_ = ParseIntegerOrDie(option);
406    } else if (StartsWith(option, "-Xstacktracefile:")) {
407// always show stack traces in debug builds
408#ifdef NDEBUG
409      parsed->stack_trace_file_ = option.substr(strlen("-Xstacktracefile:"));
410#endif
411    } else if (option == "sensitiveThread") {
412      parsed->hook_is_sensitive_thread_ = reinterpret_cast<bool (*)()>(options[i].second);
413    } else if (option == "vfprintf") {
414      parsed->hook_vfprintf_ = reinterpret_cast<int (*)(FILE *, const char*, va_list)>(options[i].second);
415    } else if (option == "exit") {
416      parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second);
417    } else if (option == "abort") {
418      parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second);
419    } else if (option == "host-prefix") {
420      parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second);
421    } else if (option == "-Xgenregmap" || option == "-Xgc:precise") {
422      // We silently ignore these for backwards compatibility.
423    } else {
424      if (!ignore_unrecognized) {
425        // TODO: print usage via vfprintf
426        LOG(ERROR) << "Unrecognized option " << option;
427        // TODO: this should exit, but for now tolerate unknown options
428        //return NULL;
429      }
430    }
431  }
432
433  if (!parsed->is_compiler_ && parsed->image_.empty()) {
434    parsed->image_ += GetAndroidRoot();
435    parsed->image_ += "/framework/boot.art";
436  }
437  if (parsed->heap_growth_limit_ == 0) {
438    parsed->heap_growth_limit_ = parsed->heap_maximum_size_;
439  }
440
441  LOG(INFO) << "Build type: "
442#ifndef NDEBUG
443            << "debug"
444#else
445            << "optimized"
446#endif
447            << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off");
448
449  return parsed.release();
450}
451
452Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
453  // TODO: acquire a static mutex on Runtime to avoid racing.
454  if (Runtime::instance_ != NULL) {
455    return NULL;
456  }
457  instance_ = new Runtime;
458  if (!instance_->Init(options, ignore_unrecognized)) {
459    delete instance_;
460    instance_ = NULL;
461  }
462  return instance_;
463}
464
465void CreateSystemClassLoader() {
466  if (ClassLoader::UseCompileTimeClassPath()) {
467    return;
468  }
469
470  Thread* self = Thread::Current();
471
472  // Must be in the kNative state for calling native methods.
473  CHECK_EQ(self->GetState(), Thread::kNative);
474
475  JNIEnv* env = self->GetJniEnv();
476  ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader"));
477  CHECK(ClassLoader_class.get() != NULL);
478  jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(),
479                                                          "getSystemClassLoader",
480                                                          "()Ljava/lang/ClassLoader;");
481  CHECK(getSystemClassLoader != NULL);
482  ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(),
483                                                                        getSystemClassLoader));
484  CHECK(class_loader.get() != NULL);
485
486  Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get()));
487
488  ScopedLocalRef<jclass> Thread_class(env, env->FindClass("java/lang/Thread"));
489  CHECK(Thread_class.get() != NULL);
490  jfieldID contextClassLoader = env->GetFieldID(Thread_class.get(),
491                                                "contextClassLoader",
492                                                "Ljava/lang/ClassLoader;");
493  CHECK(contextClassLoader != NULL);
494  ScopedLocalRef<jobject> self_jobject(env, AddLocalReference<jobject>(env, self->GetPeer()));
495  env->SetObjectField(self_jobject.get(), contextClassLoader, class_loader.get());
496}
497
498void Runtime::Start() {
499  VLOG(startup) << "Runtime::Start entering";
500
501  CHECK(host_prefix_.empty()) << host_prefix_;
502
503  // Restore main thread state to kNative as expected by native code
504  Thread::Current()->SetState(Thread::kNative);
505
506  started_ = true;
507
508  // InitNativeMethods needs to be after started_ so that the classes
509  // it touches will have methods linked to the oat file if necessary.
510  InitNativeMethods();
511
512  Thread::FinishStartup();
513
514  if (!is_zygote_) {
515    DidForkFromZygote();
516  }
517
518  StartDaemonThreads();
519
520  CreateSystemClassLoader();
521
522  Thread::Current()->GetJniEnv()->locals.AssertEmpty();
523
524  VLOG(startup) << "Runtime::Start exiting";
525}
526
527void Runtime::DidForkFromZygote() {
528  is_zygote_ = false;
529
530  StartSignalCatcher();
531
532  // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
533  // this will pause the runtime, so we probably want this to come last.
534  Dbg::StartJdwp();
535}
536
537void Runtime::StartSignalCatcher() {
538  if (!is_zygote_) {
539    signal_catcher_ = new SignalCatcher(stack_trace_file_);
540  }
541}
542
543void Runtime::StartDaemonThreads() {
544  VLOG(startup) << "Runtime::StartDaemonThreads entering";
545
546  Thread* self = Thread::Current();
547
548  // Must be in the kNative state for calling native methods.
549  CHECK_EQ(self->GetState(), Thread::kNative);
550
551  JNIEnv* env = self->GetJniEnv();
552  ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Daemons"));
553  CHECK(c.get() != NULL);
554  jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V");
555  CHECK(mid != NULL);
556  env->CallStaticVoidMethod(c.get(), mid);
557  CHECK(!env->ExceptionCheck());
558
559  VLOG(startup) << "Runtime::StartDaemonThreads exiting";
560}
561
562bool Runtime::IsShuttingDown() const {
563  return shutting_down_;
564}
565
566bool Runtime::IsStarted() const {
567  return started_;
568}
569
570bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
571  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
572
573  UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
574  if (options.get() == NULL) {
575    LOG(ERROR) << "Failed to parse options";
576    return false;
577  }
578  VLOG(startup) << "Runtime::Init -verbose:startup enabled";
579
580  SetJniGlobalsMax(options->jni_globals_max_);
581  Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
582
583  host_prefix_ = options->host_prefix_;
584  boot_class_path_ = options->boot_class_path_;
585  class_path_ = options->class_path_;
586  properties_ = options->properties_;
587
588  is_compiler_ = options->is_compiler_;
589  is_zygote_ = options->is_zygote_;
590
591  vfprintf_ = options->hook_vfprintf_;
592  exit_ = options->hook_exit_;
593  abort_ = options->hook_abort_;
594
595  default_stack_size_ = options->stack_size_;
596  stack_trace_file_ = options->stack_trace_file_;
597
598  monitor_list_ = new MonitorList;
599  thread_list_ = new ThreadList;
600  intern_table_ = new InternTable;
601
602  Heap::Init(options->heap_initial_size_,
603             options->heap_growth_limit_,
604             options->heap_maximum_size_,
605             options->image_);
606
607  BlockSignals();
608
609  java_vm_ = new JavaVMExt(this, options.get());
610
611  Thread::Startup();
612
613  // ClassLinker needs an attached thread, but we can't fully attach a thread
614  // without creating objects.
615  Thread::Attach(this, "main", false);
616
617  // Set us to runnable so tools using a runtime can allocate and GC by default
618  Thread::Current()->SetState(Thread::kRunnable);
619
620  CHECK_GE(Heap::GetSpaces().size(), 1U);
621  class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace())
622                   ? ClassLinker::Create(intern_table_)
623                   : ClassLinker::Create(options->boot_class_path_, intern_table_));
624
625  VLOG(startup) << "Runtime::Init exiting";
626  return true;
627}
628
629void Runtime::InitNativeMethods() {
630  VLOG(startup) << "Runtime::InitNativeMethods entering";
631  Thread* self = Thread::Current();
632  JNIEnv* env = self->GetJniEnv();
633
634  // Must be in the kNative state for calling native methods (JNI_OnLoad code).
635  CHECK_EQ(self->GetState(), Thread::kNative);
636
637  // First set up JniConstants, which is used by both the runtime's built-in native
638  // methods and libcore.
639  JniConstants::init(env);
640
641  // Then set up the native methods provided by the runtime itself.
642  RegisterRuntimeNativeMethods(env);
643
644  // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad.
645  // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's
646  // the library that implements System.loadLibrary!
647  LoadJniLibrary(instance_->GetJavaVM(), "javacore");
648  VLOG(startup) << "Runtime::InitNativeMethods exiting";
649}
650
651void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
652#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
653  // Register Throwable first so that registration of other native methods can throw exceptions
654  REGISTER(register_java_lang_Throwable);
655  REGISTER(register_dalvik_system_DexFile);
656  REGISTER(register_dalvik_system_VMDebug);
657  REGISTER(register_dalvik_system_VMRuntime);
658  REGISTER(register_dalvik_system_VMStack);
659  REGISTER(register_dalvik_system_Zygote);
660  REGISTER(register_java_lang_Class);
661  REGISTER(register_java_lang_Object);
662  REGISTER(register_java_lang_Runtime);
663  REGISTER(register_java_lang_String);
664  REGISTER(register_java_lang_System);
665  REGISTER(register_java_lang_Thread);
666  REGISTER(register_java_lang_VMClassLoader);
667  REGISTER(register_java_lang_reflect_Array);
668  REGISTER(register_java_lang_reflect_Constructor);
669  REGISTER(register_java_lang_reflect_Field);
670  REGISTER(register_java_lang_reflect_Method);
671  REGISTER(register_java_lang_reflect_Proxy);
672  REGISTER(register_java_util_concurrent_atomic_AtomicLong);
673  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
674  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal);
675  REGISTER(register_sun_misc_Unsafe);
676#undef REGISTER
677}
678
679void Runtime::Dump(std::ostream& os) {
680  // TODO: dump other runtime statistics?
681  GetClassLinker()->DumpForSigQuit(os);
682  GetInternTable()->DumpForSigQuit(os);
683  os << "\n";
684
685  thread_list_->Dump(os);
686}
687
688void Runtime::DumpLockHolders(std::ostream& os) {
689  pid_t heap_lock_owner = Heap::GetLockOwner();
690  pid_t thread_list_lock_owner = GetThreadList()->GetLockOwner();
691  pid_t classes_lock_owner = GetClassLinker()->GetClassesLockOwner();
692  pid_t dex_lock_owner = GetClassLinker()->GetDexLockOwner();
693  if ((heap_lock_owner | thread_list_lock_owner | classes_lock_owner | dex_lock_owner) != 0) {
694    os << "Heap lock owner tid: " << heap_lock_owner << "\n"
695       << "ThreadList lock owner tid: " << thread_list_lock_owner << "\n"
696       << "ClassLinker classes lock owner tid: " << classes_lock_owner << "\n"
697       << "ClassLinker dex lock owner tid: " << dex_lock_owner << "\n";
698  }
699}
700
701void Runtime::SetStatsEnabled(bool new_state) {
702  if (new_state == true) {
703    GetStats()->Clear(~0);
704    // TODO: wouldn't it make more sense to clear _all_ threads' stats?
705    Thread::Current()->GetStats()->Clear(~0);
706  }
707  stats_enabled_ = new_state;
708}
709
710void Runtime::ResetStats(int kinds) {
711  GetStats()->Clear(kinds & 0xffff);
712  // TODO: wouldn't it make more sense to clear _all_ threads' stats?
713  Thread::Current()->GetStats()->Clear(kinds >> 16);
714}
715
716RuntimeStats* Runtime::GetStats() {
717  return &stats_;
718}
719
720int32_t Runtime::GetStat(int kind) {
721  RuntimeStats* stats;
722  if (kind < (1<<16)) {
723    stats = GetStats();
724  } else {
725    stats = Thread::Current()->GetStats();
726    kind >>= 16;
727  }
728  switch (kind) {
729  case KIND_ALLOCATED_OBJECTS:
730    return stats->allocated_objects;
731  case KIND_ALLOCATED_BYTES:
732    return stats->allocated_bytes;
733  case KIND_FREED_OBJECTS:
734    return stats->freed_objects;
735  case KIND_FREED_BYTES:
736    return stats->freed_bytes;
737  case KIND_GC_INVOCATIONS:
738    return stats->gc_for_alloc_count;
739  case KIND_CLASS_INIT_COUNT:
740    return stats->class_init_count;
741  case KIND_CLASS_INIT_TIME:
742    // Convert ns to us, reduce to 32 bits.
743    return (int) (stats->class_init_time_ns / 1000);
744  case KIND_EXT_ALLOCATED_OBJECTS:
745  case KIND_EXT_ALLOCATED_BYTES:
746  case KIND_EXT_FREED_OBJECTS:
747  case KIND_EXT_FREED_BYTES:
748    return 0;  // backward compatibility
749  default:
750    CHECK(false);
751    return -1; // unreachable
752  }
753}
754
755void Runtime::BlockSignals() {
756  sigset_t sigset;
757  if (sigemptyset(&sigset) == -1) {
758    PLOG(FATAL) << "sigemptyset failed";
759  }
760  if (sigaddset(&sigset, SIGPIPE) == -1) {
761    PLOG(ERROR) << "sigaddset SIGPIPE failed";
762  }
763  // SIGQUIT is used to dump the runtime's state (including stack traces).
764  if (sigaddset(&sigset, SIGQUIT) == -1) {
765    PLOG(ERROR) << "sigaddset SIGQUIT failed";
766  }
767  // SIGUSR1 is used to initiate a heap dump.
768  if (sigaddset(&sigset, SIGUSR1) == -1) {
769    PLOG(ERROR) << "sigaddset SIGUSR1 failed";
770  }
771  CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0);
772}
773
774void Runtime::AttachCurrentThread(const char* name, bool as_daemon) {
775  Thread::Attach(instance_, name, as_daemon);
776}
777
778void Runtime::DetachCurrentThread() {
779  // TODO: check we're not calling DetachCurrentThread from a call stack that
780  // includes managed frames. (It's only valid if the stack is all-native.)
781  thread_list_->Unregister();
782}
783
784void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
785  Dbg::VisitRoots(visitor, arg);
786  class_linker_->VisitRoots(visitor, arg);
787  intern_table_->VisitRoots(visitor, arg);
788  java_vm_->VisitRoots(visitor, arg);
789  thread_list_->VisitRoots(visitor, arg);
790  visitor(jni_stub_array_, arg);
791  visitor(abstract_method_error_stub_array_, arg);
792  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
793    visitor(resolution_stub_array_[i], arg);
794  }
795  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
796    visitor(callee_save_method_[i], arg);
797  }
798}
799
800bool Runtime::HasJniDlsymLookupStub() const {
801  return jni_stub_array_ != NULL;
802}
803
804ByteArray* Runtime::GetJniDlsymLookupStub() const {
805  CHECK(jni_stub_array_ != NULL);
806  return jni_stub_array_;
807}
808
809void Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) {
810  CHECK(jni_stub_array != NULL)  << " jni_stub_array=" << jni_stub_array;
811  CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array)
812      << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array;
813  jni_stub_array_ = jni_stub_array;
814}
815
816bool Runtime::HasAbstractMethodErrorStubArray() const {
817  return abstract_method_error_stub_array_ != NULL;
818}
819
820ByteArray* Runtime::GetAbstractMethodErrorStubArray() const {
821  CHECK(abstract_method_error_stub_array_ != NULL);
822  return abstract_method_error_stub_array_;
823}
824
825void Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) {
826  CHECK(abstract_method_error_stub_array != NULL);
827  CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array);
828  abstract_method_error_stub_array_ = abstract_method_error_stub_array;
829}
830
831
832Runtime::TrampolineType Runtime::GetTrampolineType(Method* method) {
833  if (method == NULL) {
834    return Runtime::kUnknownMethod;
835  } else if (method->IsStatic()) {
836    return Runtime::kStaticMethod;
837  } else {
838    return Runtime::kInstanceMethod;
839  }
840}
841
842bool Runtime::HasResolutionStubArray(TrampolineType type) const {
843  return resolution_stub_array_[type] != NULL;
844}
845
846ByteArray* Runtime::GetResolutionStubArray(TrampolineType type) const {
847  CHECK(HasResolutionStubArray(type));
848  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType));
849  return resolution_stub_array_[type];
850}
851
852void Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type) {
853  CHECK(resolution_stub_array != NULL);
854  CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array);
855  resolution_stub_array_[type] = resolution_stub_array;
856}
857
858Method* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) {
859  Class* method_class = Method::GetMethodClass();
860  SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
861  method->SetDeclaringClass(method_class);
862  // TODO: use a special method for callee saves
863  method->SetMethodIndex(DexFile::kDexNoIndex16);
864  method->SetCode(NULL);
865  if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
866    uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6)  | (1 << art::arm::R7) |
867                          (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
868    uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
869    uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9);
870    uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills :0) |
871                           (type == kSaveAll ? all_spills :0) | (1 << art::arm::LR);
872    uint32_t fp_all_spills = (1 << art::arm::S0)  | (1 << art::arm::S1)  | (1 << art::arm::S2) |
873                             (1 << art::arm::S3)  | (1 << art::arm::S4)  | (1 << art::arm::S5) |
874                             (1 << art::arm::S6)  | (1 << art::arm::S7)  | (1 << art::arm::S8) |
875                             (1 << art::arm::S9)  | (1 << art::arm::S10) | (1 << art::arm::S11) |
876                             (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) |
877                             (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) |
878                             (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) |
879                             (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) |
880                             (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) |
881                             (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) |
882                             (1 << art::arm::S30) | (1 << art::arm::S31);
883    uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0;
884    size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
885                                 __builtin_popcount(fp_spills) /* fprs */ +
886                                 1 /* Method* */) * kPointerSize, kStackAlignment);
887    method->SetFrameSizeInBytes(frame_size);
888    method->SetCoreSpillMask(core_spills);
889    method->SetFpSpillMask(fp_spills);
890  } else if (instruction_set == kX86) {
891    method->SetFrameSizeInBytes(32);
892    method->SetCoreSpillMask((1 << art::x86::EBX) | (1 << art::x86::EBP) | (1 << art::x86::ESI) |
893                             (1 << art::x86::EDI));
894    method->SetFpSpillMask(0);
895  } else {
896    UNIMPLEMENTED(FATAL);
897  }
898  return method.get();
899}
900
901bool Runtime::HasCalleeSaveMethod(CalleeSaveType type) const {
902  return callee_save_method_[type] != NULL;
903}
904
905// Returns a special method that describes all callee saves being spilled to the stack.
906Method* Runtime::GetCalleeSaveMethod(CalleeSaveType type) const {
907  CHECK(HasCalleeSaveMethod(type));
908  return callee_save_method_[type];
909}
910
911void Runtime::SetCalleeSaveMethod(Method* method, CalleeSaveType type) {
912  DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
913  callee_save_method_[type] = method;
914}
915
916void Runtime::EnableMethodTracing(Trace* tracer) {
917  CHECK(!IsMethodTracingActive());
918  tracer_ = tracer;
919}
920
921void Runtime::DisableMethodTracing() {
922  CHECK(IsMethodTracingActive());
923  delete tracer_;
924  tracer_ = NULL;
925}
926
927bool Runtime::IsMethodTracingActive() const {
928  return (tracer_ != NULL);
929}
930
931Trace* Runtime::GetTracer() const {
932  CHECK(IsMethodTracingActive());
933  return tracer_;
934}
935
936}  // namespace art
937