It should be possible to jettison JIT stub routines even if they are currently running
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2012 23:26:54 +0000 (23:26 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2012 23:26:54 +0000 (23:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=90731

Reviewed by Gavin Barraclough.

This gives the GC awareness of all JIT-generated stubs for inline caches. That
means that if you want to delete a JIT-generated stub, you don't have to worry
about whether or not it is currently running: if there is a chance that it might
be, the GC will kindly defer deletion until non-running-ness is proved.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/Instruction.h:
(JSC):
(PolymorphicStubInfo):
(JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
(JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
* bytecode/PolymorphicPutByIdList.cpp:
(JSC::PutByIdAccess::fromStructureStubInfo):
* bytecode/PolymorphicPutByIdList.h:
(JSC::PutByIdAccess::transition):
(JSC::PutByIdAccess::replace):
(JSC::PutByIdAccess::stubRoutine):
(PutByIdAccess):
(JSC::PolymorphicPutByIdList::currentSlowPathTarget):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::reset):
* dfg/DFGRepatch.cpp:
(JSC::DFG::generateProtoChainAccessStub):
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDList):
(JSC::DFG::tryBuildGetByIDProtoList):
(JSC::DFG::emitPutReplaceStub):
(JSC::DFG::emitPutTransitionStub):
(JSC::DFG::tryCachePutByID):
(JSC::DFG::tryBuildPutByIdList):
* heap/ConservativeRoots.cpp:
(JSC):
(DummyMarkHook):
(JSC::DummyMarkHook::mark):
(JSC::ConservativeRoots::add):
(CompositeMarkHook):
(JSC::CompositeMarkHook::CompositeMarkHook):
(JSC::CompositeMarkHook::mark):
* heap/ConservativeRoots.h:
(JSC):
(ConservativeRoots):
* heap/Heap.cpp:
(JSC::Heap::markRoots):
(JSC::Heap::deleteUnmarkedCompiledCode):
* heap/Heap.h:
(JSC):
(Heap):
* heap/JITStubRoutineSet.cpp: Added.
(JSC):
(JSC::JITStubRoutineSet::JITStubRoutineSet):
(JSC::JITStubRoutineSet::~JITStubRoutineSet):
(JSC::JITStubRoutineSet::add):
(JSC::JITStubRoutineSet::clearMarks):
(JSC::JITStubRoutineSet::markSlow):
(JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines):
(JSC::JITStubRoutineSet::traceMarkedStubRoutines):
* heap/JITStubRoutineSet.h: Added.
(JSC):
(JITStubRoutineSet):
(JSC::JITStubRoutineSet::mark):
* heap/MachineStackMarker.h:
(JSC):
* interpreter/RegisterFile.cpp:
(JSC::RegisterFile::gatherConservativeRoots):
* interpreter/RegisterFile.h:
(JSC):
* jit/ExecutableAllocator.cpp:
(JSC::DemandExecutableAllocator::DemandExecutableAllocator):
* jit/ExecutableAllocator.h:
(JSC):
* jit/ExecutableAllocatorFixedVMPool.cpp:
(JSC):
(JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator):
* jit/GCAwareJITStubRoutine.cpp: Added.
(JSC):
(JSC::GCAwareJITStubRoutine::GCAwareJITStubRoutine):
(JSC::GCAwareJITStubRoutine::~GCAwareJITStubRoutine):
(JSC::GCAwareJITStubRoutine::observeZeroRefCount):
(JSC::GCAwareJITStubRoutine::deleteFromGC):
(JSC::GCAwareJITStubRoutine::markRequiredObjectsInternal):
(JSC::MarkingGCAwareJITStubRoutineWithOneObject::MarkingGCAwareJITStubRoutineWithOneObject):
(JSC::MarkingGCAwareJITStubRoutineWithOneObject::~MarkingGCAwareJITStubRoutineWithOneObject):
(JSC::MarkingGCAwareJITStubRoutineWithOneObject::markRequiredObjectsInternal):
(JSC::createJITStubRoutine):
* jit/GCAwareJITStubRoutine.h: Added.
(JSC):
(GCAwareJITStubRoutine):
(JSC::GCAwareJITStubRoutine::markRequiredObjects):
(MarkingGCAwareJITStubRoutineWithOneObject):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::privateCompilePutByIdTransition):
(JSC::JIT::privateCompilePatchGetArrayLength):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::privateCompilePutByIdTransition):
(JSC::JIT::privateCompilePatchGetArrayLength):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):
* jit/JITStubRoutine.cpp: Added.
(JSC):
(JSC::JITStubRoutine::~JITStubRoutine):
(JSC::JITStubRoutine::observeZeroRefCount):
* jit/JITStubRoutine.h: Added.
(JSC):
(JITStubRoutine):
(JSC::JITStubRoutine::JITStubRoutine):
(JSC::JITStubRoutine::createSelfManagedRoutine):
(JSC::JITStubRoutine::code):
(JSC::JITStubRoutine::asCodePtr):
(JSC::JITStubRoutine::ref):
(JSC::JITStubRoutine::deref):
(JSC::JITStubRoutine::startAddress):
(JSC::JITStubRoutine::endAddress):
(JSC::JITStubRoutine::addressStep):
(JSC::JITStubRoutine::canPerformRangeFilter):
(JSC::JITStubRoutine::filteringStartAddress):
(JSC::JITStubRoutine::filteringExtentSize):
(JSC::JITStubRoutine::passesFilter):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
(JSC::getPolymorphicAccessStructureListSlot):

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

31 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/bytecode/Instruction.h
Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp
Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h
Source/JavaScriptCore/bytecode/StructureStubInfo.h
Source/JavaScriptCore/dfg/DFGRepatch.cpp
Source/JavaScriptCore/heap/ConservativeRoots.cpp
Source/JavaScriptCore/heap/ConservativeRoots.h
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/JITStubRoutineSet.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/JITStubRoutineSet.h [new file with mode: 0644]
Source/JavaScriptCore/heap/MachineStackMarker.h
Source/JavaScriptCore/interpreter/RegisterFile.cpp
Source/JavaScriptCore/interpreter/RegisterFile.h
Source/JavaScriptCore/jit/ExecutableAllocator.cpp
Source/JavaScriptCore/jit/ExecutableAllocator.h
Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp [new file with mode: 0644]
Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h [new file with mode: 0644]
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
Source/JavaScriptCore/jit/JITStubRoutine.cpp [new file with mode: 0644]
Source/JavaScriptCore/jit/JITStubRoutine.h [new file with mode: 0644]
Source/JavaScriptCore/jit/JITStubs.cpp
Source/WTF/wtf/MetaAllocatorHandle.h

