Reland "[typedarray] Move external/data pointer to JSTypedArray."
This is a reland of 4b86fea530
with
copy&paste typo in CodeStubAssembler::AllocateByteArray() fixed
(bug led to holes in new space, which was crashing reproducibly
on the ia32 bot).
Original change's description:
> [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}
Tbr: petermarshall@chromium.org
Bug: chromium:951196, chromium:965583, v8:4153, v8:7881, v8:9183
Change-Id: I87fcdb28532c5f08cc227332a4d59546cb423810
Cq-Include-Trybots: luci.chromium.try:linux-rel, win7-rel
Cq-Include-Trybots: luci.v8.try:v8_linux_shared_compile_rel
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1631592
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61864}
This commit is contained in:
parent
d4968875f5
commit
70bd7cf0ef
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -538,16 +538,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>';
|
||||
@ -616,8 +609,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
|
||||
@ -635,16 +627,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
|
||||
@ -751,7 +742,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';
|
||||
@ -960,18 +951,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
|
||||
@ -983,6 +962,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:
|
||||
@ -1025,8 +1006,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';
|
||||
@ -1035,8 +1016,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:
|
||||
@ -1443,7 +1422,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;
|
||||
@ -1826,12 +1804,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;
|
||||
@ -2295,6 +2267,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));
|
||||
|
||||
@ -2309,8 +2283,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):
|
||||
@ -2714,7 +2688,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;
|
||||
|
@ -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);
|
||||
|
@ -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)),
|
||||
¬_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)),
|
||||
¬_float_or_clamped, &invalid);
|
||||
|
||||
BIND(&invalid);
|
||||
@ -86,7 +84,7 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray(
|
||||
}
|
||||
|
||||
BIND(¬_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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
ByteArray::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");
|
||||
@ -4906,8 +4931,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);
|
||||
@ -6595,8 +6620,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(
|
||||
@ -6608,16 +6642,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);
|
||||
}
|
||||
@ -10365,7 +10389,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)));
|
||||
@ -10417,7 +10466,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) {
|
||||
@ -10505,24 +10554,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) {
|
||||
@ -10556,34 +10587,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,
|
||||
@ -10602,7 +10605,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
|
||||
@ -10636,21 +10639,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);
|
||||
|
@ -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);
|
||||
@ -3035,20 +3038,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).
|
||||
@ -3276,6 +3271,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);
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -2590,9 +2590,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
|
||||
@ -2916,7 +2916,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;
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -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()));
|
||||
|
@ -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,
|
||||
|
10
src/ic/ic.cc
10
src/ic/ic.cc
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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_),
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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.
|
||||
|
14
test/mjsunit/regress/regress-v8-4153-1.js
Normal file
14
test/mjsunit/regress/regress-v8-4153-1.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --verify-heap
|
||||
|
||||
// Create tiny (on-heap) instances of TypedArrays to make sure
|
||||
// that the ByteArrays are properly sized (in new space).
|
||||
var arrays = [
|
||||
Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array,
|
||||
Float32Array, Float64Array, Uint8ClampedArray, BigInt64Array, BigUint64Array
|
||||
].map(C => {
|
||||
new C(1)
|
||||
});
|
@ -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> {};
|
||||
|
@ -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',
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user