Add code size to oat files
Change-Id: Ic2519551864dd7090ba98f2fc92318f95f92947f
diff --git a/Android.mk b/Android.mk
index 904a5f1..6eb90bd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -204,6 +204,7 @@
adb shell rm $(DEXPREOPT_BOOT_JAR_DIR)/*.oat
adb shell rm $(DEXPREOPT_BOOT_JAR_DIR)/*.art
adb shell rm system/app/*.oat
+ adb shell rm data/run-test/*.oat
########################################################################
# cpplint target
diff --git a/src/exception_test.cc b/src/exception_test.cc
index eebba9d..120f16a 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -38,8 +38,13 @@
dex_ = &Runtime::Current()->GetClassLinker()->FindDexFile(my_klass_->GetDexCache());
- for (size_t i = 0 ; i < 12; i++) {
- fake_code_.push_back(0x70000000 | i);
+ uint32_t code_size = 12;
+ fake_code_.push_back((code_size >> 24) & 0xFF);
+ fake_code_.push_back((code_size >> 16) & 0xFF);
+ fake_code_.push_back((code_size >> 8) & 0xFF);
+ fake_code_.push_back((code_size >> 0) & 0xFF);
+ for (size_t i = 0 ; i < code_size; i++) {
+ fake_code_.push_back(0x70 | i);
}
fake_mapping_data_.push_back(2); // first element is count of remaining elements
@@ -49,13 +54,13 @@
method_f_ = my_klass_->FindVirtualMethod("f", "()I");
ASSERT_TRUE(method_f_ != NULL);
method_f_->SetFrameSizeInBytes(kStackAlignment);
- method_f_->SetCode(CompiledMethod::CodePointer(&fake_code_[0], kThumb2));
+ method_f_->SetCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
method_f_->SetMappingTable(&fake_mapping_data_[0]);
method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
ASSERT_TRUE(method_g_ != NULL);
method_g_->SetFrameSizeInBytes(kStackAlignment);
- method_g_->SetCode(CompiledMethod::CodePointer(&fake_code_[0], kThumb2));
+ method_g_->SetCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
method_g_->SetMappingTable(&fake_mapping_data_[0]);
}
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 22dc92c..f0c004d 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -82,7 +82,7 @@
return false;
}
CHECK(requested_base == 0 || requested_base == map->Begin())
- << GetLocation() << " " << reinterpret_cast<void*>(map->Begin());
+ << GetLocation() << " " << reinterpret_cast<void*>(map->Begin());
DCHECK_EQ(0, memcmp(&oat_header, map->Begin(), sizeof(OatHeader))) << GetLocation();
off_t code_offset = oat_header.GetExecutableOffset();
diff --git a/src/oat_file.h b/src/oat_file.h
index 831934a..9fcba2f 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -90,6 +90,15 @@
const void* GetCode() const {
return GetOatPointer<const void*>(code_offset_);
}
+ uint32_t GetCodeSize() const {
+ uintptr_t code = reinterpret_cast<uint32_t>(GetCode());
+ if (code == 0) {
+ return 0;
+ }
+ // TODO: make this Thumb2 specific
+ code &= ~0x1;
+ return reinterpret_cast<uint32_t*>(code)[-1];
+ }
const uint32_t* GetMappingTable() const {
return GetOatPointer<const uint32_t*>(mapping_table_offset_);
}
@@ -102,6 +111,13 @@
const Method::InvokeStub* GetInvokeStub() const {
return GetOatPointer<const Method::InvokeStub*>(invoke_stub_offset_);
}
+ uint32_t GetInvokeStubSize() const {
+ uintptr_t code = reinterpret_cast<uint32_t>(GetInvokeStub());
+ if (code == 0) {
+ return 0;
+ }
+ return reinterpret_cast<uint32_t*>(code)[-1];
+ }
~OatMethod();
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index dcdff9a..1ac247e 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -220,9 +220,10 @@
offset = compiled_method->AlignCode(offset);
DCHECK_ALIGNED(offset, kArmAlignment);
const std::vector<uint8_t>& code = compiled_method->GetCode();
- size_t code_size = code.size() * sizeof(code[0]);
+ uint32_t code_size = code.size() * sizeof(code[0]);
+ CHECK_NE(code_size, 0U);
uint32_t thumb_offset = compiled_method->CodeDelta();
- code_offset = (code_size == 0) ? 0 : offset + thumb_offset;
+ code_offset = offset + sizeof(code_size) + thumb_offset;
// Deduplicate code arrays
std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
@@ -230,10 +231,10 @@
code_offset = code_iter->second;
} else {
code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&code, code_offset));
+ offset += sizeof(code_size); // code size is prepended before code
offset += code_size;
oat_header_->UpdateChecksum(&code[0], code_size);
}
-
frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
core_spill_mask = compiled_method->GetCoreSpillMask();
fp_spill_mask = compiled_method->GetFpSpillMask();
@@ -297,8 +298,9 @@
offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
DCHECK_ALIGNED(offset, kArmAlignment);
const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
- size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
- invoke_stub_offset = (invoke_stub_size == 0) ? 0 : offset;
+ uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
+ CHECK_NE(invoke_stub_size, 0U);
+ invoke_stub_offset = offset + sizeof(invoke_stub_size);
// Deduplicate invoke stubs
std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
@@ -306,6 +308,7 @@
invoke_stub_offset = stub_iter->second;
} else {
code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&invoke_stub, invoke_stub_offset));
+ offset += sizeof(invoke_stub_size); // invoke stub size is prepended before code
offset += invoke_stub_size;
oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
}
@@ -522,19 +525,22 @@
}
DCHECK_ALIGNED(code_offset, kArmAlignment);
const std::vector<uint8_t>& code = compiled_method->GetCode();
- size_t code_size = code.size() * sizeof(code[0]);
+ uint32_t code_size = code.size() * sizeof(code[0]);
+ CHECK_NE(code_size, 0U);
// Deduplicate code arrays
- size_t offset = code_offset + compiled_method->CodeDelta();
+ size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta();
std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
- DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
- || code_iter->second == method_offsets.code_offset_)
- << PrettyMethod(method_idx, dex_file);
+ DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
} else {
- DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
- || offset == method_offsets.code_offset_)
- << PrettyMethod(method_idx, dex_file);
+ DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+ if (!file->WriteFully(&code_size, sizeof(code_size))) {
+ ReportWriteFailure("method code size", method_idx, dex_file, file);
+ return 0;
+ }
+ code_offset += sizeof(code_size);
+ DCHECK_CODE_OFFSET();
if (!file->WriteFully(&code[0], code_size)) {
ReportWriteFailure("method code", method_idx, dex_file, file);
return 0;
@@ -633,20 +639,23 @@
}
DCHECK_ALIGNED(code_offset, kArmAlignment);
const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
- size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
+ uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
+ CHECK_NE(invoke_stub_size, 0U);
// Deduplicate invoke stubs
+ size_t offset = code_offset + sizeof(invoke_stub_size);
std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
code_offsets_.find(&invoke_stub);
- if (stub_iter != code_offsets_.end() &&
- code_offset != method_offsets.invoke_stub_offset_) {
- DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
- || stub_iter->second == method_offsets.invoke_stub_offset_)
- << PrettyMethod(method_idx, dex_file);
+ if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) {
+ DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
} else {
- DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
- || code_offset == method_offsets.invoke_stub_offset_)
- << PrettyMethod(method_idx, dex_file);
+ DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+ if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
+ ReportWriteFailure("invoke stub code size", method_idx, dex_file, file);
+ return 0;
+ }
+ code_offset += sizeof(invoke_stub_size);
+ DCHECK_CODE_OFFSET();
if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
return 0;
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 5574bb7..96af3b0 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -138,6 +138,10 @@
return end_offset - begin_offset;
}
+ InstructionSet GetInstructionSet() {
+ return oat_file_.GetOatHeader().GetInstructionSet();
+ }
+
const void* GetOatCode(Method* m) {
MethodHelper mh(m);
for (size_t i = 0; i < oat_dex_files_.size(); i++) {
@@ -299,9 +303,9 @@
DumpGcMap(os, oat_method.GetGcMap());
os << StringPrintf("\t\tinvoke_stub: %p (offset=0x%08x)\n",
oat_method.GetInvokeStub(), oat_method.GetInvokeStubOffset());
- os << "\t\tCODE:\n";
+ os << "\t\tCODE: (size=" << oat_method.GetCodeSize() << ")\n";
DumpCode(os, oat_method.GetCode(), oat_method.GetMappingTable(), dex_file, code_item);
- os << "\t\tINVOKE STUB:\n";
+ os << "\t\tINVOKE STUB: (size=" << oat_method.GetInvokeStubSize() << ")\n";
DumpCode(os, reinterpret_cast<const void*>(oat_method.GetInvokeStub()), NULL, dex_file, NULL);
}
@@ -620,17 +624,36 @@
bool InDumpSpace(const Object* object) {
return image_space_.Contains(object);
- }
+ }
- const void* GetOatCode(Method* m) {
+ const void* GetOatCodeBegin(Method* m) {
Runtime* runtime = Runtime::Current();
const void* code = m->GetCode();
if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
code = oat_dumper_->GetOatCode(m);
}
+ if (oat_dumper_->GetInstructionSet() == kThumb2) {
+ code = reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) & ~0x1);
+ }
return code;
}
+ uint32_t GetOatCodeSize(Method* m) {
+ const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetOatCodeBegin(m));
+ if (oat_code_begin == NULL) {
+ return 0;
+ }
+ return oat_code_begin[-1];
+ }
+
+ const void* GetOatCodeEnd(Method* m) {
+ const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetOatCodeBegin(m));
+ if (oat_code_begin == NULL) {
+ return NULL;
+ }
+ return oat_code_begin + GetOatCodeSize(m);
+ }
+
static void Callback(Object* obj, void* arg) {
DCHECK(obj != NULL);
DCHECK(arg != NULL);
@@ -712,7 +735,7 @@
if (first_occurrence) {
state->stats_.managed_to_native_code_bytes += invoke_stub_size;
}
- const void* oat_code = state->GetOatCode(method);
+ const void* oat_code = state->GetOatCodeBegin(method);
size_t code_size = state->ComputeOatSize(oat_code, &first_occurrence);
if (first_occurrence) {
state->stats_.native_to_managed_code_bytes += code_size;
@@ -756,16 +779,17 @@
if (first_occurance) {
state->stats_.native_to_managed_code_bytes += invoke_stub_size;
}
- const void* oat_code = state->GetOatCode(method);
- size_t code_size = state->ComputeOatSize(oat_code, &first_occurance);
+ const void* oat_code_begin = state->GetOatCodeBegin(method);
+ const void* oat_code_end = state->GetOatCodeEnd(method);
+ // TODO: use oat_code_size and remove code_size based on offsets
+ // uint32_t oat_code_size = state->GetOatCodeSize(method);
+ size_t code_size = state->ComputeOatSize(oat_code_begin, &first_occurance);
if (first_occurance) {
state->stats_.managed_code_bytes += code_size;
}
state->stats_.managed_code_bytes_ignoring_deduplication += code_size;
- if (oat_code != method->GetCode()) {
- StringAppendF(&summary, "\t\tOAT CODE: %p\n", oat_code);
- }
+ StringAppendF(&summary, "\t\tOAT CODE: %p-%p\n", oat_code_begin, oat_code_end);
StringAppendF(&summary, "\t\tSIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
diff --git a/src/object.h b/src/object.h
index b3a4805..3a7efa2 100644
--- a/src/object.h
+++ b/src/object.h
@@ -633,6 +633,27 @@
SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, code_), code, false);
}
+ uint32_t GetCodeSize() const {
+ DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetCode());
+ if (code == 0) {
+ return 0;
+ }
+ // TODO: make this Thumb2 specific
+ code &= ~0x1;
+ return reinterpret_cast<uint32_t*>(code)[-1];
+ }
+
+ bool IsWithinCode(uintptr_t pc) const {
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetCode());
+ if (code == 0) {
+ return pc == 0;
+ }
+ return (code <= pc && pc < code + GetCodeSize());
+ }
+
+ void AssertPcIsWithinCode(uintptr_t pc) const;
+
uint32_t GetOatCodeOffset() const {
DCHECK(!Runtime::Current()->IsStarted());
return reinterpret_cast<uint32_t>(GetCode());
@@ -781,7 +802,7 @@
}
// Native to managed invocation stub entry point
- InvokeStub* GetInvokeStub() const {
+ const InvokeStub* GetInvokeStub() const {
InvokeStub* result = GetFieldPtr<InvokeStub*>(
OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), false);
// TODO: DCHECK(result != NULL); should be ahead of time compiled
@@ -793,6 +814,14 @@
invoke_stub, false);
}
+ uint32_t GetInvokeStubSize() const {
+ const uint32_t* invoke_stub = reinterpret_cast<const uint32_t*>(GetInvokeStub());
+ if (invoke_stub == NULL) {
+ return 0;
+ }
+ return invoke_stub[-1];
+ }
+
uint32_t GetOatInvokeStubOffset() const {
DCHECK(!Runtime::Current()->IsStarted());
return reinterpret_cast<uint32_t>(GetInvokeStub());
@@ -2303,6 +2332,23 @@
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_dex_index_), false);
}
+inline void Method::AssertPcIsWithinCode(uintptr_t pc) const {
+#ifndef NDEBUG
+ if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) {
+ return;
+ }
+ Runtime* runtime = Runtime::Current();
+ if (GetCode() == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
+ return;
+ }
+ DCHECK(IsWithinCode(pc))
+ << PrettyMethod(this)
+ << " pc=" << std::hex << pc
+ << " code=" << GetCode()
+ << " size=" << GetCodeSize();
+#endif
+}
+
inline String* Class::GetName() const {
return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
}
diff --git a/src/thread.cc b/src/thread.cc
index b511aa7..629cb0f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1205,7 +1205,7 @@
while (frame.GetSP() != NULL) {
for ( ; frame.GetMethod() != NULL; frame.Next()) {
- // DCHECK(frame.GetMethod()->IsWithinCode(pc)); // TODO: restore IsWithinCode
+ frame.GetMethod()->AssertPcIsWithinCode(pc);
bool should_continue = visitor->VisitFrame(frame, pc);
if (!should_continue) {
return;