Revision: 15000
Author:   dslo...@chromium.org
Date:     Fri Jun  7 03:52:11 2013
Log:      Recording array buffer views.

R=hpa...@chromium.org
BUG=

Review URL: https://codereview.chromium.org/15562008
http://code.google.com/p/v8/source/detail?r=15000

Added:
 /branches/bleeding_edge/test/cctest/test-weaktypedarrays.cc
Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/src/objects-visiting-inl.h
 /branches/bleeding_edge/src/objects-visiting.cc
 /branches/bleeding_edge/src/objects-visiting.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/test/cctest/cctest.gyp

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/cctest/test-weaktypedarrays.cc Fri Jun 7 03:52:11 2013
@@ -0,0 +1,380 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+#include "api.h"
+#include "heap.h"
+#include "objects.h"
+
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static Isolate* GetIsolateFrom(LocalContext* context) {
+  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
+}
+
+
+static int CountArrayBuffersInWeakList(Heap* heap) {
+  int count = 0;
+  for (Object* o = heap->array_buffers_list();
+       o != Smi::FromInt(0);
+       o = JSArrayBuffer::cast(o)->weak_next()) {
+    count++;
+  }
+  return count;
+}
+
+
+static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) {
+  for (Object* o = heap->array_buffers_list();
+       o != Smi::FromInt(0);
+       o = JSArrayBuffer::cast(o)->weak_next()) {
+    if (ab == o) return true;
+  }
+  return false;
+}
+
+
+static int CountTypedArrays(JSArrayBuffer* array_buffer) {
+  int count = 0;
+  for (Object* o = array_buffer->weak_first_array();
+       o != Smi::FromInt(0);
+       o = JSTypedArray::cast(o)->weak_next()) {
+    count++;
+  }
+
+  return count;
+}
+
+static bool HasTypedArrayInWeakList(JSArrayBuffer* array_buffer,
+                                    JSTypedArray* ta) {
+  for (Object* o = array_buffer->weak_first_array();
+       o != Smi::FromInt(0);
+       o = JSTypedArray::cast(o)->weak_next()) {
+    if (ta == o) return true;
+  }
+  return false;
+}
+
+
+TEST(WeakArrayBuffersFromApi) {
+  v8::V8::Initialize();
+  LocalContext context;
+  Isolate* isolate = GetIsolateFrom(&context);
+
+  CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+  {
+    v8::HandleScope s1(context->GetIsolate());
+    v8::Handle<v8::ArrayBuffer> ab1 = v8::ArrayBuffer::New(256);
+    {
+      v8::HandleScope s2(context->GetIsolate());
+      v8::Handle<v8::ArrayBuffer> ab2 = v8::ArrayBuffer::New(128);
+
+      Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);
+      Handle<JSArrayBuffer> iab2 = v8::Utils::OpenHandle(*ab2);
+      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()));
+      CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1));
+      CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab2));
+    }
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+    {
+      HandleScope scope2(isolate);
+      Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);
+
+      CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1));
+    }
+  }
+
+  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+  CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+}
+
+
+TEST(WeakArrayBuffersFromScript) {
+  v8::V8::Initialize();
+  LocalContext context;
+  Isolate* isolate = GetIsolateFrom(&context);
+
+  for (int i = 1; i <= 3; i++) {
+    // Create 3 array buffers, make i-th of them garbage,
+    // validate correct state of array buffer weak list.
+    CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+    {
+      v8::HandleScope scope(context->GetIsolate());
+
+      {
+        v8::HandleScope s1(context->GetIsolate());
+        CompileRun("var ab1 = new ArrayBuffer(256);"
+                   "var ab2 = new ArrayBuffer(256);"
+                   "var ab3 = new ArrayBuffer(256);");
+        v8::Handle<v8::ArrayBuffer> ab1(
+            v8::ArrayBuffer::Cast(*CompileRun("ab1")));
+        v8::Handle<v8::ArrayBuffer> ab2(
+            v8::ArrayBuffer::Cast(*CompileRun("ab2")));
+        v8::Handle<v8::ArrayBuffer> ab3(
+            v8::ArrayBuffer::Cast(*CompileRun("ab3")));
+
+        CHECK_EQ(3, CountArrayBuffersInWeakList(isolate->heap()));
+        CHECK(HasArrayBufferInWeakList(isolate->heap(),
+              *v8::Utils::OpenHandle(*ab1)));
+        CHECK(HasArrayBufferInWeakList(isolate->heap(),
+              *v8::Utils::OpenHandle(*ab2)));
+        CHECK(HasArrayBufferInWeakList(isolate->heap(),
+              *v8::Utils::OpenHandle(*ab3)));
+      }
+
+      i::ScopedVector<char> source(1024);
+      i::OS::SNPrintF(source, "ab%d = null;", i);
+      CompileRun(source.start());
+      isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+      isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+
+      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()));
+
+      {
+        v8::HandleScope s2(context->GetIsolate());
+        for (int j = 1; j <= 3; j++) {
+          if (j == i) continue;
+          i::OS::SNPrintF(source, "ab%d", j);
+          v8::Handle<v8::ArrayBuffer> ab(
+              v8::ArrayBuffer::Cast(*CompileRun(source.start())));
+          CHECK(HasArrayBufferInWeakList(isolate->heap(),
+                *v8::Utils::OpenHandle(*ab)));
+          }
+      }
+
+      CompileRun("ab1 = null; ab2 = null; ab3 = null;");
+    }
+
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+  }
+}
+
+template <typename TypedArray>
+void TestTypedArrayFromApi() {
+  v8::V8::Initialize();
+  LocalContext context;
+  Isolate* isolate = GetIsolateFrom(&context);
+
+  v8::HandleScope s1(context->GetIsolate());
+  v8::Handle<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(2048);
+  Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
+  {
+    v8::HandleScope s2(context->GetIsolate());
+    v8::Handle<TypedArray> ta1 = TypedArray::New(ab, 0, 256);
+    {
+      v8::HandleScope s3(context->GetIsolate());
+      v8::Handle<TypedArray> ta2 = TypedArray::New(ab, 0, 128);
+
+      Handle<JSTypedArray> ita1 = v8::Utils::OpenHandle(*ta1);
+      Handle<JSTypedArray> ita2 = v8::Utils::OpenHandle(*ta2);
+      CHECK_EQ(2, CountTypedArrays(*iab));
+      CHECK(HasTypedArrayInWeakList(*iab, *ita1));
+      CHECK(HasTypedArrayInWeakList(*iab, *ita2));
+    }
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    CHECK_EQ(1, CountTypedArrays(*iab));
+    Handle<JSTypedArray> ita1 = v8::Utils::OpenHandle(*ta1);
+    CHECK(HasTypedArrayInWeakList(*iab, *ita1));
+  }
+  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+
+  CHECK_EQ(0, CountTypedArrays(*iab));
+}
+
+
+TEST(Uint8ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Uint8Array>();
+}
+
+
+TEST(Int8ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Int8Array>();
+}
+
+
+TEST(Uint16ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Uint16Array>();
+}
+
+
+TEST(Int16ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Int16Array>();
+}
+
+
+TEST(Uint32ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Uint32Array>();
+}
+
+
+TEST(Int32ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Int32Array>();
+}
+
+
+TEST(Float32ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Float32Array>();
+}
+
+
+TEST(Float64ArrayFromApi) {
+  TestTypedArrayFromApi<v8::Float64Array>();
+}
+
+
+TEST(Uint8ClampedArrayFromApi) {
+  TestTypedArrayFromApi<v8::Uint8ClampedArray>();
+}
+
+template <typename TypedArray>
+static void TestTypedArrayFromScript(const char* constructor) {
+  v8::V8::Initialize();
+  LocalContext context;
+  Isolate* isolate = GetIsolateFrom(&context);
+  v8::HandleScope scope(context->GetIsolate());
+  CompileRun("var ab = new ArrayBuffer(2048);");
+  for (int i = 1; i <= 3; i++) {
+    // Create 3 typed arrays, make i-th of them garbage,
+    // validate correct state of typed array weak list.
+    v8::HandleScope s0(context->GetIsolate());
+    i::ScopedVector<char> source(2048);
+
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+
+    {
+      v8::HandleScope s1(context->GetIsolate());
+      i::OS::SNPrintF(source,
+                  "var ta1 = new %s(ab);"
+                  "var ta2 = new %s(ab);"
+                  "var ta3 = new %s(ab)",
+                  constructor, constructor, constructor);
+
+      CompileRun(source.start());
+ v8::Handle<v8::ArrayBuffer> ab(v8::ArrayBuffer::Cast(*CompileRun("ab")));
+      v8::Handle<TypedArray> ta1(TypedArray::Cast(*CompileRun("ta1")));
+      v8::Handle<TypedArray> ta2(TypedArray::Cast(*CompileRun("ta2")));
+      v8::Handle<TypedArray> ta3(TypedArray::Cast(*CompileRun("ta3")));
+      CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+      Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
+      CHECK_EQ(3, CountTypedArrays(*iab));
+      CHECK(HasTypedArrayInWeakList(*iab, *v8::Utils::OpenHandle(*ta1)));
+      CHECK(HasTypedArrayInWeakList(*iab, *v8::Utils::OpenHandle(*ta2)));
+      CHECK(HasTypedArrayInWeakList(*iab, *v8::Utils::OpenHandle(*ta3)));
+    }
+
+    i::OS::SNPrintF(source, "ta%d = null;", i);
+    CompileRun(source.start());
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+
+    {
+      v8::HandleScope s2(context->GetIsolate());
+ v8::Handle<v8::ArrayBuffer> ab(v8::ArrayBuffer::Cast(*CompileRun("ab")));
+      Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
+      CHECK_EQ(2, CountTypedArrays(*iab));
+      for (int j = 1; j <= 3; j++) {
+        if (j == i) continue;
+        i::OS::SNPrintF(source, "ta%d", j);
+        v8::Handle<TypedArray> ta(
+            TypedArray::Cast(*CompileRun(source.start())));
+        CHECK(HasTypedArrayInWeakList(*iab, *v8::Utils::OpenHandle(*ta)));
+      }
+    }
+
+    CompileRun("ta1 = null; ta2 = null; ta3 = null;");
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
+
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+
+    {
+      v8::HandleScope s3(context->GetIsolate());
+ v8::Handle<v8::ArrayBuffer> ab(v8::ArrayBuffer::Cast(*CompileRun("ab")));
+      Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
+      CHECK_EQ(0, CountTypedArrays(*iab));
+    }
+  }
+}
+
+
+TEST(Uint8ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Uint8Array>("Uint8Array");
+}
+
+
+TEST(Int8ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Int8Array>("Int8Array");
+}
+
+
+TEST(Uint16ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Uint16Array>("Uint16Array");
+}
+
+
+TEST(Int16ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Int16Array>("Int16Array");
+}
+
+
+TEST(Uint32ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Uint32Array>("Uint32Array");
+}
+
+
+TEST(Int32ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Int32Array>("Int32Array");
+}
+
+
+TEST(Float32ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Float32Array>("Float32Array");
+}
+
+
+TEST(Float64ArrayFromScript) {
+  TestTypedArrayFromScript<v8::Float64Array>("Float64Array");
+}
+
+
+TEST(Uint8ClampedArrayFromScript) {
+  TestTypedArrayFromScript<v8::Uint8ClampedArray>("Uint8ClampedArray");
+}
+
=======================================
--- /branches/bleeding_edge/include/v8.h        Fri Jun  7 03:46:51 2013
+++ /branches/bleeding_edge/include/v8.h        Fri Jun  7 03:52:11 2013
@@ -6171,6 +6171,14 @@
 #endif
   return static_cast<Float64Array*>(value);
 }
