fourthTier: DFG should have its own notion of StructureChain, and it should be possib...
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2013 03:59:44 +0000 (03:59 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2013 03:59:44 +0000 (03:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=115841

Reviewed by Oliver Hunt.

This adds IntendedStructureChain, which is like StructureChain, except that it holds a bit
more information and can be validated independantly of its owning Structure and lexical
GlobalObject, since it remembers both of those things. It's also malloc'd and RefCounted
rather than GC'd, so it can be allocated in a concurrent compilation thread.

Gave this class a bunch of methods to allow the following idiom:

- Snapshot a structure chain concurrently. This structure chain may end up being
  wrong in case of races, but in that case we will find out when we try to validate
  it.

- Perform validation on the structure chain itself, without recomputing the chain.
  Previously, many chain validation methods (prototypeChainMayInterceptStoreTo() for
  example) recomputed the chain, and hence, were inherently racy: you could build one
  chain and then validate against a different chain, and hence not realize that the
  chain you did build was actually broken for your purposes, because the chain you
  checked was a different one.

- Validate that the chain is still the right one at any time, allowing the cancellation
  of compilation if there was a race.

Also added DFG::DesiredStructureChains, which tracks those intended structure chains that
the compiler had already chosen to use. If any of those are invalid at link time, throw
out the compilation.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeForChain):
(JSC::GetByIdStatus::computeFor):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::chain):
(GetByIdStatus):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
(JSC::PutByIdStatus::computeFor):
* bytecode/PutByIdStatus.h:
(JSC::PutByIdStatus::PutByIdStatus):
(JSC::PutByIdStatus::structureChain):
(PutByIdStatus):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDesiredStructureChains.cpp: Added.
(DFG):
(JSC::DFG::DesiredStructureChains::DesiredStructureChains):
(JSC::DFG::DesiredStructureChains::~DesiredStructureChains):
(JSC::DFG::DesiredStructureChains::areStillValid):
* dfg/DFGDesiredStructureChains.h: Added.
(DFG):
(DesiredStructureChains):
(JSC::DFG::DesiredStructureChains::addLazily):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::isStillValid):
(DFG):
* dfg/DFGGraph.h:
(Graph):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::linkFunction):
* ftl/FTLLink.cpp:
(JSC::FTL::link):
* runtime/IntendedStructureChain.cpp: Added.
(JSC):
(JSC::IntendedStructureChain::IntendedStructureChain):
(JSC::IntendedStructureChain::~IntendedStructureChain):
(JSC::IntendedStructureChain::isStillValid):
(JSC::IntendedStructureChain::matches):
(JSC::IntendedStructureChain::chain):
(JSC::IntendedStructureChain::mayInterceptStoreTo):
(JSC::IntendedStructureChain::isNormalized):
(JSC::IntendedStructureChain::terminalPrototype):
* runtime/IntendedStructureChain.h: Added.
(JSC):
(IntendedStructureChain):
(JSC::IntendedStructureChain::head):
(JSC::IntendedStructureChain::size):
(JSC::IntendedStructureChain::at):
(JSC::IntendedStructureChain::operator[]):
(JSC::IntendedStructureChain::last):
* runtime/Structure.cpp:
(JSC::Structure::prototypeChainMayInterceptStoreTo):
* runtime/Structure.h:
(Structure):
* runtime/StructureInlines.h:
(JSC::Structure::storedPrototypeObject):
(JSC):
(JSC::Structure::storedPrototypeStructure):

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

22 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
Source/JavaScriptCore/bytecode/GetByIdStatus.h
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
Source/JavaScriptCore/bytecode/PutByIdStatus.h
Source/JavaScriptCore/dfg/DFGAbstractState.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDesiredStructureChains.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGDesiredStructureChains.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp [deleted file]
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h [deleted file]
Source/JavaScriptCore/ftl/FTLLink.cpp
Source/JavaScriptCore/runtime/IntendedStructureChain.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/IntendedStructureChain.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureInlines.h

index a7fc98e..f3095cb 100644 (file)
@@ -1,3 +1,103 @@
+2013-05-09  Filip Pizlo  <fpizlo@apple.com>
+
+        fourthTier: DFG should have its own notion of StructureChain, and it should be possible to validate it after compilation finishes
+        https://bugs.webkit.org/show_bug.cgi?id=115841
+
+        Reviewed by Oliver Hunt.
+        
+        This adds IntendedStructureChain, which is like StructureChain, except that it holds a bit
+        more information and can be validated independantly of its owning Structure and lexical
+        GlobalObject, since it remembers both of those things. It's also malloc'd and RefCounted
+        rather than GC'd, so it can be allocated in a concurrent compilation thread.
+        
+        Gave this class a bunch of methods to allow the following idiom:
+        
+        - Snapshot a structure chain concurrently. This structure chain may end up being
+          wrong in case of races, but in that case we will find out when we try to validate
+          it.
+        
+        - Perform validation on the structure chain itself, without recomputing the chain.
+          Previously, many chain validation methods (prototypeChainMayInterceptStoreTo() for
+          example) recomputed the chain, and hence, were inherently racy: you could build one
+          chain and then validate against a different chain, and hence not realize that the
+          chain you did build was actually broken for your purposes, because the chain you
+          checked was a different one.
+        
+        - Validate that the chain is still the right one at any time, allowing the cancellation
+          of compilation if there was a race.
+        
+        Also added DFG::DesiredStructureChains, which tracks those intended structure chains that
+        the compiler had already chosen to use. If any of those are invalid at link time, throw
+        out the compilation.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeForChain):
+        (JSC::GetByIdStatus::computeFor):
+        * bytecode/GetByIdStatus.h:
+        (JSC::GetByIdStatus::GetByIdStatus):
+        (JSC::GetByIdStatus::chain):
+        (GetByIdStatus):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFromLLInt):
+        (JSC::PutByIdStatus::computeFor):
+        * bytecode/PutByIdStatus.h:
+        (JSC::PutByIdStatus::PutByIdStatus):
+        (JSC::PutByIdStatus::structureChain):
+        (PutByIdStatus):
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDesiredStructureChains.cpp: Added.
+        (DFG):
+        (JSC::DFG::DesiredStructureChains::DesiredStructureChains):
+        (JSC::DFG::DesiredStructureChains::~DesiredStructureChains):
+        (JSC::DFG::DesiredStructureChains::areStillValid):
+        * dfg/DFGDesiredStructureChains.h: Added.
+        (DFG):
+        (DesiredStructureChains):
+        (JSC::DFG::DesiredStructureChains::addLazily):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::isStillValid):
+        (DFG):
+        * dfg/DFGGraph.h:
+        (Graph):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        (JSC::DFG::JITCompiler::linkFunction):
+        * ftl/FTLLink.cpp:
+        (JSC::FTL::link):
+        * runtime/IntendedStructureChain.cpp: Added.
+        (JSC):
+        (JSC::IntendedStructureChain::IntendedStructureChain):
+        (JSC::IntendedStructureChain::~IntendedStructureChain):
+        (JSC::IntendedStructureChain::isStillValid):
+        (JSC::IntendedStructureChain::matches):
+        (JSC::IntendedStructureChain::chain):
+        (JSC::IntendedStructureChain::mayInterceptStoreTo):
+        (JSC::IntendedStructureChain::isNormalized):
+        (JSC::IntendedStructureChain::terminalPrototype):
+        * runtime/IntendedStructureChain.h: Added.
+        (JSC):
+        (IntendedStructureChain):
+        (JSC::IntendedStructureChain::head):
+        (JSC::IntendedStructureChain::size):
+        (JSC::IntendedStructureChain::at):
+        (JSC::IntendedStructureChain::operator[]):
+        (JSC::IntendedStructureChain::last):
+        * runtime/Structure.cpp:
+        (JSC::Structure::prototypeChainMayInterceptStoreTo):
+        * runtime/Structure.h:
+        (Structure):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::storedPrototypeObject):
+        (JSC):
+        (JSC::Structure::storedPrototypeStructure):
+
 2013-05-06  Mark Lam  <mark.lam@apple.com>
 
         Fix broken 32-bit build + some clean up in JITStubs.cpp.
index 00df89d..6bf0343 100644 (file)
                A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; };
                A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A72FFD64139985A800E5365A /* KeywordLookup.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C225CD1399849C00FF1662 /* KeywordLookup.h */; };
+               A7301047179A056200C64E38 /* DFGDesiredStructureChains.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7301043179A056200C64E38 /* DFGDesiredStructureChains.cpp */; };
+               A7301048179A056200C64E38 /* DFGDesiredStructureChains.h in Headers */ = {isa = PBXBuildFile; fileRef = A7301044179A056200C64E38 /* DFGDesiredStructureChains.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = A730B6101250068F009D25B1 /* StrictEvalActivation.h */; };
                A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */; };
                A731B25A130093880040A7FA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
                A784A26411D16622005776AC /* SyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A792A33F179A02C5005C1D7D /* VM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A792A33D179A02C5005C1D7D /* VM.cpp */; };
                A792A340179A02C5005C1D7D /* VM.h in Headers */ = {isa = PBXBuildFile; fileRef = A792A33E179A02C5005C1D7D /* VM.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A7A7C341179A063B00EFE1B8 /* IntendedStructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A7C33F179A063B00EFE1B8 /* IntendedStructureChain.cpp */; };
+               A7A7C342179A063B00EFE1B8 /* IntendedStructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7C340179A063B00EFE1B8 /* IntendedStructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7AFC17915F7EFE30048F57B /* ResolveOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = A7AFC17715F7EFE30048F57B /* ResolveOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; };
                A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; };
                A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; };
                A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; };
+               A7301043179A056200C64E38 /* DFGDesiredStructureChains.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredStructureChains.cpp; path = dfg/DFGDesiredStructureChains.cpp; sourceTree = "<group>"; };
+               A7301044179A056200C64E38 /* DFGDesiredStructureChains.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredStructureChains.h; path = dfg/DFGDesiredStructureChains.h; sourceTree = "<group>"; };
                A730B6101250068F009D25B1 /* StrictEvalActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StrictEvalActivation.h; sourceTree = "<group>"; };
                A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StrictEvalActivation.cpp; sourceTree = "<group>"; };
                A7386551118697B400540279 /* SpecializedThunkJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecializedThunkJIT.h; sourceTree = "<group>"; };
                A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedCodeBlock.cpp; sourceTree = "<group>"; };
                A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedCodeBlock.h; sourceTree = "<group>"; };
                A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectRefPrivate.h; sourceTree = "<group>"; };
+               A7A7C33F179A063B00EFE1B8 /* IntendedStructureChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntendedStructureChain.cpp; sourceTree = "<group>"; };
+               A7A7C340179A063B00EFE1B8 /* IntendedStructureChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntendedStructureChain.h; sourceTree = "<group>"; };
                A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTBuilder.h; sourceTree = "<group>"; };
                A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyntaxChecker.h; sourceTree = "<group>"; };
                A7AFC17715F7EFE30048F57B /* ResolveOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResolveOperation.h; sourceTree = "<group>"; };
                034768DFFF38A50411DB9C8B /* Products */ = {
                        isa = PBXGroup;
                        children = (
+                               0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
                                932F5BD90822A1C700736975 /* JavaScriptCore.framework */,
                                932F5BE10822A1C700736975 /* jsc */,
-                               0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
                                141211200A48793C00480255 /* minidom */,
                                14BD59BF0A3E8F9000BAF59C /* testapi */,
                                6511230514046A4C002B101D /* testRegExp */,
                                0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
                                E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
                                E178633F0D9BEC0000D74E75 /* InitializeThreading.h */,
+                               A7A7C33F179A063B00EFE1B8 /* IntendedStructureChain.cpp */,
+                               A7A7C340179A063B00EFE1B8 /* IntendedStructureChain.h */,
                                BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */,
                                BC11667A0E199C05008066DD /* InternalFunction.h */,
                                86BF642A148DB2B5004DE36A /* Intrinsic.h */,
                                0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
                                0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
                                0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
+                               A7301043179A056200C64E38 /* DFGDesiredStructureChains.cpp */,
+                               A7301044179A056200C64E38 /* DFGDesiredStructureChains.h */,
                                0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
                                0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */,
                                0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */,
                                0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */,
                                BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
                                0FB7F39515ED8E4600F167B2 /* ArrayConventions.h in Headers */,
-                               0F0D85B21723455400338210 /* CodeBlockLock.h in Headers */,
                                0F63945515D07057006A597C /* ArrayProfile.h in Headers */,
                                BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
                                BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */,
                                0F73D7AF165A143000ACAB71 /* ClosureCallStubRoutine.h in Headers */,
                                969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */,
                                0F8F94411667633200D61971 /* CodeBlockHash.h in Headers */,
+                               0F0D85B21723455400338210 /* CodeBlockLock.h in Headers */,
                                0F96EBB316676EF6008BADE3 /* CodeBlockWithJITType.h in Headers */,
                                A77F1822164088B200640A47 /* CodeCache.h in Headers */,
                                86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */,
                                0FBE0F7316C1DB050082C5E8 /* DFGCPSRethreadingPhase.h in Headers */,
                                0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */,
                                0F2FC77316E12F740038D976 /* DFGDCEPhase.h in Headers */,
+                               0F8F2B9A172F0501007DBDA5 /* DFGDesiredIdentifiers.h in Headers */,
+                               A7301048179A056200C64E38 /* DFGDesiredStructureChains.h in Headers */,
+                               0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
                                0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */,
                                0FD81AD3154FB4F000983E72 /* DFGDominators.h in Headers */,
                                0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */,
                                0FEA0A2C170B661900BB722C /* FTLFormattedValue.h in Headers */,
                                0FEA0A241709606900BB722C /* FTLIntrinsicRepository.h in Headers */,
                                0FEA0A0E170513DB00BB722C /* FTLJITCode.h in Headers */,
+                               0F8F2B96172E04A3007DBDA5 /* FTLLink.h in Headers */,
                                0FEA0A141706363600BB722C /* FTLLLVMHeaders.h in Headers */,
                                0FEA0A10170513DB00BB722C /* FTLLowerDFGToLLVM.h in Headers */,
                                0F235BDD17178E1C00690C7F /* FTLOSRExit.h in Headers */,
                                0FB7F39B15ED8E4600F167B2 /* IndexingType.h in Headers */,
                                BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */,
                                969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */,
+                               A7A7C342179A063B00EFE1B8 /* IntendedStructureChain.h in Headers */,
                                BC11667B0E199C05008066DD /* InternalFunction.h in Headers */,
                                1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */,
                                860BD801148EA6F200112B2F /* Intrinsic.h in Headers */,
                                BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
                                BC18C4210E16F5CD00B34460 /* JSGlobalObject.h in Headers */,
                                BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */,
-                               0F8F2B96172E04A3007DBDA5 /* FTLLink.h in Headers */,
                                A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */,
                                BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */,
                                C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */,
                                86E3C612167BABD7006D760A /* JSValue.h in Headers */,
                                86E3C61B167BABEE006D760A /* JSValueInternal.h in Headers */,
                                BC18C42C0E16F5CD00B34460 /* JSValueRef.h in Headers */,
-                               0F8F2B9A172F0501007DBDA5 /* DFGDesiredIdentifiers.h in Headers */,
                                BC18C42D0E16F5CD00B34460 /* JSVariableObject.h in Headers */,
                                86E3C615167BABD7006D760A /* JSVirtualMachine.h in Headers */,
                                86E3C61D167BABEE006D760A /* JSVirtualMachineInternal.h in Headers */,
                                FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */,
                                0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
                                0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
-                               0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
                                0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */,
                                0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */,
                                0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */,
                                147F39BD107EC37600427A48 /* ArgList.cpp in Sources */,
                                147F39BE107EC37600427A48 /* Arguments.cpp in Sources */,
                                86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */,
-                               0F6E5C191724AF3D005C574F /* WebKitLLVMLibraryAnchor.cpp in Sources */,
                                A74DE1D0120B875600D40D5B /* ARMv7Assembler.cpp in Sources */,
                                65C02850171795E200351E35 /* ARMv7Disassembler.cpp in Sources */,
                                65C0285C1717966800351E35 /* ARMv7DOpcode.cpp in Sources */,
                                BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */,
                                149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */,
                                0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */,
+                               0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */,
                                0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */,
                                0F63948415E48118006A597C /* DFGArrayMode.cpp in Sources */,
                                0FC0976E1468AB5100CF2442 /* DFGAssemblyHelpers.cpp in Sources */,
                                0FBE0F7216C1DB030082C5E8 /* DFGCPSRethreadingPhase.cpp in Sources */,
                                0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
                                0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
+                               0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
+                               A7301047179A056200C64E38 /* DFGDesiredStructureChains.cpp in Sources */,
+                               0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
                                0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */,
                                0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */,
                                0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */,
                                86EC9DD21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp in Sources */,
                                86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */,
                                86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
-                               0F8F2B9E17306C8D007DBDA5 /* SourceCode.cpp in Sources */,
                                0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
                                0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */,
                                0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */,
                                0F235BDA17178E1C00690C7F /* FTLExitValue.cpp in Sources */,
                                0FEA0A281709623B00BB722C /* FTLIntrinsicRepository.cpp in Sources */,
                                0FEA0A0D170513DB00BB722C /* FTLJITCode.cpp in Sources */,
+                               0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
                                0FEA0A0F170513DB00BB722C /* FTLLowerDFGToLLVM.cpp in Sources */,
                                0F235BDC17178E1C00690C7F /* FTLOSRExit.cpp in Sources */,
                                0F235BDF17178E1C00690C7F /* FTLOSRExitCompiler.cpp in Sources */,
                                0FF0F19F16B72A17005DF95B /* FunctionExecutableDump.cpp in Sources */,
                                147F39CC107EC37600427A48 /* FunctionPrototype.cpp in Sources */,
                                C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */,
-                               0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
                                0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
                                C2239D1A16262BDD005AC5FD /* GCThread.cpp in Sources */,
                                C21122E115DD9AB300790E3A /* GCThreadSharedData.cpp in Sources */,
                                0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */,
                                14280855107EC0E70013E7B2 /* GetterSetter.cpp in Sources */,
                                142E3135134FF0A600AFADB5 /* HandleSet.cpp in Sources */,
-                               0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */,
                                142E3137134FF0A600AFADB5 /* HandleStack.cpp in Sources */,
                                14BA7A9713AADFF8005B7C2C /* Heap.cpp in Sources */,
                                C24D31E2161CD695002AA4DB /* HeapStatistics.cpp in Sources */,
                                C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */,
                                0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */,
                                E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */,
+                               A7A7C341179A063B00EFE1B8 /* IntendedStructureChain.cpp in Sources */,
                                147F39CF107EC37600427A48 /* InternalFunction.cpp in Sources */,
                                1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */,
                                1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */,
                                14469DE7107EC7E700650446 /* PropertyNameArray.cpp in Sources */,
                                14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */,
                                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
-                               0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
                                1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */,
                                0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
                                0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
                                1429D8850ED21C3D00B89619 /* SamplingTool.cpp in Sources */,
                                C225494315F7DBAA0065E898 /* SlotVisitor.cpp in Sources */,
                                9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */,
+                               0F8F2B9E17306C8D007DBDA5 /* SourceCode.cpp in Sources */,
                                0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */,
                                E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */,
                                0F0CD4C415F6B6BB0032F1C0 /* SparseArrayValueMap.cpp in Sources */,
                                BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */,
                                C2DF442F1707AC0100A5CA96 /* SuperRegion.cpp in Sources */,
                                0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */,
-                               0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
                                A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */,
                                0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
                                0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,
                                14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */,
                                14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */,
                                14E84FA014EE1ACC00D6D5D4 /* WeakSet.cpp in Sources */,
+                               0F6E5C191724AF3D005C574F /* WebKitLLVMLibraryAnchor.cpp in Sources */,
                                0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */,
                                863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */,
                                86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */,
index 33a2eb7..3a8c700 100644 (file)
@@ -64,7 +64,7 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
 #endif
 }
 
-void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBlock, StringImpl* uid, Structure* structure)
+void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBlock, StringImpl* uid)
 {
 #if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
     // Validate the chain. If the chain is invalid, then currently the best thing
@@ -77,17 +77,13 @@ void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBl
     // have now is that if the structure chain has changed between when it was
     // cached on in the baseline JIT and when the DFG tried to inline the access,
     // then we fall back on a polymorphic access.
-    Structure* currentStructure = structure;
-    JSObject* currentObject = 0;
-    for (unsigned i = 0; i < result.m_chain.size(); ++i) {
-        ASSERT(!currentStructure->isDictionary());
-        currentObject = asObject(currentStructure->prototypeForLookup(profiledBlock));
-        currentStructure = result.m_chain[i];
-        if (currentObject->structure() != currentStructure)
-            return;
-    }
+    if (!result.m_chain->isStillValid())
+        return;
     
-    ASSERT(currentObject);
+    JSObject* currentObject = result.m_chain->terminalPrototype();
+    Structure* currentStructure = result.m_chain->last();
+    
+    ASSERT_UNUSED(currentObject, currentObject);
         
     unsigned attributesIgnored;
     JSCell* specificValue;
@@ -99,13 +95,12 @@ void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBl
     if (!isValidOffset(result.m_offset))
         return;
         
-    result.m_structureSet.add(structure);
+    result.m_structureSet.add(result.m_chain->head());
     result.m_specificValue = JSValue(specificValue);
 #else
     UNUSED_PARAM(result);
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(uid);
-    UNUSED_PARAM(structure);
     UNREACHABLE_FOR_PLATFORM();
 #endif
 }
@@ -221,21 +216,23 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
     case access_get_by_id_proto: {
         if (!stubInfo.u.getByIdProto.isDirect)
             return GetByIdStatus(MakesCalls, true);
-        result.m_chain.append(stubInfo.u.getByIdProto.prototypeStructure.get());
-        computeForChain(
-            result, profiledBlock, uid,
-            stubInfo.u.getByIdProto.baseObjectStructure.get());
+        result.m_chain = adoptRef(new IntendedStructureChain(
+            profiledBlock,
+            stubInfo.u.getByIdProto.baseObjectStructure.get(),
+            stubInfo.u.getByIdProto.prototypeStructure.get()));
+        computeForChain(result, profiledBlock, uid);
         break;
     }
         
     case access_get_by_id_chain: {
         if (!stubInfo.u.getByIdChain.isDirect)
             return GetByIdStatus(MakesCalls, true);
-        for (unsigned i = 0; i < stubInfo.u.getByIdChain.count; ++i)
-            result.m_chain.append(stubInfo.u.getByIdChain.chain->head()[i].get());
-        computeForChain(
-            result, profiledBlock, uid,
-            stubInfo.u.getByIdChain.baseObjectStructure.get());
+        result.m_chain = adoptRef(new IntendedStructureChain(
+            profiledBlock,
+            stubInfo.u.getByIdChain.baseObjectStructure.get(),
+            stubInfo.u.getByIdChain.chain.get(),
+            stubInfo.u.getByIdChain.count));
+        computeForChain(result, profiledBlock, uid);
         break;
     }
         
index c2f185d..844afa8 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef GetByIdStatus_h
 #define GetByIdStatus_h
 
+#include "IntendedStructureChain.h"
 #include "PropertyOffset.h"
 #include "StructureSet.h"
 #include <wtf/NotFound.h>
@@ -59,7 +60,7 @@ public:
     
     GetByIdStatus(
         State state, bool wasSeenInJIT, const StructureSet& structureSet = StructureSet(),
-        PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>())
+        PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), PassRefPtr<IntendedStructureChain> chain = nullptr)
         : m_state(state)
         , m_structureSet(structureSet)
         , m_chain(chain)
@@ -82,19 +83,19 @@ public:
     bool makesCalls() const { return m_state == MakesCalls; }
     
     const StructureSet& structureSet() const { return m_structureSet; }
-    const Vector<Structure*>& chain() const { return m_chain; } // Returns empty vector if this is a direct access.
+    IntendedStructureChain* chain() const { return const_cast<IntendedStructureChain*>(m_chain.get()); } // Returns null if this is a direct access.
     JSValue specificValue() const { return m_specificValue; } // Returns JSValue() if there is no specific value.
     PropertyOffset offset() const { return m_offset; }
     
     bool wasSeenInJIT() const { return m_wasSeenInJIT; }
     
 private:
-    static void computeForChain(GetByIdStatus& result, CodeBlock*, StringImpl* uid, Structure*);
+    static void computeForChain(GetByIdStatus& result, CodeBlock*, StringImpl* uid);
     static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
     
     State m_state;
     StructureSet m_structureSet;
-    Vector<Structure*> m_chain;
+    RefPtr<IntendedStructureChain> m_chain;
     JSValue m_specificValue;
     PropertyOffset m_offset;
     bool m_wasSeenInJIT;
index 1419725..b50ff19 100644 (file)
@@ -72,7 +72,10 @@ PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
     if (!isValidOffset(offset))
         return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
     
-    return PutByIdStatus(SimpleTransition, structure, newStructure, chain, offset);
+    return PutByIdStatus(
+        SimpleTransition, structure, newStructure,
+        chain ? adoptRef(new IntendedStructureChain(profiledBlock, structure, chain)) : 0,
+        offset);
 #else
     return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
 #endif
@@ -129,7 +132,9 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
                 SimpleTransition,
                 stubInfo.u.putByIdTransition.previousStructure.get(),
                 stubInfo.u.putByIdTransition.structure.get(),
-                stubInfo.u.putByIdTransition.chain.get(),
+                stubInfo.u.putByIdTransition.chain ? adoptRef(new IntendedStructureChain(
+                    profiledBlock, stubInfo.u.putByIdTransition.previousStructure.get(),
+                    stubInfo.u.putByIdTransition.chain.get())) : 0,
                 offset);
         }
         return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
@@ -181,9 +186,12 @@ PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, St
     if (structure->typeInfo().type() == StringType)
         return PutByIdStatus(TakesSlowPath);
     
+    RefPtr<IntendedStructureChain> chain;
     if (!isDirect) {
+        chain = adoptRef(new IntendedStructureChain(globalObject, structure));
+        
         // If the prototype chain has setters or read-only properties, then give up.
-        if (structure->prototypeChainMayInterceptStoreTo(vm, uid))
+        if (chain->mayInterceptStoreTo(vm, uid))
             return PutByIdStatus(TakesSlowPath);
         
         // If the prototype chain hasn't been normalized (i.e. there are proxies or dictionaries)
@@ -193,7 +201,7 @@ PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, St
         // dictionaries if we have evidence to suggest that those objects were never used as
         // prototypes in a cacheable prototype access - i.e. there's a good chance that some of
         // the other checks below will fail.
-        if (!isPrototypeChainNormalized(globalObject, structure))
+        if (!chain->isNormalized())
             return PutByIdStatus(TakesSlowPath);
     }
     
@@ -216,9 +224,7 @@ PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, St
     ASSERT(!transition->transitionDidInvolveSpecificValue());
     ASSERT(isValidOffset(offset));
     
-    return PutByIdStatus(
-        SimpleTransition, structure, transition,
-        structure->prototypeChain(vm, globalObject), offset);
+    return PutByIdStatus(SimpleTransition, structure, transition, chain.release(), offset);
 }
 
 } // namespace JSC
index 87878e7..ba2cf11 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef PutByIdStatus_h
 #define PutByIdStatus_h
 
+#include "IntendedStructureChain.h"
 #include "PropertyOffset.h"
 #include <wtf/NotFound.h>
 #include <wtf/text/StringImpl.h>
@@ -76,7 +77,7 @@ public:
         State state,
         Structure* oldStructure,
         Structure* newStructure,
-        StructureChain* structureChain,
+        PassRefPtr<IntendedStructureChain> structureChain,
         PropertyOffset offset)
         : m_state(state)
         , m_oldStructure(oldStructure)
@@ -86,7 +87,7 @@ public:
     {
         ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure);
         ASSERT((m_state != SimpleTransition) == !m_newStructure);
-        ASSERT((m_state != SimpleTransition) == !m_structureChain);
+        ASSERT(!((m_state != SimpleTransition) && m_structureChain));
         ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == invalidOffset));
     }
     
@@ -103,7 +104,7 @@ public:
     
     Structure* oldStructure() const { return m_oldStructure; }
     Structure* newStructure() const { return m_newStructure; }
-    StructureChain* structureChain() const { return m_structureChain; }
+    IntendedStructureChain* structureChain() const { return m_structureChain.get(); }
     PropertyOffset offset() const { return m_offset; }
     
 private:
@@ -112,7 +113,7 @@ private:
     State m_state;
     Structure* m_oldStructure;
     Structure* m_newStructure;
-    StructureChain* m_structureChain;
+    RefPtr<IntendedStructureChain> m_structureChain;
     PropertyOffset m_offset;
 };
 
index ea77b8e..ba277ca 100644 (file)
@@ -1301,7 +1301,7 @@ bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
                     // Assert things that we can't handle and that the computeFor() method
                     // above won't be able to return.
                     ASSERT(status.structureSet().size() == 1);
-                    ASSERT(status.chain().isEmpty());
+                    ASSERT(!status.chain());
                     
                     if (status.specificValue())
                         forNode(node).set(m_graph, status.specificValue());
index 55dbf8b..e6b6a9d 100644 (file)
@@ -1735,12 +1735,13 @@ void ByteCodeParser::handleGetById(
                 
     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
     
-    if (!getByIdStatus.chain().isEmpty()) {
+    if (getByIdStatus.chain()) {
+        m_graph.m_chains.addLazily(getByIdStatus.chain());
         Structure* currentStructure = getByIdStatus.structureSet().singletonStructure();
         JSObject* currentObject = 0;
-        for (unsigned i = 0; i < getByIdStatus.chain().size(); ++i) {
+        for (unsigned i = 0; i < getByIdStatus.chain()->size(); ++i) {
             currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
-            currentStructure = getByIdStatus.chain()[i];
+            currentStructure = getByIdStatus.chain()->at(i);
             base = addStructureTransitionCheck(currentObject, currentStructure);
         }
     }
@@ -2617,13 +2618,14 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 storageAccessData.offset = indexRelativeToBase(putByIdStatus.offset());
                 storageAccessData.identifierNumber = identifierNumber;
                 m_graph.m_storageAccessData.append(storageAccessData);
-            } else if (!hasExitSite
-                       && putByIdStatus.isSimpleTransition()
-                       && structureChainIsStillValid(
-                           direct,
-                           putByIdStatus.oldStructure(),
-                           putByIdStatus.structureChain())) {
-
+            } else if (
+                !hasExitSite
+                && putByIdStatus.isSimpleTransition()
+                && (!putByIdStatus.structureChain()
+                    || putByIdStatus.structureChain()->isStillValid())) {
+                
+                m_graph.m_chains.addLazily(putByIdStatus.structureChain());
+                
                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
                 if (!direct) {
                     if (!putByIdStatus.oldStructure()->storedPrototype().isNull()) {
@@ -2631,8 +2633,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                             putByIdStatus.oldStructure()->storedPrototype().asCell());
                     }
                     
-                    for (WriteBarrier<Structure>* it = putByIdStatus.structureChain()->head(); *it; ++it) {
-                        JSValue prototype = (*it)->storedPrototype();
+                    for (unsigned i = 0; i < putByIdStatus.structureChain()->size(); ++i) {
+                        JSValue prototype = putByIdStatus.structureChain()->at(i)->storedPrototype();
                         if (prototype.isNull())
                             continue;
                         ASSERT(prototype.isCell());
index c289743..4151bef 100644 (file)
@@ -164,7 +164,7 @@ private:
                 }
                 
                 ASSERT(status.structureSet().size() == 1);
-                ASSERT(status.chain().isEmpty());
+                ASSERT(!status.chain());
                 ASSERT(status.structureSet().singletonStructure() == structure);
                 
                 // Now before we do anything else, push the CFA forward over the GetById
@@ -261,8 +261,10 @@ private:
                                 structure->storedPrototype().asCell());
                         }
                         
-                        for (WriteBarrier<Structure>* it = status.structureChain()->head(); *it; ++it) {
-                            JSValue prototype = (*it)->storedPrototype();
+                        m_graph.m_chains.addLazily(status.structureChain());
+                        
+                        for (unsigned i = 0; i < status.structureChain()->size(); ++i) {
+                            JSValue prototype = status.structureChain()->at(i)->storedPrototype();
                             if (prototype.isNull())
                                 continue;
                             ASSERT(prototype.isCell());
diff --git a/Source/JavaScriptCore/dfg/DFGDesiredStructureChains.cpp b/Source/JavaScriptCore/dfg/DFGDesiredStructureChains.cpp
new file mode 100644 (file)
index 0000000..04bd5f0
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGDesiredStructureChains.h"
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+DesiredStructureChains::DesiredStructureChains() { }
+DesiredStructureChains::~DesiredStructureChains() { }
+
+bool DesiredStructureChains::areStillValid() const
+{
+    for (unsigned i = 0; i < m_vector.size(); ++i) {
+        if (!m_vector[i]->isStillValid())
+            return false;
+    }
+    return true;
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/Source/JavaScriptCore/dfg/DFGDesiredStructureChains.h b/Source/JavaScriptCore/dfg/DFGDesiredStructureChains.h
new file mode 100644 (file)
index 0000000..553e962
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGDesiredStructureChains_h
+#define DFGDesiredStructureChains_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "IntendedStructureChain.h"
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+class DesiredStructureChains {
+public:
+    DesiredStructureChains();
+    ~DesiredStructureChains();
+    
+    void addLazily(PassRefPtr<IntendedStructureChain> chain)
+    {
+        m_vector.append(chain);
+    }
+    
+    bool areStillValid() const;
+private:
+    Vector<RefPtr<IntendedStructureChain> > m_vector;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGDesiredStructureChains_h
+
index f54f2fa..a1b7220 100644 (file)
@@ -445,6 +445,12 @@ void Graph::resetExitStates()
     }
 }
 
+bool Graph::isStillValid() const
+{
+    return m_watchpoints.areStillValid()
+        && m_chains.areStillValid();
+}
+
 } } // namespace JSC::DFG
 
 #endif
index 87cf0a0..83e9765 100644 (file)
@@ -35,6 +35,7 @@
 #include "DFGAssemblyHelpers.h"
 #include "DFGBasicBlock.h"
 #include "DFGDesiredIdentifiers.h"
+#include "DFGDesiredStructureChains.h"
 #include "DFGDesiredWatchpoints.h"
 #include "DFGDominators.h"
 #include "DFGLongLivedState.h"
@@ -700,6 +701,8 @@ public:
         }
     }
     
