CodeBlock::jettison() should be implicit
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Sep 2013 16:39:29 +0000 (16:39 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Sep 2013 16:39:29 +0000 (16:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=120567

Reviewed by Oliver Hunt.

This is a risky change from a performance standpoint, but I believe it's
necessary. This makes all CodeBlocks get swept by GC. Nobody but the GC
can delete CodeBlocks because the GC always holds a reference to them.
Once a CodeBlock reaches just one reference (i.e. the one from the GC)
then the GC will free it only if it's not on the stack.

This allows me to get rid of the jettisoning logic. We need this for FTL
tier-up. Well; we don't need it, but it will help prevent a lot of bugs.
Previously, if you wanted to to replace one code block with another, you
had to remember to tell the GC that the previous code block is
"jettisoned". We would need to do this when tiering up from DFG to FTL
and when dealing with DFG-to-FTL OSR entry code blocks. There are a lot
of permutations here - tiering up to the FTL, OSR entering into the FTL,
deciding that an OSR entry code block is not relevant anymore - just to
name a few. In each of these cases we'd have to jettison the previous
code block. It smells like a huge source of future bugs.

So I made jettisoning implicit by making the GC always watch out for a
CodeBlock being owned solely by the GC.

This change is performance neutral.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::visitAggregate):
(JSC::CodeBlock::jettison):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::setJITCode):
(JSC::CodeBlock::shouldImmediatelyAssumeLivenessDuringScan):
(JSC::CodeBlockSet::mark):
* dfg/DFGCommonData.h:
(JSC::DFG::CommonData::CommonData):
* heap/CodeBlockSet.cpp: Added.
(JSC::CodeBlockSet::CodeBlockSet):
(JSC::CodeBlockSet::~CodeBlockSet):
(JSC::CodeBlockSet::add):
(JSC::CodeBlockSet::clearMarks):
(JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
(JSC::CodeBlockSet::traceMarked):
* heap/CodeBlockSet.h: Added.
* heap/ConservativeRoots.cpp:
(JSC::ConservativeRoots::add):
* heap/ConservativeRoots.h:
* heap/DFGCodeBlocks.cpp: Removed.
* heap/DFGCodeBlocks.h: Removed.
* heap/Heap.cpp:
(JSC::Heap::markRoots):
(JSC::Heap::deleteAllCompiledCode):
(JSC::Heap::deleteUnmarkedCompiledCode):
* heap/Heap.h:
* interpreter/JSStack.cpp:
(JSC::JSStack::gatherConservativeRoots):
* interpreter/JSStack.h:
* runtime/Executable.cpp:
(JSC::ScriptExecutable::installCode):
* runtime/Executable.h:
* runtime/VM.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@154986 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/dfg/DFGCommonData.h
Source/JavaScriptCore/heap/CodeBlockSet.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/CodeBlockSet.h [new file with mode: 0644]
Source/JavaScriptCore/heap/ConservativeRoots.cpp
Source/JavaScriptCore/heap/ConservativeRoots.h
Source/JavaScriptCore/heap/DFGCodeBlocks.cpp [deleted file]
Source/JavaScriptCore/heap/DFGCodeBlocks.h [deleted file]
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/interpreter/JSStack.cpp
Source/JavaScriptCore/interpreter/JSStack.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/VM.h

index 711b8de..bb3fc5b 100644 (file)
@@ -169,30 +169,10 @@ set(JavaScriptCore_SOURCES
     disassembler/X86Disassembler.cpp
 
     heap/BlockAllocator.cpp
-    heap/CopiedSpace.cpp
-    heap/CopyVisitor.cpp
-    heap/ConservativeRoots.cpp
-    heap/DFGCodeBlocks.cpp
-    heap/GCIncomingRefCountedSet.h
-    heap/GCIncomingRefCounted.h
-    heap/GCIncomingRefCountedSetInlines.h
-    heap/GCIncomingRefCountedInlines.h
-    heap/GCThread.cpp
-    heap/GCThreadSharedData.cpp
-    heap/HandleSet.cpp
-    heap/HandleStack.cpp
-    heap/Heap.cpp
-    heap/HeapStatistics.cpp
-    heap/HeapTimer.cpp
-    heap/IncrementalSweeper.cpp
-    heap/JITStubRoutineSet.cpp
-    heap/MachineStackMarker.cpp
-
-    heap/BlockAllocator.cpp
+    heap/CodeBlockSet.cpp
     heap/ConservativeRoots.cpp
     heap/CopiedSpace.cpp
     heap/CopyVisitor.cpp
-    heap/DFGCodeBlocks.cpp
     heap/GCThread.cpp
     heap/GCThreadSharedData.cpp
     heap/HandleSet.cpp
@@ -200,6 +180,7 @@ set(JavaScriptCore_SOURCES
     heap/Heap.cpp
     heap/HeapStatistics.cpp
     heap/HeapTimer.cpp
+    heap/IncrementalSweeper.cpp
     heap/JITStubRoutineSet.cpp
     heap/MachineStackMarker.cpp
     heap/MarkStack.cpp
index 22b13fa..7f9da15 100644 (file)
@@ -1,3 +1,74 @@
+2013-09-02  Filip Pizlo  <fpizlo@apple.com>
+
+        CodeBlock::jettison() should be implicit
+        https://bugs.webkit.org/show_bug.cgi?id=120567
+
+        Reviewed by Oliver Hunt.
+        
+        This is a risky change from a performance standpoint, but I believe it's
+        necessary. This makes all CodeBlocks get swept by GC. Nobody but the GC
+        can delete CodeBlocks because the GC always holds a reference to them.
+        Once a CodeBlock reaches just one reference (i.e. the one from the GC)
+        then the GC will free it only if it's not on the stack.
+        
+        This allows me to get rid of the jettisoning logic. We need this for FTL
+        tier-up. Well; we don't need it, but it will help prevent a lot of bugs.
+        Previously, if you wanted to to replace one code block with another, you
+        had to remember to tell the GC that the previous code block is
+        "jettisoned". We would need to do this when tiering up from DFG to FTL
+        and when dealing with DFG-to-FTL OSR entry code blocks. There are a lot
+        of permutations here - tiering up to the FTL, OSR entering into the FTL,
+        deciding that an OSR entry code block is not relevant anymore - just to
+        name a few. In each of these cases we'd have to jettison the previous
+        code block. It smells like a huge source of future bugs.
+        
+        So I made jettisoning implicit by making the GC always watch out for a
+        CodeBlock being owned solely by the GC.
+        
+        This change is performance neutral.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::~CodeBlock):
+        (JSC::CodeBlock::visitAggregate):
+        (JSC::CodeBlock::jettison):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::setJITCode):
+        (JSC::CodeBlock::shouldImmediatelyAssumeLivenessDuringScan):
+        (JSC::CodeBlockSet::mark):
+        * dfg/DFGCommonData.h:
+        (JSC::DFG::CommonData::CommonData):
+        * heap/CodeBlockSet.cpp: Added.
+        (JSC::CodeBlockSet::CodeBlockSet):
+        (JSC::CodeBlockSet::~CodeBlockSet):
+        (JSC::CodeBlockSet::add):
+        (JSC::CodeBlockSet::clearMarks):
+        (JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
+        (JSC::CodeBlockSet::traceMarked):
+        * heap/CodeBlockSet.h: Added.
+        * heap/ConservativeRoots.cpp:
+        (JSC::ConservativeRoots::add):
+        * heap/ConservativeRoots.h:
+        * heap/DFGCodeBlocks.cpp: Removed.
+        * heap/DFGCodeBlocks.h: Removed.
+        * heap/Heap.cpp:
+        (JSC::Heap::markRoots):
+        (JSC::Heap::deleteAllCompiledCode):
+        (JSC::Heap::deleteUnmarkedCompiledCode):
+        * heap/Heap.h:
+        * interpreter/JSStack.cpp:
+        (JSC::JSStack::gatherConservativeRoots):
+        * interpreter/JSStack.h:
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::installCode):
+        * runtime/Executable.h:
+        * runtime/VM.h:
+
 2013-09-02  Darin Adler  <darin@apple.com>
 
         [Mac] No need for HardAutorelease, which is same as CFBridgingRelease
index 1cc4824..68aff1f 100644 (file)
@@ -442,6 +442,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/ftl/FTLValueFromBlock.h \
        Source/JavaScriptCore/ftl/FTLValueSource.cpp \
        Source/JavaScriptCore/ftl/FTLValueSource.h \
+       Source/JavaScriptCore/heap/CodeBlockSet.cpp \
+       Source/JavaScriptCore/heap/CodeBlockSet.h \
        Source/JavaScriptCore/heap/CopiedAllocator.h \
        Source/JavaScriptCore/heap/CopiedBlock.h \
        Source/JavaScriptCore/heap/CopiedBlockInlines.h \
@@ -456,8 +458,6 @@ javascriptcore_sources += \
        Source/JavaScriptCore/heap/ConservativeRoots.cpp \
        Source/JavaScriptCore/heap/ConservativeRoots.h \
        Source/JavaScriptCore/heap/DeferGC.h \
-       Source/JavaScriptCore/heap/DFGCodeBlocks.cpp \
-       Source/JavaScriptCore/heap/DFGCodeBlocks.h \
        Source/JavaScriptCore/heap/GCAssertions.h \
        Source/JavaScriptCore/heap/GCIncomingRefCounted.h \
        Source/JavaScriptCore/heap/GCIncomingRefCountedInlines.h \
index 589f328..b06edad 100644 (file)
     <ClCompile Include="..\dfg\DFGDriver.cpp" />\r
     <ClCompile Include="..\disassembler\Disassembler.cpp" />\r
     <ClCompile Include="..\heap\BlockAllocator.cpp" />\r
+    <ClCompile Include="..\heap\CodeBlockSet.cpp" />\r
     <ClCompile Include="..\heap\ConservativeRoots.cpp" />\r
     <ClCompile Include="..\heap\CopiedSpace.cpp" />\r
     <ClCompile Include="..\heap\CopyVisitor.cpp" />\r
-    <ClCompile Include="..\heap\DFGCodeBlocks.cpp" />\r
     <ClCompile Include="..\heap\GCThread.cpp" />\r
     <ClCompile Include="..\heap\GCThreadSharedData.cpp" />\r
     <ClCompile Include="..\heap\HandleSet.cpp" />\r
     <ClInclude Include="..\dfg\DFGOSREntry.h" />\r
     <ClInclude Include="..\disassembler\Disassembler.h" />\r
     <ClInclude Include="..\heap\BlockAllocator.h" />\r
+    <ClInclude Include="..\heap\CodeBlockSet.h" />\r
     <ClInclude Include="..\heap\ConservativeRoots.h" />\r
     <ClInclude Include="..\heap\CopiedAllocator.h" />\r
     <ClInclude Include="..\heap\CopiedBlock.h" />\r
     <ClInclude Include="..\heap\CopyVisitor.h" />\r
     <ClInclude Include="..\heap\CopyVisitorInlines.h" />\r
     <ClInclude Include="..\heap\CopyWorkList.h" />\r
-    <ClInclude Include="..\heap\DFGCodeBlocks.h" />\r
     <ClInclude Include="..\heap\GCAssertions.h" />\r
     <ClInclude Include="..\heap\GCThread.h" />\r
     <ClInclude Include="..\heap\GCThreadSharedData.h" />\r
index 1673eaf..86c9d9e 100644 (file)
                0F2BDC4D1522818600CD8910 /* DFGMinifiedNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */; };
                0F2BDC4F15228BF300CD8910 /* DFGValueSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */; };
                0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC5015228FFA00CD8910 /* DFGVariableEvent.cpp */; };