+
+
+Uint8ClampedArray* Uint8ClampedArray::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Uint8ClampedArray*>(value);
+}


 Function* Function::Cast(v8::Value* value) {
=======================================
--- /branches/bleeding_edge/src/api.cc  Thu Jun  6 06:16:52 2013
+++ /branches/bleeding_edge/src/api.cc  Fri Jun  7 03:52:11 2013
@@ -6206,6 +6206,9 @@

   obj->set_buffer(*buffer);

+  obj->set_weak_next(buffer->weak_first_array());
+  buffer->set_weak_first_array(*obj);
+
   i::Handle<i::Object> byte_offset_object = isolate->factory()->NewNumber(
         static_cast<double>(byte_offset));
   obj->set_byte_offset(*byte_offset_object);
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Jun  6 07:21:35 2013
+++ /branches/bleeding_edge/src/bootstrapper.cc Fri Jun  7 03:52:11 2013
@@ -1324,8 +1324,7 @@
     Handle<JSFunction> array_buffer_fun =
         InstallFunction(
             global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
-            JSArrayBuffer::kSize +
-              v8::ArrayBuffer::kInternalFieldCount * kPointerSize,
+            JSArrayBuffer::kSizeWithInternalFields,
             isolate()->initial_object_prototype(),
             Builtins::kIllegal, true, true);
     native_context()->set_array_buffer_fun(*array_buffer_fun);
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Jun  6 08:40:28 2013
+++ /branches/bleeding_edge/src/heap.cc Fri Jun  7 03:52:11 2013
@@ -180,6 +180,7 @@

   memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
   native_contexts_list_ = NULL;
+  array_buffers_list_ = Smi::FromInt(0);
   mark_compact_collector_.heap_ = this;
   external_string_table_.heap_ = this;
   // Put a dummy entry in the remembered pages so we can find the list the
@@ -1539,11 +1540,6 @@


 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
-  Object* undefined = undefined_value();
-  Object* head = undefined;
-  Context* tail = NULL;
-  Object* candidate = native_contexts_list_;
-
   // We don't record weak slots during marking or scavenges.
   // Instead we do it once when we complete mark-compact cycle.
// Note that write barrier has no effect if we are already in the middle of
@@ -1551,6 +1547,16 @@
   bool record_slots =
       gc_state() == MARK_COMPACT &&
       mark_compact_collector()->is_compacting();
+  ProcessArrayBuffers(retainer, record_slots);
+  ProcessNativeContexts(retainer, record_slots);
+}
+
+void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer,
+                                 bool record_slots) {
+  Object* undefined = undefined_value();
+  Object* head = undefined;
+  Context* tail = NULL;
+  Object* candidate = native_contexts_list_;

   while (candidate != undefined) {
     // Check whether to keep the candidate in the list.
@@ -1617,6 +1623,101 @@
   // Update the head of the list of contexts.
   native_contexts_list_ = head;
 }
+
+
+template <class T>
+struct WeakListVisitor;
+
+
+template <class T>
+static Object* VisitWeakList(Object* list,
+                      MarkCompactCollector* collector,
+                      WeakObjectRetainer* retainer, bool record_slots) {
+  Object* head = Smi::FromInt(0);
+  T* tail = NULL;
+  while (list != Smi::FromInt(0)) {
+    Object* retained = retainer->RetainAs(list);
+    if (retained != NULL) {
+      if (head == Smi::FromInt(0)) {
+        head = retained;
+      } else {
+        ASSERT(tail != NULL);
+        WeakListVisitor<T>::set_weak_next(tail, retained);
+        if (record_slots) {
+          Object** next_slot =
+ HeapObject::RawField(tail, WeakListVisitor<T>::kWeakNextOffset);
+          collector->RecordSlot(next_slot, next_slot, retained);
+        }
+      }
+      tail = reinterpret_cast<T*>(retained);
+      WeakListVisitor<T>::VisitLiveObject(
+          tail, collector, retainer, record_slots);
+    }
+    list = WeakListVisitor<T>::get_weak_next(reinterpret_cast<T*>(list));
+  }
+  if (tail != NULL) {
+    tail->set_weak_next(Smi::FromInt(0));
+  }
+  return head;
+}
+
+
+template<>
+struct WeakListVisitor<JSTypedArray> {
+  static void set_weak_next(JSTypedArray* obj, Object* next) {
+    obj->set_weak_next(next);
+  }
+
+  static Object* get_weak_next(JSTypedArray* obj) {
+    return obj->weak_next();
+  }
+
+  static void VisitLiveObject(JSTypedArray* obj,
+                              MarkCompactCollector* collector,
+                              WeakObjectRetainer* retainer,
+                              bool record_slots) {}
+
+  static const int kWeakNextOffset = JSTypedArray::kWeakNextOffset;
+};
+
+
+template<>
+struct WeakListVisitor<JSArrayBuffer> {
+  static void set_weak_next(JSArrayBuffer* obj, Object* next) {
+    obj->set_weak_next(next);
+  }
+
+  static Object* get_weak_next(JSArrayBuffer* obj) {
+    return obj->weak_next();
+  }
+
+  static void VisitLiveObject(JSArrayBuffer* array_buffer,
+                              MarkCompactCollector* collector,
+                              WeakObjectRetainer* retainer,
+                              bool record_slots) {
+    Object* typed_array_obj =
+        VisitWeakList<JSTypedArray>(array_buffer->weak_first_array(),
+                                    collector, retainer, record_slots);
+    array_buffer->set_weak_first_array(typed_array_obj);
+    if (typed_array_obj != Smi::FromInt(0) && record_slots) {
+      Object** slot = HeapObject::RawField(
+          array_buffer, JSArrayBuffer::kWeakFirstArrayOffset);
+      collector->RecordSlot(slot, slot, typed_array_obj);
+    }
+  }
+
+  static const int kWeakNextOffset = JSArrayBuffer::kWeakNextOffset;
+};
+
+
+void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer,
+                               bool record_slots) {
+  Object* array_buffer_obj =
+      VisitWeakList<JSArrayBuffer>(array_buffers_list(),
+                                   mark_compact_collector(),
+                                   retainer, record_slots);
+  set_array_buffers_list(array_buffer_obj);
+}


 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
