[Torque] Port Array.prototype.find and findIndex to Torque
Happily, with the port of Array.prototype.find and findIndex, we can remove a large set of library functions from array-builtins-gen.cc. BUG: v8:7672 Change-Id: I74e07fe00162b34b2246c868386d4551ba4dc032 Reviewed-on: https://chromium-review.googlesource.com/c/1484296 Commit-Queue: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#59902}
This commit is contained in:
parent
1937e2b128
commit
ada192fe21
4
BUILD.gn
4
BUILD.gn
@ -902,6 +902,8 @@ torque_files = [
|
||||
"src/builtins/array-copywithin.tq",
|
||||
"src/builtins/array-every.tq",
|
||||
"src/builtins/array-filter.tq",
|
||||
"src/builtins/array-find.tq",
|
||||
"src/builtins/array-findindex.tq",
|
||||
"src/builtins/array-foreach.tq",
|
||||
"src/builtins/array-join.tq",
|
||||
"src/builtins/array-lastindexof.tq",
|
||||
@ -933,6 +935,8 @@ torque_namespaces = [
|
||||
"array",
|
||||
"array-copywithin",
|
||||
"array-filter",
|
||||
"array-find",
|
||||
"array-findindex",
|
||||
"array-foreach",
|
||||
"array-join",
|
||||
"array-map",
|
||||
|
158
src/builtins/array-find.tq
Normal file
158
src/builtins/array-find.tq
Normal file
@ -0,0 +1,158 @@
|
||||
// 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_find {
|
||||
transitioning javascript builtin
|
||||
ArrayFindLoopEagerDeoptContinuation(implicit context: Context)(
|
||||
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
|
||||
length: Object): Object {
|
||||
// All continuation points in the optimized find 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 ArrayFindLoopContinuation(
|
||||
jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength);
|
||||
}
|
||||
|
||||
transitioning javascript builtin
|
||||
ArrayFindLoopLazyDeoptContinuation(implicit context: Context)(
|
||||
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
|
||||
length: Object, result: Object): Object {
|
||||
// This deopt continuation point is never actually called, it just
|
||||
// exists to make stack traces correct from a ThrowTypeError if the
|
||||
// callback was found to be non-callable.
|
||||
unreachable;
|
||||
}
|
||||
|
||||
// Continuation that is called after a lazy deoptimization from TF that
|
||||
// happens right after the callback and it's returned value must be handled
|
||||
// before iteration continues.
|
||||
transitioning javascript builtin
|
||||
ArrayFindLoopAfterCallbackLazyDeoptContinuation(implicit context: Context)(
|
||||
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
|
||||
length: Object, foundValue: Object, isFound: Object): Object {
|
||||
// All continuation points in the optimized find 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. find() needs
|
||||
// to pick up at the next step, which is returning the element if the
|
||||
// callback value is truthy. Otherwise, continue the search by calling the
|
||||
// continuation.
|
||||
|
||||
if (ToBoolean(isFound)) {
|
||||
return foundValue;
|
||||
}
|
||||
|
||||
return ArrayFindLoopContinuation(
|
||||
jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength);
|
||||
}
|
||||
|
||||
transitioning builtin ArrayFindLoopContinuation(implicit context: Context)(
|
||||
receiver: JSReceiver, callbackfn: Callable, thisArg: Object,
|
||||
o: JSReceiver, initialK: Number, length: Number): 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. i. Let kValue be ? Get(O, Pk).
|
||||
const value: Object = GetProperty(o, k);
|
||||
|
||||
// 6c. Let testResult be ToBoolean(? Call(predicate, T, <<kValue, k,
|
||||
// O>>)).
|
||||
const testResult: Object =
|
||||
Call(context, callbackfn, thisArg, value, k, o);
|
||||
|
||||
// 6d. If testResult is true, return kValue.
|
||||
if (ToBoolean(testResult)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// 6e. Increase k by 1. (done by the loop).
|
||||
}
|
||||
return Undefined;
|
||||
}
|
||||
|
||||
transitioning macro FastArrayFind(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);
|
||||
const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k);
|
||||
let fastOW = FastJSArrayWitness{fastO};
|
||||
|
||||
// Build a fast loop over the smi array.
|
||||
for (; k < smiLen; k++) {
|
||||
fastOW.Recheck() otherwise goto Bailout(k);
|
||||
|
||||
// Ensure that we haven't walked beyond a possibly updated length.
|
||||
if (k >= fastOW.Get().length) goto Bailout(k);
|
||||
|
||||
const value: Object = fastOW.LoadElementOrUndefined(k);
|
||||
const testResult: Object =
|
||||
Call(context, callbackfn, thisArg, value, k, fastOW.Get());
|
||||
if (ToBoolean(testResult)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return Undefined;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.find
|
||||
transitioning javascript builtin
|
||||
ArrayPrototypeFind(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 NotCallableError;
|
||||
}
|
||||
const callbackfn =
|
||||
Cast<Callable>(arguments[0]) otherwise NotCallableError;
|
||||
|
||||
// 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 FastArrayFind(o, len, callbackfn, thisArg)
|
||||
otherwise Bailout;
|
||||
}
|
||||
label Bailout(k: Smi) deferred {
|
||||
return ArrayFindLoopContinuation(o, callbackfn, thisArg, o, k, len);
|
||||
}
|
||||
}
|
||||
label NotCallableError deferred {
|
||||
ThrowTypeError(kCalledNonCallable, arguments[0]);
|
||||
}
|
||||
label NullOrUndefinedError deferred {
|
||||
ThrowTypeError(kCalledOnNullOrUndefined, 'Array.prototype.find');
|
||||
}
|
||||
}
|
||||
}
|
161
src/builtins/array-findindex.tq
Normal file
161
src/builtins/array-findindex.tq
Normal file
@ -0,0 +1,161 @@
|
||||
// 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_findindex {
|
||||
transitioning javascript builtin
|
||||
ArrayFindIndexLoopEagerDeoptContinuation(implicit context: Context)(
|
||||
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
|
||||
length: Object): Object {
|
||||
// All continuation points in the optimized findIndex 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 ArrayFindIndexLoopContinuation(
|
||||
jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength);
|
||||
}
|
||||
|
||||
transitioning javascript builtin
|
||||
ArrayFindIndexLoopLazyDeoptContinuation(implicit context: Context)(
|
||||
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
|
||||
length: Object, result: Object): Object {
|
||||
// This deopt continuation point is never actually called, it just
|
||||
// exists to make stack traces correct from a ThrowTypeError if the
|
||||
// callback was found to be non-callable.
|
||||
unreachable;
|
||||
}
|
||||
|
||||
// Continuation that is called after a lazy deoptimization from TF that
|
||||
// happens right after the callback and it's returned value must be handled
|
||||
// before iteration continues.
|
||||
transitioning javascript builtin
|
||||
ArrayFindIndexLoopAfterCallbackLazyDeoptContinuation(implicit context:
|
||||
Context)(
|
||||
receiver: Object, callback: Object, thisArg: Object, initialK: Object,
|
||||
length: Object, foundValue: Object, isFound: Object): Object {
|
||||
// All continuation points in the optimized findIndex 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. find() needs
|
||||
// to pick up at the next step, which is returning the element if the
|
||||
// callback value is truthy. Otherwise, continue the search by calling the
|
||||
// continuation.
|
||||
|
||||
if (ToBoolean(isFound)) {
|
||||
return foundValue;
|
||||
}
|
||||
|
||||
return ArrayFindIndexLoopContinuation(
|
||||
jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength);
|
||||
}
|
||||
|
||||
transitioning builtin ArrayFindIndexLoopContinuation(implicit context:
|
||||
Context)(
|
||||
receiver: JSReceiver, callbackfn: Callable, thisArg: Object,
|
||||
o: JSReceiver, initialK: Number, length: Number): Number {
|
||||
// 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. i. Let kValue be ? Get(O, Pk).
|
||||
const value: Object = GetProperty(o, k);
|
||||
|
||||
// 6c. Let testResult be ToBoolean(? Call(predicate, T, <<kValue, k,
|
||||
// O>>)).
|
||||
const testResult: Object =
|
||||
Call(context, callbackfn, thisArg, value, k, o);
|
||||
|
||||
// 6d. If testResult is true, return k.
|
||||
if (ToBoolean(testResult)) {
|
||||
return k;
|
||||
}
|
||||
|
||||
// 6e. Increase k by 1. (done by the loop).
|
||||
}
|
||||
return Convert<Smi>(-1);
|
||||
}
|
||||
|
||||
transitioning macro FastArrayFindIndex(implicit context: Context)(
|
||||
o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Number
|
||||
labels Bailout(Smi) {
|
||||
let k: Smi = 0;
|
||||
const smiLen = Cast<Smi>(len) otherwise goto Bailout(k);
|
||||
const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k);
|
||||
let fastOW = FastJSArrayWitness{fastO};
|
||||
|
||||
// Build a fast loop over the smi array.
|
||||
for (; k < smiLen; k++) {
|
||||
fastOW.Recheck() otherwise goto Bailout(k);
|
||||
|
||||
// Ensure that we haven't walked beyond a possibly updated length.
|
||||
if (k >= fastOW.Get().length) goto Bailout(k);
|
||||
|
||||
const value: Object = fastOW.LoadElementOrUndefined(k);
|
||||
const testResult: Object =
|
||||
Call(context, callbackfn, thisArg, value, k, fastOW.Get());
|
||||
if (ToBoolean(testResult)) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
|
||||
transitioning javascript builtin
|
||||
ArrayPrototypeFindIndex(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 NotCallableError;
|
||||
}
|
||||
const callbackfn =
|
||||
Cast<Callable>(arguments[0]) otherwise NotCallableError;
|
||||
|
||||
// 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 FastArrayFindIndex(o, len, callbackfn, thisArg)
|
||||
otherwise Bailout;
|
||||
}
|
||||
label Bailout(k: Smi) deferred {
|
||||
return ArrayFindIndexLoopContinuation(
|
||||
o, callbackfn, thisArg, o, k, len);
|
||||
}
|
||||
}
|
||||
label NotCallableError deferred {
|
||||
ThrowTypeError(kCalledNonCallable, arguments[0]);
|
||||
}
|
||||
label NullOrUndefinedError deferred {
|
||||
ThrowTypeError(kCalledOnNullOrUndefined, 'Array.prototype.findIndex');
|
||||
}
|
||||
}
|
||||
}
|
@ -1526,6 +1526,15 @@ struct FastJSArrayWitness {
|
||||
}
|
||||
}
|
||||
|
||||
LoadElementOrUndefined(implicit context: Context)(k: Smi): Object {
|
||||
try {
|
||||
return this.LoadElementNoHole(k) otherwise FoundHole;
|
||||
}
|
||||
label FoundHole {
|
||||
return Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
stable: JSArray;
|
||||
unstable: FastJSArray;
|
||||
map: Map;
|
||||
|
@ -233,97 +233,6 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
|
||||
argc_ = argc;
|
||||
}
|
||||
|
||||
void ArrayBuiltinsAssembler::GenerateIteratingArrayBuiltinBody(
|
||||
const char* name, const BuiltinResultGenerator& generator,
|
||||
const CallResultProcessor& processor, const PostLoopAction& action,
|
||||
const Callable& slow_case_continuation,
|
||||
MissingPropertyMode missing_property_mode, ForEachDirection direction) {
|
||||
Label non_array(this), array_changes(this, {&k_, &a_, &to_});
|
||||
|
||||
// TODO(danno): Seriously? Do we really need to throw the exact error
|
||||
// message on null and undefined so that the webkit tests pass?
|
||||
Label throw_null_undefined_exception(this, Label::kDeferred);
|
||||
GotoIf(IsNullOrUndefined(receiver()), &throw_null_undefined_exception);
|
||||
|
||||
// By the book: taken directly from the ECMAScript 2015 specification
|
||||
|
||||
// 1. Let O be ToObject(this value).
|
||||
// 2. ReturnIfAbrupt(O)
|
||||
o_ = ToObject_Inline(context(), receiver());
|
||||
|
||||
// 3. Let len be ToLength(Get(O, "length")).
|
||||
// 4. ReturnIfAbrupt(len).
|
||||
TVARIABLE(Number, merged_length);
|
||||
Label has_length(this, &merged_length), not_js_array(this);
|
||||
GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), ¬_js_array);
|
||||
merged_length = LoadJSArrayLength(CAST(o()));
|
||||
Goto(&has_length);
|
||||
|
||||
BIND(¬_js_array);
|
||||
{
|
||||
Node* len_property =
|
||||
GetProperty(context(), o(), isolate()->factory()->length_string());
|
||||
merged_length = ToLength_Inline(context(), len_property);
|
||||
Goto(&has_length);
|
||||
}
|
||||
BIND(&has_length);
|
||||
{
|
||||
len_ = merged_length.value();
|
||||
|
||||
// 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
|
||||
Label type_exception(this, Label::kDeferred);
|
||||
Label done(this);
|
||||
GotoIf(TaggedIsSmi(callbackfn()), &type_exception);
|
||||
Branch(IsCallableMap(LoadMap(callbackfn())), &done, &type_exception);
|
||||
|
||||
BIND(&throw_null_undefined_exception);
|
||||
ThrowTypeError(context(), MessageTemplate::kCalledOnNullOrUndefined,
|
||||
name);
|
||||
|
||||
BIND(&type_exception);
|
||||
ThrowTypeError(context(), MessageTemplate::kCalledNonCallable,
|
||||
callbackfn());
|
||||
|
||||
BIND(&done);
|
||||
}
|
||||
|
||||
// 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
||||
// [Already done by the arguments adapter]
|
||||
|
||||
if (direction == ForEachDirection::kForward) {
|
||||
// 7. Let k be 0.
|
||||
k_.Bind(SmiConstant(0));
|
||||
} else {
|
||||
k_.Bind(NumberDec(len()));
|
||||
}
|
||||
|
||||
generator(this);
|
||||
|
||||
HandleFastElements(processor, action, &fully_spec_compliant_, direction,
|
||||
missing_property_mode);
|
||||
|
||||
BIND(&fully_spec_compliant_);
|
||||
|
||||
Node* result =
|
||||
CallStub(slow_case_continuation, context(), receiver(), callbackfn(),
|
||||
this_arg(), a_.value(), o(), k_.value(), len(), to_.value());
|
||||
ReturnFromBuiltin(result);
|
||||
}
|
||||
|
||||
void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinLoopContinuation(
|
||||
TNode<Context> context, TNode<Object> receiver, Node* callbackfn,
|
||||
Node* this_arg, Node* a, TNode<JSReceiver> o, Node* initial_k,
|
||||
TNode<Number> len, Node* to) {
|
||||
context_ = context;
|
||||
this_arg_ = this_arg;
|
||||
callbackfn_ = callbackfn;
|
||||
a_.Bind(a);
|
||||
k_.Bind(initial_k);
|
||||
o_ = o;
|
||||
len_ = len;
|
||||
to_.Bind(to);
|
||||
}
|
||||
|
||||
void ArrayBuiltinsAssembler::GenerateIteratingTypedArrayBuiltinBody(
|
||||
const char* name, const BuiltinResultGenerator& generator,
|
||||
const CallResultProcessor& processor, const PostLoopAction& action,
|
||||
@ -410,65 +319,6 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayBuiltinsAssembler::GenerateIteratingArrayBuiltinLoopContinuation(
|
||||
const CallResultProcessor& processor, const PostLoopAction& action,
|
||||
MissingPropertyMode missing_property_mode, ForEachDirection direction) {
|
||||
Label loop(this, {&k_, &a_, &to_});
|
||||
Label after_loop(this);
|
||||
Goto(&loop);
|
||||
BIND(&loop);
|
||||
{
|
||||
if (direction == ForEachDirection::kForward) {
|
||||
// 8. Repeat, while k < len
|
||||
GotoIfNumberGreaterThanOrEqual(k(), len_, &after_loop);
|
||||
} else {
|
||||
// OR
|
||||
// 10. Repeat, while k >= 0
|
||||
GotoIfNumberGreaterThanOrEqual(SmiConstant(-1), k(), &after_loop);
|
||||
}
|
||||
|
||||
Label done_element(this, &to_);
|
||||
// a. 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.
|
||||
CSA_ASSERT(this, IsSafeInteger(k()));
|
||||
|
||||
if (missing_property_mode == MissingPropertyMode::kSkip) {
|
||||
// b. Let kPresent be HasProperty(O, Pk).
|
||||
// c. ReturnIfAbrupt(kPresent).
|
||||
TNode<Oddball> k_present =
|
||||
HasProperty(context(), o(), k(), kHasProperty);
|
||||
|
||||
// d. If kPresent is true, then
|
||||
GotoIf(IsFalse(k_present), &done_element);
|
||||
}
|
||||
|
||||
// i. Let kValue be Get(O, Pk).
|
||||
// ii. ReturnIfAbrupt(kValue).
|
||||
Node* k_value = GetProperty(context(), o(), k());
|
||||
|
||||
// iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
|
||||
// iv. ReturnIfAbrupt(funcResult).
|
||||
a_.Bind(processor(this, k_value, k()));
|
||||
Goto(&done_element);
|
||||
|
||||
BIND(&done_element);
|
||||
|
||||
if (direction == ForEachDirection::kForward) {
|
||||
// e. Increase k by 1.
|
||||
k_.Bind(NumberInc(k()));
|
||||
} else {
|
||||
// e. Decrease k by 1.
|
||||
k_.Bind(NumberDec(k()));
|
||||
}
|
||||
Goto(&loop);
|
||||
}
|
||||
BIND(&after_loop);
|
||||
|
||||
action(this);
|
||||
Return(a_.value());
|
||||
}
|
||||
|
||||
ElementsKind ArrayBuiltinsAssembler::ElementsKindForInstanceType(
|
||||
InstanceType type) {
|
||||
switch (type) {
|
||||
@ -516,133 +366,6 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
|
||||
advance_mode);
|
||||
}
|
||||
|
||||
void ArrayBuiltinsAssembler::VisitAllFastElementsOneKind(
|
||||
ElementsKind kind, const CallResultProcessor& processor,
|
||||
Label* array_changed, ParameterMode mode, ForEachDirection direction,
|
||||
MissingPropertyMode missing_property_mode, TNode<Smi> length) {
|
||||
Comment("begin VisitAllFastElementsOneKind");
|
||||
// We only use this kind of processing if the no-elements protector is
|
||||
// in place at the start. We'll continue checking during array iteration.
|
||||
CSA_ASSERT(this, Word32BinaryNot(IsNoElementsProtectorCellInvalid()));
|
||||
VARIABLE(original_map, MachineRepresentation::kTagged);
|
||||
original_map.Bind(LoadMap(o()));
|
||||
VariableList list({&original_map, &a_, &k_, &to_}, zone());
|
||||
Node* start = IntPtrOrSmiConstant(0, mode);
|
||||
Node* end = TaggedToParameter(length, mode);
|
||||
IndexAdvanceMode advance_mode = direction == ForEachDirection::kReverse
|
||||
? IndexAdvanceMode::kPre
|
||||
: IndexAdvanceMode::kPost;
|
||||
if (direction == ForEachDirection::kReverse) std::swap(start, end);
|
||||
BuildFastLoop(
|
||||
list, start, end,
|
||||
[=, &original_map](Node* index) {
|
||||
k_.Bind(ParameterToTagged(index, mode));
|
||||
Label one_element_done(this), hole_element(this),
|
||||
process_element(this);
|
||||
|
||||
// Check if o's map has changed during the callback. If so, we have to
|
||||
// fall back to the slower spec implementation for the rest of the
|
||||
// iteration.
|
||||
Node* o_map = LoadMap(o());
|
||||
GotoIf(WordNotEqual(o_map, original_map.value()), array_changed);
|
||||
|
||||
TNode<JSArray> o_array = CAST(o());
|
||||
// Check if o's length has changed during the callback and if the
|
||||
// index is now out of range of the new length.
|
||||
GotoIf(SmiGreaterThanOrEqual(CAST(k_.value()),
|
||||
CAST(LoadJSArrayLength(o_array))),
|
||||
array_changed);
|
||||
|
||||
// Re-load the elements array. If may have been resized.
|
||||
Node* elements = LoadElements(o_array);
|
||||
|
||||
// Fast case: load the element directly from the elements FixedArray
|
||||
// and call the callback if the element is not the hole.
|
||||
DCHECK(kind == PACKED_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS);
|
||||
int base_size = kind == PACKED_ELEMENTS
|
||||
? FixedArray::kHeaderSize
|
||||
: (FixedArray::kHeaderSize - kHeapObjectTag);
|
||||
Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size);
|
||||
VARIABLE(value, MachineRepresentation::kTagged);
|
||||
if (kind == PACKED_ELEMENTS) {
|
||||
value.Bind(LoadObjectField(elements, offset));
|
||||
GotoIf(WordEqual(value.value(), TheHoleConstant()), &hole_element);
|
||||
} else {
|
||||
Node* double_value =
|
||||
LoadDoubleWithHoleCheck(elements, offset, &hole_element);
|
||||
value.Bind(AllocateHeapNumberWithValue(double_value));
|
||||
}
|
||||
Goto(&process_element);
|
||||
|
||||
BIND(&hole_element);
|
||||
if (missing_property_mode == MissingPropertyMode::kSkip) {
|
||||
// The NoElementsProtectorCell could go invalid during callbacks.
|
||||
Branch(IsNoElementsProtectorCellInvalid(), array_changed,
|
||||
&one_element_done);
|
||||
} else {
|
||||
value.Bind(UndefinedConstant());
|
||||
Goto(&process_element);
|
||||
}
|
||||
BIND(&process_element);
|
||||
{
|
||||
a_.Bind(processor(this, value.value(), k()));
|
||||
Goto(&one_element_done);
|
||||
}
|
||||
BIND(&one_element_done);
|
||||
},
|
||||
1, mode, advance_mode);
|
||||
Comment("end VisitAllFastElementsOneKind");
|
||||
}
|
||||
|
||||
void ArrayBuiltinsAssembler::HandleFastElements(
|
||||
const CallResultProcessor& processor, const PostLoopAction& action,
|
||||
Label* slow, ForEachDirection direction,
|
||||
MissingPropertyMode missing_property_mode) {
|
||||
Label switch_on_elements_kind(this), fast_elements(this),
|
||||
maybe_double_elements(this), fast_double_elements(this);
|
||||
|
||||
Comment("begin HandleFastElements");
|
||||
// Non-smi lengths must use the slow path.
|
||||
GotoIf(TaggedIsNotSmi(len()), slow);
|
||||
|
||||
BranchIfFastJSArray(o(), context(),
|
||||
&switch_on_elements_kind, slow);
|
||||
|
||||
BIND(&switch_on_elements_kind);
|
||||
TNode<Smi> smi_len = CAST(len());
|
||||
// Select by ElementsKind
|
||||
Node* kind = LoadElementsKind(o());
|
||||
Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
|
||||
&maybe_double_elements, &fast_elements);
|
||||
|
||||
ParameterMode mode = OptimalParameterMode();
|
||||
BIND(&fast_elements);
|
||||
{
|
||||
VisitAllFastElementsOneKind(PACKED_ELEMENTS, processor, slow, mode,
|
||||
direction, missing_property_mode, smi_len);
|
||||
|
||||
action(this);
|
||||
|
||||
// No exception, return success
|
||||
ReturnFromBuiltin(a_.value());
|
||||
}
|
||||
|
||||
BIND(&maybe_double_elements);
|
||||
Branch(IsElementsKindGreaterThan(kind, HOLEY_DOUBLE_ELEMENTS), slow,
|
||||
&fast_double_elements);
|
||||
|
||||
BIND(&fast_double_elements);
|
||||
{
|
||||
VisitAllFastElementsOneKind(PACKED_DOUBLE_ELEMENTS, processor, slow, mode,
|
||||
direction, missing_property_mode, smi_len);
|
||||
|
||||
action(this);
|
||||
|
||||
// No exception, return success
|
||||
ReturnFromBuiltin(a_.value());
|
||||
}
|
||||
}
|
||||
|
||||
// Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
|
||||
void ArrayBuiltinsAssembler::GenerateArraySpeciesCreate(TNode<Number> len) {
|
||||
Label runtime(this, Label::kDeferred), done(this);
|
||||
@ -1085,199 +808,6 @@ TF_BUILTIN(CloneFastJSArrayFillingHoles, ArrayBuiltinsAssembler) {
|
||||
HoleConversionMode::kConvertToUndefined));
|
||||
}
|
||||
|
||||
TF_BUILTIN(ArrayFindLoopContinuation, 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::FindProcessor,
|
||||
&ArrayBuiltinsAssembler::NullPostLoopAction,
|
||||
MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
|
||||
}
|
||||
|
||||
// Continuation that is called after an eager deoptimization from TF (ex. the
|
||||
// array changes during iteration).
|
||||
TF_BUILTIN(ArrayFindLoopEagerDeoptContinuation, 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::kArrayFindLoopContinuation, context, receiver,
|
||||
callbackfn, this_arg, UndefinedConstant(), receiver,
|
||||
initial_k, len, UndefinedConstant()));
|
||||
}
|
||||
|
||||
// Continuation that is called after a lazy deoptimization from TF (ex. the
|
||||
// callback function is no longer callable).
|
||||
TF_BUILTIN(ArrayFindLoopLazyDeoptContinuation, 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::kArrayFindLoopContinuation, context, receiver,
|
||||
callbackfn, this_arg, UndefinedConstant(), receiver,
|
||||
initial_k, len, UndefinedConstant()));
|
||||
}
|
||||
|
||||
// Continuation that is called after a lazy deoptimization from TF that happens
|
||||
// right after the callback and it's returned value must be handled before
|
||||
// iteration continues.
|
||||
TF_BUILTIN(ArrayFindLoopAfterCallbackLazyDeoptContinuation,
|
||||
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* found_value = Parameter(Descriptor::kFoundValue);
|
||||
Node* is_found = Parameter(Descriptor::kIsFound);
|
||||
|
||||
// This custom lazy deopt point is right after the callback. find() needs
|
||||
// to pick up at the next step, which is returning the element if the callback
|
||||
// value is truthy. Otherwise, continue the search by calling the
|
||||
// continuation.
|
||||
Label if_true(this), if_false(this);
|
||||
BranchIfToBooleanIsTrue(is_found, &if_true, &if_false);
|
||||
BIND(&if_true);
|
||||
Return(found_value);
|
||||
BIND(&if_false);
|
||||
Return(CallBuiltin(Builtins::kArrayFindLoopContinuation, context, receiver,
|
||||
callbackfn, this_arg, UndefinedConstant(), receiver,
|
||||
initial_k, len, UndefinedConstant()));
|
||||
}
|
||||
|
||||
// ES #sec-get-%typedarray%.prototype.find
|
||||
TF_BUILTIN(ArrayPrototypeFind, 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.find", &ArrayBuiltinsAssembler::FindResultGenerator,
|
||||
&ArrayBuiltinsAssembler::FindProcessor,
|
||||
&ArrayBuiltinsAssembler::NullPostLoopAction,
|
||||
Builtins::CallableFor(isolate(), Builtins::kArrayFindLoopContinuation),
|
||||
MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
|
||||
}
|
||||
|
||||
TF_BUILTIN(ArrayFindIndexLoopContinuation, 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::FindIndexProcessor,
|
||||
&ArrayBuiltinsAssembler::NullPostLoopAction,
|
||||
MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
|
||||
}
|
||||
|
||||
TF_BUILTIN(ArrayFindIndexLoopEagerDeoptContinuation, 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::kArrayFindIndexLoopContinuation, context,
|
||||
receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
|
||||
initial_k, len, UndefinedConstant()));
|
||||
}
|
||||
|
||||
TF_BUILTIN(ArrayFindIndexLoopLazyDeoptContinuation, 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::kArrayFindIndexLoopContinuation, context,
|
||||
receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
|
||||
initial_k, len, UndefinedConstant()));
|
||||
}
|
||||
|
||||
TF_BUILTIN(ArrayFindIndexLoopAfterCallbackLazyDeoptContinuation,
|
||||
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* found_value = Parameter(Descriptor::kFoundValue);
|
||||
Node* is_found = Parameter(Descriptor::kIsFound);
|
||||
|
||||
// This custom lazy deopt point is right after the callback. find() needs
|
||||
// to pick up at the next step, which is returning the element if the callback
|
||||
// value is truthy. Otherwise, continue the search by calling the
|
||||
// continuation.
|
||||
Label if_true(this), if_false(this);
|
||||
BranchIfToBooleanIsTrue(is_found, &if_true, &if_false);
|
||||
BIND(&if_true);
|
||||
Return(found_value);
|
||||
BIND(&if_false);
|
||||
Return(CallBuiltin(Builtins::kArrayFindIndexLoopContinuation, context,
|
||||
receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
|
||||
initial_k, len, UndefinedConstant()));
|
||||
}
|
||||
|
||||
// ES #sec-get-%typedarray%.prototype.findIndex
|
||||
TF_BUILTIN(ArrayPrototypeFindIndex, 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.findIndex",
|
||||
&ArrayBuiltinsAssembler::FindIndexResultGenerator,
|
||||
&ArrayBuiltinsAssembler::FindIndexProcessor,
|
||||
&ArrayBuiltinsAssembler::NullPostLoopAction,
|
||||
Builtins::CallableFor(isolate(),
|
||||
Builtins::kArrayFindIndexLoopContinuation),
|
||||
MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
|
||||
}
|
||||
|
||||
class ArrayPopulatorAssembler : public CodeStubAssembler {
|
||||
public:
|
||||
explicit ArrayPopulatorAssembler(compiler::CodeAssemblerState* state)
|
||||
|
@ -23,8 +23,6 @@ class ArrayBuiltinsAssembler : public CodeStubAssembler {
|
||||
|
||||
typedef std::function<void(ArrayBuiltinsAssembler* masm)> PostLoopAction;
|
||||
|
||||
enum class MissingPropertyMode { kSkip, kUseUndefined };
|
||||
|
||||
void FindResultGenerator();
|
||||
|
||||
Node* FindProcessor(Node* k_value, Node* k);
|
||||
@ -51,12 +49,6 @@ class ArrayBuiltinsAssembler : public CodeStubAssembler {
|
||||
|
||||
void ReducePostLoopAction();
|
||||
|
||||
void FilterResultGenerator();
|
||||
|
||||
Node* FilterProcessor(Node* k_value, Node* k);
|
||||
|
||||
void MapResultGenerator();
|
||||
|
||||
void TypedArrayMapResultGenerator();
|
||||
|
||||
Node* SpecCompliantMapProcessor(Node* k_value, Node* k);
|
||||
@ -106,27 +98,11 @@ class ArrayBuiltinsAssembler : public CodeStubAssembler {
|
||||
TNode<Object> receiver, Node* callbackfn,
|
||||
Node* this_arg, TNode<IntPtrT> argc);
|
||||
|
||||
void GenerateIteratingArrayBuiltinBody(
|
||||
const char* name, const BuiltinResultGenerator& generator,
|
||||
const CallResultProcessor& processor, const PostLoopAction& action,
|
||||
const Callable& slow_case_continuation,
|
||||
MissingPropertyMode missing_property_mode,
|
||||
ForEachDirection direction = ForEachDirection::kForward);
|
||||
void InitIteratingArrayBuiltinLoopContinuation(
|
||||
TNode<Context> context, TNode<Object> receiver, Node* callbackfn,
|
||||
Node* this_arg, Node* a, TNode<JSReceiver> o, Node* initial_k,
|
||||
TNode<Number> len, Node* to);
|
||||
|
||||
void GenerateIteratingTypedArrayBuiltinBody(
|
||||
const char* name, const BuiltinResultGenerator& generator,
|
||||
const CallResultProcessor& processor, const PostLoopAction& action,
|
||||
ForEachDirection direction = ForEachDirection::kForward);
|
||||
|
||||
void GenerateIteratingArrayBuiltinLoopContinuation(
|
||||
const CallResultProcessor& processor, const PostLoopAction& action,
|
||||
MissingPropertyMode missing_property_mode,
|
||||
ForEachDirection direction = ForEachDirection::kForward);
|
||||
|
||||
void TailCallArrayConstructorStub(
|
||||
const Callable& callable, TNode<Context> context,
|
||||
TNode<JSFunction> target, TNode<HeapObject> allocation_site_or_undefined,
|
||||
@ -167,18 +143,6 @@ class ArrayBuiltinsAssembler : public CodeStubAssembler {
|
||||
Label* detached, ForEachDirection direction,
|
||||
TNode<JSTypedArray> typed_array);
|
||||
|
||||
void VisitAllFastElementsOneKind(ElementsKind kind,
|
||||
const CallResultProcessor& processor,
|
||||
Label* array_changed, ParameterMode mode,
|
||||
ForEachDirection direction,
|
||||
MissingPropertyMode missing_property_mode,
|
||||
TNode<Smi> length);
|
||||
|
||||
void HandleFastElements(const CallResultProcessor& processor,
|
||||
const PostLoopAction& action, Label* slow,
|
||||
ForEachDirection direction,
|
||||
MissingPropertyMode missing_property_mode);
|
||||
|
||||
// Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
|
||||
// This version is specialized to create a zero length array
|
||||
// of the elements kind of the input array.
|
||||
|
@ -352,27 +352,6 @@ namespace internal {
|
||||
TFS(ExtractFastJSArray, kSource, kBegin, kCount) \
|
||||
/* ES6 #sec-array.prototype.entries */ \
|
||||
TFJ(ArrayPrototypeEntries, 0, kReceiver) \
|
||||
/* ES6 #sec-array.prototype.find */ \
|
||||
TFS(ArrayFindLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
|
||||
kObject, kInitialK, kLength, kTo) \
|
||||
TFJ(ArrayFindLoopEagerDeoptContinuation, 4, kReceiver, kCallbackFn, \
|
||||
kThisArg, kInitialK, kLength) \
|
||||
TFJ(ArrayFindLoopLazyDeoptContinuation, 5, kReceiver, kCallbackFn, kThisArg, \
|
||||
kInitialK, kLength, kResult) \
|
||||
TFJ(ArrayFindLoopAfterCallbackLazyDeoptContinuation, 6, kReceiver, \
|
||||
kCallbackFn, kThisArg, kInitialK, kLength, kFoundValue, kIsFound) \
|
||||
TFJ(ArrayPrototypeFind, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-array.prototype.findIndex */ \
|
||||
TFS(ArrayFindIndexLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
|
||||
kArray, kObject, kInitialK, kLength, kTo) \
|
||||
TFJ(ArrayFindIndexLoopEagerDeoptContinuation, 4, kReceiver, kCallbackFn, \
|
||||
kThisArg, kInitialK, kLength) \
|
||||
TFJ(ArrayFindIndexLoopLazyDeoptContinuation, 5, kReceiver, kCallbackFn, \
|
||||
kThisArg, kInitialK, kLength, kResult) \
|
||||
TFJ(ArrayFindIndexLoopAfterCallbackLazyDeoptContinuation, 6, kReceiver, \
|
||||
kCallbackFn, kThisArg, kInitialK, kLength, kFoundValue, kIsFound) \
|
||||
TFJ(ArrayPrototypeFindIndex, \
|
||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-array.prototype.keys */ \
|
||||
TFJ(ArrayPrototypeKeys, 0, kReceiver) \
|
||||
/* ES6 #sec-array.prototype.values */ \
|
||||
|
Loading…
Reference in New Issue
Block a user