-               0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */; };
                0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2F16828A7E003C2F8D /* UnusedPointer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F2E892D16D02BAF009E4FD2 /* DFGMinifiedID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51016B3A964003F696B /* DFGMinifiedID.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */; };
                0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */; };
                0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FD82E86141F3FF100179C94 /* SpeculatedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E84141F3FDA00179C94 /* SpeculatedType.cpp */; };
+               0FD8A31317D4326C00CA2C40 /* CodeBlockSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD8A31117D4326C00CA2C40 /* CodeBlockSet.cpp */; };
+               0FD8A31417D4326C00CA2C40 /* CodeBlockSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD8A31217D4326C00CA2C40 /* CodeBlockSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FDB2CC9173DA520007B3C1B /* FTLAbbreviatedTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CC7173DA51E007B3C1B /* FTLAbbreviatedTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CC8173DA51E007B3C1B /* FTLValueFromBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */; };
                0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedNode.cpp; path = dfg/DFGMinifiedNode.cpp; sourceTree = "<group>"; };
                0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValueSource.cpp; path = dfg/DFGValueSource.cpp; sourceTree = "<group>"; };
                0F2BDC5015228FFA00CD8910 /* DFGVariableEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableEvent.cpp; path = dfg/DFGVariableEvent.cpp; sourceTree = "<group>"; };
-               0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; };
-               0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; };
                0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDCEPhase.cpp; path = dfg/DFGDCEPhase.cpp; sourceTree = "<group>"; };
                0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDCEPhase.h; path = dfg/DFGDCEPhase.h; sourceTree = "<group>"; };
                0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = "<group>"; };
                0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSREntry.cpp; path = dfg/DFGOSREntry.cpp; sourceTree = "<group>"; };
                0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSREntry.h; path = dfg/DFGOSREntry.h; sourceTree = "<group>"; };
                0FD82E84141F3FDA00179C94 /* SpeculatedType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpeculatedType.cpp; sourceTree = "<group>"; };
+               0FD8A31117D4326C00CA2C40 /* CodeBlockSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockSet.cpp; sourceTree = "<group>"; };
+               0FD8A31217D4326C00CA2C40 /* CodeBlockSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockSet.h; sourceTree = "<group>"; };
                0FDB2CC7173DA51E007B3C1B /* FTLAbbreviatedTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLAbbreviatedTypes.h; path = ftl/FTLAbbreviatedTypes.h; sourceTree = "<group>"; };
                0FDB2CC8173DA51E007B3C1B /* FTLValueFromBlock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLValueFromBlock.h; path = ftl/FTLValueFromBlock.h; sourceTree = "<group>"; };
                0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGWorklist.cpp; path = dfg/DFGWorklist.cpp; sourceTree = "<group>"; };
                        children = (
                                14816E19154CC56C00B8054C /* BlockAllocator.cpp */,
                                14816E1A154CC56C00B8054C /* BlockAllocator.h */,