@@ -1794,6 +1895,14 @@
                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
                     Visit);

+    table_.Register(kVisitJSArrayBuffer,
+                    &ObjectEvacuationStrategy<POINTER_OBJECT>::
+                    Visit);
+
+    table_.Register(kVisitJSTypedArray,
+                    &ObjectEvacuationStrategy<POINTER_OBJECT>::
+                    Visit);
+
     table_.Register(kVisitJSRegExp,
                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
                     Visit);
=======================================
--- /branches/bleeding_edge/src/heap.h  Thu Jun  6 08:40:28 2013
+++ /branches/bleeding_edge/src/heap.h  Fri Jun  7 03:52:11 2013
@@ -1352,6 +1352,12 @@
   }
   Object* native_contexts_list() { return native_contexts_list_; }

+  void set_array_buffers_list(Object* object) {
+    array_buffers_list_ = object;
+  }
+  Object* array_buffers_list() { return array_buffers_list_; }
+
+
   // Number of mark-sweeps.
   unsigned int ms_count() { return ms_count_; }

@@ -2022,6 +2028,8 @@

   Object* native_contexts_list_;

+  Object* array_buffers_list_;
+
   StoreBufferRebuilder store_buffer_rebuilder_;

   struct StringTypeTable {
@@ -2165,6 +2173,9 @@
   // Code to be run before and after mark-compact.
   void MarkCompactPrologue();

+ void ProcessNativeContexts(WeakObjectRetainer* retainer, bool record_slots); + void ProcessArrayBuffers(WeakObjectRetainer* retainer, bool record_slots);
+
   // Record statistics before and after garbage collection.
   void ReportStatisticsBeforeGC();
   void ReportStatisticsAfterGC();
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Jun  6 08:40:28 2013
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Jun  7 03:52:11 2013
@@ -5328,12 +5328,17 @@
 void JSArrayBuffer::set_is_external(bool value) {
   set_flag(BooleanBit::set(flag(), kIsExternalBit, value));
 }
+
+
+ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset)
+ACCESSORS(JSArrayBuffer, weak_first_array, Object, kWeakFirstArrayOffset)


 ACCESSORS(JSTypedArray, buffer, Object, kBufferOffset)
 ACCESSORS(JSTypedArray, byte_offset, Object, kByteOffsetOffset)
 ACCESSORS(JSTypedArray, byte_length, Object, kByteLengthOffset)
 ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
