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

Side by Side Diff: src/runtime/runtime-typedarray.cc

Issue 1069883002: WIP SharedArrayBuffer implementation (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months 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
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/runtime/runtime.h" 8 #include "src/runtime/runtime.h"
9 #include "src/runtime/runtime-utils.h" 9 #include "src/runtime/runtime-utils.h"
10 10
11 11
12 namespace v8 { 12 namespace v8 {
13 namespace internal { 13 namespace internal {
14 14
15 void Runtime::FreeArrayBuffer(Isolate* isolate, 15 void Runtime::FreeArrayBuffer(Isolate* isolate,
16 JSArrayBuffer* phantom_array_buffer) { 16 JSArrayBuffer* phantom_array_buffer) {
17 if (phantom_array_buffer->should_be_freed()) { 17 if (phantom_array_buffer->should_be_freed()) {
18 DCHECK(phantom_array_buffer->is_external()); 18 DCHECK(phantom_array_buffer->is_external());
19 free(phantom_array_buffer->backing_store()); 19 free(phantom_array_buffer->backing_store());
20 } 20 }
21 if (phantom_array_buffer->is_external()) return; 21 if (phantom_array_buffer->is_external()) return;
22 22
23 size_t allocated_length = 23 size_t allocated_length =
24 NumberToSize(isolate, phantom_array_buffer->byte_length()); 24 NumberToSize(isolate, phantom_array_buffer->byte_length());
25 25
26 reinterpret_cast<v8::Isolate*>(isolate) 26 reinterpret_cast<v8::Isolate*>(isolate)
27 ->AdjustAmountOfExternalAllocatedMemory( 27 ->AdjustAmountOfExternalAllocatedMemory(
28 -static_cast<int64_t>(allocated_length)); 28 -static_cast<int64_t>(allocated_length));
29 CHECK(V8::ArrayBufferAllocator() != NULL); 29 if (phantom_array_buffer->is_shared()) {
30 V8::ArrayBufferAllocator()->Free(phantom_array_buffer->backing_store(), 30 CHECK(V8::SharedArrayBufferAllocator() != NULL);
31 allocated_length); 31 V8::SharedArrayBufferAllocator()->Free(
32 phantom_array_buffer->backing_store(), allocated_length);
33 } else {
34 CHECK(V8::ArrayBufferAllocator() != NULL);
35 V8::ArrayBufferAllocator()->Free(phantom_array_buffer->backing_store(),
36 allocated_length);
37 }
32 } 38 }
33 39
34 40
35 void Runtime::SetupArrayBuffer(Isolate* isolate, 41 void Runtime::SetupArrayBuffer(Isolate* isolate,
36 Handle<JSArrayBuffer> array_buffer, 42 Handle<JSArrayBuffer> array_buffer,
37 bool is_external, void* data, 43 bool is_external, void* data,
38 size_t allocated_length) { 44 size_t allocated_length, bool is_shared) {
39 DCHECK(array_buffer->GetInternalFieldCount() == 45 DCHECK(array_buffer->GetInternalFieldCount() ==
40 v8::ArrayBuffer::kInternalFieldCount); 46 v8::ArrayBuffer::kInternalFieldCount);
41 for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) { 47 for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
42 array_buffer->SetInternalField(i, Smi::FromInt(0)); 48 array_buffer->SetInternalField(i, Smi::FromInt(0));
43 } 49 }
44 array_buffer->set_backing_store(data); 50 array_buffer->set_backing_store(data);
45 array_buffer->set_flag(Smi::FromInt(0)); 51 array_buffer->set_flag(Smi::FromInt(0));
46 array_buffer->set_is_external(is_external); 52 array_buffer->set_is_external(is_external);
47 array_buffer->set_is_neuterable(true); 53 array_buffer->set_is_neuterable(true);
54 array_buffer->set_is_shared(is_shared);
48 55
49 Handle<Object> byte_length = 56 Handle<Object> byte_length =
50 isolate->factory()->NewNumberFromSize(allocated_length); 57 isolate->factory()->NewNumberFromSize(allocated_length);
51 CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber()); 58 CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
52 array_buffer->set_byte_length(*byte_length); 59 array_buffer->set_byte_length(*byte_length);
53 60
54 array_buffer->set_weak_next(isolate->heap()->array_buffers_list()); 61 array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
55 isolate->heap()->set_array_buffers_list(*array_buffer); 62 isolate->heap()->set_array_buffers_list(*array_buffer);
56 array_buffer->set_weak_first_view(isolate->heap()->undefined_value()); 63 array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
57 } 64 }
58 65
59 66
60 bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate, 67 bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate,
61 Handle<JSArrayBuffer> array_buffer, 68 Handle<JSArrayBuffer> array_buffer,
62 size_t allocated_length, 69 size_t allocated_length,
63 bool initialize) { 70 bool initialize, bool is_shared) {
64 void* data; 71 void* data;
65 CHECK(V8::ArrayBufferAllocator() != NULL); 72 CHECK(is_shared ? V8::SharedArrayBufferAllocator() != NULL
73 : V8::ArrayBufferAllocator() != NULL);
66 // Prevent creating array buffers when serializing. 74 // Prevent creating array buffers when serializing.
67 DCHECK(!isolate->serializer_enabled()); 75 DCHECK(!isolate->serializer_enabled());
68 if (allocated_length != 0) { 76 if (allocated_length != 0) {
69 if (initialize) { 77 if (is_shared) {
70 data = V8::ArrayBufferAllocator()->Allocate(allocated_length); 78 if (initialize) {
79 data = V8::SharedArrayBufferAllocator()->Allocate(allocated_length);
80 } else {
81 data = V8::SharedArrayBufferAllocator()->AllocateUninitialized(
82 allocated_length);
83 }
71 } else { 84 } else {
72 data = 85 if (initialize) {
73 V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length); 86 data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
87 } else {
88 data =
89 V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
90 }
74 } 91 }
75 if (data == NULL) return false; 92 if (data == NULL) return false;
76 } else { 93 } else {
77 data = NULL; 94 data = NULL;
78 } 95 }
79 96
80 SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length); 97 SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length,
98 is_shared);
81 99
82 reinterpret_cast<v8::Isolate*>(isolate) 100 reinterpret_cast<v8::Isolate*>(isolate)
83 ->AdjustAmountOfExternalAllocatedMemory(allocated_length); 101 ->AdjustAmountOfExternalAllocatedMemory(allocated_length);
84 102
85 return true; 103 return true;
86 } 104 }
87 105
88 106
89 void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) { 107 void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
90 Isolate* isolate = array_buffer->GetIsolate(); 108 Isolate* isolate = array_buffer->GetIsolate();
(...skipping 28 matching lines...) Expand all
119 } 137 }
120 } 138 }
121 view_obj = handle(view->weak_next(), isolate); 139 view_obj = handle(view->weak_next(), isolate);
122 } 140 }
123 array_buffer->Neuter(); 141 array_buffer->Neuter();
124 } 142 }
125 143
126 144
127 RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) { 145 RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) {
128 HandleScope scope(isolate); 146 HandleScope scope(isolate);
129 DCHECK(args.length() == 2); 147 DCHECK(args.length() == 3);
130 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0); 148 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
131 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1); 149 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1);
150 CONVERT_BOOLEAN_ARG_CHECKED(isShared, 2);
132 if (!holder->byte_length()->IsUndefined()) { 151 if (!holder->byte_length()->IsUndefined()) {
133 // ArrayBuffer is already initialized; probably a fuzz test. 152 // ArrayBuffer is already initialized; probably a fuzz test.
134 return *holder; 153 return *holder;
135 } 154 }
136 size_t allocated_length = 0; 155 size_t allocated_length = 0;
137 if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) { 156 if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) {
138 THROW_NEW_ERROR_RETURN_FAILURE( 157 THROW_NEW_ERROR_RETURN_FAILURE(
139 isolate, NewRangeError("invalid_array_buffer_length", 158 isolate, NewRangeError("invalid_array_buffer_length",
140 HandleVector<Object>(NULL, 0))); 159 HandleVector<Object>(NULL, 0)));
141 } 160 }
142 if (!Runtime::SetupArrayBufferAllocatingData(isolate, holder, 161 if (!Runtime::SetupArrayBufferAllocatingData(
143 allocated_length)) { 162 isolate, holder, allocated_length, true, isShared)) {
144 THROW_NEW_ERROR_RETURN_FAILURE( 163 THROW_NEW_ERROR_RETURN_FAILURE(
145 isolate, NewRangeError("invalid_array_buffer_length", 164 isolate, NewRangeError("invalid_array_buffer_length",
146 HandleVector<Object>(NULL, 0))); 165 HandleVector<Object>(NULL, 0)));
147 } 166 }
148 return *holder; 167 return *holder;
149 } 168 }
150 169
151 170
152 RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) { 171 RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
153 SealHandleScope shs(isolate); 172 SealHandleScope shs(isolate);
154 DCHECK(args.length() == 1); 173 DCHECK(args.length() == 1);
155 CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0); 174 CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
156 return holder->byte_length(); 175 return holder->byte_length();
157 } 176 }
158 177
159 178
179 RUNTIME_FUNCTION(Runtime_ArrayBufferIsShared) {
180 SealHandleScope shs(isolate);
181 DCHECK(args.length() == 1);
182 CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
183 return isolate->heap()->ToBoolean(holder->is_shared());
184 }
185
186
160 RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) { 187 RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
161 HandleScope scope(isolate); 188 HandleScope scope(isolate);
162 DCHECK(args.length() == 3); 189 DCHECK(args.length() == 3);
163 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0); 190 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
164 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1); 191 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
165 CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2); 192 CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
166 RUNTIME_ASSERT(!source.is_identical_to(target)); 193 RUNTIME_ASSERT(!source.is_identical_to(target));
167 size_t start = 0; 194 size_t start = 0;
168 RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start)); 195 RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
169 size_t target_length = NumberToSize(isolate, target->byte_length()); 196 size_t target_length = NumberToSize(isolate, target->byte_length());
(...skipping 19 matching lines...) Expand all
189 216
190 217
191 RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) { 218 RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
192 HandleScope scope(isolate); 219 HandleScope scope(isolate);
193 DCHECK(args.length() == 1); 220 DCHECK(args.length() == 1);
194 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0); 221 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
195 if (array_buffer->backing_store() == NULL) { 222 if (array_buffer->backing_store() == NULL) {
196 CHECK(Smi::FromInt(0) == array_buffer->byte_length()); 223 CHECK(Smi::FromInt(0) == array_buffer->byte_length());
197 return isolate->heap()->undefined_value(); 224 return isolate->heap()->undefined_value();
198 } 225 }
226 // Shared array buffers should never be neutered.
227 DCHECK(!array_buffer->is_shared());
199 DCHECK(!array_buffer->is_external()); 228 DCHECK(!array_buffer->is_external());
200 void* backing_store = array_buffer->backing_store(); 229 void* backing_store = array_buffer->backing_store();
201 size_t byte_length = NumberToSize(isolate, array_buffer->byte_length()); 230 size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
202 array_buffer->set_is_external(true); 231 array_buffer->set_is_external(true);
203 Runtime::NeuterArrayBuffer(array_buffer); 232 Runtime::NeuterArrayBuffer(array_buffer);
204 V8::ArrayBufferAllocator()->Free(backing_store, byte_length); 233 V8::ArrayBufferAllocator()->Free(backing_store, byte_length);
205 return isolate->heap()->undefined_value(); 234 return isolate->heap()->undefined_value();
206 } 235 }
207 236
208 237
(...skipping 14 matching lines...) Expand all
223 #undef ARRAY_ID_CASE 252 #undef ARRAY_ID_CASE
224 253
225 default: 254 default:
226 UNREACHABLE(); 255 UNREACHABLE();
227 } 256 }
228 } 257 }
229 258
230 259
231 RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { 260 RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
232 HandleScope scope(isolate); 261 HandleScope scope(isolate);
233 DCHECK(args.length() == 5); 262 DCHECK(args.length() == 6);
234 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); 263 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
235 CONVERT_SMI_ARG_CHECKED(arrayId, 1); 264 CONVERT_SMI_ARG_CHECKED(arrayId, 1);
236 CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2); 265 CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
237 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3); 266 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3);
238 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4); 267 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
268 CONVERT_BOOLEAN_ARG_CHECKED(isShared, 5);
239 269
240 RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST && 270 RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
241 arrayId <= Runtime::ARRAY_ID_LAST); 271 arrayId <= Runtime::ARRAY_ID_LAST);
242 272
243 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. 273 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
244 size_t element_size = 1; // Bogus initialization. 274 size_t element_size = 1; // Bogus initialization.
245 ElementsKind external_elements_kind = 275 ElementsKind external_elements_kind =
246 EXTERNAL_INT8_ELEMENTS; // Bogus initialization. 276 EXTERNAL_INT8_ELEMENTS; // Bogus initialization.
247 ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization. 277 ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
248 Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind, 278 Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind,
249 &fixed_elements_kind, &element_size); 279 &fixed_elements_kind, &element_size);
250 RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind); 280 RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
251 281
252 size_t byte_offset = 0; 282 size_t byte_offset = 0;
253 size_t byte_length = 0; 283 size_t byte_length = 0;
254 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset)); 284 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset));
255 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length)); 285 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length));
256 286
257 if (maybe_buffer->IsJSArrayBuffer()) { 287 if (maybe_buffer->IsJSArrayBuffer()) {
258 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); 288 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
259 size_t array_buffer_byte_length = 289 size_t array_buffer_byte_length =
260 NumberToSize(isolate, buffer->byte_length()); 290 NumberToSize(isolate, buffer->byte_length());
261 RUNTIME_ASSERT(byte_offset <= array_buffer_byte_length); 291 RUNTIME_ASSERT(byte_offset <= array_buffer_byte_length);
262 RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length); 292 RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length);
293 RUNTIME_ASSERT(isShared == buffer->is_shared());
263 } else { 294 } else {
264 RUNTIME_ASSERT(maybe_buffer->IsNull()); 295 RUNTIME_ASSERT(maybe_buffer->IsNull());
265 } 296 }
266 297
267 RUNTIME_ASSERT(byte_length % element_size == 0); 298 RUNTIME_ASSERT(byte_length % element_size == 0);
268 size_t length = byte_length / element_size; 299 size_t length = byte_length / element_size;
269 300
270 if (length > static_cast<unsigned>(Smi::kMaxValue)) { 301 if (length > static_cast<unsigned>(Smi::kMaxValue)) {
271 THROW_NEW_ERROR_RETURN_FAILURE( 302 THROW_NEW_ERROR_RETURN_FAILURE(
272 isolate, NewRangeError("invalid_typed_array_length", 303 isolate, NewRangeError("invalid_typed_array_length",
273 HandleVector<Object>(NULL, 0))); 304 HandleVector<Object>(NULL, 0)));
274 } 305 }
275 306
276 // All checks are done, now we can modify objects. 307 // All checks are done, now we can modify objects.
277 308
278 DCHECK(holder->GetInternalFieldCount() == 309 DCHECK(holder->GetInternalFieldCount() ==
279 v8::ArrayBufferView::kInternalFieldCount); 310 v8::ArrayBufferView::kInternalFieldCount);
280 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { 311 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
281 holder->SetInternalField(i, Smi::FromInt(0)); 312 holder->SetInternalField(i, Smi::FromInt(0));
282 } 313 }
283 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); 314 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
284 holder->set_length(*length_obj); 315 holder->set_length(*length_obj);
285 holder->set_byte_offset(*byte_offset_object); 316 holder->set_byte_offset(*byte_offset_object);
286 holder->set_byte_length(*byte_length_object); 317 holder->set_byte_length(*byte_length_object);
318 holder->set_is_shared(isShared);
287 319
288 Heap* heap = isolate->heap(); 320 Heap* heap = isolate->heap();
289 if (!maybe_buffer->IsNull()) { 321 if (!maybe_buffer->IsNull()) {
290 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); 322 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
291 holder->set_buffer(*buffer); 323 holder->set_buffer(*buffer);
292 324
293 if (heap->InNewSpace(*holder)) { 325 if (heap->InNewSpace(*holder)) {
294 holder->set_weak_next(heap->new_array_buffer_views_list()); 326 holder->set_weak_next(heap->new_array_buffer_views_list());
295 heap->set_new_array_buffer_views_list(*holder); 327 heap->set_new_array_buffer_views_list(*holder);
296 } else { 328 } else {
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 DATA_VIEW_SETTER(Uint16, uint16_t) 833 DATA_VIEW_SETTER(Uint16, uint16_t)
802 DATA_VIEW_SETTER(Int16, int16_t) 834 DATA_VIEW_SETTER(Int16, int16_t)
803 DATA_VIEW_SETTER(Uint32, uint32_t) 835 DATA_VIEW_SETTER(Uint32, uint32_t)
804 DATA_VIEW_SETTER(Int32, int32_t) 836 DATA_VIEW_SETTER(Int32, int32_t)
805 DATA_VIEW_SETTER(Float32, float) 837 DATA_VIEW_SETTER(Float32, float)
806 DATA_VIEW_SETTER(Float64, double) 838 DATA_VIEW_SETTER(Float64, double)
807 839
808 #undef DATA_VIEW_SETTER 840 #undef DATA_VIEW_SETTER
809 } 841 }
810 } // namespace v8::internal 842 } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/runtime/runtime.h ('k') | src/typedarray.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698