Commit f2cd359a authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[TurboFan] Speculatively lower ToPrimitiveToString to CheckString.

Adds support for Speculatively lower ToPrimitiveToString to CheckString
where the type hint shows the value has always been a string.

BUG=v8:6243

Change-Id: I7f36deb8c2bc309e6d0546e099c76ac518c6be09
Reviewed-on: https://chromium-review.googlesource.com/521123
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45760}
parent 8bc98b5c
......@@ -146,7 +146,7 @@ compiler::Node* ConversionBuiltinsAssembler::ToPrimitiveToString(
BIND(&to_string);
{
if (feedback) {
feedback->Bind(SmiConstant(ToPrimitiveToStringFeedback::kAny));
feedback->Bind(SmiConstant(BinaryOperationFeedback::kAny));
}
result.Bind(CallBuiltin(Builtins::kToString, context, result.value()));
Goto(&done);
......@@ -155,7 +155,7 @@ compiler::Node* ConversionBuiltinsAssembler::ToPrimitiveToString(
BIND(&is_string);
{
if (feedback) {
feedback->Bind(SmiConstant(ToPrimitiveToStringFeedback::kString));
feedback->Bind(SmiConstant(BinaryOperationFeedback::kString));
}
Goto(&done);
}
......
......@@ -2176,7 +2176,16 @@ void BytecodeGraphBuilder::VisitToNumber() {
void BytecodeGraphBuilder::VisitToPrimitiveToString() {
PrepareEagerCheckpoint();
Node* object = environment()->LookupAccumulator();
Node* node = NewNode(javascript()->ToPrimitiveToString(), object);
Node* node = nullptr;
FeedbackSlot slot =
feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1));
if (Node* simplified = TryBuildSimplifiedToPrimitiveToString(object, slot)) {
node = simplified;
} else {
node = NewNode(javascript()->ToPrimitiveToString(), object);
}
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node,
Environment::kAttachFrameState);
}
......@@ -2667,6 +2676,20 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value,
return nullptr;
}
Node* BytecodeGraphBuilder::TryBuildSimplifiedToPrimitiveToString(
Node* value, FeedbackSlot slot) {
Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency();
Reduction early_reduction =
type_hint_lowering().ReduceToPrimitiveToStringOperation(value, effect,
control, slot);
if (early_reduction.Changed()) {
ApplyEarlyReduction(early_reduction);
return early_reduction.replacement();
}
return nullptr;
}
Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
Node* receiver,
FeedbackSlot slot) {
......
......@@ -193,6 +193,7 @@ class BytecodeGraphBuilder {
Node* TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, Node* right,
FeedbackSlot slot);
Node* TryBuildSimplifiedToNumber(Node* input, FeedbackSlot slot);
Node* TryBuildSimplifiedToPrimitiveToString(Node* input, FeedbackSlot slot);
Node* TryBuildSimplifiedLoadNamed(const Operator* op, Node* receiver,
FeedbackSlot slot);
Node* TryBuildSimplifiedLoadKeyed(const Operator* op, Node* receiver,
......
......@@ -256,6 +256,19 @@ Reduction JSTypeHintLowering::ReduceToNumberOperation(Node* input, Node* effect,
return Reduction();
}
Reduction JSTypeHintLowering::ReduceToPrimitiveToStringOperation(
Node* input, Node* effect, Node* control, FeedbackSlot slot) const {
DCHECK(!slot.IsInvalid());
BinaryOpICNexus nexus(feedback_vector(), slot);
BinaryOperationHint hint = nexus.GetBinaryOperationFeedback();
if (hint == BinaryOperationHint::kString) {
Node* node = jsgraph()->graph()->NewNode(
jsgraph()->simplified()->CheckString(), input, effect, control);
return Reduction(node);
}
return Reduction();
}
Reduction JSTypeHintLowering::ReduceLoadNamedOperation(
const Operator* op, Node* obj, Node* effect, Node* control,
FeedbackSlot slot) const {
......
......@@ -59,6 +59,11 @@ class JSTypeHintLowering {
Reduction ReduceToNumberOperation(Node* value, Node* effect, Node* control,
FeedbackSlot slot) const;
// Potential reduction to ToPrimitiveToString operations
Reduction ReduceToPrimitiveToStringOperation(Node* value, Node* effect,
Node* control,
FeedbackSlot slot) const;
// Potential reduction of property access operations.
Reduction ReduceLoadNamedOperation(const Operator* op, Node* obj,
Node* effect, Node* control,
......
......@@ -1237,15 +1237,6 @@ inline uint32_t ObjectHash(Address address) {
kPointerSizeLog2);
}
// Type feedback is encoded in such a way that, we can combine the feedback
// at different points by performing an 'OR' operation. Type feedback moves
// to a more generic type when we combine feedback.
// kString -> kAny
class ToPrimitiveToStringFeedback {
public:
enum { kNone = 0x0, kString = 0x1, kAny = 0x3 };
};
// Type feedback is encoded in such a way that, we can combine the feedback
// at different points by performing an 'OR' operation. Type feedback moves
// to a more generic type when we combine feedback.
......
......@@ -4937,18 +4937,18 @@ TEST(InterpreterToPrimitiveToString) {
} test_cases[] = {
{factory->NewStringFromAsciiChecked("Foo"),
factory->NewStringFromAsciiChecked("Foo"),
ToPrimitiveToStringFeedback::kString},
BinaryOperationFeedback::kString},
{handle(Smi::FromInt(123), isolate),
factory->NewStringFromAsciiChecked("123"),
ToPrimitiveToStringFeedback::kAny},
BinaryOperationFeedback::kAny},
{factory->NewHeapNumber(2.45), factory->NewStringFromAsciiChecked("2.45"),
ToPrimitiveToStringFeedback::kAny},
BinaryOperationFeedback::kAny},
{factory->undefined_value(),
factory->NewStringFromAsciiChecked("undefined"),
ToPrimitiveToStringFeedback::kAny},
BinaryOperationFeedback::kAny},
{InterpreterTester::NewObject("({ val : 123 })"),
factory->NewStringFromAsciiChecked("[object Object]"),
ToPrimitiveToStringFeedback::kAny},
BinaryOperationFeedback::kAny},
};
for (size_t i = 0; i < arraysize(test_cases); i++) {
......
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