+ACCESSORS(JSTypedArray, weak_next, Object, kWeakNextOffset)

 ACCESSORS(JSRegExp, data, Object, kDataOffset)

=======================================
--- /branches/bleeding_edge/src/objects-printer.cc      Thu Jun  6 08:40:28 2013
+++ /branches/bleeding_edge/src/objects-printer.cc      Fri Jun  7 03:52:11 2013
@@ -540,8 +540,6 @@
     case JS_FUNCTION_TYPE: return "JS_FUNCTION";
     case CODE_TYPE: return "CODE";
     case JS_ARRAY_TYPE: return "JS_ARRAY";
-    case JS_ARRAY_BUFFER_TYPE: return "JS_ARRAY_BUFFER";
-    case JS_TYPED_ARRAY_TYPE: return "JS_TYPED_ARRAY";
     case JS_PROXY_TYPE: return "JS_PROXY";
     case JS_WEAK_MAP_TYPE: return "JS_WEAK_MAP";
     case JS_REGEXP_TYPE: return "JS_REGEXP";
@@ -549,6 +547,8 @@
     case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
     case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
     case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
+    case JS_TYPED_ARRAY_TYPE: return "JS_TYPED_ARRAY";
+    case JS_ARRAY_BUFFER_TYPE: return "JS_ARRAY_BUFFER";
     case FOREIGN_TYPE: return "FOREIGN";
     case JS_MESSAGE_OBJECT_TYPE: return "JS_MESSAGE_OBJECT_TYPE";
 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
