blob: 9db7588b3a3a256c873891880024c7554983ef5e [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"
David Sehr3215fff2018-04-03 17:10:12 -070021#include "base/malloc_arena_pool.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010022#include "stack_map_stream.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010023
24#include "gtest/gtest.h"
25
26namespace art {
27
David Srbecky09ed0982016-02-12 21:58:43 +000028// Check that the stack mask of given stack map is identical
29// to the given bit vector. Returns true if they are same.
30static bool CheckStackMask(
David Srbecky45aa5982016-03-18 02:15:09 +000031 const CodeInfo& code_info,
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 Srbecky052f8ca2018-04-26 15:42:54 +010034 BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
Vladimir Marko8b20b5c2018-05-29 15:32:55 +000035 if (bit_vector.GetNumberOfBits() > code_info.GetNumberOfStackMaskBits()) {
David Srbecky09ed0982016-02-12 21:58:43 +000036 return false;
37 }
Vladimir Marko8b20b5c2018-05-29 15:32:55 +000038 for (size_t i = 0; i < code_info.GetNumberOfStackMaskBits(); ++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) {
David Sehr3215fff2018-04-03 17:10:12 -070049 MallocArenaPool 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 Srbecky052f8ca2018-04-26 15:42:54 +010067 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010068
David Srbecky052f8ca2018-04-26 15:42:54 +010069 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
David Srbecky09ed0982016-02-12 21:58:43 +000070 ASSERT_EQ(2u, number_of_catalog_entries);
David Srbecky052f8ca2018-04-26 15:42:54 +010071 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
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 Srbecky052f8ca2018-04-26 15:42:54 +010078 StackMap stack_map = code_info.GetStackMapAt(0);
79 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
80 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
81 ASSERT_EQ(0u, stack_map.GetDexPc());
82 ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
83 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010084
David Srbecky052f8ca2018-04-26 15:42:54 +010085 ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010086
David Srbecky052f8ca2018-04-26 15:42:54 +010087 ASSERT_TRUE(stack_map.HasDexRegisterMap());
Roland Levillaina552e1c2015-03-26 15:01:03 +000088 DexRegisterMap dex_register_map =
David Srbecky052f8ca2018-04-26 15:42:54 +010089 code_info.GetDexRegisterMapOf(stack_map, 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(
David Srbecky052f8ca2018-04-26 15:42:54 +0100100 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100101 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100102 1, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100103 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100104 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100105 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100106 1, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100107 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
David Srbecky052f8ca2018-04-26 15:42:54 +0100108 0, number_of_dex_registers, code_info));
109 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
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
David Srbecky052f8ca2018-04-26 15:42:54 +0100126 ASSERT_FALSE(stack_map.HasInlineInfo());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100127}
128
129TEST(StackMapTest, Test2) {
David Sehr3215fff2018-04-03 17:10:12 -0700130 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100131 ArenaStack arena_stack(&pool);
132 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100133 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000134 ArtMethod art_method;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100135
Vladimir Marko69d310e2017-10-09 14:12:23 +0100136 ArenaBitVector sp_mask1(&allocator, 0, true);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100137 sp_mask1.SetBit(2);
138 sp_mask1.SetBit(4);
Roland Levillain12baf472015-03-05 12:41:42 +0000139 size_t number_of_dex_registers = 2;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100140 size_t number_of_dex_registers_in_inline_info = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100141 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100142 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
143 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000144 stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100145 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000146 stream.BeginInlineInfoEntry(&art_method, 2, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100147 stream.EndInlineInfoEntry();
Calin Juravle4f46ac52015-04-23 18:47:21 +0100148 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100149
Vladimir Marko69d310e2017-10-09 14:12:23 +0100150 ArenaBitVector sp_mask2(&allocator, 0, true);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100151 sp_mask2.SetBit(3);
David Brazdilf10a25f2015-06-02 14:29:52 +0100152 sp_mask2.SetBit(8);
Calin Juravle4f46ac52015-04-23 18:47:21 +0100153 stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100154 stream.AddDexRegisterEntry(Kind::kInRegister, 18); // Short location.
155 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100156 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100157
Vladimir Marko69d310e2017-10-09 14:12:23 +0100158 ArenaBitVector sp_mask3(&allocator, 0, true);
David Brazdild9cb68e2015-08-25 13:52:43 +0100159 sp_mask3.SetBit(1);
160 sp_mask3.SetBit(5);
161 stream.BeginStackMapEntry(2, 192, 0xAB, &sp_mask3, number_of_dex_registers, 0);
162 stream.AddDexRegisterEntry(Kind::kInRegister, 6); // Short location.
163 stream.AddDexRegisterEntry(Kind::kInRegisterHigh, 8); // Short location.
164 stream.EndStackMapEntry();
165
Vladimir Marko69d310e2017-10-09 14:12:23 +0100166 ArenaBitVector sp_mask4(&allocator, 0, true);
David Brazdild9cb68e2015-08-25 13:52:43 +0100167 sp_mask4.SetBit(6);
168 sp_mask4.SetBit(7);
169 stream.BeginStackMapEntry(3, 256, 0xCD, &sp_mask4, number_of_dex_registers, 0);
170 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location, same in stack map 2.
171 stream.AddDexRegisterEntry(Kind::kInFpuRegisterHigh, 1); // Short location.
172 stream.EndStackMapEntry();
173
Calin Juravle4f46ac52015-04-23 18:47:21 +0100174 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100175 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100176 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700177 stream.FillInCodeInfo(region);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100178
Nicolas Geoffray39468442014-09-02 15:17:15 +0100179 CodeInfo code_info(region);
David Srbecky052f8ca2018-04-26 15:42:54 +0100180 ASSERT_EQ(4u, code_info.GetNumberOfStackMaps());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100181
David Srbecky052f8ca2018-04-26 15:42:54 +0100182 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
David Srbecky09ed0982016-02-12 21:58:43 +0000183 ASSERT_EQ(7u, number_of_catalog_entries);
David Srbecky052f8ca2018-04-26 15:42:54 +0100184 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
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 Srbecky052f8ca2018-04-26 15:42:54 +0100193 StackMap stack_map = code_info.GetStackMapAt(0);
194 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
195 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
196 ASSERT_EQ(0u, stack_map.GetDexPc());
197 ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
198 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100199
David Srbecky052f8ca2018-04-26 15:42:54 +0100200 ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask1));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100201
David Srbecky052f8ca2018-04-26 15:42:54 +0100202 ASSERT_TRUE(stack_map.HasDexRegisterMap());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000203 DexRegisterMap dex_register_map =
David Srbecky052f8ca2018-04-26 15:42:54 +0100204 code_info.GetDexRegisterMapOf(stack_map, 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(
David Srbecky052f8ca2018-04-26 15:42:54 +0100215 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100216 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100217 1, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100218 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100219 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100220 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100221 1, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100222 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
David Srbecky052f8ca2018-04-26 15:42:54 +0100223 0, number_of_dex_registers, code_info));
224 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
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
David Srbecky052f8ca2018-04-26 15:42:54 +0100241 ASSERT_TRUE(stack_map.HasInlineInfo());
242 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
243 ASSERT_EQ(2u, inline_info.GetDepth());
244 ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(0));
245 ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(1));
246 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(0));
247 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(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 Srbecky052f8ca2018-04-26 15:42:54 +0100252 StackMap stack_map = code_info.GetStackMapAt(1);
253 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u)));
254 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u)));
255 ASSERT_EQ(1u, stack_map.GetDexPc());
256 ASSERT_EQ(128u, stack_map.GetNativePcOffset(kRuntimeISA));
257 ASSERT_EQ(0xFFu, code_info.GetRegisterMaskOf(stack_map));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100258
David Srbecky052f8ca2018-04-26 15:42:54 +0100259 ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask2));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100260
David Srbecky052f8ca2018-04-26 15:42:54 +0100261 ASSERT_TRUE(stack_map.HasDexRegisterMap());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000262 DexRegisterMap dex_register_map =
David Srbecky052f8ca2018-04-26 15:42:54 +0100263 code_info.GetDexRegisterMapOf(stack_map, 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(
David Srbecky052f8ca2018-04-26 15:42:54 +0100274 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100275 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100276 1, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100277 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100278 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100279 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100280 1, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100281 ASSERT_EQ(18, dex_register_map.GetMachineRegister(
David Srbecky052f8ca2018-04-26 15:42:54 +0100282 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100283 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
David Srbecky052f8ca2018-04-26 15:42:54 +0100284 1, number_of_dex_registers, code_info));
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
David Srbecky052f8ca2018-04-26 15:42:54 +0100301 ASSERT_FALSE(stack_map.HasInlineInfo());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000302 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100303
304 // Third stack map.
305 {
David Srbecky052f8ca2018-04-26 15:42:54 +0100306 StackMap stack_map = code_info.GetStackMapAt(2);
307 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u)));
308 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u)));
309 ASSERT_EQ(2u, stack_map.GetDexPc());
310 ASSERT_EQ(192u, stack_map.GetNativePcOffset(kRuntimeISA));
311 ASSERT_EQ(0xABu, code_info.GetRegisterMaskOf(stack_map));
David Brazdild9cb68e2015-08-25 13:52:43 +0100312
David Srbecky052f8ca2018-04-26 15:42:54 +0100313 ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask3));
David Brazdild9cb68e2015-08-25 13:52:43 +0100314
David Srbecky052f8ca2018-04-26 15:42:54 +0100315 ASSERT_TRUE(stack_map.HasDexRegisterMap());
David Brazdild9cb68e2015-08-25 13:52:43 +0100316 DexRegisterMap dex_register_map =
David Srbecky052f8ca2018-04-26 15:42:54 +0100317 code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
David Brazdild9cb68e2015-08-25 13:52:43 +0100318 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(
David Srbecky052f8ca2018-04-26 15:42:54 +0100328 0, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100329 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100330 1, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100331 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100332 0, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100333 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100334 1, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100335 ASSERT_EQ(6, dex_register_map.GetMachineRegister(
David Srbecky052f8ca2018-04-26 15:42:54 +0100336 0, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100337 ASSERT_EQ(8, dex_register_map.GetMachineRegister(
David Srbecky052f8ca2018-04-26 15:42:54 +0100338 1, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100339
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
David Srbecky052f8ca2018-04-26 15:42:54 +0100355 ASSERT_FALSE(stack_map.HasInlineInfo());
David Brazdild9cb68e2015-08-25 13:52:43 +0100356 }
357
358 // Fourth stack map.
359 {
David Srbecky052f8ca2018-04-26 15:42:54 +0100360 StackMap stack_map = code_info.GetStackMapAt(3);
361 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u)));
362 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u)));
363 ASSERT_EQ(3u, stack_map.GetDexPc());
364 ASSERT_EQ(256u, stack_map.GetNativePcOffset(kRuntimeISA));
365 ASSERT_EQ(0xCDu, code_info.GetRegisterMaskOf(stack_map));
David Brazdild9cb68e2015-08-25 13:52:43 +0100366
David Srbecky052f8ca2018-04-26 15:42:54 +0100367 ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask4));
David Brazdild9cb68e2015-08-25 13:52:43 +0100368
David Srbecky052f8ca2018-04-26 15:42:54 +0100369 ASSERT_TRUE(stack_map.HasDexRegisterMap());
David Brazdild9cb68e2015-08-25 13:52:43 +0100370 DexRegisterMap dex_register_map =
David Srbecky052f8ca2018-04-26 15:42:54 +0100371 code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
David Brazdild9cb68e2015-08-25 13:52:43 +0100372 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(
David Srbecky052f8ca2018-04-26 15:42:54 +0100382 0, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100383 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100384 1, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100385 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100386 0, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100387 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100388 1, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100389 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
David Srbecky052f8ca2018-04-26 15:42:54 +0100390 0, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100391 ASSERT_EQ(1, dex_register_map.GetMachineRegister(
David Srbecky052f8ca2018-04-26 15:42:54 +0100392 1, number_of_dex_registers, code_info));
David Brazdild9cb68e2015-08-25 13:52:43 +0100393
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
David Srbecky052f8ca2018-04-26 15:42:54 +0100409 ASSERT_FALSE(stack_map.HasInlineInfo());
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) {
David Sehr3215fff2018-04-03 17:10:12 -0700414 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100415 ArenaStack arena_stack(&pool);
416 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100417 StackMapStream stream(&allocator, kRuntimeISA);
Mathieu Chartier32289082017-02-09 15:57:37 -0800418 ArtMethod art_method;
419
Vladimir Marko69d310e2017-10-09 14:12:23 +0100420 ArenaBitVector sp_mask1(&allocator, 0, true);
Mathieu Chartier32289082017-02-09 15:57:37 -0800421 sp_mask1.SetBit(2);
422 sp_mask1.SetBit(4);
423 const size_t number_of_dex_registers = 2;
424 const size_t number_of_dex_registers_in_inline_info = 2;
425 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 1);
426 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
427 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
428 stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
429 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
430 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
431 stream.EndInlineInfoEntry();
432 stream.EndStackMapEntry();
433
434 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100435 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Mathieu Chartier32289082017-02-09 15:57:37 -0800436 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700437 stream.FillInCodeInfo(region);
Mathieu Chartier32289082017-02-09 15:57:37 -0800438
439 CodeInfo code_info(region);
David Srbecky052f8ca2018-04-26 15:42:54 +0100440 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
Mathieu Chartier32289082017-02-09 15:57:37 -0800441
David Srbecky052f8ca2018-04-26 15:42:54 +0100442 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
Mathieu Chartier32289082017-02-09 15:57:37 -0800443 ASSERT_EQ(2u, number_of_catalog_entries);
David Srbecky052f8ca2018-04-26 15:42:54 +0100444 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
Mathieu Chartier32289082017-02-09 15:57:37 -0800445 // 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 {
David Srbecky052f8ca2018-04-26 15:42:54 +0100453 StackMap stack_map = code_info.GetStackMapAt(0);
454 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
455 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
456 ASSERT_EQ(0u, stack_map.GetDexPc());
457 ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
458 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
Mathieu Chartier32289082017-02-09 15:57:37 -0800459
David Srbecky052f8ca2018-04-26 15:42:54 +0100460 ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask1));
Mathieu Chartier32289082017-02-09 15:57:37 -0800461
David Srbecky052f8ca2018-04-26 15:42:54 +0100462 ASSERT_TRUE(stack_map.HasDexRegisterMap());
463 DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers));
Mathieu Chartier32289082017-02-09 15:57:37 -0800464 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
David Srbecky052f8ca2018-04-26 15:42:54 +0100473 ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0, number_of_dex_registers, code_info));
Mathieu Chartier32289082017-02-09 15:57:37 -0800474 ASSERT_EQ(Kind::kConstant,
David Srbecky052f8ca2018-04-26 15:42:54 +0100475 map.GetLocationKind(1, number_of_dex_registers, code_info));
Mathieu Chartier32289082017-02-09 15:57:37 -0800476 ASSERT_EQ(Kind::kInStack,
David Srbecky052f8ca2018-04-26 15:42:54 +0100477 map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
Mathieu Chartier32289082017-02-09 15:57:37 -0800478 ASSERT_EQ(Kind::kConstantLargeValue,
David Srbecky052f8ca2018-04-26 15:42:54 +0100479 map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
480 ASSERT_EQ(0, map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info));
481 ASSERT_EQ(-2, map.GetConstant(1, number_of_dex_registers, code_info));
Mathieu Chartier32289082017-02-09 15:57:37 -0800482
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.
David Srbecky052f8ca2018-04-26 15:42:54 +0100500 ASSERT_TRUE(stack_map.HasInlineInfo());
501 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
502 EXPECT_EQ(inline_info.GetDexRegisterMapOffsetAtDepth(0),
503 stack_map.GetDexRegisterMapOffset());
Mathieu Chartier32289082017-02-09 15:57:37 -0800504 }
505}
506
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000507TEST(StackMapTest, TestNonLiveDexRegisters) {
David Sehr3215fff2018-04-03 17:10:12 -0700508 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100509 ArenaStack arena_stack(&pool);
510 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100511 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000512
Vladimir Marko69d310e2017-10-09 14:12:23 +0100513 ArenaBitVector sp_mask(&allocator, 0, false);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000514 uint32_t number_of_dex_registers = 2;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100515 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100516 stream.AddDexRegisterEntry(Kind::kNone, 0); // No location.
517 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100518 stream.EndStackMapEntry();
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000519
Calin Juravle4f46ac52015-04-23 18:47:21 +0100520 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100521 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000522 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700523 stream.FillInCodeInfo(region);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000524
525 CodeInfo code_info(region);
David Srbecky052f8ca2018-04-26 15:42:54 +0100526 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000527
David Srbecky052f8ca2018-04-26 15:42:54 +0100528 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
David Srbecky09ed0982016-02-12 21:58:43 +0000529 ASSERT_EQ(1u, number_of_catalog_entries);
David Srbecky052f8ca2018-04-26 15:42:54 +0100530 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
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 Srbecky052f8ca2018-04-26 15:42:54 +0100536 StackMap stack_map = code_info.GetStackMapAt(0);
537 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
538 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
539 ASSERT_EQ(0u, stack_map.GetDexPc());
540 ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
541 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000542
David Srbecky052f8ca2018-04-26 15:42:54 +0100543 ASSERT_TRUE(stack_map.HasDexRegisterMap());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000544 DexRegisterMap dex_register_map =
David Srbecky052f8ca2018-04-26 15:42:54 +0100545 code_info.GetDexRegisterMapOf(stack_map, 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(
David Srbecky052f8ca2018-04-26 15:42:54 +0100556 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100557 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100558 1, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100559 ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100560 0, number_of_dex_registers, code_info));
David Brazdilf677ebf2015-05-29 16:29:43 +0100561 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
David Srbecky052f8ca2018-04-26 15:42:54 +0100562 1, number_of_dex_registers, code_info));
563 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
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
David Srbecky052f8ca2018-04-26 15:42:54 +0100580 ASSERT_FALSE(stack_map.HasInlineInfo());
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) {
David Sehr3215fff2018-04-03 17:10:12 -0700587 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100588 ArenaStack arena_stack(&pool);
589 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100590 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000591
Vladimir Marko69d310e2017-10-09 14:12:23 +0100592 ArenaBitVector sp_mask(&allocator, 0, false);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000593 uint32_t number_of_dex_registers = 1024;
594 // Create the first stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100595 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000596 uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
597 for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
598 // Use two different Dex register locations to populate this map,
599 // as using a single value (in the whole CodeInfo object) would
600 // make this Dex register mapping data empty (see
601 // art::DexRegisterMap::SingleEntrySizeInBits).
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100602 stream.AddDexRegisterEntry(Kind::kConstant, i % 2); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000603 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100604 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000605 // Create the second stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100606 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000607 for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100608 stream.AddDexRegisterEntry(Kind::kConstant, 0); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000609 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100610 stream.EndStackMapEntry();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000611
Calin Juravle4f46ac52015-04-23 18:47:21 +0100612 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100613 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000614 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700615 stream.FillInCodeInfo(region);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000616
617 CodeInfo code_info(region);
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 Srbecky052f8ca2018-04-26 15:42:54 +0100621 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
David Srbecky09ed0982016-02-12 21:58:43 +0000622 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 Srbecky052f8ca2018-04-26 15:42:54 +0100632 StackMap stack_map0 = code_info.GetStackMapAt(0);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000633 DexRegisterMap dex_register_map0 =
David Srbecky052f8ca2018-04-26 15:42:54 +0100634 code_info.GetDexRegisterMapOf(stack_map0, 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 Srbecky052f8ca2018-04-26 15:42:54 +0100639 StackMap stack_map1 = code_info.GetStackMapAt(1);
640 ASSERT_TRUE(stack_map1.HasDexRegisterMap());
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).
David Srbecky052f8ca2018-04-26 15:42:54 +0100644 ASSERT_NE(stack_map1.GetDexRegisterMapOffset(),
645 StackMap::kNoValue);
646 ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(), 0xFFu);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000647}
648
Calin Juravle6ae70962015-03-18 16:31:28 +0000649TEST(StackMapTest, TestShareDexRegisterMap) {
David Sehr3215fff2018-04-03 17:10:12 -0700650 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100651 ArenaStack arena_stack(&pool);
652 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100653 StackMapStream stream(&allocator, kRuntimeISA);
Calin Juravle6ae70962015-03-18 16:31:28 +0000654
Vladimir Marko69d310e2017-10-09 14:12:23 +0100655 ArenaBitVector sp_mask(&allocator, 0, false);
Calin Juravle6ae70962015-03-18 16:31:28 +0000656 uint32_t number_of_dex_registers = 2;
657 // First stack map.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100658 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100659 stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
660 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100661 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000662 // Second stack map, which should share the same dex register 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 // Third stack map (doesn't share the 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, 2); // 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
Calin Juravle4f46ac52015-04-23 18:47:21 +0100673 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100674 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Calin Juravle6ae70962015-03-18 16:31:28 +0000675 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700676 stream.FillInCodeInfo(region);
Calin Juravle6ae70962015-03-18 16:31:28 +0000677
678 CodeInfo ci(region);
David Brazdilf677ebf2015-05-29 16:29:43 +0100679
Calin Juravle6ae70962015-03-18 16:31:28 +0000680 // Verify first stack map.
David Srbecky052f8ca2018-04-26 15:42:54 +0100681 StackMap sm0 = ci.GetStackMapAt(0);
682 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, number_of_dex_registers);
683 ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci));
684 ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci));
Calin Juravle6ae70962015-03-18 16:31:28 +0000685
686 // Verify second stack map.
David Srbecky052f8ca2018-04-26 15:42:54 +0100687 StackMap sm1 = ci.GetStackMapAt(1);
688 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, number_of_dex_registers);
689 ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci));
690 ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci));
Calin Juravle6ae70962015-03-18 16:31:28 +0000691
692 // Verify third stack map.
David Srbecky052f8ca2018-04-26 15:42:54 +0100693 StackMap sm2 = ci.GetStackMapAt(2);
694 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, number_of_dex_registers);
695 ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci));
696 ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci));
Calin Juravle6ae70962015-03-18 16:31:28 +0000697
698 // Verify dex register map offsets.
David Srbecky052f8ca2018-04-26 15:42:54 +0100699 ASSERT_EQ(sm0.GetDexRegisterMapOffset(),
700 sm1.GetDexRegisterMapOffset());
701 ASSERT_NE(sm0.GetDexRegisterMapOffset(),
702 sm2.GetDexRegisterMapOffset());
703 ASSERT_NE(sm1.GetDexRegisterMapOffset(),
704 sm2.GetDexRegisterMapOffset());
Calin Juravle6ae70962015-03-18 16:31:28 +0000705}
706
Roland Levillaina552e1c2015-03-26 15:01:03 +0000707TEST(StackMapTest, TestNoDexRegisterMap) {
David Sehr3215fff2018-04-03 17:10:12 -0700708 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100709 ArenaStack arena_stack(&pool);
710 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100711 StackMapStream stream(&allocator, kRuntimeISA);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000712
Vladimir Marko69d310e2017-10-09 14:12:23 +0100713 ArenaBitVector sp_mask(&allocator, 0, false);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000714 uint32_t number_of_dex_registers = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100715 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
716 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000717
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000718 number_of_dex_registers = 1;
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800719 stream.BeginStackMapEntry(1, 68, 0x4, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000720 stream.EndStackMapEntry();
721
Calin Juravle4f46ac52015-04-23 18:47:21 +0100722 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100723 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000724 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700725 stream.FillInCodeInfo(region);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000726
727 CodeInfo code_info(region);
David Srbecky052f8ca2018-04-26 15:42:54 +0100728 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000729
David Srbecky052f8ca2018-04-26 15:42:54 +0100730 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
David Srbecky09ed0982016-02-12 21:58:43 +0000731 ASSERT_EQ(0u, number_of_catalog_entries);
David Srbecky052f8ca2018-04-26 15:42:54 +0100732 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000733 ASSERT_EQ(0u, location_catalog.Size());
734
David Srbecky052f8ca2018-04-26 15:42:54 +0100735 StackMap stack_map = code_info.GetStackMapAt(0);
736 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
737 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
738 ASSERT_EQ(0u, stack_map.GetDexPc());
739 ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
740 ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000741
David Srbecky052f8ca2018-04-26 15:42:54 +0100742 ASSERT_FALSE(stack_map.HasDexRegisterMap());
743 ASSERT_FALSE(stack_map.HasInlineInfo());
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000744
David Srbecky052f8ca2018-04-26 15:42:54 +0100745 stack_map = code_info.GetStackMapAt(1);
746 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1)));
747 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68)));
748 ASSERT_EQ(1u, stack_map.GetDexPc());
749 ASSERT_EQ(68u, stack_map.GetNativePcOffset(kRuntimeISA));
750 ASSERT_EQ(0x4u, code_info.GetRegisterMaskOf(stack_map));
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000751
David Srbecky052f8ca2018-04-26 15:42:54 +0100752 ASSERT_FALSE(stack_map.HasDexRegisterMap());
753 ASSERT_FALSE(stack_map.HasInlineInfo());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000754}
755
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100756TEST(StackMapTest, InlineTest) {
David Sehr3215fff2018-04-03 17:10:12 -0700757 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100758 ArenaStack arena_stack(&pool);
759 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100760 StackMapStream stream(&allocator, kRuntimeISA);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000761 ArtMethod art_method;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100762
Vladimir Marko69d310e2017-10-09 14:12:23 +0100763 ArenaBitVector sp_mask1(&allocator, 0, true);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100764 sp_mask1.SetBit(2);
765 sp_mask1.SetBit(4);
766
767 // First stack map.
768 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, 2, 2);
769 stream.AddDexRegisterEntry(Kind::kInStack, 0);
770 stream.AddDexRegisterEntry(Kind::kConstant, 4);
771
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000772 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100773 stream.AddDexRegisterEntry(Kind::kInStack, 8);
774 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000775 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100776 stream.AddDexRegisterEntry(Kind::kInStack, 16);
777 stream.AddDexRegisterEntry(Kind::kConstant, 20);
778 stream.AddDexRegisterEntry(Kind::kInRegister, 15);
779 stream.EndInlineInfoEntry();
780
781 stream.EndStackMapEntry();
782
783 // Second stack map.
784 stream.BeginStackMapEntry(2, 22, 0x3, &sp_mask1, 2, 3);
785 stream.AddDexRegisterEntry(Kind::kInStack, 56);
786 stream.AddDexRegisterEntry(Kind::kConstant, 0);
787
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000788 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100789 stream.AddDexRegisterEntry(Kind::kInStack, 12);
790 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000791 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100792 stream.AddDexRegisterEntry(Kind::kInStack, 80);
793 stream.AddDexRegisterEntry(Kind::kConstant, 10);
794 stream.AddDexRegisterEntry(Kind::kInRegister, 5);
795 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000796 stream.BeginInlineInfoEntry(&art_method, 5, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100797 stream.EndInlineInfoEntry();
798
799 stream.EndStackMapEntry();
800
801 // Third stack map.
802 stream.BeginStackMapEntry(4, 56, 0x3, &sp_mask1, 2, 0);
803 stream.AddDexRegisterEntry(Kind::kNone, 0);
804 stream.AddDexRegisterEntry(Kind::kConstant, 4);
805 stream.EndStackMapEntry();
806
807 // Fourth stack map.
808 stream.BeginStackMapEntry(6, 78, 0x3, &sp_mask1, 2, 3);
809 stream.AddDexRegisterEntry(Kind::kInStack, 56);
810 stream.AddDexRegisterEntry(Kind::kConstant, 0);
811
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000812 stream.BeginInlineInfoEntry(&art_method, 2, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100813 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000814 stream.BeginInlineInfoEntry(&art_method, 5, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100815 stream.AddDexRegisterEntry(Kind::kInRegister, 2);
816 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000817 stream.BeginInlineInfoEntry(&art_method, 10, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100818 stream.AddDexRegisterEntry(Kind::kNone, 0);
819 stream.AddDexRegisterEntry(Kind::kInRegister, 3);
820 stream.EndInlineInfoEntry();
821
822 stream.EndStackMapEntry();
823
824 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100825 void* memory = allocator.Alloc(size, kArenaAllocMisc);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100826 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700827 stream.FillInCodeInfo(region);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100828
829 CodeInfo ci(region);
830
831 {
832 // Verify first stack map.
David Srbecky052f8ca2018-04-26 15:42:54 +0100833 StackMap sm0 = ci.GetStackMapAt(0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100834
David Srbecky052f8ca2018-04-26 15:42:54 +0100835 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, 2);
836 ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
837 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100838
David Srbecky052f8ca2018-04-26 15:42:54 +0100839 InlineInfo if0 = ci.GetInlineInfoOf(sm0);
840 ASSERT_EQ(2u, if0.GetDepth());
841 ASSERT_EQ(2u, if0.GetDexPcAtDepth(0));
842 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(0));
843 ASSERT_EQ(3u, if0.GetDexPcAtDepth(1));
844 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(1));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100845
David Srbecky052f8ca2018-04-26 15:42:54 +0100846 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, 1);
847 ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100848
David Srbecky052f8ca2018-04-26 15:42:54 +0100849 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, 3);
850 ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci));
851 ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci));
852 ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100853 }
854
855 {
856 // Verify second stack map.
David Srbecky052f8ca2018-04-26 15:42:54 +0100857 StackMap sm1 = ci.GetStackMapAt(1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100858
David Srbecky052f8ca2018-04-26 15:42:54 +0100859 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, 2);
860 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
861 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100862
David Srbecky052f8ca2018-04-26 15:42:54 +0100863 InlineInfo if1 = ci.GetInlineInfoOf(sm1);
864 ASSERT_EQ(3u, if1.GetDepth());
865 ASSERT_EQ(2u, if1.GetDexPcAtDepth(0));
866 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(0));
867 ASSERT_EQ(3u, if1.GetDexPcAtDepth(1));
868 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(1));
869 ASSERT_EQ(5u, if1.GetDexPcAtDepth(2));
870 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100871
David Srbecky052f8ca2018-04-26 15:42:54 +0100872 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, 1);
873 ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100874
David Srbecky052f8ca2018-04-26 15:42:54 +0100875 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, 3);
876 ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci));
877 ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci));
878 ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100879
David Srbecky052f8ca2018-04-26 15:42:54 +0100880 ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100881 }
882
883 {
884 // Verify third stack map.
David Srbecky052f8ca2018-04-26 15:42:54 +0100885 StackMap sm2 = ci.GetStackMapAt(2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100886
David Srbecky052f8ca2018-04-26 15:42:54 +0100887 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100888 ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
David Srbecky052f8ca2018-04-26 15:42:54 +0100889 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci));
890 ASSERT_FALSE(sm2.HasInlineInfo());
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100891 }
892
893 {
894 // Verify fourth stack map.
David Srbecky052f8ca2018-04-26 15:42:54 +0100895 StackMap sm3 = ci.GetStackMapAt(3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100896
David Srbecky052f8ca2018-04-26 15:42:54 +0100897 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, 2);
898 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
899 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100900
David Srbecky052f8ca2018-04-26 15:42:54 +0100901 InlineInfo if2 = ci.GetInlineInfoOf(sm3);
902 ASSERT_EQ(3u, if2.GetDepth());
903 ASSERT_EQ(2u, if2.GetDexPcAtDepth(0));
904 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(0));
905 ASSERT_EQ(5u, if2.GetDexPcAtDepth(1));
906 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(1));
907 ASSERT_EQ(10u, if2.GetDexPcAtDepth(2));
908 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100909
David Srbecky052f8ca2018-04-26 15:42:54 +0100910 ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100911
David Srbecky052f8ca2018-04-26 15:42:54 +0100912 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, 1);
913 ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100914
David Srbecky052f8ca2018-04-26 15:42:54 +0100915 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100916 ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
David Srbecky052f8ca2018-04-26 15:42:54 +0100917 ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100918 }
919}
920
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800921TEST(StackMapTest, CodeOffsetTest) {
David Srbecky052f8ca2018-04-26 15:42:54 +0100922 // Test minimum alignments, and decoding.
Vladimir Marko33bff252017-11-01 14:35:42 +0000923 CodeOffset offset_thumb2 =
924 CodeOffset::FromOffset(kThumb2InstructionAlignment, InstructionSet::kThumb2);
925 CodeOffset offset_arm64 =
926 CodeOffset::FromOffset(kArm64InstructionAlignment, InstructionSet::kArm64);
927 CodeOffset offset_x86 =
928 CodeOffset::FromOffset(kX86InstructionAlignment, InstructionSet::kX86);
929 CodeOffset offset_x86_64 =
930 CodeOffset::FromOffset(kX86_64InstructionAlignment, InstructionSet::kX86_64);
931 CodeOffset offset_mips =
932 CodeOffset::FromOffset(kMipsInstructionAlignment, InstructionSet::kMips);
933 CodeOffset offset_mips64 =
934 CodeOffset::FromOffset(kMips64InstructionAlignment, InstructionSet::kMips64);
935 EXPECT_EQ(offset_thumb2.Uint32Value(InstructionSet::kThumb2), kThumb2InstructionAlignment);
936 EXPECT_EQ(offset_arm64.Uint32Value(InstructionSet::kArm64), kArm64InstructionAlignment);
937 EXPECT_EQ(offset_x86.Uint32Value(InstructionSet::kX86), kX86InstructionAlignment);
938 EXPECT_EQ(offset_x86_64.Uint32Value(InstructionSet::kX86_64), kX86_64InstructionAlignment);
939 EXPECT_EQ(offset_mips.Uint32Value(InstructionSet::kMips), kMipsInstructionAlignment);
940 EXPECT_EQ(offset_mips64.Uint32Value(InstructionSet::kMips64), kMips64InstructionAlignment);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800941}
942
David Srbecky45aa5982016-03-18 02:15:09 +0000943TEST(StackMapTest, TestDeduplicateStackMask) {
David Sehr3215fff2018-04-03 17:10:12 -0700944 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100945 ArenaStack arena_stack(&pool);
946 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100947 StackMapStream stream(&allocator, kRuntimeISA);
David Srbecky45aa5982016-03-18 02:15:09 +0000948
Vladimir Marko69d310e2017-10-09 14:12:23 +0100949 ArenaBitVector sp_mask(&allocator, 0, true);
David Srbecky45aa5982016-03-18 02:15:09 +0000950 sp_mask.SetBit(1);
951 sp_mask.SetBit(4);
952 stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
953 stream.EndStackMapEntry();
954 stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
955 stream.EndStackMapEntry();
956
957 size_t size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100958 void* memory = allocator.Alloc(size, kArenaAllocMisc);
David Srbecky45aa5982016-03-18 02:15:09 +0000959 MemoryRegion region(memory, size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700960 stream.FillInCodeInfo(region);
David Srbecky45aa5982016-03-18 02:15:09 +0000961
962 CodeInfo code_info(region);
David Srbecky052f8ca2018-04-26 15:42:54 +0100963 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
David Srbecky45aa5982016-03-18 02:15:09 +0000964
David Srbecky052f8ca2018-04-26 15:42:54 +0100965 StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4);
966 StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8);
967 EXPECT_EQ(stack_map1.GetStackMaskIndex(),
968 stack_map2.GetStackMaskIndex());
David Srbecky45aa5982016-03-18 02:15:09 +0000969}
970
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800971TEST(StackMapTest, TestInvokeInfo) {
David Sehr3215fff2018-04-03 17:10:12 -0700972 MallocArenaPool pool;
Vladimir Marko174b2e22017-10-12 13:34:49 +0100973 ArenaStack arena_stack(&pool);
974 ScopedArenaAllocator allocator(&arena_stack);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100975 StackMapStream stream(&allocator, kRuntimeISA);
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800976
Vladimir Marko69d310e2017-10-09 14:12:23 +0100977 ArenaBitVector sp_mask(&allocator, 0, true);
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800978 sp_mask.SetBit(1);
979 stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
980 stream.AddInvoke(kSuper, 1);
981 stream.EndStackMapEntry();
982 stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
983 stream.AddInvoke(kStatic, 3);
984 stream.EndStackMapEntry();
985 stream.BeginStackMapEntry(0, 16, 0x3, &sp_mask, 0, 0);
986 stream.AddInvoke(kDirect, 65535);
987 stream.EndStackMapEntry();
988
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700989 const size_t code_info_size = stream.PrepareForFillIn();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100990 MemoryRegion code_info_region(allocator.Alloc(code_info_size, kArenaAllocMisc), code_info_size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700991 stream.FillInCodeInfo(code_info_region);
Mathieu Chartierd776ff02017-01-17 09:32:18 -0800992
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700993 const size_t method_info_size = stream.ComputeMethodInfoSize();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100994 MemoryRegion method_info_region(allocator.Alloc(method_info_size, kArenaAllocMisc),
995 method_info_size);
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700996 stream.FillInMethodInfo(method_info_region);
997
998 CodeInfo code_info(code_info_region);
999 MethodInfo method_info(method_info_region.begin());
David Srbecky052f8ca2018-04-26 15:42:54 +01001000 ASSERT_EQ(3u, code_info.GetNumberOfStackMaps());
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001001
David Srbecky052f8ca2018-04-26 15:42:54 +01001002 InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4));
1003 InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8));
1004 InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16));
1005 InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12));
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001006 EXPECT_FALSE(invoke_invalid.IsValid()); // No entry for that index.
1007 EXPECT_TRUE(invoke1.IsValid());
1008 EXPECT_TRUE(invoke2.IsValid());
1009 EXPECT_TRUE(invoke3.IsValid());
David Srbecky052f8ca2018-04-26 15:42:54 +01001010 EXPECT_EQ(invoke1.GetInvokeType(), kSuper);
1011 EXPECT_EQ(invoke1.GetMethodIndex(method_info), 1u);
1012 EXPECT_EQ(invoke1.GetNativePcOffset(kRuntimeISA), 4u);
1013 EXPECT_EQ(invoke2.GetInvokeType(), kStatic);
1014 EXPECT_EQ(invoke2.GetMethodIndex(method_info), 3u);
1015 EXPECT_EQ(invoke2.GetNativePcOffset(kRuntimeISA), 8u);
1016 EXPECT_EQ(invoke3.GetInvokeType(), kDirect);
1017 EXPECT_EQ(invoke3.GetMethodIndex(method_info), 65535u);
1018 EXPECT_EQ(invoke3.GetNativePcOffset(kRuntimeISA), 16u);
Mathieu Chartierd776ff02017-01-17 09:32:18 -08001019}
1020
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001021} // namespace art