index a5a6ed8..412be29 100644 (file)
@@ -109,6 +109,7 @@ SET(JavaScriptCore_SOURCES
     heap/Heap.cpp
     heap/HeapTimer.cpp
     heap/IncrementalSweeper.cpp
+    heap/JITStubRoutineSet.cpp
     heap/MachineStackMarker.cpp
     heap/MarkedAllocator.cpp
     heap/MarkedBlock.cpp
@@ -129,6 +130,7 @@ SET(JavaScriptCore_SOURCES
 
     jit/ExecutableAllocator.cpp
     jit/HostCallReturnValue.cpp
+    jit/GCAwareJITStubRoutine.cpp
     jit/JITArithmetic32_64.cpp
     jit/JITArithmetic.cpp
     jit/JITCall32_64.cpp
@@ -139,6 +141,7 @@ SET(JavaScriptCore_SOURCES
     jit/JITOpcodes.cpp
     jit/JITPropertyAccess32_64.cpp
     jit/JITPropertyAccess.cpp
+    jit/JITStubRoutine.cpp
     jit/JITStubs.cpp
     jit/ThunkGenerators.cpp
 
index 32671d2..61814ec 100644 (file)
@@ -1,3 +1,143 @@
+2012-07-09  Filip Pizlo  <fpizlo@apple.com>
+
+        It should be possible to jettison JIT stub routines even if they are currently running
+        https://bugs.webkit.org/show_bug.cgi?id=90731
+
+        Reviewed by Gavin Barraclough.
+        
+        This gives the GC awareness of all JIT-generated stubs for inline caches. That
+        means that if you want to delete a JIT-generated stub, you don't have to worry
+        about whether or not it is currently running: if there is a chance that it might
+        be, the GC will kindly defer deletion until non-running-ness is proved.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * bytecode/Instruction.h:
+        (JSC):
+        (PolymorphicStubInfo):
+        (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
+        (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
+        * bytecode/PolymorphicPutByIdList.cpp:
+        (JSC::PutByIdAccess::fromStructureStubInfo):
+        * bytecode/PolymorphicPutByIdList.h:
+        (JSC::PutByIdAccess::transition):
+        (JSC::PutByIdAccess::replace):
+        (JSC::PutByIdAccess::stubRoutine):
+        (PutByIdAccess):
+        (JSC::PolymorphicPutByIdList::currentSlowPathTarget):
+        * bytecode/StructureStubInfo.h:
+        (JSC::StructureStubInfo::reset):
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::generateProtoChainAccessStub):
+        (JSC::DFG::tryCacheGetByID):
+        (JSC::DFG::tryBuildGetByIDList):
+        (JSC::DFG::tryBuildGetByIDProtoList):
+        (JSC::DFG::emitPutReplaceStub):
+        (JSC::DFG::emitPutTransitionStub):
+        (JSC::DFG::tryCachePutByID):
+        (JSC::DFG::tryBuildPutByIdList):
+        * heap/ConservativeRoots.cpp:
+        (JSC):
+        (DummyMarkHook):
+        (JSC::DummyMarkHook::mark):
+        (JSC::ConservativeRoots::add):
+        (CompositeMarkHook):
+        (JSC::CompositeMarkHook::CompositeMarkHook):
+        (JSC::CompositeMarkHook::mark):
+        * heap/ConservativeRoots.h:
+        (JSC):
+        (ConservativeRoots):
+        * heap/Heap.cpp:
+        (JSC::Heap::markRoots):
+        (JSC::Heap::deleteUnmarkedCompiledCode):
+        * heap/Heap.h:
+        (JSC):
+        (Heap):
+        * heap/JITStubRoutineSet.cpp: Added.
+        (JSC):
+        (JSC::JITStubRoutineSet::JITStubRoutineSet):
+        (JSC::JITStubRoutineSet::~JITStubRoutineSet):
+        (JSC::JITStubRoutineSet::add):
+        (JSC::JITStubRoutineSet::clearMarks):
+        (JSC::JITStubRoutineSet::markSlow):
+        (JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines):
+        (JSC::JITStubRoutineSet::traceMarkedStubRoutines):
+        * heap/JITStubRoutineSet.h: Added.
+        (JSC):
+        (JITStubRoutineSet):
+        (JSC::JITStubRoutineSet::mark):
+        * heap/MachineStackMarker.h:
+        (JSC):
+        * interpreter/RegisterFile.cpp:
+        (JSC::RegisterFile::gatherConservativeRoots):
+        * interpreter/RegisterFile.h:
+        (JSC):
+        * jit/ExecutableAllocator.cpp:
+        (JSC::DemandExecutableAllocator::DemandExecutableAllocator):
+        * jit/ExecutableAllocator.h:
+        (JSC):
+        * jit/ExecutableAllocatorFixedVMPool.cpp:
+        (JSC):
+        (JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator):
+        * jit/GCAwareJITStubRoutine.cpp: Added.
+        (JSC):
+        (JSC::GCAwareJITStubRoutine::GCAwareJITStubRoutine):
+        (JSC::GCAwareJITStubRoutine::~GCAwareJITStubRoutine):
+        (JSC::GCAwareJITStubRoutine::observeZeroRefCount):
+        (JSC::GCAwareJITStubRoutine::deleteFromGC):
+        (JSC::GCAwareJITStubRoutine::markRequiredObjectsInternal):
+        (JSC::MarkingGCAwareJITStubRoutineWithOneObject::MarkingGCAwareJITStubRoutineWithOneObject):
+        (JSC::MarkingGCAwareJITStubRoutineWithOneObject::~MarkingGCAwareJITStubRoutineWithOneObject):
+        (JSC::MarkingGCAwareJITStubRoutineWithOneObject::markRequiredObjectsInternal):
+        (JSC::createJITStubRoutine):
+        * jit/GCAwareJITStubRoutine.h: Added.
+        (JSC):
+        (GCAwareJITStubRoutine):
+        (JSC::GCAwareJITStubRoutine::markRequiredObjects):
+        (MarkingGCAwareJITStubRoutineWithOneObject):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::privateCompilePutByIdTransition):
+        (JSC::JIT::privateCompilePatchGetArrayLength):
+        (JSC::JIT::privateCompileGetByIdProto):
+        (JSC::JIT::privateCompileGetByIdSelfList):
+        (JSC::JIT::privateCompileGetByIdProtoList):
+        (JSC::JIT::privateCompileGetByIdChainList):
+        (JSC::JIT::privateCompileGetByIdChain):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::privateCompilePutByIdTransition):
+        (JSC::JIT::privateCompilePatchGetArrayLength):
+        (JSC::JIT::privateCompileGetByIdProto):
+        (JSC::JIT::privateCompileGetByIdSelfList):
+        (JSC::JIT::privateCompileGetByIdProtoList):
+        (JSC::JIT::privateCompileGetByIdChainList):
+        (JSC::JIT::privateCompileGetByIdChain):
+        * jit/JITStubRoutine.cpp: Added.
+        (JSC):
+        (JSC::JITStubRoutine::~JITStubRoutine):
+        (JSC::JITStubRoutine::observeZeroRefCount):
+        * jit/JITStubRoutine.h: Added.
+        (JSC):
+        (JITStubRoutine):
+        (JSC::JITStubRoutine::JITStubRoutine):
+        (JSC::JITStubRoutine::createSelfManagedRoutine):
+        (JSC::JITStubRoutine::code):
+        (JSC::JITStubRoutine::asCodePtr):
+        (JSC::JITStubRoutine::ref):
+        (JSC::JITStubRoutine::deref):
+        (JSC::JITStubRoutine::startAddress):
+        (JSC::JITStubRoutine::endAddress):
+        (JSC::JITStubRoutine::addressStep):
+        (JSC::JITStubRoutine::canPerformRangeFilter):
+        (JSC::JITStubRoutine::filteringStartAddress):
+        (JSC::JITStubRoutine::filteringExtentSize):
+        (JSC::JITStubRoutine::passesFilter):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        (JSC::getPolymorphicAccessStructureListSlot):
+
 2012-07-09  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r122107.
index 7619f64..7e6056e 100644 (file)
@@ -265,6 +265,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/heap/BlockAllocator.h \
        Source/JavaScriptCore/heap/Heap.cpp \
        Source/JavaScriptCore/heap/Heap.h \
+       Source/JavaScriptCore/heap/JITStubRoutineSet.cpp \
+       Source/JavaScriptCore/heap/JITStubRoutineSet.h \
        Source/JavaScriptCore/heap/ListableHandler.h \
        Source/JavaScriptCore/heap/Local.h \
        Source/JavaScriptCore/heap/LocalScope.h \
@@ -354,6 +356,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/jit/CompactJITCodeMap.h \
        Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
        Source/JavaScriptCore/jit/ExecutableAllocator.h \
+       Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp \
+       Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h \
        Source/JavaScriptCore/jit/HostCallReturnValue.cpp \
        Source/JavaScriptCore/jit/HostCallReturnValue.h \
        Source/JavaScriptCore/jit/JITArithmetic32_64.cpp \
@@ -373,6 +377,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp \
        Source/JavaScriptCore/jit/JITPropertyAccess.cpp \
        Source/JavaScriptCore/jit/JITStubCall.h \
+       Source/JavaScriptCore/jit/JITStubRoutine.cpp \
+       Source/JavaScriptCore/jit/JITStubRoutine.h \
        Source/JavaScriptCore/jit/JITStubs.cpp \
        Source/JavaScriptCore/jit/JITStubs.h \
        Source/JavaScriptCore/jit/JITWriteBarrier.h \
index a0e32f8..92749eb 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\..\jit\GCAwareJITStubRoutine.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\jit\GCAwareJITStubRoutine.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\jit\JIT.cpp"
                                >
                        </File>
                                >
                        </File>
                        <File
+                               RelativePath="..\..\jit\JITStubRoutine.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\jit\JITStubRoutine.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\jit\JITStubs.cpp"
                                >
                        </File>
                                >
                        </File>
                        <File
+                               RelativePath="..\..\heap\JITStubRoutineSet.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\heap\JITStubRoutineSet.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\heap\IncrementalSweeper.h"
                                >
                        </File>
index 12a310d..188c1ff 100644 (file)
                0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; };
                0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F766D2815A8CC1E008F363E /* JITStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */; };