=======================================
--- /branches/bleeding_edge/src/objects-visiting-inl.h Thu May 16 01:39:24 2013 +++ /branches/bleeding_edge/src/objects-visiting-inl.h Fri Jun 7 03:52:11 2013
@@ -79,6 +79,10 @@

   table_.Register(kVisitJSFunction, &VisitJSFunction);

+  table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer);
+
+  table_.Register(kVisitJSTypedArray, &VisitJSTypedArray);
+
   table_.Register(kVisitFreeSpace, &VisitFreeSpace);

   table_.Register(kVisitJSWeakMap, &JSObjectVisitor::Visit);
@@ -96,6 +100,43 @@
                                           kVisitStruct,
                                           kVisitStructGeneric>();
 }
+
+
+template<typename StaticVisitor>
+int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
+    Map* map, HeapObject* object) {
+  Heap* heap = map->GetHeap();
+
+  STATIC_ASSERT(
+      JSArrayBuffer::kWeakFirstArrayOffset ==
+      JSArrayBuffer::kWeakNextOffset + kPointerSize);
+  VisitPointers(
+      heap,
+ HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
+      HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset));
+  VisitPointers(
+      heap,
+      HeapObject::RawField(object,
+          JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize),
+ HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
+  return JSArrayBuffer::kSizeWithInternalFields;
+}
+
+
+template<typename StaticVisitor>
+int StaticNewSpaceVisitor<StaticVisitor>::VisitJSTypedArray(
+    Map* map, HeapObject* object) {
+  VisitPointers(
+      map->GetHeap(),
+ HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset),
+      HeapObject::RawField(object, JSTypedArray::kWeakNextOffset));
+  VisitPointers(
+      map->GetHeap(),
+      HeapObject::RawField(object,
+          JSTypedArray::kWeakNextOffset + kPointerSize),
+      HeapObject::RawField(object, JSTypedArray::kSize));
+  return JSTypedArray::kSize;
+}


 template<typename StaticVisitor>
