use PartitionAllocator for ArrayBuffers in the main process
This commit is contained in:
parent
3122820e58
commit
1f575ca3af
1 changed files with 81 additions and 4 deletions
|
@ -9,6 +9,7 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/task/current_thread.h"
|
#include "base/task/current_thread.h"
|
||||||
#include "base/task/thread_pool/initialization_util.h"
|
#include "base/task/thread_pool/initialization_util.h"
|
||||||
|
@ -65,6 +66,83 @@ struct base::trace_event::TraceValue::Helper<
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
|
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
|
||||||
|
public:
|
||||||
|
enum InitializationPolicy { kZeroInitialize, kDontInitialize };
|
||||||
|
|
||||||
|
ArrayBufferAllocator() {
|
||||||
|
// Ref.
|
||||||
|
// https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/wtf/allocator/partitions.cc;l=94;drc=062c315a858a87f834e16a144c2c8e9591af2beb
|
||||||
|
allocator_->init({base::PartitionOptions::Alignment::kRegular,
|
||||||
|
base::PartitionOptions::ThreadCache::kDisabled,
|
||||||
|
base::PartitionOptions::Quarantine::kAllowed,
|
||||||
|
base::PartitionOptions::RefCount::kDisabled});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate() methods return null to signal allocation failure to V8, which
|
||||||
|
// should respond by throwing a RangeError, per
|
||||||
|
// http://www.ecma-international.org/ecma-262/6.0/#sec-createbytedatablock.
|
||||||
|
void* Allocate(size_t size) override {
|
||||||
|
void* result = AllocateMemoryOrNull(size, kZeroInitialize);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* AllocateUninitialized(size_t size) override {
|
||||||
|
void* result = AllocateMemoryOrNull(size, kDontInitialize);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Realloc(void* data, size_t size) override {
|
||||||
|
return allocator_->root()->Realloc(data, size, "Electron");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void* data, size_t size) override {
|
||||||
|
allocator_->root()->Free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void* AllocateMemoryOrNull(size_t size, InitializationPolicy policy) {
|
||||||
|
return AllocateMemoryWithFlags(size, policy,
|
||||||
|
base::PartitionAllocReturnNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* AllocateMemoryWithFlags(size_t size,
|
||||||
|
InitializationPolicy policy,
|
||||||
|
int flags) {
|
||||||
|
// The array buffer contents are sometimes expected to be 16-byte aligned in
|
||||||
|
// order to get the best optimization of SSE, especially in case of audio
|
||||||
|
// and video buffers. Hence, align the given size up to 16-byte boundary.
|
||||||
|
// Technically speaking, 16-byte aligned size doesn't mean 16-byte aligned
|
||||||
|
// address, but this heuristics works with the current implementation of
|
||||||
|
// PartitionAlloc (and PartitionAlloc doesn't support a better way for now).
|
||||||
|
if (base::kAlignment <
|
||||||
|
16) { // base::kAlignment is a compile-time constant.
|
||||||
|
size_t aligned_size = base::bits::AlignUp(size, 16);
|
||||||
|
if (size == 0) {
|
||||||
|
aligned_size = 16;
|
||||||
|
}
|
||||||
|
if (aligned_size >= size) { // Only when no overflow
|
||||||
|
size = aligned_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (policy == kZeroInitialize) {
|
||||||
|
flags |= base::PartitionAllocZeroFill;
|
||||||
|
}
|
||||||
|
void* data = allocator_->root()->AllocFlags(flags, size, "Electron");
|
||||||
|
if (base::kAlignment < 16) {
|
||||||
|
char* ptr = reinterpret_cast<char*>(data);
|
||||||
|
DCHECK_EQ(base::bits::AlignUp(ptr, 16), ptr)
|
||||||
|
<< "Pointer " << ptr << " not 16B aligned for size " << size;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static base::NoDestructor<base::PartitionAllocator> allocator_;
|
||||||
|
};
|
||||||
|
|
||||||
|
base::NoDestructor<base::PartitionAllocator> ArrayBufferAllocator::allocator_{};
|
||||||
|
|
||||||
JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop)
|
JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop)
|
||||||
: isolate_(Initialize(event_loop)),
|
: isolate_(Initialize(event_loop)),
|
||||||
isolate_holder_(base::ThreadTaskRunnerHandle::Get(),
|
isolate_holder_(base::ThreadTaskRunnerHandle::Get(),
|
||||||
|
@ -249,10 +327,9 @@ v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
|
||||||
tracing_controller, gin::V8Platform::PageAllocator());
|
tracing_controller, gin::V8Platform::PageAllocator());
|
||||||
|
|
||||||
v8::V8::InitializePlatform(platform_);
|
v8::V8::InitializePlatform(platform_);
|
||||||
gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode,
|
gin::IsolateHolder::Initialize(
|
||||||
gin::ArrayBufferAllocator::SharedInstance(),
|
gin::IsolateHolder::kNonStrictMode, new ArrayBufferAllocator(),
|
||||||
nullptr /* external_reference_table */,
|
nullptr /* external_reference_table */, false /* create_v8_platform */);
|
||||||
false /* create_v8_platform */);
|
|
||||||
|
|
||||||
v8::Isolate* isolate = v8::Isolate::Allocate();
|
v8::Isolate* isolate = v8::Isolate::Allocate();
|
||||||
platform_->RegisterIsolate(isolate, event_loop);
|
platform_->RegisterIsolate(isolate, event_loop);
|
||||||
|
|
Loading…
Reference in a new issue