Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Unified Diff: src/builtins/builtins-array-gen.cc

Issue 2752273003: [builtins] Implement Array.prototype.reduce in the CSA (Closed)
Patch Set: Cleanup Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/builtins-array-gen.cc
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc
index 75ec67e05494155f0ee3e29b74fbfaf1c2a5f6a9..8080fdc728a7385164426832ac9fbea0fb2eb1ab 100644
--- a/src/builtins/builtins-array-gen.cc
+++ b/src/builtins/builtins-array-gen.cc
@@ -14,13 +14,22 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
- typedef std::function<Node*(Node* o, Node* len)> BuiltinResultGenerator;
- typedef std::function<void(Node* a, Node* pK, Node* value)>
+ typedef std::function<std::pair<Node*, Node*>(
danno 2017/03/17 10:26:31 Per Camillo's comments, I am going to add comments
+ ArrayBuiltinCodeStubAssembler* masm, Node* this_arg, Node* o, Node* len)>
+ BuiltinResultGenerator;
+
+ typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm,
+ Node* context, Node* callbackfn, Node* this_arg,
+ Node* k_value, Node* k, Node* o, Node* a)>
CallResultProcessor;
+ typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm, Node* context,
+ Node* a)>
+ PostLoopAction;
+
void GenerateIteratingArrayBuiltinBody(
const char* name, const BuiltinResultGenerator& generator,
- const CallResultProcessor& processor,
+ const CallResultProcessor& processor, const PostLoopAction& action,
const Callable& slow_case_continuation) {
Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver);
Node* callbackfn = Parameter(IteratingArrayBuiltinDescriptor::kCallback);
@@ -29,7 +38,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget);
Variable k(this, MachineRepresentation::kTagged, SmiConstant(0));
- Label non_array(this), slow(this, &k), array_changes(this, &k);
+ Variable a(this, MachineRepresentation::kTagged, UndefinedConstant());
+ Label non_array(this), slow(this, {&k, &a}), array_changes(this, {&k, &a});
// TODO(danno): Seriously? Do we really need to throw the exact error
// message on null and undefined so that the webkit tests pass?
@@ -85,16 +95,19 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
Bind(&done);
- Node* a = generator(o, len);
+ Node* initial_a;
+ Node* initial_k;
+ std::tie(initial_a, initial_k) = generator(this, this_arg, o, len);
// 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
// [Already done by the arguments adapter]
- HandleFastElements(context, this_arg, o, len, callbackfn, processor, a, k,
- &slow);
-
// 7. Let k be 0.
- // Already done above in initialization of the Variable k
+ k.Bind(initial_k);
+ a.Bind(initial_a);
+
+ HandleFastElements(context, this_arg, o, len, callbackfn, processor, action,
+ a, k, &slow);
Bind(&slow);
@@ -103,16 +116,16 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
TailCallStub(
slow_case_continuation, context, target, new_target,
Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity),
- receiver, callbackfn, this_arg, a, o, k.value(), len);
+ receiver, callbackfn, this_arg, a.value(), o, k.value(), len);
}
void GenerateIteratingArrayBuiltinLoopContinuation(
- const CallResultProcessor& processor) {
+ const CallResultProcessor& processor, const PostLoopAction& action) {
Node* callbackfn =
Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback);
Node* this_arg =
Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg);
- Node* a =
+ Node* initial_a =
Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray);
Node* o =
Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject);
@@ -125,7 +138,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
// 8. Repeat, while k < len
Variable k(this, MachineRepresentation::kTagged, initial_k);
- Label loop(this, &k);
+ Variable a(this, MachineRepresentation::kTagged, initial_a);
+ Label loop(this, {&k, &a});
Label after_loop(this);
Goto(&loop);
Bind(&loop);
@@ -149,10 +163,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
// iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
// iv. ReturnIfAbrupt(funcResult).
- Node* result = CallJS(CodeFactory::Call(isolate()), context, callbackfn,
- this_arg, k_value, k.value(), o);
-
- processor(a, p_k, result);
+ a.Bind(processor(this, context, callbackfn, this_arg, k_value, k.value(),
+ o, a.value()));
Goto(&done_element);
Bind(&done_element);
@@ -161,42 +173,136 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
Goto(&loop);
}
Bind(&after_loop);
- Return(a);
+
+ action(this, context, a.value());
+
+ Return(a.value());
}
- void ForEachProcessor(Node* a, Node* p_k, Node* value) {}
+ std::pair<Node*, Node*> ForEachResultGenerator(Node* this_arg, Node* o,
+ Node* len) {
+ return std::make_pair(UndefinedConstant(), SmiConstant(0));
+ }
- void SomeProcessor(Node* a, Node* p_k, Node* value) {
+ Node* ForEachProcessor(Node* context, Node* callbackfn, Node* this_arg,
+ Node* k_value, Node* k, Node* o, Node* a) {
+ CallJS(CodeFactory::Call(isolate()), context, callbackfn, this_arg, k_value,
+ k, o);
+ return a;
+ }
+
+ std::pair<Node*, Node*> SomeResultGenerator(Node* this_arg, Node* o,
+ Node* len) {
+ return std::make_pair(FalseConstant(), SmiConstant(0));
+ }
+
+ Node* SomeProcessor(Node* context, Node* callbackfn, Node* this_arg,
+ Node* k_value, Node* k, Node* o, Node* a) {
+ Node* value = CallJS(CodeFactory::Call(isolate()), context, callbackfn,
+ this_arg, k_value, k, o);
Label false_continue(this), return_true(this);
BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
Bind(&return_true);
Return(TrueConstant());
Bind(&false_continue);
+ return a;
+ }
+
+ std::pair<Node*, Node*> EveryResultGenerator(Node* this_arg, Node* o,
+ Node* len) {
+ return std::make_pair(TrueConstant(), SmiConstant(0));
}
- void EveryProcessor(Node* a, Node* p_k, Node* value) {
+ Node* EveryProcessor(Node* context, Node* callbackfn, Node* this_arg,
+ Node* k_value, Node* k, Node* o, Node* a) {
+ Node* value = CallJS(CodeFactory::Call(isolate()), context, callbackfn,
+ this_arg, k_value, k, o);
Label true_continue(this), return_false(this);
BranchIfToBooleanIsTrue(value, &true_continue, &return_false);
Bind(&return_false);
Return(FalseConstant());
Bind(&true_continue);
+ return a;
+ }
+
+ std::pair<Node*, Node*> ReduceResultGenerator(Node* initial_value, Node* o,
+ Node* len) {
+ Variable a(this, MachineRepresentation::kTagged, UndefinedConstant());
+ Label no_initial_value(this), has_initial_value(this), done(this, {&a});
+
+ // 8. If initialValue is present, then
+ Node* parent_frame_ptr = LoadParentFramePointer();
+ Node* marker_or_function = LoadBufferObject(
+ parent_frame_ptr, CommonFrameConstants::kContextOrFrameTypeOffset);
+ GotoIf(
+ MarkerIsNotFrameType(marker_or_function, StackFrame::ARGUMENTS_ADAPTOR),
+ &has_initial_value);
+
+ // Has arguments adapter, check count.
+ Node* adapted_parameter_count = LoadBufferObject(
+ parent_frame_ptr, ArgumentsAdaptorFrameConstants::kLengthOffset);
+ Branch(SmiLessThan(adapted_parameter_count,
+ SmiConstant(IteratingArrayBuiltinDescriptor::kThisArg)),
+ &no_initial_value, &has_initial_value);
+
+ // a. Set accumulator to initialValue.
+ Bind(&has_initial_value);
+ a.Bind(initial_value);
+ Goto(&done);
+
+ // 9. Else initialValue is not present,
+ Bind(&no_initial_value);
+
+ // a. Let kPresent be false.
+ a.Bind(TheHoleConstant());
+ Goto(&done);
+ Bind(&done);
+ return std::make_pair(a.value(), SmiConstant(0));
}
+ Node* ReduceProcessor(Node* context, Node* callbackfn, Node* this_arg,
+ Node* k_value, Node* k, Node* o, Node* a) {
+ Variable result(this, MachineRepresentation::kTagged);
+ Label done(this, {&result}), initial(this);
+ GotoIf(WordEqual(a, TheHoleConstant()), &initial);
+ result.Bind(CallJS(CodeFactory::Call(isolate()), context, callbackfn,
+ UndefinedConstant(), a, k_value, k, o));
+ Goto(&done);
+
+ Bind(&initial);
+ result.Bind(k_value);
+ Goto(&done);
+
+ Bind(&done);
+ return result.value();
+ }
+
+ void ReducePostLoopAction(Node* context, Node* a) {
+ Label ok(this);
+ GotoIf(WordNotEqual(a, TheHoleConstant()), &ok);
+ CallRuntime(Runtime::kThrowTypeError, context,
+ SmiConstant(MessageTemplate::kReduceNoInitial));
+ Unreachable();
+ Bind(&ok);
+ }
+
+ void NullPostLoopAction(Node* context, Node* a) {}
+
private:
Node* VisitAllFastElementsOneKind(Node* context, ElementsKind kind,
Node* this_arg, Node* o, Node* len,
Node* callbackfn,
const CallResultProcessor& processor,
- Node* a, Label* array_changed,
+ Variable& a, Label* array_changed,
ParameterMode mode) {
Comment("begin VisitAllFastElementsOneKind");
Variable original_map(this, MachineRepresentation::kTagged);
original_map.Bind(LoadMap(o));
- VariableList list({&original_map}, zone());
+ VariableList list({&original_map, &a}, zone());
Node* last_index = nullptr;
BuildFastLoop(
list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len, mode),
- [=, &original_map, &last_index](Node* index) {
+ [=, &a, &original_map, &last_index](Node* index) {
last_index = index;
Label one_element_done(this), hole_element(this);
@@ -231,9 +337,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
LoadDoubleWithHoleCheck(elements, offset, &hole_element);
value = AllocateHeapNumberWithValue(double_value);
}
- Node* result = CallJS(CodeFactory::Call(isolate()), context,
- callbackfn, this_arg, value, tagged_index, o);
- processor(a, tagged_index, result);
+ a.Bind(processor(this, context, callbackfn, this_arg, value,
+ tagged_index, o, a.value()));
Goto(&one_element_done);
Bind(&hole_element);
@@ -250,8 +355,10 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
}
void HandleFastElements(Node* context, Node* this_arg, Node* o, Node* len,
- Node* callbackfn, CallResultProcessor processor,
- Node* a, Variable& k, Label* slow) {
+ Node* callbackfn,
+ const CallResultProcessor& processor,
+ const PostLoopAction& action, Variable& a,
+ Variable& k, Label* slow) {
Label switch_on_elements_kind(this), fast_elements(this),
maybe_double_elements(this), fast_double_elements(this);
@@ -279,8 +386,10 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
context, FAST_ELEMENTS, this_arg, o, len, callbackfn, processor, a,
&array_changed, mode);
+ action(this, context, a.value());
+
// No exception, return success
- Return(a);
+ Return(a.value());
Bind(&array_changed);
k.Bind(ParameterToTagged(last_index, mode));
@@ -298,8 +407,10 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
context, FAST_DOUBLE_ELEMENTS, this_arg, o, len, callbackfn,
processor, a, &array_changed, mode);
+ action(this, context, a.value());
+
// No exception, return success
- Return(a);
+ Return(a.value());
Bind(&array_changed);
k.Bind(ParameterToTagged(last_index, mode));
@@ -464,51 +575,64 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) {
GenerateIteratingArrayBuiltinLoopContinuation(
- [this](Node* a, Node* p_k, Node* value) {
- ForEachProcessor(a, p_k, value);
- });
+ &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) {
GenerateIteratingArrayBuiltinBody(
"Array.prototype.forEach",
- [=](Node*, Node*) { return UndefinedConstant(); },
- [this](Node* a, Node* p_k, Node* value) {
- ForEachProcessor(a, p_k, value);
- },
+ &ArrayBuiltinCodeStubAssembler::ForEachResultGenerator,
+ &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
CodeFactory::ArrayForEachLoopContinuation(isolate()));
}
TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) {
GenerateIteratingArrayBuiltinLoopContinuation(
- [this](Node* a, Node* p_k, Node* value) {
- SomeProcessor(a, p_k, value);
- });
+ &ArrayBuiltinCodeStubAssembler::SomeProcessor,
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) {
GenerateIteratingArrayBuiltinBody(
- "Array.prototype.some", [=](Node*, Node*) { return FalseConstant(); },
- [this](Node* a, Node* p_k, Node* value) { SomeProcessor(a, p_k, value); },
+ "Array.prototype.some",
+ &ArrayBuiltinCodeStubAssembler::SomeResultGenerator,
+ &ArrayBuiltinCodeStubAssembler::SomeProcessor,
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
CodeFactory::ArraySomeLoopContinuation(isolate()));
}
TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) {
GenerateIteratingArrayBuiltinLoopContinuation(
- [this](Node* a, Node* p_k, Node* value) {
- EveryProcessor(a, p_k, value);
- });
+ &ArrayBuiltinCodeStubAssembler::EveryProcessor,
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) {
GenerateIteratingArrayBuiltinBody(
- "Array.prototype.every", [=](Node*, Node*) { return TrueConstant(); },
- [this](Node* a, Node* p_k, Node* value) {
- EveryProcessor(a, p_k, value);
- },
+ "Array.prototype.every",
+ &ArrayBuiltinCodeStubAssembler::EveryResultGenerator,
+ &ArrayBuiltinCodeStubAssembler::EveryProcessor,
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
CodeFactory::ArrayEveryLoopContinuation(isolate()));
}
+TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) {
+ GenerateIteratingArrayBuiltinLoopContinuation(
+ &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
+ &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction);
+}
+
+TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) {
+ GenerateIteratingArrayBuiltinBody(
+ "Array.prototype.reduce",
+ &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
+ &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
+ &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
+ CodeFactory::ArrayReduceLoopContinuation(isolate()));
+}
+
TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
Node* object = Parameter(1);
Node* context = Parameter(4);
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698