+                               0FD8A31117D4326C00CA2C40 /* CodeBlockSet.cpp */,
+                               0FD8A31217D4326C00CA2C40 /* CodeBlockSet.h */,
                                146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
                                149DAAF212EB559D0083B12B /* ConservativeRoots.h */,
                                C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */,
                                C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */,
                                C218D13F1655CFD50062BB81 /* CopyWorkList.h */,
                                0F136D4B174AD69B0075B354 /* DeferGC.h */,
-                               0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */,
-                               0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */,
                                BCBE2CAD14E985AA000593AD /* GCAssertions.h */,
                                0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */,
                                0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */,
                                0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */,
                                A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */,
                                A77A424217A0BBFD00A8DB81 /* DFGClobberSet.h in Headers */,
-                               0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */,
                                0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
                                0FEA0A32170D40BF00BB722C /* DFGCommonData.h in Headers */,
                                0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */,
                                A77A424317A0BBFD00A8DB81 /* DFGSafeToExecute.h in Headers */,
                                A741017F179DAF80002EB8BA /* DFGSaneStringGetByValSlowPathGenerator.h in Headers */,
                                86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */,
+                               0FD8A31417D4326C00CA2C40 /* CodeBlockSet.h in Headers */,
                                0F766D4615B3701F008F363E /* DFGScratchRegisterAllocator.h in Headers */,
                                0F1E3A67153A21E2000F9456 /* DFGSilentRegisterSavePlan.h in Headers */,
                                0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */,
                                0F3B3A271544C995003ED0FF /* DFGCFGSimplificationPhase.cpp in Sources */,
                                A77A423F17A0BBFD00A8DB81 /* DFGClobberize.cpp in Sources */,
                                A77A424117A0BBFD00A8DB81 /* DFGClobberSet.cpp in Sources */,
-                               0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */,
                                0FF0F19D16B72A08005DF95B /* DFGCommon.cpp in Sources */,
                                0FEA0A31170D40BF00BB722C /* DFGCommonData.cpp in Sources */,
                                0F38B01717CFE75500B144D3 /* DFGCompilationKey.cpp in Sources */,
                                147F39D6107EC37600427A48 /* JSCJSValue.cpp in Sources */,
                                1440FCE40A51E46B0005F061 /* JSClassRef.cpp in Sources */,
                                86E3C616167BABEE006D760A /* JSContext.mm in Sources */,
+                               0FD8A31317D4326C00CA2C40 /* CodeBlockSet.cpp in Sources */,
                                14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */,
                                A72028B61797601E0098028C /* JSCTestRunnerUtils.cpp in Sources */,
                                0F2B66EB17B6B5AB00A7AE3F /* JSDataView.cpp in Sources */,
index 27645d0..eba5dc7 100644 (file)
@@ -82,11 +82,11 @@ SOURCES += \
     bytecode/Watchpoint.cpp \
     bytecompiler/BytecodeGenerator.cpp \
     bytecompiler/NodesCodegen.cpp \
+    heap/CodeBlockSet.cpp \
     heap/CopiedSpaceInlines.h \
     heap/CopiedSpace.cpp \
     heap/CopyVisitor.cpp \
     heap/ConservativeRoots.cpp \
-    heap/DFGCodeBlocks.cpp \
     heap/Weak.cpp \
     heap/WeakBlock.cpp \
     heap/WeakHandleOwner.cpp \
index a2aecc7..52f7552 100644 (file)
@@ -1504,6 +1504,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
 {
+    ASSERT(m_heap->isDeferred());
     setNumParameters(other.numParameters());
     optimizeAfterWarmUp();
     jitAfterWarmUp();
@@ -1516,6 +1517,9 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
         m_rareData->m_switchJumpTables = other.m_rareData->m_switchJumpTables;
         m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
     }
+    
+    m_heap->m_codeBlocks.add(this);
+    m_heap->reportExtraMemoryCost(sizeof(CodeBlock));
 }
 
 CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
@@ -1544,7 +1548,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
 {
-    m_vm->startedCompiling(this);
+    ASSERT(m_heap->isDeferred());
 
     ASSERT(m_source);
     setNumParameters(unlinkedCodeBlock->numParameters());
@@ -1842,7 +1846,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
 
     if (Options::dumpGeneratedBytecodes())
         dumpBytecode();
-    m_vm->finishedCompiling(this);
+    m_heap->m_codeBlocks.add(this);
+    m_heap->reportExtraMemoryCost(sizeof(CodeBlock));
 }
 
 CodeBlock::~CodeBlock()
@@ -1850,12 +1855,6 @@ CodeBlock::~CodeBlock()
     if (m_vm->m_perBytecodeProfiler)
         m_vm->m_perBytecodeProfiler->notifyDestruction(this);
     
-#if ENABLE(DFG_JIT)
-    // Remove myself from the set of DFG code blocks. Note that I may not be in this set
-    // (because I'm not a DFG code block), in which case this is a no-op anyway.
-    m_vm->heap.m_dfgCodeBlocks.m_set.remove(this);
-#endif
-    
 #if ENABLE(VERBOSE_VALUE_PROFILE)
     dumpValueProfiles();
 #endif
