Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 75b9f2ffdba65109984bf3cf05c040fc5e3e560e..6c5ec1c46e4d8775151bc30ac9b3fbfe84f82fe8 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -791,6 +791,24 @@ bool Runtime::SetupArrayBufferAllocatingData( |
} |
+void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) { |
+ Isolate* isolate = array_buffer->GetIsolate(); |
+ for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate); |
+ !view_obj->IsUndefined();) { |
+ Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj)); |
+ if (view->IsJSTypedArray()) { |
+ JSTypedArray::cast(*view)->Neuter(); |
+ } else if (view->IsJSDataView()) { |
+ JSDataView::cast(*view)->Neuter(); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ view_obj = handle(view->weak_next(), isolate); |
+ } |
+ array_buffer->Neuter(); |
+} |
+ |
+ |
RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) { |
HandleScope scope(isolate); |
ASSERT(args.length() == 2); |
@@ -844,7 +862,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) { |
if (target_length == 0) return isolate->heap()->undefined_value(); |
- ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start); |
+ size_t source_byte_length = NumberToSize(isolate, source->byte_length()); |
+ CHECK(start <= source_byte_length); |
+ CHECK(source_byte_length - start >= target_length); |
uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store()); |
uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store()); |
CopyBytes(target_data, source_data + start, target_length); |
@@ -862,6 +882,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) { |
} |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferNeuter) { |
+ HandleScope scope(isolate); |
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0); |
+ ASSERT(!array_buffer->is_external()); |
+ void* backing_store = array_buffer->backing_store(); |
+ size_t byte_length = NumberToSize(isolate, array_buffer->byte_length()); |
+ array_buffer->set_is_external(true); |
+ Runtime::NeuterArrayBuffer(array_buffer); |
+ V8::ArrayBufferAllocator()->Free(backing_store, byte_length); |
+ return isolate->heap()->undefined_value(); |
+} |
+ |
+ |
void Runtime::ArrayIdToTypeAndSize( |
int arrayId, ExternalArrayType* array_type, size_t* element_size) { |
switch (arrayId) { |
@@ -905,7 +938,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
size_t byte_offset = NumberToSize(isolate, *byte_offset_object); |
size_t byte_length = NumberToSize(isolate, *byte_length_object); |
- ASSERT(byte_length % element_size == 0); |
+ size_t array_buffer_byte_length = |
+ NumberToSize(isolate, buffer->byte_length()); |
+ CHECK(byte_offset <= array_buffer_byte_length); |
+ CHECK(array_buffer_byte_length - byte_offset >= byte_length); |
+ |
+ CHECK_EQ(0, static_cast<int>(byte_length % element_size)); |
size_t length = byte_length / element_size; |
if (length > static_cast<unsigned>(Smi::kMaxValue)) { |