Index: src/builtins/builtins-array-gen.cc |
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
index dd45c2ee4aad79bf879d518e568474d1aff99fc0..621b0de04851333c119d0f5f3438088200721066 100644 |
--- a/src/builtins/builtins-array-gen.cc |
+++ b/src/builtins/builtins-array-gen.cc |
@@ -12,10 +12,16 @@ namespace internal { |
class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
public: |
explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state) |
- : CodeStubAssembler(state) {} |
+ : CodeStubAssembler(state), to_(this, MachineRepresentation::kTagged) { |
+ to_.Bind(SmiConstant(0)); |
+ } |
- typedef std::function<Node*(Node* o, Node* len)> BuiltinResultGenerator; |
- typedef std::function<void(Node* a, Node* pK, Node* value)> |
+ typedef std::function<Node*(Node* context, Node* o, Node* len)> |
+ BuiltinResultGenerator; |
+ typedef std::function<void(Node* context, Node* a)> |
+ BuiltinResultIndexInitializer; |
+ typedef std::function<void(Node* context, Node* value, Node* a, |
+ Node* callback_result)> |
CallResultProcessor; |
void GenerateIteratingArrayBuiltinBody( |
@@ -87,7 +93,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Bind(&done); |
- Node* a = generator(o, len); |
+ Node* a = generator(context, o, len); |
// 6. If thisArg was supplied, let T be thisArg; else let T be undefined. |
// [Already done by the arguments adapter] |
@@ -109,6 +115,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
} |
void GenerateIteratingArrayBuiltinLoopContinuation( |
+ const BuiltinResultIndexInitializer& index_initializer, |
const CallResultProcessor& processor) { |
// TODO(ishell): use constants from Descriptor once the JSFunction linkage |
// arguments are reordered. |
@@ -127,16 +134,19 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Node* context = |
Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext); |
+ index_initializer(context, a); |
+ |
// 8. Repeat, while k < len |
Variable k(this, MachineRepresentation::kTagged, initial_k); |
- Label loop(this, &k); |
+ VariableList list({&k, &to_}, zone()); |
+ Label loop(this, list); |
Label after_loop(this); |
Goto(&loop); |
Bind(&loop); |
{ |
GotoUnlessNumberLessThan(k.value(), len, &after_loop); |
- Label done_element(this); |
+ Label done_element(this, &to_); |
// a. Let Pk be ToString(k). |
Node* p_k = ToString(context, k.value()); |
@@ -153,10 +163,11 @@ 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); |
+ Node* callback_result = |
+ CallJS(CodeFactory::Call(isolate()), context, callbackfn, this_arg, |
+ k_value, k.value(), o); |
- processor(a, p_k, result); |
+ processor(context, k_value, a, callback_result); |
Goto(&done_element); |
Bind(&done_element); |
@@ -168,24 +179,67 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Return(a); |
} |
- void ForEachProcessor(Node* a, Node* p_k, Node* value) {} |
+ Node* FilterResultGenerator(Node* context, Node* o, Node* len) { |
+ // 7. Let A be ArraySpeciesCreate(O, 0). |
+ return ArraySpeciesCreate(context, o, SmiConstant(0)); |
+ } |
+ |
+ void FilterResultIndexReinitializer(Node* context, Node* a) { |
+ Variable merged_length(this, MachineRepresentation::kTagged); |
+ Label has_length(this, &merged_length), not_js_array(this); |
+ GotoIf(DoesntHaveInstanceType(a, JS_ARRAY_TYPE), ¬_js_array); |
+ merged_length.Bind(LoadJSArrayLength(a)); |
+ Goto(&has_length); |
+ Bind(¬_js_array); |
+ Node* len_property = |
+ GetProperty(context, a, isolate()->factory()->length_string()); |
+ merged_length.Bind( |
+ CallStub(CodeFactory::ToLength(isolate()), context, len_property)); |
+ Goto(&has_length); |
+ Bind(&has_length); |
+ Node* len = merged_length.value(); |
+ |
+ to_.Bind(len); |
+ } |
+ |
+ void ForEachProcessor(Node* context, Node* value, Node* a, |
+ Node* callback_result) {} |
- void SomeProcessor(Node* a, Node* p_k, Node* value) { |
+ void SomeProcessor(Node* context, Node* value, Node* a, |
+ Node* callback_result) { |
Label false_continue(this), return_true(this); |
- BranchIfToBooleanIsTrue(value, &return_true, &false_continue); |
+ BranchIfToBooleanIsTrue(callback_result, &return_true, &false_continue); |
Bind(&return_true); |
Return(TrueConstant()); |
Bind(&false_continue); |
} |
- void EveryProcessor(Node* a, Node* p_k, Node* value) { |
+ void EveryProcessor(Node* context, Node* value, Node* a, |
+ Node* callback_result) { |
Label true_continue(this), return_false(this); |
- BranchIfToBooleanIsTrue(value, &true_continue, &return_false); |
+ BranchIfToBooleanIsTrue(callback_result, &true_continue, &return_false); |
Bind(&return_false); |
Return(FalseConstant()); |
Bind(&true_continue); |
} |
+ void FilterProcessor(Node* context, Node* value, Node* a, |
+ Node* callback_result) { |
+ Label true_continue(this, &to_), false_continue(this); |
+ BranchIfToBooleanIsTrue(callback_result, &true_continue, &false_continue); |
+ Bind(&true_continue); |
+ |
+ // 1. let status be CreateDataPropertyOrThrow(A, ToString(to), kValue). |
+ // 2. ReturnIfAbrupt(status) |
+ Node* const p_to = ToString(context, to_.value()); |
+ CallRuntime(Runtime::kCreateDataProperty, context, a, p_to, value); |
+ |
+ // 3. Increase to by 1. |
+ to_.Bind(NumberInc(to_.value())); |
+ Goto(&false_continue); |
+ Bind(&false_continue); |
+ } |
+ |
private: |
Node* VisitAllFastElementsOneKind(Node* context, ElementsKind kind, |
Node* this_arg, Node* o, Node* len, |
@@ -196,7 +250,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Comment("begin VisitAllFastElementsOneKind"); |
Variable original_map(this, MachineRepresentation::kTagged); |
original_map.Bind(LoadMap(o)); |
- VariableList list({&original_map}, zone()); |
+ VariableList list({&original_map, &to_}, zone()); |
Node* last_index = nullptr; |
BuildFastLoop( |
list, IntPtrOrSmiConstant(0, mode), TaggedToParameter(len, mode), |
@@ -235,9 +289,10 @@ 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); |
+ Node* callback_result = |
+ CallJS(CodeFactory::Call(isolate()), context, callbackfn, |
+ this_arg, value, tagged_index, o); |
+ processor(context, value, a, callback_result); |
Goto(&one_element_done); |
Bind(&hole_element); |
@@ -310,6 +365,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Goto(slow); |
} |
} |
+ |
+ Variable to_; |
}; |
TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
@@ -470,47 +527,76 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
GenerateIteratingArrayBuiltinLoopContinuation( |
- [this](Node* a, Node* p_k, Node* value) { |
- ForEachProcessor(a, p_k, value); |
+ [](Node* context, Node* a) {}, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ ForEachProcessor(context, value, a, callback_result); |
+ }); |
+} |
+ |
+TF_BUILTIN(ArrayFilter, ArrayBuiltinCodeStubAssembler) { |
+ GenerateIteratingArrayBuiltinBody( |
+ "Array.prototype.filter", |
+ [=](Node* context, Node* o, Node* len) { |
+ return FilterResultGenerator(context, o, len); |
+ }, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ FilterProcessor(context, value, a, callback_result); |
+ }, |
+ CodeFactory::ArrayFilterLoopContinuation(isolate())); |
+} |
+ |
+TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
+ GenerateIteratingArrayBuiltinLoopContinuation( |
+ [this](Node* context, Node* a) { |
+ FilterResultIndexReinitializer(context, a); |
+ }, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ FilterProcessor(context, value, a, callback_result); |
}); |
} |
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); |
+ [=](Node*, Node*, Node*) { return UndefinedConstant(); }, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ ForEachProcessor(context, value, a, callback_result); |
}, |
CodeFactory::ArrayForEachLoopContinuation(isolate())); |
} |
TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
GenerateIteratingArrayBuiltinLoopContinuation( |
- [this](Node* a, Node* p_k, Node* value) { |
- SomeProcessor(a, p_k, value); |
+ [](Node* context, Node* a) {}, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ SomeProcessor(context, value, a, callback_result); |
}); |
} |
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", |
+ [=](Node*, Node*, Node*) { return FalseConstant(); }, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ SomeProcessor(context, value, a, callback_result); |
+ }, |
CodeFactory::ArraySomeLoopContinuation(isolate())); |
} |
TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
GenerateIteratingArrayBuiltinLoopContinuation( |
- [this](Node* a, Node* p_k, Node* value) { |
- EveryProcessor(a, p_k, value); |
+ [](Node* context, Node* a) {}, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ EveryProcessor(context, value, a, callback_result); |
}); |
} |
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", |
+ [=](Node*, Node*, Node*) { return TrueConstant(); }, |
+ [this](Node* context, Node* value, Node* a, Node* callback_result) { |
+ EveryProcessor(context, value, a, callback_result); |
}, |
CodeFactory::ArrayEveryLoopContinuation(isolate())); |
} |