blob: d40e8981bd4598a67ce9f8a4e81da041d0f1d8f1 [file] [log] [blame]
[email protected]a22998a2013-11-10 05:00:501// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avi90e658dd2015-12-21 07:16:195#include <stddef.h>
[email protected]a22998a2013-11-10 05:00:506#include <stdlib.h>
7
[email protected]73dcce92014-02-20 08:24:048#include "base/logging.h"
9#include "gin/array_buffer.h"
10#include "gin/per_isolate_data.h"
11
[email protected]a22998a2013-11-10 05:00:5012namespace gin {
13
[email protected]73dcce92014-02-20 08:24:0414namespace {
15
16gin::WrapperInfo g_array_buffer_wrapper_info = {gin::kEmbedderNativeGin};
17
18} // namespace
19
anujk.sharmac1b6156b2015-01-20 21:47:3620static_assert(V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT == 2,
21 "array buffers must have two internal fields");
[email protected]a22998a2013-11-10 05:00:5022
[email protected]a22998a2013-11-10 05:00:5023// ArrayBufferAllocator -------------------------------------------------------
24
25void* ArrayBufferAllocator::Allocate(size_t length) {
26 return calloc(1, length);
27}
28
29void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
30 return malloc(length);
31}
32
33void ArrayBufferAllocator::Free(void* data, size_t length) {
34 free(data);
35}
36
37ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() {
38 static ArrayBufferAllocator* instance = new ArrayBufferAllocator();
39 return instance;
40}
41
[email protected]e87f3122013-11-12 00:41:2742// ArrayBuffer::Private -------------------------------------------------------
[email protected]a22998a2013-11-10 05:00:5043
44// This class exists to solve a tricky lifetime problem. The V8 API doesn't
45// want to expose a direct view into the memory behind an array buffer because
46// V8 might deallocate that memory during garbage collection. Instead, the V8
47// API forces us to externalize the buffer and take ownership of the memory.
48// In order to know when to free the memory, we need to figure out both when
49// we're done with it and when V8 is done with it.
50//
51// To determine whether we're done with the memory, every view we have into
[email protected]e87f3122013-11-12 00:41:2752// the array buffer takes a reference to the ArrayBuffer::Private object that
[email protected]a22998a2013-11-10 05:00:5053// actually owns the memory. To determine when V8 is done with the memory, we
54// open a weak handle to the ArrayBuffer object. When we receive the weak
55// callback, we know the object is about to be garbage collected and we can
56// drop V8's implied reference to the memory.
57//
[email protected]e87f3122013-11-12 00:41:2758// The final subtlety is that we need every ArrayBuffer into the same array
59// buffer to AddRef the same ArrayBuffer::Private. To make that work, we store
60// a pointer to the ArrayBuffer::Private object in an internal field of the
[email protected]a22998a2013-11-10 05:00:5061// ArrayBuffer object.
62//
[email protected]855ab432013-11-18 17:09:3663class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> {
[email protected]a22998a2013-11-10 05:00:5064 public:
65 static scoped_refptr<Private> From(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4866 v8::Local<v8::ArrayBuffer> array);
[email protected]a22998a2013-11-10 05:00:5067
[email protected]a22998a2013-11-10 05:00:5068 void* buffer() const { return buffer_; }
69 size_t length() const { return length_; }
70
71 private:
[email protected]855ab432013-11-18 17:09:3672 friend class base::RefCounted<Private>;
73
deepak.sfaaa1b62015-04-30 07:30:4874 Private(v8::Isolate* isolate, v8::Local<v8::ArrayBuffer> array);
[email protected]a22998a2013-11-10 05:00:5075 ~Private();
76
dcarney99ade9082015-04-22 09:55:4277 static void FirstWeakCallback(const v8::WeakCallbackInfo<Private>& data);
78 static void SecondWeakCallback(const v8::WeakCallbackInfo<Private>& data);
[email protected]a22998a2013-11-10 05:00:5079
dcarney99ade9082015-04-22 09:55:4280 v8::Global<v8::ArrayBuffer> array_buffer_;
[email protected]855ab432013-11-18 17:09:3681 scoped_refptr<Private> self_reference_;
[email protected]73dcce92014-02-20 08:24:0482 v8::Isolate* isolate_;
[email protected]a22998a2013-11-10 05:00:5083 void* buffer_;
84 size_t length_;
85};
86
[email protected]e87f3122013-11-12 00:41:2787scoped_refptr<ArrayBuffer::Private> ArrayBuffer::Private::From(
deepak.sfaaa1b62015-04-30 07:30:4888 v8::Isolate* isolate, v8::Local<v8::ArrayBuffer> array) {
[email protected]a22998a2013-11-10 05:00:5089 if (array->IsExternal()) {
deepak.sfaaa1b62015-04-30 07:30:4890 CHECK_EQ(WrapperInfo::From(v8::Local<v8::Object>::Cast(array)),
[email protected]73dcce92014-02-20 08:24:0491 &g_array_buffer_wrapper_info)
92 << "Cannot mix blink and gin ArrayBuffers";
[email protected]a22998a2013-11-10 05:00:5093 return make_scoped_refptr(static_cast<Private*>(
[email protected]73dcce92014-02-20 08:24:0494 array->GetAlignedPointerFromInternalField(kEncodedValueIndex)));
[email protected]a22998a2013-11-10 05:00:5095 }
96 return make_scoped_refptr(new Private(isolate, array));
97}
98
[email protected]e87f3122013-11-12 00:41:2799ArrayBuffer::Private::Private(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48100 v8::Local<v8::ArrayBuffer> array)
[email protected]73dcce92014-02-20 08:24:04101 : array_buffer_(isolate, array), isolate_(isolate) {
[email protected]a22998a2013-11-10 05:00:50102 // Take ownership of the array buffer.
[email protected]73dcce92014-02-20 08:24:04103 CHECK(!array->IsExternal());
[email protected]a22998a2013-11-10 05:00:50104 v8::ArrayBuffer::Contents contents = array->Externalize();
105 buffer_ = contents.Data();
106 length_ = contents.ByteLength();
107
[email protected]73dcce92014-02-20 08:24:04108 array->SetAlignedPointerInInternalField(kWrapperInfoIndex,
109 &g_array_buffer_wrapper_info);
110 array->SetAlignedPointerInInternalField(kEncodedValueIndex, this);
[email protected]a22998a2013-11-10 05:00:50111
dcarney99ade9082015-04-22 09:55:42112 self_reference_ = this; // Cleared in SecondWeakCallback.
113 array_buffer_.SetWeak(this, FirstWeakCallback,
114 v8::WeakCallbackType::kParameter);
[email protected]a22998a2013-11-10 05:00:50115}
116
[email protected]e87f3122013-11-12 00:41:27117ArrayBuffer::Private::~Private() {
[email protected]73dcce92014-02-20 08:24:04118 PerIsolateData::From(isolate_)->allocator()->Free(buffer_, length_);
[email protected]a22998a2013-11-10 05:00:50119}
120
dcarney99ade9082015-04-22 09:55:42121void ArrayBuffer::Private::FirstWeakCallback(
122 const v8::WeakCallbackInfo<Private>& data) {
[email protected]a22998a2013-11-10 05:00:50123 Private* parameter = data.GetParameter();
124 parameter->array_buffer_.Reset();
dcarney99ade9082015-04-22 09:55:42125 data.SetSecondPassCallback(SecondWeakCallback);
126}
127
128void ArrayBuffer::Private::SecondWeakCallback(
129 const v8::WeakCallbackInfo<Private>& data) {
130 Private* parameter = data.GetParameter();
[email protected]93f9f3602013-11-21 18:38:51131 parameter->self_reference_ = NULL;
[email protected]a22998a2013-11-10 05:00:50132}
133
[email protected]e87f3122013-11-12 00:41:27134// ArrayBuffer ----------------------------------------------------------------
[email protected]a22998a2013-11-10 05:00:50135
[email protected]7618ebbb2013-11-27 03:38:26136ArrayBuffer::ArrayBuffer()
137 : bytes_(0),
[email protected]e87f3122013-11-12 00:41:27138 num_bytes_(0) {
[email protected]a22998a2013-11-10 05:00:50139}
140
[email protected]e87f3122013-11-12 00:41:27141ArrayBuffer::ArrayBuffer(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48142 v8::Local<v8::ArrayBuffer> array) {
[email protected]7618ebbb2013-11-27 03:38:26143 private_ = ArrayBuffer::Private::From(isolate, array);
[email protected]a22998a2013-11-10 05:00:50144 bytes_ = private_->buffer();
145 num_bytes_ = private_->length();
146}
147
[email protected]e87f3122013-11-12 00:41:27148ArrayBuffer::~ArrayBuffer() {
149}
150
[email protected]48c21632013-12-12 21:32:34151ArrayBuffer& ArrayBuffer::operator=(const ArrayBuffer& other) {
152 private_ = other.private_;
153 bytes_ = other.bytes_;
154 num_bytes_ = other.num_bytes_;
155 return *this;
156}
157
[email protected]e87f3122013-11-12 00:41:27158// Converter<ArrayBuffer> -----------------------------------------------------
159
[email protected]7618ebbb2013-11-27 03:38:26160bool Converter<ArrayBuffer>::FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48161 v8::Local<v8::Value> val,
[email protected]e87f3122013-11-12 00:41:27162 ArrayBuffer* out) {
163 if (!val->IsArrayBuffer())
164 return false;
deepak.sfaaa1b62015-04-30 07:30:48165 *out = ArrayBuffer(isolate, v8::Local<v8::ArrayBuffer>::Cast(val));
[email protected]e87f3122013-11-12 00:41:27166 return true;
167}
168
169// ArrayBufferView ------------------------------------------------------------
170
[email protected]7618ebbb2013-11-27 03:38:26171ArrayBufferView::ArrayBufferView()
172 : offset_(0),
[email protected]e87f3122013-11-12 00:41:27173 num_bytes_(0) {
174}
175
176ArrayBufferView::ArrayBufferView(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48177 v8::Local<v8::ArrayBufferView> view)
[email protected]e87f3122013-11-12 00:41:27178 : array_buffer_(isolate, view->Buffer()),
179 offset_(view->ByteOffset()),
180 num_bytes_(view->ByteLength()) {
181}
182
183ArrayBufferView::~ArrayBufferView() {
184}
185
[email protected]dfc613d2014-05-16 13:16:52186ArrayBufferView& ArrayBufferView::operator=(const ArrayBufferView& other) {
187 array_buffer_ = other.array_buffer_;
188 offset_ = other.offset_;
189 num_bytes_ = other.num_bytes_;
190 return *this;
191}
192
193
[email protected]e87f3122013-11-12 00:41:27194// Converter<ArrayBufferView> -------------------------------------------------
195
[email protected]7618ebbb2013-11-27 03:38:26196bool Converter<ArrayBufferView>::FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48197 v8::Local<v8::Value> val,
[email protected]e87f3122013-11-12 00:41:27198 ArrayBufferView* out) {
199 if (!val->IsArrayBufferView())
200 return false;
deepak.sfaaa1b62015-04-30 07:30:48201 *out = ArrayBufferView(isolate, v8::Local<v8::ArrayBufferView>::Cast(val));
[email protected]e87f3122013-11-12 00:41:27202 return true;
203}
204
[email protected]a22998a2013-11-10 05:00:50205} // namespace gin