Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JSC] Convert GetByVal + StringIdent constant to GetById to encourage…
… megamorphic IC

https://bugs.webkit.org/show_bug.cgi?id=255709
rdar://108302994

Reviewed by Alexey Shvayka.

This patch converts DFG/FTL GetByVal + StringIdent constant to GetById. The main benefit of this is that
we can use megamorphic IC from GetById.

                                ToT                     Patched

    megamorphic-dfg       10.9843+-0.0357     ^      7.3780+-0.0332        ^ definitely 1.4888x faster

* JSTests/microbenchmarks/megamorphic-dfg.js: Added.
(test):
(test2):
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* Source/JavaScriptCore/dfg/DFGNode.cpp:
(JSC::DFG::Node::convertToGetById):
* Source/JavaScriptCore/dfg/DFGNode.h:

Canonical link: https://commits.webkit.org/263200@main
  • Loading branch information
Constellation committed Apr 20, 2023
1 parent b85832f commit d77ef3a
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 0 deletions.
25 changes: 25 additions & 0 deletions JSTests/microbenchmarks/megamorphic-dfg.js
@@ -0,0 +1,25 @@
//@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py
(function() {
var array = [];
for (var i = 0; i < 1000; ++i) {
var o = {};
o["i" + i] = i;
o.f = 42;
array.push(o);
}

function test(array, index) {
return test2(array, index, 'f');
}

function test2(array, index, name) {
return array[index][name];
}
noInline(test);

for (var i = 0; i < 1000000; ++i) {
var result = test(array, i % array.length);
if (result != 42)
throw "Error: bad result: " + result;
}
})();
15 changes: 15 additions & 0 deletions Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Expand Up @@ -2397,6 +2397,21 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi

if (didFold)
break;

if (m_graph.child(node, 0).useKind() == ObjectUse && node->arrayMode().type() == Array::Generic) {
AbstractValue& property = forNode(m_graph.child(node, 1));
if (JSValue constant = property.value()) {
if (constant.isString()) {
JSString* string = asString(constant);
if (CacheableIdentifier::isCacheableIdentifierCell(string) && !parseIndex(CacheableIdentifier::createFromCell(string).uid())) {
m_state.setShouldTryConstantFolding(true);
didFoldClobberWorld();
makeHeapTopForNode(node);
break;
}
}
}
}
}

if (node->op() != GetByVal) {
Expand Down
23 changes: 23 additions & 0 deletions Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Expand Up @@ -695,6 +695,29 @@ class ConstantFoldingPhase : public Phase {
break;
}

case GetByVal: {
if (m_graph.child(node, 0).useKind() == ObjectUse && node->arrayMode().type() == Array::Generic) {
AbstractValue& property = m_state.forNode(m_graph.child(node, 1));
if (JSValue constant = property.value()) {
if (constant.isString()) {
JSString* string = asString(constant);
if (CacheableIdentifier::isCacheableIdentifierCell(string) && !parseIndex(CacheableIdentifier::createFromCell(string).uid())) {
const StringImpl* impl = string->tryGetValueImpl();
RELEASE_ASSERT(impl);
m_graph.freezeStrong(string);
m_graph.identifiers().ensure(const_cast<UniquedStringImpl*>(static_cast<const UniquedStringImpl*>(impl)));
m_insertionSet.insertCheck(indexInBlock, node->origin, m_graph.child(node, 0));
node->convertToGetById(m_graph, CacheableIdentifier::createFromCell(string));
changed = true;
break;
}
}
}
}
break;

}

case ToPrimitive: {
if (m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol | SpecBigInt))
break;
Expand Down
16 changes: 16 additions & 0 deletions Source/JavaScriptCore/dfg/DFGNode.cpp
Expand Up @@ -353,6 +353,22 @@ void Node::convertToRegExpTestInline(FrozenValue* globalObject, FrozenValue* reg
m_opInfo2 = regExp;
}

void Node::convertToGetById(Graph& graph, CacheableIdentifier identifier)
{
ASSERT(op() == GetByVal);
Edge base = graph.varArgChild(this, 0);
ASSERT(base.useKind() == ObjectUse);
for (unsigned i = 0; i < numChildren(); ++i) {
Edge& edge = graph.varArgChild(this, i);
edge = Edge();
}
setOpAndDefaultFlags(GetById);
children.child1() = Edge(base.node(), CellUse);
children.child2() = Edge();
children.child3() = Edge();
m_opInfo = identifier;
}

String Node::tryGetString(Graph& graph)
{
if (hasConstant())
Expand Down
2 changes: 2 additions & 0 deletions Source/JavaScriptCore/dfg/DFGNode.h
Expand Up @@ -517,6 +517,8 @@ struct Node {
void convertToIdentity();
void convertToIdentityOn(Node*);

void convertToGetById(Graph&, CacheableIdentifier);

bool mustGenerate() const
{
return m_flags & NodeMustGenerate;
Expand Down

0 comments on commit d77ef3a

Please sign in to comment.