1b4536b7de576b20c74c612406c5d3132998075efVladimir Marko/* 2b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * Copyright (C) 2015 The Android Open Source Project 3b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * 4b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 5b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * you may not use this file except in compliance with the License. 6b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * You may obtain a copy of the License at 7b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * 8b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 9b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * 10b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * Unless required by applicable law or agreed to in writing, software 11b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 12b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * See the License for the specific language governing permissions and 14b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * limitations under the License. 15b4536b7de576b20c74c612406c5d3132998075efVladimir Marko */ 16b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 17b4536b7de576b20c74c612406c5d3132998075efVladimir Marko#include "dex_cache_array_fixups_arm.h" 18b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 19b4536b7de576b20c74c612406c5d3132998075efVladimir Marko#include "base/arena_containers.h" 20b4536b7de576b20c74c612406c5d3132998075efVladimir Marko#include "utils/dex_cache_arrays_layout-inl.h" 21b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 22b4536b7de576b20c74c612406c5d3132998075efVladimir Markonamespace art { 23b4536b7de576b20c74c612406c5d3132998075efVladimir Markonamespace arm { 24b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 25b4536b7de576b20c74c612406c5d3132998075efVladimir Marko/** 26b4536b7de576b20c74c612406c5d3132998075efVladimir Marko * Finds instructions that need the dex cache arrays base as an input. 27b4536b7de576b20c74c612406c5d3132998075efVladimir Marko */ 28b4536b7de576b20c74c612406c5d3132998075efVladimir Markoclass DexCacheArrayFixupsVisitor : public HGraphVisitor { 29b4536b7de576b20c74c612406c5d3132998075efVladimir Marko public: 30b4536b7de576b20c74c612406c5d3132998075efVladimir Marko explicit DexCacheArrayFixupsVisitor(HGraph* graph) 31b4536b7de576b20c74c612406c5d3132998075efVladimir Marko : HGraphVisitor(graph), 32b4536b7de576b20c74c612406c5d3132998075efVladimir Marko dex_cache_array_bases_(std::less<const DexFile*>(), 33b4536b7de576b20c74c612406c5d3132998075efVladimir Marko // Attribute memory use to code generator. 34b4536b7de576b20c74c612406c5d3132998075efVladimir Marko graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) {} 35b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 36fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko void MoveBasesIfNeeded() { 37fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko for (const auto& entry : dex_cache_array_bases_) { 38fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko // Bring the base closer to the first use (previously, it was in the 39fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko // entry block) and relieve some pressure on the register allocator 40fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko // while avoiding recalculation of the base in a loop. 41fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko HArmDexCacheArraysBase* base = entry.second; 42fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko base->MoveBeforeFirstUserAndOutOfLoops(); 43fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko } 44fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko } 45fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko 46b4536b7de576b20c74c612406c5d3132998075efVladimir Marko private: 47cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko void VisitLoadString(HLoadString* load_string) OVERRIDE { 48cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // If this is a load with PC-relative access to the dex cache methods array, 49cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // we need to add the dex cache arrays base as the special input. 50cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko if (load_string->GetLoadKind() == HLoadString::LoadKind::kDexCachePcRelative) { 51cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // Initialize base for target dex file if needed. 52cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko const DexFile& dex_file = load_string->GetDexFile(); 53cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko HArmDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(dex_file); 54cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // Update the element offset in base. 55cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko DexCacheArraysLayout layout(kArmPointerSize, &dex_file); 56cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko base->UpdateElementOffset(layout.StringOffset(load_string->GetStringIndex())); 57cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // Add the special argument base to the load. 58cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko load_string->AddSpecialInput(base); 59cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko } 60cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko } 61cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko 62b4536b7de576b20c74c612406c5d3132998075efVladimir Marko void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE { 63b4536b7de576b20c74c612406c5d3132998075efVladimir Marko // If this is an invoke with PC-relative access to the dex cache methods array, 64b4536b7de576b20c74c612406c5d3132998075efVladimir Marko // we need to add the dex cache arrays base as the special input. 65b4536b7de576b20c74c612406c5d3132998075efVladimir Marko if (invoke->HasPcRelativeDexCache()) { 66b4536b7de576b20c74c612406c5d3132998075efVladimir Marko // Initialize base for target method dex file if needed. 67b4536b7de576b20c74c612406c5d3132998075efVladimir Marko MethodReference target_method = invoke->GetTargetMethod(); 68fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko HArmDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(*target_method.dex_file); 69b4536b7de576b20c74c612406c5d3132998075efVladimir Marko // Update the element offset in base. 70b4536b7de576b20c74c612406c5d3132998075efVladimir Marko DexCacheArraysLayout layout(kArmPointerSize, target_method.dex_file); 71b4536b7de576b20c74c612406c5d3132998075efVladimir Marko base->UpdateElementOffset(layout.MethodOffset(target_method.dex_method_index)); 72b4536b7de576b20c74c612406c5d3132998075efVladimir Marko // Add the special argument base to the method. 73b4536b7de576b20c74c612406c5d3132998075efVladimir Marko DCHECK(!invoke->HasCurrentMethodInput()); 74b4536b7de576b20c74c612406c5d3132998075efVladimir Marko invoke->AddSpecialInput(base); 75b4536b7de576b20c74c612406c5d3132998075efVladimir Marko } 76b4536b7de576b20c74c612406c5d3132998075efVladimir Marko } 77b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 78fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko HArmDexCacheArraysBase* GetOrCreateDexCacheArrayBase(const DexFile& dex_file) { 79b4536b7de576b20c74c612406c5d3132998075efVladimir Marko // Ensure we only initialize the pointer once for each dex file. 80b4536b7de576b20c74c612406c5d3132998075efVladimir Marko auto lb = dex_cache_array_bases_.lower_bound(&dex_file); 81b4536b7de576b20c74c612406c5d3132998075efVladimir Marko if (lb != dex_cache_array_bases_.end() && 82b4536b7de576b20c74c612406c5d3132998075efVladimir Marko !dex_cache_array_bases_.key_comp()(&dex_file, lb->first)) { 83b4536b7de576b20c74c612406c5d3132998075efVladimir Marko return lb->second; 84b4536b7de576b20c74c612406c5d3132998075efVladimir Marko } 85b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 86fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko // Insert the base at the start of the entry block, move it to a better 87fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko // position later in MoveBaseIfNeeded(). 88fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko HArmDexCacheArraysBase* base = new (GetGraph()->GetArena()) HArmDexCacheArraysBase(dex_file); 89fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko HBasicBlock* entry_block = GetGraph()->GetEntryBlock(); 90fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko entry_block->InsertInstructionBefore(base, entry_block->GetFirstInstruction()); 91b4536b7de576b20c74c612406c5d3132998075efVladimir Marko dex_cache_array_bases_.PutBefore(lb, &dex_file, base); 92b4536b7de576b20c74c612406c5d3132998075efVladimir Marko return base; 93b4536b7de576b20c74c612406c5d3132998075efVladimir Marko } 94b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 95b4536b7de576b20c74c612406c5d3132998075efVladimir Marko using DexCacheArraysBaseMap = 96b4536b7de576b20c74c612406c5d3132998075efVladimir Marko ArenaSafeMap<const DexFile*, HArmDexCacheArraysBase*, std::less<const DexFile*>>; 97b4536b7de576b20c74c612406c5d3132998075efVladimir Marko DexCacheArraysBaseMap dex_cache_array_bases_; 98b4536b7de576b20c74c612406c5d3132998075efVladimir Marko}; 99b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 100b4536b7de576b20c74c612406c5d3132998075efVladimir Markovoid DexCacheArrayFixups::Run() { 10115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray if (graph_->HasIrreducibleLoops()) { 10215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray // Do not run this optimization, as irreducible loops do not work with an instruction 10315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray // that can be live-in at the irreducible loop header. 10415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray return; 10515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray } 106b4536b7de576b20c74c612406c5d3132998075efVladimir Marko DexCacheArrayFixupsVisitor visitor(graph_); 107b4536b7de576b20c74c612406c5d3132998075efVladimir Marko visitor.VisitInsertionOrder(); 108fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko visitor.MoveBasesIfNeeded(); 109b4536b7de576b20c74c612406c5d3132998075efVladimir Marko} 110b4536b7de576b20c74c612406c5d3132998075efVladimir Marko 111b4536b7de576b20c74c612406c5d3132998075efVladimir Marko} // namespace arm 112b4536b7de576b20c74c612406c5d3132998075efVladimir Marko} // namespace art 113