[dataview]: Move DataView setters to Torque.
This CL completely reimplements the DataView setters in Torque, and removes the former C++ runtime implementation. Change-Id: I66cdd35712e46f3931d6530a4512fa3c8eb3b3bf Reviewed-on: https://chromium-review.googlesource.com/1104162 Commit-Queue: Théotime Grohens <theotime@google.com> Reviewed-by: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#53800}
This commit is contained in:
parent
8f8c53ba75
commit
e947d21e3d
1
BUILD.gn
1
BUILD.gn
@ -2277,7 +2277,6 @@ v8_source_set("v8_base") {
|
||||
"src/runtime/runtime-classes.cc",
|
||||
"src/runtime/runtime-collections.cc",
|
||||
"src/runtime/runtime-compiler.cc",
|
||||
"src/runtime/runtime-dataview.cc",
|
||||
"src/runtime/runtime-date.cc",
|
||||
"src/runtime/runtime-debug.cc",
|
||||
"src/runtime/runtime-forin.cc",
|
||||
|
@ -201,11 +201,14 @@ extern macro IsDoubleElementsKind(constexpr ElementsKind): constexpr bool;
|
||||
extern macro SmiAbove(Smi, Smi): bool;
|
||||
|
||||
extern operator '==' macro WordEqual(intptr, intptr): bool;
|
||||
extern operator '==' macro WordEqual(uintptr, uintptr): bool;
|
||||
extern operator '!=' macro WordNotEqual(intptr, intptr): bool;
|
||||
extern operator '!=' macro WordNotEqual(uintptr, uintptr): bool;
|
||||
extern operator '<' macro IntPtrLessThan(intptr, intptr): bool;
|
||||
extern operator '>' macro IntPtrGreaterThan(intptr, intptr): bool;
|
||||
extern operator '<=' macro IntPtrLessThanOrEqual(intptr, intptr): bool;
|
||||
extern operator '>=' macro IntPtrGreaterThanOrEqual(intptr, intptr): bool;
|
||||
extern operator '>=' macro UintPtrGreaterThanOrEqual(uintptr, uintptr): bool;
|
||||
|
||||
extern operator '==' macro Float64Equal(float64, float64): bool;
|
||||
extern operator '!=' macro Float64NotEqual(float64, float64): bool;
|
||||
@ -233,6 +236,7 @@ extern operator '>>>' macro SmiShr(Smi, constexpr int31): Smi;
|
||||
extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
|
||||
extern operator '-' macro IntPtrSub(intptr, intptr): intptr;
|
||||
extern operator '>>>' macro WordShr(intptr, intptr): intptr;
|
||||
extern operator '>>>' macro WordShr(uintptr, uintptr): uintptr;
|
||||
extern operator '<<' macro WordShl(intptr, intptr): intptr;
|
||||
extern operator '&' macro WordAnd(intptr, intptr): intptr;
|
||||
|
||||
@ -240,10 +244,11 @@ extern operator '+' macro Int32Add(int32, int32): int32;
|
||||
extern operator '-' macro Int32Sub(int32, int32): int32;
|
||||
extern operator '*' macro Int32Mul(int32, int32): int32;
|
||||
extern operator '%' macro Int32Mod(int32, int32): int32;
|
||||
extern operator '&' macro Word32And(int32, int32): int32;
|
||||
extern operator '&' macro Word32And(word32, word32): int32;
|
||||
|
||||
extern operator '==' macro Word32Equal(word32, word32): bool;
|
||||
extern operator '!=' macro Word32NotEqual(word32, word32): bool;
|
||||
extern operator '>>>' macro Word32Shr(word32, word32): word32;
|
||||
extern operator '<<' macro Word32Shl(word32, word32): word32;
|
||||
extern operator '|' macro Word32Or(word32, word32): word32;
|
||||
|
||||
@ -347,6 +352,9 @@ from_constexpr<int32>(i: constexpr int31): int32 {
|
||||
from_constexpr<word32>(i: constexpr int31): word32 {
|
||||
return from_constexpr<int32>(i);
|
||||
}
|
||||
from_constexpr<uintptr>(i: constexpr int31): uintptr {
|
||||
return ChangeUint32ToWord(i);
|
||||
}
|
||||
from_constexpr<Smi>(i: constexpr int31): Smi {
|
||||
return SmiConstant(i);
|
||||
}
|
||||
@ -400,7 +408,7 @@ macro convert<A : type>(ui: uint32): A;
|
||||
convert<Number>(ui: uint32): Number {
|
||||
return ChangeUint32ToTagged(ui);
|
||||
}
|
||||
macro convert<A: type>(word: word32): A;
|
||||
macro convert<A : type>(word: word32): A;
|
||||
convert<int32>(word: word32): int32 {
|
||||
return Signed(word);
|
||||
}
|
||||
@ -411,7 +419,7 @@ convert<uintptr>(word: word32): uintptr {
|
||||
return ChangeUint32ToWord(word);
|
||||
}
|
||||
macro convert<A : type>(i: intptr): A;
|
||||
convert<int32>(i: intptr): int32 {
|
||||
convert<word32>(i: intptr): word32 {
|
||||
return TruncateIntPtrToInt32(i);
|
||||
}
|
||||
convert<uintptr>(i: intptr): uintptr {
|
||||
@ -420,10 +428,13 @@ convert<uintptr>(i: intptr): uintptr {
|
||||
convert<Smi>(i: intptr): Smi {
|
||||
return SmiTag(i);
|
||||
}
|
||||
macro convert<A: type>(ui: uintptr): A;
|
||||
macro convert<A : type>(ui: uintptr): A;
|
||||
convert<intptr>(ui: uintptr): intptr {
|
||||
return Signed(ui);
|
||||
}
|
||||
convert<word32>(ui: uintptr): word32 {
|
||||
return TruncateIntPtrToInt32(Signed(ui));
|
||||
}
|
||||
macro convert<A : type>(s: Smi): A;
|
||||
convert<intptr>(s: Smi): intptr {
|
||||
return SmiUntag(s);
|
||||
|
@ -18,15 +18,15 @@ class DataViewBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
|
||||
: BaseBuiltinsFromDSLAssembler(state) {}
|
||||
|
||||
TNode<Smi> LoadDataViewByteOffset(TNode<JSDataView> data_view) {
|
||||
return LoadObjectField<Smi>(data_view, JSDataView::kByteOffsetOffset);
|
||||
return CAST(LoadObjectField(data_view, JSDataView::kByteOffsetOffset));
|
||||
}
|
||||
|
||||
TNode<Smi> LoadDataViewByteLength(TNode<JSDataView> data_view) {
|
||||
return LoadObjectField<Smi>(data_view, JSDataView::kByteLengthOffset);
|
||||
return CAST(LoadObjectField(data_view, JSDataView::kByteLengthOffset));
|
||||
}
|
||||
|
||||
TNode<Uint32T> LoadUint8(TNode<RawPtrT> data_pointer, TNode<IntPtrT> offset) {
|
||||
return UncheckedCast<Uint32T>(
|
||||
TNode<Int32T> LoadUint8(TNode<RawPtrT> data_pointer, TNode<IntPtrT> offset) {
|
||||
return UncheckedCast<Int32T>(
|
||||
Load(MachineType::Uint8(), data_pointer, offset));
|
||||
}
|
||||
|
||||
@ -35,6 +35,12 @@ class DataViewBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
|
||||
Load(MachineType::Int8(), data_pointer, offset));
|
||||
}
|
||||
|
||||
void StoreWord8(TNode<RawPtrT> data_pointer, TNode<IntPtrT> offset,
|
||||
TNode<Word32T> value) {
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord8, data_pointer, offset,
|
||||
value);
|
||||
}
|
||||
|
||||
int32_t DataViewElementSize(ElementsKind elements_kind) {
|
||||
return ElementsKindToByteSize(elements_kind);
|
||||
}
|
||||
@ -43,6 +49,16 @@ class DataViewBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
|
||||
return IntPtrConstant(BigInt::SignBits::encode(sign) |
|
||||
BigInt::LengthBits::encode(digits));
|
||||
}
|
||||
|
||||
TNode<UintPtrT> DataViewDecodeBigIntLength(TNode<BigInt> value) {
|
||||
TNode<WordT> bitfield = LoadBigIntBitfield(value);
|
||||
return DecodeWord<BigIntBase::LengthBits>(bitfield);
|
||||
}
|
||||
|
||||
TNode<UintPtrT> DataViewDecodeBigIntSign(TNode<BigInt> value) {
|
||||
TNode<WordT> bitfield = LoadBigIntBitfield(value);
|
||||
return DecodeWord<BigIntBase::SignBits>(bitfield);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -74,28 +74,31 @@ module data_view {
|
||||
}
|
||||
|
||||
extern macro BitcastInt32ToFloat32(word32): float32;
|
||||
extern macro BitcastFloat32ToInt32(float32): word32;
|
||||
extern macro Float64ExtractLowWord32(float64): word32;
|
||||
extern macro Float64ExtractHighWord32(float64): word32;
|
||||
extern macro Float64InsertLowWord32(float64, word32): float64;
|
||||
extern macro Float64InsertHighWord32(float64, word32): float64;
|
||||
|
||||
extern macro LoadUint8(RawPtr, intptr): int32;
|
||||
extern macro LoadInt8(RawPtr, intptr): int32;
|
||||
|
||||
macro LoadDataViewUint8(data_pointer: RawPtr, offset: intptr): Smi {
|
||||
return convert<Smi>(LoadUint8(data_pointer, offset));
|
||||
macro LoadDataViewUint8(buffer: JSArrayBuffer, offset: intptr): Smi {
|
||||
return convert<Smi>(LoadUint8(buffer.backing_store, offset));
|
||||
}
|
||||
|
||||
macro LoadDataViewInt8(data_pointer: RawPtr, offset: intptr): Smi {
|
||||
return convert<Smi>(LoadInt8(data_pointer, offset));
|
||||
macro LoadDataViewInt8(buffer: JSArrayBuffer, offset: intptr): Smi {
|
||||
return convert<Smi>(LoadInt8(buffer.backing_store, offset));
|
||||
}
|
||||
|
||||
macro LoadDataView16(data_pointer: RawPtr, offset: intptr,
|
||||
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 = LoadUint8(data_pointer, offset);
|
||||
@ -114,9 +117,10 @@ module data_view {
|
||||
}
|
||||
}
|
||||
|
||||
macro LoadDataView32(data_pointer: RawPtr, offset: intptr,
|
||||
macro LoadDataView32(buffer: JSArrayBuffer, offset: intptr,
|
||||
requested_little_endian: bool,
|
||||
signed: constexpr bool): Number {
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
let b0: word32 = LoadUint8(data_pointer, offset);
|
||||
let b1: word32 = LoadUint8(data_pointer, offset + 1);
|
||||
let b2: word32 = LoadUint8(data_pointer, offset + 2);
|
||||
@ -139,8 +143,9 @@ module data_view {
|
||||
}
|
||||
}
|
||||
|
||||
macro LoadDataViewFloat32(data_pointer: RawPtr, offset: intptr,
|
||||
macro LoadDataViewFloat32(buffer: JSArrayBuffer, offset: intptr,
|
||||
requested_little_endian: bool): HeapNumber {
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
let b0: word32 = LoadUint8(data_pointer, offset);
|
||||
let b1: word32 = LoadUint8(data_pointer, offset + 1);
|
||||
let b2: word32 = LoadUint8(data_pointer, offset + 2);
|
||||
@ -161,8 +166,9 @@ module data_view {
|
||||
return AllocateHeapNumberWithValue(float_res);
|
||||
}
|
||||
|
||||
macro LoadDataViewFloat64(data_pointer: RawPtr, offset: intptr,
|
||||
macro LoadDataViewFloat64(buffer: JSArrayBuffer, offset: intptr,
|
||||
requested_little_endian: bool): HeapNumber {
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
let b0: word32 = LoadUint8(data_pointer, offset);
|
||||
let b1: word32 = LoadUint8(data_pointer, offset + 1);
|
||||
let b2: word32 = LoadUint8(data_pointer, offset + 2);
|
||||
@ -293,9 +299,10 @@ module data_view {
|
||||
return result;
|
||||
}
|
||||
|
||||
macro LoadDataViewBigInt(data_pointer: RawPtr, offset: intptr,
|
||||
macro LoadDataViewBigInt(buffer: JSArrayBuffer, offset: intptr,
|
||||
requested_little_endian: bool,
|
||||
signed: constexpr bool): BigInt {
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
let b0: word32 = LoadUint8(data_pointer, offset);
|
||||
let b1: word32 = LoadUint8(data_pointer, offset + 1);
|
||||
let b2: word32 = LoadUint8(data_pointer, offset + 2);
|
||||
@ -345,13 +352,14 @@ module data_view {
|
||||
let data_view: JSDataView = ValidateDataView(
|
||||
context, receiver, 'get DataView.prototype.get');
|
||||
|
||||
let getIndex: Smi;
|
||||
let getIndexSmi: Smi;
|
||||
try {
|
||||
getIndex = ToSmiIndex(offset, context) otherwise RangeError;
|
||||
getIndexSmi = ToSmiIndex(offset, context) otherwise RangeError;
|
||||
}
|
||||
label RangeError {
|
||||
ThrowRangeError(context, kInvalidDataViewAccessorOffset);
|
||||
}
|
||||
let getIndex: intptr = convert<intptr>(getIndexSmi);
|
||||
|
||||
let littleEndian: bool = ToBoolean(requested_little_endian);
|
||||
let buffer: JSArrayBuffer = data_view.buffer;
|
||||
@ -360,39 +368,36 @@ module data_view {
|
||||
ThrowTypeError(context, kDetachedOperation, 'DataView.prototype.get');
|
||||
}
|
||||
|
||||
let viewOffset: Smi = data_view.byte_offset;
|
||||
let viewSize: Smi = data_view.byte_length;
|
||||
let elementSize: Smi = DataViewElementSize(kind);
|
||||
let viewOffset: intptr = convert<intptr>(data_view.byte_offset);
|
||||
let viewSize: intptr = convert<intptr>(data_view.byte_length);
|
||||
let elementSize: intptr = DataViewElementSize(kind);
|
||||
|
||||
if (getIndex + elementSize > viewSize ||
|
||||
getIndex + elementSize < getIndex) {
|
||||
// TODO(theotime): do we really need to check for overflow here?
|
||||
if (getIndex + elementSize > viewSize) {
|
||||
ThrowRangeError(context, kInvalidDataViewAccessorOffset);
|
||||
}
|
||||
|
||||
let bufferIndex: intptr = convert<intptr>(getIndex + viewOffset);
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
let bufferIndex: intptr = getIndex + viewOffset;
|
||||
|
||||
if constexpr (kind == UINT8_ELEMENTS) {
|
||||
return LoadDataViewUint8(data_pointer, bufferIndex);
|
||||
return LoadDataViewUint8(buffer, bufferIndex);
|
||||
} else if constexpr (kind == INT8_ELEMENTS) {
|
||||
return LoadDataViewInt8(data_pointer, bufferIndex);
|
||||
return LoadDataViewInt8(buffer, bufferIndex);
|
||||
} else if constexpr (kind == UINT16_ELEMENTS) {
|
||||
return LoadDataView16(data_pointer, bufferIndex, littleEndian, false);
|
||||
return LoadDataView16(buffer, bufferIndex, littleEndian, false);
|
||||
} else if constexpr (kind == INT16_ELEMENTS) {
|
||||
return LoadDataView16(data_pointer, bufferIndex, littleEndian, true);
|
||||
return LoadDataView16(buffer, bufferIndex, littleEndian, true);
|
||||
} else if constexpr (kind == UINT32_ELEMENTS) {
|
||||
return LoadDataView32(data_pointer, bufferIndex, littleEndian, false);
|
||||
return LoadDataView32(buffer, bufferIndex, littleEndian, false);
|
||||
} else if constexpr (kind == INT32_ELEMENTS) {
|
||||
return LoadDataView32(data_pointer, bufferIndex, littleEndian, true);
|
||||
return LoadDataView32(buffer, bufferIndex, littleEndian, true);
|
||||
} else if constexpr (kind == FLOAT32_ELEMENTS) {
|
||||
return LoadDataViewFloat32(data_pointer, bufferIndex, littleEndian);
|
||||
return LoadDataViewFloat32(buffer, bufferIndex, littleEndian);
|
||||
} else if constexpr (kind == FLOAT64_ELEMENTS) {
|
||||
return LoadDataViewFloat64(data_pointer, bufferIndex, littleEndian);
|
||||
return LoadDataViewFloat64(buffer, bufferIndex, littleEndian);
|
||||
} else if constexpr (kind == BIGINT64_ELEMENTS) {
|
||||
return LoadDataViewBigInt(data_pointer, bufferIndex, littleEndian, true);
|
||||
return LoadDataViewBigInt(buffer, bufferIndex, littleEndian, true);
|
||||
} else if constexpr (kind == BIGUINT64_ELEMENTS) {
|
||||
return LoadDataViewBigInt(data_pointer, bufferIndex, littleEndian, false);
|
||||
return LoadDataViewBigInt(buffer, bufferIndex, littleEndian, false);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
@ -510,27 +515,218 @@ module data_view {
|
||||
BIGUINT64_ELEMENTS);
|
||||
}
|
||||
|
||||
// Context, receiver, byteOffset, value, littleEndian
|
||||
extern runtime
|
||||
DataViewSetInt8(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetUint8(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetInt16(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetUint16(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetInt32(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetUint32(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetFloat32(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetFloat64(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetBigInt64(Context, Object, Object, Object, Object): Object;
|
||||
extern runtime
|
||||
DataViewSetBigUint64(Context, Object, Object, Object, Object): Object;
|
||||
extern macro ToNumber(Context, Object): Number;
|
||||
extern macro ToBigInt(Context, Object): BigInt;
|
||||
extern macro TruncateFloat64ToFloat32(float64): float32;
|
||||
extern macro TruncateFloat64ToWord32(float64): word32;
|
||||
|
||||
extern macro StoreWord8(RawPtr, intptr, word32): void;
|
||||
|
||||
macro StoreDataView8(buffer: JSArrayBuffer, offset: intptr,
|
||||
value: word32): void {
|
||||
StoreWord8(buffer.backing_store, offset, value & 0xFF);
|
||||
}
|
||||
|
||||
macro StoreDataView16(buffer: JSArrayBuffer, offset: intptr, value: word32,
|
||||
requested_little_endian: bool): void {
|
||||
let b0: word32 = value & 0xFF;
|
||||
let b1: word32 = (value >>> 8) & 0xFF;
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
|
||||
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: word32,
|
||||
requested_little_endian: bool): void {
|
||||
let b0: word32 = value & 0xFF;
|
||||
let b1: word32 = (value >>> 8) & 0xFF;
|
||||
let b2: word32 = (value >>> 16) & 0xFF;
|
||||
let b3: word32 = value >>> 24; // We don't need to mask here.
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
|
||||
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: word32, high_word: word32,
|
||||
requested_little_endian: bool): void {
|
||||
let b0: word32 = low_word & 0xFF;
|
||||
let b1: word32 = (low_word >>> 8) & 0xFF;
|
||||
let b2: word32 = (low_word >>> 16) & 0xFF;
|
||||
let b3: word32 = low_word >>> 24;
|
||||
|
||||
let b4: word32 = high_word & 0xFF;
|
||||
let b5: word32 = (high_word >>> 8) & 0xFF;
|
||||
let b6: word32 = (high_word >>> 16) & 0xFF;
|
||||
let b7: word32 = high_word >>> 24;
|
||||
|
||||
let data_pointer: RawPtr = buffer.backing_store;
|
||||
|
||||
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): void {
|
||||
|
||||
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: word32 = 0;
|
||||
let high_word: word32 = 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<word32>(value); // Truncates value to 32 bits.
|
||||
high_word = convert<word32>(value >>> 32);
|
||||
}
|
||||
else { // There might be either 1 or 2 BigInt digits we need to load.
|
||||
low_word = convert<word32>(LoadBigIntDigit(bigint_value, 0));
|
||||
if (length >= 2) { // Only load the second digit if there is one.
|
||||
high_word = convert<word32>(LoadBigIntDigit(bigint_value, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sign != 0) { // The number is negative, convert it.
|
||||
high_word = 0 - convert<int32>(high_word);
|
||||
if (low_word != 0) {
|
||||
high_word = convert<int32>(high_word) - 1;
|
||||
}
|
||||
low_word = 0 - convert<int32>(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 getIndexSmi: Smi;
|
||||
try {
|
||||
getIndexSmi = ToSmiIndex(offset, context) otherwise RangeError;
|
||||
}
|
||||
label RangeError {
|
||||
ThrowRangeError(context, kInvalidDataViewAccessorOffset);
|
||||
}
|
||||
let getIndex: intptr = convert<intptr>(getIndexSmi);
|
||||
|
||||
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: intptr = convert<intptr>(data_view.byte_offset);
|
||||
let viewSize: intptr = convert<intptr>(data_view.byte_length);
|
||||
let elementSize: intptr = DataViewElementSize(kind);
|
||||
|
||||
if (getIndex + elementSize > viewSize) {
|
||||
ThrowRangeError(context, kInvalidDataViewAccessorOffset);
|
||||
}
|
||||
|
||||
let bufferIndex: intptr = getIndex + viewOffset;
|
||||
|
||||
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: word32 = Float64ExtractLowWord32(double_value);
|
||||
let high_word: word32 = Float64ExtractHighWord32(double_value);
|
||||
StoreDataView64(buffer, bufferIndex, low_word, high_word,
|
||||
littleEndian);
|
||||
}
|
||||
}
|
||||
return Undefined;
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetInt8(
|
||||
context: Context, receiver: Object, ...arguments): Object {
|
||||
@ -540,7 +736,8 @@ module data_view {
|
||||
let value : Object = arguments.length > 1 ?
|
||||
arguments[1] :
|
||||
Undefined;
|
||||
return DataViewSetInt8(context, receiver, offset, value, Undefined);
|
||||
return DataViewSet(context, receiver, offset, value, Undefined,
|
||||
INT8_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetUint8(
|
||||
@ -551,7 +748,8 @@ module data_view {
|
||||
let value : Object = arguments.length > 1 ?
|
||||
arguments[1] :
|
||||
Undefined;
|
||||
return DataViewSetUint8(context, receiver, offset, value, Undefined);
|
||||
return DataViewSet(context, receiver, offset, value, Undefined,
|
||||
UINT8_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetInt16(
|
||||
@ -565,8 +763,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetInt16(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, INT16_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetUint16(
|
||||
@ -580,8 +778,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetUint16(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, UINT16_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetInt32(
|
||||
@ -595,8 +793,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetInt32(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, INT32_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetUint32(
|
||||
@ -610,8 +808,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetUint32(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, UINT32_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetFloat32(
|
||||
@ -625,8 +823,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetFloat32(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, FLOAT32_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetFloat64(
|
||||
@ -640,8 +838,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetFloat64(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, FLOAT64_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetBigInt64(
|
||||
@ -655,8 +853,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetBigInt64(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, BIGINT64_ELEMENTS);
|
||||
}
|
||||
|
||||
javascript builtin DataViewPrototypeSetBigUint64(
|
||||
@ -670,8 +868,8 @@ module data_view {
|
||||
let is_little_endian : Object = arguments.length > 2 ?
|
||||
arguments[2] :
|
||||
Undefined;
|
||||
return DataViewSetBigUint64(context, receiver, offset, value,
|
||||
is_little_endian);
|
||||
return DataViewSet(context, receiver, offset, value,
|
||||
is_little_endian, BIGUINT64_ELEMENTS);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -525,6 +525,7 @@ TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
|
||||
V(ChangeUint32ToFloat64, Float64T, Word32T) \
|
||||
V(ChangeUint32ToUint64, Uint64T, Word32T) \
|
||||
V(BitcastInt32ToFloat32, Float32T, Word32T) \
|
||||
V(BitcastFloat32ToInt32, Word32T, Float32T) \
|
||||
V(RoundFloat64ToInt32, Int32T, Float64T) \
|
||||
V(RoundInt32ToFloat32, Int32T, Float32T) \
|
||||
V(Float64SilenceNaN, Float64T, Float64T) \
|
||||
|
@ -1,210 +0,0 @@
|
||||
// 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.
|
||||
|
||||
#include "src/runtime/runtime-utils.h"
|
||||
|
||||
#include "src/arguments.h"
|
||||
#include "src/elements.h"
|
||||
#include "src/heap/factory.h"
|
||||
#include "src/messages.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/runtime/runtime.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
bool NeedToFlipBytes(bool is_little_endian) {
|
||||
#ifdef V8_TARGET_LITTLE_ENDIAN
|
||||
return !is_little_endian;
|
||||
#else
|
||||
return is_little_endian;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <size_t n>
|
||||
void CopyBytes(uint8_t* target, uint8_t const* source) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
*(target++) = *(source++);
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t n>
|
||||
void FlipBytes(uint8_t* target, uint8_t const* source) {
|
||||
source = source + (n - 1);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
*(target++) = *(source--);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MaybeHandle<Object> DataViewConvertInput(Isolate* isolate,
|
||||
Handle<Object> input) {
|
||||
return Object::ToNumber(input);
|
||||
}
|
||||
|
||||
template <>
|
||||
MaybeHandle<Object> DataViewConvertInput<int64_t>(Isolate* isolate,
|
||||
Handle<Object> input) {
|
||||
return BigInt::FromObject(isolate, input);
|
||||
}
|
||||
|
||||
template <>
|
||||
MaybeHandle<Object> DataViewConvertInput<uint64_t>(Isolate* isolate,
|
||||
Handle<Object> input) {
|
||||
return BigInt::FromObject(isolate, input);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T DataViewConvertValue(Handle<Object> value);
|
||||
|
||||
template <>
|
||||
int8_t DataViewConvertValue<int8_t>(Handle<Object> value) {
|
||||
return static_cast<int8_t>(DoubleToInt32(value->Number()));
|
||||
}
|
||||
|
||||
template <>
|
||||
int16_t DataViewConvertValue<int16_t>(Handle<Object> value) {
|
||||
return static_cast<int16_t>(DoubleToInt32(value->Number()));
|
||||
}
|
||||
|
||||
template <>
|
||||
int32_t DataViewConvertValue<int32_t>(Handle<Object> value) {
|
||||
return DoubleToInt32(value->Number());
|
||||
}
|
||||
|
||||
template <>
|
||||
uint8_t DataViewConvertValue<uint8_t>(Handle<Object> value) {
|
||||
return static_cast<uint8_t>(DoubleToUint32(value->Number()));
|
||||
}
|
||||
|
||||
template <>
|
||||
uint16_t DataViewConvertValue<uint16_t>(Handle<Object> value) {
|
||||
return static_cast<uint16_t>(DoubleToUint32(value->Number()));
|
||||
}
|
||||
|
||||
template <>
|
||||
uint32_t DataViewConvertValue<uint32_t>(Handle<Object> value) {
|
||||
return DoubleToUint32(value->Number());
|
||||
}
|
||||
|
||||
template <>
|
||||
float DataViewConvertValue<float>(Handle<Object> value) {
|
||||
return static_cast<float>(value->Number());
|
||||
}
|
||||
|
||||
template <>
|
||||
double DataViewConvertValue<double>(Handle<Object> value) {
|
||||
return value->Number();
|
||||
}
|
||||
|
||||
template <>
|
||||
int64_t DataViewConvertValue<int64_t>(Handle<Object> value) {
|
||||
return BigInt::cast(*value)->AsInt64();
|
||||
}
|
||||
|
||||
template <>
|
||||
uint64_t DataViewConvertValue<uint64_t>(Handle<Object> value) {
|
||||
return BigInt::cast(*value)->AsUint64();
|
||||
}
|
||||
|
||||
// ES6 section 24.2.1.2 SetViewValue (view, requestIndex, isLittleEndian, type,
|
||||
// value)
|
||||
template <typename T>
|
||||
MaybeHandle<Object> SetViewValue(Isolate* isolate, Handle<JSDataView> data_view,
|
||||
Handle<Object> request_index,
|
||||
bool is_little_endian, Handle<Object> value,
|
||||
const char* method) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, request_index,
|
||||
Object::ToIndex(isolate, request_index,
|
||||
MessageTemplate::kInvalidDataViewAccessorOffset),
|
||||
Object);
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
|
||||
DataViewConvertInput<T>(isolate, value), Object);
|
||||
size_t get_index = 0;
|
||||
if (!TryNumberToSize(*request_index, &get_index)) {
|
||||
THROW_NEW_ERROR(
|
||||
isolate, NewRangeError(MessageTemplate::kInvalidDataViewAccessorOffset),
|
||||
Object);
|
||||
}
|
||||
Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()),
|
||||
isolate);
|
||||
if (buffer->was_neutered()) {
|
||||
Handle<String> operation =
|
||||
isolate->factory()->NewStringFromAsciiChecked(method);
|
||||
THROW_NEW_ERROR(
|
||||
isolate, NewTypeError(MessageTemplate::kDetachedOperation, operation),
|
||||
Object);
|
||||
}
|
||||
size_t const data_view_byte_offset = NumberToSize(data_view->byte_offset());
|
||||
size_t const data_view_byte_length = NumberToSize(data_view->byte_length());
|
||||
if (get_index + sizeof(T) > data_view_byte_length ||
|
||||
get_index + sizeof(T) < get_index) { // overflow
|
||||
THROW_NEW_ERROR(
|
||||
isolate, NewRangeError(MessageTemplate::kInvalidDataViewAccessorOffset),
|
||||
Object);
|
||||
}
|
||||
union {
|
||||
T data;
|
||||
uint8_t bytes[sizeof(T)];
|
||||
} v;
|
||||
v.data = DataViewConvertValue<T>(value);
|
||||
size_t const buffer_offset = data_view_byte_offset + get_index;
|
||||
DCHECK(NumberToSize(buffer->byte_length()) >= buffer_offset + sizeof(T));
|
||||
uint8_t* const target =
|
||||
static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
|
||||
if (NeedToFlipBytes(is_little_endian)) {
|
||||
FlipBytes<sizeof(T)>(target, v.bytes);
|
||||
} else {
|
||||
CopyBytes<sizeof(T)>(target, v.bytes);
|
||||
}
|
||||
return isolate->factory()->undefined_value();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#define CHECK_RECEIVER_OBJECT(method) \
|
||||
Handle<Object> receiver = args.at<Object>(0); \
|
||||
if (!receiver->IsJSDataView()) { \
|
||||
THROW_NEW_ERROR_RETURN_FAILURE( \
|
||||
isolate, \
|
||||
NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
|
||||
isolate->factory()->NewStringFromAsciiChecked(method), \
|
||||
receiver)); \
|
||||
} \
|
||||
Handle<JSDataView> data_view = Handle<JSDataView>::cast(receiver);
|
||||
|
||||
#define DATA_VIEW_PROTOTYPE_SET(Type, type) \
|
||||
RUNTIME_FUNCTION(Runtime_DataViewSet##Type) { \
|
||||
HandleScope scope(isolate); \
|
||||
CHECK_RECEIVER_OBJECT("DataView.prototype.set" #Type); \
|
||||
Handle<Object> byte_offset = args.at<Object>(1); \
|
||||
Handle<Object> value = args.at<Object>(2); \
|
||||
Handle<Object> is_little_endian = args.at<Object>(3); \
|
||||
Handle<Object> result; \
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
|
||||
isolate, result, \
|
||||
SetViewValue<type>(isolate, data_view, byte_offset, \
|
||||
is_little_endian->BooleanValue(isolate), value, \
|
||||
"DataView.prototype.set" #Type)); \
|
||||
return *result; \
|
||||
}
|
||||
|
||||
DATA_VIEW_PROTOTYPE_SET(Int8, int8_t)
|
||||
DATA_VIEW_PROTOTYPE_SET(Uint8, uint8_t)
|
||||
DATA_VIEW_PROTOTYPE_SET(Int16, int16_t)
|
||||
DATA_VIEW_PROTOTYPE_SET(Uint16, uint16_t)
|
||||
DATA_VIEW_PROTOTYPE_SET(Int32, int32_t)
|
||||
DATA_VIEW_PROTOTYPE_SET(Uint32, uint32_t)
|
||||
DATA_VIEW_PROTOTYPE_SET(Float32, float)
|
||||
DATA_VIEW_PROTOTYPE_SET(Float64, double)
|
||||
DATA_VIEW_PROTOTYPE_SET(BigInt64, int64_t)
|
||||
DATA_VIEW_PROTOTYPE_SET(BigUint64, uint64_t)
|
||||
#undef DATA_VIEW_PROTOTYPE_SET
|
||||
|
||||
#undef CHECK_RECEIVER_OBJECT
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -569,18 +569,6 @@ namespace internal {
|
||||
F(TypedArraySet, 2, 1) \
|
||||
F(TypedArraySortFast, 1, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_DATAVIEW(F) \
|
||||
F(DataViewSetInt8, 2, 1) \
|
||||
F(DataViewSetUint8, 2, 1) \
|
||||
F(DataViewSetInt16, 3, 1) \
|
||||
F(DataViewSetUint16, 3, 1) \
|
||||
F(DataViewSetInt32, 3, 1) \
|
||||
F(DataViewSetUint32, 3, 1) \
|
||||
F(DataViewSetFloat32, 3, 1) \
|
||||
F(DataViewSetFloat64, 3, 1) \
|
||||
F(DataViewSetBigInt64, 3, 1) \
|
||||
F(DataViewSetBigUint64, 3, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_WASM(F) \
|
||||
F(ThrowWasmError, 1, 1) \
|
||||
F(ThrowWasmStackOverflow, 0, 1) \
|
||||
@ -649,7 +637,6 @@ namespace internal {
|
||||
FOR_EACH_INTRINSIC_SYMBOL(F) \
|
||||
FOR_EACH_INTRINSIC_TEST(F) \
|
||||
FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
|
||||
FOR_EACH_INTRINSIC_DATAVIEW(F) \
|
||||
FOR_EACH_INTRINSIC_WASM(F)
|
||||
|
||||
// FOR_EACH_INTRINSIC defines the list of all intrinsics, coming in 2 flavors,
|
||||
|
Loading…
Reference in New Issue
Block a user