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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/messages.h" | 8 #include "src/messages.h" |
9 #include "src/runtime/runtime.h" | 9 #include "src/runtime/runtime.h" |
10 #include "src/runtime/runtime-utils.h" | 10 #include "src/runtime/runtime-utils.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 DCHECK(args.length() == 2); | 73 DCHECK(args.length() == 2); |
74 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0); | 74 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0); |
75 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1); | 75 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1); |
76 if (!holder->byte_length()->IsUndefined()) { | 76 if (!holder->byte_length()->IsUndefined()) { |
77 // ArrayBuffer is already initialized; probably a fuzz test. | 77 // ArrayBuffer is already initialized; probably a fuzz test. |
78 return *holder; | 78 return *holder; |
79 } | 79 } |
80 size_t allocated_length = 0; | 80 size_t allocated_length = 0; |
81 if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) { | 81 if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) { |
82 THROW_NEW_ERROR_RETURN_FAILURE( | 82 THROW_NEW_ERROR_RETURN_FAILURE( |
83 isolate, NewRangeError("invalid_array_buffer_length", | 83 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength)); |
84 HandleVector<Object>(NULL, 0))); | |
85 } | 84 } |
86 if (!Runtime::SetupArrayBufferAllocatingData(isolate, holder, | 85 if (!Runtime::SetupArrayBufferAllocatingData(isolate, holder, |
87 allocated_length)) { | 86 allocated_length)) { |
88 THROW_NEW_ERROR_RETURN_FAILURE( | 87 THROW_NEW_ERROR_RETURN_FAILURE( |
89 isolate, NewRangeError("invalid_array_buffer_length", | 88 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength)); |
90 HandleVector<Object>(NULL, 0))); | |
91 } | 89 } |
92 return *holder; | 90 return *holder; |
93 } | 91 } |
94 | 92 |
95 | 93 |
96 RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) { | 94 RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) { |
97 SealHandleScope shs(isolate); | 95 SealHandleScope shs(isolate); |
98 DCHECK(args.length() == 1); | 96 DCHECK(args.length() == 1); |
99 CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0); | 97 CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0); |
100 return holder->byte_length(); | 98 return holder->byte_length(); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length); | 205 RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length); |
208 } else { | 206 } else { |
209 RUNTIME_ASSERT(maybe_buffer->IsNull()); | 207 RUNTIME_ASSERT(maybe_buffer->IsNull()); |
210 } | 208 } |
211 | 209 |
212 RUNTIME_ASSERT(byte_length % element_size == 0); | 210 RUNTIME_ASSERT(byte_length % element_size == 0); |
213 size_t length = byte_length / element_size; | 211 size_t length = byte_length / element_size; |
214 | 212 |
215 if (length > static_cast<unsigned>(Smi::kMaxValue)) { | 213 if (length > static_cast<unsigned>(Smi::kMaxValue)) { |
216 THROW_NEW_ERROR_RETURN_FAILURE( | 214 THROW_NEW_ERROR_RETURN_FAILURE( |
217 isolate, NewRangeError("invalid_typed_array_length", | 215 isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayLength)); |
218 HandleVector<Object>(NULL, 0))); | |
219 } | 216 } |
220 | 217 |
221 // All checks are done, now we can modify objects. | 218 // All checks are done, now we can modify objects. |
222 | 219 |
223 DCHECK(holder->GetInternalFieldCount() == | 220 DCHECK(holder->GetInternalFieldCount() == |
224 v8::ArrayBufferView::kInternalFieldCount); | 221 v8::ArrayBufferView::kInternalFieldCount); |
225 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | 222 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { |
226 holder->SetInternalField(i, Smi::FromInt(0)); | 223 holder->SetInternalField(i, Smi::FromInt(0)); |
227 } | 224 } |
228 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); | 225 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 if (source->IsJSTypedArray() && | 281 if (source->IsJSTypedArray() && |
285 JSTypedArray::cast(*source)->type() == array_type) { | 282 JSTypedArray::cast(*source)->type() == array_type) { |
286 length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate); | 283 length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate); |
287 } | 284 } |
288 size_t length = 0; | 285 size_t length = 0; |
289 RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length)); | 286 RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length)); |
290 | 287 |
291 if ((length > static_cast<unsigned>(Smi::kMaxValue)) || | 288 if ((length > static_cast<unsigned>(Smi::kMaxValue)) || |
292 (length > (kMaxInt / element_size))) { | 289 (length > (kMaxInt / element_size))) { |
293 THROW_NEW_ERROR_RETURN_FAILURE( | 290 THROW_NEW_ERROR_RETURN_FAILURE( |
294 isolate, NewRangeError("invalid_typed_array_length", | 291 isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayLength)); |
295 HandleVector<Object>(NULL, 0))); | |
296 } | 292 } |
297 size_t byte_length = length * element_size; | 293 size_t byte_length = length * element_size; |
298 | 294 |
299 DCHECK(holder->GetInternalFieldCount() == | 295 DCHECK(holder->GetInternalFieldCount() == |
300 v8::ArrayBufferView::kInternalFieldCount); | 296 v8::ArrayBufferView::kInternalFieldCount); |
301 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | 297 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { |
302 holder->SetInternalField(i, Smi::FromInt(0)); | 298 holder->SetInternalField(i, Smi::FromInt(0)); |
303 } | 299 } |
304 | 300 |
305 // NOTE: not initializing backing store. | 301 // NOTE: not initializing backing store. |
306 // We assume that the caller of this function will initialize holder | 302 // We assume that the caller of this function will initialize holder |
307 // with the loop | 303 // with the loop |
308 // for(i = 0; i < length; i++) { holder[i] = source[i]; } | 304 // for(i = 0; i < length; i++) { holder[i] = source[i]; } |
309 // We assume that the caller of this function is always a typed array | 305 // We assume that the caller of this function is always a typed array |
310 // constructor. | 306 // constructor. |
311 // If source is a typed array, this loop will always run to completion, | 307 // If source is a typed array, this loop will always run to completion, |
312 // so we are sure that the backing store will be initialized. | 308 // so we are sure that the backing store will be initialized. |
313 // Otherwise, the indexing operation might throw, so the loop will not | 309 // Otherwise, the indexing operation might throw, so the loop will not |
314 // run to completion and the typed array might remain partly initialized. | 310 // run to completion and the typed array might remain partly initialized. |
315 // However we further assume that the caller of this function is a typed array | 311 // However we further assume that the caller of this function is a typed array |
316 // constructor, and the exception will propagate out of the constructor, | 312 // constructor, and the exception will propagate out of the constructor, |
317 // therefore uninitialized memory will not be accessible by a user program. | 313 // therefore uninitialized memory will not be accessible by a user program. |
318 // | 314 // |
319 // TODO(dslomov): revise this once we support subclassing. | 315 // TODO(dslomov): revise this once we support subclassing. |
320 | 316 |
321 if (!Runtime::SetupArrayBufferAllocatingData(isolate, buffer, byte_length, | 317 if (!Runtime::SetupArrayBufferAllocatingData(isolate, buffer, byte_length, |
322 false)) { | 318 false)) { |
323 THROW_NEW_ERROR_RETURN_FAILURE( | 319 THROW_NEW_ERROR_RETURN_FAILURE( |
324 isolate, NewRangeError("invalid_array_buffer_length", | 320 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength)); |
325 HandleVector<Object>(NULL, 0))); | |
326 } | 321 } |
327 | 322 |
328 holder->set_buffer(*buffer); | 323 holder->set_buffer(*buffer); |
329 holder->set_byte_offset(Smi::FromInt(0)); | 324 holder->set_byte_offset(Smi::FromInt(0)); |
330 Handle<Object> byte_length_obj( | 325 Handle<Object> byte_length_obj( |
331 isolate->factory()->NewNumberFromSize(byte_length)); | 326 isolate->factory()->NewNumberFromSize(byte_length)); |
332 holder->set_byte_length(*byte_length_obj); | 327 holder->set_byte_length(*byte_length_obj); |
333 holder->set_length(*length_obj); | 328 holder->set_length(*length_obj); |
334 | 329 |
335 Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( | 330 Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj)); | 409 Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj)); |
415 size_t offset = 0; | 410 size_t offset = 0; |
416 RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset)); | 411 RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset)); |
417 size_t target_length = NumberToSize(isolate, target->length()); | 412 size_t target_length = NumberToSize(isolate, target->length()); |
418 size_t source_length = NumberToSize(isolate, source->length()); | 413 size_t source_length = NumberToSize(isolate, source->length()); |
419 size_t target_byte_length = NumberToSize(isolate, target->byte_length()); | 414 size_t target_byte_length = NumberToSize(isolate, target->byte_length()); |
420 size_t source_byte_length = NumberToSize(isolate, source->byte_length()); | 415 size_t source_byte_length = NumberToSize(isolate, source->byte_length()); |
421 if (offset > target_length || offset + source_length > target_length || | 416 if (offset > target_length || offset + source_length > target_length || |
422 offset + source_length < offset) { // overflow | 417 offset + source_length < offset) { // overflow |
423 THROW_NEW_ERROR_RETURN_FAILURE( | 418 THROW_NEW_ERROR_RETURN_FAILURE( |
424 isolate, NewRangeError("typed_array_set_source_too_large", | 419 isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge)); |
425 HandleVector<Object>(NULL, 0))); | |
426 } | 420 } |
427 | 421 |
428 size_t target_offset = NumberToSize(isolate, target->byte_offset()); | 422 size_t target_offset = NumberToSize(isolate, target->byte_offset()); |
429 size_t source_offset = NumberToSize(isolate, source->byte_offset()); | 423 size_t source_offset = NumberToSize(isolate, source->byte_offset()); |
430 uint8_t* target_base = | 424 uint8_t* target_base = |
431 static_cast<uint8_t*>(target->GetBuffer()->backing_store()) + | 425 static_cast<uint8_t*>(target->GetBuffer()->backing_store()) + |
432 target_offset; | 426 target_offset; |
433 uint8_t* source_base = | 427 uint8_t* source_base = |
434 static_cast<uint8_t*>(source->GetBuffer()->backing_store()) + | 428 static_cast<uint8_t*>(source->GetBuffer()->backing_store()) + |
435 source_offset; | 429 source_offset; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; | 601 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; |
608 if (NeedToFlipBytes(is_little_endian)) { | 602 if (NeedToFlipBytes(is_little_endian)) { |
609 FlipBytes<sizeof(T)>(target, value.bytes); | 603 FlipBytes<sizeof(T)>(target, value.bytes); |
610 } else { | 604 } else { |
611 CopyBytes<sizeof(T)>(target, value.bytes); | 605 CopyBytes<sizeof(T)>(target, value.bytes); |
612 } | 606 } |
613 return true; | 607 return true; |
614 } | 608 } |
615 | 609 |
616 | 610 |
617 #define DATA_VIEW_GETTER(TypeName, Type, Converter) \ | 611 #define DATA_VIEW_GETTER(TypeName, Type, Converter) \ |
618 RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \ | 612 RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \ |
619 HandleScope scope(isolate); \ | 613 HandleScope scope(isolate); \ |
620 DCHECK(args.length() == 3); \ | 614 DCHECK(args.length() == 3); \ |
621 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ | 615 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ |
622 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ | 616 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ |
623 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \ | 617 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \ |
624 Type result; \ | 618 Type result; \ |
625 if (DataViewGetValue(isolate, holder, offset, is_little_endian, \ | 619 if (DataViewGetValue(isolate, holder, offset, is_little_endian, \ |
626 &result)) { \ | 620 &result)) { \ |
627 return *isolate->factory()->Converter(result); \ | 621 return *isolate->factory()->Converter(result); \ |
628 } else { \ | 622 } else { \ |
629 THROW_NEW_ERROR_RETURN_FAILURE( \ | 623 THROW_NEW_ERROR_RETURN_FAILURE( \ |
630 isolate, NewRangeError("invalid_data_view_accessor_offset", \ | 624 isolate, \ |
631 HandleVector<Object>(NULL, 0))); \ | 625 NewRangeError(MessageTemplate::kInvalidDataViewAccessorOffset)); \ |
632 } \ | 626 } \ |
633 } | 627 } |
634 | 628 |
635 DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint) | 629 DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint) |
636 DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt) | 630 DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt) |
637 DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint) | 631 DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint) |
638 DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt) | 632 DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt) |
639 DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint) | 633 DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint) |
640 DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt) | 634 DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt) |
641 DATA_VIEW_GETTER(Float32, float, NewNumber) | 635 DATA_VIEW_GETTER(Float32, float, NewNumber) |
642 DATA_VIEW_GETTER(Float64, double, NewNumber) | 636 DATA_VIEW_GETTER(Float64, double, NewNumber) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 return static_cast<float>(value); | 683 return static_cast<float>(value); |
690 } | 684 } |
691 | 685 |
692 | 686 |
693 template <> | 687 template <> |
694 double DataViewConvertValue<double>(double value) { | 688 double DataViewConvertValue<double>(double value) { |
695 return value; | 689 return value; |
696 } | 690 } |
697 | 691 |
698 | 692 |
699 #define DATA_VIEW_SETTER(TypeName, Type) \ | 693 #define DATA_VIEW_SETTER(TypeName, Type) \ |
700 RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \ | 694 RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \ |
701 HandleScope scope(isolate); \ | 695 HandleScope scope(isolate); \ |
702 DCHECK(args.length() == 4); \ | 696 DCHECK(args.length() == 4); \ |
703 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ | 697 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ |
704 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ | 698 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ |
705 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); \ | 699 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); \ |
706 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \ | 700 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \ |
707 Type v = DataViewConvertValue<Type>(value->Number()); \ | 701 Type v = DataViewConvertValue<Type>(value->Number()); \ |
708 if (DataViewSetValue(isolate, holder, offset, is_little_endian, v)) { \ | 702 if (DataViewSetValue(isolate, holder, offset, is_little_endian, v)) { \ |
709 return isolate->heap()->undefined_value(); \ | 703 return isolate->heap()->undefined_value(); \ |
710 } else { \ | 704 } else { \ |
711 THROW_NEW_ERROR_RETURN_FAILURE( \ | 705 THROW_NEW_ERROR_RETURN_FAILURE( \ |
712 isolate, NewRangeError("invalid_data_view_accessor_offset", \ | 706 isolate, \ |
713 HandleVector<Object>(NULL, 0))); \ | 707 NewRangeError(MessageTemplate::kInvalidDataViewAccessorOffset)); \ |
714 } \ | 708 } \ |
715 } | 709 } |
716 | 710 |
717 DATA_VIEW_SETTER(Uint8, uint8_t) | 711 DATA_VIEW_SETTER(Uint8, uint8_t) |
718 DATA_VIEW_SETTER(Int8, int8_t) | 712 DATA_VIEW_SETTER(Int8, int8_t) |
719 DATA_VIEW_SETTER(Uint16, uint16_t) | 713 DATA_VIEW_SETTER(Uint16, uint16_t) |
720 DATA_VIEW_SETTER(Int16, int16_t) | 714 DATA_VIEW_SETTER(Int16, int16_t) |
721 DATA_VIEW_SETTER(Uint32, uint32_t) | 715 DATA_VIEW_SETTER(Uint32, uint32_t) |
722 DATA_VIEW_SETTER(Int32, int32_t) | 716 DATA_VIEW_SETTER(Int32, int32_t) |
723 DATA_VIEW_SETTER(Float32, float) | 717 DATA_VIEW_SETTER(Float32, float) |
724 DATA_VIEW_SETTER(Float64, double) | 718 DATA_VIEW_SETTER(Float64, double) |
725 | 719 |
726 #undef DATA_VIEW_SETTER | 720 #undef DATA_VIEW_SETTER |
727 } | 721 } |
728 } // namespace v8::internal | 722 } // namespace v8::internal |
OLD | NEW |