1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <stdlib.h> 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/array_buffer.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/per_isolate_data.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace gin { 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gin::WrapperInfo g_array_buffer_wrapper_info = {gin::kEmbedderNativeGin}; 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)COMPILE_ASSERT(V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT == 2, 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) array_buffers_must_have_two_internal_fields); 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ArrayBufferAllocator ------------------------------------------------------- 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void* ArrayBufferAllocator::Allocate(size_t length) { 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return calloc(1, length); 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void* ArrayBufferAllocator::AllocateUninitialized(size_t length) { 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return malloc(length); 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ArrayBufferAllocator::Free(void* data, size_t length) { 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) free(data); 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() { 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static ArrayBufferAllocator* instance = new ArrayBufferAllocator(); 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return instance; 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ArrayBuffer::Private ------------------------------------------------------- 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// This class exists to solve a tricky lifetime problem. The V8 API doesn't 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// want to expose a direct view into the memory behind an array buffer because 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// V8 might deallocate that memory during garbage collection. Instead, the V8 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// API forces us to externalize the buffer and take ownership of the memory. 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// In order to know when to free the memory, we need to figure out both when 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// we're done with it and when V8 is done with it. 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// To determine whether we're done with the memory, every view we have into 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// the array buffer takes a reference to the ArrayBuffer::Private object that 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// actually owns the memory. To determine when V8 is done with the memory, we 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// open a weak handle to the ArrayBuffer object. When we receive the weak 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// callback, we know the object is about to be garbage collected and we can 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// drop V8's implied reference to the memory. 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The final subtlety is that we need every ArrayBuffer into the same array 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// buffer to AddRef the same ArrayBuffer::Private. To make that work, we store 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// a pointer to the ArrayBuffer::Private object in an internal field of the 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ArrayBuffer object. 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> { 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public: 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static scoped_refptr<Private> From(v8::Isolate* isolate, 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<v8::ArrayBuffer> array); 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* buffer() const { return buffer_; } 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t length() const { return length_; } 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private: 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) friend class base::RefCounted<Private>; 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Private(v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array); 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ~Private(); 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static void WeakCallback( 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data); 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Persistent<v8::ArrayBuffer> array_buffer_; 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<Private> self_reference_; 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) v8::Isolate* isolate_; 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* buffer_; 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t length_; 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<ArrayBuffer::Private> ArrayBuffer::Private::From( 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array) { 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (array->IsExternal()) { 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CHECK_EQ(WrapperInfo::From(v8::Handle<v8::Object>::Cast(array)), 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &g_array_buffer_wrapper_info) 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Cannot mix blink and gin ArrayBuffers"; 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return make_scoped_refptr(static_cast<Private*>( 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) array->GetAlignedPointerFromInternalField(kEncodedValueIndex))); 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return make_scoped_refptr(new Private(isolate, array)); 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBuffer::Private::Private(v8::Isolate* isolate, 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<v8::ArrayBuffer> array) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : array_buffer_(isolate, array), isolate_(isolate) { 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Take ownership of the array buffer. 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CHECK(!array->IsExternal()); 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::ArrayBuffer::Contents contents = array->Externalize(); 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer_ = contents.Data(); 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) length_ = contents.ByteLength(); 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) array->SetAlignedPointerInInternalField(kWrapperInfoIndex, 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &g_array_buffer_wrapper_info); 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) array->SetAlignedPointerInInternalField(kEncodedValueIndex, this); 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self_reference_ = this; // Cleared in WeakCallback. 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) array_buffer_.SetWeak(this, WeakCallback); 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBuffer::Private::~Private() { 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PerIsolateData::From(isolate_)->allocator()->Free(buffer_, length_); 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ArrayBuffer::Private::WeakCallback( 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data) { 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Private* parameter = data.GetParameter(); 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) parameter->array_buffer_.Reset(); 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) parameter->self_reference_ = NULL; 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ArrayBuffer ---------------------------------------------------------------- 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBuffer::ArrayBuffer() 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : bytes_(0), 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) num_bytes_(0) { 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBuffer::ArrayBuffer(v8::Isolate* isolate, 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<v8::ArrayBuffer> array) { 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private_ = ArrayBuffer::Private::From(isolate, array); 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bytes_ = private_->buffer(); 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) num_bytes_ = private_->length(); 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBuffer::~ArrayBuffer() { 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ArrayBuffer& ArrayBuffer::operator=(const ArrayBuffer& other) { 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private_ = other.private_; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bytes_ = other.bytes_; 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) num_bytes_ = other.num_bytes_; 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return *this; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Converter<ArrayBuffer> ----------------------------------------------------- 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool Converter<ArrayBuffer>::FromV8(v8::Isolate* isolate, 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<v8::Value> val, 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ArrayBuffer* out) { 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!val->IsArrayBuffer()) 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *out = ArrayBuffer(isolate, v8::Handle<v8::ArrayBuffer>::Cast(val)); 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ArrayBufferView ------------------------------------------------------------ 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBufferView::ArrayBufferView() 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : offset_(0), 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) num_bytes_(0) { 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBufferView::ArrayBufferView(v8::Isolate* isolate, 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<v8::ArrayBufferView> view) 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : array_buffer_(isolate, view->Buffer()), 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) offset_(view->ByteOffset()), 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) num_bytes_(view->ByteLength()) { 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ArrayBufferView::~ArrayBufferView() { 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ArrayBufferView& ArrayBufferView::operator=(const ArrayBufferView& other) { 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) array_buffer_ = other.array_buffer_; 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) offset_ = other.offset_; 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) num_bytes_ = other.num_bytes_; 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return *this; 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Converter<ArrayBufferView> ------------------------------------------------- 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool Converter<ArrayBufferView>::FromV8(v8::Isolate* isolate, 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<v8::Value> val, 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ArrayBufferView* out) { 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!val->IsArrayBufferView()) 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *out = ArrayBufferView(isolate, v8::Handle<v8::ArrayBufferView>::Cast(val)); 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace gin 198