diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-03-13 14:39:40 +0000 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2015-03-13 18:28:19 +0000 |
commit | fead4e4f397455aa31905b2982d4d861126ab89d (patch) | |
tree | 21e4ccd99472bbf5cf1fac3bc20d0bca6f176022 /runtime | |
parent | cc22e3946baf035c8732e9417ab132bfe663aa45 (diff) | |
download | art-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.h | 6 | ||||
-rw-r--r-- | runtime/stack.cc | 27 | ||||
-rw-r--r-- | runtime/stack_map.h | 137 |
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; |