Index: src/compiler/js-builtin-reducer.cc |
diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc |
index bf72ca47302545484b5bef10b88627210a6daa63..a680720c39050a7c3b8c9be47e6be2bdcfa9947e 100644 |
--- a/src/compiler/js-builtin-reducer.cc |
+++ b/src/compiler/js-builtin-reducer.cc |
@@ -5,9 +5,11 @@ |
#include "src/compiler/js-builtin-reducer.h" |
#include "src/base/bits.h" |
+#include "src/code-factory.h" |
#include "src/compilation-dependencies.h" |
#include "src/compiler/access-builder.h" |
#include "src/compiler/js-graph.h" |
+#include "src/compiler/linkage.h" |
#include "src/compiler/node-matchers.h" |
#include "src/compiler/node-properties.h" |
#include "src/compiler/simplified-operator.h" |
@@ -1730,6 +1732,44 @@ Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) { |
return NoChange(); |
} |
+// ES6 String.prototype.indexOf(searchString [, position]) |
+// #sec-string.prototype.indexof |
+Reduction JSBuiltinReducer::ReduceStringIndexOf(Node* node) { |
+ int arg_count = node->op()->ValueInputCount(); |
+ if (arg_count != 3 && arg_count != 4) return NoChange(); |
+ Node* receiver; |
+ if (!(receiver = GetStringWitness(node))) return NoChange(); |
+ Node* search_string = NodeProperties::GetValueInput(node, 2); |
+ if (!NodeProperties::GetType(search_string)->Is(Type::String())) { |
+ return NoChange(); |
+ } |
+ // Replace the current JSFunctionCall to String.prototype.indexOf with a |
+ // simple Call to the unchecked StringIndexOf builtin. |
+ Callable callable = CodeFactory::StringIndexOf(isolate()); |
+ const CallInterfaceDescriptor& descriptor = callable.descriptor(); |
+ CallDescriptor* desc = |
+ Linkage::GetStubCallDescriptor(isolate(), graph()->zone(), descriptor, |
+ descriptor.GetStackParameterCount(), |
+ CallDescriptor::kNoFlags, Operator::kPure); |
+ Node* stub_code = jsgraph()->HeapConstant(callable.code()); |
+ // The Call Operator doesn't require an effect nor a control input. |
+ RelaxEffectsAndControls(node); |
+ // Remove framestate since StringIndexOf cannot deopt. |
+ node->RemoveInput(arg_count + 1); |
+ // Remove the control input. |
+ node->RemoveInput(arg_count + 2); |
+ // Replace the JSFunction from the JSFunctionCall node with the CodeStub. |
+ node->ReplaceInput(0, stub_code); |
+ if (arg_count == 3) { |
+ // Insert the missing position argument. |
+ node->InsertInput(graph()->zone(), 3, jsgraph()->ZeroConstant()); |
+ } |
+ const Operator* op = common()->Call(desc); |
+ node->TrimInputCount(op->ValueInputCount()); |
+ NodeProperties::ChangeOp(node, op); |
+ return Changed(node); |
+} |
+ |
Reduction JSBuiltinReducer::ReduceStringIterator(Node* node) { |
if (Node* receiver = GetStringWitness(node)) { |
Node* effect = NodeProperties::GetEffectInput(node); |
@@ -2101,6 +2141,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) { |
return ReduceStringCharAt(node); |
case kStringCharCodeAt: |
return ReduceStringCharCodeAt(node); |
+ case kStringIndexOf: |
+ return ReduceStringIndexOf(node); |
case kStringIterator: |
return ReduceStringIterator(node); |
case kStringIteratorNext: |