Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(737)

Unified Diff: src/runtime.cc

Issue 13064003: First steps towards implementing ArrayBuffer &co in V8 (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: ArrayBuffer.slice + more tests Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698