summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-11-19 15:58:39 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-11-21 09:59:40 +0000
commit303e0cbc6816e301f22eda7d4233d97482eb1cfa (patch)
tree42a0442457ee19b58de8bdd6abb9bf3421704726
parent70cb3b60e2b62ce2ca604032570618987f590e2f (diff)
verifier: Use `ArenaAllocator` in verifier...
... instead of `ScopedArenaAllocator`. We do not use nested `ScopedArenaAllocator`s, so we can use the `ArenaAllocator` which guarantees zero-initialization of allcated memory and avoid an unnecessary `std::fill_n()`. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 181943478 Change-Id: I04539c95ebf651a3e3b260a0c069ad6ee1eb1e5a
-rw-r--r--libartbase/base/arena_containers.h45
-rw-r--r--libartbase/base/scoped_arena_containers.h50
-rw-r--r--runtime/verifier/method_verifier.cc10
-rw-r--r--runtime/verifier/method_verifier.h11
-rw-r--r--runtime/verifier/register_line-inl.h12
-rw-r--r--runtime/verifier/register_line.h12
-rw-r--r--runtime/verifier/register_line_test.cc4
7 files changed, 69 insertions, 75 deletions
diff --git a/libartbase/base/arena_containers.h b/libartbase/base/arena_containers.h
index 80a3791383..e93c8d7bd0 100644
--- a/libartbase/base/arena_containers.h
+++ b/libartbase/base/arena_containers.h
@@ -243,6 +243,51 @@ inline ArenaAllocatorAdapter<void> ArenaAllocator::Adapter(ArenaAllocKind kind)
return ArenaAllocatorAdapter<void>(this, kind);
}
+// Special deleter that only calls the destructor. Also checks for double free errors.
+template <typename T>
+class ArenaDelete {
+ static constexpr uint8_t kMagicFill = 0xCE;
+
+ protected:
+ // Used for variable sized objects such as RegisterLine.
+ ALWAYS_INLINE void ProtectMemory(T* ptr, size_t size) const {
+ if (kRunningOnMemoryTool) {
+ memset(ptr, kMagicFill, size);
+ MEMORY_TOOL_MAKE_NOACCESS(ptr, size);
+ } else if (kIsDebugBuild) {
+ // Write a magic value to try and catch use after free errors.
+ memset(ptr, kMagicFill, size);
+ }
+ }
+
+ public:
+ void operator()(T* ptr) const {
+ if (ptr != nullptr) {
+ ptr->~T();
+ ProtectMemory(ptr, sizeof(T));
+ }
+ }
+};
+
+// In general we lack support for arrays. We would need to call the destructor on each element,
+// which requires access to the array size. Support for that is future work.
+//
+// However, we can support trivially destructible component types, as then a destructor doesn't
+// need to be called.
+template <typename T>
+class ArenaDelete<T[]> {
+ public:
+ void operator()([[maybe_unused]] T* ptr) const {
+ static_assert(std::is_trivially_destructible_v<T>,
+ "ArenaUniquePtr does not support non-trivially-destructible arrays.");
+ // TODO: Implement debug checks, and MEMORY_TOOL support.
+ }
+};
+
+// Arena unique ptr that only calls the destructor of the element.
+template <typename T>
+using ArenaUniquePtr = std::unique_ptr<T, ArenaDelete<T>>;
+
} // namespace art
#endif // ART_LIBARTBASE_BASE_ARENA_CONTAINERS_H_
diff --git a/libartbase/base/scoped_arena_containers.h b/libartbase/base/scoped_arena_containers.h
index d0ff7f535d..ee9a7461f8 100644
--- a/libartbase/base/scoped_arena_containers.h
+++ b/libartbase/base/scoped_arena_containers.h
@@ -234,56 +234,6 @@ inline ScopedArenaAllocatorAdapter<void> ScopedArenaAllocator::Adapter(ArenaAllo
return ScopedArenaAllocatorAdapter<void>(this, kind);
}
-// Special deleter that only calls the destructor. Also checks for double free errors.
-template <typename T>
-class ArenaDelete {
- static constexpr uint8_t kMagicFill = 0xCE;
-
- protected:
- // Used for variable sized objects such as RegisterLine.
- ALWAYS_INLINE void ProtectMemory(T* ptr, size_t size) const {
- if (kRunningOnMemoryTool) {
- // Writing to the memory will fail ift we already destroyed the pointer with
- // DestroyOnlyDelete since we make it no access.
- memset(ptr, kMagicFill, size);
- MEMORY_TOOL_MAKE_NOACCESS(ptr, size);
- } else if (kIsDebugBuild) {
- CHECK(ArenaStack::ArenaTagForAllocation(reinterpret_cast<void*>(ptr)) == ArenaFreeTag::kUsed)
- << "Freeing invalid object " << ptr;
- ArenaStack::ArenaTagForAllocation(reinterpret_cast<void*>(ptr)) = ArenaFreeTag::kFree;
- // Write a magic value to try and catch use after free error.
- memset(ptr, kMagicFill, size);
- }
- }
-
- public:
- void operator()(T* ptr) const {
- if (ptr != nullptr) {
- ptr->~T();
- ProtectMemory(ptr, sizeof(T));
- }
- }
-};
-
-// In general we lack support for arrays. We would need to call the destructor on each element,
-// which requires access to the array size. Support for that is future work.
-//
-// However, we can support trivially destructible component types, as then a destructor doesn't
-// need to be called.
-template <typename T>
-class ArenaDelete<T[]> {
- public:
- void operator()([[maybe_unused]] T* ptr) const {
- static_assert(std::is_trivially_destructible_v<T>,
- "ArenaUniquePtr does not support non-trivially-destructible arrays.");
- // TODO: Implement debug checks, and MEMORY_TOOL support.
- }
-};
-
-// Arena unique ptr that only calls the destructor of the element.
-template <typename T>
-using ArenaUniquePtr = std::unique_ptr<T, ArenaDelete<T>>;
-
} // namespace art
#endif // ART_LIBARTBASE_BASE_SCOPED_ARENA_CONTAINERS_H_
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 7ecf985cd2..d7bd5b8239 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -73,13 +73,13 @@ using android::base::StringPrintf;
static constexpr bool kTimeVerifyMethod = !kIsDebugBuild;
-PcToRegisterLineTable::PcToRegisterLineTable(ScopedArenaAllocator& allocator)
+PcToRegisterLineTable::PcToRegisterLineTable(ArenaAllocator& allocator)
: register_lines_(allocator.Adapter(kArenaAllocVerifier)) {}
void PcToRegisterLineTable::Init(InstructionFlags* flags,
uint32_t insns_size,
uint16_t registers_size,
- ScopedArenaAllocator& allocator,
+ ArenaAllocator& allocator,
RegTypeCache* reg_types,
uint32_t interesting_dex_pc) {
DCHECK_GT(insns_size, 0U);
@@ -4833,8 +4833,7 @@ MethodVerifier::MethodVerifier(Thread* self,
uint32_t dex_method_idx,
bool aot_mode)
: self_(self),
- arena_stack_(arena_pool),
- allocator_(&arena_stack_),
+ allocator_(arena_pool),
reg_types_(*reg_types),
reg_table_(allocator_),
work_insn_idx_(dex::kDexNoIndex),
@@ -5025,8 +5024,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
<< " took " << PrettyDuration(duration_ns)
<< (impl::IsLargeMethod(verifier.CodeItem()) ? " (large method)" : "")
<< " (" << StringPrintf("%.2f", bytecodes_per_second) << " bytecodes/s)"
- << " (" << verifier.allocator_.ApproximatePeakBytes()
- << "B approximate peak alloc)";
+ << " (" << verifier.allocator_.BytesAllocated() << "B arena alloc)";
}
}
result.types = verifier.encountered_failure_types_;
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 5b1f2e0750..74cc6e358e 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -24,8 +24,8 @@
#include <android-base/logging.h>
#include "base/arena_allocator.h"
+#include "base/arena_containers.h"
#include "base/macros.h"
-#include "base/scoped_arena_containers.h"
#include "base/value_object.h"
#include "dex/code_item_accessors.h"
#include "dex/dex_file_types.h"
@@ -66,7 +66,7 @@ class VerifierDeps;
// execution of that instruction.
class PcToRegisterLineTable {
public:
- explicit PcToRegisterLineTable(ScopedArenaAllocator& allocator);
+ explicit PcToRegisterLineTable(ArenaAllocator& allocator);
~PcToRegisterLineTable();
// Initialize the RegisterTable. Every instruction address can have a different set of information
@@ -75,7 +75,7 @@ class PcToRegisterLineTable {
void Init(InstructionFlags* flags,
uint32_t insns_size,
uint16_t registers_size,
- ScopedArenaAllocator& allocator,
+ ArenaAllocator& allocator,
RegTypeCache* reg_types,
uint32_t interesting_dex_pc);
@@ -88,7 +88,7 @@ class PcToRegisterLineTable {
}
private:
- ScopedArenaVector<RegisterLineArenaUniquePtr> register_lines_;
+ ArenaVector<RegisterLineArenaUniquePtr> register_lines_;
DISALLOW_COPY_AND_ASSIGN(PcToRegisterLineTable);
};
@@ -284,8 +284,7 @@ class MethodVerifier {
Thread* const self_;
// Arena allocator.
- ArenaStack arena_stack_;
- ScopedArenaAllocator allocator_;
+ ArenaAllocator allocator_;
RegTypeCache& reg_types_; // TODO: Change to a pointer in a separate CL.
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index d15dc7b7eb..c49649021e 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -193,7 +193,7 @@ inline void RegisterLine::DCheckUniqueNewInstanceDexPc(MethodVerifier* verifier,
inline void RegisterLine::EnsureAllocationDexPcsAvailable() {
DCHECK_NE(num_regs_, 0u);
if (allocation_dex_pcs_ == nullptr) {
- ScopedArenaAllocatorAdapter<uint32_t> allocator(monitors_.get_allocator());
+ ArenaAllocatorAdapter<uint32_t> allocator(monitors_.get_allocator());
allocation_dex_pcs_ = allocator.allocate(num_regs_);
std::fill_n(allocation_dex_pcs_, num_regs_, kNoDexPc);
}
@@ -214,14 +214,14 @@ inline size_t RegisterLine::ComputeSize(size_t num_regs) {
}
inline RegisterLine* RegisterLine::Create(size_t num_regs,
- ScopedArenaAllocator& allocator,
+ ArenaAllocator& allocator,
RegTypeCache* reg_types) {
void* memory = allocator.Alloc(ComputeSize(num_regs));
return new (memory) RegisterLine(num_regs, allocator, reg_types);
}
inline RegisterLine::RegisterLine(size_t num_regs,
- ScopedArenaAllocator& allocator,
+ ArenaAllocator& allocator,
RegTypeCache* reg_types)
: num_regs_(num_regs),
allocation_dex_pcs_(nullptr),
@@ -229,7 +229,11 @@ inline RegisterLine::RegisterLine(size_t num_regs,
reg_to_lock_depths_(std::less<uint32_t>(),
allocator.Adapter(kArenaAllocVerifier)),
this_initialized_(false) {
- std::uninitialized_fill_n(line_, num_regs_, RegTypeCache::kUndefinedCacheId);
+ // `ArenaAllocator` guarantees zero-initialization.
+ static_assert(RegTypeCache::kUndefinedCacheId == 0u);
+ DCHECK(std::all_of(line_,
+ line_ + num_regs_,
+ [](auto id) { return id == RegTypeCache::kUndefinedCacheId;}));
SetResultTypeToUnknown(reg_types);
}
diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h
index f6424e9878..58f4a6a6fb 100644
--- a/runtime/verifier/register_line.h
+++ b/runtime/verifier/register_line.h
@@ -23,10 +23,10 @@
#include <android-base/logging.h>
+#include "base/arena_containers.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/safe_map.h"
-#include "base/scoped_arena_containers.h"
namespace art HIDDEN {
@@ -67,7 +67,7 @@ class RegisterLine {
public:
using RegisterStackMask = uint32_t;
// A map from register to a bit vector of indices into the monitors_ stack.
- using RegToLockDepthsMap = ScopedArenaSafeMap<uint32_t, RegisterStackMask>;
+ using RegToLockDepthsMap = ArenaSafeMap<uint32_t, RegisterStackMask>;
// Maximum number of nested monitors to track before giving up and
// taking the slow path.
@@ -75,9 +75,7 @@ class RegisterLine {
std::numeric_limits<RegisterStackMask>::digits;
// Create a register line of num_regs registers.
- static RegisterLine* Create(size_t num_regs,
- ScopedArenaAllocator& allocator,
- RegTypeCache* reg_types);
+ static RegisterLine* Create(size_t num_regs, ArenaAllocator& allocator, RegTypeCache* reg_types);
// Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst".
void CopyRegister1(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc, TypeCategory cat)
@@ -411,7 +409,7 @@ class RegisterLine {
reg_to_lock_depths_.erase(reg);
}
- RegisterLine(size_t num_regs, ScopedArenaAllocator& allocator, RegTypeCache* reg_types);
+ RegisterLine(size_t num_regs, ArenaAllocator& allocator, RegTypeCache* reg_types);
static constexpr uint32_t kNoDexPc = static_cast<uint32_t>(-1);
@@ -425,7 +423,7 @@ class RegisterLine {
uint32_t* allocation_dex_pcs_;
// A stack of monitor enter locations.
- ScopedArenaVector<uint32_t> monitors_;
+ ArenaVector<uint32_t> monitors_;
// A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor
// stack we verify that monitor-enter/exit are correctly nested. That is, if there was a
diff --git a/runtime/verifier/register_line_test.cc b/runtime/verifier/register_line_test.cc
index e1ea2ffcbb..4d0f0c20cd 100644
--- a/runtime/verifier/register_line_test.cc
+++ b/runtime/verifier/register_line_test.cc
@@ -47,7 +47,7 @@ class RegisterLineTest : public CommonRuntimeTest {
/*api_level=*/ 0u);
}
- ScopedArenaAllocator& GetScopedArenaAllocator(MethodVerifier* verifier) {
+ ArenaAllocator& GetArenaAllocator(MethodVerifier* verifier) {
return verifier->allocator_;
}
};
@@ -119,7 +119,7 @@ TEST_F(RegisterLineTest, NewInstanceDexPcsMerging) {
constexpr size_t kNumRegs = 1u;
constexpr uint32_t kVReg = 0u;
- ScopedArenaAllocator& allocator = GetScopedArenaAllocator(verifier.get());
+ ArenaAllocator& allocator = GetArenaAllocator(verifier.get());
RegisterLineArenaUniquePtr line1(RegisterLine::Create(kNumRegs, allocator, &reg_types));
RegisterLineArenaUniquePtr line2(RegisterLine::Create(kNumRegs, allocator, &reg_types));
for (const TestCase& test_case : test_cases) {