| 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 |