Also add redzones around non-fixed mem_map(s).
Also extend -Wframe-larger-than limit to enable arm64 ASan build.
Change-Id: Ie572481a25fead59fc8978d2c317a33ac418516c
# Larger frame-size for host clang builds today
ifneq ($(ART_COVERAGE),true)
ifneq ($(NATIVE_COVERAGE),true)
- ifndef SANITIZE_HOST
- art_host_non_debug_cflags += -Wframe-larger-than=2700
- endif
- ifndef SANITIZE_TARGET
+ art_host_non_debug_cflags += -Wframe-larger-than=2700
+ ifdef SANITIZE_TARGET
+ art_target_non_debug_cflags += -Wframe-larger-than=5450
+ else
art_target_non_debug_cflags += -Wframe-larger-than=1728
endif
endif
#define ART_COMPILER_IMAGE_WRITER_H_
#include <stdint.h>
-#include <valgrind.h>
+#include "base/memory_tool.h"
#include <cstddef>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
-#include <valgrind.h>
+#include "base/memory_tool.h"
#include <fstream>
#include <iostream>
// the runtime.
LogCompletionTime();
- if (kIsDebugBuild || (RUNNING_ON_VALGRIND != 0)) {
+ if (kIsDebugBuild || (RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
delete runtime_; // See field declaration for why this is manual.
}
}
// Everything was done, do an explicit exit here to avoid running Runtime destructors that take
// time (bug 10645725) unless we're a debug build or running on valgrind. Note: The Dex2Oat class
// should not destruct the runtime in this case.
- if (!art::kIsDebugBuild && (RUNNING_ON_VALGRIND == 0)) {
+ if (!art::kIsDebugBuild && (RUNNING_ON_MEMORY_TOOL == 0)) {
exit(result);
}
return result;
#include "mem_map.h"
#include "mutex.h"
#include "thread-inl.h"
-#include <memcheck/memcheck.h>
+#include "base/memory_tool.h"
namespace art {
-static constexpr size_t kValgrindRedZoneBytes = 8;
+static constexpr size_t kMemoryToolRedZoneBytes = 8;
constexpr size_t Arena::kDefaultSize;
template <bool kCount>
}
void ArenaPool::FreeArenaChain(Arena* first) {
- if (UNLIKELY(RUNNING_ON_VALGRIND > 0)) {
+ if (UNLIKELY(RUNNING_ON_MEMORY_TOOL > 0)) {
for (Arena* arena = first; arena != nullptr; arena = arena->next_) {
- VALGRIND_MAKE_MEM_UNDEFINED(arena->memory_, arena->bytes_allocated_);
+ MEMORY_TOOL_MAKE_UNDEFINED(arena->memory_, arena->bytes_allocated_);
}
}
if (first != nullptr) {
end_(nullptr),
ptr_(nullptr),
arena_head_(nullptr),
- running_on_valgrind_(RUNNING_ON_VALGRIND > 0) {
+ is_running_on_memory_tool_(RUNNING_ON_MEMORY_TOOL) {
}
void ArenaAllocator::UpdateBytesAllocated() {
}
void* ArenaAllocator::AllocValgrind(size_t bytes, ArenaAllocKind kind) {
- size_t rounded_bytes = RoundUp(bytes + kValgrindRedZoneBytes, 8);
+ size_t rounded_bytes = RoundUp(bytes + kMemoryToolRedZoneBytes, 8);
if (UNLIKELY(ptr_ + rounded_bytes > end_)) {
// Obtain a new block.
ObtainNewArenaForAllocation(rounded_bytes);
for (uint8_t* ptr = ret; ptr < ptr_; ++ptr) {
CHECK_EQ(*ptr, 0U);
}
- VALGRIND_MAKE_MEM_NOACCESS(ret + bytes, rounded_bytes - bytes);
+ MEMORY_TOOL_MAKE_NOACCESS(ret + bytes, rounded_bytes - bytes);
return ret;
}
// Returns zeroed memory.
void* Alloc(size_t bytes, ArenaAllocKind kind = kArenaAllocMisc) ALWAYS_INLINE {
- if (UNLIKELY(running_on_valgrind_)) {
+ if (UNLIKELY(is_running_on_memory_tool_)) {
return AllocValgrind(bytes, kind);
}
bytes = RoundUp(bytes, kAlignment);
uint8_t* end_;
uint8_t* ptr_;
Arena* arena_head_;
- bool running_on_valgrind_;
+ bool is_running_on_memory_tool_;
template <typename U>
friend class ArenaAllocatorAdapter;
--- /dev/null
+/*
+ * Copyright (C) 2015 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_MEMORY_TOOL_H_
+#define ART_RUNTIME_BASE_MEMORY_TOOL_H_
+
+#include <stddef.h>
+
+#if !defined(__has_feature)
+#define __has_feature(x) 0
+#endif
+
+#if __has_feature(address_sanitizer)
+
+#include <sanitizer/asan_interface.h>
+#define ADDRESS_SANITIZER
+#define MEMORY_TOOL_MAKE_NOACCESS(p, s) __asan_poison_memory_region(p, s)
+#define MEMORY_TOOL_MAKE_UNDEFINED(p, s) __asan_unpoison_memory_region(p, s)
+#define MEMORY_TOOL_MAKE_DEFINED(p, s) __asan_unpoison_memory_region(p, s)
+#define RUNNING_ON_MEMORY_TOOL 1U
+constexpr bool kMemoryToolIsValgrind = false;
+constexpr bool kMemoryToolDetectsLeaks = true;
+constexpr bool kMemoryToolAddsRedzones = true;
+constexpr size_t kMemoryToolStackGuardSizeScale = 2;
+
+#else
+
+#include <valgrind.h>
+#include <memcheck/memcheck.h>
+#define MEMORY_TOOL_MAKE_NOACCESS(p, s) VALGRIND_MAKE_MEM_NOACCESS(p, s)
+#define MEMORY_TOOL_MAKE_UNDEFINED(p, s) VALGRIND_MAKE_MEM_UNDEFINED(p, s)
+#define MEMORY_TOOL_MAKE_DEFINED(p, s) VALGRIND_MAKE_MEM_DEFINED(p, s)
+#define RUNNING_ON_MEMORY_TOOL RUNNING_ON_VALGRIND
+constexpr bool kMemoryToolIsValgrind = true;
+constexpr bool kMemoryToolDetectsLeaks = true;
+constexpr bool kMemoryToolAddsRedzones = true;
+constexpr size_t kMemoryToolStackGuardSizeScale = 1;
+
+#endif
+
+#endif // ART_RUNTIME_BASE_MEMORY_TOOL_H_
#include "scoped_arena_allocator.h"
#include "arena_allocator.h"
-#include <memcheck/memcheck.h>
+#include "base/memory_tool.h"
namespace art {
-static constexpr size_t kValgrindRedZoneBytes = 8;
+static constexpr size_t kMemoryToolRedZoneBytes = 8;
ArenaStack::ArenaStack(ArenaPool* arena_pool)
: DebugStackRefCounter(),
top_arena_(nullptr),
top_ptr_(nullptr),
top_end_(nullptr),
- running_on_valgrind_(RUNNING_ON_VALGRIND > 0) {
+ is_running_on_memory_tool_(RUNNING_ON_MEMORY_TOOL > 0) {
}
ArenaStack::~ArenaStack() {
}
void* ArenaStack::AllocValgrind(size_t bytes, ArenaAllocKind kind) {
- size_t rounded_bytes = RoundUp(bytes + kValgrindRedZoneBytes, 8);
+ size_t rounded_bytes = RoundUp(bytes + kMemoryToolRedZoneBytes, 8);
uint8_t* ptr = top_ptr_;
if (UNLIKELY(static_cast<size_t>(top_end_ - ptr) < rounded_bytes)) {
ptr = AllocateFromNextArena(rounded_bytes);
}
CurrentStats()->RecordAlloc(bytes, kind);
top_ptr_ = ptr + rounded_bytes;
- VALGRIND_MAKE_MEM_UNDEFINED(ptr, bytes);
- VALGRIND_MAKE_MEM_NOACCESS(ptr + bytes, rounded_bytes - bytes);
+ MEMORY_TOOL_MAKE_UNDEFINED(ptr, bytes);
+ MEMORY_TOOL_MAKE_NOACCESS(ptr + bytes, rounded_bytes - bytes);
return ptr;
}
// Private - access via ScopedArenaAllocator or ScopedArenaAllocatorAdapter.
void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE {
- if (UNLIKELY(running_on_valgrind_)) {
+ if (UNLIKELY(is_running_on_memory_tool_)) {
return AllocValgrind(bytes, kind);
}
size_t rounded_bytes = RoundUp(bytes, 8);
uint8_t* top_ptr_;
uint8_t* top_end_;
- const bool running_on_valgrind_;
+ const bool is_running_on_memory_tool_;
friend class ScopedArenaAllocator;
template <typename T>
namespace allocator {
inline ALWAYS_INLINE bool RosAlloc::ShouldCheckZeroMemory() {
- return kCheckZeroMemory && !running_on_valgrind_;
+ return kCheckZeroMemory && !is_running_on_memory_tool_;
}
template<bool kThreadSafe>
#include "rosalloc.h"
+#include "base/memory_tool.h"
#include "base/mutex-inl.h"
-#include "gc/space/valgrind_settings.h"
+#include "gc/space/memory_tool_settings.h"
#include "mem_map.h"
#include "mirror/class-inl.h"
#include "mirror/object.h"
reinterpret_cast<RosAlloc::Run*>(dedicated_full_run_storage_);
RosAlloc::RosAlloc(void* base, size_t capacity, size_t max_capacity,
- PageReleaseMode page_release_mode, bool running_on_valgrind,
+ PageReleaseMode page_release_mode, bool running_on_memory_tool,
size_t page_release_size_threshold)
: base_(reinterpret_cast<uint8_t*>(base)), footprint_(capacity),
capacity_(capacity), max_capacity_(max_capacity),
bulk_free_lock_("rosalloc bulk free lock", kRosAllocBulkFreeLock),
page_release_mode_(page_release_mode),
page_release_size_threshold_(page_release_size_threshold),
- running_on_valgrind_(running_on_valgrind) {
+ is_running_on_memory_tool_(running_on_memory_tool) {
DCHECK_EQ(RoundUp(capacity, kPageSize), capacity);
DCHECK_EQ(RoundUp(max_capacity, kPageSize), max_capacity);
CHECK_LE(capacity, max_capacity);
for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
delete size_bracket_locks_[i];
}
+ if (is_running_on_memory_tool_) {
+ MEMORY_TOOL_MAKE_DEFINED(base_, capacity_);
+ }
}
void* RosAlloc::AllocPages(Thread* self, size_t num_pages, uint8_t page_map_type) {
MutexLock lock_mu(self, lock_);
size_t pm_end = page_map_size_;
size_t i = 0;
- size_t valgrind_modifier = running_on_valgrind_ ?
- 2 * ::art::gc::space::kDefaultValgrindRedZoneBytes : // Redzones before and after.
+ size_t memory_tool_modifier = is_running_on_memory_tool_ ?
+ 2 * ::art::gc::space::kDefaultMemoryToolRedZoneBytes : // Redzones before and after.
0;
while (i < pm_end) {
uint8_t pm = page_map_[i];
idx++;
}
uint8_t* start = base_ + i * kPageSize;
- if (running_on_valgrind_) {
- start += ::art::gc::space::kDefaultValgrindRedZoneBytes;
+ if (is_running_on_memory_tool_) {
+ start += ::art::gc::space::kDefaultMemoryToolRedZoneBytes;
}
mirror::Object* obj = reinterpret_cast<mirror::Object*>(start);
size_t obj_size = obj->SizeOf();
- CHECK_GT(obj_size + valgrind_modifier, kLargeSizeThreshold)
+ CHECK_GT(obj_size + memory_tool_modifier, kLargeSizeThreshold)
<< "A rosalloc large object size must be > " << kLargeSizeThreshold;
- CHECK_EQ(num_pages, RoundUp(obj_size + valgrind_modifier, kPageSize) / kPageSize)
- << "A rosalloc large object size " << obj_size + valgrind_modifier
+ CHECK_EQ(num_pages, RoundUp(obj_size + memory_tool_modifier, kPageSize) / kPageSize)
+ << "A rosalloc large object size " << obj_size + memory_tool_modifier
<< " does not match the page map table " << (num_pages * kPageSize)
<< std::endl << DumpPageMap();
i += num_pages;
}
// Call Verify() here for the lock order.
for (auto& run : runs) {
- run->Verify(self, this, running_on_valgrind_);
+ run->Verify(self, this, is_running_on_memory_tool_);
}
}
-void RosAlloc::Run::Verify(Thread* self, RosAlloc* rosalloc, bool running_on_valgrind) {
+void RosAlloc::Run::Verify(Thread* self, RosAlloc* rosalloc, bool running_on_memory_tool) {
DCHECK_EQ(magic_num_, kMagicNum) << "Bad magic number : " << Dump();
const size_t idx = size_bracket_idx_;
CHECK_LT(idx, kNumOfSizeBrackets) << "Out of range size bracket index : " << Dump();
}
// Check each slot.
size_t slots = 0;
- size_t valgrind_modifier = running_on_valgrind ?
- 2 * ::art::gc::space::kDefaultValgrindRedZoneBytes :
+ size_t memory_tool_modifier = running_on_memory_tool ?
+ 2 * ::art::gc::space::kDefaultMemoryToolRedZoneBytes :
0U;
for (size_t v = 0; v < num_vec; v++, slots += 32) {
DCHECK_GE(num_slots, slots) << "Out of bounds";
bool is_thread_local_freed = IsThreadLocal() && ((thread_local_free_vec >> i) & 0x1) != 0;
if (is_allocated && !is_thread_local_freed) {
uint8_t* slot_addr = slot_base + (slots + i) * bracket_size;
- if (running_on_valgrind) {
- slot_addr += ::art::gc::space::kDefaultValgrindRedZoneBytes;
+ if (running_on_memory_tool) {
+ slot_addr += ::art::gc::space::kDefaultMemoryToolRedZoneBytes;
}
mirror::Object* obj = reinterpret_cast<mirror::Object*>(slot_addr);
size_t obj_size = obj->SizeOf();
- CHECK_LE(obj_size + valgrind_modifier, kLargeSizeThreshold)
+ CHECK_LE(obj_size + memory_tool_modifier, kLargeSizeThreshold)
<< "A run slot contains a large object " << Dump();
- CHECK_EQ(SizeToIndex(obj_size + valgrind_modifier), idx)
+ CHECK_EQ(SizeToIndex(obj_size + memory_tool_modifier), idx)
<< PrettyTypeOf(obj) << " "
- << "obj_size=" << obj_size << "(" << obj_size + valgrind_modifier << "), idx=" << idx
+ << "obj_size=" << obj_size << "(" << obj_size + memory_tool_modifier << "), idx=" << idx
<< " A run slot contains an object with wrong size " << Dump();
}
}
// Dump the run metadata for debugging.
std::string Dump();
// Verify for debugging.
- void Verify(Thread* self, RosAlloc* rosalloc, bool running_on_valgrind)
+ void Verify(Thread* self, RosAlloc* rosalloc, bool running_on_memory_tool)
EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_);
const size_t page_release_size_threshold_;
// Whether this allocator is running under Valgrind.
- bool running_on_valgrind_;
+ bool is_running_on_memory_tool_;
// The base address of the memory region that's managed by this allocator.
uint8_t* Begin() { return base_; }
public:
RosAlloc(void* base, size_t capacity, size_t max_capacity,
PageReleaseMode page_release_mode,
- bool running_on_valgrind,
+ bool running_on_memory_tool,
size_t page_release_size_threshold = kDefaultPageReleaseSizeThreshold);
~RosAlloc();
} else if (!kInstrumented && allocator == kAllocatorTypeRosAlloc &&
(obj = rosalloc_space_->AllocThreadLocal(self, byte_count, &bytes_allocated)) &&
LIKELY(obj != nullptr)) {
- DCHECK(!running_on_valgrind_);
+ DCHECK(!is_running_on_memory_tool_);
obj->SetClass(klass);
if (kUseBakerOrBrooksReadBarrier) {
if (kUseBrooksReadBarrier) {
break;
}
case kAllocatorTypeRosAlloc: {
- if (kInstrumented && UNLIKELY(running_on_valgrind_)) {
- // If running on valgrind, we should be using the instrumented path.
+ if (kInstrumented && UNLIKELY(is_running_on_memory_tool_)) {
+ // If running on valgrind or asan, we should be using the instrumented path.
size_t max_bytes_tl_bulk_allocated = rosalloc_space_->MaxBytesBulkAllocatedFor(alloc_size);
if (UNLIKELY(IsOutOfMemoryOnAllocation<kGrow>(allocator_type,
max_bytes_tl_bulk_allocated))) {
ret = rosalloc_space_->Alloc(self, alloc_size, bytes_allocated, usable_size,
bytes_tl_bulk_allocated);
} else {
- DCHECK(!running_on_valgrind_);
+ DCHECK(!is_running_on_memory_tool_);
size_t max_bytes_tl_bulk_allocated =
rosalloc_space_->MaxBytesBulkAllocatedForNonvirtual(alloc_size);
if (UNLIKELY(IsOutOfMemoryOnAllocation<kGrow>(allocator_type,
break;
}
case kAllocatorTypeDlMalloc: {
- if (kInstrumented && UNLIKELY(running_on_valgrind_)) {
+ if (kInstrumented && UNLIKELY(is_running_on_memory_tool_)) {
// If running on valgrind, we should be using the instrumented path.
ret = dlmalloc_space_->Alloc(self, alloc_size, bytes_allocated, usable_size,
bytes_tl_bulk_allocated);
} else {
- DCHECK(!running_on_valgrind_);
+ DCHECK(!is_running_on_memory_tool_);
ret = dlmalloc_space_->AllocNonvirtual(self, alloc_size, bytes_allocated, usable_size,
bytes_tl_bulk_allocated);
}
total_allocation_time_(0),
verify_object_mode_(kVerifyObjectModeDisabled),
disable_moving_gc_count_(0),
- running_on_valgrind_(Runtime::Current()->RunningOnValgrind()),
+ is_running_on_memory_tool_(Runtime::Current()->IsRunningOnMemoryTool()),
use_tlab_(use_tlab),
main_space_backup_(nullptr),
min_interval_homogeneous_space_compaction_by_oom_(
if (gc_stress_mode_) {
backtrace_lock_ = new Mutex("GC complete lock");
}
- if (running_on_valgrind_ || gc_stress_mode_) {
+ if (is_running_on_memory_tool_ || gc_stress_mode_) {
instrumentation->InstrumentQuickAllocEntryPoints();
}
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
// Special compacting collector which uses sub-optimal bin packing to reduce zygote space size.
class ZygoteCompactingCollector FINAL : public collector::SemiSpace {
public:
- explicit ZygoteCompactingCollector(gc::Heap* heap) : SemiSpace(heap, false, "zygote collector"),
- bin_live_bitmap_(nullptr), bin_mark_bitmap_(nullptr) {
- }
+ explicit ZygoteCompactingCollector(gc::Heap* heap,
+ bool is_running_on_memory_tool)
+ : SemiSpace(heap, false, "zygote collector"),
+ bin_live_bitmap_(nullptr),
+ bin_mark_bitmap_(nullptr),
+ is_running_on_memory_tool_(is_running_on_memory_tool) {}
void BuildBins(space::ContinuousSpace* space) {
bin_live_bitmap_ = space->GetLiveBitmap();
accounting::ContinuousSpaceBitmap* bin_live_bitmap_;
// Mark bitmap of the space which contains the bins.
accounting::ContinuousSpaceBitmap* bin_mark_bitmap_;
+ const bool is_running_on_memory_tool_;
static void Callback(mirror::Object* obj, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
}
void AddBin(size_t size, uintptr_t position) {
+ if (is_running_on_memory_tool_) {
+ MEMORY_TOOL_MAKE_DEFINED(reinterpret_cast<void*>(position), size);
+ }
if (size != 0) {
bins_.insert(std::make_pair(size, position));
}
// Temporarily disable rosalloc verification because the zygote
// compaction will mess up the rosalloc internal metadata.
ScopedDisableRosAllocVerification disable_rosalloc_verif(this);
- ZygoteCompactingCollector zygote_collector(this);
+ ZygoteCompactingCollector zygote_collector(this, is_running_on_memory_tool_);
zygote_collector.BuildBins(non_moving_space_);
// Create a new bump pointer space which we will compact into.
space::BumpPointerSpace target_space("zygote bump space", non_moving_space_->End(),
collector::MarkCompact* mark_compact_collector_;
collector::ConcurrentCopying* concurrent_copying_collector_;
- const bool running_on_valgrind_;
+ const bool is_running_on_memory_tool_;
const bool use_tlab_;
// Pointer to the space which becomes the new main space when we do homogeneous space compaction.
#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
+#include "memory_tool_malloc_space-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "runtime.h"
#include "thread.h"
#include "thread_list.h"
#include "utils.h"
-#include "valgrind_malloc_space-inl.h"
namespace art {
namespace gc {
// Everything is set so record in immutable structure and leave
uint8_t* begin = mem_map->Begin();
- if (Runtime::Current()->RunningOnValgrind()) {
- return new ValgrindMallocSpace<DlMallocSpace, kDefaultValgrindRedZoneBytes, true, false>(
+ if (Runtime::Current()->IsRunningOnMemoryTool()) {
+ return new MemoryToolMallocSpace<DlMallocSpace, kDefaultMemoryToolRedZoneBytes, true, false>(
mem_map, initial_size, name, mspace, begin, end, begin + capacity, growth_limit,
can_move_objects, starting_size);
} else {
void* allocator, uint8_t* begin, uint8_t* end,
uint8_t* limit, size_t growth_limit,
bool can_move_objects) {
- if (Runtime::Current()->RunningOnValgrind()) {
- return new ValgrindMallocSpace<DlMallocSpace, kDefaultValgrindRedZoneBytes, true, false>(
+ if (Runtime::Current()->IsRunningOnMemoryTool()) {
+ return new MemoryToolMallocSpace<DlMallocSpace, kDefaultMemoryToolRedZoneBytes, true, false>(
mem_map, initial_size_, name, allocator, begin, end, limit, growth_limit,
can_move_objects, starting_size_);
} else {
namespace space {
// An alloc space is a space where objects may be allocated and garbage collected. Not final as may
-// be overridden by a ValgrindMallocSpace.
+// be overridden by a MemoryToolMallocSpace.
class DlMallocSpace : public MallocSpace {
public:
// Create a DlMallocSpace from an existing mem_map.
static DlMallocSpace* Create(const std::string& name, size_t initial_size, size_t growth_limit,
size_t capacity, uint8_t* requested_begin, bool can_move_objects);
- // Virtual to allow ValgrindMallocSpace to intercept.
+ // Virtual to allow MemoryToolMallocSpace to intercept.
virtual mirror::Object* AllocWithGrowth(Thread* self, size_t num_bytes, size_t* bytes_allocated,
size_t* usable_size,
size_t* bytes_tl_bulk_allocated)
OVERRIDE LOCKS_EXCLUDED(lock_);
- // Virtual to allow ValgrindMallocSpace to intercept.
+ // Virtual to allow MemoryToolMallocSpace to intercept.
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
size_t* usable_size, size_t* bytes_tl_bulk_allocated)
OVERRIDE LOCKS_EXCLUDED(lock_) {
return AllocNonvirtual(self, num_bytes, bytes_allocated, usable_size,
bytes_tl_bulk_allocated);
}
- // Virtual to allow ValgrindMallocSpace to intercept.
+ // Virtual to allow MemoryToolMallocSpace to intercept.
virtual size_t AllocationSize(mirror::Object* obj, size_t* usable_size) OVERRIDE {
return AllocationSizeNonvirtual(obj, usable_size);
}
- // Virtual to allow ValgrindMallocSpace to intercept.
+ // Virtual to allow MemoryToolMallocSpace to intercept.
virtual size_t Free(Thread* self, mirror::Object* ptr) OVERRIDE
LOCKS_EXCLUDED(lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Virtual to allow ValgrindMallocSpace to intercept.
+ // Virtual to allow MemoryToolMallocSpace to intercept.
virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) OVERRIDE
LOCKS_EXCLUDED(lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
namespace gc {
namespace space {
-class ValgrindLargeObjectMapSpace FINAL : public LargeObjectMapSpace {
+class MemoryToolLargeObjectMapSpace FINAL : public LargeObjectMapSpace {
public:
- explicit ValgrindLargeObjectMapSpace(const std::string& name) : LargeObjectMapSpace(name) {
+ explicit MemoryToolLargeObjectMapSpace(const std::string& name) : LargeObjectMapSpace(name) {
}
- ~ValgrindLargeObjectMapSpace() OVERRIDE {
+ ~MemoryToolLargeObjectMapSpace() OVERRIDE {
// Keep valgrind happy if there is any large objects such as dex cache arrays which aren't
// freed since they are held live by the class linker.
MutexLock mu(Thread::Current(), lock_);
size_t* usable_size, size_t* bytes_tl_bulk_allocated)
OVERRIDE {
mirror::Object* obj =
- LargeObjectMapSpace::Alloc(self, num_bytes + kValgrindRedZoneBytes * 2, bytes_allocated,
+ LargeObjectMapSpace::Alloc(self, num_bytes + kMemoryToolRedZoneBytes * 2, bytes_allocated,
usable_size, bytes_tl_bulk_allocated);
mirror::Object* object_without_rdz = reinterpret_cast<mirror::Object*>(
- reinterpret_cast<uintptr_t>(obj) + kValgrindRedZoneBytes);
- VALGRIND_MAKE_MEM_NOACCESS(reinterpret_cast<void*>(obj), kValgrindRedZoneBytes);
- VALGRIND_MAKE_MEM_NOACCESS(reinterpret_cast<uint8_t*>(object_without_rdz) + num_bytes,
- kValgrindRedZoneBytes);
+ reinterpret_cast<uintptr_t>(obj) + kMemoryToolRedZoneBytes);
+ MEMORY_TOOL_MAKE_NOACCESS(reinterpret_cast<void*>(obj), kMemoryToolRedZoneBytes);
+ MEMORY_TOOL_MAKE_NOACCESS(
+ reinterpret_cast<uint8_t*>(object_without_rdz) + num_bytes,
+ kMemoryToolRedZoneBytes);
if (usable_size != nullptr) {
*usable_size = num_bytes; // Since we have redzones, shrink the usable size.
}
size_t Free(Thread* self, mirror::Object* obj) OVERRIDE {
mirror::Object* object_with_rdz = ObjectWithRedzone(obj);
- VALGRIND_MAKE_MEM_UNDEFINED(object_with_rdz, AllocationSize(obj, nullptr));
+ MEMORY_TOOL_MAKE_UNDEFINED(object_with_rdz, AllocationSize(obj, nullptr));
return LargeObjectMapSpace::Free(self, object_with_rdz);
}
private:
static const mirror::Object* ObjectWithRedzone(const mirror::Object* obj) {
return reinterpret_cast<const mirror::Object*>(
- reinterpret_cast<uintptr_t>(obj) - kValgrindRedZoneBytes);
+ reinterpret_cast<uintptr_t>(obj) - kMemoryToolRedZoneBytes);
}
static mirror::Object* ObjectWithRedzone(mirror::Object* obj) {
return reinterpret_cast<mirror::Object*>(
- reinterpret_cast<uintptr_t>(obj) - kValgrindRedZoneBytes);
+ reinterpret_cast<uintptr_t>(obj) - kMemoryToolRedZoneBytes);
}
- static constexpr size_t kValgrindRedZoneBytes = kPageSize;
+ static constexpr size_t kMemoryToolRedZoneBytes = kPageSize;
};
void LargeObjectSpace::SwapBitmaps() {
lock_("large object map space lock", kAllocSpaceLock) {}
LargeObjectMapSpace* LargeObjectMapSpace::Create(const std::string& name) {
- if (Runtime::Current()->RunningOnValgrind()) {
- return new ValgrindLargeObjectMapSpace(name);
+ if (Runtime::Current()->IsRunningOnMemoryTool()) {
+ return new MemoryToolLargeObjectMapSpace(name);
} else {
return new LargeObjectMapSpace(name);
}
#include "space.h"
#include <ostream>
+#include "base/memory_tool.h"
namespace art {
namespace gc {
* limitations under the License.
*/
-#ifndef ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_INL_H_
-#define ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_INL_H_
+#ifndef ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_INL_H_
+#define ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_INL_H_
-#include "valgrind_malloc_space.h"
-
-#include <memcheck/memcheck.h>
-
-#include "valgrind_settings.h"
+#include "base/memory_tool.h"
+#include "memory_tool_malloc_space.h"
+#include "memory_tool_settings.h"
namespace art {
namespace gc {
namespace space {
-namespace valgrind_details {
+namespace memory_tool_details {
-template <size_t kValgrindRedZoneBytes, bool kUseObjSizeForUsable>
+template <size_t kMemoryToolRedZoneBytes, bool kUseObjSizeForUsable>
inline mirror::Object* AdjustForValgrind(void* obj_with_rdz, size_t num_bytes,
size_t bytes_allocated, size_t usable_size,
size_t bytes_tl_bulk_allocated,
if (kUseObjSizeForUsable) {
*usable_size_out = num_bytes;
} else {
- *usable_size_out = usable_size - 2 * kValgrindRedZoneBytes;
+ *usable_size_out = usable_size - 2 * kMemoryToolRedZoneBytes;
}
}
// Left redzone.
- VALGRIND_MAKE_MEM_NOACCESS(obj_with_rdz, kValgrindRedZoneBytes);
+ MEMORY_TOOL_MAKE_NOACCESS(obj_with_rdz, kMemoryToolRedZoneBytes);
// Make requested memory readable.
// (If the allocator assumes memory is zeroed out, we might get UNDEFINED warnings, so make
// everything DEFINED initially.)
mirror::Object* result = reinterpret_cast<mirror::Object*>(
- reinterpret_cast<uint8_t*>(obj_with_rdz) + kValgrindRedZoneBytes);
- VALGRIND_MAKE_MEM_DEFINED(result, num_bytes);
+ reinterpret_cast<uint8_t*>(obj_with_rdz) + kMemoryToolRedZoneBytes);
+ MEMORY_TOOL_MAKE_DEFINED(result, num_bytes);
// Right redzone. Assumes that if bytes_allocated > usable_size, then the difference is
// management data at the upper end, and for simplicity we will not protect that.
// At the moment, this fits RosAlloc (no management data in a slot, usable_size == alloc_size)
// and DlMalloc (allocation_size = (usable_size == num_bytes) + 4, 4 is management)
- VALGRIND_MAKE_MEM_NOACCESS(reinterpret_cast<uint8_t*>(result) + num_bytes,
- usable_size - (num_bytes + kValgrindRedZoneBytes));
+ MEMORY_TOOL_MAKE_NOACCESS(reinterpret_cast<uint8_t*>(result) + num_bytes,
+ usable_size - (num_bytes + kMemoryToolRedZoneBytes));
return result;
}
return obj->SizeOf<kVerifyNone>();
}
-} // namespace valgrind_details
+} // namespace memory_tool_details
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
mirror::Object*
-ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
kUseObjSizeForUsable>::AllocWithGrowth(
Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out,
size_t bytes_allocated;
size_t usable_size;
size_t bytes_tl_bulk_allocated;
- void* obj_with_rdz = S::AllocWithGrowth(self, num_bytes + 2 * kValgrindRedZoneBytes,
+ void* obj_with_rdz = S::AllocWithGrowth(self, num_bytes + 2 * kMemoryToolRedZoneBytes,
&bytes_allocated, &usable_size,
&bytes_tl_bulk_allocated);
if (obj_with_rdz == nullptr) {
return nullptr;
}
- return valgrind_details::AdjustForValgrind<kValgrindRedZoneBytes, kUseObjSizeForUsable>(
+ return memory_tool_details::AdjustForValgrind<kMemoryToolRedZoneBytes, kUseObjSizeForUsable>(
obj_with_rdz, num_bytes,
bytes_allocated, usable_size,
bytes_tl_bulk_allocated,
}
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
-mirror::Object* ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+mirror::Object* MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
kUseObjSizeForUsable>::Alloc(
Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out,
size_t bytes_allocated;
size_t usable_size;
size_t bytes_tl_bulk_allocated;
- void* obj_with_rdz = S::Alloc(self, num_bytes + 2 * kValgrindRedZoneBytes,
+ void* obj_with_rdz = S::Alloc(self, num_bytes + 2 * kMemoryToolRedZoneBytes,
&bytes_allocated, &usable_size, &bytes_tl_bulk_allocated);
if (obj_with_rdz == nullptr) {
return nullptr;
}
- return valgrind_details::AdjustForValgrind<kValgrindRedZoneBytes,
+ return memory_tool_details::AdjustForValgrind<kMemoryToolRedZoneBytes,
kUseObjSizeForUsable>(obj_with_rdz, num_bytes,
bytes_allocated, usable_size,
bytes_tl_bulk_allocated,
}
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
-mirror::Object* ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+mirror::Object* MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
kUseObjSizeForUsable>::AllocThreadUnsafe(
Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out,
size_t bytes_allocated;
size_t usable_size;
size_t bytes_tl_bulk_allocated;
- void* obj_with_rdz = S::AllocThreadUnsafe(self, num_bytes + 2 * kValgrindRedZoneBytes,
+ void* obj_with_rdz = S::AllocThreadUnsafe(self, num_bytes + 2 * kMemoryToolRedZoneBytes,
&bytes_allocated, &usable_size,
&bytes_tl_bulk_allocated);
if (obj_with_rdz == nullptr) {
return nullptr;
}
- return valgrind_details::AdjustForValgrind<kValgrindRedZoneBytes, kUseObjSizeForUsable>(
+ return memory_tool_details::AdjustForValgrind<kMemoryToolRedZoneBytes, kUseObjSizeForUsable>(
obj_with_rdz, num_bytes,
bytes_allocated, usable_size,
bytes_tl_bulk_allocated,
}
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
-size_t ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+size_t MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
kUseObjSizeForUsable>::AllocationSize(
mirror::Object* obj, size_t* usable_size) {
size_t result = S::AllocationSize(reinterpret_cast<mirror::Object*>(
- reinterpret_cast<uint8_t*>(obj) - (kAdjustForRedzoneInAllocSize ? kValgrindRedZoneBytes : 0)),
+ reinterpret_cast<uint8_t*>(obj) - (kAdjustForRedzoneInAllocSize ? kMemoryToolRedZoneBytes : 0)),
usable_size);
if (usable_size != nullptr) {
if (kUseObjSizeForUsable) {
- *usable_size = valgrind_details::GetObjSizeNoThreadSafety(obj);
+ *usable_size = memory_tool_details::GetObjSizeNoThreadSafety(obj);
} else {
- *usable_size = *usable_size - 2 * kValgrindRedZoneBytes;
+ *usable_size = *usable_size - 2 * kMemoryToolRedZoneBytes;
}
}
return result;
}
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
-size_t ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+size_t MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
kUseObjSizeForUsable>::Free(
Thread* self, mirror::Object* ptr) {
void* obj_after_rdz = reinterpret_cast<void*>(ptr);
- uint8_t* obj_with_rdz = reinterpret_cast<uint8_t*>(obj_after_rdz) - kValgrindRedZoneBytes;
+ uint8_t* obj_with_rdz = reinterpret_cast<uint8_t*>(obj_after_rdz) - kMemoryToolRedZoneBytes;
+
// Make redzones undefined.
size_t usable_size;
size_t allocation_size = AllocationSize(ptr, &usable_size);
// Use the obj-size-for-usable flag to determine whether usable_size is the more important one,
// e.g., whether there's data in the allocation_size (and usable_size can't be trusted).
if (kUseObjSizeForUsable) {
- VALGRIND_MAKE_MEM_UNDEFINED(obj_with_rdz, allocation_size);
+ MEMORY_TOOL_MAKE_UNDEFINED(obj_with_rdz, allocation_size);
} else {
- VALGRIND_MAKE_MEM_UNDEFINED(obj_with_rdz, usable_size + 2 * kValgrindRedZoneBytes);
+ MEMORY_TOOL_MAKE_UNDEFINED(obj_with_rdz, usable_size + 2 * kMemoryToolRedZoneBytes);
}
return S::Free(self, reinterpret_cast<mirror::Object*>(obj_with_rdz));
}
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
-size_t ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+size_t MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
kUseObjSizeForUsable>::FreeList(
Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
}
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
template <typename... Params>
-ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
- kUseObjSizeForUsable>::ValgrindMallocSpace(
+ kUseObjSizeForUsable>::MemoryToolMallocSpace(
MemMap* mem_map, size_t initial_size, Params... params) : S(mem_map, initial_size, params...) {
- VALGRIND_MAKE_MEM_UNDEFINED(mem_map->Begin() + initial_size,
- mem_map->Size() - initial_size);
+ MEMORY_TOOL_MAKE_DEFINED(mem_map->Begin(), initial_size);
+ MEMORY_TOOL_MAKE_UNDEFINED(mem_map->Begin() + initial_size,
+ mem_map->Size() - initial_size);
}
template <typename S,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
-size_t ValgrindMallocSpace<S,
- kValgrindRedZoneBytes,
+size_t MemoryToolMallocSpace<S,
+ kMemoryToolRedZoneBytes,
kAdjustForRedzoneInAllocSize,
kUseObjSizeForUsable>::MaxBytesBulkAllocatedFor(size_t num_bytes) {
- return S::MaxBytesBulkAllocatedFor(num_bytes + 2 * kValgrindRedZoneBytes);
+ return S::MaxBytesBulkAllocatedFor(num_bytes + 2 * kMemoryToolRedZoneBytes);
}
} // namespace space
} // namespace gc
} // namespace art
-#endif // ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_INL_H_
+#endif // ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_INL_H_
* limitations under the License.
*/
-#ifndef ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_H_
-#define ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_H_
+#ifndef ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_H_
+#define ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_H_
#include "malloc_space.h"
-#include <valgrind.h>
-
namespace art {
namespace gc {
namespace space {
-// A specialization of DlMallocSpace/RosAllocSpace that places valgrind red zones around
-// allocations.
+// A specialization of DlMallocSpace/RosAllocSpace that places memory tool red
+// zones around allocations.
template <typename BaseMallocSpaceType,
- size_t kValgrindRedZoneBytes,
+ size_t kMemoryToolRedZoneBytes,
bool kAdjustForRedzoneInAllocSize,
bool kUseObjSizeForUsable>
-class ValgrindMallocSpace FINAL : public BaseMallocSpaceType {
+class MemoryToolMallocSpace FINAL : public BaseMallocSpaceType {
public:
mirror::Object* AllocWithGrowth(Thread* self, size_t num_bytes, size_t* bytes_allocated,
size_t* usable_size, size_t* bytes_tl_bulk_allocated)
size_t MaxBytesBulkAllocatedFor(size_t num_bytes) OVERRIDE;
template <typename... Params>
- explicit ValgrindMallocSpace(MemMap* mem_map, size_t initial_size, Params... params);
- virtual ~ValgrindMallocSpace() {}
+ explicit MemoryToolMallocSpace(MemMap* mem_map, size_t initial_size, Params... params);
+ virtual ~MemoryToolMallocSpace() {}
private:
- DISALLOW_COPY_AND_ASSIGN(ValgrindMallocSpace);
+ DISALLOW_COPY_AND_ASSIGN(MemoryToolMallocSpace);
};
} // namespace space
} // namespace gc
} // namespace art
-#endif // ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_H_
+#endif // ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_H_
* limitations under the License.
*/
-#ifndef ART_RUNTIME_GC_SPACE_VALGRIND_SETTINGS_H_
-#define ART_RUNTIME_GC_SPACE_VALGRIND_SETTINGS_H_
+#ifndef ART_RUNTIME_GC_SPACE_MEMORY_TOOL_SETTINGS_H_
+#define ART_RUNTIME_GC_SPACE_MEMORY_TOOL_SETTINGS_H_
namespace art {
namespace gc {
// Default number of bytes to use as a red zone (rdz). A red zone of this size will be placed before
// and after each allocation. 8 bytes provides long/double alignment.
-static constexpr size_t kDefaultValgrindRedZoneBytes = 8;
+static constexpr size_t kDefaultMemoryToolRedZoneBytes = 8;
} // namespace space
} // namespace gc
} // namespace art
-#endif // ART_RUNTIME_GC_SPACE_VALGRIND_SETTINGS_H_
+#endif // ART_RUNTIME_GC_SPACE_MEMORY_TOOL_SETTINGS_H_
#ifndef ART_RUNTIME_GC_SPACE_ROSALLOC_SPACE_INL_H_
#define ART_RUNTIME_GC_SPACE_ROSALLOC_SPACE_INL_H_
-#include <valgrind.h>
-
+#include "base/memory_tool.h"
#include "gc/allocator/rosalloc-inl.h"
-#include "gc/space/valgrind_settings.h"
+#include "gc/space/memory_tool_settings.h"
#include "rosalloc_space.h"
#include "thread.h"
namespace gc {
namespace space {
-template<bool kMaybeRunningOnValgrind>
+template<bool kMaybeIsRunningOnMemoryTool>
inline size_t RosAllocSpace::AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) {
// obj is a valid object. Use its class in the header to get the size.
// Don't use verification since the object may be dead if we are sweeping.
size_t size = obj->SizeOf<kVerifyNone>();
- bool running_on_valgrind = false;
- if (kMaybeRunningOnValgrind) {
- running_on_valgrind = RUNNING_ON_VALGRIND != 0;
- if (running_on_valgrind) {
- size += 2 * kDefaultValgrindRedZoneBytes;
+ bool add_redzones = false;
+ if (kMaybeIsRunningOnMemoryTool) {
+ add_redzones = RUNNING_ON_MEMORY_TOOL ? kMemoryToolAddsRedzones : 0;
+ if (add_redzones) {
+ size += 2 * kDefaultMemoryToolRedZoneBytes;
}
} else {
- DCHECK_EQ(RUNNING_ON_VALGRIND, 0U);
+ DCHECK_EQ(RUNNING_ON_MEMORY_TOOL, 0U);
}
size_t size_by_size = rosalloc_->UsableSize(size);
if (kIsDebugBuild) {
- // On valgrind, the red zone has an impact...
+ // On memory tool, the red zone has an impact...
const uint8_t* obj_ptr = reinterpret_cast<const uint8_t*>(obj);
size_t size_by_ptr = rosalloc_->UsableSize(
- obj_ptr - (running_on_valgrind ? kDefaultValgrindRedZoneBytes : 0));
+ obj_ptr - (add_redzones ? kDefaultMemoryToolRedZoneBytes : 0));
if (size_by_size != size_by_ptr) {
LOG(INFO) << "Found a bad sized obj of size " << size
<< " at " << std::hex << reinterpret_cast<intptr_t>(obj_ptr) << std::dec
#include "thread.h"
#include "thread_list.h"
#include "utils.h"
-#include "valgrind_malloc_space-inl.h"
+#include "memory_tool_malloc_space-inl.h"
namespace art {
namespace gc {
static constexpr bool kVerifyFreedBytes = false;
// TODO: Fix
-// template class ValgrindMallocSpace<RosAllocSpace, allocator::RosAlloc*>;
+// template class MemoryToolMallocSpace<RosAllocSpace, allocator::RosAlloc*>;
RosAllocSpace::RosAllocSpace(MemMap* mem_map, size_t initial_size, const std::string& name,
art::gc::allocator::RosAlloc* rosalloc, uint8_t* begin, uint8_t* end,
bool low_memory_mode, bool can_move_objects) {
DCHECK(mem_map != nullptr);
- bool running_on_valgrind = Runtime::Current()->RunningOnValgrind();
+ bool running_on_memory_tool = Runtime::Current()->IsRunningOnMemoryTool();
allocator::RosAlloc* rosalloc = CreateRosAlloc(mem_map->Begin(), starting_size, initial_size,
- capacity, low_memory_mode, running_on_valgrind);
+ capacity, low_memory_mode, running_on_memory_tool);
if (rosalloc == nullptr) {
LOG(ERROR) << "Failed to initialize rosalloc for alloc space (" << name << ")";
return nullptr;
// Everything is set so record in immutable structure and leave
uint8_t* begin = mem_map->Begin();
- // TODO: Fix RosAllocSpace to support valgrind. There is currently some issues with
+ // TODO: Fix RosAllocSpace to support Valgrind/ASan. There is currently some issues with
// AllocationSize caused by redzones. b/12944686
- if (running_on_valgrind) {
- return new ValgrindMallocSpace<RosAllocSpace, kDefaultValgrindRedZoneBytes, false, true>(
+ if (running_on_memory_tool) {
+ return new MemoryToolMallocSpace<RosAllocSpace, kDefaultMemoryToolRedZoneBytes, false, true>(
mem_map, initial_size, name, rosalloc, begin, end, begin + capacity, growth_limit,
can_move_objects, starting_size, low_memory_mode);
} else {
allocator::RosAlloc* RosAllocSpace::CreateRosAlloc(void* begin, size_t morecore_start,
size_t initial_size,
size_t maximum_size, bool low_memory_mode,
- bool running_on_valgrind) {
+ bool running_on_memory_tool) {
// clear errno to allow PLOG on error
errno = 0;
// create rosalloc using our backing storage starting at begin and
low_memory_mode ?
art::gc::allocator::RosAlloc::kPageReleaseModeAll :
art::gc::allocator::RosAlloc::kPageReleaseModeSizeAndEnd,
- running_on_valgrind);
+ running_on_memory_tool);
if (rosalloc != nullptr) {
rosalloc->SetFootprintLimit(initial_size);
} else {
void* allocator, uint8_t* begin, uint8_t* end,
uint8_t* limit, size_t growth_limit,
bool can_move_objects) {
- if (Runtime::Current()->RunningOnValgrind()) {
- return new ValgrindMallocSpace<RosAllocSpace, kDefaultValgrindRedZoneBytes, false, true>(
+ if (Runtime::Current()->IsRunningOnMemoryTool()) {
+ return new MemoryToolMallocSpace<RosAllocSpace, kDefaultMemoryToolRedZoneBytes, false, true>(
mem_map, initial_size_, name, reinterpret_cast<allocator::RosAlloc*>(allocator), begin, end,
limit, growth_limit, can_move_objects, starting_size_, low_memory_mode_);
} else {
delete rosalloc_;
rosalloc_ = CreateRosAlloc(mem_map_->Begin(), starting_size_, initial_size_,
NonGrowthLimitCapacity(), low_memory_mode_,
- Runtime::Current()->RunningOnValgrind());
+ Runtime::Current()->IsRunningOnMemoryTool());
SetFootprintLimit(footprint_limit);
}
namespace space {
// An alloc space implemented using a runs-of-slots memory allocator. Not final as may be
-// overridden by a ValgrindMallocSpace.
+// overridden by a MemoryToolMallocSpace.
class RosAllocSpace : public MallocSpace {
public:
// Create a RosAllocSpace with the requested sizes. The requested
ALWAYS_INLINE size_t MaxBytesBulkAllocatedForNonvirtual(size_t num_bytes);
// TODO: NO_THREAD_SAFETY_ANALYSIS because SizeOf() requires that mutator_lock is held.
- template<bool kMaybeRunningOnValgrind>
+ template<bool kMaybeIsRunningOnMemoryTool>
size_t AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size)
NO_THREAD_SAFETY_ANALYSIS;
void* CreateAllocator(void* base, size_t morecore_start, size_t initial_size,
size_t maximum_size, bool low_memory_mode) OVERRIDE {
return CreateRosAlloc(base, morecore_start, initial_size, maximum_size, low_memory_mode,
- RUNNING_ON_VALGRIND != 0);
+ RUNNING_ON_MEMORY_TOOL != 0);
}
static allocator::RosAlloc* CreateRosAlloc(void* base, size_t morecore_start, size_t initial_size,
size_t maximum_size, bool low_memory_mode,
- bool running_on_valgrind);
+ bool running_on_memory_tool);
void InspectAllRosAlloc(void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
void* arg, bool do_null_callback_at_end)
#include "mem_map.h"
+#include "base/memory_tool.h"
#include <backtrace/BacktraceMap.h>
#include <inttypes.h>
uint8_t* page_aligned_expected =
(expected_ptr == nullptr) ? nullptr : (expected_ptr - page_offset);
+ size_t redzone_size = 0;
+ if (RUNNING_ON_MEMORY_TOOL && kMemoryToolAddsRedzones && expected_ptr == nullptr) {
+ redzone_size = kPageSize;
+ page_aligned_byte_count += redzone_size;
+ }
+
uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(page_aligned_expected,
page_aligned_byte_count,
prot,
if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) {
return nullptr;
}
+ if (redzone_size != 0) {
+ const uint8_t *real_start = actual + page_offset;
+ const uint8_t *real_end = actual + page_offset + byte_count;
+ const uint8_t *mapping_end = actual + page_aligned_byte_count;
+
+ MEMORY_TOOL_MAKE_NOACCESS(actual, real_start - actual);
+ MEMORY_TOOL_MAKE_NOACCESS(real_end, mapping_end - real_end);
+ page_aligned_byte_count -= redzone_size;
+ }
+
return new MemMap(filename, actual + page_offset, byte_count, actual, page_aligned_byte_count,
- prot, reuse);
+ prot, reuse, redzone_size);
}
MemMap::~MemMap() {
if (base_begin_ == nullptr && base_size_ == 0) {
return;
}
+
+ // Unlike Valgrind, AddressSanitizer requires that all manually poisoned memory is unpoisoned
+ // before it is returned to the system.
+ if (redzone_size_ != 0) {
+ MEMORY_TOOL_MAKE_UNDEFINED(
+ reinterpret_cast<char*>(base_begin_) + base_size_ - redzone_size_,
+ redzone_size_);
+ }
+
if (!reuse_) {
+ MEMORY_TOOL_MAKE_UNDEFINED(base_begin_, base_size_);
int result = munmap(base_begin_, base_size_);
if (result == -1) {
PLOG(FATAL) << "munmap failed";
}
MemMap::MemMap(const std::string& name, uint8_t* begin, size_t size, void* base_begin,
- size_t base_size, int prot, bool reuse)
+ size_t base_size, int prot, bool reuse, size_t redzone_size)
: name_(name), begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size),
- prot_(prot), reuse_(reuse) {
+ prot_(prot), reuse_(reuse), redzone_size_(redzone_size) {
if (size_ == 0) {
CHECK(begin_ == nullptr);
CHECK(base_begin_ == nullptr);
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
#endif
+
+ MEMORY_TOOL_MAKE_UNDEFINED(tail_base_begin, tail_base_size);
// Unmap/map the tail region.
int result = munmap(tail_base_begin, tail_base_size);
if (result == -1) {
CHECK_ALIGNED(new_size, kPageSize);
CHECK_EQ(base_size_, size_) << "Unsupported";
CHECK_LE(new_size, base_size_);
+ MEMORY_TOOL_MAKE_UNDEFINED(
+ reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(BaseBegin()) +
+ new_size),
+ base_size_ - new_size);
CHECK_EQ(munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(BaseBegin()) + new_size),
base_size_ - new_size), 0) << new_size << " " << base_size_;
base_size_ = new_size;
private:
MemMap(const std::string& name, uint8_t* begin, size_t size, void* base_begin, size_t base_size,
- int prot, bool reuse) LOCKS_EXCLUDED(Locks::mem_maps_lock_);
+ int prot, bool reuse, size_t redzone_size = 0) LOCKS_EXCLUDED(Locks::mem_maps_lock_);
static void DumpMapsLocked(std::ostream& os, bool terse)
EXCLUSIVE_LOCKS_REQUIRED(Locks::mem_maps_lock_);
// unmapping.
const bool reuse_;
+ const size_t redzone_size_;
+
#if USE_ART_LOW_4G_ALLOCATOR
static uintptr_t next_mem_pos_; // Next memory location to check for low_4g extent.
#endif
#include <memory>
-#include <valgrind.h>
+#include "base/memory_tool.h"
#include "gtest/gtest.h"
TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) {
CommonInit();
// This test may not work under valgrind.
- if (RUNNING_ON_VALGRIND == 0) {
+ if (RUNNING_ON_MEMORY_TOOL == 0) {
uintptr_t start_addr = ART_BASE_ADDRESS + 0x1000000;
std::string error_msg;
std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr",
#include <cutils/trace.h>
#include <signal.h>
#include <sys/syscall.h>
-#include <valgrind.h>
+#include "base/memory_tool.h"
#include <cstdio>
#include <cstdlib>
exit_(nullptr),
abort_(nullptr),
stats_enabled_(false),
- running_on_valgrind_(RUNNING_ON_VALGRIND > 0),
+ is_running_on_memory_tool_(RUNNING_ON_MEMORY_TOOL),
profiler_started_(false),
instrumentation_(),
main_thread_group_(nullptr),
case kMips64:
implicit_null_checks_ = true;
// Installing stack protection does not play well with valgrind.
- implicit_so_checks_ = (RUNNING_ON_VALGRIND == 0);
+ implicit_so_checks_ = !(RUNNING_ON_MEMORY_TOOL && kMemoryToolIsValgrind);
break;
default:
// Keep the defaults.
return cpu_abilist_;
}
- bool RunningOnValgrind() const {
- return running_on_valgrind_;
+ bool IsRunningOnMemoryTool() const {
+ return is_running_on_memory_tool_;
}
void SetTargetSdkVersion(int32_t version) {
bool stats_enabled_;
RuntimeStats stats_;
- const bool running_on_valgrind_;
+ const bool is_running_on_memory_tool_;
std::string profile_output_filename_;
ProfilerOptions profiler_options_;
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/bit_utils.h"
+#include "base/memory_tool.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
#include "base/to_str.h"
ConditionVariable* Thread::resume_cond_ = nullptr;
const size_t Thread::kStackOverflowImplicitCheckSize = GetStackOverflowReservedBytes(kRuntimeISA);
+// For implicit overflow checks we reserve an extra piece of memory at the bottom
+// of the stack (lowest memory). The higher portion of the memory
+// is protected against reads and the lower is available for use while
+// throwing the StackOverflow exception.
+constexpr size_t kStackOverflowProtectedSize = 4 * kMemoryToolStackGuardSizeScale * KB;
+
static const char* kThreadNameDuringStartup = "<native thread without managed peer>";
void Thread::InitCardTable() {
class Thread {
public:
- // For implicit overflow checks we reserve an extra piece of memory at the bottom
- // of the stack (lowest memory). The higher portion of the memory
- // is protected against reads and the lower is available for use while
- // throwing the StackOverflow exception.
- static constexpr size_t kStackOverflowProtectedSize = 4 * KB;
static const size_t kStackOverflowImplicitCheckSize;
// Creates a new native thread corresponding to the given managed peer.
ArtMethod* current_method, void* ucontext_ptr) {
#if __linux__
// b/18119146
- if (RUNNING_ON_VALGRIND != 0) {
+ if (RUNNING_ON_MEMORY_TOOL != 0) {
return;
}
#include "scoped_thread_state_change.h"
#include "handle_scope-inl.h"
-#include <valgrind.h>
+#include "base/memory_tool.h"
namespace art {
command.push_back("/usr/bin/id");
}
std::string error_msg;
- if (RUNNING_ON_VALGRIND == 0) {
+ if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
// Running on valgrind fails due to some memory that leaks in thread alternate signal stacks.
EXPECT_TRUE(Exec(command, &error_msg));
}
std::vector<std::string> command;
command.push_back("bogus");
std::string error_msg;
- if (RUNNING_ON_VALGRIND == 0) {
+ if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
// Running on valgrind fails due to some memory that leaks in thread alternate signal stacks.
EXPECT_FALSE(Exec(command, &error_msg));
EXPECT_NE(0U, error_msg.size());