Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: mojo/public/bindings/js/v8_array_buffer.cc

Issue 59153005: Begin implementing V8 bindings for Mojo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: spelling Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // 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
5 #include "mojo/public/bindings/js/v8_array_buffer.h"
6
7 #include <stdlib.h>
8
9 namespace mojo {
10 namespace js {
11
12 MOJO_COMPILE_ASSERT(V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT == 2,
13 array_buffers_must_have_two_internal_fields);
14
15 static const int kBufferViewPrivateIndex = 0;
16
17 // ArrayBufferAllocator -------------------------------------------------------
18
19 void* ArrayBufferAllocator::Allocate(size_t length) {
20 return calloc(1, length);
21 }
22
23 void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
24 return malloc(length);
25 }
26
27 void ArrayBufferAllocator::Free(void* data, size_t length) {
28 free(data);
29 }
30
31 ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() {
32 static ArrayBufferAllocator* instance = new ArrayBufferAllocator();
33 return instance;
34 }
35
36 // BufferView::Private --------------------------------------------------------
37
38 // This class exists to solve a tricky lifetime problem. The V8 API doesn't
39 // want to expose a direct view into the memory behind an array buffer because
40 // V8 might deallocate that memory during garbage collection. Instead, the V8
41 // API forces us to externalize the buffer and take ownership of the memory.
42 // In order to know when to free the memory, we need to figure out both when
43 // we're done with it and when V8 is done with it.
44 //
45 // To determine whether we're done with the memory, every view we have into
46 // the array buffer takes a reference to the BufferView::Private object that
47 // actually owns the memory. To determine when V8 is done with the memory, we
48 // open a weak handle to the ArrayBuffer object. When we receive the weak
49 // callback, we know the object is about to be garbage collected and we can
50 // drop V8's implied reference to the memory.
51 //
52 // The final subtlety is that we need every BufferView into the same array
53 // buffer to AddRef the same BufferView::Private. To make that work, we store a
54 // pointer to the BufferView::Private object in an internal field of the
55 // ArrayBuffer object.
56 //
57 class BufferView::Private {
58 public:
59 static Private* From(v8::Isolate* isolate,
60 v8::Handle<v8::ArrayBuffer> array);
61
62 void AddRef();
63 void Release();
64
65 void* buffer() const { return buffer_; }
66 size_t length() const { return length_; }
67
68 private:
69 Private(v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array);
70 ~Private();
71
72 static void WeakCallback(
73 const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data);
74
75 size_t ref_count_;
76 v8::Persistent<v8::ArrayBuffer> array_buffer_;
77 void* buffer_;
78 size_t length_;
79 };
80
81 BufferView::Private* BufferView::Private::From(
82 v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array) {
83 if (array->IsExternal()) {
84 return static_cast<BufferView::Private*>(
85 array->GetAlignedPointerFromInternalField(kBufferViewPrivateIndex));
86 }
87 return new Private(isolate, array);
88 }
89
90 void BufferView::Private::AddRef() {
91 ++ref_count_;
92 }
93
94 void BufferView::Private::Release() {
95 --ref_count_;
96 if (ref_count_)
97 return;
98 ArrayBufferAllocator::SharedInstance()->Free(buffer_, length_);
99 delete this;
100 }
101
102 BufferView::Private::Private(v8::Isolate* isolate,
103 v8::Handle<v8::ArrayBuffer> array)
104 : ref_count_(0),
105 array_buffer_(isolate, array) {
106 // Take ownership of the array buffer.
107 v8::ArrayBuffer::Contents contents = array->Externalize();
108 buffer_ = contents.Data();
109 length_ = contents.ByteLength();
110
111 array->SetAlignedPointerInInternalField(kBufferViewPrivateIndex, this);
112
113 AddRef(); // Balanced in WeakCallback.
114 array_buffer_.SetWeak(this, WeakCallback);
115 }
116
117 BufferView::Private::~Private() {
118 }
119
120 void BufferView::Private::WeakCallback(
121 const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data) {
122 Private* parameter = data.GetParameter();
123 parameter->array_buffer_.Reset();
124 parameter->Release(); // Balanced in BufferView::Private::Private.
125 }
126
127 // BufferView -----------------------------------------------------------------
128
129 BufferView::BufferView(v8::Isolate* isolate,
130 v8::Handle<v8::ArrayBufferView> view) {
131 Initialize(isolate, view->Buffer());
132 uint8_t* ptr = static_cast<uint8_t*>(bytes_);
133 bytes_ = static_cast<void*>(ptr + view->ByteOffset());
134 num_bytes_ = view->ByteLength();
135 }
136
137 BufferView::BufferView(v8::Isolate* isolate,
138 v8::Handle<v8::ArrayBuffer> array) {
139 Initialize(isolate, array);
140 }
141
142 BufferView::~BufferView() {
143 private_->Release(); // Balanced in BufferView::Initialize.
144 }
145
146 void BufferView::Initialize(v8::Isolate* isolate,
147 v8::Handle<v8::ArrayBuffer> array) {
148 private_ = BufferView::Private::From(isolate, array);
149 private_->AddRef(); // Balanced in BufferView::~BufferView.
150 bytes_ = private_->buffer();
151 num_bytes_ = private_->length();
152 }
153
154 } // namespace js
155 } // mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698