Commit da08dfc3 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbofan] Remove simplified operator StringCharAt

This CL now uses StringCharCodeAt + StringFromCharCode to replace
StringCharAt. Optimizations are easier to implement if we have both
operators; however, if this tanks performance a lot we have to revert.

R=bmeurer@chromium.org

Bug: v8:7531
Change-Id: I75590cc8b8db57715bc2de9f5b98d0878d62a394
Reviewed-on: https://chromium-review.googlesource.com/956134
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51877}
parent b0dc290a
......@@ -842,9 +842,6 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kStringToNumber:
result = LowerStringToNumber(node);
break;
case IrOpcode::kStringCharAt:
result = LowerStringCharAt(node);
break;
case IrOpcode::kStringCharCodeAt:
result = LowerStringCharCodeAt(node);
break;
......@@ -2673,20 +2670,6 @@ Node* EffectControlLinearizer::LowerStringToNumber(Node* node) {
__ NoContextConstant());
}
Node* EffectControlLinearizer::LowerStringCharAt(Node* node) {
Node* receiver = node->InputAt(0);
Node* position = node->InputAt(1);
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kStringCharAt);
Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
auto call_descriptor = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver,
position, __ NoContextConstant());
}
Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) {
Node* receiver = node->InputAt(0);
Node* position = node->InputAt(1);
......
......@@ -116,7 +116,6 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerSameValue(Node* node);
Node* LowerDeadValue(Node* node);
Node* LowerStringToNumber(Node* node);
Node* LowerStringCharAt(Node* node);
Node* LowerStringCharCodeAt(Node* node);
Node* LowerSeqStringCharCodeAt(Node* node);
Node* LowerStringCodePointAt(Node* node, UnicodeEncoding encoding);
......
......@@ -3429,7 +3429,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
case Builtins::kStringPrototypeIndexOf:
return ReduceStringPrototypeIndexOf(node);
case Builtins::kStringPrototypeCharAt:
return ReduceStringPrototypeStringAt(simplified()->StringCharAt(), node);
return ReduceStringPrototypeCharAt(node);
case Builtins::kStringPrototypeCharCodeAt:
return ReduceStringPrototypeStringAt(simplified()->StringCharCodeAt(),
node);
......@@ -4821,13 +4821,11 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
return Replace(value);
}
// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
// ES6 section 21.1.3.3 String.prototype.codePointAt ( pos )
Reduction JSCallReducer::ReduceStringPrototypeStringAt(
const Operator* string_access_operator, Node* node) {
DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharAt ||
string_access_operator->opcode() == IrOpcode::kStringCharCodeAt ||
DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharCodeAt ||
string_access_operator->opcode() == IrOpcode::kStringCodePointAt);
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
CallParameters const& p = CallParametersOf(node->op());
......@@ -4864,6 +4862,45 @@ Reduction JSCallReducer::ReduceStringPrototypeStringAt(
return Replace(value);
}
// ES section 21.1.3.1 String.prototype.charAt ( pos )
Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
CallParameters const& p = CallParametersOf(node->op());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange();
}
Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* index = node->op()->ValueInputCount() >= 3
? NodeProperties::GetValueInput(node, 2)
: jsgraph()->ZeroConstant();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Ensure that the {receiver} is actually a String.
receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
receiver, effect, control);
// Determine the {receiver} length.
Node* receiver_length =
graph()->NewNode(simplified()->StringLength(), receiver);
// Check that the {index} is within range.
index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
index, receiver_length, effect, control);
// Return the character from the {receiver} as single character string.
Node* masked_index = graph()->NewNode(simplified()->MaskIndexWithBound(),
index, receiver_length);
Node* value = effect =
graph()->NewNode(simplified()->StringCharCodeAt(), receiver, masked_index,
effect, control);
value = graph()->NewNode(simplified()->StringFromCharCode(), value);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
#ifdef V8_INTL_SUPPORT
Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) {
......
......@@ -116,6 +116,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceStringPrototypeSubstr(Node* node);
Reduction ReduceStringPrototypeStringAt(
const Operator* string_access_operator, Node* node);
Reduction ReduceStringPrototypeCharAt(Node* node);
#ifdef V8_INTL_SUPPORT
Reduction ReduceStringPrototypeToLowerCaseIntl(Node* node);
......
......@@ -2649,8 +2649,10 @@ Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue;
Node* vtrue = etrue = graph()->NewNode(
simplified()->StringCharAt(), receiver, masked_index, *effect, if_true);
Node* vtrue = etrue =
graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
masked_index, *effect, if_true);
vtrue = graph()->NewNode(simplified()->StringFromCharCode(), vtrue);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse = jsgraph()->UndefinedConstant();
......@@ -2671,8 +2673,9 @@ Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
// Return the character from the {receiver} as single character string.
Node* value = *effect =
graph()->NewNode(simplified()->StringCharAt(), receiver, masked_index,
*effect, *control);
graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
masked_index, *effect, *control);
value = graph()->NewNode(simplified()->StringFromCharCode(), value);
return value;
}
}
......
......@@ -341,7 +341,6 @@
V(PlainPrimitiveToFloat64) \
V(BooleanNot) \
V(StringToNumber) \
V(StringCharAt) \
V(StringCharCodeAt) \
V(SeqStringCharCodeAt) \
V(StringCodePointAt) \
......
......@@ -2349,11 +2349,6 @@ class RepresentationSelector {
return VisitBinop(node, UseInfo::AnyTagged(),
MachineRepresentation::kTaggedPointer);
}
case IrOpcode::kStringCharAt: {
VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
MachineRepresentation::kTaggedPointer);
return;
}
case IrOpcode::kStringCharCodeAt: {
Type* string_type = TypeOf(node->InputAt(0));
if (string_type->Is(Type::SeqString())) {
......
......@@ -721,7 +721,6 @@ bool operator==(CheckMinusZeroParameters const& lhs,
V(MaskIndexWithBound, Operator::kNoProperties, 2, 0)
#define EFFECT_DEPENDENT_OP_LIST(V) \
V(StringCharAt, Operator::kNoProperties, 2, 1) \
V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \
V(SeqStringCharCodeAt, Operator::kNoProperties, 2, 1) \
V(StringSubstring, Operator::kNoProperties, 3, 1)
......
......@@ -522,7 +522,6 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* StringEqual();
const Operator* StringLessThan();
const Operator* StringLessThanOrEqual();
const Operator* StringCharAt();
const Operator* StringCharCodeAt();
const Operator* SeqStringCharCodeAt();
const Operator* StringCodePointAt(UnicodeEncoding encoding);
......
......@@ -1966,8 +1966,6 @@ Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) {
return Type::String();
}
Type* Typer::Visitor::TypeStringCharAt(Node* node) { return Type::String(); }
Type* Typer::Visitor::TypeStringToLowerCaseIntl(Node* node) {
return Type::String();
}
......
......@@ -1084,12 +1084,6 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
CheckValueInputIs(node, 0, Type::String());
CheckTypeIs(node, Type::Number());
break;
case IrOpcode::kStringCharAt:
// (String, Unsigned32) -> String
CheckValueInputIs(node, 0, Type::String());
CheckValueInputIs(node, 1, Type::Unsigned32());
CheckTypeIs(node, Type::String());
break;
case IrOpcode::kStringCharCodeAt:
// (String, Unsigned32) -> UnsignedSmall
CheckValueInputIs(node, 0, Type::String());
......
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