diff options
author | Anna Henningsen <anna@addaleax.net> | 2019-02-18 17:30:10 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2019-02-25 02:01:03 +0100 |
commit | 376735345088d4b37e0e289c2eb7720419ed37ee (patch) | |
tree | 4771426f776ca9e7e30fab08e1a188f8959b29af /src/api | |
parent | a8ba838e1a94c17ecf7a290c1951040d2957cb62 (diff) | |
download | android-node-v8-376735345088d4b37e0e289c2eb7720419ed37ee.tar.gz android-node-v8-376735345088d4b37e0e289c2eb7720419ed37ee.tar.bz2 android-node-v8-376735345088d4b37e0e289c2eb7720419ed37ee.zip |
src: add debugging array allocator
Add a subclass of `ArrayBufferAllocator` that performs additional
debug checking, which in particular verifies that:
- All `ArrayBuffer` backing stores have been allocated with this
allocator, or have been explicitly marked as coming from a
compatible source.
- All memory allocated by the allocator has been freed once it is
destroyed.
PR-URL: https://github.com/nodejs/node/pull/26207
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'src/api')
-rw-r--r-- | src/api/environment.cc | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/src/api/environment.cc b/src/api/environment.cc index 7b6de8ba8d..6a56ddb511 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -75,8 +75,82 @@ void* ArrayBufferAllocator::Allocate(size_t size) { return UncheckedMalloc(size); } +DebuggingArrayBufferAllocator::~DebuggingArrayBufferAllocator() { + CHECK(allocations_.empty()); +} + +void* DebuggingArrayBufferAllocator::Allocate(size_t size) { + Mutex::ScopedLock lock(mutex_); + void* data = ArrayBufferAllocator::Allocate(size); + RegisterPointerInternal(data, size); + return data; +} + +void* DebuggingArrayBufferAllocator::AllocateUninitialized(size_t size) { + Mutex::ScopedLock lock(mutex_); + void* data = ArrayBufferAllocator::AllocateUninitialized(size); + RegisterPointerInternal(data, size); + return data; +} + +void DebuggingArrayBufferAllocator::Free(void* data, size_t size) { + Mutex::ScopedLock lock(mutex_); + UnregisterPointerInternal(data, size); + ArrayBufferAllocator::Free(data, size); +} + +void* DebuggingArrayBufferAllocator::Reallocate(void* data, + size_t old_size, + size_t size) { + Mutex::ScopedLock lock(mutex_); + void* ret = ArrayBufferAllocator::Reallocate(data, old_size, size); + if (ret == nullptr) { + if (size == 0) // i.e. equivalent to free(). + UnregisterPointerInternal(data, old_size); + return nullptr; + } + + if (data != nullptr) { + auto it = allocations_.find(data); + CHECK_NE(it, allocations_.end()); + allocations_.erase(it); + } + + RegisterPointerInternal(ret, size); + return ret; +} + +void DebuggingArrayBufferAllocator::RegisterPointer(void* data, size_t size) { + Mutex::ScopedLock lock(mutex_); + RegisterPointerInternal(data, size); +} + +void DebuggingArrayBufferAllocator::UnregisterPointer(void* data, size_t size) { + Mutex::ScopedLock lock(mutex_); + UnregisterPointerInternal(data, size); +} + +void DebuggingArrayBufferAllocator::UnregisterPointerInternal(void* data, + size_t size) { + if (data == nullptr) return; + auto it = allocations_.find(data); + CHECK_NE(it, allocations_.end()); + CHECK_EQ(it->second, size); + allocations_.erase(it); +} + +void DebuggingArrayBufferAllocator::RegisterPointerInternal(void* data, + size_t size) { + if (data == nullptr) return; + CHECK_EQ(allocations_.count(data), 0); + allocations_[data] = size; +} + ArrayBufferAllocator* CreateArrayBufferAllocator() { - return new ArrayBufferAllocator(); + if (per_process::cli_options->debug_arraybuffer_allocations) + return new DebuggingArrayBufferAllocator(); + else + return new ArrayBufferAllocator(); } void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) { |