Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (186690 => 186691)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2015-07-10 21:19:51 UTC (rev 186691)
@@ -110,6 +110,7 @@
bytecode/StructureStubClearingWatchpoint.cpp
bytecode/StructureStubInfo.cpp
bytecode/ToThisStatus.cpp
+ bytecode/TrackedReferences.cpp
bytecode/UnlinkedCodeBlock.cpp
bytecode/UnlinkedInstructionStream.cpp
bytecode/ValueRecovery.cpp
@@ -193,6 +194,7 @@
dfg/DFGLongLivedState.cpp
dfg/DFGLoopPreHeaderCreationPhase.cpp
dfg/DFGMayExit.cpp
+ dfg/DFGMinifiedGraph.cpp
dfg/DFGMinifiedNode.cpp
dfg/DFGMovHintRemovalPhase.cpp
dfg/DFGNaiveDominators.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (186690 => 186691)
--- trunk/Source/_javascript_Core/ChangeLog 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,3 +1,198 @@
+2015-07-04 Filip Pizlo <[email protected]>
+
+ DFG fragile frozen values are fundamentally broken
+ https://bugs.webkit.org/show_bug.cgi?id=146602
+
+ Reviewed by Mark Lam.
+
+ This change gets rid of the FragileValue value strength, because it was fundamentally
+ broken.
+
+ FragileValue was a value known to the compiler but not tracked by the GC in any way -
+ it wasn't marked and it wasn't weak. This was used to support AI bootstrap for OSR
+ must-handle values. The philosophy was that if the compiler did use the value for
+ optimization, it would have been strengthened to a weak value (or maybe even a strong
+ value, though we probably won't do that). But this was too much of a pipe dream. I've
+ found at least one case where the compiler did use the value, but never strengthened
+ it: it would happen if the value ended up in an OSR entry data expected value. Then if
+ we GCed, we might have killed the value, but OSR entry would still try to use it for
+ validation. That might have sort of just worked, but it's clearly shady.
+
+ The reason why we made must-handle values fragile and not weak is that most of the time
+ the values disappear from the abstract state: they are LUBed to a non-constant. If we
+ kept them around as weak, we'd have too many cases of the GC killing the code because
+ it thought that the value was somehow meaningful to the code when it was only used as a
+ temporary artifact of optimization.
+
+ So, it's true that it's very important for must-handle values not to automatically be
+ weak or strong. It's also true that the values are necessary for AI bootstrap because
+ we need to know what values OSR entry will require. But we shouldn't accomplish these
+ goals by having the compiler hold onto what are essentially dangling pointers.
+
+ This implements a better solution: instead of having InPlaceAbstractState bootstrap the
+ AI with must-handle values at the beginning, we now widen the valuesAtHead of the
+ must-handle block after AI converges. This widening is done in CFAPhase. This allows us
+ to see if the must-handle values are necessary at all. In most cases, the widening
+ takes a non-constant abstract value and simply amends something to its type based on
+ the type of the must-handle value, and so the must-handle value never actually shows up
+ in either the IR or any abstract value. In the unlikely event that the value at head is
+ bottom, we freeze the must-handle value. This change removes FragileValue, and this
+ freezing uses WeakValue as the strength. That makes sense: since the abstract value was
+ bottom, the must-handle value becomes integral to the IR and so it makes no sense for
+ the GC to keep the resulting CodeBlock alive if that must-handle value dies. This will
+ sometimes happen for example if you have a very long-running loop whose pre-header
+ allocates some object, but that pre-header appears to always exit to the optimizing JIT
+ because it was only profiled once in the LLInt and that profiling appears insufficient
+ to the DFG. In that case, we'll effectively constant-fold the references to the object
+ inside the loop, which is both efficient (yay constant folding!) and necessary
+ (otherwise we wouldn't know what the type of the variable should have been).
+
+ Testing and debugging this is complicated. So, this adds some new capabilities:
+
+ - DFG IR dumps also dump all of the FrozenValues that point to the heap along with
+ their strengths, so that it's easy to see what GC objects the DFG feels are necessary
+ for the compilation.
+
+ - DFG OSR entry preparation prints out the OSR entry data structures, so that it's easy
+ to see what GC pointers (and other things) are used for OSR entry validation. The
+ printouts are quite detailed, and should also help other kinds of OSR entry
+ debugging.
+
+ - DFG::Plan now validates whether all of the GC pointers planted in the various JITCode
+ data structures are also properly registered as either weak or strong pointers in the
+ CodeBlock. This validation check previously failed due to fragile values ending up in
+ the OSR entry data structures, both in the newly added test (dead-osr-entry-value.js)
+ and in some pre-existing tests (like earley-boyer and 3d-raytrace).
+
+ * CMakeLists.txt:
+ * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::stronglyVisitStrongReferences):
+ * bytecode/CodeOrigin.cpp:
+ (JSC::InlineCallFrame::visitAggregate):
+ * bytecode/Operands.h:
+ (JSC::Operands::operand):
+ (JSC::Operands::hasOperand):
+ * bytecode/StructureSet.cpp:
+ (JSC::StructureSet::dump):
+ (JSC::StructureSet::validateReferences):
+ * bytecode/StructureSet.h:
+ * bytecode/TrackedReferences.cpp: Added.
+ (JSC::TrackedReferences::TrackedReferences):
+ (JSC::TrackedReferences::~TrackedReferences):
+ (JSC::TrackedReferences::add):
+ (JSC::TrackedReferences::check):
+ (JSC::TrackedReferences::dump):
+ * bytecode/TrackedReferences.h: Added.
+ * dfg/DFGAbstractValue.cpp:
+ (JSC::DFG::AbstractValue::observeTransitions):
+ (JSC::DFG::AbstractValue::set):
+ (JSC::DFG::AbstractValue::fixTypeForRepresentation):
+ (JSC::DFG::AbstractValue::mergeOSREntryValue):
+ (JSC::DFG::AbstractValue::filter):
+ (JSC::DFG::AbstractValue::dumpInContext):
+ (JSC::DFG::AbstractValue::validateReferences):
+ (JSC::DFG::AbstractValue::setOSREntryValue): Deleted.
+ * dfg/DFGAbstractValue.h:
+ (JSC::DFG::AbstractValue::fullTop):
+ (JSC::DFG::AbstractValue::merge):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+ * dfg/DFGCFAPhase.cpp:
+ (JSC::DFG::CFAPhase::run):
+ * dfg/DFGCommonData.cpp:
+ (JSC::DFG::CommonData::invalidate):
+ (JSC::DFG::CommonData::validateReferences):
+ * dfg/DFGCommonData.h:
+ (JSC::DFG::CommonData::requiredRegisterCountForExecutionAndExit):
+ * dfg/DFGFrozenValue.h:
+ (JSC::DFG::FrozenValue::FrozenValue):
+ (JSC::DFG::FrozenValue::strengthenTo):
+ (JSC::DFG::FrozenValue::pointsToHeap):
+ (JSC::DFG::FrozenValue::strength):
+ (JSC::DFG::FrozenValue::freeze):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::Graph):
+ (JSC::DFG::Graph::dump):
+ (JSC::DFG::Graph::registerFrozenValues):
+ (JSC::DFG::Graph::visitChildren):
+ (JSC::DFG::Graph::freeze):
+ (JSC::DFG::Graph::freezeStrong):
+ (JSC::DFG::Graph::freezeFragile): Deleted.
+ * dfg/DFGGraph.h:
+ * dfg/DFGInPlaceAbstractState.cpp:
+ (JSC::DFG::InPlaceAbstractState::initialize):
+ * dfg/DFGJITCode.cpp:
+ (JSC::DFG::JITCode::setOptimizationThresholdBasedOnCompilationResult):
+ (JSC::DFG::JITCode::validateReferences):
+ * dfg/DFGJITCode.h:
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::addressOfDoubleConstant):
+ (JSC::DFG::JITCompiler::noticeOSREntry):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::JITCompiler::branchStructurePtr):
+ (JSC::DFG::JITCompiler::jitCode):
+ (JSC::DFG::JITCompiler::noticeOSREntry): Deleted.
+ * dfg/DFGMinifiedGraph.cpp: Added.
+ (JSC::DFG::MinifiedGraph::prepareAndShrink):
+ (JSC::DFG::MinifiedGraph::validateReferences):
+ * dfg/DFGMinifiedGraph.h:
+ (JSC::DFG::MinifiedGraph::append):
+ (JSC::DFG::MinifiedGraph::prepareAndShrink): Deleted.
+ * dfg/DFGOSREntry.cpp:
+ (JSC::DFG::OSREntryData::dumpInContext):
+ (JSC::DFG::OSREntryData::dump):
+ (JSC::DFG::prepareOSREntry):
+ * dfg/DFGOSREntry.h:
+ (JSC::DFG::getOSREntryDataBytecodeIndex):
+ * dfg/DFGPlan.cpp:
+ (JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::linkOSREntries):
+ (JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
+ * dfg/DFGStructureAbstractValue.cpp:
+ (JSC::DFG::StructureAbstractValue::dump):
+ (JSC::DFG::StructureAbstractValue::validateReferences):
+ * dfg/DFGStructureAbstractValue.h:
+ * dfg/DFGValidate.cpp:
+ (JSC::DFG::Validate::validate):
+ * dfg/DFGValueStrength.cpp:
+ (WTF::printInternal):
+ * dfg/DFGValueStrength.h:
+ (JSC::DFG::merge):
+ * ftl/FTLExitPropertyValue.cpp:
+ (JSC::FTL::ExitPropertyValue::dump):
+ (JSC::FTL::ExitPropertyValue::validateReferences):
+ * ftl/FTLExitPropertyValue.h:
+ * ftl/FTLExitTimeObjectMaterialization.cpp:
+ (JSC::FTL::ExitTimeObjectMaterialization::dump):
+ (JSC::FTL::ExitTimeObjectMaterialization::validateReferences):
+ * ftl/FTLExitTimeObjectMaterialization.h:
+ * ftl/FTLExitValue.cpp:
+ (JSC::FTL::ExitValue::dump):
+ (JSC::FTL::ExitValue::validateReferences):
+ * ftl/FTLExitValue.h:
+ * ftl/FTLJITCode.cpp:
+ (JSC::FTL::JITCode::dfgCommon):
+ (JSC::FTL::JITCode::validateReferences):
+ * ftl/FTLJITCode.h:
+ (JSC::FTL::JITCode::handles):
+ (JSC::FTL::JITCode::dataSections):
+ * ftl/FTLOSRExit.cpp:
+ (JSC::FTL::OSRExit::codeLocationForRepatch):
+ (JSC::FTL::OSRExit::validateReferences):
+ * ftl/FTLOSRExit.h:
+ (JSC::FTL::OSRExit::considerAddingAsFrequentExitSite):
+ * jit/JITCode.cpp:
+ (JSC::JITCode::typeName):
+ (JSC::JITCode::validateReferences):
+ (JSC::JITCode::execute):
+ * jit/JITCode.h:
+ (JSC::JITCode::start):
+ * tests/stress/dead-osr-entry-value.js: Added.
+ (foo):
+
2015-07-09 Filip Pizlo <[email protected]>
It should be possible to run the OSR exit fuzzer
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (186690 => 186691)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2015-07-10 21:19:51 UTC (rev 186691)
@@ -351,6 +351,7 @@
<ClCompile Include="..\bytecode\StructureStubClearingWatchpoint.cpp" />
<ClCompile Include="..\bytecode\StructureStubInfo.cpp" />
<ClCompile Include="..\bytecode\ToThisStatus.cpp" />
+ <ClCompile Include="..\bytecode\TrackedReferences.cpp" />
<ClCompile Include="..\bytecode\UnlinkedCodeBlock.cpp" />
<ClCompile Include="..\bytecode\UnlinkedInstructionStream.cpp" />
<ClCompile Include="..\bytecode\ValueRecovery.cpp" />
@@ -431,6 +432,7 @@
<ClCompile Include="..\dfg\DFGLongLivedState.cpp" />
<ClCompile Include="..\dfg\DFGLoopPreHeaderCreationPhase.cpp" />
<ClCompile Include="..\dfg\DFGMayExit.cpp" />
+ <ClCompile Include="..\dfg\DFGMinifiedGraph.cpp" />
<ClCompile Include="..\dfg\DFGMinifiedNode.cpp" />
<ClCompile Include="..\dfg\DFGMovHintRemovalPhase.cpp" />
<ClCompile Include="..\dfg\DFGNaiveDominators.cpp" />
@@ -1012,6 +1014,7 @@
<ClInclude Include="..\bytecode\StructureStubClearingWatchpoint.h" />
<ClInclude Include="..\bytecode\StructureStubInfo.h" />
<ClInclude Include="..\bytecode\ToThisStatus.h" />
+ <ClInclude Include="..\bytecode\TrackedReferences.h" />
<ClInclude Include="..\bytecode\TypeLocation.h" />
<ClInclude Include="..\bytecode\UnlinkedCodeBlock.h" />
<ClInclude Include="..\bytecode\UnlinkedInstructionStream.h" />
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (186690 => 186691)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-07-10 21:19:51 UTC (rev 186691)
@@ -106,6 +106,7 @@
0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; };
0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F1725FF1B48719A00AC3A55 /* DFGMinifiedGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */; };
0F190CAC189D82F6000AE5F0 /* ProfilerJettisonReason.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F190CAA189D82F6000AE5F0 /* ProfilerJettisonReason.cpp */; };
0F190CAD189D82F6000AE5F0 /* ProfilerJettisonReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F190CAB189D82F6000AE5F0 /* ProfilerJettisonReason.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F1DD84A18A945BE0026F3FA /* JSCInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1DD84918A945BE0026F3FA /* JSCInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -451,6 +452,8 @@
0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */; };
0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F952ABC1B487A7700C367C5 /* TrackedReferences.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F952ABA1B487A7700C367C5 /* TrackedReferences.cpp */; };
+ 0F952ABD1B487A7700C367C5 /* TrackedReferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F952ABB1B487A7700C367C5 /* TrackedReferences.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F96EBB316676EF6008BADE3 /* CodeBlockWithJITType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9749711687ADE400A4FF6A /* JSCellInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1848,6 +1851,7 @@
0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerProfiledBytecodes.h; path = profiler/ProfilerProfiledBytecodes.h; sourceTree = "<group>"; };
0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = "<group>"; };
0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
+ 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedGraph.cpp; path = dfg/DFGMinifiedGraph.cpp; sourceTree = "<group>"; };
0F190CAA189D82F6000AE5F0 /* ProfilerJettisonReason.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerJettisonReason.cpp; path = profiler/ProfilerJettisonReason.cpp; sourceTree = "<group>"; };
0F190CAB189D82F6000AE5F0 /* ProfilerJettisonReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerJettisonReason.h; path = profiler/ProfilerJettisonReason.h; sourceTree = "<group>"; };
0F1DD84918A945BE0026F3FA /* JSCInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCInlines.h; sourceTree = "<group>"; };
@@ -2191,6 +2195,8 @@
0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; };
0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdVariant.cpp; sourceTree = "<group>"; };
0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdVariant.h; sourceTree = "<group>"; };
+ 0F952ABA1B487A7700C367C5 /* TrackedReferences.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackedReferences.cpp; sourceTree = "<group>"; };
+ 0F952ABB1B487A7700C367C5 /* TrackedReferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackedReferences.h; sourceTree = "<group>"; };
0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockWithJITType.h; sourceTree = "<group>"; };
0F97496F1687ADE200A4FF6A /* JSCellInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCellInlines.h; sourceTree = "<group>"; };
@@ -5002,6 +5008,7 @@
0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */,
0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */,
A704D90217A0BAA8006BA554 /* DFGMergeMode.h */,
+ 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */,
0F2BDC3D1522801700CD8910 /* DFGMinifiedGraph.h */,
0FB4B51016B3A964003F696B /* DFGMinifiedID.h */,
0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */,
@@ -5284,6 +5291,8 @@
0F426A4A1460CD6B00131F8F /* DataFormat.h */,
0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */,
0FC712DD17CD8778008CC93C /* DeferredCompilationCallback.h */,
+ FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */,
+ FE5068641AE246390009DAB7 /* DeferredSourceDump.h */,
0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */,
0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */,
969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */,
@@ -5331,8 +5340,6 @@
0FF60AC016740F8100029779 /* ReduceWhitespace.h */,
1429D8830ED21C3D00B89619 /* SamplingTool.cpp */,
1429D8840ED21C3D00B89619 /* SamplingTool.h */,
- FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */,
- FE5068641AE246390009DAB7 /* DeferredSourceDump.h */,
0F5541AF1613C1FB00CE3E25 /* SpecialPointer.cpp */,
0F5541B01613C1FB00CE3E25 /* SpecialPointer.h */,
0FD82E84141F3FDA00179C94 /* SpeculatedType.cpp */,
@@ -5345,6 +5352,8 @@
BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */,
0F2D4DE519832DAC007D4B19 /* ToThisStatus.cpp */,
0F2D4DE619832DAC007D4B19 /* ToThisStatus.h */,
+ 0F952ABA1B487A7700C367C5 /* TrackedReferences.cpp */,
+ 0F952ABB1B487A7700C367C5 /* TrackedReferences.h */,
0F2D4DE719832DAC007D4B19 /* TypeLocation.h */,
A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */,
A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */,
@@ -6060,6 +6069,7 @@
A5840E29187CA5E600843B10 /* inline-and-minify-stylesheets-and-scripts.py in Headers */,
0F24E55617F0B71C00ABB217 /* InlineCallFrameSet.h in Headers */,
99E45A2718A1B2590026D88F /* InputCursor.h in Headers */,
+ 0F952ABD1B487A7700C367C5 /* TrackedReferences.h in Headers */,
A593CF7F1840362C00BFCE27 /* InspectorAgentBase.h in Headers */,
0F3E01AB19D353A500F61B7F /* DFGPrePostNumbering.h in Headers */,
A593CF87184038CA00BFCE27 /* InspectorAgentRegistry.h in Headers */,
@@ -7480,6 +7490,7 @@
655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */,
6546F5211A32B313006F07D5 /* NullGetterFunction.cpp in Sources */,
65525FC51A6DD801007B5495 /* NullSetterFunction.cpp in Sources */,
+ 0F1725FF1B48719A00AC3A55 /* DFGMinifiedGraph.cpp in Sources */,
14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */,
14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */,
14469DE4107EC7E700650446 /* NumberPrototype.cpp in Sources */,
@@ -7555,6 +7566,7 @@
A54CF2F5184EAB2400237F19 /* ScriptValue.cpp in Sources */,
A7299DA517D12858005F5FF9 /* SetConstructor.cpp in Sources */,
0FD1202F1A8AED12000F5280 /* FTLJSCallBase.cpp in Sources */,
+ 0F952ABC1B487A7700C367C5 /* TrackedReferences.cpp in Sources */,
A790DD6D182F499700588807 /* SetIteratorPrototype.cpp in Sources */,
A7299DA117D12848005F5FF9 /* SetPrototype.cpp in Sources */,
0F2B670417B6B5AB00A7AE3F /* SimpleTypedArrayController.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -2801,6 +2801,13 @@
#if ENABLE(DFG_JIT)
if (JITCode::isOptimizingJIT(jitType())) {
+ // FIXME: This is an antipattern for two reasons. References introduced by the DFG
+ // that aren't in the original CodeBlock being compiled should be weakly referenced.
+ // Inline call frames aren't in the original CodeBlock, so they qualify as weak. Also,
+ // those weak references should already be tracked in the DFG as weak FrozenValues. So,
+ // there is probably no need for this. We already have assertions that this should be
+ // unnecessary.
+ // https://bugs.webkit.org/show_bug.cgi?id=146613
DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
if (dfgCommon->inlineCallFrames.get())
dfgCommon->inlineCallFrames->visitAggregate(visitor);
Modified: trunk/Source/_javascript_Core/bytecode/CodeOrigin.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/bytecode/CodeOrigin.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/bytecode/CodeOrigin.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -150,6 +150,15 @@
void InlineCallFrame::visitAggregate(SlotVisitor& visitor)
{
+ // FIXME: This is an antipattern for two reasons. References introduced by the DFG
+ // that aren't in the original CodeBlock being compiled should be weakly referenced.
+ // Inline call frames aren't in the original CodeBlock, so they qualify as weak. Also,
+ // those weak references should already be tracked in the DFG as weak FrozenValues. So,
+ // there is probably no need for this. We already have assertions that this should be
+ // unnecessary. Finally, just marking the executable and not anything else in the inline
+ // call frame is almost certainly insufficient for what this method thought it was going
+ // to accomplish.
+ // https://bugs.webkit.org/show_bug.cgi?id=146613
visitor.append(&executable);
}
Modified: trunk/Source/_javascript_Core/bytecode/Operands.h (186690 => 186691)
--- trunk/Source/_javascript_Core/bytecode/Operands.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/bytecode/Operands.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013, 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
@@ -149,6 +149,7 @@
}
const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
+ const T& operand(VirtualRegister operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
bool hasOperand(int operand) const
{
Modified: trunk/Source/_javascript_Core/bytecode/StructureSet.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/bytecode/StructureSet.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/bytecode/StructureSet.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -27,6 +27,7 @@
#include "StructureSet.h"
#include "DFGAbstractValue.h"
+#include "TrackedReferences.h"
#include <wtf/CommaPrinter.h>
namespace JSC {
@@ -96,5 +97,13 @@
dumpInContext(out, nullptr);
}
+void StructureSet::validateReferences(const TrackedReferences& trackedReferences) const
+{
+ forEach(
+ [&] (Structure* structure) {
+ trackedReferences.check(structure);
+ });
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/StructureSet.h (186690 => 186691)
--- trunk/Source/_javascript_Core/bytecode/StructureSet.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/bytecode/StructureSet.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -27,13 +27,15 @@
#define StructureSet_h
#include "ArrayProfile.h"
+#include "DumpContext.h"
#include "SpeculatedType.h"
#include "Structure.h"
-#include "DumpContext.h"
#include <wtf/TinyPtrSet.h>
namespace JSC {
+class TrackedReferences;
+
namespace DFG {
class StructureAbstractValue;
struct AbstractValue;
@@ -77,6 +79,8 @@
void dumpInContext(PrintStream&, DumpContext*) const;
void dump(PrintStream&) const;
+
+ void validateReferences(const TrackedReferences&) const;
};
} // namespace JSC
Added: trunk/Source/_javascript_Core/bytecode/TrackedReferences.cpp (0 => 186691)
--- trunk/Source/_javascript_Core/bytecode/TrackedReferences.cpp (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/TrackedReferences.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -0,0 +1,81 @@
+/*
+ * 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. ``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
+ * 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 "TrackedReferences.h"
+
+#include "JSCInlines.h"
+#include <wtf/CommaPrinter.h>
+
+namespace JSC {
+
+TrackedReferences::TrackedReferences()
+{
+}
+
+TrackedReferences::~TrackedReferences()
+{
+}
+
+void TrackedReferences::add(JSCell* cell)
+{
+ if (cell)
+ m_references.add(cell);
+}
+
+void TrackedReferences::add(JSValue value)
+{
+ if (value.isCell())
+ add(value.asCell());
+}
+
+void TrackedReferences::check(JSCell* cell) const
+{
+ if (!cell)
+ return;
+
+ if (m_references.contains(cell))
+ return;
+
+ dataLog("Found untracked reference: ", RawPointer(cell), "\n");
+ dataLog("All tracked references: ", *this, "\n");
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+void TrackedReferences::check(JSValue value) const
+{
+ if (value.isCell())
+ check(value.asCell());
+}
+
+void TrackedReferences::dump(PrintStream& out) const
+{
+ CommaPrinter comma;
+ for (JSCell* cell : m_references)
+ out.print(comma, RawPointer(cell));
+}
+
+} // namespace JSC
+
Added: trunk/Source/_javascript_Core/bytecode/TrackedReferences.h (0 => 186691)
--- trunk/Source/_javascript_Core/bytecode/TrackedReferences.h (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/TrackedReferences.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -0,0 +1,56 @@
+/*
+ * 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. ``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
+ * 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 TrackedReferences_h
+#define TrackedReferences_h
+
+#include "JSCJSValue.h"
+#include "JSCell.h"
+#include <wtf/HashSet.h>
+#include <wtf/PrintStream.h>
+
+namespace JSC {
+
+class TrackedReferences {
+public:
+ TrackedReferences();
+ ~TrackedReferences();
+
+ void add(JSCell*);
+ void add(JSValue);
+
+ void check(JSCell*) const;
+ void check(JSValue) const;
+
+ void dump(PrintStream&) const;
+
+private:
+ HashSet<JSCell*> m_references;
+};
+
+} // namespace JSC
+
+#endif // TrackedReferences_h
+
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractValue.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractValue.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractValue.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-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
@@ -30,6 +30,7 @@
#include "DFGGraph.h"
#include "JSCInlines.h"
+#include "TrackedReferences.h"
namespace JSC { namespace DFG {
@@ -47,24 +48,6 @@
checkConsistency();
}
-void AbstractValue::setOSREntryValue(Graph& graph, const FrozenValue& value)
-{
- if (!!value && value.value().isCell()) {
- Structure* structure = value.structure();
- m_structure = structure;
- m_arrayModes = asArrayModes(structure->indexingType());
- } else {
- m_structure.clear();
- m_arrayModes = 0;
- }
-
- m_type = speculationFromValue(value.value());
- m_value = value.value();
-
- checkConsistency();
- assertIsRegistered(graph);
-}
-
void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobberState clobberState)
{
if (!!value && value.value().isCell()) {
@@ -172,6 +155,40 @@
fixTypeForRepresentation(graph, node->result(), node);
}
+bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
+{
+ AbstractValue oldMe = *this;
+
+ if (isClear()) {
+ FrozenValue* frozenValue = graph.freeze(value);
+ if (frozenValue->pointsToHeap()) {
+ m_structure = frozenValue->structure();
+ m_arrayModes = asArrayModes(frozenValue->structure()->indexingType());
+ } else {
+ m_structure.clear();
+ m_arrayModes = 0;
+ }
+
+ m_type = speculationFromValue(value);
+ m_value = value;
+ } else {
+ mergeSpeculation(m_type, speculationFromValue(value));
+ if (!!value && value.isCell()) {
+ Structure* structure = value.asCell()->structure();
+ graph.registerStructure(structure);
+ mergeArrayModes(m_arrayModes, asArrayModes(structure->indexingType()));
+ m_structure.merge(StructureSet(structure));
+ }
+ if (m_value != value)
+ m_value = JSValue();
+ }
+
+ checkConsistency();
+ assertIsRegistered(graph);
+
+ return oldMe != *this;
+}
+
FiltrationResult AbstractValue::filter(Graph& graph, const StructureSet& other)
{
if (isClear())
@@ -424,6 +441,12 @@
out.print(")");
}
+void AbstractValue::validateReferences(const TrackedReferences& trackedReferences)
+{
+ trackedReferences.check(m_value);
+ m_structure.validateReferences(trackedReferences);
+}
+
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractValue.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractValue.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractValue.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -39,8 +39,12 @@
#include "DumpContext.h"
#include "StructureSet.h"
-namespace JSC { namespace DFG {
+namespace JSC {
+class TrackedReferences;
+
+namespace DFG {
+
class Graph;
struct Node;
@@ -193,8 +197,6 @@
return result;
}
- void setOSREntryValue(Graph&, const FrozenValue&);
-
void set(Graph&, const FrozenValue&, StructureClobberState);
void set(Graph&, Structure*);
void set(Graph&, const StructureSet&);
@@ -254,6 +256,8 @@
return result;
}
+ bool mergeOSREntryValue(Graph&, JSValue);
+
void merge(SpeculatedType type)
{
mergeSpeculation(m_type, type);
@@ -330,6 +334,8 @@
void dumpInContext(PrintStream&, DumpContext*) const;
void dump(PrintStream&) const;
+ void validateReferences(const TrackedReferences&);
+
// This is a proven constraint on the structures that this value can have right
// now. The structure of the current value must belong to this set. The set may
// be TOP, indicating that it is the set of all possible structures, in which
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -4022,6 +4022,7 @@
ASSERT(callsiteBlockHead);
m_inlineCallFrame = byteCodeParser->m_graph.m_plan.inlineCallFrames->add();
+ byteCodeParser->m_graph.freeze(codeBlock->ownerExecutable());
initializeLazyWriteBarrierForInlineCallFrameExecutable(
byteCodeParser->m_graph.m_plan.writeBarriers,
m_inlineCallFrame->executable,
Modified: trunk/Source/_javascript_Core/dfg/DFGCFAPhase.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGCFAPhase.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGCFAPhase.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013-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
@@ -80,12 +80,52 @@
} while (m_changed);
if (m_graph.m_form != SSA) {
+ ASSERT(!m_changed);
+
+ // Widen the abstract values at the block that serves as the must-handle OSR entry.
+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+ BasicBlock* block = m_graph.block(blockIndex);
+ if (!block)
+ continue;
+
+ if (!block->isOSRTarget)
+ continue;
+ if (block->bytecodeBegin != m_graph.m_plan.osrEntryBytecodeIndex)
+ continue;
+
+ bool changed = false;
+ for (size_t i = m_graph.m_plan.mustHandleValues.size(); i--;) {
+ int operand = m_graph.m_plan.mustHandleValues.operandForIndex(i);
+ JSValue value = m_graph.m_plan.mustHandleValues[i];
+ Node* node = block->variablesAtHead.operand(operand);
+ if (!node)
+ continue;
+
+ AbstractValue& target = block->valuesAtHead.operand(operand);
+ changed |= target.mergeOSREntryValue(m_graph, value);
+ target.fixTypeForRepresentation(
+ m_graph, resultFor(node->variableAccessData()->flushFormat()));
+ }
+
+ if (changed) {
+ m_changed = true;
+ block->cfaShouldRevisit = true;
+ }
+ }
+
+ // Propagate any of the changes we just introduced.
+ while (m_changed) {
+ m_changed = false;
+ performForwardCFA();
+ }
+
// Make sure we record the intersection of all proofs that we ever allowed the
// compiler to rely upon.
for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
BasicBlock* block = m_graph.block(blockIndex);
if (!block)
continue;
+
block->intersectionOfCFAHasVisited &= block->cfaHasVisited;
for (unsigned i = block->intersectionOfPastValuesAtHead.size(); i--;)
block->intersectionOfPastValuesAtHead[i].filter(block->valuesAtHead[i]);
Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 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
@@ -32,6 +32,7 @@
#include "DFGNode.h"
#include "DFGPlan.h"
#include "JSCInlines.h"
+#include "TrackedReferences.h"
#include "VM.h"
namespace JSC { namespace DFG {
@@ -72,6 +73,24 @@
return true;
}
+void CommonData::validateReferences(const TrackedReferences& trackedReferences)
+{
+ if (InlineCallFrameSet* set = inlineCallFrames.get()) {
+ for (InlineCallFrame* inlineCallFrame : *set) {
+ for (ValueRecovery& recovery : inlineCallFrame->arguments) {
+ if (recovery.isConstant())
+ trackedReferences.check(recovery.constant());
+ }
+
+ if (ScriptExecutable* executable = inlineCallFrame->executable.get())
+ trackedReferences.check(executable);
+
+ if (inlineCallFrame->calleeRecovery.isConstant())
+ trackedReferences.check(inlineCallFrame->calleeRecovery.constant());
+ }
+ }
+}
+
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGCommonData.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -41,6 +41,7 @@
class CodeBlock;
class Identifier;
+class TrackedReferences;
namespace DFG {
@@ -86,6 +87,8 @@
{
return std::max(frameRegisterCount, requiredRegisterCountForExit);
}
+
+ void validateReferences(const TrackedReferences&);
RefPtr<InlineCallFrameSet> inlineCallFrames;
Vector<CodeOrigin, 0, UnsafeVectorOverflow> codeOrigins;
Modified: trunk/Source/_javascript_Core/dfg/DFGFrozenValue.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGFrozenValue.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGFrozenValue.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -41,14 +41,14 @@
public:
FrozenValue()
: m_structure(nullptr)
- , m_strength(FragileValue)
+ , m_strength(WeakValue)
{
}
FrozenValue(JSValue value)
: m_value(value)
, m_structure(nullptr)
- , m_strength(FragileValue)
+ , m_strength(WeakValue)
{
RELEASE_ASSERT(!value || !value.isCell());
}
@@ -60,7 +60,7 @@
{
ASSERT((!!value && value.isCell()) == !!structure);
ASSERT(!value || !value.isCell() || value.asCell()->classInfo() == structure->classInfo());
- ASSERT(!!structure || (strength == FragileValue));
+ ASSERT(!!structure || (strength == WeakValue));
}
static FrozenValue* emptySingleton();
@@ -89,12 +89,9 @@
m_strength = merge(m_strength, strength);
}
- // The strength of the value itself. The structure should be viewed as fragile
- // except if it is watched, in which case it's weak. Note that currently we
- // watch all watchable structures indiscriminantly, and so we also mark them
- // weakly. We could improve on this: any optimization that makes use of a
- // structure could signal that it has done so, and we could avoid watching
- // watchable structures that we had never marked in such a way.
+ bool pointsToHeap() const { return !!value() && value().isCell(); }
+
+ // The strength of the value itself. The structure is almost always weak.
ValueStrength strength() const { return m_strength; }
void dumpInContext(PrintStream& out, DumpContext* context) const;
@@ -116,7 +113,7 @@
return FrozenValue(
value,
(!!value && value.isCell()) ? value.asCell()->structure() : nullptr,
- FragileValue);
+ WeakValue);
}
JSValue m_value;
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -62,7 +62,6 @@
, m_codeBlock(m_plan.codeBlock.get())
, m_profiledBlock(m_codeBlock->alternative())
, m_allocator(longLivedState.m_allocator)
- , m_mustHandleValues(OperandsLike, plan.mustHandleValues)
, m_nextMachineLocal(0)
, m_fixpointState(BeforeFixpoint)
, m_structureRegistrationState(HaveNotStartedRegistering)
@@ -72,9 +71,6 @@
{
ASSERT(m_profiledBlock);
- for (unsigned i = m_mustHandleValues.size(); i--;)
- m_mustHandleValues[i] = freezeFragile(plan.mustHandleValues[i]);
-
m_hasDebuggerEnabled = m_profiledBlock->globalObject()->hasDebugger()
|| Options::forceDebuggerBytecodeGeneration();
}
@@ -529,6 +525,12 @@
out.print("\n");
}
+ out.print("GC Values:\n");
+ for (FrozenValue* value : m_frozenValues) {
+ if (value->pointsToHeap())
+ out.print(" ", inContext(*value, &myContext), "\n");
+ }
+
if (!myContext.isEmpty()) {
myContext.dump(out);
out.print("\n");
@@ -1106,13 +1108,13 @@
m_codeBlock->constants().resize(0);
m_codeBlock->constantsSourceCodeRepresentation().resize(0);
for (FrozenValue* value : m_frozenValues) {
- if (value->structure())
- ASSERT(m_plan.weakReferences.contains(value->structure()));
+ if (!value->pointsToHeap())
+ continue;
+ ASSERT(value->structure());
+ ASSERT(m_plan.weakReferences.contains(value->structure()));
+
switch (value->strength()) {
- case FragileValue: {
- break;
- }
case WeakValue: {
m_plan.weakReferences.addLazily(value->value().asCell());
break;
@@ -1202,7 +1204,7 @@
}
}
-FrozenValue* Graph::freezeFragile(JSValue value)
+FrozenValue* Graph::freeze(JSValue value)
{
if (UNLIKELY(!value))
return FrozenValue::emptySingleton();
@@ -1221,16 +1223,9 @@
return result.iterator->value = m_frozenValues.add(frozenValue);
}
-FrozenValue* Graph::freeze(JSValue value)
-{
- FrozenValue* result = freezeFragile(value);
- result->strengthenTo(WeakValue);
- return result;
-}
-
FrozenValue* Graph::freezeStrong(JSValue value)
{
- FrozenValue* result = freezeFragile(value);
+ FrozenValue* result = freeze(value);
result->strengthenTo(StrongValue);
return result;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -186,9 +186,8 @@
void dethread();
- FrozenValue* freezeFragile(JSValue value);
- FrozenValue* freeze(JSValue value); // We use weak freezing by default. Shorthand for freezeFragile(value)->strengthenTo(WeakValue);
- FrozenValue* freezeStrong(JSValue value); // Shorthand for freezeFragile(value)->strengthenTo(StrongValue).
+ FrozenValue* freeze(JSValue); // We use weak freezing by default.
+ FrozenValue* freezeStrong(JSValue); // Shorthand for freeze(value)->strengthenTo(StrongValue).
void convertToConstant(Node* node, FrozenValue* value);
void convertToConstant(Node* node, JSValue value);
@@ -800,8 +799,6 @@
NodeAllocator& m_allocator;
- Operands<FrozenValue*> m_mustHandleValues;
-
Vector< RefPtr<BasicBlock> , 8> m_blocks;
Vector<Edge, 16> m_varArgChildren;
Modified: trunk/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -150,26 +150,6 @@
block->valuesAtHead.local(i).clear();
block->valuesAtTail.local(i).clear();
}
- if (m_graph.m_form == SSA)
- continue;
- if (!block->isOSRTarget)
- continue;
- if (block->bytecodeBegin != m_graph.m_plan.osrEntryBytecodeIndex)
- continue;
- for (size_t i = 0; i < m_graph.m_mustHandleValues.size(); ++i) {
- int operand = m_graph.m_mustHandleValues.operandForIndex(i);
- Node* node = block->variablesAtHead.operand(operand);
- if (!node)
- continue;
- AbstractValue source;
- source.setOSREntryValue(m_graph, *m_graph.m_mustHandleValues[i]);
- AbstractValue& target = block->valuesAtHead.operand(operand);
- VariableAccessData* variable = node->variableAccessData();
- FlushFormat format = variable->flushFormat();
- target.merge(source);
- target.fixTypeForRepresentation(m_graph, resultFor(format));
- }
- block->cfaShouldRevisit = true;
}
if (m_graph.m_form == SSA) {
for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCode.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGJITCode.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCode.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -30,6 +30,7 @@
#include "CodeBlock.h"
#include "JSCInlines.h"
+#include "TrackedReferences.h"
namespace JSC { namespace DFG {
@@ -170,6 +171,18 @@
}
#endif // ENABLE(FTL_JIT)
+void JITCode::validateReferences(const TrackedReferences& trackedReferences)
+{
+ common.validateReferences(trackedReferences);
+
+ for (OSREntryData& entry : osrEntry) {
+ for (unsigned i = entry.m_expectedValues.size(); i--;)
+ entry.m_expectedValues[i].validateReferences(trackedReferences);
+ }
+
+ minifiedDFG.validateReferences(trackedReferences);
+}
+
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCode.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGJITCode.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCode.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-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
@@ -38,8 +38,12 @@
#include "JITCode.h"
#include <wtf/SegmentedVector.h>
-namespace JSC { namespace DFG {
+namespace JSC {
+class TrackedReferences;
+
+namespace DFG {
+
class JITCompiler;
class JITCode : public DirectJITCode {
@@ -107,6 +111,8 @@
void setOptimizationThresholdBasedOnCompilationResult(CodeBlock*, CompilationResult);
#endif // ENABLE(FTL_JIT)
+ void validateReferences(const TrackedReferences&) override;
+
void shrinkToFit();
private:
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -475,6 +475,54 @@
}
#endif
+void JITCompiler::noticeOSREntry(BasicBlock& basicBlock, JITCompiler::Label blockHead, LinkBuffer& linkBuffer)
+{
+ // OSR entry is not allowed into blocks deemed unreachable by control flow analysis.
+ if (!basicBlock.intersectionOfCFAHasVisited)
+ return;
+
+ OSREntryData* entry = m_jitCode->appendOSREntryData(basicBlock.bytecodeBegin, linkBuffer.offsetOf(blockHead));
+
+ entry->m_expectedValues = basicBlock.intersectionOfPastValuesAtHead;
+
+ // Fix the expected values: in our protocol, a dead variable will have an expected
+ // value of (None, []). But the old JIT may stash some values there. So we really
+ // need (Top, TOP).
+ for (size_t argument = 0; argument < basicBlock.variablesAtHead.numberOfArguments(); ++argument) {
+ Node* node = basicBlock.variablesAtHead.argument(argument);
+ if (!node || !node->shouldGenerate())
+ entry->m_expectedValues.argument(argument).makeHeapTop();
+ }
+ for (size_t local = 0; local < basicBlock.variablesAtHead.numberOfLocals(); ++local) {
+ Node* node = basicBlock.variablesAtHead.local(local);
+ if (!node || !node->shouldGenerate())
+ entry->m_expectedValues.local(local).makeHeapTop();
+ else {
+ VariableAccessData* variable = node->variableAccessData();
+ entry->m_machineStackUsed.set(variable->machineLocal().toLocal());
+
+ switch (variable->flushFormat()) {
+ case FlushedDouble:
+ entry->m_localsForcedDouble.set(local);
+ break;
+ case FlushedInt52:
+ entry->m_localsForcedMachineInt.set(local);
+ break;
+ default:
+ break;
+ }
+
+ if (variable->local() != variable->machineLocal()) {
+ entry->m_reshufflings.append(
+ OSREntryReshuffling(
+ variable->local().offset(), variable->machineLocal().offset()));
+ }
+ }
+ }
+
+ entry->m_reshufflings.shrinkToFit();
+}
+
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013-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
@@ -265,53 +265,7 @@
#endif
}
- void noticeOSREntry(BasicBlock& basicBlock, JITCompiler::Label blockHead, LinkBuffer& linkBuffer)
- {
- // OSR entry is not allowed into blocks deemed unreachable by control flow analysis.
- if (!basicBlock.intersectionOfCFAHasVisited)
- return;
-
- OSREntryData* entry = m_jitCode->appendOSREntryData(basicBlock.bytecodeBegin, linkBuffer.offsetOf(blockHead));
-
- entry->m_expectedValues = basicBlock.intersectionOfPastValuesAtHead;
-
- // Fix the expected values: in our protocol, a dead variable will have an expected
- // value of (None, []). But the old JIT may stash some values there. So we really
- // need (Top, TOP).
- for (size_t argument = 0; argument < basicBlock.variablesAtHead.numberOfArguments(); ++argument) {
- Node* node = basicBlock.variablesAtHead.argument(argument);
- if (!node || !node->shouldGenerate())
- entry->m_expectedValues.argument(argument).makeHeapTop();
- }
- for (size_t local = 0; local < basicBlock.variablesAtHead.numberOfLocals(); ++local) {
- Node* node = basicBlock.variablesAtHead.local(local);
- if (!node || !node->shouldGenerate())
- entry->m_expectedValues.local(local).makeHeapTop();
- else {
- VariableAccessData* variable = node->variableAccessData();
- entry->m_machineStackUsed.set(variable->machineLocal().toLocal());
-
- switch (variable->flushFormat()) {
- case FlushedDouble:
- entry->m_localsForcedDouble.set(local);
- break;
- case FlushedInt52:
- entry->m_localsForcedMachineInt.set(local);
- break;
- default:
- break;
- }
-
- if (variable->local() != variable->machineLocal()) {
- entry->m_reshufflings.append(
- OSREntryReshuffling(
- variable->local().offset(), variable->machineLocal().offset()));
- }
- }
- }
-
- entry->m_reshufflings.shrinkToFit();
- }
+ void noticeOSREntry(BasicBlock&, JITCompiler::Label blockHead, LinkBuffer&);
RefPtr<JITCode> jitCode() { return m_jitCode; }
Added: trunk/Source/_javascript_Core/dfg/DFGMinifiedGraph.cpp (0 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGMinifiedGraph.cpp (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGMinifiedGraph.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -0,0 +1,53 @@
+/*
+ * 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. ``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
+ * 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 "DFGMinifiedGraph.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "JSCInlines.h"
+#include "TrackedReferences.h"
+
+namespace JSC { namespace DFG {
+
+void MinifiedGraph::prepareAndShrink()
+{
+ std::sort(m_list.begin(), m_list.end(), MinifiedNode::compareByNodeIndex);
+ m_list.shrinkToFit();
+}
+
+void MinifiedGraph::validateReferences(const TrackedReferences& trackedReferences)
+{
+ for (MinifiedNode& node : m_list) {
+ if (node.hasConstant())
+ trackedReferences.check(node.constant());
+ }
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
Modified: trunk/Source/_javascript_Core/dfg/DFGMinifiedGraph.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGMinifiedGraph.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGMinifiedGraph.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 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
@@ -33,8 +33,12 @@
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
-namespace JSC { namespace DFG {
+namespace JSC {
+class TrackedReferences;
+
+namespace DFG {
+
class MinifiedGraph {
public:
MinifiedGraph() { }
@@ -50,12 +54,10 @@
m_list.append(node);
}
- void prepareAndShrink()
- {
- std::sort(m_list.begin(), m_list.end(), MinifiedNode::compareByNodeIndex);
- m_list.shrinkToFit();
- }
+ void prepareAndShrink();
+ void validateReferences(const TrackedReferences&);
+
private:
Vector<MinifiedNode> m_list;
};
Modified: trunk/Source/_javascript_Core/dfg/DFGOSREntry.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGOSREntry.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGOSREntry.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013, 2014, 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
@@ -35,9 +35,61 @@
#include "JIT.h"
#include "JSStackInlines.h"
#include "JSCInlines.h"
+#include <wtf/CommaPrinter.h>
namespace JSC { namespace DFG {
+void OSREntryData::dumpInContext(PrintStream& out, DumpContext* context) const
+{
+ out.print("bc#", m_bytecodeIndex, ", machine code offset = ", m_machineCodeOffset);
+ out.print(", stack rules = [");
+
+ auto printOperand = [&] (VirtualRegister reg) {
+ out.print(inContext(m_expectedValues.operand(reg), context), " (");
+ VirtualRegister toReg;
+ bool overwritten = false;
+ for (OSREntryReshuffling reshuffling : m_reshufflings) {
+ if (reg == VirtualRegister(reshuffling.fromOffset)) {
+ toReg = VirtualRegister(reshuffling.toOffset);
+ break;
+ }
+ if (reg == VirtualRegister(reshuffling.toOffset))
+ overwritten = true;
+ }
+ if (!overwritten && !toReg.isValid())
+ toReg = reg;
+ if (toReg.isValid()) {
+ if (toReg.isLocal() && !m_machineStackUsed.get(toReg.toLocal()))
+ out.print("ignored");
+ else
+ out.print("maps to ", toReg);
+ } else
+ out.print("overwritten");
+ if (reg.isLocal() && m_localsForcedDouble.get(reg.toLocal()))
+ out.print(", forced double");
+ if (reg.isLocal() && m_localsForcedMachineInt.get(reg.toLocal()))
+ out.print(", forced machine int");
+ out.print(")");
+ };
+
+ CommaPrinter comma;
+ for (size_t argumentIndex = m_expectedValues.numberOfArguments(); argumentIndex--;) {
+ out.print(comma, "arg", argumentIndex, ":");
+ printOperand(virtualRegisterForArgument(argumentIndex));
+ }
+ for (size_t localIndex = 0; localIndex < m_expectedValues.numberOfLocals(); ++localIndex) {
+ out.print(comma, "loc", localIndex, ":");
+ printOperand(virtualRegisterForLocal(localIndex));
+ }
+
+ out.print("], machine stack used = ", m_machineStackUsed);
+}
+
+void OSREntryData::dump(PrintStream& out) const
+{
+ dumpInContext(out, nullptr);
+}
+
void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIndex)
{
ASSERT(JITCode::isOptimizingJIT(codeBlock->jitType()));
Modified: trunk/Source/_javascript_Core/dfg/DFGOSREntry.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGOSREntry.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGOSREntry.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013, 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
@@ -60,6 +60,9 @@
BitVector m_localsForcedMachineInt;
Vector<OSREntryReshuffling> m_reshufflings;
BitVector m_machineStackUsed;
+
+ void dumpInContext(PrintStream&, DumpContext*) const;
+ void dump(PrintStream&) const;
};
inline unsigned getOSREntryDataBytecodeIndex(OSREntryData* osrEntryData)
Modified: trunk/Source/_javascript_Core/dfg/DFGPlan.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -76,6 +76,7 @@
#include "JSCInlines.h"
#include "OperandsInlines.h"
#include "ProfilerDatabase.h"
+#include "TrackedReferences.h"
#include <wtf/CurrentTime.h>
#if ENABLE(FTL_JIT)
@@ -536,6 +537,21 @@
reallyAdd(codeBlock->jitCode()->dfgCommon());
+ if (validationEnabled()) {
+ TrackedReferences trackedReferences;
+
+ for (WriteBarrier<JSCell>& reference : codeBlock->jitCode()->dfgCommon()->weakReferences)
+ trackedReferences.add(reference.get());
+ for (WriteBarrier<Structure>& reference : codeBlock->jitCode()->dfgCommon()->weakStructureReferences)
+ trackedReferences.add(reference.get());
+ for (WriteBarrier<Unknown>& constant : codeBlock->constants())
+ trackedReferences.add(constant.get());
+
+ // Check that any other references that we have anywhere in the JITCode are also
+ // tracked either strongly or weakly.
+ codeBlock->jitCode()->validateReferences(trackedReferences);
+ }
+
return CompilationSuccessful;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1631,6 +1631,15 @@
m_jit.noticeOSREntry(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
}
ASSERT(osrEntryIndex == m_osrEntryHeads.size());
+
+ if (verboseCompilationEnabled()) {
+ DumpContext dumpContext;
+ dataLog("OSR Entries:\n");
+ for (OSREntryData& entryData : m_jit.jitCode()->osrEntry)
+ dataLog(" ", inContext(entryData, &dumpContext), "\n");
+ if (!dumpContext.isEmpty())
+ dumpContext.dump(WTF::dataFile());
+ }
}
void SpeculativeJIT::compileDoublePutByVal(Node* node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property)
Modified: trunk/Source/_javascript_Core/dfg/DFGStructureAbstractValue.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGStructureAbstractValue.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGStructureAbstractValue.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -386,6 +386,13 @@
dumpInContext(out, 0);
}
+void StructureAbstractValue::validateReferences(const TrackedReferences& trackedReferences) const
+{
+ if (isTop())
+ return;
+ m_set.validateReferences(trackedReferences);
+}
+
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
Modified: trunk/Source/_javascript_Core/dfg/DFGStructureAbstractValue.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGStructureAbstractValue.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGStructureAbstractValue.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -34,8 +34,12 @@
#include "DumpContext.h"
#include "StructureSet.h"
-namespace JSC { namespace DFG {
+namespace JSC {
+class TrackedReferences;
+
+namespace DFG {
+
class StructureAbstractValue {
public:
StructureAbstractValue() { }
@@ -214,6 +218,8 @@
bool overlaps(const StructureSet& other) const;
bool overlaps(const StructureAbstractValue& other) const;
+ void validateReferences(const TrackedReferences&) const;
+
private:
static const uintptr_t clobberedFlag = StructureSet::reservedFlag;
static const uintptr_t topValue = StructureSet::reservedValue;
Modified: trunk/Source/_javascript_Core/dfg/DFGValidate.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGValidate.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGValidate.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -252,6 +252,10 @@
VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
}
break;
+ case DoubleConstant:
+ case Int52Constant:
+ VALIDATE((node), node->isNumberConstant());
+ break;
default:
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGValueStrength.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGValueStrength.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGValueStrength.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 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
@@ -35,9 +35,6 @@
void printInternal(PrintStream& out, ValueStrength strength)
{
switch (strength) {
- case FragileValue:
- out.print("Fragile");
- return;
case WeakValue:
out.print("Weak");
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGValueStrength.h (186690 => 186691)
--- trunk/Source/_javascript_Core/dfg/DFGValueStrength.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/dfg/DFGValueStrength.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 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
@@ -33,12 +33,6 @@
namespace JSC { namespace DFG {
enum ValueStrength {
- // The value is known to the DFG but no optimizations have been performed that require the
- // value to be kept alive. All OSR entry values are fragile until we do some optimization that
- // uses them, like actually constant folding a variable to that value. By convention we say
- // that all non-cells are fragile.
- FragileValue,
-
// The value has been used for optimization and it arose through inference. We don't want the
// fact that we optimized the code to result in the GC keeping this value alive unnecessarily,
// so we'd rather kill the code and recompile than keep the object alive longer.
@@ -52,18 +46,14 @@
inline ValueStrength merge(ValueStrength a, ValueStrength b)
{
switch (a) {
- case FragileValue:
- return b;
case WeakValue:
- if (b == StrongValue)
- return StrongValue;
- return WeakValue;
+ return b;
case StrongValue:
return StrongValue;
}
RELEASE_ASSERT_NOT_REACHED();
- return FragileValue;
+ return WeakValue;
}
} } // namespace JSC::DFG
Modified: trunk/Source/_javascript_Core/ftl/FTLExitPropertyValue.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLExitPropertyValue.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLExitPropertyValue.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -40,6 +40,11 @@
out.print(m_location, " => ", m_value);
}
+void ExitPropertyValue::validateReferences(const TrackedReferences& trackedReferences) const
+{
+ m_value.validateReferences(trackedReferences);
+}
+
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
Modified: trunk/Source/_javascript_Core/ftl/FTLExitPropertyValue.h (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLExitPropertyValue.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLExitPropertyValue.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -31,8 +31,12 @@
#include "DFGPromotedHeapLocation.h"
#include "FTLExitValue.h"
-namespace JSC { namespace FTL {
+namespace JSC {
+class TrackedReferences;
+
+namespace FTL {
+
class ExitPropertyValue {
public:
ExitPropertyValue()
@@ -54,6 +58,8 @@
ExitPropertyValue withLocalsOffset(int offset) const;
void dump(PrintStream& out) const;
+
+ void validateReferences(const TrackedReferences&) const;
private:
DFG::PromotedLocationDescriptor m_location;
Modified: trunk/Source/_javascript_Core/ftl/FTLExitTimeObjectMaterialization.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLExitTimeObjectMaterialization.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLExitTimeObjectMaterialization.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -70,6 +70,12 @@
out.print(RawPointer(this), ":", Graph::opName(m_type), "(", listDump(m_properties), ")");
}
+void ExitTimeObjectMaterialization::validateReferences(const TrackedReferences& trackedReferences) const
+{
+ for (ExitPropertyValue value : m_properties)
+ value.validateReferences(trackedReferences);
+}
+
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
Modified: trunk/Source/_javascript_Core/ftl/FTLExitTimeObjectMaterialization.h (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLExitTimeObjectMaterialization.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLExitTimeObjectMaterialization.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -33,8 +33,12 @@
#include "FTLExitValue.h"
#include <wtf/Noncopyable.h>
-namespace JSC { namespace FTL {
+namespace JSC {
+class TrackedReferences;
+
+namespace FTL {
+
class ExitTimeObjectMaterialization {
WTF_MAKE_NONCOPYABLE(ExitTimeObjectMaterialization)
public:
@@ -53,6 +57,8 @@
void dump(PrintStream& out) const;
+ void validateReferences(const TrackedReferences&) const;
+
private:
DFG::NodeType m_type;
CodeOrigin m_origin;
Modified: trunk/Source/_javascript_Core/ftl/FTLExitValue.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLExitValue.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLExitValue.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -30,6 +30,7 @@
#include "FTLExitTimeObjectMaterialization.h"
#include "JSCInlines.h"
+#include "TrackedReferences.h"
namespace JSC { namespace FTL {
@@ -126,6 +127,12 @@
dumpInContext(out, 0);
}
+void ExitValue::validateReferences(const TrackedReferences& trackedReferences) const
+{
+ if (isConstant())
+ trackedReferences.check(constant());
+}
+
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
Modified: trunk/Source/_javascript_Core/ftl/FTLExitValue.h (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLExitValue.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLExitValue.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -34,8 +34,12 @@
#include "VirtualRegister.h"
#include <wtf/PrintStream.h>
-namespace JSC { namespace FTL {
+namespace JSC {
+class TrackedReferences;
+
+namespace FTL {
+
// This is like ValueRecovery, but respects the way that the FTL does OSR
// exit: the live non-constant non-flushed values are passed as arguments
// to a noreturn tail call. ExitValue is hence mostly responsible for
@@ -222,6 +226,8 @@
void dump(PrintStream&) const;
void dumpInContext(PrintStream&, DumpContext*) const;
+ void validateReferences(const TrackedReferences&) const;
+
private:
ExitValueKind m_kind;
union {
Modified: trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 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
@@ -125,6 +125,14 @@
return &common;
}
+void JITCode::validateReferences(const TrackedReferences& trackedReferences)
+{
+ common.validateReferences(trackedReferences);
+
+ for (OSRExit& exit : osrExit)
+ exit.validateReferences(trackedReferences);
+}
+
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
Modified: trunk/Source/_javascript_Core/ftl/FTLJITCode.h (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLJITCode.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLJITCode.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 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
@@ -47,8 +47,12 @@
#define SECTION_NAME(NAME) (SECTION_NAME_PREFIX NAME)
-namespace JSC { namespace FTL {
+namespace JSC {
+class TrackedReferences;
+
+namespace FTL {
+
class JITCode : public JSC::JITCode {
public:
JITCode();
@@ -67,6 +71,8 @@
void initializeArityCheckEntrypoint(CodeRef);
void initializeAddressForCall(CodePtr);
+ void validateReferences(const TrackedReferences&) override;
+
const Vector<RefPtr<ExecutableMemoryHandle>>& handles() const { return m_handles; }
const Vector<RefPtr<DataSection>>& dataSections() const { return m_dataSections; }
Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -61,6 +61,15 @@
m_patchableCodeOffset);
}
+void OSRExit::validateReferences(const TrackedReferences& trackedReferences)
+{
+ for (unsigned i = m_values.size(); i--;)
+ m_values[i].validateReferences(trackedReferences);
+
+ for (ExitTimeObjectMaterialization* materialization : m_materializations)
+ materialization->validateReferences(trackedReferences);
+}
+
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExit.h (186690 => 186691)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExit.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExit.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -41,8 +41,12 @@
#include "ValueProfile.h"
#include "VirtualRegister.h"
-namespace JSC { namespace FTL {
+namespace JSC {
+class TrackedReferences;
+
+namespace FTL {
+
// Tracks one OSR exit site within the FTL JIT. OSR exit in FTL works by deconstructing
// the crazy that is OSR down to simple SSA CFG primitives that any compiler backend
// (including of course LLVM) can grok and do meaningful things to. An exit is just a
@@ -159,6 +163,8 @@
{
OSRExitBase::considerAddingAsFrequentExitSite(profiledCodeBlock, ExitFromFTL);
}
+
+ void validateReferences(const TrackedReferences&);
};
} } // namespace JSC::FTL
Modified: trunk/Source/_javascript_Core/jit/JITCode.cpp (186690 => 186691)
--- trunk/Source/_javascript_Core/jit/JITCode.cpp 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/jit/JITCode.cpp 2015-07-10 21:19:51 UTC (rev 186691)
@@ -64,6 +64,10 @@
}
}
+void JITCode::validateReferences(const TrackedReferences&)
+{
+}
+
JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame)
{
void* entryAddress;
Modified: trunk/Source/_javascript_Core/jit/JITCode.h (186690 => 186691)
--- trunk/Source/_javascript_Core/jit/JITCode.h 2015-07-10 21:17:47 UTC (rev 186690)
+++ trunk/Source/_javascript_Core/jit/JITCode.h 2015-07-10 21:19:51 UTC (rev 186691)
@@ -46,6 +46,7 @@
}
struct ProtoCallFrame;
+class TrackedReferences;
class VM;
class JITCode : public ThreadSafeRefCounted<JITCode> {
@@ -183,6 +184,8 @@
virtual FTL::JITCode* ftl();
virtual FTL::ForOSREntryJITCode* ftlForOSREntry();
+ virtual void validateReferences(const TrackedReferences&);
+
JSValue execute(VM*, ProtoCallFrame*);
void* start() { return dataAddressAtOffset(0); }
Added: trunk/Source/_javascript_Core/tests/stress/dead-osr-entry-value.js (0 => 186691)
--- trunk/Source/_javascript_Core/tests/stress/dead-osr-entry-value.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/dead-osr-entry-value.js 2015-07-10 21:19:51 UTC (rev 186691)
@@ -0,0 +1,16 @@
+function foo() {
+ var o = {f:42};
+ var result = 0;
+ OSRExit();
+ for (var i = 0; i < 10000; ++i) {
+ if (!DFGTrue())
+ result += o.f;
+ }
+ return result;
+}
+
+for (var i = 0; i < 1000; ++i) {
+ foo();
+ fullGC();
+}
+