Index: src/builtins/builtins-array-gen.cc |
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
index 4764d2341bb1808b556f362ba50d4c4977365f9d..f8163ff345f5a22543856f2bac01a158691bc9f0 100644 |
--- a/src/builtins/builtins-array-gen.cc |
+++ b/src/builtins/builtins-array-gen.cc |
@@ -194,7 +194,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
void GenerateIteratingArrayBuiltinBody( |
const char* name, const BuiltinResultGenerator& generator, |
const CallResultProcessor& processor, const PostLoopAction& action, |
- const Callable& slow_case_continuation) { |
+ const Callable& slow_case_continuation, |
+ ForEachDirection direction = ForEachDirection::kForward) { |
Label non_array(this), slow(this, {&k_, &a_, &to_}), |
array_changes(this, {&k_, &a_, &to_}); |
@@ -256,12 +257,17 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
// 6. If thisArg was supplied, let T be thisArg; else let T be undefined. |
// [Already done by the arguments adapter] |
- // 7. Let k be 0. |
- // [Already done in code assembler initialization] |
+ if (direction == ForEachDirection::kForward) { |
+ // 7. Let k be 0. |
+ k_.Bind(SmiConstant(0)); |
+ } else { |
+ k_.Bind(len()); |
+ k_.Bind(NumberDec(k_.value())); |
+ } |
a_.Bind(generator(this)); |
- HandleFastElements(processor, action, &slow); |
+ HandleFastElements(processor, action, &slow, direction); |
Bind(&slow); |
@@ -290,14 +296,21 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
} |
void GenerateIteratingArrayBuiltinLoopContinuation( |
- const CallResultProcessor& processor, const PostLoopAction& action) { |
- // 8. Repeat, while k < len |
+ const CallResultProcessor& processor, const PostLoopAction& action, |
+ ForEachDirection direction = ForEachDirection::kForward) { |
Label loop(this, {&k_, &a_, &to_}); |
Label after_loop(this); |
Goto(&loop); |
Bind(&loop); |
{ |
- GotoUnlessNumberLessThan(k(), len_, &after_loop); |
+ if (direction == ForEachDirection::kForward) { |
+ // 8. Repeat, while k < len |
+ GotoUnlessNumberLessThan(k(), len_, &after_loop); |
+ } else { |
+ // OR |
+ // 10. Repeat, while k >= 0 |
+ GotoUnlessNumberLessThan(SmiConstant(-1), k(), &after_loop); |
+ } |
Label done_element(this, &to_); |
// a. Let Pk be ToString(k). |
@@ -321,8 +334,13 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Bind(&done_element); |
- // e. Increase k by 1. |
- k_.Bind(NumberInc(k_.value())); |
+ 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); |
@@ -334,13 +352,20 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
private: |
void VisitAllFastElementsOneKind(ElementsKind kind, |
const CallResultProcessor& processor, |
- Label* array_changed, ParameterMode mode) { |
+ Label* array_changed, ParameterMode mode, |
+ ForEachDirection direction) { |
Comment("begin VisitAllFastElementsOneKind"); |
Variable original_map(this, MachineRepresentation::kTagged); |
original_map.Bind(LoadMap(o())); |
VariableList list({&original_map, &a_, &k_, &to_}, zone()); |
+ Node* start = IntPtrOrSmiConstant(0, mode); |
+ Node* end = TaggedToParameter(len(), mode); |
+ IndexAdvanceMode advance_mode = direction == ForEachDirection::kReverse |
+ ? IndexAdvanceMode::kPre |
+ : IndexAdvanceMode::kPost; |
+ if (direction == ForEachDirection::kReverse) std::swap(start, end); |
BuildFastLoop( |
- list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len(), mode), |
+ list, start, end, |
[=, &original_map](Node* index) { |
k_.Bind(ParameterToTagged(index, mode)); |
Label one_element_done(this), hole_element(this); |
@@ -386,12 +411,13 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Bind(&one_element_done); |
}, |
- 1, mode, IndexAdvanceMode::kPost); |
+ 1, mode, advance_mode); |
Comment("end VisitAllFastElementsOneKind"); |
} |
void HandleFastElements(const CallResultProcessor& processor, |
- const PostLoopAction& action, Label* slow) { |
+ const PostLoopAction& action, Label* slow, |
+ ForEachDirection direction) { |
Label switch_on_elements_kind(this), fast_elements(this), |
maybe_double_elements(this), fast_double_elements(this); |
@@ -414,7 +440,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
ParameterMode mode = OptimalParameterMode(); |
Bind(&fast_elements); |
{ |
- VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode); |
+ VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode, |
+ direction); |
action(this); |
@@ -428,7 +455,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Bind(&fast_double_elements); |
{ |
- VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode); |
+ VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode, |
+ direction); |
action(this); |
@@ -757,6 +785,46 @@ TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) { |
CodeFactory::ArrayReduceLoopContinuation(isolate())); |
} |
+TF_BUILTIN(ArrayReduceRightLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
+ Node* context = Parameter(Descriptor::kContext); |
+ Node* receiver = Parameter(Descriptor::kReceiver); |
+ Node* callbackfn = Parameter(Descriptor::kCallbackFn); |
+ Node* this_arg = Parameter(Descriptor::kThisArg); |
+ Node* accumulator = Parameter(Descriptor::kAccumulator); |
+ Node* object = Parameter(Descriptor::kObject); |
+ Node* initial_k = Parameter(Descriptor::kInitialK); |
+ Node* len = Parameter(Descriptor::kLength); |
+ Node* to = Parameter(Descriptor::kTo); |
+ |
+ InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn, |
+ this_arg, accumulator, object, |
+ initial_k, len, to); |
+ |
+ GenerateIteratingArrayBuiltinLoopContinuation( |
+ &ArrayBuiltinCodeStubAssembler::ReduceProcessor, |
+ &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction, |
+ ForEachDirection::kReverse); |
+} |
+ |
+TF_BUILTIN(ArrayReduceRight, ArrayBuiltinCodeStubAssembler) { |
+ Node* context = Parameter(Descriptor::kContext); |
+ Node* receiver = Parameter(Descriptor::kReceiver); |
+ Node* callbackfn = Parameter(Descriptor::kCallbackFn); |
+ Node* initial_value = Parameter(Descriptor::kInitialValue); |
+ Node* new_target = Parameter(Descriptor::kNewTarget); |
+ |
+ InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value, |
+ new_target); |
+ |
+ GenerateIteratingArrayBuiltinBody( |
+ "Array.prototype.reduceRight", |
+ &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator, |
+ &ArrayBuiltinCodeStubAssembler::ReduceProcessor, |
+ &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction, |
+ CodeFactory::ArrayReduceRightLoopContinuation(isolate()), |
+ ForEachDirection::kReverse); |
+} |
+ |
TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
Node* context = Parameter(Descriptor::kContext); |
Node* receiver = Parameter(Descriptor::kReceiver); |