summaryrefslogtreecommitdiff
path: root/compiler/oat_writer.cc
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2016-03-30 14:01:24 +0000
committer android-build-merger <android-build-merger@google.com> 2016-03-30 14:01:24 +0000
commit0b92b73c62ab4cc13ca040d4233fa69d182971cc (patch)
treedf7d6180b13430de8f255884b12f29f191d1468e /compiler/oat_writer.cc
parent01098af7a530ca65dcf5a40b3799c5147e49bd64 (diff)
parent085055f933d76579c32586488951a4497ffcf10e (diff)
Merge "Optimizing: Improve const-string code generation."
am: 085055f * commit '085055f933d76579c32586488951a4497ffcf10e': Optimizing: Improve const-string code generation. Change-Id: Idd5a215e18abba1e2161f1848cb08aefb4719cf0
Diffstat (limited to 'compiler/oat_writer.cc')
-rw-r--r--compiler/oat_writer.cc96
1 files changed, 71 insertions, 25 deletions
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index c2f19c9d61..a7d574c077 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -1046,6 +1046,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
OatDexMethodVisitor::StartClass(dex_file, class_def_index);
if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) {
dex_cache_ = class_linker_->FindDexCache(Thread::Current(), *dex_file);
+ DCHECK(dex_cache_ != nullptr);
}
return true;
}
@@ -1115,28 +1116,56 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
quick_code = ArrayRef<const uint8_t>(patched_code_);
for (const LinkerPatch& patch : compiled_method->GetPatches()) {
uint32_t literal_offset = patch.LiteralOffset();
- if (patch.Type() == kLinkerPatchCallRelative) {
- // NOTE: Relative calls across oat files are not supported.
- uint32_t target_offset = GetTargetOffset(patch);
- writer_->relative_patcher_->PatchCall(&patched_code_,
- literal_offset,
- offset_ + literal_offset,
- target_offset);
- } else if (patch.Type() == kLinkerPatchDexCacheArray) {
- uint32_t target_offset = GetDexCacheOffset(patch);
- writer_->relative_patcher_->PatchDexCacheReference(&patched_code_,
- patch,
- offset_ + literal_offset,
- target_offset);
- } else if (patch.Type() == kLinkerPatchCall) {
- uint32_t target_offset = GetTargetOffset(patch);
- PatchCodeAddress(&patched_code_, literal_offset, target_offset);
- } else if (patch.Type() == kLinkerPatchMethod) {
- ArtMethod* method = GetTargetMethod(patch);
- PatchMethodAddress(&patched_code_, literal_offset, method);
- } else if (patch.Type() == kLinkerPatchType) {
- mirror::Class* type = GetTargetType(patch);
- PatchObjectAddress(&patched_code_, literal_offset, type);
+ switch (patch.Type()) {
+ case kLinkerPatchCallRelative: {
+ // NOTE: Relative calls across oat files are not supported.
+ uint32_t target_offset = GetTargetOffset(patch);
+ writer_->relative_patcher_->PatchCall(&patched_code_,
+ literal_offset,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
+ case kLinkerPatchDexCacheArray: {
+ uint32_t target_offset = GetDexCacheOffset(patch);
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
+ case kLinkerPatchStringRelative: {
+ uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch));
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
+ case kLinkerPatchCall: {
+ uint32_t target_offset = GetTargetOffset(patch);
+ PatchCodeAddress(&patched_code_, literal_offset, target_offset);
+ break;
+ }
+ case kLinkerPatchMethod: {
+ ArtMethod* method = GetTargetMethod(patch);
+ PatchMethodAddress(&patched_code_, literal_offset, method);
+ break;
+ }
+ case kLinkerPatchString: {
+ mirror::String* string = GetTargetString(patch);
+ PatchObjectAddress(&patched_code_, literal_offset, string);
+ break;
+ }
+ case kLinkerPatchType: {
+ mirror::Class* type = GetTargetType(patch);
+ PatchObjectAddress(&patched_code_, literal_offset, type);
+ break;
+ }
+ default: {
+ DCHECK_EQ(patch.Type(), kLinkerPatchRecordPosition);
+ break;
+ }
}
}
}
@@ -1205,15 +1234,23 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
return target_offset;
}
- mirror::Class* GetTargetType(const LinkerPatch& patch)
- SHARED_REQUIRES(Locks::mutator_lock_) {
+ mirror::Class* GetTargetType(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) {
mirror::DexCache* dex_cache = (dex_file_ == patch.TargetTypeDexFile())
- ? dex_cache_ : class_linker_->FindDexCache(Thread::Current(), *patch.TargetTypeDexFile());
+ ? dex_cache_
+ : class_linker_->FindDexCache(Thread::Current(), *patch.TargetTypeDexFile());
mirror::Class* type = dex_cache->GetResolvedType(patch.TargetTypeIndex());
CHECK(type != nullptr);
return type;
}
+ mirror::String* GetTargetString(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) {
+ mirror::String* string = dex_cache_->GetResolvedString(patch.TargetStringIndex());
+ DCHECK(string != nullptr);
+ DCHECK(writer_->HasBootImage() ||
+ Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(string));
+ return string;
+ }
+
uint32_t GetDexCacheOffset(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) {
if (writer_->HasBootImage()) {
uintptr_t element = writer_->image_writer_->GetDexCacheArrayElementImageAddress<uintptr_t>(
@@ -1227,6 +1264,15 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
}
}
+ uint32_t GetTargetObjectOffset(mirror::Object* object) SHARED_REQUIRES(Locks::mutator_lock_) {
+ DCHECK(writer_->HasBootImage());
+ object = writer_->image_writer_->GetImageAddress(object);
+ size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_);
+ uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index);
+ // TODO: Clean up offset types. The target offset must be treated as signed.
+ return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object) - oat_data_begin);
+ }
+
void PatchObjectAddress(std::vector<uint8_t>* code, uint32_t offset, mirror::Object* object)
SHARED_REQUIRES(Locks::mutator_lock_) {
if (writer_->HasBootImage()) {