Skip to content

Commit 085b980

Browse files
committed
[JSC] uDFG should be able to watch JSGlobalObject WatchpointSets
https://bugs.webkit.org/show_bug.cgi?id=247154 rdar://101657085 Reviewed by Mark Lam. This patch allows uDFG to watch JSGlobalObject WatchpointSets. We extract this watchpoint insertion as a LinkerIR. And we run this when materializing DFG::JITData, which should eventually become uDFG's linking phase. We also fixed a bug where we missed visiting uDFG CallLinkInfo in CodeBlock. * Source/JavaScriptCore/bytecode/CodeBlock.cpp: (JSC::CodeBlock::finalizeJITInlineCaches): (JSC::CodeBlock::getICStatusMap): (JSC::CodeBlock::getCallLinkInfoForBytecodeIndex): * Source/JavaScriptCore/dfg/DFGGraph.h: * Source/JavaScriptCore/dfg/DFGJITCode.cpp: (JSC::DFG::JITData::JITData): (JSC::DFG::attemptToWatch): (JSC::DFG::JITData::tryInitialize): * Source/JavaScriptCore/dfg/DFGJITCode.h: (JSC::DFG::JITData::tryCreate): (JSC::DFG::JITData::create): Deleted. * Source/JavaScriptCore/dfg/DFGJITCompiler.cpp: (JSC::DFG::JITCompiler::link): (JSC::DFG::JITCompiler::addToConstantPool): * Source/JavaScriptCore/dfg/DFGJITCompiler.h: * Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp: (JSC::DFG::JITFinalizer::finalize): * Source/JavaScriptCore/dfg/DFGPlan.cpp: (JSC::DFG::Plan::tryFinalizeJITData): (JSC::DFG::Plan::finalizeJITData): Deleted. * Source/JavaScriptCore/dfg/DFGPlan.h: Canonical link: https://commits.webkit.org/256111@main
1 parent 30e20b0 commit 085b980

15 files changed

Lines changed: 212 additions & 76 deletions

‎Source/JavaScriptCore/bytecode/CodeBlock.cpp‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,10 @@ void CodeBlock::finalizeJITInlineCaches()
16021602
if (JITCode::isOptimizingJIT(jitType())) {
16031603
for (auto* callLinkInfo : m_jitCode->dfgCommon()->m_callLinkInfos)
16041604
callLinkInfo->visitWeak(vm());
1605+
if (auto* jitData = dfgJITData()) {
1606+
for (auto& callLinkInfo : jitData->callLinkInfos())
1607+
callLinkInfo.visitWeak(vm());
1608+
}
16051609
}
16061610
#endif
16071611

@@ -1708,6 +1712,10 @@ void CodeBlock::getICStatusMap(const ConcurrentJSLocker&, ICStatusMap& result)
17081712
DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
17091713
for (auto* callLinkInfo : dfgCommon->m_callLinkInfos)
17101714
result.add(callLinkInfo->codeOrigin(), ICStatus()).iterator->value.callLinkInfo = callLinkInfo;
1715+
if (auto* jitData = dfgJITData()) {
1716+
for (auto& callLinkInfo : jitData->callLinkInfos())
1717+
result.add(callLinkInfo.codeOrigin(), ICStatus()).iterator->value.callLinkInfo = &callLinkInfo;
1718+
}
17111719
for (auto& pair : dfgCommon->recordedStatuses.calls)
17121720
result.add(pair.first, ICStatus()).iterator->value.callStatus = pair.second.get();
17131721
for (auto& pair : dfgCommon->recordedStatuses.gets)
@@ -1772,6 +1780,12 @@ CallLinkInfo* CodeBlock::getCallLinkInfoForBytecodeIndex(const ConcurrentJSLocke
17721780
if (callLinkInfo->codeOrigin() == CodeOrigin(index))
17731781
return callLinkInfo;
17741782
}
1783+
if (auto* jitData = dfgJITData()) {
1784+
for (auto& callLinkInfo : jitData->callLinkInfos()) {
1785+
if (callLinkInfo.codeOrigin() == CodeOrigin(index))
1786+
return &callLinkInfo;
1787+
}
1788+
}
17751789
}
17761790
#endif
17771791
return nullptr;

‎Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2298,7 +2298,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
22982298
}
22992299