+               0F766D2B15A8CC38008F363E /* JITStubRoutineSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */; };
+               0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2A15A8CC34008F363E /* JITStubRoutineSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D2D15A8DCDD008F363E /* GCAwareJITStubRoutine.cpp */; };
+               0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D1C15A5028D008F363E /* JITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
                0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; };
                0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; };
                0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; };
+               0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; };
+               0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutine.cpp; sourceTree = "<group>"; };
+               0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutineSet.cpp; sourceTree = "<group>"; };
+               0F766D2A15A8CC34008F363E /* JITStubRoutineSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutineSet.h; sourceTree = "<group>"; };
+               0F766D2D15A8DCDD008F363E /* GCAwareJITStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCAwareJITStubRoutine.cpp; sourceTree = "<group>"; };
+               0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCAwareJITStubRoutine.h; sourceTree = "<group>"; };
                0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
                0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
                0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCCallHelpers.h; path = dfg/DFGCCallHelpers.h; sourceTree = "<group>"; };
                                A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */,
                                A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */,
                                86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */,
+                               0F766D2D15A8DCDD008F363E /* GCAwareJITStubRoutine.cpp */,
+                               0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */,
                                0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
                                0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
                                1429D92D0ED22D7000B89619 /* JIT.cpp */,
                                86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */,
                                A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */,
                                960626950FB8EC02009798AB /* JITStubCall.h */,
+                               0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */,
+                               0F766D1C15A5028D008F363E /* JITStubRoutine.h */,
                                14A23D6C0F4E19CE0023CDAD /* JITStubs.cpp */,
                                14A6581A0F4E36F4000150FD /* JITStubs.h */,
                                A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */,
                                14BA7A9613AADFF8005B7C2C /* Heap.h */,
                                C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */,
                                14F97446138C853E00DA1C67 /* HeapRootVisitor.h */,
+                               0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */,
+                               0F766D2A15A8CC34008F363E /* JITStubRoutineSet.h */,
                                0F431736146BAC65007E3890 /* ListableHandler.h */,
                                142E3130134FF0A600AFADB5 /* Local.h */,
                                142E3131134FF0A600AFADB5 /* LocalScope.h */,
                                0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */,
                                0FF42772159275D8004CB9FF /* ResolveGlobalStatus.h in Headers */,
                                0FF7168C15A3B235008F5DAA /* PropertyOffset.h in Headers */,
+                               0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */,
+                               0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */,
+                               0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */,
                                0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */,
                                0FF42771159275D5004CB9FF /* ResolveGlobalStatus.cpp in Sources */,
+                               0F766D2815A8CC1E008F363E /* JITStubRoutine.cpp in Sources */,
+                               0F766D2B15A8CC38008F363E /* JITStubRoutineSet.cpp in Sources */,
+                               0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 81a1a79..b019e41 100644 (file)
@@ -83,6 +83,7 @@ SOURCES += \
     heap/Heap.cpp \
     heap/HeapTimer.cpp \
     heap/IncrementalSweeper.cpp \
+    heap/JITStubRoutineSet.cpp \
     heap/MachineStackMarker.cpp \
     heap/MarkStack.cpp \
     heap/MarkedAllocator.cpp \
@@ -137,6 +138,7 @@ SOURCES += \
     jit/ExecutableAllocatorFixedVMPool.cpp \
     jit/ExecutableAllocator.cpp \
     jit/HostCallReturnValue.cpp \
+    jit/GCAwareJITStubRoutine.cpp \
     jit/JITArithmetic.cpp \
     jit/JITArithmetic32_64.cpp \
     jit/JITCall.cpp \
@@ -147,6 +149,7 @@ SOURCES += \
     jit/JITOpcodes32_64.cpp \
     jit/JITPropertyAccess.cpp \
     jit/JITPropertyAccess32_64.cpp \
+    jit/JITStubRoutine.cpp \
     jit/JITStubs.cpp \
     jit/ThunkGenerators.cpp \
     parser/Lexer.cpp \
index 6e76512..2e94b45 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef Instruction_h
 #define Instruction_h
 
+#include "JITStubRoutine.h"
 #include "MacroAssembler.h"
 #include "Opcode.h"
 #include "PropertySlot.h"
@@ -52,8 +53,6 @@ namespace JSC {
     struct ValueProfile;
 
 #if ENABLE(JIT)
-    typedef MacroAssemblerCodeRef PolymorphicAccessStructureListStubRoutineType;
-
     // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream.
     struct PolymorphicAccessStructureList {
         WTF_MAKE_FAST_ALLOCATED;
@@ -61,7 +60,7 @@ namespace JSC {
         struct PolymorphicStubInfo {
             bool isChain;
             bool isDirect;
-            PolymorphicAccessStructureListStubRoutineType stubRoutine;
+            RefPtr<JITStubRoutine> stubRoutine;
             WriteBarrier<Structure> base;
             union {
                 WriteBarrierBase<Structure> proto;
@@ -73,7 +72,7 @@ namespace JSC {
                 u.proto.clear();
             }
 
-            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, bool isDirect)
+            void set(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> _stubRoutine, Structure* _base, bool isDirect)
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
@@ -82,7 +81,7 @@ namespace JSC {
                 this->isDirect = isDirect;
             }
             
-            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto, bool isDirect)
+            void set(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> _stubRoutine, Structure* _base, Structure* _proto, bool isDirect)
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
@@ -91,7 +90,7 @@ namespace JSC {
                 this->isDirect = isDirect;
             }
             
-            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain, bool isDirect)
+            void set(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> _stubRoutine, Structure* _base, StructureChain* _chain, bool isDirect)
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
@@ -105,17 +104,17 @@ namespace JSC {
         {
         }
         
-        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, bool isDirect)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> stubRoutine, Structure* firstBase, bool isDirect)
         {
             list[0].set(globalData, owner, stubRoutine, firstBase, isDirect);
         }
 
-        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto, bool isDirect)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> stubRoutine, Structure* firstBase, Structure* firstProto, bool isDirect)
         {
             list[0].set(globalData, owner, stubRoutine, firstBase, firstProto, isDirect);
         }
 
-        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain, bool isDirect)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> stubRoutine, Structure* firstBase, StructureChain* firstChain, bool isDirect)
         {
             list[0].set(globalData, owner, stubRoutine, firstBase, firstChain, isDirect);
         }
index 170615b..3a87567 100644 (file)
@@ -42,7 +42,7 @@ PutByIdAccess PutByIdAccess::fromStructureStubInfo(
     case access_put_by_id_replace:
         result.m_type = Replace;
         result.m_oldStructure.copyFrom(stubInfo.u.putByIdReplace.baseObjectStructure);
-        result.m_stubRoutine = MacroAssemblerCodeRef::createSelfManagedCodeRef(initialSlowPath);
+        result.m_stubRoutine = JITStubRoutine::createSelfManagedRoutine(initialSlowPath);
         break;
         
     case access_put_by_id_transition_direct:
index 60b632d..4a20b6d 100644 (file)
@@ -60,7 +60,7 @@ public:
         Structure* oldStructure,
         Structure* newStructure,
         StructureChain* chain,
-        MacroAssemblerCodeRef stubRoutine)
+        PassRefPtr<JITStubRoutine> stubRoutine)
     {
         PutByIdAccess result;
         result.m_type = Transition;
@@ -75,7 +75,7 @@ public:
         JSGlobalData& globalData,
         JSCell* owner,
         Structure* structure,
-        MacroAssemblerCodeRef stubRoutine)
+        PassRefPtr<JITStubRoutine> stubRoutine)
     {
         PutByIdAccess result;
         result.m_type = Replace;
@@ -123,7 +123,7 @@ public:
         return m_chain.get();
     }
     
-    MacroAssemblerCodeRef stubRoutine() const
+    PassRefPtr<JITStubRoutine> stubRoutine() const
     {
         ASSERT(isTransition() || isReplace());
         return m_stubRoutine;
@@ -136,7 +136,7 @@ private:
     WriteBarrier<Structure> m_oldStructure;
     WriteBarrier<Structure> m_newStructure;
     WriteBarrier<StructureChain> m_chain;
-    MacroAssemblerCodeRef m_stubRoutine;
+    RefPtr<JITStubRoutine> m_stubRoutine;
 };
 
 class PolymorphicPutByIdList {
@@ -161,7 +161,7 @@ public:
     
     MacroAssemblerCodePtr currentSlowPathTarget() const
     {
-        return m_list.last().stubRoutine().code();
+        return m_list.last().stubRoutine()->code().code();
     }
     
     void addAccess(const PutByIdAccess&);
index 2ed0e4a..807966c 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "CodeOrigin.h"
 #include "Instruction.h"
+#include "JITStubRoutine.h"
 #include "MacroAssembler.h"
 #include "Opcode.h"
 #include "Structure.h"
@@ -168,7 +169,7 @@ namespace JSC {
         {
             deref();
             accessType = access_unset;
-            stubRoutine = MacroAssemblerCodeRef();
+            stubRoutine.clear();
         }
 
         void deref();
@@ -286,7 +287,7 @@ namespace JSC {
             } putByIdList;
         } u;
 
-        MacroAssemblerCodeRef stubRoutine;
+        RefPtr<JITStubRoutine> stubRoutine;
         CodeLocationCall callReturnLocation;
         CodeLocationLabel hotPathBegin;
     };
