LayoutDescriptor should inherit from JSTypedArray

It can't just inherit from a FixedTypedArray-like type, as we soon
assume that a FixedTypedArray-like type is always held by an
ArrayBufferView-like type

BUG=v8:3996
R=ishell@chromium.org,verwaest@chromium.org
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#27964}
This commit is contained in:
jochen 2015-04-21 06:07:32 -07:00 committed by Commit bot
parent d04aee2482
commit 6d79ceb294
8 changed files with 137 additions and 20 deletions

View File

@ -1825,9 +1825,38 @@ size_t GetExternalArrayElementSize(ExternalArrayType type) {
case kExternal##Type##Array: \
return size;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
UNREACHABLE();
return 0;
}
#undef TYPED_ARRAY_CASE
}
size_t GetFixedTypedArraysElementSize(ElementsKind kind) {
switch (kind) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case TYPE##_ELEMENTS: \
return size;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
UNREACHABLE();
return 0;
}
#undef TYPED_ARRAY_CASE
}
ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
switch (kind) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case TYPE##_ELEMENTS: \
return kExternal##Type##Array;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
UNREACHABLE();
return kExternalInt8Array;
}
UNREACHABLE();
return 0;
#undef TYPED_ARRAY_CASE
}
@ -1849,6 +1878,23 @@ JSFunction* GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) {
}
JSFunction* GetTypedArrayFun(ElementsKind elements_kind, Isolate* isolate) {
Context* native_context = isolate->context()->native_context();
switch (elements_kind) {
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype, size) \
case TYPE##_ELEMENTS: \
return native_context->type##_array_fun();
TYPED_ARRAYS(TYPED_ARRAY_FUN)
#undef TYPED_ARRAY_FUN
default:
UNREACHABLE();
return NULL;
}
}
void SetupArrayBufferView(i::Isolate* isolate,
i::Handle<i::JSArrayBufferView> obj,
i::Handle<i::JSArrayBuffer> buffer,
@ -1890,6 +1936,16 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type) {
}
Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind) {
Handle<JSFunction> typed_array_fun_handle(
GetTypedArrayFun(elements_kind, isolate()));
CALL_HEAP_FUNCTION(
isolate(), isolate()->heap()->AllocateJSObject(*typed_array_fun_handle),
JSTypedArray);
}
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
Handle<JSArrayBuffer> buffer,
size_t byte_offset,
@ -1918,6 +1974,35 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
}
Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
size_t number_of_elements) {
Handle<JSTypedArray> obj = NewJSTypedArray(elements_kind);
size_t element_size = GetFixedTypedArraysElementSize(elements_kind);
ExternalArrayType array_type = GetArrayTypeFromElementsKind(elements_kind);
CHECK(number_of_elements <=
(std::numeric_limits<size_t>::max() / element_size));
CHECK(number_of_elements <= static_cast<size_t>(Smi::kMaxValue));
size_t byte_length = number_of_elements * element_size;
obj->set_byte_offset(Smi::FromInt(0));
i::Handle<i::Object> byte_length_object =
isolate()->factory()->NewNumberFromSize(byte_length);
obj->set_byte_length(*byte_length_object);
Handle<Object> length_object = NewNumberFromSize(number_of_elements);
obj->set_length(*length_object);
obj->set_buffer(Smi::FromInt(0));
obj->set_weak_next(isolate()->heap()->undefined_value());
Handle<FixedTypedArrayBase> elements =
isolate()->factory()->NewFixedTypedArray(
static_cast<int>(number_of_elements), array_type);
obj->set_elements(*elements);
return obj;
}
Handle<JSDataView> Factory::NewJSDataView(Handle<JSArrayBuffer> buffer,
size_t byte_offset,
size_t byte_length) {

View File

@ -448,11 +448,17 @@ class Factory final {
Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type);
Handle<JSTypedArray> NewJSTypedArray(ElementsKind elements_kind);
// Creates a new JSTypedArray with the specified buffer.
Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type,
Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t length);
// Creates a new on-heap JSTypedArray.
Handle<JSTypedArray> NewJSTypedArray(ElementsKind elements_kind,
size_t number_of_elements);
Handle<JSDataView> NewJSDataView();
Handle<JSDataView> NewJSDataView(Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t byte_length);