23002300
if (node->arrayMode().isOutOfBounds()) {
2301-
if (m_graph.isWatchingArrayPrototypeIsSaneChainWatchpoint(node)) {
2301+
if (m_graph.isWatchingArrayPrototypeChainIsSaneWatchpoint(node)) {
23022302
if (node->arrayMode().type() == Array::Double && node->arrayMode().isOutOfBoundsSaneChain() && !(node->flags() & NodeBytecodeUsesAsOther))
23032303
setConstant(node, jsNumber(PNaN));
23042304
else

‎Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ class ArgumentsEliminationPhase : public Phase {
249249

250250
// If we're out-of-bounds then we proceed only if the prototype chain
251251
// for the allocation is sane (i.e. doesn't have indexed properties).
252-
if (m_graph.isWatchingObjectPrototypeIsSaneChainWatchpoint(edge.node()))
252+
if (m_graph.isWatchingObjectPrototypeChainIsSaneWatchpoint(edge.node()))
253253
break;
254254
escape(edge, source);
255255
break;
@@ -268,10 +268,10 @@ class ArgumentsEliminationPhase : public Phase {
268268
// If we're out-of-bounds then we proceed only if the prototype chain
269269
// for the allocation is sane (i.e. doesn't have indexed properties).
270270
if (edge->op() == CreateRest) {
271-
if (m_graph.isWatchingArrayPrototypeIsSaneChainWatchpoint(edge.node()))
271+
if (m_graph.isWatchingArrayPrototypeChainIsSaneWatchpoint(edge.node()))
272272
break;
273273
} else {
274-
if (m_graph.isWatchingObjectPrototypeIsSaneChainWatchpoint(edge.node()))
274+
if (m_graph.isWatchingObjectPrototypeChainIsSaneWatchpoint(edge.node()))
275275
break;
276276
}
277277
escape(edge, source);

‎Source/JavaScriptCore/dfg/DFGArrayMode.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ ArrayMode ArrayMode::refine(
255255
if (node->op() == GetByVal
256256
&& isJSArrayWithOriginalStructure()
257257
&& !graph.hasExitSite(node->origin.semantic, OutOfBounds)
258-
&& graph.isWatchingArrayPrototypeIsSaneChainWatchpoint(node))
258+
&& graph.isWatchingArrayPrototypeChainIsSaneWatchpoint(node))
259259
return withSpeculation(Array::InBoundsSaneChain);
260260
return ArrayMode(Array::Generic, action());
261261
}

‎Source/JavaScriptCore/dfg/DFGFixupPhase.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,7 @@ class FixupPhase : public Phase {
17061706
// that it doesn't contain any indexed properties, and that any holes will result in
17071707
// jsUndefined().
17081708
if (node->child1()->shouldSpeculateArray()
1709-
&& m_graph.isWatchingArrayPrototypeIsSaneChainWatchpoint(node->child1().node())
1709+
&& m_graph.isWatchingArrayPrototypeChainIsSaneWatchpoint(node->child1().node())
17101710
&& m_graph.isWatchingArrayIteratorProtocolWatchpoint(node->child1().node())
17111711
&& m_graph.isWatchingHavingABadTimeWatchpoint(node->child1().node()))
17121712
fixEdge<ArrayUse>(node->child1());
@@ -3833,7 +3833,7 @@ class FixupPhase : public Phase {
38333833

38343834
bool watchSaneChain(Node* node)
38353835
{
3836-
return m_graph.isWatchingArrayPrototypeIsSaneChainWatchpoint(node);
3836+
return m_graph.isWatchingArrayPrototypeChainIsSaneWatchpoint(node);
38373837
}
38383838

38393839
void setSaneChainIfPossible(Node* node, Array::Speculation speculation)

‎Source/JavaScriptCore/dfg/DFGGraph.h‎

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -793,10 +793,24 @@ class Graph final : public virtual Scannable {
793793
}
794794

795795
template<typename WatchpointSet>
796-
bool isWatchingGlobalObjectWatchpoint(JSGlobalObject* globalObject, WatchpointSet& set)
796+
bool isWatchingGlobalObjectWatchpoint(JSGlobalObject* globalObject, WatchpointSet& set, LinkerIR::Type type)
797797
{
798-
if (m_plan.isUnlinked())
799-
return false;
798+
if (m_plan.isUnlinked()) {
799+
if (m_codeBlock->globalObject() != globalObject)
800+
return false;
801+
802+
LinkerIR::Value value { nullptr, type };
803+
if (m_constantPoolMap.contains(value))
804+
return true;
805+
806+
if (!set.isStillValid()) {
807+
auto result = m_constantPoolMap.add(value, m_constantPoolMap.size());
808+
ASSERT_UNUSED(result, result.isNewEntry);
809+
m_constantPool.append(value);
810+
}
811+
812+
return true;
813+
}
800814

801815
if (watchpoints().isWatched(set))
802816
return true;
@@ -816,112 +830,79 @@ class Graph final : public virtual Scannable {
816830

817831
bool isWatchingHavingABadTimeWatchpoint(Node* node)
818832
{
819-
if (m_plan.isUnlinked())
820-
return false;
821-
822833
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
823834
WatchpointSet& set = globalObject->havingABadTimeWatchpointSet();
824-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
835+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::HavingABadTimeWatchpointSet);
825836
}
826837

827838
bool isWatchingMasqueradesAsUndefinedWatchpointSet(Node* node)
828839
{
829-
if (m_plan.isUnlinked())
830-
return false;
831-
832840
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
833841
WatchpointSet& set = globalObject->masqueradesAsUndefinedWatchpointSet();
834-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
842+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::MasqueradesAsUndefinedWatchpointSet);
835843
}
836844

837845
bool isWatchingArrayIteratorProtocolWatchpoint(Node* node)
838846
{
839-
if (m_plan.isUnlinked())
840-
return false;
841-
842847
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
843848
InlineWatchpointSet& set = globalObject->arrayIteratorProtocolWatchpointSet();
844-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
849+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::ArrayIteratorProtocolWatchpointSet);
845850
}
846851

847852
bool isWatchingNumberToStringWatchpoint(Node* node)
848853
{
849-
if (m_plan.isUnlinked())
850-
return false;
851-
852854
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
853855
InlineWatchpointSet& set = globalObject->numberToStringWatchpointSet();
854-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
856+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::NumberToStringWatchpointSet);
855857
}
856858

857859
bool isWatchingStructureCacheClearedWatchpoint(Node* node)
858860
{
859-
if (m_plan.isUnlinked())
860-
return false;
861-
862861
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
863862
InlineWatchpointSet& set = globalObject->structureCacheClearedWatchpointSet();
864-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
863+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::StructureCacheClearedWatchpointSet);
865864
}
866865

867866
bool isWatchingStringSymbolReplaceWatchpoint(Node* node)
868867
{
869-
if (m_plan.isUnlinked())
870-
return false;
871-
872868
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
873869
InlineWatchpointSet& set = globalObject->stringSymbolReplaceWatchpointSet();
874-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
870+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::StringSymbolReplaceWatchpointSet);
875871
}
876872

877873
bool isWatchingRegExpPrimordialPropertiesWatchpoint(Node* node)
878874
{
879-
if (m_plan.isUnlinked())
880-
return false;
881-
882875
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
883876
InlineWatchpointSet& set = globalObject->regExpPrimordialPropertiesWatchpointSet();
884-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
877+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::RegExpPrimordialPropertiesWatchpointSet);
885878
}
886879

887880
bool isWatchingArraySpeciesWatchpoint(Node* node)
888881
{
889-
if (m_plan.isUnlinked())
890-
return false;
891-
892882
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
893883
InlineWatchpointSet& set = globalObject->arraySpeciesWatchpointSet();
894-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
884+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::ArraySpeciesWatchpointSet);
895885
}
896886

