diff options
author | 2024-11-19 15:58:39 +0000 | |
---|---|---|
committer | 2024-11-21 09:59:40 +0000 | |
commit | 303e0cbc6816e301f22eda7d4233d97482eb1cfa (patch) | |
tree | 42a0442457ee19b58de8bdd6abb9bf3421704726 | |
parent | 70cb3b60e2b62ce2ca604032570618987f590e2f (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.h | 45 | ||||
-rw-r--r-- | libartbase/base/scoped_arena_containers.h | 50 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 10 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 11 | ||||
-rw-r--r-- | runtime/verifier/register_line-inl.h | 12 | ||||
-rw-r--r-- | runtime/verifier/register_line.h | 12 | ||||
-rw-r--r-- | runtime/verifier/register_line_test.cc | 4 |
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, ®_types)); RegisterLineArenaUniquePtr line2(RegisterLine::Create(kNumRegs, allocator, ®_types)); for (const TestCase& test_case : test_cases) { |