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 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 DCHECK(args.length() == 1); | 412 DCHECK(args.length() == 1); |
413 if (!args[0]->IsJSTypedArray()) { | 413 if (!args[0]->IsJSTypedArray()) { |
414 return isolate->heap()->false_value(); | 414 return isolate->heap()->false_value(); |
415 } | 415 } |
416 | 416 |
417 Handle<JSTypedArray> obj(JSTypedArray::cast(args[0])); | 417 Handle<JSTypedArray> obj(JSTypedArray::cast(args[0])); |
418 return isolate->heap()->ToBoolean(obj->GetBuffer()->is_shared() && | 418 return isolate->heap()->ToBoolean(obj->GetBuffer()->is_shared() && |
419 obj->type() == kExternalInt32Array); | 419 obj->type() == kExternalInt32Array); |
420 } | 420 } |
421 | 421 |
422 | |
423 inline static bool NeedToFlipBytes(bool is_little_endian) { | |
424 #ifdef V8_TARGET_LITTLE_ENDIAN | |
425 return !is_little_endian; | |
426 #else | |
427 return is_little_endian; | |
428 #endif | |
429 } | |
430 | |
431 | |
432 template <int n> | |
433 inline void CopyBytes(uint8_t* target, uint8_t* source) { | |
434 for (int i = 0; i < n; i++) { | |
435 *(target++) = *(source++); | |
436 } | |
437 } | |
438 | |
439 | |
440 template <int n> | |
441 inline void FlipBytes(uint8_t* target, uint8_t* source) { | |
442 source = source + (n - 1); | |
443 for (int i = 0; i < n; i++) { | |
444 *(target++) = *(source--); | |
445 } | |
446 } | |
447 | |
448 | |
449 template <typename T> | |
450 inline static bool DataViewGetValue(Isolate* isolate, | |
451 Handle<JSDataView> data_view, | |
452 Handle<Object> byte_offset_obj, | |
453 bool is_little_endian, T* result) { | |
454 size_t byte_offset = 0; | |
455 if (!TryNumberToSize(*byte_offset_obj, &byte_offset)) { | |
456 return false; | |
457 } | |
458 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); | |
459 | |
460 size_t data_view_byte_offset = NumberToSize(data_view->byte_offset()); | |
461 size_t data_view_byte_length = NumberToSize(data_view->byte_length()); | |
462 if (byte_offset + sizeof(T) > data_view_byte_length || | |
463 byte_offset + sizeof(T) < byte_offset) { // overflow | |
464 return false; | |
465 } | |
466 | |
467 union Value { | |
468 T data; | |
469 uint8_t bytes[sizeof(T)]; | |
470 }; | |
471 | |
472 Value value; | |
473 size_t buffer_offset = data_view_byte_offset + byte_offset; | |
474 DCHECK(NumberToSize(buffer->byte_length()) >= buffer_offset + sizeof(T)); | |
475 uint8_t* source = | |
476 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; | |
477 if (NeedToFlipBytes(is_little_endian)) { | |
478 FlipBytes<sizeof(T)>(value.bytes, source); | |
479 } else { | |
480 CopyBytes<sizeof(T)>(value.bytes, source); | |
481 } | |
482 *result = value.data; | |
483 return true; | |
484 } | |
485 | |
486 | |
487 template <typename T> | |
488 static bool DataViewSetValue(Isolate* isolate, Handle<JSDataView> data_view, | |
489 Handle<Object> byte_offset_obj, | |
490 bool is_little_endian, T data) { | |
491 size_t byte_offset = 0; | |
492 if (!TryNumberToSize(*byte_offset_obj, &byte_offset)) { | |
493 return false; | |
494 } | |
495 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); | |
496 | |
497 size_t data_view_byte_offset = NumberToSize(data_view->byte_offset()); | |
498 size_t data_view_byte_length = NumberToSize(data_view->byte_length()); | |
499 if (byte_offset + sizeof(T) > data_view_byte_length || | |
500 byte_offset + sizeof(T) < byte_offset) { // overflow | |
501 return false; | |
502 } | |
503 | |
504 union Value { | |
505 T data; | |
506 uint8_t bytes[sizeof(T)]; | |
507 }; | |
508 | |
509 Value value; | |
510 value.data = data; | |
511 size_t buffer_offset = data_view_byte_offset + byte_offset; | |
512 DCHECK(NumberToSize(buffer->byte_length()) >= buffer_offset + sizeof(T)); | |
513 uint8_t* target = | |
514 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; | |
515 if (NeedToFlipBytes(is_little_endian)) { | |
516 FlipBytes<sizeof(T)>(target, value.bytes); | |
517 } else { | |
518 CopyBytes<sizeof(T)>(target, value.bytes); | |
519 } | |
520 return true; | |
521 } | |
522 | |
523 | |
524 #define DATA_VIEW_GETTER(TypeName, Type, Converter) \ | |
525 RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \ | |
526 HandleScope scope(isolate); \ | |
527 DCHECK(args.length() == 3); \ | |
528 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ | |
529 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ | |
530 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \ | |
531 Type result; \ | |
532 if (DataViewGetValue(isolate, holder, offset, is_little_endian, \ | |
533 &result)) { \ | |
534 return *isolate->factory()->Converter(result); \ | |
535 } else { \ | |
536 THROW_NEW_ERROR_RETURN_FAILURE( \ | |
537 isolate, \ | |
538 NewRangeError(MessageTemplate::kInvalidDataViewAccessorOffset)); \ | |
539 } \ | |
540 } | |
541 | |
542 DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint) | |
543 DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt) | |
544 DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint) | |
545 DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt) | |
546 DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint) | |
547 DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt) | |
548 DATA_VIEW_GETTER(Float32, float, NewNumber) | |
549 DATA_VIEW_GETTER(Float64, double, NewNumber) | |
550 | |
551 #undef DATA_VIEW_GETTER | |
552 | |
553 | |
554 template <typename T> | |
555 static T DataViewConvertValue(double value); | |
556 | |
557 | |
558 template <> | |
559 int8_t DataViewConvertValue<int8_t>(double value) { | |
560 return static_cast<int8_t>(DoubleToInt32(value)); | |
561 } | |
562 | |
563 | |
564 template <> | |
565 int16_t DataViewConvertValue<int16_t>(double value) { | |
566 return static_cast<int16_t>(DoubleToInt32(value)); | |
567 } | |
568 | |
569 | |
570 template <> | |
571 int32_t DataViewConvertValue<int32_t>(double value) { | |
572 return DoubleToInt32(value); | |
573 } | |
574 | |
575 | |
576 template <> | |
577 uint8_t DataViewConvertValue<uint8_t>(double value) { | |
578 return static_cast<uint8_t>(DoubleToUint32(value)); | |
579 } | |
580 | |
581 | |
582 template <> | |
583 uint16_t DataViewConvertValue<uint16_t>(double value) { | |
584 return static_cast<uint16_t>(DoubleToUint32(value)); | |
585 } | |
586 | |
587 | |
588 template <> | |
589 uint32_t DataViewConvertValue<uint32_t>(double value) { | |
590 return DoubleToUint32(value); | |
591 } | |
592 | |
593 | |
594 template <> | |
595 float DataViewConvertValue<float>(double value) { | |
596 return static_cast<float>(value); | |
597 } | |
598 | |
599 | |
600 template <> | |
601 double DataViewConvertValue<double>(double value) { | |
602 return value; | |
603 } | |
604 | |
605 | |
606 #define DATA_VIEW_SETTER(TypeName, Type) \ | |
607 RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \ | |
608 HandleScope scope(isolate); \ | |
609 DCHECK(args.length() == 4); \ | |
610 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ | |
611 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ | |
612 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); \ | |
613 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \ | |
614 Type v = DataViewConvertValue<Type>(value->Number()); \ | |
615 if (DataViewSetValue(isolate, holder, offset, is_little_endian, v)) { \ | |
616 return isolate->heap()->undefined_value(); \ | |
617 } else { \ | |
618 THROW_NEW_ERROR_RETURN_FAILURE( \ | |
619 isolate, \ | |
620 NewRangeError(MessageTemplate::kInvalidDataViewAccessorOffset)); \ | |
621 } \ | |
622 } | |
623 | |
624 DATA_VIEW_SETTER(Uint8, uint8_t) | |
625 DATA_VIEW_SETTER(Int8, int8_t) | |
626 DATA_VIEW_SETTER(Uint16, uint16_t) | |
627 DATA_VIEW_SETTER(Int16, int16_t) | |
628 DATA_VIEW_SETTER(Uint32, uint32_t) | |
629 DATA_VIEW_SETTER(Int32, int32_t) | |
630 DATA_VIEW_SETTER(Float32, float) | |
631 DATA_VIEW_SETTER(Float64, double) | |
632 | |
633 #undef DATA_VIEW_SETTER | |
634 } // namespace internal | 422 } // namespace internal |
635 } // namespace v8 | 423 } // namespace v8 |
OLD | NEW |