diff options
27 files changed, 511 insertions, 268 deletions
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc index f582341b18..c139fcf1d8 100644 --- a/compiler/exception_test.cc +++ b/compiler/exception_test.cc @@ -20,6 +20,7 @@ #include "base/callee_save_type.h" #include "base/enums.h" #include "base/leb128.h" +#include "base/malloc_arena_pool.h" #include "class_linker.h" #include "common_runtime_test.h" #include "dex/code_item_accessors-inl.h" @@ -67,7 +68,7 @@ class ExceptionTest : public CommonRuntimeTest { fake_code_.push_back(0x70 | i); } - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stack_maps(&allocator, kRuntimeISA); diff --git a/compiler/jni/jni_cfi_test.cc b/compiler/jni/jni_cfi_test.cc index 236b5c0c2e..11b0e2ba9d 100644 --- a/compiler/jni/jni_cfi_test.cc +++ b/compiler/jni/jni_cfi_test.cc @@ -20,6 +20,7 @@ #include "arch/instruction_set.h" #include "base/arena_allocator.h" #include "base/enums.h" +#include "base/malloc_arena_pool.h" #include "cfi_test.h" #include "gtest/gtest.h" #include "jni/quick/calling_convention.h" @@ -61,7 +62,7 @@ class JNICFITest : public CFITest { const bool is_synchronized = false; const char* shorty = "IIFII"; - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); std::unique_ptr<JniCallingConvention> jni_conv( diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc index d001cfe4fc..9ccdff3a17 100644 --- a/compiler/jni/quick/jni_compiler.cc +++ b/compiler/jni/quick/jni_compiler.cc @@ -27,6 +27,7 @@ #include "base/enums.h" #include "base/logging.h" // For VLOG. #include "base/macros.h" +#include "base/malloc_arena_pool.h" #include "base/utils.h" #include "calling_convention.h" #include "class_linker.h" @@ -174,7 +175,7 @@ static JniCompiledMethod ArtJniCompileMethodInternal(CompilerDriver* driver, } } - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); // Calling conventions used to iterate over parameters to method diff --git a/compiler/linker/arm/relative_patcher_thumb2.cc b/compiler/linker/arm/relative_patcher_thumb2.cc index 78755176e4..0056c50634 100644 --- a/compiler/linker/arm/relative_patcher_thumb2.cc +++ b/compiler/linker/arm/relative_patcher_thumb2.cc @@ -21,6 +21,7 @@ #include "arch/arm/asm_support_arm.h" #include "art_method.h" #include "base/bit_utils.h" +#include "base/malloc_arena_pool.h" #include "compiled_method.h" #include "entrypoints/quick/quick_entrypoints_enum.h" #include "linker/linker_patch.h" @@ -355,7 +356,7 @@ void Thumb2RelativePatcher::CompileBakerReadBarrierThunk(arm::ArmVIXLAssembler& } std::vector<uint8_t> Thumb2RelativePatcher::CompileThunk(const ThunkKey& key) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); arm::ArmVIXLAssembler assembler(&allocator); diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc index b268204b4a..4bfe99baeb 100644 --- a/compiler/linker/arm64/relative_patcher_arm64.cc +++ b/compiler/linker/arm64/relative_patcher_arm64.cc @@ -20,6 +20,7 @@ #include "arch/arm64/instruction_set_features_arm64.h" #include "art_method.h" #include "base/bit_utils.h" +#include "base/malloc_arena_pool.h" #include "compiled_method-inl.h" #include "driver/compiler_driver.h" #include "entrypoints/quick/quick_entrypoints_enum.h" @@ -511,7 +512,7 @@ void Arm64RelativePatcher::CompileBakerReadBarrierThunk(arm64::Arm64Assembler& a } std::vector<uint8_t> Arm64RelativePatcher::CompileThunk(const ThunkKey& key) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); arm64::Arm64Assembler assembler(&allocator); diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h index 6dcbadba6e..a9bc5664c0 100644 --- a/compiler/optimizing/optimizing_unit_test.h +++ b/compiler/optimizing/optimizing_unit_test.h @@ -20,6 +20,7 @@ #include <memory> #include <vector> +#include "base/malloc_arena_pool.h" #include "base/scoped_arena_allocator.h" #include "builder.h" #include "common_compiler_test.h" @@ -97,7 +98,7 @@ class ArenaPoolAndAllocator { ScopedArenaAllocator* GetScopedAllocator() { return &scoped_allocator_; } private: - ArenaPool pool_; + MallocArenaPool pool_; ArenaAllocator allocator_; ArenaStack arena_stack_; ScopedArenaAllocator scoped_allocator_; diff --git a/compiler/optimizing/parallel_move_test.cc b/compiler/optimizing/parallel_move_test.cc index cb87cabe1c..be35201166 100644 --- a/compiler/optimizing/parallel_move_test.cc +++ b/compiler/optimizing/parallel_move_test.cc @@ -15,6 +15,7 @@ */ #include "base/arena_allocator.h" +#include "base/malloc_arena_pool.h" #include "nodes.h" #include "parallel_move_resolver.h" @@ -180,7 +181,7 @@ TYPED_TEST_CASE(ParallelMoveTest, ParallelMoveResolverTestTypes); TYPED_TEST(ParallelMoveTest, Dependency) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); { @@ -207,7 +208,7 @@ TYPED_TEST(ParallelMoveTest, Dependency) { } TYPED_TEST(ParallelMoveTest, Cycle) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); { @@ -257,7 +258,7 @@ TYPED_TEST(ParallelMoveTest, Cycle) { } TYPED_TEST(ParallelMoveTest, ConstantLast) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); TypeParam resolver(&allocator); HParallelMove* moves = new (&allocator) HParallelMove(&allocator); @@ -276,7 +277,7 @@ TYPED_TEST(ParallelMoveTest, ConstantLast) { } TYPED_TEST(ParallelMoveTest, Pairs) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); { @@ -453,7 +454,7 @@ TYPED_TEST(ParallelMoveTest, Pairs) { } TYPED_TEST(ParallelMoveTest, MultiCycles) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); { @@ -551,7 +552,7 @@ TYPED_TEST(ParallelMoveTest, MultiCycles) { // Test that we do 64bits moves before 32bits moves. TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); { @@ -610,7 +611,7 @@ TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves) { } TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves2) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); { diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc index 7e517f3485..e36c592662 100644 --- a/compiler/optimizing/stack_map_test.cc +++ b/compiler/optimizing/stack_map_test.cc @@ -18,6 +18,7 @@ #include "art_method.h" #include "base/arena_bit_vector.h" +#include "base/malloc_arena_pool.h" #include "stack_map_stream.h" #include "gtest/gtest.h" @@ -46,7 +47,7 @@ static bool CheckStackMask( using Kind = DexRegisterLocation::Kind; TEST(StackMapTest, Test1) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -128,7 +129,7 @@ TEST(StackMapTest, Test1) { } TEST(StackMapTest, Test2) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -413,7 +414,7 @@ TEST(StackMapTest, Test2) { } TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -508,7 +509,7 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) { } TEST(StackMapTest, TestNonLiveDexRegisters) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -588,7 +589,7 @@ TEST(StackMapTest, TestNonLiveDexRegisters) { // StackMap::kNoDexRegisterMapSmallEncoding, and ensure we do // not treat it as kNoDexRegisterMap. TEST(StackMapTest, DexRegisterMapOffsetOverflow) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -652,7 +653,7 @@ TEST(StackMapTest, DexRegisterMapOffsetOverflow) { } TEST(StackMapTest, TestShareDexRegisterMap) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -711,7 +712,7 @@ TEST(StackMapTest, TestShareDexRegisterMap) { } TEST(StackMapTest, TestNoDexRegisterMap) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -761,7 +762,7 @@ TEST(StackMapTest, TestNoDexRegisterMap) { } TEST(StackMapTest, InlineTest) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -949,7 +950,7 @@ TEST(StackMapTest, CodeOffsetTest) { } TEST(StackMapTest, TestDeduplicateStackMask) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); @@ -978,7 +979,7 @@ TEST(StackMapTest, TestDeduplicateStackMask) { } TEST(StackMapTest, TestInvokeInfo) { - ArenaPool pool; + MallocArenaPool pool; ArenaStack arena_stack(&pool); ScopedArenaAllocator allocator(&arena_stack); StackMapStream stream(&allocator, kRuntimeISA); diff --git a/compiler/trampolines/trampoline_compiler.cc b/compiler/trampolines/trampoline_compiler.cc index 921d401849..57360e74a3 100644 --- a/compiler/trampolines/trampoline_compiler.cc +++ b/compiler/trampolines/trampoline_compiler.cc @@ -17,6 +17,7 @@ #include "trampoline_compiler.h" #include "base/arena_allocator.h" +#include "base/malloc_arena_pool.h" #include "jni_env_ext.h" #ifdef ART_ENABLE_CODEGEN_arm @@ -243,7 +244,7 @@ static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(ArenaAllocat std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline64(InstructionSet isa, EntryPointCallingConvention abi, ThreadOffset64 offset) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); switch (isa) { #ifdef ART_ENABLE_CODEGEN_arm64 @@ -269,7 +270,7 @@ std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline64(InstructionSet is std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline32(InstructionSet isa, EntryPointCallingConvention abi, ThreadOffset32 offset) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); switch (isa) { #ifdef ART_ENABLE_CODEGEN_arm diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h index 0cb8bbb2d5..7c800b355f 100644 --- a/compiler/utils/assembler_test.h +++ b/compiler/utils/assembler_test.h @@ -26,6 +26,7 @@ #include <fstream> #include <iterator> +#include "base/malloc_arena_pool.h" #include "assembler_test_base.h" #include "common_runtime_test.h" // For ScratchFile @@ -1606,7 +1607,7 @@ class AssemblerTest : public testing::Test { static constexpr size_t kWarnManyCombinationsThreshold = 500; - ArenaPool pool_; + MallocArenaPool pool_; std::unique_ptr<ArenaAllocator> allocator_; std::unique_ptr<Ass> assembler_; std::unique_ptr<AssemblerTestInfrastructure> test_helper_; diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc index 655d17d4fb..053e202523 100644 --- a/compiler/utils/assembler_thumb_test.cc +++ b/compiler/utils/assembler_thumb_test.cc @@ -27,6 +27,7 @@ #include "utils/arm/jni_macro_assembler_arm_vixl.h" #include "base/hex_dump.h" +#include "base/malloc_arena_pool.h" #include "common_runtime_test.h" namespace art { @@ -169,7 +170,7 @@ class ArmVIXLAssemblerTest : public ::testing::Test { public: ArmVIXLAssemblerTest() : pool(), allocator(&pool), assembler(&allocator) { } - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator; ArmVIXLJNIMacroAssembler assembler; }; diff --git a/compiler/utils/jni_macro_assembler_test.h b/compiler/utils/jni_macro_assembler_test.h index 1aefc84c78..b70c18b3e2 100644 --- a/compiler/utils/jni_macro_assembler_test.h +++ b/compiler/utils/jni_macro_assembler_test.h @@ -20,6 +20,7 @@ #include "jni_macro_assembler.h" #include "assembler_test_base.h" +#include "base/malloc_arena_pool.h" #include "common_runtime_test.h" // For ScratchFile #include <sys/stat.h> @@ -139,7 +140,7 @@ class JNIMacroAssemblerTest : public testing::Test { test_helper_->Driver(*data, assembly_text, test_name); } - ArenaPool pool_; + MallocArenaPool pool_; std::unique_ptr<ArenaAllocator> allocator_; std::unique_ptr<Ass> assembler_; std::unique_ptr<AssemblerTestInfrastructure> test_helper_; diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc index 8f72db748b..cd007b32d4 100644 --- a/compiler/utils/x86/assembler_x86_test.cc +++ b/compiler/utils/x86/assembler_x86_test.cc @@ -17,13 +17,14 @@ #include "assembler_x86.h" #include "base/arena_allocator.h" +#include "base/malloc_arena_pool.h" #include "base/stl_util.h" #include "utils/assembler_test.h" namespace art { TEST(AssemblerX86, CreateBuffer) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); AssemblerBuffer buffer(&allocator); AssemblerBuffer::EnsureCapacity ensured(&buffer); diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc index 104e215cf5..0589df55d2 100644 --- a/compiler/utils/x86_64/assembler_x86_64_test.cc +++ b/compiler/utils/x86_64/assembler_x86_64_test.cc @@ -21,6 +21,7 @@ #include <random> #include "base/bit_utils.h" +#include "base/malloc_arena_pool.h" #include "base/stl_util.h" #include "jni_macro_assembler_x86_64.h" #include "utils/assembler_test.h" @@ -29,7 +30,7 @@ namespace art { TEST(AssemblerX86_64, CreateBuffer) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); AssemblerBuffer buffer(&allocator); AssemblerBuffer::EnsureCapacity ensured(&buffer); diff --git a/runtime/Android.bp b/runtime/Android.bp index c0f1c366b8..b380dab187 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -35,6 +35,8 @@ cc_defaults { "base/arena_allocator.cc", "base/arena_bit_vector.cc", "base/file_utils.cc", + "base/malloc_arena_pool.cc", + "base/mem_map_arena_pool.cc", "base/mutex.cc", "base/quasi_atomic.cc", "base/scoped_arena_allocator.cc", diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc index fe0f876d66..348a812e44 100644 --- a/runtime/base/arena_allocator.cc +++ b/runtime/base/arena_allocator.cc @@ -25,11 +25,6 @@ #include <android-base/logging.h> -#include "base/systrace.h" -#include "mem_map.h" -#include "mutex.h" -#include "thread-current-inl.h" - namespace art { constexpr size_t kMemoryToolRedZoneBytes = 8; @@ -190,194 +185,6 @@ void ArenaAllocatorMemoryTool::DoMakeInaccessible(void* ptr, size_t size) { Arena::Arena() : bytes_allocated_(0), memory_(nullptr), size_(0), next_(nullptr) { } -class MallocArena FINAL : public Arena { - public: - explicit MallocArena(size_t size = arena_allocator::kArenaDefaultSize); - virtual ~MallocArena(); - private: - static constexpr size_t RequiredOverallocation() { - return (alignof(std::max_align_t) < ArenaAllocator::kArenaAlignment) - ? ArenaAllocator::kArenaAlignment - alignof(std::max_align_t) - : 0u; - } - - uint8_t* unaligned_memory_; -}; - -MallocArena::MallocArena(size_t size) { - // We need to guarantee kArenaAlignment aligned allocation for the new arena. - // TODO: Use std::aligned_alloc() when it becomes available with C++17. - constexpr size_t overallocation = RequiredOverallocation(); - unaligned_memory_ = reinterpret_cast<uint8_t*>(calloc(1, size + overallocation)); - CHECK(unaligned_memory_ != nullptr); // Abort on OOM. - DCHECK_ALIGNED(unaligned_memory_, alignof(std::max_align_t)); - if (overallocation == 0u) { - memory_ = unaligned_memory_; - } else { - memory_ = AlignUp(unaligned_memory_, ArenaAllocator::kArenaAlignment); - if (UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) { - size_t head = memory_ - unaligned_memory_; - size_t tail = overallocation - head; - MEMORY_TOOL_MAKE_NOACCESS(unaligned_memory_, head); - MEMORY_TOOL_MAKE_NOACCESS(memory_ + size, tail); - } - } - DCHECK_ALIGNED(memory_, ArenaAllocator::kArenaAlignment); - size_ = size; -} - -MallocArena::~MallocArena() { - constexpr size_t overallocation = RequiredOverallocation(); - if (overallocation != 0u && UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) { - size_t head = memory_ - unaligned_memory_; - size_t tail = overallocation - head; - MEMORY_TOOL_MAKE_UNDEFINED(unaligned_memory_, head); - MEMORY_TOOL_MAKE_UNDEFINED(memory_ + size_, tail); - } - free(reinterpret_cast<void*>(unaligned_memory_)); -} - -class MemMapArena FINAL : public Arena { - public: - MemMapArena(size_t size, bool low_4gb, const char* name); - virtual ~MemMapArena(); - void Release() OVERRIDE; - - private: - std::unique_ptr<MemMap> map_; -}; - -MemMapArena::MemMapArena(size_t size, bool low_4gb, const char* name) { - // Round up to a full page as that's the smallest unit of allocation for mmap() - // and we want to be able to use all memory that we actually allocate. - size = RoundUp(size, kPageSize); - std::string error_msg; - map_.reset(MemMap::MapAnonymous( - name, nullptr, size, PROT_READ | PROT_WRITE, low_4gb, false, &error_msg)); - CHECK(map_.get() != nullptr) << error_msg; - memory_ = map_->Begin(); - static_assert(ArenaAllocator::kArenaAlignment <= kPageSize, - "Arena should not need stronger alignment than kPageSize."); - DCHECK_ALIGNED(memory_, ArenaAllocator::kArenaAlignment); - size_ = map_->Size(); -} - -MemMapArena::~MemMapArena() { - // Destroys MemMap via std::unique_ptr<>. -} - -void MemMapArena::Release() { - if (bytes_allocated_ > 0) { - map_->MadviseDontNeedAndZero(); - bytes_allocated_ = 0; - } -} - -void Arena::Reset() { - if (bytes_allocated_ > 0) { - memset(Begin(), 0, bytes_allocated_); - bytes_allocated_ = 0; - } -} - -ArenaPool::ArenaPool(bool use_malloc, bool low_4gb, const char* name) - : use_malloc_(use_malloc), - lock_("Arena pool lock", kArenaPoolLock), - free_arenas_(nullptr), - low_4gb_(low_4gb), - name_(name) { - if (low_4gb) { - CHECK(!use_malloc) << "low4gb must use map implementation"; - } - if (!use_malloc) { - MemMap::Init(); - } -} - -ArenaPool::~ArenaPool() { - ReclaimMemory(); -} - -void ArenaPool::ReclaimMemory() { - while (free_arenas_ != nullptr) { - Arena* arena = free_arenas_; - free_arenas_ = free_arenas_->next_; - delete arena; - } -} - -void ArenaPool::LockReclaimMemory() { - MutexLock lock(Thread::Current(), lock_); - ReclaimMemory(); -} - -Arena* ArenaPool::AllocArena(size_t size) { - Thread* self = Thread::Current(); - Arena* ret = nullptr; - { - MutexLock lock(self, lock_); - if (free_arenas_ != nullptr && LIKELY(free_arenas_->Size() >= size)) { - ret = free_arenas_; - free_arenas_ = free_arenas_->next_; - } - } - if (ret == nullptr) { - ret = use_malloc_ ? static_cast<Arena*>(new MallocArena(size)) : - new MemMapArena(size, low_4gb_, name_); - } - ret->Reset(); - return ret; -} - -void ArenaPool::TrimMaps() { - if (!use_malloc_) { - ScopedTrace trace(__PRETTY_FUNCTION__); - // Doesn't work for malloc. - MutexLock lock(Thread::Current(), lock_); - for (Arena* arena = free_arenas_; arena != nullptr; arena = arena->next_) { - arena->Release(); - } - } -} - -size_t ArenaPool::GetBytesAllocated() const { - size_t total = 0; - MutexLock lock(Thread::Current(), lock_); - for (Arena* arena = free_arenas_; arena != nullptr; arena = arena->next_) { - total += arena->GetBytesAllocated(); - } - return total; -} - -void ArenaPool::FreeArenaChain(Arena* first) { - if (UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) { - for (Arena* arena = first; arena != nullptr; arena = arena->next_) { - MEMORY_TOOL_MAKE_UNDEFINED(arena->memory_, arena->bytes_allocated_); - } - } - - if (arena_allocator::kArenaAllocatorPreciseTracking) { - // Do not reuse arenas when tracking. - while (first != nullptr) { - Arena* next = first->next_; - delete first; - first = next; - } - return; - } - - if (first != nullptr) { - Arena* last = first; - while (last->next_ != nullptr) { - last = last->next_; - } - Thread* self = Thread::Current(); - MutexLock lock(self, lock_); - last->next_ = free_arenas_; - free_arenas_ = first; - } -} - size_t ArenaAllocator::BytesAllocated() const { return ArenaAllocatorStats::BytesAllocated(); } diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h index 688f01b71f..f59cfdd69d 100644 --- a/runtime/base/arena_allocator.h +++ b/runtime/base/arena_allocator.h @@ -25,7 +25,6 @@ #include "base/dchecked_vector.h" #include "base/macros.h" #include "base/memory_tool.h" -#include "mutex.h" namespace art { @@ -236,7 +235,8 @@ class Arena { uint8_t* memory_; size_t size_; Arena* next_; - friend class ArenaPool; + friend class MallocArenaPool; + friend class MemMapArenaPool; friend class ArenaAllocator; friend class ArenaStack; friend class ScopedArenaAllocator; @@ -250,25 +250,20 @@ class Arena { class ArenaPool { public: - explicit ArenaPool(bool use_malloc = true, - bool low_4gb = false, - const char* name = "LinearAlloc"); - ~ArenaPool(); - Arena* AllocArena(size_t size) REQUIRES(!lock_); - void FreeArenaChain(Arena* first) REQUIRES(!lock_); - size_t GetBytesAllocated() const REQUIRES(!lock_); - void ReclaimMemory() NO_THREAD_SAFETY_ANALYSIS; - void LockReclaimMemory() REQUIRES(!lock_); - // Trim the maps in arenas by madvising, used by JIT to reduce memory usage. This only works - // use_malloc is false. - void TrimMaps() REQUIRES(!lock_); + virtual ~ArenaPool() = default; + + virtual Arena* AllocArena(size_t size) = 0; + virtual void FreeArenaChain(Arena* first) = 0; + virtual size_t GetBytesAllocated() const = 0; + virtual void ReclaimMemory() = 0; + virtual void LockReclaimMemory() = 0; + // Trim the maps in arenas by madvising, used by JIT to reduce memory usage. + virtual void TrimMaps() = 0; + + protected: + ArenaPool() = default; private: - const bool use_malloc_; - mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - Arena* free_arenas_ GUARDED_BY(lock_); - const bool low_4gb_; - const char* name_; DISALLOW_COPY_AND_ASSIGN(ArenaPool); }; diff --git a/runtime/base/arena_allocator_test.cc b/runtime/base/arena_allocator_test.cc index 68e26af9f8..68e99f4be0 100644 --- a/runtime/base/arena_allocator_test.cc +++ b/runtime/base/arena_allocator_test.cc @@ -16,6 +16,7 @@ #include "base/arena_allocator-inl.h" #include "base/arena_bit_vector.h" +#include "base/malloc_arena_pool.h" #include "base/memory_tool.h" #include "gtest/gtest.h" @@ -33,7 +34,7 @@ class ArenaAllocatorTest : public testing::Test { }; TEST_F(ArenaAllocatorTest, Test) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); ArenaBitVector bv(&allocator, 10, true); bv.SetBit(5); @@ -44,7 +45,7 @@ TEST_F(ArenaAllocatorTest, Test) { TEST_F(ArenaAllocatorTest, MakeDefined) { // Regression test to make sure we mark the allocated area defined. - ArenaPool pool; + MallocArenaPool pool; static constexpr size_t kSmallArraySize = 10; static constexpr size_t kLargeArraySize = 50; uint32_t* small_array; @@ -71,7 +72,7 @@ TEST_F(ArenaAllocatorTest, LargeAllocations) { } { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); // Note: Leaving some space for memory tool red zones. void* alloc1 = allocator.Alloc(arena_allocator::kArenaDefaultSize * 5 / 8); @@ -80,7 +81,7 @@ TEST_F(ArenaAllocatorTest, LargeAllocations) { ASSERT_EQ(1u, NumberOfArenas(&allocator)); } { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); void* alloc1 = allocator.Alloc(arena_allocator::kArenaDefaultSize * 13 / 16); void* alloc2 = allocator.Alloc(arena_allocator::kArenaDefaultSize * 11 / 16); @@ -92,7 +93,7 @@ TEST_F(ArenaAllocatorTest, LargeAllocations) { ASSERT_EQ(3u, NumberOfArenas(&allocator)); } { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); void* alloc1 = allocator.Alloc(arena_allocator::kArenaDefaultSize * 13 / 16); void* alloc2 = allocator.Alloc(arena_allocator::kArenaDefaultSize * 9 / 16); @@ -105,7 +106,7 @@ TEST_F(ArenaAllocatorTest, LargeAllocations) { ASSERT_EQ(2u, NumberOfArenas(&allocator)); } { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); void* alloc1 = allocator.Alloc(arena_allocator::kArenaDefaultSize * 9 / 16); void* alloc2 = allocator.Alloc(arena_allocator::kArenaDefaultSize * 13 / 16); @@ -118,7 +119,7 @@ TEST_F(ArenaAllocatorTest, LargeAllocations) { ASSERT_EQ(2u, NumberOfArenas(&allocator)); } { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); // Note: Leaving some space for memory tool red zones. for (size_t i = 0; i != 15; ++i) { @@ -133,7 +134,7 @@ TEST_F(ArenaAllocatorTest, LargeAllocations) { } TEST_F(ArenaAllocatorTest, AllocAlignment) { - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); for (size_t iterations = 0; iterations <= 10; ++iterations) { for (size_t size = 1; size <= ArenaAllocator::kAlignment + 1; ++size) { @@ -153,7 +154,7 @@ TEST_F(ArenaAllocatorTest, ReallocReuse) { { // Case 1: small aligned allocation, aligned extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2; @@ -166,7 +167,7 @@ TEST_F(ArenaAllocatorTest, ReallocReuse) { { // Case 2: small aligned allocation, non-aligned extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2; @@ -179,7 +180,7 @@ TEST_F(ArenaAllocatorTest, ReallocReuse) { { // Case 3: small non-aligned allocation, aligned extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2); @@ -192,7 +193,7 @@ TEST_F(ArenaAllocatorTest, ReallocReuse) { { // Case 4: small non-aligned allocation, aligned non-extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2); @@ -208,7 +209,7 @@ TEST_F(ArenaAllocatorTest, ReallocReuse) { { // Case 5: large allocation, aligned extend into next arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = arena_allocator::kArenaDefaultSize - @@ -222,7 +223,7 @@ TEST_F(ArenaAllocatorTest, ReallocReuse) { { // Case 6: large allocation, non-aligned extend into next arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = arena_allocator::kArenaDefaultSize - @@ -241,7 +242,7 @@ TEST_F(ArenaAllocatorTest, ReallocReuse) { TEST_F(ArenaAllocatorTest, ReallocAlignment) { { // Case 1: small aligned allocation, aligned extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2; @@ -258,7 +259,7 @@ TEST_F(ArenaAllocatorTest, ReallocAlignment) { { // Case 2: small aligned allocation, non-aligned extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2; @@ -275,7 +276,7 @@ TEST_F(ArenaAllocatorTest, ReallocAlignment) { { // Case 3: small non-aligned allocation, aligned extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2); @@ -292,7 +293,7 @@ TEST_F(ArenaAllocatorTest, ReallocAlignment) { { // Case 4: small non-aligned allocation, aligned non-extend inside arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2); @@ -312,7 +313,7 @@ TEST_F(ArenaAllocatorTest, ReallocAlignment) { { // Case 5: large allocation, aligned extend into next arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = arena_allocator::kArenaDefaultSize - @@ -330,7 +331,7 @@ TEST_F(ArenaAllocatorTest, ReallocAlignment) { { // Case 6: large allocation, non-aligned extend into next arena. - ArenaPool pool; + MallocArenaPool pool; ArenaAllocator allocator(&pool); const size_t original_size = arena_allocator::kArenaDefaultSize - diff --git a/runtime/base/malloc_arena_pool.cc b/runtime/base/malloc_arena_pool.cc new file mode 100644 index 0000000000..7df4aef25b --- /dev/null +++ b/runtime/base/malloc_arena_pool.cc @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2018 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. + */ + +#include "malloc_arena_pool.h" + +#include <sys/mman.h> + +#include <algorithm> +#include <cstddef> +#include <iomanip> +#include <numeric> + +#include <android-base/logging.h> +#include "base/arena_allocator-inl.h" + +namespace art { + +class MallocArena FINAL : public Arena { + public: + explicit MallocArena(size_t size = arena_allocator::kArenaDefaultSize); + virtual ~MallocArena(); + private: + static constexpr size_t RequiredOverallocation() { + return (alignof(std::max_align_t) < ArenaAllocator::kArenaAlignment) + ? ArenaAllocator::kArenaAlignment - alignof(std::max_align_t) + : 0u; + } + + uint8_t* unaligned_memory_; +}; + +MallocArena::MallocArena(size_t size) { + // We need to guarantee kArenaAlignment aligned allocation for the new arena. + // TODO: Use std::aligned_alloc() when it becomes available with C++17. + constexpr size_t overallocation = RequiredOverallocation(); + unaligned_memory_ = reinterpret_cast<uint8_t*>(calloc(1, size + overallocation)); + CHECK(unaligned_memory_ != nullptr); // Abort on OOM. + DCHECK_ALIGNED(unaligned_memory_, alignof(std::max_align_t)); + if (overallocation == 0u) { + memory_ = unaligned_memory_; + } else { + memory_ = AlignUp(unaligned_memory_, ArenaAllocator::kArenaAlignment); + if (UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) { + size_t head = memory_ - unaligned_memory_; + size_t tail = overallocation - head; + MEMORY_TOOL_MAKE_NOACCESS(unaligned_memory_, head); + MEMORY_TOOL_MAKE_NOACCESS(memory_ + size, tail); + } + } + DCHECK_ALIGNED(memory_, ArenaAllocator::kArenaAlignment); + size_ = size; +} + +MallocArena::~MallocArena() { + constexpr size_t overallocation = RequiredOverallocation(); + if (overallocation != 0u && UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) { + size_t head = memory_ - unaligned_memory_; + size_t tail = overallocation - head; + MEMORY_TOOL_MAKE_UNDEFINED(unaligned_memory_, head); + MEMORY_TOOL_MAKE_UNDEFINED(memory_ + size_, tail); + } + free(reinterpret_cast<void*>(unaligned_memory_)); +} + +void Arena::Reset() { + if (bytes_allocated_ > 0) { + memset(Begin(), 0, bytes_allocated_); + bytes_allocated_ = 0; + } +} + +MallocArenaPool::MallocArenaPool() : free_arenas_(nullptr) { +} + +MallocArenaPool::~MallocArenaPool() { + ReclaimMemory(); +} + +void MallocArenaPool::ReclaimMemory() { + while (free_arenas_ != nullptr) { + Arena* arena = free_arenas_; + free_arenas_ = free_arenas_->next_; + delete arena; + } +} + +void MallocArenaPool::LockReclaimMemory() { + std::lock_guard<std::mutex> lock(lock_); + ReclaimMemory(); +} + +Arena* MallocArenaPool::AllocArena(size_t size) { + Arena* ret = nullptr; + { + std::lock_guard<std::mutex> lock(lock_); + if (free_arenas_ != nullptr && LIKELY(free_arenas_->Size() >= size)) { + ret = free_arenas_; + free_arenas_ = free_arenas_->next_; + } + } + if (ret == nullptr) { + ret = new MallocArena(size); + } + ret->Reset(); + return ret; +} + +void MallocArenaPool::TrimMaps() { + // Nop, because there is no way to do madvise here. +} + +size_t MallocArenaPool::GetBytesAllocated() const { + size_t total = 0; + std::lock_guard<std::mutex> lock(lock_); + for (Arena* arena = free_arenas_; arena != nullptr; arena = arena->next_) { + total += arena->GetBytesAllocated(); + } + return total; +} + +void MallocArenaPool::FreeArenaChain(Arena* first) { + if (UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) { + for (Arena* arena = first; arena != nullptr; arena = arena->next_) { + MEMORY_TOOL_MAKE_UNDEFINED(arena->memory_, arena->bytes_allocated_); + } + } + + if (arena_allocator::kArenaAllocatorPreciseTracking) { + // Do not reuse arenas when tracking. + while (first != nullptr) { + Arena* next = first->next_; + delete first; + first = next; + } + return; + } + + if (first != nullptr) { + Arena* last = first; + while (last->next_ != nullptr) { + last = last->next_; + } + std::lock_guard<std::mutex> lock(lock_); + last->next_ = free_arenas_; + free_arenas_ = first; + } +} + +} // namespace art diff --git a/runtime/base/malloc_arena_pool.h b/runtime/base/malloc_arena_pool.h new file mode 100644 index 0000000000..9cd2572411 --- /dev/null +++ b/runtime/base/malloc_arena_pool.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 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_BASE_MALLOC_ARENA_POOL_H_ +#define ART_RUNTIME_BASE_MALLOC_ARENA_POOL_H_ + +#include <mutex> + +#include "base/arena_allocator.h" + +namespace art { + +class MallocArenaPool FINAL : public ArenaPool { + public: + MallocArenaPool(); + ~MallocArenaPool(); + Arena* AllocArena(size_t size) OVERRIDE; + void FreeArenaChain(Arena* first) OVERRIDE; + size_t GetBytesAllocated() const OVERRIDE; + void ReclaimMemory() OVERRIDE; + void LockReclaimMemory() OVERRIDE; + // Is a nop for malloc pools. + void TrimMaps() OVERRIDE; + + private: + Arena* free_arenas_; + // Use a std::mutex here as Arenas are at the bottom of the lock hierarchy when malloc is used. + mutable std::mutex lock_; + + DISALLOW_COPY_AND_ASSIGN(MallocArenaPool); +}; + +} // namespace art + +#endif // ART_RUNTIME_BASE_MALLOC_ARENA_POOL_H_ diff --git a/runtime/base/mem_map_arena_pool.cc b/runtime/base/mem_map_arena_pool.cc new file mode 100644 index 0000000000..d5ea19b70e --- /dev/null +++ b/runtime/base/mem_map_arena_pool.cc @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2018 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. + */ + +#include "mem_map_arena_pool.h" + +#include <sys/mman.h> + +#include <algorithm> +#include <cstddef> +#include <iomanip> +#include <numeric> + +#include <android-base/logging.h> + +#include "base/arena_allocator-inl.h" +#include "base/systrace.h" +#include "mem_map.h" + +namespace art { + +class MemMapArena FINAL : public Arena { + public: + MemMapArena(size_t size, bool low_4gb, const char* name); + virtual ~MemMapArena(); + void Release() OVERRIDE; + + private: + std::unique_ptr<MemMap> map_; +}; + +MemMapArena::MemMapArena(size_t size, bool low_4gb, const char* name) { + // Round up to a full page as that's the smallest unit of allocation for mmap() + // and we want to be able to use all memory that we actually allocate. + size = RoundUp(size, kPageSize); + std::string error_msg; + map_.reset(MemMap::MapAnonymous( + name, nullptr, size, PROT_READ | PROT_WRITE, low_4gb, false, &error_msg)); + CHECK(map_.get() != nullptr) << error_msg; + memory_ = map_->Begin(); + static_assert(ArenaAllocator::kArenaAlignment <= kPageSize, + "Arena should not need stronger alignment than kPageSize."); + DCHECK_ALIGNED(memory_, ArenaAllocator::kArenaAlignment); + size_ = map_->Size(); +} + +MemMapArena::~MemMapArena() { + // Destroys MemMap via std::unique_ptr<>. +} + +void MemMapArena::Release() { + if (bytes_allocated_ > 0) { + map_->MadviseDontNeedAndZero(); + bytes_allocated_ = 0; + } +} + +MemMapArenaPool::MemMapArenaPool(bool low_4gb, const char* name) + : low_4gb_(low_4gb), + name_(name), + free_arenas_(nullptr) { + MemMap::Init(); +} + +MemMapArenaPool::~MemMapArenaPool() { + ReclaimMemory(); +} + +void MemMapArenaPool::ReclaimMemory() { + while (free_arenas_ != nullptr) { + Arena* arena = free_arenas_; + free_arenas_ = free_arenas_->next_; + delete arena; + } +} + +void MemMapArenaPool::LockReclaimMemory() { + std::lock_guard<std::mutex> lock(lock_); + ReclaimMemory(); +} + +Arena* MemMapArenaPool::AllocArena(size_t size) { + Arena* ret = nullptr; + { + std::lock_guard<std::mutex> lock(lock_); + if (free_arenas_ != nullptr && LIKELY(free_arenas_->Size() >= size)) { + ret = free_arenas_; + free_arenas_ = free_arenas_->next_; + } + } + if (ret == nullptr) { + ret = new MemMapArena(size, low_4gb_, name_); + } + ret->Reset(); + return ret; +} + +void MemMapArenaPool::TrimMaps() { + ScopedTrace trace(__PRETTY_FUNCTION__); + std::lock_guard<std::mutex> lock(lock_); + for (Arena* arena = free_arenas_; arena != nullptr; arena = arena->next_) { + arena->Release(); + } +} + +size_t MemMapArenaPool::GetBytesAllocated() const { + size_t total = 0; + std::lock_guard<std::mutex> lock(lock_); + for (Arena* arena = free_arenas_; arena != nullptr; arena = arena->next_) { + total += arena->GetBytesAllocated(); + } + return total; +} + +void MemMapArenaPool::FreeArenaChain(Arena* first) { + if (UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) { + for (Arena* arena = first; arena != nullptr; arena = arena->next_) { + MEMORY_TOOL_MAKE_UNDEFINED(arena->memory_, arena->bytes_allocated_); + } + } + + if (arena_allocator::kArenaAllocatorPreciseTracking) { + // Do not reuse arenas when tracking. + while (first != nullptr) { + Arena* next = first->next_; + delete first; + first = next; + } + return; + } + + if (first != nullptr) { + Arena* last = first; + while (last->next_ != nullptr) { + last = last->next_; + } + std::lock_guard<std::mutex> lock(lock_); + last->next_ = free_arenas_; + free_arenas_ = first; + } +} + +} // namespace art diff --git a/runtime/base/mem_map_arena_pool.h b/runtime/base/mem_map_arena_pool.h new file mode 100644 index 0000000000..24e150e1e7 --- /dev/null +++ b/runtime/base/mem_map_arena_pool.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2018 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_BASE_MEM_MAP_ARENA_POOL_H_ +#define ART_RUNTIME_BASE_MEM_MAP_ARENA_POOL_H_ + +#include "base/arena_allocator.h" + +namespace art { + +class MemMapArenaPool FINAL : public ArenaPool { + public: + explicit MemMapArenaPool(bool low_4gb = false, const char* name = "LinearAlloc"); + virtual ~MemMapArenaPool(); + Arena* AllocArena(size_t size) OVERRIDE; + void FreeArenaChain(Arena* first) OVERRIDE; + size_t GetBytesAllocated() const OVERRIDE; + void ReclaimMemory() OVERRIDE; + void LockReclaimMemory() OVERRIDE; + // Trim the maps in arenas by madvising, used by JIT to reduce memory usage. + void TrimMaps() OVERRIDE; + + private: + const bool low_4gb_; + const char* name_; + Arena* free_arenas_; + // Use a std::mutex here as Arenas are second-from-the-bottom when using MemMaps, and MemMap + // itself uses std::mutex scoped to within an allocate/free only. + mutable std::mutex lock_; + + DISALLOW_COPY_AND_ASSIGN(MemMapArenaPool); +}; + +} // namespace art + +#endif // ART_RUNTIME_BASE_MEM_MAP_ARENA_POOL_H_ diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc index 1bbce4f414..f4132c2343 100644 --- a/runtime/jit/profile_compilation_info.cc +++ b/runtime/jit/profile_compilation_info.cc @@ -36,6 +36,7 @@ #include "base/dumpable.h" #include "base/file_utils.h" #include "base/logging.h" // For VLOG. +#include "base/malloc_arena_pool.h" #include "base/mutex.h" #include "base/os.h" #include "base/safe_map.h" @@ -90,7 +91,7 @@ ProfileCompilationInfo::ProfileCompilationInfo(ArenaPool* custom_arena_pool) } ProfileCompilationInfo::ProfileCompilationInfo() - : default_arena_pool_(/*use_malloc*/true, /*low_4gb*/false, "ProfileCompilationInfo"), + : default_arena_pool_(), allocator_(&default_arena_pool_), info_(allocator_.Adapter(kArenaAllocProfile)), profile_key_map_(std::less<const std::string>(), allocator_.Adapter(kArenaAllocProfile)) { diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h index 6c56db9f49..4ac8c612e0 100644 --- a/runtime/jit/profile_compilation_info.h +++ b/runtime/jit/profile_compilation_info.h @@ -23,6 +23,7 @@ #include "base/arena_containers.h" #include "base/arena_object.h" #include "base/atomic.h" +#include "base/malloc_arena_pool.h" #include "base/safe_map.h" #include "bit_memory_region.h" #include "dex/dex_cache_resolved_classes.h" @@ -792,7 +793,7 @@ class ProfileCompilationInfo { friend class ProfileAssistantTest; friend class Dex2oatLayoutTest; - ArenaPool default_arena_pool_; + MallocArenaPool default_arena_pool_; ArenaAllocator allocator_; // Vector containing the actual profile info. diff --git a/runtime/linear_alloc.h b/runtime/linear_alloc.h index 384b2e3243..87086f29d4 100644 --- a/runtime/linear_alloc.h +++ b/runtime/linear_alloc.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_LINEAR_ALLOC_H_ #include "base/arena_allocator.h" +#include "base/mutex.h" namespace art { diff --git a/runtime/runtime.cc b/runtime/runtime.cc index b80ce7de46..4068158f3f 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -62,6 +62,8 @@ #include "base/dumpable.h" #include "base/enums.h" #include "base/file_utils.h" +#include "base/malloc_arena_pool.h" +#include "base/mem_map_arena_pool.h" #include "base/memory_tool.h" #include "base/mutex.h" #include "base/os.h" @@ -1332,13 +1334,17 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { // Use MemMap arena pool for jit, malloc otherwise. Malloc arenas are faster to allocate but // can't be trimmed as easily. const bool use_malloc = IsAotCompiler(); - arena_pool_.reset(new ArenaPool(use_malloc, /* low_4gb */ false)); - jit_arena_pool_.reset( - new ArenaPool(/* use_malloc */ false, /* low_4gb */ false, "CompilerMetadata")); + if (use_malloc) { + arena_pool_.reset(new MallocArenaPool()); + jit_arena_pool_.reset(new MallocArenaPool()); + } else { + arena_pool_.reset(new MemMapArenaPool(/* low_4gb */ false)); + jit_arena_pool_.reset(new MemMapArenaPool(/* low_4gb */ false, "CompilerMetadata")); + } if (IsAotCompiler() && Is64BitInstructionSet(kRuntimeISA)) { // 4gb, no malloc. Explanation in header. - low_4gb_arena_pool_.reset(new ArenaPool(/* use_malloc */ false, /* low_4gb */ true)); + low_4gb_arena_pool_.reset(new MemMapArenaPool(/* low_4gb */ true)); } linear_alloc_.reset(CreateLinearAlloc()); diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h index 18ad6b5d0c..168eb7bb63 100644 --- a/runtime/verifier/register_line.h +++ b/runtime/verifier/register_line.h @@ -22,6 +22,7 @@ #include <android-base/logging.h> +#include "base/mutex.h" #include "base/safe_map.h" #include "base/scoped_arena_containers.h" |