Merge "Revert "Refactor HGraphBuilder and SsaBuilder to remove HLocals""
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index 6c55194..6412b24 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -53,17 +53,17 @@
}
static inline vixl::Register XRegisterFrom(Location location) {
- DCHECK(location.IsRegister());
+ DCHECK(location.IsRegister()) << location;
return vixl::Register::XRegFromCode(VIXLRegCodeFromART(location.reg()));
}
static inline vixl::Register WRegisterFrom(Location location) {
- DCHECK(location.IsRegister());
+ DCHECK(location.IsRegister()) << location;
return vixl::Register::WRegFromCode(VIXLRegCodeFromART(location.reg()));
}
static inline vixl::Register RegisterFrom(Location location, Primitive::Type type) {
- DCHECK(type != Primitive::kPrimVoid && !Primitive::IsFloatingPointType(type));
+ DCHECK(type != Primitive::kPrimVoid && !Primitive::IsFloatingPointType(type)) << type;
return type == Primitive::kPrimLong ? XRegisterFrom(location) : WRegisterFrom(location);
}
@@ -77,17 +77,17 @@
}
static inline vixl::FPRegister DRegisterFrom(Location location) {
- DCHECK(location.IsFpuRegister());
+ DCHECK(location.IsFpuRegister()) << location;
return vixl::FPRegister::DRegFromCode(location.reg());
}
static inline vixl::FPRegister SRegisterFrom(Location location) {
- DCHECK(location.IsFpuRegister());
+ DCHECK(location.IsFpuRegister()) << location;
return vixl::FPRegister::SRegFromCode(location.reg());
}
static inline vixl::FPRegister FPRegisterFrom(Location location, Primitive::Type type) {
- DCHECK(Primitive::IsFloatingPointType(type));
+ DCHECK(Primitive::IsFloatingPointType(type)) << type;
return type == Primitive::kPrimDouble ? DRegisterFrom(location) : SRegisterFrom(location);
}
@@ -124,7 +124,7 @@
} else if (instr->IsNullConstant()) {
return 0;
} else {
- DCHECK(instr->IsLongConstant());
+ DCHECK(instr->IsLongConstant()) << instr->DebugName();
return instr->AsLongConstant()->GetValue();
}
}
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index e3172df..d936a8c 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1061,14 +1061,19 @@
caller_instruction_counter);
callee_graph->SetArtMethod(resolved_method);
- OptimizingCompilerStats inline_stats;
+ // When they are needed, allocate `inline_stats` on the heap instead
+ // of on the stack, as Clang might produce a stack frame too large
+ // for this function, that would not fit the requirements of the
+ // `-Wframe-larger-than` option.
+ std::unique_ptr<OptimizingCompilerStats> inline_stats =
+ (stats_ == nullptr) ? nullptr : MakeUnique<OptimizingCompilerStats>();
HGraphBuilder builder(callee_graph,
&dex_compilation_unit,
&outer_compilation_unit_,
resolved_method->GetDexFile(),
*code_item,
compiler_driver_,
- &inline_stats,
+ inline_stats.get(),
resolved_method->GetQuickenedInfo(),
dex_cache);
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 5de2306..a589ef0 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -368,17 +368,16 @@
GenReverse(invoke->GetLocations(), Primitive::kPrimLong, GetVIXLAssembler());
}
-static void GenBitCount(HInvoke* instr, bool is_long, vixl::MacroAssembler* masm) {
- DCHECK(instr->GetType() == Primitive::kPrimInt);
- DCHECK((is_long && instr->InputAt(0)->GetType() == Primitive::kPrimLong) ||
- (!is_long && instr->InputAt(0)->GetType() == Primitive::kPrimInt));
+static void GenBitCount(HInvoke* instr, Primitive::Type type, vixl::MacroAssembler* masm) {
+ DCHECK(Primitive::IsIntOrLongType(type)) << type;
+ DCHECK_EQ(instr->GetType(), Primitive::kPrimInt);
+ DCHECK_EQ(Primitive::PrimitiveKind(instr->InputAt(0)->GetType()), type);
- Location out = instr->GetLocations()->Out();
UseScratchRegisterScope temps(masm);
Register src = InputRegisterAt(instr, 0);
- Register dst = is_long ? XRegisterFrom(out) : WRegisterFrom(out);
- FPRegister fpr = is_long ? temps.AcquireD() : temps.AcquireS();
+ Register dst = RegisterFrom(instr->GetLocations()->Out(), type);
+ FPRegister fpr = (type == Primitive::kPrimLong) ? temps.AcquireD() : temps.AcquireS();
__ Fmov(fpr, src);
__ Cnt(fpr.V8B(), fpr.V8B());
@@ -391,7 +390,7 @@
}
void IntrinsicCodeGeneratorARM64::VisitLongBitCount(HInvoke* invoke) {
- GenBitCount(invoke, /* is_long */ true, GetVIXLAssembler());
+ GenBitCount(invoke, Primitive::kPrimLong, GetVIXLAssembler());
}
void IntrinsicLocationsBuilderARM64::VisitIntegerBitCount(HInvoke* invoke) {
@@ -399,7 +398,7 @@
}
void IntrinsicCodeGeneratorARM64::VisitIntegerBitCount(HInvoke* invoke) {
- GenBitCount(invoke, /* is_long */ false, GetVIXLAssembler());
+ GenBitCount(invoke, Primitive::kPrimInt, GetVIXLAssembler());
}
static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) {
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index 1280587..19c6a22 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -614,8 +614,6 @@
Primitive::Type type,
bool isR6,
MipsAssembler* assembler) {
- DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
-
Register out = locations->Out().AsRegister<Register>();
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
@@ -663,7 +661,8 @@
__ MulR2(out, out, TMP);
}
__ Srl(out, out, 24);
- } else if (type == Primitive::kPrimLong) {
+ } else {
+ DCHECK_EQ(type, Primitive::kPrimLong);
Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
Register tmp_hi = locations->GetTemp(0).AsRegister<Register>();
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 95fdb9b..4aab3e2 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -2387,10 +2387,10 @@
if (invoke->InputAt(0)->IsConstant()) {
// Evaluate this at compile time.
int64_t value = Int64FromConstant(invoke->InputAt(0)->AsConstant());
- value = is_long
+ int32_t result = is_long
? POPCOUNT(static_cast<uint64_t>(value))
: POPCOUNT(static_cast<uint32_t>(value));
- codegen->Load32BitValue(out, value);
+ codegen->Load32BitValue(out, result);
return;
}
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 9e568f7..9ca4ef0 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2402,10 +2402,10 @@
if (invoke->InputAt(0)->IsConstant()) {
// Evaluate this at compile time.
int64_t value = Int64FromConstant(invoke->InputAt(0)->AsConstant());
- value = is_long
+ int32_t result = is_long
? POPCOUNT(static_cast<uint64_t>(value))
: POPCOUNT(static_cast<uint32_t>(value));
- codegen->Load32BitValue(out, value);
+ codegen->Load32BitValue(out, result);
return;
}
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index c571312..11a254e 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -137,8 +137,9 @@
size_t StackMapStream::PrepareForFillIn() {
int stack_mask_number_of_bits = stack_mask_max_ + 1; // Need room for max element too.
- inline_info_size_ = ComputeInlineInfoSize();
dex_register_maps_size_ = ComputeDexRegisterMapsSize();
+ ComputeInlineInfoEncoding(); // needs dex_register_maps_size_.
+ inline_info_size_ = inline_infos_.size() * inline_info_encoding_.GetEntrySize();
uint32_t max_native_pc_offset = ComputeMaxNativePcOffset();
size_t stack_map_size = stack_map_encoding_.SetFromSizes(max_native_pc_offset,
dex_pc_max_,
@@ -158,9 +159,10 @@
// Prepare the CodeInfo variable-sized encoding.
CodeInfoEncoding code_info_encoding;
code_info_encoding.non_header_size = non_header_size;
- code_info_encoding.stack_map_encoding = stack_map_encoding_;
code_info_encoding.number_of_stack_maps = stack_maps_.size();
code_info_encoding.stack_map_size_in_bytes = stack_map_size;
+ code_info_encoding.stack_map_encoding = stack_map_encoding_;
+ code_info_encoding.inline_info_encoding = inline_info_encoding_;
code_info_encoding.number_of_location_catalog_entries = location_catalog_entries_.size();
code_info_encoding.Compress(&code_info_encoding_);
@@ -224,10 +226,26 @@
return size;
}
-size_t StackMapStream::ComputeInlineInfoSize() const {
- return inline_infos_.size() * InlineInfo::SingleEntrySize()
- // For encoding the depth.
- + (number_of_stack_maps_with_inline_info_ * InlineInfo::kFixedSize);
+void StackMapStream::ComputeInlineInfoEncoding() {
+ uint32_t method_index_max = 0;
+ uint32_t dex_pc_max = 0;
+ uint32_t invoke_type_max = 0;
+
+ uint32_t inline_info_index = 0;
+ for (const StackMapEntry& entry : stack_maps_) {
+ for (size_t j = 0; j < entry.inlining_depth; ++j) {
+ InlineInfoEntry inline_entry = inline_infos_[inline_info_index++];
+ method_index_max = std::max(method_index_max, inline_entry.method_index);
+ dex_pc_max = std::max(dex_pc_max, inline_entry.dex_pc);
+ invoke_type_max = std::max(invoke_type_max, static_cast<uint32_t>(inline_entry.invoke_type));
+ }
+ }
+ DCHECK_EQ(inline_info_index, inline_infos_.size());
+
+ inline_info_encoding_.SetFromSizes(method_index_max,
+ dex_pc_max,
+ invoke_type_max,
+ dex_register_maps_size_);
}
void StackMapStream::FillIn(MemoryRegion region) {
@@ -321,7 +339,7 @@
if (entry.inlining_depth != 0) {
MemoryRegion inline_region = inline_infos_region.Subregion(
next_inline_info_offset,
- InlineInfo::kFixedSize + entry.inlining_depth * InlineInfo::SingleEntrySize());
+ entry.inlining_depth * inline_info_encoding_.GetEntrySize());
next_inline_info_offset += inline_region.size();
InlineInfo inline_info(inline_region);
@@ -329,16 +347,18 @@
stack_map.SetInlineDescriptorOffset(
stack_map_encoding_, inline_region.start() - dex_register_locations_region.start());
- inline_info.SetDepth(entry.inlining_depth);
+ inline_info.SetDepth(inline_info_encoding_, entry.inlining_depth);
DCHECK_LE(entry.inline_infos_start_index + entry.inlining_depth, inline_infos_.size());
for (size_t depth = 0; depth < entry.inlining_depth; ++depth) {
InlineInfoEntry inline_entry = inline_infos_[depth + entry.inline_infos_start_index];
- inline_info.SetMethodIndexAtDepth(depth, inline_entry.method_index);
- inline_info.SetDexPcAtDepth(depth, inline_entry.dex_pc);
- inline_info.SetInvokeTypeAtDepth(depth, inline_entry.invoke_type);
+ inline_info.SetMethodIndexAtDepth(inline_info_encoding_, depth, inline_entry.method_index);
+ inline_info.SetDexPcAtDepth(inline_info_encoding_, depth, inline_entry.dex_pc);
+ inline_info.SetInvokeTypeAtDepth(inline_info_encoding_, depth, inline_entry.invoke_type);
if (inline_entry.num_dex_registers == 0) {
// No dex map available.
- inline_info.SetDexRegisterMapOffsetAtDepth(depth, StackMap::kNoDexRegisterMap);
+ inline_info.SetDexRegisterMapOffsetAtDepth(inline_info_encoding_,
+ depth,
+ StackMap::kNoDexRegisterMap);
DCHECK(inline_entry.live_dex_registers_mask == nullptr);
} else {
MemoryRegion register_region = dex_register_locations_region.Subregion(
@@ -348,7 +368,8 @@
next_dex_register_map_offset += register_region.size();
DexRegisterMap dex_register_map(register_region);
inline_info.SetDexRegisterMapOffsetAtDepth(
- depth, register_region.start() - dex_register_locations_region.start());
+ inline_info_encoding_,
+ depth, register_region.start() - dex_register_locations_region.start());
FillInDexRegisterMap(dex_register_map,
inline_entry.num_dex_registers,
@@ -513,14 +534,17 @@
DCHECK_EQ(stack_map.HasInlineInfo(stack_map_encoding), (entry.inlining_depth != 0));
if (entry.inlining_depth != 0) {
InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- DCHECK_EQ(inline_info.GetDepth(), entry.inlining_depth);
+ DCHECK_EQ(inline_info.GetDepth(encoding.inline_info_encoding), entry.inlining_depth);
for (size_t d = 0; d < entry.inlining_depth; ++d) {
size_t inline_info_index = entry.inline_infos_start_index + d;
DCHECK_LT(inline_info_index, inline_infos_.size());
InlineInfoEntry inline_entry = inline_infos_[inline_info_index];
- DCHECK_EQ(inline_info.GetDexPcAtDepth(d), inline_entry.dex_pc);
- DCHECK_EQ(inline_info.GetMethodIndexAtDepth(d), inline_entry.method_index);
- DCHECK_EQ(inline_info.GetInvokeTypeAtDepth(d), inline_entry.invoke_type);
+ DCHECK_EQ(inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, d),
+ inline_entry.dex_pc);
+ DCHECK_EQ(inline_info.GetMethodIndexAtDepth(encoding.inline_info_encoding, d),
+ inline_entry.method_index);
+ DCHECK_EQ(inline_info.GetInvokeTypeAtDepth(encoding.inline_info_encoding, d),
+ inline_entry.invoke_type);
CheckDexRegisterMap(code_info,
code_info.GetDexRegisterMapAtDepth(
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index b686748..41f72f5 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -156,7 +156,7 @@
size_t ComputeDexRegisterMapSize(uint32_t num_dex_registers,
const BitVector* live_dex_registers_mask) const;
size_t ComputeDexRegisterMapsSize() const;
- size_t ComputeInlineInfoSize() const;
+ void ComputeInlineInfoEncoding();
// Returns the index of an entry with the same dex register map as the current_entry,
// or kNoSameDexMapFound if no such entry exists.
@@ -200,6 +200,7 @@
StackMapEntry current_entry_;
InlineInfoEntry current_inline_info_;
StackMapEncoding stack_map_encoding_;
+ InlineInfoEncoding inline_info_encoding_;
ArenaVector<uint8_t> code_info_encoding_;
size_t inline_info_size_;
size_t dex_register_maps_size_;
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 3552487..967fd96 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -237,13 +237,13 @@
ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- ASSERT_EQ(2u, inline_info.GetDepth());
- ASSERT_EQ(82u, inline_info.GetMethodIndexAtDepth(0));
- ASSERT_EQ(42u, inline_info.GetMethodIndexAtDepth(1));
- ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(0));
- ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(1));
- ASSERT_EQ(kDirect, inline_info.GetInvokeTypeAtDepth(0));
- ASSERT_EQ(kStatic, inline_info.GetInvokeTypeAtDepth(1));
+ ASSERT_EQ(2u, inline_info.GetDepth(encoding.inline_info_encoding));
+ ASSERT_EQ(82u, inline_info.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(42u, inline_info.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(kDirect, inline_info.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(kStatic, inline_info.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1));
}
// Second stack map.
@@ -741,13 +741,13 @@
ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
InlineInfo if0 = ci.GetInlineInfoOf(sm0, encoding);
- ASSERT_EQ(2u, if0.GetDepth());
- ASSERT_EQ(2u, if0.GetDexPcAtDepth(0));
- ASSERT_EQ(42u, if0.GetMethodIndexAtDepth(0));
- ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(0));
- ASSERT_EQ(3u, if0.GetDexPcAtDepth(1));
- ASSERT_EQ(82u, if0.GetMethodIndexAtDepth(1));
- ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(1));
+ ASSERT_EQ(2u, if0.GetDepth(encoding.inline_info_encoding));
+ ASSERT_EQ(2u, if0.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(42u, if0.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(3u, if0.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(82u, if0.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1));
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, encoding, 1);
ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
@@ -767,16 +767,16 @@
ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
InlineInfo if1 = ci.GetInlineInfoOf(sm1, encoding);
- ASSERT_EQ(3u, if1.GetDepth());
- ASSERT_EQ(2u, if1.GetDexPcAtDepth(0));
- ASSERT_EQ(42u, if1.GetMethodIndexAtDepth(0));
- ASSERT_EQ(kDirect, if1.GetInvokeTypeAtDepth(0));
- ASSERT_EQ(3u, if1.GetDexPcAtDepth(1));
- ASSERT_EQ(82u, if1.GetMethodIndexAtDepth(1));
- ASSERT_EQ(kStatic, if1.GetInvokeTypeAtDepth(1));
- ASSERT_EQ(5u, if1.GetDexPcAtDepth(2));
- ASSERT_EQ(52u, if1.GetMethodIndexAtDepth(2));
- ASSERT_EQ(kVirtual, if1.GetInvokeTypeAtDepth(2));
+ ASSERT_EQ(3u, if1.GetDepth(encoding.inline_info_encoding));
+ ASSERT_EQ(2u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(42u, if1.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(kDirect, if1.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(3u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(82u, if1.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(kStatic, if1.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(5u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 2));
+ ASSERT_EQ(52u, if1.GetMethodIndexAtDepth(encoding.inline_info_encoding, 2));
+ ASSERT_EQ(kVirtual, if1.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 2));
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, encoding, 1);
ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
@@ -786,7 +786,7 @@
ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci, encoding));
ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
- ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(2));
+ ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, 2));
}
{
@@ -808,18 +808,18 @@
ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding);
- ASSERT_EQ(3u, if2.GetDepth());
- ASSERT_EQ(2u, if2.GetDexPcAtDepth(0));
- ASSERT_EQ(42u, if2.GetMethodIndexAtDepth(0));
- ASSERT_EQ(kVirtual, if2.GetInvokeTypeAtDepth(0));
- ASSERT_EQ(5u, if2.GetDexPcAtDepth(1));
- ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(1));
- ASSERT_EQ(kInterface, if2.GetInvokeTypeAtDepth(1));
- ASSERT_EQ(10u, if2.GetDexPcAtDepth(2));
- ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(2));
- ASSERT_EQ(kStatic, if2.GetInvokeTypeAtDepth(2));
+ ASSERT_EQ(3u, if2.GetDepth(encoding.inline_info_encoding));
+ ASSERT_EQ(2u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(42u, if2.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(kVirtual, if2.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0));
+ ASSERT_EQ(5u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(kInterface, if2.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1));
+ ASSERT_EQ(10u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 2));
+ ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(encoding.inline_info_encoding, 2));
+ ASSERT_EQ(kStatic, if2.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 2));
- ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0));
+ ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, 0));
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, encoding, 1);
ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci, encoding));
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 116261b..16fbfaa 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -42,11 +42,12 @@
template <bool kResolve = true>
inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
const InlineInfo& inline_info,
+ const InlineInfoEncoding& encoding,
uint8_t inlining_depth)
SHARED_REQUIRES(Locks::mutator_lock_) {
- uint32_t method_index = inline_info.GetMethodIndexAtDepth(inlining_depth);
+ uint32_t method_index = inline_info.GetMethodIndexAtDepth(encoding, inlining_depth);
InvokeType invoke_type = static_cast<InvokeType>(
- inline_info.GetInvokeTypeAtDepth(inlining_depth));
+ inline_info.GetInvokeTypeAtDepth(encoding, inlining_depth));
ArtMethod* caller = outer_method->GetDexCacheResolvedMethod(method_index, sizeof(void*));
if (!caller->IsRuntimeMethod()) {
return caller;
@@ -68,7 +69,10 @@
if (inlining_depth == 0) {
class_loader.Assign(outer_method->GetClassLoader());
} else {
- caller = GetResolvedMethod<kResolve>(outer_method, inline_info, inlining_depth - 1);
+ caller = GetResolvedMethod<kResolve>(outer_method,
+ inline_info,
+ encoding,
+ inlining_depth - 1);
class_loader.Assign(caller->GetClassLoader());
}
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 3368411..e46576e 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -280,7 +280,10 @@
DCHECK(stack_map.IsValid());
if (stack_map.HasInlineInfo(encoding.stack_map_encoding)) {
InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- caller = GetResolvedMethod(outer_method, inline_info, inline_info.GetDepth() - 1);
+ caller = GetResolvedMethod(outer_method,
+ inline_info,
+ encoding.inline_info_encoding,
+ inline_info.GetDepth(encoding.inline_info_encoding) - 1);
}
}
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 1a96d0f..f3e8dba 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -332,7 +332,8 @@
DCHECK(stack_map.IsValid());
if (stack_map.HasInlineInfo(encoding.stack_map_encoding)) {
InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- return inline_info.GetDexPcAtDepth(inline_info.GetDepth() - 1);
+ return inline_info.GetDexPcAtDepth(encoding.inline_info_encoding,
+ inline_info.GetDepth(encoding.inline_info_encoding)-1);
} else {
return stack_map.GetDexPc(encoding.stack_map_encoding);
}
diff --git a/runtime/oat.h b/runtime/oat.h
index 68e71c4..469a65f 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- static constexpr uint8_t kOatVersion[] = { '0', '7', '7', '\0' };
+ static constexpr uint8_t kOatVersion[] = { '0', '7', '8', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 2336365..c22eb92 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -130,11 +130,19 @@
if (IsInInlinedFrame()) {
size_t depth_in_stack_map = current_inlining_depth_ - 1;
InlineInfo inline_info = GetCurrentInlineInfo();
+ const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
+ CodeInfoEncoding encoding = method_header->GetOptimizedCodeInfo().ExtractEncoding();
DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
bool allow_resolve = walk_kind_ != StackWalkKind::kIncludeInlinedFramesNoResolve;
return allow_resolve
- ? GetResolvedMethod<true>(*GetCurrentQuickFrame(), inline_info, depth_in_stack_map)
- : GetResolvedMethod<false>(*GetCurrentQuickFrame(), inline_info, depth_in_stack_map);
+ ? GetResolvedMethod<true>(*GetCurrentQuickFrame(),
+ inline_info,
+ encoding.inline_info_encoding,
+ depth_in_stack_map)
+ : GetResolvedMethod<false>(*GetCurrentQuickFrame(),
+ inline_info,
+ encoding.inline_info_encoding,
+ depth_in_stack_map);
} else {
return *cur_quick_frame_;
}
@@ -148,7 +156,10 @@
} else if (cur_quick_frame_ != nullptr) {
if (IsInInlinedFrame()) {
size_t depth_in_stack_map = current_inlining_depth_ - 1;
- return GetCurrentInlineInfo().GetDexPcAtDepth(depth_in_stack_map);
+ const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
+ CodeInfoEncoding encoding = method_header->GetOptimizedCodeInfo().ExtractEncoding();
+ return GetCurrentInlineInfo().GetDexPcAtDepth(encoding.inline_info_encoding,
+ depth_in_stack_map);
} else if (cur_oat_quick_method_header_ == nullptr) {
return DexFile::kDexNoIndex;
} else {
@@ -875,7 +886,7 @@
if (stack_map.IsValid() && stack_map.HasInlineInfo(encoding.stack_map_encoding)) {
InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
DCHECK_EQ(current_inlining_depth_, 0u);
- for (current_inlining_depth_ = inline_info.GetDepth();
+ for (current_inlining_depth_ = inline_info.GetDepth(encoding.inline_info_encoding);
current_inlining_depth_ != 0;
--current_inlining_depth_) {
bool should_continue = VisitFrame();
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index b51baf1..a7e7c21 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -101,6 +101,17 @@
<< ")\n";
}
+void InlineInfoEncoding::Dump(VariableIndentationOutputStream* vios) const {
+ vios->Stream()
+ << "InlineInfoEncoding"
+ << " (method_index_bit_offset=" << static_cast<uint32_t>(kMethodIndexBitOffset)
+ << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_)
+ << ", invoke_type_bit_offset=" << static_cast<uint32_t>(invoke_type_bit_offset_)
+ << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_)
+ << ", total_bit_size=" << static_cast<uint32_t>(total_bit_size_)
+ << ")\n";
+}
+
void CodeInfo::Dump(VariableIndentationOutputStream* vios,
uint32_t code_offset,
uint16_t number_of_dex_registers,
@@ -113,6 +124,9 @@
<< ")\n";
ScopedIndentation indent1(vios);
encoding.stack_map_encoding.Dump(vios);
+ if (HasInlineInfo(encoding)) {
+ encoding.inline_info_encoding.Dump(vios);
+ }
// Display the Dex register location catalog.
GetDexRegisterLocationCatalog(encoding).Dump(vios, *this);
// Display stack maps along with (live) Dex register maps.
@@ -207,18 +221,22 @@
void InlineInfo::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
uint16_t number_of_dex_registers[]) const {
- vios->Stream() << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
+ InlineInfoEncoding inline_info_encoding = code_info.ExtractEncoding().inline_info_encoding;
+ vios->Stream() << "InlineInfo with depth "
+ << static_cast<uint32_t>(GetDepth(inline_info_encoding))
+ << "\n";
- for (size_t i = 0; i < GetDepth(); ++i) {
+ for (size_t i = 0; i < GetDepth(inline_info_encoding); ++i) {
vios->Stream()
<< " At depth " << i
<< std::hex
- << " (dex_pc=0x" << GetDexPcAtDepth(i)
+ << " (dex_pc=0x" << GetDexPcAtDepth(inline_info_encoding, i)
<< std::dec
- << ", method_index=" << GetMethodIndexAtDepth(i)
- << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(i))
+ << ", method_index=" << GetMethodIndexAtDepth(inline_info_encoding, i)
+ << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(inline_info_encoding,
+ i))
<< ")\n";
- if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) {
+ if (HasDexRegisterMapAtDepth(inline_info_encoding, i) && (number_of_dex_registers != nullptr)) {
CodeInfoEncoding encoding = code_info.ExtractEncoding();
DexRegisterMap dex_register_map =
code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]);
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 9e8884e..7c50f97 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -24,12 +24,6 @@
namespace art {
-#define ELEMENT_BYTE_OFFSET_AFTER(PreviousElement) \
- k ## PreviousElement ## Offset + sizeof(PreviousElement ## Type)
-
-#define ELEMENT_BIT_OFFSET_AFTER(PreviousElement) \
- k ## PreviousElement ## BitOffset + PreviousElement ## BitSize
-
class VariableIndentationOutputStream;
// Size of a frame slot, in bytes. This constant is a signed value,
@@ -888,102 +882,139 @@
friend class StackMapStream;
};
+class InlineInfoEncoding {
+ public:
+ void SetFromSizes(size_t method_index_max,
+ size_t dex_pc_max,
+ size_t invoke_type_max,
+ size_t dex_register_map_size) {
+ total_bit_size_ = kMethodIndexBitOffset;
+ total_bit_size_ += MinimumBitsToStore(method_index_max);
+
+ dex_pc_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
+ total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max);
+
+ invoke_type_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
+ total_bit_size_ += MinimumBitsToStore(invoke_type_max);
+
+ // We also need +1 for kNoDexRegisterMap, but since the size is strictly
+ // greater than any offset we might try to encode, we already implicitly have it.
+ dex_register_map_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
+ total_bit_size_ += MinimumBitsToStore(dex_register_map_size);
+ }
+
+ ALWAYS_INLINE FieldEncoding GetMethodIndexEncoding() const {
+ return FieldEncoding(kMethodIndexBitOffset, dex_pc_bit_offset_);
+ }
+ ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const {
+ return FieldEncoding(dex_pc_bit_offset_, invoke_type_bit_offset_, -1 /* min_value */);
+ }
+ ALWAYS_INLINE FieldEncoding GetInvokeTypeEncoding() const {
+ return FieldEncoding(invoke_type_bit_offset_, dex_register_map_bit_offset_);
+ }
+ ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const {
+ return FieldEncoding(dex_register_map_bit_offset_, total_bit_size_, -1 /* min_value */);
+ }
+ ALWAYS_INLINE size_t GetEntrySize() const {
+ return RoundUp(total_bit_size_, kBitsPerByte) / kBitsPerByte;
+ }
+
+ void Dump(VariableIndentationOutputStream* vios) const;
+
+ private:
+ static constexpr uint8_t kIsLastBitOffset = 0;
+ static constexpr uint8_t kMethodIndexBitOffset = 1;
+ uint8_t dex_pc_bit_offset_;
+ uint8_t invoke_type_bit_offset_;
+ uint8_t dex_register_map_bit_offset_;
+ uint8_t total_bit_size_;
+};
+
/**
* Inline information for a specific PC. The information is of the form:
*
- * [inlining_depth, entry+]
- *
- * where `entry` is of the form:
- *
- * [dex_pc, method_index, dex_register_map_offset].
+ * [is_last, method_index, dex_pc, invoke_type, dex_register_map_offset]+.
*/
class InlineInfo {
public:
- // Memory layout: fixed contents.
- typedef uint8_t DepthType;
- // Memory layout: single entry contents.
- typedef uint32_t MethodIndexType;
- typedef uint32_t DexPcType;
- typedef uint8_t InvokeTypeType;
- typedef uint32_t DexRegisterMapType;
-
- explicit InlineInfo(MemoryRegion region) : region_(region) {}
-
- DepthType GetDepth() const {
- return region_.LoadUnaligned<DepthType>(kDepthOffset);
+ explicit InlineInfo(MemoryRegion region) : region_(region) {
}
- void SetDepth(DepthType depth) {
- region_.StoreUnaligned<DepthType>(kDepthOffset, depth);
+ ALWAYS_INLINE uint32_t GetDepth(const InlineInfoEncoding& encoding) const {
+ size_t depth = 0;
+ while (!GetRegionAtDepth(encoding, depth++).LoadBit(0)) { } // Check is_last bit.
+ return depth;
}
- MethodIndexType GetMethodIndexAtDepth(DepthType depth) const {
- return region_.LoadUnaligned<MethodIndexType>(
- kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset);
+ ALWAYS_INLINE void SetDepth(const InlineInfoEncoding& encoding, uint32_t depth) {
+ DCHECK_GT(depth, 0u);
+ for (size_t d = 0; d < depth; ++d) {
+ GetRegionAtDepth(encoding, d).StoreBit(0, d == depth - 1); // Set is_last bit.
+ }
}
- void SetMethodIndexAtDepth(DepthType depth, MethodIndexType index) {
- region_.StoreUnaligned<MethodIndexType>(
- kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset, index);
+ ALWAYS_INLINE uint32_t GetMethodIndexAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth) const {
+ return encoding.GetMethodIndexEncoding().Load(GetRegionAtDepth(encoding, depth));
}
- DexPcType GetDexPcAtDepth(DepthType depth) const {
- return region_.LoadUnaligned<DexPcType>(
- kFixedSize + depth * SingleEntrySize() + kDexPcOffset);
+ ALWAYS_INLINE void SetMethodIndexAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth,
+ uint32_t index) {
+ encoding.GetMethodIndexEncoding().Store(GetRegionAtDepth(encoding, depth), index);
}
- void SetDexPcAtDepth(DepthType depth, DexPcType dex_pc) {
- region_.StoreUnaligned<DexPcType>(
- kFixedSize + depth * SingleEntrySize() + kDexPcOffset, dex_pc);
+ ALWAYS_INLINE uint32_t GetDexPcAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth) const {
+ return encoding.GetDexPcEncoding().Load(GetRegionAtDepth(encoding, depth));
}
- InvokeTypeType GetInvokeTypeAtDepth(DepthType depth) const {
- return region_.LoadUnaligned<InvokeTypeType>(
- kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset);
+ ALWAYS_INLINE void SetDexPcAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth,
+ uint32_t dex_pc) {
+ encoding.GetDexPcEncoding().Store(GetRegionAtDepth(encoding, depth), dex_pc);
}
- void SetInvokeTypeAtDepth(DepthType depth, InvokeTypeType invoke_type) {
- region_.StoreUnaligned<InvokeTypeType>(
- kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset, invoke_type);
+ ALWAYS_INLINE uint32_t GetInvokeTypeAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth) const {
+ return encoding.GetInvokeTypeEncoding().Load(GetRegionAtDepth(encoding, depth));
}
- DexRegisterMapType GetDexRegisterMapOffsetAtDepth(DepthType depth) const {
- return region_.LoadUnaligned<DexRegisterMapType>(
- kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset);
+ ALWAYS_INLINE void SetInvokeTypeAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth,
+ uint32_t invoke_type) {
+ encoding.GetInvokeTypeEncoding().Store(GetRegionAtDepth(encoding, depth), invoke_type);
}
- void SetDexRegisterMapOffsetAtDepth(DepthType depth, DexRegisterMapType offset) {
- region_.StoreUnaligned<DexRegisterMapType>(
- kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset, offset);
+ ALWAYS_INLINE uint32_t GetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth) const {
+ return encoding.GetDexRegisterMapEncoding().Load(GetRegionAtDepth(encoding, depth));
}
- bool HasDexRegisterMapAtDepth(DepthType depth) const {
- return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoDexRegisterMap;
+ ALWAYS_INLINE void SetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth,
+ uint32_t offset) {
+ encoding.GetDexRegisterMapEncoding().Store(GetRegionAtDepth(encoding, depth), offset);
}
- static size_t SingleEntrySize() {
- return kFixedEntrySize;
+ ALWAYS_INLINE bool HasDexRegisterMapAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth) const {
+ return GetDexRegisterMapOffsetAtDepth(encoding, depth) != StackMap::kNoDexRegisterMap;
}
void Dump(VariableIndentationOutputStream* vios,
- const CodeInfo& info, uint16_t* number_of_dex_registers) const;
-
+ const CodeInfo& info,
+ uint16_t* number_of_dex_registers) const;
private:
- static constexpr int kDepthOffset = 0;
- static constexpr int kFixedSize = ELEMENT_BYTE_OFFSET_AFTER(Depth);
-
- static constexpr int kMethodIndexOffset = 0;
- static constexpr int kDexPcOffset = ELEMENT_BYTE_OFFSET_AFTER(MethodIndex);
- static constexpr int kInvokeTypeOffset = ELEMENT_BYTE_OFFSET_AFTER(DexPc);
- static constexpr int kDexRegisterMapOffset = ELEMENT_BYTE_OFFSET_AFTER(InvokeType);
- static constexpr int kFixedEntrySize = ELEMENT_BYTE_OFFSET_AFTER(DexRegisterMap);
+ ALWAYS_INLINE MemoryRegion GetRegionAtDepth(const InlineInfoEncoding& encoding,
+ uint32_t depth) const {
+ size_t entry_size = encoding.GetEntrySize();
+ DCHECK_GT(entry_size, 0u);
+ return region_.Subregion(depth * entry_size, entry_size);
+ }
MemoryRegion region_;
-
- friend class CodeInfo;
- friend class StackMap;
- friend class StackMapStream;
};
// Most of the fields are encoded as ULEB128 to save space.
@@ -993,6 +1024,7 @@
uint32_t stack_map_size_in_bytes;
uint32_t number_of_location_catalog_entries;
StackMapEncoding stack_map_encoding;
+ InlineInfoEncoding inline_info_encoding;
uint8_t header_size;
CodeInfoEncoding() { }
@@ -1003,9 +1035,18 @@
number_of_stack_maps = DecodeUnsignedLeb128(&ptr);
stack_map_size_in_bytes = DecodeUnsignedLeb128(&ptr);
number_of_location_catalog_entries = DecodeUnsignedLeb128(&ptr);
- static_assert(alignof(StackMapEncoding) == 1, "StackMapEncoding should not require alignment");
+ static_assert(alignof(StackMapEncoding) == 1,
+ "StackMapEncoding should not require alignment");
stack_map_encoding = *reinterpret_cast<const StackMapEncoding*>(ptr);
ptr += sizeof(StackMapEncoding);
+ if (stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0) {
+ static_assert(alignof(InlineInfoEncoding) == 1,
+ "InlineInfoEncoding should not require alignment");
+ inline_info_encoding = *reinterpret_cast<const InlineInfoEncoding*>(ptr);
+ ptr += sizeof(InlineInfoEncoding);
+ } else {
+ inline_info_encoding = InlineInfoEncoding{}; // NOLINT.
+ }
header_size = dchecked_integral_cast<uint8_t>(ptr - reinterpret_cast<const uint8_t*>(data));
}
@@ -1015,8 +1056,12 @@
EncodeUnsignedLeb128(dest, number_of_stack_maps);
EncodeUnsignedLeb128(dest, stack_map_size_in_bytes);
EncodeUnsignedLeb128(dest, number_of_location_catalog_entries);
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&stack_map_encoding);
- dest->insert(dest->end(), ptr, ptr + sizeof(stack_map_encoding));
+ const uint8_t* stack_map_ptr = reinterpret_cast<const uint8_t*>(&stack_map_encoding);
+ dest->insert(dest->end(), stack_map_ptr, stack_map_ptr + sizeof(StackMapEncoding));
+ if (stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0) {
+ const uint8_t* inline_info_ptr = reinterpret_cast<const uint8_t*>(&inline_info_encoding);
+ dest->insert(dest->end(), inline_info_ptr, inline_info_ptr + sizeof(InlineInfoEncoding));
+ }
}
};
@@ -1110,11 +1155,11 @@
InlineInfo inline_info,
const CodeInfoEncoding& encoding,
uint32_t number_of_dex_registers) const {
- if (!inline_info.HasDexRegisterMapAtDepth(depth)) {
+ if (!inline_info.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, depth)) {
return DexRegisterMap();
} else {
- uint32_t offset = GetDexRegisterMapsOffset(encoding)
- + inline_info.GetDexRegisterMapOffsetAtDepth(depth);
+ uint32_t offset = GetDexRegisterMapsOffset(encoding) +
+ inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info_encoding, depth);
size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers);
return DexRegisterMap(region_.Subregion(offset, size));
}
@@ -1124,9 +1169,7 @@
DCHECK(stack_map.HasInlineInfo(encoding.stack_map_encoding));
uint32_t offset = stack_map.GetInlineDescriptorOffset(encoding.stack_map_encoding)
+ GetDexRegisterMapsOffset(encoding);
- uint8_t depth = region_.LoadUnaligned<uint8_t>(offset);
- return InlineInfo(region_.Subregion(offset,
- InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize()));
+ return InlineInfo(region_.Subregion(offset, region_.size() - offset));
}
StackMap GetStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
diff --git a/test/564-checker-bitcount/src/Main.java b/test/564-checker-bitcount/src/Main.java
index 2683b25..aad9689 100644
--- a/test/564-checker-bitcount/src/Main.java
+++ b/test/564-checker-bitcount/src/Main.java
@@ -20,67 +20,187 @@
// CHECK-START-X86_64: int Main.bits32(int) disassembly (after)
// CHECK-DAG: popcnt
- /// CHECK-START: int Main.bits32(int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount
- /// CHECK-DAG: Return [<<Result>>]
- private static int bits32(int x) {
+
+ /// CHECK-START: int Main.$noinline$BitCountBoolean(boolean) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int $noinline$BitCountBoolean(boolean x) {
+ if (doThrow) { throw new Error(); } // Try defeating inlining.
+ return Integer.bitCount(x ? 1 : 0);
+ }
+
+ /// CHECK-START: int Main.$noinline$BitCountByte(byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int $noinline$BitCountByte(byte x) {
+ if (doThrow) { throw new Error(); } // Try defeating inlining.
return Integer.bitCount(x);
}
- /// CHECK-START: int Main.bits64(long) intrinsics_recognition (after)
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongBitCount
- /// CHECK-DAG: Return [<<Result>>]
- private static int bits64(long x) {
+ /// CHECK-START: int Main.$noinline$BitCountShort(short) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int $noinline$BitCountShort(short x) {
+ if (doThrow) { throw new Error(); } // Try defeating inlining.
+ return Integer.bitCount(x);
+ }
+
+ /// CHECK-START: int Main.$noinline$BitCountChar(char) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int $noinline$BitCountChar(char x) {
+ if (doThrow) { throw new Error(); } // Try defeating inlining.
+ return Integer.bitCount(x);
+ }
+
+ /// CHECK-START: int Main.$noinline$BitCountInt(int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int $noinline$BitCountInt(int x) {
+ if (doThrow) { throw new Error(); } // Try defeating inlining.
+ return Integer.bitCount(x);
+ }
+
+ /// CHECK-START: int Main.$noinline$BitCountLong(long) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongBitCount
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int $noinline$BitCountLong(long x) {
+ if (doThrow) { throw new Error(); } // Try defeating inlining.
return Long.bitCount(x);
}
+ public static void testBitCountBoolean() {
+ expectEqualsInt($noinline$BitCountBoolean(false), 0);
+ expectEqualsInt($noinline$BitCountBoolean(true), 1);
+ }
+
+ public static void testBitCountByte() {
+ // Number of bits in an 32-bit integer representing the sign
+ // extension of a byte value widened to an int.
+ int signExtensionSize = Integer.SIZE - Byte.SIZE;
+ // Sign bit position in a byte.
+ int signBit = Byte.SIZE - 1;
+
+ expectEqualsInt($noinline$BitCountByte((byte) 0x00), 0);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x01), 1);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x10), 1);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x11), 2);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x03), 2);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x70), 3);
+ expectEqualsInt($noinline$BitCountByte((byte) 0xF0), 4 + signExtensionSize);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x0F), 4);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x12), 2);
+ expectEqualsInt($noinline$BitCountByte((byte) 0x9A), 4 + signExtensionSize);
+ expectEqualsInt($noinline$BitCountByte((byte) 0xFF), 8 + signExtensionSize);
+
+ for (int i = 0; i < Byte.SIZE; i++) {
+ expectEqualsInt($noinline$BitCountByte((byte) (1 << i)),
+ (i < signBit) ? 1 : 1 + signExtensionSize);
+ }
+ }
+
+ public static void testBitCountShort() {
+ // Number of bits in an 32-bit integer representing the sign
+ // extension of a short value widened to an int.
+ int signExtensionSize = Integer.SIZE - Short.SIZE;
+ // Sign bit position in a short.
+ int signBit = Short.SIZE - 1;
+
+ expectEqualsInt($noinline$BitCountShort((short) 0x0000), 0);
+ expectEqualsInt($noinline$BitCountShort((short) 0x0001), 1);
+ expectEqualsInt($noinline$BitCountShort((short) 0x1000), 1);
+ expectEqualsInt($noinline$BitCountShort((short) 0x1001), 2);
+ expectEqualsInt($noinline$BitCountShort((short) 0x0003), 2);
+ expectEqualsInt($noinline$BitCountShort((short) 0x7000), 3);
+ expectEqualsInt($noinline$BitCountShort((short) 0x0F00), 4);
+ expectEqualsInt($noinline$BitCountShort((short) 0x0011), 2);
+ expectEqualsInt($noinline$BitCountShort((short) 0x1100), 2);
+ expectEqualsInt($noinline$BitCountShort((short) 0x1111), 4);
+ expectEqualsInt($noinline$BitCountShort((short) 0x1234), 5);
+ expectEqualsInt($noinline$BitCountShort((short) 0x9ABC), 9 + signExtensionSize);
+ expectEqualsInt($noinline$BitCountShort((short) 0xFFFF), 16 + signExtensionSize);
+
+ for (int i = 0; i < Short.SIZE; i++) {
+ expectEqualsInt($noinline$BitCountShort((short) (1 << i)),
+ (i < signBit) ? 1 : 1 + signExtensionSize);
+ }
+ }
+
+ public static void testBitCountChar() {
+ expectEqualsInt($noinline$BitCountChar((char) 0x0000), 0);
+ expectEqualsInt($noinline$BitCountChar((char) 0x0001), 1);
+ expectEqualsInt($noinline$BitCountChar((char) 0x1000), 1);
+ expectEqualsInt($noinline$BitCountChar((char) 0x1001), 2);
+ expectEqualsInt($noinline$BitCountChar((char) 0x0003), 2);
+ expectEqualsInt($noinline$BitCountChar((char) 0x7000), 3);
+ expectEqualsInt($noinline$BitCountChar((char) 0x0F00), 4);
+ expectEqualsInt($noinline$BitCountChar((char) 0x0011), 2);
+ expectEqualsInt($noinline$BitCountChar((char) 0x1100), 2);
+ expectEqualsInt($noinline$BitCountChar((char) 0x1111), 4);
+ expectEqualsInt($noinline$BitCountChar((char) 0x1234), 5);
+ expectEqualsInt($noinline$BitCountChar((char) 0x9ABC), 9);
+ expectEqualsInt($noinline$BitCountChar((char) 0xFFFF), 16);
+
+ for (int i = 0; i < Character.SIZE; i++) {
+ expectEqualsInt($noinline$BitCountChar((char) (1 << i)), 1);
+ }
+ }
+
+ public static void testBitCountInt() {
+ expectEqualsInt($noinline$BitCountInt(0x00000000), 0);
+ expectEqualsInt($noinline$BitCountInt(0x00000001), 1);
+ expectEqualsInt($noinline$BitCountInt(0x10000000), 1);
+ expectEqualsInt($noinline$BitCountInt(0x10000001), 2);
+ expectEqualsInt($noinline$BitCountInt(0x00000003), 2);
+ expectEqualsInt($noinline$BitCountInt(0x70000000), 3);
+ expectEqualsInt($noinline$BitCountInt(0x000F0000), 4);
+ expectEqualsInt($noinline$BitCountInt(0x00001111), 4);
+ expectEqualsInt($noinline$BitCountInt(0x11110000), 4);
+ expectEqualsInt($noinline$BitCountInt(0x11111111), 8);
+ expectEqualsInt($noinline$BitCountInt(0x12345678), 13);
+ expectEqualsInt($noinline$BitCountInt(0x9ABCDEF0), 19);
+ expectEqualsInt($noinline$BitCountInt(0xFFFFFFFF), 32);
+
+ for (int i = 0; i < Integer.SIZE; i++) {
+ expectEqualsInt($noinline$BitCountInt(1 << i), 1);
+ }
+ }
+
+ public static void testBitCountLong() {
+ expectEqualsInt($noinline$BitCountLong(0x0000000000000000L), 0);
+ expectEqualsInt($noinline$BitCountLong(0x0000000000000001L), 1);
+ expectEqualsInt($noinline$BitCountLong(0x1000000000000000L), 1);
+ expectEqualsInt($noinline$BitCountLong(0x1000000000000001L), 2);
+ expectEqualsInt($noinline$BitCountLong(0x0000000000000003L), 2);
+ expectEqualsInt($noinline$BitCountLong(0x7000000000000000L), 3);
+ expectEqualsInt($noinline$BitCountLong(0x000F000000000000L), 4);
+ expectEqualsInt($noinline$BitCountLong(0x0000000011111111L), 8);
+ expectEqualsInt($noinline$BitCountLong(0x1111111100000000L), 8);
+ expectEqualsInt($noinline$BitCountLong(0x1111111111111111L), 16);
+ expectEqualsInt($noinline$BitCountLong(0x123456789ABCDEF1L), 33);
+ expectEqualsInt($noinline$BitCountLong(0xFFFFFFFFFFFFFFFFL), 64);
+
+ for (int i = 0; i < Long.SIZE; i++) {
+ expectEqualsInt($noinline$BitCountLong(1L << i), 1);
+ }
+ }
+
public static void main(String args[]) {
- expectEquals32(bits32(0x00000000), 0);
- expectEquals32(bits32(0x00000001), 1);
- expectEquals32(bits32(0x10000000), 1);
- expectEquals32(bits32(0x10000001), 2);
- expectEquals32(bits32(0x00000003), 2);
- expectEquals32(bits32(0x70000000), 3);
- expectEquals32(bits32(0x000F0000), 4);
- expectEquals32(bits32(0x00001111), 4);
- expectEquals32(bits32(0x11110000), 4);
- expectEquals32(bits32(0x11111111), 8);
- expectEquals32(bits32(0x12345678), 13);
- expectEquals32(bits32(0x9ABCDEF0), 19);
- expectEquals32(bits32(0xFFFFFFFF), 32);
-
- for (int i = 0; i < 32; i++) {
- expectEquals32(bits32(1 << i), 1);
- }
-
- expectEquals64(bits64(0x0000000000000000L), 0);
- expectEquals64(bits64(0x0000000000000001L), 1);
- expectEquals64(bits64(0x1000000000000000L), 1);
- expectEquals64(bits64(0x1000000000000001L), 2);
- expectEquals64(bits64(0x0000000000000003L), 2);
- expectEquals64(bits64(0x7000000000000000L), 3);
- expectEquals64(bits64(0x000F000000000000L), 4);
- expectEquals64(bits64(0x0000000011111111L), 8);
- expectEquals64(bits64(0x1111111100000000L), 8);
- expectEquals64(bits64(0x1111111111111111L), 16);
- expectEquals64(bits64(0x123456789ABCDEF1L), 33);
- expectEquals64(bits64(0xFFFFFFFFFFFFFFFFL), 64);
-
- for (int i = 0; i < 64; i++) {
- expectEquals64(bits64(1L << i), 1);
- }
+ testBitCountBoolean();
+ testBitCountByte();
+ testBitCountShort();
+ testBitCountChar();
+ testBitCountInt();
+ testBitCountLong();
System.out.println("passed");
}
- private static void expectEquals32(int expected, int result) {
+ private static void expectEqualsInt(int expected, int result) {
if (expected != result) {
throw new Error("Expected: " + expected + ", found: " + result);
}
}
- private static void expectEquals64(long expected, long result) {
- if (expected != result) {
- throw new Error("Expected: " + expected + ", found: " + result);
- }
- }
+
+ private static boolean doThrow = false;
}
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py
index 6ff19d5..520c4ae 100644
--- a/tools/checker/match/file.py
+++ b/tools/checker/match/file.py
@@ -172,8 +172,8 @@
# match a check group against the first output group of the same name.
c1Pass = c1File.findPass(testCase.name)
if c1Pass is None:
- Logger.fail("Test case \"{}\" not found in the CFG file".format(testCase.name),
- testCase.fileName, testCase.startLineNo)
+ Logger.fail("Test case not found in the CFG file",
+ testCase.fileName, testCase.startLineNo, testCase.name)
Logger.startTest(testCase.name)
try: