Commit 26af9b61 authored by fpizlo@apple.com's avatar fpizlo@apple.com

Global object variable accesses should not require an extra load

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

Source/JavaScriptCore: 

Reviewed by Gavin Barraclough and Geoffrey Garen.
        
Previously, if you wanted to access a global variable, you'd first have
to load the register array from the appropriate global object and then
either load or store at an offset to the register array. This is because
JSGlobalObject inherited from JSVariableObject, and JSVariableObject is
designed with the pessimistic assumption that its register array may
point into the call stack. This is never the case for global objects.
Hence, even though the global object may add more registers at any time,
it does not need to store them in a contiguous array. It can use a
SegmentedVector or similar.
        
This patch refactors global objects and variable objects as follows:
        
- The functionality to track variables in an indexable array using a
  SymbolTable to map names to indices is moved into JSSymbolTableObject,
  which is now a supertype of JSVariableObject. JSVariableObject is now
  just a holder for a registers array and implements the registerAt()
  method that is left abstract in JSSymbolTableObject. Because all users
  of JSVariableObject know whether they are a JSStaticScopeObject,
  JSActivation, or JSGlobalObject, this "abstract" method is not virtual;
  instead the utility methods that would call registerAt() are now
  template functions that require you to know statically what subtype of
  JSSymbolTableObject you're using (JSVariableObject or something else),
  so that registerAt() can be statically bound.
        
- A new class is added called JSSegmentedVariableObject, which only
  differs from JSVariableObject in how it allocates registers. It uses a
  SegmentedVector instead of manually managing a pointer to a contiguous
  slab of registers. This changes the interface somewhat; for example
  with JSVariableObject if you wanted to add a register you had to do
  it yourself since the JSVariableObject didn't know how the registers
  array ought to be allocated. With JSSegmentedVariableObject you can
  just call addRegisters(). JSSegmentedVariableObject preserves the
  invariant that once you get a pointer into a register, that pointer
  will continue to be valid so long as the JSSegmentedVariableObject is
  alive. This allows the JITs and interpreters to skip the extra load.
        
- JSGlobalObject now inherits from JSSegmentedVariableObject. For now
  (and possibly forever) it is the only subtype of this new class.
        
- The bytecode format is changed so that get_global_var and
  put_global_var have a pointer to the register directly rather than
  having an index. A convenience method is provided in
  JSSegmentedVariableObject to get the index given a a pointer, which is
  used for assertions and debug dumps.
        
This appears to be a 1% across the board win.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
* bytecode/Instruction.h:
(Instruction):
(JSC::Instruction::Instruction):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::ResolveResult::registerPointer):
(JSC):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::retrieveLastUnaryOp):
(JSC::BytecodeGenerator::resolve):
(JSC::BytecodeGenerator::resolveConstDecl):
(JSC::BytecodeGenerator::emitGetStaticVar):
(JSC::BytecodeGenerator::emitPutStaticVar):
* bytecompiler/BytecodeGenerator.h:
(ResolveResult):
(BytecodeGenerator):
* dfg/DFGAssemblyHelpers.h:
(AssemblyHelpers):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::globalVarLoadElimination):
(JSC::DFG::CSEPhase::globalVarStoreElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::globalObjectFor):
(Graph):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasVarNumber):
(Node):
(JSC::DFG::Node::hasRegisterPointer):
(JSC::DFG::Node::registerPointer):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* heap/Heap.h:
(Heap):
(JSC::Heap::isWriteBarrierEnabled):
(JSC):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::privateExecute):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_global_var):
(JSC::JIT::emit_op_put_global_var):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_global_var):
(JSC::JIT::emit_op_put_global_var):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/JSGlobalObject.cpp:
(JSC):
(JSC::JSGlobalObject::put):
(JSC::JSGlobalObject::putDirectVirtual):
(JSC::JSGlobalObject::defineOwnProperty):
(JSC::JSGlobalObject::visitChildren):
(JSC::JSGlobalObject::addStaticGlobals):
(JSC::JSGlobalObject::getOwnPropertySlot):
(JSC::JSGlobalObject::getOwnPropertyDescriptor):
* runtime/JSGlobalObject.h:
(JSGlobalObject):
(JSC::JSGlobalObject::JSGlobalObject):
(JSC):
(JSC::JSGlobalObject::hasOwnPropertyForWrite):
* runtime/JSSegmentedVariableObject.cpp: Added.
(JSC):
(JSC::JSSegmentedVariableObject::findRegisterIndex):
(JSC::JSSegmentedVariableObject::addRegisters):
(JSC::JSSegmentedVariableObject::visitChildren):
* runtime/JSSegmentedVariableObject.h: Added.
(JSC):
(JSSegmentedVariableObject):
(JSC::JSSegmentedVariableObject::registerAt):
(JSC::JSSegmentedVariableObject::assertRegisterIsInThisObject):
(JSC::JSSegmentedVariableObject::JSSegmentedVariableObject):
(JSC::JSSegmentedVariableObject::finishCreation):
* runtime/JSStaticScopeObject.cpp:
(JSC::JSStaticScopeObject::put):
(JSC::JSStaticScopeObject::putDirectVirtual):
(JSC::JSStaticScopeObject::getOwnPropertySlot):
* runtime/JSSymbolTableObject.cpp: Added.
(JSC):
(JSC::JSSymbolTableObject::destroy):
(JSC::JSSymbolTableObject::deleteProperty):
(JSC::JSSymbolTableObject::getOwnPropertyNames):
(JSC::JSSymbolTableObject::putDirectVirtual):
(JSC::JSSymbolTableObject::isDynamicScope):
* runtime/JSSymbolTableObject.h: Added.
(JSC):
(JSSymbolTableObject):
(JSC::JSSymbolTableObject::symbolTable):
(JSC::JSSymbolTableObject::JSSymbolTableObject):
(JSC::JSSymbolTableObject::finishCreation):
(JSC::symbolTableGet):
(JSC::symbolTablePut):
(JSC::symbolTablePutWithAttributes):
* runtime/JSVariableObject.cpp:
(JSC):
* runtime/JSVariableObject.h:
(JSVariableObject):
(JSC::JSVariableObject::JSVariableObject):
(JSC::JSVariableObject::finishCreation):
(JSC):
* runtime/WriteBarrier.h:

Source/WebCore: 

Reviewed by Gavin Barraclough and Geoffrey Garen.

Updated JSDOMWindowBase.cpp to use the new symbol table API. this->symbolTableFoo(...)
becomes symbolTableFoo(this, ...).
                
No new tests because no change in behavior.

* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::updateDocument):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@119655 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 8dd226e5
......@@ -186,9 +186,11 @@ SET(JavaScriptCore_SOURCES
runtime/JSObject.cpp
runtime/JSONObject.cpp
runtime/JSPropertyNameIterator.cpp
runtime/JSSegmentedVariableObject.cpp
runtime/JSStaticScopeObject.cpp
runtime/JSString.cpp
runtime/JSStringJoiner.cpp
runtime/JSSymbolTableObject.cpp
runtime/JSValue.cpp
runtime/JSVariableObject.cpp
runtime/JSWrapperObject.cpp
......
2012-06-06 Filip Pizlo <fpizlo@apple.com>
Global object variable accesses should not require an extra load
https://bugs.webkit.org/show_bug.cgi?id=88385
Reviewed by Gavin Barraclough and Geoffrey Garen.
Previously, if you wanted to access a global variable, you'd first have
to load the register array from the appropriate global object and then
either load or store at an offset to the register array. This is because
JSGlobalObject inherited from JSVariableObject, and JSVariableObject is
designed with the pessimistic assumption that its register array may
point into the call stack. This is never the case for global objects.
Hence, even though the global object may add more registers at any time,
it does not need to store them in a contiguous array. It can use a
SegmentedVector or similar.
This patch refactors global objects and variable objects as follows:
- The functionality to track variables in an indexable array using a
SymbolTable to map names to indices is moved into JSSymbolTableObject,
which is now a supertype of JSVariableObject. JSVariableObject is now
just a holder for a registers array and implements the registerAt()
method that is left abstract in JSSymbolTableObject. Because all users
of JSVariableObject know whether they are a JSStaticScopeObject,
JSActivation, or JSGlobalObject, this "abstract" method is not virtual;
instead the utility methods that would call registerAt() are now
template functions that require you to know statically what subtype of
JSSymbolTableObject you're using (JSVariableObject or something else),
so that registerAt() can be statically bound.
- A new class is added called JSSegmentedVariableObject, which only
differs from JSVariableObject in how it allocates registers. It uses a
SegmentedVector instead of manually managing a pointer to a contiguous
slab of registers. This changes the interface somewhat; for example
with JSVariableObject if you wanted to add a register you had to do
it yourself since the JSVariableObject didn't know how the registers
array ought to be allocated. With JSSegmentedVariableObject you can
just call addRegisters(). JSSegmentedVariableObject preserves the
invariant that once you get a pointer into a register, that pointer
will continue to be valid so long as the JSSegmentedVariableObject is
alive. This allows the JITs and interpreters to skip the extra load.
- JSGlobalObject now inherits from JSSegmentedVariableObject. For now
(and possibly forever) it is the only subtype of this new class.
- The bytecode format is changed so that get_global_var and
put_global_var have a pointer to the register directly rather than
having an index. A convenience method is provided in
JSSegmentedVariableObject to get the index given a a pointer, which is
used for assertions and debug dumps.
This appears to be a 1% across the board win.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
* bytecode/Instruction.h:
(Instruction):
(JSC::Instruction::Instruction):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::ResolveResult::registerPointer):
(JSC):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::retrieveLastUnaryOp):
(JSC::BytecodeGenerator::resolve):
(JSC::BytecodeGenerator::resolveConstDecl):
(JSC::BytecodeGenerator::emitGetStaticVar):
(JSC::BytecodeGenerator::emitPutStaticVar):
* bytecompiler/BytecodeGenerator.h:
(ResolveResult):
(BytecodeGenerator):
* dfg/DFGAssemblyHelpers.h:
(AssemblyHelpers):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::globalVarLoadElimination):
(JSC::DFG::CSEPhase::globalVarStoreElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::globalObjectFor):
(Graph):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasVarNumber):
(Node):
(JSC::DFG::Node::hasRegisterPointer):
(JSC::DFG::Node::registerPointer):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* heap/Heap.h:
(Heap):
(JSC::Heap::isWriteBarrierEnabled):
(JSC):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::privateExecute):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_global_var):
(JSC::JIT::emit_op_put_global_var):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_global_var):
(JSC::JIT::emit_op_put_global_var):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/JSGlobalObject.cpp:
(JSC):
(JSC::JSGlobalObject::put):
(JSC::JSGlobalObject::putDirectVirtual):
(JSC::JSGlobalObject::defineOwnProperty):
(JSC::JSGlobalObject::visitChildren):
(JSC::JSGlobalObject::addStaticGlobals):
(JSC::JSGlobalObject::getOwnPropertySlot):
(JSC::JSGlobalObject::getOwnPropertyDescriptor):
* runtime/JSGlobalObject.h:
(JSGlobalObject):
(JSC::JSGlobalObject::JSGlobalObject):
(JSC):
(JSC::JSGlobalObject::hasOwnPropertyForWrite):
* runtime/JSSegmentedVariableObject.cpp: Added.
(JSC):
(JSC::JSSegmentedVariableObject::findRegisterIndex):
(JSC::JSSegmentedVariableObject::addRegisters):
(JSC::JSSegmentedVariableObject::visitChildren):
* runtime/JSSegmentedVariableObject.h: Added.
(JSC):
(JSSegmentedVariableObject):
(JSC::JSSegmentedVariableObject::registerAt):
(JSC::JSSegmentedVariableObject::assertRegisterIsInThisObject):
(JSC::JSSegmentedVariableObject::JSSegmentedVariableObject):
(JSC::JSSegmentedVariableObject::finishCreation):
* runtime/JSStaticScopeObject.cpp:
(JSC::JSStaticScopeObject::put):
(JSC::JSStaticScopeObject::putDirectVirtual):
(JSC::JSStaticScopeObject::getOwnPropertySlot):
* runtime/JSSymbolTableObject.cpp: Added.
(JSC):
(JSC::JSSymbolTableObject::destroy):
(JSC::JSSymbolTableObject::deleteProperty):
(JSC::JSSymbolTableObject::getOwnPropertyNames):
(JSC::JSSymbolTableObject::putDirectVirtual):
(JSC::JSSymbolTableObject::isDynamicScope):
* runtime/JSSymbolTableObject.h: Added.
(JSC):
(JSSymbolTableObject):
(JSC::JSSymbolTableObject::symbolTable):
(JSC::JSSymbolTableObject::JSSymbolTableObject):
(JSC::JSSymbolTableObject::finishCreation):
(JSC::symbolTableGet):
(JSC::symbolTablePut):
(JSC::symbolTablePutWithAttributes):
* runtime/JSVariableObject.cpp:
(JSC):
* runtime/JSVariableObject.h:
(JSVariableObject):
(JSC::JSVariableObject::JSVariableObject):
(JSC::JSVariableObject::finishCreation):
(JSC):
* runtime/WriteBarrier.h:
2012-06-06 Filip Pizlo <fpizlo@apple.com>
DFG arguments access slow path should not crash if the arguments haven't been created
......
......@@ -501,6 +501,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/JSONObject.h \
Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
Source/JavaScriptCore/runtime/JSPropertyNameIterator.h \
Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp \
Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h \
Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp \
Source/JavaScriptCore/runtime/JSStaticScopeObject.h \
Source/JavaScriptCore/runtime/JSStringBuilder.h \
......@@ -508,6 +510,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/JSStringJoiner.h \
Source/JavaScriptCore/runtime/JSString.cpp \
Source/JavaScriptCore/runtime/JSString.h \
Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp \
Source/JavaScriptCore/runtime/JSSymbolTableObject.h \
Source/JavaScriptCore/runtime/JSType.h \
Source/JavaScriptCore/runtime/JSTypeInfo.h \
Source/JavaScriptCore/runtime/JSValue.cpp \
......
......@@ -140,7 +140,7 @@ EXPORTS
?deleteOwnedPtr@WTF@@YAXPAUHFONT__@@@Z
?deleteOwnedPtr@WTF@@YAXPAUHRGN__@@@Z
?deleteProperty@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@@Z
?deleteProperty@JSVariableObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@@Z
?deleteProperty@JSSymbolTableObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@@Z
?deletePropertyByIndex@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@I@Z
?deleteTable@HashTable@JSC@@QBEXXZ
?despecifyDictionaryFunction@Structure@JSC@@QAEXAAVJSGlobalData@2@VPropertyName@2@@Z
......@@ -194,7 +194,7 @@ EXPORTS
?getOwnPropertyDescriptor@JSGlobalObject@JSC@@SA_NPAVJSObject@2@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z
?getOwnPropertyDescriptor@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z
?getOwnPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnPropertyNames@JSVariableObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnPropertyNames@JSSymbolTableObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnPropertySlot@JSGlobalObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@AAVPropertySlot@2@@Z
?getOwnPropertySlotByIndex@JSArray@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z
?getOwnPropertySlotByIndex@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z
......
......@@ -873,6 +873,14 @@
RelativePath="..\..\runtime\JSPropertyNameIterator.h"
>
</File>
<File
RelativePath="..\..\runtime\JSSegmentedVariableObject.cpp"
>
</File>
<File
RelativePath="..\..\runtime\JSSegmentedVariableObject.h"
>
</File>
<File
RelativePath="..\..\runtime\JSStaticScopeObject.cpp"
>
......@@ -897,6 +905,14 @@
RelativePath="..\..\runtime\JSStringJoiner.h"
>
</File>
<File
RelativePath="..\..\runtime\JSSymbolTableObject.cpp"
>
</File>
<File
RelativePath="..\..\runtime\JSSymbolTableObject.h"
>
</File>
<File
RelativePath="..\..\runtime\JSType.h"
>
......
......@@ -135,6 +135,10 @@
0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */; };
0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */; };
0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */; };
0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */; };
......@@ -828,6 +832,10 @@
0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCCallHelpers.h; path = dfg/DFGCCallHelpers.h; sourceTree = "<group>"; };
0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSymbolTableObject.cpp; sourceTree = "<group>"; };
0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSymbolTableObject.h; sourceTree = "<group>"; };
0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSegmentedVariableObject.cpp; sourceTree = "<group>"; };
0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSegmentedVariableObject.h; sourceTree = "<group>"; };
0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallLinkStatus.cpp; sourceTree = "<group>"; };
0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallLinkStatus.h; sourceTree = "<group>"; };
0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdStatus.cpp; sourceTree = "<group>"; };
......@@ -1934,6 +1942,8 @@
A7F9935D0FD7325100A0B2D0 /* JSONObject.h */,
A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */,
A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */,
0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */,
0F919D0F157F3327004A4E7D /* JSSegmentedVariableObject.h */,
A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */,
A7E42C180E3938830065A544 /* JSStaticScopeObject.h */,
BC02E9B60E1842FA000F9297 /* JSString.cpp */,
......@@ -1941,6 +1951,8 @@
86E85538111B9968001AF51E /* JSStringBuilder.h */,
2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */,
2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */,
0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */,
0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */,
14ABB454099C2A0F00E2A24F /* JSType.h */,
6507D2970E871E4A00D7D896 /* JSTypeInfo.h */,
F692A8870255597D01FF60F7 /* JSValue.cpp */,
......@@ -2657,6 +2669,8 @@
0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */,
0FD81AD3154FB4F000983E72 /* DFGDominators.h in Headers */,
0F16015E156198C900C2587C /* DFGArgumentsSimplificationPhase.h in Headers */,
0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */,
0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -3229,6 +3243,8 @@
0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */,
0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */,
C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */,
0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */,
0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -194,9 +194,11 @@ SOURCES += \
runtime/JSObject.cpp \
runtime/JSONObject.cpp \
runtime/JSPropertyNameIterator.cpp \
runtime/JSSegmentedVariableObject.cpp \
runtime/JSStaticScopeObject.cpp \
runtime/JSString.cpp \
runtime/JSStringJoiner.cpp \
runtime/JSSymbolTableObject.cpp \
runtime/JSValue.cpp \
runtime/JSVariableObject.cpp \
runtime/JSWrapperObject.cpp \
......
......@@ -923,15 +923,15 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_get_global_var: {
int r0 = (++it)->u.operand;
int index = (++it)->u.operand;
dataLog("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index);
WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
dataLog("[%4d] get_global_var\t %s, g%d(%p)\n", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer);
it++;
break;
}
case op_put_global_var: {
int index = (++it)->u.operand;
WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
int r0 = (++it)->u.operand;
dataLog("[%4d] put_global_var\t %d, %s\n", location, index, registerName(exec, r0).data());
dataLog("[%4d] put_global_var\t g%d(%p), %s\n", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data());
break;
}
case op_resolve_base: {
......
......@@ -191,6 +191,8 @@ namespace JSC {
Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
Instruction(ValueProfile* profile) { u.profile = profile; }
Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; }
union {
Opcode opcode;
......@@ -198,6 +200,7 @@ namespace JSC {
WriteBarrierBase<Structure> structure;
WriteBarrierBase<StructureChain> structureChain;
WriteBarrierBase<JSCell> jsCell;
WriteBarrier<Unknown>* registerPointer;
PropertySlot::GetValueFunc getterFunc;
LLIntCallLinkInfo* callLinkInfo;
ValueProfile* profile;
......
......@@ -161,6 +161,11 @@ void ResolveResult::checkValidity()
}
#endif
WriteBarrier<Unknown>* ResolveResult::registerPointer() const
{
return &jsCast<JSGlobalObject*>(globalObject())->registerAt(index());
}
static bool s_dumpsGeneratedCode = false;
void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
......@@ -280,7 +285,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s
size_t newGlobals = varStack.size() + functionStack.size();
if (!newGlobals)
return;
globalObject->resizeRegisters(symbolTable->size() + newGlobals);
globalObject->addRegisters(newGlobals);
for (size_t i = 0; i < functionStack.size(); ++i) {
FunctionBodyNode* function = functionStack[i];
......@@ -679,6 +684,14 @@ void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
srcIndex = instructions().at(size - 1).u.operand;
}
void BytecodeGenerator::retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex)
{
ASSERT(instructions().size() >= 3);
size_t size = instructions().size();
dstPointer = instructions().at(size - 2).u.registerPointer;
srcIndex = instructions().at(size - 1).u.operand;
}
void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
{
ASSERT(instructions().size() >= 4);
......@@ -1178,7 +1191,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
flags |= ResolveResult::DynamicFlag;
break;
}
JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope);
JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope);
SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
// Found the property
......@@ -1243,7 +1256,7 @@ ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
JSObject* currentScope = iter->get();
if (!currentScope->isVariableObject())
continue;
JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope);
JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope);
SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
if (entry.isNull())
continue;
......@@ -1446,16 +1459,16 @@ RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveRe
case ResolveResult::IndexedGlobal:
case ResolveResult::ReadOnlyIndexedGlobal:
if (m_lastOpcodeID == op_put_global_var) {
int dstIndex;
WriteBarrier<Unknown>* dstPointer;
int srcIndex;
retrieveLastUnaryOp(dstIndex, srcIndex);
if (dstIndex == resolveResult.index() && srcIndex == dst->index())
retrieveLastUnaryOp(dstPointer, srcIndex);
if (dstPointer == resolveResult.registerPointer() && srcIndex == dst->index())
return dst;
}
profile = emitProfiledOpcode(op_get_global_var);
instructions().append(dst->index());
instructions().append(resolveResult.index());
instructions().append(resolveResult.registerPointer());
instructions().append(profile);
return dst;
......@@ -1483,7 +1496,7 @@ RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResu
case ResolveResult::IndexedGlobal:
case ResolveResult::ReadOnlyIndexedGlobal:
emitOpcode(op_put_global_var);
instructions().append(resolveResult.index());
instructions().append(resolveResult.registerPointer());
instructions().append(value->index());
return value;
......
......@@ -197,6 +197,7 @@ namespace JSC {
int index() const { ASSERT (isIndexed() || isRegister()); return m_index; }
size_t depth() const { ASSERT(isScoped()); return m_depth; }
JSObject* globalObject() const { ASSERT(isGlobal()); ASSERT(m_globalObject); return m_globalObject; }
WriteBarrier<Unknown>* registerPointer() const;
bool isRegister() const { return m_type & RegisterFlag; }
bool isDynamic() const { return m_type & DynamicFlag; }
......@@ -541,6 +542,7 @@ namespace JSC {
ValueProfile* emitProfiledOpcode(OpcodeID);
void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
void retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex);
ALWAYS_INLINE void rewindBinaryOp();
ALWAYS_INLINE void rewindUnaryOp();
......
......@@ -115,21 +115,6 @@ public:
#endif
}
static Address addressForGlobalVar(GPRReg global, int32_t varNumber)
{
return Address(global, varNumber * sizeof(Register));
}
static Address tagForGlobalVar(GPRReg global, int32_t varNumber)
{
return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
}
static Address payloadForGlobalVar(GPRReg global, int32_t varNumber)
{
return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
}
static Address addressFor(VirtualRegister virtualRegister)
{
return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
......
......@@ -2216,14 +2216,20 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_get_global_var: {
PredictedType prediction = getPrediction();
NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand), OpInfo(prediction));
NodeIndex getGlobalVar = addToGraph(
GetGlobalVar,
OpInfo(m_inlineStackTop->m_codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),
OpInfo(prediction));
set(currentInstruction[1].u.operand, getGlobalVar);
NEXT_OPCODE(op_get_global_var);
}
case op_put_global_var: {
NodeIndex value = get(currentInstruction[2].u.operand);
addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
addToGraph(
PutGlobalVar,
OpInfo(m_inlineStackTop->m_codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
value);
NEXT_OPCODE(op_put_global_var);
}
......
......@@ -194,18 +194,18 @@ private:
return NoNode;
}
NodeIndex globalVarLoadElimination(unsigned varNumber, JSGlobalObject* globalObject)
NodeIndex globalVarLoadElimination(WriteBarrier<Unknown>* registerPointer)
{
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
Node& node = m_graph[index];
switch (node.op()) {
case GetGlobalVar:
if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
if (node.registerPointer() == registerPointer)
return index;
break;
case PutGlobalVar:
if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
if (node.registerPointer() == registerPointer)
return node.child1().index();
break;
default:
......@@ -217,7 +217,7 @@ private:
return NoNode;
}
NodeIndex globalVarStoreElimination(unsigned varNumber, JSGlobalObject* globalObject)
NodeIndex globalVarStoreElimination(WriteBarrier<Unknown>* registerPointer)
{
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
......@@ -226,12 +226,12 @@ private:
continue;
switch (node.op()) {
case PutGlobalVar:
if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
if (node.registerPointer() == registerPointer)
return index;
break;
case GetGlobalVar:
if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
if (node.registerPointer() == registerPointer)
return NoNode;
break;
......@@ -982,13 +982,13 @@ private:
// Finally handle heap accesses. These are not quite pure, but we can still
// optimize them provided that some subtle conditions are met.
case GetGlobalVar:
setReplacement(globalVarLoadElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
setReplacement(globalVarLoadElimination(node.registerPointer()));
break;
case PutGlobalVar:
if (m_fixpointState == FixpointNotConverged)
break;
eliminate(globalVarStoreElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
eliminate(globalVarStoreElimination(node.registerPointer()));
break;
case GetByVal:
......
......@@ -202,6 +202,13 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("%svar%u", hasPrinted ? ", " : "", node.varNumber());
hasPrinted = true;
}
if (node.hasRegisterPointer()) {
dataLog(
"%sglobal%u(%p)", hasPrinted ? ", " : "",
globalObjectFor(node.codeOrigin)->findRegisterIndex(node.registerPointer()),
node.registerPointer());
hasPrinted = true;
}
if (node.hasIdentifier()) {
dataLog("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), m_codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
hasPrinted = true;
......
......@@ -310,6 +310,11 @@ public:
return &m_structureTransitionData.last();
}
JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
{
return m_codeBlock->globalObjectFor(codeOrigin);
}
ExecutableBase* executableFor(InlineCallFrame* inlineCallFrame)
{
if (!inlineCallFrame)
......
......@@ -421,7 +421,7 @@ struct Node {