@@ -1905,33 +1904,29 @@ void EvalCodeCache::visitAggregate(SlotVisitor& visitor)
 
 void CodeBlock::visitAggregate(SlotVisitor& visitor)
 {
-#if ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT)
-    if (JITCode::isOptimizingJIT(jitType())) {
-        DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
-        
-        // I may be asked to scan myself more than once, and it may even happen concurrently.
-        // To this end, use a CAS loop to check if I've been called already. Only one thread
-        // may proceed past this point - whichever one wins the CAS race.
-        unsigned oldValue;
-        do {
-            oldValue = dfgCommon->visitAggregateHasBeenCalled;
-            if (oldValue) {
-                // Looks like someone else won! Return immediately to ensure that we don't
-                // trace the same CodeBlock concurrently. Doing so is hazardous since we will
-                // be mutating the state of ValueProfiles, which contain JSValues, which can
-                // have word-tearing on 32-bit, leading to awesome timing-dependent crashes
-                // that are nearly impossible to track down.
-                
-                // Also note that it must be safe to return early as soon as we see the
-                // value true (well, (unsigned)1), since once a GC thread is in this method
-                // and has won the CAS race (i.e. was responsible for setting the value true)
-                // it will definitely complete the rest of this method before declaring
-                // termination.
-                return;
-            }
-        } while (!WTF::weakCompareAndSwap(&dfgCommon->visitAggregateHasBeenCalled, 0, 1));
-    }
-#endif // ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT)
+#if ENABLE(PARALLEL_GC)
+    // I may be asked to scan myself more than once, and it may even happen concurrently.
+    // To this end, use a CAS loop to check if I've been called already. Only one thread
+    // may proceed past this point - whichever one wins the CAS race.
+    unsigned oldValue;
+    do {
+        oldValue = m_visitAggregateHasBeenCalled;
+        if (oldValue) {
+            // Looks like someone else won! Return immediately to ensure that we don't
+            // trace the same CodeBlock concurrently. Doing so is hazardous since we will
+            // be mutating the state of ValueProfiles, which contain JSValues, which can
+            // have word-tearing on 32-bit, leading to awesome timing-dependent crashes
+            // that are nearly impossible to track down.
+            
+            // Also note that it must be safe to return early as soon as we see the
+            // value true (well, (unsigned)1), since once a GC thread is in this method
+            // and has won the CAS race (i.e. was responsible for setting the value true)
+            // it will definitely complete the rest of this method before declaring
+            // termination.
+            return;
+        }
+    } while (!WTF::weakCompareAndSwap(&m_visitAggregateHasBeenCalled, 0, 1));
+#endif // ENABLE(PARALLEL_GC)
     
     if (!!m_alternative)
         m_alternative->visitAggregate(visitor);
@@ -2740,28 +2735,14 @@ DFG::CapabilityLevel FunctionCodeBlock::capabilityLevelInternal()
 
 void CodeBlock::jettison()
 {
+    DeferGC deferGC(*m_heap);
     ASSERT(JITCode::isOptimizingJIT(jitType()));
     ASSERT(this == replacement());
     alternative()->optimizeAfterWarmUp();
     tallyFrequentExitSites();
     if (DFG::shouldShowDisassembly())
         dataLog("Jettisoning ", *this, ".\n");
-    jettisonImpl();
-}
-
-void ProgramCodeBlock::jettisonImpl()
-{
-    static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*vm());
-}
-
-void EvalCodeBlock::jettisonImpl()
-{
-    static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*vm());
-}
-
-void FunctionCodeBlock::jettisonImpl()
-{
-    static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*vm(), m_isConstructor ? CodeForConstruct : CodeForCall);
+    alternative()->install();
 }
 #endif
 
index 4756bfb..50cae29 100644 (file)
 #include "CallLinkInfo.h"
 #include "CallReturnOffsetToBytecodeOffset.h"
 #include "CodeBlockHash.h"
+#include "CodeBlockSet.h"
 #include "ConcurrentJITLock.h"
 #include "CodeOrigin.h"
 #include "CodeType.h"
 #include "CompactJITCodeMap.h"
-#include "DFGCodeBlocks.h"
 #include "DFGCommon.h"
 #include "DFGCommonData.h"
 #include "DFGExitProfile.h"
@@ -83,7 +83,6 @@
 
 namespace JSC {
 
-class DFGCodeBlocks;
 class ExecState;
 class LLIntOffsetsExtractor;
 class RepatchBuffer;
@@ -273,14 +272,12 @@ public:
     
     void setJITCode(PassRefPtr<JITCode> code, MacroAssemblerCodePtr codeWithArityCheck)
     {
+        ASSERT(m_heap->isDeferred());
+        m_heap->reportExtraMemoryCost(code->size());
         ConcurrentJITLocker locker(m_lock);
         WTF::storeStoreFence(); // This is probably not needed because the lock will also do something similar, but it's good to be paranoid.
         m_jitCode = code;
         m_jitCodeWithArityCheck = codeWithArityCheck;
-#if ENABLE(DFG_JIT)
-        if (JITCode::isOptimizingJIT(JITCode::jitTypeFor(m_jitCode)))
-            m_vm->heap.m_dfgCodeBlocks.m_set.add(this);
-#endif
     }
     PassRefPtr<JITCode> jitCode() { return m_jitCode; }
     MacroAssemblerCodePtr jitCodeWithArityCheck() { return m_jitCodeWithArityCheck; }
@@ -961,9 +958,6 @@ public:
     bool m_allTransitionsHaveBeenMarked; // Initialized and used on every GC.
     
 protected:
-#if ENABLE(JIT)
-    virtual void jettisonImpl() = 0;
-#endif
     virtual void visitWeakReferences(SlotVisitor&);
     virtual void finalizeUnconditionally();
 
@@ -974,7 +968,7 @@ protected:
 #endif
 
 private:
-    friend class DFGCodeBlocks;
+    friend class CodeBlockSet;
     
     void noticeIncomingCall(ExecState* callerFrame);
     
@@ -1017,17 +1011,16 @@ private:
 #if ENABLE(DFG_JIT)
     bool shouldImmediatelyAssumeLivenessDuringScan()
     {
-        // Null m_dfgData means that this is a baseline JIT CodeBlock. Baseline JIT
-        // CodeBlocks don't need to be jettisoned when their weak references go
-        // stale. So if a basline JIT CodeBlock gets scanned, we can assume that
-        // this means that it's live.
+        // Interpreter and Baseline JIT CodeBlocks don't need to be jettisoned when
+        // their weak references go stale. So if a basline JIT CodeBlock gets
+        // scanned, we can assume that this means that it's live.
         if (!JITCode::isOptimizingJIT(jitType()))
             return true;
 
         // For simplicity, we don't attempt to jettison code blocks during GC if
         // they are executing. Instead we strongly mark their weak references to
         // allow them to continue to execute soundly.
-        if (m_jitCode->dfgCommon()->mayBeExecuting)
+        if (m_mayBeExecuting)
             return true;
 
         if (Options::forceDFGCodeBlockLiveness())
@@ -1067,6 +1060,8 @@ private:
 
     bool m_isStrictMode;
     bool m_needsActivation;
+    bool m_mayBeExecuting;
+    uint8_t m_visitAggregateHasBeenCalled;
 
     RefPtr<SourceProvider> m_source;
     unsigned m_sourceOffset;
@@ -1186,7 +1181,6 @@ public:
 
 #if ENABLE(JIT)
 protected:
-    virtual void jettisonImpl();
     virtual CodeBlock* replacement();
     virtual DFG::CapabilityLevel capabilityLevelInternal();
 #endif
@@ -1209,7 +1203,6 @@ public:
     
 #if ENABLE(JIT)
 protected:
-    virtual void jettisonImpl();
     virtual CodeBlock* replacement();
     virtual DFG::CapabilityLevel capabilityLevelInternal();
 #endif
@@ -1232,7 +1225,6 @@ public:
     
 #if ENABLE(JIT)
 protected:
-    virtual void jettisonImpl();
     virtual CodeBlock* replacement();
     virtual DFG::CapabilityLevel capabilityLevelInternal();
 #endif
@@ -1291,8 +1283,7 @@ inline JSValue ExecState::argumentAfterCapture(size_t argument)
     return this[codeBlock()->argumentIndexAfterCapture(argument)].jsValue();
 }
 
-#if ENABLE(DFG_JIT)
-inline void DFGCodeBlocks::mark(void* candidateCodeBlock)
+inline void CodeBlockSet::mark(void* candidateCodeBlock)
 {
     // We have to check for 0 and -1 because those are used by the HashMap as markers.
     uintptr_t value = reinterpret_cast<uintptr_t>(candidateCodeBlock);
@@ -1307,9 +1298,8 @@ inline void DFGCodeBlocks::mark(void* candidateCodeBlock)
     if (iter == m_set.end())
         return;
     
-    (*iter)->m_jitCode->dfgCommon()->mayBeExecuting = true;
+    (*iter)->m_mayBeExecuting = true;
 }
-#endif
 
 } // namespace JSC
 