@@ -149,6 +190,10 @@

   table_.Register(kVisitJSFunction, &VisitJSFunction);

+  table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer);
+
+  table_.Register(kVisitJSTypedArray, &VisitJSTypedArray);
+
   // Registration for kVisitJSRegExp is done by StaticVisitor.

   table_.Register(kVisitPropertyCell,
@@ -398,6 +443,41 @@
       HeapObject::RawField(object, JSRegExp::kPropertiesOffset),
       HeapObject::RawField(object, last_property_offset));
 }
+
+
+template<typename StaticVisitor>
+void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
+    Map* map, HeapObject* object) {
+  Heap* heap = map->GetHeap();
+
+  STATIC_ASSERT(
+      JSArrayBuffer::kWeakFirstArrayOffset ==
+      JSArrayBuffer::kWeakNextOffset + kPointerSize);
+  StaticVisitor::VisitPointers(
+      heap,
+ HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
+      HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset));
+  StaticVisitor::VisitPointers(
+      heap,
+      HeapObject::RawField(object,
+          JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize),
+ HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
+}
+
+
+template<typename StaticVisitor>
+void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray(
+    Map* map, HeapObject* object) {
+  StaticVisitor::VisitPointers(
+      map->GetHeap(),
+ HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset),
+      HeapObject::RawField(object, JSTypedArray::kWeakNextOffset));
+  StaticVisitor::VisitPointers(
+      map->GetHeap(),
+      HeapObject::RawField(object,
+        JSTypedArray::kWeakNextOffset + kPointerSize),
+      HeapObject::RawField(object, JSTypedArray::kSize));
+}


 template<typename StaticVisitor>