index 060e5fc..752316f 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "DFGCCallHelpers.h"
 #include "DFGSpeculativeJIT.h"
+#include "GCAwareJITStubRoutine.h"
 #include "LinkBuffer.h"
 #include "Operations.h"
 #include "PolymorphicPutByIdList.h"
@@ -106,7 +107,7 @@ static void linkRestoreScratch(LinkBuffer& patchBuffer, bool needToRestoreScratc
     linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase));
 }
 
-static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stubInfo, StructureChain* chain, size_t count, PropertyOffset offset, Structure* structure, CodeLocationLabel successLabel, CodeLocationLabel slowCaseLabel, MacroAssemblerCodeRef& stubRoutine)
+static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stubInfo, StructureChain* chain, size_t count, PropertyOffset offset, Structure* structure, CodeLocationLabel successLabel, CodeLocationLabel slowCaseLabel, RefPtr<JITStubRoutine>& stubRoutine)
 {
     JSGlobalData* globalData = &exec->globalData();
 
@@ -166,7 +167,7 @@ static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stu
     
     linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
     
-    stubRoutine = FINALIZE_CODE(
+    stubRoutine = FINALIZE_CODE_FOR_STUB(
         patchBuffer,
         ("DFG prototype chain access stub for CodeBlock %p, return point %p",
          exec->codeBlock(), successLabel.executableAddress()));
@@ -220,14 +221,14 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
         
         linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCases);
         
-        stubInfo.stubRoutine = FINALIZE_CODE(
+        stubInfo.stubRoutine = FINALIZE_CODE_FOR_STUB(
             patchBuffer,
             ("DFG GetById array length stub for CodeBlock %p, return point %p",
              exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
                  stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
         
         RepatchBuffer repatchBuffer(codeBlock);
-        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
+        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine->code().code()));
         repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById);
         
         return true;
@@ -276,7 +277,7 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
     generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase), stubInfo.stubRoutine);
     
     RepatchBuffer repatchBuffer(codeBlock);
-    repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
+    repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine->code().code()));
     repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdProtoBuildList);
     
     stubInfo.initGetByIdChain(*globalData, codeBlock->ownerExecutable(), structure, prototypeChain, count, true);
@@ -323,7 +324,7 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
         listIndex = 0;
     } else if (stubInfo.accessType == access_get_by_id_self) {
         ASSERT(!stubInfo.stubRoutine);
-        polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), MacroAssemblerCodeRef::createSelfManagedCodeRef(stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true);
+        polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), JITStubRoutine::createSelfManagedRoutine(stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true);
         stubInfo.initGetByIdSelfList(polymorphicStructureList, 1);
         listIndex = 1;
     } else {
@@ -433,7 +434,7 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
         
         CodeLocationLabel lastProtoBegin;
         if (listIndex)
-            lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine.code());
+            lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine->code().code());
         else
             lastProtoBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase);
         ASSERT(!!lastProtoBegin);
@@ -445,17 +446,23 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
             patchBuffer.link(handlerCall, lookupExceptionHandlerInStub);
         }
         
-        MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
-            patchBuffer,
-            ("DFG GetById polymorphic list access for CodeBlock %p, return point %p",
-             exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
-                 stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
+        RefPtr<JITStubRoutine> stubRoutine =
+            createJITStubRoutine(
+                FINALIZE_CODE(
+                    patchBuffer,
+                    ("DFG GetById polymorphic list access for CodeBlock %p, return point %p",
+                     exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+                         stubInfo.patch.dfg.deltaCallToDone).executableAddress())),
+                *globalData,
+                codeBlock->ownerExecutable(),
+                slot.cachedPropertyType() == PropertySlot::Getter
+                || slot.cachedPropertyType() == PropertySlot::Custom);
         
         polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
         
         CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck);
         RepatchBuffer repatchBuffer(codeBlock);
-        repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+        repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
         
         if (listIndex < (POLYMORPHIC_LIST_CACHE_SIZE - 1))
             return true;
@@ -499,7 +506,7 @@ static bool tryBuildGetByIDProtoList(ExecState* exec, JSValue baseValue, const I
     if (stubInfo.accessType == access_get_by_id_chain) {
         ASSERT(!!stubInfo.stubRoutine);
         polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), stubInfo.stubRoutine, stubInfo.u.getByIdChain.baseObjectStructure.get(), stubInfo.u.getByIdChain.chain.get(), true);
-        stubInfo.stubRoutine = MacroAssemblerCodeRef();
+        stubInfo.stubRoutine.clear();
         stubInfo.initGetByIdProtoList(polymorphicStructureList, 1);
     } else {
         ASSERT(stubInfo.accessType == access_get_by_id_proto_list);
@@ -510,10 +517,10 @@ static bool tryBuildGetByIDProtoList(ExecState* exec, JSValue baseValue, const I
     if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
         stubInfo.u.getByIdProtoList.listSize++;
         
-        CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine.code());
+        CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine->code().code());
         ASSERT(!!lastProtoBegin);
 
-        MacroAssemblerCodeRef stubRoutine;
+        RefPtr<JITStubRoutine> stubRoutine;
         
         generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), lastProtoBegin, stubRoutine);
         
@@ -521,7 +528,7 @@ static bool tryBuildGetByIDProtoList(ExecState* exec, JSValue baseValue, const I
         
         CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck);
         RepatchBuffer repatchBuffer(codeBlock);
-        repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+        repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
         
         if (listIndex < (POLYMORPHIC_LIST_CACHE_SIZE - 1))
             return true;
@@ -581,7 +588,7 @@ static void emitPutReplaceStub(
     PutKind,
     Structure* structure,
     CodeLocationLabel failureLabel,
-    MacroAssemblerCodeRef& stubRoutine)
+    RefPtr<JITStubRoutine>& stubRoutine)
 {
     JSGlobalData* globalData = &exec->globalData();
     GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR);
@@ -655,7 +662,7 @@ static void emitPutReplaceStub(
     patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
     patchBuffer.link(failure, failureLabel);
             
-    stubRoutine = FINALIZE_CODE(
+    stubRoutine = FINALIZE_CODE_FOR_STUB(
         patchBuffer,
         ("DFG PutById replace stub for CodeBlock %p, return point %p",
          exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
@@ -673,7 +680,7 @@ static void emitPutTransitionStub(
     Structure* oldStructure,
     StructureChain* prototypeChain,
     CodeLocationLabel failureLabel,
-    MacroAssemblerCodeRef& stubRoutine)
+    RefPtr<JITStubRoutine>& stubRoutine)
 {
     JSGlobalData* globalData = &exec->globalData();
 
@@ -754,8 +761,8 @@ static void emitPutTransitionStub(
         patchBuffer.link(failure, failureLabel);
     else
         patchBuffer.link(failureCases, failureLabel);
-            
-    stubRoutine = FINALIZE_CODE(
+    
+    stubRoutine = FINALIZE_CODE_FOR_STUB(
         patchBuffer,
         ("DFG PutById transition stub for CodeBlock %p, return point %p",
          exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
@@ -799,7 +806,7 @@ static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier
                 stubInfo.stubRoutine);
             
             RepatchBuffer repatchBuffer(codeBlock);
-            repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
+            repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine->code().code()));
             repatchBuffer.relink(stubInfo.callReturnLocation, appropriateListBuildingPutByIdFunction(slot, putKind));
             
             stubInfo.initPutByIdTransition(*globalData, codeBlock->ownerExecutable(), oldStructure, structure, prototypeChain, putKind == Direct);
@@ -841,7 +848,7 @@ static bool tryBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identi
     // Optimize self access.
     if (slot.base() == baseValue) {
         PolymorphicPutByIdList* list;
-        MacroAssemblerCodeRef stubRoutine;
+        RefPtr<JITStubRoutine> stubRoutine;
         
         if (slot.type() == PutPropertySlot::NewProperty) {
             if (structure->isDictionary())
@@ -888,7 +895,7 @@ static bool tryBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identi
         }
         
         RepatchBuffer repatchBuffer(codeBlock);
-        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubRoutine.code()));
+        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubRoutine->code().code()));
         
         if (list->isFull())
             repatchBuffer.relink(stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind));
index d63faeb..6b9cbef 100644 (file)
@@ -62,11 +62,6 @@ void ConservativeRoots::grow()
     m_roots = newRoots;
 }
 
