Index: src/builtins/builtins-array-gen.cc |
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
index dedea279c50600c768f2ae9049a8d0367a182181..75ec67e05494155f0ee3e29b74fbfaf1c2a5f6a9 100644 |
--- a/src/builtins/builtins-array-gen.cc |
+++ b/src/builtins/builtins-array-gen.cc |
@@ -18,10 +18,16 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
typedef std::function<void(Node* a, Node* pK, Node* value)> |
CallResultProcessor; |
- void GenerateArrayIteratingBuiltinBody( |
- const char* name, Node* receiver, Node* callbackfn, Node* this_arg, |
- Node* context, const BuiltinResultGenerator& generator, |
- const CallResultProcessor& processor) { |
+ void GenerateIteratingArrayBuiltinBody( |
+ const char* name, const BuiltinResultGenerator& generator, |
+ const CallResultProcessor& processor, |
+ const Callable& slow_case_continuation) { |
+ Node* receiver = Parameter(IteratingArrayBuiltinDescriptor::kReceiver); |
+ Node* callbackfn = Parameter(IteratingArrayBuiltinDescriptor::kCallback); |
+ Node* this_arg = Parameter(IteratingArrayBuiltinDescriptor::kThisArg); |
+ Node* context = Parameter(IteratingArrayBuiltinDescriptor::kContext); |
+ Node* new_target = Parameter(IteratingArrayBuiltinDescriptor::kNewTarget); |
+ |
Variable k(this, MachineRepresentation::kTagged, SmiConstant(0)); |
Label non_array(this), slow(this, &k), array_changes(this, &k); |
@@ -91,47 +97,89 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
// Already done above in initialization of the Variable k |
Bind(&slow); |
+ |
+ Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, |
+ MachineType::TaggedPointer()); |
+ TailCallStub( |
+ slow_case_continuation, context, target, new_target, |
+ Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity), |
+ receiver, callbackfn, this_arg, a, o, k.value(), len); |
+ } |
+ |
+ void GenerateIteratingArrayBuiltinLoopContinuation( |
+ const CallResultProcessor& processor) { |
+ Node* callbackfn = |
+ Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kCallback); |
+ Node* this_arg = |
+ Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kThisArg); |
+ Node* a = |
+ Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kArray); |
+ Node* o = |
+ Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kObject); |
+ Node* initial_k = |
+ Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kInitialK); |
+ Node* len = |
+ Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kLength); |
+ Node* context = |
+ Parameter(IteratingArrayBuiltinLoopContinuationDescriptor::kContext); |
+ |
+ // 8. Repeat, while k < len |
+ Variable k(this, MachineRepresentation::kTagged, initial_k); |
+ Label loop(this, &k); |
+ Label after_loop(this); |
+ Goto(&loop); |
+ Bind(&loop); |
{ |
- // 8. Repeat, while k < len |
- Label loop(this, &k); |
- Label after_loop(this); |
- Goto(&loop); |
- Bind(&loop); |
- { |
- GotoUnlessNumberLessThan(k.value(), len, &after_loop); |
+ GotoUnlessNumberLessThan(k.value(), len, &after_loop); |
- Label done_element(this); |
- // a. Let Pk be ToString(k). |
- Node* p_k = ToString(context, k.value()); |
+ Label done_element(this); |
+ // a. Let Pk be ToString(k). |
+ Node* p_k = ToString(context, k.value()); |
- // b. Let kPresent be HasProperty(O, Pk). |
- // c. ReturnIfAbrupt(kPresent). |
- Node* k_present = |
- CallStub(CodeFactory::HasProperty(isolate()), context, p_k, o); |
+ // b. Let kPresent be HasProperty(O, Pk). |
+ // c. ReturnIfAbrupt(kPresent). |
+ Node* k_present = HasProperty(o, p_k, context); |
- // d. If kPresent is true, then |
- GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); |
+ // d. If kPresent is true, then |
+ GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element); |
- // i. Let kValue be Get(O, Pk). |
- // ii. ReturnIfAbrupt(kValue). |
- Node* k_value = GetProperty(context, o, k.value()); |
+ // i. Let kValue be Get(O, Pk). |
+ // ii. ReturnIfAbrupt(kValue). |
+ Node* k_value = GetProperty(context, o, k.value()); |
- // 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); |
+ // 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); |
- Goto(&done_element); |
- Bind(&done_element); |
+ processor(a, p_k, result); |
+ Goto(&done_element); |
+ Bind(&done_element); |
- // e. Increase k by 1. |
- k.Bind(NumberInc(k.value())); |
- Goto(&loop); |
- } |
- Bind(&after_loop); |
- Return(a); |
+ // e. Increase k by 1. |
+ k.Bind(NumberInc(k.value())); |
+ Goto(&loop); |
} |
+ Bind(&after_loop); |
+ Return(a); |
+ } |
+ |
+ void ForEachProcessor(Node* a, Node* p_k, Node* value) {} |
+ |
+ void SomeProcessor(Node* a, Node* p_k, Node* value) { |
+ Label false_continue(this), return_true(this); |
+ BranchIfToBooleanIsTrue(value, &return_true, &false_continue); |
+ Bind(&return_true); |
+ Return(TrueConstant()); |
+ Bind(&false_continue); |
+ } |
+ |
+ void EveryProcessor(Node* a, Node* p_k, Node* value) { |
+ Label true_continue(this), return_false(this); |
+ BranchIfToBooleanIsTrue(value, &true_continue, &return_false); |
+ Bind(&return_false); |
+ Return(FalseConstant()); |
+ Bind(&true_continue); |
} |
private: |
@@ -414,54 +462,53 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
} |
} |
-TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) { |
- Node* receiver = Parameter(ForEachDescriptor::kReceiver); |
- Node* callbackfn = Parameter(ForEachDescriptor::kCallback); |
- Node* this_arg = Parameter(ForEachDescriptor::kThisArg); |
- Node* context = Parameter(ForEachDescriptor::kContext); |
+TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
+ GenerateIteratingArrayBuiltinLoopContinuation( |
+ [this](Node* a, Node* p_k, Node* value) { |
+ ForEachProcessor(a, p_k, value); |
+ }); |
+} |
- GenerateArrayIteratingBuiltinBody( |
- "Array.prototype.forEach", receiver, callbackfn, this_arg, context, |
+TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) { |
+ GenerateIteratingArrayBuiltinBody( |
+ "Array.prototype.forEach", |
[=](Node*, Node*) { return UndefinedConstant(); }, |
- [](Node* a, Node* p_k, Node* value) {}); |
+ [this](Node* a, Node* p_k, Node* value) { |
+ ForEachProcessor(a, p_k, value); |
+ }, |
+ CodeFactory::ArrayForEachLoopContinuation(isolate())); |
} |
-TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) { |
- Node* receiver = Parameter(ForEachDescriptor::kReceiver); |
- Node* callbackfn = Parameter(ForEachDescriptor::kCallback); |
- Node* this_arg = Parameter(ForEachDescriptor::kThisArg); |
- Node* context = Parameter(ForEachDescriptor::kContext); |
- |
- GenerateArrayIteratingBuiltinBody( |
- "Array.prototype.every", receiver, callbackfn, this_arg, context, |
- [=](Node*, Node*) { return TrueConstant(); }, |
- [=](Node* a, Node* p_k, Node* value) { |
- Label true_continue(this), return_false(this); |
- BranchIfToBooleanIsTrue(value, &true_continue, &return_false); |
- Bind(&return_false); |
- Return(FalseConstant()); |
- Bind(&true_continue); |
+TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
+ GenerateIteratingArrayBuiltinLoopContinuation( |
+ [this](Node* a, Node* p_k, Node* value) { |
+ SomeProcessor(a, p_k, value); |
}); |
} |
TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) { |
- Node* receiver = Parameter(ForEachDescriptor::kReceiver); |
- Node* callbackfn = Parameter(ForEachDescriptor::kCallback); |
- Node* this_arg = Parameter(ForEachDescriptor::kThisArg); |
- Node* context = Parameter(ForEachDescriptor::kContext); |
- |
- GenerateArrayIteratingBuiltinBody( |
- "Array.prototype.some", receiver, callbackfn, this_arg, context, |
- [=](Node*, Node*) { return FalseConstant(); }, |
- [=](Node* a, Node* p_k, Node* value) { |
- Label false_continue(this), return_true(this); |
- BranchIfToBooleanIsTrue(value, &return_true, &false_continue); |
- Bind(&return_true); |
- Return(TrueConstant()); |
- Bind(&false_continue); |
+ GenerateIteratingArrayBuiltinBody( |
+ "Array.prototype.some", [=](Node*, Node*) { return FalseConstant(); }, |
+ [this](Node* a, Node* p_k, Node* value) { SomeProcessor(a, p_k, value); }, |
+ CodeFactory::ArraySomeLoopContinuation(isolate())); |
+} |
+ |
+TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) { |
+ GenerateIteratingArrayBuiltinLoopContinuation( |
+ [this](Node* a, Node* p_k, Node* value) { |
+ EveryProcessor(a, p_k, value); |
}); |
} |
+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); |
+ }, |
+ CodeFactory::ArrayEveryLoopContinuation(isolate())); |
+} |
+ |
TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { |
Node* object = Parameter(1); |
Node* context = Parameter(4); |