~Dex2Oat() {
delete runtime_;
- LogCompletionTime();
}
- void LogCompletionTime() {
+ void LogCompletionTime(const CompilerDriver* compiler) {
LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_)
- << " (threads: " << thread_count_ << ")";
+ << " (threads: " << thread_count_ << ") " << compiler->GetMemoryUsageString();
}
t2.NewTiming("Writing ELF");
if (!driver->WriteElf(android_root, is_host, dex_files, &oat_writer, oat_file)) {
LOG(ERROR) << "Failed to write ELF file " << oat_file->GetPath();
+ oat_file->Erase();
return nullptr;
}
std::string error_msg;
if (!PatchOatCode(driver.get(), oat_file, oat_location, &error_msg)) {
LOG(ERROR) << "Failed to fixup ELF file " << oat_file->GetPath() << ": " << error_msg;
+ oat_file->Erase();
return nullptr;
}
}
// during development when fatal aborts lead to a cascade of failures
// that result in a deadlock.
class WatchDog {
-// WatchDog defines its own CHECK_PTHREAD_CALL to avoid using Log which uses locks
+// WatchDog defines its own CHECK_PTHREAD_CALL to avoid using LOG which uses locks
#undef CHECK_PTHREAD_CALL
#define CHECK_WATCH_DOG_PTHREAD_CALL(call, args, what) \
do { \
message.c_str());
}
- static void Warn(const std::string& message) {
- Message('W', message);
- }
-
static void Fatal(const std::string& message) {
Message('F', message);
exit(1);
}
void Wait() {
- bool warning = true;
- CHECK_GT(kWatchDogTimeoutSeconds, kWatchDogWarningSeconds);
// TODO: tune the multiplier for GC verification, the following is just to make the timeout
// large.
int64_t multiplier = kVerifyObjectSupport > kVerifyObjectModeFast ? 100 : 1;
- timespec warning_ts;
- InitTimeSpec(true, CLOCK_REALTIME, multiplier * kWatchDogWarningSeconds * 1000, 0, &warning_ts);
timespec timeout_ts;
InitTimeSpec(true, CLOCK_REALTIME, multiplier * kWatchDogTimeoutSeconds * 1000, 0, &timeout_ts);
const char* reason = "dex2oat watch dog thread waiting";
CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&mutex_), reason);
while (!shutting_down_) {
- int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &mutex_,
- warning ? &warning_ts
- : &timeout_ts));
+ int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &mutex_, &timeout_ts));
if (rc == ETIMEDOUT) {
- std::string message(StringPrintf("dex2oat did not finish after %d seconds",
- warning ? kWatchDogWarningSeconds
- : kWatchDogTimeoutSeconds));
- if (warning) {
- Warn(message.c_str());
- warning = false;
- } else {
- Fatal(message.c_str());
- }
+ Fatal(StringPrintf("dex2oat did not finish after %d seconds", kWatchDogTimeoutSeconds));
} else if (rc != 0) {
std::string message(StringPrintf("pthread_cond_timedwait failed: %s",
strerror(errno)));
// Debug builds are slower so they have larger timeouts.
static const unsigned int kSlowdownFactor = kIsDebugBuild ? 5U : 1U;
#if ART_USE_PORTABLE_COMPILER
- // 2 minutes scaled by kSlowdownFactor.
- static const unsigned int kWatchDogWarningSeconds = kSlowdownFactor * 2 * 60;
// 30 minutes scaled by kSlowdownFactor.
static const unsigned int kWatchDogTimeoutSeconds = kSlowdownFactor * 30 * 60;
#else
- // 1 minutes scaled by kSlowdownFactor.
- static const unsigned int kWatchDogWarningSeconds = kSlowdownFactor * 1 * 60;
// 6 minutes scaled by kSlowdownFactor.
static const unsigned int kWatchDogTimeoutSeconds = kSlowdownFactor * 6 * 60;
#endif
pthread_attr_t attr_;
pthread_t pthread_;
};
-const unsigned int WatchDog::kWatchDogWarningSeconds;
const unsigned int WatchDog::kWatchDogTimeoutSeconds;
// Given a set of instruction features from the build, parse it. The
}
if (create_file && fchmod(oat_file->Fd(), 0644) != 0) {
PLOG(ERROR) << "Failed to make oat file world readable: " << oat_location;
+ oat_file->Erase();
return EXIT_FAILURE;
}
size_t failure_count = OpenDexFiles(dex_filenames, dex_locations, boot_class_path);
if (failure_count > 0) {
LOG(ERROR) << "Failed to open some dex files: " << failure_count;
+ oat_file->Erase();
return EXIT_FAILURE;
}
runtime_options.push_back(std::make_pair("bootclasspath", &boot_class_path));
thread_count)) {
LOG(ERROR) << "Failed to create dex2oat";
timings.EndTiming();
+ oat_file->Erase();
return EXIT_FAILURE;
}
std::unique_ptr<Dex2Oat> dex2oat(p_dex2oat);
LOG(ERROR) << "Failed to create list of image classes from '" << image_classes_filename <<
"': " << error_msg;
timings.EndTiming();
+ oat_file->Erase();
return EXIT_FAILURE;
}
} else if (image) {
LOG(ERROR) << "Failed to create list of compiled classes from '" << compiled_classes_filename
<< "': " << error_msg;
timings.EndTiming();
+ oat_file->Erase();
return EXIT_FAILURE;
}
} else if (image) {
LOG(ERROR) << "Failed to open zip from file descriptor for '" << zip_location << "': "
<< error_msg;
timings.EndTiming();
+ oat_file->Erase();
return EXIT_FAILURE;
}
if (!DexFile::OpenFromZip(*zip_archive.get(), zip_location, &error_msg, &dex_files)) {
LOG(ERROR) << "Failed to open dex from file descriptor for zip file '" << zip_location
<< "': " << error_msg;
timings.EndTiming();
+ oat_file->Erase();
return EXIT_FAILURE;
}
ATRACE_END();
if (failure_count > 0) {
LOG(ERROR) << "Failed to open some dex files: " << failure_count;
timings.EndTiming();
+ oat_file->Erase();
return EXIT_FAILURE;
}
}
LOG(INFO) << Dumpable<CumulativeLogger>(compiler_phases_timings);
}
+ dex2oat->LogCompletionTime(compiler.get());
// Everything was successfully written, do an explicit exit here to avoid running Runtime
// destructors that take time (bug 10645725) unless we're a debug build or running on valgrind.
if (!kIsDebugBuild && (RUNNING_ON_VALGRIND == 0)) {
- dex2oat->LogCompletionTime();
exit(EXIT_SUCCESS);
}