Commit ffe886de authored by ishell's avatar ishell Committed by Commit bot

Support for typed arrays added to Heap::RightTrimFixedArray().

BUG=chromium:472513
LOG=Y

Review URL: https://codereview.chromium.org/1058793002

Cr-Commit-Position: refs/heads/master@{#27586}
parent ce7cc511
......@@ -3525,6 +3525,7 @@ void Heap::AdjustLiveBytes(Address address, int by, InvocationMode mode) {
FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
int elements_to_trim) {
DCHECK(!object->IsFixedTypedArrayBase());
const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
const int bytes_to_trim = elements_to_trim * element_size;
Map* map = object->map();
......@@ -3580,14 +3581,30 @@ void Heap::RightTrimFixedArray<Heap::FROM_MUTATOR>(FixedArrayBase*, int);
template<Heap::InvocationMode mode>
void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
const int bytes_to_trim = elements_to_trim * element_size;
const int len = object->length();
DCHECK(elements_to_trim < len);
int bytes_to_trim;
if (object->IsFixedTypedArrayBase()) {
InstanceType type = object->map()->instance_type();
bytes_to_trim =
FixedTypedArrayBase::TypedArraySize(type, len) -
FixedTypedArrayBase::TypedArraySize(type, len - elements_to_trim);
} else {
const int element_size =
object->IsFixedArray() ? kPointerSize : kDoubleSize;
bytes_to_trim = elements_to_trim * element_size;
}
// For now this trick is only applied to objects in new and paged space.
DCHECK(object->map() != fixed_cow_array_map());
const int len = object->length();
DCHECK(elements_to_trim < len);
if (bytes_to_trim == 0) {
// No need to create filler and update live bytes counters, just initialize
// header of the trimmed array.
object->synchronized_set_length(len - elements_to_trim);
return;
}
// Calculate location of new array end.
Address new_end = object->address() + object->Size() - bytes_to_trim;
......
......@@ -4225,7 +4225,7 @@ void* FixedTypedArrayBase::DataPtr() {
}
int FixedTypedArrayBase::DataSize(InstanceType type) {
int FixedTypedArrayBase::ElementSize(InstanceType type) {
int element_size;
switch (type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
......@@ -4239,7 +4239,12 @@ int FixedTypedArrayBase::DataSize(InstanceType type) {
UNREACHABLE();
return 0;
}
return length() * element_size;
return element_size;
}
int FixedTypedArrayBase::DataSize(InstanceType type) {
return length() * ElementSize(type);
}
......@@ -4258,6 +4263,11 @@ int FixedTypedArrayBase::TypedArraySize(InstanceType type) {
}
int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
}
uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
......
......@@ -4880,6 +4880,7 @@ class FixedTypedArrayBase: public FixedArrayBase {
inline int size();
static inline int TypedArraySize(InstanceType type, int length);
inline int TypedArraySize(InstanceType type);
// Use with care: returns raw pointer into heap.
......@@ -4888,6 +4889,8 @@ class FixedTypedArrayBase: public FixedArrayBase {
inline int DataSize();
private:
static inline int ElementSize(InstanceType type);
inline int DataSize(InstanceType type);
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
......
......@@ -5312,3 +5312,54 @@ TEST(WritableVsImmortalRoots) {
CHECK(!immortal || !writable);
}
}
static void TestRightTrimFixedTypedArray(v8::ExternalArrayType type,
int initial_length,
int elements_to_trim) {
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Heap* heap = isolate->heap();
Handle<FixedTypedArrayBase> array =
factory->NewFixedTypedArray(initial_length, type);
int old_size = array->size();
heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, elements_to_trim);
// Check that free space filler is at the right place and did not smash the
// array header.
CHECK(array->IsFixedArrayBase());
CHECK_EQ(initial_length - elements_to_trim, array->length());
int new_size = array->size();
if (new_size != old_size) {
// Free space filler should be created in this case.
Address next_obj_address = array->address() + array->size();
CHECK(HeapObject::FromAddress(next_obj_address)->IsFiller());
}
heap->CollectAllAvailableGarbage();
}
TEST(Regress472513) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
// The combination of type/initial_length/elements_to_trim triggered
// typed array header smashing with free space filler (crbug/472513).
// 64-bit cases.
TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 32, 6);
TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 32 - 7, 6);
TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 16, 6);
TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 16 - 3, 6);
TestRightTrimFixedTypedArray(v8::kExternalUint32Array, 8, 6);
TestRightTrimFixedTypedArray(v8::kExternalUint32Array, 8 - 1, 6);
// 32-bit cases.
TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 16, 3);
TestRightTrimFixedTypedArray(v8::kExternalUint8Array, 16 - 3, 3);
TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 8, 3);
TestRightTrimFixedTypedArray(v8::kExternalUint16Array, 8 - 1, 3);
TestRightTrimFixedTypedArray(v8::kExternalUint32Array, 4, 3);
}
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