index 145bb65..16d34c2 100644 (file)
@@ -66,11 +66,7 @@ struct WeakReferenceTransition {
 class CommonData {
     WTF_MAKE_NONCOPYABLE(CommonData);
 public:
-    CommonData()
-        : mayBeExecuting(false)
-        , isJettisoned(false)
-    {
-    }
+    CommonData() { }
     
     void notifyCompilingStructureTransition(Plan&, CodeBlock*, Node*);
     
@@ -81,11 +77,8 @@ public:
     Vector<WriteBarrier<JSCell> > weakReferences;
     
     RefPtr<Profiler::Compilation> compilation;
-    bool mayBeExecuting;
-    bool isJettisoned;
     bool livenessHasBeenProved; // Initialized and used on every GC.
     bool allTransitionsHaveBeenMarked; // Initialized and used on every GC.
-    unsigned visitAggregateHasBeenCalled; // Unsigned to make it work seamlessly with the broadest set of CAS implementations.
 };
 
 } } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/heap/CodeBlockSet.cpp b/Source/JavaScriptCore/heap/CodeBlockSet.cpp
new file mode 100644 (file)
index 0000000..ae27480
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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. ``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 "CodeBlockSet.h"
+
+#include "CodeBlock.h"
+#include "SlotVisitor.h"
+
+namespace JSC {
+
+static const bool verbose = false;
+
+CodeBlockSet::CodeBlockSet() { }
+
+CodeBlockSet::~CodeBlockSet()
+{
+    HashSet<CodeBlock*>::iterator iter = m_set.begin();
+    HashSet<CodeBlock*>::iterator end = m_set.end();
+    for (; iter != end; ++iter)
+        (*iter)->deref();
+}
+
+void CodeBlockSet::add(PassRefPtr<CodeBlock> codeBlock)
+{
+    bool isNewEntry = m_set.add(codeBlock.leakRef()).isNewEntry;
+    ASSERT_UNUSED(isNewEntry, isNewEntry);
+}
+
+void CodeBlockSet::clearMarks()
+{
+    HashSet<CodeBlock*>::iterator iter = m_set.begin();
+    HashSet<CodeBlock*>::iterator end = m_set.end();
+    for (; iter != end; ++iter) {
+        CodeBlock* codeBlock = *iter;
+        codeBlock->m_mayBeExecuting = false;
+        codeBlock->m_visitAggregateHasBeenCalled = false;
+    }
+}
+
+void CodeBlockSet::deleteUnmarkedAndUnreferenced()
+{
+    // This needs to be a fixpoint because code blocks that are unmarked may
+    // refer to each other. For example, a DFG code block that is owned by
+    // the GC may refer to an FTL for-entry code block that is also owned by
+    // the GC.
+    Vector<CodeBlock*, 16> toRemove;
+    if (verbose)
+        dataLog("Fixpointing over unmarked, set size = ", m_set.size(), "...\n");
+    for (;;) {
+        HashSet<CodeBlock*>::iterator iter = m_set.begin();
+        HashSet<CodeBlock*>::iterator end = m_set.end();
+        for (; iter != end; ++iter) {
+            CodeBlock* codeBlock = *iter;
+            if (!codeBlock->hasOneRef())
+                continue;
+            if (codeBlock->m_mayBeExecuting)
+                continue;
+            codeBlock->deref();
+            toRemove.append(codeBlock);
+        }
+        if (verbose)
+            dataLog("    Removing ", toRemove.size(), " blocks.\n");
+        if (toRemove.isEmpty())
+            break;
+        for (unsigned i = toRemove.size(); i--;)
+            m_set.remove(toRemove[i]);
+        toRemove.resize(0);
+    }
+}
+
+void CodeBlockSet::traceMarked(SlotVisitor& visitor)
+{
+    if (verbose)
+        dataLog("Tracing ", m_set.size(), " code blocks.\n");
+    HashSet<CodeBlock*>::iterator iter = m_set.begin();
+    HashSet<CodeBlock*>::iterator end = m_set.end();
+    for (; iter != end; ++iter) {
+        CodeBlock* codeBlock = *iter;
+        if (!codeBlock->m_mayBeExecuting)
+            continue;
+        codeBlock->visitAggregate(visitor);
+    }
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/heap/CodeBlockSet.h b/Source/JavaScriptCore/heap/CodeBlockSet.h
new file mode 100644 (file)
index 0000000..2e4e606
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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. ``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 CodeBlockSet_h
+#define CodeBlockSet_h
+
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+class CodeBlock;
+class SlotVisitor;
+
+// CodeBlockSet tracks all CodeBlocks. Every CodeBlock starts out with one
+// reference coming in from GC. The GC is responsible for freeing CodeBlocks
+// once they hasOneRef() and nobody is running code from that CodeBlock.
+
+class CodeBlockSet {
+    WTF_MAKE_NONCOPYABLE(CodeBlockSet);
+
+public:
+    CodeBlockSet();
+    ~CodeBlockSet();
+    
+    // Add a CodeBlock. This is only called by CodeBlock constructors.
+    void add(PassRefPtr<CodeBlock>);
+    
+    // Clear all mark bits associated with DFG code blocks.
+    void clearMarks();
+    
+    // Mark a pointer that may be a CodeBlock that belongs to the set of DFG
+    // blocks. This is defined in CodeBlock.h.
+    void mark(void* candidateCodeBlock);
+    
+    // Delete all code blocks that are only referenced by this set (i.e. owned
+    // by this set), and that have not been marked.
+    void deleteUnmarkedAndUnreferenced();
+    
+    // Trace all marked code blocks. The CodeBlock is free to make use of
+    // mayBeExecuting.
+    void traceMarked(SlotVisitor&);
+
+private:
+    // This is not a set of RefPtr<CodeBlock> because we need to be able to find
+    // arbitrary bogus pointers. I could have written a thingy that had peek types
+    // and all, but that seemed like overkill.
+    HashSet<CodeBlock* > m_set;
+};
+
+} // namespace JSC
+
+#endif // CodeBlockSet_h
+
index 752ce27..9212683 100644 (file)
@@ -27,9 +27,9 @@
 #include "ConservativeRoots.h"
 
 #include "CodeBlock.h"
+#include "CodeBlockSet.h"
 #include "CopiedSpace.h"
 #include "CopiedSpaceInlines.h"
-#include "DFGCodeBlocks.h"
 #include "JSCell.h"
 #include "JSObject.h"
 #include "Structure.h"
@@ -140,10 +140,9 @@ private:
 };
 
 void ConservativeRoots::add(
-    void* begin, void* end, JITStubRoutineSet& jitStubRoutines, DFGCodeBlocks& dfgCodeBlocks)
+    void* begin, void* end, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks)
 {
-    CompositeMarkHook<JITStubRoutineSet, DFGCodeBlocks> markHook(
-        jitStubRoutines, dfgCodeBlocks);
+    CompositeMarkHook<JITStubRoutineSet, CodeBlockSet> markHook(jitStubRoutines, codeBlocks);
     genericAddSpan(begin, end, markHook);
 }
 
index 219bdcc..0cad933 100644 (file)
@@ -32,7 +32,7 @@
 
 namespace JSC {
 
-class DFGCodeBlocks;
+class CodeBlockSet;
 class Heap;
 class JITStubRoutineSet;
 class JSCell;
@@ -44,7 +44,7 @@ public:
 
     void add(void* begin, void* end);
     void add(void* begin, void* end, JITStubRoutineSet&);
-    void add(void* begin, void* end, JITStubRoutineSet&, DFGCodeBlocks&);
+    void add(void* begin, void* end, JITStubRoutineSet&, CodeBlockSet&);
     
     size_t size();
     JSCell** roots();
diff --git a/Source/JavaScriptCore/heap/DFGCodeBlocks.cpp b/Source/JavaScriptCore/heap/DFGCodeBlocks.cpp
deleted file mode 100644 (file)
index 4871231..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2011 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 "DFGCodeBlocks.h"
-
-#include "CodeBlock.h"
-#include "SlotVisitor.h"
-#include <wtf/Vector.h>
-
-namespace JSC {
-
-#if ENABLE(DFG_JIT)
-
-DFGCodeBlocks::DFGCodeBlocks() { }
-
-DFGCodeBlocks::~DFGCodeBlocks()
-{
-    Vector<RefPtr<CodeBlock>, 16> toRemove;
-    
-    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
-        if ((*iter)->jitCode()->dfgCommon()->isJettisoned)
-            toRemove.append(adoptRef(*iter));
-    }
-}
-
-void DFGCodeBlocks::jettison(PassRefPtr<CodeBlock> codeBlockPtr)
-{
-    // We don't want to delete it now; we just want its pointer.
-    CodeBlock* codeBlock = codeBlockPtr.leakRef();
-    
-    ASSERT(codeBlock);
-    ASSERT(JITCode::isOptimizingJIT(codeBlock->jitType()));
-    
-    // It should not have already been jettisoned.
-    ASSERT(!codeBlock->jitCode()->dfgCommon()->isJettisoned);
-
-    // We should have this block already.
-    ASSERT(m_set.find(codeBlock) != m_set.end());
-    
-    codeBlock->jitCode()->dfgCommon()->isJettisoned = true;
-}
-
-void DFGCodeBlocks::clearMarks()
-{
-    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
-        (*iter)->jitCode()->dfgCommon()->mayBeExecuting = false;
-        (*iter)->jitCode()->dfgCommon()->visitAggregateHasBeenCalled = false;
-    }
-}
-
-void DFGCodeBlocks::deleteUnmarkedJettisonedCodeBlocks()
-{
-    Vector<RefPtr<CodeBlock>, 16> toRemove;
-    
-    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
-        if ((*iter)->jitCode()->dfgCommon()->isJettisoned && !(*iter)->jitCode()->dfgCommon()->mayBeExecuting)
-            toRemove.append(adoptRef(*iter));
-    }
-}
-
-void DFGCodeBlocks::traceMarkedCodeBlocks(SlotVisitor& visitor)
-{
-    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
-        if ((*iter)->jitCode()->dfgCommon()->mayBeExecuting)
-            (*iter)->visitAggregate(visitor);
-    }
-}
-
-#else // ENABLE(DFG_JIT)
-
-void DFGCodeBlocks::jettison(PassRefPtr<CodeBlock>)
-{
-}
-
-#endif // ENABLE(DFG_JIT)
-
-} // namespace JSC
-
-
diff --git a/Source/JavaScriptCore/heap/DFGCodeBlocks.h b/Source/JavaScriptCore/heap/DFGCodeBlocks.h
deleted file mode 100644 (file)
index e696319..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2011 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 DFGCodeBlocks_h
-#define DFGCodeBlocks_h
-
-#include <wtf/FastAllocBase.h>
-#include <wtf/HashSet.h>
-#include <wtf/PassOwnPtr.h>
-
-namespace JSC {
-
-class CodeBlock;
-class SlotVisitor;
-
-// DFGCodeBlocks notifies the garbage collector about optimized code blocks that
-// have different marking behavior depending on whether or not they are on the
-// stack, and that may be jettisoned. Jettisoning is the process of discarding
-// a code block after all calls to it have been unlinked. This class takes special
-// care to ensure that if there are still call frames that are using the code
-// block, then it should not be immediately deleted, but rather, it should be
-// deleted once we know that there are no longer any references to it from any
-// call frames. This class takes its name from the DFG compiler; only code blocks
-// compiled by the DFG need special marking behavior if they are on the stack, and
-// only those code blocks may be jettisoned.
-
-#if ENABLE(DFG_JIT)
-class DFGCodeBlocks {
-    WTF_MAKE_FAST_ALLOCATED;
-
-public:
-    DFGCodeBlocks();
-    ~DFGCodeBlocks();
-    
-    // Inform the collector that a code block has been jettisoned form its
-    // executable and should only be kept alive if there are call frames that use
-    // it. This is typically called either from a recompilation trigger, or from
-    // an unconditional finalizer associated with a CodeBlock that had weak
-    // references, where some subset of those references were dead.
-    void jettison(PassRefPtr<CodeBlock>);
-    
-    // Clear all mark bits associated with DFG code blocks.
-    void clearMarks();
-    
-    // Mark a pointer that may be a CodeBlock that belongs to the set of DFG code
-    // blocks. This is defined inline in CodeBlock.h
-    void mark(void* candidateCodeBlock);
-    
-    // Delete all jettisoned code blocks that have not been marked (i.e. are not referenced
-    // from call frames).
-    void deleteUnmarkedJettisonedCodeBlocks();
-    
-    // Trace all marked code blocks (i.e. are referenced from call frames). The CodeBlock
-    // is free to make use of m_dfgData->isMarked and m_dfgData->isJettisoned.
-    void traceMarkedCodeBlocks(SlotVisitor&);
-
-private:
-    friend class CodeBlock;
-    
-    HashSet<CodeBlock*> m_set;
-};
-#else
-class DFGCodeBlocks {
-    WTF_MAKE_FAST_ALLOCATED;
-
-public:
-    void jettison(PassRefPtr<CodeBlock>);
-    void clearMarks() { }
-    void mark(void*) { }
-    void deleteUnmarkedJettisonedCodeBlocks() { }
-    void traceMarkedCodeBlocks(SlotVisitor&) { }
-};
-#endif
-
-} // namespace JSC
-
-#endif
index a40a488..372c355 100644 (file)
@@ -354,11 +354,6 @@ bool Heap::unprotect(JSValue k)
     return m_protectedValues.remove(k.asCell());
 }
 
