Commit ad0afdae authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[ubsan] Duplicate FixedArray{,Base} temporarily

In preparation for incrementally migrating subclasses to deriving
from FixedArrayPtr/FixedArrayBasePtr. Once that is done for all
subclasses, this duplication will be dropped again.

Bug: v8:3770
Change-Id: I6d664997fdcb18f7c0f37183d9f920ae30f3b749
Reviewed-on: https://chromium-review.googlesource.com/c/1345325Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57702}
parent a119ed63
......@@ -2046,6 +2046,11 @@ Handle<FixedArray> Factory::CopyFixedArrayWithMap(Handle<FixedArray> array,
Handle<Map> map) {
return CopyArrayWithMap(array, map);
}
// TODO(3770): Replacement for the above, temporarily separate.
Handle<FixedArrayPtr> Factory::CopyFixedArrayWithMap(
Handle<FixedArrayPtr> array, Handle<Map> map) {
return CopyArrayWithMap(array, map);
}
Handle<FixedArray> Factory::CopyFixedArrayAndGrow(Handle<FixedArray> array,
int grow_by,
......
......@@ -513,6 +513,8 @@ class V8_EXPORT_PRIVATE Factory {
Handle<FixedArray> CopyFixedArrayWithMap(Handle<FixedArray> array,
Handle<Map> map);
Handle<FixedArrayPtr> CopyFixedArrayWithMap(Handle<FixedArrayPtr> array,
Handle<Map> map);
Handle<FixedArray> CopyFixedArrayAndGrow(
Handle<FixedArray> array, int grow_by,
......
......@@ -10292,6 +10292,27 @@ Handle<FixedArray> FixedArray::SetAndGrow(Isolate* isolate,
new_array->set(index, *value);
return new_array;
}
Handle<FixedArrayPtr> FixedArrayPtr::SetAndGrow(Isolate* isolate,
Handle<FixedArrayPtr> array,
int index, Handle<Object> value,
PretenureFlag pretenure) {
if (index < array->length()) {
array->set(index, *value);
return array;
}
int capacity = array->length();
do {
capacity = JSObject::NewElementsCapacity(capacity);
} while (capacity <= index);
Handle<FixedArrayPtr> new_array(
isolate->factory()
->NewUninitializedFixedArray(capacity, pretenure)
.location());
array->CopyTo(0, *new_array, 0, array->length());
new_array->FillWithHoles(array->length(), new_array->length());
new_array->set(index, *value);
return new_array;
}
bool FixedArray::ContainsSortedNumbers() {
for (int i = 1; i < length(); ++i) {
......@@ -10306,6 +10327,9 @@ bool FixedArray::ContainsSortedNumbers() {
}
return true;
}
bool FixedArrayPtr::ContainsSortedNumbers() {
return reinterpret_cast<FixedArray*>(ptr())->ContainsSortedNumbers();
}
Handle<FixedArray> FixedArray::ShrinkOrEmpty(Isolate* isolate,
Handle<FixedArray> array,
......@@ -10317,6 +10341,18 @@ Handle<FixedArray> FixedArray::ShrinkOrEmpty(Isolate* isolate,
return array;
}
}
Handle<FixedArrayPtr> FixedArrayPtr::ShrinkOrEmpty(Isolate* isolate,
Handle<FixedArrayPtr> array,
int new_length) {
if (new_length == 0) {
// TODO(3770): Drop type conversion.
return Handle<FixedArrayPtr>(
array->GetReadOnlyRoots().empty_fixed_array_handle().location());
} else {
array->Shrink(isolate, new_length);
return array;
}
}
void FixedArray::Shrink(Isolate* isolate, int new_length) {
DCHECK(0 < new_length && new_length <= length());
......@@ -10324,6 +10360,13 @@ void FixedArray::Shrink(Isolate* isolate, int new_length) {
isolate->heap()->RightTrimFixedArray(this, length() - new_length);
}
}
void FixedArrayPtr::Shrink(Isolate* isolate, int new_length) {
DCHECK(0 < new_length && new_length <= length());
if (new_length < length()) {
isolate->heap()->RightTrimFixedArray(reinterpret_cast<FixedArray*>(ptr()),
length() - new_length);
}
}
void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos,
int len) const {
......@@ -10336,16 +10379,17 @@ void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos,
dest->set(dest_pos+index, get(pos+index), mode);
}
}
#ifdef DEBUG
bool FixedArray::IsEqualTo(FixedArray* other) {
if (length() != other->length()) return false;
for (int i = 0 ; i < length(); ++i) {
if (get(i) != other->get(i)) return false;
void FixedArrayPtr::CopyTo(int pos, FixedArrayPtr dest, int dest_pos,
int len) const {
DisallowHeapAllocation no_gc;
// Return early if len == 0 so that we don't try to read the write barrier off
// a canonical read-only empty fixed array.
if (len == 0) return;
WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
for (int index = 0; index < len; index++) {
dest->set(dest_pos + index, get(pos + index), mode);
}
return true;
}
#endif
void JSObject::PrototypeRegistryCompactionCallback(HeapObject* value,
int old_index,
......
......@@ -18,10 +18,15 @@
namespace v8 {
namespace internal {
OBJECT_CONSTRUCTORS_IMPL(FixedArrayBasePtr, HeapObjectPtr)
OBJECT_CONSTRUCTORS_IMPL(FixedArrayPtr, FixedArrayBasePtr)
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR2(FixedArrayPtr)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR2(FixedArrayBasePtr)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(TemplateList)
......@@ -29,7 +34,9 @@ CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakArrayList)
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SMI_ACCESSORS(FixedArrayBasePtr, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBasePtr, length, kLengthOffset)
SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
......@@ -40,12 +47,18 @@ SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
Object* FixedArrayBase::unchecked_synchronized_length() const {
return ACQUIRE_READ_FIELD(this, kLengthOffset);
}
Object* FixedArrayBasePtr::unchecked_synchronized_length() const {
return ACQUIRE_READ_FIELD(this, kLengthOffset);
}
ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
ObjectSlot FixedArray::GetFirstElementAddress() {
return ObjectSlot(FIELD_ADDR(this, OffsetOfElementAt(0)));
}
ObjectSlot FixedArrayPtr::GetFirstElementAddress() {
return ObjectSlot(FIELD_ADDR(this, OffsetOfElementAt(0)));
}
bool FixedArray::ContainsOnlySmisOrHoles() {
Object* the_hole = GetReadOnlyRoots().the_hole_value();
......@@ -56,15 +69,26 @@ bool FixedArray::ContainsOnlySmisOrHoles() {
}
return true;
}
bool FixedArrayPtr::ContainsOnlySmisOrHoles() {
return reinterpret_cast<FixedArray*>(ptr())->ContainsOnlySmisOrHoles();
}
Object* FixedArray::get(int index) const {
DCHECK(index >= 0 && index < this->length());
return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
}
Object* FixedArrayPtr::get(int index) const {
DCHECK(index >= 0 && index < this->length());
return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
}
Handle<Object> FixedArray::get(FixedArray* array, int index, Isolate* isolate) {
return handle(array->get(index), isolate);
}
Handle<Object> FixedArrayPtr::get(FixedArrayPtr array, int index,
Isolate* isolate) {
return handle(array->get(index), isolate);
}
template <class T>
MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
......@@ -72,6 +96,12 @@ MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
return Handle<T>(T::cast(obj), isolate);
}
template <class T>
MaybeHandle<T> FixedArrayPtr::GetValue(Isolate* isolate, int index) const {
Object* obj = get(index);
if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
return Handle<T>(T::cast(obj), isolate);
}
template <class T>
Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
......@@ -79,10 +109,19 @@ Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
CHECK(!obj->IsUndefined(isolate));
return Handle<T>(T::cast(obj), isolate);
}
template <class T>
Handle<T> FixedArrayPtr::GetValueChecked(Isolate* isolate, int index) const {
Object* obj = get(index);
CHECK(!obj->IsUndefined(isolate));
return Handle<T>(T::cast(obj), isolate);
}
bool FixedArray::is_the_hole(Isolate* isolate, int index) {
return get(index)->IsTheHole(isolate);
}
bool FixedArrayPtr::is_the_hole(Isolate* isolate, int index) {
return get(index)->IsTheHole(isolate);
}
void FixedArray::set(int index, Smi value) {
DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
......@@ -91,6 +130,9 @@ void FixedArray::set(int index, Smi value) {
int offset = kHeaderSize + index * kPointerSize;
RELAXED_WRITE_FIELD(this, offset, value);
}
void FixedArrayPtr::set(int index, Smi value) {
reinterpret_cast<FixedArray*>(ptr())->set(index, value);
}
void FixedArray::set(int index, Object* value) {
DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
......@@ -101,6 +143,9 @@ void FixedArray::set(int index, Object* value) {
RELAXED_WRITE_FIELD(this, offset, value);
WRITE_BARRIER(this, offset, value);
}
void FixedArrayPtr::set(int index, Object* value) {
reinterpret_cast<FixedArray*>(ptr())->set(index, value);
}
void FixedArray::set(int index, Object* value, WriteBarrierMode mode) {
DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
......@@ -110,6 +155,9 @@ void FixedArray::set(int index, Object* value, WriteBarrierMode mode) {
RELAXED_WRITE_FIELD(this, offset, value);
CONDITIONAL_WRITE_BARRIER(this, offset, value, mode);
}
void FixedArrayPtr::set(int index, Object* value, WriteBarrierMode mode) {
reinterpret_cast<FixedArray*>(ptr())->set(index, value, mode);
}
void FixedArray::NoWriteBarrierSet(FixedArray* array, int index,
Object* value) {
......@@ -119,24 +167,44 @@ void FixedArray::NoWriteBarrierSet(FixedArray* array, int index,
DCHECK(!Heap::InNewSpace(value));
RELAXED_WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
}
void FixedArrayPtr::NoWriteBarrierSet(FixedArrayPtr array, int index,
Object* value) {
DCHECK_NE(array->map(), array->GetReadOnlyRoots().fixed_cow_array_map());
DCHECK_GE(index, 0);
DCHECK_LT(index, array->length());
DCHECK(!Heap::InNewSpace(value));
RELAXED_WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
}
void FixedArray::set_undefined(int index) {
set_undefined(GetReadOnlyRoots(), index);
}
void FixedArrayPtr::set_undefined(int index) {
reinterpret_cast<FixedArray*>(ptr())->set_undefined(index);
}
void FixedArray::set_undefined(Isolate* isolate, int index) {
set_undefined(ReadOnlyRoots(isolate), index);
}
void FixedArrayPtr::set_undefined(Isolate* isolate, int index) {
reinterpret_cast<FixedArray*>(ptr())->set_undefined(isolate, index);
}
void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
FixedArray::NoWriteBarrierSet(this, index, ro_roots.undefined_value());
}
void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
void FixedArrayPtr::set_null(int index) {
reinterpret_cast<FixedArray*>(ptr())->set_null(index);
}
void FixedArray::set_null(Isolate* isolate, int index) {
set_null(ReadOnlyRoots(isolate), index);
}
void FixedArrayPtr::set_null(Isolate* isolate, int index) {
reinterpret_cast<FixedArray*>(ptr())->set_null(isolate, index);
}
void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
FixedArray::NoWriteBarrierSet(this, index, ro_roots.null_value());
......@@ -145,10 +213,16 @@ void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
void FixedArray::set_the_hole(int index) {
set_the_hole(GetReadOnlyRoots(), index);
}
void FixedArrayPtr::set_the_hole(int index) {
reinterpret_cast<FixedArray*>(ptr())->set_the_hole(index);
}
void FixedArray::set_the_hole(Isolate* isolate, int index) {
set_the_hole(ReadOnlyRoots(isolate), index);
}
void FixedArrayPtr::set_the_hole(Isolate* isolate, int index) {
reinterpret_cast<FixedArray*>(ptr())->set_the_hole(isolate, index);
}
void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
FixedArray::NoWriteBarrierSet(this, index, ro_roots.the_hole_value());
......@@ -159,20 +233,37 @@ void FixedArray::FillWithHoles(int from, int to) {
set_the_hole(i);
}
}
void FixedArrayPtr::FillWithHoles(int from, int to) {
for (int i = from; i < to; i++) {
set_the_hole(i);
}
}
ObjectSlot FixedArray::data_start() {
return HeapObject::RawField(this, OffsetOfElementAt(0));
}
ObjectSlot FixedArrayPtr::data_start() {
return RawField(OffsetOfElementAt(0));
}
ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
return HeapObject::RawField(this, OffsetOfElementAt(index));
}
ObjectSlot FixedArrayPtr::RawFieldOfElementAt(int index) {
return RawField(OffsetOfElementAt(index));
}
void FixedArray::MoveElements(Heap* heap, int dst_index, int src_index, int len,
WriteBarrierMode mode) {
DisallowHeapAllocation no_gc;
heap->MoveElements(this, dst_index, src_index, len, mode);
}
void FixedArrayPtr::MoveElements(Heap* heap, int dst_index, int src_index,
int len, WriteBarrierMode mode) {
DisallowHeapAllocation no_gc;
heap->MoveElements(reinterpret_cast<FixedArray*>(ptr()), dst_index, src_index,
len, mode);
}
double FixedDoubleArray::get_scalar(int index) {
DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
......
......@@ -102,6 +102,43 @@ class FixedArrayBase : public HeapObject {
static const int kHeaderSize = kLengthOffset + kPointerSize;
};
// TODO(3770): Replacement for the above.
class FixedArrayBasePtr : public HeapObjectPtr {
public:
// [length]: length of the array.
inline int length() const;
inline void set_length(int value);
// Get and set the length using acquire loads and release stores.
inline int synchronized_length() const;
inline void synchronized_set_length(int value);
inline Object* unchecked_synchronized_length() const;
// TODO(3770): Temporary.
operator FixedArrayBase*() const {
return reinterpret_cast<FixedArrayBase*>(ptr());
}
DECL_CAST2(FixedArrayBasePtr)
// Maximal allowed size, in bytes, of a single FixedArrayBase.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
#ifdef V8_HOST_ARCH_32_BIT
static const int kMaxSize = 512 * MB;
#else
static const int kMaxSize = 1024 * MB;
#endif // V8_HOST_ARCH_32_BIT
// Layout description.
// Length is smi tagged when it is stored.
static const int kLengthOffset = FixedArrayBase::kLengthOffset;
static const int kHeaderSize = FixedArrayBase::kHeaderSize;
OBJECT_CONSTRUCTORS(FixedArrayBasePtr, HeapObjectPtr)
};
// FixedArray describes fixed-sized arrays with element type Object*.
class FixedArray : public FixedArrayBase {
public:
......@@ -187,10 +224,6 @@ class FixedArray : public FixedArrayBase {
// Dispatched behavior.
DECL_PRINTER(FixedArray)
DECL_VERIFIER(FixedArray)
#ifdef DEBUG
// Checks if two FixedArrays have identical contents.
bool IsEqualTo(FixedArray* other);
#endif
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
......@@ -210,6 +243,105 @@ class FixedArray : public FixedArrayBase {
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
};
// TODO(3770): Replacement for the above.
class FixedArrayPtr : public FixedArrayBasePtr {
public:
// TODO(3770): Temporary.
operator FixedArray*() const { return reinterpret_cast<FixedArray*>(ptr()); }
// Setter and getter for elements.
inline Object* get(int index) const;
static inline Handle<Object> get(FixedArrayPtr array, int index,
Isolate* isolate);
template <class T>
MaybeHandle<T> GetValue(Isolate* isolate, int index) const;
template <class T>
Handle<T> GetValueChecked(Isolate* isolate, int index) const;
// Return a grown copy if the index is bigger than the array's length.
static Handle<FixedArrayPtr> SetAndGrow(
Isolate* isolate, Handle<FixedArrayPtr> array, int index,
Handle<Object> value, PretenureFlag pretenure = NOT_TENURED);
// Setter that uses write barrier.
inline void set(int index, Object* value);
inline bool is_the_hole(Isolate* isolate, int index);
// Setter that doesn't need write barrier.
inline void set(int index, Smi value);
// Setter with explicit barrier mode.
inline void set(int index, Object* value, WriteBarrierMode mode);
// Setters for frequently used oddballs located in old space.
inline void set_undefined(int index);
inline void set_undefined(Isolate* isolate, int index);
inline void set_null(int index);
inline void set_null(Isolate* isolate, int index);
inline void set_the_hole(int index);
inline void set_the_hole(Isolate* isolate, int index);
inline ObjectSlot GetFirstElementAddress();
inline bool ContainsOnlySmisOrHoles();
// Returns true iff the elements are Numbers and sorted ascending.
bool ContainsSortedNumbers();
// Gives access to raw memory which stores the array's data.
inline ObjectSlot data_start();
inline void MoveElements(Heap* heap, int dst_index, int src_index, int len,
WriteBarrierMode mode);
inline void FillWithHoles(int from, int to);
// Shrink the array and insert filler objects. {new_length} must be > 0.
void Shrink(Isolate* isolate, int new_length);
// If {new_length} is 0, return the canonical empty FixedArray. Otherwise
// like above.
static Handle<FixedArrayPtr> ShrinkOrEmpty(Isolate* isolate,
Handle<FixedArrayPtr> array,
int new_length);
// Copy a sub array from the receiver to dest.
void CopyTo(int pos, FixedArrayPtr dest, int dest_pos, int len) const;
// Garbage collection support.
static constexpr int SizeFor(int length) {
return kHeaderSize + length * kPointerSize;
}
// Code Generation support.
static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); }
// Garbage collection support.
inline ObjectSlot RawFieldOfElementAt(int index);
DECL_CAST2(FixedArrayPtr)
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
static_assert(Internals::IsValidSmi(kMaxLength),
"FixedArray maxLength not a Smi");
// Maximally allowed length for regular (non large object space) object.
STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
static const int kMaxRegularLength =
(kMaxRegularHeapObjectSize - kHeaderSize) / kPointerSize;
// Dispatched behavior.
DECL_PRINTER(FixedArrayPtr)
DECL_VERIFIER(FixedArrayPtr)
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
static inline void NoWriteBarrierSet(FixedArrayPtr array, int index,
Object* value);
OBJECT_CONSTRUCTORS(FixedArrayPtr, FixedArrayBasePtr)
};
// FixedArray alias added only because of IsFixedArrayExact() predicate, which
// checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
// check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
......
......@@ -46,6 +46,13 @@ STRUCT_LIST(TYPE_CHECK_FORWARDER)
ODDBALL_LIST(TYPE_CHECK_FORWARDER)
#undef TYPE_CHECK_FORWARDER
bool ObjectPtr::IsFixedArrayBasePtr() const {
return reinterpret_cast<Object*>(ptr())->IsFixedArrayBase();
}
bool ObjectPtr::IsFixedArrayPtr() const {
return reinterpret_cast<Object*>(ptr())->IsFixedArray();
}
double ObjectPtr::Number() const {
return reinterpret_cast<Object*>(ptr())->Number();
}
......
......@@ -57,6 +57,10 @@ class ObjectPtr {
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
#undef IS_TYPE_FUNCTION_DECL
// TODO(3770): Drop these after migrating the respective classes:
inline bool IsFixedArrayBasePtr() const;
inline bool IsFixedArrayPtr() const;
inline bool IsObject() const { return true; }
inline double Number() const;
inline bool ToInt32(int32_t* value) const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment