dex_cache_array_fixups_arm.cc revision b4536b7de576b20c74c612406c5d3132998075ef
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
36b4536b7de576b20c74c612406c5d3132998075efVladimir Marko private:
37b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
38b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    // If this is an invoke with PC-relative access to the dex cache methods array,
39b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    // we need to add the dex cache arrays base as the special input.
40b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    if (invoke->HasPcRelativeDexCache()) {
41b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      // Initialize base for target method dex file if needed.
42b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      MethodReference target_method = invoke->GetTargetMethod();
43b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      HArmDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(invoke, *target_method.dex_file);
44b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      // Update the element offset in base.
45b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      DexCacheArraysLayout layout(kArmPointerSize, target_method.dex_file);
46b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      base->UpdateElementOffset(layout.MethodOffset(target_method.dex_method_index));
47b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      // Add the special argument base to the method.
48b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      DCHECK(!invoke->HasCurrentMethodInput());
49b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      invoke->AddSpecialInput(base);
50b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    }
51b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  }
52b4536b7de576b20c74c612406c5d3132998075efVladimir Marko
53b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  HArmDexCacheArraysBase* GetOrCreateDexCacheArrayBase(HInstruction* user,
54b4536b7de576b20c74c612406c5d3132998075efVladimir Marko                                                       const DexFile& dex_file) {
55b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    // Ensure we only initialize the pointer once for each dex file.
56b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    auto lb = dex_cache_array_bases_.lower_bound(&dex_file);
57b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    if (lb != dex_cache_array_bases_.end() &&
58b4536b7de576b20c74c612406c5d3132998075efVladimir Marko        !dex_cache_array_bases_.key_comp()(&dex_file, lb->first)) {
59b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      return lb->second;
60b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    }
61b4536b7de576b20c74c612406c5d3132998075efVladimir Marko
62b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    HGraph* graph = GetGraph();
63b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    HBasicBlock* entry = graph->GetEntryBlock();
64b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    HArmDexCacheArraysBase* base = new (graph->GetArena()) HArmDexCacheArraysBase(dex_file);
65b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    HInstruction* insert_pos = (user->GetBlock() == entry) ? user : entry->GetLastInstruction();
66b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    entry->InsertInstructionBefore(base, insert_pos);
67b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    dex_cache_array_bases_.PutBefore(lb, &dex_file, base);
68b4536b7de576b20c74c612406c5d3132998075efVladimir Marko    return base;
69b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  }
70b4536b7de576b20c74c612406c5d3132998075efVladimir Marko
71b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  using DexCacheArraysBaseMap =
72b4536b7de576b20c74c612406c5d3132998075efVladimir Marko      ArenaSafeMap<const DexFile*, HArmDexCacheArraysBase*, std::less<const DexFile*>>;
73b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  DexCacheArraysBaseMap dex_cache_array_bases_;
74b4536b7de576b20c74c612406c5d3132998075efVladimir Marko};
75b4536b7de576b20c74c612406c5d3132998075efVladimir Marko
76b4536b7de576b20c74c612406c5d3132998075efVladimir Markovoid DexCacheArrayFixups::Run() {
77b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  DexCacheArrayFixupsVisitor visitor(graph_);
78b4536b7de576b20c74c612406c5d3132998075efVladimir Marko  visitor.VisitInsertionOrder();
79b4536b7de576b20c74c612406c5d3132998075efVladimir Marko}
80b4536b7de576b20c74c612406c5d3132998075efVladimir Marko
81b4536b7de576b20c74c612406c5d3132998075efVladimir Marko}  // namespace arm
82b4536b7de576b20c74c612406c5d3132998075efVladimir Marko}  // namespace art
83