Commit f08c3fd3 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Inline String.prototype.concat with PlainPrimitive parameter.

When we hit a call to String.prototype.concat builtin, where we can
infer that the receiver is a String and there's exactly one parameter,
which is of type PlainPrimitive, then we can reduce that to a call to
the StringAddStub instead, optionally converting the non-String - but
PlainPrimitive - parameter to a String.

BUG=v8:5267
R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2758383002
Cr-Commit-Position: refs/heads/master@{#43957}
parent de04df74
...@@ -1807,6 +1807,37 @@ Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) { ...@@ -1807,6 +1807,37 @@ Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) {
return NoChange(); return NoChange();
} }
// ES6 String.prototype.concat(...args)
// #sec-string.prototype.concat
Reduction JSBuiltinReducer::ReduceStringConcat(Node* node) {
if (Node* receiver = GetStringWitness(node)) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::PlainPrimitive())) {
// String.prototype.concat(lhs:string, rhs:plain-primitive)
// -> Call[StringAddStub](lhs, rhs)
StringAddFlags flags = r.InputsMatchOne(Type::String())
? STRING_ADD_CHECK_NONE
: STRING_ADD_CONVERT_RIGHT;
// TODO(turbofan): Massage the FrameState of the {node} here once we
// have an artificial builtin frame type, so that it looks like the
// exception from StringAdd overflow came from String.prototype.concat
// builtin instead of the calling function.
Callable const callable =
CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState,
Operator::kNoDeopt | Operator::kNoWrite);
node->ReplaceInput(0, jsgraph()->HeapConstant(callable.code()));
node->ReplaceInput(1, receiver);
NodeProperties::ChangeOp(node, common()->Call(desc));
return Changed(node);
}
}
return NoChange();
}
// ES6 String.prototype.indexOf(searchString [, position]) // ES6 String.prototype.indexOf(searchString [, position])
// #sec-string.prototype.indexof // #sec-string.prototype.indexof
Reduction JSBuiltinReducer::ReduceStringIndexOf(Node* node) { Reduction JSBuiltinReducer::ReduceStringIndexOf(Node* node) {
...@@ -2208,6 +2239,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) { ...@@ -2208,6 +2239,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
return ReduceStringCharAt(node); return ReduceStringCharAt(node);
case kStringCharCodeAt: case kStringCharCodeAt:
return ReduceStringCharCodeAt(node); return ReduceStringCharCodeAt(node);
case kStringConcat:
return ReduceStringConcat(node);
case kStringIndexOf: case kStringIndexOf:
return ReduceStringIndexOf(node); return ReduceStringIndexOf(node);
case kStringIterator: case kStringIterator:
......
...@@ -103,6 +103,7 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final ...@@ -103,6 +103,7 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final
Reduction ReduceObjectCreate(Node* node); Reduction ReduceObjectCreate(Node* node);
Reduction ReduceStringCharAt(Node* node); Reduction ReduceStringCharAt(Node* node);
Reduction ReduceStringCharCodeAt(Node* node); Reduction ReduceStringCharCodeAt(Node* node);
Reduction ReduceStringConcat(Node* node);
Reduction ReduceStringFromCharCode(Node* node); Reduction ReduceStringFromCharCode(Node* node);
Reduction ReduceStringIndexOf(Node* node); Reduction ReduceStringIndexOf(Node* node);
Reduction ReduceStringIterator(Node* node); Reduction ReduceStringIterator(Node* node);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment