Commit dc3d148e authored by mhahnenberg@apple.com's avatar mhahnenberg@apple.com
Browse files

Structure should have a StructureRareData field to save space

https://bugs.webkit.org/show_bug.cgi?id=108659

Reviewed by Oliver Hunt.

Many of the fields in Structure are used in a subset of all total Structures; however, all Structures must 
pay the memory cost of those fields, regardless of whether they use them or not. Since we can have potentially 
many Structures on a single page (e.g. bing.com creates ~1500 Structures), it would be profitable to 
refactor Structure so that not every Structure has to pay the memory costs for these infrequently used fields.

To accomplish this, we can create a new StructureRareData class to house these seldom used fields which we 
can allocate on demand whenever a Structure requires it. This StructureRareData can itself be a JSCell, and 
can do all the marking of the fields for the Structure. The StructureRareData field will be part of a union 
with m_previous to minimize overhead. We'll add a new field to JSTypeInfo to indicate that the Structure has 
a StructureRareData field. During transitions, a Structure will clone its previous Structure's StructureRareData 
if it has one. There could be some potential for optimizing this process, but the initial implementation will 
be dumb since we'd be paying these overhead costs for each Structure anyways.

Initially we'll only put two fields in the StructureRareData to avoid a memory regression. Over time we'll 
continue to move fields from Structure to StructureRareData. Optimistically, this could potentially reduce our 
Structure memory footprint by up to around 75%. It could also clear the way for removing destructors from 
Structures (and into StructureRareData).

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* dfg/DFGRepatch.cpp: Includes for linking purposes.
* jit/JITStubs.cpp:
* jsc.cpp:
* llint/LLIntSlowPaths.cpp:
* runtime/JSCellInlines.h: Added ifdef guards.
* runtime/JSGlobalData.cpp: New Structure for StructureRareData class.
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSGlobalObject.h:
* runtime/JSTypeInfo.h: New flag to indicate whether or not a Structure has a StructureRareData field.
(JSC::TypeInfo::flags):
(JSC::TypeInfo::structureHasRareData):
* runtime/ObjectPrototype.cpp:
* runtime/Structure.cpp: We use a combined WriteBarrier<JSCell> field m_previousOrRareData to avoid compiler issues.
(JSC::Structure::dumpStatistics):
(JSC::Structure::Structure): 
(JSC::Structure::materializePropertyMap):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::nonPropertyTransition):
(JSC::Structure::pin):
(JSC::Structure::allocateRareData): Handles allocating a brand new StructureRareData field.
(JSC::Structure::cloneRareDataFrom): Handles cloning a StructureRareData field from another. Used during Structure 
transitions.
(JSC::Structure::visitChildren): We no longer have to worry about marking m_objectToStringValue.
* runtime/Structure.h:
(JSC::Structure::previousID): Checks the structureHasRareData flag to see where it should get the previous Structure.
(JSC::Structure::objectToStringValue): Reads the value from the StructureRareData. If it doesn't exist, returns 0.
(JSC::Structure::setObjectToStringValue): Ensures that we have a StructureRareData field, then forwards the function 
call to it.
(JSC::Structure::materializePropertyMapIfNecessary):
(JSC::Structure::setPreviousID): Checks for StructureRareData and forwards if necessary.
(Structure):
(JSC::Structure::clearPreviousID): Ditto.
(JSC::Structure::create):
* runtime/StructureRareData.cpp: Added. All of the basic functionality of a JSCell with the fields that we've moved 
from Structure and the functions required to access/modify those fields as Structure would have done.
(JSC):
(JSC::StructureRareData::createStructure):
(JSC::StructureRareData::create):
(JSC::StructureRareData::clone):
(JSC::StructureRareData::StructureRareData):
(JSC::StructureRareData::visitChildren):
* runtime/StructureRareData.h: Added.
(JSC):
(StructureRareData):
* runtime/StructureRareDataInlines.h: Added.
(JSC):
(JSC::StructureRareData::previousID):
(JSC::StructureRareData::setPreviousID):
(JSC::StructureRareData::clearPreviousID):
(JSC::Structure::previous): Handles the ugly casting to get the value of the right type of m_previousOrRareData.
(JSC::Structure::rareData): Ditto.
(JSC::StructureRareData::objectToStringValue):
(JSC::StructureRareData::setObjectToStringValue):

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* dfg/DFGRepatch.cpp:
* jit/JITStubs.cpp:
* jsc.cpp:
* llint/LLIntSlowPaths.cpp:
* runtime/JSCellInlines.h:
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSGlobalObject.h:
* runtime/JSTypeInfo.h:
(JSC):
(JSC::TypeInfo::flags):
(JSC::TypeInfo::structureHasRareData):
* runtime/ObjectPrototype.cpp:
* runtime/Structure.cpp:
(JSC::Structure::dumpStatistics):
(JSC::Structure::Structure):
(JSC::Structure::materializePropertyMap):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::nonPropertyTransition):
(JSC::Structure::pin):
(JSC::Structure::allocateRareData):
(JSC):
(JSC::Structure::cloneRareDataFrom):
(JSC::Structure::visitChildren):
* runtime/Structure.h:
(JSC::Structure::previousID):
(JSC::Structure::objectToStringValue):
(JSC::Structure::setObjectToStringValue):
(JSC::Structure::materializePropertyMapIfNecessary):
(JSC::Structure::setPreviousID):
(Structure):
(JSC::Structure::clearPreviousID):
(JSC::Structure::previous):
(JSC::Structure::rareData):
(JSC::Structure::create):
* runtime/StructureRareData.cpp: Added.
(JSC):
(JSC::StructureRareData::createStructure):
(JSC::StructureRareData::create):
(JSC::StructureRareData::clone):
(JSC::StructureRareData::StructureRareData):
(JSC::StructureRareData::visitChildren):
* runtime/StructureRareData.h: Added.
(JSC):
(StructureRareData):
* runtime/StructureRareDataInlines.h: Added.
(JSC):
(JSC::StructureRareData::previousID):
(JSC::StructureRareData::setPreviousID):
(JSC::StructureRareData::clearPreviousID):
(JSC::StructureRareData::objectToStringValue):
(JSC::StructureRareData::setObjectToStringValue):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@141651 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 003eb25d
......@@ -290,6 +290,7 @@ set(JavaScriptCore_SOURCES
runtime/StringPrototype.cpp
runtime/StringRecursionChecker.cpp
runtime/Structure.cpp
runtime/StructureRareData.cpp
runtime/StructureChain.cpp
runtime/SymbolTable.cpp
runtime/TimeoutChecker.cpp
......
2013-02-01 Mark Hahnenberg <mhahnenberg@apple.com>
Structure should have a StructureRareData field to save space
https://bugs.webkit.org/show_bug.cgi?id=108659
Reviewed by Oliver Hunt.
Many of the fields in Structure are used in a subset of all total Structures; however, all Structures must
pay the memory cost of those fields, regardless of whether they use them or not. Since we can have potentially
many Structures on a single page (e.g. bing.com creates ~1500 Structures), it would be profitable to
refactor Structure so that not every Structure has to pay the memory costs for these infrequently used fields.
To accomplish this, we can create a new StructureRareData class to house these seldom used fields which we
can allocate on demand whenever a Structure requires it. This StructureRareData can itself be a JSCell, and
can do all the marking of the fields for the Structure. The StructureRareData field will be part of a union
with m_previous to minimize overhead. We'll add a new field to JSTypeInfo to indicate that the Structure has
a StructureRareData field. During transitions, a Structure will clone its previous Structure's StructureRareData
if it has one. There could be some potential for optimizing this process, but the initial implementation will
be dumb since we'd be paying these overhead costs for each Structure anyways.
Initially we'll only put two fields in the StructureRareData to avoid a memory regression. Over time we'll
continue to move fields from Structure to StructureRareData. Optimistically, this could potentially reduce our
Structure memory footprint by up to around 75%. It could also clear the way for removing destructors from
Structures (and into StructureRareData).
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* dfg/DFGRepatch.cpp: Includes for linking purposes.
* jit/JITStubs.cpp:
* jsc.cpp:
* llint/LLIntSlowPaths.cpp:
* runtime/JSCellInlines.h: Added ifdef guards.
* runtime/JSGlobalData.cpp: New Structure for StructureRareData class.
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSGlobalObject.h:
* runtime/JSTypeInfo.h: New flag to indicate whether or not a Structure has a StructureRareData field.
(JSC::TypeInfo::flags):
(JSC::TypeInfo::structureHasRareData):
* runtime/ObjectPrototype.cpp:
* runtime/Structure.cpp: We use a combined WriteBarrier<JSCell> field m_previousOrRareData to avoid compiler issues.
(JSC::Structure::dumpStatistics):
(JSC::Structure::Structure):
(JSC::Structure::materializePropertyMap):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::nonPropertyTransition):
(JSC::Structure::pin):
(JSC::Structure::allocateRareData): Handles allocating a brand new StructureRareData field.
(JSC::Structure::cloneRareDataFrom): Handles cloning a StructureRareData field from another. Used during Structure
transitions.
(JSC::Structure::visitChildren): We no longer have to worry about marking m_objectToStringValue.
* runtime/Structure.h:
(JSC::Structure::previousID): Checks the structureHasRareData flag to see where it should get the previous Structure.
(JSC::Structure::objectToStringValue): Reads the value from the StructureRareData. If it doesn't exist, returns 0.
(JSC::Structure::setObjectToStringValue): Ensures that we have a StructureRareData field, then forwards the function
call to it.
(JSC::Structure::materializePropertyMapIfNecessary):
(JSC::Structure::setPreviousID): Checks for StructureRareData and forwards if necessary.
(Structure):
(JSC::Structure::clearPreviousID): Ditto.
(JSC::Structure::create):
* runtime/StructureRareData.cpp: Added. All of the basic functionality of a JSCell with the fields that we've moved
from Structure and the functions required to access/modify those fields as Structure would have done.
(JSC):
(JSC::StructureRareData::createStructure):
(JSC::StructureRareData::create):
(JSC::StructureRareData::clone):
(JSC::StructureRareData::StructureRareData):
(JSC::StructureRareData::visitChildren):
* runtime/StructureRareData.h: Added.
(JSC):
(StructureRareData):
* runtime/StructureRareDataInlines.h: Added.
(JSC):
(JSC::StructureRareData::previousID):
(JSC::StructureRareData::setPreviousID):
(JSC::StructureRareData::clearPreviousID):
(JSC::Structure::previous): Handles the ugly casting to get the value of the right type of m_previousOrRareData.
(JSC::Structure::rareData): Ditto.
(JSC::StructureRareData::objectToStringValue):
(JSC::StructureRareData::setObjectToStringValue):
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* dfg/DFGRepatch.cpp:
* jit/JITStubs.cpp:
* jsc.cpp:
* llint/LLIntSlowPaths.cpp:
* runtime/JSCellInlines.h:
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSGlobalObject.h:
* runtime/JSTypeInfo.h:
(JSC):
(JSC::TypeInfo::flags):
(JSC::TypeInfo::structureHasRareData):
* runtime/ObjectPrototype.cpp:
* runtime/Structure.cpp:
(JSC::Structure::dumpStatistics):
(JSC::Structure::Structure):
(JSC::Structure::materializePropertyMap):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::nonPropertyTransition):
(JSC::Structure::pin):
(JSC::Structure::allocateRareData):
(JSC):
(JSC::Structure::cloneRareDataFrom):
(JSC::Structure::visitChildren):
* runtime/Structure.h:
(JSC::Structure::previousID):
(JSC::Structure::objectToStringValue):
(JSC::Structure::setObjectToStringValue):
(JSC::Structure::materializePropertyMapIfNecessary):
(JSC::Structure::setPreviousID):
(Structure):
(JSC::Structure::clearPreviousID):
(JSC::Structure::previous):
(JSC::Structure::rareData):
(JSC::Structure::create):
* runtime/StructureRareData.cpp: Added.
(JSC):
(JSC::StructureRareData::createStructure):
(JSC::StructureRareData::create):
(JSC::StructureRareData::clone):
(JSC::StructureRareData::StructureRareData):
(JSC::StructureRareData::visitChildren):
* runtime/StructureRareData.h: Added.
(JSC):
(StructureRareData):
* runtime/StructureRareDataInlines.h: Added.
(JSC):
(JSC::StructureRareData::previousID):
(JSC::StructureRareData::setPreviousID):
(JSC::StructureRareData::clearPreviousID):
(JSC::StructureRareData::objectToStringValue):
(JSC::StructureRareData::setObjectToStringValue):
2013-02-01 Balazs Kilvady <kilvadyb@homejinni.com>
 
offlineasm BaseIndex handling is broken on ARM due to MIPS changes
......
......@@ -748,6 +748,9 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/StructureChain.h \
Source/JavaScriptCore/runtime/Structure.cpp \
Source/JavaScriptCore/runtime/Structure.h \
Source/JavaScriptCore/runtime/StructureRareData.cpp \
Source/JavaScriptCore/runtime/StructureRareData.h \
Source/JavaScriptCore/runtime/StructureRareDataInlines.h \
Source/JavaScriptCore/runtime/StructureTransitionTable.h \
Source/JavaScriptCore/runtime/SymbolTable.cpp \
Source/JavaScriptCore/runtime/SymbolTable.h \
......
......@@ -1337,6 +1337,18 @@
RelativePath="..\..\runtime\StructureChain.h"
>
</File>
<File
RelativePath="..\..\runtime\StructureRareData.cpp"
>
</File>
<File
RelativePath="..\..\runtime\StructureRareData.h"
>
</File>
<File
RelativePath="..\..\runtime\StructureRareDataInlines.h"
>
</File>
<File
RelativePath="..\..\runtime\StructureTransitionTable.h"
>
......
......@@ -790,6 +790,7 @@
BCF605140E203EF800B9A64D /* ArgList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF605120E203EF800B9A64D /* ArgList.h */; settings = {ATTRIBUTES = (Private, ); }; };
BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFD8C900EEB2EE700283848 /* JumpTable.cpp */; };
BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; };
C20BA92D16BB1C1500B3AEA2 /* StructureRareDataInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C20BA92C16BB1C1500B3AEA2 /* StructureRareDataInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
C21122E115DD9AB300790E3A /* GCThreadSharedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21122DE15DD9AB300790E3A /* GCThreadSharedData.cpp */; };
C21122E215DD9AB300790E3A /* GCThreadSharedData.h in Headers */ = {isa = PBXBuildFile; fileRef = C21122DF15DD9AB300790E3A /* GCThreadSharedData.h */; settings = {ATTRIBUTES = (Private, ); }; };
C21122E315DD9AB300790E3A /* MarkStackInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C21122E015DD9AB300790E3A /* MarkStackInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -818,7 +819,9 @@
C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E526BC1590EF000054E48D /* HeapTimer.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAA3F8149A830800FCE112 /* CopiedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */; };
C2FC9BD316644DFB00810D33 /* CopiedBlockInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FC9BD216644DFB00810D33 /* CopiedBlockInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2FE18A416BAEC4000AF3061 /* StructureRareData.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FE18A316BAEC4000AF3061 /* StructureRareData.h */; settings = {ATTRIBUTES = (Private, ); }; };
DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; };
E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; };
......@@ -1670,6 +1673,7 @@
BCF605120E203EF800B9A64D /* ArgList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgList.h; sourceTree = "<group>"; };
BCFD8C900EEB2EE700283848 /* JumpTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JumpTable.cpp; sourceTree = "<group>"; };
BCFD8C910EEB2EE700283848 /* JumpTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JumpTable.h; sourceTree = "<group>"; };
C20BA92C16BB1C1500B3AEA2 /* StructureRareDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureRareDataInlines.h; sourceTree = "<group>"; };
C21122DE15DD9AB300790E3A /* GCThreadSharedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCThreadSharedData.cpp; sourceTree = "<group>"; };
C21122DF15DD9AB300790E3A /* GCThreadSharedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCThreadSharedData.h; sourceTree = "<group>"; };
C21122E015DD9AB300790E3A /* MarkStackInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStackInlines.h; sourceTree = "<group>"; };
......@@ -1696,7 +1700,9 @@
C2E526BC1590EF000054E48D /* HeapTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapTimer.h; sourceTree = "<group>"; };
C2EAA3F8149A830800FCE112 /* CopiedSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedSpace.h; sourceTree = "<group>"; };
C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedAllocator.h; sourceTree = "<group>"; };
C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureRareData.cpp; sourceTree = "<group>"; };
C2FC9BD216644DFB00810D33 /* CopiedBlockInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedBlockInlines.h; sourceTree = "<group>"; };
C2FE18A316BAEC4000AF3061 /* StructureRareData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureRareData.h; sourceTree = "<group>"; };
D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; };
D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; };
DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCActivityCallback.h; sourceTree = "<group>"; };
......@@ -2522,6 +2528,9 @@
1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
A7DCB77912E3D90500911940 /* WriteBarrier.h */,
C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */,
C2FE18A316BAEC4000AF3061 /* StructureRareData.h */,
C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */,
C20BA92C16BB1C1500B3AEA2 /* StructureRareDataInlines.h */,
);
path = runtime;
sourceTree = "<group>";
......@@ -2885,7 +2894,9 @@
BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */,
0FB7F39615ED8E4600F167B2 /* ArrayStorage.h in Headers */,
9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */,
C20BA92D16BB1C1500B3AEA2 /* StructureRareDataInlines.h in Headers */,
86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */,
C2FE18A416BAEC4000AF3061 /* StructureRareData.h in Headers */,
A784A26111D16622005776AC /* ASTBuilder.h in Headers */,
147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */,
866739D213BFDE710023D87C /* BigInteger.h in Headers */,
......@@ -3951,6 +3962,7 @@
0FF0F19D16B72A08005DF95B /* DFGCommon.cpp in Sources */,
0FF0F19E16B72A0B005DF95B /* DFGEdge.cpp in Sources */,
0FF0F19F16B72A17005DF95B /* FunctionExecutableDump.cpp in Sources */,
C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -310,6 +310,7 @@ SOURCES += \
runtime/StringRecursionChecker.cpp \
runtime/StructureChain.cpp \
runtime/Structure.cpp \
runtime/StructureRareData.cpp \
runtime/SymbolTable.cpp \
runtime/TimeoutChecker.cpp \
tools/CodeProfile.cpp \
......
......@@ -37,6 +37,7 @@
#include "Operations.h"
#include "PolymorphicPutByIdList.h"
#include "RepatchBuffer.h"
#include "StructureRareDataInlines.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace DFG {
......
......@@ -68,6 +68,7 @@
#include "RepatchBuffer.h"
#include "SamplingTool.h"
#include "Strong.h"
#include "StructureRareDataInlines.h"
#include <wtf/StdLibExtras.h>
#include <stdarg.h>
#include <stdio.h>
......
......@@ -38,6 +38,7 @@
#include "JSString.h"
#include "Operations.h"
#include "SamplingTool.h"
#include "StructureRareDataInlines.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
......
......@@ -49,6 +49,7 @@
#include "LowLevelInterpreter.h"
#include "ObjectConstructor.h"
#include "Operations.h"
#include "StructureRareDataInlines.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace LLInt {
......
......@@ -23,8 +23,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef JSCellInlines_h
#define JSCellInlines_h
#include "CallFrame.h"
#include "Handle.h"
#include "JSCell.h"
#include "JSObject.h"
#include "JSString.h"
#include "Structure.h"
namespace JSC {
......@@ -187,3 +194,4 @@ inline bool JSCell::toBoolean(ExecState* exec) const
} // namespace JSC
#endif // JSCellInlines_h
......@@ -208,6 +208,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
JSLockHolder lock(this);
IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
structureStructure.set(*this, Structure::createStructure(*this));
structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull()));
terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
......
......@@ -226,6 +226,7 @@ namespace JSC {
const HashTable* stringConstructorTable;
Strong<Structure> structureStructure;
Strong<Structure> structureRareDataStructure;
Strong<Structure> debuggerActivationStructure;
Strong<Structure> interruptedExecutionErrorStructure;
Strong<Structure> terminatedExecutionErrorStructure;
......
......@@ -31,6 +31,7 @@
#include "SpecialPointer.h"
#include "StringPrototype.h"
#include "StructureChain.h"
#include "StructureRareDataInlines.h"
#include "Watchpoint.h"
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
......
......@@ -47,6 +47,7 @@ namespace JSC {
static const unsigned OverridesGetPropertyNames = 1 << 8;
static const unsigned ProhibitsPropertyCaching = 1 << 9;
static const unsigned HasImpureGetOwnPropertySlot = 1 << 10;
static const unsigned StructureHasRareData = 1 << 11;
class TypeInfo {
public:
......@@ -70,6 +71,7 @@ namespace JSC {
bool isNumberObject() const { return type() == NumberObjectType; }
bool isName() const { return type() == NameInstanceType; }
unsigned flags() const { return (static_cast<unsigned>(m_flags2) << 8) | static_cast<unsigned>(m_flags); }
bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); }
bool implementsHasInstance() const { return isSetOnFlags1(ImplementsHasInstance); }
bool isEnvironmentRecord() const { return isSetOnFlags1(IsEnvironmentRecord); }
......@@ -81,6 +83,7 @@ namespace JSC {
bool overridesGetPropertyNames() const { return isSetOnFlags2(OverridesGetPropertyNames); }
bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); }
bool hasImpureGetOwnPropertySlot() const { return isSetOnFlags2(HasImpureGetOwnPropertySlot); }
bool structureHasRareData() const { return isSetOnFlags2(StructureHasRareData); }
static ptrdiff_t flagsOffset()
{
......
......@@ -26,6 +26,7 @@
#include "JSString.h"
#include "JSStringBuilder.h"
#include "Operations.h"
#include "StructureRareDataInlines.h"
namespace JSC {
......
......@@ -31,6 +31,7 @@
#include "Lookup.h"
#include "PropertyNameArray.h"
#include "StructureChain.h"
#include "StructureRareDataInlines.h"
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/RefPtr.h>
#include <wtf/Threading.h>
......@@ -120,7 +121,7 @@ void Structure::dumpStatistics()
switch (structure->m_transitionTable.size()) {
case 0:
++numberLeaf;
if (!structure->m_previous)
if (!structure->previousID())
++numberSingletons;
break;
......@@ -172,6 +173,7 @@ Structure::Structure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSV
{
ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity());
ASSERT(static_cast<PropertyOffset>(inlineCapacity) < firstOutOfLineOffset);
ASSERT(!typeInfo.structureHasRareData());
}
const ClassInfo Structure::s_info = { "Structure", 0, 0, 0, CREATE_METHOD_TABLE(Structure) };
......@@ -242,7 +244,7 @@ void Structure::materializePropertyMap(JSGlobalData& globalData)
while ((structure = structure->previousID())) {
if (structure->m_isPinnedPropertyTable) {
ASSERT(structure->m_propertyTable);
ASSERT(!structure->m_previous);
ASSERT(!structure->previousID());
m_propertyTable = structure->m_propertyTable->copy(globalData, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
break;
......@@ -363,7 +365,7 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
Structure* transition = create(globalData, structure);
transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
transition->m_previous.set(globalData, transition, structure);
transition->setPreviousID(globalData, transition, structure);
transition->m_nameInPrevious = propertyName.uid();
transition->m_attributesInPrevious = attributes;
transition->m_specificValueInPrevious.setMayBeNull(globalData, transition, specificValue);
......@@ -374,7 +376,7 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
else
transition->m_propertyTable = structure->m_propertyTable.release();
} else {
if (structure->m_previous)
if (structure->previousID())
transition->materializePropertyMap(globalData);
else
transition->createPropertyMap();
......@@ -551,7 +553,7 @@ Structure* Structure::nonPropertyTransition(JSGlobalData& globalData, Structure*
}
Structure* transition = create(globalData, structure);
transition->m_previous.set(globalData, transition, structure);
transition->setPreviousID(globalData, transition, structure);
transition->m_attributesInPrevious = attributes;
transition->m_indexingType = indexingType;
transition->m_offset = structure->m_offset;
......@@ -563,7 +565,7 @@ Structure* Structure::nonPropertyTransition(JSGlobalData& globalData, Structure*
else
transition->m_propertyTable = structure->m_propertyTable.release();
} else {
if (structure->m_previous)
if (structure->previousID())
transition->materializePropertyMap(globalData);
else
transition->createPropertyMap();
......@@ -670,10 +672,25 @@ void Structure::pin()
{
ASSERT(m_propertyTable);
m_isPinnedPropertyTable = true;
m_previous.clear();
clearPreviousID();
m_nameInPrevious.clear();
}
void Structure::allocateRareData(JSGlobalData& globalData)
{
ASSERT(!typeInfo().structureHasRareData());
StructureRareData* rareData = StructureRareData::create(globalData, previous());
m_typeInfo = TypeInfo(typeInfo().type(), typeInfo().flags() | StructureHasRareData);
m_previousOrRareData.set(globalData, this, rareData);
}
void Structure::cloneRareDataFrom(JSGlobalData& globalData, const Structure* other)
{
ASSERT(other->typeInfo().structureHasRareData());
StructureRareData* newRareData = StructureRareData::clone(globalData, other->rareData());
m_previousOrRareData.set(globalData, this, newRareData);
}
#if DUMP_PROPERTYMAP_STATS
struct PropertyMapStatisticsExitLogger {
......@@ -840,7 +857,7 @@ void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
visitor.append(&thisObject->m_prototype);
visitor.append(&thisObject->m_cachedPrototypeChain);
}
visitor.append(&thisObject->m_previous);
visitor.append(&thisObject->m_previousOrRareData);
visitor.append(&thisObject->m_specificValueInPrevious);
visitor.append(&thisObject->m_enumerationCache);
if (thisObject->m_propertyTable) {
......@@ -848,7 +865,6 @@ void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
for (PropertyTable::iterator ptr = thisObject->m_propertyTable->begin(); ptr != end; ++ptr)
visitor.append(&ptr->specificValue);
}
visitor.append(&thisObject->m_objectToStringValue);
}
bool Structure::prototypeChainMayInterceptStoreTo(JSGlobalData& globalData, PropertyName propertyName)
......
......@@ -35,6 +35,7 @@
#include "PropertyName.h"
#include "PropertyNameArray.h"
#include "Protect.h"
#include "StructureRareData.h"
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
#include "Watchpoint.h"
......@@ -178,7 +179,9 @@ namespace JSC {
Structure* previousID() const
{
ASSERT(structure()->classInfo() == &s_info);
return m_previous.get();
if (typeInfo().structureHasRareData())
return rareData()->previousID();
return previous();
}
bool transitivelyTransitionedFrom(Structure* structureToFind);
......@@ -289,11 +292,18 @@ namespace JSC {
JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
void getPropertyNamesFromStructure(JSGlobalData&, PropertyNameArray&, EnumerationMode);
JSString* objectToStringValue() { return m_objectToStringValue.get(); }
JSString* objectToStringValue()
{
if (!typeInfo().structureHasRareData())
return 0;
return rareData()->objectToStringValue();
}
void setObjectToStringValue(JSGlobalData& globalData, const JSCell* owner, JSString* value)
{
m_objectToStringValue.set(globalData, owner, value);
if (!typeInfo().structureHasRareData())
allocateRareData(globalData);
rareData()->setObjectToStringValue(globalData, owner, value);
}
bool staticFunctionsReified()
......@@ -394,7 +404,7 @@ namespace JSC {
void materializePropertyMapIfNecessary(JSGlobalData& globalData)
{
ASSERT(structure()->classInfo() == &s_info);
if (!m_propertyTable && m_previous)
if (!m_propertyTable && previousID())
materializePropertyMap(globalData);
}
void materializePropertyMapIfNecessaryForPinning(JSGlobalData& globalData)
......@@ -404,6 +414,22 @@ namespace JSC {
materializePropertyMap(globalData);
}
void setPreviousID(JSGlobalData& globalData, Structure* transition, Structure* structure)
{
if (typeInfo().structureHasRareData())
rareData()->setPreviousID(globalData, transition, structure);
else
m_previousOrRareData.set(globalData, transition, structure);
}
void clearPreviousID()
{
if (typeInfo().structureHasRareData())
rareData()->clearPreviousID();
else
m_previousOrRareData.clear();
}
int transitionCount() const
{
// Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
......@@ -415,6 +441,21 @@ namespace JSC {
void pin();
Structure* previous() const
{
ASSERT(!typeInfo().structureHasRareData());
return static_cast<Structure*>(m_previousOrRareData.get());
}
StructureRareData* rareData() const
{
ASSERT(typeInfo().structureHasRareData());
return static_cast<StructureRareData*>(m_previousOrRareData.get());
}
void allocateRareData(JSGlobalData&);
void cloneRareDataFrom(JSGlobalData&, const Structure*);
static const int s_maxTransitionLength = 64;
static const unsigned maxSpecificFunctionThrashCount = 3;
......@@ -426,7 +467,8 @@ namespace JSC {
WriteBarrier<Unknown> m_prototype;
mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
WriteBarrier<Structure> m_previous;
WriteBarrier<JSCell> m_previousOrRareData;