-void Heap::jettisonDFGCodeBlock(PassRefPtr<CodeBlock> codeBlock)
-{
-    m_dfgCodeBlocks.jettison(codeBlock);
-}
-
 void Heap::addReference(JSCell* cell, ArrayBuffer* buffer)
 {
     if (m_arrayBuffers.addReference(cell, buffer)) {
@@ -457,11 +452,10 @@ void Heap::markRoots()
     }
 
     ConservativeRoots stackRoots(&m_objectSpace.blocks(), &m_storageSpace);
-    m_dfgCodeBlocks.clearMarks();
+    m_codeBlocks.clearMarks();
     {
         GCPHASE(GatherStackRoots);
-        stack().gatherConservativeRoots(
-            stackRoots, m_jitStubRoutines, m_dfgCodeBlocks);
+        stack().gatherConservativeRoots(stackRoots, m_jitStubRoutines, m_codeBlocks);
     }
 
 #if ENABLE(DFG_JIT)
@@ -485,12 +479,6 @@ void Heap::markRoots()
     {
         ParallelModeEnabler enabler(visitor);
 
-        if (m_vm->codeBlocksBeingCompiled.size()) {
-            GCPHASE(VisitActiveCodeBlock);
-            for (size_t i = 0; i < m_vm->codeBlocksBeingCompiled.size(); i++)
-                m_vm->codeBlocksBeingCompiled[i]->visitAggregate(visitor);
-        }
-
         m_vm->smallStrings.visitStrongReferences(visitor);
 
         {
@@ -558,7 +546,7 @@ void Heap::markRoots()
         {
             GCPHASE(TraceCodeBlocksAndJITStubRoutines);
             MARK_LOG_ROOT(visitor, "Trace Code Blocks and JIT Stub Routines");
-            m_dfgCodeBlocks.traceMarkedCodeBlocks(visitor);
+            m_codeBlocks.traceMarked(visitor);
             m_jitStubRoutines.traceMarkedStubRoutines(visitor);
             visitor.donateAndDrain();
         }
@@ -683,8 +671,8 @@ void Heap::deleteAllCompiledCode()
         static_cast<FunctionExecutable*>(current)->clearCodeIfNotCompiling();
     }
 
-    m_dfgCodeBlocks.clearMarks();
-    m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+    m_codeBlocks.clearMarks();
+    m_codeBlocks.deleteUnmarkedAndUnreferenced();
 }
 
 void Heap::deleteUnmarkedCompiledCode()
@@ -701,7 +689,7 @@ void Heap::deleteUnmarkedCompiledCode()
         m_compiledCode.remove(current);
     }
 
-    m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+    m_codeBlocks.deleteUnmarkedAndUnreferenced();
     m_jitStubRoutines.deleteUnmarkedJettisonedStubRoutines();
 }
 
index e422fb6..6a3389f 100644 (file)
@@ -24,8 +24,8 @@
 
 #include "ArrayBuffer.h"
 #include "BlockAllocator.h"
+#include "CodeBlockSet.h"
 #include "CopyVisitor.h"
-#include "DFGCodeBlocks.h"
 #include "GCIncomingRefCountedSet.h"
 #include "GCThreadSharedData.h"
 #include "HandleSet.h"
@@ -144,8 +144,6 @@ namespace JSC {
         JS_EXPORT_PRIVATE void protect(JSValue);
         JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
         
-        void jettisonDFGCodeBlock(PassRefPtr<CodeBlock>);
-
         size_t extraSize(); // extra memory usage outside of pages allocated by the heap
         JS_EXPORT_PRIVATE size_t size();
         JS_EXPORT_PRIVATE size_t capacity();
@@ -273,7 +271,7 @@ namespace JSC {
 
         HandleSet m_handleSet;
         HandleStack m_handleStack;
-        DFGCodeBlocks m_dfgCodeBlocks;
+        CodeBlockSet m_codeBlocks;
         JITStubRoutineSet m_jitStubRoutines;
         FinalizerOwner m_finalizerOwner;
         
index ec2962a..bfdcecb 100644 (file)
@@ -96,9 +96,9 @@ void JSStack::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
     conservativeRoots.add(begin(), getTopOfStack());
 }
 
-void JSStack::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, DFGCodeBlocks& dfgCodeBlocks)
+void JSStack::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks)
 {
-    conservativeRoots.add(begin(), getTopOfStack(), jitStubRoutines, dfgCodeBlocks);
+    conservativeRoots.add(begin(), getTopOfStack(), jitStubRoutines, codeBlocks);
 }
 
 void JSStack::releaseExcessCapacity()
