summaryrefslogtreecommitdiffstats
path: root/runtime/stack_map.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/stack_map.cc')
-rw-r--r--runtime/stack_map.cc249
1 files changed, 164 insertions, 85 deletions
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 020a6e6..11e7e44 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -16,133 +16,198 @@
#include "stack_map.h"
+#include <stdint.h>
+
namespace art {
-constexpr uint32_t StackMap::kNoDexRegisterMapSmallEncoding;
-constexpr uint32_t StackMap::kNoInlineInfoSmallEncoding;
+constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
constexpr uint32_t StackMap::kNoDexRegisterMap;
constexpr uint32_t StackMap::kNoInlineInfo;
+DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_register_number,
+ uint16_t number_of_dex_registers,
+ const CodeInfo& code_info) const {
+ DexRegisterLocationCatalog dex_register_location_catalog =
+ code_info.GetDexRegisterLocationCatalog();
+ size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
+ dex_register_number,
+ number_of_dex_registers,
+ code_info.GetNumberOfDexRegisterLocationCatalogEntries());
+ return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
+}
+
+DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
+ uint16_t number_of_dex_registers,
+ const CodeInfo& code_info) const {
+ DexRegisterLocationCatalog dex_register_location_catalog =
+ code_info.GetDexRegisterLocationCatalog();
+ size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
+ dex_register_number,
+ number_of_dex_registers,
+ code_info.GetNumberOfDexRegisterLocationCatalogEntries());
+ return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
+}
+
+// Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true,
+// this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF.
+static uint32_t LoadAt(MemoryRegion region,
+ size_t number_of_bytes,
+ size_t offset,
+ bool check_max = false) {
+ if (number_of_bytes == 0u) {
+ DCHECK(!check_max);
+ return 0;
+ } else if (number_of_bytes == 1u) {
+ uint8_t value = region.LoadUnaligned<uint8_t>(offset);
+ if (check_max && value == 0xFF) {
+ return -1;
+ } else {
+ return value;
+ }
+ } else if (number_of_bytes == 2u) {
+ uint16_t value = region.LoadUnaligned<uint16_t>(offset);
+ if (check_max && value == 0xFFFF) {
+ return -1;
+ } else {
+ return value;
+ }
+ } else if (number_of_bytes == 3u) {
+ uint16_t low = region.LoadUnaligned<uint16_t>(offset);
+ uint16_t high = region.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t));
+ uint32_t value = (high << 16) + low;
+ if (check_max && value == 0xFFFFFF) {
+ return -1;
+ } else {
+ return value;
+ }
+ } else {
+ DCHECK_EQ(number_of_bytes, 4u);
+ return region.LoadUnaligned<uint32_t>(offset);
+ }
+}
+
+static void StoreAt(MemoryRegion region, size_t number_of_bytes, size_t offset, uint32_t value) {
+ if (number_of_bytes == 0u) {
+ DCHECK_EQ(value, 0u);
+ } else if (number_of_bytes == 1u) {
+ region.StoreUnaligned<uint8_t>(offset, value);
+ } else if (number_of_bytes == 2u) {
+ region.StoreUnaligned<uint16_t>(offset, value);
+ } else if (number_of_bytes == 3u) {
+ region.StoreUnaligned<uint16_t>(offset, Low16Bits(value));
+ region.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value));
+ } else {
+ region.StoreUnaligned<uint32_t>(offset, value);
+ DCHECK_EQ(number_of_bytes, 4u);
+ }
+}
+
uint32_t StackMap::GetDexPc(const CodeInfo& info) const {
- return info.HasSmallDexPc()
- ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset())
- : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset());
+ return LoadAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset());
}
void StackMap::SetDexPc(const CodeInfo& info, uint32_t dex_pc) {
- DCHECK(!info.HasSmallDexPc() || IsUint<kBitsForSmallEncoding>(dex_pc)) << dex_pc;
- info.HasSmallDexPc()
- ? region_.StoreUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc)
- : region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc);
+ StoreAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset(), dex_pc);
}
uint32_t StackMap::GetNativePcOffset(const CodeInfo& info) const {
- return info.HasSmallNativePc()
- ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapNativePcOffset())
- : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapNativePcOffset());
+ return LoadAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset());
}
void StackMap::SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset) {
- DCHECK(!info.HasSmallNativePc()
- || IsUint<kBitsForSmallEncoding>(native_pc_offset)) << native_pc_offset;
- uint32_t entry = info.ComputeStackMapNativePcOffset();
- info.HasSmallNativePc()
- ? region_.StoreUnaligned<kSmallEncoding>(entry, native_pc_offset)
- : region_.StoreUnaligned<kLargeEncoding>(entry, native_pc_offset);
+ StoreAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset(), native_pc_offset);
}
uint32_t StackMap::GetDexRegisterMapOffset(const CodeInfo& info) const {
- if (info.HasSmallDexRegisterMap()) {
- uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
- info.ComputeStackMapDexRegisterMapOffset());
- if (value == kNoDexRegisterMapSmallEncoding) {
- return kNoDexRegisterMap;
- } else {
- return value;
- }
- } else {
- return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexRegisterMapOffset());
- }
+ return LoadAt(region_,
+ info.NumberOfBytesForDexRegisterMap(),
+ info.ComputeStackMapDexRegisterMapOffset(),
+ /* check_max */ true);
}
void StackMap::SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset) {
- DCHECK(!info.HasSmallDexRegisterMap()
- || (IsUint<kBitsForSmallEncoding>(offset)
- || (offset == kNoDexRegisterMap))) << offset;
- size_t dex_register_map_entry = info.ComputeStackMapDexRegisterMapOffset();
- info.HasSmallDexRegisterMap()
- ? region_.StoreUnaligned<kSmallEncoding>(dex_register_map_entry, offset)
- : region_.StoreUnaligned<kLargeEncoding>(dex_register_map_entry, offset);
+ StoreAt(region_,
+ info.NumberOfBytesForDexRegisterMap(),
+ info.ComputeStackMapDexRegisterMapOffset(),
+ offset);
}
uint32_t StackMap::GetInlineDescriptorOffset(const CodeInfo& info) const {
if (!info.HasInlineInfo()) return kNoInlineInfo;
- if (info.HasSmallInlineInfo()) {
- uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
- info.ComputeStackMapInlineInfoOffset());
- if (value == kNoInlineInfoSmallEncoding) {
- return kNoInlineInfo;
- } else {
- return value;
- }
- } else {
- return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapInlineInfoOffset());
- }
+ return LoadAt(region_,
+ info.NumberOfBytesForInlineInfo(),
+ info.ComputeStackMapInlineInfoOffset(),
+ /* check_max */ true);
}
void StackMap::SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset) {
DCHECK(info.HasInlineInfo());
- DCHECK(!info.HasSmallInlineInfo()
- || (IsUint<kBitsForSmallEncoding>(offset)
- || (offset == kNoInlineInfo))) << offset;
- size_t inline_entry = info.ComputeStackMapInlineInfoOffset();
- info.HasSmallInlineInfo()
- ? region_.StoreUnaligned<kSmallEncoding>(inline_entry, offset)
- : region_.StoreUnaligned<kLargeEncoding>(inline_entry, offset);
+ StoreAt(region_,
+ info.NumberOfBytesForInlineInfo(),
+ info.ComputeStackMapInlineInfoOffset(),
+ offset);
}
uint32_t StackMap::GetRegisterMask(const CodeInfo& info) const {
- return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset());
+ return LoadAt(region_,
+ info.NumberOfBytesForRegisterMask(),
+ info.ComputeStackMapRegisterMaskOffset());
}
void StackMap::SetRegisterMask(const CodeInfo& info, uint32_t mask) {
- region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset(), mask);
+ StoreAt(region_,
+ info.NumberOfBytesForRegisterMask(),
+ info.ComputeStackMapRegisterMaskOffset(),
+ mask);
}
-size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
- bool has_inline_info,
- bool is_small_inline_info,
- bool is_small_dex_map,
- bool is_small_dex_pc,
- bool is_small_native_pc) {
- return StackMap::kFixedSize
- + stack_mask_size
- + (has_inline_info ? NumberOfBytesForEntry(is_small_inline_info) : 0)
- + NumberOfBytesForEntry(is_small_dex_map)
- + NumberOfBytesForEntry(is_small_dex_pc)
- + NumberOfBytesForEntry(is_small_native_pc);
+size_t StackMap::ComputeStackMapSizeInternal(size_t stack_mask_size,
+ size_t number_of_bytes_for_inline_info,
+ size_t number_of_bytes_for_dex_map,
+ size_t number_of_bytes_for_dex_pc,
+ size_t number_of_bytes_for_native_pc,
+ size_t number_of_bytes_for_register_mask) {
+ return stack_mask_size
+ + number_of_bytes_for_inline_info
+ + number_of_bytes_for_dex_map
+ + number_of_bytes_for_dex_pc
+ + number_of_bytes_for_native_pc
+ + number_of_bytes_for_register_mask;
}
size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
size_t inline_info_size,
size_t dex_register_map_size,
size_t dex_pc_max,
- size_t native_pc_max) {
- return ComputeStackMapSize(
+ size_t native_pc_max,
+ size_t register_mask_max) {
+ return ComputeStackMapSizeInternal(
stack_mask_size,
- inline_info_size != 0,
- // + 1 to also encode kNoInlineInfo.
- IsUint<kBitsForSmallEncoding>(inline_info_size + dex_register_map_size + 1),
+ inline_info_size == 0
+ ? 0
+ // + 1 to also encode kNoInlineInfo.
+ : CodeInfo::EncodingSizeInBytes(inline_info_size + dex_register_map_size + 1),
// + 1 to also encode kNoDexRegisterMap.
- IsUint<kBitsForSmallEncoding>(dex_register_map_size + 1),
- IsUint<kBitsForSmallEncoding>(dex_pc_max),
- IsUint<kBitsForSmallEncoding>(native_pc_max));
+ CodeInfo::EncodingSizeInBytes(dex_register_map_size + 1),
+ CodeInfo::EncodingSizeInBytes(dex_pc_max),
+ CodeInfo::EncodingSizeInBytes(native_pc_max),
+ CodeInfo::EncodingSizeInBytes(register_mask_max));
}
MemoryRegion StackMap::GetStackMask(const CodeInfo& info) const {
return region_.Subregion(info.ComputeStackMapStackMaskOffset(), info.GetStackMaskSize());
}
+static void DumpRegisterMapping(std::ostream& os,
+ size_t dex_register_num,
+ DexRegisterLocation location,
+ const std::string& prefix = "v",
+ const std::string& suffix = "") {
+ os << " " << prefix << dex_register_num << ": "
+ << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
+ << " (" << location.GetValue() << ")" << suffix << '\n';
+}
+
void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
StackMap stack_map = GetStackMapAt(stack_map_num);
os << " StackMap " << stack_map_num
@@ -168,13 +233,25 @@ void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
<< ", number_of_dex_registers=" << number_of_dex_registers
<< ", number_of_stack_maps=" << number_of_stack_maps
<< ", has_inline_info=" << HasInlineInfo()
- << ", has_small_inline_info=" << HasSmallInlineInfo()
- << ", has_small_dex_register_map=" << HasSmallDexRegisterMap()
- << ", has_small_dex_pc=" << HasSmallDexPc()
- << ", has_small_native_pc=" << HasSmallNativePc()
+ << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
+ << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
+ << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
+ << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
+ << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
<< ")\n";
- // Display stack maps along with Dex register maps.
+ // Display the Dex register location catalog.
+ size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
+ size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
+ os << " DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
+ << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
+ DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
+ for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
+ DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
+ DumpRegisterMapping(os, i, location, "entry ");
+ }
+
+ // Display stack maps along with (live) Dex register maps.
for (size_t i = 0; i < number_of_stack_maps; ++i) {
StackMap stack_map = GetStackMapAt(i);
DumpStackMapHeader(os, i);
@@ -183,11 +260,13 @@ void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
// TODO: Display the bit mask of live Dex registers.
for (size_t j = 0; j < number_of_dex_registers; ++j) {
if (dex_register_map.IsDexRegisterLive(j)) {
+ size_t location_catalog_entry_index = dex_register_map.GetLocationCatalogEntryIndex(
+ j, number_of_dex_registers, number_of_location_catalog_entries);
DexRegisterLocation location =
- dex_register_map.GetLocationKindAndValue(j, number_of_dex_registers);
- os << " " << "v" << j << ": "
- << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
- << " (" << location.GetValue() << ")" << '\n';
+ dex_register_map.GetDexRegisterLocation(j, number_of_dex_registers, *this);
+ DumpRegisterMapping(
+ os, j, location, "v",
+ "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
}
}
}