897-
bool isWatchingArrayPrototypeIsSaneChainWatchpoint(Node* node)
887+
bool isWatchingArrayPrototypeChainIsSaneWatchpoint(Node* node)
898888
{
899-
if (m_plan.isUnlinked())
900-
return false;
901-
902889
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
903890
InlineWatchpointSet& set = globalObject->arrayPrototypeChainIsSaneWatchpointSet();
904-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
891+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::ArrayPrototypeChainIsSaneWatchpointSet);
905892
}
906893

907-
bool isWatchingStringPrototypeIsSaneChainWatchpoint(Node* node)
894+
bool isWatchingStringPrototypeChainIsSaneWatchpoint(Node* node)
908895
{
909-
if (m_plan.isUnlinked())
910-
return false;
911-
912896
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
913897
InlineWatchpointSet& set = globalObject->stringPrototypeChainIsSaneWatchpointSet();
914-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
898+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::StringPrototypeChainIsSaneWatchpointSet);
915899
}
916900

917-
bool isWatchingObjectPrototypeIsSaneChainWatchpoint(Node* node)
901+
bool isWatchingObjectPrototypeChainIsSaneWatchpoint(Node* node)
918902
{
919-
if (m_plan.isUnlinked())
920-
return false;
921-
922903
JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
923904
InlineWatchpointSet& set = globalObject->objectPrototypeChainIsSaneWatchpointSet();
924-
return isWatchingGlobalObjectWatchpoint(globalObject, set);
905+
return isWatchingGlobalObjectWatchpoint(globalObject, set, LinkerIR::Type::ObjectPrototypeChainIsSaneWatchpointSet);
925906
}
926907

927908
Profiler::Compilation* compilation() { return m_plan.compilation(); }
@@ -1287,6 +1268,9 @@ class Graph final : public virtual Scannable {
12871268
HashMap<GenericHashKey<int64_t>, double*> m_doubleConstantsMap;
12881269
Bag<double> m_doubleConstants;
12891270
#endif
1271+
1272+
Vector<LinkerIR::Value> m_constantPool;
1273+
HashMap<LinkerIR::Value, LinkerIR::Constant, LinkerIR::ValueHash, LinkerIR::ValueTraits> m_constantPoolMap;
12901274

12911275
OptimizationFixpointState m_fixpointState;
12921276
StructureRegistrationState m_structureRegistrationState;

0 commit comments

Comments
 (0)