Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index d9dd12e1876967373184d057fe465647a141e2c2..3e343ecfe7b5a6e6d319c2100ebf13e40fa87b7f 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -26,6 +26,7 @@ |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
#include <stdlib.h> |
+#include <limits> |
#include "v8.h" |
@@ -778,6 +779,124 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) { |
} |
+static size_t ArrayBufferAllocatedLength(Isolate* isolate, |
+ JSArrayBuffer* buffer) { |
+ NoHandleAllocation hc(isolate); |
+ Object* byte_length = buffer->byte_length(); |
+ if (byte_length->IsSmi()) { |
+ return Smi::cast(byte_length)->value(); |
+ } else { |
+ double value = HeapNumber::cast(byte_length)->value(); |
+ return static_cast<size_t>(value); |
+ } |
+} |
+ |
+ |
+static void ArrayBufferWeakCallback(v8::Isolate* external_isolate, |
+ Persistent<Value> object, |
+ void* data) { |
+ Isolate* isolate = reinterpret_cast<Isolate*>(external_isolate); |
+ HandleScope scope(isolate); |
+ Handle<Object> internal_object = Utils::OpenHandle(*object); |
+ |
+ size_t allocated_length = ArrayBufferAllocatedLength( |
+ isolate, JSArrayBuffer::cast(*internal_object)); |
+ isolate->heap()->AdjustAmountOfExternalAllocatedMemory(-allocated_length); |
+ if (data != NULL) |
+ free(data); |
+ object.Dispose(external_isolate); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 2); |
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1); |
+ size_t allocated_length; |
+ if (byteLength->IsSmi()) { |
+ allocated_length = Smi::cast(*byteLength)->value(); |
+ } else { |
+ ASSERT(byteLength->IsHeapNumber()); |
+ double value = HeapNumber::cast(*byteLength)->value(); |
+ |
+ ASSERT(value >= 0); |
+ |
+ if (value > std::numeric_limits<size_t>::max()) { |
+ return isolate->Throw( |
+ *isolate->factory()->NewRangeError("invalid_array_buffer_length", |
+ HandleVector<Object>(NULL, 0))); |
+ } |
+ |
+ allocated_length = static_cast<size_t>(value); |
+ } |
+ |
+ void* data; |
+ if (allocated_length != 0) { |
+ data = malloc(allocated_length); |
+ |
+ if (data == NULL) { |
+ return isolate->Throw(*isolate->factory()-> |
+ NewRangeError("invalid_array_buffer_length", |
+ HandleVector<Object>(NULL, 0))); |
+ } |
+ |
+ memset(data, 0, allocated_length); |
+ } else { |
+ data = NULL; |
+ } |
+ holder->set_backing_store(data); |
+ |
+ Object* byte_length; |
+ { |
+ MaybeObject* maybe_byte_length = |
+ isolate->heap()->NumberFromDouble(allocated_length); |
+ if (!maybe_byte_length->ToObject(&byte_length)) return maybe_byte_length; |
+ } |
+ CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber()); |
+ holder->set_byte_length(byte_length); |
+ |
+ v8::Isolate* external_isolate = reinterpret_cast<v8::Isolate*>(isolate); |
+ v8::Handle<Object> external_holder(*holder); |
+ Persistent<Object> weak_handle = Persistent<Object>::New( |
+ external_isolate, external_holder); |
+ weak_handle.MakeWeak(external_isolate, data, ArrayBufferWeakCallback); |
+ weak_handle.MarkIndependent(external_isolate); |
+ isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length); |
+ |
+ return *holder; |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) { |
+ NoHandleAllocation ha(isolate); |
+ ASSERT(args.length() == 1); |
+ CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0); |
+ return holder->byte_length(); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 3); |
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1); |
+ CONVERT_DOUBLE_ARG_CHECKED(first, 2); |
+ size_t start = static_cast<size_t>(first); |
+ size_t source_length = ArrayBufferAllocatedLength(isolate, *source); |
+ size_t target_length = ArrayBufferAllocatedLength(isolate, *target); |
+ |
+ if (target_length == 0) |
+ return isolate->heap()->undefined_value(); |
+ |
+ ASSERT(source_length - target_length >= start); |
+ 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); |
+ return isolate->heap()->undefined_value(); |
+} |
+ |
+ |
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) { |
HandleScope scope(isolate); |
ASSERT(args.length() == 1); |
@@ -5798,6 +5917,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) { |
} |
+// ES6 draft 9.1.11 |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) { |
+ NoHandleAllocation ha(isolate); |
+ ASSERT(args.length() == 1); |
+ |
+ CONVERT_DOUBLE_ARG_CHECKED(number, 0); |
+ |
+ // We do not include 0 so that we don't have to treat +0 / -0 cases. |
+ if (number > 0 && number <= Smi::kMaxValue) { |
+ return Smi::FromInt(static_cast<int>(number)); |
+ } |
+ if (number <= 0) { |
+ return Smi::FromInt(0); |
+ } |
+ return isolate->heap()->NumberFromDouble(DoubleToInteger(number)); |
+} |
+ |
+ |
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) { |
NoHandleAllocation ha(isolate); |
ASSERT(args.length() == 1); |