+    bool isStillValid() const;
+    
     VM& m_vm;
     CodeBlock* m_codeBlock;
     RefPtr<Profiler::Compilation> m_compilation;
@@ -729,6 +732,7 @@ public:
     Operands<JSValue> m_mustHandleValues;
     DesiredWatchpoints m_watchpoints;
     DesiredIdentifiers m_identifiers;
+    DesiredStructureChains m_chains;
     
     OptimizationFixpointState m_fixpointState;
     GraphForm m_form;
index 0e89d4f..80063c3 100644 (file)
@@ -272,7 +272,7 @@ bool JITCompiler::compile()
 
 bool JITCompiler::link(RefPtr<JSC::JITCode>& entry)
 {
-    if (!m_graph.m_watchpoints.areStillValid())
+    if (!m_graph.isStillValid())
         return false;
     
     LinkBuffer linkBuffer(*m_vm, this, m_codeBlock, JITCompilationCanFail);
@@ -372,7 +372,7 @@ bool JITCompiler::compileFunction()
 
 bool JITCompiler::linkFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck)
 {
-    if (!m_graph.m_watchpoints.areStillValid())
+    if (!m_graph.isStillValid())
         return false;
 
     // === Link ===
diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h
deleted file mode 100644 (file)
index e69de29..0000000
index a65ec00..4f85a58 100644 (file)
@@ -49,7 +49,7 @@ static void compileEntry(CCallHelpers& jit)
 
 bool link(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
 {
-    if (!state.graph.m_watchpoints.areStillValid()) {
+    if (!state.graph.isStillValid()) {
         LLVMDisposeExecutionEngine(state.engine);
         return false;
     }
diff --git a/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp b/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp
new file mode 100644 (file)
index 0000000..b38dae9
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2013 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "IntendedStructureChain.h"
+
+#include "CodeBlock.h"
+#include "Operations.h"
+#include "StructureChain.h"
+
+namespace JSC {
+
+IntendedStructureChain::IntendedStructureChain(JSGlobalObject* globalObject, Structure* head)
+    : m_globalObject(globalObject)
+    , m_head(head)
+{
+    JSValue prototype = head->prototypeForLookup(globalObject);
+    if (prototype.isNull())
+        return;
+    for (Structure* current = asObject(prototype)->structure(); current; current = current->storedPrototypeStructure())
+        m_vector.append(current);
+}
+
+IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, Structure* prototypeStructure)
+    : m_globalObject(codeBlock->globalObject())
+    , m_head(head)
+{
+    m_vector.append(prototypeStructure);
+}
+
+IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain)
+    : m_globalObject(codeBlock->globalObject())
+    , m_head(head)
+{
+    for (unsigned i = 0; chain->head()[i]; ++i)
+        m_vector.append(chain->head()[i].get());
+}
+
+IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain, unsigned count)
+    : m_globalObject(codeBlock->globalObject())
+    , m_head(head)
+{
+    for (unsigned i = 0; i < count; ++i)
+        m_vector.append(chain->head()[i].get());
+}
+
+IntendedStructureChain::~IntendedStructureChain()
+{
+}
+
+bool IntendedStructureChain::isStillValid() const
+{
+    JSValue currentPrototype = m_head->prototypeForLookup(m_globalObject);
+    for (unsigned i = 0; i < m_vector.size(); ++i) {
+        if (asObject(currentPrototype)->structure() != m_vector[i])
+            return false;
+        currentPrototype = m_vector[i]->storedPrototype();
+    }
+    return true;
+}
+
+bool IntendedStructureChain::matches(StructureChain* chain) const
+{
+    for (unsigned i = 0; i < m_vector.size(); ++i) {
+        if (m_vector[i] != chain->head()[i].get())
+            return false;
+    }
+    if (chain->head()[m_vector.size()])
+        return false;
+    return true;
+}
+
+StructureChain* IntendedStructureChain::chain(VM& vm) const
+{
+    ASSERT(isStillValid());
+    StructureChain* result = StructureChain::create(vm, m_head);
+    ASSERT(matches(result));
+    return result;
+}
+
+bool IntendedStructureChain::mayInterceptStoreTo(VM& vm, StringImpl* uid)
+{
+    for (unsigned i = 0; i < m_vector.size(); ++i) {
+        unsigned attributes;
+        JSCell* specificValue;
+        PropertyOffset offset = m_vector[i]->getConcurrently(vm, uid, attributes, specificValue);
+        if (!isValidOffset(offset))
+            continue;
+        if (attributes & (ReadOnly | Accessor))
+            return true;
+        return false;
+    }
+    return false;
+}
+
+bool IntendedStructureChain::isNormalized()
+{
+    if (m_head->typeInfo().type() == ProxyType)
+        return false;
+    for (unsigned i = 0; i < m_vector.size(); ++i) {
+        Structure* structure = m_vector[i];
+        if (structure->typeInfo().type() == ProxyType)
+            return false;
+        if (structure->isDictionary())
+            return false;
+    }
+    return true;
+}
+
+JSObject* IntendedStructureChain::terminalPrototype() const
+{
+    ASSERT(!m_vector.isEmpty());
+    if (m_vector.size() == 1)
+        return asObject(m_head->prototypeForLookup(m_globalObject));
+    return asObject(m_vector[m_vector.size() - 2]->storedPrototype());
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/runtime/IntendedStructureChain.h b/Source/JavaScriptCore/runtime/IntendedStructureChain.h
new file mode 100644 (file)
index 0000000..40af95c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef IntendedStructureChain_h
+#define IntendedStructureChain_h
+
+#include "Structure.h"
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+class CodeBlock;
+class JSGlobalObject;
+class StructureChain;
+class VM;
+
+class IntendedStructureChain : public RefCounted<IntendedStructureChain> {
+public:
+    IntendedStructureChain(JSGlobalObject* globalObject, Structure* head);
+    IntendedStructureChain(CodeBlock* codeBlock, Structure* head, Structure* prototypeStructure);
+    IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain);
+    IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain, unsigned count);
+    ~IntendedStructureChain();
+    
+    bool isStillValid() const;
+    bool matches(StructureChain*) const;
+    StructureChain* chain(VM&) const;
+    bool mayInterceptStoreTo(VM&, StringImpl* uid);
+    bool isNormalized();
+    
+    Structure* head() const { return m_head; }
+    
+    size_t size() const { return m_vector.size(); }
+    Structure* at(size_t index) { return m_vector[index]; }
+    Structure* operator[](size_t index) { return at(index); }
+    
+    JSObject* terminalPrototype() const;
+    
+    Structure* last() const { return m_vector.last(); }
+private:
+    JSGlobalObject* m_globalObject;
+    Structure* m_head;
+    Vector<Structure*> m_vector;
+};
+
+} // namespace JSC
+
+#endif // IntendedStructureChain_h
index b2190aa..20f05f5 100644 (file)
@@ -970,13 +970,9 @@ void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
         thisObject->m_propertyTableUnsafe.clear();
 }
 
-bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, StringImpl* uid)
+bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
 {
-    // Note, this method is called from two kinds of places: (1) assertions and (2)
-    // the compilation thread. As such, it does things somewhat carefully to ensure
-    // thread safety. Currently that only affects the way we do Structure::get().
-    
-    unsigned i = toUInt32FromStringImpl(uid);
+    unsigned i = propertyName.asIndex();
     if (i != PropertyName::NotAnIndex)
         return anyObjectInChainMayInterceptIndexedAccesses();
     
@@ -989,7 +985,7 @@ bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, StringImpl* uid)
         
         unsigned attributes;
         JSCell* specificValue;
-        PropertyOffset offset = current->getConcurrently(vm, uid, attributes, specificValue);
+        PropertyOffset offset = current->get(vm, propertyName, attributes, specificValue);
         if (!JSC::isValidOffset(offset))
             continue;
         
@@ -1000,11 +996,6 @@ bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, StringImpl* uid)
     }
 }
 
-bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
-{
-    return prototypeChainMayInterceptStoreTo(vm, propertyName.uid());
-}
-
 #if DO_PROPERTYMAP_CONSTENCY_CHECK
 
 void PropertyTable::checkConsistency()
index 12a411b..51a119c 100644 (file)
@@ -154,6 +154,8 @@ public:
     void setGlobalObject(VM& vm, JSGlobalObject* globalObject) { m_globalObject.set(vm, this, globalObject); }
         
     JSValue storedPrototype() const { return m_prototype.get(); }
+    JSObject* storedPrototypeObject() const;
+    Structure* storedPrototypeStructure() const;
     JSValue prototypeForLookup(ExecState*) const;
     JSValue prototypeForLookup(JSGlobalObject*) const;
     JSValue prototypeForLookup(CodeBlock*) const;
@@ -162,7 +164,6 @@ public:
     static void visitChildren(JSCell*, SlotVisitor&);
         
     // Will just the prototype chain intercept this property access?
-    bool prototypeChainMayInterceptStoreTo(VM&, StringImpl* uid);
     bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
         
     bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }
index 4e4286d..3a90565 100644 (file)
@@ -56,6 +56,22 @@ inline Structure* Structure::create(VM& vm, const Structure* structure)
     return newStructure;
 }
 
+inline JSObject* Structure::storedPrototypeObject() const
+{
+    JSValue value = m_prototype.get();
+    if (value.isNull())
+        return 0;
+    return asObject(value);
+}
+
+inline Structure* Structure::storedPrototypeStructure() const
+{
+    JSObject* object = storedPrototypeObject();
+    if (!object)
+        return 0;
+    return object->structure();
+}
+
 inline PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
 {
     ASSERT(!isCompilationThread());