LayoutDescriptor should inherit from JSTypedArray
authorjochen <jochen@chromium.org>
Tue, 21 Apr 2015 13:07:32 +0000 (06:07 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 21 Apr 2015 13:07:14 +0000 (13:07 +0000)
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}

src/factory.cc
src/factory.h
src/layout-descriptor-inl.h
src/layout-descriptor.cc
src/layout-descriptor.h
src/objects-inl.h
src/objects-printer.cc
test/cctest/test-unboxed-doubles.cc

index eda7cdda84e18fc2d18fa1479cbdc986c68217bc..1047711b657b1de128488ef04e152c0a7d7f7e18 100644 (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) {
index 87ec2e6e701b9e7bc4125e170d5f556eaab71ca5..72991d9bf0ca7ef405c170a6f19029a5a2f3305f 100644 (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);
index ba76704d5fc1f5c8883838a61de046268129c0d9..c7b0f71dac7873e96e6dc3954254890c1250633a 100644 (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);
 }
 
 
index 66a1f0fb07950404a4d36c9bca9b5c4a6be15014..312429f0c6d40a63811f9fafdfd045e2e1aaaba6 100644 (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);
index 0a14f53198f5c4fd48dd78b28d4b33d5d8792526..b68decfa418cf7af344bb823b7e965a6c27453a6 100644 (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);
 
index 5f3d0747e6a5b4c5aa337c01d89fc72ca86e21c2..8ff7866f0a08b325a02cc93e012736c2bbdc89df 100644 (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 {
index cb3f27a79b0e3f8ece986a4df7bbad7d991863fe..6e30303370d647c9f88695b818cf001eb6b82fd1 100644 (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));
index 75e7d5ae8394d23c3e1dd20073270793549f7133..a5c225e3606c3c0f70fc62ad1e250b207b365f80 100644 (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.