summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/data-view.tq
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/data-view.tq')
-rw-r--r--deps/v8/src/builtins/data-view.tq896
1 files changed, 896 insertions, 0 deletions
diff --git a/deps/v8/src/builtins/data-view.tq b/deps/v8/src/builtins/data-view.tq
new file mode 100644
index 0000000000..7cdc74a944
--- /dev/null
+++ b/deps/v8/src/builtins/data-view.tq
@@ -0,0 +1,896 @@
+// Copyright 2018 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module data_view {
+
+ extern operator '.buffer'
+ macro LoadArrayBufferViewBuffer(JSArrayBufferView): JSArrayBuffer;
+ extern operator '.byte_length'
+ macro LoadDataViewByteLength(JSDataView): Number;
+ extern operator '.byte_offset'
+ macro LoadDataViewByteOffset(JSDataView): Number;
+ extern operator '.backing_store'
+ macro LoadArrayBufferBackingStore(JSArrayBuffer): RawPtr;
+
+ macro WasNeutered(view: JSArrayBufferView): bool {
+ return IsDetachedBuffer(view.buffer);
+ }
+
+ macro ValidateDataView(context: Context,
+ o: Object, method: String): JSDataView {
+ try {
+ return cast<JSDataView>(o) otherwise CastError;
+ }
+ label CastError {
+ ThrowTypeError(context, kIncompatibleMethodReceiver, method);
+ }
+ }
+
+ // ES6 section 24.2.4.1 get DataView.prototype.buffer
+ javascript builtin DataViewPrototypeGetBuffer(
+ context: Context, receiver: Object, ...arguments): JSArrayBuffer {
+ let data_view: JSDataView = ValidateDataView(
+ context, receiver, 'get DataView.prototype.buffer');
+ return data_view.buffer;
+ }
+
+ // ES6 section 24.2.4.2 get DataView.prototype.byteLength
+ javascript builtin DataViewPrototypeGetByteLength(
+ context: Context, receiver: Object, ...arguments): Number {
+ let data_view: JSDataView = ValidateDataView(
+ context, receiver, 'get DataView.prototype.byte_length');
+ if (WasNeutered(data_view)) {
+ // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
+ // here if the JSArrayBuffer of the {data_view} was neutered.
+ return 0;
+ }
+ return data_view.byte_length;
+ }
+
+ // ES6 section 24.2.4.3 get DataView.prototype.byteOffset
+ javascript builtin DataViewPrototypeGetByteOffset(
+ context: Context, receiver: Object, ...arguments): Number {
+ let data_view: JSDataView = ValidateDataView(
+ context, receiver, 'get DataView.prototype.byte_offset');
+ if (WasNeutered(data_view)) {
+ // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
+ // here if the JSArrayBuffer of the {data_view} was neutered.
+ return 0;
+ }
+ return data_view.byte_offset;
+ }
+
+ extern macro BitcastInt32ToFloat32(uint32): float32;
+ extern macro BitcastFloat32ToInt32(float32): uint32;
+ extern macro Float64ExtractLowWord32(float64): uint32;
+ extern macro Float64ExtractHighWord32(float64): uint32;
+ extern macro Float64InsertLowWord32(float64, uint32): float64;
+ extern macro Float64InsertHighWord32(float64, uint32): float64;
+
+ extern macro LoadUint8(RawPtr, intptr): uint32;
+ extern macro LoadInt8(RawPtr, intptr): int32;
+
+ macro LoadDataViewUint8(buffer: JSArrayBuffer, offset: intptr): Smi {
+ return convert<Smi>(LoadUint8(buffer.backing_store, offset));
+ }
+
+ macro LoadDataViewInt8(buffer: JSArrayBuffer, offset: intptr): Smi {
+ return convert<Smi>(LoadInt8(buffer.backing_store, offset));
+ }
+
+ macro LoadDataView16(buffer: JSArrayBuffer, offset: intptr,
+ requested_little_endian: bool,
+ signed: constexpr bool): Number {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: int32;
+ let b1: int32;
+ let result: int32;
+
+ // Sign-extend the most significant byte by loading it as an Int8.
+ if (requested_little_endian) {
+ b0 = Signed(LoadUint8(data_pointer, offset));
+ b1 = LoadInt8(data_pointer, offset + 1);
+ result = (b1 << 8) + b0;
+ } else {
+ b0 = LoadInt8(data_pointer, offset);
+ b1 = Signed(LoadUint8(data_pointer, offset + 1));
+ result = (b0 << 8) + b1;
+ }
+ if constexpr (signed) {
+ return convert<Smi>(result);
+ } else {
+ // Bit-mask the higher bits to prevent sign extension if we're unsigned.
+ return convert<Smi>(result & 0xFFFF);
+ }
+ }
+
+ macro LoadDataView32(buffer: JSArrayBuffer, offset: intptr,
+ requested_little_endian: bool,
+ signed: constexpr bool): Number {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: uint32 = LoadUint8(data_pointer, offset);
+ let b1: uint32 = LoadUint8(data_pointer, offset + 1);
+ let b2: uint32 = LoadUint8(data_pointer, offset + 2);
+ let b3: uint32 = LoadUint8(data_pointer, offset + 3);
+ let result: uint32;
+
+ if (requested_little_endian) {
+ result = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+ } else {
+ result = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+ }
+
+ if constexpr (signed) {
+ return convert<Number>(Signed(result));
+ } else {
+ return convert<Number>(result);
+ }
+ }
+
+ macro LoadDataViewFloat32(buffer: JSArrayBuffer, offset: intptr,
+ requested_little_endian: bool): Number {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: uint32 = LoadUint8(data_pointer, offset);
+ let b1: uint32 = LoadUint8(data_pointer, offset + 1);
+ let b2: uint32 = LoadUint8(data_pointer, offset + 2);
+ let b3: uint32 = LoadUint8(data_pointer, offset + 3);
+ let result: uint32;
+
+ if (requested_little_endian) {
+ result = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+ } else {
+ result = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+ }
+
+ let float_res: float64 = convert<float64>(BitcastInt32ToFloat32(result));
+ return convert<Number>(float_res);
+ }
+
+ macro LoadDataViewFloat64(buffer: JSArrayBuffer, offset: intptr,
+ requested_little_endian: bool): Number {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: uint32 = LoadUint8(data_pointer, offset);
+ let b1: uint32 = LoadUint8(data_pointer, offset + 1);
+ let b2: uint32 = LoadUint8(data_pointer, offset + 2);
+ let b3: uint32 = LoadUint8(data_pointer, offset + 3);
+ let b4: uint32 = LoadUint8(data_pointer, offset + 4);
+ let b5: uint32 = LoadUint8(data_pointer, offset + 5);
+ let b6: uint32 = LoadUint8(data_pointer, offset + 6);
+ let b7: uint32 = LoadUint8(data_pointer, offset + 7);
+ let low_word: uint32;
+ let high_word: uint32;
+
+ if (requested_little_endian) {
+ low_word = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+ high_word = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4;
+ } else {
+ high_word = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+ low_word = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+ }
+
+ let result: float64 = 0;
+ result = Float64InsertLowWord32(result, low_word);
+ result = Float64InsertHighWord32(result, high_word);
+
+ return convert<Number>(result);
+ }
+
+ extern macro AllocateBigInt(intptr): BigInt;
+ extern macro StoreBigIntBitfield(BigInt, intptr): void;
+ extern macro StoreBigIntDigit(BigInt, constexpr int31, uintptr): void;
+ extern macro DataViewEncodeBigIntBits(constexpr bool,
+ constexpr int31): intptr;
+
+ const kPositiveBigInt: constexpr bool generates 'false';
+ const kNegativeBigInt: constexpr bool generates 'true';
+ const kZeroDigitBigInt: constexpr int31 generates '0';
+ const kOneDigitBigInt: constexpr int31 generates '1';
+ const kTwoDigitBigInt: constexpr int31 generates '2';
+
+ macro CreateEmptyBigInt(is_positive: bool, length: constexpr int31): BigInt {
+ // Allocate a BigInt with the desired length (number of digits).
+ let result: BigInt = AllocateBigInt(length);
+
+ // Write the desired sign and length to the BigInt bitfield.
+ if (is_positive) {
+ StoreBigIntBitfield(result,
+ DataViewEncodeBigIntBits(kPositiveBigInt, length));
+ } else {
+ StoreBigIntBitfield(result,
+ DataViewEncodeBigIntBits(kNegativeBigInt, length));
+ }
+
+ return result;
+ }
+
+ // Create a BigInt on a 64-bit architecture from two 32-bit values.
+ macro MakeBigIntOn64Bit(low_word: uint32, high_word: uint32,
+ signed: constexpr bool): BigInt {
+
+ // 0n is represented by a zero-length BigInt.
+ if (low_word == 0 && high_word == 0) {
+ return AllocateBigInt(kZeroDigitBigInt);
+ }
+
+ let is_positive: bool = true;
+ let high_part: intptr = Signed(convert<uintptr>(high_word));
+ let low_part: intptr = Signed(convert<uintptr>(low_word));
+ let raw_value: intptr = (high_part << 32) + low_part;
+
+ if constexpr (signed) {
+ if (raw_value < 0) {
+ is_positive = false;
+ // We have to store the absolute value of raw_value in the digit.
+ raw_value = 0 - raw_value;
+ }
+ }
+
+ // Allocate the BigInt and store the absolute value.
+ let result: BigInt = CreateEmptyBigInt(is_positive, kOneDigitBigInt);
+
+ StoreBigIntDigit(result, 0, Unsigned(raw_value));
+
+ return result;
+ }
+
+ // Create a BigInt on a 32-bit architecture from two 32-bit values.
+ macro MakeBigIntOn32Bit(low_word: uint32, high_word: uint32,
+ signed: constexpr bool): BigInt {
+
+ // 0n is represented by a zero-length BigInt.
+ if (low_word == 0 && high_word == 0) {
+ return AllocateBigInt(kZeroDigitBigInt);
+ }
+
+ // On a 32-bit platform, we might need 1 or 2 digits to store the number.
+ let need_two_digits: bool = false;
+ let is_positive: bool = true;
+
+ // We need to do some math on low_word and high_word,
+ // so convert them to int32.
+ let low_part: int32 = Signed(low_word);
+ let high_part: int32 = Signed(high_word);
+
+ // If high_word == 0, the number is positive, and we only need 1 digit,
+ // so we don't have anything to do.
+ // Otherwise, all cases are possible.
+ if (high_word != 0) {
+ if constexpr (signed) {
+
+ // If high_part < 0, the number is always negative.
+ if (high_part < 0) {
+ is_positive = false;
+
+ // We have to compute the absolute value by hand.
+ // There will be a negative carry from the low word
+ // to the high word iff low != 0.
+ high_part = 0 - high_part;
+ if (low_part != 0) {
+ high_part = high_part - 1;
+ }
+ low_part = 0 - low_part;
+
+ // Here, high_part could be 0 again so we might have 1 or 2 digits.
+ if (high_part != 0) {
+ need_two_digits = true;
+ }
+
+ } else {
+ // In this case, the number is positive, and we need 2 digits.
+ need_two_digits = true;
+ }
+
+ } else {
+ // In this case, the number is positive (unsigned),
+ // and we need 2 digits.
+ need_two_digits = true;
+ }
+ }
+
+ // Allocate the BigInt with the right sign and length.
+ let result: BigInt;
+ if (need_two_digits) {
+ result = CreateEmptyBigInt(is_positive, kTwoDigitBigInt);
+ } else {
+ result = CreateEmptyBigInt(is_positive, kOneDigitBigInt);
+ }
+
+ // Finally, write the digit(s) to the BigInt.
+ StoreBigIntDigit(result, 0, Unsigned(convert<intptr>(low_part)));
+
+ if (need_two_digits) {
+ StoreBigIntDigit(result, 1, Unsigned(convert<intptr>(high_part)));
+ }
+
+ return result;
+ }
+
+ macro MakeBigInt(low_word: uint32, high_word: uint32,
+ signed: constexpr bool): BigInt {
+ // A BigInt digit has the platform word size, so we only need one digit
+ // on 64-bit platforms but may need two on 32-bit.
+ if constexpr (Is64()) {
+ return MakeBigIntOn64Bit(low_word, high_word, signed);
+ } else {
+ return MakeBigIntOn32Bit(low_word, high_word, signed);
+ }
+ }
+
+ macro LoadDataViewBigInt(buffer: JSArrayBuffer, offset: intptr,
+ requested_little_endian: bool,
+ signed: constexpr bool): BigInt {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: uint32 = LoadUint8(data_pointer, offset);
+ let b1: uint32 = LoadUint8(data_pointer, offset + 1);
+ let b2: uint32 = LoadUint8(data_pointer, offset + 2);
+ let b3: uint32 = LoadUint8(data_pointer, offset + 3);
+ let b4: uint32 = LoadUint8(data_pointer, offset + 4);
+ let b5: uint32 = LoadUint8(data_pointer, offset + 5);
+ let b6: uint32 = LoadUint8(data_pointer, offset + 6);
+ let b7: uint32 = LoadUint8(data_pointer, offset + 7);
+ let low_word: uint32;
+ let high_word: uint32;
+
+ if (requested_little_endian) {
+ low_word = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+ high_word = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4;
+ } else {
+ high_word = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+ low_word = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+ }
+
+ return MakeBigInt(low_word, high_word, signed);
+ }
+
+ extern macro ToSmiIndex(Object, Context): Smi labels RangeError;
+ extern macro DataViewElementSize(constexpr ElementsKind): constexpr int31;
+
+ macro DataViewGet(context: Context,
+ receiver: Object,
+ offset: Object,
+ requested_little_endian: Object,
+ kind: constexpr ElementsKind): Numeric {
+
+ // TODO(theotime): add more specific method name to match
+ // the former implementation.
+ let data_view: JSDataView = ValidateDataView(
+ context, receiver, 'get DataView.prototype.get');
+
+ let getIndex: Number;
+ try {
+ getIndex = ToIndex(offset, context) otherwise RangeError;
+ }
+ label RangeError {
+ ThrowRangeError(context, kInvalidDataViewAccessorOffset);
+ }
+
+ let littleEndian: bool = ToBoolean(requested_little_endian);
+ let buffer: JSArrayBuffer = data_view.buffer;
+
+ if (IsDetachedBuffer(buffer)) {
+ ThrowTypeError(context, kDetachedOperation, 'DataView.prototype.get');
+ }
+
+ let viewOffset: Number = data_view.byte_offset;
+ let viewSize: Number = data_view.byte_length;
+ let elementSize: Number = DataViewElementSize(kind);
+
+ if (getIndex + elementSize > viewSize) {
+ ThrowRangeError(context, kInvalidDataViewAccessorOffset);
+ }
+
+ let getIndexFloat: float64 = convert<float64>(getIndex);
+ let getIndexIntptr: intptr = Signed(convert<uintptr>(getIndexFloat));
+ let viewOffsetFloat: float64 = convert<float64>(viewOffset);
+ let viewOffsetIntptr: intptr = Signed(convert<uintptr>(viewOffsetFloat));
+
+ let bufferIndex: intptr = getIndexIntptr + viewOffsetIntptr;
+
+ if constexpr (kind == UINT8_ELEMENTS) {
+ return LoadDataViewUint8(buffer, bufferIndex);
+ } else if constexpr (kind == INT8_ELEMENTS) {
+ return LoadDataViewInt8(buffer, bufferIndex);
+ } else if constexpr (kind == UINT16_ELEMENTS) {
+ return LoadDataView16(buffer, bufferIndex, littleEndian, false);
+ } else if constexpr (kind == INT16_ELEMENTS) {
+ return LoadDataView16(buffer, bufferIndex, littleEndian, true);
+ } else if constexpr (kind == UINT32_ELEMENTS) {
+ return LoadDataView32(buffer, bufferIndex, littleEndian, false);
+ } else if constexpr (kind == INT32_ELEMENTS) {
+ return LoadDataView32(buffer, bufferIndex, littleEndian, true);
+ } else if constexpr (kind == FLOAT32_ELEMENTS) {
+ return LoadDataViewFloat32(buffer, bufferIndex, littleEndian);
+ } else if constexpr (kind == FLOAT64_ELEMENTS) {
+ return LoadDataViewFloat64(buffer, bufferIndex, littleEndian);
+ } else if constexpr (kind == BIGINT64_ELEMENTS) {
+ return LoadDataViewBigInt(buffer, bufferIndex, littleEndian, true);
+ } else if constexpr (kind == BIGUINT64_ELEMENTS) {
+ return LoadDataViewBigInt(buffer, bufferIndex, littleEndian, false);
+ } else {
+ unreachable;
+ }
+ }
+
+ javascript builtin DataViewPrototypeGetInt8(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, Undefined, INT8_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetUint8(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, Undefined, UINT8_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetInt16(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ INT16_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetUint16(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ UINT16_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetInt32(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ INT32_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetUint32(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ UINT32_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetFloat32(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ FLOAT32_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetFloat64(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ FLOAT64_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetBigInt64(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ BIGINT64_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeGetBigUint64(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewGet(context, receiver, offset, is_little_endian,
+ BIGUINT64_ELEMENTS);
+ }
+
+ extern macro ToNumber(Context, Object): Number;
+ extern macro ToBigInt(Context, Object): BigInt;
+ extern macro TruncateFloat64ToFloat32(float64): float32;
+ extern macro TruncateFloat64ToWord32(float64): uint32;
+
+ extern macro StoreWord8(RawPtr, intptr, uint32): void;
+
+ macro StoreDataView8(buffer: JSArrayBuffer, offset: intptr,
+ value: uint32) {
+ StoreWord8(buffer.backing_store, offset, value & 0xFF);
+ }
+
+ macro StoreDataView16(buffer: JSArrayBuffer, offset: intptr, value: uint32,
+ requested_little_endian: bool) {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: uint32 = value & 0xFF;
+ let b1: uint32 = (value >>> 8) & 0xFF;
+
+ if (requested_little_endian) {
+ StoreWord8(data_pointer, offset, b0);
+ StoreWord8(data_pointer, offset + 1, b1);
+ } else {
+ StoreWord8(data_pointer, offset, b1);
+ StoreWord8(data_pointer, offset + 1, b0);
+ }
+ }
+
+ macro StoreDataView32(buffer: JSArrayBuffer, offset: intptr, value: uint32,
+ requested_little_endian: bool) {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: uint32 = value & 0xFF;
+ let b1: uint32 = (value >>> 8) & 0xFF;
+ let b2: uint32 = (value >>> 16) & 0xFF;
+ let b3: uint32 = value >>> 24; // We don't need to mask here.
+
+ if (requested_little_endian) {
+ StoreWord8(data_pointer, offset, b0);
+ StoreWord8(data_pointer, offset + 1, b1);
+ StoreWord8(data_pointer, offset + 2, b2);
+ StoreWord8(data_pointer, offset + 3, b3);
+ } else {
+ StoreWord8(data_pointer, offset, b3);
+ StoreWord8(data_pointer, offset + 1, b2);
+ StoreWord8(data_pointer, offset + 2, b1);
+ StoreWord8(data_pointer, offset + 3, b0);
+ }
+ }
+
+ macro StoreDataView64(buffer: JSArrayBuffer, offset: intptr,
+ low_word: uint32, high_word: uint32,
+ requested_little_endian: bool) {
+ let data_pointer: RawPtr = buffer.backing_store;
+
+ let b0: uint32 = low_word & 0xFF;
+ let b1: uint32 = (low_word >>> 8) & 0xFF;
+ let b2: uint32 = (low_word >>> 16) & 0xFF;
+ let b3: uint32 = low_word >>> 24;
+
+ let b4: uint32 = high_word & 0xFF;
+ let b5: uint32 = (high_word >>> 8) & 0xFF;
+ let b6: uint32 = (high_word >>> 16) & 0xFF;
+ let b7: uint32 = high_word >>> 24;
+
+
+ if (requested_little_endian) {
+ StoreWord8(data_pointer, offset, b0);
+ StoreWord8(data_pointer, offset + 1, b1);
+ StoreWord8(data_pointer, offset + 2, b2);
+ StoreWord8(data_pointer, offset + 3, b3);
+ StoreWord8(data_pointer, offset + 4, b4);
+ StoreWord8(data_pointer, offset + 5, b5);
+ StoreWord8(data_pointer, offset + 6, b6);
+ StoreWord8(data_pointer, offset + 7, b7);
+ } else {
+ StoreWord8(data_pointer, offset, b7);
+ StoreWord8(data_pointer, offset + 1, b6);
+ StoreWord8(data_pointer, offset + 2, b5);
+ StoreWord8(data_pointer, offset + 3, b4);
+ StoreWord8(data_pointer, offset + 4, b3);
+ StoreWord8(data_pointer, offset + 5, b2);
+ StoreWord8(data_pointer, offset + 6, b1);
+ StoreWord8(data_pointer, offset + 7, b0);
+ }
+ }
+
+ extern macro DataViewDecodeBigIntLength(BigInt): uintptr;
+ extern macro DataViewDecodeBigIntSign(BigInt): uintptr;
+ extern macro LoadBigIntDigit(BigInt, constexpr int31): uintptr;
+
+ // We might get here a BigInt that is bigger than 64 bits, but we're only
+ // interested in the 64 lowest ones. This means the lowest BigInt digit
+ // on 64-bit platforms, and the 2 lowest BigInt digits on 32-bit ones.
+ macro StoreDataViewBigInt(buffer: JSArrayBuffer, offset: intptr,
+ bigint_value: BigInt,
+ requested_little_endian: bool) {
+
+ let length: uintptr = DataViewDecodeBigIntLength(bigint_value);
+ let sign: uintptr = DataViewDecodeBigIntSign(bigint_value);
+
+ // The 32-bit words that will hold the BigInt's value in
+ // two's complement representation.
+ let low_word: uint32 = 0;
+ let high_word: uint32 = 0;
+
+ // The length is nonzero if and only if the BigInt's value is nonzero.
+ if (length != 0) {
+ if constexpr (Is64()) {
+ // There is always exactly 1 BigInt digit to load in this case.
+ let value: uintptr = LoadBigIntDigit(bigint_value, 0);
+ low_word = convert<uint32>(value); // Truncates value to 32 bits.
+ high_word = convert<uint32>(value >>> 32);
+ }
+ else { // There might be either 1 or 2 BigInt digits we need to load.
+ low_word = convert<uint32>(LoadBigIntDigit(bigint_value, 0));
+ if (length >= 2) { // Only load the second digit if there is one.
+ high_word = convert<uint32>(LoadBigIntDigit(bigint_value, 1));
+ }
+ }
+ }
+
+ if (sign != 0) { // The number is negative, convert it.
+ high_word = Unsigned(0 - Signed(high_word));
+ if (low_word != 0) {
+ high_word = Unsigned(Signed(high_word) - 1);
+ }
+ low_word = Unsigned(0 - Signed(low_word));
+ }
+
+ StoreDataView64(buffer, offset, low_word, high_word,
+ requested_little_endian);
+ }
+
+ macro DataViewSet(context: Context,
+ receiver: Object,
+ offset: Object,
+ value: Object,
+ requested_little_endian: Object,
+ kind: constexpr ElementsKind): Object {
+
+ // TODO(theotime): add more specific method name to match
+ // the former implementation.
+ let data_view: JSDataView = ValidateDataView(
+ context, receiver, 'get DataView.prototype.get');
+
+ let getIndex: Number;
+ try {
+ getIndex = ToIndex(offset, context) otherwise RangeError;
+ }
+ label RangeError {
+ ThrowRangeError(context, kInvalidDataViewAccessorOffset);
+ }
+
+ let littleEndian: bool = ToBoolean(requested_little_endian);
+ let buffer: JSArrayBuffer = data_view.buffer;
+
+ let bigint_value: BigInt;
+ let num_value: Number;
+ // According to ES6 section 24.2.1.2 SetViewValue, we must perform
+ // the conversion before doing the bounds check.
+ if constexpr (kind == BIGUINT64_ELEMENTS || kind == BIGINT64_ELEMENTS) {
+ bigint_value = ToBigInt(context, value);
+ } else {
+ num_value = ToNumber(context, value);
+ }
+
+ if (IsDetachedBuffer(buffer)) {
+ ThrowTypeError(context, kDetachedOperation, 'DataView.prototype.get');
+ }
+
+ let viewOffset: Number = data_view.byte_offset;
+ let viewSize: Number = data_view.byte_length;
+ let elementSize: Number = DataViewElementSize(kind);
+
+ if (getIndex + elementSize > viewSize) {
+ ThrowRangeError(context, kInvalidDataViewAccessorOffset);
+ }
+
+ let getIndexFloat: float64 = convert<float64>(getIndex);
+ let getIndexIntptr: intptr = Signed(convert<uintptr>(getIndexFloat));
+ let viewOffsetFloat: float64 = convert<float64>(viewOffset);
+ let viewOffsetIntptr: intptr = Signed(convert<uintptr>(viewOffsetFloat));
+
+ let bufferIndex: intptr = getIndexIntptr + viewOffsetIntptr;
+
+ if constexpr (kind == BIGUINT64_ELEMENTS || kind == BIGINT64_ELEMENTS) {
+ StoreDataViewBigInt(buffer, bufferIndex, bigint_value,
+ littleEndian);
+ }
+ else {
+ let double_value: float64 = ChangeNumberToFloat64(num_value);
+
+ if constexpr (kind == UINT8_ELEMENTS || kind == INT8_ELEMENTS) {
+ StoreDataView8(buffer, bufferIndex,
+ TruncateFloat64ToWord32(double_value));
+ }
+ else if constexpr (kind == UINT16_ELEMENTS || kind == INT16_ELEMENTS) {
+ StoreDataView16(buffer, bufferIndex,
+ TruncateFloat64ToWord32(double_value), littleEndian);
+ }
+ else if constexpr (kind == UINT32_ELEMENTS || kind == INT32_ELEMENTS) {
+ StoreDataView32(buffer, bufferIndex,
+ TruncateFloat64ToWord32(double_value), littleEndian);
+ }
+ else if constexpr (kind == FLOAT32_ELEMENTS) {
+ let float_value: float32 = TruncateFloat64ToFloat32(double_value);
+ StoreDataView32(buffer, bufferIndex,
+ BitcastFloat32ToInt32(float_value), littleEndian);
+ }
+ else if constexpr (kind == FLOAT64_ELEMENTS) {
+ let low_word: uint32 = Float64ExtractLowWord32(double_value);
+ let high_word: uint32 = Float64ExtractHighWord32(double_value);
+ StoreDataView64(buffer, bufferIndex, low_word, high_word,
+ littleEndian);
+ }
+ }
+ return Undefined;
+ }
+
+ javascript builtin DataViewPrototypeSetInt8(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value, Undefined,
+ INT8_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetUint8(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value, Undefined,
+ UINT8_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetInt16(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, INT16_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetUint16(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, UINT16_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetInt32(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, INT32_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetUint32(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, UINT32_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetFloat32(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, FLOAT32_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetFloat64(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, FLOAT64_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetBigInt64(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, BIGINT64_ELEMENTS);
+ }
+
+ javascript builtin DataViewPrototypeSetBigUint64(
+ context: Context, receiver: Object, ...arguments): Object {
+ let offset: Object = arguments.length > 0 ?
+ arguments[0] :
+ Undefined;
+ let value : Object = arguments.length > 1 ?
+ arguments[1] :
+ Undefined;
+ let is_little_endian : Object = arguments.length > 2 ?
+ arguments[2] :
+ Undefined;
+ return DataViewSet(context, receiver, offset, value,
+ is_little_endian, BIGUINT64_ELEMENTS);
+ }
+
+}