OLD | NEW |
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/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/factory.h" | 8 #include "src/factory.h" |
9 #include "src/messages.h" | 9 #include "src/messages.h" |
10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 | 31 |
32 if (source->was_neutered() || target->was_neutered()) { | 32 if (source->was_neutered() || target->was_neutered()) { |
33 THROW_NEW_ERROR_RETURN_FAILURE( | 33 THROW_NEW_ERROR_RETURN_FAILURE( |
34 isolate, NewTypeError(MessageTemplate::kDetachedOperation, | 34 isolate, NewTypeError(MessageTemplate::kDetachedOperation, |
35 isolate->factory()->NewStringFromAsciiChecked( | 35 isolate->factory()->NewStringFromAsciiChecked( |
36 "ArrayBuffer.prototype.slice"))); | 36 "ArrayBuffer.prototype.slice"))); |
37 } | 37 } |
38 | 38 |
39 CHECK(!source.is_identical_to(target)); | 39 CHECK(!source.is_identical_to(target)); |
40 size_t start = 0, target_length = 0; | 40 size_t start = 0, target_length = 0; |
41 CHECK(TryNumberToSize(isolate, *first, &start)); | 41 CHECK(TryNumberToSize(*first, &start)); |
42 CHECK(TryNumberToSize(isolate, *new_length, &target_length)); | 42 CHECK(TryNumberToSize(*new_length, &target_length)); |
43 CHECK(NumberToSize(isolate, target->byte_length()) >= target_length); | 43 CHECK(NumberToSize(target->byte_length()) >= target_length); |
44 | 44 |
45 if (target_length == 0) return isolate->heap()->undefined_value(); | 45 if (target_length == 0) return isolate->heap()->undefined_value(); |
46 | 46 |
47 size_t source_byte_length = NumberToSize(isolate, source->byte_length()); | 47 size_t source_byte_length = NumberToSize(source->byte_length()); |
48 CHECK(start <= source_byte_length); | 48 CHECK(start <= source_byte_length); |
49 CHECK(source_byte_length - start >= target_length); | 49 CHECK(source_byte_length - start >= target_length); |
50 uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store()); | 50 uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store()); |
51 uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store()); | 51 uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store()); |
52 CopyBytes(target_data, source_data + start, target_length); | 52 CopyBytes(target_data, source_data + start, target_length); |
53 return isolate->heap()->undefined_value(); | 53 return isolate->heap()->undefined_value(); |
54 } | 54 } |
55 | 55 |
56 | 56 |
57 RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) { | 57 RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) { |
58 HandleScope scope(isolate); | 58 HandleScope scope(isolate); |
59 DCHECK(args.length() == 1); | 59 DCHECK(args.length() == 1); |
60 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0); | 60 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0); |
61 if (array_buffer->backing_store() == NULL) { | 61 if (array_buffer->backing_store() == NULL) { |
62 CHECK(Smi::FromInt(0) == array_buffer->byte_length()); | 62 CHECK(Smi::FromInt(0) == array_buffer->byte_length()); |
63 return isolate->heap()->undefined_value(); | 63 return isolate->heap()->undefined_value(); |
64 } | 64 } |
65 // Shared array buffers should never be neutered. | 65 // Shared array buffers should never be neutered. |
66 CHECK(!array_buffer->is_shared()); | 66 CHECK(!array_buffer->is_shared()); |
67 DCHECK(!array_buffer->is_external()); | 67 DCHECK(!array_buffer->is_external()); |
68 void* backing_store = array_buffer->backing_store(); | 68 void* backing_store = array_buffer->backing_store(); |
69 size_t byte_length = NumberToSize(isolate, array_buffer->byte_length()); | 69 size_t byte_length = NumberToSize(array_buffer->byte_length()); |
70 array_buffer->set_is_external(true); | 70 array_buffer->set_is_external(true); |
71 isolate->heap()->UnregisterArrayBuffer(*array_buffer); | 71 isolate->heap()->UnregisterArrayBuffer(*array_buffer); |
72 array_buffer->Neuter(); | 72 array_buffer->Neuter(); |
73 isolate->array_buffer_allocator()->Free(backing_store, byte_length); | 73 isolate->array_buffer_allocator()->Free(backing_store, byte_length); |
74 return isolate->heap()->undefined_value(); | 74 return isolate->heap()->undefined_value(); |
75 } | 75 } |
76 | 76 |
77 | 77 |
78 void Runtime::ArrayIdToTypeAndSize(int arrayId, ExternalArrayType* array_type, | 78 void Runtime::ArrayIdToTypeAndSize(int arrayId, ExternalArrayType* array_type, |
79 ElementsKind* fixed_elements_kind, | 79 ElementsKind* fixed_elements_kind, |
(...skipping 30 matching lines...) Expand all Loading... |
110 | 110 |
111 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. | 111 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. |
112 size_t element_size = 1; // Bogus initialization. | 112 size_t element_size = 1; // Bogus initialization. |
113 ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization. | 113 ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization. |
114 Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind, | 114 Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind, |
115 &element_size); | 115 &element_size); |
116 CHECK(holder->map()->elements_kind() == fixed_elements_kind); | 116 CHECK(holder->map()->elements_kind() == fixed_elements_kind); |
117 | 117 |
118 size_t byte_offset = 0; | 118 size_t byte_offset = 0; |
119 size_t byte_length = 0; | 119 size_t byte_length = 0; |
120 CHECK(TryNumberToSize(isolate, *byte_offset_object, &byte_offset)); | 120 CHECK(TryNumberToSize(*byte_offset_object, &byte_offset)); |
121 CHECK(TryNumberToSize(isolate, *byte_length_object, &byte_length)); | 121 CHECK(TryNumberToSize(*byte_length_object, &byte_length)); |
122 | 122 |
123 if (maybe_buffer->IsJSArrayBuffer()) { | 123 if (maybe_buffer->IsJSArrayBuffer()) { |
124 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); | 124 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); |
125 size_t array_buffer_byte_length = | 125 size_t array_buffer_byte_length = NumberToSize(buffer->byte_length()); |
126 NumberToSize(isolate, buffer->byte_length()); | |
127 CHECK(byte_offset <= array_buffer_byte_length); | 126 CHECK(byte_offset <= array_buffer_byte_length); |
128 CHECK(array_buffer_byte_length - byte_offset >= byte_length); | 127 CHECK(array_buffer_byte_length - byte_offset >= byte_length); |
129 } else { | 128 } else { |
130 CHECK(maybe_buffer->IsNull(isolate)); | 129 CHECK(maybe_buffer->IsNull(isolate)); |
131 } | 130 } |
132 | 131 |
133 CHECK(byte_length % element_size == 0); | 132 CHECK(byte_length % element_size == 0); |
134 size_t length = byte_length / element_size; | 133 size_t length = byte_length / element_size; |
135 | 134 |
136 if (length > static_cast<unsigned>(Smi::kMaxValue)) { | 135 if (length > static_cast<unsigned>(Smi::kMaxValue)) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 | 196 |
198 CHECK(holder->map()->elements_kind() == fixed_elements_kind); | 197 CHECK(holder->map()->elements_kind() == fixed_elements_kind); |
199 | 198 |
200 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 199 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
201 size_t length = 0; | 200 size_t length = 0; |
202 if (source->IsJSTypedArray() && | 201 if (source->IsJSTypedArray() && |
203 JSTypedArray::cast(*source)->type() == array_type) { | 202 JSTypedArray::cast(*source)->type() == array_type) { |
204 length_obj = handle(JSTypedArray::cast(*source)->length(), isolate); | 203 length_obj = handle(JSTypedArray::cast(*source)->length(), isolate); |
205 length = JSTypedArray::cast(*source)->length_value(); | 204 length = JSTypedArray::cast(*source)->length_value(); |
206 } else { | 205 } else { |
207 CHECK(TryNumberToSize(isolate, *length_obj, &length)); | 206 CHECK(TryNumberToSize(*length_obj, &length)); |
208 } | 207 } |
209 | 208 |
210 if ((length > static_cast<unsigned>(Smi::kMaxValue)) || | 209 if ((length > static_cast<unsigned>(Smi::kMaxValue)) || |
211 (length > (kMaxInt / element_size))) { | 210 (length > (kMaxInt / element_size))) { |
212 THROW_NEW_ERROR_RETURN_FAILURE( | 211 THROW_NEW_ERROR_RETURN_FAILURE( |
213 isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayLength)); | 212 isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayLength)); |
214 } | 213 } |
215 size_t byte_length = length * element_size; | 214 size_t byte_length = length * element_size; |
216 | 215 |
217 DCHECK_EQ(v8::ArrayBufferView::kInternalFieldCount, | 216 DCHECK_EQ(v8::ArrayBufferView::kInternalFieldCount, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 static_cast<int>(length), array_type, | 253 static_cast<int>(length), array_type, |
255 static_cast<uint8_t*>(buffer->backing_store())); | 254 static_cast<uint8_t*>(buffer->backing_store())); |
256 holder->set_elements(*elements); | 255 holder->set_elements(*elements); |
257 | 256 |
258 if (source->IsJSTypedArray()) { | 257 if (source->IsJSTypedArray()) { |
259 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source)); | 258 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source)); |
260 | 259 |
261 if (typed_array->type() == holder->type()) { | 260 if (typed_array->type() == holder->type()) { |
262 uint8_t* backing_store = | 261 uint8_t* backing_store = |
263 static_cast<uint8_t*>(typed_array->GetBuffer()->backing_store()); | 262 static_cast<uint8_t*>(typed_array->GetBuffer()->backing_store()); |
264 size_t source_byte_offset = | 263 size_t source_byte_offset = NumberToSize(typed_array->byte_offset()); |
265 NumberToSize(isolate, typed_array->byte_offset()); | |
266 memcpy(buffer->backing_store(), backing_store + source_byte_offset, | 264 memcpy(buffer->backing_store(), backing_store + source_byte_offset, |
267 byte_length); | 265 byte_length); |
268 return isolate->heap()->true_value(); | 266 return isolate->heap()->true_value(); |
269 } | 267 } |
270 } | 268 } |
271 | 269 |
272 return isolate->heap()->false_value(); | 270 return isolate->heap()->false_value(); |
273 } | 271 } |
274 | 272 |
275 | 273 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 if (!args[1]->IsJSTypedArray()) | 319 if (!args[1]->IsJSTypedArray()) |
322 return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY); | 320 return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY); |
323 | 321 |
324 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0); | 322 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0); |
325 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1); | 323 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1); |
326 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset_obj, 2); | 324 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset_obj, 2); |
327 | 325 |
328 Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj)); | 326 Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj)); |
329 Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj)); | 327 Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj)); |
330 size_t offset = 0; | 328 size_t offset = 0; |
331 CHECK(TryNumberToSize(isolate, *offset_obj, &offset)); | 329 CHECK(TryNumberToSize(*offset_obj, &offset)); |
332 size_t target_length = target->length_value(); | 330 size_t target_length = target->length_value(); |
333 size_t source_length = source->length_value(); | 331 size_t source_length = source->length_value(); |
334 size_t target_byte_length = NumberToSize(isolate, target->byte_length()); | 332 size_t target_byte_length = NumberToSize(target->byte_length()); |
335 size_t source_byte_length = NumberToSize(isolate, source->byte_length()); | 333 size_t source_byte_length = NumberToSize(source->byte_length()); |
336 if (offset > target_length || offset + source_length > target_length || | 334 if (offset > target_length || offset + source_length > target_length || |
337 offset + source_length < offset) { // overflow | 335 offset + source_length < offset) { // overflow |
338 THROW_NEW_ERROR_RETURN_FAILURE( | 336 THROW_NEW_ERROR_RETURN_FAILURE( |
339 isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge)); | 337 isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge)); |
340 } | 338 } |
341 | 339 |
342 size_t target_offset = NumberToSize(isolate, target->byte_offset()); | 340 size_t target_offset = NumberToSize(target->byte_offset()); |
343 size_t source_offset = NumberToSize(isolate, source->byte_offset()); | 341 size_t source_offset = NumberToSize(source->byte_offset()); |
344 uint8_t* target_base = | 342 uint8_t* target_base = |
345 static_cast<uint8_t*>(target->GetBuffer()->backing_store()) + | 343 static_cast<uint8_t*>(target->GetBuffer()->backing_store()) + |
346 target_offset; | 344 target_offset; |
347 uint8_t* source_base = | 345 uint8_t* source_base = |
348 static_cast<uint8_t*>(source->GetBuffer()->backing_store()) + | 346 static_cast<uint8_t*>(source->GetBuffer()->backing_store()) + |
349 source_offset; | 347 source_offset; |
350 | 348 |
351 // Typed arrays of the same type: use memmove. | 349 // Typed arrays of the same type: use memmove. |
352 if (target->type() == source->type()) { | 350 if (target->type() == source->type()) { |
353 memmove(target_base + offset * target->element_size(), source_base, | 351 memmove(target_base + offset * target->element_size(), source_base, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 } | 445 } |
448 } | 446 } |
449 | 447 |
450 | 448 |
451 template <typename T> | 449 template <typename T> |
452 inline static bool DataViewGetValue(Isolate* isolate, | 450 inline static bool DataViewGetValue(Isolate* isolate, |
453 Handle<JSDataView> data_view, | 451 Handle<JSDataView> data_view, |
454 Handle<Object> byte_offset_obj, | 452 Handle<Object> byte_offset_obj, |
455 bool is_little_endian, T* result) { | 453 bool is_little_endian, T* result) { |
456 size_t byte_offset = 0; | 454 size_t byte_offset = 0; |
457 if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) { | 455 if (!TryNumberToSize(*byte_offset_obj, &byte_offset)) { |
458 return false; | 456 return false; |
459 } | 457 } |
460 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); | 458 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); |
461 | 459 |
462 size_t data_view_byte_offset = | 460 size_t data_view_byte_offset = NumberToSize(data_view->byte_offset()); |
463 NumberToSize(isolate, data_view->byte_offset()); | 461 size_t data_view_byte_length = NumberToSize(data_view->byte_length()); |
464 size_t data_view_byte_length = | |
465 NumberToSize(isolate, data_view->byte_length()); | |
466 if (byte_offset + sizeof(T) > data_view_byte_length || | 462 if (byte_offset + sizeof(T) > data_view_byte_length || |
467 byte_offset + sizeof(T) < byte_offset) { // overflow | 463 byte_offset + sizeof(T) < byte_offset) { // overflow |
468 return false; | 464 return false; |
469 } | 465 } |
470 | 466 |
471 union Value { | 467 union Value { |
472 T data; | 468 T data; |
473 uint8_t bytes[sizeof(T)]; | 469 uint8_t bytes[sizeof(T)]; |
474 }; | 470 }; |
475 | 471 |
476 Value value; | 472 Value value; |
477 size_t buffer_offset = data_view_byte_offset + byte_offset; | 473 size_t buffer_offset = data_view_byte_offset + byte_offset; |
478 DCHECK(NumberToSize(isolate, buffer->byte_length()) >= | 474 DCHECK(NumberToSize(buffer->byte_length()) >= buffer_offset + sizeof(T)); |
479 buffer_offset + sizeof(T)); | |
480 uint8_t* source = | 475 uint8_t* source = |
481 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; | 476 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; |
482 if (NeedToFlipBytes(is_little_endian)) { | 477 if (NeedToFlipBytes(is_little_endian)) { |
483 FlipBytes<sizeof(T)>(value.bytes, source); | 478 FlipBytes<sizeof(T)>(value.bytes, source); |
484 } else { | 479 } else { |
485 CopyBytes<sizeof(T)>(value.bytes, source); | 480 CopyBytes<sizeof(T)>(value.bytes, source); |
486 } | 481 } |
487 *result = value.data; | 482 *result = value.data; |
488 return true; | 483 return true; |
489 } | 484 } |
490 | 485 |
491 | 486 |
492 template <typename T> | 487 template <typename T> |
493 static bool DataViewSetValue(Isolate* isolate, Handle<JSDataView> data_view, | 488 static bool DataViewSetValue(Isolate* isolate, Handle<JSDataView> data_view, |
494 Handle<Object> byte_offset_obj, | 489 Handle<Object> byte_offset_obj, |
495 bool is_little_endian, T data) { | 490 bool is_little_endian, T data) { |
496 size_t byte_offset = 0; | 491 size_t byte_offset = 0; |
497 if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) { | 492 if (!TryNumberToSize(*byte_offset_obj, &byte_offset)) { |
498 return false; | 493 return false; |
499 } | 494 } |
500 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); | 495 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); |
501 | 496 |
502 size_t data_view_byte_offset = | 497 size_t data_view_byte_offset = NumberToSize(data_view->byte_offset()); |
503 NumberToSize(isolate, data_view->byte_offset()); | 498 size_t data_view_byte_length = NumberToSize(data_view->byte_length()); |
504 size_t data_view_byte_length = | |
505 NumberToSize(isolate, data_view->byte_length()); | |
506 if (byte_offset + sizeof(T) > data_view_byte_length || | 499 if (byte_offset + sizeof(T) > data_view_byte_length || |
507 byte_offset + sizeof(T) < byte_offset) { // overflow | 500 byte_offset + sizeof(T) < byte_offset) { // overflow |
508 return false; | 501 return false; |
509 } | 502 } |
510 | 503 |
511 union Value { | 504 union Value { |
512 T data; | 505 T data; |
513 uint8_t bytes[sizeof(T)]; | 506 uint8_t bytes[sizeof(T)]; |
514 }; | 507 }; |
515 | 508 |
516 Value value; | 509 Value value; |
517 value.data = data; | 510 value.data = data; |
518 size_t buffer_offset = data_view_byte_offset + byte_offset; | 511 size_t buffer_offset = data_view_byte_offset + byte_offset; |
519 DCHECK(NumberToSize(isolate, buffer->byte_length()) >= | 512 DCHECK(NumberToSize(buffer->byte_length()) >= buffer_offset + sizeof(T)); |
520 buffer_offset + sizeof(T)); | |
521 uint8_t* target = | 513 uint8_t* target = |
522 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; | 514 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; |
523 if (NeedToFlipBytes(is_little_endian)) { | 515 if (NeedToFlipBytes(is_little_endian)) { |
524 FlipBytes<sizeof(T)>(target, value.bytes); | 516 FlipBytes<sizeof(T)>(target, value.bytes); |
525 } else { | 517 } else { |
526 CopyBytes<sizeof(T)>(target, value.bytes); | 518 CopyBytes<sizeof(T)>(target, value.bytes); |
527 } | 519 } |
528 return true; | 520 return true; |
529 } | 521 } |
530 | 522 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 DATA_VIEW_SETTER(Uint16, uint16_t) | 626 DATA_VIEW_SETTER(Uint16, uint16_t) |
635 DATA_VIEW_SETTER(Int16, int16_t) | 627 DATA_VIEW_SETTER(Int16, int16_t) |
636 DATA_VIEW_SETTER(Uint32, uint32_t) | 628 DATA_VIEW_SETTER(Uint32, uint32_t) |
637 DATA_VIEW_SETTER(Int32, int32_t) | 629 DATA_VIEW_SETTER(Int32, int32_t) |
638 DATA_VIEW_SETTER(Float32, float) | 630 DATA_VIEW_SETTER(Float32, float) |
639 DATA_VIEW_SETTER(Float64, double) | 631 DATA_VIEW_SETTER(Float64, double) |
640 | 632 |
641 #undef DATA_VIEW_SETTER | 633 #undef DATA_VIEW_SETTER |
642 } // namespace internal | 634 } // namespace internal |
643 } // namespace v8 | 635 } // namespace v8 |
OLD | NEW |