blob: a842c6e4525b9db6ed3b55c6c56a80849b0c9a8f [file] [log] [blame]
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "stack_map.h"
Mathieu Chartiere5d80f82015-10-15 17:47:48 -070018
Nicolas Geoffray5d37c152017-01-12 13:25:19 +000019#include "art_method.h"
Mathieu Chartiere5d80f82015-10-15 17:47:48 -070020#include "base/arena_bit_vector.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010021#include "stack_map_stream.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010022
23#include "gtest/gtest.h"
24
25namespace art {
26
David Srbecky09ed0982016-02-12 21:58:43 +000027// Check that the stack mask of given stack map is identical
28// to the given bit vector. Returns true if they are same.
29static bool CheckStackMask(
David Srbecky45aa5982016-03-18 02:15:09 +000030 const CodeInfo& code_info,
31 const CodeInfoEncoding& encoding,
David Srbecky09ed0982016-02-12 21:58:43 +000032 const StackMap& stack_map,
David Srbecky09ed0982016-02-12 21:58:43 +000033 const BitVector& bit_vector) {
David Srbecky45aa5982016-03-18 02:15:09 +000034 BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
Mathieu Chartier575d3e62017-02-06 11:00:40 -080035 if (bit_vector.GetNumberOfBits() > encoding.stack_mask.encoding.BitSize()) {
David Srbecky09ed0982016-02-12 21:58:43 +000036 return false;
37 }
Mathieu Chartier575d3e62017-02-06 11:00:40 -080038 for (size_t i = 0; i < encoding.stack_mask.encoding.BitSize(); ++i) {
David Srbecky45aa5982016-03-18 02:15:09 +000039 if (stack_mask.LoadBit(i) != bit_vector.IsBitSet(i)) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010040 return false;
41 }
42 }
43 return true;
44}
45
Roland Levillaina552e1c2015-03-26 15:01:03 +000046using Kind = DexRegisterLocation::Kind;
47
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010048TEST(StackMapTest, Test1) {
49 ArenaPool pool;
50 ArenaAllocator arena(&pool);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -080051 StackMapStream stream(&arena, kRuntimeISA);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010052
53 ArenaBitVector sp_mask(&arena, 0, false);
Roland Levillain12baf472015-03-05 12:41:42 +000054 size_t number_of_dex_registers = 2;
Calin Juravle4f46ac52015-04-23 18:47:21 +010055 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +010056 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
57 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Short location.
Calin Juravle4f46ac52015-04-23 18:47:21 +010058 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010059
Calin Juravle4f46ac52015-04-23 18:47:21 +010060 size_t size = stream.PrepareForFillIn();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010061 void* memory = arena.Alloc(size, kArenaAllocMisc);
62 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -070063 stream.FillInCodeInfo(region);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010064
Nicolas Geoffray39468442014-09-02 15:17:15 +010065 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +000066 CodeInfoEncoding encoding = code_info.ExtractEncoding();
67 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010068
David Srbecky09ed0982016-02-12 21:58:43 +000069 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
70 ASSERT_EQ(2u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +010071 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +000072 // The Dex register location catalog contains:
73 // - one 1-byte short Dex register location, and
74 // - one 5-byte large Dex register location.
75 size_t expected_location_catalog_size = 1u + 5u;
76 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
77
David Brazdilf677ebf2015-05-29 16:29:43 +010078 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
79 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
80 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -080081 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
82 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -080083 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010084
David Srbecky45aa5982016-03-18 02:15:09 +000085 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010086
Mathieu Chartier575d3e62017-02-06 11:00:40 -080087 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +000088 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +010089 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +000090 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
91 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
92 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
93 // The Dex register map contains:
94 // - one 1-byte live bit mask, and
95 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
96 size_t expected_dex_register_map_size = 1u + 1u;
97 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
98
David Brazdilf677ebf2015-05-29 16:29:43 +010099 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
100 0, number_of_dex_registers, code_info, encoding));
101 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
102 1, number_of_dex_registers, code_info, encoding));
103 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
104 0, number_of_dex_registers, code_info, encoding));
105 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
106 1, number_of_dex_registers, code_info, encoding));
107 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
108 0, number_of_dex_registers, code_info, encoding));
109 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000110
111 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000112 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000113 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000114 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000115 ASSERT_EQ(0u, index0);
116 ASSERT_EQ(1u, index1);
117 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
118 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
119 ASSERT_EQ(Kind::kInStack, location0.GetKind());
120 ASSERT_EQ(Kind::kConstant, location1.GetKind());
121 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
122 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000123 ASSERT_EQ(0, location0.GetValue());
124 ASSERT_EQ(-2, location1.GetValue());
Roland Levillain12baf472015-03-05 12:41:42 +0000125
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800126 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100127}
128
129TEST(StackMapTest, Test2) {
130 ArenaPool pool;
131 ArenaAllocator arena(&pool);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800132 StackMapStream stream(&arena, kRuntimeISA);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000133 ArtMethod art_method;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100134
135 ArenaBitVector sp_mask1(&arena, 0, true);
136 sp_mask1.SetBit(2);
137 sp_mask1.SetBit(4);
Roland Levillain12baf472015-03-05 12:41:42 +0000138 size_t number_of_dex_registers = 2;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100139 size_t number_of_dex_registers_in_inline_info = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100140 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100141 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
142 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000143 stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100144 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000145 stream.BeginInlineInfoEntry(&art_method, 2, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100146 stream.EndInlineInfoEntry();
Calin Juravle4f46ac52015-04-23 18:47:21 +0100147 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100148
149 ArenaBitVector sp_mask2(&arena, 0, true);
150 sp_mask2.SetBit(3);
David Brazdilf10a25f2015-06-02 14:29:52 +0100151 sp_mask2.SetBit(8);
Calin Juravle4f46ac52015-04-23 18:47:21 +0100152 stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100153 stream.AddDexRegisterEntry(Kind::kInRegister, 18); // Short location.
154 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100155 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100156
David Brazdild9cb68e2015-08-25 13:52:43 +0100157 ArenaBitVector sp_mask3(&arena, 0, true);
158 sp_mask3.SetBit(1);
159 sp_mask3.SetBit(5);
160 stream.BeginStackMapEntry(2, 192, 0xAB, &sp_mask3, number_of_dex_registers, 0);
161 stream.AddDexRegisterEntry(Kind::kInRegister, 6); // Short location.
162 stream.AddDexRegisterEntry(Kind::kInRegisterHigh, 8); // Short location.
163 stream.EndStackMapEntry();
164
165 ArenaBitVector sp_mask4(&arena, 0, true);
166 sp_mask4.SetBit(6);
167 sp_mask4.SetBit(7);
168 stream.BeginStackMapEntry(3, 256, 0xCD, &sp_mask4, number_of_dex_registers, 0);
169 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location, same in stack map 2.
170 stream.AddDexRegisterEntry(Kind::kInFpuRegisterHigh, 1); // Short location.
171 stream.EndStackMapEntry();
172
Calin Juravle4f46ac52015-04-23 18:47:21 +0100173 size_t size = stream.PrepareForFillIn();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100174 void* memory = arena.Alloc(size, kArenaAllocMisc);
175 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700176 stream.FillInCodeInfo(region);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100177
Nicolas Geoffray39468442014-09-02 15:17:15 +0100178 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000179 CodeInfoEncoding encoding = code_info.ExtractEncoding();
180 ASSERT_EQ(4u, code_info.GetNumberOfStackMaps(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100181
David Srbecky09ed0982016-02-12 21:58:43 +0000182 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
183 ASSERT_EQ(7u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100184 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000185 // The Dex register location catalog contains:
David Brazdild9cb68e2015-08-25 13:52:43 +0100186 // - six 1-byte short Dex register locations, and
Roland Levillaina552e1c2015-03-26 15:01:03 +0000187 // - one 5-byte large Dex register location.
David Brazdild9cb68e2015-08-25 13:52:43 +0100188 size_t expected_location_catalog_size = 6u * 1u + 5u;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000189 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
190
Roland Levillain12baf472015-03-05 12:41:42 +0000191 // First stack map.
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000192 {
David Brazdilf677ebf2015-05-29 16:29:43 +0100193 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
194 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
195 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800196 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
197 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800198 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100199
David Srbecky45aa5982016-03-18 02:15:09 +0000200 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100201
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800202 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000203 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100204 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000205 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
206 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
207 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
208 // The Dex register map contains:
209 // - one 1-byte live bit mask, and
210 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
211 size_t expected_dex_register_map_size = 1u + 1u;
212 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
213
David Brazdilf677ebf2015-05-29 16:29:43 +0100214 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
215 0, number_of_dex_registers, code_info, encoding));
216 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
217 1, number_of_dex_registers, code_info, encoding));
218 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
219 0, number_of_dex_registers, code_info, encoding));
220 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
221 1, number_of_dex_registers, code_info, encoding));
222 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
223 0, number_of_dex_registers, code_info, encoding));
224 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000225
226 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000227 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000228 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000229 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000230 ASSERT_EQ(0u, index0);
231 ASSERT_EQ(1u, index1);
232 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
233 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
234 ASSERT_EQ(Kind::kInStack, location0.GetKind());
235 ASSERT_EQ(Kind::kConstant, location1.GetKind());
236 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
237 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000238 ASSERT_EQ(0, location0.GetValue());
239 ASSERT_EQ(-2, location1.GetValue());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100240
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800241 ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
David Brazdilf677ebf2015-05-29 16:29:43 +0100242 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800243 ASSERT_EQ(2u, inline_info.GetDepth(encoding.inline_info.encoding));
244 ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
245 ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
246 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
247 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000248 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100249
Roland Levillain12baf472015-03-05 12:41:42 +0000250 // Second stack map.
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000251 {
David Brazdilf677ebf2015-05-29 16:29:43 +0100252 StackMap stack_map = code_info.GetStackMapAt(1, encoding);
253 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u, encoding)));
254 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800255 ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map.encoding));
256 ASSERT_EQ(128u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800257 ASSERT_EQ(0xFFu, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100258
David Srbecky45aa5982016-03-18 02:15:09 +0000259 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask2));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100260
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800261 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000262 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100263 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000264 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
265 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
266 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
267 // The Dex register map contains:
268 // - one 1-byte live bit mask, and
269 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
270 size_t expected_dex_register_map_size = 1u + 1u;
271 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
272
David Brazdilf677ebf2015-05-29 16:29:43 +0100273 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
274 0, number_of_dex_registers, code_info, encoding));
275 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
276 1, number_of_dex_registers, code_info, encoding));
277 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
278 0, number_of_dex_registers, code_info, encoding));
279 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
280 1, number_of_dex_registers, code_info, encoding));
281 ASSERT_EQ(18, dex_register_map.GetMachineRegister(
282 0, number_of_dex_registers, code_info, encoding));
283 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
284 1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000285
286 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000287 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000288 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000289 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000290 ASSERT_EQ(2u, index0);
291 ASSERT_EQ(3u, index1);
292 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
293 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
294 ASSERT_EQ(Kind::kInRegister, location0.GetKind());
295 ASSERT_EQ(Kind::kInFpuRegister, location1.GetKind());
296 ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
297 ASSERT_EQ(Kind::kInFpuRegister, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000298 ASSERT_EQ(18, location0.GetValue());
299 ASSERT_EQ(3, location1.GetValue());
Roland Levillain12baf472015-03-05 12:41:42 +0000300
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800301 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000302 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100303
304 // Third stack map.
305 {
306 StackMap stack_map = code_info.GetStackMapAt(2, encoding);
307 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u, encoding)));
308 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800309 ASSERT_EQ(2u, stack_map.GetDexPc(encoding.stack_map.encoding));
310 ASSERT_EQ(192u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800311 ASSERT_EQ(0xABu, code_info.GetRegisterMaskOf(encoding, stack_map));
David Brazdild9cb68e2015-08-25 13:52:43 +0100312
David Srbecky45aa5982016-03-18 02:15:09 +0000313 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask3));
David Brazdild9cb68e2015-08-25 13:52:43 +0100314
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800315 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100316 DexRegisterMap dex_register_map =
317 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
318 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
319 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
320 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
321 // The Dex register map contains:
322 // - one 1-byte live bit mask, and
323 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
324 size_t expected_dex_register_map_size = 1u + 1u;
325 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
326
327 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
328 0, number_of_dex_registers, code_info, encoding));
329 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(
330 1, number_of_dex_registers, code_info, encoding));
331 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
332 0, number_of_dex_registers, code_info, encoding));
333 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationInternalKind(
334 1, number_of_dex_registers, code_info, encoding));
335 ASSERT_EQ(6, dex_register_map.GetMachineRegister(
336 0, number_of_dex_registers, code_info, encoding));
337 ASSERT_EQ(8, dex_register_map.GetMachineRegister(
338 1, number_of_dex_registers, code_info, encoding));
339
340 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000341 0, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100342 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000343 1, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100344 ASSERT_EQ(4u, index0);
345 ASSERT_EQ(5u, index1);
346 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
347 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
348 ASSERT_EQ(Kind::kInRegister, location0.GetKind());
349 ASSERT_EQ(Kind::kInRegisterHigh, location1.GetKind());
350 ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
351 ASSERT_EQ(Kind::kInRegisterHigh, location1.GetInternalKind());
352 ASSERT_EQ(6, location0.GetValue());
353 ASSERT_EQ(8, location1.GetValue());
354
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800355 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100356 }
357
358 // Fourth stack map.
359 {
360 StackMap stack_map = code_info.GetStackMapAt(3, encoding);
361 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u, encoding)));
362 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800363 ASSERT_EQ(3u, stack_map.GetDexPc(encoding.stack_map.encoding));
364 ASSERT_EQ(256u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800365 ASSERT_EQ(0xCDu, code_info.GetRegisterMaskOf(encoding, stack_map));
David Brazdild9cb68e2015-08-25 13:52:43 +0100366
David Srbecky45aa5982016-03-18 02:15:09 +0000367 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask4));
David Brazdild9cb68e2015-08-25 13:52:43 +0100368
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800369 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100370 DexRegisterMap dex_register_map =
371 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
372 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
373 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
374 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
375 // The Dex register map contains:
376 // - one 1-byte live bit mask, and
377 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
378 size_t expected_dex_register_map_size = 1u + 1u;
379 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
380
381 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
382 0, number_of_dex_registers, code_info, encoding));
383 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(
384 1, number_of_dex_registers, code_info, encoding));
385 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
386 0, number_of_dex_registers, code_info, encoding));
387 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationInternalKind(
388 1, number_of_dex_registers, code_info, encoding));
389 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
390 0, number_of_dex_registers, code_info, encoding));
391 ASSERT_EQ(1, dex_register_map.GetMachineRegister(
392 1, number_of_dex_registers, code_info, encoding));
393
394 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000395 0, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100396 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000397 1, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100398 ASSERT_EQ(3u, index0); // Shared with second stack map.
399 ASSERT_EQ(6u, index1);
400 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
401 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
402 ASSERT_EQ(Kind::kInFpuRegister, location0.GetKind());
403 ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetKind());
404 ASSERT_EQ(Kind::kInFpuRegister, location0.GetInternalKind());
405 ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetInternalKind());
406 ASSERT_EQ(3, location0.GetValue());
407 ASSERT_EQ(1, location1.GetValue());
408
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800409 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100410 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100411}
412
Mathieu Chartier32289082017-02-09 15:57:37 -0800413TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
414 ArenaPool pool;
415 ArenaAllocator arena(&pool);
416 StackMapStream stream(&arena, kRuntimeISA);
417 ArtMethod art_method;
418
419 ArenaBitVector sp_mask1(&arena, 0, true);
420 sp_mask1.SetBit(2);
421 sp_mask1.SetBit(4);
422 const size_t number_of_dex_registers = 2;
423 const size_t number_of_dex_registers_in_inline_info = 2;
424 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 1);
425 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
426 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
427 stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
428 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
429 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
430 stream.EndInlineInfoEntry();
431 stream.EndStackMapEntry();
432
433 size_t size = stream.PrepareForFillIn();
434 void* memory = arena.Alloc(size, kArenaAllocMisc);
435 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700436 stream.FillInCodeInfo(region);
Mathieu Chartier32289082017-02-09 15:57:37 -0800437
438 CodeInfo code_info(region);
439 CodeInfoEncoding encoding = code_info.ExtractEncoding();
440 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
441
442 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
443 ASSERT_EQ(2u, number_of_catalog_entries);
444 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
445 // The Dex register location catalog contains:
446 // - one 1-byte short Dex register locations, and
447 // - one 5-byte large Dex register location.
448 const size_t expected_location_catalog_size = 1u + 5u;
449 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
450
451 // First stack map.
452 {
453 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
454 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
455 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
456 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
457 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
458 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
459
460 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
461
462 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
463 DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers));
464 ASSERT_TRUE(map.IsDexRegisterLive(0));
465 ASSERT_TRUE(map.IsDexRegisterLive(1));
466 ASSERT_EQ(2u, map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
467 // The Dex register map contains:
468 // - one 1-byte live bit mask, and
469 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
470 size_t expected_map_size = 1u + 1u;
471 ASSERT_EQ(expected_map_size, map.Size());
472
473 ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0, number_of_dex_registers, code_info, encoding));
474 ASSERT_EQ(Kind::kConstant,
475 map.GetLocationKind(1, number_of_dex_registers, code_info, encoding));
476 ASSERT_EQ(Kind::kInStack,
477 map.GetLocationInternalKind(0, number_of_dex_registers, code_info, encoding));
478 ASSERT_EQ(Kind::kConstantLargeValue,
479 map.GetLocationInternalKind(1, number_of_dex_registers, code_info, encoding));
480 ASSERT_EQ(0, map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info, encoding));
481 ASSERT_EQ(-2, map.GetConstant(1, number_of_dex_registers, code_info, encoding));
482
483 const size_t index0 =
484 map.GetLocationCatalogEntryIndex(0, number_of_dex_registers, number_of_catalog_entries);
485 const size_t index1 =
486 map.GetLocationCatalogEntryIndex(1, number_of_dex_registers, number_of_catalog_entries);
487 ASSERT_EQ(0u, index0);
488 ASSERT_EQ(1u, index1);
489 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
490 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
491 ASSERT_EQ(Kind::kInStack, location0.GetKind());
492 ASSERT_EQ(Kind::kConstant, location1.GetKind());
493 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
494 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
495 ASSERT_EQ(0, location0.GetValue());
496 ASSERT_EQ(-2, location1.GetValue());
497
498 // Test that the inline info dex register map deduplicated to the same offset as the stack map
499 // one.
500 ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
501 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
502 EXPECT_EQ(inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info.encoding, 0),
503 stack_map.GetDexRegisterMapOffset(encoding.stack_map.encoding));
504 }
505}
506
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000507TEST(StackMapTest, TestNonLiveDexRegisters) {
508 ArenaPool pool;
509 ArenaAllocator arena(&pool);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800510 StackMapStream stream(&arena, kRuntimeISA);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000511
512 ArenaBitVector sp_mask(&arena, 0, false);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000513 uint32_t number_of_dex_registers = 2;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100514 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100515 stream.AddDexRegisterEntry(Kind::kNone, 0); // No location.
516 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100517 stream.EndStackMapEntry();
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000518
Calin Juravle4f46ac52015-04-23 18:47:21 +0100519 size_t size = stream.PrepareForFillIn();
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000520 void* memory = arena.Alloc(size, kArenaAllocMisc);
521 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700522 stream.FillInCodeInfo(region);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000523
524 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000525 CodeInfoEncoding encoding = code_info.ExtractEncoding();
526 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000527
David Srbecky09ed0982016-02-12 21:58:43 +0000528 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
529 ASSERT_EQ(1u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100530 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000531 // The Dex register location catalog contains:
532 // - one 5-byte large Dex register location.
533 size_t expected_location_catalog_size = 5u;
534 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
535
David Brazdilf677ebf2015-05-29 16:29:43 +0100536 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
537 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
538 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800539 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
540 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800541 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000542
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800543 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000544 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100545 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000546 ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
547 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
548 ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
549 // The Dex register map contains:
550 // - one 1-byte live bit mask.
551 // No space is allocated for the sole location catalog entry index, as it is useless.
552 size_t expected_dex_register_map_size = 1u + 0u;
553 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
554
David Brazdilf677ebf2015-05-29 16:29:43 +0100555 ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind(
556 0, number_of_dex_registers, code_info, encoding));
557 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
558 1, number_of_dex_registers, code_info, encoding));
559 ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind(
560 0, number_of_dex_registers, code_info, encoding));
561 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
562 1, number_of_dex_registers, code_info, encoding));
563 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000564
565 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000566 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000567 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000568 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000569 ASSERT_EQ(DexRegisterLocationCatalog::kNoLocationEntryIndex, index0);
570 ASSERT_EQ(0u, index1);
571 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
572 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
573 ASSERT_EQ(Kind::kNone, location0.GetKind());
574 ASSERT_EQ(Kind::kConstant, location1.GetKind());
575 ASSERT_EQ(Kind::kNone, location0.GetInternalKind());
576 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
577 ASSERT_EQ(0, location0.GetValue());
578 ASSERT_EQ(-2, location1.GetValue());
579
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800580 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000581}
582
583// Generate a stack map whose dex register offset is
584// StackMap::kNoDexRegisterMapSmallEncoding, and ensure we do
585// not treat it as kNoDexRegisterMap.
586TEST(StackMapTest, DexRegisterMapOffsetOverflow) {
587 ArenaPool pool;
588 ArenaAllocator arena(&pool);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800589 StackMapStream stream(&arena, kRuntimeISA);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000590
591 ArenaBitVector sp_mask(&arena, 0, false);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000592 uint32_t number_of_dex_registers = 1024;
593 // Create the first stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100594 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000595 uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
596 for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
597 // Use two different Dex register locations to populate this map,
598 // as using a single value (in the whole CodeInfo object) would
599 // make this Dex register mapping data empty (see
600 // art::DexRegisterMap::SingleEntrySizeInBits).
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100601 stream.AddDexRegisterEntry(Kind::kConstant, i % 2); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000602 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100603 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000604 // Create the second stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100605 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000606 for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100607 stream.AddDexRegisterEntry(Kind::kConstant, 0); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000608 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100609 stream.EndStackMapEntry();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000610
Calin Juravle4f46ac52015-04-23 18:47:21 +0100611 size_t size = stream.PrepareForFillIn();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000612 void* memory = arena.Alloc(size, kArenaAllocMisc);
613 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700614 stream.FillInCodeInfo(region);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000615
616 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000617 CodeInfoEncoding encoding = code_info.ExtractEncoding();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000618 // The location catalog contains two entries (DexRegisterLocation(kConstant, 0)
619 // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index
620 // has a size of 1 bit.
David Srbecky09ed0982016-02-12 21:58:43 +0000621 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
622 ASSERT_EQ(2u, number_of_catalog_entries);
623 ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_catalog_entries));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000624
625 // The first Dex register map contains:
626 // - a live register bit mask for 1024 registers (that is, 128 bytes of
627 // data); and
628 // - Dex register mapping information for 1016 1-bit Dex (live) register
629 // locations (that is, 127 bytes of data).
630 // Hence it has a size of 255 bytes, and therefore...
631 ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers));
David Brazdilf677ebf2015-05-29 16:29:43 +0100632 StackMap stack_map0 = code_info.GetStackMapAt(0, encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000633 DexRegisterMap dex_register_map0 =
David Brazdilf677ebf2015-05-29 16:29:43 +0100634 code_info.GetDexRegisterMapOf(stack_map0, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000635 ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
David Srbecky09ed0982016-02-12 21:58:43 +0000636 number_of_catalog_entries));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000637 ASSERT_EQ(255u, dex_register_map0.Size());
638
David Brazdilf677ebf2015-05-29 16:29:43 +0100639 StackMap stack_map1 = code_info.GetStackMapAt(1, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800640 ASSERT_TRUE(stack_map1.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000641 // ...the offset of the second Dex register map (relative to the
642 // beginning of the Dex register maps region) is 255 (i.e.,
643 // kNoDexRegisterMapSmallEncoding).
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800644 ASSERT_NE(stack_map1.GetDexRegisterMapOffset(encoding.stack_map.encoding),
David Srbecky09ed0982016-02-12 21:58:43 +0000645 StackMap::kNoDexRegisterMap);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800646 ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(encoding.stack_map.encoding), 0xFFu);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000647}
648
Calin Juravle6ae70962015-03-18 16:31:28 +0000649TEST(StackMapTest, TestShareDexRegisterMap) {
650 ArenaPool pool;
651 ArenaAllocator arena(&pool);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800652 StackMapStream stream(&arena, kRuntimeISA);
Calin Juravle6ae70962015-03-18 16:31:28 +0000653
654 ArenaBitVector sp_mask(&arena, 0, false);
655 uint32_t number_of_dex_registers = 2;
656 // First stack map.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100657 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100658 stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
659 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100660 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000661 // Second stack map, which should share the same dex register map.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100662 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100663 stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
664 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100665 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000666 // Third stack map (doesn't share the dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100667 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100668 stream.AddDexRegisterEntry(Kind::kInRegister, 2); // Short location.
669 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100670 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000671
Calin Juravle4f46ac52015-04-23 18:47:21 +0100672 size_t size = stream.PrepareForFillIn();
Calin Juravle6ae70962015-03-18 16:31:28 +0000673 void* memory = arena.Alloc(size, kArenaAllocMisc);
674 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700675 stream.FillInCodeInfo(region);
Calin Juravle6ae70962015-03-18 16:31:28 +0000676
677 CodeInfo ci(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000678 CodeInfoEncoding encoding = ci.ExtractEncoding();
David Brazdilf677ebf2015-05-29 16:29:43 +0100679
Calin Juravle6ae70962015-03-18 16:31:28 +0000680 // Verify first stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100681 StackMap sm0 = ci.GetStackMapAt(0, encoding);
682 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, number_of_dex_registers);
683 ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
684 ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000685
686 // Verify second stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100687 StackMap sm1 = ci.GetStackMapAt(1, encoding);
688 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, encoding, number_of_dex_registers);
689 ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
690 ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000691
692 // Verify third stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100693 StackMap sm2 = ci.GetStackMapAt(2, encoding);
694 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, encoding, number_of_dex_registers);
695 ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
696 ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000697
698 // Verify dex register map offsets.
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800699 ASSERT_EQ(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
700 sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding));
701 ASSERT_NE(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
702 sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
703 ASSERT_NE(sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding),
704 sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000705}
706
Roland Levillaina552e1c2015-03-26 15:01:03 +0000707TEST(StackMapTest, TestNoDexRegisterMap) {
708 ArenaPool pool;
709 ArenaAllocator arena(&pool);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800710 StackMapStream stream(&arena, kRuntimeISA);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000711
712 ArenaBitVector sp_mask(&arena, 0, false);
713 uint32_t number_of_dex_registers = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100714 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
715 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000716
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000717 number_of_dex_registers = 1;
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800718 stream.BeginStackMapEntry(1, 68, 0x4, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000719 stream.EndStackMapEntry();
720
Calin Juravle4f46ac52015-04-23 18:47:21 +0100721 size_t size = stream.PrepareForFillIn();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000722 void* memory = arena.Alloc(size, kArenaAllocMisc);
723 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700724 stream.FillInCodeInfo(region);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000725
726 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000727 CodeInfoEncoding encoding = code_info.ExtractEncoding();
728 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000729
David Srbecky09ed0982016-02-12 21:58:43 +0000730 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
731 ASSERT_EQ(0u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100732 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000733 ASSERT_EQ(0u, location_catalog.Size());
734
David Brazdilf677ebf2015-05-29 16:29:43 +0100735 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
736 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
737 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800738 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
739 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800740 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000741
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800742 ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
743 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000744
745 stack_map = code_info.GetStackMapAt(1, encoding);
746 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1, encoding)));
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800747 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800748 ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map.encoding));
749 ASSERT_EQ(68u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800750 ASSERT_EQ(0x4u, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000751
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800752 ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
753 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000754}
755
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100756TEST(StackMapTest, InlineTest) {
757 ArenaPool pool;
758 ArenaAllocator arena(&pool);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800759 StackMapStream stream(&arena, kRuntimeISA);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000760 ArtMethod art_method;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100761
762 ArenaBitVector sp_mask1(&arena, 0, true);
763 sp_mask1.SetBit(2);
764 sp_mask1.SetBit(4);
765
766 // First stack map.
767 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, 2, 2);
768 stream.AddDexRegisterEntry(Kind::kInStack, 0);
769 stream.AddDexRegisterEntry(Kind::kConstant, 4);
770
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000771 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100772 stream.AddDexRegisterEntry(Kind::kInStack, 8);
773 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000774 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100775 stream.AddDexRegisterEntry(Kind::kInStack, 16);
776 stream.AddDexRegisterEntry(Kind::kConstant, 20);
777 stream.AddDexRegisterEntry(Kind::kInRegister, 15);
778 stream.EndInlineInfoEntry();
779
780 stream.EndStackMapEntry();
781
782 // Second stack map.
783 stream.BeginStackMapEntry(2, 22, 0x3, &sp_mask1, 2, 3);
784 stream.AddDexRegisterEntry(Kind::kInStack, 56);
785 stream.AddDexRegisterEntry(Kind::kConstant, 0);
786
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000787 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100788 stream.AddDexRegisterEntry(Kind::kInStack, 12);
789 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000790 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100791 stream.AddDexRegisterEntry(Kind::kInStack, 80);
792 stream.AddDexRegisterEntry(Kind::kConstant, 10);
793 stream.AddDexRegisterEntry(Kind::kInRegister, 5);
794 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000795 stream.BeginInlineInfoEntry(&art_method, 5, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100796 stream.EndInlineInfoEntry();
797
798 stream.EndStackMapEntry();
799
800 // Third stack map.
801 stream.BeginStackMapEntry(4, 56, 0x3, &sp_mask1, 2, 0);
802 stream.AddDexRegisterEntry(Kind::kNone, 0);
803 stream.AddDexRegisterEntry(Kind::kConstant, 4);
804 stream.EndStackMapEntry();
805
806 // Fourth stack map.
807 stream.BeginStackMapEntry(6, 78, 0x3, &sp_mask1, 2, 3);
808 stream.AddDexRegisterEntry(Kind::kInStack, 56);
809 stream.AddDexRegisterEntry(Kind::kConstant, 0);
810
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000811 stream.BeginInlineInfoEntry(&art_method, 2, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100812 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000813 stream.BeginInlineInfoEntry(&art_method, 5, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100814 stream.AddDexRegisterEntry(Kind::kInRegister, 2);
815 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000816 stream.BeginInlineInfoEntry(&art_method, 10, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100817 stream.AddDexRegisterEntry(Kind::kNone, 0);
818 stream.AddDexRegisterEntry(Kind::kInRegister, 3);
819 stream.EndInlineInfoEntry();
820
821 stream.EndStackMapEntry();
822
823 size_t size = stream.PrepareForFillIn();
824 void* memory = arena.Alloc(size, kArenaAllocMisc);
825 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700826 stream.FillInCodeInfo(region);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100827
828 CodeInfo ci(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000829 CodeInfoEncoding encoding = ci.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100830
831 {
832 // Verify first stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100833 StackMap sm0 = ci.GetStackMapAt(0, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100834
David Brazdilf677ebf2015-05-29 16:29:43 +0100835 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, 2);
836 ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
837 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100838
David Brazdilf677ebf2015-05-29 16:29:43 +0100839 InlineInfo if0 = ci.GetInlineInfoOf(sm0, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800840 ASSERT_EQ(2u, if0.GetDepth(encoding.inline_info.encoding));
841 ASSERT_EQ(2u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
842 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
843 ASSERT_EQ(3u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
844 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100845
David Brazdilf677ebf2015-05-29 16:29:43 +0100846 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, encoding, 1);
847 ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100848
David Brazdilf677ebf2015-05-29 16:29:43 +0100849 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, encoding, 3);
850 ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
851 ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci, encoding));
852 ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100853 }
854
855 {
856 // Verify second stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100857 StackMap sm1 = ci.GetStackMapAt(1, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100858
David Brazdilf677ebf2015-05-29 16:29:43 +0100859 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, encoding, 2);
860 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
861 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100862
David Brazdilf677ebf2015-05-29 16:29:43 +0100863 InlineInfo if1 = ci.GetInlineInfoOf(sm1, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800864 ASSERT_EQ(3u, if1.GetDepth(encoding.inline_info.encoding));
865 ASSERT_EQ(2u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
866 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
867 ASSERT_EQ(3u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
868 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
869 ASSERT_EQ(5u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
870 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100871
David Brazdilf677ebf2015-05-29 16:29:43 +0100872 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, encoding, 1);
873 ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100874
David Brazdilf677ebf2015-05-29 16:29:43 +0100875 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, encoding, 3);
876 ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
877 ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci, encoding));
878 ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100879
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800880 ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100881 }
882
883 {
884 // Verify third stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100885 StackMap sm2 = ci.GetStackMapAt(2, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100886
David Brazdilf677ebf2015-05-29 16:29:43 +0100887 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, encoding, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100888 ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
David Brazdilf677ebf2015-05-29 16:29:43 +0100889 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800890 ASSERT_FALSE(sm2.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100891 }
892
893 {
894 // Verify fourth stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100895 StackMap sm3 = ci.GetStackMapAt(3, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100896
David Brazdilf677ebf2015-05-29 16:29:43 +0100897 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, encoding, 2);
898 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
899 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100900
David Brazdilf677ebf2015-05-29 16:29:43 +0100901 InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800902 ASSERT_EQ(3u, if2.GetDepth(encoding.inline_info.encoding));
903 ASSERT_EQ(2u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
904 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
905 ASSERT_EQ(5u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
906 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
907 ASSERT_EQ(10u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
908 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100909
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800910 ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, 0));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100911
David Brazdilf677ebf2015-05-29 16:29:43 +0100912 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, encoding, 1);
913 ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100914
David Brazdilf677ebf2015-05-29 16:29:43 +0100915 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, encoding, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100916 ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
David Brazdilf677ebf2015-05-29 16:29:43 +0100917 ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100918 }
919}
920
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800921TEST(StackMapTest, CodeOffsetTest) {
922 // Test minimum alignments, encoding, and decoding.
923 CodeOffset offset_thumb2 = CodeOffset::FromOffset(kThumb2InstructionAlignment, kThumb2);
924 CodeOffset offset_arm64 = CodeOffset::FromOffset(kArm64InstructionAlignment, kArm64);
925 CodeOffset offset_x86 = CodeOffset::FromOffset(kX86InstructionAlignment, kX86);
926 CodeOffset offset_x86_64 = CodeOffset::FromOffset(kX86_64InstructionAlignment, kX86_64);
927 CodeOffset offset_mips = CodeOffset::FromOffset(kMipsInstructionAlignment, kMips);
928 CodeOffset offset_mips64 = CodeOffset::FromOffset(kMips64InstructionAlignment, kMips64);
929 EXPECT_EQ(offset_thumb2.Uint32Value(kThumb2), kThumb2InstructionAlignment);
930 EXPECT_EQ(offset_arm64.Uint32Value(kArm64), kArm64InstructionAlignment);
931 EXPECT_EQ(offset_x86.Uint32Value(kX86), kX86InstructionAlignment);
932 EXPECT_EQ(offset_x86_64.Uint32Value(kX86_64), kX86_64InstructionAlignment);
933 EXPECT_EQ(offset_mips.Uint32Value(kMips), kMipsInstructionAlignment);
934 EXPECT_EQ(offset_mips64.Uint32Value(kMips64), kMips64InstructionAlignment);
935}
936
David Srbecky45aa5982016-03-18 02:15:09 +0000937TEST(StackMapTest, TestDeduplicateStackMask) {
938 ArenaPool pool;
939 ArenaAllocator arena(&pool);
940 StackMapStream stream(&arena, kRuntimeISA);
941
942 ArenaBitVector sp_mask(&arena, 0, true);
943 sp_mask.SetBit(1);
944 sp_mask.SetBit(4);
945 stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
946 stream.EndStackMapEntry();
947 stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
948 stream.EndStackMapEntry();
949
950 size_t size = stream.PrepareForFillIn();
951 void* memory = arena.Alloc(size, kArenaAllocMisc);
952 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700953 stream.FillInCodeInfo(region);
David Srbecky45aa5982016-03-18 02:15:09 +0000954
955 CodeInfo code_info(region);
956 CodeInfoEncoding encoding = code_info.ExtractEncoding();
957 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
958
959 StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4, encoding);
960 StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800961 EXPECT_EQ(stack_map1.GetStackMaskIndex(encoding.stack_map.encoding),
962 stack_map2.GetStackMaskIndex(encoding.stack_map.encoding));
David Srbecky45aa5982016-03-18 02:15:09 +0000963}
964
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800965TEST(StackMapTest, TestInvokeInfo) {
966 ArenaPool pool;
967 ArenaAllocator arena(&pool);
968 StackMapStream stream(&arena, kRuntimeISA);
969
970 ArenaBitVector sp_mask(&arena, 0, true);
971 sp_mask.SetBit(1);
972 stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
973 stream.AddInvoke(kSuper, 1);
974 stream.EndStackMapEntry();
975 stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
976 stream.AddInvoke(kStatic, 3);
977 stream.EndStackMapEntry();
978 stream.BeginStackMapEntry(0, 16, 0x3, &sp_mask, 0, 0);
979 stream.AddInvoke(kDirect, 65535);
980 stream.EndStackMapEntry();
981
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700982 const size_t code_info_size = stream.PrepareForFillIn();
983 MemoryRegion code_info_region(arena.Alloc(code_info_size, kArenaAllocMisc), code_info_size);
984 stream.FillInCodeInfo(code_info_region);
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800985
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700986 const size_t method_info_size = stream.ComputeMethodInfoSize();
987 MemoryRegion method_info_region(arena.Alloc(method_info_size, kArenaAllocMisc), method_info_size);
988 stream.FillInMethodInfo(method_info_region);
989
990 CodeInfo code_info(code_info_region);
991 MethodInfo method_info(method_info_region.begin());
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800992 CodeInfoEncoding encoding = code_info.ExtractEncoding();
993 ASSERT_EQ(3u, code_info.GetNumberOfStackMaps(encoding));
994
995 InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4, encoding));
996 InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8, encoding));
997 InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16, encoding));
998 InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12, encoding));
999 EXPECT_FALSE(invoke_invalid.IsValid()); // No entry for that index.
1000 EXPECT_TRUE(invoke1.IsValid());
1001 EXPECT_TRUE(invoke2.IsValid());
1002 EXPECT_TRUE(invoke3.IsValid());
1003 EXPECT_EQ(invoke1.GetInvokeType(encoding.invoke_info.encoding), kSuper);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001004 EXPECT_EQ(invoke1.GetMethodIndex(encoding.invoke_info.encoding, method_info), 1u);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001005 EXPECT_EQ(invoke1.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 4u);
1006 EXPECT_EQ(invoke2.GetInvokeType(encoding.invoke_info.encoding), kStatic);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001007 EXPECT_EQ(invoke2.GetMethodIndex(encoding.invoke_info.encoding, method_info), 3u);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001008 EXPECT_EQ(invoke2.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 8u);
1009 EXPECT_EQ(invoke3.GetInvokeType(encoding.invoke_info.encoding), kDirect);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001010 EXPECT_EQ(invoke3.GetMethodIndex(encoding.invoke_info.encoding, method_info), 65535u);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001011 EXPECT_EQ(invoke3.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 16u);
1012}
1013
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001014} // namespace art