[typedarray] Move external/data pointer to JSTypedArray.

As the next step in supporting huge typed arrays in V8, this moves the
external/data pointer from the FixedTypedArrayBase backing store to the
JSTypedArray instance itself, and replaces the special backing stores
with a plain ByteArray (removing all the code for the FixedTypedArrayBase
class hierarchy). By doing so, we can drastically simplify the system
around typed arrays.

Note: Several places in the code base used to check the instance type
of the elements backing store of a JSTypedArray instead of checking the
elements kind on the JSTypedArray map directly. Those had to be fixed,
since the backing store is now always a ByteArray.

Drive-by-fix: Move all the typed elements access related code into the
elements.cc file to properly encapsulate the accesses.

Doc: http://doc/1Z-wM2qwvAuxH46e9ivtkYvKzzwYZg8ymm0x0wJaomow
Bug: chromium:951196, chromium:965583, v8:4153, v8:7881, v8:9183
Change-Id: I8cc06b190c53e34155000b4560f5f3ef40621646
Cq-Include-Trybots: luci.chromium.try:linux-rel,win7-rel
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1627535
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61855}
This commit is contained in:
Benedikt Meurer 2019-05-27 15:55:03 +02:00 committed by Commit Bot
parent d365f62ec1
commit 4b86fea530
69 changed files with 1581 additions and 2526 deletions

View File

@ -7237,9 +7237,7 @@ size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
DCHECK(self->IsJSTypedArray());
i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*self),
isolate);
i::Handle<i::FixedTypedArrayBase> fixed_array(
i::FixedTypedArrayBase::cast(typed_array->elements()), isolate);
source = reinterpret_cast<char*>(fixed_array->DataPtr());
source = reinterpret_cast<char*>(typed_array->DataPtr());
}
memcpy(dest, source + byte_offset, bytes_to_copy);
}

View File

