Separate oat from image
Change-Id: If2abdb99826ead14e3465d90ba2acffd89709389
diff --git a/src/runtime.cc b/src/runtime.cc
index 0dc5229..6cde082 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -10,9 +10,13 @@
#include "UniquePtr.h"
#include "class_linker.h"
#include "heap.h"
+#include "image.h"
#include "intern_table.h"
#include "jni_internal.h"
+#include "oat_file.h"
#include "signal_catcher.h"
+#include "space.h"
+#include "stl_util.h"
#include "thread.h"
#include "thread_list.h"
@@ -32,6 +36,7 @@
signal_catcher_(NULL),
java_vm_(NULL),
jni_stub_array_(NULL),
+ abstract_method_error_stub_array_(NULL),
callee_save_method_(NULL),
started_(false),
vfprintf_(NULL),
@@ -48,6 +53,7 @@
// Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
delete thread_list_;
+ STLDeleteElements(&oat_files_);
delete class_linker_;
Heap::Destroy();
delete intern_table_;
@@ -186,6 +192,7 @@
Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) {
UniquePtr<ParsedOptions> parsed(new ParsedOptions());
parsed->boot_image_ = NULL;
+ parsed->boot_oat_ = NULL;
#ifdef NDEBUG
// -Xcheck:jni is off by default for regular builds...
parsed->check_jni_ = false;
@@ -244,10 +251,15 @@
const StringPiece& value = options[i].first;
parsed->class_path_string_ = value.data();
} else if (option.starts_with("-Xbootimage:")) {
- // TODO: remove when intern_addr_ is removed, just use -Ximage:
+ // TODO: remove and just use -Ximage:
parsed->boot_image_ = option.substr(strlen("-Xbootimage:")).data();
+ } else if (option.starts_with("-Xbootoat:")) {
+ // TODO: remove and just use -Xoat:
+ parsed->boot_oat_ = option.substr(strlen("-Xbootoat:")).data();
} else if (option.starts_with("-Ximage:")) {
parsed->images_.push_back(option.substr(strlen("-Ximage:")).data());
+ } else if (option.starts_with("-Xoat:")) {
+ parsed->oats_.push_back(option.substr(strlen("-Xoat:")).data());
} else if (option.starts_with("-Xcheck:jni")) {
parsed->check_jni_ = true;
} else if (option.starts_with("-Xms")) {
@@ -402,7 +414,7 @@
UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
if (options.get() == NULL) {
- LOG(WARNING) << "Failed to parse options";
+ LOG(ERROR) << "Failed to parse options";
return false;
}
verbose_startup_ = options->IsVerbose("startup");
@@ -424,7 +436,7 @@
intern_table_ = new InternTable;
Heap::Init(options->heap_initial_size_, options->heap_maximum_size_,
- options->boot_image_, options->images_);
+ options->boot_image_, options->images_);
BlockSignals();
@@ -439,7 +451,19 @@
class_linker_ = ClassLinker::Create(options->boot_class_path_,
options->class_path_,
intern_table_,
- Heap::GetBootSpace());
+ Heap::GetBootSpace() != NULL);
+ if (Heap::GetBootSpace() != NULL) {
+ if (!OpenOat(Heap::GetBootSpace(), options->boot_oat_)) {
+ LOG(ERROR) << "Failed to open boot oat " << options->boot_oat_;
+ return false;
+ }
+ }
+ for (size_t i = 0; i < options->oats_.size(); i++) {
+ if (!OpenOat(Heap::GetSpaces()[i+1], options->oats_[i])) {
+ LOG(ERROR) << "Failed to open oat " << options->oats_[i];
+ return false;
+ }
+ }
if (IsVerboseStartup()) {
LOG(INFO) << "Runtime::Init exiting";
@@ -447,6 +471,49 @@
return true;
}
+bool Runtime::OpenOat(const Space* space, const char* oat) {
+ if (IsVerboseStartup()) {
+ LOG(INFO) << "Runtime::OpenOat entering " << oat;
+ }
+ // TODO: check in ParsedOptions?
+ if (space == NULL) {
+ LOG(ERROR) << "oat specified without image";
+ return false;
+ }
+ if (oat == NULL) {
+ LOG(ERROR) << "image specified without oat";
+ return false;
+ }
+ const ImageHeader& image_header = space->GetImageHeader();
+ String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
+ std::string oat_filename = oat_location->ToModifiedUtf8();
+ if (!StringPiece(oat).ends_with(oat_filename)) {
+ LOG(ERROR) << "oat file name " << oat
+ << " does not match value found in image: " << oat_filename;
+ return false;
+ }
+ // TODO: we should be able to just use oat_filename instead of oat
+ // if we passed the prefix argument to find it on the host during cross compilation.
+ OatFile* oat_file = OatFile::Open(std::string(oat), "", image_header.GetOatBaseAddr());
+ if (oat_file == NULL) {
+ LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image";
+ return false;
+ }
+ uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
+ uint32_t image_oat_checksum = image_header.GetOatChecksum();
+ if (oat_checksum != image_oat_checksum) {
+ LOG(ERROR) << "Failed to match oat filechecksum " << std::hex << oat_checksum
+ << " to expected oat checksum " << std::hex << oat_checksum
+ << " in image";
+ return false;
+ }
+ oat_files_.push_back(oat_file);
+ if (IsVerboseStartup()) {
+ LOG(INFO) << "Runtime::OpenOat exiting";
+ }
+ return true;
+}
+
void Runtime::InitNativeMethods() {
if (IsVerboseStartup()) {
LOG(INFO) << "Runtime::InitNativeMethods entering";
@@ -598,13 +665,58 @@
thread_list_->Unregister();
}
+void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
+ class_linker_->VisitRoots(visitor, arg);
+ intern_table_->VisitRoots(visitor, arg);
+ java_vm_->VisitRoots(visitor, arg);
+ thread_list_->VisitRoots(visitor, arg);
+ visitor(jni_stub_array_, arg);
+ visitor(abstract_method_error_stub_array_, arg);
+ visitor(callee_save_method_, arg);
+
+ //(*visitor)(&gDvm.outOfMemoryObj, 0, ROOT_VM_INTERNAL, arg);
+ //(*visitor)(&gDvm.internalErrorObj, 0, ROOT_VM_INTERNAL, arg);
+ //(*visitor)(&gDvm.noClassDefFoundErrorObj, 0, ROOT_VM_INTERNAL, arg);
+ UNIMPLEMENTED(WARNING) << "some roots not marked";
+}
+
+bool Runtime::HasJniStubArray() const {
+ return jni_stub_array_ != NULL;
+}
+
+ByteArray* Runtime::GetJniStubArray() const {
+ CHECK(jni_stub_array_ != NULL);
+ return jni_stub_array_;
+}
+
+void Runtime::SetJniStubArray(ByteArray* jni_stub_array) {
+ CHECK(jni_stub_array != NULL);
+ CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array);
+ jni_stub_array_ = jni_stub_array;
+}
+
+bool Runtime::HasAbstractMethodErrorStubArray() const {
+ return abstract_method_error_stub_array_ != NULL;
+}
+
+ByteArray* Runtime::GetAbstractMethodErrorStubArray() const {
+ CHECK(abstract_method_error_stub_array_ != NULL);
+ return abstract_method_error_stub_array_;
+}
+
+void Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) {
+ CHECK(abstract_method_error_stub_array != NULL);
+ CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array);
+ abstract_method_error_stub_array_ = abstract_method_error_stub_array;
+}
+
Method* Runtime::CreateCalleeSaveMethod(InstructionSet insns) {
Class* method_class = Method::GetMethodClass();
Method* method = down_cast<Method*>(method_class->AllocObject());
method->SetDeclaringClass(method_class);
method->SetName(intern_table_->InternStrong("$$$callee_save_method$$$"));
method->SetSignature(intern_table_->InternStrong("()V"));
- method->SetCode(NULL, insns, NULL);
+ method->SetCodeArray(NULL, insns);
if ((insns == kThumb2) || (insns == kArm)) {
size_t frame_size = (12 /* gprs */ + 32 /* fprs */ + 4 /* data */) * kPointerSize;
method->SetFrameSizeInBytes(frame_size);
@@ -667,18 +779,19 @@
return method;
}
-void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
- class_linker_->VisitRoots(visitor, arg);
- intern_table_->VisitRoots(visitor, arg);
- java_vm_->VisitRoots(visitor, arg);
- thread_list_->VisitRoots(visitor, arg);
- visitor(jni_stub_array_, arg);
- visitor(callee_save_method_, arg);
-
- //(*visitor)(&gDvm.outOfMemoryObj, 0, ROOT_VM_INTERNAL, arg);
- //(*visitor)(&gDvm.internalErrorObj, 0, ROOT_VM_INTERNAL, arg);
- //(*visitor)(&gDvm.noClassDefFoundErrorObj, 0, ROOT_VM_INTERNAL, arg);
- UNIMPLEMENTED(WARNING) << "some roots not marked";
+bool Runtime::HasCalleeSaveMethod() const {
+ return callee_save_method_ != NULL;
}
+// Returns a special method that describes all callee saves being spilled to the stack.
+Method* Runtime::GetCalleeSaveMethod() const {
+ CHECK(callee_save_method_ != NULL);
+ return callee_save_method_;
+}
+
+void Runtime::SetCalleeSaveMethod(Method* method) {
+ callee_save_method_ = method;
+}
+
+
} // namespace art