Commit d3797add authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[Turbofan] Introduce StringToNumber opcode

If we have good lower bound type information in simplified lowering
that the input to PlainPrimitiveToNumber is a string, then we'd like
to introduce a call to the StringToNumber builtin. However, this
requires more careful management of the effect chain than we had
previously. To fix this, introduce a StringToNumber opcode which
defers the graph alteration until effect-control-linearization,
when the effect chain is available for careful wiring.

Bug: v8:6929
Change-Id: I4f0e43fe474a44d0dfa095a3a01caece649d82db
Reviewed-on: https://chromium-review.googlesource.com/727934Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48741}
parent efe438c5
...@@ -855,6 +855,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, ...@@ -855,6 +855,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kStringIndexOf: case IrOpcode::kStringIndexOf:
result = LowerStringIndexOf(node); result = LowerStringIndexOf(node);
break; break;
case IrOpcode::kStringToNumber:
result = LowerStringToNumber(node);
break;
case IrOpcode::kStringCharAt: case IrOpcode::kStringCharAt:
result = LowerStringCharAt(node); result = LowerStringCharAt(node);
break; break;
...@@ -2479,6 +2482,19 @@ Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) { ...@@ -2479,6 +2482,19 @@ Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) {
__ Int32Constant(0)); __ Int32Constant(0));
} }
Node* EffectControlLinearizer::LowerStringToNumber(Node* node) {
Node* string = node->InputAt(0);
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kStringToNumber);
Operator::Properties properties = Operator::kEliminatable;
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
return __ Call(desc, __ HeapConstant(callable.code()), string,
__ NoContextConstant());
}
Node* EffectControlLinearizer::LowerStringCharAt(Node* node) { Node* EffectControlLinearizer::LowerStringCharAt(Node* node) {
Node* receiver = node->InputAt(0); Node* receiver = node->InputAt(0);
Node* position = node->InputAt(1); Node* position = node->InputAt(1);
......
...@@ -103,6 +103,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer { ...@@ -103,6 +103,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerNewSmiOrObjectElements(Node* node); Node* LowerNewSmiOrObjectElements(Node* node);
Node* LowerNewArgumentsElements(Node* node); Node* LowerNewArgumentsElements(Node* node);
Node* LowerArrayBufferWasNeutered(Node* node); Node* LowerArrayBufferWasNeutered(Node* node);
Node* LowerStringToNumber(Node* node);
Node* LowerStringCharAt(Node* node); Node* LowerStringCharAt(Node* node);
Node* LowerStringCharCodeAt(Node* node); Node* LowerStringCharCodeAt(Node* node);
Node* LowerSeqStringCharCodeAt(Node* node); Node* LowerSeqStringCharCodeAt(Node* node);
......
...@@ -320,6 +320,7 @@ ...@@ -320,6 +320,7 @@
V(PlainPrimitiveToWord32) \ V(PlainPrimitiveToWord32) \
V(PlainPrimitiveToFloat64) \ V(PlainPrimitiveToFloat64) \
V(BooleanNot) \ V(BooleanNot) \
V(StringToNumber) \
V(StringCharAt) \ V(StringCharAt) \
V(StringCharCodeAt) \ V(StringCharCodeAt) \
V(SeqStringCharCodeAt) \ V(SeqStringCharCodeAt) \
......
...@@ -2645,7 +2645,9 @@ class RepresentationSelector { ...@@ -2645,7 +2645,9 @@ class RepresentationSelector {
if (lower()) DeferReplacement(node, node->InputAt(0)); if (lower()) DeferReplacement(node, node->InputAt(0));
} else if (InputIs(node, Type::String())) { } else if (InputIs(node, Type::String())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) lowering->DoStringToNumber(node); if (lower()) {
NodeProperties::ChangeOp(node, simplified()->StringToNumber());
}
} else if (truncation.IsUsedAsWord32()) { } else if (truncation.IsUsedAsWord32()) {
if (InputIs(node, Type::NumberOrOddball())) { if (InputIs(node, Type::NumberOrOddball())) {
VisitUnop(node, UseInfo::TruncatingWord32(), VisitUnop(node, UseInfo::TruncatingWord32(),
...@@ -3645,20 +3647,6 @@ void SimplifiedLowering::DoShift(Node* node, Operator const* op, ...@@ -3645,20 +3647,6 @@ void SimplifiedLowering::DoShift(Node* node, Operator const* op,
ChangeToPureOp(node, op); ChangeToPureOp(node, op);
} }
void SimplifiedLowering::DoStringToNumber(Node* node) {
Operator::Properties properties = Operator::kEliminatable;
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kStringToNumber);
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
node->InsertInput(graph()->zone(), 0,
jsgraph()->HeapConstant(callable.code()));
node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant());
node->AppendInput(graph()->zone(), graph()->start());
NodeProperties::ChangeOp(node, common()->Call(desc));
}
void SimplifiedLowering::DoIntegral32ToBit(Node* node) { void SimplifiedLowering::DoIntegral32ToBit(Node* node) {
Node* const input = node->InputAt(0); Node* const input = node->InputAt(0);
Node* const zero = jsgraph()->Int32Constant(0); Node* const zero = jsgraph()->Int32Constant(0);
......
...@@ -35,7 +35,6 @@ class SimplifiedLowering final { ...@@ -35,7 +35,6 @@ class SimplifiedLowering final {
void DoJSToNumberTruncatesToWord32(Node* node, void DoJSToNumberTruncatesToWord32(Node* node,
RepresentationSelector* selector); RepresentationSelector* selector);
void DoShift(Node* node, Operator const* op, Type* rhs_type); void DoShift(Node* node, Operator const* op, Type* rhs_type);
void DoStringToNumber(Node* node);
void DoIntegral32ToBit(Node* node); void DoIntegral32ToBit(Node* node);
void DoOrderedNumberToBit(Node* node); void DoOrderedNumberToBit(Node* node);
void DoNumberToBit(Node* node); void DoNumberToBit(Node* node);
......
...@@ -549,6 +549,7 @@ DeoptimizeReason DeoptimizeReasonOf(const Operator* op) { ...@@ -549,6 +549,7 @@ DeoptimizeReason DeoptimizeReasonOf(const Operator* op) {
V(NumberToUint32, Operator::kNoProperties, 1, 0) \ V(NumberToUint32, Operator::kNoProperties, 1, 0) \
V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0) \ V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0) \
V(NumberSilenceNaN, Operator::kNoProperties, 1, 0) \ V(NumberSilenceNaN, Operator::kNoProperties, 1, 0) \
V(StringToNumber, Operator::kNoProperties, 1, 0) \
V(StringCharAt, Operator::kNoProperties, 2, 1) \ V(StringCharAt, Operator::kNoProperties, 2, 1) \
V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \ V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \
V(SeqStringCharCodeAt, Operator::kNoProperties, 2, 1) \ V(SeqStringCharCodeAt, Operator::kNoProperties, 2, 1) \
......
...@@ -389,6 +389,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final ...@@ -389,6 +389,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* SpeculativeToNumber(NumberOperationHint hint); const Operator* SpeculativeToNumber(NumberOperationHint hint);
const Operator* StringToNumber();
const Operator* PlainPrimitiveToNumber(); const Operator* PlainPrimitiveToNumber();
const Operator* PlainPrimitiveToWord32(); const Operator* PlainPrimitiveToWord32();
const Operator* PlainPrimitiveToFloat64(); const Operator* PlainPrimitiveToFloat64();
......
...@@ -1801,6 +1801,10 @@ Type* Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) { ...@@ -1801,6 +1801,10 @@ Type* Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) {
return TypeBinaryOp(node, NumberLessThanOrEqualTyper); return TypeBinaryOp(node, NumberLessThanOrEqualTyper);
} }
Type* Typer::Visitor::TypeStringToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
}
Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) { Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber); return TypeUnaryOp(node, ToNumber);
} }
......
...@@ -967,6 +967,11 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -967,6 +967,11 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 1, Type::String()); CheckValueInputIs(node, 1, Type::String());
CheckTypeIs(node, Type::Boolean()); CheckTypeIs(node, Type::Boolean());
break; break;
case IrOpcode::kStringToNumber:
// String -> Number
CheckValueInputIs(node, 0, Type::String());
CheckTypeIs(node, Type::Number());
break;
case IrOpcode::kStringCharAt: case IrOpcode::kStringCharAt:
// (String, Unsigned32) -> String // (String, Unsigned32) -> String
CheckValueInputIs(node, 0, Type::String()); 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