Revision: 24657
Author: [email protected]
Date: Thu Oct 16 10:55:26 2014 UTC
Log: Implement .forEach() on typed arrays
BUG=v8:3578
LOG=Y
[email protected], [email protected]
Review URL: https://codereview.chromium.org/583723002
Patch from Adrian Perez de Castro <[email protected]>.
https://code.google.com/p/v8/source/detail?r=24657
Added:
/branches/bleeding_edge/src/harmony-typedarray.js
/branches/bleeding_edge/test/mjsunit/harmony/typedarrays-foreach.js
Modified:
/branches/bleeding_edge/BUILD.gn
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/runtime/runtime-typedarray.cc
/branches/bleeding_edge/src/runtime/runtime.h
/branches/bleeding_edge/tools/gyp/v8.gyp
=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/harmony-typedarray.js Thu Oct 16 10:55:26
2014 UTC
@@ -0,0 +1,79 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+// This file relies on the fact that the following declaration has been
made
+// in runtime.js:
+// var $Array = global.Array;
+
+// -------------------------------------------------------------------
+
+macro TYPED_ARRAYS(FUNCTION)
+// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
+FUNCTION(1, Uint8Array, 1)
+FUNCTION(2, Int8Array, 1)
+FUNCTION(3, Uint16Array, 2)
+FUNCTION(4, Int16Array, 2)
+FUNCTION(5, Uint32Array, 4)
+FUNCTION(6, Int32Array, 4)
+FUNCTION(7, Float32Array, 4)
+FUNCTION(8, Float64Array, 8)
+FUNCTION(9, Uint8ClampedArray, 1)
+endmacro
+
+
+macro TYPED_ARRAY_HARMONY_ADDITIONS(ARRAY_ID, NAME, ELEMENT_SIZE)
+
+// ES6 draft 08-24-14, section 22.2.3.12
+function NAMEForEach(f /* thisArg */) { // length == 1
+ if (!%IsTypedArray(this)) {
+ throw MakeTypeError('not_typed_array', []);
+ }
+ if (!IS_SPEC_FUNCTION(f)) {
+ throw MakeTypeError('called_non_callable', [ f ]);
+ }
+
+ var length = %_TypedArrayGetLength(this);
+ var receiver;
+
+ if (%_ArgumentsLength() > 1) {
+ receiver = %_Arguments(1);
+ }
+
+ var needs_wrapper = false;
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ } else {
+ needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
+ }
+
+ var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
+ for (var i = 0; i < length; i++) {
+ var element = this[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ var new_receiver = needs_wrapper ? ToObject(receiver) : receiver;
+ %_CallFunction(new_receiver, TO_OBJECT_INLINE(element), i, this, f);
+ }
+}
+endmacro
+
+TYPED_ARRAYS(TYPED_ARRAY_HARMONY_ADDITIONS)
+
+
+function HarmonyTypedArrayExtendPrototypes() {
+macro EXTEND_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
+ %CheckIsBootstrapping();
+
+ // Set up non-enumerable functions on the prototype object.
+ InstallFunctions(global.NAME.prototype, DONT_ENUM, $Array(
+ "forEach", NAMEForEach
+ ));
+endmacro
+
+ TYPED_ARRAYS(EXTEND_TYPED_ARRAY)
+}
+
+HarmonyTypedArrayExtendPrototypes();
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/harmony/typedarrays-foreach.js Thu
Oct 16 10:55:26 2014 UTC
@@ -0,0 +1,140 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-arrays --allow-natives-syntax
+
+var typedArrayConstructors = [
+ Uint8Array,
+ Int8Array,
+ Uint16Array,
+ Int16Array,
+ Uint32Array,
+ Int32Array,
+ Uint8ClampedArray,
+ Float32Array,
+ Float64Array];
+
+function CheckTypedArrayIsNeutered(array) {
+ assertEquals(0, array.byteLength);
+ assertEquals(0, array.byteOffset);
+ assertEquals(0, array.length);
+}
+
+function TestTypedArrayForEach(constructor) {
+ assertEquals(1, constructor.prototype.forEach.length);
+
+ var a = new constructor(2);
+ a[0] = 0;
+ a[1] = 1;
+
+ var count = 0;
+ a.forEach(function (n) { count++; });
+ assertEquals(2, count);
+
+ // Use specified object as this object when calling the function.
+ var o = { value: 42 };
+ var result = [];
+ a.forEach(function (n, index, array) { result.push(this.value); }, o);
+ assertArrayEquals([42, 42], result);
+
+ // Modify the original array.
+ count = 0;
+ a.forEach(function (n, index, array) { array[index] = n + 1; count++ });
+ assertEquals(2, count);
+ assertArrayEquals([1, 2], a);
+
+ // Check that values passed as second argument are wrapped into
+ // objects when calling into sloppy mode functions.
+ function CheckWrapping(value, wrapper) {
+ var wrappedValue = new wrapper(value);
+
+ a.forEach(function () {
+ assertEquals("object", typeof this);
+ assertEquals(wrappedValue, this);
+ }, value);
+
+ a.forEach(function () {
+ "use strict";
+ assertEquals(typeof value, typeof this);
+ assertEquals(value, this);
+ }, value);
+ }
+ CheckWrapping(true, Boolean);
+ CheckWrapping(false, Boolean);
+ CheckWrapping("xxx", String);
+ CheckWrapping(42, Number);
+ CheckWrapping(3.14, Number);
+ CheckWrapping({}, Object);
+
+ // Throw before completing iteration, only the first element
+ // should be modified when thorwing mid-way.
+ count = 0;
+ a[0] = 42;
+ a[1] = 42;
+ try {
+ a.forEach(function (n, index, array) {
+ if (count > 0) throw "meh";
+ array[index] = n + 1;
+ count++;
+ });
+ } catch (e) {
+ }
+ assertEquals(1, count);
+ assertEquals(43, a[0]);
+ assertEquals(42, a[1]);
+
+ // Neutering the buffer backing the typed array mid-way should
+ // still make .forEach() finish, and the array should keep being
+ // empty after neutering it.
+ count = 0;
+ a.forEach(function (n, index, array) {
+ if (count > 0) %ArrayBufferNeuter(array.buffer);
+ array[index] = n + 1;
+ count++;
+ });
+ assertEquals(2, count);
+ CheckTypedArrayIsNeutered(a);
+ assertEquals(undefined, a[0]);
+
+ // The method must work for typed arrays created from ArrayBuffer.
+ // The length of the ArrayBuffer is chosen so it is a multiple of
+ // all lengths of the typed array items.
+ a = new constructor(new ArrayBuffer(64));
+ count = 0;
+ a.forEach(function (n) { count++ });
+ assertEquals(a.length, count);
+
+ // Externalizing the array mid-way accessing the .buffer property
+ // should work.
+ a = new constructor(2);
+ count = 0;
+ var buffer = undefined;
+ a.forEach(function (n, index, array) {
+ if (count++ > 0)
+ buffer = array.buffer;
+ });
+ assertEquals(2, count);
+ assertTrue(!!buffer);
+ assertEquals("ArrayBuffer", %_ClassOf(buffer));
+ assertSame(buffer, a.buffer);
+
+ // The %TypedArray%.forEach() method should not work when
+ // transplanted to objects that are not typed arrays.
+ assertThrows(function () { constructor.prototype.forEach.call([1, 2, 3],
function (x) {}) }, TypeError);
+ assertThrows(function () { constructor.prototype.forEach.call("abc",
function (x) {}) }, TypeError);
+ assertThrows(function () { constructor.prototype.forEach.call({},
function (x) {}) }, TypeError);
+ assertThrows(function () { constructor.prototype.forEach.call(0,
function (x) {}) }, TypeError);
+
+ // Method must be useable on instances of other typed arrays.
+ for (var i = 0; i < typedArrayConstructors.length; i++) {
+ count = 0;
+ a = new typedArrayConstructors[i](4);
+ constructor.prototype.forEach.call(a, function (x) { count++ });
+ assertEquals(a.length, count);
+ }
+}
+
+for (i = 0; i < typedArrayConstructors.length; i++) {
+ TestTypedArrayForEach(typedArrayConstructors[i]);
+}
=======================================
--- /branches/bleeding_edge/BUILD.gn Mon Oct 13 14:18:10 2014 UTC
+++ /branches/bleeding_edge/BUILD.gn Thu Oct 16 10:55:26 2014 UTC
@@ -243,6 +243,7 @@
"src/generator.js",
"src/harmony-string.js",
"src/harmony-array.js",
+ "src/harmony-typedarray.js",
"src/harmony-classes.js",
]
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Tue Oct 14 14:46:11 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Thu Oct 16 10:55:26 2014 UTC
@@ -2086,6 +2086,7 @@
INSTALL_EXPERIMENTAL_NATIVE(i, proxies, "proxy.js")
INSTALL_EXPERIMENTAL_NATIVE(i, strings, "harmony-string.js")
INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-array.js")
+ INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-typedarray.js")
INSTALL_EXPERIMENTAL_NATIVE(i, classes, "harmony-classes.js")
}
=======================================
--- /branches/bleeding_edge/src/runtime/runtime-typedarray.cc Mon Sep 29
09:32:38 2014 UTC
+++ /branches/bleeding_edge/src/runtime/runtime-typedarray.cc Thu Oct 16
10:55:26 2014 UTC
@@ -498,6 +498,13 @@
FixedTypedArrayBase::kDataOffset);
return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
}
+
+
+RUNTIME_FUNCTION(Runtime_IsTypedArray) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ return isolate->heap()->ToBoolean(args[0]->IsJSTypedArray());
+}
RUNTIME_FUNCTION(Runtime_DataViewInitialize) {
=======================================
--- /branches/bleeding_edge/src/runtime/runtime.h Wed Oct 15 13:26:43 2014
UTC
+++ /branches/bleeding_edge/src/runtime/runtime.h Thu Oct 16 10:55:26 2014
UTC
@@ -351,6 +351,7 @@
F(ArrayBufferIsView, 1, 1) \
F(ArrayBufferNeuter, 1, 1) \
\
+ F(IsTypedArray, 1, 1) \
F(TypedArrayInitializeFromArrayLike, 4, 1) \
F(TypedArrayGetBuffer, 1, 1) \
F(TypedArraySetFastCases, 3, 1) \
=======================================
--- /branches/bleeding_edge/tools/gyp/v8.gyp Mon Oct 13 09:36:12 2014 UTC
+++ /branches/bleeding_edge/tools/gyp/v8.gyp Thu Oct 16 10:55:26 2014 UTC
@@ -1604,6 +1604,7 @@
'../../src/generator.js',
'../../src/harmony-string.js',
'../../src/harmony-array.js',
+ '../../src/harmony-typedarray.js',
'../../src/harmony-classes.js',
],
'libraries_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries.bin',
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.