summaryrefslogtreecommitdiff
path: root/compiler/driver/compiled_method_storage_test.cc
blob: 0695cb56b31e227f00a8786d9ae4d115cae21a8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

#include "compiled_method_storage.h"
#include "compiled_method.h"
#include "compiler_driver.h"
#include "compiler_options.h"
#include "dex/verification_results.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"

namespace art {

TEST(CompiledMethodStorage, Deduplicate) {
  CompilerOptions compiler_options;
  VerificationResults verification_results(&compiler_options);
  DexFileToMethodInlinerMap method_inliner_map;
  CompilerDriver driver(&compiler_options,
                        &verification_results,
                        &method_inliner_map,
                        Compiler::kOptimizing,
                        /* instruction_set_ */ kNone,
                        /* instruction_set_features */ nullptr,
                        /* boot_image */ false,
                        /* image_classes */ nullptr,
                        /* compiled_classes */ nullptr,
                        /* compiled_methods */ nullptr,
                        /* thread_count */ 1u,
                        /* dump_stats */ false,
                        /* dump_passes */ false,
                        /* timer */ nullptr,
                        /* swap_fd */ -1,
                        /* profile_compilation_info */ nullptr);
  CompiledMethodStorage* storage = driver.GetCompiledMethodStorage();

  ASSERT_TRUE(storage->DedupeEnabled());  // The default.

  const uint8_t raw_code1[] = { 1u, 2u, 3u };
  const uint8_t raw_code2[] = { 4u, 3u, 2u, 1u };
  ArrayRef<const uint8_t> code[] = {
      ArrayRef<const uint8_t>(raw_code1),
      ArrayRef<const uint8_t>(raw_code2),
  };
  const SrcMapElem raw_src_map1[] = { { 1u, 2u }, { 3u, 4u }, { 5u, 6u } };
  const SrcMapElem raw_src_map2[] = { { 8u, 7u }, { 6u, 5u }, { 4u, 3u }, { 2u, 1u } };
  ArrayRef<const SrcMapElem> src_map[] = {
      ArrayRef<const SrcMapElem>(raw_src_map1),
      ArrayRef<const SrcMapElem>(raw_src_map2),
  };
  const uint8_t raw_mapping_table1[] = { 5, 6, 7 };
  const uint8_t raw_mapping_table2[] = { 7, 6, 5, 4 };
  ArrayRef<const uint8_t> mapping_table[] = {
      ArrayRef<const uint8_t>(raw_mapping_table1),
      ArrayRef<const uint8_t>(raw_mapping_table2),
  };
  const uint8_t raw_vmap_table1[] = { 2, 4, 6 };
  const uint8_t raw_vmap_table2[] = { 7, 5, 3, 1 };
  ArrayRef<const uint8_t> vmap_table[] = {
      ArrayRef<const uint8_t>(raw_vmap_table1),
      ArrayRef<const uint8_t>(raw_vmap_table2),
  };
  const uint8_t raw_gc_map1[] = { 9, 8, 7 };
  const uint8_t raw_gc_map2[] = { 6, 7, 8, 9 };
  ArrayRef<const uint8_t> gc_map[] = {
      ArrayRef<const uint8_t>(raw_gc_map1),
      ArrayRef<const uint8_t>(raw_gc_map2),
  };
  const uint8_t raw_cfi_info1[] = { 1, 3, 5 };
  const uint8_t raw_cfi_info2[] = { 8, 6, 4, 2 };
  ArrayRef<const uint8_t> cfi_info[] = {
      ArrayRef<const uint8_t>(raw_cfi_info1),
      ArrayRef<const uint8_t>(raw_cfi_info2),
  };
  const LinkerPatch raw_patches1[] = {
      LinkerPatch::CodePatch(0u, nullptr, 1u),
      LinkerPatch::MethodPatch(4u, nullptr, 1u),
  };
  const LinkerPatch raw_patches2[] = {
      LinkerPatch::CodePatch(0u, nullptr, 1u),
      LinkerPatch::MethodPatch(4u, nullptr, 2u),
  };
  ArrayRef<const LinkerPatch> patches[] = {
      ArrayRef<const LinkerPatch>(raw_patches1),
      ArrayRef<const LinkerPatch>(raw_patches2),
  };

  std::vector<CompiledMethod*> compiled_methods;
  compiled_methods.reserve(1u << 7);
  for (auto&& c : code) {
    for (auto&& s : src_map) {
      for (auto&& m : mapping_table) {
        for (auto&& v : vmap_table) {
          for (auto&& g : gc_map) {
            for (auto&& f : cfi_info) {
              for (auto&& p : patches) {
                compiled_methods.push_back(CompiledMethod::SwapAllocCompiledMethod(
                        &driver, kNone, c, 0u, 0u, 0u, s, m, v, g, f, p));
              }
            }
          }
        }
      }
    }
  }
  constexpr size_t code_bit = 1u << 6;
  constexpr size_t src_map_bit = 1u << 5;
  constexpr size_t mapping_table_bit = 1u << 4;
  constexpr size_t vmap_table_bit = 1u << 3;
  constexpr size_t gc_map_bit = 1u << 2;
  constexpr size_t cfi_info_bit = 1u << 1;
  constexpr size_t patches_bit = 1u << 0;
  CHECK_EQ(compiled_methods.size(), 1u << 7);
  for (size_t i = 0; i != compiled_methods.size(); ++i) {
    for (size_t j = 0; j != compiled_methods.size(); ++j) {
      CompiledMethod* lhs = compiled_methods[i];
      CompiledMethod* rhs = compiled_methods[j];
      bool same_code = ((i ^ j) & code_bit) == 0u;
      bool same_src_map = ((i ^ j) & src_map_bit) == 0u;
      bool same_mapping_table = ((i ^ j) & mapping_table_bit) == 0u;
      bool same_vmap_table = ((i ^ j) & vmap_table_bit) == 0u;
      bool same_gc_map = ((i ^ j) & gc_map_bit) == 0u;
      bool same_cfi_info = ((i ^ j) & cfi_info_bit) == 0u;
      bool same_patches = ((i ^ j) & patches_bit) == 0u;
      ASSERT_EQ(same_code, lhs->GetQuickCode().data() == rhs->GetQuickCode().data())
          << i << " " << j;
      ASSERT_EQ(same_src_map, lhs->GetSrcMappingTable().data() == rhs->GetSrcMappingTable().data())
          << i << " " << j;
      ASSERT_EQ(same_mapping_table, lhs->GetMappingTable().data() == rhs->GetMappingTable().data())
          << i << " " << j;
      ASSERT_EQ(same_vmap_table, lhs->GetVmapTable().data() == rhs->GetVmapTable().data())
          << i << " " << j;
      ASSERT_EQ(same_gc_map, lhs->GetGcMap().data() == rhs->GetGcMap().data())
          << i << " " << j;
      ASSERT_EQ(same_cfi_info, lhs->GetCFIInfo().data() == rhs->GetCFIInfo().data())
          << i << " " << j;
      ASSERT_EQ(same_patches, lhs->GetPatches().data() == rhs->GetPatches().data())
          << i << " " << j;
    }
  }
  for (CompiledMethod* method : compiled_methods) {
    CompiledMethod::ReleaseSwapAllocatedCompiledMethod(&driver, method);
  }
}

}  // namespace art