-class DummyMarkHook {
-public:
-    void mark(void*) { }
-};
-
 template<typename MarkHook>
 inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook)
 {
@@ -110,15 +105,48 @@ void ConservativeRoots::genericAddSpan(void* begin, void* end, MarkHook& markHoo
         genericAddPointer(*it, filter, markHook);
 }
 
+class DummyMarkHook {
+public:
+    void mark(void*) { }
+};
+
 void ConservativeRoots::add(void* begin, void* end)
 {
-    DummyMarkHook hook;
-    genericAddSpan(begin, end, hook);
+    DummyMarkHook dummy;
+    genericAddSpan(begin, end, dummy);
 }
 
-void ConservativeRoots::add(void* begin, void* end, DFGCodeBlocks& dfgCodeBlocks)
+void ConservativeRoots::add(void* begin, void* end, JITStubRoutineSet& jitStubRoutines)
+{
+    genericAddSpan(begin, end, jitStubRoutines);
+}
+
+template<typename T, typename U>
+class CompositeMarkHook {
+public:
+    CompositeMarkHook(T& first, U& second)
+        : m_first(first)
+        , m_second(second)
+    {
+    }
+    
+    void mark(void* address)
+    {
+        m_first.mark(address);
+        m_second.mark(address);
+    }
+
+private:
+    T& m_first;
+    U& m_second;
+};
+
+void ConservativeRoots::add(
+    void* begin, void* end, JITStubRoutineSet& jitStubRoutines, DFGCodeBlocks& dfgCodeBlocks)
 {
-    genericAddSpan(begin, end, dfgCodeBlocks);
+    CompositeMarkHook<JITStubRoutineSet, DFGCodeBlocks> markHook(
+        jitStubRoutines, dfgCodeBlocks);
+    genericAddSpan(begin, end, markHook);
 }
 
 } // namespace JSC
index 9d9e9ba..219bdcc 100644 (file)
 
 namespace JSC {
 
-class JSCell;
 class DFGCodeBlocks;
 class Heap;
+class JITStubRoutineSet;
+class JSCell;
 
 class ConservativeRoots {
 public:
@@ -42,7 +43,8 @@ public:
     ~ConservativeRoots();
 
     void add(void* begin, void* end);
-    void add(void* begin, void* end, DFGCodeBlocks&);
+    void add(void* begin, void* end, JITStubRoutineSet&);
+    void add(void* begin, void* end, JITStubRoutineSet&, DFGCodeBlocks&);
     
     size_t size();
     JSCell** roots();
index 450c3a5..3771327 100644 (file)
@@ -420,6 +420,7 @@ void Heap::markRoots(bool fullGC)
     // We gather conservative roots before clearing mark bits because conservative
     // gathering uses the mark bits to determine whether a reference is valid.
     ConservativeRoots machineThreadRoots(&m_objectSpace.blocks(), &m_storageSpace);
+    m_jitStubRoutines.clearMarks();
     {
         GCPHASE(GatherConservativeRoots);
         m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy);
@@ -429,7 +430,8 @@ void Heap::markRoots(bool fullGC)
     m_dfgCodeBlocks.clearMarks();
     {
         GCPHASE(GatherRegisterFileRoots);
-        registerFile().gatherConservativeRoots(registerFileRoots, m_dfgCodeBlocks);
+        registerFile().gatherConservativeRoots(
+            registerFileRoots, m_jitStubRoutines, m_dfgCodeBlocks);
     }
 
 #if ENABLE(DFG_JIT)
@@ -540,9 +542,10 @@ void Heap::markRoots(bool fullGC)
         }
     
         {
-            GCPHASE(TraceCodeBlocks);
-            MARK_LOG_ROOT(visitor, "Trace Code Blocks");
+            GCPHASE(TraceCodeBlocksAndJITStubRoutines);
+            MARK_LOG_ROOT(visitor, "Trace Code Blocks and JIT Stub Routines");
             m_dfgCodeBlocks.traceMarkedCodeBlocks(visitor);
+            m_jitStubRoutines.traceMarkedStubRoutines(visitor);
             visitor.donateAndDrain();
         }
     
@@ -665,6 +668,7 @@ void Heap::deleteUnmarkedCompiledCode()
     }
 
     m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+    m_jitStubRoutines.deleteUnmarkedJettisonedStubRoutines();
 }
 
 void Heap::collectAllGarbage()
index a559f92..a43be3d 100644 (file)
@@ -26,6 +26,7 @@
 #include "DFGCodeBlocks.h"
 #include "HandleSet.h"
 #include "HandleStack.h"
+#include "JITStubRoutineSet.h"
 #include "MarkedAllocator.h"
 #include "MarkedBlock.h"
 #include "MarkedBlockSet.h"
