[Torque] Implement Array.prototype.every and some in Torque

Just a straightforward port.

bug:v8:7672

Change-Id: Ie2511cda23d7b61775e3619d61dde43c8ae48c7f
Reviewed-on: https://chromium-review.googlesource.com/c/1425916
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59638}
This commit is contained in:
Mike Stanton 2019-02-15 19:29:40 +01:00 committed by Commit Bot
parent 9542fd8fa0
commit 9bf0c69674
8 changed files with 387 additions and 234 deletions

View File

@ -900,6 +900,7 @@ torque_files = [
"src/builtins/arguments.tq", "src/builtins/arguments.tq",
"src/builtins/array.tq", "src/builtins/array.tq",
"src/builtins/array-copywithin.tq", "src/builtins/array-copywithin.tq",
"src/builtins/array-every.tq",
"src/builtins/array-filter.tq", "src/builtins/array-filter.tq",
"src/builtins/array-foreach.tq", "src/builtins/array-foreach.tq",
"src/builtins/array-join.tq", "src/builtins/array-join.tq",
@ -908,6 +909,7 @@ torque_files = [
"src/builtins/array-map.tq", "src/builtins/array-map.tq",
"src/builtins/array-reverse.tq", "src/builtins/array-reverse.tq",
"src/builtins/array-slice.tq", "src/builtins/array-slice.tq",
"src/builtins/array-some.tq",
"src/builtins/array-splice.tq", "src/builtins/array-splice.tq",
"src/builtins/array-unshift.tq", "src/builtins/array-unshift.tq",
"src/builtins/collections.tq", "src/builtins/collections.tq",

172
src/builtins/array-every.tq Normal file
View File

@ -0,0 +1,172 @@
// Copyright 2018 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.
namespace array {
transitioning javascript builtin
ArrayEveryLoopEagerDeoptContinuation(implicit context: Context)(
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
length: Object): Object {
// All continuation points in the optimized every implementation are
// after the ToObject(O) call that ensures we are dealing with a
// JSReceiver.
//
// Also, this great mass of casts is necessary because the signature
// of Torque javascript builtins requires Object type for all parameters
// other than {context}.
const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const numberK = Cast<Number>(initialK) otherwise unreachable;
const numberLength = Cast<Number>(length) otherwise unreachable;
return ArrayEveryLoopContinuation(
jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
numberLength, Undefined);
}
transitioning javascript builtin
ArrayEveryLoopLazyDeoptContinuation(implicit context: Context)(
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
length: Object, result: Object): Object {
// All continuation points in the optimized every implementation are
// after the ToObject(O) call that ensures we are dealing with a
// JSReceiver.
const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
const callbackfn = Cast<Callable>(callback) otherwise unreachable;
let numberK = Cast<Number>(initialK) otherwise unreachable;
const numberLength = Cast<Number>(length) otherwise unreachable;
// This custom lazy deopt point is right after the callback. every() needs
// to pick up at the next step, which is either continuing to the next
// array element or returning false if {result} is false.
if (!ToBoolean(result)) {
return False;
}
numberK = numberK + 1;
return ArrayEveryLoopContinuation(
jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
numberLength, Undefined);
}
transitioning builtin ArrayEveryLoopContinuation(implicit context: Context)(
receiver: JSReceiver, callbackfn: Callable, thisArg: Object,
array: Object, o: JSReceiver, initialK: Number, length: Number,
initialTo: Object): Object {
// 5. Let k be 0.
// 6. Repeat, while k < len
for (let k: Number = initialK; k < length; k++) {
// 6a. Let Pk be ! ToString(k).
// k is guaranteed to be a positive integer, hence ToString is
// side-effect free and HasProperty/GetProperty do the conversion inline.
// 6b. Let kPresent be ? HasProperty(O, Pk).
const kPresent: Boolean = HasProperty_Inline(o, k);
// 6c. If kPresent is true, then
if (kPresent == True) {
// 6c. i. Let kValue be ? Get(O, Pk).
const kValue: Object = GetProperty(o, k);
// 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>).
const result: Object = Call(context, callbackfn, thisArg, kValue, k, o);
// iii. If selected is true, then...
if (!ToBoolean(result)) {
return False;
}
}
// 6d. Increase k by 1. (done by the loop).
}
return True;
}
transitioning macro
EveryVisitAllElements<FixedArrayType: type>(implicit context: Context)(
o: FastJSArray, len: Smi, callbackfn: Callable,
thisArg: Object): Boolean labels Bailout(Smi) {
let k: Smi = 0;
let fastO = FastJSArrayWitness{o};
// Build a fast loop over the smi array.
for (; k < len; k++) {
// Ensure that we haven't walked beyond a possibly updated length.
if (k >= fastO.Get().length) goto Bailout(k);
try {
const value: Object = LoadElementNoHole<FixedArrayType>(fastO.Get(), k)
otherwise FoundHole;
const result: Object =
Call(context, callbackfn, thisArg, value, k, fastO.Get());
if (!ToBoolean(result)) {
return False;
}
}
label FoundHole {}
fastO.Recheck() otherwise goto Bailout(k + 1);
}
return True;
}
transitioning macro FastArrayEvery(implicit context: Context)(
o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object
labels Bailout(Smi) {
let k: Smi = 0;
const smiLen = Cast<Smi>(len) otherwise goto Bailout(k);
let fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k);
const elementsKind: ElementsKind = fastO.map.elements_kind;
if (IsElementsKindLessThanOrEqual(elementsKind, HOLEY_ELEMENTS)) {
return EveryVisitAllElements<FixedArray>(
fastO, smiLen, callbackfn, thisArg) otherwise Bailout;
}
assert(IsDoubleElementsKind(elementsKind));
return EveryVisitAllElements<FixedDoubleArray>(
fastO, smiLen, callbackfn, thisArg) otherwise Bailout;
}
// https://tc39.github.io/ecma262/#sec-array.prototype.every
transitioning javascript builtin
ArrayEvery(implicit context: Context)(receiver: Object, ...arguments):
Object {
try {
if (IsNullOrUndefined(receiver)) {
goto NullOrUndefinedError;
}
// 1. Let O be ? ToObject(this value).
const o: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const len: Number = GetLengthProperty(o);
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (arguments.length == 0) {
goto TypeError;
}
const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError;
// 4. If thisArg is present, let T be thisArg; else let T be undefined.
const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined;
// Special cases.
try {
return FastArrayEvery(o, len, callbackfn, thisArg)
otherwise Bailout;
}
label Bailout(kValue: Smi) deferred {
return ArrayEveryLoopContinuation(
o, callbackfn, thisArg, Undefined, o, kValue, len, Undefined);
}
}
label TypeError deferred {
ThrowTypeError(context, kCalledNonCallable, arguments[0]);
}
label NullOrUndefinedError deferred {
ThrowTypeError(
context, kCalledOnNullOrUndefined, 'Array.prototype.every');
}
}
}

View File

@ -14,14 +14,12 @@ namespace array_filter {
// Also, this great mass of casts is necessary because the signature // Also, this great mass of casts is necessary because the signature
// of Torque javascript builtins requires Object type for all parameters // of Torque javascript builtins requires Object type for all parameters
// other than {context}. // other than {context}.
const jsreceiver: JSReceiver = const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const callbackfn: Callable = Cast<Callable>(callback) otherwise unreachable; const outputArray = Cast<JSReceiver>(array) otherwise unreachable;
const outputArray: JSReceiver = const numberK = Cast<Number>(initialK) otherwise unreachable;
Cast<JSReceiver>(array) otherwise unreachable; const numberTo = Cast<Number>(initialTo) otherwise unreachable;
const numberK: Number = Cast<Number>(initialK) otherwise unreachable; const numberLength = Cast<Number>(length) otherwise unreachable;
const numberTo: Number = Cast<Number>(initialTo) otherwise unreachable;
const numberLength: Number = Cast<Number>(length) otherwise unreachable;
return ArrayFilterLoopContinuation( return ArrayFilterLoopContinuation(
jsreceiver, callbackfn, thisArg, outputArray, jsreceiver, numberK, jsreceiver, callbackfn, thisArg, outputArray, jsreceiver, numberK,
@ -36,14 +34,12 @@ namespace array_filter {
// All continuation points in the optimized filter implementation are // All continuation points in the optimized filter implementation are
// after the ToObject(O) call that ensures we are dealing with a // after the ToObject(O) call that ensures we are dealing with a
// JSReceiver. // JSReceiver.
const jsreceiver: JSReceiver = const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const callbackfn: Callable = Cast<Callable>(callback) otherwise unreachable; const outputArray = Cast<JSReceiver>(array) otherwise unreachable;
const outputArray: JSReceiver = let numberK = Cast<Number>(initialK) otherwise unreachable;
Cast<JSReceiver>(array) otherwise unreachable; let numberTo = Cast<Number>(initialTo) otherwise unreachable;
let numberK: Number = Cast<Number>(initialK) otherwise unreachable; const numberLength = Cast<Number>(length) otherwise unreachable;
let numberTo: Number = Cast<Number>(initialTo) otherwise unreachable;
const numberLength: Number = Cast<Number>(length) otherwise unreachable;
// This custom lazy deopt point is right after the callback. filter() needs // This custom lazy deopt point is right after the callback. filter() needs
// to pick up at the next step, which is setting the callback result in // to pick up at the next step, which is setting the callback result in
@ -142,10 +138,9 @@ namespace array_filter {
labels Bailout(Smi, Smi) { labels Bailout(Smi, Smi) {
let k: Smi = 0; let k: Smi = 0;
let to: Smi = 0; let to: Smi = 0;
const smiLen: Smi = Cast<Smi>(len) otherwise goto Bailout(k, to); const smiLen = Cast<Smi>(len) otherwise goto Bailout(k, to);
const fastArray: FastJSArray = const fastArray = Cast<FastJSArray>(array) otherwise goto Bailout(k, to);
Cast<FastJSArray>(array) otherwise goto Bailout(k, to); let fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k, to);
let fastO: FastJSArray = Cast<FastJSArray>(o) otherwise goto Bailout(k, to);
EnsureArrayPushable(fastArray.map) otherwise goto Bailout(k, to); EnsureArrayPushable(fastArray.map) otherwise goto Bailout(k, to);
const elementsKind: ElementsKind = fastO.map.elements_kind; const elementsKind: ElementsKind = fastO.map.elements_kind;
if (IsElementsKindLessThanOrEqual(elementsKind, HOLEY_SMI_ELEMENTS)) { if (IsElementsKindLessThanOrEqual(elementsKind, HOLEY_SMI_ELEMENTS)) {
@ -172,7 +167,7 @@ namespace array_filter {
receiver: JSReceiver): JSReceiver labels Slow { receiver: JSReceiver): JSReceiver labels Slow {
const len: Smi = 0; const len: Smi = 0;
if (IsArraySpeciesProtectorCellInvalid()) goto Slow; if (IsArraySpeciesProtectorCellInvalid()) goto Slow;
const o: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; const o = Cast<FastJSArray>(receiver) otherwise Slow;
const newMap: Map = const newMap: Map =
LoadJSArrayElementsMap(o.map.elements_kind, LoadNativeContext(context)); LoadJSArrayElementsMap(o.map.elements_kind, LoadNativeContext(context));
return AllocateJSArray(PACKED_SMI_ELEMENTS, newMap, len, len); return AllocateJSArray(PACKED_SMI_ELEMENTS, newMap, len, len);
@ -197,8 +192,7 @@ namespace array_filter {
if (arguments.length == 0) { if (arguments.length == 0) {
goto TypeError; goto TypeError;
} }
const callbackfn: Callable = const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError;
Cast<Callable>(arguments[0]) otherwise TypeError;
// 4. If thisArg is present, let T be thisArg; else let T be undefined. // 4. If thisArg is present, let T be thisArg; else let T be undefined.
const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined;

View File

@ -10,11 +10,10 @@ namespace array_foreach {
// All continuation points in the optimized forEach implemntation are // All continuation points in the optimized forEach implemntation are
// after the ToObject(O) call that ensures we are dealing with a // after the ToObject(O) call that ensures we are dealing with a
// JSReceiver. // JSReceiver.
const jsreceiver: JSReceiver = const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const callbackfn: Callable = Cast<Callable>(callback) otherwise unreachable; const numberK = Cast<Number>(initialK) otherwise unreachable;
const numberK: Number = Cast<Number>(initialK) otherwise unreachable; const numberLength = Cast<Number>(length) otherwise unreachable;
const numberLength: Number = Cast<Number>(length) otherwise unreachable;
return ArrayForEachLoopContinuation( return ArrayForEachLoopContinuation(
jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK, jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
@ -28,11 +27,10 @@ namespace array_foreach {
// All continuation points in the optimized forEach implemntation are // All continuation points in the optimized forEach implemntation are
// after the ToObject(O) call that ensures we are dealing with a // after the ToObject(O) call that ensures we are dealing with a
// JSReceiver. // JSReceiver.
const jsreceiver: JSReceiver = const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const callbackfn: Callable = Cast<Callable>(callback) otherwise unreachable; const numberK = Cast<Number>(initialK) otherwise unreachable;
const numberK: Number = Cast<Number>(initialK) otherwise unreachable; const numberLength = Cast<Number>(length) otherwise unreachable;
const numberLength: Number = Cast<Number>(length) otherwise unreachable;
return ArrayForEachLoopContinuation( return ArrayForEachLoopContinuation(
jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK, jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
@ -92,8 +90,8 @@ namespace array_foreach {
o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object
labels Bailout(Smi) { labels Bailout(Smi) {
let k: Smi = 0; let k: Smi = 0;
const smiLen: Smi = Cast<Smi>(len) otherwise goto Bailout(k); const smiLen = Cast<Smi>(len) otherwise goto Bailout(k);
let fastO: FastJSArray = Cast<FastJSArray>(o) otherwise goto Bailout(k); let fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k);
const elementsKind: ElementsKind = fastO.map.elements_kind; const elementsKind: ElementsKind = fastO.map.elements_kind;
if (IsElementsKindGreaterThan(elementsKind, HOLEY_ELEMENTS)) { if (IsElementsKindGreaterThan(elementsKind, HOLEY_ELEMENTS)) {
VisitAllElements<FixedDoubleArray>(fastO, smiLen, callbackfn, thisArg) VisitAllElements<FixedDoubleArray>(fastO, smiLen, callbackfn, thisArg)
@ -123,8 +121,7 @@ namespace array_foreach {
if (arguments.length == 0) { if (arguments.length == 0) {
goto TypeError; goto TypeError;
} }
const callbackfn: Callable = const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError;
Cast<Callable>(arguments[0]) otherwise TypeError;
// 4. If thisArg is present, let T be thisArg; else let T be undefined. // 4. If thisArg is present, let T be thisArg; else let T be undefined.
const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined;

View File

@ -14,13 +14,11 @@ namespace array_map {
// Also, this great mass of casts is necessary because the signature // Also, this great mass of casts is necessary because the signature
// of Torque javascript builtins requires Object type for all parameters // of Torque javascript builtins requires Object type for all parameters
// other than {context}. // other than {context}.
const jsreceiver: JSReceiver = const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const callbackfn: Callable = Cast<Callable>(callback) otherwise unreachable; const outputArray = Cast<JSReceiver>(array) otherwise unreachable;
const outputArray: JSReceiver = const numberK = Cast<Number>(initialK) otherwise unreachable;
Cast<JSReceiver>(array) otherwise unreachable; const numberLength = Cast<Number>(length) otherwise unreachable;
const numberK: Number = Cast<Number>(initialK) otherwise unreachable;
const numberLength: Number = Cast<Number>(length) otherwise unreachable;
return ArrayMapLoopContinuation( return ArrayMapLoopContinuation(
jsreceiver, callbackfn, thisArg, outputArray, jsreceiver, numberK, jsreceiver, callbackfn, thisArg, outputArray, jsreceiver, numberK,
@ -34,13 +32,11 @@ namespace array_map {
// All continuation points in the optimized filter implementation are // All continuation points in the optimized filter implementation are
// after the ToObject(O) call that ensures we are dealing with a // after the ToObject(O) call that ensures we are dealing with a
// JSReceiver. // JSReceiver.
const jsreceiver: JSReceiver = const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const callbackfn: Callable = Cast<Callable>(callback) otherwise unreachable; const outputArray = Cast<JSReceiver>(array) otherwise unreachable;
const outputArray: JSReceiver = let numberK = Cast<Number>(initialK) otherwise unreachable;
Cast<JSReceiver>(array) otherwise unreachable; const numberLength = Cast<Number>(length) otherwise unreachable;
let numberK: Number = Cast<Number>(initialK) otherwise unreachable;
const numberLength: Number = Cast<Number>(length) otherwise unreachable;
// This custom lazy deopt point is right after the callback. map() needs // This custom lazy deopt point is right after the callback. map() needs
// to pick up at the next step, which is setting the callback result in // to pick up at the next step, which is setting the callback result in
@ -220,7 +216,7 @@ namespace array_map {
o: JSReceiver, len: Smi, callbackfn: Callable, thisArg: Object): JSArray o: JSReceiver, len: Smi, callbackfn: Callable, thisArg: Object): JSArray
labels Bailout(JSArray, Smi) { labels Bailout(JSArray, Smi) {
let k: Smi = 0; let k: Smi = 0;
let fastO: FastJSArray = Cast<FastJSArray>(o) otherwise unreachable; let fastO = Cast<FastJSArray>(o) otherwise unreachable;
let vector = Vector{len}; let vector = Vector{len};
const elementsKind: ElementsKind = fastO.map.elements_kind; const elementsKind: ElementsKind = fastO.map.elements_kind;
try { try {
@ -254,8 +250,8 @@ namespace array_map {
macro FastMapSpeciesCreate(implicit context: Context)( macro FastMapSpeciesCreate(implicit context: Context)(
receiver: JSReceiver, length: Number): JSArray labels Bailout { receiver: JSReceiver, length: Number): JSArray labels Bailout {
if (IsArraySpeciesProtectorCellInvalid()) goto Bailout; if (IsArraySpeciesProtectorCellInvalid()) goto Bailout;
const o: FastJSArray = Cast<FastJSArray>(receiver) otherwise Bailout; const o = Cast<FastJSArray>(receiver) otherwise Bailout;
const smiLength: Smi = Cast<Smi>(length) otherwise Bailout; const smiLength = Cast<Smi>(length) otherwise Bailout;
const newMap: Map = const newMap: Map =
LoadJSArrayElementsMap(PACKED_SMI_ELEMENTS, LoadNativeContext(context)); LoadJSArrayElementsMap(PACKED_SMI_ELEMENTS, LoadNativeContext(context));
return AllocateJSArray(PACKED_SMI_ELEMENTS, newMap, smiLength, smiLength); return AllocateJSArray(PACKED_SMI_ELEMENTS, newMap, smiLength, smiLength);
@ -276,8 +272,7 @@ namespace array_map {
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception. // 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (arguments.length == 0) goto TypeError; if (arguments.length == 0) goto TypeError;
const callbackfn: Callable = const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError;
Cast<Callable>(arguments[0]) otherwise TypeError;
// 4. If thisArg is present, let T be thisArg; else let T be undefined. // 4. If thisArg is present, let T be thisArg; else let T be undefined.
const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined;

171
src/builtins/array-some.tq Normal file
View File

@ -0,0 +1,171 @@
// Copyright 2018 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.
namespace array {
transitioning javascript builtin
ArraySomeLoopEagerDeoptContinuation(implicit context: Context)(
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
length: Object): Object {
// All continuation points in the optimized some implementation are
// after the ToObject(O) call that ensures we are dealing with a
// JSReceiver.
//
// Also, this great mass of casts is necessary because the signature
// of Torque javascript builtins requires Object type for all parameters
// other than {context}.
const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
const callbackfn = Cast<Callable>(callback) otherwise unreachable;
const numberK = Cast<Number>(initialK) otherwise unreachable;
const numberLength = Cast<Number>(length) otherwise unreachable;
return ArraySomeLoopContinuation(
jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
numberLength, Undefined);
}
transitioning javascript builtin
ArraySomeLoopLazyDeoptContinuation(implicit context: Context)(
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
length: Object, result: Object): Object {
// All continuation points in the optimized some implementation are
// after the ToObject(O) call that ensures we are dealing with a
// JSReceiver.
const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
const callbackfn = Cast<Callable>(callback) otherwise unreachable;
let numberK = Cast<Number>(initialK) otherwise unreachable;
const numberLength = Cast<Number>(length) otherwise unreachable;
// This custom lazy deopt point is right after the callback. some() needs
// to pick up at the next step: if the result is true, then return,
// otherwise, keep going through the array starting from k + 1.
if (ToBoolean(result)) {
return True;
}
numberK = numberK + 1;
return ArraySomeLoopContinuation(
jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
numberLength, Undefined);
}
transitioning builtin ArraySomeLoopContinuation(implicit context: Context)(
receiver: JSReceiver, callbackfn: Callable, thisArg: Object,
array: Object, o: JSReceiver, initialK: Number, length: Number,
initialTo: Object): Object {
// 5. Let k be 0.
// 6. Repeat, while k < len
for (let k: Number = initialK; k < length; k++) {
// 6a. Let Pk be ! ToString(k).
// k is guaranteed to be a positive integer, hence ToString is
// side-effect free and HasProperty/GetProperty do the conversion inline.
// 6b. Let kPresent be ? HasProperty(O, Pk).
const kPresent: Boolean = HasProperty_Inline(o, k);
// 6c. If kPresent is true, then
if (kPresent == True) {
// 6c. i. Let kValue be ? Get(O, Pk).
const kValue: Object = GetProperty(o, k);
// 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>).
const result: Object = Call(context, callbackfn, thisArg, kValue, k, o);
// iii. If selected is true, then...
if (ToBoolean(result)) {
return True;
}
}
// 6d. Increase k by 1. (done by the loop).
}
return False;
}
transitioning macro
SomeVisitAllElements<FixedArrayType: type>(implicit context: Context)(
o: FastJSArray, len: Smi, callbackfn: Callable, thisArg: Object): Boolean
labels Bailout(Smi) {
let k: Smi = 0;
let fastO = FastJSArrayWitness{o};
// Build a fast loop over the smi array.
for (; k < len; k++) {
// Ensure that we haven't walked beyond a possibly updated length.
if (k >= fastO.Get().length) goto Bailout(k);
try {
const value: Object = LoadElementNoHole<FixedArrayType>(fastO.Get(), k)
otherwise FoundHole;
const result: Object =
Call(context, callbackfn, thisArg, value, k, fastO.Get());
if (ToBoolean(result)) {
return True;
}
}
label FoundHole {}
fastO.Recheck() otherwise goto Bailout(k + 1);
}
return False;
}
transitioning macro FastArraySome(implicit context: Context)(
o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object
labels Bailout(Smi) {
let k: Smi = 0;
const smiLen = Cast<Smi>(len) otherwise goto Bailout(k);
let fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k);
const elementsKind: ElementsKind = fastO.map.elements_kind;
if (IsElementsKindLessThanOrEqual(elementsKind, HOLEY_ELEMENTS)) {
return SomeVisitAllElements<FixedArray>(
fastO, smiLen, callbackfn, thisArg)
otherwise Bailout;
}
assert(IsDoubleElementsKind(elementsKind));
return SomeVisitAllElements<FixedDoubleArray>(
fastO, smiLen, callbackfn, thisArg) otherwise Bailout;
}
// https://tc39.github.io/ecma262/#sec-array.prototype.some
transitioning javascript builtin
ArraySome(implicit context: Context)(receiver: Object, ...arguments): Object {
try {
if (IsNullOrUndefined(receiver)) {
goto NullOrUndefinedError;
}
// 1. Let O be ? ToObject(this value).
const o: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const len: Number = GetLengthProperty(o);
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (arguments.length == 0) {
goto TypeError;
}
const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError;
// 4. If thisArg is present, let T be thisArg; else let T be undefined.
const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined;
// Special cases.
try {
return FastArraySome(o, len, callbackfn, thisArg)
otherwise Bailout;
}
label Bailout(kValue: Smi) deferred {
return ArraySomeLoopContinuation(
o, callbackfn, thisArg, Undefined, o, kValue, len, Undefined);
}
}
label TypeError deferred {
ThrowTypeError(context, kCalledNonCallable, arguments[0]);
}
label NullOrUndefinedError deferred {
ThrowTypeError(context, kCalledOnNullOrUndefined, 'Array.prototype.some');
}
}
}

View File

@ -1609,87 +1609,6 @@ TF_BUILTIN(TypedArrayPrototypeForEach, ArrayBuiltinsAssembler) {
&ArrayBuiltinsAssembler::NullPostLoopAction); &ArrayBuiltinsAssembler::NullPostLoopAction);
} }
TF_BUILTIN(ArraySomeLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Node* result = Parameter(Descriptor::kResult);
// This custom lazy deopt point is right after the callback. every() needs
// to pick up at the next step, which is either continuing to the next
// array element or returning false if {result} is false.
Label true_continue(this), false_continue(this);
// iii. If selected is true, then...
BranchIfToBooleanIsTrue(result, &true_continue, &false_continue);
BIND(&true_continue);
{ Return(TrueConstant()); }
BIND(&false_continue);
{
// Increment k.
initial_k = NumberInc(initial_k);
Return(CallBuiltin(Builtins::kArraySomeLoopContinuation, context, receiver,
callbackfn, this_arg, FalseConstant(), receiver,
initial_k, len, UndefinedConstant()));
}
}
TF_BUILTIN(ArraySomeLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Return(CallBuiltin(Builtins::kArraySomeLoopContinuation, context, receiver,
callbackfn, this_arg, FalseConstant(), receiver, initial_k,
len, UndefinedConstant()));
}
TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* array = Parameter(Descriptor::kArray);
TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinsAssembler::SomeProcessor,
&ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
}
TF_BUILTIN(ArraySome, ArrayBuiltinsAssembler) {
TNode<IntPtrT> argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = args.GetReceiver();
Node* callbackfn = args.GetOptionalArgumentValue(0);
Node* this_arg = args.GetOptionalArgumentValue(1);
InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
GenerateIteratingArrayBuiltinBody(
"Array.prototype.some", &ArrayBuiltinsAssembler::SomeResultGenerator,
&ArrayBuiltinsAssembler::SomeProcessor,
&ArrayBuiltinsAssembler::NullPostLoopAction,
Builtins::CallableFor(isolate(), Builtins::kArraySomeLoopContinuation),
MissingPropertyMode::kSkip);
}
TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinsAssembler) { TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinsAssembler) {
TNode<IntPtrT> argc = TNode<IntPtrT> argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
@ -1708,87 +1627,6 @@ TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinsAssembler) {
&ArrayBuiltinsAssembler::NullPostLoopAction); &ArrayBuiltinsAssembler::NullPostLoopAction);
} }
TF_BUILTIN(ArrayEveryLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Node* result = Parameter(Descriptor::kResult);
// This custom lazy deopt point is right after the callback. every() needs
// to pick up at the next step, which is either continuing to the next
// array element or returning false if {result} is false.
Label true_continue(this), false_continue(this);
// iii. If selected is true, then...
BranchIfToBooleanIsTrue(result, &true_continue, &false_continue);
BIND(&true_continue);
{
// Increment k.
initial_k = NumberInc(initial_k);
Return(CallBuiltin(Builtins::kArrayEveryLoopContinuation, context, receiver,
callbackfn, this_arg, TrueConstant(), receiver,
initial_k, len, UndefinedConstant()));
}
BIND(&false_continue);
{ Return(FalseConstant()); }
}
TF_BUILTIN(ArrayEveryLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Return(CallBuiltin(Builtins::kArrayEveryLoopContinuation, context, receiver,
callbackfn, this_arg, TrueConstant(), receiver, initial_k,
len, UndefinedConstant()));
}
TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* array = Parameter(Descriptor::kArray);
TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinsAssembler::EveryProcessor,
&ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
}
TF_BUILTIN(ArrayEvery, ArrayBuiltinsAssembler) {
TNode<IntPtrT> argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = args.GetReceiver();
Node* callbackfn = args.GetOptionalArgumentValue(0);
Node* this_arg = args.GetOptionalArgumentValue(1);
InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
GenerateIteratingArrayBuiltinBody(
"Array.prototype.every", &ArrayBuiltinsAssembler::EveryResultGenerator,
&ArrayBuiltinsAssembler::EveryProcessor,
&ArrayBuiltinsAssembler::NullPostLoopAction,
Builtins::CallableFor(isolate(), Builtins::kArrayEveryLoopContinuation),
MissingPropertyMode::kSkip);
}
TF_BUILTIN(TypedArrayPrototypeEvery, ArrayBuiltinsAssembler) { TF_BUILTIN(TypedArrayPrototypeEvery, ArrayBuiltinsAssembler) {
TNode<IntPtrT> argc = TNode<IntPtrT> argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));

View File

@ -350,22 +350,6 @@ namespace internal {
TFS(CloneFastJSArray, kSource) \ TFS(CloneFastJSArray, kSource) \
TFS(CloneFastJSArrayFillingHoles, kSource) \ TFS(CloneFastJSArrayFillingHoles, kSource) \
TFS(ExtractFastJSArray, kSource, kBegin, kCount) \ TFS(ExtractFastJSArray, kSource, kBegin, kCount) \
/* ES6 #sec-array.prototype.every */ \
TFS(ArrayEveryLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArrayEveryLoopEagerDeoptContinuation, 4, kReceiver, kCallbackFn, \
kThisArg, kInitialK, kLength) \
TFJ(ArrayEveryLoopLazyDeoptContinuation, 5, kReceiver, kCallbackFn, \
kThisArg, kInitialK, kLength, kResult) \
TFJ(ArrayEvery, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.some */ \
TFS(ArraySomeLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArraySomeLoopEagerDeoptContinuation, 4, kReceiver, kCallbackFn, \
kThisArg, kInitialK, kLength) \
TFJ(ArraySomeLoopLazyDeoptContinuation, 5, kReceiver, kCallbackFn, kThisArg, \
kInitialK, kLength, kResult) \
TFJ(ArraySome, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.reduce */ \ /* ES6 #sec-array.prototype.reduce */ \
TFS(ArrayReduceLoopContinuation, kReceiver, kCallbackFn, kThisArg, \ TFS(ArrayReduceLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
kAccumulator, kObject, kInitialK, kLength, kTo) \ kAccumulator, kObject, kInitialK, kLength, kTo) \