=======================================
--- /branches/bleeding_edge/src/objects-visiting.cc     Tue Apr 16 07:16:30 2013
+++ /branches/bleeding_edge/src/objects-visiting.cc     Fri Jun  7 03:52:11 2013
@@ -134,6 +134,12 @@
     case FILLER_TYPE:
       return kVisitDataObjectGeneric;

+    case JS_ARRAY_BUFFER_TYPE:
+      return kVisitJSArrayBuffer;
+
+    case JS_TYPED_ARRAY_TYPE:
+      return kVisitJSTypedArray;
+
     case JS_OBJECT_TYPE:
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     case JS_GENERATOR_OBJECT_TYPE:
@@ -145,8 +151,6 @@
     case JS_GLOBAL_OBJECT_TYPE:
     case JS_BUILTINS_OBJECT_TYPE:
     case JS_MESSAGE_OBJECT_TYPE:
-    case JS_ARRAY_BUFFER_TYPE:
-    case JS_TYPED_ARRAY_TYPE:
       return GetVisitorIdForSize(kVisitJSObject,
                                  kVisitJSObjectGeneric,
                                  instance_size);
=======================================
--- /branches/bleeding_edge/src/objects-visiting.h      Fri Mar 22 09:51:28 2013
+++ /branches/bleeding_edge/src/objects-visiting.h      Fri Jun  7 03:52:11 2013
@@ -92,6 +92,8 @@
   V(SharedFunctionInfo)       \
   V(JSFunction)               \
   V(JSWeakMap)                \
+  V(JSArrayBuffer)            \
+  V(JSTypedArray)             \
   V(JSRegExp)

// For data objects, JS objects and structs along with generic visitor which
@@ -332,6 +334,9 @@
   INLINE(static int VisitFreeSpace(Map* map, HeapObject* object)) {
     return FreeSpace::cast(object)->Size();
   }
