allow disabling of ArrayBuffer neutering
authordcarney@chromium.org <dcarney@chromium.org>
Wed, 29 Oct 2014 10:36:36 +0000 (10:36 +0000)
committerdcarney@chromium.org <dcarney@chromium.org>
Wed, 29 Oct 2014 10:37:12 +0000 (10:37 +0000)
BUG=
R=dslomov@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#24973}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24973 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/api.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime/runtime-typedarray.cc
test/cctest/test-api.cc

index 92eb11b..e783727 100644 (file)
@@ -2956,10 +2956,15 @@ class V8_EXPORT ArrayBuffer : public Object {
   bool IsExternal() const;
 
   /**
+   * Returns true if this ArrayBuffer may be neutered.
+   */
+  bool IsNeuterable() 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.
+   * ArrayBuffer should have been externalized and must be neuterable.
    */
   void Neuter();
 
index c04393d..6a7c40a 100644 (file)
@@ -6038,6 +6038,11 @@ bool v8::ArrayBuffer::IsExternal() const {
 }
 
 
+bool v8::ArrayBuffer::IsNeuterable() const {
+  return Utils::OpenHandle(this)->is_neuterable();
+}
+
+
 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
   Utils::ApiCheck(!obj->is_external(),
@@ -6058,6 +6063,8 @@ void v8::ArrayBuffer::Neuter() {
   Utils::ApiCheck(obj->is_external(),
                   "v8::ArrayBuffer::Neuter",
                   "Only externalized ArrayBuffers can be neutered");
+  Utils::ApiCheck(obj->is_neuterable(), "v8::ArrayBuffer::Neuter",
+                  "Only neuterable ArrayBuffers can be neutered");
   LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
   ENTER_V8(isolate);
   i::Runtime::NeuterArrayBuffer(obj);
index c00ecdd..b0996af 100644 (file)
@@ -6300,6 +6300,16 @@ void JSArrayBuffer::set_should_be_freed(bool value) {
 }
 
 
+bool JSArrayBuffer::is_neuterable() {
+  return BooleanBit::get(flag(), kIsNeuterableBit);
+}
+
+
+void JSArrayBuffer::set_is_neuterable(bool value) {
+  set_flag(BooleanBit::set(flag(), kIsNeuterableBit, value));
+}
+
+
 ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset)
 ACCESSORS(JSArrayBuffer, weak_first_view, Object, kWeakFirstViewOffset)
 
index c0814a8..ea07582 100644 (file)
@@ -16365,13 +16365,15 @@ void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
 
 
 void JSArrayBuffer::Neuter() {
-  DCHECK(is_external());
+  CHECK(is_neuterable());
+  CHECK(is_external());
   set_backing_store(NULL);
   set_byte_length(Smi::FromInt(0));
 }
 
 
 void JSArrayBufferView::NeuterView() {
+  CHECK(JSArrayBuffer::cast(buffer())->is_neuterable());
   set_byte_offset(Smi::FromInt(0));
   set_byte_length(Smi::FromInt(0));
 }
index f6c4d19..d513f97 100644 (file)
@@ -9961,6 +9961,9 @@ class JSArrayBuffer: public JSObject {
   inline bool should_be_freed();
   inline void set_should_be_freed(bool value);
 
+  inline bool is_neuterable();
+  inline void set_is_neuterable(bool value);
+
   // [weak_next]: linked list of array buffers.
   DECL_ACCESSORS(weak_next, Object)
 
@@ -9990,6 +9993,7 @@ class JSArrayBuffer: public JSObject {
   // Bit position in a flag
   static const int kIsExternalBit = 0;
   static const int kShouldBeFreed = 1;
+  static const int kIsNeuterableBit = 2;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer);
 };
index d702ff9..cd2c0eb 100644 (file)
@@ -44,6 +44,7 @@ void Runtime::SetupArrayBuffer(Isolate* isolate,
   array_buffer->set_backing_store(data);
   array_buffer->set_flag(Smi::FromInt(0));
   array_buffer->set_is_external(is_external);
+  array_buffer->set_is_neuterable(true);
 
   Handle<Object> byte_length =
       isolate->factory()->NewNumberFromSize(allocated_length);
index 717cfb3..11393f0 100644 (file)
@@ -3293,6 +3293,24 @@ THREADED_TEST(ArrayBuffer_External) {
 }
 
 
+THREADED_TEST(ArrayBuffer_DisableNeuter) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+  i::ScopedVector<uint8_t> my_data(100);
+  memset(my_data.start(), 0, 100);
+  Local<v8::ArrayBuffer> ab =
+      v8::ArrayBuffer::New(isolate, my_data.start(), 100);
+  CHECK(ab->IsNeuterable());
+
+  i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+  buf->set_is_neuterable(false);
+
+  CHECK(!ab->IsNeuterable());
+}
+
+
 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));