@@ -44,10 +45,12 @@ namespace JSC {
     class CodeBlock;
     class ExecutableBase;
     class GCActivityCallback;
+    class GCAwareJITStubRoutine;
     class GlobalCodeBlock;
     class Heap;
     class HeapRootVisitor;
     class IncrementalSweeper;
+    class JITStubRoutine;
     class JSCell;
     class JSGlobalData;
     class JSValue;
@@ -168,6 +171,8 @@ namespace JSC {
 
     private:
         friend class CodeBlock;
+        friend class GCAwareJITStubRoutine;
+        friend class JITStubRoutine;
         friend class LLIntOffsetsExtractor;
         friend class MarkedSpace;
         friend class MarkedAllocator;
@@ -229,6 +234,7 @@ namespace JSC {
         HandleSet m_handleSet;
         HandleStack m_handleStack;
         DFGCodeBlocks m_dfgCodeBlocks;
+        JITStubRoutineSet m_jitStubRoutines;
         FinalizerOwner m_finalizerOwner;
         
         bool m_isSafeToCollect;
diff --git a/Source/JavaScriptCore/heap/JITStubRoutineSet.cpp b/Source/JavaScriptCore/heap/JITStubRoutineSet.cpp
new file mode 100644 (file)
index 0000000..054bf06
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2012 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 "JITStubRoutineSet.h"
+
+#if ENABLE(JIT)
+
+#include "GCAwareJITStubRoutine.h"
+#include "ScopeChain.h"
+#include "SlotVisitor.h"
+
+namespace JSC {
+
+JITStubRoutineSet::JITStubRoutineSet() { }
+JITStubRoutineSet::~JITStubRoutineSet()
+{
+    for (size_t i = m_listOfRoutines.size(); i--;) {
+        GCAwareJITStubRoutine* routine = m_listOfRoutines[i];
+        
+        routine->m_mayBeExecuting = false;
+        
+        if (!routine->m_isJettisoned) {
+            // Inform the deref() routine that it should delete this guy as soon
+            // as the ref count reaches zero.
+            routine->m_isJettisoned = true;
+            continue;
+        }
+        
+        routine->deleteFromGC();
+    }
+}
+
+void JITStubRoutineSet::add(GCAwareJITStubRoutine* routine)
+{
+    ASSERT(!routine->m_isJettisoned);
+    
+    m_listOfRoutines.append(routine);
+    
+    uintptr_t start = routine->startAddress();
+    uintptr_t end = routine->endAddress();
+    uintptr_t step = JITStubRoutine::addressStep();
+    for (uintptr_t iter = start; iter < end; iter += step) {
+        ASSERT(m_addressToRoutineMap.find(iter) == m_addressToRoutineMap.end());
+        m_addressToRoutineMap.add(iter, routine);
+    }
+}
+
+void JITStubRoutineSet::clearMarks()
+{
+    for (size_t i = m_listOfRoutines.size(); i--;)
+        m_listOfRoutines[i]->m_mayBeExecuting = false;
+}
+
+void JITStubRoutineSet::markSlow(uintptr_t address)
+{
+    HashMap<uintptr_t, GCAwareJITStubRoutine*>::iterator iter =
+        m_addressToRoutineMap.find(address & ~(JITStubRoutine::addressStep() - 1));
+    
+    if (iter == m_addressToRoutineMap.end())
+        return;
+    
+    iter->second->m_mayBeExecuting = true;
+}
+
+void JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines()
+{
+    for (size_t i = 0; i < m_listOfRoutines.size(); i++) {
+        GCAwareJITStubRoutine* routine = m_listOfRoutines[i];
+        if (!routine->m_isJettisoned || routine->m_mayBeExecuting)
+            continue;
+        
+        uintptr_t start = routine->startAddress();
+        uintptr_t end = routine->endAddress();
+        uintptr_t step = JITStubRoutine::addressStep();
+        for (uintptr_t iter = start; iter < end; iter += step) {
+            ASSERT(m_addressToRoutineMap.find(iter) != m_addressToRoutineMap.end());
+            ASSERT(m_addressToRoutineMap.find(iter)->second == routine);
+            m_addressToRoutineMap.remove(iter);
+        }
+        
+        routine->deleteFromGC();
+        
+        m_listOfRoutines[i] = m_listOfRoutines.last();
+        m_listOfRoutines.removeLast();
+        i--;
+    }
+}
+
+void JITStubRoutineSet::traceMarkedStubRoutines(SlotVisitor& visitor)
+{
+    for (size_t i = m_listOfRoutines.size(); i--;) {
+        GCAwareJITStubRoutine* routine = m_listOfRoutines[i];
+        if (!routine->m_mayBeExecuting)
+            continue;
+        
+        routine->markRequiredObjects(visitor);
+    }
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
diff --git a/Source/JavaScriptCore/heap/JITStubRoutineSet.h b/Source/JavaScriptCore/heap/JITStubRoutineSet.h
new file mode 100644 (file)
index 0000000..ea12013
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 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 JITStubRoutineSet_h
+#define JITStubRoutineSet_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "JITStubRoutine.h"
+#include <wtf/FastAllocBase.h>
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class GCAwareJITStubRoutine;
+class SlotVisitor;
+
+class JITStubRoutineSet {
+    WTF_MAKE_NONCOPYABLE(JITStubRoutineSet);
+    WTF_MAKE_FAST_ALLOCATED;
+    
+public:
+    JITStubRoutineSet();
+    ~JITStubRoutineSet();
+    
+    void add(GCAwareJITStubRoutine*);
+
+    void clearMarks();
+    
+    void mark(void* candidateAddress)
+    {
+        uintptr_t address = reinterpret_cast<uintptr_t>(candidateAddress);
+        if (!JITStubRoutine::passesFilter(address))
+            return;
+        
+        markSlow(address);
+    }
+    
+    void deleteUnmarkedJettisonedStubRoutines();
+    
+    void traceMarkedStubRoutines(SlotVisitor&);
+    
+private:
+    void markSlow(uintptr_t address);
+    
+    HashMap<uintptr_t, GCAwareJITStubRoutine*> m_addressToRoutineMap;
+    Vector<GCAwareJITStubRoutine*> m_listOfRoutines;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // JITStubRoutineSet_h
+
index 0f5a4c3..5c7705f 100644 (file)
@@ -28,8 +28,8 @@
 
 namespace JSC {
 
-    class Heap;
     class ConservativeRoots;
+    class Heap;
 
     class MachineThreads {
         WTF_MAKE_NONCOPYABLE(MachineThreads);
index b723527..dacb538 100644 (file)
@@ -73,9 +73,9 @@ void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
     conservativeRoots.add(begin(), end());
 }
 
-void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots, DFGCodeBlocks& dfgCodeBlocks)
+void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, DFGCodeBlocks& dfgCodeBlocks)
 {
-    conservativeRoots.add(begin(), end(), dfgCodeBlocks);
+    conservativeRoots.add(begin(), end(), jitStubRoutines, dfgCodeBlocks);
 }
 
 void RegisterFile::releaseExcessCapacity()
index 21ad7fb..8fff820 100644 (file)
@@ -39,6 +39,7 @@ namespace JSC {
 
     class ConservativeRoots;
     class DFGCodeBlocks;
+    class JITStubRoutineSet;
     class LLIntOffsetsExtractor;
 
     class RegisterFile {
@@ -64,7 +65,7 @@ namespace JSC {
         ~RegisterFile();
         
         void gatherConservativeRoots(ConservativeRoots&);
-        void gatherConservativeRoots(ConservativeRoots&, DFGCodeBlocks&);
+        void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, DFGCodeBlocks&);
 
         Register* begin() const { return static_cast<Register*>(m_reservation.base()); }
         Register* end() const { return m_end; }
index 7939919..e9bb66c 100644 (file)
@@ -55,7 +55,7 @@ namespace JSC {
 class DemandExecutableAllocator : public MetaAllocator {
 public:
     DemandExecutableAllocator()
-        : MetaAllocator(32) // round up all allocations to 32 bytes
+        : MetaAllocator(jitAllocationGranule)
     {
         MutexLocker lock(allocatorsMutex());
         allocators().add(this);
index 8cd5cba..85779e6 100644 (file)
@@ -77,6 +77,8 @@ namespace JSC {
 class JSGlobalData;
 void releaseExecutableMemory(JSGlobalData&);
 
+static const unsigned jitAllocationGranule = 32;
+
 inline size_t roundUpAllocationSize(size_t request, size_t granularity)
 {
     if ((std::numeric_limits<size_t>::max() - granularity) <= request)
@@ -101,6 +103,18 @@ typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle;
 class DemandExecutableAllocator;
 #endif
 
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
+#if CPU(ARM)
+static const size_t fixedExecutableMemoryPoolSize = 16 * 1024 * 1024;
+#elif CPU(X86_64)
+static const size_t fixedExecutableMemoryPoolSize = 1024 * 1024 * 1024;
+#else
+static const size_t fixedExecutableMemoryPoolSize = 32 * 1024 * 1024;
+#endif
+
+extern uintptr_t startOfFixedExecutableMemoryPool;
+#endif
+
 class ExecutableAllocator {
     enum ProtectionSetting { Writable, Executable };
 
index 2e08f12..ad3343d 100644 (file)
@@ -45,27 +45,23 @@ using namespace WTF;
 
 namespace JSC {
     
-#if CPU(ARM)
-static const size_t fixedPoolSize = 16 * 1024 * 1024;
-#elif CPU(X86_64)
-static const size_t fixedPoolSize = 1024 * 1024 * 1024;
-#else
-static const size_t fixedPoolSize = 32 * 1024 * 1024;
-#endif
+uintptr_t startOfFixedExecutableMemoryPool;
 
 class FixedVMPoolExecutableAllocator : public MetaAllocator {
 public:
     FixedVMPoolExecutableAllocator()
-        : MetaAllocator(32) // round up all allocations to 32 bytes
+        : MetaAllocator(jitAllocationGranule) // round up all allocations to 32 bytes
     {
-        m_reservation = PageReservation::reserveWithGuardPages(fixedPoolSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+        m_reservation = PageReservation::reserveWithGuardPages(fixedExecutableMemoryPoolSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
 #if !(ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
         if (!m_reservation)
             CRASH();
 #endif
         if (m_reservation) {
-            ASSERT(m_reservation.size() == fixedPoolSize);
+            ASSERT(m_reservation.size() == fixedExecutableMemoryPoolSize);
             addFreshFreeSpace(m_reservation.base(), m_reservation.size());
+            
+            startOfFixedExecutableMemoryPool = reinterpret_cast<uintptr_t>(m_reservation.base());
         }
     }
     
diff --git a/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp b/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp
new file mode 100644 (file)
index 0000000..7ea6117
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2012 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 "GCAwareJITStubRoutine.h"
+
+#if ENABLE(JIT)
+
+#include "Heap.h"
+#include "JSGlobalData.h"
+#include "ScopeChain.h"
+#include "SlotVisitor.h"
+#include "Structure.h"
+
+namespace JSC {
+
+GCAwareJITStubRoutine::GCAwareJITStubRoutine(
+    const MacroAssemblerCodeRef& code, JSGlobalData& globalData)
+    : JITStubRoutine(code)
+    , m_mayBeExecuting(false)
+    , m_isJettisoned(false)
+{
+    globalData.heap.m_jitStubRoutines.add(this);
+}
+    
+GCAwareJITStubRoutine::~GCAwareJITStubRoutine() { }
+
+void GCAwareJITStubRoutine::observeZeroRefCount()
+{
+    if (m_isJettisoned) {
+        // This case is needed for when the system shuts down. It may be that
+        // the JIT stub routine set gets deleted before we get around to deleting
+        // this guy. In that case the GC informs us that we're jettisoned already
+        // and that we should delete ourselves as soon as the ref count reaches
+        // zero.
+        delete this;
+        return;
+    }
+    
+    ASSERT(!m_refCount);
+
+    m_isJettisoned = true;
+}
+
+void GCAwareJITStubRoutine::deleteFromGC()
+{
+    ASSERT(m_isJettisoned);
+    ASSERT(!m_refCount);
+    ASSERT(!m_mayBeExecuting);
+    
+    delete this;
+}
+
+void GCAwareJITStubRoutine::markRequiredObjectsInternal(SlotVisitor&)
+{
+}
+
+MarkingGCAwareJITStubRoutineWithOneObject::MarkingGCAwareJITStubRoutineWithOneObject(
+    const MacroAssemblerCodeRef& code, JSGlobalData& globalData, const JSCell* owner,
+    JSCell* object)
+    : GCAwareJITStubRoutine(code, globalData)
+    , m_object(globalData, owner, object)
+{
+}
+
+MarkingGCAwareJITStubRoutineWithOneObject::~MarkingGCAwareJITStubRoutineWithOneObject()
+{
+}
+
+void MarkingGCAwareJITStubRoutineWithOneObject::markRequiredObjectsInternal(SlotVisitor& visitor)
+{
+    visitor.append(&m_object);
+}
+
+PassRefPtr<JITStubRoutine> createJITStubRoutine(
+    const MacroAssemblerCodeRef& code,
+    JSGlobalData& globalData,
+    const JSCell*,
+    bool makesCalls)
+{
+    if (!makesCalls)
+        return adoptRef(new JITStubRoutine(code));
+
+    return static_pointer_cast<JITStubRoutine>(
+        adoptRef(new GCAwareJITStubRoutine(code, globalData)));
+}
+
+PassRefPtr<JITStubRoutine> createJITStubRoutine(
+    const MacroAssemblerCodeRef& code,
+    JSGlobalData& globalData,
+    const JSCell* owner,
+    bool makesCalls,
+    JSCell* object)
+{
+    if (!makesCalls)
+        return adoptRef(new JITStubRoutine(code));
+    
+    return static_pointer_cast<JITStubRoutine>(
+        adoptRef(new MarkingGCAwareJITStubRoutineWithOneObject(code, globalData, owner, object)));
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
diff --git a/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h b/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h
new file mode 100644 (file)
index 0000000..59bc76b
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2012 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 GCAwareJITStubRoutine_h
+#define GCAwareJITStubRoutine_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "JITStubRoutine.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "WriteBarrier.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class JITStubRoutineSet;
+
+// Use this stub routine if you know that your code might be on stack when
+// either GC or other kinds of stub deletion happen. Basicaly, if your stub
+// routine makes calls (either to JS code or to C++ code) then you should
+// assume that it's possible for that JS or C++ code to do something that
+// causes the system to try to delete your routine. Using this routine type
+// ensures that the actual deletion is delayed until the GC proves that the
+// routine is no longer running. You can also subclass this routine if you
+// want to mark additional objects during GC in those cases where the
+// routine is known to be executing, or if you want to force this routine to
+// keep other routines alive (for example due to the use of a slow-path
+// list which does not get reclaimed all at once).
+class GCAwareJITStubRoutine : public JITStubRoutine {
+public:
+    GCAwareJITStubRoutine(const MacroAssemblerCodeRef&, JSGlobalData&);
+    virtual ~GCAwareJITStubRoutine();
+    
+    void markRequiredObjects(SlotVisitor& visitor)
+    {
+        markRequiredObjectsInternal(visitor);
+    }
+    
+    void deleteFromGC();
+    
+protected:
+    virtual void observeZeroRefCount();
+    
+    virtual void markRequiredObjectsInternal(SlotVisitor&);
+
+private:
+    friend class JITStubRoutineSet;
+
+    bool m_mayBeExecuting;
+    bool m_isJettisoned;
+};
+
+// Use this if you want to mark one additional object during GC if your stub
+// routine is known to be executing.
+class MarkingGCAwareJITStubRoutineWithOneObject : public GCAwareJITStubRoutine {
+public:
+    MarkingGCAwareJITStubRoutineWithOneObject(
+        const MacroAssemblerCodeRef&, JSGlobalData&, const JSCell* owner, JSCell*);
+    virtual ~MarkingGCAwareJITStubRoutineWithOneObject();
+    
+protected:
+    virtual void markRequiredObjectsInternal(SlotVisitor&);
+
+private:
+    WriteBarrier<JSCell> m_object;
+};
+
+// Helper for easily creating a GC-aware JIT stub routine. For the varargs,
+// pass zero or more JSCell*'s. This will either create a JITStubRoutine, a
+// GCAwareJITStubRoutine, or an ObjectMarkingGCAwareJITStubRoutine as
+// appropriate. Generally you only need to pass pointers that will be used
+// after the first call to C++ or JS.
+// 
+// PassRefPtr<JITStubRoutine> createJITStubRoutine(
+//    const MacroAssemblerCodeRef& code,
+//    JSGlobalData& globalData,
+//    const JSCell* owner,
+//    bool makesCalls,
+//    ...);
+//
+// Note that we don't actually use C-style varargs because that leads to
+// strange type-related problems. For example it would preclude us from using
+// our custom of passing '0' as NULL pointer. Besides, when I did try to write
+// this function using varargs, I ended up with more code than this simple
+// way.
+
+PassRefPtr<JITStubRoutine> createJITStubRoutine(
+    const MacroAssemblerCodeRef&, JSGlobalData&, const JSCell* owner, bool makesCalls);
+PassRefPtr<JITStubRoutine> createJITStubRoutine(
+    const MacroAssemblerCodeRef&, JSGlobalData&, const JSCell* owner, bool makesCalls,
+    JSCell*);
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // GCAwareJITStubRoutine_h
+
index b682785..466cff7 100644 (file)
@@ -29,6 +29,7 @@
 #include "JIT.h"
 
 #include "CodeBlock.h"
+#include "GCAwareJITStubRoutine.h"
 #include "GetterSetter.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
@@ -595,12 +596,17 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
-    stubInfo->stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline put_by_id transition for CodeBlock %p, return point %p",
-         m_codeBlock, returnAddress.value()));
+    stubInfo->stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline put_by_id transition for CodeBlock %p, return point %p",
+             m_codeBlock, returnAddress.value())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        willNeedStorageRealloc,
+        newStructure);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
+    repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine->code().code()));
 }
 
 void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, PropertyOffset cachedOffset, ReturnAddressPtr returnAddress)
@@ -657,7 +663,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = FINALIZE_CODE(
+    stubInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
         patchBuffer,
         ("Basline JIT get_by_id array length stub for CodeBlock %p, return point %p",
          m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
@@ -666,7 +672,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine->code().code()));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
@@ -724,16 +730,20 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
         }
     }
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline JIT get_by_id proto stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    stubInfo->stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline JIT get_by_id proto stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine->code().code()));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
@@ -776,7 +786,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructures->list[currentIndex - 1].stubRoutine.code());
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(JITStubRoutine::asCodePtr(polymorphicStructures->list[currentIndex - 1].stubRoutine));
     if (!lastProtoBegin)
         lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
 
@@ -785,18 +795,22 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    MacroAssemblerCodeRef stubCode = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline JIT get_by_id list stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubCode = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline JIT get_by_id list stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
 
     polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, isDirect);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode->code().code()));
 }
 
 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, CallFrame* callFrame)
@@ -848,24 +862,28 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(JITStubRoutine::asCodePtr(prototypeStructures->list[currentIndex - 1].stubRoutine));
     patchBuffer.link(failureCases1, lastProtoBegin);
     patchBuffer.link(failureCases2, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    MacroAssemblerCodeRef stubCode = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline JIT get_by_id proto list stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubCode = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline JIT get_by_id proto list stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
     prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, prototypeStructure, isDirect);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode->code().code()));
 }
 
 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, CallFrame* callFrame)
@@ -921,18 +939,22 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(JITStubRoutine::asCodePtr(prototypeStructures->list[currentIndex - 1].stubRoutine));
 
     patchBuffer.link(bucketsOfFail, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    CodeRef stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline JIT get_by_id chain list stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline JIT get_by_id chain list stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
 
     // Track the stub we have created so that it will be deleted later.
     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
@@ -940,7 +962,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
 }
 
 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
@@ -999,17 +1021,21 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     // Track the stub we have created so that it will be deleted later.
-    CodeRef stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline JIT get_by_id chain stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline JIT get_by_id chain stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
     stubInfo->stubRoutine = stubRoutine;
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
index 799e958..84996d9 100644 (file)
@@ -30,6 +30,7 @@
 #include "JIT.h"
 
 #include "CodeBlock.h"
+#include "GCAwareJITStubRoutine.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
@@ -557,12 +558,17 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
-    stubInfo->stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline put_by_id transition stub for CodeBlock %p, return point %p",
-         m_codeBlock, returnAddress.value()));
+    stubInfo->stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline put_by_id transition stub for CodeBlock %p, return point %p",
+             m_codeBlock, returnAddress.value())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        willNeedStorageRealloc,
+        newStructure);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
+    repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine->code().code()));
 }
 
 void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, PropertyOffset cachedOffset, ReturnAddressPtr returnAddress)