index fe4012d..5263a9c 100644 (file)
@@ -41,8 +41,8 @@
 
 namespace JSC {
 
+    class CodeBlockSet;
     class ConservativeRoots;
-    class DFGCodeBlocks;
     class ExecState;
     class JITStubRoutineSet;
     class VM;
@@ -71,7 +71,7 @@ namespace JSC {
         ~JSStack();
         
         void gatherConservativeRoots(ConservativeRoots&);
-        void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, DFGCodeBlocks&);
+        void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&);
 
         Register* begin() const { return static_cast<Register*>(m_reservation.base()); }
         Register* end() const { return m_end; }
index a1d6d31..ca22a85 100644 (file)
@@ -90,20 +90,6 @@ Intrinsic NativeExecutable::intrinsic() const
 }
 #endif
 
-#if ENABLE(JIT)
-// Utility method used for jettisoning code blocks.
-template<typename T>
-static void jettisonCodeBlock(VM& vm, RefPtr<T>& codeBlock)
-{
-    ASSERT(JITCode::isOptimizingJIT(codeBlock->jitType()));
-    ASSERT(codeBlock->alternative());
-    RefPtr<T> codeBlockToJettison = codeBlock.release();
-    codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
-    codeBlockToJettison->unlinkIncomingCalls();
-    vm.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
-}
-#endif
-
 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
 
 #if ENABLE(JIT)
@@ -125,12 +111,6 @@ void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
     
     ASSERT(vm.heap.isDeferred());
     
-    if (JITCode::isJIT(genericCodeBlock->jitType())) {
-        vm.heap.reportExtraMemoryCost(
-            sizeof(CodeBlock) + genericCodeBlock->jitCode()->size());
-    } else
-        vm.heap.reportExtraMemoryCost(sizeof(CodeBlock));
-    
     CodeSpecializationKind kind = genericCodeBlock->specializationKind();
     
     RefPtr<CodeBlock> oldCodeBlock;
@@ -376,15 +356,6 @@ inline const char* samplingDescription(JITCode::JITType jitType)
     }
 }
 
-#if ENABLE(JIT)
-void EvalExecutable::jettisonOptimizedCode(VM& vm)
-{
-    jettisonCodeBlock(vm, m_evalCodeBlock);
-    m_jitCodeForCall = m_evalCodeBlock->jitCode();
-    ASSERT(!m_jitCodeForCallWithArityCheck);
-}
-#endif // ENABLE(JIT)
-
 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
@@ -426,15 +397,6 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
     return error.toErrorObject(lexicalGlobalObject, m_source);
 }
 
-#if ENABLE(JIT)
-void ProgramExecutable::jettisonOptimizedCode(VM& vm)
-{
-    jettisonCodeBlock(vm, m_programCodeBlock);
-    m_jitCodeForCall = m_programCodeBlock->jitCode();
-    ASSERT(!m_jitCodeForCallWithArityCheck);
-}
-#endif
-
 void ProgramExecutable::unlinkCalls()
 {
 #if ENABLE(JIT)
@@ -518,22 +480,6 @@ FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKi
     return result;
 }
 
-#if ENABLE(JIT)
-void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
-{
-    jettisonCodeBlock(vm, m_codeBlockForCall);
-    m_jitCodeForCall = m_codeBlockForCall->jitCode();
-    m_jitCodeForCallWithArityCheck = m_codeBlockForCall->jitCodeWithArityCheck();
-}
-
-void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM& vm)
-{
-    jettisonCodeBlock(vm, m_codeBlockForConstruct);
-    m_jitCodeForConstruct = m_codeBlockForConstruct->jitCode();
-    m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->jitCodeWithArityCheck();
-}
-#endif
-
 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
index 0cb3bb9..4a14f95 100644 (file)
@@ -445,10 +445,6 @@ public:
 
     static void destroy(JSCell*);
 
-#if ENABLE(JIT)
-    void jettisonOptimizedCode(VM&);
-#endif
-
     EvalCodeBlock* codeBlock()
     {
         return m_evalCodeBlock.get();
@@ -506,10 +502,6 @@ public:
 
     static void destroy(JSCell*);
 
-#if ENABLE(JIT)
-    void jettisonOptimizedCode(VM&);
-#endif
-
     ProgramCodeBlock* codeBlock()
     {
         return m_programCodeBlock.get();
@@ -581,10 +573,6 @@ public:
         return m_codeBlockForConstruct.get();
     }
         
-#if ENABLE(JIT)
-    void jettisonOptimizedCodeForCall(VM&);
-#endif
-
     bool isGeneratedForCall() const
     {
         return m_codeBlockForCall;
@@ -595,10 +583,6 @@ public:
         return m_codeBlockForCall.get();
     }
 
-#if ENABLE(JIT)
-    void jettisonOptimizedCodeForConstruct(VM&);
-#endif
-
     bool isGeneratedForConstruct() const
     {
         return m_codeBlockForConstruct;
@@ -609,18 +593,6 @@ public:
         return m_codeBlockForConstruct.get();
     }
         
-#if ENABLE(JIT)
-    void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
-    {
-        if (kind == CodeForCall) 
-            jettisonOptimizedCodeForCall(vm);
-        else {
-            ASSERT(kind == CodeForConstruct);
-            jettisonOptimizedCodeForConstruct(vm);
-        }
-    }
-#endif
-        
     bool isGeneratedFor(CodeSpecializationKind kind)
     {
         if (kind == CodeForCall)
index 8604a11..cf49a66 100644 (file)
@@ -274,17 +274,6 @@ namespace JSC {
         NumericStrings numericStrings;
         DateInstanceCache dateInstanceCache;
         WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT;
-        Vector<CodeBlock*> codeBlocksBeingCompiled;
-        void startedCompiling(CodeBlock* codeBlock)
-        {
-            codeBlocksBeingCompiled.append(codeBlock);
-        }
-
-        void finishedCompiling(CodeBlock* codeBlock)
-        {
-            ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last());
-            codeBlocksBeingCompiled.removeLast();
-        }
 
         void setInDefineOwnProperty(bool inDefineOwnProperty)
         {