diff options
Diffstat (limited to 'chromium/gin/array_buffer.cc')
-rw-r--r-- | chromium/gin/array_buffer.cc | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/chromium/gin/array_buffer.cc b/chromium/gin/array_buffer.cc index d40e8981bd4..fb1c5f3a113 100644 --- a/chromium/gin/array_buffer.cc +++ b/chromium/gin/array_buffer.cc @@ -5,10 +5,20 @@ #include <stddef.h> #include <stdlib.h> +#include "base/allocator/partition_allocator/page_allocator.h" #include "base/logging.h" +#include "build/build_config.h" #include "gin/array_buffer.h" #include "gin/per_isolate_data.h" +#if defined(OS_POSIX) +#include <sys/mman.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif +#endif + namespace gin { namespace { @@ -30,10 +40,74 @@ void* ArrayBufferAllocator::AllocateUninitialized(size_t length) { return malloc(length); } +void* ArrayBufferAllocator::Reserve(size_t length) { + void* const hint = nullptr; +#if defined(OS_POSIX) + int const access_flag = PROT_NONE; + void* const ret = + mmap(hint, length, access_flag, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (ret == MAP_FAILED) { + return nullptr; + } + return ret; +#else + DWORD const access_flag = PAGE_NOACCESS; + return VirtualAlloc(hint, length, MEM_RESERVE, access_flag); +#endif +} + void ArrayBufferAllocator::Free(void* data, size_t length) { free(data); } +void ArrayBufferAllocator::Free(void* data, + size_t length, + AllocationMode mode) { + switch (mode) { + case AllocationMode::kNormal: + Free(data, length); + return; + case AllocationMode::kReservation: { +#if defined(OS_POSIX) + int const ret = munmap(data, length); + CHECK(!ret); +#else + BOOL const ret = VirtualFree(data, 0, MEM_RELEASE); + CHECK(ret); +#endif + return; + } + default: + NOTREACHED(); + } +} + +void ArrayBufferAllocator::SetProtection(void* data, + size_t length, + Protection protection) { + switch (protection) { + case Protection::kNoAccess: { +#if defined(OS_POSIX) + int ret = mprotect(data, length, PROT_NONE); + CHECK(!ret); +#else + BOOL ret = VirtualFree(data, length, MEM_DECOMMIT); + CHECK(ret); +#endif + break; + } + case Protection::kReadWrite: +#if defined(OS_POSIX) + mprotect(data, length, PROT_READ | PROT_WRITE); +#else + VirtualAlloc(data, length, MEM_COMMIT, PAGE_READWRITE); +#endif + break; + default: + NOTREACHED(); + } +} + ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() { static ArrayBufferAllocator* instance = new ArrayBufferAllocator(); return instance; @@ -82,6 +156,9 @@ class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> { v8::Isolate* isolate_; void* buffer_; size_t length_; + void* allocation_base_; + size_t allocation_length_; + v8::ArrayBuffer::Allocator::AllocationMode allocation_mode_; }; scoped_refptr<ArrayBuffer::Private> ArrayBuffer::Private::From( @@ -104,6 +181,14 @@ ArrayBuffer::Private::Private(v8::Isolate* isolate, v8::ArrayBuffer::Contents contents = array->Externalize(); buffer_ = contents.Data(); length_ = contents.ByteLength(); + allocation_base_ = contents.AllocationBase(); + allocation_length_ = contents.AllocationLength(); + allocation_mode_ = contents.AllocationMode(); + + DCHECK(reinterpret_cast<uintptr_t>(allocation_base_) <= + reinterpret_cast<uintptr_t>(buffer_)); + DCHECK(reinterpret_cast<uintptr_t>(buffer_) + length_ <= + reinterpret_cast<uintptr_t>(allocation_base_) + allocation_length_); array->SetAlignedPointerInInternalField(kWrapperInfoIndex, &g_array_buffer_wrapper_info); @@ -115,7 +200,8 @@ ArrayBuffer::Private::Private(v8::Isolate* isolate, } ArrayBuffer::Private::~Private() { - PerIsolateData::From(isolate_)->allocator()->Free(buffer_, length_); + PerIsolateData::From(isolate_)->allocator()->Free( + allocation_base_, allocation_length_, allocation_mode_); } void ArrayBuffer::Private::FirstWeakCallback( |