Commit 240a8c35 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbofan] Migrate String.p.concat to JSCallReducer

Bug: v8:7250, v8:7340
Change-Id: Ic302a811dd827fc1692240c225b3e580a54a3a2f
Reviewed-on: https://chromium-review.googlesource.com/943422Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51683}
parent f48e7349
......@@ -934,37 +934,6 @@ Node* GetStringWitness(Node* node) {
} // namespace
// 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);
auto call_descriptor = 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(call_descriptor));
return Changed(node);
}
}
return NoChange();
}
// ES section #sec-string.prototype.slice
Reduction JSBuiltinReducer::ReduceStringSlice(Node* node) {
if (Node* receiver = GetStringWitness(node)) {
......@@ -1140,8 +1109,6 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
return ReduceCollectionIteratorNext(
node, OrderedHashSet::kEntrySize, factory()->empty_ordered_hash_set(),
FIRST_SET_ITERATOR_TYPE, LAST_SET_ITERATOR_TYPE);
case kStringConcat:
return ReduceStringConcat(node);
case kStringSlice:
return ReduceStringSlice(node);
case kArrayBufferIsView:
......
......@@ -64,7 +64,6 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final
Reduction ReduceNumberParseInt(Node* node);
Reduction ReduceObjectCreate(Node* node);
Reduction ReduceStringSlice(Node* node);
Reduction ReduceStringConcat(Node* node);
Reduction ReduceArrayBufferIsView(Node* node);
Reduction ReduceArrayBufferViewAccessor(Node* node,
InstanceType instance_type,
......
......@@ -3351,6 +3351,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
return ReduceStringPrototypeIterator(node);
case Builtins::kStringIteratorPrototypeNext:
return ReduceStringIteratorPrototypeNext(node);
case Builtins::kStringPrototypeConcat:
return ReduceStringPrototypeConcat(node, shared);
case Builtins::kTypedArrayPrototypeEntries:
return ReduceTypedArrayIterator(node, IterationKind::kEntries);
case Builtins::kTypedArrayPrototypeKeys:
......@@ -5202,6 +5204,50 @@ Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
return NoChange();
}
// ES #sec-string.prototype.concat
Reduction JSCallReducer::ReduceStringPrototypeConcat(
Node* node, Handle<SharedFunctionInfo> shared) {
if (node->op()->ValueInputCount() < 2) return NoChange();
CallParameters const& p = CallParametersOf(node->op());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange();
}
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* context = NodeProperties::GetContextInput(node);
Node* receiver = effect =
graph()->NewNode(simplified()->CheckString(p.feedback()),
NodeProperties::GetValueInput(node, 1), effect, control);
if (node->op()->ValueInputCount() < 3) {
ReplaceWithValue(node, receiver, effect, control);
return Replace(receiver);
}
Node* argument = effect =
graph()->NewNode(simplified()->CheckString(p.feedback()),
NodeProperties::GetValueInput(node, 2), effect, control);
Callable const callable =
CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
auto call_descriptor = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState,
Operator::kNoDeopt | Operator::kNoWrite);
// 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.
Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
Node* value = effect = control = graph()->NewNode(
common()->Call(call_descriptor), jsgraph()->HeapConstant(callable.code()),
receiver, argument, context, outer_frame_state, effect, control);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
Reduction JSCallReducer::ReduceAsyncFunctionPromiseCreate(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
Node* context = NodeProperties::GetContextInput(node);
......
......@@ -125,6 +125,8 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceStringFromCharCode(Node* node);
Reduction ReduceStringPrototypeIterator(Node* node);
Reduction ReduceStringIteratorPrototypeNext(Node* node);
Reduction ReduceStringPrototypeConcat(Node* node,
Handle<SharedFunctionInfo> shared);
Reduction ReduceAsyncFunctionPromiseCreate(Node* node);
Reduction ReduceAsyncFunctionPromiseRelease(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