Move MethodInfo to CodeInfo.
There is no need to treat it specially any more,
because of the de-duplication at BitTable level.
This saves 0.6% of oat file size.
Test: test-art-host-gtest
Change-Id: Ife7927d736243879a41d6f325d49ebf6930a63f6
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 0ed26d3..e6f3d0b 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -45,7 +45,7 @@
namespace art {
inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
- const MethodInfo& method_info,
+ const CodeInfo& code_info,
const BitTableRange<InlineInfo>& inline_infos)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!outer_method->IsObsolete());
@@ -62,7 +62,7 @@
return inline_info.GetArtMethod();
}
- uint32_t method_index = inline_info.GetMethodIndex(method_info);
+ uint32_t method_index = code_info.GetMethodIndexOf(inline_info);
if (inline_info.GetDexPc() == static_cast<uint32_t>(-1)) {
// "charAt" special case. It is the only non-leaf method we inline across dex files.
ArtMethod* inlined_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt);
@@ -77,7 +77,7 @@
for (InlineInfo inline_info : inline_infos) {
DCHECK(!inline_info.EncodesArtMethod());
DCHECK_NE(inline_info.GetDexPc(), static_cast<uint32_t>(-1));
- uint32_t method_index = inline_info.GetMethodIndex(method_info);
+ uint32_t method_index = code_info.GetMethodIndexOf(inline_info);
ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index,
method->GetDexCache(),
method->GetClassLoader());
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index a5ebce5..5421f69 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -202,12 +202,11 @@
DCHECK(current_code->IsOptimized());
uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
CodeInfo code_info(current_code, CodeInfo::DecodeFlags::InlineInfoOnly);
- MethodInfo method_info = current_code->GetOptimizedMethodInfo();
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
DCHECK(stack_map.IsValid());
BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map);
if (!inline_infos.empty()) {
- caller = GetResolvedMethod(outer_method, method_info, inline_infos);
+ caller = GetResolvedMethod(outer_method, code_info, inline_infos);
}
}
if (kIsDebugBuild && do_caller_check) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index be4e4e6..aca169b 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1236,7 +1236,6 @@
CHECK(current_code->IsOptimized());
uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
CodeInfo code_info(current_code);
- MethodInfo method_info = current_code->GetOptimizedMethodInfo();
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
CHECK(stack_map.IsValid());
uint32_t dex_pc = stack_map.GetDexPc();
@@ -1261,7 +1260,7 @@
tag = "encoded ";
caller = inline_info.GetArtMethod();
} else {
- uint32_t method_index = inline_info.GetMethodIndex(method_info);
+ uint32_t method_index = code_info.GetMethodIndexOf(inline_info);
if (dex_pc == static_cast<uint32_t>(-1)) {
tag = "special ";
CHECK(inline_info.Equals(inline_infos.back()));
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 9aa0556..b92affa 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -411,7 +411,6 @@
uint8_t* JitCodeCache::CommitCode(Thread* self,
ArtMethod* method,
uint8_t* stack_map,
- uint8_t* method_info,
uint8_t* roots_data,
const uint8_t* code,
size_t code_size,
@@ -423,7 +422,6 @@
uint8_t* result = CommitCodeInternal(self,
method,
stack_map,
- method_info,
roots_data,
code,
code_size,
@@ -438,7 +436,6 @@
result = CommitCodeInternal(self,
method,
stack_map,
- method_info,
roots_data,
code,
code_size,
@@ -748,7 +745,6 @@
uint8_t* JitCodeCache::CommitCodeInternal(Thread* self,
ArtMethod* method,
uint8_t* stack_map,
- uint8_t* method_info,
uint8_t* roots_data,
const uint8_t* code,
size_t code_size,
@@ -783,7 +779,6 @@
method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
new (method_header) OatQuickMethodHeader(
(stack_map != nullptr) ? code_ptr - stack_map : 0u,
- (method_info != nullptr) ? code_ptr - method_info : 0u,
code_size);
// Flush caches before we remove write permission because some ARMv8 Qualcomm kernels may
// trigger a segfault if a page fault occurs when requesting a cache maintenance operation.
@@ -1046,14 +1041,12 @@
size_t JitCodeCache::ReserveData(Thread* self,
size_t stack_map_size,
- size_t method_info_size,
size_t number_of_roots,
ArtMethod* method,
uint8_t** stack_map_data,
- uint8_t** method_info_data,
uint8_t** roots_data) {
size_t table_size = ComputeRootTableSize(number_of_roots);
- size_t size = RoundUp(stack_map_size + method_info_size + table_size, sizeof(void*));
+ size_t size = RoundUp(stack_map_size + table_size, sizeof(void*));
uint8_t* result = nullptr;
{
@@ -1083,13 +1076,11 @@
if (result != nullptr) {
*roots_data = result;
*stack_map_data = result + table_size;
- *method_info_data = *stack_map_data + stack_map_size;
FillRootTableLength(*roots_data, number_of_roots);
return size;
} else {
*roots_data = nullptr;
*stack_map_data = nullptr;
- *method_info_data = nullptr;
return 0;
}
}
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index d17fb26..29f9c9c 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -136,7 +136,6 @@
uint8_t* CommitCode(Thread* self,
ArtMethod* method,
uint8_t* stack_map,
- uint8_t* method_info,
uint8_t* roots_data,
const uint8_t* code,
size_t code_size,
@@ -166,11 +165,9 @@
// Return the number of bytes allocated.
size_t ReserveData(Thread* self,
size_t stack_map_size,
- size_t method_info_size,
size_t number_of_roots,
ArtMethod* method,
uint8_t** stack_map_data,
- uint8_t** method_info_data,
uint8_t** roots_data)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!lock_);
@@ -295,7 +292,6 @@
uint8_t* CommitCodeInternal(Thread* self,
ArtMethod* method,
uint8_t* stack_map,
- uint8_t* method_info,
uint8_t* roots_data,
const uint8_t* code,
size_t code_size,
diff --git a/runtime/method_info.h b/runtime/method_info.h
deleted file mode 100644
index 6f74678..0000000
--- a/runtime/method_info.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef ART_RUNTIME_METHOD_INFO_H_
-#define ART_RUNTIME_METHOD_INFO_H_
-
-#include <android-base/logging.h>
-
-#include "base/leb128.h"
-#include "base/macros.h"
-#include "base/bit_memory_region.h"
-
-namespace art {
-
-// Method info is for not dedupe friendly data of a method. Currently it only holds methods indices.
-// Putting this data in MethodInfo instead of code infos saves ~5% oat size.
-class MethodInfo {
- using MethodIndexType = uint16_t;
-
- public:
- // Reading mode
- explicit MethodInfo(const uint8_t* ptr) {
- if (ptr != nullptr) {
- num_method_indices_ = DecodeUnsignedLeb128(&ptr);
- region_ = BitMemoryRegion(
- MemoryRegion(const_cast<uint8_t*>(ptr), num_method_indices_ * sizeof(MethodIndexType)));
- }
- }
-
- // Writing mode
- MethodInfo(uint8_t* ptr, size_t num_method_indices) : num_method_indices_(num_method_indices) {
- DCHECK(ptr != nullptr);
- ptr = EncodeUnsignedLeb128(ptr, num_method_indices_);
- region_ = BitMemoryRegion(MemoryRegion(ptr, num_method_indices_ * sizeof(MethodIndexType)));
- }
-
- static size_t ComputeSize(size_t num_method_indices) {
- uint8_t temp[8];
- uint8_t* ptr = temp;
- ptr = EncodeUnsignedLeb128(ptr, num_method_indices);
- return (ptr - temp) + num_method_indices * sizeof(MethodIndexType);
- }
-
- ALWAYS_INLINE MethodIndexType GetMethodIndex(size_t index) const {
- // Use bit functions to avoid pesky alignment requirements.
- return region_.LoadBits(index * BitSizeOf<MethodIndexType>(), BitSizeOf<MethodIndexType>());
- }
-
- void SetMethodIndex(size_t index, MethodIndexType method_index) {
- region_.StoreBits(index * BitSizeOf<MethodIndexType>(),
- method_index,
- BitSizeOf<MethodIndexType>());
- }
-
- size_t NumMethodIndices() const {
- return num_method_indices_;
- }
-
- private:
- size_t num_method_indices_ = 0u;
- BitMemoryRegion region_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_METHOD_INFO_H_
diff --git a/runtime/oat.h b/runtime/oat.h
index c286f46..69aaceb 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: Deduplicate stackmaps at BitTable level.
- static constexpr uint8_t kOatVersion[] = { '1', '5', '7', '\0' };
+ // Last oat version changed reason: Move MethodInfo into CodeInfo.
+ static constexpr uint8_t kOatVersion[] = { '1', '5', '8', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_quick_method_header.h b/runtime/oat_quick_method_header.h
index 3b9f466..8798c69 100644
--- a/runtime/oat_quick_method_header.h
+++ b/runtime/oat_quick_method_header.h
@@ -20,7 +20,6 @@
#include "arch/instruction_set.h"
#include "base/macros.h"
#include "base/utils.h"
-#include "method_info.h"
#include "quick/quick_method_frame_info.h"
#include "stack_map.h"
@@ -33,10 +32,8 @@
public:
OatQuickMethodHeader() = default;
OatQuickMethodHeader(uint32_t vmap_table_offset,
- uint32_t method_info_offset,
uint32_t code_size)
: vmap_table_offset_(vmap_table_offset),
- method_info_offset_(method_info_offset),
code_size_(code_size) {
}
@@ -74,20 +71,6 @@
return code_ - vmap_table_offset_;
}
- const void* GetOptimizedMethodInfoPtr() const {
- DCHECK(IsOptimized());
- return reinterpret_cast<const void*>(code_ - method_info_offset_);
- }
-
- uint8_t* GetOptimizedMethodInfoPtr() {
- DCHECK(IsOptimized());
- return code_ - method_info_offset_;
- }
-
- MethodInfo GetOptimizedMethodInfo() const {
- return MethodInfo(reinterpret_cast<const uint8_t*>(GetOptimizedMethodInfoPtr()));
- }
-
const uint8_t* GetCode() const {
return code_;
}
@@ -112,18 +95,6 @@
return &vmap_table_offset_;
}
- uint32_t GetMethodInfoOffset() const {
- return method_info_offset_;
- }
-
- void SetMethodInfoOffset(uint32_t offset) {
- method_info_offset_ = offset;
- }
-
- const uint32_t* GetMethodInfoOffsetAddr() const {
- return &method_info_offset_;
- }
-
const uint8_t* GetVmapTable() const {
CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler";
return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_;
@@ -186,11 +157,6 @@
// The offset in bytes from the start of the vmap table to the end of the header.
uint32_t vmap_table_offset_ = 0u;
- // The offset in bytes from the start of the method info to the end of the header.
- // The method info offset is not in the CodeInfo since CodeInfo has good dedupe properties that
- // would be lost from doing so. The method info memory region contains method indices since they
- // are hard to dedupe.
- uint32_t method_info_offset_ = 0u;
// The code size in bytes. The highest bit is used to signify if the compiled
// code with the method header has should_deoptimize flag.
uint32_t code_size_ = 0u;
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 85b1ea0..ce99fb9 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -81,9 +81,9 @@
} else if (cur_quick_frame_ != nullptr) {
if (IsInInlinedFrame()) {
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
- MethodInfo method_info = method_header->GetOptimizedMethodInfo();
+ CodeInfo code_info(method_header);
DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
- return GetResolvedMethod(*GetCurrentQuickFrame(), method_info, current_inline_frames_);
+ return GetResolvedMethod(*GetCurrentQuickFrame(), code_info, current_inline_frames_);
} else {
return *cur_quick_frame_;
}
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index e8746bc..cd82284 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -58,6 +58,7 @@
BitMemoryReader reader(data, /* bit_offset */ 0);
DecodeTable(stack_maps_, reader, data);
DecodeTable(inline_infos_, reader, data);
+ DecodeTable(method_infos_, reader, data);
if (flags & DecodeFlags::InlineInfoOnly) {
return;
}
@@ -99,6 +100,7 @@
BitMemoryWriter<std::vector<uint8_t>> writer(out, /* bit_offset */ out->size() * kBitsPerByte);
DedupeTable<StackMap>(writer, reader, dedupe_map);
DedupeTable<InlineInfo>(writer, reader, dedupe_map);
+ DedupeTable<MethodInfo>(writer, reader, dedupe_map);
DedupeTable<RegisterMask>(writer, reader, dedupe_map);
DedupeTable<MaskInfo>(writer, reader, dedupe_map);
DedupeTable<MaskInfo>(writer, reader, dedupe_map);
@@ -211,9 +213,10 @@
Stats* stats = parent->Child("CodeInfo");
stats->AddBytes(Size());
AddTableSizeStats<StackMap>("StackMaps", stack_maps_, stats);
+ AddTableSizeStats<InlineInfo>("InlineInfos", inline_infos_, stats);
+ AddTableSizeStats<MethodInfo>("MethodInfo", method_infos_, stats);
AddTableSizeStats<RegisterMask>("RegisterMasks", register_masks_, stats);
AddTableSizeStats<MaskInfo>("StackMasks", stack_masks_, stats);
- AddTableSizeStats<InlineInfo>("InlineInfos", inline_infos_, stats);
AddTableSizeStats<MaskInfo>("DexRegisterMasks", dex_register_masks_, stats);
AddTableSizeStats<DexRegisterMapInfo>("DexRegisterMaps", dex_register_maps_, stats);
AddTableSizeStats<DexRegisterInfo>("DexRegisterCatalog", dex_register_catalog_, stats);
@@ -271,14 +274,14 @@
void CodeInfo::Dump(VariableIndentationOutputStream* vios,
uint32_t code_offset,
bool verbose,
- InstructionSet instruction_set,
- const MethodInfo& method_info) const {
+ InstructionSet instruction_set) const {
vios->Stream() << "CodeInfo\n";
ScopedIndentation indent1(vios);
DumpTable<StackMap>(vios, "StackMaps", stack_maps_, verbose);
+ DumpTable<InlineInfo>(vios, "InlineInfos", inline_infos_, verbose);
+ DumpTable<MethodInfo>(vios, "MethodInfo", method_infos_, verbose);
DumpTable<RegisterMask>(vios, "RegisterMasks", register_masks_, verbose);
DumpTable<MaskInfo>(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */);
- DumpTable<InlineInfo>(vios, "InlineInfos", inline_infos_, verbose);
DumpTable<MaskInfo>(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */);
DumpTable<DexRegisterMapInfo>(vios, "DexRegisterMaps", dex_register_maps_, verbose);
DumpTable<DexRegisterInfo>(vios, "DexRegisterCatalog", dex_register_catalog_, verbose);
@@ -286,14 +289,13 @@
// Display stack maps along with (live) Dex register maps.
if (verbose) {
for (StackMap stack_map : stack_maps_) {
- stack_map.Dump(vios, *this, method_info, code_offset, instruction_set);
+ stack_map.Dump(vios, *this, code_offset, instruction_set);
}
}
}
void StackMap::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
- const MethodInfo& method_info,
uint32_t code_offset,
InstructionSet instruction_set) const {
const uint32_t pc_offset = GetNativePcOffset(instruction_set);
@@ -312,14 +314,13 @@
vios->Stream() << ")\n";
code_info.GetDexRegisterMapOf(*this).Dump(vios);
for (InlineInfo inline_info : code_info.GetInlineInfosOf(*this)) {
- inline_info.Dump(vios, code_info, *this, method_info);
+ inline_info.Dump(vios, code_info, *this);
}
}
void InlineInfo::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
- const StackMap& stack_map,
- const MethodInfo& method_info) const {
+ const StackMap& stack_map) const {
uint32_t depth = Row() - stack_map.GetInlineInfoIndex();
vios->Stream()
<< "InlineInfo[" << Row() << "]"
@@ -332,7 +333,7 @@
} else {
vios->Stream()
<< std::dec
- << ", method_index=" << GetMethodIndex(method_info);
+ << ", method_index=" << code_info.GetMethodIndexOf(*this);
}
vios->Stream() << ")\n";
code_info.GetInlineDexRegisterMapOf(stack_map, *this).Dump(vios);
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 909aaa5..8bfae7c 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -28,7 +28,6 @@
#include "base/memory_region.h"
#include "dex/dex_file_types.h"
#include "dex_register_location.h"
-#include "method_info.h"
#include "quick/quick_method_frame_info.h"
namespace art {
@@ -164,7 +163,6 @@
void Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
- const MethodInfo& method_info,
uint32_t code_offset,
InstructionSet instruction_set) const;
};
@@ -188,10 +186,6 @@
static constexpr uint32_t kLast = -1;
static constexpr uint32_t kMore = 0;
- uint32_t GetMethodIndex(const MethodInfo& method_info) const {
- return method_info.GetMethodIndex(GetMethodInfoIndex());
- }
-
bool EncodesArtMethod() const {
return HasArtMethodLo();
}
@@ -204,8 +198,7 @@
void Dump(VariableIndentationOutputStream* vios,
const CodeInfo& info,
- const StackMap& stack_map,
- const MethodInfo& method_info) const;
+ const StackMap& stack_map) const;
};
class MaskInfo : public BitTableAccessor<1> {
@@ -262,6 +255,14 @@
}
};
+// Method indices are not very dedup friendly.
+// Separating them greatly improves dedup efficiency of the other tables.
+class MethodInfo : public BitTableAccessor<1> {
+ public:
+ BIT_TABLE_HEADER()
+ BIT_TABLE_COLUMN(0, MethodIndex)
+};
+
/**
* Wrapper around all compiler information collected for a method.
* See the Decode method at the end for the precise binary format.
@@ -329,6 +330,10 @@
return stack_maps_.NumRows();
}
+ uint32_t GetMethodIndexOf(InlineInfo inline_info) const {
+ return method_infos_.GetRow(inline_info.GetMethodInfoIndex()).GetMethodIndex();
+ }
+
ALWAYS_INLINE DexRegisterMap GetDexRegisterMapOf(StackMap stack_map) const {
if (stack_map.HasDexRegisterMap()) {
DexRegisterMap map(number_of_dex_registers_, DexRegisterLocation::Invalid());
@@ -405,8 +410,7 @@
void Dump(VariableIndentationOutputStream* vios,
uint32_t code_offset,
bool verbose,
- InstructionSet instruction_set,
- const MethodInfo& method_info) const;
+ InstructionSet instruction_set) const;
// Accumulate code info size statistics into the given Stats tree.
void AddSizeStats(/*out*/ Stats* parent) const;
@@ -446,6 +450,7 @@
uint32_t number_of_dex_registers_;
BitTable<StackMap> stack_maps_;
BitTable<InlineInfo> inline_infos_;
+ BitTable<MethodInfo> method_infos_;
BitTable<RegisterMask> register_masks_;
BitTable<MaskInfo> stack_masks_;
BitTable<MaskInfo> dex_register_masks_;