DFG should optimize StringObject.length and StringOrStringObject.length
https://bugs.webkit.org/show_bug.cgi?id=112658
Reviewed by Mark Hahnenberg.
Implemented by injecting a ToString(StringObject:@a) or ToString(StringOrStringObject:@a) prior
to GetArrayLength with ArrayMode(Array::String) if @a is predicted StringObject or
StringOrStringObject.
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::createToString):
(FixupPhase):
(JSC::DFG::FixupPhase::attemptToForceStringArrayModeByToStringConversion):
(JSC::DFG::FixupPhase::convertStringAddUse):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@146247 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 29472f0..740dc88 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -725,6 +725,17 @@
}
} else
arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
+
+ if (arrayMode.type() == Array::Generic) {
+ // Check if the input is something that we can't get array length for, but for which we
+ // could insert some conversions in order to transform it into something that we can do it
+ // for.
+ if (node->child1()->shouldSpeculateStringObject())
+ attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
+ else if (node->child1()->shouldSpeculateStringOrStringObject())
+ attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
+ }
+
if (!arrayMode.supportsLength())
break;
node->setOp(GetArrayLength);
@@ -887,6 +898,26 @@
}
template<UseKind useKind>
+ Node* createToString(Node* node, Edge edge)
+ {
+ return m_insertionSet.insertNode(
+ m_indexInBlock, SpecString, ToString, node->codeOrigin,
+ Edge(edge.node(), useKind));
+ }
+
+ template<UseKind useKind>
+ void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
+ {
+ ASSERT(arrayMode == ArrayMode(Array::Generic));
+
+ if (!canOptimizeStringObjectAccess(node->codeOrigin))
+ return;
+
+ node->child1().setNode(createToString<useKind>(node, node->child1()));
+ arrayMode = ArrayMode(Array::String);
+ }
+
+ template<UseKind useKind>
bool isStringObjectUse()
{
switch (useKind) {
@@ -916,9 +947,7 @@
// FIXME: We ought to be able to have a ToPrimitiveToString node.
observeUseKindOnNode<useKind>(edge.node());
- edge = Edge(m_insertionSet.insertNode(
- m_indexInBlock, SpecString, ToString, node->codeOrigin,
- Edge(edge.node(), useKind)), KnownStringUse);
+ edge = Edge(createToString<useKind>(node, edge), KnownStringUse);
}
template<UseKind leftUseKind>