Commit 3ef16185 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

Reland "[bigint] Implement DataView.{get,set}Big*64"

Originally reviewed at https://chromium-review.googlesource.com/929429
and landed as r51486 / d50c7731.

Update in reland: whitelisted new builtins as side effect free.

Bug: v8:6791
Change-Id: Iff45700c8a4eca23f3ee6fc9c0cb340dc027cbc6
Reviewed-on: https://chromium-review.googlesource.com/932802
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51491}
parent 34ba47da
......@@ -4404,6 +4404,20 @@ void Genesis::InitializeGlobal_harmony_bigint() {
JSObject::AddProperty(prototype, factory->to_string_tag_symbol(),
factory->BigInt_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
// Install 64-bit DataView accessors.
// TODO(jkummerow): Move these to the "DataView" section when dropping the
// FLAG_harmony_bigint.
Handle<JSObject> dataview_prototype(
JSObject::cast(native_context()->data_view_fun()->instance_prototype()));
SimpleInstallFunction(dataview_prototype, "getBigInt64",
Builtins::kDataViewPrototypeGetBigInt64, 1, false);
SimpleInstallFunction(dataview_prototype, "setBigInt64",
Builtins::kDataViewPrototypeSetBigInt64, 2, false);
SimpleInstallFunction(dataview_prototype, "getBigUint64",
Builtins::kDataViewPrototypeGetBigUint64, 1, false);
SimpleInstallFunction(dataview_prototype, "setBigUint64",
Builtins::kDataViewPrototypeSetBigUint64, 2, false);
}
#ifdef V8_INTL_SUPPORT
......
......@@ -157,6 +157,21 @@ void FlipBytes(uint8_t* target, uint8_t const* source) {
}
}
template <typename T>
MaybeHandle<Object> AllocateResult(Isolate* isolate, T value) {
return isolate->factory()->NewNumber(value);
}
template <>
MaybeHandle<Object> AllocateResult(Isolate* isolate, int64_t value) {
return BigInt::FromInt64(isolate, value);
}
template <>
MaybeHandle<Object> AllocateResult(Isolate* isolate, uint64_t value) {
return BigInt::FromUint64(isolate, value);
}
// ES6 section 24.2.1.1 GetViewValue (view, requestIndex, isLittleEndian, type)
template <typename T>
MaybeHandle<Object> GetViewValue(Isolate* isolate, Handle<JSDataView> data_view,
......@@ -196,50 +211,78 @@ MaybeHandle<Object> GetViewValue(Isolate* isolate, Handle<JSDataView> data_view,
} else {
CopyBytes<sizeof(T)>(v.bytes, source);
}
return isolate->factory()->NewNumber(v.data);
return AllocateResult<T>(isolate, v.data);
}
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(double value);
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 <>
int8_t DataViewConvertValue<int8_t>(double value) {
return static_cast<int8_t>(DoubleToInt32(value));
int32_t DataViewConvertValue<int32_t>(Handle<Object> value) {
return DoubleToInt32(value->Number());
}
template <>
int16_t DataViewConvertValue<int16_t>(double value) {
return static_cast<int16_t>(DoubleToInt32(value));
uint8_t DataViewConvertValue<uint8_t>(Handle<Object> value) {
return static_cast<uint8_t>(DoubleToUint32(value->Number()));
}
template <>
int32_t DataViewConvertValue<int32_t>(double value) {
return DoubleToInt32(value);
uint16_t DataViewConvertValue<uint16_t>(Handle<Object> value) {
return static_cast<uint16_t>(DoubleToUint32(value->Number()));
}
template <>
uint8_t DataViewConvertValue<uint8_t>(double value) {
return static_cast<uint8_t>(DoubleToUint32(value));
uint32_t DataViewConvertValue<uint32_t>(Handle<Object> value) {
return DoubleToUint32(value->Number());
}
template <>
uint16_t DataViewConvertValue<uint16_t>(double value) {
return static_cast<uint16_t>(DoubleToUint32(value));
float DataViewConvertValue<float>(Handle<Object> value) {
return static_cast<float>(value->Number());
}
template <>
uint32_t DataViewConvertValue<uint32_t>(double value) {
return DoubleToUint32(value);
double DataViewConvertValue<double>(Handle<Object> value) {
return value->Number();
}
template <>
float DataViewConvertValue<float>(double value) {
return static_cast<float>(value);
int64_t DataViewConvertValue<int64_t>(Handle<Object> value) {
return BigInt::cast(*value)->AsInt64();
}
template <>
double DataViewConvertValue<double>(double value) {
return value;
uint64_t DataViewConvertValue<uint64_t>(Handle<Object> value) {
return BigInt::cast(*value)->AsUint64();
}
// ES6 section 24.2.1.2 SetViewValue (view, requestIndex, isLittleEndian, type,
......@@ -253,7 +296,8 @@ MaybeHandle<Object> SetViewValue(Isolate* isolate, Handle<JSDataView> data_view,
Object::ToIndex(isolate, request_index,
MessageTemplate::kInvalidDataViewAccessorOffset),
Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::ToNumber(value), 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(
......@@ -274,7 +318,7 @@ MaybeHandle<Object> SetViewValue(Isolate* isolate, Handle<JSDataView> data_view,
T data;
uint8_t bytes[sizeof(T)];
} v;
v.data = DataViewConvertValue<T>(value->Number());
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 =
......@@ -310,6 +354,8 @@ DATA_VIEW_PROTOTYPE_GET(Int32, int32_t)
DATA_VIEW_PROTOTYPE_GET(Uint32, uint32_t)
DATA_VIEW_PROTOTYPE_GET(Float32, float)
DATA_VIEW_PROTOTYPE_GET(Float64, double)
DATA_VIEW_PROTOTYPE_GET(BigInt64, int64_t)
DATA_VIEW_PROTOTYPE_GET(BigUint64, uint64_t)
#undef DATA_VIEW_PROTOTYPE_GET
#define DATA_VIEW_PROTOTYPE_SET(Type, type) \
......@@ -334,6 +380,8 @@ 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
} // namespace internal
......
......@@ -456,6 +456,10 @@ namespace internal {
CPP(DataViewPrototypeSetFloat32) \
CPP(DataViewPrototypeGetFloat64) \
CPP(DataViewPrototypeSetFloat64) \
CPP(DataViewPrototypeGetBigInt64) \
CPP(DataViewPrototypeSetBigInt64) \
CPP(DataViewPrototypeGetBigUint64) \
CPP(DataViewPrototypeSetBigUint64) \
\
/* Date */ \
CPP(DateConstructor) \
......
......@@ -614,6 +614,8 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kDataViewPrototypeGetUint32:
case Builtins::kDataViewPrototypeGetFloat32:
case Builtins::kDataViewPrototypeGetFloat64:
case Builtins::kDataViewPrototypeGetBigInt64:
case Builtins::kDataViewPrototypeGetBigUint64:
// Boolean bulitins.
case Builtins::kBooleanConstructor:
case Builtins::kBooleanPrototypeToString:
......
// 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.
// Flags: --harmony-bigint
var buffer = new ArrayBuffer(64);
var dataview = new DataView(buffer, 8, 24);
var bytes = new Uint8Array(buffer);
var b1 = 0xff1234567890abcdefn;
var b1_64 = BigInt.asUintN(64, b1);
dataview.setBigInt64(8, b1);
assertEquals(0x12, bytes[16]);
assertEquals(0x34, bytes[17]);
assertEquals(0x56, bytes[18]);
assertEquals(0x78, bytes[19]);
assertEquals(0x90, bytes[20]);
assertEquals(0xab, bytes[21]);
assertEquals(0xcd, bytes[22]);
assertEquals(0xef, bytes[23]);
assertEquals(b1_64, dataview.getBigInt64(8));
dataview.setBigInt64(8, b1, true); // Little-endian.
assertEquals(0xef, bytes[16]);
assertEquals(0xcd, bytes[17]);
assertEquals(0xab, bytes[18]);
assertEquals(0x90, bytes[19]);
assertEquals(0x78, bytes[20]);
assertEquals(0x56, bytes[21]);
assertEquals(0x34, bytes[22]);
assertEquals(0x12, bytes[23]);
assertEquals(b1_64, dataview.getBigInt64(8, true));
dataview.setBigUint64(8, b1);
assertEquals(0x12, bytes[16]);
assertEquals(0x34, bytes[17]);
assertEquals(0x56, bytes[18]);
assertEquals(0x78, bytes[19]);
assertEquals(0x90, bytes[20]);
assertEquals(0xab, bytes[21]);
assertEquals(0xcd, bytes[22]);
assertEquals(0xef, bytes[23]);
assertEquals(b1_64, dataview.getBigUint64(8));
dataview.setBigUint64(8, b1, true); // Little-endian.
assertEquals(0xef, bytes[16]);
assertEquals(0xcd, bytes[17]);
assertEquals(0xab, bytes[18]);
assertEquals(0x90, bytes[19]);
assertEquals(0x78, bytes[20]);
assertEquals(0x56, bytes[21]);
assertEquals(0x34, bytes[22]);
assertEquals(0x12, bytes[23]);
assertEquals(b1_64, dataview.getBigUint64(8, true));
var b2 = -0x76543210fedcba98n;
dataview.setBigInt64(8, b2, true);
assertEquals(0x68, bytes[16]);
assertEquals(0x45, bytes[17]);
assertEquals(0x23, bytes[18]);
assertEquals(0x01, bytes[19]);
assertEquals(0xef, bytes[20]);
assertEquals(0xcd, bytes[21]);
assertEquals(0xab, bytes[22]);
assertEquals(0x89, bytes[23]);
assertEquals(b2, dataview.getBigInt64(8, true));
assertEquals(0x89abcdef01234568n, dataview.getBigUint64(8, true));
assertThrows(() => dataview.setBigInt64(0, 1), TypeError);
assertThrows(() => dataview.setBigUint64(0, 1), TypeError);
assertThrows(() => dataview.setInt32(0, 1n), TypeError);
assertThrows(() => dataview.setUint32(0, 1n), TypeError);
// None of the stores wrote out of bounds.
for (var i = 0; i < 16; i++) assertEquals(0, bytes[i]);
for (var i = 24; i < 64; i++) assertEquals(0, bytes[i]);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment