for (; jsClass; jsClass = jsClass->parentClass)
if (JSObjectFinalizeCallback finalize = jsClass->finalize)
finalize(thisRef);
- HandleSlot slot = handle.slot();
- HandleHeap::heapFor(slot)->deallocate(slot);
+ WeakHeap::deallocate(WeakImpl::asWeakImpl(handle.slot()));
}
} // namespace JSC
initialize(toRef(exec), toRef(this));
}
- bool needsFinalizer = false;
- for (JSClassRef jsClassPtr = classRef(); jsClassPtr && !needsFinalizer; jsClassPtr = jsClassPtr->parentClass)
- needsFinalizer = jsClassPtr->finalize;
- if (needsFinalizer) {
- HandleSlot slot = exec->globalData().heap.handleHeap()->allocate();
- HandleHeap::heapFor(slot)->makeWeak(slot, m_callbackObjectData.get(), classRef());
- HandleHeap::heapFor(slot)->writeBarrier(slot, this);
- *slot = this;
+ for (JSClassRef jsClassPtr = classRef(); jsClassPtr; jsClassPtr = jsClassPtr->parentClass) {
+ if (jsClassPtr->finalize) {
+ exec->globalData().heap.weakHeap()->allocate(this, m_callbackObjectData.get(), classRef());
+ break;
+ }
}
}
dfg/DFGVirtualRegisterAllocationPhase.cpp
heap/CopiedSpace.cpp
+ heap/ConservativeRoots.cpp
heap/DFGCodeBlocks.cpp
- heap/Heap.cpp
heap/HandleHeap.cpp
heap/HandleStack.cpp
+ heap/Heap.cpp
heap/MachineStackMarker.cpp
heap/MarkedAllocator.cpp
heap/MarkedBlock.cpp
heap/MarkedSpace.cpp
- heap/ConservativeRoots.cpp
heap/MarkStack.cpp
+ heap/WeakHeap.cpp
+ heap/WeakHandleOwner.cpp
+ heap/WeakBlock.cpp
debugger/Debugger.cpp
debugger/DebuggerActivation.cpp
+2012-03-29 Geoffrey Garen <ggaren@apple.com>
+
+ First step toward incremental Weak<T> finalization
+ https://bugs.webkit.org/show_bug.cgi?id=82670
+
+ Reviewed by Filip Pizlo.
+
+ This patch implements a Weak<T> heap that is compatible with incremental
+ finalization, while making as few behavior changes as possible. The behavior
+ changes it makes are:
+
+ (*) Weak<T>'s raw JSValue no longer reverts to JSValue() automatically --
+ instead, a separate flag indicates that the JSValue is no longer valid.
+ (This is required so that the JSValue can be preserved for later finalization.)
+ Objects dealing with WeakImpls directly must change to check the flag.
+
+ (*) Weak<T> is no longer a subclass of Handle<T>.
+
+ (*) DOM GC performance is different -- 9% faster in the geometric mean,
+ but 15% slower in one specific case:
+ gc-dom1.html: 6% faster
+ gc-dom2.html: 23% faster
+ gc-dom3.html: 17% faster
+ gc-dom4.html: 15% *slower*
+
+ The key features of this new heap are:
+
+ (*) Each block knows its own state, independent of any other blocks.
+
+ (*) Each block caches its own sweep result.
+
+ (*) The heap visits dead Weak<T>s at the end of GC. (It doesn't
+ mark them yet, since that would be a behavior change.)
+
+ * API/JSCallbackObject.cpp:
+ (JSC::JSCallbackObjectData::finalize):
+ * API/JSCallbackObjectFunctions.h:
+ (JSC::::init): Updated to use the new WeakHeap API.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri: Paid the build system tax since I added some new files.
+
+ * heap/Handle.h: Made WeakBlock a friend and exposed slot() as public,
+ so we can keep passing a Handle<T> to finalizers, to avoid more surface
+ area change in this patch. A follow-up patch should change the type we
+ pass to finalizers.
+
+ * heap/HandleHeap.cpp:
+ (JSC):
+ (JSC::HandleHeap::writeBarrier):
+ (JSC::HandleHeap::isLiveNode):
+ * heap/HandleHeap.h:
+ (JSC):
+ (HandleHeap):
+ (Node):
+ (JSC::HandleHeap::Node::Node): Removed all code related to Weak<T>, since
+ we have a separate WeakHeap now.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap): Removed m_extraCost because extra cost is accounted
+ for through our watermark now. Removed m_waterMark because it was unused.
+
+ (JSC::Heap::destroy): Updated for addition of WeakHeap.
+
+ (JSC::Heap::reportExtraMemoryCostSlowCase): Changed from using its own
+ variable to participating in the watermark strategy. I wanted to standardize
+ WeakHeap and all other Heap clients on this strategy, to make sure it's
+ accurate.
+
+ (JSC::Heap::markRoots): Updated for addition of WeakHeap. Added WeakHeap
+ dead visit pass, as explained above.
+
+ (JSC::Heap::collect):
+ (JSC::Heap::resetAllocators): Updated for addition of WeakHeap.
+
+ (JSC::Heap::addFinalizer):
+ (JSC::Heap::FinalizerOwner::finalize): Updated for new Weak<T> API.
+
+ * heap/Heap.h:
+ (JSC::Heap::weakHeap):
+ (Heap):
+ (JSC::Heap::addToWaterMark): Added a way to participate in the watermarking
+ strategy, since this is the best way for WeakHeap to report its memory
+ cost. (I plan to update this in a follow-up patch to make it more accurate,
+ but for now it is not less accurate than it used to be.)
+
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::MarkedSpace):
+ (JSC::MarkedSpace::resetAllocators):
+ * heap/MarkedSpace.h:
+ (MarkedSpace):
+ (JSC::MarkedSpace::addToWaterMark):
+ (JSC::MarkedSpace::didConsumeFreeList): Removed m_nurseryWaterMark because
+ it was unused, and I didn't want to update WeakHeap to keep an usused
+ variable working. Added API for above.
+
+ * heap/PassWeak.h:
+ (JSC):
+ (WeakImplAccessor):
+ (PassWeak):
+ (JSC::::operator):
+ (JSC::::get):
+ (JSC::::was):
+ (JSC::::PassWeak):
+ (JSC::::~PassWeak):
+ (JSC::UnspecifiedBoolType):
+ (JSC::::leakImpl):
+ (JSC::adoptWeak):
+ * heap/Strong.h:
+ (JSC::Strong::operator!):
+ (Strong):
+ (JSC::Strong::operator UnspecifiedBoolType*):
+ (JSC::Strong::get):
+ * heap/Weak.h:
+ (Weak):
+ (JSC::::Weak):
+ (JSC):
+ (JSC::::isHashTableDeletedValue):
+ (JSC::::~Weak):
+ (JSC::::swap):
+ (JSC::=):
+ (JSC::::operator):
+ (JSC::UnspecifiedBoolType):
+ (JSC::::release):
+ (JSC::::clear):
+ (JSC::::hashTableDeletedValue): Lots of code changes here, but they boil
+ down to two things:
+
+ (*) Allocate WeakImpls from the WeakHeap instead of Handles from the HandleHeap.
+
+ (*) Explicitly check WeakImpl::state() for non-liveness before returning
+ a value (explained above).
+
+ These files implement the new Weak<T> heap behavior described above:
+
+ * heap/WeakBlock.cpp: Added.
+ * heap/WeakBlock.h: Added.
+ * heap/WeakHandleOwner.cpp: Added.
+ * heap/WeakHandleOwner.h: Added.
+ * heap/WeakHeap.cpp: Added.
+ * heap/WeakHeap.h: Added.
+ * heap/WeakImpl.h: Added.
+
+ One interesting difference from the old heap is that we don't allow
+ clients to overwrite a WeakImpl after allocating it, and we don't recycle
+ WeakImpls prior to garbage collection. This is required for lazy finalization,
+ but it will also help us esablish a useful invariant in the future: allocating
+ a WeakImpl will be a binding contract to run a finalizer at some point in the
+ future, even if the WeakImpl is later deallocated.
+
+ * jit/JITStubs.cpp:
+ (JSC::JITThunks::hostFunctionStub): Check the Weak<T> for ! instead of
+ its JSValue, since that's our API contract now, and the JSValue might
+ be stale.
+
+ * runtime/JSCell.h:
+ (JSC::jsCast): Allow casting NULL pointers because it's useful and harmless.
+
+ * runtime/Structure.cpp:
+ (JSC::StructureTransitionTable::add): I can't remember why I did this.
+
+ * runtime/StructureTransitionTable.h:
+ * runtime/WeakGCMap.h: I had to update these classes because they allocate
+ and deallocate weak pointers manually. They should probably stop doing that.
+
2012-04-03 Keishi Hattori <keishi@webkit.org>
Disable ENABLE_DATALIST for now
Source/JavaScriptCore/heap/VTableSpectrum.cpp \
Source/JavaScriptCore/heap/VTableSpectrum.h \
Source/JavaScriptCore/heap/Weak.h \
+ Source/JavaScriptCore/heap/WeakBlock.cpp \
+ Source/JavaScriptCore/heap/WeakHeap.cpp \
+ Source/JavaScriptCore/heap/WeakHandleOwner.cpp \
Source/JavaScriptCore/heap/WeakReferenceHarvester.h \
Source/JavaScriptCore/heap/WriteBarrierSupport.cpp \
Source/JavaScriptCore/heap/WriteBarrierSupport.h \
'bytecompiler/NodesCodegen.cpp',
'bytecompiler/RegisterID.h',
'heap/ConservativeRoots.cpp',
+ 'heap/WeakHeap.cpp',
+ 'heap/WeakHandleOwner.cpp',
+ 'heap/WeakBlock.cpp',
'heap/HandleHeap.cpp',
'heap/HandleStack.cpp',
'heap/Heap.cpp',
??$strtod@$0A@$00@WTF@@YANPBDPAPAD@Z
??$strtod@$0A@$0A@@WTF@@YANPBDPAPAD@Z
??0ArrayBufferView@WTF@@IAE@V?$PassRefPtr@VArrayBuffer@WTF@@@1@I@Z
+ ??0Collator@WTF@@QAE@PBD@Z
??0CString@WTF@@QAE@PBD@Z
??0CString@WTF@@QAE@PBDI@Z
- ??0Collator@WTF@@QAE@PBD@Z
??0DateInstance@JSC@@IAE@PAVExecState@1@PAVStructure@1@@Z
??0DefaultGCActivityCallback@JSC@@QAE@PAVHeap@1@@Z
??0DropAllLocks@JSLock@JSC@@QAE@W4JSLockBehavior@2@@Z
??0StringObject@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@@Z
??0Structure@JSC@@AAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@VJSValue@1@ABVTypeInfo@1@PBUClassInfo@1@@Z
??0ThreadCondition@WTF@@QAE@XZ
- ??0UString@JSC@@QAE@PBD@Z
- ??0UString@JSC@@QAE@PBDI@Z
??0UString@JSC@@QAE@PB_W@Z
??0UString@JSC@@QAE@PB_WI@Z
+ ??0UString@JSC@@QAE@PBD@Z
+ ??0UString@JSC@@QAE@PBDI@Z
??0WTFThreadData@WTF@@QAE@XZ
??0YarrPattern@Yarr@JSC@@QAE@ABVUString@2@_N1PAPBD@Z
??1ArrayBufferView@WTF@@UAE@XZ
??1RefCountedLeakCounter@WTF@@QAE@XZ
??1SourceProviderCache@JSC@@QAE@XZ
??1ThreadCondition@WTF@@QAE@XZ
- ??1WTFThreadData@WTF@@QAE@XZ
??1WeakHandleOwner@JSC@@UAE@XZ
+ ??1WTFThreadData@WTF@@QAE@XZ
??8JSC@@YA_NABVUString@0@0@Z
??8WTF@@YA_NABVCString@0@0@Z
- ?EcmaScriptConverter@DoubleToStringConverter@double_conversion@WTF@@SAABV123@XZ
- ?ToExponential@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z
- ?ToFixed@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z
- ?ToPrecision@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z
- ?ToShortest@DoubleToStringConverter@double_conversion@WTF@@QBE_NNPAVStringBuilder@23@@Z
?absoluteTimeToWaitTimeoutInterval@WTF@@YAKN@Z
?activityCallback@Heap@JSC@@QAEPAVGCActivityCallback@2@XZ
?add@AtomicString@WTF@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@2@PBD@Z
?addStaticGlobals@JSGlobalObject@JSC@@IAEXPAUGlobalPropertyInfo@12@H@Z
?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z
?allocateSlowCase@MarkedAllocator@JSC@@AAEPAXXZ
- ?append@StringBuilder@WTF@@QAEXPBEI@Z
?append@StringBuilder@WTF@@QAEXPB_WI@Z
+ ?append@StringBuilder@WTF@@QAEXPBEI@Z
?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ
?attach@Debugger@JSC@@QAEXPAVJSGlobalObject@2@@Z
?broadcast@ThreadCondition@WTF@@QAEXXZ
?bufferLengthForStringExponential@DecimalNumber@WTF@@QBEIXZ
?byteCompile@Yarr@JSC@@YA?AV?$PassOwnPtr@UBytecodePattern@Yarr@JSC@@@WTF@@AAUYarrPattern@12@PAVBumpPointerAllocator@4@@Z
?byteSize@SourceProviderCache@JSC@@QBEIXZ
+ ?calculatedFunctionName@DebuggerCallFrame@JSC@@QBE?AVUString@2@XZ
?calculateDSTOffset@WTF@@YANNN@Z
?calculateStringHashAndLengthFromUTF8@Unicode@WTF@@YAIPBD0AAI1@Z
?calculateUTCOffset@WTF@@YAHXZ
- ?calculatedFunctionName@DebuggerCallFrame@JSC@@QBE?AVUString@2@XZ
?call@JSC@@YA?AVJSValue@1@PAVExecState@1@V21@W4CallType@1@ABTCallData@1@1ABVArgList@1@@Z
?callHostFunctionAsConstructor@JSC@@YI_JPAVExecState@1@@Z
?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
?changePrototypeTransition@Structure@JSC@@SAPAV12@AAVJSGlobalData@2@PAV12@VJSValue@2@@Z
?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVExecState@2@@Z
?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVJSGlobalData@2@@Z
- ?checkSyntax@JSC@@YA_NPAVExecState@1@ABVSourceCode@1@PAVJSValue@1@@Z
?checksum@MD5@WTF@@QAEXAAV?$Vector@E$0BA@@2@@Z
+ ?checkSyntax@JSC@@YA_NPAVExecState@1@ABVSourceCode@1@PAVJSValue@1@@Z
?className@JSObject@JSC@@SA?AVUString@2@PBV12@@Z
?clear@SourceProviderCache@JSC@@QAEXXZ
?clearBuiltinStructures@JSGlobalData@JSC@@QAEXXZ
?displayName@JSFunction@JSC@@QAE?BVUString@2@PAVExecState@2@@Z
?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z
?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z
+ ?EcmaScriptConverter@DoubleToStringConverter@double_conversion@WTF@@SAABV123@XZ
?empty@StringImpl@WTF@@SAPAV12@XZ
?enumerable@PropertyDescriptor@JSC@@QBE_NXZ
?equalUTF16WithUTF8@Unicode@WTF@@YA_NPB_W0PBD1@Z
?fastZeroedMalloc@WTF@@YAPAXI@Z
?fillGetterPropertySlot@JSObject@JSC@@AAEXAAVPropertySlot@2@PAV?$WriteBarrierBase@W4Unknown@JSC@@@2@@Z
?finalize@WeakHandleOwner@JSC@@UAEXV?$Handle@W4Unknown@JSC@@@2@PAX@Z
+ ?findAllocator@WeakHeap@JSC@@AAEPAUFreeCell@WeakBlock@2@XZ
?finishCreation@DateInstance@JSC@@IAEXAAVJSGlobalData@2@N@Z
?finishCreation@InternalFunction@JSC@@IAEXAAVJSGlobalData@2@ABVIdentifier@2@@Z
?finishCreation@JSArray@JSC@@IAEXAAVJSGlobalData@2@I@Z
?globalExec@JSGlobalObject@JSC@@QAEPAVExecState@2@XZ
?globalObjectCount@Heap@JSC@@QAEIXZ
?grow@HandleHeap@JSC@@AAEXXZ
+ ?hashSlowCase@StringImpl@WTF@@ABEIXZ
?hasInstance@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VJSValue@2@2@Z
?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@ABVIdentifier@2@@Z
?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@I@Z
- ?hashSlowCase@StringImpl@WTF@@ABEIXZ
?heap@Heap@JSC@@SAPAV12@VJSValue@2@@Z
?increment@RefCountedLeakCounter@WTF@@QAEXXZ
?init@AtomicString@WTF@@SAXXZ
?setOrderLowerFirst@Collator@WTF@@QAEX_N@Z
?setPrototype@JSObject@JSC@@QAEXAAVJSGlobalData@2@VJSValue@2@@Z
?setSetter@PropertyDescriptor@JSC@@QAEXVJSValue@2@@Z
+ ?setter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ
?setUndefined@PropertyDescriptor@JSC@@QAEXXZ
?setUpStaticFunctionSlot@JSC@@YA_NPAVExecState@1@PBVHashEntry@1@PAVJSObject@1@ABVIdentifier@1@AAVPropertySlot@1@@Z
?setWritable@PropertyDescriptor@JSC@@QAEX_N@Z
- ?setter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ
?shrinkToFit@StringBuilder@WTF@@QAEXXZ
?signal@ThreadCondition@WTF@@QAEXXZ
?singleCharacterStringRep@SmallStrings@JSC@@QAEPAVStringImpl@WTF@@E@Z
?tlsKeyCount@WTF@@YAAAJXZ
?tlsKeys@WTF@@YAPAKXZ
?toBoolean@JSString@JSC@@QBE_NPAVExecState@2@@Z
+ ?ToExponential@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z
+ ?ToFixed@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z
?toInt32@JSC@@YAHN@Z
?toInteger@JSValue@JSC@@QBENPAVExecState@2@@Z
?toNumberSlowCase@JSValue@JSC@@ABENPAVExecState@2@@Z
?toObject@JSCell@JSC@@QBEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z
?toObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z
+ ?ToPrecision@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z
+ ?ToShortest@DoubleToStringConverter@double_conversion@WTF@@QBE_NNPAVStringBuilder@23@@Z
?toString@JSObject@JSC@@QBEPAVJSString@2@PAVExecState@2@@Z
?toStringDecimal@DecimalNumber@WTF@@QBEIPA_WI@Z
?toStringExponential@DecimalNumber@WTF@@QBEIPA_WI@Z
>
</File>
<File
+ RelativePath="..\..\heap\WeakBlock.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\WeakBlock.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\WeakHeap.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\WeakHeap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\WeakImpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\WeakHandleOwner.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\WeakHandleOwner.h"
+ >
+ </File>
+ <File
RelativePath="..\..\heap\HandleStack.cpp"
>
</File>
14C5242B0F5355E900BA3D04 /* JITStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A6581A0F4E36F4000150FD /* JITStubs.h */; settings = {ATTRIBUTES = (Private, ); }; };
14D2F3DA139F4BE200491031 /* MarkedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14D2F3D8139F4BE200491031 /* MarkedSpace.cpp */; };
14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D2F3D9139F4BE200491031 /* MarkedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */; };
+ 14E84F9F14EE1ACC00D6D5D4 /* WeakBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9A14EE1ACC00D6D5D4 /* WeakBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 14E84FA014EE1ACC00D6D5D4 /* WeakHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14E84F9B14EE1ACC00D6D5D4 /* WeakHeap.cpp */; };
+ 14E84FA114EE1ACC00D6D5D4 /* WeakHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9C14EE1ACC00D6D5D4 /* WeakHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9D14EE1ACC00D6D5D4 /* WeakImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
14E9D17B107EC469004DDA21 /* JSGlobalObjectFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */; };
+ 14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F7256314EE265E00B1652B /* WeakHandleOwner.cpp */; };
+ 14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F7256414EE265E00B1652B /* WeakHandleOwner.h */; settings = {ATTRIBUTES = (Private, ); }; };
14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F97446138C853E00DA1C67 /* HeapRootVisitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
41359CF30FDD89AD00206180 /* DateConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateConversion.h */; };
451539B912DC994500EF7AC4 /* Yarr.h in Headers */ = {isa = PBXBuildFile; fileRef = 451539B812DC994500EF7AC4 /* Yarr.h */; settings = {ATTRIBUTES = (Private, ); }; };
14DA818E0D99FD2000B0A4FB /* JSActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSActivation.h; sourceTree = "<group>"; };
14DA818F0D99FD2000B0A4FB /* JSActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSActivation.cpp; sourceTree = "<group>"; };
14DE0D680D02431400AACCA2 /* JSGlobalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalObject.cpp; sourceTree = "<group>"; };
+ 14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakBlock.cpp; sourceTree = "<group>"; };
+ 14E84F9A14EE1ACC00D6D5D4 /* WeakBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakBlock.h; sourceTree = "<group>"; };
+ 14E84F9B14EE1ACC00D6D5D4 /* WeakHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakHeap.cpp; sourceTree = "<group>"; };
+ 14E84F9C14EE1ACC00D6D5D4 /* WeakHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakHeap.h; sourceTree = "<group>"; };
+ 14E84F9D14EE1ACC00D6D5D4 /* WeakImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakImpl.h; sourceTree = "<group>"; };
14F252560D08DD8D004ECFFF /* JSVariableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVariableObject.h; sourceTree = "<group>"; };
+ 14F7256314EE265E00B1652B /* WeakHandleOwner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakHandleOwner.cpp; sourceTree = "<group>"; };
+ 14F7256414EE265E00B1652B /* WeakHandleOwner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakHandleOwner.h; sourceTree = "<group>"; };
14F97446138C853E00DA1C67 /* HeapRootVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapRootVisitor.h; sourceTree = "<group>"; };
1C9051420BA9E8A70081E9D0 /* Version.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; };
1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = JavaScriptCore.xcconfig; sourceTree = "<group>"; };
0FC815121405118600CFA603 /* VTableSpectrum.cpp */,
0FC815141405118D00CFA603 /* VTableSpectrum.h */,
142E3133134FF0A600AFADB5 /* Weak.h */,
+ 14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */,
+ 14E84F9A14EE1ACC00D6D5D4 /* WeakBlock.h */,
+ 14F7256314EE265E00B1652B /* WeakHandleOwner.cpp */,
+ 14F7256414EE265E00B1652B /* WeakHandleOwner.h */,
+ 14E84F9B14EE1ACC00D6D5D4 /* WeakHeap.cpp */,
+ 14E84F9C14EE1ACC00D6D5D4 /* WeakHeap.h */,
+ 14E84F9D14EE1ACC00D6D5D4 /* WeakImpl.h */,
0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */,
0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */,
0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */,
0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */,
0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */,
1497209114EB831500FEB1B7 /* PassWeak.h in Headers */,
+ 14E84F9F14EE1ACC00D6D5D4 /* WeakBlock.h in Headers */,
+ 14E84FA114EE1ACC00D6D5D4 /* WeakHeap.h in Headers */,
+ 14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */,
+ 14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */,
0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */,
0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */,
0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */,
86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */,
C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */,
0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */,
+ 14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */,
+ 14E84FA014EE1ACC00D6D5D4 /* WeakHeap.cpp in Sources */,
+ 14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */,
0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */,
0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
0FFFC95B14EF90AD00C72532 /* DFGPhase.cpp in Sources */,
heap/CopiedSpace.cpp \
heap/ConservativeRoots.cpp \
heap/DFGCodeBlocks.cpp \
+ heap/WeakHeap.cpp \
+ heap/WeakHandleOwner.cpp \
+ heap/WeakBlock.cpp \
heap/HandleHeap.cpp \
heap/HandleStack.cpp \
heap/Heap.cpp \
typedef JSValue (HandleBase::*UnspecifiedBoolType);
operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+ HandleSlot slot() const { return m_slot; }
+
protected:
HandleBase(HandleSlot slot)
: m_slot(slot)
void swap(HandleBase& other) { std::swap(m_slot, other.m_slot); }
- HandleSlot slot() const { return m_slot; }
void setSlot(HandleSlot slot)
{
m_slot = slot;
private:
friend class HandleHeap;
+ friend class WeakBlock;
static Handle<T> wrapSlot(HandleSlot slot)
{
namespace JSC {
-WeakHandleOwner::~WeakHandleOwner()
-{
-}
-
-bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, SlotVisitor&)
-{
- return false;
-}
-
-void WeakHandleOwner::finalize(Handle<Unknown>, void*)
-{
-}
-
HandleHeap::HandleHeap(JSGlobalData* globalData)
: m_globalData(globalData)
, m_nextToFinalize(0)
}
}
-void HandleHeap::visitWeakHandles(HeapRootVisitor& heapRootVisitor)
-{
- SlotVisitor& visitor = heapRootVisitor.visitor();
-
- Node* end = m_weakList.end();
- for (Node* node = m_weakList.begin(); node != end; node = node->next()) {
-#if ENABLE(GC_VALIDATION)
- if (!isValidWeakNode(node))
- CRASH();
-#endif
- JSCell* cell = node->slot()->asCell();
- if (Heap::isMarked(cell))
- continue;
-
- WeakHandleOwner* weakOwner = node->weakOwner();
- if (!weakOwner)
- continue;
-
- if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), visitor))
- continue;
-
- heapRootVisitor.visit(node->slot());
- }
-}
-
-void HandleHeap::finalizeWeakHandles()
-{
- Node* end = m_weakList.end();
- for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) {
- m_nextToFinalize = node->next();
-#if ENABLE(GC_VALIDATION)
- if (!isValidWeakNode(node))
- CRASH();
-#endif
-
- JSCell* cell = node->slot()->asCell();
- if (Heap::isMarked(cell))
- continue;
-
- if (WeakHandleOwner* weakOwner = node->weakOwner()) {
- weakOwner->finalize(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext());
- if (m_nextToFinalize != node->next()) // Owner deallocated node.
- continue;
- }
-#if ENABLE(GC_VALIDATION)
- if (!isLiveNode(node))
- CRASH();
-#endif
- *node->slot() = JSValue();
- SentinelLinkedList<Node>::remove(node);
- m_immediateList.push(node);
- }
-
- m_nextToFinalize = 0;
-}
-
void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value)
{
// Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
return;
}
- if (node->isWeak()) {
- m_weakList.push(node);
-#if ENABLE(GC_VALIDATION)
- if (!isLiveNode(node))
- CRASH();
-#endif
- return;
- }
-
m_strongList.push(node);
#if ENABLE(GC_VALIDATION)
if (!isLiveNode(node))
return true;
}
-
-bool HandleHeap::isValidWeakNode(Node* node)
-{
- if (!isLiveNode(node))
- return false;
- if (!node->isWeak())
- return false;
-
- JSValue value = *node->slot();
- if (!value || !value.isCell())
- return false;
-
- JSCell* cell = value.asCell();
- if (!cell || !cell->structure())
- return false;
-
- return true;
-}
#endif
} // namespace JSC
class JSValue;
class SlotVisitor;
-class JS_EXPORT_PRIVATE WeakHandleOwner {
-public:
- virtual ~WeakHandleOwner();
- virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&);
- virtual void finalize(Handle<Unknown>, void* context);
-};
-
class HandleHeap {
public:
static HandleHeap* heapFor(HandleSlot);
HandleSlot allocate();
void deallocate(HandleSlot);
- void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0);
- HandleSlot copyWeak(HandleSlot);
-
void visitStrongHandles(HeapRootVisitor&);
- void visitWeakHandles(HeapRootVisitor&);
- void finalizeWeakHandles();
JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&);
-#if !ASSERT_DISABLED
- bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
- bool hasFinalizer(HandleSlot);
-#endif
-
unsigned protectedGlobalObjectCount();
template<typename Functor> void forEachStrongHandle(Functor&, const HashCountedSet<JSCell*>& skipSet);
HandleSlot slot();
HandleHeap* handleHeap();
- void makeWeak(WeakHandleOwner*, void* context);
- bool isWeak();
-
- WeakHandleOwner* weakOwner();
- void* weakOwnerContext();
-
void setPrev(Node*);
Node* prev();
Node* next();
private:
- WeakHandleOwner* emptyWeakOwner();
-
JSValue m_value;
HandleHeap* m_handleHeap;
- WeakHandleOwner* m_weakOwner;
- void* m_weakOwnerContext;
Node* m_prev;
Node* m_next;
};
JS_EXPORT_PRIVATE void grow();
#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED
- bool isValidWeakNode(Node*);
bool isLiveNode(Node*);
#endif
BlockStack<Node> m_blockStack;
SentinelLinkedList<Node> m_strongList;
- SentinelLinkedList<Node> m_weakList;
SentinelLinkedList<Node> m_immediateList;
SinglyLinkedList<Node> m_freeList;
Node* m_nextToFinalize;
m_freeList.push(node);
}
-inline HandleSlot HandleHeap::copyWeak(HandleSlot other)
-{
- Node* node = toNode(allocate());
- node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext());
- writeBarrier(node->slot(), *other);
- *node->slot() = *other;
- return toHandle(node);
-}
-
-inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context)
-{
- // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
- // File a bug with stack trace if you hit this.
- if (m_nextToFinalize)
- CRASH();
- Node* node = toNode(handle);
- node->makeWeak(weakOwner, context);
-
- SentinelLinkedList<Node>::remove(node);
- if (!*handle || !handle->isCell()) {
- m_immediateList.push(node);
- return;
- }
-
- m_weakList.push(node);
-}
-
-#if !ASSERT_DISABLED
-inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner)
-{
- return toNode(handle)->weakOwner() == weakOwner;
-}
-
-inline bool HandleHeap::hasFinalizer(HandleSlot handle)
-{
- return toNode(handle)->weakOwner();
-}
-#endif
-
inline HandleHeap::Node::Node(HandleHeap* handleHeap)
: m_handleHeap(handleHeap)
- , m_weakOwner(0)
- , m_weakOwnerContext(0)
, m_prev(0)
, m_next(0)
{
inline HandleHeap::Node::Node(WTF::SentinelTag)
: m_handleHeap(0)
- , m_weakOwner(0)
- , m_weakOwnerContext(0)
, m_prev(0)
, m_next(0)
{
return m_handleHeap;
}
-inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context)
-{
- m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner();
- m_weakOwnerContext = context;
-}
-
-inline bool HandleHeap::Node::isWeak()
-{
- return m_weakOwner; // True for emptyWeakOwner().
-}
-
-inline WeakHandleOwner* HandleHeap::Node::weakOwner()
-{
- return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner().
-}
-
-inline void* HandleHeap::Node::weakOwnerContext()
-{
- ASSERT(weakOwner());
- return m_weakOwnerContext;
-}
-
inline void HandleHeap::Node::setPrev(Node* prev)
{
m_prev = prev;
return m_next;
}
-// Sentinel to indicate that a node is weak, but its owner has no meaningful
-// callbacks. This allows us to optimize by skipping such nodes.
-inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()
-{
- return reinterpret_cast<WeakHandleOwner*>(-1);
-}
-
template<typename Functor> void HandleHeap::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet)
{
Node* end = m_strongList.end();
: m_heapSize(heapSize)
, m_minBytesPerCycle(heapSizeForHint(heapSize))
, m_lastFullGCSize(0)
- , m_waterMark(0)
, m_highWaterMark(m_minBytesPerCycle)
, m_operationInProgress(NoOperation)
, m_objectSpace(this)
, m_storageSpace(this)
, m_blockFreeingThreadShouldQuit(false)
- , m_extraCost(0)
, m_markListSet(0)
, m_activityCallback(DefaultGCActivityCallback::create(this))
, m_machineThreads(this)
, m_sharedData(globalData)
, m_slotVisitor(m_sharedData)
+ , m_weakHeap(this)
, m_handleHeap(globalData)
, m_isSafeToCollect(false)
, m_globalData(globalData)
canonicalizeCellLivenessData();
clearMarks();
- m_handleHeap.finalizeWeakHandles();
+ m_weakHeap.finalizeAll();
m_globalData->smallStrings.finalizeSmallStrings();
shrink();
m_storageSpace.destroy();
// if a large value survives one garbage collection, there is not much point to
// collecting more frequently as long as it stays alive.
- if (m_extraCost > maxExtraCost && m_extraCost > highWaterMark() / 2)
- collectAllGarbage();
- m_extraCost += cost;
+ addToWaterMark(cost);
}
void Heap::protect(JSValue k)
#endif
}
- // Weak handles must be marked last, because their owners use the set of
- // opaque roots to determine reachability.
+ // Weak references must be marked last because their liveness depends on
+ // the liveness of the rest of the object graph.
{
- GCPHASE(VisitingWeakHandles);
+ GCPHASE(VisitingLiveWeakHandles);
while (true) {
- m_handleHeap.visitWeakHandles(heapRootVisitor);
+ m_weakHeap.visitLiveWeakImpls(heapRootVisitor);
harvestWeakReferences();
if (visitor.isEmpty())
break;
}
}
}
+
+ {
+ GCPHASE(VisitingDeadWeakHandles);
+ m_weakHeap.visitDeadWeakImpls(heapRootVisitor);
+ }
+
GCCOUNTER(VisitedValueCount, visitor.visitCount());
visitor.doneCopying();
{
GCPHASE(FinalizeWeakHandles);
- m_handleHeap.finalizeWeakHandles();
+ m_weakHeap.sweep();
m_globalData->smallStrings.finalizeSmallStrings();
}
size_t proportionalBytes = 2 * newSize;
if (fullGC) {
m_lastFullGCSize = newSize;
- setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));
+ m_highWaterMark = max(proportionalBytes, m_minBytesPerCycle);
}
double lastGCEndTime = WTF::currentTime();
m_lastGCLength = lastGCEndTime - lastGCStartTime;
void Heap::resetAllocators()
{
- m_extraCost = 0;
m_objectSpace.resetAllocators();
+ m_weakHeap.resetAllocator();
}
void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
void Heap::addFinalizer(JSCell* cell, Finalizer finalizer)
{
- Weak<JSCell> weak(*globalData(), cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer));
- weak.leakHandle(); // Balanced by FinalizerOwner::finalize().
+ weakHeap()->allocate(cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); // Balanced by FinalizerOwner::finalize().
}
void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context)
{
- Weak<JSCell> weak(Weak<JSCell>::Adopt, handle);
+ HandleSlot slot = handle.slot();
Finalizer finalizer = reinterpret_cast<Finalizer>(context);
- finalizer(weak.get());
+ finalizer(slot->asCell());
+ WeakHeap::deallocate(WeakImpl::asWeakImpl(slot));
}
void Heap::addFunctionExecutable(FunctionExecutable* executable)
#include "MarkedBlockSet.h"
#include "MarkedSpace.h"
#include "SlotVisitor.h"
+#include "WeakHandleOwner.h"
+#include "WeakHeap.h"
#include "WriteBarrierSupport.h"
#include <wtf/DoublyLinkedList.h>
#include <wtf/Forward.h>
template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
+ WeakHeap* weakHeap() { return &m_weakHeap; }
HandleHeap* handleHeap() { return &m_handleHeap; }
HandleStack* handleStack() { return &m_handleStack; }
void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
+ void addToWaterMark(size_t);
+
double lastGCLength() { return m_lastGCLength; }
void discardAllCompiledCode();
size_t waterMark();
size_t highWaterMark();
- void setHighWaterMark(size_t);
bool shouldCollect();
static const size_t minExtraCost = 256;
const HeapSize m_heapSize;
const size_t m_minBytesPerCycle;
size_t m_lastFullGCSize;
- size_t m_waterMark;
size_t m_highWaterMark;
OperationInProgress m_operationInProgress;
VTableSpectrum m_destroyedTypeCounts;
#endif
- size_t m_extraCost;
-
ProtectCountSet m_protectedValues;
Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
HashSet<MarkedArgumentBuffer*>* m_markListSet;
MarkStackThreadSharedData m_sharedData;
SlotVisitor m_slotVisitor;
+ WeakHeap m_weakHeap;
HandleHeap m_handleHeap;
HandleStack m_handleStack;
DFGCodeBlocks m_dfgCodeBlocks;
return m_highWaterMark;
}
- inline void Heap::setHighWaterMark(size_t newHighWaterMark)
+ inline void Heap::addToWaterMark(size_t size)
{
- m_highWaterMark = newHighWaterMark;
+ m_objectSpace.addToWaterMark(size);
+ if (waterMark() > highWaterMark())
+ collect(DoNotSweep);
}
#if ENABLE(GGC)
MarkedSpace::MarkedSpace(Heap* heap)
: m_waterMark(0)
- , m_nurseryWaterMark(0)
, m_heap(heap)
{
for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
void MarkedSpace::resetAllocators()
{
m_waterMark = 0;
- m_nurseryWaterMark = 0;
for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
allocatorFor(cellSize).reset();
void canonicalizeCellLivenessData();
size_t waterMark();
- size_t nurseryWaterMark();
+ void addToWaterMark(size_t);
typedef HashSet<MarkedBlock*>::iterator BlockIterator;
void shrink();
void freeBlocks(MarkedBlock* head);
+
void didAddBlock(MarkedBlock*);
void didConsumeFreeList(MarkedBlock*);
Subspace m_normalSpace;
size_t m_waterMark;
- size_t m_nurseryWaterMark;
Heap* m_heap;
MarkedBlockSet m_blocks;
};
return m_waterMark;
}
-inline size_t MarkedSpace::nurseryWaterMark()
+inline void MarkedSpace::addToWaterMark(size_t size)
{
- return m_nurseryWaterMark;
+ m_waterMark += size;
}
template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell(Functor& functor)
inline void MarkedSpace::didConsumeFreeList(MarkedBlock* block)
{
- m_nurseryWaterMark += block->capacity() - block->size();
m_waterMark += block->capacity();
}
#ifndef PassWeak_h
#define PassWeak_h
+#include "JSCell.h"
#include <wtf/Assertions.h>
-#include "Handle.h"
#include <wtf/NullPtr.h>
#include <wtf/TypeTraits.h>
template<typename T> class Weak;
template<typename T> class PassWeak;
-template<typename T> PassWeak<T> adoptWeak(HandleSlot);
+template<typename T> PassWeak<T> adoptWeak(WeakImpl*);
-template<typename T> class PassWeak : public Handle<T> {
- using Handle<T>::slot;
- using Handle<T>::setSlot;
+template<typename Base, typename T> class WeakImplAccessor {
+public:
+ typedef T* GetType;
+
+ T* operator->() const;
+ T& operator*() const;
+ GetType get() const;
+
+#if !ASSERT_DISABLED
+ bool was(GetType) const;
+#endif
+};
+template<typename Base> class WeakImplAccessor<Base, Unknown> {
public:
- typedef typename Handle<T>::ExternalType ExternalType;
+ typedef JSValue GetType;
- PassWeak() : Handle<T>() { }
- PassWeak(std::nullptr_t) : Handle<T>() { }
+ const JSValue* operator->() const;
+ const JSValue& operator*() const;
+ GetType get() const;
+};
+
+template<typename T> class PassWeak : public WeakImplAccessor<PassWeak<T>, T> {
+public:
+ friend class WeakImplAccessor<PassWeak<T>, T>;
+ typedef typename WeakImplAccessor<PassWeak<T>, T>::GetType GetType;
- PassWeak(JSGlobalData& globalData, ExternalType externalType = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0)
- : Handle<T>(globalData.heap.handleHeap()->allocate())
- {
- HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
- JSValue value = HandleTypes<T>::toJSValue(externalType);
- HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
- *slot() = value;
- }
+ PassWeak();
+ PassWeak(std::nullptr_t);
+ PassWeak(JSGlobalData&, GetType = GetType(), WeakHandleOwner* = 0, void* context = 0);
// It somewhat breaks the type system to allow transfer of ownership out of
// a const PassWeak. However, it makes it much easier to work with PassWeak
// temporaries, and we don't have a need to use real const PassWeaks anyway.
- PassWeak(const PassWeak& o) : Handle<T>(o.leakHandle()) { }
- template<typename U> PassWeak(const PassWeak<U>& o) : Handle<T>(o.leakHandle()) { }
+ PassWeak(const PassWeak&);
+ template<typename U> PassWeak(const PassWeak<U>&);
- ~PassWeak()
- {
- if (!slot())
- return;
- HandleHeap::heapFor(slot())->deallocate(slot());
- setSlot(0);
- }
+ ~PassWeak();
- ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); }
+ bool operator!() const;
- HandleSlot leakHandle() const WARN_UNUSED_RETURN;
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef JSValue (PassWeak::*UnspecifiedBoolType);
+ operator UnspecifiedBoolType*() const;
+
+ WeakImpl* leakImpl() const WARN_UNUSED_RETURN;
private:
- friend PassWeak adoptWeak<T>(HandleSlot);
+ friend PassWeak adoptWeak<T>(WeakImpl*);
+ explicit PassWeak(WeakImpl*);
- explicit PassWeak(HandleSlot slot) : Handle<T>(slot) { }
+ WeakImpl* m_impl;
};
-template<typename T> inline HandleSlot PassWeak<T>::leakHandle() const
+template<typename Base, typename T> inline T* WeakImplAccessor<Base, T>::operator->() const
+{
+ ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live);
+ return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell());
+}
+
+template<typename Base, typename T> inline T& WeakImplAccessor<Base, T>::operator*() const
+{
+ ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live);
+ return *jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell());
+}
+
+template<typename Base, typename T> inline typename WeakImplAccessor<Base, T>::GetType WeakImplAccessor<Base, T>::get() const
+{
+ if (!static_cast<const Base*>(this)->m_impl || static_cast<const Base*>(this)->m_impl->state() != WeakImpl::Live)
+ return GetType();
+ return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell());
+}
+
+#if !ASSERT_DISABLED
+template<typename Base, typename T> inline bool WeakImplAccessor<Base, T>::was(typename WeakImplAccessor<Base, T>::GetType other) const
+{
+ return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()) == other;
+}
+#endif
+
+template<typename Base> inline const JSValue* WeakImplAccessor<Base, Unknown>::operator->() const
+{
+ ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live);
+ return &static_cast<const Base*>(this)->m_impl->jsValue();
+}
+
+template<typename Base> inline const JSValue& WeakImplAccessor<Base, Unknown>::operator*() const
+{
+ ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live);
+ return static_cast<const Base*>(this)->m_impl->jsValue();
+}
+
+template<typename Base> inline typename WeakImplAccessor<Base, Unknown>::GetType WeakImplAccessor<Base, Unknown>::get() const
+{
+ if (!static_cast<const Base*>(this)->m_impl || static_cast<const Base*>(this)->m_impl->state() != WeakImpl::Live)
+ return GetType();
+ return static_cast<const Base*>(this)->m_impl->jsValue();
+}
+
+template<typename T> inline PassWeak<T>::PassWeak()
+ : m_impl(0)
+{
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(std::nullptr_t)
+ : m_impl(0)
+{
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(JSGlobalData& globalData, typename PassWeak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context)
+ : m_impl(globalData.heap.weakHeap()->allocate(getType, weakOwner, context))
+{
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(const PassWeak& o)
+ : m_impl(o.leakImpl())
+{
+}
+
+template<typename T> template<typename U> inline PassWeak<T>::PassWeak(const PassWeak<U>& o)
+ : m_impl(o.leakImpl())
+{
+}
+
+template<typename T> inline PassWeak<T>::~PassWeak()
+{
+ if (!m_impl)
+ return;
+ WeakHeap::deallocate(m_impl);
+}
+
+template<typename T> inline bool PassWeak<T>::operator!() const
+{
+ return !m_impl || m_impl->state() != WeakImpl::Live || !m_impl->jsValue();
+}
+
+template<typename T> inline PassWeak<T>::operator UnspecifiedBoolType*() const
+{
+ return reinterpret_cast<UnspecifiedBoolType*>(!!*this);
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(WeakImpl* impl)
+: m_impl(impl)
+{
+}
+
+template<typename T> inline WeakImpl* PassWeak<T>::leakImpl() const
{
- HandleSlot slot = this->slot();
- const_cast<PassWeak<T>*>(this)->setSlot(0);
- return slot;
+ WeakImpl* tmp = 0;
+ std::swap(tmp, const_cast<WeakImpl*&>(m_impl));
+ return tmp;
}
-template<typename T> PassWeak<T> adoptWeak(HandleSlot slot)
+template<typename T> PassWeak<T> inline adoptWeak(WeakImpl* impl)
{
- return PassWeak<T>(slot);
+ return PassWeak<T>(impl);
}
template<typename T, typename U> inline bool operator==(const PassWeak<T>& a, const PassWeak<U>& b)
clear();
}
+ bool operator!() const { return !slot() || !*slot(); }
+
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef JSValue (HandleBase::*UnspecifiedBoolType);
+ operator UnspecifiedBoolType*() const { return !!*this ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+
void swap(Strong& other)
{
Handle<T>::swap(other);
}
+ ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); }
+
void set(JSGlobalData&, ExternalType);
template <typename U> Strong& operator=(const Strong<U>& other)
#define Weak_h
#include <wtf/Assertions.h>
-#include "Handle.h"
-#include "HandleHeap.h"
#include "JSGlobalData.h"
#include "PassWeak.h"
namespace JSC {
-// A weakly referenced handle that becomes 0 when the value it points to is garbage collected.
-template <typename T> class Weak : public Handle<T> {
+template<typename T> class Weak : public WeakImplAccessor<Weak<T>, T> {
WTF_MAKE_NONCOPYABLE(Weak);
-
- using Handle<T>::slot;
- using Handle<T>::setSlot;
-
public:
- typedef typename Handle<T>::ExternalType ExternalType;
-
- Weak()
- : Handle<T>()
- {
- }
-
- Weak(std::nullptr_t)
- : Handle<T>()
- {
- }
-
- Weak(JSGlobalData& globalData, ExternalType externalType = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0)
- : Handle<T>(globalData.heap.handleHeap()->allocate())
- {
- HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
- JSValue value = HandleTypes<T>::toJSValue(externalType);
- HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
- *slot() = value;
- }
-
- enum AdoptTag { Adopt };
- template<typename U> Weak(AdoptTag, Handle<U> handle)
- : Handle<T>(handle.slot())
- {
- validateCell(get());
- }
+ friend class WeakImplAccessor<Weak<T>, T>;
+ typedef typename WeakImplAccessor<Weak<T>, T>::GetType GetType;
+
+ Weak();
+ Weak(std::nullptr_t);
+ Weak(JSGlobalData&, GetType = GetType(), WeakHandleOwner* = 0, void* context = 0);
enum HashTableDeletedValueTag { HashTableDeletedValue };
- bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
- Weak(HashTableDeletedValueTag)
- : Handle<T>(hashTableDeletedValue())
- {
- }
-
- template<typename U> Weak(const PassWeak<U>& other)
- : Handle<T>(other.leakHandle())
- {
- }
-
- ~Weak()
- {
- clear();
- }
-
- void swap(Weak& other)
- {
- Handle<T>::swap(other);
- }
+ bool isHashTableDeletedValue() const;
+ Weak(HashTableDeletedValueTag);
- Weak& operator=(const PassWeak<T>&);
+ template<typename U> Weak(const PassWeak<U>&);
- ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); }
-
- PassWeak<T> release() { PassWeak<T> tmp = adoptWeak<T>(slot()); setSlot(0); return tmp; }
-
- void clear()
- {
- if (!slot())
- return;
- HandleHeap::heapFor(slot())->deallocate(slot());
- setSlot(0);
- }
+ ~Weak();
+
+ void swap(Weak&);
+ Weak& operator=(const PassWeak<T>&);
- HandleSlot leakHandle()
- {
- ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot()));
- HandleSlot result = slot();
- setSlot(0);
- return result;
- }
+ bool operator!() const;
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef JSValue (HandleBase::*UnspecifiedBoolType);
+ operator UnspecifiedBoolType*() const;
+
+ PassWeak<T> release();
+ void clear();
+
private:
- static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
+ static WeakImpl* hashTableDeletedValue();
+
+ WeakImpl* m_impl;
};
+template<typename T> inline Weak<T>::Weak()
+ : m_impl(0)
+{
+}
+
+template<typename T> inline Weak<T>::Weak(std::nullptr_t)
+ : m_impl(0)
+{
+}
+
+template<typename T> inline Weak<T>::Weak(JSGlobalData& globalData, typename Weak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context)
+ : m_impl(globalData.heap.weakHeap()->allocate(getType, weakOwner, context))
+{
+}
+
+template<typename T> inline bool Weak<T>::isHashTableDeletedValue() const
+{
+ return m_impl == hashTableDeletedValue();
+}
+
+template<typename T> inline Weak<T>::Weak(typename Weak<T>::HashTableDeletedValueTag)
+ : m_impl(hashTableDeletedValue())
+{
+}
+
+template<typename T> template<typename U> inline Weak<T>::Weak(const PassWeak<U>& other)
+ : m_impl(other.leakImpl())
+{
+}
+
+template<typename T> inline Weak<T>::~Weak()
+{
+ clear();
+}
+
template<class T> inline void swap(Weak<T>& a, Weak<T>& b)
{
a.swap(b);
}
+template<typename T> inline void Weak<T>::swap(Weak& other)
+{
+ std::swap(m_impl, other.m_impl);
+}
+
template<typename T> inline Weak<T>& Weak<T>::operator=(const PassWeak<T>& o)
{
clear();
- setSlot(o.leakHandle());
+ m_impl = o.leakImpl();
return *this;
}
+template<typename T> inline bool Weak<T>::operator!() const
+{
+ return !m_impl || !m_impl->jsValue() || m_impl->state() != WeakImpl::Live;
+}
+
+template<typename T> inline Weak<T>::operator UnspecifiedBoolType*() const
+{
+ return reinterpret_cast<UnspecifiedBoolType*>(!!*this);
+}
+
+template<typename T> inline PassWeak<T> Weak<T>::release()
+{
+ PassWeak<T> tmp = adoptWeak<T>(m_impl);
+ m_impl = 0;
+ return tmp;
+}
+
+template<typename T> inline void Weak<T>::clear()
+{
+ if (!m_impl)
+ return;
+ WeakHeap::deallocate(m_impl);
+ m_impl = 0;
+}
+
+template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue()
+{
+ return reinterpret_cast<WeakImpl*>(-1);
+}
+
} // namespace JSC
namespace WTF {
static PassOutType passOut(StorageType& value) { return value.release(); }
static PassOutType passOut(EmptyValueType) { return PassOutType(); }
- typedef typename StorageType::ExternalType PeekType;
+ typedef typename StorageType::GetType PeekType;
static PeekType peek(const StorageType& value) { return value.get(); }
static PeekType peek(EmptyValueType) { return PeekType(); }
};
--- /dev/null
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WeakBlock.h"
+
+#include "Heap.h"
+#include "HeapRootVisitor.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+#include "Structure.h"
+
+namespace JSC {
+
+WeakBlock* WeakBlock::create()
+{
+ PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockSize, OSAllocator::JSGCHeapPages);
+ if (!static_cast<bool>(allocation))
+ CRASH();
+ return new (NotNull, allocation.base()) WeakBlock(allocation);
+}
+
+void WeakBlock::destroy(WeakBlock* block)
+{
+ block->m_allocation.deallocate();
+}
+
+WeakBlock::WeakBlock(PageAllocationAligned& allocation)
+ : HeapBlock(allocation)
+{
+ for (size_t i = 0; i < weakImplCount(); ++i) {
+ WeakImpl* weakImpl = &weakImpls()[i];
+ new (NotNull, weakImpl) WeakImpl;
+ addToFreeList(&m_sweepResult.freeList, weakImpl);
+ }
+
+ ASSERT(!m_sweepResult.isNull() && m_sweepResult.blockIsFree);
+}
+
+void WeakBlock::finalizeAll()
+{
+ for (size_t i = 0; i < weakImplCount(); ++i) {
+ WeakImpl* weakImpl = &weakImpls()[i];
+ if (weakImpl->state() >= WeakImpl::Finalized)
+ continue;
+ weakImpl->setState(WeakImpl::Dead);
+ finalize(weakImpl);
+ }
+}
+
+void WeakBlock::sweep()
+{
+ if (!m_sweepResult.isNull())
+ return;
+
+ SweepResult sweepResult;
+ for (size_t i = 0; i < weakImplCount(); ++i) {
+ WeakImpl* weakImpl = &weakImpls()[i];
+ if (weakImpl->state() == WeakImpl::Dead)
+ finalize(weakImpl);
+ if (weakImpl->state() == WeakImpl::Deallocated)
+ addToFreeList(&sweepResult.freeList, weakImpl);
+ else
+ sweepResult.blockIsFree = false;
+ }
+
+ m_sweepResult = sweepResult;
+ ASSERT(!m_sweepResult.isNull());
+}
+
+void WeakBlock::visitLiveWeakImpls(HeapRootVisitor& heapRootVisitor)
+{
+ // If a block is completely empty, a visit won't have any effect.
+ if (!m_sweepResult.isNull() && m_sweepResult.blockIsFree)
+ return;
+
+ SlotVisitor& visitor = heapRootVisitor.visitor();
+
+ for (size_t i = 0; i < weakImplCount(); ++i) {
+ WeakImpl* weakImpl = &weakImpls()[i];
+ if (weakImpl->state() != WeakImpl::Live)
+ continue;
+
+ const JSValue& jsValue = weakImpl->jsValue();
+ if (!jsValue || !jsValue.isCell())
+ continue;
+
+ JSCell* jsCell = jsValue.asCell();
+ if (Heap::isMarked(jsCell))
+ continue;
+
+ WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
+ if (!weakHandleOwner)
+ continue;
+
+ if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(jsValue)), weakImpl->context(), visitor))
+ continue;
+
+ heapRootVisitor.visit(&const_cast<JSValue&>(jsValue));
+ }
+}
+
+void WeakBlock::visitDeadWeakImpls(HeapRootVisitor&)
+{
+ // If a block is completely empty, a visit won't have any effect.
+ if (!m_sweepResult.isNull() && m_sweepResult.blockIsFree)
+ return;
+
+ for (size_t i = 0; i < weakImplCount(); ++i) {
+ WeakImpl* weakImpl = &weakImpls()[i];
+ if (weakImpl->state() > WeakImpl::Dead)
+ continue;
+
+ const JSValue& jsValue = weakImpl->jsValue();
+ if (!jsValue || !jsValue.isCell())
+ continue;
+
+ JSCell* jsCell = jsValue.asCell();
+ if (Heap::isMarked(jsCell))
+ continue;
+
+ weakImpl->setState(WeakImpl::Dead);
+ }
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WeakBlock_h
+#define WeakBlock_h
+
+#include "HeapBlock.h"
+#include "WeakHandleOwner.h"
+#include "WeakImpl.h"
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/PageAllocationAligned.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+class HeapRootVisitor;
+class JSValue;
+class WeakHandleOwner;
+
+class WeakBlock : public HeapBlock {
+public:
+ static const size_t blockSize = 4 * KB;
+ static const size_t blockMask = ~(blockSize - 1);
+
+ struct FreeCell {
+ FreeCell* next;
+ };
+
+ struct SweepResult {
+ SweepResult();
+ bool isNull() const;
+
+ bool blockIsFree;
+ FreeCell* freeList;
+ };
+
+ static WeakBlock* create();
+ static void destroy(WeakBlock*);
+
+ static WeakBlock* blockFor(WeakImpl*);
+ static WeakImpl* asWeakImpl(FreeCell*);
+
+ void sweep();
+ const SweepResult& sweepResult();
+ SweepResult takeSweepResult();
+
+ void deallocate(WeakImpl*);
+
+ void visitLiveWeakImpls(HeapRootVisitor&);
+ void visitDeadWeakImpls(HeapRootVisitor&);
+
+ void finalizeAll();
+
+private:
+ static FreeCell* asFreeCell(WeakImpl*);
+
+ WeakBlock(PageAllocationAligned&);
+ WeakImpl* firstWeakImpl();
+ void finalize(WeakImpl*);
+ WeakImpl* weakImpls();
+ size_t weakImplCount();
+ void addToFreeList(FreeCell**, WeakImpl*);
+
+ SweepResult m_sweepResult;
+};
+
+inline WeakBlock::SweepResult::SweepResult()
+ : blockIsFree(true)
+ , freeList(0)
+{
+ ASSERT(isNull());
+}
+
+inline bool WeakBlock::SweepResult::isNull() const
+{
+ return blockIsFree && !freeList; // This state is impossible, so we can use it to mean null.
+}
+
+inline WeakBlock* WeakBlock::blockFor(WeakImpl* weakImpl)
+{
+ return reinterpret_cast<WeakBlock*>(reinterpret_cast<uintptr_t>(weakImpl) & blockMask);
+}
+
+inline WeakImpl* WeakBlock::asWeakImpl(FreeCell* freeCell)
+{
+ return reinterpret_cast<WeakImpl*>(freeCell);
+}
+
+inline WeakBlock::SweepResult WeakBlock::takeSweepResult()
+{
+ SweepResult tmp;
+ std::swap(tmp, m_sweepResult);
+ ASSERT(m_sweepResult.isNull());
+ return tmp;
+}
+
+inline const WeakBlock::SweepResult& WeakBlock::sweepResult()
+{
+ return m_sweepResult;
+}
+
+inline WeakBlock::FreeCell* WeakBlock::asFreeCell(WeakImpl* weakImpl)
+{
+ return reinterpret_cast<FreeCell*>(weakImpl);
+}
+
+inline void WeakBlock::deallocate(WeakImpl* weakImpl)
+{
+ weakImpl->setState(WeakImpl::Deallocated);
+}
+
+inline void WeakBlock::finalize(WeakImpl* weakImpl)
+{
+ ASSERT(weakImpl->state() == WeakImpl::Dead);
+ weakImpl->setState(WeakImpl::Finalized);
+ WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
+ if (!weakHandleOwner)
+ return;
+ weakHandleOwner->finalize(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(weakImpl->jsValue())), weakImpl->context());
+}
+
+inline WeakImpl* WeakBlock::weakImpls()
+{
+ return reinterpret_cast<WeakImpl*>(this) + ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
+}
+
+inline size_t WeakBlock::weakImplCount()
+{
+ return (blockSize / sizeof(WeakImpl)) - ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
+}
+
+inline void WeakBlock::addToFreeList(FreeCell** freeList, WeakImpl* weakImpl)
+{
+ ASSERT(weakImpl->state() == WeakImpl::Deallocated);
+ FreeCell* freeCell = asFreeCell(weakImpl);
+ ASSERT(!*freeList || ((char*)*freeList > (char*)this && (char*)*freeList < (char*)this + blockSize));
+ ASSERT((char*)freeCell > (char*)this && (char*)freeCell < (char*)this + blockSize);
+ freeCell->next = *freeList;
+ *freeList = freeCell;
+}
+
+} // namespace JSC
+
+#endif // WeakBlock_h
--- /dev/null
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WeakHandleOwner.h"
+
+namespace JSC {
+
+class SlotVisitor;
+template<typename T> class Handle;
+
+WeakHandleOwner::~WeakHandleOwner()
+{
+}
+
+bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, SlotVisitor&)
+{
+ return false;
+}
+
+void WeakHandleOwner::finalize(Handle<Unknown>, void*)
+{
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WeakHandleOwner_h
+#define WeakHandleOwner_h
+
+#include "Handle.h"
+
+namespace JSC {
+
+class SlotVisitor;
+
+class JS_EXPORT_PRIVATE WeakHandleOwner {
+public:
+ virtual ~WeakHandleOwner();
+ virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&);
+ virtual void finalize(Handle<Unknown>, void* context);
+};
+
+} // namespace JSC
+
+#endif // WeakHandleOwner_h
--- /dev/null
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WeakHeap.h"
+
+#include "Heap.h"
+
+namespace JSC {
+
+WeakHeap::~WeakHeap()
+{
+ WeakBlock* next = 0;
+ for (WeakBlock* block = static_cast<WeakBlock*>(m_blocks.head()); block; block = next) {
+ next = static_cast<WeakBlock*>(block->next());
+ WeakBlock::destroy(block);
+ }
+ m_blocks.clear();
+}
+
+void WeakHeap::finalizeAll()
+{
+ for (WeakBlock* block = static_cast<WeakBlock*>(m_blocks.head()); block; block = static_cast<WeakBlock*>(block->next()))
+ block->finalizeAll();
+}
+
+void WeakHeap::visitLiveWeakImpls(HeapRootVisitor& visitor)
+{
+ for (WeakBlock* block = static_cast<WeakBlock*>(m_blocks.head()); block; block = static_cast<WeakBlock*>(block->next()))
+ block->visitLiveWeakImpls(visitor);
+}
+
+void WeakHeap::visitDeadWeakImpls(HeapRootVisitor& visitor)
+{
+ for (WeakBlock* block = static_cast<WeakBlock*>(m_blocks.head()); block; block = static_cast<WeakBlock*>(block->next()))
+ block->visitDeadWeakImpls(visitor);
+}
+
+void WeakHeap::sweep()
+{
+ WeakBlock* next;
+ for (WeakBlock* block = static_cast<WeakBlock*>(m_blocks.head()); block; block = next) {
+ next = static_cast<WeakBlock*>(block->next());
+
+ // If a block is completely empty, a new sweep won't have any effect.
+ if (!block->sweepResult().isNull() && block->sweepResult().blockIsFree)
+ continue;
+
+ block->takeSweepResult(); // Force a new sweep by discarding the last sweep.
+ block->sweep();
+ }
+}
+
+void WeakHeap::resetAllocator()
+{
+ m_allocator = 0;
+ m_nextAllocator = static_cast<WeakBlock*>(m_blocks.head());
+}
+
+WeakBlock::FreeCell* WeakHeap::findAllocator()
+{
+ if (WeakBlock::FreeCell* allocator = tryFindAllocator())
+ return allocator;
+
+ m_heap->addToWaterMark(WeakBlock::blockSize);
+
+ // addToWaterMark() may cause a GC, so try again.
+ if (WeakBlock::FreeCell* allocator = tryFindAllocator())
+ return allocator;
+
+ return addAllocator();
+}
+
+WeakBlock::FreeCell* WeakHeap::tryFindAllocator()
+{
+ while (m_nextAllocator) {
+ WeakBlock* block = m_nextAllocator;
+ m_nextAllocator = static_cast<WeakBlock*>(m_nextAllocator->next());
+
+ block->sweep();
+ WeakBlock::SweepResult sweepResult = block->takeSweepResult();
+ if (sweepResult.freeList)
+ return sweepResult.freeList;
+ }
+
+ return 0;
+}
+
+WeakBlock::FreeCell* WeakHeap::addAllocator()
+{
+ WeakBlock* block = WeakBlock::create();
+ m_blocks.append(block);
+ WeakBlock::SweepResult sweepResult = block->takeSweepResult();
+ ASSERT(!sweepResult.isNull() && sweepResult.freeList);
+ return sweepResult.freeList;
+}
+
+void WeakHeap::removeAllocator(WeakBlock* block)
+{
+ m_blocks.remove(block);
+ WeakBlock::destroy(block);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WeakHeap_h
+#define WeakHeap_h
+
+#include "WeakBlock.h"
+
+namespace JSC {
+
+class Heap;
+class WeakImpl;
+
+class WeakHeap {
+public:
+ WeakHeap(Heap*);
+ void finalizeAll();
+ ~WeakHeap();
+
+ WeakImpl* allocate(JSValue, WeakHandleOwner* = 0, void* context = 0);
+ static void deallocate(WeakImpl*);
+
+ void visitLiveWeakImpls(HeapRootVisitor&);
+ void visitDeadWeakImpls(HeapRootVisitor&);
+
+ void sweep();
+ void resetAllocator();
+
+private:
+ JS_EXPORT_PRIVATE WeakBlock::FreeCell* findAllocator();
+ WeakBlock::FreeCell* tryFindAllocator();
+ WeakBlock::FreeCell* addAllocator();
+ void removeAllocator(WeakBlock*);
+
+ WeakBlock::FreeCell* m_allocator;
+ WeakBlock* m_nextAllocator;
+ DoublyLinkedList<HeapBlock> m_blocks;
+ Heap* m_heap;
+};
+
+inline WeakHeap::WeakHeap(Heap* heap)
+ : m_allocator(0)
+ , m_nextAllocator(0)
+ , m_heap(heap)
+{
+}
+
+inline WeakImpl* WeakHeap::allocate(JSValue jsValue, WeakHandleOwner* weakHandleOwner, void* context)
+{
+ WeakBlock::FreeCell* allocator = m_allocator;
+ if (UNLIKELY(!allocator))
+ allocator = findAllocator();
+ m_allocator = allocator->next;
+
+ WeakImpl* weakImpl = WeakBlock::asWeakImpl(allocator);
+ return new (NotNull, weakImpl) WeakImpl(jsValue, weakHandleOwner, context);
+}
+
+inline void WeakHeap::deallocate(WeakImpl* weakImpl)
+{
+ WeakBlock::blockFor(weakImpl)->deallocate(weakImpl);
+}
+
+} // namespace JSC
+
+#endif // WeakHeap_h
--- /dev/null
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WeakImpl_h
+#define WeakImpl_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+class WeakHandleOwner;
+
+class WeakImpl {
+public:
+ enum State {
+ Live = 0x0,
+ Dead = 0x1,
+ Finalized = 0x2,
+ Deallocated = 0x3
+ };
+
+ enum {
+ StateMask = 0x3
+ };
+
+ WeakImpl();
+ WeakImpl(JSValue, WeakHandleOwner*, void* context);
+
+ State state();
+ void setState(State);
+
+ const JSValue& jsValue();
+ WeakHandleOwner* weakHandleOwner();
+ void* context();
+
+ static WeakImpl* asWeakImpl(JSValue*);
+
+private:
+ const JSValue m_jsValue;
+ WeakHandleOwner* m_weakHandleOwner;
+ void* m_context;
+};
+
+inline WeakImpl::WeakImpl()
+ : m_weakHandleOwner(0)
+ , m_context(0)
+{
+ setState(Deallocated);
+}
+
+inline WeakImpl::WeakImpl(JSValue jsValue, WeakHandleOwner* weakHandleOwner, void* context)
+ : m_jsValue(jsValue)
+ , m_weakHandleOwner(weakHandleOwner)
+ , m_context(context)
+{
+ ASSERT(state() == Live);
+}
+
+inline WeakImpl::State WeakImpl::state()
+{
+ return static_cast<State>(reinterpret_cast<uintptr_t>(m_weakHandleOwner) & StateMask);
+}
+
+inline void WeakImpl::setState(WeakImpl::State state)
+{
+ ASSERT(state >= this->state());
+ m_weakHandleOwner = reinterpret_cast<WeakHandleOwner*>((reinterpret_cast<uintptr_t>(m_weakHandleOwner) & ~StateMask) | state);
+}
+
+inline const JSValue& WeakImpl::jsValue()
+{
+ return m_jsValue;
+}
+
+inline WeakHandleOwner* WeakImpl::weakHandleOwner()
+{
+ return reinterpret_cast<WeakHandleOwner*>((reinterpret_cast<uintptr_t>(m_weakHandleOwner) & ~StateMask));
+}
+
+inline void* WeakImpl::context()
+{
+ return m_context;
+}
+
+inline WeakImpl* WeakImpl::asWeakImpl(JSValue* slot)
+{
+ return reinterpret_cast<WeakImpl*>(reinterpret_cast<char*>(slot) + OBJECT_OFFSETOF(WeakImpl, m_jsValue));
+}
+
+} // namespace JSC
+
+#endif // WeakImpl_h
NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic)
{
HostFunctionStubMap::AddResult entry = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>());
- if (!*entry.iterator->second) {
+ if (!entry.iterator->second) {
MacroAssemblerCodeRef code;
if (generator) {
if (globalData->canUseJIT())
template<typename To, typename From>
inline To jsCast(From* from)
{
- ASSERT(from->inherits(&WTF::RemovePointer<To>::Type::s_info));
+ ASSERT(!from || from->inherits(&WTF::RemovePointer<To>::Type::s_info));
return static_cast<To>(from);
}
// There already is an entry! - we should only hit this when despecifying.
ASSERT(result.iterator.get().second->m_specificValueInPrevious);
ASSERT(!structure->m_specificValueInPrevious);
- map()->set(result.iterator, structure);
+ map()->set(globalData, result.iterator.get().first, structure);
}
}
namespace JSC {
+class JSCell;
class Structure;
class StructureTransitionTable {
return;
}
- HandleSlot slot = this->slot();
- if (!slot)
+ WeakImpl* impl = this->weakImpl();
+ if (!impl)
return;
- HandleHeap::heapFor(slot)->deallocate(slot);
+ WeakHeap::deallocate(impl);
}
inline void add(JSGlobalData&, Structure*);
return reinterpret_cast<TransitionMap*>(m_data);
}
- HandleSlot slot() const
+ WeakImpl* weakImpl() const
{
ASSERT(isUsingSingleSlot());
- return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag);
+ return reinterpret_cast<WeakImpl*>(m_data & ~UsingSingleSlotFlag);
}
void setMap(TransitionMap* map)
{
ASSERT(isUsingSingleSlot());
- if (HandleSlot slot = this->slot())
- HandleHeap::heapFor(slot)->deallocate(slot);
+ if (WeakImpl* impl = this->weakImpl())
+ WeakHeap::deallocate(impl);
// This implicitly clears the flag that indicates we're using a single transition
m_data = reinterpret_cast<intptr_t>(map);
Structure* singleTransition() const
{
ASSERT(isUsingSingleSlot());
- if (HandleSlot slot = this->slot()) {
- if (*slot)
- return reinterpret_cast<Structure*>(slot->asCell());
+ if (WeakImpl* impl = this->weakImpl()) {
+ if (impl->state() == WeakImpl::Live)
+ return reinterpret_cast<Structure*>(impl->jsValue().asCell());
}
return 0;
}
void setSingleTransition(JSGlobalData& globalData, Structure* structure)
{
ASSERT(isUsingSingleSlot());
- HandleSlot slot = this->slot();
- if (!slot) {
- slot = globalData.heap.handleHeap()->allocate();
- HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0);
- m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag;
- }
- HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure));
- *slot = reinterpret_cast<JSCell*>(structure);
+ if (WeakImpl* impl = this->weakImpl())
+ WeakHeap::deallocate(impl);
+ WeakImpl* impl = globalData.heap.weakHeap()->allocate(reinterpret_cast<JSCell*>(structure));
+ m_data = reinterpret_cast<intptr_t>(impl) | UsingSingleSlotFlag;
}
intptr_t m_data;
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(WeakGCMap);
- typedef HashMap<KeyType, HandleSlot, HashArg, KeyTraitsArg> MapType;
+ typedef HashMap<KeyType, WeakImpl*, HashArg, KeyTraitsArg> MapType;
typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
typedef typename MapType::iterator map_iterator;
{
}
- std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(m_iterator->second)); }
- std::pair<KeyType, HandleSlot> getSlot() const { return *m_iterator; }
+ std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_iterator->second->jsValue()))); }
iterator& operator++() { ++m_iterator; return *this; }
{
map_iterator end = m_map.end();
for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
- HandleHeap::heapFor(ptr->second)->deallocate(ptr->second);
+ WeakHeap::deallocate(ptr->second);
m_map.clear();
}
void remove(iterator iter)
{
ASSERT(iter.m_iterator != m_map.end());
- HandleSlot slot = iter.m_iterator->second;
- ASSERT(slot);
- HandleHeap::heapFor(slot)->deallocate(slot);
+ WeakImpl* impl = iter.m_iterator->second;
+ ASSERT(impl);
+ WeakHeap::deallocate(impl);
m_map.remove(iter.m_iterator);
}
ExternalType get(const KeyType& key) const
{
- return HandleTypes<MappedType>::getFromSlot(m_map.get(key));
- }
-
- HandleSlot getSlot(const KeyType& key) const
- {
- return m_map.get(key);
+ return HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_map.get(key)->jsValue()));
}
AddResult add(JSGlobalData& globalData, const KeyType& key, ExternalType value)
{
typename MapType::AddResult result = m_map.add(key, 0);
- if (result.isNewEntry) {
- HandleSlot slot = globalData.heap.handleHeap()->allocate();
- result.iterator->second = slot;
- HandleHeap::heapFor(slot)->makeWeak(slot, this, FinalizerCallback::finalizerContextFor(key));
- HandleHeap::heapFor(slot)->writeBarrier(slot, value);
- *slot = value;
- }
+ if (result.isNewEntry)
+ result.iterator->second = globalData.heap.weakHeap()->allocate(value, this, FinalizerCallback::finalizerContextFor(key));
+
// WeakGCMap exposes a different iterator, so we need to wrap it and create our own AddResult.
return AddResult(iterator(result.iterator), result.isNewEntry);
}
-
- void set(iterator iter, ExternalType value)
- {
- HandleSlot slot = iter.m_iterator->second;
- ASSERT(slot);
- HandleHeap::heapFor(slot)->writeBarrier(slot, value);
- *slot = value;
- }
void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
{
typename MapType::AddResult result = m_map.add(key, 0);
- HandleSlot slot = result.iterator->second;
- if (result.isNewEntry) {
- slot = globalData.heap.handleHeap()->allocate();
- HandleHeap::heapFor(slot)->makeWeak(slot, this, key);
- result.iterator->second = slot;
- }
- HandleHeap::heapFor(slot)->writeBarrier(slot, value);
- *slot = value;
+ if (!result.isNewEntry)
+ WeakHeap::deallocate(result.iterator->second);
+ result.iterator->second = globalData.heap.weakHeap()->allocate(value, this, FinalizerCallback::finalizerContextFor(key));
}
ExternalType take(const KeyType& key)
{
- HandleSlot slot = m_map.take(key);
- if (!slot)
+ WeakImpl* impl = m_map.take(key);
+ if (!impl)
return HashTraits<ExternalType>::emptyValue();
- ExternalType result = HandleTypes<MappedType>::getFromSlot(slot);
- HandleHeap::heapFor(slot)->deallocate(slot);
+ ExternalType result = HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&impl->jsValue()));
+ WeakHeap::deallocate(impl);
return result;
}
private:
virtual void finalize(Handle<Unknown> handle, void* context)
{
- HandleSlot slot = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot())));
- ASSERT(slot);
- HandleHeap::heapFor(slot)->deallocate(slot);
+ WeakImpl* impl = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot())));
+ ASSERT(impl);
+ WeakHeap::deallocate(impl);
}
MapType m_map;
+2012-03-29 Geoffrey Garen <ggaren@apple.com>
+
+ First step toward incremental Weak<T> finalization
+ https://bugs.webkit.org/show_bug.cgi?id=82670
+
+ Reviewed by Filip Pizlo.
+
+ Updated WebCore for Weak<T> API changes.
+
+ * bindings/js/DOMWrapperWorld.cpp:
+ (WebCore::JSStringOwner::finalize): We're not allowed to get() a dead Weak<T>
+ anymore, so use the debug-only was() helper function instead.
+
+ * bindings/js/JSDOMBinding.h:
+ (WebCore::uncacheWrapper): Ditto.
+
+ * bindings/js/JSNodeCustom.h:
+ (WebCore::setInlineCachedWrapper):
+ (WebCore::clearInlineCachedWrapper): We're not allowed to get() a dead
+ Weak<T>, so I had to push down these ASSERTs into ScriptWrappable.
+
+ * bindings/js/JSNodeFilterCondition.cpp:
+ (WebCore::JSNodeFilterCondition::acceptNode): Updated for non-Handle-ness
+ of Weak<T>.
+
+ * bindings/js/ScriptWrappable.h:
+ (WebCore::ScriptWrappable::setWrapper):
+ (WebCore::ScriptWrappable::clearWrapper): Use was(), as above.
+
2012-04-03 Luke Macpherson <macpherson@chromium.org>
Don't parse "show" and "hide" as valid values for display property.
{
JSString* jsString = static_cast<JSString*>(handle.get().asCell());
StringImpl* stringImpl = static_cast<StringImpl*>(context);
- ASSERT_UNUSED(jsString, m_world->m_stringCache.find(stringImpl)->second.get() == jsString);
+ ASSERT_UNUSED(jsString, m_world->m_stringCache.find(stringImpl)->second.was(jsString));
m_world->m_stringCache.remove(stringImpl);
}
{
if (clearInlineCachedWrapper(world, domObject, wrapper))
return;
- ASSERT(world->m_wrappers.find(domObject)->second.get() == wrapper);
+ ASSERT(world->m_wrappers.find(domObject)->second.was(wrapper));
world->m_wrappers.remove(domObject);
}
{
if (!world->isNormal())
return false;
- ASSERT(!node->wrapper());
node->setWrapper(*world->globalData(), wrapper, wrapperOwner(world, node), wrapperContext(world, node));
return true;
}
{
if (!world->isNormal())
return false;
- ASSERT_UNUSED(wrapper, node->wrapper() == wrapper);
- node->clearWrapper();
+ node->clearWrapper(wrapper);
return true;
}
{
JSLock lock(SilenceAssertionsOnly);
- if (!m_filter.isObject())
+ if (!m_filter || !m_filter->isObject())
return NodeFilter::FILTER_ACCEPT;
// The exec argument here should only be null if this was called from a
void setWrapper(JSC::JSGlobalData& globalData, JSDOMWrapper* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context)
{
+ ASSERT(!m_wrapper);
m_wrapper = JSC::PassWeak<JSDOMWrapper>(globalData, wrapper, wrapperOwner, context);
}
- void clearWrapper()
+ void clearWrapper(JSDOMWrapper* wrapper)
{
+ ASSERT_UNUSED(wrapper, m_wrapper.was(wrapper));
m_wrapper.clear();
}
+2012-03-29 Geoffrey Garen <ggaren@apple.com>
+
+ First step toward incremental Weak<T> finalization
+ https://bugs.webkit.org/show_bug.cgi?id=82670
+
+ Reviewed by Filip Pizlo.
+
+ Updated for API change.
+
+ * WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:
+ (WebKit::NPRuntimeObjectMap::finalize):
+
2012-04-03 Keishi Hattori <keishi@webkit.org>
Disable ENABLE_DATALIST for now
{
HashMap<NPObject*, JSC::Weak<JSNPObject> >::iterator found = m_jsNPObjects.find(static_cast<NPObject*>(context));
ASSERT(found != m_jsNPObjects.end());
- ASSERT_UNUSED(handle, asObject(handle.get()) == found->second);
+ ASSERT_UNUSED(handle, asObject(handle.get()) == found->second.get());
JSNPObject* object = found->second.get();
m_jsNPObjects.remove(found);
addToInvalidationQueue(object->leakNPObject());
#include <WebCore/HTTPHeaderMap.h>
#include <WebCore/IntRect.h>
#include <WebCore/KURL.h>
+#include <runtime/JSObject.h>
+#include <runtime/ScopeChain.h>
#include <utility>
#include <wtf/text/CString.h>
#if ENABLE(PLUGIN_PROCESS)
+#include <runtime/JSObject.h>
+#include <runtime/ScopeChain.h>
#include "NPRemoteObjectMap.h"
#include "NPRuntimeObjectMap.h"
#include "PluginProcessConnectionManager.h"