@@ -624,7 +630,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = FINALIZE_CODE(
+    stubInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
         patchBuffer,
         ("Baseline get_by_id array length stub for CodeBlock %p, return point %p",
          m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
@@ -633,7 +639,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine->code().code()));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
@@ -694,16 +700,20 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     }
 
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline get_by_id proto stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    stubInfo->stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline get_by_id proto stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine->code().code()));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
@@ -747,7 +757,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
         }
     }    
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructures->list[currentIndex - 1].stubRoutine.code());
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(JITStubRoutine::asCodePtr(polymorphicStructures->list[currentIndex - 1].stubRoutine));
     if (!lastProtoBegin)
         lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
     
@@ -756,18 +766,22 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline get_by_id self list stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline get_by_id self list stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
 
     polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
 }
 
 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, CallFrame* callFrame)
@@ -818,25 +832,29 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(JITStubRoutine::asCodePtr(prototypeStructures->list[currentIndex - 1].stubRoutine));
     patchBuffer.link(failureCases1, lastProtoBegin);
     patchBuffer.link(failureCases2, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
-    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline get_by_id proto list stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline get_by_id proto list stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
 
     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, prototypeStructure, isDirect);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
 }
 
 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, CallFrame* callFrame)
@@ -892,18 +910,22 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(JITStubRoutine::asCodePtr(prototypeStructures->list[currentIndex - 1].stubRoutine));
     
     patchBuffer.link(bucketsOfFail, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
-    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline get_by_id chain list stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline get_by_id chain list stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
     
     // Track the stub we have created so that it will be deleted later.
     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
@@ -911,7 +933,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
 }
 
 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
@@ -969,17 +991,21 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     // Track the stub we have created so that it will be deleted later.
-    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
-        patchBuffer,
-        ("Baseline get_by_id chain stub for CodeBlock %p, return point %p",
-         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
-             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
+    RefPtr<JITStubRoutine> stubRoutine = createJITStubRoutine(
+        FINALIZE_CODE(
+            patchBuffer,
+            ("Baseline get_by_id chain stub for CodeBlock %p, return point %p",
+             m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+                 stubInfo->patch.baseline.u.get.putResult).executableAddress())),
+        *m_globalData,
+        m_codeBlock->ownerExecutable(),
+        needsStubLink);
     stubInfo->stubRoutine = stubRoutine;
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine->code().code()));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
diff --git a/Source/JavaScriptCore/jit/JITStubRoutine.cpp b/Source/JavaScriptCore/jit/JITStubRoutine.cpp
new file mode 100644 (file)
index 0000000..9516653
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 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 "JITStubRoutine.h"
+
+#if ENABLE(JIT)
+
+#include "JSObject.h"
+#include "ScopeChain.h"
+#include "SlotVisitor.h"
+
+namespace JSC {
+
+JITStubRoutine::~JITStubRoutine() { }
+
+void JITStubRoutine::observeZeroRefCount()
+{
+    ASSERT(!m_refCount);
+    delete this;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
diff --git a/Source/JavaScriptCore/jit/JITStubRoutine.h b/Source/JavaScriptCore/jit/JITStubRoutine.h
new file mode 100644 (file)
index 0000000..4d54601
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2012 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 JITStubRoutine_h
+#define JITStubRoutine_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "ExecutableAllocator.h"
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class JITStubRoutineSet;
+
+// This is a base-class for JIT stub routines, and also the class you want
+// to instantiate directly if you have a routine that does not need any
+// help from the GC. If in doubt, use one of the other stub routines. But
+// if you know for sure that the stub routine cannot be on the stack while
+// someone triggers a stub routine reset, then using this will speed up
+// memory reclamation. One case where a stub routine satisfies this
+// condition is if it doesn't make any calls, to either C++ or JS code. In
+// such a routine you know that it cannot be on the stack when anything
+// interesting happens.
+// See GCAwareJITStubRoutine.h for the other stub routines.
+class JITStubRoutine {
+    WTF_MAKE_NONCOPYABLE(JITStubRoutine);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    JITStubRoutine(const MacroAssemblerCodeRef& code)
+        : m_code(code)
+        , m_refCount(1)
+    {
+    }
+    
+    // Use this if you want to pass a CodePtr to someone who insists on taking
+    // a RefPtr<JITStubRoutine>.
+    static PassRefPtr<JITStubRoutine> createSelfManagedRoutine(
+        MacroAssemblerCodePtr rawCodePointer)
+    {
+        return adoptRef(new JITStubRoutine(MacroAssemblerCodeRef::createSelfManagedCodeRef(rawCodePointer)));
+    }
+    
+    virtual ~JITStubRoutine();
+    
+    // MacroAssemblerCodeRef is copyable, but at the cost of reference
+    // counting churn. Returning a reference is a good way of reducing
+    // the churn.
+    const MacroAssemblerCodeRef& code() const { return m_code; }
+    
+    static MacroAssemblerCodePtr asCodePtr(PassRefPtr<JITStubRoutine> stubRoutine)
+    {
+        if (!stubRoutine)
+            return MacroAssemblerCodePtr();
+        
+        MacroAssemblerCodePtr result = stubRoutine->code().code();
+        ASSERT(!!result);
+        return result;
+    }
+    
+    void ref()
+    {
+        m_refCount++;
+    }
+    
+    void deref()
+    {
+        if (--m_refCount)
+            return;
+        observeZeroRefCount();
+    }
+    
+    // Helpers for the GC to determine how to deal with marking JIT stub
+    // routines.
+    uintptr_t startAddress() const { return m_code.executableMemory()->startAsInteger(); }
+    uintptr_t endAddress() const { return m_code.executableMemory()->endAsInteger(); }
+    static uintptr_t addressStep() { return jitAllocationGranule; }
+    
+    static bool canPerformRangeFilter()
+    {
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
+        return true;
+#else
+        return false;
+#endif
+    }
+    static uintptr_t filteringStartAddress()
+    {
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
+        return startOfFixedExecutableMemoryPool;
+#else
+        UNREACHABLE_FOR_PLATFORM();
+        return 0;
+#endif
+    }
+    static size_t filteringExtentSize()
+    {
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
+        return fixedExecutableMemoryPoolSize;
+#else
+        UNREACHABLE_FOR_PLATFORM();
+        return 0;
+#endif
+    }
+    static bool passesFilter(uintptr_t address)
+    {
+        if (!canPerformRangeFilter())
+            return true;
+        
+        if (address - filteringStartAddress() >= filteringExtentSize())
+            return false;
+        
+        return true;
+    }
+
+protected:
+    virtual void observeZeroRefCount();
+
+    MacroAssemblerCodeRef m_code;
+    unsigned m_refCount;
+};
+
+// Helper for the creation of simple stub routines that need no help from the GC.
+#define FINALIZE_CODE_FOR_STUB(patchBuffer, dataLogArguments) \
+    (adoptRef(new JITStubRoutine(FINALIZE_CODE((patchBuffer), dataLogArguments))))
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // JITStubRoutine_h
+
index 6325407..2273f0f 100644 (file)
@@ -1722,7 +1722,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
 
         if (stubInfo->accessType == access_get_by_id_self) {
             ASSERT(!stubInfo->stubRoutine);
-            polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->globalData(), codeBlock->ownerExecutable(), MacroAssemblerCodeRef(), stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
+            polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->globalData(), codeBlock->ownerExecutable(), 0, stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
         } else {
             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
@@ -1748,12 +1748,12 @@ static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(JSG
     switch (stubInfo->accessType) {
     case access_get_by_id_proto:
         prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
-        stubInfo->stubRoutine = MacroAssemblerCodeRef();
+        stubInfo->stubRoutine.clear();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
     case access_get_by_id_chain:
         prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
-        stubInfo->stubRoutine = MacroAssemblerCodeRef();
+        stubInfo->stubRoutine.clear();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
     case access_get_by_id_proto_list:
index c43f491..242e0b8 100644 (file)
@@ -45,17 +45,27 @@ private:
 public:
     WTF_EXPORT_PRIVATE ~MetaAllocatorHandle();
     
-    void* start()
+    void* start() const
     {
         return m_start;
     }
     
-    void* end()
+    void* end() const
     {
-        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(m_start) + m_sizeInBytes);
+        return reinterpret_cast<void*>(endAsInteger());
+    }
+    
+    uintptr_t startAsInteger() const
+    {
+        return reinterpret_cast<uintptr_t>(m_start);
+    }
+    
+    uintptr_t endAsInteger() const
+    {
+        return startAsInteger() + m_sizeInBytes;
     }
         
-    size_t sizeInBytes()
+    size_t sizeInBytes() const
     {
         return m_sizeInBytes;
     }