View File

@ -22,7 +22,7 @@ Handle<LayoutDescriptor> LayoutDescriptor::New(Isolate* isolate, int length) {
}
length = GetSlowModeBackingStoreLength(length);
return Handle<LayoutDescriptor>::cast(
isolate->factory()->NewFixedTypedArray(length, kExternalUint32Array));
isolate->factory()->NewJSTypedArray(UINT32_ELEMENTS, length));
}
@ -48,7 +48,7 @@ bool LayoutDescriptor::GetIndexes(int field_index, int* layout_word_index,
}
*layout_word_index = field_index / kNumberOfBits;
CHECK((!IsSmi() && (*layout_word_index < length())) ||
CHECK((!IsSmi() && (*layout_word_index < Smi::cast(length())->value())) ||
(IsSmi() && (*layout_word_index < 1)));
*layout_bit_index = field_index % kNumberOfBits;
@ -123,7 +123,21 @@ bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); }
int LayoutDescriptor::capacity() {
return IsSlowLayout() ? (length() * kNumberOfBits) : kSmiValueSize;
return IsSlowLayout() ? (Smi::cast(length())->value() * kNumberOfBits)
: kSmiValueSize;
}
uint32_t LayoutDescriptor::get_scalar(int index) {
DCHECK(IsSlowLayout());
return FixedTypedArray<Uint32ArrayTraits>::cast(elements())
->get_scalar(index);
}
void LayoutDescriptor::set(int index, uint32_t value) {
DCHECK(IsSlowLayout());
FixedTypedArray<Uint32ArrayTraits>::cast(elements())->set(index, value);
}

View File

