Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index d9dd12e1876967373184d057fe465647a141e2c2..4df6a2a031822e57d6830dc867d7eb9c3e373666 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,117 @@ 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 Failure::OutOfMemoryException(0x19); |
+ } |
+ |
+ allocated_length = static_cast<size_t>(value); |
+} |
rossberg
2013/03/27 17:33:14
Nit: indentation is off
Dmitry Lomov (no reviews)
2013/03/27 18:45:00
Done.
|
+ |
+ void* data; |
+ if (allocated_length != 0) { |
+ data = malloc(allocated_length); |
+ |
+ if (data == NULL) { |
+ return Failure::OutOfMemoryException(0x1A); |
+ } |
+ |
+ memset(data, 0, allocated_length); |
+ } else { |
+ data = NULL; |
+ } |
+ holder->set_backing_store(data); |
+ |
+ if (Smi::IsValid(allocated_length)) { |
rossberg
2013/03/27 17:33:14
You can use isolate->heap()->NumberFromDouble here
Dmitry Lomov (no reviews)
2013/03/27 18:45:00
Done.
|
+ holder->set_byte_length(Smi::FromInt(static_cast<int>(allocated_length))); |
+ } else { |
+ holder->set_byte_length(*isolate->factory()->NewNumber(allocated_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, holder, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, result, 1); |
rossberg
2013/03/27 17:33:14
Nit: I wouldn't call this 'result'. How about 'tar
Dmitry Lomov (no reviews)
2013/03/27 18:45:00
Done.
|
+ CONVERT_DOUBLE_ARG_CHECKED(first, 2); |
+ size_t start = static_cast<size_t>(first); |
+ size_t holder_length = ArrayBufferAllocatedLength(isolate, *holder); |
+ size_t result_length = ArrayBufferAllocatedLength(isolate, *result); |
+ |
+ if (result_length == 0) |
+ return isolate->heap()->undefined_value(); |
+ |
+ ASSERT(holder_length - result_length >= start); |
+ uint8_t* holder_data = reinterpret_cast<uint8_t*>(holder->backing_store()); |
+ uint8_t* target_data = reinterpret_cast<uint8_t*>(result->backing_store()); |
+ CopyBytes(target_data, holder_data + start, result_length); |
+ return isolate->heap()->undefined_value(); |
+} |
+ |
+ |
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) { |
HandleScope scope(isolate); |
ASSERT(args.length() == 1); |
@@ -5798,6 +5910,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); |