Move some helper methods to DexRegisterLocation.
Test: test-art-host-gtest-stack_map_test
Change-Id: I0abab008159db023d531df69214cd3bb8c0639bd
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 777a1fc..1168798 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -47,6 +47,7 @@
"debug_print.cc",
"debugger.cc",
"dex/dex_file_annotations.cc",
+ "dex_register_location.cc",
"dex_to_dex_decompiler.cc",
"elf_file.cc",
"exec_utils.cc",
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 8a2a70e..8f9f45c 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -75,7 +75,7 @@
for (int i = 0; i < number_of_references; ++i) {
int reg = registers[i];
CHECK_LT(reg, accessor.RegistersSize());
- DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(reg);
+ DexRegisterLocation location = dex_register_map[reg];
switch (location.GetKind()) {
case DexRegisterLocation::Kind::kNone:
// Not set, should not be a reference.
@@ -98,7 +98,7 @@
CHECK_EQ(location.GetValue(), 0);
break;
default:
- LOG(FATAL) << "Unexpected location kind " << location.GetInternalKind();
+ LOG(FATAL) << "Unexpected location kind " << location.GetKind();
}
}
}
diff --git a/runtime/dex_register_location.cc b/runtime/dex_register_location.cc
new file mode 100644
index 0000000..f3b0973
--- /dev/null
+++ b/runtime/dex_register_location.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dex_register_location.h"
+
+namespace art {
+
+std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind) {
+ return stream << "Kind<" << static_cast<int32_t>(kind) << ">";
+}
+
+std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg) {
+ using Kind = DexRegisterLocation::Kind;
+ switch (reg.GetKind()) {
+ case Kind::kInvalid:
+ return stream << "Invalid";
+ case Kind::kNone:
+ return stream << "None";
+ case Kind::kInStack:
+ return stream << "sp+" << reg.GetValue();
+ case Kind::kInRegister:
+ return stream << "r" << reg.GetValue();
+ case Kind::kInRegisterHigh:
+ return stream << "r" << reg.GetValue() << "/hi";
+ case Kind::kInFpuRegister:
+ return stream << "f" << reg.GetValue();
+ case Kind::kInFpuRegisterHigh:
+ return stream << "f" << reg.GetValue() << "/hi";
+ case Kind::kConstant:
+ return stream << "#" << reg.GetValue();
+ default:
+ return stream << "DexRegisterLocation(" << static_cast<uint32_t>(reg.GetKind())
+ << "," << reg.GetValue() << ")";
+ }
+}
+
+} // namespace art
diff --git a/runtime/dex_register_location.h b/runtime/dex_register_location.h
index a20dccb..98b4d41 100644
--- a/runtime/dex_register_location.h
+++ b/runtime/dex_register_location.h
@@ -48,9 +48,6 @@
Kind GetKind() const { return kind_; }
- // TODO: Remove.
- Kind GetInternalKind() const { return kind_; }
-
int32_t GetValue() const { return value_; }
bool operator==(DexRegisterLocation other) const {
@@ -61,6 +58,24 @@
return !(*this == other);
}
+ int32_t GetStackOffsetInBytes() const {
+ DCHECK(kind_ == Kind::kInStack);
+ return value_;
+ }
+
+ int32_t GetConstant() const {
+ DCHECK(kind_ == Kind::kConstant);
+ return value_;
+ }
+
+ int32_t GetMachineRegister() const {
+ DCHECK(kind_ == Kind::kInRegister ||
+ kind_ == Kind::kInRegisterHigh ||
+ kind_ == Kind::kInFpuRegister ||
+ kind_ == Kind::kInFpuRegisterHigh);
+ return value_;
+ }
+
private:
DexRegisterLocation() {}
@@ -70,9 +85,8 @@
friend class DexRegisterMap; // Allow creation of uninitialized array of locations.
};
-static inline std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind) {
- return stream << "Kind<" << static_cast<int32_t>(kind) << ">";
-}
+std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind);
+std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg);
} // namespace art
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 0a8e0cd..5e73603 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -515,7 +515,7 @@
} else {
DCHECK_EQ(vreg_map.size(), number_of_vregs);
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
- DexRegisterLocation::Kind location = vreg_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind location = vreg_map[vreg].GetKind();
if (location == DexRegisterLocation::Kind::kNone) {
// Dex register is dead or uninitialized.
continue;
@@ -529,7 +529,7 @@
DCHECK_EQ(location, DexRegisterLocation::Kind::kInStack);
int32_t vreg_value = shadow_frame->GetVReg(vreg);
- int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg);
+ int32_t slot_offset = vreg_map[vreg].GetStackOffsetInBytes();
DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size));
DCHECK_GT(slot_offset, 0);
(reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value;
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index cf1cbe7..8b99b9f 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -245,7 +245,7 @@
// Copy values between them.
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
- DexRegisterLocation::Kind catch_location = catch_vreg_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind catch_location = catch_vreg_map[vreg].GetKind();
if (catch_location == DexRegisterLocation::Kind::kNone) {
continue;
}
@@ -253,7 +253,7 @@
// Get vreg value from its current location.
uint32_t vreg_value;
- VRegKind vreg_kind = ToVRegKind(throw_vreg_map.GetLocationKind(vreg));
+ VRegKind vreg_kind = ToVRegKind(throw_vreg_map[vreg].GetKind());
bool get_vreg_success = stack_visitor->GetVReg(stack_visitor->GetMethod(),
vreg,
vreg_kind,
@@ -264,7 +264,7 @@
<< "native_pc_offset=" << stack_visitor->GetNativePcOffset() << ")";
// Copy value to the catch phi's stack slot.
- int32_t slot_offset = catch_vreg_map.GetStackOffsetInBytes(vreg);
+ int32_t slot_offset = catch_vreg_map[vreg].GetStackOffsetInBytes();
ArtMethod** frame_top = stack_visitor->GetCurrentQuickFrame();
uint8_t* slot_address = reinterpret_cast<uint8_t*>(frame_top) + slot_offset;
uint32_t* slot_ptr = reinterpret_cast<uint32_t*>(slot_address);
@@ -417,14 +417,14 @@
continue;
}
- DexRegisterLocation::Kind location = vreg_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind location = vreg_map[vreg].GetKind();
static constexpr uint32_t kDeadValue = 0xEBADDE09;
uint32_t value = kDeadValue;
bool is_reference = false;
switch (location) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = vreg_map.GetStackOffsetInBytes(vreg);
+ const int32_t offset = vreg_map[vreg].GetStackOffsetInBytes();
const uint8_t* addr = reinterpret_cast<const uint8_t*>(GetCurrentQuickFrame()) + offset;
value = *reinterpret_cast<const uint32_t*>(addr);
uint32_t bit = (offset >> 2);
@@ -437,7 +437,7 @@
case DexRegisterLocation::Kind::kInRegisterHigh:
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
- uint32_t reg = vreg_map.GetMachineRegister(vreg);
+ uint32_t reg = vreg_map[vreg].GetMachineRegister();
bool result = GetRegisterIfAccessible(reg, ToVRegKind(location), &value);
CHECK(result);
if (location == DexRegisterLocation::Kind::kInRegister) {
@@ -448,7 +448,7 @@
break;
}
case DexRegisterLocation::Kind::kConstant: {
- value = vreg_map.GetConstant(vreg);
+ value = vreg_map[vreg].GetConstant();
if (value == 0) {
// Make it a reference for extra safety.
is_reference = true;
@@ -459,9 +459,7 @@
break;
}
default: {
- LOG(FATAL)
- << "Unexpected location kind "
- << vreg_map.GetLocationInternalKind(vreg);
+ LOG(FATAL) << "Unexpected location kind " << vreg_map[vreg].GetKind();
UNREACHABLE();
}
}
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 56e47b9..2188cdc 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -242,10 +242,10 @@
return false;
}
DCHECK_EQ(dex_register_map.size(), number_of_dex_registers);
- DexRegisterLocation::Kind location_kind = dex_register_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind location_kind = dex_register_map[vreg].GetKind();
switch (location_kind) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg);
+ const int32_t offset = dex_register_map[vreg].GetStackOffsetInBytes();
const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
*val = *reinterpret_cast<const uint32_t*>(addr);
return true;
@@ -254,18 +254,16 @@
case DexRegisterLocation::Kind::kInRegisterHigh:
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
- uint32_t reg = dex_register_map.GetMachineRegister(vreg);
+ uint32_t reg = dex_register_map[vreg].GetMachineRegister();
return GetRegisterIfAccessible(reg, kind, val);
}
case DexRegisterLocation::Kind::kConstant:
- *val = dex_register_map.GetConstant(vreg);
+ *val = dex_register_map[vreg].GetConstant();
return true;
case DexRegisterLocation::Kind::kNone:
return false;
default:
- LOG(FATAL)
- << "Unexpected location kind "
- << dex_register_map.GetLocationInternalKind(vreg);
+ LOG(FATAL) << "Unexpected location kind " << dex_register_map[vreg].GetKind();
UNREACHABLE();
}
}
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 23cc1d6..43609e8 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -89,31 +89,6 @@
}
}
-std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg) {
- using Kind = DexRegisterLocation::Kind;
- switch (reg.GetKind()) {
- case Kind::kNone:
- return stream << "None";
- case Kind::kInStack:
- return stream << "sp+" << reg.GetValue();
- case Kind::kInRegister:
- return stream << "r" << reg.GetValue();
- case Kind::kInRegisterHigh:
- return stream << "r" << reg.GetValue() << "/hi";
- case Kind::kInFpuRegister:
- return stream << "f" << reg.GetValue();
- case Kind::kInFpuRegisterHigh:
- return stream << "f" << reg.GetValue() << "/hi";
- case Kind::kConstant:
- return stream << "#" << reg.GetValue();
- case Kind::kInvalid:
- return stream << "Invalid";
- default:
- return stream << "DexRegisterLocation(" << static_cast<uint32_t>(reg.GetKind())
- << "," << reg.GetValue() << ")";
- }
-}
-
template<typename Accessor>
static void AddTableSizeStats(const char* table_name,
const BitTable<Accessor::kCount>& table,
@@ -144,13 +119,13 @@
AddTableSizeStats<DexRegisterInfo>("DexRegisterCatalog", dex_register_catalog_, stats);
}
-static void DumpDexRegisterMap(VariableIndentationOutputStream* vios,
- const DexRegisterMap& map) {
- if (map.HasAnyLiveDexRegisters()) {
+void DexRegisterMap::Dump(VariableIndentationOutputStream* vios) const {
+ if (HasAnyLiveDexRegisters()) {
ScopedIndentation indent1(vios);
- for (size_t i = 0; i < map.size(); ++i) {
- if (map.IsDexRegisterLive(i)) {
- vios->Stream() << "v" << i << ":" << map.Get(i) << " ";
+ for (size_t i = 0; i < size(); ++i) {
+ DexRegisterLocation reg = (*this)[i];
+ if (reg.IsLive()) {
+ vios->Stream() << "v" << i << ":" << reg << " ";
}
}
vios->Stream() << "\n";
@@ -240,7 +215,7 @@
vios->Stream() << stack_mask.LoadBit(e - i - 1);
}
vios->Stream() << ")\n";
- DumpDexRegisterMap(vios, code_info.GetDexRegisterMapOf(*this));
+ code_info.GetDexRegisterMapOf(*this).Dump(vios);
uint32_t depth = code_info.GetInlineDepthOf(*this);
for (size_t d = 0; d < depth; d++) {
InlineInfo inline_info = code_info.GetInlineInfoAtDepth(*this, d);
@@ -267,7 +242,7 @@
<< ", method_index=" << GetMethodIndex(method_info);
}
vios->Stream() << ")\n";
- DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(depth, stack_map));
+ code_info.GetDexRegisterMapAtDepth(depth, stack_map).Dump(vios);
}
} // namespace art
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index ea358c6..aa19f09 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -54,9 +54,11 @@
// Information on Dex register locations for a specific PC.
// Effectively just a convenience wrapper for DexRegisterLocation vector.
// If the size is small enough, it keeps the data on the stack.
+// TODO: Replace this with generic purpose "small-vector" implementation.
class DexRegisterMap {
public:
using iterator = DexRegisterLocation*;
+ using const_iterator = const DexRegisterLocation*;
// Create map for given number of registers and initialize them to the given value.
DexRegisterMap(size_t count, DexRegisterLocation value) : count_(count), regs_small_{} {
@@ -70,76 +72,36 @@
DexRegisterLocation* data() {
return count_ <= kSmallCount ? regs_small_.data() : regs_large_.data();
}
+ const DexRegisterLocation* data() const {
+ return count_ <= kSmallCount ? regs_small_.data() : regs_large_.data();
+ }
iterator begin() { return data(); }
iterator end() { return data() + count_; }
-
+ const_iterator begin() const { return data(); }
+ const_iterator end() const { return data() + count_; }
size_t size() const { return count_; }
-
bool empty() const { return count_ == 0; }
- DexRegisterLocation Get(size_t index) const {
+ DexRegisterLocation& operator[](size_t index) {
DCHECK_LT(index, count_);
- return count_ <= kSmallCount ? regs_small_[index] : regs_large_[index];
+ return data()[index];
}
-
- DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number) const {
- return Get(dex_register_number).GetKind();
- }
-
- // TODO: Remove.
- DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number) const {
- return Get(dex_register_number).GetKind();
- }
-
- DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number) const {
- return Get(dex_register_number);
- }
-
- int32_t GetStackOffsetInBytes(uint16_t dex_register_number) const {
- DexRegisterLocation location = Get(dex_register_number);
- DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
- return location.GetValue();
- }
-
- int32_t GetConstant(uint16_t dex_register_number) const {
- DexRegisterLocation location = Get(dex_register_number);
- DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
- return location.GetValue();
- }
-
- int32_t GetMachineRegister(uint16_t dex_register_number) const {
- DexRegisterLocation location = Get(dex_register_number);
- DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInRegister ||
- location.GetKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
- location.GetKind() == DexRegisterLocation::Kind::kInFpuRegister ||
- location.GetKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh);
- return location.GetValue();
- }
-
- ALWAYS_INLINE bool IsDexRegisterLive(uint16_t dex_register_number) const {
- return Get(dex_register_number).IsLive();
+ const DexRegisterLocation& operator[](size_t index) const {
+ DCHECK_LT(index, count_);
+ return data()[index];
}
size_t GetNumberOfLiveDexRegisters() const {
- size_t number_of_live_dex_registers = 0;
- for (size_t i = 0; i < count_; ++i) {
- if (IsDexRegisterLive(i)) {
- ++number_of_live_dex_registers;
- }
- }
- return number_of_live_dex_registers;
+ return std::count_if(begin(), end(), [](auto& loc) { return loc.IsLive(); });
}
bool HasAnyLiveDexRegisters() const {
- for (size_t i = 0; i < count_; ++i) {
- if (IsDexRegisterLive(i)) {
- return true;
- }
- }
- return false;
+ return std::any_of(begin(), end(), [](auto& loc) { return loc.IsLive(); });
}
+ void Dump(VariableIndentationOutputStream* vios) const;
+
private:
// Store the data inline if the number of registers is small to avoid memory allocations.
// If count_ <= kSmallCount, we use the regs_small_ array, and regs_large_ otherwise.
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 4a53425..7a7a80e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3658,7 +3658,7 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
bool found = false;
for (size_t dex_reg = 0; dex_reg != number_of_dex_registers; ++dex_reg) {
- DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(dex_reg);
+ DexRegisterLocation location = dex_register_map[dex_reg];
if (location.GetKind() == kind && static_cast<size_t>(location.GetValue()) == index) {
visitor(ref, dex_reg, stack_visitor);
found = true;