Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (94444 => 94445)
--- trunk/Source/_javascript_Core/ChangeLog 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-09-02 20:41:59 UTC (rev 94445)
@@ -1,3 +1,42 @@
+2011-09-02 Oliver Hunt <[email protected]>
+
+ Use bump allocator for initial property storage
+ https://bugs.webkit.org/show_bug.cgi?id=67494
+
+ Reviewed by Gavin Barraclough.
+
+ Switch to a bump allocator for the initial out of line
+ property storage. This gives us slightly faster allocation
+ for short lived objects that need out of line storage at
+ the cost of an additional memcpy when the object survives
+ a GC pass.
+
+ No performance impact.
+
+ * _javascript_Core.exp:
+ * heap/Heap.cpp:
+ (JSC::Heap::collect):
+ * heap/Heap.h:
+ (JSC::Heap::allocatePropertyStorage):
+ (JSC::Heap::inPropertyStorageNursary):
+ * heap/NewSpace.cpp:
+ (JSC::NewSpace::NewSpace):
+ * heap/NewSpace.h:
+ (JSC::NewSpace::resetPropertyStorageNursary):
+ (JSC::NewSpace::allocatePropertyStorage):
+ (JSC::NewSpace::inPropertyStorageNursary):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::allocatePropertyStorage):
+ * runtime/JSObject.h:
+ (JSC::JSObject::~JSObject):
+ (JSC::JSObject::putDirectInternal):
+ (JSC::JSObject::putDirectWithoutTransition):
+ (JSC::JSObject::putDirectFunctionWithoutTransition):
+ (JSC::JSObject::transitionTo):
+ (JSC::JSObject::visitChildrenDirect):
+
2011-09-01 Mark Rowe <[email protected]>
Fix the build.
Modified: trunk/Source/_javascript_Core/_javascript_Core.exp (94444 => 94445)
--- trunk/Source/_javascript_Core/_javascript_Core.exp 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/_javascript_Core.exp 2011-09-02 20:41:59 UTC (rev 94445)
@@ -216,6 +216,7 @@
__ZN3JSC22globalMemoryStatisticsEv
__ZN3JSC22objectConstructorTableE
__ZN3JSC23AbstractSamplingCounter4dumpEv
+__ZN3JSC23AbstractSamplingCounter30s_abstractSamplingCounterChainE
__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC24DynamicGlobalObjectScopeC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectE
@@ -322,7 +323,7 @@
__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
__ZN3JSC8JSObject21getPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_16WriteBarrierBaseINS_7UnknownEEE
-__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSC8JSObject23allocatePropertyStorageERNS_12JSGlobalDataEmm
__ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def (94444 => 94445)
--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def 2011-09-02 20:41:59 UTC (rev 94445)
@@ -54,7 +54,7 @@
?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVExecState@2@PAVStringImpl@4@@Z
?addStaticGlobals@JSGlobalObject@JSC@@IAEXPAUGlobalPropertyInfo@12@H@Z
?allocate@Heap@JSC@@QAEPAXAAUSizeClass@NewSpace@2@@Z
- ?allocatePropertyStorage@JSObject@JSC@@QAEXII@Z
+ ?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z
?allocateSlowCase@Heap@JSC@@AAEPAXAAUSizeClass@NewSpace@2@@Z
?append@StringBuilder@WTF@@QAEXPBDI@Z
?append@StringBuilder@WTF@@QAEXPB_WI@Z
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (94444 => 94445)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2011-09-02 20:41:59 UTC (rev 94445)
@@ -683,7 +683,7 @@
// new bytes allocated) proportion, and seems to work well in benchmarks.
size_t proportionalBytes = 2 * size();
m_newSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));
-
+ m_newSpace.resetPropertyStorageNursery();
_javascript_CORE_GC_END();
(*m_activityCallback)();
Modified: trunk/Source/_javascript_Core/heap/Heap.h (94444 => 94445)
--- trunk/Source/_javascript_Core/heap/Heap.h 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2011-09-02 20:41:59 UTC (rev 94445)
@@ -91,6 +91,9 @@
void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
void collectAllGarbage();
+ inline void* allocatePropertyStorage(size_t);
+ inline bool inPropertyStorageNursery(void*);
+
void reportExtraMemoryCost(size_t cost);
void protect(JSValue);
@@ -358,6 +361,22 @@
return allocate(sizeClass);
}
+ inline void* Heap::allocatePropertyStorage(size_t bytes)
+ {
+ ASSERT(!(bytes % sizeof(JSValue)));
+ if (bytes >= NewSpace::PropertyStorageNurserySize)
+ return fastMalloc(bytes);
+ if (void* result = m_newSpace.allocatePropertyStorage(bytes))
+ return result;
+ collect(DoNotSweep);
+ return m_newSpace.allocatePropertyStorage(bytes);
+ }
+
+ inline bool Heap::inPropertyStorageNursery(void* ptr)
+ {
+ return m_newSpace.inPropertyStorageNursery(ptr);
+ }
+
} // namespace JSC
#endif // Heap_h
Modified: trunk/Source/_javascript_Core/heap/NewSpace.cpp (94444 => 94445)
--- trunk/Source/_javascript_Core/heap/NewSpace.cpp 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/heap/NewSpace.cpp 2011-09-02 20:41:59 UTC (rev 94445)
@@ -32,7 +32,9 @@
class Structure;
NewSpace::NewSpace(Heap* heap)
- : m_waterMark(0)
+ : m_propertyStorageNursery(static_cast<char*>(fastMalloc(PropertyStorageNurserySize)))
+ , m_propertyStorageAllocationPoint(m_propertyStorageNursery)
+ , m_waterMark(0)
, m_highWaterMark(0)
, m_heap(heap)
{
Modified: trunk/Source/_javascript_Core/heap/NewSpace.h (94444 => 94445)
--- trunk/Source/_javascript_Core/heap/NewSpace.h 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/heap/NewSpace.h 2011-09-02 20:41:59 UTC (rev 94445)
@@ -46,6 +46,7 @@
WTF_MAKE_NONCOPYABLE(NewSpace);
public:
static const size_t maxCellSize = 1024;
+ static const ptrdiff_t PropertyStorageNurserySize = 1024 * 1024 * 4;
struct SizeClass {
SizeClass();
@@ -63,6 +64,10 @@
SizeClass& sizeClassFor(size_t);
void* allocate(SizeClass&);
+ inline void* allocatePropertyStorage(size_t);
+ inline bool inPropertyStorageNursery(void* ptr);
+ inline void resetPropertyStorageNursery();
+
void resetAllocator();
void addBlock(SizeClass&, MarkedBlock*);
@@ -91,6 +96,8 @@
SizeClass m_preciseSizeClasses[preciseCount];
SizeClass m_impreciseSizeClasses[impreciseCount];
+ char* m_propertyStorageNursery;
+ char* m_propertyStorageAllocationPoint;
size_t m_waterMark;
size_t m_highWaterMark;
Heap* m_heap;
@@ -160,6 +167,30 @@
return firstFreeCell;
}
+ inline void NewSpace::resetPropertyStorageNursery()
+ {
+ m_propertyStorageAllocationPoint = m_propertyStorageNursery;
+ }
+
+ inline void* NewSpace::allocatePropertyStorage(size_t size)
+ {
+ char* result = m_propertyStorageAllocationPoint;
+ if (size > static_cast<size_t>(PropertyStorageNurserySize))
+ CRASH();
+ m_propertyStorageAllocationPoint += size;
+ if ((m_propertyStorageAllocationPoint - m_propertyStorageNursery) > PropertyStorageNurserySize) {
+ m_propertyStorageAllocationPoint = result;
+ return 0;
+ }
+ return result;
+ }
+
+ inline bool NewSpace::inPropertyStorageNursery(void* ptr)
+ {
+ char* addr = static_cast<char*>(ptr);
+ return static_cast<uintptr_t>(addr - m_propertyStorageNursery) < PropertyStorageNurserySize;
+ }
+
template <typename Functor> inline typename Functor::ReturnType NewSpace::forEachBlock(Functor& functor)
{
for (size_t i = 0; i < preciseCount; ++i) {
Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (94444 => 94445)
--- trunk/Source/_javascript_Core/jit/JITStubs.cpp 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp 2011-09-02 20:41:59 UTC (rev 94445)
@@ -1481,7 +1481,7 @@
ASSERT(baseValue.isObject());
JSObject* base = asObject(baseValue);
- base->allocatePropertyStorage(oldSize, newSize);
+ base->allocatePropertyStorage(*stackFrame.globalData, oldSize, newSize);
return base;
}
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (94444 => 94445)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2011-09-02 20:41:59 UTC (rev 94445)
@@ -594,21 +594,20 @@
return m_inheritorID.get();
}
-void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
+void JSObject::allocatePropertyStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize)
{
ASSERT(newSize > oldSize);
// It's important that this function not rely on m_structure, since
// we might be in the middle of a transition.
- bool wasInline = (oldSize < JSObject::baseExternalStorageCapacity);
-
PropertyStorage oldPropertyStorage = m_propertyStorage;
- PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
+ PropertyStorage newPropertyStorage = static_cast<PropertyStorage>(globalData.heap.allocatePropertyStorage(newSize * sizeof(WriteBarrierBase<Unknown>)));
+ ASSERT(newPropertyStorage);
for (unsigned i = 0; i < oldSize; ++i)
newPropertyStorage[i] = oldPropertyStorage[i];
- if (!wasInline)
+ if (!isUsingInlineStorage() && !globalData.heap.inPropertyStorageNursery(oldPropertyStorage))
delete [] oldPropertyStorage;
m_propertyStorage = newPropertyStorage;
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (94444 => 94445)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2011-09-02 20:33:34 UTC (rev 94444)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2011-09-02 20:41:59 UTC (rev 94445)
@@ -221,7 +221,7 @@
virtual ComplType exceptionType() const { return Throw; }
- void allocatePropertyStorage(size_t oldSize, size_t newSize);
+ void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage) == static_cast<const void*>(this + 1); }
void* addressOfPropertyAtOffset(size_t offset)
@@ -463,7 +463,7 @@
inline JSObject::~JSObject()
{
- if (!isUsingInlineStorage())
+ if (!isUsingInlineStorage() && !Heap::heap(this)->inPropertyStorageNursery(m_propertyStorage))
delete [] m_propertyStorage;
}
@@ -657,7 +657,7 @@
size_t currentCapacity = m_structure->propertyStorageCapacity();
offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
if (currentCapacity != m_structure->propertyStorageCapacity())
- allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+ allocatePropertyStorage(globalData, currentCapacity, m_structure->propertyStorageCapacity());
ASSERT(offset < m_structure->propertyStorageCapacity());
putDirectOffset(globalData, offset, value);
@@ -671,7 +671,7 @@
size_t currentCapacity = m_structure->propertyStorageCapacity();
if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(m_structure.get(), propertyName, attributes, specificFunction, offset)) {
if (currentCapacity != structure->propertyStorageCapacity())
- allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
+ allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity());
ASSERT(offset < structure->propertyStorageCapacity());
setStructure(globalData, structure);
@@ -721,7 +721,7 @@
Structure* structure = Structure::addPropertyTransition(globalData, m_structure.get(), propertyName, attributes, specificFunction, offset);
if (currentCapacity != structure->propertyStorageCapacity())
- allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
+ allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity());
ASSERT(offset < structure->propertyStorageCapacity());
setStructure(globalData, structure);
@@ -782,7 +782,7 @@
size_t currentCapacity = m_structure->propertyStorageCapacity();
size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, 0);
if (currentCapacity != m_structure->propertyStorageCapacity())
- allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+ allocatePropertyStorage(globalData, currentCapacity, m_structure->propertyStorageCapacity());
putDirectOffset(globalData, offset, value);
}
@@ -791,14 +791,14 @@
size_t currentCapacity = m_structure->propertyStorageCapacity();
size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, value);
if (currentCapacity != m_structure->propertyStorageCapacity())
- allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+ allocatePropertyStorage(globalData, currentCapacity, m_structure->propertyStorageCapacity());
putDirectOffset(globalData, offset, value);
}
inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
{
if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
- allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
+ allocatePropertyStorage(globalData, m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
setStructure(globalData, newStructure);
}
@@ -889,6 +889,10 @@
JSCell::visitChildren(visitor);
PropertyStorage storage = propertyStorage();
+ if (Heap::heap(this)->inPropertyStorageNursery(storage)) {
+ m_propertyStorage = new WriteBarrierBase<Unknown>[structure()->propertyStorageCapacity()];
+ memcpy(m_propertyStorage, storage, m_structure->propertyStorageSize() * sizeof(WriteBarrierBase<Unknown>));
+ }
size_t storageSize = m_structure->propertyStorageSize();
visitor.appendValues(storage, storageSize);
if (m_inheritorID)