Add the notion of ConstantStoragePointer to DFG IR
https://bugs.webkit.org/show_bug.cgi?id=125395
Reviewed by Oliver Hunt.
This pushes more typed array folding into StrengthReductionPhase, and enables CSE on
storage pointers. Previously, you might have separate nodes for the same storage
pointer and this would cause some bad register pressure in the DFG. Note that this
was really a theoretical problem and not, to my knowledge a practical one - so this
patch is basically just a clean-up.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::::executeEffects):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::constantStoragePointerCSE):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToConstantStoragePointer):
(JSC::DFG::Node::hasStoragePointer):
(JSC::DFG::Node::storagePointer):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileConstantStoragePointer):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
(JSC::DFG::StrengthReductionPhase::foldTypedArrayPropertyToConstant):
(JSC::DFG::StrengthReductionPhase::prepareToFoldTypedArray):
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileConstantStoragePointer):
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@160295 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index 9c8afe3..503722a 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -1440,7 +1440,8 @@
m_state.setHaveStructures(true);
break;
}
- case GetIndexedPropertyStorage: {
+ case GetIndexedPropertyStorage:
+ case ConstantStoragePointer: {
forNode(node).clear();
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index e25b9f8..d9dd3a0 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -162,6 +162,21 @@
return 0;
}
+ Node* constantStoragePointerCSE(Node* node)
+ {
+ for (unsigned i = endIndexForPureCSE(); i--;) {
+ Node* otherNode = m_currentBlock->at(i);
+ if (otherNode->op() != ConstantStoragePointer)
+ continue;
+
+ if (otherNode->storagePointer() != node->storagePointer())
+ continue;
+
+ return otherNode;
+ }
+ return 0;
+ }
+
Node* getCalleeLoadElimination()
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -1154,6 +1169,12 @@
setReplacement(weakConstantCSE(node));
break;
+ case ConstantStoragePointer:
+ if (cseMode == StoreElimination)
+ break;
+ setReplacement(constantStoragePointerCSE(node));
+ break;
+
case GetArrayLength:
if (cseMode == StoreElimination)
break;
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index 00f4268..e4f1156 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -116,6 +116,7 @@
case ExtractOSREntryLocal:
case Int52ToDouble:
case Int52ToValue:
+ case ConstantStoragePointer:
return;
case MovHintAndCheck:
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 2d43da7..d24debe 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -877,6 +877,10 @@
case Int52ToValue:
case InvalidationPoint:
case CheckArray:
+ case ConstantStoragePointer:
+ // These are just nodes that we don't currently expect to see during fixup.
+ // If we ever wanted to insert them prior to fixup, then we just have to create
+ // fixup rules for them.
RELEASE_ASSERT_NOT_REACHED();
break;
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index f5cefa3..c5e1b04 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -290,6 +290,12 @@
out.print(comma, "^", node->phi()->index());
if (node->hasExecutionCounter())
out.print(comma, RawPointer(node->executionCounter()));
+ if (node->hasVariableWatchpointSet())
+ out.print(comma, RawPointer(node->variableWatchpointSet()));
+ if (node->hasTypedArray())
+ out.print(comma, inContext(JSValue(node->typedArray()), context));
+ if (node->hasStoragePointer())
+ out.print(comma, RawPointer(node->storagePointer()));
if (op == JSConstant) {
out.print(comma, "$", node->constantNumber());
JSValue value = valueOfJSConstant(node);
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index 2491073..8405c70 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -407,6 +407,13 @@
children.reset();
}
+ void convertToConstantStoragePointer(void* pointer)
+ {
+ ASSERT(op() == GetIndexedPropertyStorage);
+ m_op = ConstantStoragePointer;
+ m_opInfo = bitwise_cast<uintptr_t>(pointer);
+ }
+
void convertToGetLocalUnlinked(VirtualRegister local)
{
m_op = GetLocalUnlinked;
@@ -982,6 +989,16 @@
{
return reinterpret_cast<JSArrayBufferView*>(m_opInfo);
}
+
+ bool hasStoragePointer()
+ {
+ return op() == ConstantStoragePointer;
+ }
+
+ void* storagePointer()
+ {
+ return reinterpret_cast<void*>(m_opInfo);
+ }
bool hasStructureTransitionData()
{
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 7e23916..904374b 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -171,6 +171,7 @@
macro(Arrayify, NodeMustGenerate) \
macro(ArrayifyToStructure, NodeMustGenerate) \
macro(GetIndexedPropertyStorage, NodeResultStorage) \
+ macro(ConstantStoragePointer, NodeResultStorage) \
macro(TypedArrayWatchpoint, NodeMustGenerate) \
macro(GetByOffset, NodeResultJS) \
macro(PutByOffset, NodeMustGenerate) \
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 8bbb629..971a370 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -578,6 +578,7 @@
case NotifyWrite:
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
+ case ConstantStoragePointer:
break;
// This gets ignored because it already has a prediction.
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index cc46076..33115f2 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -245,6 +245,7 @@
case NotifyWrite:
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
+ case ConstantStoragePointer:
return true;
case GetByVal:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 1979111..7b4aada 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -4042,26 +4042,16 @@
#endif
}
-bool SpeculativeJIT::compileConstantIndexedPropertyStorage(Node* node)
+void SpeculativeJIT::compileConstantStoragePointer(Node* node)
{
- JSArrayBufferView* view = m_jit.graph().tryGetFoldableViewForChild1(node);
- if (!view)
- return false;
- if (view->mode() == FastTypedArray)
- return false;
-
GPRTemporary storage(this);
GPRReg storageGPR = storage.gpr();
- m_jit.move(TrustedImmPtr(view->vector()), storageGPR);
+ m_jit.move(TrustedImmPtr(node->storagePointer()), storageGPR);
storageResult(storageGPR, node);
- return true;
}
void SpeculativeJIT::compileGetIndexedPropertyStorage(Node* node)
{
- if (compileConstantIndexedPropertyStorage(node))
- return;
-
SpeculateCellOperand base(this, node->child1());
GPRReg baseReg = base.gpr();
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index dcd8572..ec917d2 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -2027,7 +2027,7 @@
void compileArithIMul(Node*);
void compileArithDiv(Node*);
void compileArithMod(Node*);
- bool compileConstantIndexedPropertyStorage(Node*);
+ void compileConstantStoragePointer(Node*);
void compileGetIndexedPropertyStorage(Node*);
JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR);
void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 1fd9763..c98d9f5 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -3946,6 +3946,11 @@
break;
}
+ case ConstantStoragePointer: {
+ compileConstantStoragePointer(node);
+ break;
+ }
+
case GetTypedArrayByteOffset: {
compileGetTypedArrayByteOffset(node);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 4baa2e0..9615b2a 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -4243,6 +4243,11 @@
break;
}
+ case ConstantStoragePointer: {
+ compileConstantStoragePointer(node);
+ break;
+ }
+
case GetTypedArrayByteOffset: {
compileGetTypedArrayByteOffset(node);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
index 8475487..d137a07 100644
--- a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
@@ -95,9 +95,22 @@
foldTypedArrayPropertyToConstant(view, jsNumber(view->byteOffset()));
break;
- // FIXME: The constant-folding of GetIndexedPropertyStorage should be expressed
- // as an IR transformation in this phase.
- // https://bugs.webkit.org/show_bug.cgi?id=125395
+ case GetIndexedPropertyStorage:
+ if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) {
+ if (view->mode() != FastTypedArray) {
+ prepareToFoldTypedArray(view);
+ m_node->convertToConstantStoragePointer(view->vector());
+ m_changed = true;
+ break;
+ } else {
+ // FIXME: It would be awesome to be able to fold the property storage for
+ // these GC-allocated typed arrays. For now it doesn't matter because the
+ // most common use-cases for constant typed arrays involve large arrays with
+ // aliased buffer views.
+ // https://bugs.webkit.org/show_bug.cgi?id=125425
+ }
+ }
+ break;
default:
break;
@@ -106,11 +119,18 @@
void foldTypedArrayPropertyToConstant(JSArrayBufferView* view, JSValue constant)
{
+ prepareToFoldTypedArray(view);
+ m_graph.convertToConstant(m_node, constant);
+ m_changed = true;
+ }
+
+ void prepareToFoldTypedArray(JSArrayBufferView* view)
+ {
m_insertionSet.insertNode(
m_nodeIndex, SpecNone, TypedArrayWatchpoint, m_node->codeOrigin,
OpInfo(view));
- m_graph.convertToConstant(m_node, constant);
- m_changed = true;
+ m_insertionSet.insertNode(
+ m_nodeIndex, SpecNone, Phantom, m_node->codeOrigin, m_node->children);
}
InsertionSet m_insertionSet;
diff --git a/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp b/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
index c452ffb..78df550 100644
--- a/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
@@ -138,18 +138,6 @@
addLazily(m_node->symbolTable()->m_functionEnteredOnce);
break;
- case GetIndexedPropertyStorage:
- if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) {
- // FIXME: It would be awesome to be able to fold the property storage for
- // these GC-allocated typed arrays. For now it doesn't matter because the
- // most common use-cases for constant typed arrays involve large arrays with
- // aliased buffer views.
- if (view->mode() == FastTypedArray)
- break;
- addLazily(view);
- }
- break;
-
case TypedArrayWatchpoint:
addLazily(m_node->typedArray());
break;