summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2015-03-13 14:39:40 +0000
committerNicolas Geoffray <ngeoffray@google.com>2015-03-13 18:28:19 +0000
commitfead4e4f397455aa31905b2982d4d861126ab89d (patch)
tree21e4ccd99472bbf5cf1fac3bc20d0bca6f176022 /runtime
parentcc22e3946baf035c8732e9417ab132bfe663aa45 (diff)
downloadart-fead4e4f397455aa31905b2982d4d861126ab89d.zip
art-fead4e4f397455aa31905b2982d4d861126ab89d.tar.gz
art-fead4e4f397455aa31905b2982d4d861126ab89d.tar.bz2
[optimizing] Don't record None locations in the stack maps.
- moved environment recording from code generator to stack map stream - added creation/loading factory methods for the DexRegisterMap (hides internal details) - added new tests Change-Id: Ic8b6d044f0d8255c6759c19a41df332ef37876fe
Diffstat (limited to 'runtime')
-rw-r--r--runtime/check_reference_map_visitor.h6
-rw-r--r--runtime/stack.cc27
-rw-r--r--runtime/stack_map.h137
3 files changed, 117 insertions, 53 deletions
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 893ab11..0ec0295 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -66,14 +66,16 @@ class CheckReferenceMapVisitor : public StackVisitor {
mirror::ArtMethod* m = GetMethod();
CodeInfo code_info = m->GetOptimizedCodeInfo();
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+ uint16_t number_of_dex_registers = m->GetCodeItem()->registers_size_;
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, m->GetCodeItem()->registers_size_);
+ code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
MemoryRegion stack_mask = stack_map.GetStackMask();
uint32_t register_mask = stack_map.GetRegisterMask();
for (int i = 0; i < number_of_references; ++i) {
int reg = registers[i];
CHECK(reg < m->GetCodeItem()->registers_size_);
- DexRegisterLocation location = dex_register_map.GetLocationKindAndValue(reg);
+ DexRegisterLocation location =
+ dex_register_map.GetLocationKindAndValue(reg, number_of_dex_registers);
switch (location.GetKind()) {
case DexRegisterLocation::Kind::kNone:
// Not set, should not be a reference.
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 47b85ad..2d688ee 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -202,30 +202,33 @@ bool StackVisitor::GetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg,
DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
// its instructions?
DCHECK_LT(vreg, code_item->registers_size_);
+ uint16_t number_of_dex_registers = code_item->registers_size_;
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, code_item->registers_size_);
- DexRegisterLocation::Kind location_kind = dex_register_map.GetLocationKind(vreg);
+ code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+ DexRegisterLocation::Kind location_kind =
+ dex_register_map.GetLocationKind(vreg, number_of_dex_registers);
switch (location_kind) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg);
+ const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers);
const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
*val = *reinterpret_cast<const uint32_t*>(addr);
return true;
}
case DexRegisterLocation::Kind::kInRegister:
case DexRegisterLocation::Kind::kInFpuRegister: {
- uint32_t reg = dex_register_map.GetMachineRegister(vreg);
+ uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers);
return GetRegisterIfAccessible(reg, kind, val);
}
case DexRegisterLocation::Kind::kConstant:
- *val = dex_register_map.GetConstant(vreg);
+ *val = dex_register_map.GetConstant(vreg, number_of_dex_registers);
return true;
case DexRegisterLocation::Kind::kNone:
return false;
default:
LOG(FATAL)
<< "Unexpected location kind"
- << DexRegisterLocation::PrettyDescriptor(dex_register_map.GetLocationInternalKind(vreg));
+ << DexRegisterLocation::PrettyDescriptor(
+ dex_register_map.GetLocationInternalKind(vreg, number_of_dex_registers));
UNREACHABLE();
}
}
@@ -388,21 +391,23 @@ bool StackVisitor::SetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg,
const DexFile::CodeItem* code_item = m->GetCodeItem();
DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
// its instructions?
- DCHECK_LT(vreg, code_item->registers_size_);
+ uint16_t number_of_dex_registers = code_item->registers_size_;
+ DCHECK_LT(vreg, number_of_dex_registers);
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, code_item->registers_size_);
- DexRegisterLocation::Kind location_kind = dex_register_map.GetLocationKind(vreg);
+ code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+ DexRegisterLocation::Kind location_kind =
+ dex_register_map.GetLocationKind(vreg, number_of_dex_registers);
uint32_t dex_pc = m->ToDexPc(cur_quick_frame_pc_, false);
switch (location_kind) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg);
+ const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers);
uint8_t* addr = reinterpret_cast<uint8_t*>(cur_quick_frame_) + offset;
*reinterpret_cast<uint32_t*>(addr) = new_value;
return true;
}
case DexRegisterLocation::Kind::kInRegister:
case DexRegisterLocation::Kind::kInFpuRegister: {
- uint32_t reg = dex_register_map.GetMachineRegister(vreg);
+ uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers);
return SetRegisterIfAccessible(reg, new_value, kind);
}
case DexRegisterLocation::Kind::kConstant:
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 8ebafc5..0db589f 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -31,6 +31,9 @@ static ssize_t constexpr kFrameSlotSize = 4;
// Word alignment required on ARM, in bytes.
static constexpr size_t kWordAlignment = 4;
+// Size of Dex virtual registers.
+static size_t constexpr kVRegSize = 4;
+
/**
* Classes in the following file are wrapper on stack map information backed
* by a MemoryRegion. As such they read and write to the region, they don't have
@@ -191,6 +194,10 @@ class DexRegisterLocation {
DexRegisterLocation(Kind kind, int32_t value)
: kind_(kind), value_(value) {}
+ static DexRegisterLocation None() {
+ return DexRegisterLocation(Kind::kNone, 0);
+ }
+
// Get the "surface" kind of the location, i.e., the one that doesn't
// include any value with a "large" qualifier.
Kind GetKind() const {
@@ -211,8 +218,8 @@ class DexRegisterLocation {
/**
* Information on dex register values for a specific PC. The information is
* of the form:
- * [location_kind, register_value]+.
- * either on 1 or 5 bytes (see art::DexRegisterLocation::Kind).
+ * [live_bit_mask, DexRegisterLocation+].
+ * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
*/
class DexRegisterMap {
public:
@@ -221,6 +228,18 @@ class DexRegisterMap {
// Short (compressed) location, fitting on one byte.
typedef uint8_t ShortLocation;
+ static size_t LiveBitMaskSize(uint16_t number_of_dex_registers) {
+ return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
+ }
+
+ void SetLiveBitMask(size_t offset,
+ uint16_t number_of_dex_registers,
+ const BitVector& live_dex_registers_mask) {
+ for (uint16_t i = 0; i < number_of_dex_registers; i++) {
+ region_.StoreBit(offset + i, live_dex_registers_mask.IsBitSet(i));
+ }
+ }
+
void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
int32_t value = dex_register_location.GetValue();
@@ -256,39 +275,63 @@ class DexRegisterMap {
}
}
- // Find the offset of the Dex register location number `dex_register_index`.
- size_t FindLocationOffset(uint16_t dex_register_index) const {
+ bool IsDexRegisterLive(uint16_t dex_register_index) const {
size_t offset = kFixedSize;
+ return region_.LoadBit(offset + dex_register_index);
+ }
+
+ static constexpr size_t kNoDexRegisterLocationOffset = -1;
+
+ static size_t GetDexRegisterMapLocationsOffset(uint16_t number_of_dex_registers) {
+ return kLiveBitMaskOffset + LiveBitMaskSize(number_of_dex_registers);
+ }
+
+ // Find the offset of the Dex register location number `dex_register_index`.
+ size_t FindLocationOffset(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
+ if (!IsDexRegisterLive(dex_register_index)) return kNoDexRegisterLocationOffset;
+ size_t offset = GetDexRegisterMapLocationsOffset(number_of_dex_registers);
// Skip the first `dex_register_index - 1` entries.
for (uint16_t i = 0; i < dex_register_index; ++i) {
- // Read the first next byte and inspect its first 3 bits to decide
- // whether it is a short or a large location.
- DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
- if (DexRegisterLocation::IsShortLocationKind(kind)) {
- // Short location. Skip the current byte.
- offset += SingleShortEntrySize();
- } else {
- // Large location. Skip the 5 next bytes.
- offset += SingleLargeEntrySize();
+ if (IsDexRegisterLive(i)) {
+ // Read the first next byte and inspect its first 3 bits to decide
+ // whether it is a short or a large location.
+ DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
+ if (DexRegisterLocation::IsShortLocationKind(kind)) {
+ // Short location. Skip the current byte.
+ offset += SingleShortEntrySize();
+ } else {
+ // Large location. Skip the 5 next bytes.
+ offset += SingleLargeEntrySize();
+ }
}
}
return offset;
}
// Get the surface kind.
- DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_index) const {
- return DexRegisterLocation::ConvertToSurfaceKind(GetLocationInternalKind(dex_register_index));
+ DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_index,
+ uint16_t number_of_dex_registers) const {
+ return IsDexRegisterLive(dex_register_index)
+ ? DexRegisterLocation::ConvertToSurfaceKind(
+ GetLocationInternalKind(dex_register_index, number_of_dex_registers))
+ : DexRegisterLocation::Kind::kNone;
}
// Get the internal kind.
- DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_index) const {
- size_t offset = FindLocationOffset(dex_register_index);
- return ExtractKindAtOffset(offset);
+ DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_index,
+ uint16_t number_of_dex_registers) const {
+ return IsDexRegisterLive(dex_register_index)
+ ? ExtractKindAtOffset(FindLocationOffset(dex_register_index, number_of_dex_registers))
+ : DexRegisterLocation::Kind::kNone;
}
// TODO: Rename as GetDexRegisterLocation?
- DexRegisterLocation GetLocationKindAndValue(uint16_t dex_register_index) const {
- size_t offset = FindLocationOffset(dex_register_index);
+ DexRegisterLocation GetLocationKindAndValue(uint16_t dex_register_index,
+ uint16_t number_of_dex_registers) const {
+ if (!IsDexRegisterLive(dex_register_index)) {
+ return DexRegisterLocation::None();
+ }
+ size_t offset = FindLocationOffset(dex_register_index, number_of_dex_registers);
// Read the first byte and inspect its first 3 bits to get the location.
ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
@@ -311,21 +354,25 @@ class DexRegisterMap {
}
}
- int32_t GetStackOffsetInBytes(uint16_t dex_register_index) const {
- DexRegisterLocation location = GetLocationKindAndValue(dex_register_index);
+ int32_t GetStackOffsetInBytes(uint16_t dex_register_index,
+ uint16_t number_of_dex_registers) const {
+ DexRegisterLocation location =
+ GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
// GetLocationKindAndValue returns the offset in bytes.
return location.GetValue();
}
- int32_t GetConstant(uint16_t dex_register_index) const {
- DexRegisterLocation location = GetLocationKindAndValue(dex_register_index);
+ int32_t GetConstant(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
+ DexRegisterLocation location =
+ GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
return location.GetValue();
}
- int32_t GetMachineRegister(uint16_t dex_register_index) const {
- DexRegisterLocation location = GetLocationKindAndValue(dex_register_index);
+ int32_t GetMachineRegister(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
+ DexRegisterLocation location =
+ GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister
|| location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister)
<< DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
@@ -405,7 +452,8 @@ class DexRegisterMap {
return region_.size();
}
- static constexpr int kFixedSize = 0;
+ static constexpr int kLiveBitMaskOffset = 0;
+ static constexpr int kFixedSize = kLiveBitMaskOffset;
private:
// Width of the kind "field" in a short location, in bits.
@@ -428,6 +476,8 @@ class DexRegisterMap {
static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
uint8_t kind = (location >> kKindOffset) & kKindMask;
DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
+ // We do not encode kNone locations in the stack map.
+ DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
return static_cast<DexRegisterLocation::Kind>(kind);
}
@@ -678,21 +728,28 @@ class CodeInfo {
// TODO: Ideally, we would like to use art::DexRegisterMap::Size or
// art::DexRegisterMap::FindLocationOffset, but the DexRegisterMap is not
// yet built. Try to factor common code.
- size_t offset = origin + DexRegisterMap::kFixedSize;
+ size_t offset =
+ origin + DexRegisterMap::GetDexRegisterMapLocationsOffset(number_of_dex_registers);
+
+ // Create a temporary DexRegisterMap to be able to call DexRegisterMap.IsDexRegisterLive.
+ DexRegisterMap only_live_mask(MemoryRegion(region_.Subregion(origin, offset - origin)));
+
// Skip the first `number_of_dex_registers - 1` entries.
for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
- // Read the first next byte and inspect its first 3 bits to decide
- // whether it is a short or a large location.
- DexRegisterMap::ShortLocation first_byte =
- region_.LoadUnaligned<DexRegisterMap::ShortLocation>(offset);
- DexRegisterLocation::Kind kind =
- DexRegisterMap::ExtractKindFromShortLocation(first_byte);
- if (DexRegisterLocation::IsShortLocationKind(kind)) {
- // Short location. Skip the current byte.
- offset += DexRegisterMap::SingleShortEntrySize();
- } else {
- // Large location. Skip the 5 next bytes.
- offset += DexRegisterMap::SingleLargeEntrySize();
+ if (only_live_mask.IsDexRegisterLive(i)) {
+ // Read the first next byte and inspect its first 3 bits to decide
+ // whether it is a short or a large location.
+ DexRegisterMap::ShortLocation first_byte =
+ region_.LoadUnaligned<DexRegisterMap::ShortLocation>(offset);
+ DexRegisterLocation::Kind kind =
+ DexRegisterMap::ExtractKindFromShortLocation(first_byte);
+ if (DexRegisterLocation::IsShortLocationKind(kind)) {
+ // Short location. Skip the current byte.
+ offset += DexRegisterMap::SingleShortEntrySize();
+ } else {
+ // Large location. Skip the 5 next bytes.
+ offset += DexRegisterMap::SingleLargeEntrySize();
+ }
}
}
size_t size = offset - origin;