Revision: 15006
Author:   [email protected]
Date:     Fri Jun  7 08:02:20 2013
Log:      Neutering API for v8::ArrayBuffer

[email protected]

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

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/include/v8.h        Fri Jun  7 03:52:11 2013
+++ /branches/bleeding_edge/include/v8.h        Fri Jun  7 08:02:20 2013
@@ -2431,6 +2431,14 @@
    */
   bool IsExternal() const;

+  /**
+   * Neuters this ArrayBuffer and all its views (typed arrays).
+ * Neutering sets the byte length of the buffer and all typed arrays to zero,
+   * preventing JavaScript from ever accessing underlying backing store.
+   * ArrayBuffer should have been externalized.
+   */
+  void Neuter();
+
   /**
    * Pass the ownership of this ArrayBuffer's backing store to
    * a given ArrayBufferContents.
=======================================
--- /branches/bleeding_edge/src/api.cc  Fri Jun  7 03:52:11 2013
+++ /branches/bleeding_edge/src/api.cc  Fri Jun  7 08:02:20 2013
@@ -6110,6 +6110,25 @@
   contents->data_ = obj->backing_store();
   contents->byte_length_ = byte_length;
 }
+
+
+void v8::ArrayBuffer::Neuter() {
+  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
+  i::Isolate* isolate = obj->GetIsolate();
+  ApiCheck(obj->is_external(),
+           "v8::ArrayBuffer::Neuter",
+           "Only externalized ArrayBuffers can be neutered");
+  LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
+  ENTER_V8(isolate);
+
+  for (i::Handle<i::Object> array_obj(obj->weak_first_array(), isolate);
+       *array_obj != i::Smi::FromInt(0);) {
+ i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*array_obj));
+    typed_array->Neuter();
+    array_obj = i::handle(typed_array->weak_next(), isolate);
+  }
+  obj->Neuter();
+}


 size_t v8::ArrayBuffer::ByteLength() const {
=======================================
--- /branches/bleeding_edge/src/objects.cc      Fri Jun  7 06:27:03 2013
+++ /branches/bleeding_edge/src/objects.cc      Fri Jun  7 08:02:20 2013
@@ -15776,5 +15776,20 @@
   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
 }
+
+
+void JSArrayBuffer::Neuter() {
+  ASSERT(is_external());
+  set_backing_store(NULL);
+  set_byte_length(Smi::FromInt(0));
+}
+
+
+void JSTypedArray::Neuter() {
+  set_byte_offset(Smi::FromInt(0));
+  set_byte_length(Smi::FromInt(0));
+  set_length(Smi::FromInt(0));
+  set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
+}

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Jun  7 06:27:03 2013
+++ /branches/bleeding_edge/src/objects.h       Fri Jun  7 08:02:20 2013
@@ -8813,6 +8813,9 @@
   // Casting.
   static inline JSArrayBuffer* cast(Object* obj);

+  // Neutering. Only neuters the buffer, not associated typed arrays.
+  void Neuter();
+
   // Dispatched behavior.
   DECLARE_PRINTER(JSArrayBuffer)
   DECLARE_VERIFIER(JSArrayBuffer)
@@ -8852,6 +8855,9 @@
   // [weak_next]: linked list of typed arrays over the same array buffer.
   DECL_ACCESSORS(weak_next, Object)

+  // Neutering. Only neuters this typed array.
+  void Neuter();
+
   // Casting.
   static inline JSTypedArray* cast(Object* obj);

=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Fri Jun  7 01:46:39 2013
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Fri Jun  7 08:02:20 2013
@@ -2657,6 +2657,122 @@
 }


+static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
+  CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
+  CHECK_EQ(0, static_cast<int>(ta->Length()));
+  CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
+}
+
+template <typename TypedArray, int kElementSize>
+static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
+                                         int byteOffset,
+                                         int length) {
+  v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
+  CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
+  CHECK_EQ(length, static_cast<int>(ta->Length()));
+  CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
+  return ta;
+}
+
+
+THREADED_TEST(ArrayBuffer_NeuteringApi) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+  v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(1024);
+
+  v8::Handle<v8::Uint8Array> u8a =
+    CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
+  v8::Handle<v8::Uint8ClampedArray> u8c =
+    CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
+  v8::Handle<v8::Int8Array> i8a =
+    CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
+
+  v8::Handle<v8::Uint16Array> u16a =
+    CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
+  v8::Handle<v8::Int16Array> i16a =
+    CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
+
+  v8::Handle<v8::Uint32Array> u32a =
+    CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
+  v8::Handle<v8::Int32Array> i32a =
+    CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
+
+  v8::Handle<v8::Float32Array> f32a =
+    CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
+  v8::Handle<v8::Float64Array> f64a =
+    CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
+
+  v8::ArrayBufferContents contents;
+  buffer->Externalize(&contents);
+  buffer->Neuter();
+  CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
+  CheckIsNeutered(u8a);
+  CheckIsNeutered(u8c);
+  CheckIsNeutered(i8a);
+  CheckIsNeutered(u16a);
+  CheckIsNeutered(i16a);
+  CheckIsNeutered(u32a);
+  CheckIsNeutered(i32a);
+  CheckIsNeutered(f32a);
+  CheckIsNeutered(f64a);
+}
+
+THREADED_TEST(ArrayBuffer_NeuteringScript) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+  CompileRun(
+      "var ab = new ArrayBuffer(1024);"
+      "var u8a = new Uint8Array(ab, 1, 1023);"
+      "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
+      "var i8a = new Int8Array(ab, 1, 1023);"
+      "var u16a = new Uint16Array(ab, 2, 511);"
+      "var i16a = new Int16Array(ab, 2, 511);"
+      "var u32a = new Uint32Array(ab, 4, 255);"
+      "var i32a = new Int32Array(ab, 4, 255);"
+      "var f32a = new Float32Array(ab, 4, 255);"
+      "var f64a = new Float64Array(ab, 8, 127);");
+
+  v8::Handle<v8::ArrayBuffer> ab(v8::ArrayBuffer::Cast(*CompileRun("ab")));
+
+  v8::Handle<v8::Uint8Array> u8a(v8::Uint8Array::Cast(*CompileRun("u8a")));
+  v8::Handle<v8::Uint8ClampedArray> u8c(
+    v8::Uint8ClampedArray::Cast(*CompileRun("u8c")));
+  v8::Handle<v8::Int8Array> i8a(v8::Int8Array::Cast(*CompileRun("i8a")));
+
+  v8::Handle<v8::Uint16Array> u16a(
+    v8::Uint16Array::Cast(*CompileRun("u16a")));
+  v8::Handle<v8::Int16Array> i16a(
+    v8::Int16Array::Cast(*CompileRun("i16a")));
+  v8::Handle<v8::Uint32Array> u32a(
+    v8::Uint32Array::Cast(*CompileRun("u32a")));
+  v8::Handle<v8::Int32Array> i32a(
+    v8::Int32Array::Cast(*CompileRun("i32a")));
+  v8::Handle<v8::Float32Array> f32a(
+    v8::Float32Array::Cast(*CompileRun("f32a")));
+  v8::Handle<v8::Float64Array> f64a(
+    v8::Float64Array::Cast(*CompileRun("f64a")));
+
+  v8::ArrayBufferContents contents;
+  ab->Externalize(&contents);
+  ab->Neuter();
+  CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
+  CheckIsNeutered(u8a);
+  CheckIsNeutered(u8c);
+  CheckIsNeutered(i8a);
+  CheckIsNeutered(u16a);
+  CheckIsNeutered(i16a);
+  CheckIsNeutered(u32a);
+  CheckIsNeutered(i32a);
+  CheckIsNeutered(f32a);
+  CheckIsNeutered(f64a);
+}
+
+
+
 THREADED_TEST(HiddenProperties) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());

--
--
v8-dev mailing list
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to