Commit 6d79ceb2 authored by jochen's avatar jochen Committed by Commit bot

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}
parent d04aee24
...@@ -1825,9 +1825,38 @@ size_t GetExternalArrayElementSize(ExternalArrayType type) { ...@@ -1825,9 +1825,38 @@ size_t GetExternalArrayElementSize(ExternalArrayType type) {
case kExternal##Type##Array: \ case kExternal##Type##Array: \
return size; return size;
TYPED_ARRAYS(TYPED_ARRAY_CASE) 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 #undef TYPED_ARRAY_CASE
} }
...@@ -1849,6 +1878,23 @@ JSFunction* GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) { ...@@ -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, void SetupArrayBufferView(i::Isolate* isolate,
i::Handle<i::JSArrayBufferView> obj, i::Handle<i::JSArrayBufferView> obj,
i::Handle<i::JSArrayBuffer> buffer, i::Handle<i::JSArrayBuffer> buffer,
...@@ -1890,6 +1936,16 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type) { ...@@ -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<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
Handle<JSArrayBuffer> buffer, Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t byte_offset,
...@@ -1918,6 +1974,35 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type, ...@@ -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, Handle<JSDataView> Factory::NewJSDataView(Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t byte_offset,
size_t byte_length) { size_t byte_length) {
......
...@@ -448,11 +448,17 @@ class Factory final { ...@@ -448,11 +448,17 @@ class Factory final {
Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type); Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type);
Handle<JSTypedArray> NewJSTypedArray(ElementsKind elements_kind);
// Creates a new JSTypedArray with the specified buffer. // Creates a new JSTypedArray with the specified buffer.
Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type, Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type,
Handle<JSArrayBuffer> buffer, Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t length); 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<JSDataView> NewJSDataView(Handle<JSArrayBuffer> buffer, Handle<JSDataView> NewJSDataView(Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t byte_length); size_t byte_offset, size_t byte_length);
......
...@@ -22,7 +22,7 @@ Handle<LayoutDescriptor> LayoutDescriptor::New(Isolate* isolate, int length) { ...@@ -22,7 +22,7 @@ Handle<LayoutDescriptor> LayoutDescriptor::New(Isolate* isolate, int length) {
} }
length = GetSlowModeBackingStoreLength(length); length = GetSlowModeBackingStoreLength(length);
return Handle<LayoutDescriptor>::cast( 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, ...@@ -48,7 +48,7 @@ bool LayoutDescriptor::GetIndexes(int field_index, int* layout_word_index,
} }
*layout_word_index = field_index / kNumberOfBits; *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))); (IsSmi() && (*layout_word_index < 1)));
*layout_bit_index = field_index % kNumberOfBits; *layout_bit_index = field_index % kNumberOfBits;
...@@ -123,7 +123,21 @@ bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); } ...@@ -123,7 +123,21 @@ bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); }
int LayoutDescriptor::capacity() { 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);
} }
......
...@@ -106,8 +106,12 @@ Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity( ...@@ -106,8 +106,12 @@ Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
DCHECK(new_layout_descriptor->IsSlowLayout()); DCHECK(new_layout_descriptor->IsSlowLayout());
if (layout_descriptor->IsSlowLayout()) { if (layout_descriptor->IsSlowLayout()) {
memcpy(new_layout_descriptor->DataPtr(), layout_descriptor->DataPtr(), DisallowHeapAllocation no_gc;
layout_descriptor->DataSize()); 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; return new_layout_descriptor;
} else { } else {
// Fast layout. // Fast layout.
...@@ -150,7 +154,7 @@ bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length, ...@@ -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 // This is a contiguous sequence till the end of current word, proceed
// counting in the subsequent words. // counting in the subsequent words.
if (IsSlowLayout()) { if (IsSlowLayout()) {
int len = length(); int len = Smi::cast(length())->value();
++layout_word_index; ++layout_word_index;
for (; layout_word_index < len; layout_word_index++) { for (; layout_word_index < len; layout_word_index++) {
value = get_scalar(layout_word_index); value = get_scalar(layout_word_index);
...@@ -241,13 +245,20 @@ LayoutDescriptor* LayoutDescriptor::Trim(Heap* heap, Map* map, ...@@ -241,13 +245,20 @@ LayoutDescriptor* LayoutDescriptor::Trim(Heap* heap, Map* map,
// Trim, clean and reinitialize this slow-mode layout descriptor. // Trim, clean and reinitialize this slow-mode layout descriptor.
int array_length = GetSlowModeBackingStoreLength(layout_descriptor_length); int array_length = GetSlowModeBackingStoreLength(layout_descriptor_length);
int current_length = length(); int current_length = Smi::cast(length())->value();
if (current_length != array_length) { if (current_length != array_length) {
DCHECK_LT(array_length, current_length); DCHECK_LT(array_length, current_length);
int delta = current_length - array_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 = LayoutDescriptor* layout_descriptor =
Initialize(this, map, descriptors, num_descriptors); Initialize(this, map, descriptors, num_descriptors);
DCHECK_EQ(this, layout_descriptor); DCHECK_EQ(this, layout_descriptor);
......
...@@ -22,7 +22,7 @@ namespace internal { ...@@ -22,7 +22,7 @@ namespace internal {
// of the descriptor then the field is also considered tagged. // of the descriptor then the field is also considered tagged.
// Once a layout descriptor is created it is allowed only to append properties // Once a layout descriptor is created it is allowed only to append properties
// to it. // to it.
class LayoutDescriptor : public FixedTypedArray<Uint32ArrayTraits> { class LayoutDescriptor : public JSTypedArray {
public: public:
V8_INLINE bool IsTagged(int field_index); V8_INLINE bool IsTagged(int field_index);
...@@ -89,6 +89,9 @@ class LayoutDescriptor : public FixedTypedArray<Uint32ArrayTraits> { ...@@ -89,6 +89,9 @@ class LayoutDescriptor : public FixedTypedArray<Uint32ArrayTraits> {
// Capacity of layout descriptors in bits. // Capacity of layout descriptors in bits.
V8_INLINE int capacity(); 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); static Handle<LayoutDescriptor> NewForTesting(Isolate* isolate, int length);
LayoutDescriptor* SetTaggedForTesting(int field_index, bool tagged); LayoutDescriptor* SetTaggedForTesting(int field_index, bool tagged);
......
...@@ -716,9 +716,7 @@ bool Object::IsDescriptorArray() const { ...@@ -716,9 +716,7 @@ bool Object::IsDescriptorArray() const {
bool Object::IsArrayList() const { return IsFixedArray(); } bool Object::IsArrayList() const { return IsFixedArray(); }
bool Object::IsLayoutDescriptor() const { bool Object::IsLayoutDescriptor() const { return IsSmi() || IsJSTypedArray(); }
return IsSmi() || IsFixedTypedArrayBase();
}
bool Object::IsTransitionArray() const { bool Object::IsTransitionArray() const {
......
...@@ -1065,7 +1065,7 @@ void LayoutDescriptor::Print(std::ostream& os) { // NOLINT ...@@ -1065,7 +1065,7 @@ void LayoutDescriptor::Print(std::ostream& os) { // NOLINT
PrintBitMask(os, static_cast<uint32_t>(Smi::cast(this)->value())); PrintBitMask(os, static_cast<uint32_t>(Smi::cast(this)->value()));
} else { } else {
os << "slow"; os << "slow";
int len = length(); int len = Smi::cast(length())->value();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (i > 0) os << " |"; if (i > 0) os << " |";
PrintBitMask(os, get_scalar(i)); PrintBitMask(os, get_scalar(i));
......
...@@ -581,7 +581,7 @@ TEST(LayoutDescriptorCreateNewSlow) { ...@@ -581,7 +581,7 @@ TEST(LayoutDescriptorCreateNewSlow) {
LayoutDescriptor* layout_desc = *layout_descriptor; LayoutDescriptor* layout_desc = *layout_descriptor;
CHECK_EQ(layout_desc, LayoutDescriptor::cast(layout_desc)); CHECK_EQ(layout_desc, LayoutDescriptor::cast(layout_desc));
CHECK_EQ(layout_desc, LayoutDescriptor::cast_gc_safe(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. // Now make it look like a forwarding pointer to layout_descriptor_copy.
MapWord map_word = layout_desc->map_word(); MapWord map_word = layout_desc->map_word();
CHECK(!map_word.IsForwardingAddress()); CHECK(!map_word.IsForwardingAddress());
...@@ -935,7 +935,7 @@ TEST(DescriptorArrayTrimming) { ...@@ -935,7 +935,7 @@ TEST(DescriptorArrayTrimming) {
CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true)); CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true));
CHECK(map->layout_descriptor()->IsSlowLayout()); CHECK(map->layout_descriptor()->IsSlowLayout());
CHECK(map->owns_descriptors()); 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. // Add transitions to double fields.
...@@ -954,7 +954,7 @@ TEST(DescriptorArrayTrimming) { ...@@ -954,7 +954,7 @@ TEST(DescriptorArrayTrimming) {
CHECK_EQ(map->layout_descriptor(), tmp_map->layout_descriptor()); CHECK_EQ(map->layout_descriptor(), tmp_map->layout_descriptor());
} }
CHECK(map->layout_descriptor()->IsSlowLayout()); 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. // The unused tail of the layout descriptor is now "durty" because of sharing.
CHECK(map->layout_descriptor()->IsConsistentWithMap(*map)); CHECK(map->layout_descriptor()->IsConsistentWithMap(*map));
...@@ -974,7 +974,7 @@ TEST(DescriptorArrayTrimming) { ...@@ -974,7 +974,7 @@ TEST(DescriptorArrayTrimming) {
CHECK_EQ(map->NumberOfOwnDescriptors(), CHECK_EQ(map->NumberOfOwnDescriptors(),
map->instance_descriptors()->number_of_descriptors()); map->instance_descriptors()->number_of_descriptors());
CHECK(map->layout_descriptor()->IsSlowLayout()); 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. // Add transitions to tagged fields.
......
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