runtime.cc revision e0a53e99e2a01f8668d6616c3cec7e2f5a711286
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// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc 20#include <sys/mount.h> 21#include <linux/fs.h> 22 23#include <signal.h> 24#include <sys/syscall.h> 25 26#include <cstdio> 27#include <cstdlib> 28#include <limits> 29#include <vector> 30 31#include "arch/arm/registers_arm.h" 32#include "arch/mips/registers_mips.h" 33#include "arch/x86/registers_x86.h" 34#include "atomic.h" 35#include "class_linker.h" 36#include "debugger.h" 37#include "gc/accounting/card_table-inl.h" 38#include "gc/heap.h" 39#include "gc/space/space.h" 40#include "image.h" 41#include "instrumentation.h" 42#include "intern_table.h" 43#include "invoke_arg_array_builder.h" 44#include "jni_internal.h" 45#include "mirror/abstract_method-inl.h" 46#include "mirror/array.h" 47#include "mirror/class-inl.h" 48#include "mirror/class_loader.h" 49#include "mirror/field.h" 50#include "mirror/field-inl.h" 51#include "mirror/throwable.h" 52#include "monitor.h" 53#include "oat_file.h" 54#include "ScopedLocalRef.h" 55#include "scoped_thread_state_change.h" 56#include "signal_catcher.h" 57#include "signal_set.h" 58#include "sirt_ref.h" 59#include "thread.h" 60#include "thread_list.h" 61#include "trace.h" 62#include "UniquePtr.h" 63#include "verifier/method_verifier.h" 64#include "well_known_classes.h" 65 66#include "JniConstants.h" // Last to avoid LOG redefinition in ics-mr1-plus-art. 67 68namespace art { 69 70Runtime* Runtime::instance_ = NULL; 71 72Runtime::Runtime() 73 : is_compiler_(false), 74 is_zygote_(false), 75 is_concurrent_gc_enabled_(true), 76 default_stack_size_(0), 77 heap_(NULL), 78 monitor_list_(NULL), 79 thread_list_(NULL), 80 intern_table_(NULL), 81 class_linker_(NULL), 82 signal_catcher_(NULL), 83 java_vm_(NULL), 84 pre_allocated_OutOfMemoryError_(NULL), 85 resolution_method_(NULL), 86 system_class_loader_(NULL), 87 threads_being_born_(0), 88 shutdown_cond_(new ConditionVariable("Runtime shutdown", *Locks::runtime_shutdown_lock_)), 89 shutting_down_(false), 90 shutting_down_started_(false), 91 started_(false), 92 finished_starting_(false), 93 vfprintf_(NULL), 94 exit_(NULL), 95 abort_(NULL), 96 stats_enabled_(false), 97 method_trace_(0), 98 method_trace_file_size_(0), 99 instrumentation_(), 100 use_compile_time_class_path_(false), 101 main_thread_group_(NULL), 102 system_thread_group_(NULL) { 103 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 104 callee_save_methods_[i] = NULL; 105 } 106} 107 108Runtime::~Runtime() { 109 Thread* self = Thread::Current(); 110 { 111 MutexLock mu(self, *Locks::runtime_shutdown_lock_); 112 shutting_down_started_ = true; 113 while (threads_being_born_ > 0) { 114 shutdown_cond_->Wait(self); 115 } 116 shutting_down_ = true; 117 } 118 Trace::Shutdown(); 119 120 // Make sure to let the GC complete if it is running. 121 heap_->WaitForConcurrentGcToComplete(self); 122 heap_->DeleteThreadPool(); 123 124 // Make sure our internal threads are dead before we start tearing down things they're using. 125 Dbg::StopJdwp(); 126 delete signal_catcher_; 127 128 // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended. 129 delete thread_list_; 130 delete monitor_list_; 131 delete class_linker_; 132 delete heap_; 133 delete intern_table_; 134 delete java_vm_; 135 Thread::Shutdown(); 136 QuasiAtomic::Shutdown(); 137 verifier::MethodVerifier::Shutdown(); 138 // TODO: acquire a static mutex on Runtime to avoid racing. 139 CHECK(instance_ == NULL || instance_ == this); 140 instance_ = NULL; 141} 142 143struct AbortState { 144 void Dump(std::ostream& os) { 145 if (gAborting > 1) { 146 os << "Runtime aborting --- recursively, so no thread-specific detail!\n"; 147 return; 148 } 149 gAborting++; 150 os << "Runtime aborting...\n"; 151 if (Runtime::Current() == NULL) { 152 os << "(Runtime does not yet exist!)\n"; 153 return; 154 } 155 Thread* self = Thread::Current(); 156 if (self == NULL) { 157 os << "(Aborting thread was not attached to runtime!)\n"; 158 } else { 159 // TODO: we're aborting and the ScopedObjectAccess may attempt to acquire the mutator_lock_ 160 // which may block indefinitely if there's a misbehaving thread holding it exclusively. 161 // The code below should be made robust to this. 162 ScopedObjectAccess soa(self); 163 os << "Aborting thread:\n"; 164 self->Dump(os); 165 if (self->IsExceptionPending()) { 166 ThrowLocation throw_location; 167 mirror::Throwable* exception = self->GetException(&throw_location); 168 os << "Pending exception " << PrettyTypeOf(exception) 169 << " thrown by '" << throw_location.Dump() << "\n" 170 << exception->Dump(); 171 } 172 } 173 DumpAllThreads(os, self); 174 } 175 176 void DumpAllThreads(std::ostream& os, Thread* self) NO_THREAD_SAFETY_ANALYSIS { 177 bool tll_already_held = Locks::thread_list_lock_->IsExclusiveHeld(self); 178 bool ml_already_held = Locks::mutator_lock_->IsSharedHeld(self); 179 if (!tll_already_held || !ml_already_held) { 180 os << "Dumping all threads without appropriate locks held:" 181 << (!tll_already_held ? " thread list lock" : "") 182 << (!ml_already_held ? " mutator lock" : "") 183 << "\n"; 184 } 185 os << "All threads:\n"; 186 Runtime::Current()->GetThreadList()->DumpLocked(os); 187 } 188}; 189 190void Runtime::Abort() { 191 gAborting++; // set before taking any locks 192 193 // Ensure that we don't have multiple threads trying to abort at once, 194 // which would result in significantly worse diagnostics. 195 MutexLock mu(Thread::Current(), *Locks::abort_lock_); 196 197 // Get any pending output out of the way. 198 fflush(NULL); 199 200 // Many people have difficulty distinguish aborts from crashes, 201 // so be explicit. 202 AbortState state; 203 LOG(INTERNAL_FATAL) << Dumpable<AbortState>(state); 204 205 // Call the abort hook if we have one. 206 if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) { 207 LOG(INTERNAL_FATAL) << "Calling abort hook..."; 208 Runtime::Current()->abort_(); 209 // notreached 210 LOG(INTERNAL_FATAL) << "Unexpectedly returned from abort hook!"; 211 } 212 213#if defined(__GLIBC__) 214 // TODO: we ought to be able to use pthread_kill(3) here (or abort(3), 215 // which POSIX defines in terms of raise(3), which POSIX defines in terms 216 // of pthread_kill(3)). On Linux, though, libcorkscrew can't unwind through 217 // libpthread, which means the stacks we dump would be useless. Calling 218 // tgkill(2) directly avoids that. 219 syscall(__NR_tgkill, getpid(), GetTid(), SIGABRT); 220 // TODO: LLVM installs it's own SIGABRT handler so exit to be safe... Can we disable that in LLVM? 221 // If not, we could use sigaction(3) before calling tgkill(2) and lose this call to exit(3). 222 exit(1); 223#else 224 abort(); 225#endif 226 // notreached 227} 228 229bool Runtime::PreZygoteFork() { 230 heap_->PreZygoteFork(); 231 return true; 232} 233 234void Runtime::CallExitHook(jint status) { 235 if (exit_ != NULL) { 236 ScopedThreadStateChange tsc(Thread::Current(), kNative); 237 exit_(status); 238 LOG(WARNING) << "Exit hook returned instead of exiting!"; 239 } 240} 241 242// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify 243// memory sizes. [kK] indicates kilobytes, [mM] megabytes, and 244// [gG] gigabytes. 245// 246// "s" should point just past the "-Xm?" part of the string. 247// "div" specifies a divisor, e.g. 1024 if the value must be a multiple 248// of 1024. 249// 250// The spec says the -Xmx and -Xms options must be multiples of 1024. It 251// doesn't say anything about -Xss. 252// 253// Returns 0 (a useless size) if "s" is malformed or specifies a low or 254// non-evenly-divisible value. 255// 256size_t ParseMemoryOption(const char* s, size_t div) { 257 // strtoul accepts a leading [+-], which we don't want, 258 // so make sure our string starts with a decimal digit. 259 if (isdigit(*s)) { 260 char* s2; 261 size_t val = strtoul(s, &s2, 10); 262 if (s2 != s) { 263 // s2 should be pointing just after the number. 264 // If this is the end of the string, the user 265 // has specified a number of bytes. Otherwise, 266 // there should be exactly one more character 267 // that specifies a multiplier. 268 if (*s2 != '\0') { 269 // The remainder of the string is either a single multiplier 270 // character, or nothing to indicate that the value is in 271 // bytes. 272 char c = *s2++; 273 if (*s2 == '\0') { 274 size_t mul; 275 if (c == '\0') { 276 mul = 1; 277 } else if (c == 'k' || c == 'K') { 278 mul = KB; 279 } else if (c == 'm' || c == 'M') { 280 mul = MB; 281 } else if (c == 'g' || c == 'G') { 282 mul = GB; 283 } else { 284 // Unknown multiplier character. 285 return 0; 286 } 287 288 if (val <= std::numeric_limits<size_t>::max() / mul) { 289 val *= mul; 290 } else { 291 // Clamp to a multiple of 1024. 292 val = std::numeric_limits<size_t>::max() & ~(1024-1); 293 } 294 } else { 295 // There's more than one character after the numeric part. 296 return 0; 297 } 298 } 299 // The man page says that a -Xm value must be a multiple of 1024. 300 if (val % div == 0) { 301 return val; 302 } 303 } 304 } 305 return 0; 306} 307 308size_t ParseIntegerOrDie(const std::string& s) { 309 std::string::size_type colon = s.find(':'); 310 if (colon == std::string::npos) { 311 LOG(FATAL) << "Missing integer: " << s; 312 } 313 const char* begin = &s[colon + 1]; 314 char* end; 315 size_t result = strtoul(begin, &end, 10); 316 if (begin == end || *end != '\0') { 317 LOG(FATAL) << "Failed to parse integer in: " << s; 318 } 319 return result; 320} 321 322Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) { 323 UniquePtr<ParsedOptions> parsed(new ParsedOptions()); 324 const char* boot_class_path_string = getenv("BOOTCLASSPATH"); 325 if (boot_class_path_string != NULL) { 326 parsed->boot_class_path_string_ = boot_class_path_string; 327 } 328 const char* class_path_string = getenv("CLASSPATH"); 329 if (class_path_string != NULL) { 330 parsed->class_path_string_ = class_path_string; 331 } 332 // -Xcheck:jni is off by default for regular builds but on by default in debug builds. 333 parsed->check_jni_ = kIsDebugBuild; 334 335 parsed->heap_initial_size_ = gc::Heap::kDefaultInitialSize; 336 parsed->heap_maximum_size_ = gc::Heap::kDefaultMaximumSize; 337 parsed->heap_min_free_ = gc::Heap::kDefaultMinFree; 338 parsed->heap_max_free_ = gc::Heap::kDefaultMaxFree; 339 parsed->heap_target_utilization_ = gc::Heap::kDefaultTargetUtilization; 340 parsed->heap_growth_limit_ = 0; // 0 means no growth limit. 341 // Default to number of processors minus one since the main GC thread also does work. 342 parsed->heap_gc_threads_ = sysconf(_SC_NPROCESSORS_CONF) - 1; 343 parsed->stack_size_ = 0; // 0 means default. 344 parsed->low_memory_mode_ = false; 345 346 parsed->is_compiler_ = false; 347 parsed->is_zygote_ = false; 348 parsed->interpreter_only_ = false; 349 parsed->is_concurrent_gc_enabled_ = true; 350 351 parsed->lock_profiling_threshold_ = 0; 352 parsed->hook_is_sensitive_thread_ = NULL; 353 354 parsed->hook_vfprintf_ = vfprintf; 355 parsed->hook_exit_ = exit; 356 parsed->hook_abort_ = NULL; // We don't call abort(3) by default; see Runtime::Abort. 357 358 parsed->small_mode_ = false; 359 parsed->small_mode_method_threshold_ = Runtime::kDefaultSmallModeMethodThreshold; 360 parsed->small_mode_method_dex_size_limit_ = Runtime::kDefaultSmallModeMethodDexSizeLimit; 361 362 parsed->sea_ir_mode_ = false; 363// gLogVerbosity.class_linker = true; // TODO: don't check this in! 364// gLogVerbosity.compiler = true; // TODO: don't check this in! 365// gLogVerbosity.heap = true; // TODO: don't check this in! 366// gLogVerbosity.gc = true; // TODO: don't check this in! 367// gLogVerbosity.jdwp = true; // TODO: don't check this in! 368// gLogVerbosity.jni = true; // TODO: don't check this in! 369// gLogVerbosity.monitor = true; // TODO: don't check this in! 370// gLogVerbosity.startup = true; // TODO: don't check this in! 371// gLogVerbosity.third_party_jni = true; // TODO: don't check this in! 372// gLogVerbosity.threads = true; // TODO: don't check this in! 373 374 parsed->method_trace_ = false; 375 parsed->method_trace_file_ = "/data/method-trace-file.bin"; 376 parsed->method_trace_file_size_ = 10 * MB; 377 378 for (size_t i = 0; i < options.size(); ++i) { 379 const std::string option(options[i].first); 380 if (true && options[0].first == "-Xzygote") { 381 LOG(INFO) << "option[" << i << "]=" << option; 382 } 383 if (StartsWith(option, "-Xbootclasspath:")) { 384 parsed->boot_class_path_string_ = option.substr(strlen("-Xbootclasspath:")).data(); 385 } else if (option == "-classpath" || option == "-cp") { 386 // TODO: support -Djava.class.path 387 i++; 388 if (i == options.size()) { 389 // TODO: usage 390 LOG(FATAL) << "Missing required class path value for " << option; 391 return NULL; 392 } 393 const StringPiece& value = options[i].first; 394 parsed->class_path_string_ = value.data(); 395 } else if (option == "bootclasspath") { 396 parsed->boot_class_path_ 397 = reinterpret_cast<const std::vector<const DexFile*>*>(options[i].second); 398 } else if (StartsWith(option, "-Ximage:")) { 399 parsed->image_ = option.substr(strlen("-Ximage:")).data(); 400 } else if (StartsWith(option, "-Xcheck:jni")) { 401 parsed->check_jni_ = true; 402 } else if (StartsWith(option, "-Xrunjdwp:") || StartsWith(option, "-agentlib:jdwp=")) { 403 std::string tail(option.substr(option[1] == 'X' ? 10 : 15)); 404 if (tail == "help" || !Dbg::ParseJdwpOptions(tail)) { 405 LOG(FATAL) << "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n" 406 << "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n"; 407 return NULL; 408 } 409 } else if (StartsWith(option, "-Xms")) { 410 size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).c_str(), 1024); 411 if (size == 0) { 412 if (ignore_unrecognized) { 413 continue; 414 } 415 // TODO: usage 416 LOG(FATAL) << "Failed to parse " << option; 417 return NULL; 418 } 419 parsed->heap_initial_size_ = size; 420 } else if (StartsWith(option, "-Xmx")) { 421 size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).c_str(), 1024); 422 if (size == 0) { 423 if (ignore_unrecognized) { 424 continue; 425 } 426 // TODO: usage 427 LOG(FATAL) << "Failed to parse " << option; 428 return NULL; 429 } 430 parsed->heap_maximum_size_ = size; 431 } else if (StartsWith(option, "-XX:HeapGrowthLimit=")) { 432 size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapGrowthLimit=")).c_str(), 1024); 433 if (size == 0) { 434 if (ignore_unrecognized) { 435 continue; 436 } 437 // TODO: usage 438 LOG(FATAL) << "Failed to parse " << option; 439 return NULL; 440 } 441 parsed->heap_growth_limit_ = size; 442 } else if (StartsWith(option, "-XX:HeapMinFree=")) { 443 size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapMinFree=")).c_str(), 1024); 444 if (size == 0) { 445 if (ignore_unrecognized) { 446 continue; 447 } 448 // TODO: usage 449 LOG(FATAL) << "Failed to parse " << option; 450 return NULL; 451 } 452 parsed->heap_min_free_ = size; 453 } else if (StartsWith(option, "-XX:HeapMaxFree=")) { 454 size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapMaxFree=")).c_str(), 1024); 455 if (size == 0) { 456 if (ignore_unrecognized) { 457 continue; 458 } 459 // TODO: usage 460 LOG(FATAL) << "Failed to parse " << option; 461 return NULL; 462 } 463 parsed->heap_max_free_ = size; 464 } else if (StartsWith(option, "-XX:HeapTargetUtilization=")) { 465 std::istringstream iss(option.substr(strlen("-XX:HeapTargetUtilization="))); 466 double value; 467 iss >> value; 468 // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range. 469 const bool sane_val = iss.eof() && (value >= 0.1) && (value <= 0.9); 470 if (!sane_val) { 471 if (ignore_unrecognized) { 472 continue; 473 } 474 LOG(FATAL) << "Invalid option '" << option << "'"; 475 return NULL; 476 } 477 parsed->heap_target_utilization_ = value; 478 } else if (StartsWith(option, "-XX:HeapGCThreads=")) { 479 parsed->heap_gc_threads_ = 480 ParseMemoryOption(option.substr(strlen("-XX:HeapGCThreads=")).c_str(), 1024); 481 } else if (StartsWith(option, "-Xss")) { 482 size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).c_str(), 1); 483 if (size == 0) { 484 if (ignore_unrecognized) { 485 continue; 486 } 487 // TODO: usage 488 LOG(FATAL) << "Failed to parse " << option; 489 return NULL; 490 } 491 parsed->stack_size_ = size; 492 } else if (option == "-XX:LowMemoryMode") { 493 parsed->low_memory_mode_ = true; 494 } else if (StartsWith(option, "-D")) { 495 parsed->properties_.push_back(option.substr(strlen("-D"))); 496 } else if (StartsWith(option, "-Xjnitrace:")) { 497 parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:")); 498 } else if (option == "compiler") { 499 parsed->is_compiler_ = true; 500 } else if (option == "-Xzygote") { 501 parsed->is_zygote_ = true; 502 } else if (option == "-Xint") { 503 parsed->interpreter_only_ = true; 504 } else if (StartsWith(option, "-Xgc:")) { 505 std::vector<std::string> gc_options; 506 Split(option.substr(strlen("-Xgc:")), ',', gc_options); 507 for (size_t i = 0; i < gc_options.size(); ++i) { 508 if (gc_options[i] == "noconcurrent") { 509 parsed->is_concurrent_gc_enabled_ = false; 510 } else if (gc_options[i] == "concurrent") { 511 parsed->is_concurrent_gc_enabled_ = true; 512 } else { 513 LOG(WARNING) << "Ignoring unknown -Xgc option: " << gc_options[i]; 514 } 515 } 516 } else if (StartsWith(option, "-verbose:")) { 517 std::vector<std::string> verbose_options; 518 Split(option.substr(strlen("-verbose:")), ',', verbose_options); 519 for (size_t i = 0; i < verbose_options.size(); ++i) { 520 if (verbose_options[i] == "class") { 521 gLogVerbosity.class_linker = true; 522 } else if (verbose_options[i] == "compiler") { 523 gLogVerbosity.compiler = true; 524 } else if (verbose_options[i] == "heap") { 525 gLogVerbosity.heap = true; 526 } else if (verbose_options[i] == "gc") { 527 gLogVerbosity.gc = true; 528 } else if (verbose_options[i] == "jdwp") { 529 gLogVerbosity.jdwp = true; 530 } else if (verbose_options[i] == "jni") { 531 gLogVerbosity.jni = true; 532 } else if (verbose_options[i] == "monitor") { 533 gLogVerbosity.monitor = true; 534 } else if (verbose_options[i] == "startup") { 535 gLogVerbosity.startup = true; 536 } else if (verbose_options[i] == "third-party-jni") { 537 gLogVerbosity.third_party_jni = true; 538 } else if (verbose_options[i] == "threads") { 539 gLogVerbosity.threads = true; 540 } else { 541 LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i]; 542 } 543 } 544 } else if (StartsWith(option, "-Xjnigreflimit:")) { 545 // Silently ignored for backwards compatibility. 546 } else if (StartsWith(option, "-Xlockprofthreshold:")) { 547 parsed->lock_profiling_threshold_ = ParseIntegerOrDie(option); 548 } else if (StartsWith(option, "-Xstacktracefile:")) { 549 parsed->stack_trace_file_ = option.substr(strlen("-Xstacktracefile:")); 550 } else if (option == "sensitiveThread") { 551 parsed->hook_is_sensitive_thread_ = reinterpret_cast<bool (*)()>(const_cast<void*>(options[i].second)); 552 } else if (option == "vfprintf") { 553 parsed->hook_vfprintf_ = 554 reinterpret_cast<int (*)(FILE *, const char*, va_list)>(const_cast<void*>(options[i].second)); 555 } else if (option == "exit") { 556 parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(const_cast<void*>(options[i].second)); 557 } else if (option == "abort") { 558 parsed->hook_abort_ = reinterpret_cast<void(*)()>(const_cast<void*>(options[i].second)); 559 } else if (option == "host-prefix") { 560 parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second); 561 } else if (option == "-Xgenregmap" || option == "-Xgc:precise") { 562 // We silently ignore these for backwards compatibility. 563 } else if (option == "-Xmethod-trace") { 564 parsed->method_trace_ = true; 565 } else if (StartsWith(option, "-Xmethod-trace-file:")) { 566 parsed->method_trace_file_ = option.substr(strlen("-Xmethod-trace-file:")); 567 } else if (StartsWith(option, "-Xmethod-trace-file-size:")) { 568 parsed->method_trace_file_size_ = ParseIntegerOrDie(option); 569 } else if (option == "-Xprofile:threadcpuclock") { 570 Trace::SetDefaultClockSource(kProfilerClockSourceThreadCpu); 571 } else if (option == "-Xprofile:wallclock") { 572 Trace::SetDefaultClockSource(kProfilerClockSourceWall); 573 } else if (option == "-Xprofile:dualclock") { 574 Trace::SetDefaultClockSource(kProfilerClockSourceDual); 575 } else if (option == "-small") { 576 parsed->small_mode_ = true; 577 } else if (option == "-sea_ir") { 578 parsed->sea_ir_mode_ = true; 579 } else if (StartsWith(option, "-small-mode-methods-max:")) { 580 parsed->small_mode_method_threshold_ = ParseIntegerOrDie(option); 581 } else if (StartsWith(option, "-small-mode-methods-size-max:")) { 582 parsed->small_mode_method_dex_size_limit_ = ParseIntegerOrDie(option); 583 } else { 584 if (!ignore_unrecognized) { 585 // TODO: print usage via vfprintf 586 LOG(ERROR) << "Unrecognized option " << option; 587 // TODO: this should exit, but for now tolerate unknown options 588 // return NULL; 589 } 590 } 591 } 592 593 // If a reference to the dalvik core.jar snuck in, replace it with 594 // the art specific version. This can happen with on device 595 // boot.art/boot.oat generation by GenerateImage which relies on the 596 // value of BOOTCLASSPATH. 597 std::string core_jar("/core.jar"); 598 size_t core_jar_pos = parsed->boot_class_path_string_.find(core_jar); 599 if (core_jar_pos != std::string::npos) { 600 parsed->boot_class_path_string_.replace(core_jar_pos, core_jar.size(), "/core-libart.jar"); 601 } 602 603 if (!parsed->is_compiler_ && parsed->image_.empty()) { 604 parsed->image_ += GetAndroidRoot(); 605 parsed->image_ += "/framework/boot.art"; 606 } 607 if (parsed->heap_growth_limit_ == 0) { 608 parsed->heap_growth_limit_ = parsed->heap_maximum_size_; 609 } 610 611 return parsed.release(); 612} 613 614bool Runtime::Create(const Options& options, bool ignore_unrecognized) { 615 // TODO: acquire a static mutex on Runtime to avoid racing. 616 if (Runtime::instance_ != NULL) { 617 return false; 618 } 619 InitLogging(NULL); // Calls Locks::Init() as a side effect. 620 instance_ = new Runtime; 621 if (!instance_->Init(options, ignore_unrecognized)) { 622 delete instance_; 623 instance_ = NULL; 624 return false; 625 } 626 return true; 627} 628 629static void CreateSystemClassLoader() { 630 if (Runtime::Current()->UseCompileTimeClassPath()) { 631 return; 632 } 633 634 ScopedObjectAccess soa(Thread::Current()); 635 636 mirror::Class* class_loader_class = 637 soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader); 638 CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(class_loader_class, true, true)); 639 640 mirror::AbstractMethod* getSystemClassLoader = 641 class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;"); 642 CHECK(getSystemClassLoader != NULL); 643 644 JValue result; 645 ArgArray arg_array(NULL, 0); 646 InvokeWithArgArray(soa, getSystemClassLoader, &arg_array, &result, 'L'); 647 mirror::ClassLoader* class_loader = down_cast<mirror::ClassLoader*>(result.GetL()); 648 CHECK(class_loader != NULL); 649 650 soa.Self()->SetClassLoaderOverride(class_loader); 651 652 mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); 653 CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(thread_class, true, true)); 654 655 mirror::Field* contextClassLoader = thread_class->FindDeclaredInstanceField("contextClassLoader", 656 "Ljava/lang/ClassLoader;"); 657 CHECK(contextClassLoader != NULL); 658 659 contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader); 660} 661 662bool Runtime::Start() { 663 VLOG(startup) << "Runtime::Start entering"; 664 665 CHECK(host_prefix_.empty()) << host_prefix_; 666 667 // Pre-allocate an OutOfMemoryError for the double-OOME case. 668 Thread* self = Thread::Current(); 669 self->ThrowNewException(ThrowLocation(), "Ljava/lang/OutOfMemoryError;", 670 "OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available"); 671 pre_allocated_OutOfMemoryError_ = self->GetException(NULL); 672 self->ClearException(); 673 674 // Restore main thread state to kNative as expected by native code. 675 self->TransitionFromRunnableToSuspended(kNative); 676 677 started_ = true; 678 679 // InitNativeMethods needs to be after started_ so that the classes 680 // it touches will have methods linked to the oat file if necessary. 681 InitNativeMethods(); 682 683 // Initialize well known thread group values that may be accessed threads while attaching. 684 InitThreadGroups(self); 685 686 Thread::FinishStartup(); 687 688 if (is_zygote_) { 689 if (!InitZygote()) { 690 return false; 691 } 692 } else { 693 DidForkFromZygote(); 694 } 695 696 StartDaemonThreads(); 697 698 CreateSystemClassLoader(); 699 700 self->GetJniEnv()->locals.AssertEmpty(); 701 702 VLOG(startup) << "Runtime::Start exiting"; 703 704 finished_starting_ = true; 705 706 return true; 707} 708 709void Runtime::EndThreadBirth() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_) { 710 DCHECK_GT(threads_being_born_, 0U); 711 threads_being_born_--; 712 if (shutting_down_started_ && threads_being_born_ == 0) { 713 shutdown_cond_->Broadcast(Thread::Current()); 714 } 715} 716 717// Do zygote-mode-only initialization. 718bool Runtime::InitZygote() { 719 // zygote goes into its own process group 720 setpgid(0, 0); 721 722 // See storage config details at http://source.android.com/tech/storage/ 723 // Create private mount namespace shared by all children 724 if (unshare(CLONE_NEWNS) == -1) { 725 PLOG(WARNING) << "Failed to unshare()"; 726 return false; 727 } 728 729 // Mark rootfs as being a slave so that changes from default 730 // namespace only flow into our children. 731 if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) { 732 PLOG(WARNING) << "Failed to mount() rootfs as MS_SLAVE"; 733 return false; 734 } 735 736 // Create a staging tmpfs that is shared by our children; they will 737 // bind mount storage into their respective private namespaces, which 738 // are isolated from each other. 739 const char* target_base = getenv("EMULATED_STORAGE_TARGET"); 740 if (target_base != NULL) { 741 if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV, 742 "uid=0,gid=1028,mode=0050") == -1) { 743 LOG(WARNING) << "Failed to mount tmpfs to " << target_base; 744 return false; 745 } 746 } 747 748 return true; 749} 750 751void Runtime::DidForkFromZygote() { 752 is_zygote_ = false; 753 754 // Create the thread pool. 755 heap_->CreateThreadPool(); 756 757 StartSignalCatcher(); 758 759 // Start the JDWP thread. If the command-line debugger flags specified "suspend=y", 760 // this will pause the runtime, so we probably want this to come last. 761 Dbg::StartJdwp(); 762} 763 764void Runtime::StartSignalCatcher() { 765 if (!is_zygote_) { 766 signal_catcher_ = new SignalCatcher(stack_trace_file_); 767 } 768} 769 770void Runtime::StartDaemonThreads() { 771 VLOG(startup) << "Runtime::StartDaemonThreads entering"; 772 773 Thread* self = Thread::Current(); 774 775 // Must be in the kNative state for calling native methods. 776 CHECK_EQ(self->GetState(), kNative); 777 778 JNIEnv* env = self->GetJniEnv(); 779 env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons, 780 WellKnownClasses::java_lang_Daemons_start); 781 if (env->ExceptionCheck()) { 782 env->ExceptionDescribe(); 783 LOG(FATAL) << "Error starting java.lang.Daemons"; 784 } 785 786 VLOG(startup) << "Runtime::StartDaemonThreads exiting"; 787} 788 789bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { 790 CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize); 791 792 UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized)); 793 if (options.get() == NULL) { 794 LOG(ERROR) << "Failed to parse options"; 795 return false; 796 } 797 VLOG(startup) << "Runtime::Init -verbose:startup enabled"; 798 799 QuasiAtomic::Startup(); 800 801 Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_); 802 803 host_prefix_ = options->host_prefix_; 804 boot_class_path_string_ = options->boot_class_path_string_; 805 class_path_string_ = options->class_path_string_; 806 properties_ = options->properties_; 807 808 is_compiler_ = options->is_compiler_; 809 is_zygote_ = options->is_zygote_; 810 is_concurrent_gc_enabled_ = options->is_concurrent_gc_enabled_; 811 812 small_mode_ = options->small_mode_; 813 small_mode_method_threshold_ = options->small_mode_method_threshold_; 814 small_mode_method_dex_size_limit_ = options->small_mode_method_dex_size_limit_; 815 816 sea_ir_mode_ = options->sea_ir_mode_; 817 vfprintf_ = options->hook_vfprintf_; 818 exit_ = options->hook_exit_; 819 abort_ = options->hook_abort_; 820 821 default_stack_size_ = options->stack_size_; 822 stack_trace_file_ = options->stack_trace_file_; 823 824 monitor_list_ = new MonitorList; 825 thread_list_ = new ThreadList; 826 intern_table_ = new InternTable; 827 828 829 if (options->interpreter_only_) { 830 GetInstrumentation()->ForceInterpretOnly(); 831 } 832 833 heap_ = new gc::Heap(options->heap_initial_size_, 834 options->heap_growth_limit_, 835 options->heap_min_free_, 836 options->heap_max_free_, 837 options->heap_target_utilization_, 838 options->heap_maximum_size_, 839 options->image_, 840 options->is_concurrent_gc_enabled_, 841 options->heap_gc_threads_, 842 options->low_memory_mode_); 843 844 BlockSignals(); 845 InitPlatformSignalHandlers(); 846 847 java_vm_ = new JavaVMExt(this, options.get()); 848 849 Thread::Startup(); 850 851 // ClassLinker needs an attached thread, but we can't fully attach a thread without creating 852 // objects. We can't supply a thread group yet; it will be fixed later. Since we are the main 853 // thread, we do not get a java peer. 854 Thread* self = Thread::Attach("main", false, NULL, false); 855 CHECK_EQ(self->thin_lock_id_, ThreadList::kMainId); 856 CHECK(self != NULL); 857 858 // Set us to runnable so tools using a runtime can allocate and GC by default 859 self->TransitionFromSuspendedToRunnable(); 860 861 // Now we're attached, we can take the heap lock and validate the heap. 862 GetHeap()->EnableObjectValidation(); 863 864 CHECK_GE(GetHeap()->GetContinuousSpaces().size(), 1U); 865 if (GetHeap()->GetContinuousSpaces()[0]->IsImageSpace()) { 866 class_linker_ = ClassLinker::CreateFromImage(intern_table_); 867 } else { 868 CHECK(options->boot_class_path_ != NULL); 869 CHECK_NE(options->boot_class_path_->size(), 0U); 870 class_linker_ = ClassLinker::CreateFromCompiler(*options->boot_class_path_, intern_table_); 871 } 872 CHECK(class_linker_ != NULL); 873 verifier::MethodVerifier::Init(); 874 875 method_trace_ = options->method_trace_; 876 method_trace_file_ = options->method_trace_file_; 877 method_trace_file_size_ = options->method_trace_file_size_; 878 879 if (options->method_trace_) { 880 Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0, false); 881 } 882 883 VLOG(startup) << "Runtime::Init exiting"; 884 return true; 885} 886 887void Runtime::InitNativeMethods() { 888 VLOG(startup) << "Runtime::InitNativeMethods entering"; 889 Thread* self = Thread::Current(); 890 JNIEnv* env = self->GetJniEnv(); 891 892 // Must be in the kNative state for calling native methods (JNI_OnLoad code). 893 CHECK_EQ(self->GetState(), kNative); 894 895 // First set up JniConstants, which is used by both the runtime's built-in native 896 // methods and libcore. 897 JniConstants::init(env); 898 WellKnownClasses::Init(env); 899 900 // Then set up the native methods provided by the runtime itself. 901 RegisterRuntimeNativeMethods(env); 902 903 // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad. 904 // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's 905 // the library that implements System.loadLibrary! 906 { 907 std::string mapped_name(StringPrintf(OS_SHARED_LIB_FORMAT_STR, "javacore")); 908 std::string reason; 909 self->TransitionFromSuspendedToRunnable(); 910 if (!instance_->java_vm_->LoadNativeLibrary(mapped_name, NULL, reason)) { 911 LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": " << reason; 912 } 913 self->TransitionFromRunnableToSuspended(kNative); 914 } 915 916 // Initialize well known classes that may invoke runtime native methods. 917 WellKnownClasses::LateInit(env); 918 919 VLOG(startup) << "Runtime::InitNativeMethods exiting"; 920} 921 922void Runtime::InitThreadGroups(Thread* self) { 923 JNIEnvExt* env = self->GetJniEnv(); 924 ScopedJniEnvLocalRefState env_state(env); 925 main_thread_group_ = 926 env->NewGlobalRef(env->GetStaticObjectField(WellKnownClasses::java_lang_ThreadGroup, 927 WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup)); 928 CHECK(main_thread_group_ != NULL || IsCompiler()); 929 system_thread_group_ = 930 env->NewGlobalRef(env->GetStaticObjectField(WellKnownClasses::java_lang_ThreadGroup, 931 WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup)); 932 CHECK(system_thread_group_ != NULL || IsCompiler()); 933} 934 935jobject Runtime::GetMainThreadGroup() const { 936 CHECK(main_thread_group_ != NULL || IsCompiler()); 937 return main_thread_group_; 938} 939 940jobject Runtime::GetSystemThreadGroup() const { 941 CHECK(system_thread_group_ != NULL || IsCompiler()); 942 return system_thread_group_; 943} 944 945void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { 946#define REGISTER(FN) extern void FN(JNIEnv*); FN(env) 947 // Register Throwable first so that registration of other native methods can throw exceptions 948 REGISTER(register_java_lang_Throwable); 949 REGISTER(register_dalvik_system_DexFile); 950 REGISTER(register_dalvik_system_VMDebug); 951 REGISTER(register_dalvik_system_VMRuntime); 952 REGISTER(register_dalvik_system_VMStack); 953 REGISTER(register_dalvik_system_Zygote); 954 REGISTER(register_java_lang_Class); 955 REGISTER(register_java_lang_Object); 956 REGISTER(register_java_lang_Runtime); 957 REGISTER(register_java_lang_String); 958 REGISTER(register_java_lang_System); 959 REGISTER(register_java_lang_Thread); 960 REGISTER(register_java_lang_VMClassLoader); 961 REGISTER(register_java_lang_reflect_Array); 962 REGISTER(register_java_lang_reflect_Constructor); 963 REGISTER(register_java_lang_reflect_Field); 964 REGISTER(register_java_lang_reflect_Method); 965 REGISTER(register_java_lang_reflect_Proxy); 966 REGISTER(register_java_util_concurrent_atomic_AtomicLong); 967 REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer); 968 REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal); 969 REGISTER(register_sun_misc_Unsafe); 970#undef REGISTER 971} 972 973void Runtime::DumpForSigQuit(std::ostream& os) { 974 GetClassLinker()->DumpForSigQuit(os); 975 GetInternTable()->DumpForSigQuit(os); 976 GetJavaVM()->DumpForSigQuit(os); 977 GetHeap()->DumpForSigQuit(os); 978 os << "\n"; 979 980 thread_list_->DumpForSigQuit(os); 981 BaseMutex::DumpAll(os); 982} 983 984void Runtime::DumpLockHolders(std::ostream& os) { 985 uint64_t mutator_lock_owner = Locks::mutator_lock_->GetExclusiveOwnerTid(); 986 pid_t thread_list_lock_owner = GetThreadList()->GetLockOwner(); 987 pid_t classes_lock_owner = GetClassLinker()->GetClassesLockOwner(); 988 pid_t dex_lock_owner = GetClassLinker()->GetDexLockOwner(); 989 if ((thread_list_lock_owner | classes_lock_owner | dex_lock_owner) != 0) { 990 os << "Mutator lock exclusive owner tid: " << mutator_lock_owner << "\n" 991 << "ThreadList lock owner tid: " << thread_list_lock_owner << "\n" 992 << "ClassLinker classes lock owner tid: " << classes_lock_owner << "\n" 993 << "ClassLinker dex lock owner tid: " << dex_lock_owner << "\n"; 994 } 995} 996 997void Runtime::SetStatsEnabled(bool new_state) { 998 if (new_state == true) { 999 GetStats()->Clear(~0); 1000 // TODO: wouldn't it make more sense to clear _all_ threads' stats? 1001 Thread::Current()->GetStats()->Clear(~0); 1002 } 1003 stats_enabled_ = new_state; 1004} 1005 1006void Runtime::ResetStats(int kinds) { 1007 GetStats()->Clear(kinds & 0xffff); 1008 // TODO: wouldn't it make more sense to clear _all_ threads' stats? 1009 Thread::Current()->GetStats()->Clear(kinds >> 16); 1010} 1011 1012int32_t Runtime::GetStat(int kind) { 1013 RuntimeStats* stats; 1014 if (kind < (1<<16)) { 1015 stats = GetStats(); 1016 } else { 1017 stats = Thread::Current()->GetStats(); 1018 kind >>= 16; 1019 } 1020 switch (kind) { 1021 case KIND_ALLOCATED_OBJECTS: 1022 return stats->allocated_objects; 1023 case KIND_ALLOCATED_BYTES: 1024 return stats->allocated_bytes; 1025 case KIND_FREED_OBJECTS: 1026 return stats->freed_objects; 1027 case KIND_FREED_BYTES: 1028 return stats->freed_bytes; 1029 case KIND_GC_INVOCATIONS: 1030 return stats->gc_for_alloc_count; 1031 case KIND_CLASS_INIT_COUNT: 1032 return stats->class_init_count; 1033 case KIND_CLASS_INIT_TIME: 1034 // Convert ns to us, reduce to 32 bits. 1035 return static_cast<int>(stats->class_init_time_ns / 1000); 1036 case KIND_EXT_ALLOCATED_OBJECTS: 1037 case KIND_EXT_ALLOCATED_BYTES: 1038 case KIND_EXT_FREED_OBJECTS: 1039 case KIND_EXT_FREED_BYTES: 1040 return 0; // backward compatibility 1041 default: 1042 LOG(FATAL) << "Unknown statistic " << kind; 1043 return -1; // unreachable 1044 } 1045} 1046 1047void Runtime::BlockSignals() { 1048 SignalSet signals; 1049 signals.Add(SIGPIPE); 1050 // SIGQUIT is used to dump the runtime's state (including stack traces). 1051 signals.Add(SIGQUIT); 1052 // SIGUSR1 is used to initiate a GC. 1053 signals.Add(SIGUSR1); 1054 signals.Block(); 1055} 1056 1057bool Runtime::AttachCurrentThread(const char* thread_name, bool as_daemon, jobject thread_group, 1058 bool create_peer) { 1059 bool success = Thread::Attach(thread_name, as_daemon, thread_group, create_peer) != NULL; 1060 if (thread_name == NULL) { 1061 LOG(WARNING) << *Thread::Current() << " attached without supplying a name"; 1062 } 1063 return success; 1064} 1065 1066void Runtime::DetachCurrentThread() { 1067 Thread* self = Thread::Current(); 1068 if (self == NULL) { 1069 LOG(FATAL) << "attempting to detach thread that is not attached"; 1070 } 1071 if (self->HasManagedStack()) { 1072 LOG(FATAL) << *Thread::Current() << " attempting to detach while still running code"; 1073 } 1074 thread_list_->Unregister(self); 1075} 1076 1077void Runtime::VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_dirty, 1078 bool clean_dirty) { 1079 if (!only_dirty || intern_table_->IsDirty()) { 1080 intern_table_->VisitRoots(visitor, arg, clean_dirty); 1081 } 1082 if (!only_dirty || class_linker_->IsDirty()) { 1083 class_linker_->VisitRoots(visitor, arg, clean_dirty); 1084 } 1085} 1086 1087void Runtime::VisitNonThreadRoots(RootVisitor* visitor, void* arg) { 1088 java_vm_->VisitRoots(visitor, arg); 1089 if (pre_allocated_OutOfMemoryError_ != NULL) { 1090 visitor(pre_allocated_OutOfMemoryError_, arg); 1091 } 1092 visitor(resolution_method_, arg); 1093 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 1094 visitor(callee_save_methods_[i], arg); 1095 } 1096} 1097 1098void Runtime::VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) { 1099 thread_list_->VisitRoots(visitor, arg); 1100 VisitNonThreadRoots(visitor, arg); 1101} 1102 1103void Runtime::VisitRoots(RootVisitor* visitor, void* arg, bool only_dirty, bool clean_dirty) { 1104 VisitConcurrentRoots(visitor, arg, only_dirty, clean_dirty); 1105 VisitNonConcurrentRoots(visitor, arg); 1106} 1107 1108mirror::AbstractMethod* Runtime::CreateResolutionMethod() { 1109 mirror::Class* method_class = mirror::AbstractMethod::GetMethodClass(); 1110 Thread* self = Thread::Current(); 1111 SirtRef<mirror::AbstractMethod> 1112 method(self, down_cast<mirror::AbstractMethod*>(method_class->AllocObject(self))); 1113 method->SetDeclaringClass(method_class); 1114 // TODO: use a special method for resolution method saves 1115 method->SetDexMethodIndex(DexFile::kDexNoIndex16); 1116 // When compiling, the code pointer will get set later when the image is loaded. 1117 Runtime* r = Runtime::Current(); 1118 ClassLinker* cl = r->GetClassLinker(); 1119 method->SetEntryPointFromCompiledCode(r->IsCompiler() ? NULL : GetResolutionTrampoline(cl)); 1120 return method.get(); 1121} 1122 1123mirror::AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, 1124 CalleeSaveType type) { 1125 mirror::Class* method_class = mirror::AbstractMethod::GetMethodClass(); 1126 Thread* self = Thread::Current(); 1127 SirtRef<mirror::AbstractMethod> 1128 method(self, down_cast<mirror::AbstractMethod*>(method_class->AllocObject(self))); 1129 method->SetDeclaringClass(method_class); 1130 // TODO: use a special method for callee saves 1131 method->SetDexMethodIndex(DexFile::kDexNoIndex16); 1132 method->SetEntryPointFromCompiledCode(NULL); 1133 if ((instruction_set == kThumb2) || (instruction_set == kArm)) { 1134 uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) | 1135 (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11); 1136 uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3); 1137 uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9); 1138 uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) | 1139 (type == kSaveAll ? all_spills : 0) | (1 << art::arm::LR); 1140 uint32_t fp_all_spills = (1 << art::arm::S0) | (1 << art::arm::S1) | (1 << art::arm::S2) | 1141 (1 << art::arm::S3) | (1 << art::arm::S4) | (1 << art::arm::S5) | 1142 (1 << art::arm::S6) | (1 << art::arm::S7) | (1 << art::arm::S8) | 1143 (1 << art::arm::S9) | (1 << art::arm::S10) | (1 << art::arm::S11) | 1144 (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) | 1145 (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) | 1146 (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) | 1147 (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) | 1148 (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) | 1149 (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) | 1150 (1 << art::arm::S30) | (1 << art::arm::S31); 1151 uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0; 1152 size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ + 1153 __builtin_popcount(fp_spills) /* fprs */ + 1154 1 /* Method* */) * kPointerSize, kStackAlignment); 1155 method->SetFrameSizeInBytes(frame_size); 1156 method->SetCoreSpillMask(core_spills); 1157 method->SetFpSpillMask(fp_spills); 1158 } else if (instruction_set == kMips) { 1159 uint32_t ref_spills = (1 << art::mips::S2) | (1 << art::mips::S3) | (1 << art::mips::S4) | 1160 (1 << art::mips::S5) | (1 << art::mips::S6) | (1 << art::mips::S7) | 1161 (1 << art::mips::GP) | (1 << art::mips::FP); 1162 uint32_t arg_spills = (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3); 1163 uint32_t all_spills = (1 << art::mips::S0) | (1 << art::mips::S1); 1164 uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) | 1165 (type == kSaveAll ? all_spills : 0) | (1 << art::mips::RA); 1166 size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ + 1167 (type == kRefsAndArgs ? 0 : 3) + 1 /* Method* */) * 1168 kPointerSize, kStackAlignment); 1169 method->SetFrameSizeInBytes(frame_size); 1170 method->SetCoreSpillMask(core_spills); 1171 method->SetFpSpillMask(0); 1172 } else if (instruction_set == kX86) { 1173 uint32_t ref_spills = (1 << art::x86::EBP) | (1 << art::x86::ESI) | (1 << art::x86::EDI); 1174 uint32_t arg_spills = (1 << art::x86::ECX) | (1 << art::x86::EDX) | (1 << art::x86::EBX); 1175 uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) | 1176 (1 << art::x86::kNumberOfCpuRegisters); // fake return address callee save 1177 size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ + 1178 1 /* Method* */) * kPointerSize, kStackAlignment); 1179 method->SetFrameSizeInBytes(frame_size); 1180 method->SetCoreSpillMask(core_spills); 1181 method->SetFpSpillMask(0); 1182 } else { 1183 UNIMPLEMENTED(FATAL); 1184 } 1185 return method.get(); 1186} 1187 1188void Runtime::SetCalleeSaveMethod(mirror::AbstractMethod* method, CalleeSaveType type) { 1189 DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType)); 1190 callee_save_methods_[type] = method; 1191} 1192 1193const std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(jobject class_loader) { 1194 if (class_loader == NULL) { 1195 return GetClassLinker()->GetBootClassPath(); 1196 } 1197 CHECK(UseCompileTimeClassPath()); 1198 CompileTimeClassPaths::const_iterator it = compile_time_class_paths_.find(class_loader); 1199 CHECK(it != compile_time_class_paths_.end()); 1200 return it->second; 1201} 1202 1203void Runtime::SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path) { 1204 CHECK(!IsStarted()); 1205 use_compile_time_class_path_ = true; 1206 compile_time_class_paths_.Put(class_loader, class_path); 1207} 1208 1209} // namespace art 1210