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}
This commit is contained in:
parent
ce7cc5119c
commit
ffe886de48
@ -3525,6 +3525,7 @@ void Heap::AdjustLiveBytes(Address address, int by, InvocationMode mode) {
|
|||||||
|
|
||||||
FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
|
FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
|
||||||
int elements_to_trim) {
|
int elements_to_trim) {
|
||||||
|
DCHECK(!object->IsFixedTypedArrayBase());
|
||||||
const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
|
const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
|
||||||
const int bytes_to_trim = elements_to_trim * element_size;
|
const int bytes_to_trim = elements_to_trim * element_size;
|
||||||
Map* map = object->map();
|
Map* map = object->map();
|
||||||
@ -3580,14 +3581,30 @@ void Heap::RightTrimFixedArray<Heap::FROM_MUTATOR>(FixedArrayBase*, int);
|
|||||||
|
|
||||||
template<Heap::InvocationMode mode>
|
template<Heap::InvocationMode mode>
|
||||||
void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
|
void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
|
||||||
const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
|
const int len = object->length();
|
||||||
const int bytes_to_trim = elements_to_trim * element_size;
|
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.
|
// For now this trick is only applied to objects in new and paged space.
|
||||||
DCHECK(object->map() != fixed_cow_array_map());
|
DCHECK(object->map() != fixed_cow_array_map());
|
||||||
|
|
||||||
const int len = object->length();
|
if (bytes_to_trim == 0) {
|
||||||
DCHECK(elements_to_trim < len);
|
// 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.
|
// Calculate location of new array end.
|
||||||
Address new_end = object->address() + object->Size() - bytes_to_trim;
|
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;
|
int element_size;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||||
@ -4239,7 +4239,12 @@ int FixedTypedArrayBase::DataSize(InstanceType type) {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return 0;
|
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; }
|
uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -4880,6 +4880,7 @@ class FixedTypedArrayBase: public FixedArrayBase {
|
|||||||
|
|
||||||
inline int size();
|
inline int size();
|
||||||
|
|
||||||
|
static inline int TypedArraySize(InstanceType type, int length);
|
||||||
inline int TypedArraySize(InstanceType type);
|
inline int TypedArraySize(InstanceType type);
|
||||||
|
|
||||||
// Use with care: returns raw pointer into heap.
|
// Use with care: returns raw pointer into heap.
|
||||||
@ -4888,6 +4889,8 @@ class FixedTypedArrayBase: public FixedArrayBase {
|
|||||||
inline int DataSize();
|
inline int DataSize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static inline int ElementSize(InstanceType type);
|
||||||
|
|
||||||
inline int DataSize(InstanceType type);
|
inline int DataSize(InstanceType type);
|
||||||
|
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
|
||||||
|
@ -5312,3 +5312,54 @@ TEST(WritableVsImmortalRoots) {
|
|||||||
CHECK(!immortal || !writable);
|
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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user