+
+  INLINE(static int VisitJSArrayBuffer(Map* map, HeapObject* object));
+  INLINE(static int VisitJSTypedArray(Map* map, HeapObject* object));

   class DataObjectVisitor {
    public:
@@ -407,6 +412,8 @@
INLINE(static void VisitSharedFunctionInfo(Map* map, HeapObject* object));
   INLINE(static void VisitJSFunction(Map* map, HeapObject* object));
   INLINE(static void VisitJSRegExp(Map* map, HeapObject* object));
+  INLINE(static void VisitJSArrayBuffer(Map* map, HeapObject* object));
+  INLINE(static void VisitJSTypedArray(Map* map, HeapObject* object));
   INLINE(static void VisitNativeContext(Map* map, HeapObject* object));

   // Mark pointers in a Map and its TransitionArray together, possibly
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Jun  6 08:40:28 2013
+++ /branches/bleeding_edge/src/objects.h       Fri Jun  7 03:52:11 2013
@@ -8786,6 +8786,12 @@
   inline bool is_external();
   inline void set_is_external(bool value);

+  // [weak_next]: linked list of array buffers.
+  DECL_ACCESSORS(weak_next, Object)
+
+  // [weak_first_array]: weak linked list of typed arrays.
+  DECL_ACCESSORS(weak_first_array, Object)
+
   // Casting.
   static inline JSArrayBuffer* cast(Object* obj);

@@ -8796,7 +8802,12 @@
   static const int kBackingStoreOffset = JSObject::kHeaderSize;
   static const int kByteLengthOffset = kBackingStoreOffset + kPointerSize;
   static const int kFlagOffset = kByteLengthOffset + kPointerSize;
-  static const int kSize = kFlagOffset + kPointerSize;
+  static const int kWeakNextOffset = kFlagOffset + kPointerSize;
+  static const int kWeakFirstArrayOffset = kWeakNextOffset + kPointerSize;
+  static const int kSize = kWeakFirstArrayOffset + kPointerSize;
+
+  static const int kSizeWithInternalFields =
+      kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize;

  private:
   // Bit position in a flag
@@ -8820,6 +8831,9 @@
   // [length]: length of typed array in elements.
   DECL_ACCESSORS(length, Object)

+  // [weak_next]: linked list of typed arrays over the same array buffer.
+  DECL_ACCESSORS(weak_next, Object)
+
   // Casting.
   static inline JSTypedArray* cast(Object* obj);

@@ -8834,7 +8848,8 @@
   static const int kByteOffsetOffset = kBufferOffset + kPointerSize;
   static const int kByteLengthOffset = kByteOffsetOffset + kPointerSize;
   static const int kLengthOffset = kByteLengthOffset + kPointerSize;
-  static const int kSize = kLengthOffset + kPointerSize;
+  static const int kWeakNextOffset = kLengthOffset + kPointerSize;
+  static const int kSize = kWeakNextOffset + kPointerSize;

  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray);
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Thu Jun  6 06:28:22 2013
+++ /branches/bleeding_edge/src/runtime.cc      Fri Jun  7 03:52:11 2013
@@ -687,6 +687,10 @@
       isolate->factory()->NewNumberFromSize(allocated_length);
   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
   array_buffer->set_byte_length(*byte_length);
+
+  array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
+  isolate->heap()->set_array_buffers_list(*array_buffer);
+  array_buffer->set_weak_first_array(Smi::FromInt(0));
 }


@@ -855,6 +859,8 @@

Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
   holder->set_length(*length_obj);
+  holder->set_weak_next(buffer->weak_first_array());
+  buffer->set_weak_first_array(*holder);

   Handle<ExternalArray> elements =
       isolate->factory()->NewExternalArray(
=======================================
--- /branches/bleeding_edge/test/cctest/cctest.gyp      Wed Jun  5 08:43:53 2013
+++ /branches/bleeding_edge/test/cctest/cctest.gyp      Fri Jun  7 03:52:11 2013
@@ -103,7 +103,8 @@
         'test-unbound-queue.cc',
         'test-utils.cc',
         'test-version.cc',
-        'test-weakmaps.cc'
+        'test-weakmaps.cc',
+        'test-weaktypedarrays.cc'
       ],
       'conditions': [
         ['v8_target_arch=="ia32"', {

--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to