Revert "[typedarray] Make JSTypedArray::length authoritative."
This reverts commit ad44c258d7
.
Reason for revert: Missed some users: crbug.com/v8/9105
Original change's description:
> [typedarray] Make JSTypedArray::length authoritative.
>
> This is the first step towards full huge typed array support in V8.
> Before this change, the JSTypedArray::length and the elements backing
> store length (FixedTypedArrayBase::length) were used more or less
> interchangeably to determine the number of elements in a JSTypedArray.
>
> With this change we disentangle these two lengths, and instead make
> JSTypedArray::length authoritative. For on-heap typed arrays, the
> FixedTypedArrayBase::length will remain the number of elements in the
> backing store, but for the off-heap typed arrays, this length will be
> set to 0 (matching the fact that the FixedTypedArrayBase instance does
> not contain any elements itself).
>
> This also unifies the JSTypedArray::set_/length() and length_value()
> methods to only have JSTypedArray::set_/length() which returns/takes
> size_t values. Currently this still requires the values to be in Smi
> range, but later we will extend this to allow arbitrary size_t values
> (in the safe integer range).
>
> Bug: v8:4153, v8:7881
> Change-Id: Iff9089130bb31fa9e08e0cf913e7ab52c3dbf107
> Cq-Include-Trybots: luci.chromium.try:linux-blink-rel
> Doc: http://doc/1Z-wM2qwvAuxH46e9ivtkYvKzzwYZg8ymm0x0wJaomow
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1543729
> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
> Reviewed-by: Peter Marshall <petermarshall@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Reviewed-by: Ben Titzer <titzer@chromium.org>
> Reviewed-by: Hannes Payer <hpayer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#60648}
TBR=jarin@chromium.org,titzer@chromium.org,hpayer@chromium.org,petermarshall@chromium.org,bmeurer@chromium.org
# Not skipping CQ checks because original CL landed > 1 day ago.
TBR=jarin@chromium.org, szuend@chromium.org
Bug: v8:4153, v8:7881
Change-Id: I96992bff15b4a2765ae4a557d2c37e78269c927d
Cq-Include-Trybots: luci.chromium.try:linux-blink-rel
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1593294
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61172}
This commit is contained in:
parent
d83f023e2c
commit
1810066662
@ -7589,7 +7589,7 @@ size_t v8::ArrayBufferView::ByteLength() {
|
||||
|
||||
size_t v8::TypedArray::Length() {
|
||||
i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
|
||||
return obj->WasDetached() ? 0 : obj->length();
|
||||
return obj->WasDetached() ? 0 : obj->length_value();
|
||||
}
|
||||
|
||||
static_assert(v8::TypedArray::kMaxLength == i::Smi::kMaxValue,
|
||||
|
@ -470,8 +470,9 @@ extern class JSArrayBufferView extends JSObject {
|
||||
}
|
||||
|
||||
extern class JSTypedArray extends JSArrayBufferView {
|
||||
AttachOffHeapBuffer(buffer: JSArrayBuffer, map: Map, byteOffset: uintptr):
|
||||
void {
|
||||
AttachOffHeapBuffer(
|
||||
buffer: JSArrayBuffer, map: Map, length: PositiveSmi,
|
||||
byteOffset: uintptr): void {
|
||||
const basePointer: Smi = 0;
|
||||
|
||||
// The max byteOffset is 8 * MaxSmi on the particular platform. 32 bit
|
||||
@ -492,7 +493,7 @@ extern class JSTypedArray extends JSArrayBufferView {
|
||||
this.buffer = buffer;
|
||||
this.elements = new FixedTypedArrayBase{
|
||||
map,
|
||||
length: 0,
|
||||
length,
|
||||
base_pointer: basePointer,
|
||||
external_pointer: externalPointer
|
||||
};
|
||||
|
@ -74,7 +74,8 @@ V8_WARN_UNUSED_RESULT Maybe<size_t> ValidateAtomicAccess(
|
||||
|
||||
size_t access_index;
|
||||
if (!TryNumberToSize(*access_index_obj, &access_index) ||
|
||||
typed_array->WasDetached() || access_index >= typed_array->length()) {
|
||||
typed_array->WasDetached() ||
|
||||
access_index >= typed_array->length_value()) {
|
||||
isolate->Throw(*isolate->factory()->NewRangeError(
|
||||
MessageTemplate::kInvalidAtomicAccessIndex));
|
||||
return Nothing<size_t>();
|
||||
|
@ -51,7 +51,7 @@ BUILTIN(TypedArrayPrototypeCopyWithin) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
|
||||
|
||||
int64_t len = array->length();
|
||||
int64_t len = array->length_value();
|
||||
int64_t to = 0;
|
||||
int64_t from = 0;
|
||||
int64_t final = len;
|
||||
@ -124,7 +124,7 @@ BUILTIN(TypedArrayPrototypeFill) {
|
||||
Object::ToNumber(isolate, obj_value));
|
||||
}
|
||||
|
||||
int64_t len = array->length();
|
||||
int64_t len = array->length_value();
|
||||
int64_t start = 0;
|
||||
int64_t end = len;
|
||||
|
||||
@ -171,7 +171,7 @@ BUILTIN(TypedArrayPrototypeIncludes) {
|
||||
|
||||
if (args.length() < 2) return ReadOnlyRoots(isolate).false_value();
|
||||
|
||||
int64_t len = array->length();
|
||||
int64_t len = array->length_value();
|
||||
if (len == 0) return ReadOnlyRoots(isolate).false_value();
|
||||
|
||||
int64_t index = 0;
|
||||
@ -203,7 +203,7 @@ BUILTIN(TypedArrayPrototypeIndexOf) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
|
||||
|
||||
int64_t len = array->length();
|
||||
int64_t len = array->length_value();
|
||||
if (len == 0) return Smi::FromInt(-1);
|
||||
|
||||
int64_t index = 0;
|
||||
@ -234,7 +234,7 @@ BUILTIN(TypedArrayPrototypeLastIndexOf) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
|
||||
|
||||
int64_t len = array->length();
|
||||
int64_t len = array->length_value();
|
||||
if (len == 0) return Smi::FromInt(-1);
|
||||
|
||||
int64_t index = len - 1;
|
||||
|
@ -73,7 +73,8 @@ namespace typed_array_createtypedarray {
|
||||
label AttachOffHeapBuffer(bufferObj: Object) {
|
||||
const buffer = Cast<JSArrayBuffer>(bufferObj) otherwise unreachable;
|
||||
const byteOffset: uintptr = 0;
|
||||
typedArray.AttachOffHeapBuffer(buffer, elementsInfo.map, byteOffset);
|
||||
typedArray.AttachOffHeapBuffer(
|
||||
buffer, elementsInfo.map, length, byteOffset);
|
||||
}
|
||||
|
||||
const byteOffset: uintptr = 0;
|
||||
@ -236,7 +237,8 @@ namespace typed_array_createtypedarray {
|
||||
}
|
||||
|
||||
SetupTypedArray(typedArray, newLength, offset, newByteLength);
|
||||
typedArray.AttachOffHeapBuffer(buffer, elementsInfo.map, offset);
|
||||
typedArray.AttachOffHeapBuffer(
|
||||
buffer, elementsInfo.map, newLength, offset);
|
||||
}
|
||||
label IfInvalidAlignment(problemString: String) deferred {
|
||||
ThrowInvalidTypedArrayAlignment(typedArray.map, problemString);
|
||||
|
@ -10494,6 +10494,12 @@ void CodeStubAssembler::EmitBigTypedArrayElementStore(
|
||||
TVARIABLE(UintPtrT, var_high);
|
||||
BigIntToRawBytes(bigint_value, &var_low, &var_high);
|
||||
|
||||
// Assert that offset < elements.length. Given that it's an offset for a raw
|
||||
// pointer we correct it by the usual kHeapObjectTag offset.
|
||||
CSA_ASSERT(
|
||||
this, IsOffsetInBounds(offset, LoadAndUntagFixedArrayBaseLength(elements),
|
||||
kHeapObjectTag, BIGINT64_ELEMENTS));
|
||||
|
||||
MachineRepresentation rep = WordT::kMachineRepresentation;
|
||||
#if defined(V8_TARGET_BIG_ENDIAN)
|
||||
if (!Is64()) {
|
||||
|
@ -354,7 +354,7 @@ class JSTypedArrayData : public JSObjectData {
|
||||
Handle<JSTypedArray> object);
|
||||
|
||||
bool is_on_heap() const { return is_on_heap_; }
|
||||
size_t length() const { return length_; }
|
||||
size_t length_value() const { return length_value_; }
|
||||
void* elements_external_pointer() const { return elements_external_pointer_; }
|
||||
|
||||
void Serialize(JSHeapBroker* broker);
|
||||
@ -364,7 +364,7 @@ class JSTypedArrayData : public JSObjectData {
|
||||
|
||||
private:
|
||||
bool const is_on_heap_;
|
||||
size_t const length_;
|
||||
size_t const length_value_;
|
||||
void* const elements_external_pointer_;
|
||||
|
||||
bool serialized_ = false;
|
||||
@ -375,7 +375,7 @@ JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
|
||||
Handle<JSTypedArray> object)
|
||||
: JSObjectData(broker, storage, object),
|
||||
is_on_heap_(object->is_on_heap()),
|
||||
length_(object->length()),
|
||||
length_value_(object->length_value()),
|
||||
elements_external_pointer_(
|
||||
FixedTypedArrayBase::cast(object->elements())->external_pointer()) {}
|
||||
|
||||
@ -2601,7 +2601,7 @@ BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
|
||||
BIMODAL_ACCESSOR(JSFunction, FeedbackVector, feedback_vector)
|
||||
|
||||
BIMODAL_ACCESSOR_C(JSTypedArray, bool, is_on_heap)
|
||||
BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length)
|
||||
BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length_value)
|
||||
BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
|
||||
|
||||
BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
|
||||
|
@ -635,7 +635,7 @@ class JSTypedArrayRef : public JSObjectRef {
|
||||
Handle<JSTypedArray> object() const;
|
||||
|
||||
bool is_on_heap() const;
|
||||
size_t length() const;
|
||||
size_t length_value() const;
|
||||
void* elements_external_pointer() const;
|
||||
|
||||
void Serialize();
|
||||
|
@ -2572,7 +2572,8 @@ JSNativeContextSpecialization::BuildElementAccess(
|
||||
GetTypedArrayConstant(broker(), receiver);
|
||||
if (typed_array.has_value()) {
|
||||
buffer = jsgraph()->Constant(typed_array->buffer());
|
||||
length = jsgraph()->Constant(static_cast<double>(typed_array->length()));
|
||||
length =
|
||||
jsgraph()->Constant(static_cast<double>(typed_array->length_value()));
|
||||
|
||||
// Load the (known) base and external pointer for the {receiver}. The
|
||||
// {external_pointer} might be invalid if the {buffer} was detached, so
|
||||
|
@ -148,9 +148,8 @@ void DebugPropertyIterator::FillKeysForCurrentPrototypeAndStage() {
|
||||
bool has_exotic_indices = receiver->IsJSTypedArray();
|
||||
if (stage_ == kExoticIndices) {
|
||||
if (!has_exotic_indices) return;
|
||||
// TODO(bmeurer, v8:4153): Change this to size_t later.
|
||||
exotic_length_ =
|
||||
static_cast<uint32_t>(Handle<JSTypedArray>::cast(receiver)->length());
|
||||
exotic_length_ = static_cast<uint32_t>(
|
||||
Handle<JSTypedArray>::cast(receiver)->length_value());
|
||||
return;
|
||||
}
|
||||
bool skip_indices = has_exotic_indices;
|
||||
|
@ -3080,10 +3080,8 @@ class TypedElementsAccessor
|
||||
|
||||
static uint32_t GetCapacityImpl(JSObject holder,
|
||||
FixedArrayBase backing_store) {
|
||||
JSTypedArray typed_array = JSTypedArray::cast(holder);
|
||||
if (WasDetached(typed_array)) return 0;
|
||||
// TODO(bmeurer, v8:4153): We need to support arbitrary size_t here.
|
||||
return static_cast<uint32_t>(typed_array->length());
|
||||
if (WasDetached(holder)) return 0;
|
||||
return backing_store->length();
|
||||
}
|
||||
|
||||
static uint32_t NumberOfElementsImpl(JSObject receiver,
|
||||
@ -3135,7 +3133,7 @@ class TypedElementsAccessor
|
||||
// Ensure indexes are within array bounds
|
||||
CHECK_LE(0, start);
|
||||
CHECK_LE(start, end);
|
||||
CHECK_LE(end, array->length());
|
||||
CHECK_LE(end, array->length_value());
|
||||
|
||||
DisallowHeapAllocation no_gc;
|
||||
BackingStore elements = BackingStore::cast(receiver->elements());
|
||||
@ -3155,24 +3153,23 @@ class TypedElementsAccessor
|
||||
Handle<Object> value,
|
||||
uint32_t start_from, uint32_t length) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
JSTypedArray typed_array = JSTypedArray::cast(*receiver);
|
||||
|
||||
// TODO(caitp): return Just(false) here when implementing strict throwing on
|
||||
// detached views.
|
||||
if (WasDetached(typed_array)) {
|
||||
if (WasDetached(*receiver)) {
|
||||
return Just(value->IsUndefined(isolate) && length > start_from);
|
||||
}
|
||||
|
||||
BackingStore elements = BackingStore::cast(typed_array->elements());
|
||||
if (value->IsUndefined(isolate) && length > typed_array->length()) {
|
||||
BackingStore elements = BackingStore::cast(receiver->elements());
|
||||
if (value->IsUndefined(isolate) &&
|
||||
length > static_cast<uint32_t>(elements->length())) {
|
||||
return Just(true);
|
||||
}
|
||||
ctype typed_search_value;
|
||||
// Prototype has no elements, and not searching for the hole --- limit
|
||||
// search to backing store length.
|
||||
if (typed_array->length() < length) {
|
||||
// TODO(bmeurer, v8:4153): Don't cast to uint32_t here.
|
||||
length = static_cast<uint32_t>(typed_array->length());
|
||||
if (static_cast<uint32_t>(elements->length()) < length) {
|
||||
length = elements->length();
|
||||
}
|
||||
|
||||
if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
|
||||
@ -3218,11 +3215,10 @@ class TypedElementsAccessor
|
||||
Handle<Object> value,
|
||||
uint32_t start_from, uint32_t length) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
JSTypedArray typed_array = JSTypedArray::cast(*receiver);
|
||||
|
||||
if (WasDetached(typed_array)) return Just<int64_t>(-1);
|
||||
if (WasDetached(*receiver)) return Just<int64_t>(-1);
|
||||
|
||||
BackingStore elements = BackingStore::cast(typed_array->elements());
|
||||
BackingStore elements = BackingStore::cast(receiver->elements());
|
||||
ctype typed_search_value;
|
||||
|
||||
if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
|
||||
@ -3254,9 +3250,8 @@ class TypedElementsAccessor
|
||||
|
||||
// Prototype has no elements, and not searching for the hole --- limit
|
||||
// search to backing store length.
|
||||
if (typed_array->length() < length) {
|
||||
// TODO(bmeurer, v8:4153): Don't cast to uint32_t here.
|
||||
length = static_cast<uint32_t>(typed_array->length());
|
||||
if (static_cast<uint32_t>(elements->length()) < length) {
|
||||
length = elements->length();
|
||||
}
|
||||
|
||||
for (uint32_t k = start_from; k < length; ++k) {
|
||||
@ -3270,11 +3265,9 @@ class TypedElementsAccessor
|
||||
Handle<Object> value,
|
||||
uint32_t start_from) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
JSTypedArray typed_array = JSTypedArray::cast(*receiver);
|
||||
DCHECK(!WasDetached(*receiver));
|
||||
|
||||
DCHECK(!WasDetached(typed_array));
|
||||
|
||||
BackingStore elements = BackingStore::cast(typed_array->elements());
|
||||
BackingStore elements = BackingStore::cast(receiver->elements());
|
||||
ctype typed_search_value;
|
||||
|
||||
if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
|
||||
@ -3304,7 +3297,8 @@ class TypedElementsAccessor
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK_LT(start_from, typed_array->length());
|
||||
DCHECK_LT(start_from, elements->length());
|
||||
|
||||
uint32_t k = start_from;
|
||||
do {
|
||||
ctype element_k = elements->get_scalar(k);
|
||||
@ -3315,13 +3309,11 @@ class TypedElementsAccessor
|
||||
|
||||
static void ReverseImpl(JSObject receiver) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
JSTypedArray typed_array = JSTypedArray::cast(receiver);
|
||||
DCHECK(!WasDetached(receiver));
|
||||
|
||||
DCHECK(!WasDetached(typed_array));
|
||||
BackingStore elements = BackingStore::cast(receiver->elements());
|
||||
|
||||
BackingStore elements = BackingStore::cast(typed_array->elements());
|
||||
|
||||
size_t len = typed_array->length();
|
||||
uint32_t len = elements->length();
|
||||
if (len == 0) return;
|
||||
|
||||
ctype* data = static_cast<ctype*>(elements->DataPtr());
|
||||
@ -3357,10 +3349,10 @@ class TypedElementsAccessor
|
||||
CHECK(!source->WasDetached());
|
||||
CHECK(!destination->WasDetached());
|
||||
DCHECK_LE(start, end);
|
||||
DCHECK_LE(end, source->length());
|
||||
DCHECK_LE(end, source->length_value());
|
||||
|
||||
size_t count = end - start;
|
||||
DCHECK_LE(count, destination->length());
|
||||
DCHECK_LE(count, destination->length_value());
|
||||
|
||||
FixedTypedArrayBase src_elements =
|
||||
FixedTypedArrayBase::cast(source->elements());
|
||||
@ -3432,9 +3424,10 @@ class TypedElementsAccessor
|
||||
BackingStore destination_elements =
|
||||
BackingStore::cast(destination->elements());
|
||||
|
||||
DCHECK_LE(offset, destination->length());
|
||||
DCHECK_LE(length, destination->length() - offset);
|
||||
DCHECK_LE(length, source->length());
|
||||
DCHECK_LE(offset, destination->length_value());
|
||||
DCHECK_LE(length, destination->length_value() - offset);
|
||||
DCHECK(source->length()->IsSmi());
|
||||
DCHECK_LE(length, source->length_value());
|
||||
|
||||
InstanceType source_type = source_elements->map()->instance_type();
|
||||
InstanceType destination_type =
|
||||
@ -3524,7 +3517,7 @@ class TypedElementsAccessor
|
||||
length <= current_length);
|
||||
USE(current_length);
|
||||
|
||||
size_t dest_length = destination->length();
|
||||
size_t dest_length = destination->length_value();
|
||||
DCHECK(length + offset <= dest_length);
|
||||
USE(dest_length);
|
||||
|
||||
@ -3636,7 +3629,7 @@ class TypedElementsAccessor
|
||||
Isolate* isolate = destination->GetIsolate();
|
||||
Handle<JSTypedArray> destination_ta =
|
||||
Handle<JSTypedArray>::cast(destination);
|
||||
DCHECK_LE(offset + length, destination_ta->length());
|
||||
DCHECK_LE(offset + length, destination_ta->length_value());
|
||||
CHECK(!destination_ta->WasDetached());
|
||||
|
||||
if (length == 0) return *isolate->factory()->undefined_value();
|
||||
@ -3664,7 +3657,8 @@ class TypedElementsAccessor
|
||||
}
|
||||
// If we have to copy more elements than we have in the source, we need to
|
||||
// do special handling and conversion; that happens in the slow case.
|
||||
if (!source_ta->WasDetached() && length + offset <= source_ta->length()) {
|
||||
if (!source_ta->WasDetached() &&
|
||||
length + offset <= source_ta->length_value()) {
|
||||
CopyElementsFromTypedArray(*source_ta, *destination_ta, length, offset);
|
||||
return *isolate->factory()->undefined_value();
|
||||
}
|
||||
|
@ -1821,8 +1821,10 @@ Handle<BytecodeArray> Factory::NewBytecodeArray(
|
||||
}
|
||||
|
||||
Handle<FixedTypedArrayBase> Factory::NewFixedTypedArrayWithExternalPointer(
|
||||
ExternalArrayType array_type, void* external_pointer,
|
||||
int length, ExternalArrayType array_type, void* external_pointer,
|
||||
AllocationType allocation) {
|
||||
// TODO(7881): Smi length check
|
||||
DCHECK(0 <= length && length <= Smi::kMaxValue);
|
||||
int size = FixedTypedArrayBase::kHeaderSize;
|
||||
HeapObject result = AllocateRawWithImmortalMap(
|
||||
size, allocation,
|
||||
@ -1831,7 +1833,7 @@ Handle<FixedTypedArrayBase> Factory::NewFixedTypedArrayWithExternalPointer(
|
||||
isolate());
|
||||
elements->set_base_pointer(Smi::kZero, SKIP_WRITE_BARRIER);
|
||||
elements->set_external_pointer(external_pointer);
|
||||
elements->set_length(0);
|
||||
elements->set_length(length);
|
||||
return elements;
|
||||
}
|
||||
|
||||
@ -3309,11 +3311,12 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
|
||||
size_t byte_length = length * element_size;
|
||||
SetupArrayBufferView(isolate(), obj, buffer, byte_offset, byte_length);
|
||||
|
||||
obj->set_length(length);
|
||||
Handle<Object> length_object = NewNumberFromSize(length, allocation);
|
||||
obj->set_length(*length_object);
|
||||
|
||||
Handle<FixedTypedArrayBase> elements = NewFixedTypedArrayWithExternalPointer(
|
||||
type, static_cast<uint8_t*>(buffer->backing_store()) + byte_offset,
|
||||
allocation);
|
||||
static_cast<int>(length), type,
|
||||
static_cast<uint8_t*>(buffer->backing_store()) + byte_offset, allocation);
|
||||
Handle<Map> map = JSObject::GetElementsTransitionMap(obj, elements_kind);
|
||||
JSObject::SetMapAndElements(obj, map, elements);
|
||||
return obj;
|
||||
@ -3341,7 +3344,7 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
|
||||
|
||||
obj->set_byte_offset(0);
|
||||
obj->set_byte_length(byte_length);
|
||||
obj->set_length(number_of_elements);
|
||||
obj->set_length(Smi::FromIntptr(static_cast<intptr_t>(number_of_elements)));
|
||||
|
||||
Handle<JSArrayBuffer> buffer =
|
||||
NewJSArrayBuffer(SharedFlag::kNotShared, allocation);
|
||||
|
@ -484,7 +484,7 @@ class V8_EXPORT_PRIVATE Factory {
|
||||
Handle<FixedArray> constant_pool);
|
||||
|
||||
Handle<FixedTypedArrayBase> NewFixedTypedArrayWithExternalPointer(
|
||||
ExternalArrayType array_type, void* external_pointer,
|
||||
int length, ExternalArrayType array_type, void* external_pointer,
|
||||
AllocationType allocation = AllocationType::kYoung);
|
||||
|
||||
Handle<FixedTypedArrayBase> NewFixedTypedArray(
|
||||
|
10
src/ic/ic.cc
10
src/ic/ic.cc
@ -1254,15 +1254,13 @@ bool ConvertKeyToIndex(Handle<Object> receiver, Handle<Object> key,
|
||||
}
|
||||
|
||||
bool IsOutOfBoundsAccess(Handle<Object> receiver, uint32_t index) {
|
||||
size_t length;
|
||||
uint32_t length = 0;
|
||||
if (receiver->IsJSArray()) {
|
||||
length = JSArray::cast(*receiver)->length()->Number();
|
||||
} else if (receiver->IsJSTypedArray()) {
|
||||
length = JSTypedArray::cast(*receiver)->length();
|
||||
} else if (receiver->IsJSObject()) {
|
||||
length = JSObject::cast(*receiver)->elements()->length();
|
||||
JSArray::cast(*receiver)->length()->ToArrayLength(&length);
|
||||
} else if (receiver->IsString()) {
|
||||
length = String::cast(*receiver)->length();
|
||||
} else if (receiver->IsJSObject()) {
|
||||
length = JSObject::cast(*receiver)->elements()->length();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -761,10 +761,7 @@ JsonStringifier::Result JsonStringifier::SerializeJSObject(
|
||||
|
||||
if (property_list_.is_null() &&
|
||||
!object->map()->IsCustomElementsReceiverMap() &&
|
||||
object->HasFastProperties() &&
|
||||
(object->elements() == ReadOnlyRoots(isolate_).empty_fixed_array() ||
|
||||
object->elements() ==
|
||||
ReadOnlyRoots(isolate_).empty_slow_element_dictionary())) {
|
||||
object->HasFastProperties() && object->elements()->length() == 0) {
|
||||
DCHECK(!object->IsJSGlobalProxy());
|
||||
DCHECK(!object->HasIndexedInterceptor());
|
||||
DCHECK(!object->HasNamedInterceptor());
|
||||
|
@ -448,9 +448,7 @@ FastKeyAccumulator::GetOwnKeysWithUninitializedEnumCache() {
|
||||
Handle<JSObject> object = Handle<JSObject>::cast(receiver_);
|
||||
// Uninitalized enum cache
|
||||
Map map = object->map();
|
||||
if (object->elements() != ReadOnlyRoots(isolate_).empty_fixed_array() &&
|
||||
object->elements() !=
|
||||
ReadOnlyRoots(isolate_).empty_slow_element_dictionary()) {
|
||||
if (object->elements()->length() != 0) {
|
||||
// Assume that there are elements.
|
||||
return MaybeHandle<FixedArray>();
|
||||
}
|
||||
|
@ -528,8 +528,7 @@ void FixedTypedArray<Traits>::FixedTypedArrayVerify(Isolate* isolate) {
|
||||
CHECK_EQ(reinterpret_cast<Address>(external_pointer()),
|
||||
FixedTypedArrayBase::kDataOffset - kHeapObjectTag);
|
||||
} else {
|
||||
CHECK_EQ(Smi::kZero, base_pointer());
|
||||
CHECK_EQ(0, length());
|
||||
CHECK_EQ(base_pointer(), Smi::kZero);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1379,7 +1379,7 @@ void JSTypedArray::JSTypedArrayPrint(std::ostream& os) { // NOLINT
|
||||
os << "\n - buffer: " << Brief(buffer());
|
||||
os << "\n - byte_offset: " << byte_offset();
|
||||
os << "\n - byte_length: " << byte_length();
|
||||
os << "\n - length: " << length();
|
||||
os << "\n - length: " << Brief(length());
|
||||
if (!buffer()->IsJSArrayBuffer()) {
|
||||
os << "\n <invalid buffer>\n";
|
||||
return;
|
||||
|
@ -953,7 +953,7 @@ MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
|
||||
isolate, array, length);
|
||||
} else if (object->IsJSTypedArray()) {
|
||||
Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(object);
|
||||
size_t length = array->length();
|
||||
size_t length = array->length_value();
|
||||
if (array->WasDetached() ||
|
||||
length > static_cast<size_t>(FixedArray::kMaxLength)) {
|
||||
return MaybeHandle<FixedArray>();
|
||||
|
@ -641,9 +641,7 @@ double Float64ArrayTraits::defaultValue() {
|
||||
|
||||
template <class Traits>
|
||||
typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
|
||||
// TODO(bmeurer, v8:4153): Solve this differently.
|
||||
// DCHECK((index < this->length()));
|
||||
CHECK_GE(index, 0);
|
||||
DCHECK((index >= 0) && (index < this->length()));
|
||||
return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
|
||||
}
|
||||
|
||||
@ -678,9 +676,7 @@ typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
|
||||
|
||||
template <class Traits>
|
||||
void FixedTypedArray<Traits>::set(int index, ElementType value) {
|
||||
// TODO(bmeurer, v8:4153): Solve this differently.
|
||||
// CHECK((index < this->length()));
|
||||
CHECK_GE(index, 0);
|
||||
CHECK((index >= 0) && (index < this->length()));
|
||||
// See the comment in FixedTypedArray<Traits>::get_scalar.
|
||||
auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
|
||||
TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
|
||||
|
@ -132,17 +132,20 @@ bool JSArrayBufferView::WasDetached() const {
|
||||
return JSArrayBuffer::cast(buffer())->was_detached();
|
||||
}
|
||||
|
||||
size_t JSTypedArray::length() const {
|
||||
// TODO(bmeurer, v8:4153): Change this to size_t later.
|
||||
int length = Smi::cast(raw_length())->value();
|
||||
DCHECK_LE(0, length);
|
||||
return length;
|
||||
Object JSTypedArray::length() const { return READ_FIELD(*this, kLengthOffset); }
|
||||
|
||||
size_t JSTypedArray::length_value() const {
|
||||
double val = length()->Number();
|
||||
DCHECK_LE(val, kMaxSafeInteger); // 2^53-1
|
||||
DCHECK_GE(val, -kMaxSafeInteger); // -2^53+1
|
||||
DCHECK_LE(val, std::numeric_limits<size_t>::max());
|
||||
DCHECK_GE(val, std::numeric_limits<size_t>::min());
|
||||
return static_cast<size_t>(val);
|
||||
}
|
||||
|
||||
void JSTypedArray::set_length(size_t value) {
|
||||
// TODO(bmeurer, v8:4153): Change this to size_t later.
|
||||
CHECK_LE(value, Smi::kMaxValue);
|
||||
set_raw_length(Smi::FromInt(static_cast<int>(value)), SKIP_WRITE_BARRIER);
|
||||
void JSTypedArray::set_length(Object value, WriteBarrierMode mode) {
|
||||
WRITE_FIELD(*this, kLengthOffset, value);
|
||||
CONDITIONAL_WRITE_BARRIER(*this, kLengthOffset, value, mode);
|
||||
}
|
||||
|
||||
bool JSTypedArray::is_on_heap() const {
|
||||
@ -175,7 +178,9 @@ MaybeHandle<JSTypedArray> JSTypedArray::Validate(Isolate* isolate,
|
||||
return array;
|
||||
}
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
ACCESSORS(JSTypedArray, raw_length, Object, kLengthOffset)
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -181,7 +181,8 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
|
||||
fixed_typed_array->DataSize());
|
||||
Handle<FixedTypedArrayBase> new_elements =
|
||||
isolate->factory()->NewFixedTypedArrayWithExternalPointer(
|
||||
typed_array->type(), static_cast<uint8_t*>(buffer->backing_store()));
|
||||
fixed_typed_array->length(), typed_array->type(),
|
||||
static_cast<uint8_t*>(buffer->backing_store()));
|
||||
|
||||
typed_array->set_elements(*new_elements);
|
||||
DCHECK(!typed_array->is_on_heap());
|
||||
@ -225,7 +226,7 @@ Maybe<bool> JSTypedArray::DefineOwnProperty(Isolate* isolate,
|
||||
NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
|
||||
}
|
||||
// 3b iv. Let length be O.[[ArrayLength]].
|
||||
size_t length = o->length();
|
||||
size_t length = o->length_value();
|
||||
// 3b v. If numericIndex ≥ length, return false.
|
||||
if (o->WasDetached() || index >= length) {
|
||||
RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
|
||||
|
@ -180,7 +180,8 @@ class JSArrayBufferView : public JSObject {
|
||||
class JSTypedArray : public JSArrayBufferView {
|
||||
public:
|
||||
// [length]: length of typed array in elements.
|
||||
DECL_PRIMITIVE_ACCESSORS(length, size_t)
|
||||
DECL_ACCESSORS(length, Object)
|
||||
inline size_t length_value() const;
|
||||
|
||||
// ES6 9.4.5.3
|
||||
V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty(
|
||||
@ -223,8 +224,9 @@ class JSTypedArray : public JSArrayBufferView {
|
||||
private:
|
||||
static Handle<JSArrayBuffer> MaterializeArrayBuffer(
|
||||
Handle<JSTypedArray> typed_array);
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
DECL_ACCESSORS(raw_length, Object)
|
||||
#endif
|
||||
|
||||
OBJECT_CONSTRUCTORS(JSTypedArray, JSArrayBufferView);
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsNumWaitersForTesting) {
|
||||
CONVERT_SIZE_ARG_CHECKED(index, 1);
|
||||
CHECK(!sta->WasDetached());
|
||||
CHECK(sta->GetBuffer()->is_shared());
|
||||
CHECK_LT(index, sta->length());
|
||||
CHECK_LT(index, NumberToSize(sta->length()));
|
||||
CHECK_EQ(sta->type(), kExternalInt32Array);
|
||||
|
||||
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
|
||||
|
@ -60,6 +60,13 @@ RUNTIME_FUNCTION(Runtime_TypedArrayCopyElements) {
|
||||
return accessor->CopyElements(source, target, length);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_TypedArrayGetLength) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
|
||||
return holder->length();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ArrayBufferViewWasDetached) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
@ -105,7 +112,7 @@ RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, array, 0);
|
||||
DCHECK(!array->WasDetached());
|
||||
|
||||
size_t length = array->length();
|
||||
size_t length = array->length_value();
|
||||
if (length <= 1) return *array;
|
||||
|
||||
Handle<FixedTypedArrayBase> elements(
|
||||
@ -211,7 +218,7 @@ RUNTIME_FUNCTION(Runtime_TypedArraySet) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len,
|
||||
Object::ToLength(isolate, len));
|
||||
|
||||
if (uint_offset + len->Number() > target->length()) {
|
||||
if (uint_offset + len->Number() > target->length_value()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge));
|
||||
}
|
||||
|
@ -524,6 +524,7 @@ namespace internal {
|
||||
I(IsTypedArray, 1, 1) \
|
||||
F(TypedArrayCopyElements, 3, 1) \
|
||||
F(TypedArrayGetBuffer, 1, 1) \
|
||||
F(TypedArrayGetLength, 1, 1) \
|
||||
F(TypedArraySet, 2, 1) \
|
||||
F(TypedArraySortFast, 1, 1)
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
[Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array,
|
||||
Uint32Array, Float32Array, Float64Array]
|
||||
.forEach(constructor => {
|
||||
const empty = new constructor(0);
|
||||
assertEquals('{}', JSON.stringify(empty));
|
||||
|
||||
const tiny = new constructor(2).fill(123);
|
||||
assertEquals('{"0":123,"1":123}', JSON.stringify(tiny));
|
||||
|
||||
const huge = new constructor(64).fill(123);
|
||||
assertEquals(
|
||||
'{"0":123,"1":123,"2":123,"3":123,"4":123,"5":123,"6":123,"7":123,"8":123,"9":123,"10":123,"11":123,"12":123,"13":123,"14":123,"15":123,"16":123,"17":123,"18":123,"19":123,"20":123,"21":123,"22":123,"23":123,"24":123,"25":123,"26":123,"27":123,"28":123,"29":123,"30":123,"31":123,"32":123,"33":123,"34":123,"35":123,"36":123,"37":123,"38":123,"39":123,"40":123,"41":123,"42":123,"43":123,"44":123,"45":123,"46":123,"47":123,"48":123,"49":123,"50":123,"51":123,"52":123,"53":123,"54":123,"55":123,"56":123,"57":123,"58":123,"59":123,"60":123,"61":123,"62":123,"63":123}',
|
||||
JSON.stringify(huge));
|
||||
});
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
[Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array,
|
||||
Uint32Array, Float32Array, Float64Array]
|
||||
.forEach(constructor => {
|
||||
const huge = new constructor(128);
|
||||
assertEquals(Array.from({length: 128}).map((_, i) => String(i)),
|
||||
Object.keys(huge));
|
||||
|
||||
const tiny = new constructor(2);
|
||||
assertEquals(["0", "1"], Object.keys(tiny));
|
||||
|
||||
const empty = new constructor(0);
|
||||
assertEquals([], Object.keys(empty));
|
||||
});
|
Loading…
Reference in New Issue
Block a user