@ -106,8 +106,12 @@ Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
DCHECK(new_layout_descriptor->IsSlowLayout());
if (layout_descriptor->IsSlowLayout()) {
memcpy(new_layout_descriptor->DataPtr(), layout_descriptor->DataPtr(),
layout_descriptor->DataSize());
DisallowHeapAllocation no_gc;
Handle<FixedTypedArrayBase> elements(
FixedTypedArrayBase::cast(layout_descriptor->elements()));
Handle<FixedTypedArrayBase> new_elements(
FixedTypedArrayBase::cast(new_layout_descriptor->elements()));
memcpy(new_elements->DataPtr(), elements->DataPtr(), elements->DataSize());
return new_layout_descriptor;
} else {
// Fast layout.
@ -150,7 +154,7 @@ bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length,
// This is a contiguous sequence till the end of current word, proceed
// counting in the subsequent words.
if (IsSlowLayout()) {
int len = length();
int len = Smi::cast(length())->value();
++layout_word_index;
for (; layout_word_index < len; layout_word_index++) {
value = get_scalar(layout_word_index);
@ -241,13 +245,20 @@ LayoutDescriptor* LayoutDescriptor::Trim(Heap* heap, Map* map,
// Trim, clean and reinitialize this slow-mode layout descriptor.
int array_length = GetSlowModeBackingStoreLength(layout_descriptor_length);
int current_length = length();
int current_length = Smi::cast(length())->value();
if (current_length != array_length) {
DCHECK_LT(array_length, current_length);
int delta = current_length - array_length;
heap->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(this, delta);
heap->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(elements(), delta);
set_byte_length(Smi::FromInt(array_length * 4));
set_length(Smi::FromInt(array_length));
}
{
DisallowHeapAllocation no_gc;
Handle<FixedTypedArrayBase> fixed_array(
FixedTypedArrayBase::cast(elements()));
memset(fixed_array->DataPtr(), 0, fixed_array->DataSize());
}
memset(DataPtr(), 0, DataSize());
LayoutDescriptor* layout_descriptor =
Initialize(this, map, descriptors, num_descriptors);
DCHECK_EQ(this, layout_descriptor);

View File

@ -22,7 +22,7 @@ namespace internal {
// of the descriptor then the field is also considered tagged.
// Once a layout descriptor is created it is allowed only to append properties
// to it.
class LayoutDescriptor : public FixedTypedArray<Uint32ArrayTraits> {
class LayoutDescriptor : public JSTypedArray {
public:
V8_INLINE bool IsTagged(int field_index);
@ -89,6 +89,9 @@ class LayoutDescriptor : public FixedTypedArray<Uint32ArrayTraits> {
// Capacity of layout descriptors in bits.
V8_INLINE int capacity();
V8_INLINE uint32_t get_scalar(int index);
V8_INLINE void set(int index, uint32_t value);
static Handle<LayoutDescriptor> NewForTesting(Isolate* isolate, int length);
LayoutDescriptor* SetTaggedForTesting(int field_index, bool tagged);

View File

@ -716,9 +716,7 @@ bool Object::IsDescriptorArray() const {
bool Object::IsArrayList() const { return IsFixedArray(); }
bool Object::IsLayoutDescriptor() const {
return IsSmi() || IsFixedTypedArrayBase();
}
bool Object::IsLayoutDescriptor() const { return IsSmi() || IsJSTypedArray(); }
bool Object::IsTransitionArray() const {

View File

@ -1065,7 +1065,7 @@ void LayoutDescriptor::Print(std::ostream& os) { // NOLINT
PrintBitMask(os, static_cast<uint32_t>(Smi::cast(this)->value()));
} else {
os << "slow";
int len = length();
int len = Smi::cast(length())->value();
for (int i = 0; i < len; i++) {
if (i > 0) os << " |";
PrintBitMask(os, get_scalar(i));

View File

@ -581,7 +581,7 @@ TEST(LayoutDescriptorCreateNewSlow) {
LayoutDescriptor* layout_desc = *layout_descriptor;
CHECK_EQ(layout_desc, LayoutDescriptor::cast(layout_desc));
CHECK_EQ(layout_desc, LayoutDescriptor::cast_gc_safe(layout_desc));
CHECK(layout_descriptor->IsFixedTypedArrayBase());
CHECK(layout_descriptor->IsJSTypedArray());
// Now make it look like a forwarding pointer to layout_descriptor_copy.
MapWord map_word = layout_desc->map_word();
CHECK(!map_word.IsForwardingAddress());
@ -935,7 +935,7 @@ TEST(DescriptorArrayTrimming) {
CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true));
CHECK(map->layout_descriptor()->IsSlowLayout());
CHECK(map->owns_descriptors());
CHECK_EQ(2, map->layout_descriptor()->length());
CHECK_EQ(2, Smi::cast(map->layout_descriptor()->length())->value());
{
// Add transitions to double fields.
@ -954,7 +954,7 @@ TEST(DescriptorArrayTrimming) {
CHECK_EQ(map->layout_descriptor(), tmp_map->layout_descriptor());
}
CHECK(map->layout_descriptor()->IsSlowLayout());
CHECK_EQ(4, map->layout_descriptor()->length());
CHECK_EQ(4, Smi::cast(map->layout_descriptor()->length())->value());
// The unused tail of the layout descriptor is now "durty" because of sharing.
CHECK(map->layout_descriptor()->IsConsistentWithMap(*map));
@ -974,7 +974,7 @@ TEST(DescriptorArrayTrimming) {
CHECK_EQ(map->NumberOfOwnDescriptors(),
map->instance_descriptors()->number_of_descriptors());
CHECK(map->layout_descriptor()->IsSlowLayout());
CHECK_EQ(2, map->layout_descriptor()->length());
CHECK_EQ(2, Smi::cast(map->layout_descriptor()->length())->value());
{
// Add transitions to tagged fields.