Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (184437 => 184438)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2015-05-16 21:01:42 UTC (rev 184438)
@@ -227,7 +227,7 @@
dfg/DFGSpeculativeJIT64.cpp
dfg/DFGStackLayoutPhase.cpp
dfg/DFGStaticExecutionCountEstimationPhase.cpp
- dfg/DFGStoreBarrierInsertionPhase.cpp
+ dfg/DFGStoreBarrierElisionPhase.cpp
dfg/DFGStrengthReductionPhase.cpp
dfg/DFGStructureAbstractValue.cpp
dfg/DFGStructureRegistrationPhase.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (184437 => 184438)
--- trunk/Source/_javascript_Core/ChangeLog 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-05-16 21:01:42 UTC (rev 184438)
@@ -1,3 +1,17 @@
+2015-05-16 Commit Queue <[email protected]>
+
+ Unreviewed, rolling out r184415.
+ https://bugs.webkit.org/show_bug.cgi?id=145096
+
+ Broke several tests (Requested by msaboff on #webkit).
+
+ Reverted changeset:
+
+ "Insert store barriers late so that IR transformations don't
+ have to worry about them"
+ https://bugs.webkit.org/show_bug.cgi?id=145015
+ http://trac.webkit.org/changeset/184415
+
2015-05-14 Filip Pizlo <[email protected]>
Insert store barriers late so that IR transformations don't have to worry about them
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (184437 => 184438)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2015-05-16 21:01:42 UTC (rev 184438)
@@ -467,7 +467,7 @@
<ClCompile Include="..\dfg\DFGSSALoweringPhase.cpp" />
<ClCompile Include="..\dfg\DFGStackLayoutPhase.cpp" />
<ClCompile Include="..\dfg\DFGStaticExecutionCountEstimationPhase.cpp" />
- <ClCompile Include="..\dfg\DFGStoreBarrierInsertionPhase.cpp" />
+ <ClCompile Include="..\dfg\DFGStoreBarrierElisionPhase.cpp" />
<ClCompile Include="..\dfg\DFGStrengthReductionPhase.cpp" />
<ClCompile Include="..\dfg\DFGStructureAbstractValue.cpp" />
<ClCompile Include="..\dfg\DFGStructureRegistrationPhase.cpp" />
@@ -1173,7 +1173,7 @@
<ClInclude Include="..\dfg\DFGSSALoweringPhase.h" />
<ClInclude Include="..\dfg\DFGStackLayoutPhase.h" />
<ClInclude Include="..\dfg\DFGStaticExecutionCountEstimationPhase.h" />
- <ClInclude Include="..\dfg\DFGStoreBarrierInsertionPhase.h" />
+ <ClInclude Include="..\dfg\DFGStoreBarrierElisionPhase.h" />
<ClInclude Include="..\dfg\DFGStrengthReductionPhase.h" />
<ClInclude Include="..\dfg\DFGStructureAbstractValue.h" />
<ClInclude Include="..\dfg\DFGStructureClobberState.h" />
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (184437 => 184438)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-05-16 21:01:42 UTC (rev 184438)
@@ -462,8 +462,6 @@
0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D33991803ADB70073C2BC /* FTLStackMaps.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9D36941AE9CC33000D4DFB /* DFGCleanUpPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D36921AE9CC33000D4DFB /* DFGCleanUpPhase.cpp */; };
0F9D36951AE9CC33000D4DFB /* DFGCleanUpPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D36931AE9CC33000D4DFB /* DFGCleanUpPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F9E32631B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */; };
- 0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */; };
0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */; };
@@ -930,6 +928,8 @@
2AAD964A18569417001F93BE /* RecursiveAllocationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AAD964918569417001F93BE /* RecursiveAllocationScope.h */; };
2AC922BB18A16182003CE0FB /* FTLDWARFDebugLineInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AC922B918A16182003CE0FB /* FTLDWARFDebugLineInfo.cpp */; };
2AC922BC18A16182003CE0FB /* FTLDWARFDebugLineInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */; };
+ 2ACCF3DE185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */; };
+ 2ACCF3DF185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */; };
2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; };
2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */; };
@@ -2201,8 +2201,6 @@
0F9D33991803ADB70073C2BC /* FTLStackMaps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLStackMaps.h; path = ftl/FTLStackMaps.h; sourceTree = "<group>"; };
0F9D36921AE9CC33000D4DFB /* DFGCleanUpPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCleanUpPhase.cpp; path = dfg/DFGCleanUpPhase.cpp; sourceTree = "<group>"; };
0F9D36931AE9CC33000D4DFB /* DFGCleanUpPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCleanUpPhase.h; path = dfg/DFGCleanUpPhase.h; sourceTree = "<group>"; };
- 0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierInsertionPhase.cpp; path = dfg/DFGStoreBarrierInsertionPhase.cpp; sourceTree = "<group>"; };
- 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierInsertionPhase.h; path = dfg/DFGStoreBarrierInsertionPhase.h; sourceTree = "<group>"; };
0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStackLayoutPhase.cpp; path = dfg/DFGStackLayoutPhase.cpp; sourceTree = "<group>"; };
0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStackLayoutPhase.h; path = dfg/DFGStackLayoutPhase.h; sourceTree = "<group>"; };
0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicPutByIdList.cpp; sourceTree = "<group>"; };
@@ -2639,6 +2637,8 @@
2AAD964918569417001F93BE /* RecursiveAllocationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursiveAllocationScope.h; sourceTree = "<group>"; };
2AC922B918A16182003CE0FB /* FTLDWARFDebugLineInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLDWARFDebugLineInfo.cpp; path = ftl/FTLDWARFDebugLineInfo.cpp; sourceTree = "<group>"; };
2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLDWARFDebugLineInfo.h; path = ftl/FTLDWARFDebugLineInfo.h; sourceTree = "<group>"; };
+ 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierElisionPhase.cpp; path = dfg/DFGStoreBarrierElisionPhase.cpp; sourceTree = "<group>"; };
+ 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierElisionPhase.h; path = dfg/DFGStoreBarrierElisionPhase.h; sourceTree = "<group>"; };
2AD2EDFA19799E38004D6478 /* EnumerationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumerationMode.h; sourceTree = "<group>"; };
2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = "<group>"; };
2ADFA26218EF3540004F9FCC /* GCLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCLogging.cpp; sourceTree = "<group>"; };
@@ -5089,8 +5089,8 @@
0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */,
0F4F29DD18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp */,
0F4F29DE18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h */,
- 0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */,
- 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */,
+ 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */,
+ 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */,
0FC20CB31852E2C600C9E954 /* DFGStrengthReductionPhase.cpp */,
0FC20CB41852E2C600C9E954 /* DFGStrengthReductionPhase.h */,
0F893BDA1936E23C001211F4 /* DFGStructureAbstractValue.cpp */,
@@ -5894,8 +5894,8 @@
A7D89D0017A0B8CC00773AD8 /* DFGSSAConversionPhase.h in Headers */,
0FC20CBA18556A3500C9E954 /* DFGSSALoweringPhase.h in Headers */,
0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */,
- 0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */,
0F4F29E018B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h in Headers */,
+ 2ACCF3DF185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h in Headers */,
0FC20CB61852E2C600C9E954 /* DFGStrengthReductionPhase.h in Headers */,
0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */,
0F2FCCFF18A60070001A27F8 /* DFGThreadData.h in Headers */,
@@ -7181,6 +7181,7 @@
0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
0F4F29DF18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp in Sources */,
0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */,
+ 2ACCF3DE185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp in Sources */,
0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */,
0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */,
0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
@@ -7201,7 +7202,6 @@
0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */,
0F2BDC4A1522809A00CD8910 /* DFGVariableEventStream.cpp in Sources */,
0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */,
- 0F9E32631B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp in Sources */,
0FC97F4118202119002C9B26 /* DFGWatchpointCollectionPhase.cpp in Sources */,
0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */,
0F9D3370165DBB90005AD387 /* Disassembler.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/dfg/DFGBlockMap.h (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGBlockMap.h 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGBlockMap.h 2015-05-16 21:01:42 UTC (rev 184438)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -58,26 +58,6 @@
return m_vector[blockIndex];
}
- T& at(BlockIndex blockIndex)
- {
- return m_vector[blockIndex];
- }
-
- const T& at(BlockIndex blockIndex) const
- {
- return m_vector[blockIndex];
- }
-
- T& at(BasicBlock* block)
- {
- return m_vector[block->index];
- }
-
- const T& at(BasicBlock* block) const
- {
- return m_vector[block->index];
- }
-
T& operator[](BlockIndex blockIndex)
{
return m_vector[blockIndex];
Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2015-05-16 21:01:42 UTC (rev 184438)
@@ -597,6 +597,7 @@
Node* allocatePropertyStorage = m_insertionSet.insertNode(
indexInBlock, SpecNone, AllocatePropertyStorage,
origin, OpInfo(transition), childEdge);
+ m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
propertyStorage = Edge(allocatePropertyStorage);
} else {
ASSERT(variant.oldStructureForTransition()->outOfLineCapacity());
@@ -608,6 +609,7 @@
OpInfo(transition), childEdge,
Edge(m_insertionSet.insertNode(
indexInBlock, SpecNone, GetButterfly, origin, childEdge)));
+ m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
propertyStorage = Edge(reallocatePropertyStorage);
}
Modified: trunk/Source/_javascript_Core/dfg/DFGEpoch.h (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGEpoch.h 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGEpoch.h 2015-05-16 21:01:42 UTC (rev 184438)
@@ -87,26 +87,6 @@
return !(*this == other);
}
- bool operator<(const Epoch& other) const
- {
- return m_epoch < other.m_epoch;
- }
-
- bool operator>(const Epoch& other) const
- {
- return other < *this;
- }
-
- bool operator<=(const Epoch& other) const
- {
- return !(*this > other);
- }
-
- bool operator>=(const Epoch& other) const
- {
- return !(*this < other);
- }
-
void dump(PrintStream&) const;
private:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-05-16 21:01:42 UTC (rev 184438)
@@ -722,7 +722,7 @@
case Array::SlowPutArrayStorage:
fixEdge<KnownCellUse>(child1);
fixEdge<Int32Use>(child2);
- speculateForBarrier(child3);
+ insertStoreBarrier(m_indexInBlock, child1, child3);
break;
default:
fixEdge<KnownCellUse>(child1);
@@ -760,7 +760,7 @@
break;
case Array::Contiguous:
case Array::ArrayStorage:
- speculateForBarrier(node->child2());
+ insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
break;
default:
break;
@@ -922,6 +922,7 @@
case PutStructure: {
fixEdge<KnownCellUse>(node->child1());
+ insertStoreBarrier(m_indexInBlock, node->child1());
break;
}
@@ -934,7 +935,7 @@
case PutClosureVar:
case PutToArguments: {
fixEdge<KnownCellUse>(node->child1());
- speculateForBarrier(node->child2());
+ insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
break;
}
@@ -949,6 +950,7 @@
case AllocatePropertyStorage:
case ReallocatePropertyStorage: {
fixEdge<KnownCellUse>(node->child1());
+ insertStoreBarrier(m_indexInBlock + 1, node->child1());
break;
}
@@ -984,7 +986,7 @@
case PutByIdFlush:
case PutByIdDirect: {
fixEdge<CellUse>(node->child1());
- speculateForBarrier(node->child2());
+ insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
break;
}
@@ -1027,13 +1029,13 @@
if (!node->child1()->hasStorageResult())
fixEdge<KnownCellUse>(node->child1());
fixEdge<KnownCellUse>(node->child2());
- speculateForBarrier(node->child3());
+ insertStoreBarrier(m_indexInBlock, node->child2(), node->child3());
break;
}
case MultiPutByOffset: {
fixEdge<CellUse>(node->child1());
- speculateForBarrier(node->child2());
+ insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
break;
}
@@ -1113,16 +1115,16 @@
case PutStack:
case KillStack:
case GetStack:
- case StoreBarrier:
// 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.
- DFG_CRASH(m_graph, node, "Unexpected node during fixup");
+ RELEASE_ASSERT_NOT_REACHED();
break;
case PutGlobalVar: {
fixEdge<CellUse>(node->child1());
- speculateForBarrier(node->child2());
+ insertStoreBarrier(
+ m_indexInBlock, node->child1(), node->child2());
break;
}
@@ -1296,6 +1298,7 @@
case Unreachable:
case ExtractOSREntryLocal:
case LoopHint:
+ case StoreBarrier:
case MovHint:
case ZombieHint:
case BottomValue:
@@ -1759,35 +1762,37 @@
edge.setUseKind(useKind);
}
- void speculateForBarrier(Edge value)
+ void insertStoreBarrier(unsigned indexInBlock, Edge base, Edge value = Edge())
{
- if (!isFTL(m_graph.m_plan.mode))
- return;
-
- if (value->shouldSpeculateInt32()) {
- insertCheck<Int32Use>(m_indexInBlock, value.node());
- return;
- }
+ if (!!value) {
+ if (value->shouldSpeculateInt32()) {
+ insertCheck<Int32Use>(indexInBlock, value.node());
+ return;
+ }
- if (value->shouldSpeculateBoolean()) {
- insertCheck<BooleanUse>(m_indexInBlock, value.node());
- return;
- }
+ if (value->shouldSpeculateBoolean()) {
+ insertCheck<BooleanUse>(indexInBlock, value.node());
+ return;
+ }
- if (value->shouldSpeculateOther()) {
- insertCheck<OtherUse>(m_indexInBlock, value.node());
- return;
- }
+ if (value->shouldSpeculateOther()) {
+ insertCheck<OtherUse>(indexInBlock, value.node());
+ return;
+ }
- if (value->shouldSpeculateNumber()) {
- insertCheck<NumberUse>(m_indexInBlock, value.node());
- return;
- }
+ if (value->shouldSpeculateNumber()) {
+ insertCheck<NumberUse>(indexInBlock, value.node());
+ return;
+ }
- if (value->shouldSpeculateNotCell()) {
- insertCheck<NotCellUse>(m_indexInBlock, value.node());
- return;
+ if (value->shouldSpeculateNotCell()) {
+ insertCheck<NotCellUse>(indexInBlock, value.node());
+ return;
+ }
}
+
+ m_insertionSet.insertNode(
+ indexInBlock, SpecNone, StoreBarrier, m_currentNode->origin, base);
}
template<UseKind useKind>
Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-05-16 21:01:42 UTC (rev 184438)
@@ -613,7 +613,11 @@
}
case StoreBarrier: {
- DFG_CRASH(m_graph, node, "Unexpected store barrier during sinking.");
+ Node* target = node->child1().node();
+ if (m_sinkCandidates.contains(target)) {
+ ASSERT(target->isPhantomAllocation());
+ node->remove();
+ }
break;
}
@@ -850,6 +854,7 @@
case MovHint:
case PutHint:
+ case StoreBarrier:
break;
case PutStructure:
Modified: trunk/Source/_javascript_Core/dfg/DFGPlan.cpp (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2015-05-16 21:01:42 UTC (rev 184438)
@@ -60,7 +60,7 @@
#include "DFGSSALoweringPhase.h"
#include "DFGStackLayoutPhase.h"
#include "DFGStaticExecutionCountEstimationPhase.h"
-#include "DFGStoreBarrierInsertionPhase.h"
+#include "DFGStoreBarrierElisionPhase.h"
#include "DFGStrengthReductionPhase.h"
#include "DFGStructureRegistrationPhase.h"
#include "DFGTierUpCheckInjectionPhase.h"
@@ -315,7 +315,7 @@
performTierUpCheckInjection(dfg);
- performFastStoreBarrierInsertion(dfg);
+ performStoreBarrierElision(dfg);
performCleanUp(dfg);
performCPSRethreading(dfg);
performDCE(dfg);
@@ -387,9 +387,9 @@
// about code motion assumes that it's OK to insert GC points in random places.
dfg.m_fixpointState = FixpointConverged;
+ performStoreBarrierElision(dfg);
performLivenessAnalysis(dfg);
performCFA(dfg);
- performGlobalStoreBarrierInsertion(dfg);
if (Options::enableMovHintRemoval())
performMovHintRemoval(dfg);
performCleanUp(dfg);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-05-16 21:01:42 UTC (rev 184438)
@@ -562,11 +562,10 @@
case MaterializeCreateActivation:
case PutStack:
case KillStack:
- case StoreBarrier:
case GetStack: {
// This node should never be visible at this stage of compilation. It is
// inserted by fixup(), which follows this phase.
- DFG_CRASH(m_graph, node, "Unexpected node during prediction propagation");
+ RELEASE_ASSERT_NOT_REACHED();
break;
}
@@ -618,6 +617,7 @@
#ifndef NDEBUG
// These get ignored because they don't return anything.
+ case StoreBarrier:
case PutByValDirect:
case PutByVal:
case PutClosureVar:
Added: trunk/Source/_javascript_Core/dfg/DFGStoreBarrierElisionPhase.cpp (0 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGStoreBarrierElisionPhase.cpp (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGStoreBarrierElisionPhase.cpp 2015-05-16 21:01:42 UTC (rev 184438)
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DFGStoreBarrierElisionPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGBasicBlock.h"
+#include "DFGClobberize.h"
+#include "DFGDoesGC.h"
+#include "DFGGraph.h"
+#include "DFGPhase.h"
+#include "JSCInlines.h"
+#include <wtf/HashSet.h>
+
+namespace JSC { namespace DFG {
+
+class StoreBarrierElisionPhase : public Phase {
+public:
+ StoreBarrierElisionPhase(Graph& graph)
+ : Phase(graph, "store barrier elision")
+ , m_currentBlock(0)
+ , m_currentIndex(0)
+ {
+ }
+
+ bool run()
+ {
+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
+ m_currentBlock = m_graph.block(blockIndex);
+ if (!m_currentBlock)
+ continue;
+ handleBlock(m_currentBlock);
+ }
+ return true;
+ }
+
+private:
+ bool allocatesFreshObject(Node* node)
+ {
+ switch (node->op()) {
+ case NewObject:
+ case NewArray:
+ case NewArrayWithSize:
+ case NewArrayBuffer:
+ case NewTypedArray:
+ case NewRegexp:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ void noticeFreshObject(HashSet<Node*>& dontNeedBarriers, Node* node)
+ {
+ ASSERT(allocatesFreshObject(node));
+ dontNeedBarriers.add(node);
+ }
+
+ Node* getBaseOfStore(Node* barrierNode)
+ {
+ ASSERT(barrierNode->isStoreBarrier());
+ return barrierNode->child1().node();
+ }
+
+ bool shouldBeElided(HashSet<Node*>& dontNeedBarriers, Node* node)
+ {
+ ASSERT(node->isStoreBarrier());
+ return dontNeedBarriers.contains(node->child1().node());
+ }
+
+ void elideBarrier(Node* node)
+ {
+ ASSERT(node->isStoreBarrier());
+ node->remove();
+ }
+
+ void handleNode(HashSet<Node*>& dontNeedBarriers, Node* node)
+ {
+ if (doesGC(m_graph, node))
+ dontNeedBarriers.clear();
+
+ if (allocatesFreshObject(node))
+ noticeFreshObject(dontNeedBarriers, node);
+
+ if (!node->isStoreBarrier())
+ return;
+
+ if (shouldBeElided(dontNeedBarriers, node)) {
+ elideBarrier(node);
+ return;
+ }
+
+ Node* base = getBaseOfStore(node);
+ if (!base)
+ return;
+
+ if (dontNeedBarriers.contains(base))
+ return;
+ dontNeedBarriers.add(base);
+ }
+
+ bool handleBlock(BasicBlock* block)
+ {
+ HashSet<Node*> dontNeedBarriers;
+ for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
+ m_currentIndex = indexInBlock;
+ Node* node = block->at(indexInBlock);
+ handleNode(dontNeedBarriers, node);
+ }
+ return true;
+ }
+
+ BasicBlock* m_currentBlock;
+ unsigned m_currentIndex;
+};
+
+bool performStoreBarrierElision(Graph& graph)
+{
+ SamplingRegion samplingRegion("DFG Store Barrier Elision Phase");
+ return runPhase<StoreBarrierElisionPhase>(graph);
+}
+
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
Copied: trunk/Source/_javascript_Core/dfg/DFGStoreBarrierElisionPhase.h (from rev 184437, trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.h) (0 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGStoreBarrierElisionPhase.h (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGStoreBarrierElisionPhase.h 2015-05-16 21:01:42 UTC (rev 184438)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DFGStoreBarrierElisionPhase_h
+#define DFGStoreBarrierElisionPhase_h
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+bool performStoreBarrierElision(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // DFGStoreBarrierElisionPhase_h
Deleted: trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp 2015-05-16 21:01:42 UTC (rev 184438)
@@ -1,528 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DFGStoreBarrierInsertionPhase.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGAbstractInterpreterInlines.h"
-#include "DFGBlockMapInlines.h"
-#include "DFGDoesGC.h"
-#include "DFGGraph.h"
-#include "DFGInPlaceAbstractState.h"
-#include "DFGInsertionSet.h"
-#include "DFGPhase.h"
-#include "JSCInlines.h"
-#include <wtf/CommaPrinter.h>
-#include <wtf/HashSet.h>
-
-namespace JSC { namespace DFG {
-
-namespace {
-
-bool verbose = false;
-
-enum class PhaseMode {
- // Does only a local analysis for store barrier insertion and assumes that pointers live
- // from predecessor blocks may need barriers. Assumes CPS conventions. Does not use AI for
- // eliminating store barriers, but does a best effort to eliminate barriers when you're
- // storing a non-cell value by using Node::result() and by looking at constants. The local
- // analysis is based on GC epochs, so it will eliminate a lot of locally redundant barriers.
- Fast,
-
- // Does a global analysis for store barrier insertion. Reuses the GC-epoch-based analysis
- // used by Fast, but adds a conservative merge rule for propagating information from one
- // block to the next. This will ensure for example that if a value V coming from multiple
- // predecessors in B didn't need any more barriers at the end of each predecessor (either
- // because it was the last allocated object in that predecessor or because it just had a
- // barrier executed), then until we hit another GC point in B, we won't need another barrier
- // on V. Uses AI for eliminating barriers when we know that the value being stored is not a
- // cell. Assumes SSA conventions.
- Global
-};
-
-template<PhaseMode mode>
-class StoreBarrierInsertionPhase : public Phase {
-public:
- StoreBarrierInsertionPhase(Graph& graph)
- : Phase(graph, mode == PhaseMode::Fast ? "fast store barrier insertion" : "global store barrier insertion")
- , m_insertionSet(graph)
- {
- }
-
- bool run()
- {
- if (verbose) {
- dataLog("Starting store barrier insertion:\n");
- m_graph.dump();
- }
-
- switch (mode) {
- case PhaseMode::Fast: {
- DFG_ASSERT(m_graph, nullptr, m_graph.m_form != SSA);
-
- m_graph.clearEpochs();
- for (BasicBlock* block : m_graph.blocksInNaturalOrder())
- handleBlock(block);
- return true;
- }
-
- case PhaseMode::Global: {
- DFG_ASSERT(m_graph, nullptr, m_graph.m_form == SSA);
-
- m_state = std::make_unique<InPlaceAbstractState>(m_graph);
- m_interpreter = std::make_unique<AbstractInterpreter<InPlaceAbstractState>>(m_graph, *m_state);
-
- m_isConverged = false;
-
- // First run the analysis. Inside basic blocks we use an epoch-based analysis that
- // is very precise. At block boundaries, we just propagate which nodes may need a
- // barrier. This gives us a very nice bottom->top fixpoint: we start out assuming
- // that no node needs any barriers at block boundaries, and then we converge
- // towards believing that all nodes need barriers. "Needing a barrier" is like
- // saying that the node is in a past epoch. "Not needing a barrier" is like saying
- // that the node is in the current epoch.
- m_stateAtHead = std::make_unique<BlockMap<HashSet<Node*>>>(m_graph);
- m_stateAtTail = std::make_unique<BlockMap<HashSet<Node*>>>(m_graph);
-
- BlockList postOrder = m_graph.blocksInPostOrder();
-
- bool changed = true;
- while (changed) {
- changed = false;
-
- // Intentional backwards loop because we are using RPO.
- for (unsigned blockIndex = postOrder.size(); blockIndex--;) {
- BasicBlock* block = postOrder[blockIndex];
-
- if (!handleBlock(block)) {
- // If the block didn't finish, then it cannot affect the fixpoint.
- continue;
- }
-
- // Construct the state-at-tail based on the epochs of live nodes and the
- // current epoch. We grow state-at-tail monotonically to ensure convergence.
- bool thisBlockChanged = false;
- for (Node* node : block->ssa->liveAtTail) {
- if (node->epoch() != m_currentEpoch) {
- // If the node is older than the current epoch, then we may need to
- // run a barrier on it in the future. So, add it to the state.
- thisBlockChanged |= m_stateAtTail->at(block).add(node).isNewEntry;
- }
- }
-
- if (!thisBlockChanged) {
- // This iteration didn't learn anything new about this block.
- continue;
- }
-
- // Changed things. Make sure that we loop one more time.
- changed = true;
-
- for (BasicBlock* successor : block->successors()) {
- for (Node* node : m_stateAtTail->at(block))
- m_stateAtHead->at(successor).add(node);
- }
- }
- }
-
- // Tell handleBlock() that it's time to actually insert barriers for real.
- m_isConverged = true;
-
- for (BasicBlock* block : m_graph.blocksInNaturalOrder())
- handleBlock(block);
-
- return true;
- } }
-
- RELEASE_ASSERT_NOT_REACHED();
- return false;
- }
-
-private:
- bool handleBlock(BasicBlock* block)
- {
- if (verbose) {
- dataLog("Dealing with block ", pointerDump(block), "\n");
- if (reallyInsertBarriers())
- dataLog(" Really inserting barriers.\n");
- }
-
- m_currentEpoch = Epoch::first();
-
- if (mode == PhaseMode::Global) {
- if (!block->cfaHasVisited)
- return false;
- m_state->beginBasicBlock(block);
-
- for (Node* node : block->ssa->liveAtHead) {
- if (m_stateAtHead->at(block).contains(node)) {
- // If previous blocks tell us that this node may need a barrier in the
- // future, then put it in the ancient primordial epoch. This forces us to
- // emit a barrier on any possibly-cell store, regardless of the epoch of the
- // stored value.
- node->setEpoch(Epoch());
- } else {
- // If previous blocks aren't requiring us to run a barrier on this node,
- // then put it in the current epoch. This means that we will skip barriers
- // on this node so long as we don't allocate. It also means that we won't
- // run barriers on stores to on one such node into another such node. That's
- // fine, because nodes would be excluded from the state set if at the tails
- // of all predecessors they always had the current epoch.
- node->setEpoch(m_currentEpoch);
- }
- }
- }
-
- bool result = true;
-
- for (m_nodeIndex = 0; m_nodeIndex < block->size(); ++m_nodeIndex) {
- m_node = block->at(m_nodeIndex);
-
- if (verbose) {
- dataLog(
- " ", m_currentEpoch, ": Looking at node ", m_node, " with children: ");
- CommaPrinter comma;
- m_graph.doToChildren(
- m_node,
- [&] (Edge edge) {
- dataLog(comma, edge, " (", edge->epoch(), ")");
- });
- dataLog("\n");
- }
-
- if (mode == PhaseMode::Global) {
- // Execute edges separately because we don't want to insert barriers if the
- // operation doing the store does a check that ensures that the child is not
- // a cell.
- m_interpreter->startExecuting();
- m_interpreter->executeEdges(m_node);
- }
-
- switch (m_node->op()) {
- case PutByValDirect:
- case PutByVal:
- case PutByValAlias: {
- switch (m_node->arrayMode().modeForPut().type()) {
- case Array::Contiguous:
- case Array::ArrayStorage:
- case Array::SlowPutArrayStorage: {
- Edge child1 = m_graph.varArgChild(m_node, 0);
- Edge child3 = m_graph.varArgChild(m_node, 2);
- considerBarrier(child1, child3);
- break;
- }
- default:
- break;
- }
- break;
- }
-
- case ArrayPush: {
- switch (m_node->arrayMode().type()) {
- case Array::Contiguous:
- case Array::ArrayStorage:
- considerBarrier(m_node->child1(), m_node->child2());
- break;
- default:
- break;
- }
- break;
- }
-
- case PutStructure: {
- considerBarrier(m_node->child1());
- break;
- }
-
- case PutClosureVar:
- case PutToArguments:
- case PutById:
- case PutByIdFlush:
- case PutByIdDirect:
- case MultiPutByOffset: {
- considerBarrier(m_node->child1(), m_node->child2());
- break;
- }
-
- case PutByOffset: {
- considerBarrier(m_node->child2(), m_node->child3());
- break;
- }
-
- case PutGlobalVar: {
- considerBarrier(m_node->child1(), m_node->child2());
- break;
- }
-
- default:
- break;
- }
-
- if (doesGC(m_graph, m_node))
- m_currentEpoch.bump();
-
- switch (m_node->op()) {
- case NewObject:
- case NewArray:
- case NewArrayWithSize:
- case NewArrayBuffer:
- case NewTypedArray:
- case NewRegexp:
- case MaterializeNewObject:
- case MaterializeCreateActivation:
- case NewStringObject:
- case MakeRope:
- case CreateActivation:
- case CreateDirectArguments:
- case CreateScopedArguments:
- case CreateClonedArguments:
- case NewFunction:
- // Nodes that allocate get to set their epoch because for those nodes we know
- // that they will be the newest object in the heap.
- m_node->setEpoch(m_currentEpoch);
- break;
-
- case AllocatePropertyStorage:
- case ReallocatePropertyStorage:
- // These allocate but then run their own barrier.
- insertBarrier(m_nodeIndex + 1, m_node->child1().node());
- m_node->setEpoch(Epoch());
- break;
-
- case Upsilon:
- m_node->phi()->setEpoch(m_node->epoch());
- m_node->setEpoch(Epoch());
- break;
-
- default:
- // For nodes that aren't guaranteed to allocate, we say that their return value
- // (if there is one) could be arbitrarily old.
- m_node->setEpoch(Epoch());
- break;
- }
-
- if (verbose) {
- dataLog(
- " ", m_currentEpoch, ": Done with node ", m_node, " (", m_node->epoch(),
- ") with children: ");
- CommaPrinter comma;
- m_graph.doToChildren(
- m_node,
- [&] (Edge edge) {
- dataLog(comma, edge, " (", edge->epoch(), ")");
- });
- dataLog("\n");
- }
-
- if (mode == PhaseMode::Global) {
- if (!m_interpreter->executeEffects(m_nodeIndex, m_node)) {
- result = false;
- break;
- }
- }
- }
-
- if (mode == PhaseMode::Global)
- m_state->reset();
-
- if (reallyInsertBarriers())
- m_insertionSet.execute(block);
-
- return result;
- }
-
- void considerBarrier(Edge base, Edge child)
- {
- if (verbose)
- dataLog(" Considering adding barrier ", base, " => ", child, "\n");
-
- // We don't need a store barrier if the child is guaranteed to not be a cell.
- switch (mode) {
- case PhaseMode::Fast: {
- // Don't try too hard because it's too expensive to run AI.
- if (child->hasConstant()) {
- if (!child->asJSValue().isCell()) {
- if (verbose)
- dataLog(" Rejecting because of constant type.\n");
- return;
- }
- } else {
- switch (child->result()) {
- case NodeResultNumber:
- case NodeResultDouble:
- case NodeResultInt32:
- case NodeResultInt52:
- case NodeResultBoolean:
- if (verbose)
- dataLog(" Rejecting because of result type.\n");
- return;
- default:
- break;
- }
- }
- break;
- }
-
- case PhaseMode::Global: {
- // Go into rage mode to eliminate any chance of a barrier with a non-cell child. We
- // can afford to keep around AI in Global mode.
- if (!m_interpreter->needsTypeCheck(child, ~SpecCell)) {
- if (verbose)
- dataLog(" Rejecting because of AI type.\n");
- return;
- }
- break;
- } }
-
- // We don't need a store barrier if the base is at least as new as the child. For
- // example this won't need a barrier:
- //
- // var o = {}
- // var p = {}
- // p.f = o
- //
- // This is stronger than the currentEpoch rule in considerBarrier(Edge), because it will
- // also eliminate barriers in cases like this:
- //
- // var o = {} // o.epoch = 1, currentEpoch = 1
- // var p = {} // o.epoch = 1, p.epoch = 2, currentEpoch = 2
- // var q = {} // o.epoch = 1, p.epoch = 2, q.epoch = 3, currentEpoch = 3
- // p.f = o // p.epoch >= o.epoch
- //
- // This relationship works because if it holds then we are in one of the following
- // scenarios. Note that we don't know *which* of these scenarios we are in, but it's
- // one of them (though without loss of generality, you can replace "a GC happened" with
- // "many GCs happened").
- //
- // 1) There is no GC between the allocation/last-barrier of base, child and now. Then
- // we definitely don't need a barrier.
- //
- // 2) There was a GC after child was allocated but before base was allocated. Then we
- // don't need a barrier, because base is still a new object.
- //
- // 3) There was a GC after both child and base were allocated. Then they are both old.
- // We don't need barriers on stores of old into old. Note that in this case it
- // doesn't matter if there was also a GC between the allocation of child and base.
- //
- // Note that barriers will lift an object into the current epoch. This is sort of weird.
- // It means that later if you store that object into some other object, and that other
- // object was previously newer object, you'll think that you need a barrier. We could
- // avoid this by tracking allocation epoch and barrier epoch separately. For now I think
- // that this would be overkill. But this does mean that there are the following
- // possibilities when this relationship holds:
- //
- // 4) Base is allocated first. A GC happens and base becomes old. Then we allocate
- // child. (Note that alternatively the GC could happen during the allocation of
- // child.) Then we run a barrier on base. Base will appear to be as new as child
- // (same epoch). At this point, we don't need another barrier on base.
- //
- // 5) Base is allocated first. Then we allocate child. Then we run a GC. Then we run a
- // barrier on base. Base will appear newer than child. We don't need a barrier
- // because both objects are old.
- //
- // Something we watch out for here is that the null epoch is a catch-all for objects
- // allocated before we did any epoch tracking. Two objects being in the null epoch
- // means that we don't know their epoch relationship.
- if (!!base->epoch() && base->epoch() >= child->epoch()) {
- if (verbose)
- dataLog(" Rejecting because of epoch ordering.\n");
- return;
- }
-
- considerBarrier(base);
- }
-
- void considerBarrier(Edge base)
- {
- if (verbose)
- dataLog(" Considering adding barrier on ", base, "\n");
-
- // We don't need a store barrier if the epoch of the base is identical to the current
- // epoch. That means that we either just allocated the object and so it's guaranteed to
- // be in newgen, or we just ran a barrier on it so it's guaranteed to be remembered
- // already.
- if (base->epoch() == m_currentEpoch) {
- if (verbose)
- dataLog(" Rejecting because it's in the current epoch.\n");
- return;
- }
-
- if (verbose)
- dataLog(" Inserting barrier.\n");
- insertBarrier(m_nodeIndex, base.node());
- }
-
- void insertBarrier(unsigned nodeIndex, Node* base)
- {
- // If we're in global mode, we should only insert the barriers once we have converged.
- if (!reallyInsertBarriers())
- return;
-
- // FIXME: We could support StoreBarrier(UntypedUse:). That would be sort of cool.
- // But right now we don't need it.
- m_insertionSet.insertNode(
- nodeIndex, SpecNone, StoreBarrier, m_node->origin, Edge(base, CellUse));
-
- base->setEpoch(m_currentEpoch);
- }
-
- bool reallyInsertBarriers()
- {
- return mode == PhaseMode::Fast || m_isConverged;
- }
-
- InsertionSet m_insertionSet;
- Epoch m_currentEpoch;
- unsigned m_nodeIndex;
- Node* m_node;
-
- // Things we only use in Global mode.
- std::unique_ptr<InPlaceAbstractState> m_state;
- std::unique_ptr<AbstractInterpreter<InPlaceAbstractState>> m_interpreter;
- std::unique_ptr<BlockMap<HashSet<Node*>>> m_stateAtHead;
- std::unique_ptr<BlockMap<HashSet<Node*>>> m_stateAtTail;
- bool m_isConverged;
-};
-
-} // anonymous namespace
-
-bool performFastStoreBarrierInsertion(Graph& graph)
-{
- SamplingRegion samplingRegion("DFG Fast Store Barrier Insertion Phase");
- return runPhase<StoreBarrierInsertionPhase<PhaseMode::Fast>>(graph);
-}
-
-bool performGlobalStoreBarrierInsertion(Graph& graph)
-{
- SamplingRegion samplingRegion("DFG Global Store Barrier Insertion Phase");
- return runPhase<StoreBarrierInsertionPhase<PhaseMode::Global>>(graph);
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
Deleted: trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.h (184437 => 184438)
--- trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.h 2015-05-16 20:00:04 UTC (rev 184437)
+++ trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.h 2015-05-16 21:01:42 UTC (rev 184438)
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DFGStoreBarrierInsertionPhase_h
-#define DFGStoreBarrierInsertionPhase_h
-
-#if ENABLE(DFG_JIT)
-
-namespace JSC { namespace DFG {
-
-class Graph;
-
-// Inserts store barriers in a block-local manner without consulting the abstract interpreter.
-// Uses a simple epoch-based analysis to avoid inserting redundant barriers. This phase requires
-// that we are not in SSA.
-bool performFastStoreBarrierInsertion(Graph&);
-
-// Inserts store barriers using a global analysis and consults the abstract interpreter. Uses a
-// simple epoch-based analysis to avoid inserting redundant barriers, but only propagates "same
-// epoch as current" property from one block to the next. This phase requires SSA. This phase
-// also requires having valid AI and liveness.
-bool performGlobalStoreBarrierInsertion(Graph&);
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
-#endif // DFGStoreBarrierInsertionPhase_h
-