blob: 7e517f34850a5c661e62c7bc7499dbeef4b9d67a [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;
Vladimir Marko174b2e22017-10-12 13:34:49 +010050 ArenaStack arena_stack(&pool);
51 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +010052 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010053
Vladimir Marko69d310e2017-10-09 14:12:23 +010054 ArenaBitVector sp_mask(&allocator, 0, false);
Roland Levillain12baf472015-03-05 12:41:42 +000055 size_t number_of_dex_registers = 2;
Calin Juravle4f46ac52015-04-23 18:47:21 +010056 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +010057 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
58 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Short location.
Calin Juravle4f46ac52015-04-23 18:47:21 +010059 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010060
Calin Juravle4f46ac52015-04-23 18:47:21 +010061 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +010062 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010063 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -070064 stream.FillInCodeInfo(region);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010065
Nicolas Geoffray39468442014-09-02 15:17:15 +010066 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +000067 CodeInfoEncoding encoding = code_info.ExtractEncoding();
68 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010069
David Srbecky09ed0982016-02-12 21:58:43 +000070 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
71 ASSERT_EQ(2u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +010072 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +000073 // The Dex register location catalog contains:
74 // - one 1-byte short Dex register location, and
75 // - one 5-byte large Dex register location.
76 size_t expected_location_catalog_size = 1u + 5u;
77 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
78
David Brazdilf677ebf2015-05-29 16:29:43 +010079 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
80 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
81 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -080082 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
83 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -080084 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010085
David Srbecky45aa5982016-03-18 02:15:09 +000086 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010087
Mathieu Chartier575d3e62017-02-06 11:00:40 -080088 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +000089 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +010090 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +000091 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
92 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
93 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
94 // The Dex register map contains:
95 // - one 1-byte live bit mask, and
96 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
97 size_t expected_dex_register_map_size = 1u + 1u;
98 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
99
David Brazdilf677ebf2015-05-29 16:29:43 +0100100 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
101 0, number_of_dex_registers, code_info, encoding));
102 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
103 1, number_of_dex_registers, code_info, encoding));
104 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
105 0, number_of_dex_registers, code_info, encoding));
106 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
107 1, number_of_dex_registers, code_info, encoding));
108 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
109 0, number_of_dex_registers, code_info, encoding));
110 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000111
112 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000113 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000114 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000115 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000116 ASSERT_EQ(0u, index0);
117 ASSERT_EQ(1u, index1);
118 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
119 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
120 ASSERT_EQ(Kind::kInStack, location0.GetKind());
121 ASSERT_EQ(Kind::kConstant, location1.GetKind());
122 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
123 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000124 ASSERT_EQ(0, location0.GetValue());
125 ASSERT_EQ(-2, location1.GetValue());
Roland Levillain12baf472015-03-05 12:41:42 +0000126
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800127 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100128}
129
130TEST(StackMapTest, Test2) {
131 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100132 ArenaStack arena_stack(&pool);
133 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100134 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000135 ArtMethod art_method;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100136
Vladimir Marko69d310e2017-10-09 14:12:23 +0100137 ArenaBitVector sp_mask1(&allocator, 0, true);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100138 sp_mask1.SetBit(2);
139 sp_mask1.SetBit(4);
Roland Levillain12baf472015-03-05 12:41:42 +0000140 size_t number_of_dex_registers = 2;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100141 size_t number_of_dex_registers_in_inline_info = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100142 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100143 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
144 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000145 stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100146 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000147 stream.BeginInlineInfoEntry(&art_method, 2, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100148 stream.EndInlineInfoEntry();
Calin Juravle4f46ac52015-04-23 18:47:21 +0100149 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100150
Vladimir Marko69d310e2017-10-09 14:12:23 +0100151 ArenaBitVector sp_mask2(&allocator, 0, true);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100152 sp_mask2.SetBit(3);
David Brazdilf10a25f2015-06-02 14:29:52 +0100153 sp_mask2.SetBit(8);
Calin Juravle4f46ac52015-04-23 18:47:21 +0100154 stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100155 stream.AddDexRegisterEntry(Kind::kInRegister, 18); // Short location.
156 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100157 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100158
Vladimir Marko69d310e2017-10-09 14:12:23 +0100159 ArenaBitVector sp_mask3(&allocator, 0, true);
David Brazdild9cb68e2015-08-25 13:52:43 +0100160 sp_mask3.SetBit(1);
161 sp_mask3.SetBit(5);
162 stream.BeginStackMapEntry(2, 192, 0xAB, &sp_mask3, number_of_dex_registers, 0);
163 stream.AddDexRegisterEntry(Kind::kInRegister, 6); // Short location.
164 stream.AddDexRegisterEntry(Kind::kInRegisterHigh, 8); // Short location.
165 stream.EndStackMapEntry();
166
Vladimir Marko69d310e2017-10-09 14:12:23 +0100167 ArenaBitVector sp_mask4(&allocator, 0, true);
David Brazdild9cb68e2015-08-25 13:52:43 +0100168 sp_mask4.SetBit(6);
169 sp_mask4.SetBit(7);
170 stream.BeginStackMapEntry(3, 256, 0xCD, &sp_mask4, number_of_dex_registers, 0);
171 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location, same in stack map 2.
172 stream.AddDexRegisterEntry(Kind::kInFpuRegisterHigh, 1); // Short location.
173 stream.EndStackMapEntry();
174
Calin Juravle4f46ac52015-04-23 18:47:21 +0100175 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100176 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100177 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700178 stream.FillInCodeInfo(region);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100179
Nicolas Geoffray39468442014-09-02 15:17:15 +0100180 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000181 CodeInfoEncoding encoding = code_info.ExtractEncoding();
182 ASSERT_EQ(4u, code_info.GetNumberOfStackMaps(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100183
David Srbecky09ed0982016-02-12 21:58:43 +0000184 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
185 ASSERT_EQ(7u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100186 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000187 // The Dex register location catalog contains:
David Brazdild9cb68e2015-08-25 13:52:43 +0100188 // - six 1-byte short Dex register locations, and
Roland Levillaina552e1c2015-03-26 15:01:03 +0000189 // - one 5-byte large Dex register location.
David Brazdild9cb68e2015-08-25 13:52:43 +0100190 size_t expected_location_catalog_size = 6u * 1u + 5u;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000191 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
192
Roland Levillain12baf472015-03-05 12:41:42 +0000193 // First stack map.
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000194 {
David Brazdilf677ebf2015-05-29 16:29:43 +0100195 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
196 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
197 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800198 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
199 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800200 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100201
David Srbecky45aa5982016-03-18 02:15:09 +0000202 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100203
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800204 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000205 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100206 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000207 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
208 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
209 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
210 // The Dex register map contains:
211 // - one 1-byte live bit mask, and
212 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
213 size_t expected_dex_register_map_size = 1u + 1u;
214 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
215
David Brazdilf677ebf2015-05-29 16:29:43 +0100216 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
217 0, number_of_dex_registers, code_info, encoding));
218 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
219 1, number_of_dex_registers, code_info, encoding));
220 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
221 0, number_of_dex_registers, code_info, encoding));
222 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
223 1, number_of_dex_registers, code_info, encoding));
224 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
225 0, number_of_dex_registers, code_info, encoding));
226 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000227
228 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000229 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000230 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000231 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000232 ASSERT_EQ(0u, index0);
233 ASSERT_EQ(1u, index1);
234 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
235 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
236 ASSERT_EQ(Kind::kInStack, location0.GetKind());
237 ASSERT_EQ(Kind::kConstant, location1.GetKind());
238 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
239 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000240 ASSERT_EQ(0, location0.GetValue());
241 ASSERT_EQ(-2, location1.GetValue());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100242
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800243 ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
David Brazdilf677ebf2015-05-29 16:29:43 +0100244 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800245 ASSERT_EQ(2u, inline_info.GetDepth(encoding.inline_info.encoding));
246 ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
247 ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
248 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
249 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000250 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100251
Roland Levillain12baf472015-03-05 12:41:42 +0000252 // Second stack map.
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000253 {
David Brazdilf677ebf2015-05-29 16:29:43 +0100254 StackMap stack_map = code_info.GetStackMapAt(1, encoding);
255 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u, encoding)));
256 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800257 ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map.encoding));
258 ASSERT_EQ(128u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800259 ASSERT_EQ(0xFFu, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100260
David Srbecky45aa5982016-03-18 02:15:09 +0000261 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask2));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100262
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800263 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000264 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100265 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000266 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
267 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
268 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
269 // The Dex register map contains:
270 // - one 1-byte live bit mask, and
271 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
272 size_t expected_dex_register_map_size = 1u + 1u;
273 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
274
David Brazdilf677ebf2015-05-29 16:29:43 +0100275 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
276 0, number_of_dex_registers, code_info, encoding));
277 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
278 1, number_of_dex_registers, code_info, encoding));
279 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
280 0, number_of_dex_registers, code_info, encoding));
281 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
282 1, number_of_dex_registers, code_info, encoding));
283 ASSERT_EQ(18, dex_register_map.GetMachineRegister(
284 0, number_of_dex_registers, code_info, encoding));
285 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
286 1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000287
288 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000289 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000290 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000291 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000292 ASSERT_EQ(2u, index0);
293 ASSERT_EQ(3u, index1);
294 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
295 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
296 ASSERT_EQ(Kind::kInRegister, location0.GetKind());
297 ASSERT_EQ(Kind::kInFpuRegister, location1.GetKind());
298 ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
299 ASSERT_EQ(Kind::kInFpuRegister, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000300 ASSERT_EQ(18, location0.GetValue());
301 ASSERT_EQ(3, location1.GetValue());
Roland Levillain12baf472015-03-05 12:41:42 +0000302
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800303 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000304 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100305
306 // Third stack map.
307 {
308 StackMap stack_map = code_info.GetStackMapAt(2, encoding);
309 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u, encoding)));
310 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800311 ASSERT_EQ(2u, stack_map.GetDexPc(encoding.stack_map.encoding));
312 ASSERT_EQ(192u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800313 ASSERT_EQ(0xABu, code_info.GetRegisterMaskOf(encoding, stack_map));
David Brazdild9cb68e2015-08-25 13:52:43 +0100314
David Srbecky45aa5982016-03-18 02:15:09 +0000315 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask3));
David Brazdild9cb68e2015-08-25 13:52:43 +0100316
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800317 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100318 DexRegisterMap dex_register_map =
319 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
320 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
321 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
322 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
323 // The Dex register map contains:
324 // - one 1-byte live bit mask, and
325 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
326 size_t expected_dex_register_map_size = 1u + 1u;
327 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
328
329 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
330 0, number_of_dex_registers, code_info, encoding));
331 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(
332 1, number_of_dex_registers, code_info, encoding));
333 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
334 0, number_of_dex_registers, code_info, encoding));
335 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationInternalKind(
336 1, number_of_dex_registers, code_info, encoding));
337 ASSERT_EQ(6, dex_register_map.GetMachineRegister(
338 0, number_of_dex_registers, code_info, encoding));
339 ASSERT_EQ(8, dex_register_map.GetMachineRegister(
340 1, number_of_dex_registers, code_info, encoding));
341
342 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000343 0, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100344 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000345 1, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100346 ASSERT_EQ(4u, index0);
347 ASSERT_EQ(5u, index1);
348 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
349 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
350 ASSERT_EQ(Kind::kInRegister, location0.GetKind());
351 ASSERT_EQ(Kind::kInRegisterHigh, location1.GetKind());
352 ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
353 ASSERT_EQ(Kind::kInRegisterHigh, location1.GetInternalKind());
354 ASSERT_EQ(6, location0.GetValue());
355 ASSERT_EQ(8, location1.GetValue());
356
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800357 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100358 }
359
360 // Fourth stack map.
361 {
362 StackMap stack_map = code_info.GetStackMapAt(3, encoding);
363 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u, encoding)));
364 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800365 ASSERT_EQ(3u, stack_map.GetDexPc(encoding.stack_map.encoding));
366 ASSERT_EQ(256u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800367 ASSERT_EQ(0xCDu, code_info.GetRegisterMaskOf(encoding, stack_map));
David Brazdild9cb68e2015-08-25 13:52:43 +0100368
David Srbecky45aa5982016-03-18 02:15:09 +0000369 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask4));
David Brazdild9cb68e2015-08-25 13:52:43 +0100370
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800371 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100372 DexRegisterMap dex_register_map =
373 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
374 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
375 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
376 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
377 // The Dex register map contains:
378 // - one 1-byte live bit mask, and
379 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
380 size_t expected_dex_register_map_size = 1u + 1u;
381 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
382
383 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
384 0, number_of_dex_registers, code_info, encoding));
385 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(
386 1, number_of_dex_registers, code_info, encoding));
387 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
388 0, number_of_dex_registers, code_info, encoding));
389 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationInternalKind(
390 1, number_of_dex_registers, code_info, encoding));
391 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
392 0, number_of_dex_registers, code_info, encoding));
393 ASSERT_EQ(1, dex_register_map.GetMachineRegister(
394 1, number_of_dex_registers, code_info, encoding));
395
396 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000397 0, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100398 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000399 1, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100400 ASSERT_EQ(3u, index0); // Shared with second stack map.
401 ASSERT_EQ(6u, index1);
402 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
403 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
404 ASSERT_EQ(Kind::kInFpuRegister, location0.GetKind());
405 ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetKind());
406 ASSERT_EQ(Kind::kInFpuRegister, location0.GetInternalKind());
407 ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetInternalKind());
408 ASSERT_EQ(3, location0.GetValue());
409 ASSERT_EQ(1, location1.GetValue());
410
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800411 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100412 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100413}
414
Mathieu Chartier32289082017-02-09 15:57:37 -0800415TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
416 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100417 ArenaStack arena_stack(&pool);
418 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100419 StackMapStream stream(&allocator, kRuntimeISA);
Mathieu Chartier32289082017-02-09 15:57:37 -0800420 ArtMethod art_method;
421
Vladimir Marko69d310e2017-10-09 14:12:23 +0100422 ArenaBitVector sp_mask1(&allocator, 0, true);
Mathieu Chartier32289082017-02-09 15:57:37 -0800423 sp_mask1.SetBit(2);
424 sp_mask1.SetBit(4);
425 const size_t number_of_dex_registers = 2;
426 const size_t number_of_dex_registers_in_inline_info = 2;
427 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 1);
428 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
429 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
430 stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
431 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
432 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
433 stream.EndInlineInfoEntry();
434 stream.EndStackMapEntry();
435
436 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100437 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Mathieu Chartier32289082017-02-09 15:57:37 -0800438 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700439 stream.FillInCodeInfo(region);
Mathieu Chartier32289082017-02-09 15:57:37 -0800440
441 CodeInfo code_info(region);
442 CodeInfoEncoding encoding = code_info.ExtractEncoding();
443 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
444
445 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
446 ASSERT_EQ(2u, number_of_catalog_entries);
447 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
448 // The Dex register location catalog contains:
449 // - one 1-byte short Dex register locations, and
450 // - one 5-byte large Dex register location.
451 const size_t expected_location_catalog_size = 1u + 5u;
452 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
453
454 // First stack map.
455 {
456 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
457 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
458 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
459 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
460 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
461 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
462
463 ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
464
465 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
466 DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers));
467 ASSERT_TRUE(map.IsDexRegisterLive(0));
468 ASSERT_TRUE(map.IsDexRegisterLive(1));
469 ASSERT_EQ(2u, map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
470 // The Dex register map contains:
471 // - one 1-byte live bit mask, and
472 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
473 size_t expected_map_size = 1u + 1u;
474 ASSERT_EQ(expected_map_size, map.Size());
475
476 ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0, number_of_dex_registers, code_info, encoding));
477 ASSERT_EQ(Kind::kConstant,
478 map.GetLocationKind(1, number_of_dex_registers, code_info, encoding));
479 ASSERT_EQ(Kind::kInStack,
480 map.GetLocationInternalKind(0, number_of_dex_registers, code_info, encoding));
481 ASSERT_EQ(Kind::kConstantLargeValue,
482 map.GetLocationInternalKind(1, number_of_dex_registers, code_info, encoding));
483 ASSERT_EQ(0, map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info, encoding));
484 ASSERT_EQ(-2, map.GetConstant(1, number_of_dex_registers, code_info, encoding));
485
486 const size_t index0 =
487 map.GetLocationCatalogEntryIndex(0, number_of_dex_registers, number_of_catalog_entries);
488 const size_t index1 =
489 map.GetLocationCatalogEntryIndex(1, number_of_dex_registers, number_of_catalog_entries);
490 ASSERT_EQ(0u, index0);
491 ASSERT_EQ(1u, index1);
492 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
493 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
494 ASSERT_EQ(Kind::kInStack, location0.GetKind());
495 ASSERT_EQ(Kind::kConstant, location1.GetKind());
496 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
497 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
498 ASSERT_EQ(0, location0.GetValue());
499 ASSERT_EQ(-2, location1.GetValue());
500
501 // Test that the inline info dex register map deduplicated to the same offset as the stack map
502 // one.
503 ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
504 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
505 EXPECT_EQ(inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info.encoding, 0),
506 stack_map.GetDexRegisterMapOffset(encoding.stack_map.encoding));
507 }
508}
509
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000510TEST(StackMapTest, TestNonLiveDexRegisters) {
511 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100512 ArenaStack arena_stack(&pool);
513 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100514 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000515
Vladimir Marko69d310e2017-10-09 14:12:23 +0100516 ArenaBitVector sp_mask(&allocator, 0, false);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000517 uint32_t number_of_dex_registers = 2;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100518 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100519 stream.AddDexRegisterEntry(Kind::kNone, 0); // No location.
520 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100521 stream.EndStackMapEntry();
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000522
Calin Juravle4f46ac52015-04-23 18:47:21 +0100523 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100524 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000525 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700526 stream.FillInCodeInfo(region);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000527
528 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000529 CodeInfoEncoding encoding = code_info.ExtractEncoding();
530 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000531
David Srbecky09ed0982016-02-12 21:58:43 +0000532 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
533 ASSERT_EQ(1u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100534 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000535 // The Dex register location catalog contains:
536 // - one 5-byte large Dex register location.
537 size_t expected_location_catalog_size = 5u;
538 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
539
David Brazdilf677ebf2015-05-29 16:29:43 +0100540 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
541 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
542 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800543 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
544 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800545 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000546
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800547 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000548 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100549 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000550 ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
551 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
552 ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
553 // The Dex register map contains:
554 // - one 1-byte live bit mask.
555 // No space is allocated for the sole location catalog entry index, as it is useless.
556 size_t expected_dex_register_map_size = 1u + 0u;
557 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
558
David Brazdilf677ebf2015-05-29 16:29:43 +0100559 ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind(
560 0, number_of_dex_registers, code_info, encoding));
561 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
562 1, number_of_dex_registers, code_info, encoding));
563 ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind(
564 0, number_of_dex_registers, code_info, encoding));
565 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
566 1, number_of_dex_registers, code_info, encoding));
567 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000568
569 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000570 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000571 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000572 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000573 ASSERT_EQ(DexRegisterLocationCatalog::kNoLocationEntryIndex, index0);
574 ASSERT_EQ(0u, index1);
575 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
576 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
577 ASSERT_EQ(Kind::kNone, location0.GetKind());
578 ASSERT_EQ(Kind::kConstant, location1.GetKind());
579 ASSERT_EQ(Kind::kNone, location0.GetInternalKind());
580 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
581 ASSERT_EQ(0, location0.GetValue());
582 ASSERT_EQ(-2, location1.GetValue());
583
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800584 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000585}
586
587// Generate a stack map whose dex register offset is
588// StackMap::kNoDexRegisterMapSmallEncoding, and ensure we do
589// not treat it as kNoDexRegisterMap.
590TEST(StackMapTest, DexRegisterMapOffsetOverflow) {
591 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100592 ArenaStack arena_stack(&pool);
593 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100594 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000595
Vladimir Marko69d310e2017-10-09 14:12:23 +0100596 ArenaBitVector sp_mask(&allocator, 0, false);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000597 uint32_t number_of_dex_registers = 1024;
598 // Create the first stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100599 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000600 uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
601 for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
602 // Use two different Dex register locations to populate this map,
603 // as using a single value (in the whole CodeInfo object) would
604 // make this Dex register mapping data empty (see
605 // art::DexRegisterMap::SingleEntrySizeInBits).
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100606 stream.AddDexRegisterEntry(Kind::kConstant, i % 2); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000607 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100608 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000609 // Create the second stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100610 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000611 for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100612 stream.AddDexRegisterEntry(Kind::kConstant, 0); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000613 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100614 stream.EndStackMapEntry();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000615
Calin Juravle4f46ac52015-04-23 18:47:21 +0100616 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100617 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000618 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700619 stream.FillInCodeInfo(region);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000620
621 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000622 CodeInfoEncoding encoding = code_info.ExtractEncoding();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000623 // The location catalog contains two entries (DexRegisterLocation(kConstant, 0)
624 // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index
625 // has a size of 1 bit.
David Srbecky09ed0982016-02-12 21:58:43 +0000626 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
627 ASSERT_EQ(2u, number_of_catalog_entries);
628 ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_catalog_entries));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000629
630 // The first Dex register map contains:
631 // - a live register bit mask for 1024 registers (that is, 128 bytes of
632 // data); and
633 // - Dex register mapping information for 1016 1-bit Dex (live) register
634 // locations (that is, 127 bytes of data).
635 // Hence it has a size of 255 bytes, and therefore...
636 ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers));
David Brazdilf677ebf2015-05-29 16:29:43 +0100637 StackMap stack_map0 = code_info.GetStackMapAt(0, encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000638 DexRegisterMap dex_register_map0 =
David Brazdilf677ebf2015-05-29 16:29:43 +0100639 code_info.GetDexRegisterMapOf(stack_map0, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000640 ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
David Srbecky09ed0982016-02-12 21:58:43 +0000641 number_of_catalog_entries));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000642 ASSERT_EQ(255u, dex_register_map0.Size());
643
David Brazdilf677ebf2015-05-29 16:29:43 +0100644 StackMap stack_map1 = code_info.GetStackMapAt(1, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800645 ASSERT_TRUE(stack_map1.HasDexRegisterMap(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000646 // ...the offset of the second Dex register map (relative to the
647 // beginning of the Dex register maps region) is 255 (i.e.,
648 // kNoDexRegisterMapSmallEncoding).
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800649 ASSERT_NE(stack_map1.GetDexRegisterMapOffset(encoding.stack_map.encoding),
David Srbecky09ed0982016-02-12 21:58:43 +0000650 StackMap::kNoDexRegisterMap);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800651 ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(encoding.stack_map.encoding), 0xFFu);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000652}
653
Calin Juravle6ae70962015-03-18 16:31:28 +0000654TEST(StackMapTest, TestShareDexRegisterMap) {
655 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100656 ArenaStack arena_stack(&pool);
657 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100658 StackMapStream stream(&allocator, kRuntimeISA);
Calin Juravle6ae70962015-03-18 16:31:28 +0000659
Vladimir Marko69d310e2017-10-09 14:12:23 +0100660 ArenaBitVector sp_mask(&allocator, 0, false);
Calin Juravle6ae70962015-03-18 16:31:28 +0000661 uint32_t number_of_dex_registers = 2;
662 // First stack map.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100663 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100664 stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
665 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100666 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000667 // Second stack map, which should share the same dex register map.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100668 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100669 stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
670 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100671 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000672 // Third stack map (doesn't share the dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100673 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100674 stream.AddDexRegisterEntry(Kind::kInRegister, 2); // Short location.
675 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100676 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000677
Calin Juravle4f46ac52015-04-23 18:47:21 +0100678 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100679 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Calin Juravle6ae70962015-03-18 16:31:28 +0000680 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700681 stream.FillInCodeInfo(region);
Calin Juravle6ae70962015-03-18 16:31:28 +0000682
683 CodeInfo ci(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000684 CodeInfoEncoding encoding = ci.ExtractEncoding();
David Brazdilf677ebf2015-05-29 16:29:43 +0100685
Calin Juravle6ae70962015-03-18 16:31:28 +0000686 // Verify first stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100687 StackMap sm0 = ci.GetStackMapAt(0, encoding);
688 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, number_of_dex_registers);
689 ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
690 ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000691
692 // Verify second stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100693 StackMap sm1 = ci.GetStackMapAt(1, encoding);
694 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, encoding, number_of_dex_registers);
695 ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
696 ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000697
698 // Verify third stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100699 StackMap sm2 = ci.GetStackMapAt(2, encoding);
700 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, encoding, number_of_dex_registers);
701 ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
702 ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000703
704 // Verify dex register map offsets.
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800705 ASSERT_EQ(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
706 sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding));
707 ASSERT_NE(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
708 sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
709 ASSERT_NE(sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding),
710 sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000711}
712
Roland Levillaina552e1c2015-03-26 15:01:03 +0000713TEST(StackMapTest, TestNoDexRegisterMap) {
714 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100715 ArenaStack arena_stack(&pool);
716 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100717 StackMapStream stream(&allocator, kRuntimeISA);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000718
Vladimir Marko69d310e2017-10-09 14:12:23 +0100719 ArenaBitVector sp_mask(&allocator, 0, false);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000720 uint32_t number_of_dex_registers = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100721 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
722 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000723
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000724 number_of_dex_registers = 1;
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800725 stream.BeginStackMapEntry(1, 68, 0x4, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000726 stream.EndStackMapEntry();
727
Calin Juravle4f46ac52015-04-23 18:47:21 +0100728 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100729 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000730 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700731 stream.FillInCodeInfo(region);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000732
733 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000734 CodeInfoEncoding encoding = code_info.ExtractEncoding();
735 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000736
David Srbecky09ed0982016-02-12 21:58:43 +0000737 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
738 ASSERT_EQ(0u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100739 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000740 ASSERT_EQ(0u, location_catalog.Size());
741
David Brazdilf677ebf2015-05-29 16:29:43 +0100742 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
743 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
744 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800745 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
746 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800747 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000748
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800749 ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
750 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000751
752 stack_map = code_info.GetStackMapAt(1, encoding);
753 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1, encoding)));
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800754 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68, encoding)));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800755 ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map.encoding));
756 ASSERT_EQ(68u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800757 ASSERT_EQ(0x4u, code_info.GetRegisterMaskOf(encoding, stack_map));
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000758
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800759 ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
760 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000761}
762
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100763TEST(StackMapTest, InlineTest) {
764 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100765 ArenaStack arena_stack(&pool);
766 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100767 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000768 ArtMethod art_method;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100769
Vladimir Marko69d310e2017-10-09 14:12:23 +0100770 ArenaBitVector sp_mask1(&allocator, 0, true);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100771 sp_mask1.SetBit(2);
772 sp_mask1.SetBit(4);
773
774 // First stack map.
775 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, 2, 2);
776 stream.AddDexRegisterEntry(Kind::kInStack, 0);
777 stream.AddDexRegisterEntry(Kind::kConstant, 4);
778
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000779 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100780 stream.AddDexRegisterEntry(Kind::kInStack, 8);
781 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000782 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100783 stream.AddDexRegisterEntry(Kind::kInStack, 16);
784 stream.AddDexRegisterEntry(Kind::kConstant, 20);
785 stream.AddDexRegisterEntry(Kind::kInRegister, 15);
786 stream.EndInlineInfoEntry();
787
788 stream.EndStackMapEntry();
789
790 // Second stack map.
791 stream.BeginStackMapEntry(2, 22, 0x3, &sp_mask1, 2, 3);
792 stream.AddDexRegisterEntry(Kind::kInStack, 56);
793 stream.AddDexRegisterEntry(Kind::kConstant, 0);
794
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000795 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100796 stream.AddDexRegisterEntry(Kind::kInStack, 12);
797 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000798 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100799 stream.AddDexRegisterEntry(Kind::kInStack, 80);
800 stream.AddDexRegisterEntry(Kind::kConstant, 10);
801 stream.AddDexRegisterEntry(Kind::kInRegister, 5);
802 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000803 stream.BeginInlineInfoEntry(&art_method, 5, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100804 stream.EndInlineInfoEntry();
805
806 stream.EndStackMapEntry();
807
808 // Third stack map.
809 stream.BeginStackMapEntry(4, 56, 0x3, &sp_mask1, 2, 0);
810 stream.AddDexRegisterEntry(Kind::kNone, 0);
811 stream.AddDexRegisterEntry(Kind::kConstant, 4);
812 stream.EndStackMapEntry();
813
814 // Fourth stack map.
815 stream.BeginStackMapEntry(6, 78, 0x3, &sp_mask1, 2, 3);
816 stream.AddDexRegisterEntry(Kind::kInStack, 56);
817 stream.AddDexRegisterEntry(Kind::kConstant, 0);
818
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000819 stream.BeginInlineInfoEntry(&art_method, 2, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100820 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000821 stream.BeginInlineInfoEntry(&art_method, 5, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100822 stream.AddDexRegisterEntry(Kind::kInRegister, 2);
823 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000824 stream.BeginInlineInfoEntry(&art_method, 10, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100825 stream.AddDexRegisterEntry(Kind::kNone, 0);
826 stream.AddDexRegisterEntry(Kind::kInRegister, 3);
827 stream.EndInlineInfoEntry();
828
829 stream.EndStackMapEntry();
830
831 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100832 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100833 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700834 stream.FillInCodeInfo(region);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100835
836 CodeInfo ci(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000837 CodeInfoEncoding encoding = ci.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100838
839 {
840 // Verify first stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100841 StackMap sm0 = ci.GetStackMapAt(0, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100842
David Brazdilf677ebf2015-05-29 16:29:43 +0100843 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, 2);
844 ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
845 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100846
David Brazdilf677ebf2015-05-29 16:29:43 +0100847 InlineInfo if0 = ci.GetInlineInfoOf(sm0, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800848 ASSERT_EQ(2u, if0.GetDepth(encoding.inline_info.encoding));
849 ASSERT_EQ(2u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
850 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
851 ASSERT_EQ(3u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
852 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100853
David Brazdilf677ebf2015-05-29 16:29:43 +0100854 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, encoding, 1);
855 ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100856
David Brazdilf677ebf2015-05-29 16:29:43 +0100857 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, encoding, 3);
858 ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
859 ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci, encoding));
860 ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100861 }
862
863 {
864 // Verify second stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100865 StackMap sm1 = ci.GetStackMapAt(1, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100866
David Brazdilf677ebf2015-05-29 16:29:43 +0100867 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, encoding, 2);
868 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
869 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100870
David Brazdilf677ebf2015-05-29 16:29:43 +0100871 InlineInfo if1 = ci.GetInlineInfoOf(sm1, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800872 ASSERT_EQ(3u, if1.GetDepth(encoding.inline_info.encoding));
873 ASSERT_EQ(2u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
874 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
875 ASSERT_EQ(3u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
876 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
877 ASSERT_EQ(5u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
878 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100879
David Brazdilf677ebf2015-05-29 16:29:43 +0100880 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, encoding, 1);
881 ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100882
David Brazdilf677ebf2015-05-29 16:29:43 +0100883 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, encoding, 3);
884 ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
885 ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci, encoding));
886 ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100887
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800888 ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100889 }
890
891 {
892 // Verify third stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100893 StackMap sm2 = ci.GetStackMapAt(2, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100894
David Brazdilf677ebf2015-05-29 16:29:43 +0100895 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, encoding, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100896 ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
David Brazdilf677ebf2015-05-29 16:29:43 +0100897 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800898 ASSERT_FALSE(sm2.HasInlineInfo(encoding.stack_map.encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100899 }
900
901 {
902 // Verify fourth stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100903 StackMap sm3 = ci.GetStackMapAt(3, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100904
David Brazdilf677ebf2015-05-29 16:29:43 +0100905 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, encoding, 2);
906 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
907 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100908
David Brazdilf677ebf2015-05-29 16:29:43 +0100909 InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800910 ASSERT_EQ(3u, if2.GetDepth(encoding.inline_info.encoding));
911 ASSERT_EQ(2u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
912 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
913 ASSERT_EQ(5u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
914 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
915 ASSERT_EQ(10u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
916 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100917
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800918 ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, 0));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100919
David Brazdilf677ebf2015-05-29 16:29:43 +0100920 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, encoding, 1);
921 ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100922
David Brazdilf677ebf2015-05-29 16:29:43 +0100923 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, encoding, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100924 ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
David Brazdilf677ebf2015-05-29 16:29:43 +0100925 ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100926 }
927}
928
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800929TEST(StackMapTest, CodeOffsetTest) {
930 // Test minimum alignments, encoding, and decoding.
Vladimir Marko33bff252017-11-01 14:35:42 +0000931 CodeOffset offset_thumb2 =
932 CodeOffset::FromOffset(kThumb2InstructionAlignment, InstructionSet::kThumb2);
933 CodeOffset offset_arm64 =
934 CodeOffset::FromOffset(kArm64InstructionAlignment, InstructionSet::kArm64);
935 CodeOffset offset_x86 =
936 CodeOffset::FromOffset(kX86InstructionAlignment, InstructionSet::kX86);
937 CodeOffset offset_x86_64 =
938 CodeOffset::FromOffset(kX86_64InstructionAlignment, InstructionSet::kX86_64);
939 CodeOffset offset_mips =
940 CodeOffset::FromOffset(kMipsInstructionAlignment, InstructionSet::kMips);
941 CodeOffset offset_mips64 =
942 CodeOffset::FromOffset(kMips64InstructionAlignment, InstructionSet::kMips64);
943 EXPECT_EQ(offset_thumb2.Uint32Value(InstructionSet::kThumb2), kThumb2InstructionAlignment);
944 EXPECT_EQ(offset_arm64.Uint32Value(InstructionSet::kArm64), kArm64InstructionAlignment);
945 EXPECT_EQ(offset_x86.Uint32Value(InstructionSet::kX86), kX86InstructionAlignment);
946 EXPECT_EQ(offset_x86_64.Uint32Value(InstructionSet::kX86_64), kX86_64InstructionAlignment);
947 EXPECT_EQ(offset_mips.Uint32Value(InstructionSet::kMips), kMipsInstructionAlignment);
948 EXPECT_EQ(offset_mips64.Uint32Value(InstructionSet::kMips64), kMips64InstructionAlignment);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800949}
950
David Srbecky45aa5982016-03-18 02:15:09 +0000951TEST(StackMapTest, TestDeduplicateStackMask) {
952 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100953 ArenaStack arena_stack(&pool);
954 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100955 StackMapStream stream(&allocator, kRuntimeISA);
David Srbecky45aa5982016-03-18 02:15:09 +0000956
Vladimir Marko69d310e2017-10-09 14:12:23 +0100957 ArenaBitVector sp_mask(&allocator, 0, true);
David Srbecky45aa5982016-03-18 02:15:09 +0000958 sp_mask.SetBit(1);
959 sp_mask.SetBit(4);
960 stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
961 stream.EndStackMapEntry();
962 stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
963 stream.EndStackMapEntry();
964
965 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100966 void* memory = allocator.Alloc(size, kArenaAllocMisc);
David Srbecky45aa5982016-03-18 02:15:09 +0000967 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700968 stream.FillInCodeInfo(region);
David Srbecky45aa5982016-03-18 02:15:09 +0000969
970 CodeInfo code_info(region);
971 CodeInfoEncoding encoding = code_info.ExtractEncoding();
972 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
973
974 StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4, encoding);
975 StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8, encoding);
Mathieu Chartier575d3e62017-02-06 11:00:40 -0800976 EXPECT_EQ(stack_map1.GetStackMaskIndex(encoding.stack_map.encoding),
977 stack_map2.GetStackMaskIndex(encoding.stack_map.encoding));
David Srbecky45aa5982016-03-18 02:15:09 +0000978}
979
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800980TEST(StackMapTest, TestInvokeInfo) {
981 ArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100982 ArenaStack arena_stack(&pool);
983 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100984 StackMapStream stream(&allocator, kRuntimeISA);
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800985
Vladimir Marko69d310e2017-10-09 14:12:23 +0100986 ArenaBitVector sp_mask(&allocator, 0, true);
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800987 sp_mask.SetBit(1);
988 stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
989 stream.AddInvoke(kSuper, 1);
990 stream.EndStackMapEntry();
991 stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
992 stream.AddInvoke(kStatic, 3);
993 stream.EndStackMapEntry();
994 stream.BeginStackMapEntry(0, 16, 0x3, &sp_mask, 0, 0);
995 stream.AddInvoke(kDirect, 65535);
996 stream.EndStackMapEntry();
997
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700998 const size_t code_info_size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100999 MemoryRegion code_info_region(allocator.Alloc(code_info_size, kArenaAllocMisc), code_info_size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001000 stream.FillInCodeInfo(code_info_region);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001001
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001002 const size_t method_info_size = stream.ComputeMethodInfoSize();
Vladimir Marko69d310e2017-10-09 14:12:23 +01001003 MemoryRegion method_info_region(allocator.Alloc(method_info_size, kArenaAllocMisc),
1004 method_info_size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001005 stream.FillInMethodInfo(method_info_region);
1006
1007 CodeInfo code_info(code_info_region);
1008 MethodInfo method_info(method_info_region.begin());
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001009 CodeInfoEncoding encoding = code_info.ExtractEncoding();
1010 ASSERT_EQ(3u, code_info.GetNumberOfStackMaps(encoding));
1011
1012 InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4, encoding));
1013 InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8, encoding));
1014 InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16, encoding));
1015 InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12, encoding));
1016 EXPECT_FALSE(invoke_invalid.IsValid()); // No entry for that index.
1017 EXPECT_TRUE(invoke1.IsValid());
1018 EXPECT_TRUE(invoke2.IsValid());
1019 EXPECT_TRUE(invoke3.IsValid());
1020 EXPECT_EQ(invoke1.GetInvokeType(encoding.invoke_info.encoding), kSuper);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001021 EXPECT_EQ(invoke1.GetMethodIndex(encoding.invoke_info.encoding, method_info), 1u);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001022 EXPECT_EQ(invoke1.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 4u);
1023 EXPECT_EQ(invoke2.GetInvokeType(encoding.invoke_info.encoding), kStatic);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001024 EXPECT_EQ(invoke2.GetMethodIndex(encoding.invoke_info.encoding, method_info), 3u);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001025 EXPECT_EQ(invoke2.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 8u);
1026 EXPECT_EQ(invoke3.GetInvokeType(encoding.invoke_info.encoding), kDirect);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -07001027 EXPECT_EQ(invoke3.GetMethodIndex(encoding.invoke_info.encoding, method_info), 65535u);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001028 EXPECT_EQ(invoke3.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 16u);
1029}
1030
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001031} // namespace art