diff options
| author | 2016-03-30 14:01:24 +0000 | |
|---|---|---|
| committer | 2016-03-30 14:01:24 +0000 | |
| commit | 0b92b73c62ab4cc13ca040d4233fa69d182971cc (patch) | |
| tree | df7d6180b13430de8f255884b12f29f191d1468e /compiler/oat_writer.cc | |
| parent | 01098af7a530ca65dcf5a40b3799c5147e49bd64 (diff) | |
| parent | 085055f933d76579c32586488951a4497ffcf10e (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.cc | 96 |
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()) { |