Skip to content

Commit 1ebbaaa

Browse files
dehrenbergCommit bot
authored andcommitted
Factor out core of Array.forEach and .every, for use in TypedArrays
The idea is to make this the model for future TypedArray methods. A possible downside could be lower array method performance if everything gets polymorhpic (but if enough inlining happens, it should still be fast), but on the upside, this change means that the TypedArray methods won't create as much code size bloat. BUG=v8:3578 LOG=Y R=adamk@chromium.org CC=arv@chromium.org, caitpotter88@gmail.com Review URL: https://codereview.chromium.org/1133503003 Cr-Commit-Position: refs/heads/master@{#28351}
1 parent c50d981 commit 1ebbaaa

4 files changed

Lines changed: 45 additions & 72 deletions

File tree

src/array.js

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ var $arrayShift;
1010
var $arraySlice;
1111
var $arraySplice;
1212
var $arrayUnshift;
13+
var $innerArrayForEach;
14+
var $innerArrayEvery;
1315

1416
(function(global, shared, exports) {
1517

@@ -1179,15 +1181,7 @@ function ArrayFilter(f, receiver) {
11791181
return result;
11801182
}
11811183

1182-
1183-
function ArrayForEach(f, receiver) {
1184-
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.forEach");
1185-
1186-
// Pull out the length so that modifications to the length in the
1187-
// loop will not affect the looping and side effects are visible.
1188-
var array = $toObject(this);
1189-
var length = TO_UINT32(array.length);
1190-
1184+
function InnerArrayForEach(f, receiver, array, length) {
11911185
if (!IS_SPEC_FUNCTION(f)) throw MakeTypeError(kCalledNonCallable, f);
11921186
var needs_wrapper = false;
11931187
if (IS_NULL(receiver)) {
@@ -1209,6 +1203,16 @@ function ArrayForEach(f, receiver) {
12091203
}
12101204
}
12111205

1206+
function ArrayForEach(f, receiver) {
1207+
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.forEach");
1208+
1209+
// Pull out the length so that modifications to the length in the
1210+
// loop will not affect the looping and side effects are visible.
1211+
var array = $toObject(this);
1212+
var length = TO_UINT32(array.length);
1213+
InnerArrayForEach(f, receiver, array, length);
1214+
}
1215+
12121216

12131217
// Executes the function once for each element present in the
12141218
// array until it finds one where callback returns true.
@@ -1243,14 +1247,7 @@ function ArraySome(f, receiver) {
12431247
}
12441248

12451249

1246-
function ArrayEvery(f, receiver) {
1247-
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.every");
1248-
1249-
// Pull out the length so that modifications to the length in the
1250-
// loop will not affect the looping and side effects are visible.
1251-
var array = $toObject(this);
1252-
var length = TO_UINT32(array.length);
1253-
1250+
function InnerArrayEvery(f, receiver, array, length) {
12541251
if (!IS_SPEC_FUNCTION(f)) throw MakeTypeError(kCalledNonCallable, f);
12551252
var needs_wrapper = false;
12561253
if (IS_NULL(receiver)) {
@@ -1273,6 +1270,16 @@ function ArrayEvery(f, receiver) {
12731270
return true;
12741271
}
12751272

1273+
function ArrayEvery(f, receiver) {
1274+
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.every");
1275+
1276+
// Pull out the length so that modifications to the length in the
1277+
// loop will not affect the looping and side effects are visible.
1278+
var array = $toObject(this);
1279+
var length = TO_UINT32(array.length);
1280+
return InnerArrayEvery(f, receiver, array, length);
1281+
}
1282+
12761283

12771284
function ArrayMap(f, receiver) {
12781285
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.map");
@@ -1595,4 +1602,7 @@ $arraySlice = ArraySlice;
15951602
$arraySplice = ArraySplice;
15961603
$arrayUnshift = ArrayUnshift;
15971604

1598-
})
1605+
$innerArrayForEach = InnerArrayForEach;
1606+
$innerArrayEvery = InnerArrayEvery;
1607+
1608+
});

src/harmony-typedarray.js

Lines changed: 8 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -30,70 +30,27 @@ TYPED_ARRAYS(DECLARE_GLOBALS)
3030
// -------------------------------------------------------------------
3131

3232
// ES6 draft 05-05-15, section 22.2.3.7
33-
function TypedArrayEvery(f /* thisArg */) { // length == 1
34-
if (!%IsTypedArray(this)) {
35-
throw MakeTypeError('not_typed_array', []);
36-
}
37-
if (!IS_SPEC_FUNCTION(f)) throw MakeTypeError(kCalledNonCallable, f);
33+
function TypedArrayEvery(f, receiver) {
34+
if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
3835

3936
var length = %_TypedArrayGetLength(this);
40-
var receiver;
41-
42-
if (%_ArgumentsLength() > 1) {
43-
receiver = %_Arguments(1);
44-
}
4537

46-
var needs_wrapper = false;
47-
if (IS_NULL(receiver)) {
48-
if (%IsSloppyModeFunction(mapfn)) receiver = UNDEFINED;
49-
} else if (!IS_UNDEFINED(receiver)) {
50-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
51-
}
52-
53-
var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
54-
for (var i = 0; i < length; i++) {
55-
var element = this[i];
56-
// Prepare break slots for debugger step in.
57-
if (stepping) %DebugPrepareStepInIfStepping(f);
58-
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
59-
if (!%_CallFunction(new_receiver, TO_OBJECT_INLINE(element), i, this, f)) {
60-
return false;
61-
}
62-
}
63-
return true;
38+
return $innerArrayEvery(f, receiver, this, length);
6439
}
40+
%FunctionSetLength(TypedArrayEvery, 1);
6541

6642
// ES6 draft 08-24-14, section 22.2.3.12
67-
function TypedArrayForEach(f /* thisArg */) { // length == 1
43+
function TypedArrayForEach(f, receiver) {
6844
if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
69-
if (!IS_SPEC_FUNCTION(f)) throw MakeTypeError(kCalledNonCallable, f);
7045

7146
var length = %_TypedArrayGetLength(this);
72-
var receiver;
73-
74-
if (%_ArgumentsLength() > 1) {
75-
receiver = %_Arguments(1);
76-
}
7747

78-
var needs_wrapper = false;
79-
if (IS_NULL(receiver)) {
80-
if (%IsSloppyModeFunction(mapfn)) receiver = UNDEFINED;
81-
} else if (!IS_UNDEFINED(receiver)) {
82-
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
83-
}
84-
85-
var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
86-
for (var i = 0; i < length; i++) {
87-
var element = this[i];
88-
// Prepare break slots for debugger step in.
89-
if (stepping) %DebugPrepareStepInIfStepping(f);
90-
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
91-
%_CallFunction(new_receiver, TO_OBJECT_INLINE(element), i, this, f);
92-
}
48+
$innerArrayForEach(f, receiver, this, length);
9349
}
50+
%FunctionSetLength(TypedArrayForEach, 1);
9451

9552
// ES6 draft 08-24-14, section 22.2.2.2
96-
function TypedArrayOf() { // length == 0
53+
function TypedArrayOf() {
9754
var length = %_ArgumentsLength();
9855
var array = new this(length);
9956
for (var i = 0; i < length; i++) {

test/mjsunit/harmony/typedarrays-every.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ function TestTypedArrayForEach(constructor) {
8585
// still make .forEach() finish, and the array should keep being
8686
// empty after neutering it.
8787
count = 0;
88-
a = new constructor(2);
88+
a = new constructor(3);
8989
result = a.every(function (n, index, array) {
90+
assertFalse(array[index] === undefined); // don't get here if neutered
9091
if (count > 0) %ArrayBufferNeuter(array.buffer);
9192
array[index] = n + 1;
9293
count++;

test/mjsunit/harmony/typedarrays-foreach.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,13 @@ function TestTypedArrayForEach(constructor) {
8585
assertEquals(42, a[1]);
8686

8787
// Neutering the buffer backing the typed array mid-way should
88-
// still make .forEach() finish, and the array should keep being
89-
// empty after neutering it.
88+
// still make .forEach() finish, but exiting early due to the missing
89+
// elements, and the array should keep being empty after detaching it.
90+
// TODO(dehrenberg): According to the ES6 spec, accessing or testing
91+
// for members on a detached TypedArray should throw, so really this
92+
// should throw in the third iteration. However, this behavior matches
93+
// the Khronos spec.
94+
a = new constructor(3);
9095
count = 0;
9196
a.forEach(function (n, index, array) {
9297
if (count > 0) %ArrayBufferNeuter(array.buffer);

0 commit comments

Comments
 (0)