@ -383,31 +383,31 @@ namespace array_join {
if (IsElementsKindGreaterThan(kind, UINT32_ELEMENTS)) {
if (kind == INT32_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedInt32Array>;
loadFn = LoadJoinTypedElement<typed_array::Int32Elements>;
} else if (kind == FLOAT32_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedFloat32Array>;
loadFn = LoadJoinTypedElement<typed_array::Float32Elements>;
} else if (kind == FLOAT64_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedFloat64Array>;
loadFn = LoadJoinTypedElement<typed_array::Float64Elements>;
} else if (kind == UINT8_CLAMPED_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedUint8ClampedArray>;
loadFn = LoadJoinTypedElement<typed_array::Uint8ClampedElements>;
} else if (kind == BIGUINT64_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedBigUint64Array>;
loadFn = LoadJoinTypedElement<typed_array::BigUint64Elements>;
} else if (kind == BIGINT64_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedBigInt64Array>;
loadFn = LoadJoinTypedElement<typed_array::BigInt64Elements>;
} else {
unreachable;
}
} else {
if (kind == UINT8_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedUint8Array>;
loadFn = LoadJoinTypedElement<typed_array::Uint8Elements>;
} else if (kind == INT8_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedInt8Array>;
loadFn = LoadJoinTypedElement<typed_array::Int8Elements>;
} else if (kind == UINT16_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedUint16Array>;
loadFn = LoadJoinTypedElement<typed_array::Uint16Elements>;
} else if (kind == INT16_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedInt16Array>;
loadFn = LoadJoinTypedElement<typed_array::Int16Elements>;
} else if (kind == UINT32_ELEMENTS) {
loadFn = LoadJoinTypedElement<FixedUint32Array>;
loadFn = LoadJoinTypedElement<typed_array::Uint32Elements>;
} else {
unreachable;
}

View File

@ -533,16 +533,9 @@ extern class JSBoundFunction extends JSObject {
type Callable = JSFunction | JSBoundFunction | JSProxy;
extern class FixedTypedArrayBase extends FixedArrayBase {
base_pointer: Smi;
external_pointer: RawPtr;
}
extern operator '.length_intptr' macro LoadAndUntagFixedArrayBaseLength(
FixedArrayBase): intptr;
type FixedTypedArray extends FixedTypedArrayBase
generates 'TNode<FixedTypedArray>';
type SloppyArgumentsElements extends FixedArray;
type NumberDictionary extends HeapObject
generates 'TNode<NumberDictionary>';
@ -611,8 +604,7 @@ extern class JSArrayBufferView extends JSObject {
}
extern class JSTypedArray extends JSArrayBufferView {
AttachOffHeapBuffer(buffer: JSArrayBuffer, map: Map, byteOffset: uintptr):
void {
AttachOffHeapBuffer(buffer: JSArrayBuffer, byteOffset: uintptr): void {
const basePointer: Smi = 0;
// The max byteOffset is 8 * MaxSmi on the particular platform. 32 bit
@ -630,16 +622,15 @@ extern class JSTypedArray extends JSArrayBufferView {
IsMockArrayBufferAllocatorFlag() ||
Convert<uintptr>(externalPointer) >= Convert<uintptr>(backingStore));
this.elements = kEmptyByteArray;
this.buffer = buffer;
this.elements = new FixedTypedArrayBase{
map,
length: 0,
base_pointer: basePointer,
external_pointer: externalPointer
};
this.external_pointer = externalPointer;
this.base_pointer = basePointer;
}
length: uintptr;
external_pointer: RawPtr;
base_pointer: ByteArray | Smi;
}
@noVerifier
@ -746,7 +737,7 @@ extern class PropertyCell extends HeapObject {
dependent_code: DependentCode;
}
extern class JSDataView extends JSArrayBufferView {}
extern class JSDataView extends JSArrayBufferView { data_pointer: RawPtr; }
type ElementsKind generates 'TNode<Int32T>' constexpr 'ElementsKind';
type LanguageMode extends Smi constexpr 'LanguageMode';
@ -955,18 +946,6 @@ const kWithSlackTracking: constexpr SlackTrackingMode
const kNoSlackTracking: constexpr SlackTrackingMode
generates 'SlackTrackingMode::kNoSlackTracking';
type FixedUint8Array extends FixedTypedArray;
type FixedInt8Array extends FixedTypedArray;
type FixedUint16Array extends FixedTypedArray;
type FixedInt16Array extends FixedTypedArray;
type FixedUint32Array extends FixedTypedArray;
type FixedInt32Array extends FixedTypedArray;
type FixedFloat32Array extends FixedTypedArray;
type FixedFloat64Array extends FixedTypedArray;
type FixedUint8ClampedArray extends FixedTypedArray;
type FixedBigUint64Array extends FixedTypedArray;
type FixedBigInt64Array extends FixedTypedArray;
const kFixedDoubleArrays: constexpr ExtractFixedArrayFlags
generates 'CodeStubAssembler::ExtractFixedArrayFlag::kFixedDoubleArrays';
const kAllFixedArrays: constexpr ExtractFixedArrayFlags
@ -978,6 +957,8 @@ const kFixedArrayMapRootIndex:
constexpr RootIndex generates 'RootIndex::kFixedArrayMap';
const kFixedCOWArrayMapRootIndex:
constexpr RootIndex generates 'RootIndex::kFixedCOWArrayMap';
const kEmptyByteArrayRootIndex:
constexpr RootIndex generates 'RootIndex::kEmptyByteArray';
const kEmptyFixedArrayRootIndex:
constexpr RootIndex generates 'RootIndex::kEmptyFixedArray';
const kTheHoleValueRootIndex:
@ -1020,8 +1001,8 @@ const kPropertyNotFunction: constexpr MessageTemplate
const kMaxArrayIndex:
constexpr uint32 generates 'JSArray::kMaxArrayIndex';
const kTypedArrayMaxByteLength:
constexpr uintptr generates 'FixedTypedArrayBase::kMaxByteLength';
const kArrayBufferMaxByteLength:
constexpr uintptr generates 'JSArrayBuffer::kMaxByteLength';
const V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP:
constexpr int31 generates 'V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP';
const kMaxSafeInteger: constexpr float64 generates 'kMaxSafeInteger';
@ -1030,8 +1011,6 @@ const kSmiMax: uintptr = kSmiMaxValue;
const kStringMaxLength: constexpr int31 generates 'String::kMaxLength';
const kFixedArrayMaxLength:
constexpr int31 generates 'FixedArray::kMaxLength';
const kFixedTypedArrayBaseHeaderSize: constexpr intptr
generates 'FixedTypedArrayBase::kHeaderSize';
const kObjectAlignmentMask: constexpr intptr
generates 'kObjectAlignmentMask';
const kMinAddedElementsCapacity:
@ -1438,7 +1417,6 @@ extern transitioning runtime TransitionElementsKindWithKind(
extern macro LoadBufferObject(RawPtr, constexpr int32): Object;
extern macro LoadBufferPointer(RawPtr, constexpr int32): RawPtr;
extern macro LoadBufferSmi(RawPtr, constexpr int32): Smi;
extern macro LoadFixedTypedArrayOnHeapBackingStore(FixedTypedArrayBase): RawPtr;
extern macro LoadRoot(constexpr RootIndex): Object;
extern macro StoreRoot(constexpr RootIndex, Object): Object;
@ -1821,12 +1799,6 @@ Cast<NumberDictionary>(o: HeapObject): NumberDictionary
goto CastError;
}
Cast<FixedTypedArrayBase>(o: HeapObject): FixedTypedArrayBase
labels CastError {
if (IsFixedTypedArray(o)) return %RawDownCast<FixedTypedArrayBase>(o);
goto CastError;
}
Cast<String>(o: HeapObject): String
labels CastError {
return HeapObjectToString(o) otherwise CastError;
@ -2282,6 +2254,8 @@ UnsafeCast<Object>(o: Object): Object {
const kFixedArrayMap: Map =
%RawDownCast<Map>(LoadRoot(kFixedArrayMapRootIndex));
const kCOWMap: Map = %RawDownCast<Map>(LoadRoot(kFixedCOWArrayMapRootIndex));
const kEmptyByteArray: ByteArray =
%RawDownCast<ByteArray>(LoadRoot(kEmptyByteArrayRootIndex));
const kEmptyFixedArray: FixedArray =
%RawDownCast<FixedArray>(LoadRoot(kEmptyFixedArrayRootIndex));
@ -2296,8 +2270,8 @@ extern macro IsMockArrayBufferAllocatorFlag(): bool;
extern macro IsPrototypeTypedArrayPrototype(implicit context: Context)(Map):
bool;
extern operator '.data_ptr' macro TypedArrayBuiltinsAssembler::LoadDataPtr(
JSTypedArray): RawPtr;
extern operator '.data_ptr' macro LoadJSTypedArrayBackingStore(JSTypedArray):
RawPtr;
extern operator '.elements_kind' macro LoadMapElementsKind(Map): ElementsKind;
extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray):
@ -2701,7 +2675,6 @@ extern macro IsJSFunction(HeapObject): bool;
extern macro IsJSObject(HeapObject): bool;
extern macro IsJSTypedArray(HeapObject): bool;
extern macro IsNumberDictionary(HeapObject): bool;
extern macro IsFixedTypedArray(HeapObject): bool;
extern macro IsContext(HeapObject): bool;
extern macro IsJSReceiver(HeapObject): bool;
extern macro TaggedIsCallable(Object): bool;

View File

@ -46,8 +46,7 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
CSA_ASSERT(this, UintPtrLessThanOrEqual(SmiUntag(CAST(len_)),
LoadJSTypedArrayLength(a)));
fast_typed_array_target_ =
Word32Equal(LoadInstanceType(LoadElements(original_array)),
LoadInstanceType(LoadElements(a)));
Word32Equal(LoadElementsKind(original_array), LoadElementsKind(a));
a_.Bind(a);
}
@ -151,8 +150,8 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
Label throw_not_typed_array(this, Label::kDeferred);
GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
GotoIfNot(HasInstanceType(CAST(receiver_), JS_TYPED_ARRAY_TYPE),
&throw_not_typed_array);
TNode<Map> typed_array_map = LoadMap(CAST(receiver_));
GotoIfNot(IsJSTypedArrayMap(typed_array_map), &throw_not_typed_array);
TNode<JSTypedArray> typed_array = CAST(receiver_);
o_ = typed_array;
@ -179,13 +178,13 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
BIND(&unexpected_instance_type);
Unreachable();
std::vector<int32_t> instance_types = {
#define INSTANCE_TYPE(Type, type, TYPE, ctype) FIXED_##TYPE##_ARRAY_TYPE,
TYPED_ARRAYS(INSTANCE_TYPE)
#undef INSTANCE_TYPE
std::vector<int32_t> elements_kinds = {
#define ELEMENTS_KIND(Type, type, TYPE, ctype) TYPE##_ELEMENTS,
TYPED_ARRAYS(ELEMENTS_KIND)
#undef ELEMENTS_KIND
};
std::list<Label> labels;
for (size_t i = 0; i < instance_types.size(); ++i) {
for (size_t i = 0; i < elements_kinds.size(); ++i) {
labels.emplace_back(this);
}
std::vector<Label*> label_ptrs;
@ -203,16 +202,15 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
k_.Bind(NumberDec(len()));
}
CSA_ASSERT(this, IsSafeInteger(k()));
Node* instance_type = LoadInstanceType(LoadElements(typed_array));
Switch(instance_type, &unexpected_instance_type, instance_types.data(),
TNode<Int32T> elements_kind = LoadMapElementsKind(typed_array_map);
Switch(elements_kind, &unexpected_instance_type, elements_kinds.data(),
label_ptrs.data(), labels.size());
size_t i = 0;
for (auto it = labels.begin(); it != labels.end(); ++i, ++it) {
BIND(&*it);
Label done(this);
source_elements_kind_ = ElementsKindForInstanceType(
static_cast<InstanceType>(instance_types[i]));
source_elements_kind_ = static_cast<ElementsKind>(elements_kinds[i]);
// TODO(tebbi): Silently cancelling the loop on buffer detachment is a
// spec violation. Should go to &throw_detached and throw a TypeError
// instead.
@ -226,21 +224,6 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
}
}
ElementsKind ArrayBuiltinsAssembler::ElementsKindForInstanceType(
InstanceType type) {
switch (type) {
#define INSTANCE_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE: \
return TYPE##_ELEMENTS;
TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
#undef INSTANCE_TYPE_TO_ELEMENTS_KIND
default:
UNREACHABLE();
}
}
void ArrayBuiltinsAssembler::VisitAllTypedArrayElements(
Node* array_buffer, const CallResultProcessor& processor, Label* detached,
ForEachDirection direction, TNode<JSTypedArray> typed_array) {
@ -248,13 +231,7 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
FastLoopBody body = [&](Node* index) {
GotoIf(IsDetachedBuffer(array_buffer), detached);
Node* elements = LoadElements(typed_array);
Node* base_ptr =
LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
Node* external_ptr =
LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
MachineType::Pointer());
Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
TNode<RawPtrT> data_ptr = LoadJSTypedArrayBackingStore(typed_array);
Node* value = LoadFixedTypedArrayElementAsTagged(
data_ptr, index, source_elements_kind_, SMI_PARAMETERS);
k_.Bind(index);
@ -1668,14 +1645,7 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
&allocate_iterator_result);
TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
Node* elements = LoadElements(CAST(array));
Node* base_ptr =
LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
Node* external_ptr =
LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
MachineType::Pointer());
TNode<WordT> data_ptr =
IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
TNode<RawPtrT> data_ptr = LoadJSTypedArrayBackingStore(CAST(array));
var_value.Bind(LoadFixedTypedArrayElementAsTagged(data_ptr, CAST(index),
elements_kind));
Goto(&allocate_entry_if_needed);

View File

@ -26,7 +26,7 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler {
Node* value,
Node* value_high);
void ValidateSharedTypedArray(Node* tagged, Node* context,
Node** out_instance_type,
Node** out_elements_kind,
Node** out_backing_store);
Node* ConvertTaggedAtomicIndexToWord32(Node* tagged, Node* context,
Node** number_index);
@ -46,7 +46,7 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler {
};
void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray(
Node* tagged, Node* context, Node** out_instance_type,
Node* tagged, Node* context, Node** out_elements_kind,
Node** out_backing_store) {
Label not_float_or_clamped(this), invalid(this);
@ -54,8 +54,8 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray(
GotoIf(TaggedIsSmi(tagged), &invalid);
// Fail if the array's instance type is not JSTypedArray.
GotoIfNot(InstanceTypeEqual(LoadInstanceType(tagged), JS_TYPED_ARRAY_TYPE),
&invalid);
Node* tagged_map = LoadMap(tagged);
GotoIfNot(IsJSTypedArrayMap(tagged_map), &invalid);
// Fail if the array's JSArrayBuffer is not shared.
TNode<JSArrayBuffer> array_buffer = LoadJSArrayBufferViewBuffer(CAST(tagged));
@ -63,20 +63,18 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray(
GotoIfNot(IsSetWord32<JSArrayBuffer::IsSharedBit>(bitfield), &invalid);
// Fail if the array's element type is float32, float64 or clamped.
Node* elements_instance_type = LoadInstanceType(LoadElements(tagged));
STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
GotoIf(Int32LessThan(elements_instance_type,
Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)),
STATIC_ASSERT(INT8_ELEMENTS < FLOAT32_ELEMENTS);
STATIC_ASSERT(INT16_ELEMENTS < FLOAT32_ELEMENTS);
STATIC_ASSERT(INT32_ELEMENTS < FLOAT32_ELEMENTS);
STATIC_ASSERT(UINT8_ELEMENTS < FLOAT32_ELEMENTS);
STATIC_ASSERT(UINT16_ELEMENTS < FLOAT32_ELEMENTS);
STATIC_ASSERT(UINT32_ELEMENTS < FLOAT32_ELEMENTS);
Node* elements_kind = LoadMapElementsKind(tagged_map);
GotoIf(Int32LessThan(elements_kind, Int32Constant(FLOAT32_ELEMENTS)),
&not_float_or_clamped);
STATIC_ASSERT(FIXED_BIGINT64_ARRAY_TYPE > FIXED_UINT8_CLAMPED_ARRAY_TYPE);
STATIC_ASSERT(FIXED_BIGUINT64_ARRAY_TYPE > FIXED_UINT8_CLAMPED_ARRAY_TYPE);
Branch(Int32GreaterThan(elements_instance_type,
Int32Constant(FIXED_UINT8_CLAMPED_ARRAY_TYPE)),
STATIC_ASSERT(BIGINT64_ELEMENTS > UINT8_CLAMPED_ELEMENTS);
STATIC_ASSERT(BIGUINT64_ELEMENTS > UINT8_CLAMPED_ELEMENTS);
Branch(Int32GreaterThan(elements_kind, Int32Constant(UINT8_CLAMPED_ELEMENTS)),
&not_float_or_clamped, &invalid);
BIND(&invalid);
@ -86,7 +84,7 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray(
}
BIND(&not_float_or_clamped);
*out_instance_type = elements_instance_type;
*out_elements_kind = elements_kind;
TNode<RawPtrT> backing_store = LoadJSArrayBufferBackingStore(array_buffer);
TNode<UintPtrT> byte_offset = LoadJSArrayBufferViewByteOffset(CAST(tagged));
@ -169,9 +167,9 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) {
Node* index = Parameter(Descriptor::kIndex);
Node* context = Parameter(Descriptor::kContext);
Node* instance_type;
Node* elements_kind;
Node* backing_store;
ValidateSharedTypedArray(array, context, &instance_type, &backing_store);
ValidateSharedTypedArray(array, context, &elements_kind, &backing_store);
Node* index_integer;
Node* index_word32 =
@ -182,13 +180,11 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) {
Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this),
i64(this), u64(this), other(this);
int32_t case_values[] = {
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE,
FIXED_INT16_ARRAY_TYPE, FIXED_UINT16_ARRAY_TYPE,
FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
FIXED_BIGINT64_ARRAY_TYPE, FIXED_BIGUINT64_ARRAY_TYPE,
INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS, UINT16_ELEMENTS,
INT32_ELEMENTS, UINT32_ELEMENTS, BIGINT64_ELEMENTS, BIGUINT64_ELEMENTS,
};
Label* case_labels[] = {&i8, &u8, &i16, &u16, &i32, &u32, &i64, &u64};
Switch(instance_type, &other, case_values, case_labels,
Switch(elements_kind, &other, case_values, case_labels,
arraysize(case_labels));
BIND(&i8);
@ -243,9 +239,9 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) {
Node* value = Parameter(Descriptor::kValue);
Node* context = Parameter(Descriptor::kContext);
Node* instance_type;
Node* elements_kind;
Node* backing_store;
ValidateSharedTypedArray(array, context, &instance_type, &backing_store);
ValidateSharedTypedArray(array, context, &elements_kind, &backing_store);
Node* index_integer;
Node* index_word32 =
@ -254,11 +250,9 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) {
Node* index_word = ChangeUint32ToWord(index_word32);
Label u8(this), u16(this), u32(this), u64(this), other(this);
STATIC_ASSERT(FIXED_BIGINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_BIGUINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
GotoIf(
Int32GreaterThan(instance_type, Int32Constant(FIXED_UINT32_ARRAY_TYPE)),
&u64);
STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS);
STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS);
GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &u64);
Node* value_integer = ToInteger_Inline(CAST(context), CAST(value));
Node* value_word32 = TruncateTaggedToWord32(context, value_integer);
@ -268,11 +262,11 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) {
#endif
int32_t case_values[] = {
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS,
UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS,
};
Label* case_labels[] = {&u8, &u8, &u16, &u16, &u32, &u32};
Switch(instance_type, &other, case_values, case_labels,
Switch(elements_kind, &other, case_values, case_labels,
arraysize(case_labels));
BIND(&u8);
@ -319,9 +313,9 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) {
Node* value = Parameter(Descriptor::kValue);
Node* context = Parameter(Descriptor::kContext);
Node* instance_type;
Node* elements_kind;
Node* backing_store;
ValidateSharedTypedArray(array, context, &instance_type, &backing_store);
ValidateSharedTypedArray(array, context, &elements_kind, &backing_store);
Node* index_integer;
Node* index_word32 =
@ -336,11 +330,9 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) {
Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this),
i64(this), u64(this), big(this), other(this);
STATIC_ASSERT(FIXED_BIGINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_BIGUINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
GotoIf(
Int32GreaterThan(instance_type, Int32Constant(FIXED_UINT32_ARRAY_TYPE)),
&big);
STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS);
STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS);
GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big);
Node* value_integer = ToInteger_Inline(CAST(context), CAST(value));
#if DEBUG
@ -349,13 +341,13 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) {
Node* value_word32 = TruncateTaggedToWord32(context, value_integer);
int32_t case_values[] = {
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS,
UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS,
};
Label* case_labels[] = {
&i8, &u8, &i16, &u16, &i32, &u32,
};
Switch(instance_type, &other, case_values, case_labels,
Switch(elements_kind, &other, case_values, case_labels,
arraysize(case_labels));
BIND(&i8);
@ -393,10 +385,8 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) {
TVARIABLE(UintPtrT, var_high);
BigIntToRawBytes(value_bigint, &var_low, &var_high);
Node* high = Is64() ? nullptr : static_cast<Node*>(var_high.value());
GotoIf(Word32Equal(instance_type, Int32Constant(FIXED_BIGINT64_ARRAY_TYPE)),
&i64);
GotoIf(Word32Equal(instance_type, Int32Constant(FIXED_BIGUINT64_ARRAY_TYPE)),
&u64);
GotoIf(Word32Equal(elements_kind, Int32Constant(BIGINT64_ELEMENTS)), &i64);
GotoIf(Word32Equal(elements_kind, Int32Constant(BIGUINT64_ELEMENTS)), &u64);
Unreachable();
BIND(&i64);
@ -425,9 +415,9 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) {
Node* new_value = Parameter(Descriptor::kNewValue);
Node* context = Parameter(Descriptor::kContext);
Node* instance_type;
Node* elements_kind;
Node* backing_store;
ValidateSharedTypedArray(array, context, &instance_type, &backing_store);
ValidateSharedTypedArray(array, context, &elements_kind, &backing_store);
Node* index_integer;
Node* index_word32 =
@ -443,11 +433,9 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) {
Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this),
i64(this), u64(this), big(this), other(this);
STATIC_ASSERT(FIXED_BIGINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_BIGUINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
GotoIf(
Int32GreaterThan(instance_type, Int32Constant(FIXED_UINT32_ARRAY_TYPE)),
&big);
STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS);
STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS);
GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big);
Node* old_value_integer = ToInteger_Inline(CAST(context), CAST(old_value));
Node* new_value_integer = ToInteger_Inline(CAST(context), CAST(new_value));
@ -458,13 +446,13 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) {
Node* new_value_word32 = TruncateTaggedToWord32(context, new_value_integer);
int32_t case_values[] = {
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS,
UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS,
};
Label* case_labels[] = {
&i8, &u8, &i16, &u16, &i32, &u32,
};
Switch(instance_type, &other, case_values, case_labels,
Switch(elements_kind, &other, case_values, case_labels,
arraysize(case_labels));
BIND(&i8);
@ -511,10 +499,8 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) {
BigIntToRawBytes(new_value_bigint, &var_new_low, &var_new_high);
Node* old_high = Is64() ? nullptr : static_cast<Node*>(var_old_high.value());
Node* new_high = Is64() ? nullptr : static_cast<Node*>(var_new_high.value());
GotoIf(Word32Equal(instance_type, Int32Constant(FIXED_BIGINT64_ARRAY_TYPE)),
&i64);
GotoIf(Word32Equal(instance_type, Int32Constant(FIXED_BIGUINT64_ARRAY_TYPE)),
&u64);
GotoIf(Word32Equal(elements_kind, Int32Constant(BIGINT64_ELEMENTS)), &i64);
GotoIf(Word32Equal(elements_kind, Int32Constant(BIGUINT64_ELEMENTS)), &u64);
Unreachable();
BIND(&i64);
@ -557,9 +543,9 @@ BINOP_BUILTIN(Xor)
void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon(
Node* array, Node* index, Node* value, Node* context,
AssemblerFunction function, Runtime::FunctionId runtime_function) {
Node* instance_type;
Node* elements_kind;
Node* backing_store;
ValidateSharedTypedArray(array, context, &instance_type, &backing_store);
ValidateSharedTypedArray(array, context, &elements_kind, &backing_store);
Node* index_integer;
Node* index_word32 =
@ -575,11 +561,9 @@ void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon(
Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this),
i64(this), u64(this), big(this), other(this);
STATIC_ASSERT(FIXED_BIGINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
STATIC_ASSERT(FIXED_BIGUINT64_ARRAY_TYPE > FIXED_UINT32_ARRAY_TYPE);
GotoIf(
Int32GreaterThan(instance_type, Int32Constant(FIXED_UINT32_ARRAY_TYPE)),
&big);
STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS);
STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS);
GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big);
Node* value_integer = ToInteger_Inline(CAST(context), CAST(value));
#if DEBUG
@ -588,13 +572,13 @@ void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon(
Node* value_word32 = TruncateTaggedToWord32(context, value_integer);
int32_t case_values[] = {
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS,
UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS,
};
Label* case_labels[] = {
&i8, &u8, &i16, &u16, &i32, &u32,
};
Switch(instance_type, &other, case_values, case_labels,
Switch(elements_kind, &other, case_values, case_labels,
arraysize(case_labels));
BIND(&i8);
@ -634,10 +618,8 @@ void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon(
TVARIABLE(UintPtrT, var_high);
BigIntToRawBytes(value_bigint, &var_low, &var_high);
Node* high = Is64() ? nullptr : static_cast<Node*>(var_high.value());
GotoIf(Word32Equal(instance_type, Int32Constant(FIXED_BIGINT64_ARRAY_TYPE)),
&i64);
GotoIf(Word32Equal(instance_type, Int32Constant(FIXED_BIGUINT64_ARRAY_TYPE)),
&u64);
GotoIf(Word32Equal(elements_kind, Int32Constant(BIGINT64_ELEMENTS)), &i64);
GotoIf(Word32Equal(elements_kind, Int32Constant(BIGUINT64_ELEMENTS)), &u64);
Unreachable();
BIND(&i64);

View File

@ -28,23 +28,6 @@ using TNode = compiler::TNode<T>;
// -----------------------------------------------------------------------------
// ES6 section 22.2 TypedArray Objects
TNode<Map> TypedArrayBuiltinsAssembler::LoadMapForType(
TNode<JSTypedArray> array) {
TVARIABLE(Map, var_typed_map);
TNode<Map> array_map = LoadMap(array);
TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
ReadOnlyRoots roots(isolate());
DispatchTypedArrayByElementsKind(
elements_kind,
[&](ElementsKind kind, int size, int typed_array_fun_index) {
Handle<Map> map(roots.MapForFixedTypedArray(kind), isolate());
var_typed_map = HeapConstant(map);
});
return var_typed_map.value();
}
// Setup the TypedArray which is under construction.
// - Set the length.
// - Set the byte_offset.
@ -70,6 +53,7 @@ void TypedArrayBuiltinsAssembler::SetupTypedArray(TNode<JSTypedArray> holder,
// Allocate a new ArrayBuffer and initialize it with empty properties and
// elements.
// TODO(bmeurer,v8:4153): Rename this and maybe fix up the implementation a bit.
TNode<JSArrayBuffer> TypedArrayBuiltinsAssembler::AllocateEmptyOnHeapBuffer(
TNode<Context> context, TNode<JSTypedArray> holder,
TNode<UintPtrT> byte_length) {
@ -115,47 +99,16 @@ TNode<JSArrayBuffer> TypedArrayBuiltinsAssembler::AllocateEmptyOnHeapBuffer(
StoreObjectFieldNoWriteBarrier(buffer, offset, SmiConstant(0));
}
StoreObjectField(holder, JSArrayBufferView::kBufferOffset, buffer);
return buffer;
}
StoreObjectField(holder, JSTypedArray::kBufferOffset, buffer);
TNode<FixedTypedArrayBase> TypedArrayBuiltinsAssembler::AllocateOnHeapElements(
TNode<Map> map, TNode<IntPtrT> total_size, TNode<Number> length) {
CSA_ASSERT(this, IntPtrGreaterThanOrEqual(total_size, IntPtrConstant(0)));
// Allocate a FixedTypedArray and set the length, base pointer and external
// pointer.
CSA_ASSERT(this, IsRegularHeapObjectSize(total_size));
TNode<HeapObject> elements;
if (UnalignedLoadSupported(MachineRepresentation::kFloat64) &&
UnalignedStoreSupported(MachineRepresentation::kFloat64)) {
elements = AllocateInNewSpace(total_size);
} else {
elements = AllocateInNewSpace(total_size, kDoubleAlignment);
}
// These skipped write barriers are marked unsafe because the MemoryOptimizer
// currently doesn't handle double alignment, so it fails at verifying them.
UnsafeStoreObjectFieldNoWriteBarrier(elements,
FixedTypedArrayBase::kMapOffset, map);
UnsafeStoreObjectFieldNoWriteBarrier(
elements, FixedTypedArrayBase::kLengthOffset, length);
UnsafeStoreObjectFieldNoWriteBarrier(
elements, FixedTypedArrayBase::kBasePointerOffset, elements);
TNode<ByteArray> elements = AllocateByteArray(byte_length);
StoreObjectField(holder, JSTypedArray::kElementsOffset, elements);
StoreObjectField(holder, JSTypedArray::kBasePointerOffset, elements);
StoreObjectFieldNoWriteBarrier(
elements, FixedTypedArrayBase::kExternalPointerOffset,
IntPtrConstant(FixedTypedArrayBase::ExternalPointerValueForOnHeapArray()),
holder, JSTypedArray::kExternalPointerOffset,
PointerConstant(JSTypedArray::ExternalPointerForOnHeapArray()),
MachineType::PointerRepresentation());
return CAST(elements);
}
TNode<RawPtrT> TypedArrayBuiltinsAssembler::LoadDataPtr(
TNode<JSTypedArray> typed_array) {
TNode<FixedArrayBase> elements = LoadElements(typed_array);
CSA_ASSERT(this, IsFixedTypedArray(elements));
return LoadFixedTypedArrayBackingStore(CAST(elements));
return buffer;
}
TF_BUILTIN(TypedArrayBaseConstructor, TypedArrayBuiltinsAssembler) {
@ -286,13 +239,10 @@ TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(
[&](ElementsKind kind, int size, int typed_array_fun_index) {
DCHECK_GT(size, 0);
var_size_log2 = UintPtrConstant(ElementsKindToShiftSize(kind));
Handle<Map> map(roots.MapForFixedTypedArray(kind), isolate());
var_map = HeapConstant(map);
});
return TorqueGeneratedTypedArrayBuiltinsAssembler::TypedArrayElementsInfo{
var_size_log2.value(), var_map.value(), elements_kind};
var_size_log2.value(), elements_kind};
}
TNode<JSFunction> TypedArrayBuiltinsAssembler::GetDefaultConstructor(
@ -397,8 +347,8 @@ void TypedArrayBuiltinsAssembler::SetTypedArraySource(
// Grab pointers and byte lengths we need later on.
TNode<RawPtrT> target_data_ptr = LoadDataPtr(target);
TNode<RawPtrT> source_data_ptr = LoadDataPtr(source);
TNode<RawPtrT> target_data_ptr = LoadJSTypedArrayBackingStore(target);
TNode<RawPtrT> source_data_ptr = LoadJSTypedArrayBackingStore(source);
TNode<Word32T> source_el_kind = LoadElementsKind(source);
TNode<Word32T> target_el_kind = LoadElementsKind(target);
@ -816,34 +766,25 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) {
DispatchTypedArrayByElementsKind(
elements_kind,
[&](ElementsKind kind, int size, int typed_array_fun_index) {
TNode<FixedTypedArrayBase> elements =
CAST(LoadElements(new_typed_array));
BuildFastLoop(
IntPtrConstant(0), length,
[&](Node* index) {
TNode<Object> item = args.AtIndex(index, INTPTR_PARAMETERS);
TNode<IntPtrT> intptr_index = UncheckedCast<IntPtrT>(index);
if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) {
EmitBigTypedArrayElementStore(new_typed_array, elements,
intptr_index, item, context,
&if_detached);
} else {
Node* value =
PrepareValueForWriteToTypedArray(item, kind, context);
Node* value =
PrepareValueForWriteToTypedArray(item, kind, context);
// ToNumber may execute JavaScript code, which could detach
// the array's buffer.
Node* buffer = LoadObjectField(new_typed_array,
JSTypedArray::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), &if_detached);
// ToNumber/ToBigInt may execute JavaScript code, which could
// detach the array's buffer.
Node* buffer =
LoadObjectField(new_typed_array, JSTypedArray::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), &if_detached);
// GC may move backing store in ToNumber, thus load backing
// store everytime in this loop.
TNode<RawPtrT> backing_store =
LoadFixedTypedArrayBackingStore(elements);
StoreElement(backing_store, kind, index, value,
INTPTR_PARAMETERS);
}
// GC may move backing store in ToNumber, thus load backing
// store everytime in this loop.
TNode<RawPtrT> backing_store =
LoadJSTypedArrayBackingStore(new_typed_array);
StoreElement(backing_store, kind, index, value,
INTPTR_PARAMETERS);
},
1, ParameterMode::INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
});
@ -1039,7 +980,6 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) {
TNode<Word32T> elements_kind = LoadElementsKind(target_obj.value());
// 7e/13 : Copy the elements
TNode<FixedTypedArrayBase> elements = CAST(LoadElements(target_obj.value()));
BuildFastLoop(
SmiConstant(0), final_length.value(),
[&](Node* index) {
@ -1050,31 +990,24 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) {
CAST(CallJS(CodeFactory::Call(isolate()), context, map_fn, this_arg,
k_value, index));
TNode<IntPtrT> intptr_index = SmiUntag(index);
DispatchTypedArrayByElementsKind(
elements_kind,
[&](ElementsKind kind, int size, int typed_array_fun_index) {
if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) {
EmitBigTypedArrayElementStore(target_obj.value(), elements,
intptr_index, mapped_value,
context, &if_detached);
} else {
Node* const final_value = PrepareValueForWriteToTypedArray(
mapped_value, kind, context);
Node* const final_value =
PrepareValueForWriteToTypedArray(mapped_value, kind, context);
// ToNumber may execute JavaScript code, which could detach
// the array's buffer.
Node* buffer = LoadObjectField(target_obj.value(),
JSTypedArray::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), &if_detached);
// ToNumber/ToBigInt may execute JavaScript code, which could
// detach the array's buffer.
Node* buffer = LoadObjectField(target_obj.value(),
JSTypedArray::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), &if_detached);
// GC may move backing store in map_fn, thus load backing
// store in each iteration of this loop.
TNode<RawPtrT> backing_store =
LoadFixedTypedArrayBackingStore(elements);
StoreElement(backing_store, kind, index, final_value,
SMI_PARAMETERS);
}
// GC may move backing store in map_fn, thus load backing
// store in each iteration of this loop.
TNode<RawPtrT> backing_store =
LoadJSTypedArrayBackingStore(target_obj.value());
StoreElement(backing_store, kind, index, final_value,
SMI_PARAMETERS);
});
},
1, ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost);

View File

@ -40,15 +40,10 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
TNode<JSTypedArray> holder,
TNode<UintPtrT> byte_length);
TNode<FixedTypedArrayBase> AllocateOnHeapElements(TNode<Map> map,
TNode<IntPtrT> byte_length,
TNode<Number> length);
TNode<Map> LoadMapForType(TNode<JSTypedArray> array);
TNode<BoolT> IsMockArrayBufferAllocatorFlag();
TNode<UintPtrT> CalculateExternalPointer(TNode<UintPtrT> backing_store,
TNode<UintPtrT> byte_offset);
TNode<RawPtrT> LoadDataPtr(TNode<JSTypedArray> typed_array);
// Returns true if kind is either UINT8_ELEMENTS or UINT8_CLAMPED_ELEMENTS.
TNode<Word32T> IsUint8ElementsKind(TNode<Word32T> kind);

View File

@ -93,14 +93,12 @@ BUILTIN(TypedArrayPrototypeCopyWithin) {
DCHECK_LT(to, len);
DCHECK_GE(len - count, 0);
Handle<FixedTypedArrayBase> elements(
FixedTypedArrayBase::cast(array->elements()), isolate);
size_t element_size = array->element_size();
to = to * element_size;
from = from * element_size;
count = count * element_size;
uint8_t* data = static_cast<uint8_t*>(elements->DataPtr());
uint8_t* data = static_cast<uint8_t*>(array->DataPtr());
std::memmove(data + to, data + from, count);
return *array;

View File

@ -12,8 +12,6 @@ namespace typed_array_createtypedarray {
implicit context: Context)(JSFunction, JSReceiver): JSTypedArray;
extern macro TypedArrayBuiltinsAssembler::AllocateEmptyOnHeapBuffer(
implicit context: Context)(JSTypedArray, uintptr): JSArrayBuffer;
extern macro TypedArrayBuiltinsAssembler::AllocateOnHeapElements(
Map, intptr, Number): FixedTypedArrayBase;
extern macro TypedArrayBuiltinsAssembler::GetDefaultConstructor(
implicit context: Context)(JSTypedArray): JSFunction;
extern macro TypedArrayBuiltinsAssembler::IsSharedArrayBuffer(JSArrayBuffer):
@ -26,12 +24,6 @@ namespace typed_array_createtypedarray {
extern runtime TypedArrayCopyElements(Context, JSTypedArray, Object, Number):
void;
macro CalculateTotalElementsByteSize(byteLength: intptr): intptr {
return (kFixedTypedArrayBaseHeaderSize + kObjectAlignmentMask +
byteLength) &
~kObjectAlignmentMask;
}
transitioning macro TypedArrayInitialize(implicit context: Context)(
initialize: constexpr bool, typedArray: JSTypedArray, length: PositiveSmi,
elementsInfo: typed_array::TypedArrayElementsInfo,
@ -51,14 +43,8 @@ namespace typed_array_createtypedarray {
AllocateEmptyOnHeapBuffer(typedArray, byteLength);
const totalSize =
CalculateTotalElementsByteSize(Convert<intptr>(byteLength));
const elements =
AllocateOnHeapElements(elementsInfo.map, totalSize, length);
typedArray.elements = elements;
if constexpr (initialize) {
const backingStore = LoadFixedTypedArrayOnHeapBackingStore(elements);
const backingStore = typedArray.data_ptr;
typed_array::CallCMemset(backingStore, 0, byteLength);
}
}
@ -73,7 +59,7 @@ 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, byteOffset);
}
const byteOffset: uintptr = 0;
@ -126,7 +112,7 @@ namespace typed_array_createtypedarray {
goto IfSlow;
} else if (length > 0) {
assert(byteLength <= kTypedArrayMaxByteLength);
assert(byteLength <= kArrayBufferMaxByteLength);
typed_array::CallCMemcpy(typedArray.data_ptr, src.data_ptr, byteLength);
}
}
@ -240,7 +226,7 @@ namespace typed_array_createtypedarray {
SetupTypedArray(
typedArray, Convert<uintptr>(newLength), offset, newByteLength);
typedArray.AttachOffHeapBuffer(buffer, elementsInfo.map, offset);
typedArray.AttachOffHeapBuffer(buffer, offset);
}
label IfInvalidAlignment(problemString: String) deferred {
ThrowInvalidTypedArrayAlignment(typedArray.map, problemString);
@ -290,12 +276,14 @@ namespace typed_array_createtypedarray {
const array: JSTypedArray = EmitFastNewObject(target, newTarget);
// We need to set the byte_offset / byte_length to some sane values
// to keep the heap verifier happy.
// TODO(bmeurer): Fix this initialization to not use EmitFastNewObject,
// which causes the problem, since it puts Undefined into all slots of
// the object even though that doesn't make any sense for these fields.
// TODO(bmeurer, v8:4153): Fix this initialization to not use
// EmitFastNewObject, which causes the problem, since it puts
// Undefined into all slots of the object even though that
// doesn't make any sense for these fields.
array.byte_offset = 0;
array.byte_length = 0;
array.length = 0;
array.base_pointer = Convert<Smi>(0);
// 5. Let elementSize be the Number value of the Element Size value in Table
// 56 for constructorName.

View File

@ -5,6 +5,21 @@
#include 'src/builtins/builtins-typed-array-gen.h'
namespace typed_array {
// Naming convention from elements.cc. We have a similar intent but implement
// fastpaths using generics instead of using a class hierarchy for elements
// kinds specific implementations.
type Uint8Elements;
type Int8Elements;
type Uint16Elements;
type Int16Elements;
type Uint32Elements;
type Int32Elements;
type Float32Elements;
type Float64Elements;
type Uint8ClampedElements;
type BigUint64Elements;
type BigInt64Elements;
struct TypedArrayElementsInfo {
// Calculates the number of bytes required for specified number of elements.
CalculateByteLength(lengthSmi: PositiveSmi): uintptr labels IfInvalid {
@ -34,7 +49,6 @@ namespace typed_array {
}
sizeLog2: uintptr;
map: Map;
kind: ElementsKind;
}
extern runtime TypedArraySortFast(Context, Object): JSTypedArray;
@ -55,8 +69,8 @@ namespace typed_array {
ElementsKind): bool;
extern macro LoadFixedTypedArrayElementAsTagged(
RawPtr, Smi, constexpr ElementsKind, constexpr ParameterMode): Object;
extern macro StoreFixedTypedArrayElementFromTagged(
Context, FixedTypedArrayBase, Smi, Object, constexpr ElementsKind,
extern macro StoreJSTypedArrayElementFromTagged(
Context, JSTypedArray, Smi, Object, constexpr ElementsKind,
constexpr ParameterMode);
type LoadFn = builtin(Context, JSTypedArray, Smi) => Object;
@ -120,31 +134,31 @@ namespace typed_array {
macro GetLoadFnForElementsKind(elementsKind: ElementsKind): LoadFn {
if (IsElementsKindGreaterThan(elementsKind, UINT32_ELEMENTS)) {
if (elementsKind == INT32_ELEMENTS) {
return LoadFixedElement<FixedInt32Array>;
return LoadFixedElement<Int32Elements>;
} else if (elementsKind == FLOAT32_ELEMENTS) {
return LoadFixedElement<FixedFloat32Array>;
return LoadFixedElement<Float32Elements>;
} else if (elementsKind == FLOAT64_ELEMENTS) {
return LoadFixedElement<FixedFloat64Array>;
return LoadFixedElement<Float64Elements>;
} else if (elementsKind == UINT8_CLAMPED_ELEMENTS) {
return LoadFixedElement<FixedUint8ClampedArray>;
return LoadFixedElement<Uint8ClampedElements>;
} else if (elementsKind == BIGUINT64_ELEMENTS) {
return LoadFixedElement<FixedBigUint64Array>;
return LoadFixedElement<BigUint64Elements>;
} else if (elementsKind == BIGINT64_ELEMENTS) {
return LoadFixedElement<FixedBigInt64Array>;
return LoadFixedElement<BigInt64Elements>;
} else {
unreachable;
}
} else {
if (elementsKind == UINT8_ELEMENTS) {
return LoadFixedElement<FixedUint8Array>;
return LoadFixedElement<Uint8Elements>;
} else if (elementsKind == INT8_ELEMENTS) {
return LoadFixedElement<FixedInt8Array>;
return LoadFixedElement<Int8Elements>;
} else if (elementsKind == UINT16_ELEMENTS) {
return LoadFixedElement<FixedUint16Array>;
return LoadFixedElement<Uint16Elements>;
} else if (elementsKind == INT16_ELEMENTS) {
return LoadFixedElement<FixedInt16Array>;
return LoadFixedElement<Int16Elements>;
} else if (elementsKind == UINT32_ELEMENTS) {
return LoadFixedElement<FixedUint32Array>;
return LoadFixedElement<Uint32Elements>;
} else {
unreachable;
}
@ -152,37 +166,37 @@ namespace typed_array {
}
macro KindForArrayType<T: type>(): constexpr ElementsKind;
KindForArrayType<FixedUint8Array>(): constexpr ElementsKind {
KindForArrayType<Uint8Elements>(): constexpr ElementsKind {
return UINT8_ELEMENTS;
}
KindForArrayType<FixedInt8Array>(): constexpr ElementsKind {
KindForArrayType<Int8Elements>(): constexpr ElementsKind {
return INT8_ELEMENTS;
}
KindForArrayType<FixedUint16Array>(): constexpr ElementsKind {
KindForArrayType<Uint16Elements>(): constexpr ElementsKind {
return UINT16_ELEMENTS;
}
KindForArrayType<FixedInt16Array>(): constexpr ElementsKind {
KindForArrayType<Int16Elements>(): constexpr ElementsKind {
return INT16_ELEMENTS;
}
KindForArrayType<FixedUint32Array>(): constexpr ElementsKind {
KindForArrayType<Uint32Elements>(): constexpr ElementsKind {
return UINT32_ELEMENTS;
}
KindForArrayType<FixedInt32Array>(): constexpr ElementsKind {
KindForArrayType<Int32Elements>(): constexpr ElementsKind {
return INT32_ELEMENTS;
}
KindForArrayType<FixedFloat32Array>(): constexpr ElementsKind {
KindForArrayType<Float32Elements>(): constexpr ElementsKind {
return FLOAT32_ELEMENTS;
}
KindForArrayType<FixedFloat64Array>(): constexpr ElementsKind {
KindForArrayType<Float64Elements>(): constexpr ElementsKind {
return FLOAT64_ELEMENTS;
}
KindForArrayType<FixedUint8ClampedArray>(): constexpr ElementsKind {
KindForArrayType<Uint8ClampedElements>(): constexpr ElementsKind {
return UINT8_CLAMPED_ELEMENTS;
}
KindForArrayType<FixedBigUint64Array>(): constexpr ElementsKind {
KindForArrayType<BigUint64Elements>(): constexpr ElementsKind {
return BIGUINT64_ELEMENTS;
}
KindForArrayType<FixedBigInt64Array>(): constexpr ElementsKind {
KindForArrayType<BigInt64Elements>(): constexpr ElementsKind {
return BIGINT64_ELEMENTS;
}
@ -193,12 +207,11 @@ namespace typed_array {
}
builtin StoreFixedElement<T: type>(
context: Context, array: JSTypedArray, index: Smi,
context: Context, typedArray: JSTypedArray, index: Smi,
value: Object): Object {
const elements: FixedTypedArrayBase =
UnsafeCast<FixedTypedArrayBase>(array.elements);
StoreFixedTypedArrayElementFromTagged(
context, elements, index, value, KindForArrayType<T>(), SMI_PARAMETERS);
StoreJSTypedArrayElementFromTagged(
context, typedArray, index, value, KindForArrayType<T>(),
SMI_PARAMETERS);
return Undefined;
}
@ -313,42 +326,42 @@ namespace typed_array {
if (IsElementsKindGreaterThan(elementsKind, UINT32_ELEMENTS)) {
if (elementsKind == INT32_ELEMENTS) {
loadfn = LoadFixedElement<FixedInt32Array>;
storefn = StoreFixedElement<FixedInt32Array>;
loadfn = LoadFixedElement<Int32Elements>;
storefn = StoreFixedElement<Int32Elements>;
} else if (elementsKind == FLOAT32_ELEMENTS) {
loadfn = LoadFixedElement<FixedFloat32Array>;
storefn = StoreFixedElement<FixedFloat32Array>;
loadfn = LoadFixedElement<Float32Elements>;
storefn = StoreFixedElement<Float32Elements>;
} else if (elementsKind == FLOAT64_ELEMENTS) {
loadfn = LoadFixedElement<FixedFloat64Array>;
storefn = StoreFixedElement<FixedFloat64Array>;
loadfn = LoadFixedElement<Float64Elements>;
storefn = StoreFixedElement<Float64Elements>;
} else if (elementsKind == UINT8_CLAMPED_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint8ClampedArray>;
storefn = StoreFixedElement<FixedUint8ClampedArray>;
loadfn = LoadFixedElement<Uint8ClampedElements>;
storefn = StoreFixedElement<Uint8ClampedElements>;
} else if (elementsKind == BIGUINT64_ELEMENTS) {
loadfn = LoadFixedElement<FixedBigUint64Array>;
storefn = StoreFixedElement<FixedBigUint64Array>;
loadfn = LoadFixedElement<BigUint64Elements>;
storefn = StoreFixedElement<BigUint64Elements>;
} else if (elementsKind == BIGINT64_ELEMENTS) {
loadfn = LoadFixedElement<FixedBigInt64Array>;
storefn = StoreFixedElement<FixedBigInt64Array>;
loadfn = LoadFixedElement<BigInt64Elements>;
storefn = StoreFixedElement<BigInt64Elements>;
} else {
unreachable;
}
} else {
if (elementsKind == UINT8_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint8Array>;
storefn = StoreFixedElement<FixedUint8Array>;
loadfn = LoadFixedElement<Uint8Elements>;
storefn = StoreFixedElement<Uint8Elements>;
} else if (elementsKind == INT8_ELEMENTS) {
loadfn = LoadFixedElement<FixedInt8Array>;
storefn = StoreFixedElement<FixedInt8Array>;
loadfn = LoadFixedElement<Int8Elements>;
storefn = StoreFixedElement<Int8Elements>;
} else if (elementsKind == UINT16_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint16Array>;
storefn = StoreFixedElement<FixedUint16Array>;
loadfn = LoadFixedElement<Uint16Elements>;
storefn = StoreFixedElement<Uint16Elements>;
} else if (elementsKind == INT16_ELEMENTS) {
loadfn = LoadFixedElement<FixedInt16Array>;
storefn = StoreFixedElement<FixedInt16Array>;
loadfn = LoadFixedElement<Int16Elements>;
storefn = StoreFixedElement<Int16Elements>;
} else if (elementsKind == UINT32_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint32Array>;
storefn = StoreFixedElement<FixedUint32Array>;
loadfn = LoadFixedElement<Uint32Elements>;
storefn = StoreFixedElement<Uint32Elements>;
} else {
unreachable;
}

View File

@ -2032,39 +2032,18 @@ TNode<IntPtrT> CodeStubAssembler::LoadPropertyArrayLength(
return Signed(DecodeWord<PropertyArray::LengthField>(value));
}
TNode<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayBackingStore(
TNode<FixedTypedArrayBase> typed_array) {
TNode<RawPtrT> CodeStubAssembler::LoadJSTypedArrayBackingStore(
TNode<JSTypedArray> typed_array) {
// Backing store = external_pointer + base_pointer.
Node* external_pointer =
LoadObjectField(typed_array, FixedTypedArrayBase::kExternalPointerOffset,
LoadObjectField(typed_array, JSTypedArray::kExternalPointerOffset,
MachineType::Pointer());
Node* base_pointer =
LoadObjectField(typed_array, FixedTypedArrayBase::kBasePointerOffset);
LoadObjectField(typed_array, JSTypedArray::kBasePointerOffset);
return UncheckedCast<RawPtrT>(
IntPtrAdd(external_pointer, BitcastTaggedToWord(base_pointer)));
}
TNode<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayOnHeapBackingStore(
TNode<FixedTypedArrayBase> typed_array) {
// This is specialized method of retrieving the backing store pointer for on
// heap allocated typed array buffer. On heap allocated buffer's backing
// stores are a fixed offset from the pointer to a typed array's elements. See
// TypedArrayBuiltinsAssembler::AllocateOnHeapElements().
TNode<WordT> backing_store =
IntPtrAdd(BitcastTaggedToWord(typed_array),
IntPtrConstant(
FixedTypedArrayBase::ExternalPointerValueForOnHeapArray()));
#ifdef DEBUG
// Verify that this is an on heap backing store.
TNode<RawPtrT> expected_backing_store_pointer =
LoadFixedTypedArrayBackingStore(typed_array);
CSA_ASSERT(this, WordEqual(backing_store, expected_backing_store_pointer));
#endif
return UncheckedCast<RawPtrT>(backing_store);
}
Node* CodeStubAssembler::LoadFixedBigInt64ArrayElementAsTagged(
Node* data_pointer, Node* offset) {
if (Is64()) {
@ -2340,11 +2319,11 @@ TNode<Numeric> CodeStubAssembler::LoadFixedTypedArrayElementAsTagged(
return var_result.value();
}
void CodeStubAssembler::StoreFixedTypedArrayElementFromTagged(
TNode<Context> context, TNode<FixedTypedArrayBase> elements,
void CodeStubAssembler::StoreJSTypedArrayElementFromTagged(
TNode<Context> context, TNode<JSTypedArray> typed_array,
TNode<Object> index_node, TNode<Object> value, ElementsKind elements_kind,
ParameterMode parameter_mode) {
TNode<RawPtrT> data_pointer = LoadFixedTypedArrayBackingStore(elements);
TNode<RawPtrT> data_pointer = LoadJSTypedArrayBackingStore(typed_array);
switch (elements_kind) {
case UINT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
@ -2369,13 +2348,10 @@ void CodeStubAssembler::StoreFixedTypedArrayElementFromTagged(
LoadHeapNumberValue(CAST(value)), parameter_mode);
break;
case BIGUINT64_ELEMENTS:
case BIGINT64_ELEMENTS: {
TNode<IntPtrT> offset =
ElementOffsetFromIndex(index_node, elements_kind, parameter_mode, 0);
EmitBigTypedArrayElementStore(elements, data_pointer, offset,
CAST(value));
case BIGINT64_ELEMENTS:
StoreElement(data_pointer, elements_kind, index_node,
UncheckedCast<BigInt>(value), parameter_mode);
break;
}
default:
UNREACHABLE();
}
@ -3196,6 +3172,55 @@ TNode<UintPtrT> CodeStubAssembler::LoadBigIntDigit(TNode<BigInt> bigint,
MachineType::UintPtr()));
}
TNode<ByteArray> CodeStubAssembler::AllocateByteArray(TNode<UintPtrT> length,
AllocationFlags flags) {
Comment("AllocateByteArray");
VARIABLE(var_result, MachineRepresentation::kTagged);
// Compute the ByteArray size and check if it fits into new space.
Label if_lengthiszero(this), if_sizeissmall(this),
if_notsizeissmall(this, Label::kDeferred), if_join(this);
GotoIf(WordEqual(length, UintPtrConstant(0)), &if_lengthiszero);
Node* raw_size = GetArrayAllocationSize(
Signed(length), UINT8_ELEMENTS, INTPTR_PARAMETERS,
SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
TNode<WordT> size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
&if_sizeissmall, &if_notsizeissmall);
BIND(&if_sizeissmall);
{
// Just allocate the ByteArray in new space.
TNode<Object> result =
AllocateInNewSpace(UncheckedCast<IntPtrT>(size), flags);
DCHECK(RootsTable::IsImmortalImmovable(RootIndex::kByteArrayMap));
StoreMapNoWriteBarrier(result, RootIndex::kByteArrayMap);
StoreObjectFieldNoWriteBarrier(result, ByteArray::kLengthOffset,
SmiTag(Signed(length)));
var_result.Bind(result);
Goto(&if_join);
}
BIND(&if_notsizeissmall);
{
// We might need to allocate in large object space, go to the runtime.
Node* result = CallRuntime(Runtime::kAllocateByteArray, NoContextConstant(),
ChangeUintPtrToTagged(length));
var_result.Bind(result);
Goto(&if_join);
}
BIND(&if_lengthiszero);
{
var_result.Bind(LoadRoot(RootIndex::kEmptyByteArray));
Goto(&if_join);
}
BIND(&if_join);
return CAST(var_result.value());
}
TNode<String> CodeStubAssembler::AllocateSeqOneByteString(
uint32_t length, AllocationFlags flags) {
Comment("AllocateSeqOneByteString");
@ -4893,8 +4918,8 @@ void CodeStubAssembler::CopyFixedArrayElements(
Comment("[ CopyFixedArrayElements");
// Typed array elements are not supported.
DCHECK(!IsFixedTypedArrayElementsKind(from_kind));
DCHECK(!IsFixedTypedArrayElementsKind(to_kind));
DCHECK(!IsTypedArrayElementsKind(from_kind));
DCHECK(!IsTypedArrayElementsKind(to_kind));
Label done(this);
bool from_double_elements = IsDoubleElementsKind(from_kind);
@ -6582,8 +6607,17 @@ TNode<BoolT> CodeStubAssembler::IsJSFunctionMap(SloppyTNode<Map> map) {
return IsJSFunctionInstanceType(LoadMapInstanceType(map));
}
TNode<BoolT> CodeStubAssembler::IsJSTypedArrayInstanceType(
SloppyTNode<Int32T> instance_type) {
return InstanceTypeEqual(instance_type, JS_TYPED_ARRAY_TYPE);
}
TNode<BoolT> CodeStubAssembler::IsJSTypedArrayMap(SloppyTNode<Map> map) {
return IsJSTypedArrayInstanceType(LoadMapInstanceType(map));
}
TNode<BoolT> CodeStubAssembler::IsJSTypedArray(SloppyTNode<HeapObject> object) {
return HasInstanceType(object, JS_TYPED_ARRAY_TYPE);
return IsJSTypedArrayMap(LoadMap(object));
}
TNode<BoolT> CodeStubAssembler::IsJSArrayBuffer(
@ -6595,16 +6629,6 @@ TNode<BoolT> CodeStubAssembler::IsJSDataView(TNode<HeapObject> object) {
return HasInstanceType(object, JS_DATA_VIEW_TYPE);
}
TNode<BoolT> CodeStubAssembler::IsFixedTypedArray(
SloppyTNode<HeapObject> object) {
TNode<Int32T> instance_type = LoadInstanceType(object);
return UncheckedCast<BoolT>(Word32And(
Int32GreaterThanOrEqual(instance_type,
Int32Constant(FIRST_FIXED_TYPED_ARRAY_TYPE)),
Int32LessThanOrEqual(instance_type,
Int32Constant(LAST_FIXED_TYPED_ARRAY_TYPE))));
}
TNode<BoolT> CodeStubAssembler::IsJSRegExp(SloppyTNode<HeapObject> object) {
return HasInstanceType(object, JS_REGEXP_TYPE);
}
@ -10352,7 +10376,32 @@ MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) {
void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind,
Node* index, Node* value,
ParameterMode mode) {
if (IsFixedTypedArrayElementsKind(kind)) {
if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) {
TNode<IntPtrT> offset = ElementOffsetFromIndex(index, kind, mode, 0);
TVARIABLE(UintPtrT, var_low);
// Only used on 32-bit platforms.
TVARIABLE(UintPtrT, var_high);
BigIntToRawBytes(CAST(value), &var_low, &var_high);
MachineRepresentation rep = WordT::kMachineRepresentation;
#if defined(V8_TARGET_BIG_ENDIAN)
if (!Is64()) {
StoreNoWriteBarrier(rep, elements, offset, var_high.value());
StoreNoWriteBarrier(rep, elements,
IntPtrAdd(offset, IntPtrConstant(kSystemPointerSize)),
var_low.value());
} else {
StoreNoWriteBarrier(rep, elements, offset, var_low.value());
}
#else
StoreNoWriteBarrier(rep, elements, offset, var_low.value());
if (!Is64()) {
StoreNoWriteBarrier(rep, elements,
IntPtrAdd(offset, IntPtrConstant(kSystemPointerSize)),
var_high.value());
}
#endif
} else if (IsTypedArrayElementsKind(kind)) {
if (kind == UINT8_CLAMPED_ELEMENTS) {
CSA_ASSERT(this,
Word32Equal(value, Word32And(Int32Constant(0xFF), value)));
@ -10404,7 +10453,7 @@ Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) {
Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
TNode<Object> input, ElementsKind elements_kind, TNode<Context> context) {
DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
DCHECK(IsTypedArrayElementsKind(elements_kind));
MachineRepresentation rep;
switch (elements_kind) {
@ -10492,24 +10541,6 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
return var_result.value();
}
void CodeStubAssembler::EmitBigTypedArrayElementStore(
TNode<JSTypedArray> object, TNode<FixedTypedArrayBase> elements,
TNode<IntPtrT> intptr_key, TNode<Object> value, TNode<Context> context,
Label* opt_if_detached) {
TNode<BigInt> bigint_value = ToBigInt(context, value);
if (opt_if_detached != nullptr) {
// Check if buffer has been detached. Must happen after {ToBigInt}!
Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), opt_if_detached);
}
TNode<RawPtrT> backing_store = LoadFixedTypedArrayBackingStore(elements);
TNode<IntPtrT> offset = ElementOffsetFromIndex(intptr_key, BIGINT64_ELEMENTS,
INTPTR_PARAMETERS, 0);
EmitBigTypedArrayElementStore(elements, backing_store, offset, bigint_value);
}
void CodeStubAssembler::BigIntToRawBytes(TNode<BigInt> bigint,
TVariable<UintPtrT>* var_low,
TVariable<UintPtrT>* var_high) {
@ -10543,34 +10574,6 @@ void CodeStubAssembler::BigIntToRawBytes(TNode<BigInt> bigint,
BIND(&done);
}
void CodeStubAssembler::EmitBigTypedArrayElementStore(
TNode<FixedTypedArrayBase> elements, TNode<RawPtrT> backing_store,
TNode<IntPtrT> offset, TNode<BigInt> bigint_value) {
TVARIABLE(UintPtrT, var_low);
// Only used on 32-bit platforms.
TVARIABLE(UintPtrT, var_high);
BigIntToRawBytes(bigint_value, &var_low, &var_high);
MachineRepresentation rep = WordT::kMachineRepresentation;
#if defined(V8_TARGET_BIG_ENDIAN)
if (!Is64()) {
StoreNoWriteBarrier(rep, backing_store, offset, var_high.value());
StoreNoWriteBarrier(rep, backing_store,
IntPtrAdd(offset, IntPtrConstant(kSystemPointerSize)),
var_low.value());
} else {
StoreNoWriteBarrier(rep, backing_store, offset, var_low.value());
}
#else
StoreNoWriteBarrier(rep, backing_store, offset, var_low.value());
if (!Is64()) {
StoreNoWriteBarrier(rep, backing_store,
IntPtrAdd(offset, IntPtrConstant(kSystemPointerSize)),
var_high.value());
}
#endif
}
void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
ElementsKind elements_kind,
KeyedAccessStoreMode store_mode,
@ -10589,7 +10592,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
ParameterMode parameter_mode = INTPTR_PARAMETERS;
TNode<IntPtrT> intptr_key = TryToIntptr(key, bailout);
if (IsFixedTypedArrayElementsKind(elements_kind)) {
if (IsTypedArrayElementsKind(elements_kind)) {
Label done(this);
// IntegerIndexedElementSet converts value to a Number/BigInt prior to the
@ -10623,21 +10626,9 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
DebugBreak();
}
if (elements_kind == BIGINT64_ELEMENTS ||
elements_kind == BIGUINT64_ELEMENTS) {
TNode<BigInt> bigint_value = UncheckedCast<BigInt>(value);
TNode<RawPtrT> backing_store =
LoadFixedTypedArrayBackingStore(CAST(elements));
TNode<IntPtrT> offset = ElementOffsetFromIndex(
intptr_key, BIGINT64_ELEMENTS, INTPTR_PARAMETERS, 0);
EmitBigTypedArrayElementStore(CAST(elements), backing_store, offset,
bigint_value);
} else {
Node* backing_store = LoadFixedTypedArrayBackingStore(CAST(elements));
StoreElement(backing_store, elements_kind, intptr_key, value,
parameter_mode);
}
TNode<RawPtrT> backing_store = LoadJSTypedArrayBackingStore(CAST(object));
StoreElement(backing_store, elements_kind, intptr_key, value,
parameter_mode);
Goto(&done);
BIND(&done);

View File

@ -1233,10 +1233,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Float64T> LoadDoubleWithHoleCheck(
SloppyTNode<Object> base, SloppyTNode<IntPtrT> offset, Label* if_hole,
MachineType machine_type = MachineType::Float64());
TNode<RawPtrT> LoadFixedTypedArrayBackingStore(
TNode<FixedTypedArrayBase> typed_array);
TNode<RawPtrT> LoadFixedTypedArrayOnHeapBackingStore(
TNode<FixedTypedArrayBase> typed_array);
Node* LoadFixedTypedArrayElementAsTagged(
Node* data_pointer, Node* index_node, ElementsKind elements_kind,
ParameterMode parameter_mode = INTPTR_PARAMETERS);
@ -1253,10 +1249,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BigInt> BigIntFromInt32Pair(TNode<IntPtrT> low, TNode<IntPtrT> high);
TNode<BigInt> BigIntFromUint32Pair(TNode<UintPtrT> low, TNode<UintPtrT> high);
void StoreFixedTypedArrayElementFromTagged(
TNode<Context> context, TNode<FixedTypedArrayBase> elements,
TNode<Object> index_node, TNode<Object> value, ElementsKind elements_kind,
ParameterMode parameter_mode);
void StoreJSTypedArrayElementFromTagged(TNode<Context> context,
TNode<JSTypedArray> typed_array,
TNode<Object> index_node,
TNode<Object> value,
ElementsKind elements_kind,
ParameterMode parameter_mode);
// Context manipulation
TNode<Object> LoadContextElement(SloppyTNode<Context> context,
@ -1542,6 +1540,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Word32T> LoadBigIntBitfield(TNode<BigInt> bigint);
TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint, int digit_index);
// Allocate a ByteArray with the given length.
TNode<ByteArray> AllocateByteArray(TNode<UintPtrT> length,
AllocationFlags flags = kNone);
// Allocate a SeqOneByteString with the given length.
TNode<String> AllocateSeqOneByteString(uint32_t length,
AllocationFlags flags = kNone);
@ -2207,7 +2209,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> IsFixedArrayWithKindOrEmpty(SloppyTNode<HeapObject> object,
ElementsKind kind);
TNode<BoolT> IsFixedDoubleArray(SloppyTNode<HeapObject> object);
TNode<BoolT> IsFixedTypedArray(SloppyTNode<HeapObject> object);
TNode<BoolT> IsFunctionWithPrototypeSlotMap(SloppyTNode<Map> map);
TNode<BoolT> IsHashTable(SloppyTNode<HeapObject> object);
TNode<BoolT> IsEphemeronHashTable(SloppyTNode<HeapObject> object);
@ -2241,6 +2242,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> IsJSReceiverMap(SloppyTNode<Map> map);
TNode<BoolT> IsJSReceiver(SloppyTNode<HeapObject> object);
TNode<BoolT> IsJSRegExp(SloppyTNode<HeapObject> object);
TNode<BoolT> IsJSTypedArrayInstanceType(SloppyTNode<Int32T> instance_type);
TNode<BoolT> IsJSTypedArrayMap(SloppyTNode<Map> map);
TNode<BoolT> IsJSTypedArray(SloppyTNode<HeapObject> object);
TNode<BoolT> IsJSValueInstanceType(SloppyTNode<Int32T> instance_type);
TNode<BoolT> IsJSValueMap(SloppyTNode<Map> map);
@ -3034,20 +3037,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Context> context);
// Store value to an elements array with given elements kind.
// TODO(turbofan): For BIGINT64_ELEMENTS and BIGUINT64_ELEMENTS
// we pass {value} as BigInt object instead of int64_t. We should
// teach TurboFan to handle int64_t on 32-bit platforms eventually.
void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value,
ParameterMode mode);
void EmitBigTypedArrayElementStore(TNode<JSTypedArray> object,
TNode<FixedTypedArrayBase> elements,
TNode<IntPtrT> intptr_key,
TNode<Object> value,
TNode<Context> context,
Label* opt_if_detached);
// Part of the above, refactored out to reuse in another place.
void EmitBigTypedArrayElementStore(TNode<FixedTypedArrayBase> elements,
TNode<RawPtrT> backing_store,
TNode<IntPtrT> offset,
TNode<BigInt> bigint_value);
// Implements the BigInt part of
// https://tc39.github.io/proposal-bigint/#sec-numbertorawbytes,
// including truncation to 64 bits (i.e. modulo 2^64).
@ -3275,6 +3270,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// JSTypedArray helpers
TNode<UintPtrT> LoadJSTypedArrayLength(TNode<JSTypedArray> typed_array);
TNode<RawPtrT> LoadJSTypedArrayBackingStore(TNode<JSTypedArray> typed_array);
TNode<IntPtrT> ElementOffsetFromIndex(Node* index, ElementsKind kind,
ParameterMode mode, int base_size = 0);

View File

@ -415,6 +415,29 @@ FieldAccess AccessBuilder::ForJSTypedArrayLength() {
return access;
}
// static
FieldAccess AccessBuilder::ForJSTypedArrayBasePointer() {
FieldAccess access = {
kTaggedBase, JSTypedArray::kBasePointerOffset,
MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::OtherInternal(), MachineType::TypeCompressedTagged(),
kPointerWriteBarrier, LoadSensitivity::kCritical};
return access;
}
// static
FieldAccess AccessBuilder::ForJSTypedArrayExternalPointer() {
FieldAccess access = {kTaggedBase,
JSTypedArray::kExternalPointerOffset,
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::ExternalPointer(),
MachineType::Pointer(),
kNoWriteBarrier,
LoadSensitivity::kCritical};
return access;
}
// static
FieldAccess AccessBuilder::ForJSDataViewDataPointer() {
FieldAccess access = {kTaggedBase, JSDataView::kDataPointerOffset,
@ -531,29 +554,6 @@ FieldAccess AccessBuilder::ForPropertyArrayLengthAndHash() {
return access;
}
// static
FieldAccess AccessBuilder::ForFixedTypedArrayBaseBasePointer() {
FieldAccess access = {
kTaggedBase, FixedTypedArrayBase::kBasePointerOffset,
MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::OtherInternal(), MachineType::TypeCompressedTagged(),
kPointerWriteBarrier, LoadSensitivity::kCritical};
return access;
}
// static
FieldAccess AccessBuilder::ForFixedTypedArrayBaseExternalPointer() {
FieldAccess access = {kTaggedBase,
FixedTypedArrayBase::kExternalPointerOffset,
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::ExternalPointer(),
MachineType::Pointer(),
kNoWriteBarrier,
LoadSensitivity::kCritical};
return access;
}
// static
FieldAccess AccessBuilder::ForDescriptorArrayEnumCache() {
FieldAccess access = {
@ -998,7 +998,7 @@ ElementAccess AccessBuilder::ForTypedArrayElement(
ExternalArrayType type, bool is_external,
LoadSensitivity load_sensitivity) {
BaseTaggedness taggedness = is_external ? kUntaggedBase : kTaggedBase;
int header_size = is_external ? 0 : FixedTypedArrayBase::kDataOffset;
int header_size = is_external ? 0 : ByteArray::kHeaderSize;
switch (type) {
case kExternalInt8Array: {
ElementAccess access = {taggedness, header_size,

View File

@ -137,6 +137,12 @@ class V8_EXPORT_PRIVATE AccessBuilder final
// Provides access to JSTypedArray::length() field.
static FieldAccess ForJSTypedArrayLength();
// Provides access to JSTypedArray::base_pointer() field.
static FieldAccess ForJSTypedArrayBasePointer();
// Provides access to JSTypedArray::external_pointer() field.
static FieldAccess ForJSTypedArrayExternalPointer();
// Provides access to JSDataView::data_pointer() field.
static FieldAccess ForJSDataViewDataPointer();
@ -170,12 +176,6 @@ class V8_EXPORT_PRIVATE AccessBuilder final
// Provides access to PropertyArray::length() field.
static FieldAccess ForPropertyArrayLengthAndHash();
// Provides access to FixedTypedArrayBase::base_pointer() field.
static FieldAccess ForFixedTypedArrayBaseBasePointer();
// Provides access to FixedTypedArrayBase::external_pointer() field.
static FieldAccess ForFixedTypedArrayBaseExternalPointer();
// Provides access to DescriptorArray::enum_cache() field.
static FieldAccess ForDescriptorArrayEnumCache();

View File

@ -799,6 +799,9 @@ class V8_EXPORT_PRIVATE CodeAssembler {
TNode<UintPtrT> UintPtrConstant(uintptr_t value) {
return Unsigned(IntPtrConstant(bit_cast<intptr_t>(value)));
}
TNode<RawPtrT> PointerConstant(void* value) {
return ReinterpretCast<RawPtrT>(IntPtrConstant(bit_cast<intptr_t>(value)));
}
TNode<Number> NumberConstant(double value);
TNode<Smi> SmiConstant(Smi value);
TNode<Smi> SmiConstant(int value);

View File

@ -4766,7 +4766,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// Check that various {iterated_object_maps} have compatible elements kinds.
ElementsKind elements_kind =
MapRef(broker(), iterated_object_maps[0]).elements_kind();
if (IsFixedTypedArrayElementsKind(elements_kind)) {
if (IsTypedArrayElementsKind(elements_kind)) {
// TurboFan doesn't support loading from BigInt typed arrays yet.
if (elements_kind == BIGUINT64_ELEMENTS ||
elements_kind == BIGINT64_ELEMENTS) {
@ -4793,7 +4793,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// was reliable.
inference.InsertMapChecks(jsgraph(), &effect, control, p.feedback());
if (IsFixedTypedArrayElementsKind(elements_kind)) {
if (IsTypedArrayElementsKind(elements_kind)) {
// See if we can skip the detaching check.
if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
// Bail out if the {iterated_object}s JSArrayBuffer was detached.
@ -4821,7 +4821,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// {iterated_object} is either a JSArray or a JSTypedArray. For the
// latter case we even know that it's a Smi in UnsignedSmall range.
FieldAccess index_access = AccessBuilder::ForJSArrayIteratorNextIndex();
if (IsFixedTypedArrayElementsKind(elements_kind)) {
if (IsTypedArrayElementsKind(elements_kind)) {
index_access.type = TypeCache::Get()->kJSTypedArrayLengthType;
index_access.machine_type = MachineType::TypeCompressedTaggedSigned();
index_access.write_barrier_kind = kNoWriteBarrier;
@ -4845,7 +4845,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// already know something about the length here, which we can leverage
// to generate Word32 operations below without additional checking.
FieldAccess length_access =
IsFixedTypedArrayElementsKind(elements_kind)
IsTypedArrayElementsKind(elements_kind)
? AccessBuilder::ForJSTypedArrayLength()
: AccessBuilder::ForJSArrayLength(elements_kind);
Node* length = effect = graph()->NewNode(
@ -4875,15 +4875,15 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
DCHECK(iteration_kind == IterationKind::kEntries ||
iteration_kind == IterationKind::kValues);
if (IsFixedTypedArrayElementsKind(elements_kind)) {
Node* base_ptr = etrue = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
elements, etrue, if_true);
if (IsTypedArrayElementsKind(elements_kind)) {
Node* base_ptr = etrue =
graph()->NewNode(simplified()->LoadField(
AccessBuilder::ForJSTypedArrayBasePointer()),
iterated_object, etrue, if_true);
Node* external_ptr = etrue = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
elements, etrue, if_true);
AccessBuilder::ForJSTypedArrayExternalPointer()),
iterated_object, etrue, if_true);
ExternalArrayType array_type = kExternalInt8Array;
switch (elements_kind) {
@ -4952,7 +4952,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
done_false = jsgraph()->TrueConstant();
value_false = jsgraph()->UndefinedConstant();
if (!IsFixedTypedArrayElementsKind(elements_kind)) {
if (!IsTypedArrayElementsKind(elements_kind)) {
// Mark the {iterator} as exhausted by setting the [[NextIndex]] to a
// value that will never pass the length check again (aka the maximum
// value possible for the specific iterated object). Note that this is

View File

@ -340,7 +340,7 @@ class JSTypedArrayData : public JSObjectData {
bool is_on_heap() const { return is_on_heap_; }
size_t length() const { return length_; }
void* elements_external_pointer() const { return elements_external_pointer_; }
void* external_pointer() const { return external_pointer_; }
void Serialize(JSHeapBroker* broker);
bool serialized() const { return serialized_; }
@ -350,7 +350,7 @@ class JSTypedArrayData : public JSObjectData {
private:
bool const is_on_heap_;
size_t const length_;
void* const elements_external_pointer_;
void* const external_pointer_;
bool serialized_ = false;
HeapObjectData* buffer_ = nullptr;
@ -361,8 +361,7 @@ JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
: JSObjectData(broker, storage, object),
is_on_heap_(object->is_on_heap()),
length_(object->length()),
elements_external_pointer_(
FixedTypedArrayBase::cast(object->elements()).external_pointer()) {}
external_pointer_(object->external_pointer()) {}
void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
if (serialized_) return;
@ -2679,12 +2678,12 @@ BIMODAL_ACCESSOR_C(String, int, length)
BIMODAL_ACCESSOR(FeedbackCell, HeapObject, value)
void* JSTypedArrayRef::elements_external_pointer() const {
void* JSTypedArrayRef::external_pointer() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
return FixedTypedArrayBase::cast(object()->elements()).external_pointer();
return object()->external_pointer();
}
return data()->AsJSTypedArray()->elements_external_pointer();
return data()->AsJSTypedArray()->external_pointer();
}
bool MapRef::IsInobjectSlackTrackingInProgress() const {
@ -3253,7 +3252,7 @@ bool CanInlineElementAccess(MapRef const& map) {
if (map.has_indexed_interceptor()) return false;
ElementsKind const elements_kind = map.elements_kind();
if (IsFastElementsKind(elements_kind)) return true;
if (IsFixedTypedArrayElementsKind(elements_kind) &&
if (IsTypedArrayElementsKind(elements_kind) &&
elements_kind != BIGUINT64_ELEMENTS &&
elements_kind != BIGINT64_ELEMENTS) {
return true;

View File

@ -655,7 +655,7 @@ class JSTypedArrayRef : public JSObjectRef {
bool is_on_heap() const;
size_t length() const;
void* elements_external_pointer() const;
void* external_pointer() const;
void Serialize();
bool serialized() const;

View File

@ -1510,7 +1510,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// Check if we have the necessary data for building element accesses.
for (ElementAccessInfo const& access_info : access_infos) {
if (!IsFixedTypedArrayElementsKind(access_info.elements_kind())) continue;
if (!IsTypedArrayElementsKind(access_info.elements_kind())) continue;
base::Optional<JSTypedArrayRef> typed_array =
GetTypedArrayConstant(broker(), receiver);
if (typed_array.has_value()) {
@ -2554,8 +2554,8 @@ JSNativeContextSpecialization::BuildElementAccess(
ElementsKind elements_kind = access_info.elements_kind();
ZoneVector<Handle<Map>> const& receiver_maps = access_info.receiver_maps();
if (IsFixedTypedArrayElementsKind(elements_kind)) {
Node* buffer;
if (IsTypedArrayElementsKind(elements_kind)) {
Node* buffer_or_receiver = receiver;
Node* length;
Node* base_pointer;
Node* external_pointer;
@ -2565,7 +2565,6 @@ JSNativeContextSpecialization::BuildElementAccess(
base::Optional<JSTypedArrayRef> typed_array =
GetTypedArrayConstant(broker(), receiver);
if (typed_array.has_value()) {
buffer = jsgraph()->Constant(typed_array->buffer());
length = jsgraph()->Constant(static_cast<double>(typed_array->length()));
// Load the (known) base and external pointer for the {receiver}. The
@ -2573,23 +2572,13 @@ JSNativeContextSpecialization::BuildElementAccess(
// we need to make sure that any access is properly guarded.
base_pointer = jsgraph()->ZeroConstant();
external_pointer =
jsgraph()->PointerConstant(typed_array->elements_external_pointer());
jsgraph()->PointerConstant(typed_array->external_pointer());
} else {
// Load the {receiver}s length.
length = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
receiver, effect, control);
// Load the buffer for the {receiver}.
buffer = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
receiver, effect, control);
// Load the elements for the {receiver}.
Node* elements = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
receiver, effect, control);
// Load the base pointer for the {receiver}. This will always be Smi
// zero unless we allow on-heap TypedArrays, which is only the case
// for Chrome. Node and Electron both set this limit to 0. Setting
@ -2598,21 +2587,30 @@ JSNativeContextSpecialization::BuildElementAccess(
if (V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP == 0) {
base_pointer = jsgraph()->ZeroConstant();
} else {
base_pointer = effect = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
elements, effect, control);
base_pointer = effect =
graph()->NewNode(simplified()->LoadField(
AccessBuilder::ForJSTypedArrayBasePointer()),
receiver, effect, control);
}
// Load the external pointer for the {receiver}s {elements}.
external_pointer = effect = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
elements, effect, control);
// Load the external pointer for the {receiver}.
external_pointer = effect =
graph()->NewNode(simplified()->LoadField(
AccessBuilder::ForJSTypedArrayExternalPointer()),
receiver, effect, control);
}
// See if we can skip the detaching check.
if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
// Load the buffer for the {receiver}.
Node* buffer =
typed_array.has_value()
? jsgraph()->Constant(typed_array->buffer())
: (effect = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForJSArrayBufferViewBuffer()),
receiver, effect, control));
// Deopt if the {buffer} was detached.
// Note: A detached buffer leads to megamorphic feedback.
Node* buffer_bit_field = effect = graph()->NewNode(
@ -2627,6 +2625,9 @@ JSNativeContextSpecialization::BuildElementAccess(
effect = graph()->NewNode(
simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached),
check, effect, control);
// Retain the {buffer} instead of {receiver} to reduce live ranges.
buffer_or_receiver = buffer;
}
if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS ||
@ -2668,8 +2669,9 @@ JSNativeContextSpecialization::BuildElementAccess(
{
// Perform the actual load
vtrue = etrue = graph()->NewNode(
simplified()->LoadTypedElement(external_array_type), buffer,
base_pointer, external_pointer, index, etrue, if_true);
simplified()->LoadTypedElement(external_array_type),
buffer_or_receiver, base_pointer, external_pointer, index,
etrue, if_true);
}
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
@ -2689,8 +2691,9 @@ JSNativeContextSpecialization::BuildElementAccess(
} else {
// Perform the actual load.
value = effect = graph()->NewNode(
simplified()->LoadTypedElement(external_array_type), buffer,
base_pointer, external_pointer, index, effect, control);
simplified()->LoadTypedElement(external_array_type),
buffer_or_receiver, base_pointer, external_pointer, index, effect,
control);
}
break;
}
@ -2725,8 +2728,9 @@ JSNativeContextSpecialization::BuildElementAccess(
{
// Perform the actual store.
etrue = graph()->NewNode(
simplified()->StoreTypedElement(external_array_type), buffer,
base_pointer, external_pointer, index, value, etrue, if_true);
simplified()->StoreTypedElement(external_array_type),
buffer_or_receiver, base_pointer, external_pointer, index,
value, etrue, if_true);
}
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
@ -2741,8 +2745,9 @@ JSNativeContextSpecialization::BuildElementAccess(
} else {
// Perform the actual store
effect = graph()->NewNode(
simplified()->StoreTypedElement(external_array_type), buffer,
base_pointer, external_pointer, index, value, effect, control);
simplified()->StoreTypedElement(external_array_type),
buffer_or_receiver, base_pointer, external_pointer, index, value,
effect, control);
}
break;
}

View File

@ -324,11 +324,6 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
// require bit set types, they should get kOtherInternal.
case MUTABLE_HEAP_NUMBER_TYPE:
case FREE_SPACE_TYPE:
#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE:
TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE)
#undef FIXED_TYPED_ARRAY_CASE
case FILLER_TYPE:
case ACCESS_CHECK_INFO_TYPE:
case ASM_WASM_DATA_TYPE:

View File

@ -250,14 +250,6 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
FeedbackVector::cast(*this).FeedbackVectorVerify(isolate);
break;
#define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE: \
Fixed##Type##Array::cast(*this).FixedTypedArrayVerify(isolate); \
break;
TYPED_ARRAYS(VERIFY_TYPED_ARRAY)
#undef VERIFY_TYPED_ARRAY
case CODE_TYPE:
Code::cast(*this).CodeVerify(isolate);
break;
@ -523,18 +515,6 @@ void FeedbackVector::FeedbackVectorVerify(Isolate* isolate) {
CHECK(code->IsSmi() || code->IsWeakOrCleared());
}
template <class Traits>
void FixedTypedArray<Traits>::FixedTypedArrayVerify(Isolate* isolate) {
CHECK(IsHeapObject() && map().instance_type() == Traits::kInstanceType);
if (base_pointer().ptr() == ptr()) {
CHECK_EQ(reinterpret_cast<Address>(external_pointer()),
FixedTypedArrayBase::kDataOffset - kHeapObjectTag);
} else {
CHECK_EQ(Smi::kZero, base_pointer());
CHECK_EQ(0, number_of_elements_onheap_only());
}
}
bool JSObject::ElementsAreSafeToExamine() const {
// If a GC was caused while constructing this object, the elements
// pointer may point to a one pointer filler map.
@ -542,17 +522,16 @@ bool JSObject::ElementsAreSafeToExamine() const {
}
namespace {
void VerifyJSObjectElements(Isolate* isolate, JSObject object) {
// Only TypedArrays can have these specialized elements.
if (object.IsJSTypedArray()) {
// TODO(cbruni): Fix CreateTypedArray to either not instantiate the object
// or propertly initialize it on errors during construction.
/* CHECK(object->HasFixedTypedArrayElements()); */
/* CHECK(object->elements()->IsFixedTypedArrayBase()); */
// TODO(bmeurer,v8:4153): Fix CreateTypedArray to either not instantiate
// the object or propertly initialize it on errors during construction.
/* CHECK(object->HasTypedArrayElements()); */
return;
}
CHECK(!object.HasFixedTypedArrayElements());
CHECK(!object.elements().IsFixedTypedArrayBase());
CHECK(!object.elements().IsByteArray());
if (object.HasDoubleElements()) {
if (object.elements().length() > 0) {

View File

@ -210,14 +210,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
FreeSpace::cast(*this).FreeSpacePrint(os);
break;
#define PRINT_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype) \
case Fixed##Type##Array::kInstanceType: \
Fixed##Type##Array::cast(*this).FixedTypedArrayPrint(os); \
break;
TYPED_ARRAYS(PRINT_FIXED_TYPED_ARRAY)
#undef PRINT_FIXED_TYPED_ARRAY
case FILLER_TYPE:
os << "filler";
break;
@ -477,20 +469,6 @@ void FreeSpace::FreeSpacePrint(std::ostream& os) { // NOLINT
os << "free space, size " << Size() << "\n";
}
template <class Traits>
void FixedTypedArray<Traits>::FixedTypedArrayPrint(
std::ostream& os) { // NOLINT
PrintHeader(os, Traits::ArrayTypeName());
os << "\n - length: " << number_of_elements_onheap_only()
<< "\n - base_pointer: ";
if (base_pointer().ptr() == kNullAddress) {
os << "<nullptr>";
} else {
os << Brief(base_pointer());
}
os << "\n - external_pointer: " << external_pointer() << "\n";
}
bool JSObject::PrintProperties(std::ostream& os) { // NOLINT
if (HasFastProperties()) {
DescriptorArray descs = map().instance_descriptors();
@ -586,6 +564,30 @@ void DoPrintElements(std::ostream& os, Object object, int length) { // NOLINT
}
}
template <typename ElementType>
void PrintTypedArrayElements(std::ostream& os, const ElementType* data_ptr,
size_t length) {
if (length == 0) return;
size_t previous_index = 0;
ElementType previous_value = data_ptr[0];
ElementType value = 0;
for (size_t i = 1; i <= length; i++) {
if (i < length) value = data_ptr[i];
if (i != length && previous_value == value) {
continue;
}
os << "\n";
std::stringstream ss;
ss << previous_index;
if (previous_index != i - 1) {
ss << '-' << (i - 1);
}
os << std::setw(12) << ss.str() << ": " << previous_value;
previous_index = i;
previous_value = value;
}
}
template <typename T>
void PrintFixedArrayElements(std::ostream& os, T array) {
// Print in array notation for non-sparse arrays.
@ -685,12 +687,13 @@ void JSObject::PrintElements(std::ostream& os) { // NOLINT
break;
}
// TODO(bmeurer, v8:4153): Change this to size_t later.
#define PRINT_ELEMENTS(Type, type, TYPE, elementType) \
case TYPE##_ELEMENTS: { \
int length = static_cast<int>(JSTypedArray::cast(*this).length()); \
DoPrintElements<Fixed##Type##Array>(os, elements(), length); \
break; \
#define PRINT_ELEMENTS(Type, type, TYPE, elementType) \
case TYPE##_ELEMENTS: { \
size_t length = JSTypedArray::cast(*this).length(); \
const elementType* data_ptr = \
static_cast<const elementType*>(JSTypedArray::cast(*this).DataPtr()); \
PrintTypedArrayElements<elementType>(os, data_ptr, length); \
break; \
}
TYPED_ARRAYS(PRINT_ELEMENTS)
#undef PRINT_ELEMENTS
@ -749,10 +752,8 @@ static void JSObjectPrintBody(std::ostream& os,
if (obj.PrintProperties(os)) os << "\n ";
os << "}\n";
if (print_elements) {
int length = obj.HasFixedTypedArrayElements()
? FixedTypedArrayBase::cast(obj.elements())
.number_of_elements_onheap_only()
: obj.elements().length();
size_t length = obj.IsJSTypedArray() ? JSTypedArray::cast(obj).length()
: obj.elements().length();
if (length > 0) obj.PrintElements(os);
}
int embedder_fields = obj.GetEmbedderFieldCount();

View File

@ -1814,45 +1814,6 @@ Handle<BytecodeArray> Factory::NewBytecodeArray(
return instance;
}
Handle<FixedTypedArrayBase> Factory::NewFixedTypedArrayWithExternalPointer(
ExternalArrayType array_type, void* external_pointer,
AllocationType allocation) {
int size = FixedTypedArrayBase::kHeaderSize;
HeapObject result = AllocateRawWithImmortalMap(
size, allocation,
ReadOnlyRoots(isolate()).MapForFixedTypedArray(array_type));
Handle<FixedTypedArrayBase> elements(FixedTypedArrayBase::cast(result),
isolate());
elements->set_base_pointer(Smi::kZero, SKIP_WRITE_BARRIER);
elements->set_external_pointer(external_pointer);
elements->set_number_of_elements_onheap_only(0);
return elements;
}
Handle<FixedTypedArrayBase> Factory::NewFixedTypedArray(
size_t length, size_t byte_length, ExternalArrayType array_type,
bool initialize, AllocationType allocation) {
// TODO(7881): Smi length check
DCHECK(0 <= length && length <= Smi::kMaxValue);
CHECK(byte_length <= kMaxInt - FixedTypedArrayBase::kDataOffset);
size_t size =
OBJECT_POINTER_ALIGN(byte_length + FixedTypedArrayBase::kDataOffset);
Map map = ReadOnlyRoots(isolate()).MapForFixedTypedArray(array_type);
AllocationAlignment alignment =
array_type == kExternalFloat64Array ? kDoubleAligned : kWordAligned;
HeapObject object = AllocateRawWithImmortalMap(static_cast<int>(size),
allocation, map, alignment);
Handle<FixedTypedArrayBase> elements(FixedTypedArrayBase::cast(object),
isolate());
elements->set_base_pointer(*elements, SKIP_WRITE_BARRIER);
elements->set_external_pointer(
FixedTypedArrayBase::ExternalPointerPtrForOnHeapArray());
elements->set_number_of_elements_onheap_only(static_cast<int>(length));
if (initialize) memset(elements->DataPtr(), 0, elements->DataSize());
return elements;
}
Handle<Cell> Factory::NewCell(Handle<Object> value) {
AllowDeferredHandleDereference convert_to_cell;
STATIC_ASSERT(Cell::kSize <= kMaxRegularHeapObjectSize);
@ -2919,7 +2880,7 @@ Handle<JSObject> Factory::NewJSObjectFromMap(
InitializeJSObjectFromMap(js_obj, empty_fixed_array(), map);
DCHECK(js_obj->HasFastElements() || js_obj->HasFixedTypedArrayElements() ||
DCHECK(js_obj->HasFastElements() || js_obj->HasTypedArrayElements() ||
js_obj->HasFastStringWrapperElements() ||
js_obj->HasFastArgumentsElements() || js_obj->HasDictionaryElements());
return js_obj;
@ -3159,9 +3120,8 @@ void Factory::TypeAndSizeForElementsKind(ElementsKind kind,
namespace {
static void ForFixedTypedArray(ExternalArrayType array_type,
size_t* element_size,
ElementsKind* element_kind) {
void ForFixedTypedArray(ExternalArrayType array_type, size_t* element_size,
ElementsKind* element_kind) {
switch (array_type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case kExternal##Type##Array: \
@ -3175,25 +3135,50 @@ static void ForFixedTypedArray(ExternalArrayType array_type,
UNREACHABLE();
}
JSFunction GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) {
NativeContext native_context = isolate->context().native_context();
switch (type) {
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype) \
case kExternal##Type##Array: \
return native_context.type##_array_fun();
} // namespace
TYPED_ARRAYS(TYPED_ARRAY_FUN)
#undef TYPED_ARRAY_FUN
Handle<JSArrayBufferView> Factory::NewJSArrayBufferView(
Handle<Map> map, Handle<FixedArrayBase> elements,
Handle<JSArrayBuffer> buffer, size_t byte_offset, size_t byte_length,
AllocationType allocation) {
CHECK_LE(byte_length, buffer->byte_length());
CHECK_LE(byte_offset, buffer->byte_length());
CHECK_LE(byte_offset + byte_length, buffer->byte_length());
Handle<JSArrayBufferView> array_buffer_view =
Handle<JSArrayBufferView>::cast(NewJSObjectFromMap(map, allocation));
array_buffer_view->set_elements(*elements);
array_buffer_view->set_buffer(*buffer);
array_buffer_view->set_byte_offset(byte_offset);
array_buffer_view->set_byte_length(byte_length);
for (int i = 0; i < v8::ArrayBufferView::kEmbedderFieldCount; i++) {
array_buffer_view->SetEmbedderField(i, Smi::kZero);
}
UNREACHABLE();
DCHECK_EQ(array_buffer_view->GetEmbedderFieldCount(),
v8::ArrayBufferView::kEmbedderFieldCount);
return array_buffer_view;
}
JSFunction GetTypedArrayFun(ElementsKind elements_kind, Isolate* isolate) {
NativeContext native_context = isolate->context().native_context();
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t length,
AllocationType allocation) {
size_t element_size;
ElementsKind elements_kind;
ForFixedTypedArray(type, &element_size, &elements_kind);
size_t byte_length = length * element_size;
CHECK_LE(length, JSTypedArray::kMaxLength);
CHECK_EQ(length, byte_length / element_size);
CHECK_EQ(0, byte_offset % ElementsKindToByteSize(elements_kind));
Handle<Map> map;
switch (elements_kind) {
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
return native_context.type##_array_fun();
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
map = \
handle(isolate()->native_context()->type##_array_fun().initial_map(), \
isolate()); \
break;
TYPED_ARRAYS(TYPED_ARRAY_FUN)
#undef TYPED_ARRAY_FUN
@ -3201,111 +3186,24 @@ JSFunction GetTypedArrayFun(ElementsKind elements_kind, Isolate* isolate) {
default:
UNREACHABLE();
}
}
void SetupArrayBufferView(i::Isolate* isolate,
i::Handle<i::JSArrayBufferView> obj,
i::Handle<i::JSArrayBuffer> buffer,
size_t byte_offset, size_t byte_length) {
DCHECK_LE(byte_offset + byte_length, buffer->byte_length());
DCHECK_EQ(obj->GetEmbedderFieldCount(),
v8::ArrayBufferView::kEmbedderFieldCount);
for (int i = 0; i < v8::ArrayBufferView::kEmbedderFieldCount; i++) {
obj->SetEmbedderField(i, Smi::kZero);
}
obj->set_buffer(*buffer);
obj->set_byte_offset(byte_offset);
obj->set_byte_length(byte_length);
}
} // namespace
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
AllocationType allocation) {
Handle<JSFunction> typed_array_fun(GetTypedArrayFun(type, isolate()),
isolate());
Handle<Map> map(typed_array_fun->initial_map(), isolate());
return Handle<JSTypedArray>::cast(NewJSObjectFromMap(map, allocation));
}
Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
AllocationType allocation) {
Handle<JSFunction> typed_array_fun(GetTypedArrayFun(elements_kind, isolate()),
isolate());
Handle<Map> map(typed_array_fun->initial_map(), isolate());
return Handle<JSTypedArray>::cast(NewJSObjectFromMap(map, allocation));
}
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t length,
AllocationType allocation) {
Handle<JSTypedArray> obj = NewJSTypedArray(type, allocation);
size_t element_size;
ElementsKind elements_kind;
ForFixedTypedArray(type, &element_size, &elements_kind);
CHECK_EQ(byte_offset % element_size, 0);
CHECK(length <= (std::numeric_limits<size_t>::max() / element_size));
// TODO(7881): Smi length check
CHECK(length <= static_cast<size_t>(Smi::kMaxValue));
size_t byte_length = length * element_size;
SetupArrayBufferView(isolate(), obj, buffer, byte_offset, byte_length);
obj->set_length(length);
Handle<FixedTypedArrayBase> elements = NewFixedTypedArrayWithExternalPointer(
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;
}
Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
size_t number_of_elements,
AllocationType allocation) {
Handle<JSTypedArray> obj = NewJSTypedArray(elements_kind, allocation);
DCHECK_EQ(obj->GetEmbedderFieldCount(),
v8::ArrayBufferView::kEmbedderFieldCount);
for (int i = 0; i < v8::ArrayBufferView::kEmbedderFieldCount; i++) {
obj->SetEmbedderField(i, Smi::kZero);
}
size_t element_size;
ExternalArrayType array_type;
TypeAndSizeForElementsKind(elements_kind, &array_type, &element_size);
CHECK(number_of_elements <=
(std::numeric_limits<size_t>::max() / element_size));
// TODO(7881): Smi length check
CHECK(number_of_elements <= static_cast<size_t>(Smi::kMaxValue));
size_t byte_length = number_of_elements * element_size;
obj->set_byte_offset(0);
obj->set_byte_length(byte_length);
obj->set_length(number_of_elements);
Handle<JSArrayBuffer> buffer =
NewJSArrayBuffer(SharedFlag::kNotShared, allocation);
JSArrayBuffer::Setup(buffer, isolate(), true, nullptr, byte_length,
SharedFlag::kNotShared);
obj->set_buffer(*buffer);
Handle<FixedTypedArrayBase> elements = NewFixedTypedArray(
number_of_elements, byte_length, array_type, true, allocation);
obj->set_elements(*elements);
return obj;
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(
NewJSArrayBufferView(map, empty_byte_array(), buffer, byte_offset,
byte_length, allocation));
typed_array->set_length(length);
typed_array->set_external_pointer(
reinterpret_cast<byte*>(buffer->backing_store()) + byte_offset);
typed_array->set_base_pointer(Smi::kZero);
return typed_array;
}
Handle<JSDataView> Factory::NewJSDataView(Handle<JSArrayBuffer> buffer,
size_t byte_offset,
size_t byte_length) {
size_t byte_length,
AllocationType allocation) {
Handle<Map> map(isolate()->native_context()->data_view_fun().initial_map(),
isolate());
Handle<JSDataView> obj = Handle<JSDataView>::cast(NewJSObjectFromMap(map));
SetupArrayBufferView(isolate(), obj, buffer, byte_offset, byte_length);
Handle<JSDataView> obj = Handle<JSDataView>::cast(NewJSArrayBufferView(
map, empty_fixed_array(), buffer, byte_offset, byte_length, allocation));
obj->set_data_pointer(static_cast<uint8_t*>(buffer->backing_store()) +
byte_offset);
return obj;

View File

@ -40,6 +40,7 @@ class EnumCache;
class FinalizationGroupCleanupJobTask;
class FreshlyAllocatedBigInt;
class Isolate;
class JSArrayBufferView;
class JSDataView;
class JSGeneratorObject;
class JSMap;
@ -490,14 +491,6 @@ class V8_EXPORT_PRIVATE Factory {
int frame_size, int parameter_count,
Handle<FixedArray> constant_pool);
Handle<FixedTypedArrayBase> NewFixedTypedArrayWithExternalPointer(
ExternalArrayType array_type, void* external_pointer,
AllocationType allocation = AllocationType::kYoung);
Handle<FixedTypedArrayBase> NewFixedTypedArray(
size_t length, size_t byte_length, ExternalArrayType array_type,
bool initialize, AllocationType allocation = AllocationType::kYoung);
Handle<Cell> NewCell(Handle<Object> value);
Handle<PropertyCell> NewPropertyCell(
@ -696,27 +689,15 @@ class V8_EXPORT_PRIVATE Factory {
ExternalArrayType* array_type,
size_t* element_size);
Handle<JSTypedArray> NewJSTypedArray(
ExternalArrayType type,
AllocationType allocation = AllocationType::kYoung);
Handle<JSTypedArray> NewJSTypedArray(
ElementsKind elements_kind,
AllocationType allocation = AllocationType::kYoung);
// Creates a new JSTypedArray with the specified buffer.
Handle<JSTypedArray> NewJSTypedArray(
ExternalArrayType type, Handle<JSArrayBuffer> buffer, size_t byte_offset,
size_t length, AllocationType allocation = AllocationType::kYoung);
// Creates a new on-heap JSTypedArray.
Handle<JSTypedArray> NewJSTypedArray(
ElementsKind elements_kind, size_t number_of_elements,
Handle<JSDataView> NewJSDataView(
Handle<JSArrayBuffer> buffer, size_t byte_offset, size_t byte_length,
AllocationType allocation = AllocationType::kYoung);
Handle<JSDataView> NewJSDataView(Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t byte_length);
Handle<JSIteratorResult> NewJSIteratorResult(Handle<Object> value, bool done);
Handle<JSAsyncFromSyncIterator> NewJSAsyncFromSyncIterator(
Handle<JSReceiver> sync_iterator, Handle<Object> next);
@ -1041,6 +1022,11 @@ class V8_EXPORT_PRIVATE Factory {
Handle<Map> map, AllocationType allocation,
Handle<AllocationSite> allocation_site);
Handle<JSArrayBufferView> NewJSArrayBufferView(
Handle<Map> map, Handle<FixedArrayBase> elements,
Handle<JSArrayBuffer> buffer, size_t byte_offset, size_t byte_length,
AllocationType allocation);
// Allocate memory for an uninitialized array (e.g., a FixedArray or similar).
HeapObject AllocateRawArray(int size, AllocationType allocation);
HeapObject AllocateRawFixedArray(int length, AllocationType allocation);

View File

@ -2594,9 +2594,9 @@ STATIC_ASSERT(IsAligned(FixedDoubleArray::kHeaderSize, kDoubleAlignment));
// is only kTaggedSize aligned but we can keep using unaligned access since
// both x64 and arm64 architectures (where pointer compression supported)
// allow unaligned access to doubles.
STATIC_ASSERT(IsAligned(FixedTypedArrayBase::kDataOffset, kTaggedSize));
STATIC_ASSERT(IsAligned(ByteArray::kHeaderSize, kTaggedSize));
#else
STATIC_ASSERT(IsAligned(FixedTypedArrayBase::kDataOffset, kDoubleAlignment));
STATIC_ASSERT(IsAligned(ByteArray::kHeaderSize, kDoubleAlignment));
#endif
#ifdef V8_HOST_ARCH_32_BIT
@ -2920,7 +2920,6 @@ void Heap::RightTrimFixedArray(FixedArrayBase object, int elements_to_trim) {
DCHECK_GE(elements_to_trim, 0);
int bytes_to_trim;
DCHECK(!object.IsFixedTypedArrayBase());
if (object.IsByteArray()) {
int new_size = ByteArray::SizeFor(len - elements_to_trim);
bytes_to_trim = ByteArray::SizeFor(len) - new_size;

View File

@ -14,7 +14,7 @@ namespace v8 {
namespace internal {
// TODO(jkummerow): Drop the duplication: V(x, x) -> V(x).
#define TYPED_VISITOR_ID_LIST_CLASSES(V) \
#define TYPED_VISITOR_ID_LIST(V) \
V(AllocationSite, AllocationSite) \
V(BigInt, BigInt) \
V(ByteArray, ByteArray) \
@ -32,7 +32,6 @@ namespace internal {
V(FeedbackVector, FeedbackVector) \
V(FixedArray, FixedArray) \
V(FixedDoubleArray, FixedDoubleArray) \
V(FixedTypedArrayBase, FixedTypedArrayBase) \
V(JSArrayBuffer, JSArrayBuffer) \
V(JSDataView, JSDataView) \
V(JSFunction, JSFunction) \
@ -64,16 +63,9 @@ namespace internal {
V(WasmInstanceObject, WasmInstanceObject)
#define FORWARD_DECLARE(TypeName, Type) class Type;
TYPED_VISITOR_ID_LIST_CLASSES(FORWARD_DECLARE)
TYPED_VISITOR_ID_LIST(FORWARD_DECLARE)
#undef FORWARD_DECLARE
#define TYPED_VISITOR_ID_LIST_TYPEDEFS(V) \
V(FixedFloat64Array, FixedFloat64Array)
#define TYPED_VISITOR_ID_LIST(V) \
TYPED_VISITOR_ID_LIST_CLASSES(V) \
TYPED_VISITOR_ID_LIST_TYPEDEFS(V)
// The base class for visitors that need to dispatch on object type. The default
// behavior of all visit functions is to iterate body of the given object using
// the BodyDescriptor of the object.

View File

@ -186,27 +186,6 @@ AllocationResult Heap::Allocate(Map map, AllocationType allocation_type) {
return result;
}
AllocationResult Heap::AllocateEmptyFixedTypedArray(
ExternalArrayType array_type) {
int size = OBJECT_POINTER_ALIGN(FixedTypedArrayBase::kDataOffset);
HeapObject object;
AllocationResult allocation = AllocateRaw(
size, AllocationType::kReadOnly,
array_type == kExternalFloat64Array ? kDoubleAligned : kWordAligned);
if (!allocation.To(&object)) return allocation;
object.set_map_after_allocation(
ReadOnlyRoots(this).MapForFixedTypedArray(array_type),
SKIP_WRITE_BARRIER);
FixedTypedArrayBase elements = FixedTypedArrayBase::cast(object);
elements.set_base_pointer(elements, SKIP_WRITE_BARRIER);
elements.set_external_pointer(
FixedTypedArrayBase::ExternalPointerPtrForOnHeapArray());
elements.set_number_of_elements_onheap_only(0);
return elements;
}
bool Heap::CreateInitialMaps() {
HeapObject obj;
{
@ -426,12 +405,6 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_VARSIZE_MAP(SMALL_ORDERED_NAME_DICTIONARY_TYPE,
small_ordered_name_dictionary)
#define ALLOCATE_FIXED_TYPED_ARRAY_MAP(Type, type, TYPE, ctype) \
ALLOCATE_VARSIZE_MAP(FIXED_##TYPE##_ARRAY_TYPE, fixed_##type##_array)
TYPED_ARRAYS(ALLOCATE_FIXED_TYPED_ARRAY_MAP)
#undef ALLOCATE_FIXED_TYPED_ARRAY_MAP
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, sloppy_arguments_elements)
ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
@ -612,18 +585,6 @@ bool Heap::CreateInitialMaps() {
set_empty_closure_feedback_cell_array(ClosureFeedbackCellArray::cast(obj));
}
#define ALLOCATE_EMPTY_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype) \
{ \
FixedTypedArrayBase obj; \
if (!AllocateEmptyFixedTypedArray(kExternal##Type##Array).To(&obj)) { \
return false; \
} \
set_empty_fixed_##type##_array(obj); \
}
TYPED_ARRAYS(ALLOCATE_EMPTY_FIXED_TYPED_ARRAY)
#undef ALLOCATE_EMPTY_FIXED_TYPED_ARRAY
DCHECK(!InYoungGeneration(roots.empty_fixed_array()));
roots.bigint_map().SetConstructorFunctionIndex(

View File

@ -334,17 +334,16 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
BIND(&if_element);
Comment("element_load");
Node* intptr_index = TryToIntptr(p->name, miss);
Node* elements = LoadElements(holder);
Node* is_jsarray_condition =
IsSetWord<LoadHandler::IsJsArrayBits>(handler_word);
Node* elements_kind =
DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word);
Label if_hole(this), unimplemented_elements_kind(this),
if_oob(this, Label::kDeferred);
EmitElementLoad(holder, elements, elements_kind, intptr_index,
is_jsarray_condition, &if_hole, &rebox_double,
&var_double_value, &unimplemented_elements_kind, &if_oob,
miss, exit_point, access_mode);
EmitElementLoad(holder, elements_kind, intptr_index, is_jsarray_condition,
&if_hole, &rebox_double, &var_double_value,
&unimplemented_elements_kind, &if_oob, miss, exit_point,
access_mode);
BIND(&unimplemented_elements_kind);
{
@ -1869,83 +1868,87 @@ void AccessorAssembler::EmitFastElementsBoundsCheck(Node* object,
}
void AccessorAssembler::EmitElementLoad(
Node* object, Node* elements, Node* elements_kind,
SloppyTNode<IntPtrT> intptr_index, Node* is_jsarray_condition,
Label* if_hole, Label* rebox_double, Variable* var_double_value,
Label* unimplemented_elements_kind, Label* out_of_bounds, Label* miss,
ExitPoint* exit_point, LoadAccessMode access_mode) {
Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this),
if_fast_double(this), if_fast_holey_double(this), if_nonfast(this),
if_dictionary(this);
GotoIf(
Node* object, Node* elements_kind, SloppyTNode<IntPtrT> intptr_index,
Node* is_jsarray_condition, Label* if_hole, Label* rebox_double,
Variable* var_double_value, Label* unimplemented_elements_kind,
Label* out_of_bounds, Label* miss, ExitPoint* exit_point,
LoadAccessMode access_mode) {
Label if_typed_array(this), if_fast(this), if_fast_packed(this),
if_fast_holey(this), if_fast_double(this), if_fast_holey_double(this),
if_nonfast(this), if_dictionary(this);
Branch(
Int32GreaterThan(elements_kind, Int32Constant(LAST_FROZEN_ELEMENTS_KIND)),
&if_nonfast);
&if_nonfast, &if_fast);
EmitFastElementsBoundsCheck(object, elements, intptr_index,
is_jsarray_condition, out_of_bounds);
int32_t kinds[] = {// Handled by if_fast_packed.
PACKED_SMI_ELEMENTS, PACKED_ELEMENTS,
PACKED_SEALED_ELEMENTS, PACKED_FROZEN_ELEMENTS,
// Handled by if_fast_holey.
HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS, HOLEY_FROZEN_ELEMENTS,
HOLEY_SEALED_ELEMENTS,
// Handled by if_fast_double.
PACKED_DOUBLE_ELEMENTS,
// Handled by if_fast_holey_double.
HOLEY_DOUBLE_ELEMENTS};
Label* labels[] = {
// FAST_{SMI,}_ELEMENTS
&if_fast_packed, &if_fast_packed, &if_fast_packed, &if_fast_packed,
// FAST_HOLEY_{SMI,}_ELEMENTS
&if_fast_holey, &if_fast_holey, &if_fast_holey, &if_fast_holey,
// PACKED_DOUBLE_ELEMENTS
&if_fast_double,
// HOLEY_DOUBLE_ELEMENTS
&if_fast_holey_double};
Switch(elements_kind, unimplemented_elements_kind, kinds, labels,
arraysize(kinds));
BIND(&if_fast_packed);
BIND(&if_fast);
{
Comment("fast packed elements");
exit_point->Return(
access_mode == LoadAccessMode::kHas
? TrueConstant()
: UnsafeLoadFixedArrayElement(CAST(elements), intptr_index));
}
TNode<FixedArrayBase> elements = LoadJSObjectElements(CAST(object));
EmitFastElementsBoundsCheck(object, elements, intptr_index,
is_jsarray_condition, out_of_bounds);
int32_t kinds[] = {// Handled by if_fast_packed.
PACKED_SMI_ELEMENTS, PACKED_ELEMENTS,
PACKED_SEALED_ELEMENTS, PACKED_FROZEN_ELEMENTS,
// Handled by if_fast_holey.
HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS,
HOLEY_FROZEN_ELEMENTS, HOLEY_SEALED_ELEMENTS,
// Handled by if_fast_double.
PACKED_DOUBLE_ELEMENTS,
// Handled by if_fast_holey_double.
HOLEY_DOUBLE_ELEMENTS};
Label* labels[] = {
// FAST_{SMI,}_ELEMENTS
&if_fast_packed, &if_fast_packed, &if_fast_packed, &if_fast_packed,
// FAST_HOLEY_{SMI,}_ELEMENTS
&if_fast_holey, &if_fast_holey, &if_fast_holey, &if_fast_holey,
// PACKED_DOUBLE_ELEMENTS
&if_fast_double,
// HOLEY_DOUBLE_ELEMENTS
&if_fast_holey_double};
Switch(elements_kind, unimplemented_elements_kind, kinds, labels,
arraysize(kinds));
BIND(&if_fast_holey);
{
Comment("fast holey elements");
Node* element = UnsafeLoadFixedArrayElement(CAST(elements), intptr_index);
GotoIf(WordEqual(element, TheHoleConstant()), if_hole);
exit_point->Return(access_mode == LoadAccessMode::kHas ? TrueConstant()
: element);
}
BIND(&if_fast_double);
{
Comment("packed double elements");
if (access_mode == LoadAccessMode::kHas) {
exit_point->Return(TrueConstant());
} else {
var_double_value->Bind(LoadFixedDoubleArrayElement(
elements, intptr_index, MachineType::Float64()));
Goto(rebox_double);
BIND(&if_fast_packed);
{
Comment("fast packed elements");
exit_point->Return(
access_mode == LoadAccessMode::kHas
? TrueConstant()
: UnsafeLoadFixedArrayElement(CAST(elements), intptr_index));
}
}
BIND(&if_fast_holey_double);
{
Comment("holey double elements");
Node* value = LoadFixedDoubleArrayElement(elements, intptr_index,
MachineType::Float64(), 0,
INTPTR_PARAMETERS, if_hole);
if (access_mode == LoadAccessMode::kHas) {
exit_point->Return(TrueConstant());
} else {
var_double_value->Bind(value);
Goto(rebox_double);
BIND(&if_fast_holey);
{
Comment("fast holey elements");
Node* element = UnsafeLoadFixedArrayElement(CAST(elements), intptr_index);
GotoIf(WordEqual(element, TheHoleConstant()), if_hole);
exit_point->Return(access_mode == LoadAccessMode::kHas ? TrueConstant()
: element);
}
BIND(&if_fast_double);
{
Comment("packed double elements");
if (access_mode == LoadAccessMode::kHas) {
exit_point->Return(TrueConstant());
} else {
var_double_value->Bind(LoadFixedDoubleArrayElement(
CAST(elements), intptr_index, MachineType::Float64()));
Goto(rebox_double);
}
}
BIND(&if_fast_holey_double);
{
Comment("holey double elements");
Node* value = LoadFixedDoubleArrayElement(CAST(elements), intptr_index,
MachineType::Float64(), 0,
INTPTR_PARAMETERS, if_hole);
if (access_mode == LoadAccessMode::kHas) {
exit_point->Return(TrueConstant());
} else {
var_double_value->Bind(value);
Goto(rebox_double);
}
}
}
@ -1959,123 +1962,127 @@ void AccessorAssembler::EmitElementLoad(
GotoIf(Word32Equal(elements_kind, Int32Constant(DICTIONARY_ELEMENTS)),
&if_dictionary);
Goto(unimplemented_elements_kind);
}
BIND(&if_dictionary);
{
Comment("dictionary elements");
GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds);
BIND(&if_dictionary);
{
Comment("dictionary elements");
GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds);
TNode<Object> value = BasicLoadNumberDictionaryElement(
CAST(elements), intptr_index, miss, if_hole);
exit_point->Return(access_mode == LoadAccessMode::kHas ? TrueConstant()
: value);
}
TNode<FixedArrayBase> elements = LoadJSObjectElements(CAST(object));
TNode<Object> value = BasicLoadNumberDictionaryElement(
CAST(elements), intptr_index, miss, if_hole);
exit_point->Return(access_mode == LoadAccessMode::kHas ? TrueConstant()
: value);
}
BIND(&if_typed_array);
{
Comment("typed elements");
// Check if buffer has been detached.
Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), miss);
BIND(&if_typed_array);
{
Comment("typed elements");
// Check if buffer has been detached.
Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), miss);
// Bounds check.
TNode<UintPtrT> length = LoadJSTypedArrayLength(CAST(object));
GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds);
if (access_mode == LoadAccessMode::kHas) {
exit_point->Return(TrueConstant());
} else {
Node* backing_store = LoadFixedTypedArrayBackingStore(CAST(elements));
// Bounds check.
TNode<UintPtrT> length = LoadJSTypedArrayLength(CAST(object));
GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds);
if (access_mode == LoadAccessMode::kHas) {
exit_point->Return(TrueConstant());
} else {
Node* backing_store = LoadJSTypedArrayBackingStore(CAST(object));
Label uint8_elements(this), int8_elements(this), uint16_elements(this),
int16_elements(this), uint32_elements(this), int32_elements(this),
float32_elements(this), float64_elements(this),
bigint64_elements(this), biguint64_elements(this);
Label* elements_kind_labels[] = {
&uint8_elements, &uint8_elements, &int8_elements,
&uint16_elements, &int16_elements, &uint32_elements,
&int32_elements, &float32_elements, &float64_elements,
&bigint64_elements, &biguint64_elements};
int32_t elements_kinds[] = {
UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS,
INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS,
BIGINT64_ELEMENTS, BIGUINT64_ELEMENTS};
const size_t kTypedElementsKindCount =
LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1;
DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
Switch(elements_kind, miss, elements_kinds, elements_kind_labels,
kTypedElementsKindCount);
BIND(&uint8_elements);
{
Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too.
Node* element = Load(MachineType::Uint8(), backing_store, intptr_index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&int8_elements);
{
Comment("INT8_ELEMENTS");
Node* element = Load(MachineType::Int8(), backing_store, intptr_index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&uint16_elements);
{
Comment("UINT16_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(1));
Node* element = Load(MachineType::Uint16(), backing_store, index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&int16_elements);
{
Comment("INT16_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(1));
Node* element = Load(MachineType::Int16(), backing_store, index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&uint32_elements);
{
Comment("UINT32_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(2));
Node* element = Load(MachineType::Uint32(), backing_store, index);
exit_point->Return(ChangeUint32ToTagged(element));
}
BIND(&int32_elements);
{
Comment("INT32_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(2));
Node* element = Load(MachineType::Int32(), backing_store, index);
exit_point->Return(ChangeInt32ToTagged(element));
}
BIND(&float32_elements);
{
Comment("FLOAT32_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(2));
Node* element = Load(MachineType::Float32(), backing_store, index);
var_double_value->Bind(ChangeFloat32ToFloat64(element));
Goto(rebox_double);
}
BIND(&float64_elements);
{
Comment("FLOAT64_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(3));
Node* element = Load(MachineType::Float64(), backing_store, index);
var_double_value->Bind(element);
Goto(rebox_double);
}
BIND(&bigint64_elements);
{
Comment("BIGINT64_ELEMENTS");
exit_point->Return(LoadFixedTypedArrayElementAsTagged(
backing_store, intptr_index, BIGINT64_ELEMENTS, INTPTR_PARAMETERS));
}
BIND(&biguint64_elements);
{
Comment("BIGUINT64_ELEMENTS");
exit_point->Return(LoadFixedTypedArrayElementAsTagged(
backing_store, intptr_index, BIGUINT64_ELEMENTS,
INTPTR_PARAMETERS));
Label uint8_elements(this), int8_elements(this), uint16_elements(this),
int16_elements(this), uint32_elements(this), int32_elements(this),
float32_elements(this), float64_elements(this),
bigint64_elements(this), biguint64_elements(this);
Label* elements_kind_labels[] = {
&uint8_elements, &uint8_elements, &int8_elements,
&uint16_elements, &int16_elements, &uint32_elements,
&int32_elements, &float32_elements, &float64_elements,
&bigint64_elements, &biguint64_elements};
int32_t elements_kinds[] = {
UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS,
INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS,
BIGINT64_ELEMENTS, BIGUINT64_ELEMENTS};
const size_t kTypedElementsKindCount =
LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1;
DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
Switch(elements_kind, miss, elements_kinds, elements_kind_labels,
kTypedElementsKindCount);
BIND(&uint8_elements);
{
Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too.
Node* element =
Load(MachineType::Uint8(), backing_store, intptr_index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&int8_elements);
{
Comment("INT8_ELEMENTS");
Node* element =
Load(MachineType::Int8(), backing_store, intptr_index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&uint16_elements);
{
Comment("UINT16_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(1));
Node* element = Load(MachineType::Uint16(), backing_store, index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&int16_elements);
{
Comment("INT16_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(1));
Node* element = Load(MachineType::Int16(), backing_store, index);
exit_point->Return(SmiFromInt32(element));
}
BIND(&uint32_elements);
{
Comment("UINT32_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(2));
Node* element = Load(MachineType::Uint32(), backing_store, index);
exit_point->Return(ChangeUint32ToTagged(element));
}
BIND(&int32_elements);
{
Comment("INT32_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(2));
Node* element = Load(MachineType::Int32(), backing_store, index);
exit_point->Return(ChangeInt32ToTagged(element));
}
BIND(&float32_elements);
{
Comment("FLOAT32_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(2));
Node* element = Load(MachineType::Float32(), backing_store, index);
var_double_value->Bind(ChangeFloat32ToFloat64(element));
Goto(rebox_double);
}
BIND(&float64_elements);
{
Comment("FLOAT64_ELEMENTS");
Node* index = WordShl(intptr_index, IntPtrConstant(3));
Node* element = Load(MachineType::Float64(), backing_store, index);
var_double_value->Bind(element);
Goto(rebox_double);
}
BIND(&bigint64_elements);
{
Comment("BIGINT64_ELEMENTS");
exit_point->Return(LoadFixedTypedArrayElementAsTagged(
backing_store, intptr_index, BIGINT64_ELEMENTS,
INTPTR_PARAMETERS));
}
BIND(&biguint64_elements);
{
Comment("BIGUINT64_ELEMENTS");
exit_point->Return(LoadFixedTypedArrayElementAsTagged(
backing_store, intptr_index, BIGUINT64_ELEMENTS,
INTPTR_PARAMETERS));
}
}
}
}
@ -2131,7 +2138,6 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
// Receivers requiring non-standard element accesses (interceptors, access
// checks, strings and string wrappers, proxies) are handled in the runtime.
GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &if_custom);
Node* elements = LoadElements(receiver);
Node* elements_kind = LoadMapElementsKind(receiver_map);
Node* is_jsarray_condition = InstanceTypeEqual(instance_type, JS_ARRAY_TYPE);
VARIABLE(var_double_value, MachineRepresentation::kFloat64);
@ -2140,10 +2146,9 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
// Unimplemented elements kinds fall back to a runtime call.
Label* unimplemented_elements_kind = slow;
IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
EmitElementLoad(receiver, elements, elements_kind, index,
is_jsarray_condition, &if_element_hole, &rebox_double,
&var_double_value, unimplemented_elements_kind, &if_oob, slow,
&direct_exit);
EmitElementLoad(receiver, elements_kind, index, is_jsarray_condition,
&if_element_hole, &rebox_double, &var_double_value,
unimplemented_elements_kind, &if_oob, slow, &direct_exit);
BIND(&rebox_double);
Return(AllocateHeapNumberWithValue(var_double_value.value()));

View File

@ -307,7 +307,7 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
void EmitFastElementsBoundsCheck(Node* object, Node* elements,
Node* intptr_index,
Node* is_jsarray_condition, Label* miss);
void EmitElementLoad(Node* object, Node* elements, Node* elements_kind,
void EmitElementLoad(Node* object, Node* elements_kind,
SloppyTNode<IntPtrT> key, Node* is_jsarray_condition,
Label* if_hole, Label* rebox_double,
Variable* var_double_value,

View File

@ -1186,7 +1186,7 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map,
}
DCHECK(IsFastElementsKind(elements_kind) ||
IsFrozenOrSealedElementsKind(elements_kind) ||
IsFixedTypedArrayElementsKind(elements_kind));
IsTypedArrayElementsKind(elements_kind));
bool convert_hole_to_undefined =
(elements_kind == HOLEY_SMI_ELEMENTS ||
elements_kind == HOLEY_ELEMENTS) &&
@ -1855,7 +1855,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
if (store_mode != STANDARD_STORE) {
size_t external_arrays = 0;
for (Handle<Map> map : target_receiver_maps) {
if (map->has_fixed_typed_array_elements()) {
if (map->has_typed_array_elements()) {
DCHECK(!IsStoreInArrayLiteralICKind(kind()));
external_arrays++;
}
@ -1903,10 +1903,10 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
CodeFactory::KeyedStoreIC_SloppyArguments(isolate(), store_mode).code();
} else if (receiver_map->has_fast_elements() ||
receiver_map->has_sealed_elements() ||
receiver_map->has_fixed_typed_array_elements()) {
receiver_map->has_typed_array_elements()) {
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
code = CodeFactory::StoreFastElementIC(isolate(), store_mode).code();
if (receiver_map->has_fixed_typed_array_elements()) return code;
if (receiver_map->has_typed_array_elements()) return code;
} else if (IsStoreInArrayLiteralICKind(kind())) {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), StoreInArrayLiteralIC_SlowStub);
@ -2012,7 +2012,7 @@ KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, uint32_t index) {
return STORE_AND_GROW_HANDLE_COW;
}
if (!FLAG_trace_external_array_abuse &&
receiver->map().has_fixed_typed_array_elements() && oob_access) {
receiver->map().has_typed_array_elements() && oob_access) {
return STORE_IGNORE_OUT_OF_BOUNDS;
}
return receiver->elements().IsCowArray() ? STORE_HANDLE_COW : STANDARD_STORE;

View File

@ -58,7 +58,7 @@ int ElementsKindToByteSize(ElementsKind elements_kind) {
int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
if (IsFixedTypedArrayElementsKind(elements_kind)) {
if (IsTypedArrayElementsKind(elements_kind)) {
return 0;
} else {
return FixedArray::kHeaderSize - kHeapObjectTag;
@ -154,8 +154,8 @@ bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
ElementsKind to_kind) {
if (!IsFastElementsKind(from_kind)) return false;
if (!IsFastTransitionTarget(to_kind)) return false;
DCHECK(!IsFixedTypedArrayElementsKind(from_kind));
DCHECK(!IsFixedTypedArrayElementsKind(to_kind));
DCHECK(!IsTypedArrayElementsKind(from_kind));
DCHECK(!IsTypedArrayElementsKind(to_kind));
switch (from_kind) {
case PACKED_SMI_ELEMENTS:
return to_kind != PACKED_SMI_ELEMENTS;

View File

@ -123,14 +123,13 @@ inline bool IsStringWrapperElementsKind(ElementsKind kind) {
SLOW_STRING_WRAPPER_ELEMENTS);
}
inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
inline bool IsTypedArrayElementsKind(ElementsKind kind) {
return IsInRange(kind, FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
}
inline bool IsTerminalElementsKind(ElementsKind kind) {
return kind == TERMINAL_FAST_ELEMENTS_KIND ||
IsFixedTypedArrayElementsKind(kind);
return kind == TERMINAL_FAST_ELEMENTS_KIND || IsTypedArrayElementsKind(kind);
}
inline bool IsFastElementsKind(ElementsKind kind) {
@ -139,7 +138,7 @@ inline bool IsFastElementsKind(ElementsKind kind) {
}
inline bool IsTransitionElementsKind(ElementsKind kind) {
return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind) ||
return IsFastElementsKind(kind) || IsTypedArrayElementsKind(kind) ||
kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
kind == FAST_STRING_WRAPPER_ELEMENTS;
}

View File

@ -44,17 +44,17 @@
// - FastPackedDoubleElementsAccessor
// - FastHoleyDoubleElementsAccessor
// - TypedElementsAccessor: template, with instantiations:
// - FixedUint8ElementsAccessor
// - FixedInt8ElementsAccessor
// - FixedUint16ElementsAccessor
// - FixedInt16ElementsAccessor
// - FixedUint32ElementsAccessor
// - FixedInt32ElementsAccessor
// - FixedFloat32ElementsAccessor
// - FixedFloat64ElementsAccessor
// - FixedUint8ClampedElementsAccessor
// - FixedBigUint64ElementsAccessor
// - FixedBigInt64ElementsAccessor
// - Uint8ElementsAccessor
// - Int8ElementsAccessor
// - Uint16ElementsAccessor
// - Int16ElementsAccessor
// - Uint32ElementsAccessor
// - Int32ElementsAccessor
// - Float32ElementsAccessor
// - Float64ElementsAccessor
// - Uint8ClampedElementsAccessor
// - BigUint64ElementsAccessor
// - BigInt64ElementsAccessor
// - DictionaryElementsAccessor
// - SloppyArgumentsElementsAccessor
// - FastSloppyArgumentsElementsAccessor
@ -100,18 +100,17 @@ enum Where { AT_START, AT_END };
FixedArray) \
V(SlowStringWrapperElementsAccessor, SLOW_STRING_WRAPPER_ELEMENTS, \
FixedArray) \
V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \
V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \
V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \
V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \
V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \
V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \
V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \
FixedUint8ClampedArray) \
V(FixedBigUint64ElementsAccessor, BIGUINT64_ELEMENTS, FixedBigUint64Array) \
V(FixedBigInt64ElementsAccessor, BIGINT64_ELEMENTS, FixedBigInt64Array)
V(Uint8ElementsAccessor, UINT8_ELEMENTS, ByteArray) \
V(Int8ElementsAccessor, INT8_ELEMENTS, ByteArray) \
V(Uint16ElementsAccessor, UINT16_ELEMENTS, ByteArray) \
V(Int16ElementsAccessor, INT16_ELEMENTS, ByteArray) \
V(Uint32ElementsAccessor, UINT32_ELEMENTS, ByteArray) \
V(Int32ElementsAccessor, INT32_ELEMENTS, ByteArray) \
V(Float32ElementsAccessor, FLOAT32_ELEMENTS, ByteArray) \
V(Float64ElementsAccessor, FLOAT64_ELEMENTS, ByteArray) \
V(Uint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, ByteArray) \
V(BigUint64ElementsAccessor, BIGUINT64_ELEMENTS, ByteArray) \
V(BigInt64ElementsAccessor, BIGINT64_ELEMENTS, ByteArray)
template <ElementsKind Kind>
class ElementsKindTraits {
@ -1088,7 +1087,7 @@ class ElementsAccessorBase : public InternalElementsAccessor {
Handle<Object> value;
if (details.kind() == kData) {
value = Subclass::GetImpl(isolate, object->elements(), entry);
value = Subclass::GetInternalImpl(object, entry);
} else {
// This might modify the elements and/or change the elements kind.
LookupIterator it(isolate, object, index, LookupIterator::OWN);
@ -2905,32 +2904,117 @@ class FastHoleyDoubleElementsAccessor
ElementsKindTraits<HOLEY_DOUBLE_ELEMENTS>> {};
// Super class for all external element arrays.
template <ElementsKind Kind, typename ctype>
template <ElementsKind Kind, typename ElementType>
class TypedElementsAccessor
: public ElementsAccessorBase<TypedElementsAccessor<Kind, ctype>,
: public ElementsAccessorBase<TypedElementsAccessor<Kind, ElementType>,
ElementsKindTraits<Kind>> {
public:
using BackingStore = typename ElementsKindTraits<Kind>::BackingStore;
using AccessorClass = TypedElementsAccessor<Kind, ctype>;
using AccessorClass = TypedElementsAccessor<Kind, ElementType>;
static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
Object value) {
SetImpl(holder->elements(), entry, value);
// Conversions from (other) scalar values.
static ElementType FromScalar(int value) {
return static_cast<ElementType>(value);
}
static ElementType FromScalar(uint32_t value) {
return static_cast<ElementType>(value);
}
static ElementType FromScalar(double value) {
return FromScalar(DoubleToInt32(value));
}
static ElementType FromScalar(int64_t value) { UNREACHABLE(); }
static ElementType FromScalar(uint64_t value) { UNREACHABLE(); }
// Conversions from objects / handles.
static ElementType FromObject(Object value, bool* lossless = nullptr) {
if (value.IsSmi()) {
return FromScalar(Smi::ToInt(value));
} else if (value.IsHeapNumber()) {
return FromScalar(HeapNumber::cast(value).value());
} else {
// Clamp undefined here as well. All other types have been
// converted to a number type further up in the call chain.
DCHECK(value.IsUndefined());
return FromScalar(Oddball::cast(value).to_number_raw());
}
}
static ElementType FromHandle(Handle<Object> value,
bool* lossless = nullptr) {
return FromObject(*value, lossless);
}
static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
Object value) {
BackingStore::cast(backing_store).SetValue(entry, value);
// Conversion of scalar value to handlified object.
static Handle<Object> ToHandle(Isolate* isolate, ElementType value);
static void SetImpl(Handle<JSObject> holder, uint32_t entry, Object value) {
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(holder);
DCHECK_LE(entry, typed_array->length());
SetImpl(static_cast<ElementType*>(typed_array->DataPtr()), entry,
FromObject(value));
}
static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
Object value, WriteBarrierMode mode) {
BackingStore::cast(backing_store)->SetValue(entry, value);
static void SetImpl(ElementType* data_ptr, size_t entry, ElementType value) {
// The JavaScript memory model allows for racy reads and writes to a
// SharedArrayBuffer's backing store. ThreadSanitizer will catch these
// racy accesses and warn about them, so we disable TSAN for these reads
// and writes using annotations.
//
// We don't use relaxed atomics here, as it is not a requirement of the
// JavaScript memory model to have tear-free reads of overlapping accesses,
// and using relaxed atomics may introduce overhead.
TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
// TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
// fields (external pointers, doubles and BigInt data) are only
// kTaggedSize aligned so we have to use unaligned pointer friendly way of
// accessing them in order to avoid undefined behavior in C++ code.
WriteUnalignedValue<ElementType>(
reinterpret_cast<Address>(data_ptr + entry), value);
} else {
data_ptr[entry] = value;
}
TSAN_ANNOTATE_IGNORE_WRITES_END;
}
static Handle<Object> GetInternalImpl(Handle<JSObject> holder,
uint32_t entry) {
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(holder);
Isolate* isolate = typed_array->GetIsolate();
DCHECK_LE(entry, typed_array->length());
DCHECK(!typed_array->WasDetached());
ElementType elem =
GetImpl(static_cast<ElementType*>(typed_array->DataPtr()), entry);
return ToHandle(isolate, elem);
}
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase backing_store,
uint32_t entry) {
return BackingStore::get(isolate, BackingStore::cast(backing_store), entry);
UNREACHABLE();
}
static ElementType GetImpl(ElementType* data_ptr, size_t entry) {
// The JavaScript memory model allows for racy reads and writes to a
// SharedArrayBuffer's backing store. ThreadSanitizer will catch these
// racy accesses and warn about them, so we disable TSAN for these reads
// and writes using annotations.
//
// We don't use relaxed atomics here, as it is not a requirement of the
// JavaScript memory model to have tear-free reads of overlapping accesses,
// and using relaxed atomics may introduce overhead.
TSAN_ANNOTATE_IGNORE_READS_BEGIN;
ElementType result;
if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
// TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
// fields (external pointers, doubles and BigInt data) are only
// kTaggedSize aligned so we have to use unaligned pointer friendly way of
// accessing them in order to avoid undefined behavior in C++ code.
result = ReadUnalignedValue<ElementType>(
reinterpret_cast<Address>(data_ptr + entry));
} else {
result = data_ptr[entry];
}
TSAN_ANNOTATE_IGNORE_READS_END;
return result;
}
static PropertyDetails GetDetailsImpl(JSObject holder, uint32_t entry) {
@ -2996,7 +3080,7 @@ class TypedElementsAccessor
Handle<FixedArrayBase> elements(receiver->elements(), isolate);
uint32_t length = AccessorClass::GetCapacityImpl(*receiver, *elements);
for (uint32_t i = 0; i < length; i++) {
Handle<Object> value = AccessorClass::GetImpl(isolate, *elements, i);
Handle<Object> value = AccessorClass::GetInternalImpl(receiver, i);
accumulator->AddKey(value, convert);
}
}
@ -3010,8 +3094,7 @@ class TypedElementsAccessor
Handle<FixedArrayBase> elements(object->elements(), isolate);
uint32_t length = AccessorClass::GetCapacityImpl(*object, *elements);
for (uint32_t index = 0; index < length; ++index) {
Handle<Object> value =
AccessorClass::GetImpl(isolate, *elements, index);
Handle<Object> value = AccessorClass::GetInternalImpl(object, index);
if (get_entries) {
value = MakeEntryPair(isolate, index, value);
}
@ -3022,30 +3105,24 @@ class TypedElementsAccessor
return Just(true);
}
static Object FillImpl(Handle<JSObject> receiver, Handle<Object> obj_value,
static Object FillImpl(Handle<JSObject> receiver, Handle<Object> value,
uint32_t start, uint32_t end) {
Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(receiver);
DCHECK(!array->WasDetached());
DCHECK(obj_value->IsNumeric());
ctype value = BackingStore::FromHandle(obj_value);
// Ensure indexes are within array bounds
CHECK_LE(0, start);
CHECK_LE(start, end);
CHECK_LE(end, array->length());
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(receiver);
DCHECK(!typed_array->WasDetached());
DCHECK_LE(0, start);
DCHECK_LE(start, end);
DCHECK_LE(end, typed_array->length());
DisallowHeapAllocation no_gc;
BackingStore elements = BackingStore::cast(receiver->elements());
ctype* data = static_cast<ctype*>(elements.DataPtr());
if (COMPRESS_POINTERS_BOOL && alignof(ctype) > kTaggedSize) {
ElementType scalar = FromHandle(value);
ElementType* data = static_cast<ElementType*>(typed_array->DataPtr());
if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
// TODO(ishell, v8:8875): See UnalignedSlot<T> for details.
std::fill(UnalignedSlot<ctype>(data + start),
UnalignedSlot<ctype>(data + end), value);
std::fill(UnalignedSlot<ElementType>(data + start),
UnalignedSlot<ElementType>(data + end), scalar);
} else {
std::fill(data + start, data + end, value);
std::fill(data + start, data + end, scalar);
}
return *array;
return *typed_array;
}
static Maybe<bool> IncludesValueImpl(Isolate* isolate,
@ -3061,11 +3138,10 @@ class TypedElementsAccessor
return Just(value->IsUndefined(isolate) && length > start_from);
}
BackingStore elements = BackingStore::cast(typed_array.elements());
if (value->IsUndefined(isolate) && length > typed_array.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) {
@ -3073,10 +3149,13 @@ class TypedElementsAccessor
length = static_cast<uint32_t>(typed_array.length());
}
ElementType typed_search_value;
ElementType* data_ptr =
reinterpret_cast<ElementType*>(typed_array.DataPtr());
if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
if (!value->IsBigInt()) return Just(false);
bool lossless;
typed_search_value = BackingStore::FromHandle(value, &lossless);
typed_search_value = FromHandle(value, &lossless);
if (!lossless) return Just(false);
} else {
if (!value->IsNumber()) return Just(false);
@ -3088,25 +3167,26 @@ class TypedElementsAccessor
}
if (std::isnan(search_value)) {
for (uint32_t k = start_from; k < length; ++k) {
double element_k = elements.get_scalar(k);
if (std::isnan(element_k)) return Just(true);
double elem_k =
static_cast<double>(AccessorClass::GetImpl(data_ptr, k));
if (std::isnan(elem_k)) return Just(true);
}
return Just(false);
}
} else if (search_value < std::numeric_limits<ctype>::lowest() ||
search_value > std::numeric_limits<ctype>::max()) {
} else if (search_value < std::numeric_limits<ElementType>::lowest() ||
search_value > std::numeric_limits<ElementType>::max()) {
// Return false if value can't be represented in this space.
return Just(false);
}
typed_search_value = static_cast<ctype>(search_value);
typed_search_value = static_cast<ElementType>(search_value);
if (static_cast<double>(typed_search_value) != search_value) {
return Just(false); // Loss of precision.
}
}
for (uint32_t k = start_from; k < length; ++k) {
ctype element_k = elements.get_scalar(k);
if (element_k == typed_search_value) return Just(true);
ElementType elem_k = AccessorClass::GetImpl(data_ptr, k);
if (elem_k == typed_search_value) return Just(true);
}
return Just(false);
}
@ -3120,13 +3200,14 @@ class TypedElementsAccessor
if (typed_array.WasDetached()) return Just<int64_t>(-1);
BackingStore elements = BackingStore::cast(typed_array.elements());
ctype typed_search_value;
ElementType typed_search_value;
ElementType* data_ptr =
reinterpret_cast<ElementType*>(typed_array.DataPtr());
if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
if (!value->IsBigInt()) return Just<int64_t>(-1);
bool lossless;
typed_search_value = BackingStore::FromHandle(value, &lossless);
typed_search_value = FromHandle(value, &lossless);
if (!lossless) return Just<int64_t>(-1);
} else {
if (!value->IsNumber()) return Just<int64_t>(-1);
@ -3139,12 +3220,12 @@ class TypedElementsAccessor
if (std::isnan(search_value)) {
return Just<int64_t>(-1);
}
} else if (search_value < std::numeric_limits<ctype>::lowest() ||
search_value > std::numeric_limits<ctype>::max()) {
} else if (search_value < std::numeric_limits<ElementType>::lowest() ||
search_value > std::numeric_limits<ElementType>::max()) {
// Return false if value can't be represented in this ElementsKind.
return Just<int64_t>(-1);
}
typed_search_value = static_cast<ctype>(search_value);
typed_search_value = static_cast<ElementType>(search_value);
if (static_cast<double>(typed_search_value) != search_value) {
return Just<int64_t>(-1); // Loss of precision.
}
@ -3158,8 +3239,8 @@ class TypedElementsAccessor
}
for (uint32_t k = start_from; k < length; ++k) {
ctype element_k = elements.get_scalar(k);
if (element_k == typed_search_value) return Just<int64_t>(k);
ElementType elem_k = AccessorClass::GetImpl(data_ptr, k);
if (elem_k == typed_search_value) return Just<int64_t>(k);
}
return Just<int64_t>(-1);
}
@ -3172,31 +3253,32 @@ class TypedElementsAccessor
DCHECK(!typed_array.WasDetached());
BackingStore elements = BackingStore::cast(typed_array.elements());
ctype typed_search_value;
ElementType typed_search_value;
ElementType* data_ptr =
reinterpret_cast<ElementType*>(typed_array.DataPtr());
if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
if (!value->IsBigInt()) return Just<int64_t>(-1);
bool lossless;
typed_search_value = BackingStore::FromHandle(value, &lossless);
typed_search_value = FromHandle(value, &lossless);
if (!lossless) return Just<int64_t>(-1);
} else {
if (!value->IsNumber()) return Just<int64_t>(-1);
double search_value = value->Number();
if (!std::isfinite(search_value)) {
if (std::is_integral<ctype>::value) {
if (std::is_integral<ElementType>::value) {
// Integral types cannot represent +Inf or NaN.
return Just<int64_t>(-1);
} else if (std::isnan(search_value)) {
// Strict Equality Comparison of NaN is always false.
return Just<int64_t>(-1);
}
} else if (search_value < std::numeric_limits<ctype>::lowest() ||
search_value > std::numeric_limits<ctype>::max()) {
} else if (search_value < std::numeric_limits<ElementType>::lowest() ||
search_value > std::numeric_limits<ElementType>::max()) {
// Return -1 if value can't be represented in this ElementsKind.
return Just<int64_t>(-1);
}
typed_search_value = static_cast<ctype>(search_value);
typed_search_value = static_cast<ElementType>(search_value);
if (static_cast<double>(typed_search_value) != search_value) {
return Just<int64_t>(-1); // Loss of precision.
}
@ -3205,8 +3287,8 @@ class TypedElementsAccessor
DCHECK_LT(start_from, typed_array.length());
uint32_t k = start_from;
do {
ctype element_k = elements.get_scalar(k);
if (element_k == typed_search_value) return Just<int64_t>(k);
ElementType elem_k = AccessorClass::GetImpl(data_ptr, k);
if (elem_k == typed_search_value) return Just<int64_t>(k);
} while (k-- != 0);
return Just<int64_t>(-1);
}
@ -3217,16 +3299,14 @@ class TypedElementsAccessor
DCHECK(!typed_array.WasDetached());
BackingStore elements = BackingStore::cast(typed_array.elements());
size_t len = typed_array.length();
if (len == 0) return;
ctype* data = static_cast<ctype*>(elements.DataPtr());
if (COMPRESS_POINTERS_BOOL && alignof(ctype) > kTaggedSize) {
ElementType* data = static_cast<ElementType*>(typed_array.DataPtr());
if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
// TODO(ishell, v8:8875): See UnalignedSlot<T> for details.
std::reverse(UnalignedSlot<ctype>(data),
UnalignedSlot<ctype>(data + len));
std::reverse(UnalignedSlot<ElementType>(data),
UnalignedSlot<ElementType>(data + len));
} else {
std::reverse(data, data + len);
}
@ -3235,13 +3315,10 @@ class TypedElementsAccessor
static Handle<FixedArray> CreateListFromArrayLikeImpl(Isolate* isolate,
Handle<JSObject> object,
uint32_t length) {
DCHECK(!Handle<JSArrayBufferView>::cast(object)->WasDetached());
DCHECK(object->IsJSTypedArray());
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object);
Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
Handle<BackingStore> elements(BackingStore::cast(object->elements()),
isolate);
for (uint32_t i = 0; i < length; i++) {
Handle<Object> value = AccessorClass::GetImpl(isolate, *elements, i);
Handle<Object> value = AccessorClass::GetInternalImpl(typed_array, i);
result->set(i, *value);
}
return result;
@ -3256,37 +3333,17 @@ class TypedElementsAccessor
CHECK(!destination.WasDetached());
DCHECK_LE(start, end);
DCHECK_LE(end, source.length());
size_t count = end - start;
DCHECK_LE(count, destination.length());
FixedTypedArrayBase src_elements =
FixedTypedArrayBase::cast(source.elements());
BackingStore dest_elements = BackingStore::cast(destination.elements());
size_t element_size = source.element_size();
uint8_t* source_data =
static_cast<uint8_t*>(src_elements.DataPtr()) + start * element_size;
// Fast path for the same type result array
if (source.type() == destination.type()) {
uint8_t* dest_data = static_cast<uint8_t*>(dest_elements.DataPtr());
// The spec defines the copy-step iteratively, which means that we
// cannot use memcpy if the buffer is shared.
uint8_t* end_ptr = source_data + count * element_size;
while (source_data < end_ptr) {
*dest_data++ = *source_data++;
}
return;
}
ElementType* dest_data = static_cast<ElementType*>(destination.DataPtr());
switch (source.GetElementsKind()) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
CopyBetweenBackingStores<Type##ArrayTraits>(source_data, dest_elements, \
count, 0); \
break;
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: { \
ctype* source_data = reinterpret_cast<ctype*>(source.DataPtr()) + start; \
CopyBetweenBackingStores<TYPE##_ELEMENTS, ctype>(source_data, dest_data, \
count); \
break; \
}
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
default:
@ -3295,23 +3352,24 @@ class TypedElementsAccessor
}
}
static bool HasSimpleRepresentation(InstanceType type) {
return !(type == FIXED_FLOAT32_ARRAY_TYPE ||
type == FIXED_FLOAT64_ARRAY_TYPE ||
type == FIXED_UINT8_CLAMPED_ARRAY_TYPE);
static bool HasSimpleRepresentation(ExternalArrayType type) {
return !(type == kExternalFloat32Array || type == kExternalFloat64Array ||
type == kExternalUint8ClampedArray);
}
template <typename SourceTraits>
static void CopyBetweenBackingStores(void* source_data_ptr, BackingStore dest,
size_t length, uint32_t offset) {
template <ElementsKind SourceKind, typename SourceElementType>
static void CopyBetweenBackingStores(SourceElementType* source_data_ptr,
ElementType* dest_data_ptr,
size_t length) {
DisallowHeapAllocation no_gc;
for (uint32_t i = 0; i < length; i++) {
for (size_t i = 0; i < length; i++) {
// We use scalar accessors to avoid boxing/unboxing, so there are no
// allocations.
typename SourceTraits::ElementType elem =
FixedTypedArray<SourceTraits>::get_scalar_from_data_ptr(
SourceElementType source_elem =
TypedElementsAccessor<SourceKind, SourceElementType>::GetImpl(
source_data_ptr, i);
dest.set(offset + i, dest.from(elem));
ElementType dest_elem = FromScalar(source_elem);
SetImpl(dest_data_ptr, i, dest_elem);
}
}
@ -3325,25 +3383,20 @@ class TypedElementsAccessor
CHECK(!source.WasDetached());
CHECK(!destination.WasDetached());
FixedTypedArrayBase source_elements =
FixedTypedArrayBase::cast(source.elements());
BackingStore destination_elements =
BackingStore::cast(destination.elements());
DCHECK_LE(offset, destination.length());
DCHECK_LE(length, destination.length() - offset);
DCHECK_LE(length, source.length());
InstanceType source_type = source_elements.map().instance_type();
InstanceType destination_type = destination_elements.map().instance_type();
ExternalArrayType source_type = source.type();
ExternalArrayType destination_type = destination.type();
bool same_type = source_type == destination_type;
bool same_size = source.element_size() == destination.element_size();
bool both_are_simple = HasSimpleRepresentation(source_type) &&
HasSimpleRepresentation(destination_type);
uint8_t* source_data = static_cast<uint8_t*>(source_elements.DataPtr());
uint8_t* dest_data = static_cast<uint8_t*>(destination_elements.DataPtr());
uint8_t* source_data = static_cast<uint8_t*>(source.DataPtr());
uint8_t* dest_data = static_cast<uint8_t*>(destination.DataPtr());
size_t source_byte_length = source.byte_length();
size_t dest_byte_length = destination.byte_length();
@ -3368,10 +3421,11 @@ class TypedElementsAccessor
}
switch (source.GetElementsKind()) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
CopyBetweenBackingStores<Type##ArrayTraits>( \
source_data, destination_elements, length, offset); \
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
CopyBetweenBackingStores<TYPE##_ELEMENTS, ctype>( \
reinterpret_cast<ctype*>(source_data), \
reinterpret_cast<ElementType*>(dest_data) + offset, length); \
break;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
@ -3426,7 +3480,6 @@ class TypedElementsAccessor
USE(dest_length);
ElementsKind kind = source.GetElementsKind();
BackingStore dest = BackingStore::cast(destination.elements());
// When we find the hole, we normally have to look up the element on the
// prototype chain, which is not handled here and we return false instead.
@ -3435,34 +3488,32 @@ class TypedElementsAccessor
// the hole into undefined.
if (HoleyPrototypeLookupRequired(isolate, context, source)) return false;
Object undefined = ReadOnlyRoots(isolate).undefined_value();
Oddball undefined = ReadOnlyRoots(isolate).undefined_value();
ElementType* dest_data =
reinterpret_cast<ElementType*>(destination.DataPtr()) + offset;
// Fastpath for packed Smi kind.
// Fast-path for packed Smi kind.
if (kind == PACKED_SMI_ELEMENTS) {
FixedArray source_store = FixedArray::cast(source.elements());
for (uint32_t i = 0; i < length; i++) {
Object elem = source_store.get(i);
DCHECK(elem.IsSmi());
int int_value = Smi::ToInt(elem);
dest.set(offset + i, dest.from(int_value));
SetImpl(dest_data, i, FromScalar(Smi::ToInt(elem)));
}
return true;
} else if (kind == HOLEY_SMI_ELEMENTS) {
FixedArray source_store = FixedArray::cast(source.elements());
for (uint32_t i = 0; i < length; i++) {
if (source_store.is_the_hole(isolate, i)) {
dest.SetValue(offset + i, undefined);
SetImpl(dest_data, i, FromObject(undefined));
} else {
Object elem = source_store.get(i);
DCHECK(elem.IsSmi());
int int_value = Smi::ToInt(elem);
dest.set(offset + i, dest.from(int_value));
SetImpl(dest_data, i, FromScalar(Smi::ToInt(elem)));
}
}
return true;
} else if (kind == PACKED_DOUBLE_ELEMENTS) {
// Fastpath for packed double kind. We avoid boxing and then immediately
// Fast-path for packed double kind. We avoid boxing and then immediately
// unboxing the double here by using get_scalar.
FixedDoubleArray source_store = FixedDoubleArray::cast(source.elements());
@ -3470,17 +3521,17 @@ class TypedElementsAccessor
// Use the from_double conversion for this specific TypedArray type,
// rather than relying on C++ to convert elem.
double elem = source_store.get_scalar(i);
dest.set(offset + i, dest.from(elem));
SetImpl(dest_data, i, FromScalar(elem));
}
return true;
} else if (kind == HOLEY_DOUBLE_ELEMENTS) {
FixedDoubleArray source_store = FixedDoubleArray::cast(source.elements());
for (uint32_t i = 0; i < length; i++) {
if (source_store.is_the_hole(i)) {
dest.SetValue(offset + i, undefined);
SetImpl(dest_data, i, FromObject(undefined));
} else {
double elem = source_store.get_scalar(i);
dest.set(offset + i, dest.from(elem));
SetImpl(dest_data, i, FromScalar(elem));
}
}
return true;
@ -3492,13 +3543,21 @@ class TypedElementsAccessor
Handle<JSTypedArray> destination,
size_t length, uint32_t offset) {
Isolate* isolate = destination->GetIsolate();
Handle<BackingStore> destination_elements(
BackingStore::cast(destination->elements()), isolate);
for (uint32_t i = 0; i < length; i++) {
LookupIterator it(isolate, source, i);
for (size_t i = 0; i < length; i++) {
Handle<Object> elem;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem,
Object::GetProperty(&it));
if (i <= kMaxUInt32) {
LookupIterator it(isolate, source, static_cast<uint32_t>(i));
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem,
Object::GetProperty(&it));
} else {
char buffer[kDoubleToCStringMinBufferSize];
Vector<char> string(buffer, arraysize(buffer));
DoubleToCString(static_cast<double>(i), string);
Handle<Name> name = isolate->factory()->InternalizeUtf8String(string);
LookupIterator it(isolate, source, name);
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem,
Object::GetProperty(&it));
}
if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem,
BigInt::FromObject(isolate, elem));
@ -3517,7 +3576,8 @@ class TypedElementsAccessor
}
// The spec says we store the length, then get each element, so we don't
// need to check changes to length.
destination_elements->SetValue(offset + i, *elem);
// TODO(bmeurer, v8:4153): Remove this static_cast.
SetImpl(destination, static_cast<uint32_t>(offset + i), *elem);
}
return *isolate->factory()->undefined_value();
}
@ -3544,29 +3604,15 @@ class TypedElementsAccessor
source_kind == BIGINT64_ELEMENTS || source_kind == BIGUINT64_ELEMENTS;
bool target_is_bigint =
Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS;
if (target_is_bigint) {
if (V8_UNLIKELY(!source_is_bigint)) {
Handle<Object> first =
JSReceiver::GetElement(isolate, source_ta, 0).ToHandleChecked();
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kBigIntFromObject, first));
}
} else {
if (V8_UNLIKELY(source_is_bigint)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kBigIntToNumber));
}
}
// 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_is_bigint == target_is_bigint && !source_ta->WasDetached() &&
length + offset <= source_ta->length()) {
CopyElementsFromTypedArray(*source_ta, *destination_ta, length, offset);
return *isolate->factory()->undefined_value();
}
}
// Fast cases for packed numbers kinds where we don't need to allocate.
if (source->IsJSArray()) {
} else if (source->IsJSArray()) {
// Fast cases for packed numbers kinds where we don't need to allocate.
Handle<JSArray> source_js_array = Handle<JSArray>::cast(source);
size_t current_length;
if (source_js_array->length().IsNumber() &&
@ -3586,10 +3632,214 @@ class TypedElementsAccessor
}
};
#define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype) \
using Fixed##Type##ElementsAccessor = \
TypedElementsAccessor<TYPE##_ELEMENTS, ctype>;
// static
template <>
Handle<Object> TypedElementsAccessor<INT8_ELEMENTS, int8_t>::ToHandle(
Isolate* isolate, int8_t value) {
return handle(Smi::FromInt(value), isolate);
}
// static
template <>
Handle<Object> TypedElementsAccessor<UINT8_ELEMENTS, uint8_t>::ToHandle(
Isolate* isolate, uint8_t value) {
return handle(Smi::FromInt(value), isolate);
}
// static
template <>
Handle<Object> TypedElementsAccessor<INT16_ELEMENTS, int16_t>::ToHandle(
Isolate* isolate, int16_t value) {
return handle(Smi::FromInt(value), isolate);
}
// static
template <>
Handle<Object> TypedElementsAccessor<UINT16_ELEMENTS, uint16_t>::ToHandle(
Isolate* isolate, uint16_t value) {
return handle(Smi::FromInt(value), isolate);
}
// static
template <>
Handle<Object> TypedElementsAccessor<INT32_ELEMENTS, int32_t>::ToHandle(
Isolate* isolate, int32_t value) {
return isolate->factory()->NewNumberFromInt(value);
}
// static
template <>
Handle<Object> TypedElementsAccessor<UINT32_ELEMENTS, uint32_t>::ToHandle(
Isolate* isolate, uint32_t value) {
return isolate->factory()->NewNumberFromUint(value);
}
// static
template <>
float TypedElementsAccessor<FLOAT32_ELEMENTS, float>::FromScalar(double value) {
using limits = std::numeric_limits<float>;
if (value > limits::max()) return limits::infinity();
if (value < limits::lowest()) return -limits::infinity();
return static_cast<float>(value);
}
// static
template <>
Handle<Object> TypedElementsAccessor<FLOAT32_ELEMENTS, float>::ToHandle(
Isolate* isolate, float value) {
return isolate->factory()->NewNumber(value);
}
// static
template <>
double TypedElementsAccessor<FLOAT64_ELEMENTS, double>::FromScalar(
double value) {
return value;
}
// static
template <>
Handle<Object> TypedElementsAccessor<FLOAT64_ELEMENTS, double>::ToHandle(
Isolate* isolate, double value) {
return isolate->factory()->NewNumber(value);
}
// static
template <>
uint8_t TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::FromScalar(
int value) {
if (value < 0x00) return 0x00;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
// static
template <>
uint8_t TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::FromScalar(
uint32_t value) {
// We need this special case for Uint32 -> Uint8Clamped, because the highest
// Uint32 values will be negative as an int, clamping to 0, rather than 255.
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
// static
template <>
uint8_t TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::FromScalar(
double value) {
// Handle NaNs and less than zero values which clamp to zero.
if (!(value > 0)) return 0;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(lrint(value));
}
// static
template <>
Handle<Object> TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::ToHandle(
Isolate* isolate, uint8_t value) {
return handle(Smi::FromInt(value), isolate);
}
// static
template <>
int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
int value) {
UNREACHABLE();
}
// static
template <>
int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
uint32_t value) {
UNREACHABLE();
}
// static
template <>
int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
double value) {
UNREACHABLE();
}
// static
template <>
int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
int64_t value) {
return value;
}
// static
template <>
int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
uint64_t value) {
return static_cast<int64_t>(value);
}
// static
template <>
int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromObject(
Object value, bool* lossless) {
return BigInt::cast(value).AsInt64(lossless);
}
// static
template <>
Handle<Object> TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::ToHandle(
Isolate* isolate, int64_t value) {
return BigInt::FromInt64(isolate, value);
}
// static
template <>
uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
int value) {
UNREACHABLE();
}
// static
template <>
uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
uint32_t value) {
UNREACHABLE();
}
// static
template <>
uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
double value) {
UNREACHABLE();
}
// static
template <>
uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
int64_t value) {
return static_cast<uint64_t>(value);
}
// static
template <>
uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
uint64_t value) {
return value;
}
// static
template <>
uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromObject(
Object value, bool* lossless) {
return BigInt::cast(value).AsUint64(lossless);
}
// static
template <>
Handle<Object> TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::ToHandle(
Isolate* isolate, uint64_t value) {
return BigInt::FromUint64(isolate, value);
}
#define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype) \
using Type##ElementsAccessor = TypedElementsAccessor<TYPE##_ELEMENTS, ctype>;
TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR)
#undef FIXED_ELEMENTS_ACCESSOR
@ -4481,7 +4731,7 @@ void CopyFastNumberJSArrayElementsToTypedArray(Address raw_context,
switch (destination.GetElementsKind()) {
#define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
CHECK(Fixed##Type##ElementsAccessor::TryCopyElementsFastNumber( \
CHECK(Type##ElementsAccessor::TryCopyElementsFastNumber( \
context, source, destination, length, static_cast<uint32_t>(offset))); \
break;
TYPED_ARRAYS(TYPED_ARRAYS_CASE)
@ -4500,7 +4750,7 @@ void CopyTypedArrayElementsToTypedArray(Address raw_source,
switch (destination.GetElementsKind()) {
#define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
Fixed##Type##ElementsAccessor::CopyElementsFromTypedArray( \
Type##ElementsAccessor::CopyElementsFromTypedArray( \
source, destination, length, static_cast<uint32_t>(offset)); \
break;
TYPED_ARRAYS(TYPED_ARRAYS_CASE)

View File

@ -30,7 +30,6 @@ namespace internal {
OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(FixedTypedArrayBase, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
@ -58,40 +57,13 @@ CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(TemplateList)
CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakArrayList)
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
int FixedArrayBase::length() const {
#ifdef DEBUG
// Only read the map word once to avoid race with evacuator.
MapWord mw = map_word();
if (!mw.IsForwardingAddress()) {
DCHECK(!IsInRange(mw.ToMap().instance_type(), FIRST_FIXED_TYPED_ARRAY_TYPE,
LAST_FIXED_TYPED_ARRAY_TYPE));
}
#endif
Object value = READ_FIELD(*this, kLengthOffset);
return Smi::ToInt(value);
}
void FixedArrayBase::set_length(int value) {
DCHECK(!IsInRange(map().instance_type(), FIRST_FIXED_TYPED_ARRAY_TYPE,
LAST_FIXED_TYPED_ARRAY_TYPE));
WRITE_FIELD(*this, kLengthOffset, Smi::FromInt(value));
}
void FixedTypedArrayBase::set_number_of_elements_onheap_only(int value) {
WRITE_FIELD(*this, kLengthOffset, Smi::FromInt(value));
}
int FixedTypedArrayBase::number_of_elements_onheap_only() const {
Object value = READ_FIELD(*this, kLengthOffset);
return Smi::ToInt(value);
}
SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
@ -103,8 +75,6 @@ Object FixedArrayBase::unchecked_synchronized_length() const {
return ACQUIRE_READ_FIELD(*this, kLengthOffset);
}
ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
ObjectSlot FixedArray::GetFirstElementAddress() {
return RawField(OffsetOfElementAt(0));
}
@ -611,372 +581,6 @@ int PodArray<T>::length() const {
return ByteArray::length() / sizeof(T);
}
void* FixedTypedArrayBase::external_pointer() const {
return reinterpret_cast<void*>(ReadField<Address>(kExternalPointerOffset));
}
void FixedTypedArrayBase::set_external_pointer(void* value) {
WriteField<Address>(kExternalPointerOffset, reinterpret_cast<Address>(value));
}
void* FixedTypedArrayBase::DataPtr() {
return reinterpret_cast<void*>(
base_pointer().ptr() + reinterpret_cast<intptr_t>(external_pointer()));
}
int FixedTypedArrayBase::ElementSize(InstanceType type) {
int element_size;
switch (type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE: \
element_size = sizeof(ctype); \
break;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
default:
UNREACHABLE();
}
return element_size;
}
int FixedTypedArrayBase::DataSize(InstanceType type) const {
if (base_pointer() == Smi::kZero) return 0;
return number_of_elements_onheap_only() * ElementSize(type);
}
int FixedTypedArrayBase::DataSize() const {
return DataSize(map().instance_type());
}
int FixedTypedArrayBase::size() const {
return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
}
int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
}
// static
int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
}
uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
int8_t Int8ArrayTraits::defaultValue() { return 0; }
uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
int16_t Int16ArrayTraits::defaultValue() { return 0; }
uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
int32_t Int32ArrayTraits::defaultValue() { return 0; }
float Float32ArrayTraits::defaultValue() {
return std::numeric_limits<float>::quiet_NaN();
}
double Float64ArrayTraits::defaultValue() {
return std::numeric_limits<double>::quiet_NaN();
}
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);
return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
}
// static
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
void* data_ptr, int index) {
typename Traits::ElementType* ptr = reinterpret_cast<ElementType*>(data_ptr);
// The JavaScript memory model allows for racy reads and writes to a
// SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
// ThreadSanitizer will catch these racy accesses and warn about them, so we
// disable TSAN for these reads and writes using annotations.
//
// We don't use relaxed atomics here, as it is not a requirement of the
// JavaScript memory model to have tear-free reads of overlapping accesses,
// and using relaxed atomics may introduce overhead.
TSAN_ANNOTATE_IGNORE_READS_BEGIN;
ElementType result;
if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
// TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
// fields (external pointers, doubles and BigInt data) are only kTaggedSize
// aligned so we have to use unaligned pointer friendly way of accessing
// them in order to avoid undefined behavior in C++ code.
result = ReadUnalignedValue<ElementType>(reinterpret_cast<Address>(ptr) +
index * sizeof(ElementType));
} else {
result = ptr[index];
}
TSAN_ANNOTATE_IGNORE_READS_END;
return result;
}
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);
// See the comment in FixedTypedArray<Traits>::get_scalar.
auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
// TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
// fields (external pointers, doubles and BigInt data) are only kTaggedSize
// aligned so we have to use unaligned pointer friendly way of accessing
// them in order to avoid undefined behavior in C++ code.
WriteUnalignedValue<ElementType>(
reinterpret_cast<Address>(ptr) + index * sizeof(ElementType), value);
} else {
ptr[index] = value;
}
TSAN_ANNOTATE_IGNORE_WRITES_END;
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
return static_cast<ElementType>(value);
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
if (value < 0) return 0;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
template <>
inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int value) {
UNREACHABLE();
}
template <>
inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int value) {
UNREACHABLE();
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
return static_cast<ElementType>(value);
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
// We need this special case for Uint32 -> Uint8Clamped, because the highest
// Uint32 values will be negative as an int, clamping to 0, rather than 255.
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
template <>
inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint32_t value) {
UNREACHABLE();
}
template <>
inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint32_t value) {
UNREACHABLE();
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
return static_cast<ElementType>(DoubleToInt32(value));
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
// Handle NaNs and less than zero values which clamp to zero.
if (!(value > 0)) return 0;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(lrint(value));
}
template <>
inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(double value) {
UNREACHABLE();
}
template <>
inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
UNREACHABLE();
}
template <>
inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
using limits = std::numeric_limits<float>;
if (value > limits::max()) return limits::infinity();
if (value < limits::lowest()) return -limits::infinity();
return static_cast<float>(value);
}
template <>
inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
return value;
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(int64_t value) {
UNREACHABLE();
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(uint64_t value) {
UNREACHABLE();
}
template <>
inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int64_t value) {
return value;
}
template <>
inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint64_t value) {
return value;
}
template <>
inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int64_t value) {
return static_cast<uint64_t>(value);
}
template <>
inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint64_t value) {
return static_cast<int64_t>(value);
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::FromHandle(
Handle<Object> value, bool* lossless) {
if (value->IsSmi()) {
return from(Smi::ToInt(*value));
}
DCHECK(value->IsHeapNumber());
return from(HeapNumber::cast(*value).value());
}
template <>
inline int64_t FixedTypedArray<BigInt64ArrayTraits>::FromHandle(
Handle<Object> value, bool* lossless) {
DCHECK(value->IsBigInt());
return BigInt::cast(*value).AsInt64(lossless);
}
template <>
inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::FromHandle(
Handle<Object> value, bool* lossless) {
DCHECK(value->IsBigInt());
return BigInt::cast(*value).AsUint64(lossless);
}
template <class Traits>
Handle<Object> FixedTypedArray<Traits>::get(Isolate* isolate,
FixedTypedArray<Traits> array,
int index) {
return Traits::ToHandle(isolate, array.get_scalar(index));
}
template <class Traits>
void FixedTypedArray<Traits>::SetValue(uint32_t index, Object value) {
ElementType cast_value = Traits::defaultValue();
if (value.IsSmi()) {
int int_value = Smi::ToInt(value);
cast_value = from(int_value);
} else if (value.IsHeapNumber()) {
double double_value = HeapNumber::cast(value).value();
cast_value = from(double_value);
} else {
// Clamp undefined to the default value. All other types have been
// converted to a number type further up in the call chain.
DCHECK(value.IsUndefined());
}
set(index, cast_value);
}
template <>
inline void FixedTypedArray<BigInt64ArrayTraits>::SetValue(uint32_t index,
Object value) {
DCHECK(value.IsBigInt());
set(index, BigInt::cast(value).AsInt64());
}
template <>
inline void FixedTypedArray<BigUint64ArrayTraits>::SetValue(uint32_t index,
Object value) {
DCHECK(value.IsBigInt());
set(index, BigInt::cast(value).AsUint64());
}
Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
uint8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
return isolate->factory()->NewNumberFromUint(scalar);
}
Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
return isolate->factory()->NewNumberFromInt(scalar);
}
Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
return isolate->factory()->NewNumber(scalar);
}
Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
return isolate->factory()->NewNumber(scalar);
}
Handle<Object> BigInt64ArrayTraits::ToHandle(Isolate* isolate, int64_t scalar) {
return BigInt::FromInt64(isolate, scalar);
}
Handle<Object> BigUint64ArrayTraits::ToHandle(Isolate* isolate,
uint64_t scalar) {
return BigInt::FromUint64(isolate, scalar);
}
// static
template <class Traits>
STATIC_CONST_MEMBER_DEFINITION const InstanceType
FixedTypedArray<Traits>::kInstanceType;
template <class Traits>
FixedTypedArray<Traits>::FixedTypedArray(Address ptr)
: FixedTypedArrayBase(ptr) {
DCHECK(IsHeapObject() && map().instance_type() == Traits::kInstanceType);
}
template <class Traits>
FixedTypedArray<Traits> FixedTypedArray<Traits>::cast(Object object) {
return FixedTypedArray<Traits>(object.ptr());
}
int TemplateList::length() const {
return Smi::ToInt(FixedArray::cast(*this).get(kLengthIndex));
}

View File

@ -576,141 +576,6 @@ class PodArray : public ByteArray {
OBJECT_CONSTRUCTORS(PodArray<T>, ByteArray);
};
class FixedTypedArrayBase : public FixedArrayBase {
public:
// [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr.
DECL_ACCESSORS(base_pointer, Object)
// [external_pointer]: Contains the offset between base_pointer and the start
// of the data. If the base_pointer is a nullptr, the external_pointer
// therefore points to the actual backing store.
DECL_PRIMITIVE_ACCESSORS(external_pointer, void*)
// Dispatched behavior.
DECL_CAST(FixedTypedArrayBase)
// [number_of_elements_onheap]: This length is the number of elements stored
// in this FixedTypedArray if it is on-heap. It is always 0 for the off-heap
// case (where the base_pointer == 0). It is only useful for printing,
// verification and object setup as it does not represent the length of the
// associated JSTypedArray object anymore.
inline int number_of_elements_onheap_only() const;
inline void set_number_of_elements_onheap_only(int value);
// These length accessors are deleted because the meaning of length() has
// changed (see comment above). For the length of a JSTypedArray, use
// JSTypedArray::length(). For the number of elements in an on-heap
// FixedTypedArray, use number_of_elements_onheap_only() above.
inline int length() const = delete;
inline void set_length(int) = delete;
DEFINE_FIELD_OFFSET_CONSTANTS(FixedArrayBase::kHeaderSize,
TORQUE_GENERATED_FIXED_TYPED_ARRAY_BASE_FIELDS)
static const int kHeaderSize = kSize;
#ifdef V8_COMPRESS_POINTERS
// TODO(ishell, v8:8875): When pointer compression is enabled the kHeaderSize
// is only kTaggedSize aligned but we can keep using unaligned access since
// both x64 and arm64 architectures (where pointer compression supported)
// allow unaligned access to doubles.
STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize));
#else
STATIC_ASSERT(IsAligned(kHeaderSize, kDoubleAlignment));
#endif
static const int kDataOffset = kHeaderSize;
static const int kMaxElementSize = 8;
#ifdef V8_HOST_ARCH_32_BIT
static const size_t kMaxByteLength = std::numeric_limits<size_t>::max();
#else
static const size_t kMaxByteLength =
static_cast<size_t>(Smi::kMaxValue) * kMaxElementSize;
#endif // V8_HOST_ARCH_32_BIT
static const size_t kMaxLength = Smi::kMaxValue;
class BodyDescriptor;
inline int size() const;
static inline int TypedArraySize(InstanceType type, int length);
inline int TypedArraySize(InstanceType type) const;
// Use with care: returns raw pointer into heap.
inline void* DataPtr();
inline int DataSize() const;
static inline intptr_t ExternalPointerValueForOnHeapArray() {
return FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
}
static inline void* ExternalPointerPtrForOnHeapArray() {
return reinterpret_cast<void*>(ExternalPointerValueForOnHeapArray());
}
private:
static inline int ElementSize(InstanceType type);
inline int DataSize(InstanceType type) const;
OBJECT_CONSTRUCTORS(FixedTypedArrayBase, FixedArrayBase);
};
template <class Traits>
class FixedTypedArray : public FixedTypedArrayBase {
public:
using ElementType = typename Traits::ElementType;
static const InstanceType kInstanceType = Traits::kInstanceType;
DECL_CAST(FixedTypedArray<Traits>)
static inline ElementType get_scalar_from_data_ptr(void* data_ptr, int index);
inline ElementType get_scalar(int index);
static inline Handle<Object> get(Isolate* isolate, FixedTypedArray array,
int index);
inline void set(int index, ElementType value);
static inline ElementType from(int value);
static inline ElementType from(uint32_t value);
static inline ElementType from(double value);
static inline ElementType from(int64_t value);
static inline ElementType from(uint64_t value);
static inline ElementType FromHandle(Handle<Object> value,
bool* lossless = nullptr);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
inline void SetValue(uint32_t index, Object value);
DECL_PRINTER(FixedTypedArray)
DECL_VERIFIER(FixedTypedArray)
private:
OBJECT_CONSTRUCTORS(FixedTypedArray, FixedTypedArrayBase);
};
#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType) \
STATIC_ASSERT(sizeof(elementType) <= FixedTypedArrayBase::kMaxElementSize); \
class Type##ArrayTraits { \
public: /* NOLINT */ \
using ElementType = elementType; \
static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
static const char* ArrayTypeName() { return "Fixed" #Type "Array"; } \
static inline Handle<Object> ToHandle(Isolate* isolate, \
elementType scalar); \
static inline elementType defaultValue(); \
}; \
\
using Fixed##Type##Array = FixedTypedArray<Type##ArrayTraits>;
TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)
#undef FIXED_TYPED_ARRAY_TRAITS
class TemplateList : public FixedArray {
public:
static Handle<TemplateList> New(Isolate* isolate, int size);

View File

@ -19,11 +19,6 @@ namespace InstanceTypeChecker {
// Define type checkers for classes with single instance type.
INSTANCE_TYPE_CHECKERS_SINGLE(INSTANCE_TYPE_CHECKER)
#define TYPED_ARRAY_INSTANCE_TYPE_CHECKER(Type, type, TYPE, ctype) \
INSTANCE_TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
TYPED_ARRAYS(TYPED_ARRAY_INSTANCE_TYPE_CHECKER)
#undef TYPED_ARRAY_INSTANCE_TYPE_CHECKER
#define STRUCT_INSTANCE_TYPE_CHECKER(TYPE, Name, name) \
INSTANCE_TYPE_CHECKER(Name, TYPE)
STRUCT_LIST(STRUCT_INSTANCE_TYPE_CHECKER)
@ -40,8 +35,7 @@ INSTANCE_TYPE_CHECKERS_RANGE(INSTANCE_TYPE_CHECKER_RANGE)
V8_INLINE bool IsFixedArrayBase(InstanceType instance_type) {
return IsFixedArray(instance_type) || IsFixedDoubleArray(instance_type) ||
IsFixedTypedArrayBase(instance_type) || IsByteArray(instance_type) ||
IsBytecodeArray(instance_type);
IsByteArray(instance_type) || IsBytecodeArray(instance_type);
}
V8_INLINE bool IsHeapObject(InstanceType instance_type) { return true; }
@ -69,11 +63,6 @@ V8_INLINE bool IsJSReceiver(InstanceType instance_type) {
// pointer rather than looking up the instance type.
INSTANCE_TYPE_CHECKERS(TYPE_CHECKER)
#define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype) \
TYPE_CHECKER(Fixed##Type##Array)
TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
#undef TYPED_ARRAY_TYPE_CHECKER
} // namespace internal
} // namespace v8

View File

@ -131,17 +131,6 @@ enum InstanceType : uint16_t {
BYTE_ARRAY_TYPE,
BYTECODE_ARRAY_TYPE,
FREE_SPACE_TYPE,
FIXED_INT8_ARRAY_TYPE, // FIRST_FIXED_TYPED_ARRAY_TYPE
FIXED_UINT8_ARRAY_TYPE,
FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE,
FIXED_INT32_ARRAY_TYPE,
FIXED_UINT32_ARRAY_TYPE,
FIXED_FLOAT32_ARRAY_TYPE,
FIXED_FLOAT64_ARRAY_TYPE,
FIXED_UINT8_CLAMPED_ARRAY_TYPE,
FIXED_BIGINT64_ARRAY_TYPE,
FIXED_BIGUINT64_ARRAY_TYPE, // LAST_FIXED_TYPED_ARRAY_TYPE
FIXED_DOUBLE_ARRAY_TYPE,
FEEDBACK_METADATA_TYPE,
FILLER_TYPE, // LAST_DATA_TYPE
@ -343,9 +332,6 @@ enum InstanceType : uint16_t {
// Boundaries for testing if given HeapObject is a subclass of Microtask.
FIRST_MICROTASK_TYPE = CALLABLE_TASK_TYPE,
LAST_MICROTASK_TYPE = FINALIZATION_GROUP_CLEANUP_JOB_TASK_TYPE,
// Boundaries for testing for a fixed typed array.
FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE,
LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_BIGUINT64_ARRAY_TYPE,
// Boundary for promotion to old space.
LAST_DATA_TYPE = FILLER_TYPE,
// Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
@ -515,8 +501,6 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
#define INSTANCE_TYPE_CHECKERS_RANGE(V) \
V(Context, FIRST_CONTEXT_TYPE, LAST_CONTEXT_TYPE) \
V(FixedArray, FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE) \
V(FixedTypedArrayBase, FIRST_FIXED_TYPED_ARRAY_TYPE, \
LAST_FIXED_TYPED_ARRAY_TYPE) \
V(HashTable, FIRST_HASH_TABLE_TYPE, LAST_HASH_TABLE_TYPE) \
V(JSMapIterator, FIRST_MAP_ITERATOR_TYPE, LAST_MAP_ITERATOR_TYPE) \
V(JSSetIterator, FIRST_SET_ITERATOR_TYPE, LAST_SET_ITERATOR_TYPE) \

View File

@ -136,12 +136,31 @@ void JSTypedArray::set_length(size_t value) {
WriteField<size_t>(kLengthOffset, value);
}
void* JSTypedArray::external_pointer() const {
return reinterpret_cast<void*>(ReadField<Address>(kExternalPointerOffset));
}
void JSTypedArray::set_external_pointer(void* value) {
WriteField<Address>(kExternalPointerOffset, reinterpret_cast<Address>(value));
}
ACCESSORS(JSTypedArray, base_pointer, Object, kBasePointerOffset)
void* JSTypedArray::DataPtr() {
return reinterpret_cast<void*>(
base_pointer().ptr() + reinterpret_cast<intptr_t>(external_pointer()));
}
bool JSTypedArray::is_on_heap() const {
DisallowHeapAllocation no_gc;
// Checking that buffer()->backing_store() is not nullptr is not sufficient;
// it will be nullptr when byte_length is 0 as well.
FixedTypedArrayBase fta = FixedTypedArrayBase::cast(elements());
return fta.base_pointer().ptr() == fta.ptr();
return base_pointer().ptr() == elements().ptr();
}
// static
void* JSTypedArray::ExternalPointerForOnHeapArray() {
return reinterpret_cast<void*>(ByteArray::kHeaderSize - kHeapObjectTag);
}
// static

View File

@ -150,10 +150,7 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
Isolate* isolate = typed_array->GetIsolate();
DCHECK(IsFixedTypedArrayElementsKind(typed_array->GetElementsKind()));
Handle<FixedTypedArrayBase> fixed_typed_array(
FixedTypedArrayBase::cast(typed_array->elements()), isolate);
DCHECK(IsTypedArrayElementsKind(typed_array->GetElementsKind()));
Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
isolate);
@ -162,14 +159,13 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
void* backing_store =
isolate->array_buffer_allocator()->AllocateUninitialized(
fixed_typed_array->DataSize());
typed_array->byte_length());
if (backing_store == nullptr) {
isolate->heap()->FatalProcessOutOfMemory(
"JSTypedArray::MaterializeArrayBuffer");
}
buffer->set_is_external(false);
DCHECK_EQ(buffer->byte_length(),
static_cast<uintptr_t>(fixed_typed_array->DataSize()));
DCHECK_EQ(buffer->byte_length(), typed_array->byte_length());
// Initialize backing store at last to avoid handling of |JSArrayBuffers| that
// are currently being constructed in the |ArrayBufferTracker|. The
// registration method below handles the case of registering a buffer that has
@ -177,13 +173,12 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
buffer->set_backing_store(backing_store);
// RegisterNewArrayBuffer expects a valid length for adjusting counters.
isolate->heap()->RegisterNewArrayBuffer(*buffer);
memcpy(buffer->backing_store(), fixed_typed_array->DataPtr(),
fixed_typed_array->DataSize());
Handle<FixedTypedArrayBase> new_elements =
isolate->factory()->NewFixedTypedArrayWithExternalPointer(
typed_array->type(), static_cast<uint8_t*>(buffer->backing_store()));
memcpy(buffer->backing_store(), typed_array->DataPtr(),
typed_array->byte_length());
typed_array->set_elements(*new_elements);
typed_array->set_elements(ReadOnlyRoots(isolate).empty_byte_array());
typed_array->set_external_pointer(backing_store);
typed_array->set_base_pointer(Smi::kZero);
DCHECK(!typed_array->is_on_heap());
return buffer;
@ -270,13 +265,13 @@ Maybe<bool> JSTypedArray::DefineOwnProperty(Isolate* isolate,
}
ExternalArrayType JSTypedArray::type() {
switch (elements().map().instance_type()) {
#define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE: \
switch (map().elements_kind()) {
#define ELEMENTS_KIND_TO_ARRAY_TYPE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
return kExternal##Type##Array;
TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
#undef INSTANCE_TYPE_TO_ARRAY_TYPE
TYPED_ARRAYS(ELEMENTS_KIND_TO_ARRAY_TYPE)
#undef ELEMENTS_KIND_TO_ARRAY_TYPE
default:
UNREACHABLE();
@ -284,13 +279,13 @@ ExternalArrayType JSTypedArray::type() {
}
size_t JSTypedArray::element_size() {
switch (elements().map().instance_type()) {
#define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE: \
switch (map().elements_kind()) {
#define ELEMENTS_KIND_TO_ELEMENT_SIZE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
return sizeof(ctype);
TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
#undef INSTANCE_TYPE_TO_ELEMENT_SIZE
TYPED_ARRAYS(ELEMENTS_KIND_TO_ELEMENT_SIZE)
#undef ELEMENTS_KIND_TO_ELEMENT_SIZE
default:
UNREACHABLE();

View File

@ -172,6 +172,9 @@ class JSArrayBufferView : public JSObject {
JS_ARRAY_BUFFER_VIEW_FIELDS)
#undef JS_ARRAY_BUFFER_VIEW_FIELDS
STATIC_ASSERT(IsAligned(kByteOffsetOffset, kUIntptrSize));
STATIC_ASSERT(IsAligned(kByteLengthOffset, kUIntptrSize));
OBJECT_CONSTRUCTORS(JSArrayBufferView, JSObject);
};
@ -183,6 +186,12 @@ class JSTypedArray : public JSArrayBufferView {
// [length]: length of typed array in elements.
DECL_PRIMITIVE_ACCESSORS(length, size_t)
// [external_pointer]: TODO(v8:4153)
DECL_PRIMITIVE_ACCESSORS(external_pointer, void*)
// [base_pointer]: TODO(v8:4153)
DECL_ACCESSORS(base_pointer, Object)
// ES6 9.4.5.3
V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty(
Isolate* isolate, Handle<JSTypedArray> o, Handle<Object> key,
@ -195,9 +204,14 @@ class JSTypedArray : public JSArrayBufferView {
V8_EXPORT_PRIVATE Handle<JSArrayBuffer> GetBuffer();
// Use with care: returns raw pointer into heap.
inline void* DataPtr();
// Whether the buffer's backing store is on-heap or off-heap.
inline bool is_on_heap() const;
static inline void* ExternalPointerForOnHeapArray();
static inline MaybeHandle<JSTypedArray> Validate(Isolate* isolate,
Handle<Object> receiver,
const char* method_name);
@ -207,16 +221,21 @@ class JSTypedArray : public JSArrayBufferView {
DECL_VERIFIER(JSTypedArray)
// Layout description.
#define JS_TYPED_ARRAY_FIELDS(V) \
/* Raw data fields. */ \
V(kLengthOffset, kUIntptrSize) \
/* Header size. */ \
#define JS_TYPED_ARRAY_FIELDS(V) \
/* Raw data fields. */ \
V(kLengthOffset, kUIntptrSize) \
V(kExternalPointerOffset, kSystemPointerSize) \
V(kBasePointerOffset, kTaggedSize) \
/* Header size. */ \
V(kHeaderSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSArrayBufferView::kHeaderSize,
JS_TYPED_ARRAY_FIELDS)
#undef JS_TYPED_ARRAY_FIELDS
STATIC_ASSERT(IsAligned(kLengthOffset, kUIntptrSize));
STATIC_ASSERT(IsAligned(kExternalPointerOffset, kSystemPointerSize));
static const int kSizeWithEmbedderFields =
kHeaderSize +
v8::ArrayBufferView::kEmbedderFieldCount * kEmbedderDataSlotSize;
@ -252,6 +271,8 @@ class JSDataView : public JSArrayBufferView {
JS_DATA_VIEW_FIELDS)
#undef JS_DATA_VIEW_FIELDS
STATIC_ASSERT(IsAligned(kDataPointerOffset, kUIntptrSize));
static const int kSizeWithEmbedderFields =
kHeaderSize +
v8::ArrayBufferView::kEmbedderFieldCount * kEmbedderDataSlotSize;

View File

@ -34,7 +34,7 @@ bool JSArray::SetLengthWouldNormalize(Heap* heap, uint32_t new_length) {
bool JSArray::AllowsSetLength() {
bool result = elements().IsFixedArray() || elements().IsFixedDoubleArray();
DCHECK(result == !HasFixedTypedArrayElements());
DCHECK(result == !HasTypedArrayElements());
return result;
}

View File

@ -848,15 +848,14 @@ bool JSObject::HasSlowStringWrapperElements() {
return GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS;
}
bool JSObject::HasFixedTypedArrayElements() {
bool JSObject::HasTypedArrayElements() {
DCHECK(!elements().is_null());
return map().has_fixed_typed_array_elements();
return map().has_typed_array_elements();
}
#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype) \
bool JSObject::HasFixed##Type##Elements() { \
FixedArrayBase array = elements(); \
return array.map().instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \
#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype) \
bool JSObject::HasFixed##Type##Elements() { \
return map().elements_kind() == TYPE##_ELEMENTS; \
}
TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)

View File

@ -3218,7 +3218,7 @@ Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
// Special case: properties of typed arrays cannot be reconfigured to
// non-writable nor to non-enumerable.
if (it->IsElement() && object->HasFixedTypedArrayElements()) {
if (it->IsElement() && object->HasTypedArrayElements()) {
return Object::RedefineIncompatibleProperty(
it->isolate(), it->GetName(), value, should_throw);
}
@ -3446,7 +3446,7 @@ void JSObject::RequireSlowElements(NumberDictionary dictionary) {
}
Handle<NumberDictionary> JSObject::NormalizeElements(Handle<JSObject> object) {
DCHECK(!object->HasFixedTypedArrayElements());
DCHECK(!object->HasTypedArrayElements());
Isolate* isolate = object->GetIsolate();
bool is_sloppy_arguments = object->HasSloppyArgumentsElements();
{
@ -3630,7 +3630,7 @@ bool TestElementsIntegrityLevel(JSObject object, PropertyAttributes level) {
NumberDictionary::cast(object.elements()), object.GetReadOnlyRoots(),
level);
}
if (IsFixedTypedArrayElementsKind(kind)) {
if (IsTypedArrayElementsKind(kind)) {
if (level == FROZEN && JSArrayBufferView::cast(object).byte_length() > 0)
return false; // TypedArrays with elements can't be frozen.
return TestPropertiesIntegrityLevel(object, level);
@ -3695,7 +3695,7 @@ Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
NewTypeError(MessageTemplate::kCannotPreventExt));
}
if (!object->HasFixedTypedArrayElements()) {
if (!object->HasTypedArrayElements()) {
// If there are fast elements we normalize.
Handle<NumberDictionary> dictionary = NormalizeElements(object);
DCHECK(object->HasDictionaryElements() ||
@ -3807,8 +3807,7 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
}
Handle<NumberDictionary> new_element_dictionary;
if (!object->HasFixedTypedArrayElements() &&
!object->HasDictionaryElements() &&
if (!object->HasTypedArrayElements() && !object->HasDictionaryElements() &&
!object->HasSlowStringWrapperElements()) {
int length = object->IsJSArray()
? Smi::ToInt(Handle<JSArray>::cast(object)->length())
@ -3835,7 +3834,7 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
if (!transition.is_null()) {
Handle<Map> transition_map(transition, isolate);
DCHECK(transition_map->has_dictionary_elements() ||
transition_map->has_fixed_typed_array_elements() ||
transition_map->has_typed_array_elements() ||
transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS ||
transition_map->has_frozen_or_sealed_elements());
DCHECK(!transition_map->is_extensible());
@ -3887,7 +3886,7 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
// Both seal and preventExtensions always go through without modifications to
// typed array elements. Freeze works only if there are no actual elements.
if (object->HasFixedTypedArrayElements()) {
if (object->HasTypedArrayElements()) {
if (attrs == FROZEN && JSArrayBufferView::cast(*object).byte_length() > 0) {
isolate->Throw(*isolate->factory()->NewTypeError(
MessageTemplate::kCannotFreezeArrayBufferView));
@ -4030,7 +4029,7 @@ MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
// Ignore accessors on typed arrays.
if (it->IsElement() && object->HasFixedTypedArrayElements()) {
if (it->IsElement() && object->HasTypedArrayElements()) {
return it->factory()->undefined_value();
}
@ -4067,7 +4066,7 @@ MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
}
// Ignore accessors on typed arrays.
if (it.IsElement() && object->HasFixedTypedArrayElements()) {
if (it.IsElement() && object->HasTypedArrayElements()) {
return it.factory()->undefined_value();
}

View File

@ -339,7 +339,7 @@ class JSObject : public JSReceiver {
inline bool HasPackedElements();
inline bool HasFrozenOrSealedElements();
inline bool HasFixedTypedArrayElements();
inline bool HasTypedArrayElements();
inline bool HasFixedUint8ClampedElements();
inline bool HasFixedArrayElements();

View File

@ -517,7 +517,7 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
Handle<JSObject> holder_obj = Handle<JSObject>::cast(holder);
if (IsElement()) {
DCHECK(!holder_obj->HasFixedTypedArrayElements());
DCHECK(!holder_obj->HasTypedArrayElements());
DCHECK(attributes != NONE || !holder_obj->HasFastElements());
Handle<FixedArrayBase> elements(holder_obj->elements(), isolate());
holder_obj->GetElementsAccessor()->Reconfigure(holder_obj, elements,

View File

@ -198,9 +198,8 @@ FixedArrayBase Map::GetInitialElements() const {
result = GetReadOnlyRoots().empty_fixed_array();
} else if (has_fast_sloppy_arguments_elements()) {
result = GetReadOnlyRoots().empty_sloppy_arguments_elements();
} else if (has_fixed_typed_array_elements()) {
result =
GetReadOnlyRoots().EmptyFixedTypedArrayForTypedArray(elements_kind());
} else if (has_typed_array_elements()) {
result = GetReadOnlyRoots().empty_byte_array();
} else if (has_dictionary_elements()) {
result = GetReadOnlyRoots().empty_slow_element_dictionary();
} else {
@ -487,8 +486,8 @@ bool Map::has_fast_string_wrapper_elements() const {
return elements_kind() == FAST_STRING_WRAPPER_ELEMENTS;
}
bool Map::has_fixed_typed_array_elements() const {
return IsFixedTypedArrayElementsKind(elements_kind());
bool Map::has_typed_array_elements() const {
return IsTypedArrayElementsKind(elements_kind());
}
bool Map::has_dictionary_elements() const {

View File

@ -323,7 +323,7 @@ MapUpdater::State MapUpdater::FindRootMap() {
// the seal transitions), so change {to_kind} accordingly.
DCHECK(to_kind == DICTIONARY_ELEMENTS ||
to_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
IsFixedTypedArrayElementsKind(to_kind) ||
IsTypedArrayElementsKind(to_kind) ||
IsFrozenOrSealedElementsKind(to_kind));
to_kind = integrity_source_map_->elements_kind();
}

View File

@ -325,21 +325,6 @@ VisitorId Map::GetVisitorId(Map map) {
case BIGINT_TYPE:
return kVisitBigInt;
case FIXED_UINT8_ARRAY_TYPE:
case FIXED_INT8_ARRAY_TYPE:
case FIXED_UINT16_ARRAY_TYPE:
case FIXED_INT16_ARRAY_TYPE:
case FIXED_UINT32_ARRAY_TYPE:
case FIXED_INT32_ARRAY_TYPE:
case FIXED_FLOAT32_ARRAY_TYPE:
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
case FIXED_BIGUINT64_ARRAY_TYPE:
case FIXED_BIGINT64_ARRAY_TYPE:
return kVisitFixedTypedArrayBase;
case FIXED_FLOAT64_ARRAY_TYPE:
return kVisitFixedFloat64Array;
case ALLOCATION_SITE_TYPE:
return kVisitAllocationSite;
@ -1004,7 +989,7 @@ Map Map::TryUpdateSlow(Isolate* isolate, Map old_map) {
// the integrity level transition sets the elements to dictionary mode.
DCHECK(to_kind == DICTIONARY_ELEMENTS ||
to_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
IsFixedTypedArrayElementsKind(to_kind) ||
IsTypedArrayElementsKind(to_kind) ||
IsHoleyFrozenOrSealedElementsKind(to_kind));
to_kind = info.integrity_level_source_map.elements_kind();
}
@ -2027,7 +2012,7 @@ Handle<Map> Map::CopyForPreventExtensions(
isolate, map, new_desc, new_layout_descriptor, flag, transition_marker,
reason, SPECIAL_TRANSITION);
new_map->set_is_extensible(false);
if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
if (!IsTypedArrayElementsKind(map->elements_kind())) {
ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
? SLOW_STRING_WRAPPER_ELEMENTS
: DICTIONARY_ELEMENTS;

View File

@ -42,8 +42,6 @@ enum InstanceType : uint16_t;
V(FeedbackCell) \
V(FeedbackVector) \
V(FixedArray) \
V(FixedFloat64Array) \
V(FixedTypedArrayBase) \
V(FreeSpace) \
V(JSApiObject) \
V(JSArrayBuffer) \
@ -423,7 +421,7 @@ class Map : public HeapObject {
inline bool has_sloppy_arguments_elements() const;
inline bool has_fast_sloppy_arguments_elements() const;
inline bool has_fast_string_wrapper_elements() const;
inline bool has_fixed_typed_array_elements() const;
inline bool has_typed_array_elements() const;
inline bool has_dictionary_elements() const;
inline bool has_frozen_or_sealed_elements() const;
inline bool has_sealed_elements() const;

View File

@ -114,19 +114,7 @@ class ZoneForwardList;
V(FixedArray) \
V(FixedArrayBase) \
V(FixedArrayExact) \
V(FixedBigInt64Array) \
V(FixedBigUint64Array) \
V(FixedDoubleArray) \
V(FixedFloat32Array) \
V(FixedFloat64Array) \
V(FixedInt16Array) \
V(FixedInt32Array) \
V(FixedInt8Array) \
V(FixedTypedArrayBase) \
V(FixedUint16Array) \
V(FixedUint32Array) \
V(FixedUint8Array) \
V(FixedUint8ClampedArray) \
V(Foreign) \
V(FrameArray) \
V(FreeSpace) \

View File

@ -335,6 +335,8 @@ class JSTypedArray::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
if (offset < kEndOfTaggedFieldsOffset) return true;
// TODO(v8:4153): Remove this.
if (offset == kBasePointerOffset) return true;
if (offset < kHeaderSize) return false;
return IsValidJSObjectSlotImpl(map, obj, offset);
}
@ -344,6 +346,8 @@ class JSTypedArray::BodyDescriptor final : public BodyDescriptorBase {
ObjectVisitor* v) {
// JSTypedArray contains raw data that the GC does not know about.
IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
// TODO(v8:4153): Remove this.
IteratePointer(obj, kBasePointerOffset, v);
IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
}
@ -460,23 +464,6 @@ class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
}
};
class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
return offset == kBasePointerOffset;
}
template <typename ObjectVisitor>
static inline void IterateBody(Map map, HeapObject obj, int object_size,
ObjectVisitor* v) {
IteratePointer(obj, kBasePointerOffset, v);
}
static inline int SizeOf(Map map, HeapObject object) {
return FixedTypedArrayBase::cast(object).size();
}
};
class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
@ -1040,13 +1027,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case BIGINT_TYPE:
return ReturnType();
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE: \
return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3, \
p4);
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
case SHARED_FUNCTION_INFO_TYPE: {
return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3,
p4);

View File

@ -71,18 +71,6 @@ namespace internal {
V(BYTECODE_ARRAY_TYPE) \
V(FREE_SPACE_TYPE) \
\
V(FIXED_INT8_ARRAY_TYPE) \
V(FIXED_UINT8_ARRAY_TYPE) \
V(FIXED_INT16_ARRAY_TYPE) \
V(FIXED_UINT16_ARRAY_TYPE) \
V(FIXED_INT32_ARRAY_TYPE) \
V(FIXED_UINT32_ARRAY_TYPE) \
V(FIXED_FLOAT32_ARRAY_TYPE) \
V(FIXED_FLOAT64_ARRAY_TYPE) \
V(FIXED_UINT8_CLAMPED_ARRAY_TYPE) \
V(FIXED_BIGINT64_ARRAY_TYPE) \
V(FIXED_BIGUINT64_ARRAY_TYPE) \
\
V(FIXED_DOUBLE_ARRAY_TYPE) \
V(FEEDBACK_METADATA_TYPE) \
V(FILLER_TYPE) \

View File

@ -421,8 +421,9 @@ CAST_ACCESSOR(RegExpMatchInfo)
CAST_ACCESSOR(ScopeInfo)
bool Object::HasValidElements() {
// Dictionary is covered under FixedArray.
return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
// Dictionary is covered under FixedArray. ByteArray is used
// for the JSTypedArray backing stores.
return IsFixedArray() || IsFixedDoubleArray() || IsByteArray();
}
bool Object::FilterKey(PropertyFilter filter) {
@ -794,6 +795,9 @@ WriteBarrierMode HeapObject::GetWriteBarrierMode(
// static
AllocationAlignment HeapObject::RequiredAlignment(Map map) {
// TODO(bmeurer, v8:4153): We should think about requiring double alignment
// in general for ByteArray, since they are used as backing store for typed
// arrays now.
#ifdef V8_COMPRESS_POINTERS
// TODO(ishell, v8:8875): Consider using aligned allocations once the
// allocation alignment inconsistency is fixed. For now we keep using
@ -802,10 +806,7 @@ AllocationAlignment HeapObject::RequiredAlignment(Map map) {
#endif // V8_COMPRESS_POINTERS
#ifdef V8_HOST_ARCH_32_BIT
int instance_type = map.instance_type();
if (instance_type == FIXED_FLOAT64_ARRAY_TYPE ||
instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
return kDoubleAligned;
}
if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) return kDoubleAligned;
if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
#endif // V8_HOST_ARCH_32_BIT
return kWordAligned;

View File

@ -1977,15 +1977,6 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
case FREE_SPACE_TYPE:
os << "<FreeSpace[" << FreeSpace::cast(*this).size() << "]>";
break;
#define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype) \
case FIXED_##TYPE##_ARRAY_TYPE: \
os << "<Fixed" #Type "Array[" \
<< Fixed##Type##Array::cast(*this).number_of_elements_onheap_only() \
<< "]>"; \
break;
TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
#undef TYPED_ARRAY_SHORT_PRINT
case PREPARSE_DATA_TYPE: {
PreparseData data = PreparseData::cast(*this);
@ -2248,11 +2239,6 @@ int HeapObject::SizeFromMap(Map map) const {
return WeakArrayList::SizeForCapacity(
WeakArrayList::unchecked_cast(*this).synchronized_capacity());
}
if (IsInRange(instance_type, FIRST_FIXED_TYPED_ARRAY_TYPE,
LAST_FIXED_TYPED_ARRAY_TYPE)) {
return FixedTypedArrayBase::unchecked_cast(*this).TypedArraySize(
instance_type);
}
if (instance_type == SMALL_ORDERED_HASH_SET_TYPE) {
return SmallOrderedHashSet::SizeFor(
SmallOrderedHashSet::unchecked_cast(*this).Capacity());
@ -2699,7 +2685,7 @@ Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
Handle<Object> to_assign = value;
// Convert the incoming value to a number for storing into typed arrays.
if (it->IsElement() && receiver->IsJSObject() &&
JSObject::cast(*receiver).HasFixedTypedArrayElements()) {
JSObject::cast(*receiver).HasTypedArrayElements()) {
ElementsKind elements_kind = JSObject::cast(*receiver).GetElementsKind();
if (elements_kind == BIGINT64_ELEMENTS ||
elements_kind == BIGUINT64_ELEMENTS) {
@ -2786,12 +2772,11 @@ Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
Object::TypeOf(isolate, array), array));
}
if (FLAG_trace_external_array_abuse &&
array->HasFixedTypedArrayElements()) {
if (FLAG_trace_external_array_abuse && array->HasTypedArrayElements()) {
CheckArrayAbuse(array, "typed elements write", it->index(), true);
}
if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
if (FLAG_trace_js_array_abuse && !array->HasTypedArrayElements()) {
CheckArrayAbuse(array, "elements write", it->index(), false);
}
}

View File

@ -83,26 +83,6 @@ ReadOnlyRoots::ReadOnlyRoots(Address* ro_roots) : read_only_roots_(ro_roots) {}
READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)
#undef ROOT_ACCESSOR
Map ReadOnlyRoots::MapForFixedTypedArray(ExternalArrayType array_type) {
RootIndex root_index = RootsTable::RootIndexForFixedTypedArray(array_type);
DCHECK(CheckType(root_index));
return Map::unchecked_cast(Object(at(root_index)));
}
Map ReadOnlyRoots::MapForFixedTypedArray(ElementsKind elements_kind) {
RootIndex root_index = RootsTable::RootIndexForFixedTypedArray(elements_kind);
DCHECK(CheckType(root_index));
return Map::unchecked_cast(Object(at(root_index)));
}
FixedTypedArrayBase ReadOnlyRoots::EmptyFixedTypedArrayForTypedArray(
ElementsKind elements_kind) {
RootIndex root_index =
RootsTable::RootIndexForEmptyFixedTypedArray(elements_kind);
DCHECK(CheckType(root_index));
return FixedTypedArrayBase::unchecked_cast(Object(at(root_index)));
}
Address& ReadOnlyRoots::at(RootIndex root_index) const {
size_t index = static_cast<size_t>(root_index);
DCHECK_LT(index, kEntriesCount);

View File

@ -17,48 +17,6 @@ const char* RootsTable::root_names_[RootsTable::kEntriesCount] = {
#undef ROOT_NAME
};
// static
RootIndex RootsTable::RootIndexForFixedTypedArray(
ExternalArrayType array_type) {
switch (array_type) {
#define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype) \
case kExternal##Type##Array: \
return RootIndex::kFixed##Type##ArrayMap;
TYPED_ARRAYS(ARRAY_TYPE_TO_ROOT_INDEX)
#undef ARRAY_TYPE_TO_ROOT_INDEX
}
UNREACHABLE();
}
// static
RootIndex RootsTable::RootIndexForFixedTypedArray(ElementsKind elements_kind) {
switch (elements_kind) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
return RootIndex::kFixed##Type##ArrayMap;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
UNREACHABLE();
#undef TYPED_ARRAY_CASE
}
}
// static
RootIndex RootsTable::RootIndexForEmptyFixedTypedArray(
ElementsKind elements_kind) {
switch (elements_kind) {
#define ELEMENT_KIND_TO_ROOT_INDEX(Type, type, TYPE, ctype) \
case TYPE##_ELEMENTS: \
return RootIndex::kEmptyFixed##Type##Array;
TYPED_ARRAYS(ELEMENT_KIND_TO_ROOT_INDEX)
#undef ELEMENT_KIND_TO_ROOT_INDEX
default:
UNREACHABLE();
}
}
void ReadOnlyRoots::Iterate(RootVisitor* visitor) {
visitor->VisitRootPointers(Root::kReadOnlyRootList, nullptr,
FullObjectSlot(read_only_roots_),

View File

@ -17,7 +17,6 @@ namespace internal {
// Forward declarations.
enum ElementsKind : uint8_t;
class FixedTypedArrayBase;
template <typename T>
class Handle;
class Heap;
@ -150,18 +149,6 @@ class Symbol;
UncachedExternalOneByteInternalizedStringMap) \
V(Map, uncached_external_one_byte_string_map, \
UncachedExternalOneByteStringMap) \
/* Array element maps */ \
V(Map, fixed_uint8_array_map, FixedUint8ArrayMap) \
V(Map, fixed_int8_array_map, FixedInt8ArrayMap) \
V(Map, fixed_uint16_array_map, FixedUint16ArrayMap) \
V(Map, fixed_int16_array_map, FixedInt16ArrayMap) \
V(Map, fixed_uint32_array_map, FixedUint32ArrayMap) \
V(Map, fixed_int32_array_map, FixedInt32ArrayMap) \
V(Map, fixed_float32_array_map, FixedFloat32ArrayMap) \
V(Map, fixed_float64_array_map, FixedFloat64ArrayMap) \
V(Map, fixed_uint8_clamped_array_map, FixedUint8ClampedArrayMap) \
V(Map, fixed_biguint64_array_map, FixedBigUint64ArrayMap) \
V(Map, fixed_bigint64_array_map, FixedBigInt64ArrayMap) \
/* Oddball maps */ \
V(Map, undefined_map, UndefinedMap) \
V(Map, the_hole_map, TheHoleMap) \
@ -184,19 +171,6 @@ class Symbol;
EmptyArrayBoilerplateDescription) \
V(ClosureFeedbackCellArray, empty_closure_feedback_cell_array, \
EmptyClosureFeedbackCellArray) \
V(FixedTypedArrayBase, empty_fixed_uint8_array, EmptyFixedUint8Array) \
V(FixedTypedArrayBase, empty_fixed_int8_array, EmptyFixedInt8Array) \
V(FixedTypedArrayBase, empty_fixed_uint16_array, EmptyFixedUint16Array) \
V(FixedTypedArrayBase, empty_fixed_int16_array, EmptyFixedInt16Array) \
V(FixedTypedArrayBase, empty_fixed_uint32_array, EmptyFixedUint32Array) \
V(FixedTypedArrayBase, empty_fixed_int32_array, EmptyFixedInt32Array) \
V(FixedTypedArrayBase, empty_fixed_float32_array, EmptyFixedFloat32Array) \
V(FixedTypedArrayBase, empty_fixed_float64_array, EmptyFixedFloat64Array) \
V(FixedTypedArrayBase, empty_fixed_uint8_clamped_array, \
EmptyFixedUint8ClampedArray) \
V(FixedTypedArrayBase, empty_fixed_biguint64_array, \
EmptyFixedBigUint64Array) \
V(FixedTypedArrayBase, empty_fixed_bigint64_array, EmptyFixedBigInt64Array) \
V(FixedArray, empty_sloppy_arguments_elements, EmptySloppyArgumentsElements) \
V(NumberDictionary, empty_slow_element_dictionary, \
EmptySlowElementDictionary) \
@ -428,10 +402,6 @@ class RootsTable {
return static_cast<int>(root_index) * kSystemPointerSize;
}
static RootIndex RootIndexForFixedTypedArray(ExternalArrayType array_type);
static RootIndex RootIndexForFixedTypedArray(ElementsKind elements_kind);
static RootIndex RootIndexForEmptyFixedTypedArray(ElementsKind elements_kind);
// Immortal immovable root objects are allocated in OLD space and GC never
// moves them and the root table entries are guaranteed to not be modified
// after initialization. Note, however, that contents of those root objects
@ -527,11 +497,6 @@ class ReadOnlyRoots {
READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)
#undef ROOT_ACCESSOR
V8_INLINE Map MapForFixedTypedArray(ExternalArrayType array_type);
V8_INLINE Map MapForFixedTypedArray(ElementsKind elements_kind);
V8_INLINE FixedTypedArrayBase
EmptyFixedTypedArrayForTypedArray(ElementsKind elements_kind);
// Iterate over all the read-only roots. This is not necessary for garbage
// collection and is usually only performed as part of (de)serialization or
// heap verification.

View File

@ -149,7 +149,7 @@ RUNTIME_FUNCTION(Runtime_NormalizeElements) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
CHECK(!array->HasFixedTypedArrayElements());
CHECK(!array->HasTypedArrayElements());
CHECK(!array->IsJSGlobalProxy());
JSObject::NormalizeElements(array);
return *array;

View File

@ -309,6 +309,14 @@ RUNTIME_FUNCTION(Runtime_AllocateInOldGeneration) {
AllocationType::kOld);
}
RUNTIME_FUNCTION(Runtime_AllocateByteArray) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_SMI_ARG_CHECKED(length, 0);
DCHECK_LT(0, length);
return *isolate->factory()->NewByteArray(length);
}
RUNTIME_FUNCTION(Runtime_AllocateSeqOneByteString) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());

View File

@ -102,9 +102,6 @@ RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
size_t length = array->length();
if (length <= 1) return *array;
Handle<FixedTypedArrayBase> elements(
FixedTypedArrayBase::cast(array->elements()), isolate);
// In case of a SAB, the data is copied into temporary memory, as
// std::sort might crash in case the underlying data is concurrently
// modified while sorting.
@ -120,7 +117,7 @@ RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
CHECK_LE(bytes, INT_MAX);
array_copy = isolate->factory()->NewByteArray(static_cast<int>(bytes));
std::memcpy(static_cast<void*>(array_copy->GetDataStartAddress()),
static_cast<void*>(elements->DataPtr()), bytes);
static_cast<void*>(array->DataPtr()), bytes);
}
DisallowHeapAllocation no_gc;
@ -131,7 +128,7 @@ RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
ctype* data = \
copy_data \
? reinterpret_cast<ctype*>(array_copy->GetDataStartAddress()) \
: static_cast<ctype*>(elements->DataPtr()); \
: static_cast<ctype*>(array->DataPtr()); \
if (kExternal##Type##Array == kExternalFloat64Array || \
kExternal##Type##Array == kExternalFloat32Array) { \
if (COMPRESS_POINTERS_BOOL && alignof(ctype) > kTaggedSize) { \
@ -160,7 +157,7 @@ RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
if (copy_data) {
DCHECK(!array_copy.is_null());
const size_t bytes = array->byte_length();
std::memcpy(static_cast<void*>(elements->DataPtr()),
std::memcpy(static_cast<void*>(array->DataPtr()),
static_cast<void*>(array_copy->GetDataStartAddress()), bytes);
}

View File

@ -201,6 +201,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_INTERNAL(F, I) \
F(AccessCheck, 1, 1) \
F(AllocateByteArray, 1, 1) \
F(AllocateInYoungGeneration, 1, 1) \
F(AllocateInOldGeneration, 2, 1) \
F(AllocateSeqOneByteString, 1, 1) \

View File

@ -289,18 +289,13 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, int space) {
data_view.byte_offset());
} else if (obj.IsJSTypedArray()) {
JSTypedArray typed_array = JSTypedArray::cast(obj);
CHECK_LE(typed_array.byte_offset(), Smi::kMaxValue);
int32_t byte_offset = static_cast<int32_t>(typed_array.byte_offset());
if (byte_offset > 0) {
FixedTypedArrayBase elements =
FixedTypedArrayBase::cast(typed_array.elements());
// Must be off-heap layout.
DCHECK(!typed_array.is_on_heap());
void* pointer_with_offset = reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(elements.external_pointer()) +
byte_offset);
elements.set_external_pointer(pointer_with_offset);
// Only fixup for the off-heap case.
if (!typed_array.is_on_heap()) {
Smi store_index(
reinterpret_cast<Address>(typed_array.external_pointer()));
byte* backing_store = off_heap_backing_stores_[store_index.value()] +
typed_array.byte_offset();
typed_array.set_external_pointer(backing_store);
}
} else if (obj.IsJSArrayBuffer()) {
JSArrayBuffer buffer = JSArrayBuffer::cast(obj);
@ -312,14 +307,6 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, int space) {
buffer.set_backing_store(backing_store);
isolate_->heap()->RegisterNewArrayBuffer(buffer);
}
} else if (obj.IsFixedTypedArrayBase()) {
FixedTypedArrayBase fta = FixedTypedArrayBase::cast(obj);
// Only fixup for the off-heap case.
if (fta.base_pointer() == Smi::kZero) {
Smi store_index(reinterpret_cast<Address>(fta.external_pointer()));
void* backing_store = off_heap_backing_stores_[store_index.value()];
fta.set_external_pointer(backing_store);
}
} else if (obj.IsBytecodeArray()) {
// TODO(mythria): Remove these once we store the default values for these
// fields in the serializer.

View File

@ -359,9 +359,6 @@ int32_t Serializer::ObjectSerializer::SerializeBackingStore(
void Serializer::ObjectSerializer::SerializeJSTypedArray() {
JSTypedArray typed_array = JSTypedArray::cast(object_);
FixedTypedArrayBase elements =
FixedTypedArrayBase::cast(typed_array.elements());
if (!typed_array.WasDetached()) {
if (!typed_array.is_on_heap()) {
// Explicitly serialize the backing store now.
@ -374,23 +371,18 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() {
// We need to calculate the backing store from the external pointer
// because the ArrayBuffer may already have been serialized.
void* backing_store = reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(elements.external_pointer()) -
reinterpret_cast<intptr_t>(typed_array.external_pointer()) -
byte_offset);
int32_t ref = SerializeBackingStore(backing_store, byte_length);
// The external_pointer is the backing_store + typed_array->byte_offset.
// To properly share the buffer, we set the backing store ref here. On
// deserialization we re-add the byte_offset to external_pointer.
elements.set_external_pointer(
typed_array.set_external_pointer(
reinterpret_cast<void*>(Smi::FromInt(ref).ptr()));
}
} else {
// When a JSArrayBuffer is detached, the FixedTypedArray that points to the
// same backing store does not know anything about it. This fixup step finds
// detached TypedArrays and clears the values in the FixedTypedArray so that
// we don't try to serialize the now invalid backing store.
elements.set_external_pointer(reinterpret_cast<void*>(Smi::kZero.ptr()));
elements.set_number_of_elements_onheap_only(0);
typed_array.set_external_pointer(nullptr);
}
SerializeObject();
}

View File

@ -15657,14 +15657,13 @@ static void CheckElementValue(i::Isolate* isolate,
CHECK_EQ(expected, i::Smi::ToInt(element));
}
template <class ExternalArrayClass, class ElementType>
template <class ElementType>
static void ObjectWithExternalArrayTestHelper(Local<Context> context,
v8::Local<Object> obj,
v8::Local<v8::TypedArray> obj,
int element_count,
i::ExternalArrayType array_type,
int64_t low, int64_t high) {
i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
i::Handle<i::JSTypedArray> jsobj = v8::Utils::OpenHandle(*obj);
v8::Isolate* v8_isolate = context->GetIsolate();
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
obj->Set(context, v8_str("field"), v8::Int32::New(v8_isolate, 1503))
@ -15895,11 +15894,11 @@ static void ObjectWithExternalArrayTestHelper(Local<Context> context,
CHECK(result->BooleanValue(v8_isolate));
}
i::Handle<ExternalArrayClass> array(
ExternalArrayClass::cast(i::Handle<i::JSObject>::cast(jsobj)->elements()),
isolate);
for (int i = 0; i < element_count; i++) {
array->set(i, static_cast<ElementType>(i));
{
ElementType* data_ptr = static_cast<ElementType*>(jsobj->DataPtr());
for (int i = 0; i < element_count; i++) {
data_ptr[i] = static_cast<ElementType>(i);
}
}
bool old_natives_flag_sentry = i::FLAG_allow_natives_syntax;
@ -15984,101 +15983,7 @@ static void ObjectWithExternalArrayTestHelper(Local<Context> context,
CHECK_EQ(23, result->Int32Value(context).FromJust());
}
template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
class ElementType>
static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
ElementType low, ElementType high) {
i::FLAG_allow_natives_syntax = true;
LocalContext context;
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
v8::HandleScope scope(context->GetIsolate());
const int kElementCount = 260;
i::Handle<i::JSTypedArray> jsobj =
factory->NewJSTypedArray(elements_kind, kElementCount);
i::Handle<FixedTypedArrayClass> fixed_array(
FixedTypedArrayClass::cast(jsobj->elements()), isolate);
CHECK_EQ(FixedTypedArrayClass::kInstanceType,
fixed_array->map().instance_type());
CHECK_EQ(kElementCount, jsobj->length());
CHECK_EQ(kElementCount, fixed_array->number_of_elements_onheap_only());
CcTest::CollectAllGarbage();
for (int i = 0; i < kElementCount; i++) {
fixed_array->set(i, static_cast<ElementType>(i));
}
// Force GC to trigger verification.
CcTest::CollectAllGarbage();
for (int i = 0; i < kElementCount; i++) {
CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
static_cast<int64_t>(fixed_array->get_scalar(i)));
}
v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
context.local(), obj, kElementCount, array_type,
static_cast<int64_t>(low),
static_cast<int64_t>(high));
}
THREADED_TEST(FixedUint8Array) {
FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
i::kExternalUint8Array, 0x0, 0xFF);
}
THREADED_TEST(FixedUint8ClampedArray) {
FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
i::kExternalUint8ClampedArray, 0x0, 0xFF);
}
THREADED_TEST(FixedInt8Array) {
FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
i::kExternalInt8Array, -0x80, 0x7F);
}
THREADED_TEST(FixedUint16Array) {
FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
i::kExternalUint16Array, 0x0, 0xFFFF);
}
THREADED_TEST(FixedInt16Array) {
FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
i::kExternalInt16Array, -0x8000, 0x7FFF);
}
THREADED_TEST(FixedUint32Array) {
FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
i::kExternalUint32Array, 0x0, UINT_MAX);
}
THREADED_TEST(FixedInt32Array) {
FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
i::kExternalInt32Array, INT_MIN, INT_MAX);
}
THREADED_TEST(FixedFloat32Array) {
FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
i::kExternalFloat32Array, -500, 500);
}
THREADED_TEST(FixedFloat64Array) {
FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
i::kExternalFloat64Array, -500, 500);
}
template <typename ElementType, typename TypedArray, class ExternalArrayClass,
class ArrayBufferType>
template <typename ElementType, typename TypedArray, class ArrayBufferType>
void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
int64_t high) {
const int kElementCount = 50;
@ -16105,64 +16010,60 @@ void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
data[i] = static_cast<ElementType>(i);
}
ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
env.local(), ta, kElementCount, array_type, low, high);
ObjectWithExternalArrayTestHelper<ElementType>(env.local(), ta, kElementCount,
array_type, low, high);
}
THREADED_TEST(Uint8Array) {
TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
TypedArrayTestHelper<uint8_t, v8::Uint8Array, v8::ArrayBuffer>(
i::kExternalUint8Array, 0, 0xFF);
}
THREADED_TEST(Int8Array) {
TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
TypedArrayTestHelper<int8_t, v8::Int8Array, v8::ArrayBuffer>(
i::kExternalInt8Array, -0x80, 0x7F);
}
THREADED_TEST(Uint16Array) {
TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
TypedArrayTestHelper<uint16_t, v8::Uint16Array, v8::ArrayBuffer>(
i::kExternalUint16Array, 0, 0xFFFF);
}
THREADED_TEST(Int16Array) {
TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
0x7FFF);
TypedArrayTestHelper<int16_t, v8::Int16Array, v8::ArrayBuffer>(
i::kExternalInt16Array, -0x8000, 0x7FFF);
}
THREADED_TEST(Uint32Array) {
TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
TypedArrayTestHelper<uint32_t, v8::Uint32Array, v8::ArrayBuffer>(
i::kExternalUint32Array, 0, UINT_MAX);
}
THREADED_TEST(Int32Array) {
TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
INT_MAX);
TypedArrayTestHelper<int32_t, v8::Int32Array, v8::ArrayBuffer>(
i::kExternalInt32Array, INT_MIN, INT_MAX);
}
THREADED_TEST(Float32Array) {
TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
TypedArrayTestHelper<float, v8::Float32Array, v8::ArrayBuffer>(
i::kExternalFloat32Array, -500, 500);
}
THREADED_TEST(Float64Array) {
TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
TypedArrayTestHelper<double, v8::Float64Array, v8::ArrayBuffer>(
i::kExternalFloat64Array, -500, 500);
}
THREADED_TEST(Uint8ClampedArray) {
TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
i::FixedUint8ClampedArray, v8::ArrayBuffer>(
TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, v8::ArrayBuffer>(
i::kExternalUint8ClampedArray, 0, 0xFF);
}
@ -16236,71 +16137,63 @@ THREADED_TEST(SkipArrayBufferDuringScavenge) {
THREADED_TEST(SharedUint8Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
TypedArrayTestHelper<uint8_t, v8::Uint8Array, v8::SharedArrayBuffer>(
i::kExternalUint8Array, 0, 0xFF);
}
THREADED_TEST(SharedInt8Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
0x7F);
TypedArrayTestHelper<int8_t, v8::Int8Array, v8::SharedArrayBuffer>(
i::kExternalInt8Array, -0x80, 0x7F);
}
THREADED_TEST(SharedUint16Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
0xFFFF);
TypedArrayTestHelper<uint16_t, v8::Uint16Array, v8::SharedArrayBuffer>(
i::kExternalUint16Array, 0, 0xFFFF);
}
THREADED_TEST(SharedInt16Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
0x7FFF);
TypedArrayTestHelper<int16_t, v8::Int16Array, v8::SharedArrayBuffer>(
i::kExternalInt16Array, -0x8000, 0x7FFF);
}
THREADED_TEST(SharedUint32Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
UINT_MAX);
TypedArrayTestHelper<uint32_t, v8::Uint32Array, v8::SharedArrayBuffer>(
i::kExternalUint32Array, 0, UINT_MAX);
}
THREADED_TEST(SharedInt32Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
INT_MAX);
TypedArrayTestHelper<int32_t, v8::Int32Array, v8::SharedArrayBuffer>(
i::kExternalInt32Array, INT_MIN, INT_MAX);
}
THREADED_TEST(SharedFloat32Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
500);
TypedArrayTestHelper<float, v8::Float32Array, v8::SharedArrayBuffer>(
i::kExternalFloat32Array, -500, 500);
}
THREADED_TEST(SharedFloat64Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
500);
TypedArrayTestHelper<double, v8::Float64Array, v8::SharedArrayBuffer>(
i::kExternalFloat64Array, -500, 500);
}
THREADED_TEST(SharedUint8ClampedArray) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, v8::SharedArrayBuffer>(
i::kExternalUint8ClampedArray, 0, 0xFF);
}

View File

@ -1542,8 +1542,10 @@ TEST(TryLookupElement) {
}
{
Handle<JSTypedArray> object = factory->NewJSTypedArray(INT32_ELEMENTS, 2);
Local<v8::ArrayBuffer> buffer = Utils::ToLocal(object->GetBuffer());
v8::Local<v8::ArrayBuffer> buffer =
v8::ArrayBuffer::New(reinterpret_cast<v8::Isolate*>(isolate), 8);
Handle<JSTypedArray> object = factory->NewJSTypedArray(
kExternalInt32Array, v8::Utils::OpenHandle(*buffer), 0, 2);
CHECK_EQ(INT32_ELEMENTS, object->map().elements_kind());

View File

@ -1105,7 +1105,6 @@ UNINITIALIZED_TEST(CustomSnapshotDataBlobDetachedArrayBuffer) {
i::Handle<i::JSTypedArray> array =
i::Handle<i::JSTypedArray>::cast(v8::Utils::OpenHandle(*x));
CHECK(array->WasDetached());
CHECK_NULL(FixedTypedArrayBase::cast(array->elements()).external_pointer());
}
isolate->Dispose();
delete[] blob.data; // We can dispose of the snapshot blob now.

View File

@ -146,26 +146,25 @@ const ElementAccess kElementAccesses[] = {
{kUntaggedBase, 0, Type::Number(),
MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone),
kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
MachineType::Int8(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
{kTaggedBase, ByteArray::kHeaderSize, Type::Signed32(), MachineType::Int8(),
kNoWriteBarrier},
{kTaggedBase, ByteArray::kHeaderSize, Type::Unsigned32(),
MachineType::Uint8(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
{kTaggedBase, ByteArray::kHeaderSize, Type::Signed32(),
MachineType::Int16(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
{kTaggedBase, ByteArray::kHeaderSize, Type::Unsigned32(),
MachineType::Uint16(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
{kTaggedBase, ByteArray::kHeaderSize, Type::Signed32(),
MachineType::Int32(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
{kTaggedBase, ByteArray::kHeaderSize, Type::Unsigned32(),
MachineType::Uint32(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
{kTaggedBase, ByteArray::kHeaderSize, Type::Number(),
MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
{kTaggedBase, ByteArray::kHeaderSize, Type::Number(),
MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
kNoWriteBarrier}};
class SimplifiedElementAccessOperatorTest
: public TestWithZone,
public ::testing::WithParamInterface<ElementAccess> {};

View File

@ -240,7 +240,6 @@ extras_accessors = [
'JSObject, elements, Object, kElementsOffset',
'JSObject, internal_fields, uintptr_t, kHeaderSize',
'FixedArray, data, uintptr_t, kHeaderSize',
'FixedTypedArrayBase, external_pointer, uintptr_t, kExternalPointerOffset',
'JSArrayBuffer, backing_store, uintptr_t, kBackingStoreOffset',
'JSArrayBuffer, byte_length, size_t, kByteLengthOffset',
'JSArrayBufferView, byte_length, size_t, kByteLengthOffset',

View File

@ -36,107 +36,96 @@ INSTANCE_TYPES = {
72: "BYTE_ARRAY_TYPE",
73: "BYTECODE_ARRAY_TYPE",
74: "FREE_SPACE_TYPE",
75: "FIXED_INT8_ARRAY_TYPE",
76: "FIXED_UINT8_ARRAY_TYPE",
77: "FIXED_INT16_ARRAY_TYPE",
78: "FIXED_UINT16_ARRAY_TYPE",
79: "FIXED_INT32_ARRAY_TYPE",
80: "FIXED_UINT32_ARRAY_TYPE",
81: "FIXED_FLOAT32_ARRAY_TYPE",
82: "FIXED_FLOAT64_ARRAY_TYPE",
83: "FIXED_UINT8_CLAMPED_ARRAY_TYPE",
84: "FIXED_BIGINT64_ARRAY_TYPE",
85: "FIXED_BIGUINT64_ARRAY_TYPE",
86: "FIXED_DOUBLE_ARRAY_TYPE",
87: "FEEDBACK_METADATA_TYPE",
88: "FILLER_TYPE",
89: "ACCESS_CHECK_INFO_TYPE",
90: "ACCESSOR_INFO_TYPE",
91: "ACCESSOR_PAIR_TYPE",
92: "ALIASED_ARGUMENTS_ENTRY_TYPE",
93: "ALLOCATION_MEMENTO_TYPE",
94: "ASM_WASM_DATA_TYPE",
95: "ASYNC_GENERATOR_REQUEST_TYPE",
96: "CLASS_POSITIONS_TYPE",
97: "DEBUG_INFO_TYPE",
98: "ENUM_CACHE_TYPE",
99: "FUNCTION_TEMPLATE_INFO_TYPE",
100: "FUNCTION_TEMPLATE_RARE_DATA_TYPE",
101: "INTERCEPTOR_INFO_TYPE",
102: "INTERPRETER_DATA_TYPE",
103: "MODULE_INFO_ENTRY_TYPE",
104: "MODULE_TYPE",
105: "OBJECT_TEMPLATE_INFO_TYPE",
106: "PROMISE_CAPABILITY_TYPE",
107: "PROMISE_REACTION_TYPE",
108: "PROTOTYPE_INFO_TYPE",
109: "SCRIPT_TYPE",
110: "SOURCE_POSITION_TABLE_WITH_FRAME_CACHE_TYPE",
111: "STACK_FRAME_INFO_TYPE",
112: "STACK_TRACE_FRAME_TYPE",
113: "TEMPLATE_OBJECT_DESCRIPTION_TYPE",
114: "TUPLE2_TYPE",
115: "TUPLE3_TYPE",
116: "ARRAY_BOILERPLATE_DESCRIPTION_TYPE",
117: "WASM_CAPI_FUNCTION_DATA_TYPE",
118: "WASM_DEBUG_INFO_TYPE",
119: "WASM_EXCEPTION_TAG_TYPE",
120: "WASM_EXPORTED_FUNCTION_DATA_TYPE",
121: "WASM_JS_FUNCTION_DATA_TYPE",
122: "CALLABLE_TASK_TYPE",
123: "CALLBACK_TASK_TYPE",
124: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
125: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
126: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE",
127: "FINALIZATION_GROUP_CLEANUP_JOB_TASK_TYPE",
128: "ALLOCATION_SITE_TYPE",
129: "EMBEDDER_DATA_ARRAY_TYPE",
130: "FIXED_ARRAY_TYPE",
131: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE",
132: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE",
133: "HASH_TABLE_TYPE",
134: "ORDERED_HASH_MAP_TYPE",
135: "ORDERED_HASH_SET_TYPE",
136: "ORDERED_NAME_DICTIONARY_TYPE",
137: "NAME_DICTIONARY_TYPE",
138: "GLOBAL_DICTIONARY_TYPE",
139: "NUMBER_DICTIONARY_TYPE",
140: "SIMPLE_NUMBER_DICTIONARY_TYPE",
141: "STRING_TABLE_TYPE",
142: "EPHEMERON_HASH_TABLE_TYPE",
143: "SCOPE_INFO_TYPE",
144: "SCRIPT_CONTEXT_TABLE_TYPE",
145: "AWAIT_CONTEXT_TYPE",
146: "BLOCK_CONTEXT_TYPE",
147: "CATCH_CONTEXT_TYPE",
148: "DEBUG_EVALUATE_CONTEXT_TYPE",
149: "EVAL_CONTEXT_TYPE",
150: "FUNCTION_CONTEXT_TYPE",
151: "MODULE_CONTEXT_TYPE",
152: "NATIVE_CONTEXT_TYPE",
153: "SCRIPT_CONTEXT_TYPE",
154: "WITH_CONTEXT_TYPE",
155: "WEAK_FIXED_ARRAY_TYPE",
156: "TRANSITION_ARRAY_TYPE",
157: "CALL_HANDLER_INFO_TYPE",
158: "CELL_TYPE",
159: "CODE_DATA_CONTAINER_TYPE",
160: "DESCRIPTOR_ARRAY_TYPE",
161: "FEEDBACK_CELL_TYPE",
162: "FEEDBACK_VECTOR_TYPE",
163: "LOAD_HANDLER_TYPE",
164: "PREPARSE_DATA_TYPE",
165: "PROPERTY_ARRAY_TYPE",
166: "PROPERTY_CELL_TYPE",
167: "SHARED_FUNCTION_INFO_TYPE",
168: "SMALL_ORDERED_HASH_MAP_TYPE",
169: "SMALL_ORDERED_HASH_SET_TYPE",
170: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
171: "STORE_HANDLER_TYPE",
172: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
173: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
174: "WEAK_ARRAY_LIST_TYPE",
175: "WEAK_CELL_TYPE",
75: "FIXED_DOUBLE_ARRAY_TYPE",
76: "FEEDBACK_METADATA_TYPE",
77: "FILLER_TYPE",
78: "ACCESS_CHECK_INFO_TYPE",
79: "ACCESSOR_INFO_TYPE",
80: "ACCESSOR_PAIR_TYPE",
81: "ALIASED_ARGUMENTS_ENTRY_TYPE",
82: "ALLOCATION_MEMENTO_TYPE",
83: "ASM_WASM_DATA_TYPE",
84: "ASYNC_GENERATOR_REQUEST_TYPE",
85: "CLASS_POSITIONS_TYPE",
86: "DEBUG_INFO_TYPE",
87: "ENUM_CACHE_TYPE",
88: "FUNCTION_TEMPLATE_INFO_TYPE",
89: "FUNCTION_TEMPLATE_RARE_DATA_TYPE",
90: "INTERCEPTOR_INFO_TYPE",
91: "INTERPRETER_DATA_TYPE",
92: "MODULE_INFO_ENTRY_TYPE",
93: "MODULE_TYPE",
94: "OBJECT_TEMPLATE_INFO_TYPE",
95: "PROMISE_CAPABILITY_TYPE",
96: "PROMISE_REACTION_TYPE",
97: "PROTOTYPE_INFO_TYPE",
98: "SCRIPT_TYPE",
99: "SOURCE_POSITION_TABLE_WITH_FRAME_CACHE_TYPE",
100: "STACK_FRAME_INFO_TYPE",
101: "STACK_TRACE_FRAME_TYPE",
102: "TEMPLATE_OBJECT_DESCRIPTION_TYPE",
103: "TUPLE2_TYPE",
104: "TUPLE3_TYPE",
105: "ARRAY_BOILERPLATE_DESCRIPTION_TYPE",
106: "WASM_CAPI_FUNCTION_DATA_TYPE",
107: "WASM_DEBUG_INFO_TYPE",
108: "WASM_EXCEPTION_TAG_TYPE",
109: "WASM_EXPORTED_FUNCTION_DATA_TYPE",
110: "WASM_JS_FUNCTION_DATA_TYPE",
111: "CALLABLE_TASK_TYPE",
112: "CALLBACK_TASK_TYPE",
113: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
114: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
115: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE",
116: "FINALIZATION_GROUP_CLEANUP_JOB_TASK_TYPE",
117: "ALLOCATION_SITE_TYPE",
118: "EMBEDDER_DATA_ARRAY_TYPE",
119: "FIXED_ARRAY_TYPE",
120: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE",
121: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE",
122: "HASH_TABLE_TYPE",
123: "ORDERED_HASH_MAP_TYPE",
124: "ORDERED_HASH_SET_TYPE",
125: "ORDERED_NAME_DICTIONARY_TYPE",
126: "NAME_DICTIONARY_TYPE",
127: "GLOBAL_DICTIONARY_TYPE",
128: "NUMBER_DICTIONARY_TYPE",
129: "SIMPLE_NUMBER_DICTIONARY_TYPE",
130: "STRING_TABLE_TYPE",
131: "EPHEMERON_HASH_TABLE_TYPE",
132: "SCOPE_INFO_TYPE",
133: "SCRIPT_CONTEXT_TABLE_TYPE",
134: "AWAIT_CONTEXT_TYPE",
135: "BLOCK_CONTEXT_TYPE",
136: "CATCH_CONTEXT_TYPE",
137: "DEBUG_EVALUATE_CONTEXT_TYPE",
138: "EVAL_CONTEXT_TYPE",
139: "FUNCTION_CONTEXT_TYPE",
140: "MODULE_CONTEXT_TYPE",
141: "NATIVE_CONTEXT_TYPE",
142: "SCRIPT_CONTEXT_TYPE",
143: "WITH_CONTEXT_TYPE",
144: "WEAK_FIXED_ARRAY_TYPE",
145: "TRANSITION_ARRAY_TYPE",
146: "CALL_HANDLER_INFO_TYPE",
147: "CELL_TYPE",
148: "CODE_DATA_CONTAINER_TYPE",
149: "DESCRIPTOR_ARRAY_TYPE",
150: "FEEDBACK_CELL_TYPE",
151: "FEEDBACK_VECTOR_TYPE",
152: "LOAD_HANDLER_TYPE",
153: "PREPARSE_DATA_TYPE",
154: "PROPERTY_ARRAY_TYPE",
155: "PROPERTY_CELL_TYPE",
156: "SHARED_FUNCTION_INFO_TYPE",
157: "SMALL_ORDERED_HASH_MAP_TYPE",
158: "SMALL_ORDERED_HASH_SET_TYPE",
159: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
160: "STORE_HANDLER_TYPE",
161: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
162: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
163: "WEAK_ARRAY_LIST_TYPE",
164: "WEAK_CELL_TYPE",
1024: "JS_PROXY_TYPE",
1025: "JS_GLOBAL_OBJECT_TYPE",
1026: "JS_GLOBAL_PROXY_TYPE",
@ -200,10 +189,10 @@ KNOWN_MAPS = {
("read_only_space", 0x00139): (74, "FreeSpaceMap"),
("read_only_space", 0x00189): (68, "MetaMap"),
("read_only_space", 0x00209): (67, "NullMap"),
("read_only_space", 0x00271): (160, "DescriptorArrayMap"),
("read_only_space", 0x002d1): (155, "WeakFixedArrayMap"),
("read_only_space", 0x00321): (88, "OnePointerFillerMap"),
("read_only_space", 0x00371): (88, "TwoPointerFillerMap"),
("read_only_space", 0x00271): (149, "DescriptorArrayMap"),
("read_only_space", 0x002d1): (144, "WeakFixedArrayMap"),
("read_only_space", 0x00321): (77, "OnePointerFillerMap"),
("read_only_space", 0x00371): (77, "TwoPointerFillerMap"),
("read_only_space", 0x003f1): (67, "UninitializedMap"),
("read_only_space", 0x00461): (8, "OneByteInternalizedStringMap"),
("read_only_space", 0x00501): (67, "UndefinedMap"),
@ -211,71 +200,71 @@ KNOWN_MAPS = {
("read_only_space", 0x005e1): (67, "TheHoleMap"),
("read_only_space", 0x00689): (67, "BooleanMap"),
("read_only_space", 0x00761): (72, "ByteArrayMap"),
("read_only_space", 0x007b1): (130, "FixedArrayMap"),
("read_only_space", 0x00801): (130, "FixedCOWArrayMap"),
("read_only_space", 0x00851): (133, "HashTableMap"),
("read_only_space", 0x007b1): (119, "FixedArrayMap"),
("read_only_space", 0x00801): (119, "FixedCOWArrayMap"),
("read_only_space", 0x00851): (122, "HashTableMap"),
("read_only_space", 0x008a1): (64, "SymbolMap"),
("read_only_space", 0x008f1): (40, "OneByteStringMap"),
("read_only_space", 0x00941): (143, "ScopeInfoMap"),
("read_only_space", 0x00991): (167, "SharedFunctionInfoMap"),
("read_only_space", 0x00941): (132, "ScopeInfoMap"),
("read_only_space", 0x00991): (156, "SharedFunctionInfoMap"),
("read_only_space", 0x009e1): (69, "CodeMap"),
("read_only_space", 0x00a31): (150, "FunctionContextMap"),
("read_only_space", 0x00a81): (158, "CellMap"),
("read_only_space", 0x00ad1): (166, "GlobalPropertyCellMap"),
("read_only_space", 0x00a31): (139, "FunctionContextMap"),
("read_only_space", 0x00a81): (147, "CellMap"),
("read_only_space", 0x00ad1): (155, "GlobalPropertyCellMap"),
("read_only_space", 0x00b21): (71, "ForeignMap"),
("read_only_space", 0x00b71): (156, "TransitionArrayMap"),
("read_only_space", 0x00bc1): (162, "FeedbackVectorMap"),
("read_only_space", 0x00b71): (145, "TransitionArrayMap"),
("read_only_space", 0x00bc1): (151, "FeedbackVectorMap"),
("read_only_space", 0x00c61): (67, "ArgumentsMarkerMap"),
("read_only_space", 0x00d01): (67, "ExceptionMap"),
("read_only_space", 0x00da1): (67, "TerminationExceptionMap"),
("read_only_space", 0x00e49): (67, "OptimizedOutMap"),
("read_only_space", 0x00ee9): (67, "StaleRegisterMap"),
("read_only_space", 0x00f59): (152, "NativeContextMap"),
("read_only_space", 0x00fa9): (151, "ModuleContextMap"),
("read_only_space", 0x00ff9): (149, "EvalContextMap"),
("read_only_space", 0x01049): (153, "ScriptContextMap"),
("read_only_space", 0x01099): (145, "AwaitContextMap"),
("read_only_space", 0x010e9): (146, "BlockContextMap"),
("read_only_space", 0x01139): (147, "CatchContextMap"),
("read_only_space", 0x01189): (154, "WithContextMap"),
("read_only_space", 0x011d9): (148, "DebugEvaluateContextMap"),
("read_only_space", 0x01229): (144, "ScriptContextTableMap"),
("read_only_space", 0x01279): (132, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x012c9): (87, "FeedbackMetadataArrayMap"),
("read_only_space", 0x01319): (130, "ArrayListMap"),
("read_only_space", 0x00f59): (141, "NativeContextMap"),
("read_only_space", 0x00fa9): (140, "ModuleContextMap"),
("read_only_space", 0x00ff9): (138, "EvalContextMap"),
("read_only_space", 0x01049): (142, "ScriptContextMap"),
("read_only_space", 0x01099): (134, "AwaitContextMap"),
("read_only_space", 0x010e9): (135, "BlockContextMap"),
("read_only_space", 0x01139): (136, "CatchContextMap"),
("read_only_space", 0x01189): (143, "WithContextMap"),
("read_only_space", 0x011d9): (137, "DebugEvaluateContextMap"),
("read_only_space", 0x01229): (133, "ScriptContextTableMap"),
("read_only_space", 0x01279): (121, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x012c9): (76, "FeedbackMetadataArrayMap"),
("read_only_space", 0x01319): (119, "ArrayListMap"),
("read_only_space", 0x01369): (66, "BigIntMap"),
("read_only_space", 0x013b9): (131, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x013b9): (120, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x01409): (73, "BytecodeArrayMap"),
("read_only_space", 0x01459): (159, "CodeDataContainerMap"),
("read_only_space", 0x014a9): (86, "FixedDoubleArrayMap"),
("read_only_space", 0x014f9): (138, "GlobalDictionaryMap"),
("read_only_space", 0x01549): (161, "ManyClosuresCellMap"),
("read_only_space", 0x01599): (130, "ModuleInfoMap"),
("read_only_space", 0x01459): (148, "CodeDataContainerMap"),
("read_only_space", 0x014a9): (75, "FixedDoubleArrayMap"),
("read_only_space", 0x014f9): (127, "GlobalDictionaryMap"),
("read_only_space", 0x01549): (150, "ManyClosuresCellMap"),
("read_only_space", 0x01599): (119, "ModuleInfoMap"),
("read_only_space", 0x015e9): (70, "MutableHeapNumberMap"),
("read_only_space", 0x01639): (137, "NameDictionaryMap"),
("read_only_space", 0x01689): (161, "NoClosuresCellMap"),
("read_only_space", 0x016d9): (139, "NumberDictionaryMap"),
("read_only_space", 0x01729): (161, "OneClosureCellMap"),
("read_only_space", 0x01779): (134, "OrderedHashMapMap"),
("read_only_space", 0x017c9): (135, "OrderedHashSetMap"),
("read_only_space", 0x01819): (136, "OrderedNameDictionaryMap"),
("read_only_space", 0x01869): (164, "PreparseDataMap"),
("read_only_space", 0x018b9): (165, "PropertyArrayMap"),
("read_only_space", 0x01909): (157, "SideEffectCallHandlerInfoMap"),
("read_only_space", 0x01959): (157, "SideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x019a9): (157, "NextCallSideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x019f9): (140, "SimpleNumberDictionaryMap"),
("read_only_space", 0x01a49): (130, "SloppyArgumentsElementsMap"),
("read_only_space", 0x01a99): (168, "SmallOrderedHashMapMap"),
("read_only_space", 0x01ae9): (169, "SmallOrderedHashSetMap"),
("read_only_space", 0x01b39): (170, "SmallOrderedNameDictionaryMap"),
("read_only_space", 0x01b89): (141, "StringTableMap"),
("read_only_space", 0x01bd9): (172, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x01c29): (173, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x01c79): (174, "WeakArrayListMap"),
("read_only_space", 0x01cc9): (142, "EphemeronHashTableMap"),
("read_only_space", 0x01d19): (129, "EmbedderDataArrayMap"),
("read_only_space", 0x01d69): (175, "WeakCellMap"),
("read_only_space", 0x01639): (126, "NameDictionaryMap"),
("read_only_space", 0x01689): (150, "NoClosuresCellMap"),
("read_only_space", 0x016d9): (128, "NumberDictionaryMap"),
("read_only_space", 0x01729): (150, "OneClosureCellMap"),
("read_only_space", 0x01779): (123, "OrderedHashMapMap"),
("read_only_space", 0x017c9): (124, "OrderedHashSetMap"),
("read_only_space", 0x01819): (125, "OrderedNameDictionaryMap"),
("read_only_space", 0x01869): (153, "PreparseDataMap"),
("read_only_space", 0x018b9): (154, "PropertyArrayMap"),
("read_only_space", 0x01909): (146, "SideEffectCallHandlerInfoMap"),
("read_only_space", 0x01959): (146, "SideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x019a9): (146, "NextCallSideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x019f9): (129, "SimpleNumberDictionaryMap"),
("read_only_space", 0x01a49): (119, "SloppyArgumentsElementsMap"),
("read_only_space", 0x01a99): (157, "SmallOrderedHashMapMap"),
("read_only_space", 0x01ae9): (158, "SmallOrderedHashSetMap"),
("read_only_space", 0x01b39): (159, "SmallOrderedNameDictionaryMap"),
("read_only_space", 0x01b89): (130, "StringTableMap"),
("read_only_space", 0x01bd9): (161, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x01c29): (162, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x01c79): (163, "WeakArrayListMap"),
("read_only_space", 0x01cc9): (131, "EphemeronHashTableMap"),
("read_only_space", 0x01d19): (118, "EmbedderDataArrayMap"),
("read_only_space", 0x01d69): (164, "WeakCellMap"),
("read_only_space", 0x01db9): (58, "NativeSourceStringMap"),
("read_only_space", 0x01e09): (32, "StringMap"),
("read_only_space", 0x01e59): (41, "ConsOneByteStringMap"),
@ -293,66 +282,55 @@ KNOWN_MAPS = {
("read_only_space", 0x02219): (18, "UncachedExternalInternalizedStringMap"),
("read_only_space", 0x02269): (26, "UncachedExternalOneByteInternalizedStringMap"),
("read_only_space", 0x022b9): (58, "UncachedExternalOneByteStringMap"),
("read_only_space", 0x02309): (76, "FixedUint8ArrayMap"),
("read_only_space", 0x02359): (75, "FixedInt8ArrayMap"),
("read_only_space", 0x023a9): (78, "FixedUint16ArrayMap"),
("read_only_space", 0x023f9): (77, "FixedInt16ArrayMap"),
("read_only_space", 0x02449): (80, "FixedUint32ArrayMap"),
("read_only_space", 0x02499): (79, "FixedInt32ArrayMap"),
("read_only_space", 0x024e9): (81, "FixedFloat32ArrayMap"),
("read_only_space", 0x02539): (82, "FixedFloat64ArrayMap"),
("read_only_space", 0x02589): (83, "FixedUint8ClampedArrayMap"),
("read_only_space", 0x025d9): (85, "FixedBigUint64ArrayMap"),
("read_only_space", 0x02629): (84, "FixedBigInt64ArrayMap"),
("read_only_space", 0x02679): (67, "SelfReferenceMarkerMap"),
("read_only_space", 0x026e1): (98, "EnumCacheMap"),
("read_only_space", 0x02781): (116, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x02ad1): (101, "InterceptorInfoMap"),
("read_only_space", 0x05269): (89, "AccessCheckInfoMap"),
("read_only_space", 0x052b9): (90, "AccessorInfoMap"),
("read_only_space", 0x05309): (91, "AccessorPairMap"),
("read_only_space", 0x05359): (92, "AliasedArgumentsEntryMap"),
("read_only_space", 0x053a9): (93, "AllocationMementoMap"),
("read_only_space", 0x053f9): (94, "AsmWasmDataMap"),
("read_only_space", 0x05449): (95, "AsyncGeneratorRequestMap"),
("read_only_space", 0x05499): (96, "ClassPositionsMap"),
("read_only_space", 0x054e9): (97, "DebugInfoMap"),
("read_only_space", 0x05539): (99, "FunctionTemplateInfoMap"),
("read_only_space", 0x05589): (100, "FunctionTemplateRareDataMap"),
("read_only_space", 0x055d9): (102, "InterpreterDataMap"),
("read_only_space", 0x05629): (103, "ModuleInfoEntryMap"),
("read_only_space", 0x05679): (104, "ModuleMap"),
("read_only_space", 0x056c9): (105, "ObjectTemplateInfoMap"),
("read_only_space", 0x05719): (106, "PromiseCapabilityMap"),
("read_only_space", 0x05769): (107, "PromiseReactionMap"),
("read_only_space", 0x057b9): (108, "PrototypeInfoMap"),
("read_only_space", 0x05809): (109, "ScriptMap"),
("read_only_space", 0x05859): (110, "SourcePositionTableWithFrameCacheMap"),
("read_only_space", 0x058a9): (111, "StackFrameInfoMap"),
("read_only_space", 0x058f9): (112, "StackTraceFrameMap"),
("read_only_space", 0x05949): (113, "TemplateObjectDescriptionMap"),
("read_only_space", 0x05999): (114, "Tuple2Map"),
("read_only_space", 0x059e9): (115, "Tuple3Map"),
("read_only_space", 0x05a39): (117, "WasmCapiFunctionDataMap"),
("read_only_space", 0x05a89): (118, "WasmDebugInfoMap"),
("read_only_space", 0x05ad9): (119, "WasmExceptionTagMap"),
("read_only_space", 0x05b29): (120, "WasmExportedFunctionDataMap"),
("read_only_space", 0x05b79): (121, "WasmJSFunctionDataMap"),
("read_only_space", 0x05bc9): (122, "CallableTaskMap"),
("read_only_space", 0x05c19): (123, "CallbackTaskMap"),
("read_only_space", 0x05c69): (124, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x05cb9): (125, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05d09): (126, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x05d59): (127, "FinalizationGroupCleanupJobTaskMap"),
("read_only_space", 0x05da9): (128, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05df9): (128, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05e49): (163, "LoadHandler1Map"),
("read_only_space", 0x05e99): (163, "LoadHandler2Map"),
("read_only_space", 0x05ee9): (163, "LoadHandler3Map"),
("read_only_space", 0x05f39): (171, "StoreHandler0Map"),
("read_only_space", 0x05f89): (171, "StoreHandler1Map"),
("read_only_space", 0x05fd9): (171, "StoreHandler2Map"),
("read_only_space", 0x06029): (171, "StoreHandler3Map"),
("read_only_space", 0x02309): (67, "SelfReferenceMarkerMap"),
("read_only_space", 0x02371): (87, "EnumCacheMap"),
("read_only_space", 0x02411): (105, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x02601): (90, "InterceptorInfoMap"),
("read_only_space", 0x04d99): (78, "AccessCheckInfoMap"),
("read_only_space", 0x04de9): (79, "AccessorInfoMap"),
("read_only_space", 0x04e39): (80, "AccessorPairMap"),
("read_only_space", 0x04e89): (81, "AliasedArgumentsEntryMap"),
("read_only_space", 0x04ed9): (82, "AllocationMementoMap"),
("read_only_space", 0x04f29): (83, "AsmWasmDataMap"),
("read_only_space", 0x04f79): (84, "AsyncGeneratorRequestMap"),
("read_only_space", 0x04fc9): (85, "ClassPositionsMap"),
("read_only_space", 0x05019): (86, "DebugInfoMap"),
("read_only_space", 0x05069): (88, "FunctionTemplateInfoMap"),
("read_only_space", 0x050b9): (89, "FunctionTemplateRareDataMap"),
("read_only_space", 0x05109): (91, "InterpreterDataMap"),
("read_only_space", 0x05159): (92, "ModuleInfoEntryMap"),
("read_only_space", 0x051a9): (93, "ModuleMap"),
("read_only_space", 0x051f9): (94, "ObjectTemplateInfoMap"),
("read_only_space", 0x05249): (95, "PromiseCapabilityMap"),
("read_only_space", 0x05299): (96, "PromiseReactionMap"),
("read_only_space", 0x052e9): (97, "PrototypeInfoMap"),
("read_only_space", 0x05339): (98, "ScriptMap"),
("read_only_space", 0x05389): (99, "SourcePositionTableWithFrameCacheMap"),
("read_only_space", 0x053d9): (100, "StackFrameInfoMap"),
("read_only_space", 0x05429): (101, "StackTraceFrameMap"),
("read_only_space", 0x05479): (102, "TemplateObjectDescriptionMap"),
("read_only_space", 0x054c9): (103, "Tuple2Map"),
("read_only_space", 0x05519): (104, "Tuple3Map"),
("read_only_space", 0x05569): (106, "WasmCapiFunctionDataMap"),
("read_only_space", 0x055b9): (107, "WasmDebugInfoMap"),
("read_only_space", 0x05609): (108, "WasmExceptionTagMap"),
("read_only_space", 0x05659): (109, "WasmExportedFunctionDataMap"),
("read_only_space", 0x056a9): (110, "WasmJSFunctionDataMap"),
("read_only_space", 0x056f9): (111, "CallableTaskMap"),
("read_only_space", 0x05749): (112, "CallbackTaskMap"),
("read_only_space", 0x05799): (113, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x057e9): (114, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05839): (115, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x05889): (116, "FinalizationGroupCleanupJobTaskMap"),
("read_only_space", 0x058d9): (117, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05929): (117, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05979): (152, "LoadHandler1Map"),
("read_only_space", 0x059c9): (152, "LoadHandler2Map"),
("read_only_space", 0x05a19): (152, "LoadHandler3Map"),
("read_only_space", 0x05a69): (160, "StoreHandler0Map"),
("read_only_space", 0x05ab9): (160, "StoreHandler1Map"),
("read_only_space", 0x05b09): (160, "StoreHandler2Map"),
("read_only_space", 0x05b59): (160, "StoreHandler3Map"),
("map_space", 0x00139): (1057, "ExternalMap"),
("map_space", 0x00189): (1073, "JSMessageObjectMap"),
}
@ -377,40 +355,29 @@ KNOWN_OBJECTS = {
("read_only_space", 0x00d71): "TerminationException",
("read_only_space", 0x00e19): "OptimizedOut",
("read_only_space", 0x00eb9): "StaleRegister",
("read_only_space", 0x026c9): "EmptyEnumCache",
("read_only_space", 0x02731): "EmptyPropertyArray",
("read_only_space", 0x02741): "EmptyByteArray",
("read_only_space", 0x02751): "EmptyObjectBoilerplateDescription",
("read_only_space", 0x02769): "EmptyArrayBoilerplateDescription",
("read_only_space", 0x027d1): "EmptyClosureFeedbackCellArray",
("read_only_space", 0x027e1): "EmptyFixedUint8Array",
("read_only_space", 0x02801): "EmptyFixedInt8Array",
("read_only_space", 0x02821): "EmptyFixedUint16Array",
("read_only_space", 0x02841): "EmptyFixedInt16Array",
("read_only_space", 0x02861): "EmptyFixedUint32Array",
("read_only_space", 0x02881): "EmptyFixedInt32Array",
("read_only_space", 0x028a1): "EmptyFixedFloat32Array",
("read_only_space", 0x028c1): "EmptyFixedFloat64Array",
("read_only_space", 0x028e1): "EmptyFixedUint8ClampedArray",
("read_only_space", 0x02901): "EmptyFixedBigUint64Array",
("read_only_space", 0x02921): "EmptyFixedBigInt64Array",
("read_only_space", 0x02941): "EmptySloppyArgumentsElements",
("read_only_space", 0x02961): "EmptySlowElementDictionary",
("read_only_space", 0x029a9): "EmptyOrderedHashMap",
("read_only_space", 0x029d1): "EmptyOrderedHashSet",
("read_only_space", 0x029f9): "EmptyFeedbackMetadata",
("read_only_space", 0x02a09): "EmptyPropertyCell",
("read_only_space", 0x02a31): "EmptyPropertyDictionary",
("read_only_space", 0x02a81): "NoOpInterceptorInfo",
("read_only_space", 0x02b21): "EmptyWeakArrayList",
("read_only_space", 0x02b39): "InfinityValue",
("read_only_space", 0x02b49): "MinusZeroValue",
("read_only_space", 0x02b59): "MinusInfinityValue",
("read_only_space", 0x02b69): "SelfReferenceMarker",
("read_only_space", 0x02bc1): "OffHeapTrampolineRelocationInfo",
("read_only_space", 0x02bd9): "TrampolineTrivialCodeDataContainer",
("read_only_space", 0x02bf1): "TrampolinePromiseRejectionCodeDataContainer",
("read_only_space", 0x02c09): "HashSeed",
("read_only_space", 0x02359): "EmptyEnumCache",
("read_only_space", 0x023c1): "EmptyPropertyArray",
("read_only_space", 0x023d1): "EmptyByteArray",
("read_only_space", 0x023e1): "EmptyObjectBoilerplateDescription",
("read_only_space", 0x023f9): "EmptyArrayBoilerplateDescription",
("read_only_space", 0x02461): "EmptyClosureFeedbackCellArray",
("read_only_space", 0x02471): "EmptySloppyArgumentsElements",
("read_only_space", 0x02491): "EmptySlowElementDictionary",
("read_only_space", 0x024d9): "EmptyOrderedHashMap",
("read_only_space", 0x02501): "EmptyOrderedHashSet",
("read_only_space", 0x02529): "EmptyFeedbackMetadata",
("read_only_space", 0x02539): "EmptyPropertyCell",
("read_only_space", 0x02561): "EmptyPropertyDictionary",
("read_only_space", 0x025b1): "NoOpInterceptorInfo",
("read_only_space", 0x02651): "EmptyWeakArrayList",
("read_only_space", 0x02669): "InfinityValue",
("read_only_space", 0x02679): "MinusZeroValue",
("read_only_space", 0x02689): "MinusInfinityValue",
("read_only_space", 0x02699): "SelfReferenceMarker",
("read_only_space", 0x026f1): "OffHeapTrampolineRelocationInfo",
("read_only_space", 0x02709): "TrampolineTrivialCodeDataContainer",
("read_only_space", 0x02721): "TrampolinePromiseRejectionCodeDataContainer",
("read_only_space", 0x02739): "HashSeed",
("old_space", 0x00139): "ArgumentsIteratorAccessor",
("old_space", 0x001a9): "ArrayLengthAccessor",
("old_space", 0x00219): "BoundFunctionLengthAccessor",