Chromium Code Reviews| 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); |