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):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index a7fc98e..f3095cb 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -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.
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 00df89d..6bf0343 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -740,6 +740,8 @@
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 */; };
@@ -762,6 +764,8 @@
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, ); }; };
@@ -1734,6 +1738,8 @@
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>"; };
@@ -1755,6 +1761,8 @@
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>"; };
@@ -2021,9 +2029,9 @@
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
+ 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
932F5BD90822A1C700736975 /* JavaScriptCore.framework */,
932F5BE10822A1C700736975 /* jsc */,
- 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
141211200A48793C00480255 /* minidom */,
14BD59BF0A3E8F9000BAF59C /* testapi */,
6511230514046A4C002B101D /* testRegExp */,
@@ -2655,6 +2663,8 @@
0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
E178633F0D9BEC0000D74E75 /* InitializeThreading.h */,
+ A7A7C33F179A063B00EFE1B8 /* IntendedStructureChain.cpp */,
+ A7A7C340179A063B00EFE1B8 /* IntendedStructureChain.h */,
BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */,
BC11667A0E199C05008066DD /* InternalFunction.h */,
86BF642A148DB2B5004DE36A /* Intrinsic.h */,
@@ -2903,6 +2913,8 @@
0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
+ A7301043179A056200C64E38 /* DFGDesiredStructureChains.cpp */,
+ A7301044179A056200C64E38 /* DFGDesiredStructureChains.h */,
0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */,
0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */,
@@ -3203,7 +3215,6 @@
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 */,
@@ -3231,6 +3242,7 @@
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 */,
@@ -3289,6 +3301,9 @@
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 */,
@@ -3373,6 +3388,7 @@
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 */,
@@ -3413,6 +3429,7 @@
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 */,
@@ -3459,7 +3476,6 @@
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 */,
@@ -3488,7 +3504,6 @@
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 */,
@@ -3514,7 +3529,6 @@
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 */,
@@ -4048,7 +4062,6 @@
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 */,
@@ -4088,6 +4101,7 @@
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 */,
@@ -4103,6 +4117,9 @@
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 */,
@@ -4133,7 +4150,6 @@
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 */,
@@ -4167,6 +4183,7 @@
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 */,
@@ -4179,14 +4196,12 @@
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 */,
@@ -4196,6 +4211,7 @@
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 */,
@@ -4324,7 +4340,6 @@
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 */,
@@ -4340,6 +4355,7 @@
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 */,
@@ -4357,7 +4373,6 @@
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 */,
@@ -4378,6 +4393,7 @@
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 */,
diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
index 33a2eb7..3a8c700 100644
--- a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
@@ -64,7 +64,7 @@
#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 @@
// 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 @@
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 @@
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;
}
diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.h b/Source/JavaScriptCore/bytecode/GetByIdStatus.h
index c2f185d..844afa8 100644
--- a/Source/JavaScriptCore/bytecode/GetByIdStatus.h
+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.h
@@ -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 @@
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 @@
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;
diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
index 1419725..b50ff19 100644
--- a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
+++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
@@ -72,7 +72,10 @@
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 @@
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 @@
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 @@
// 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 @@
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
diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.h b/Source/JavaScriptCore/bytecode/PutByIdStatus.h
index 87878e7..ba2cf11 100644
--- a/Source/JavaScriptCore/bytecode/PutByIdStatus.h
+++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.h
@@ -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 @@
State state,
Structure* oldStructure,
Structure* newStructure,
- StructureChain* structureChain,
+ PassRefPtr<IntendedStructureChain> structureChain,
PropertyOffset offset)
: m_state(state)
, m_oldStructure(oldStructure)
@@ -86,7 +87,7 @@
{
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 @@
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 @@
State m_state;
Structure* m_oldStructure;
Structure* m_newStructure;
- StructureChain* m_structureChain;
+ RefPtr<IntendedStructureChain> m_structureChain;
PropertyOffset m_offset;
};
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index ea77b8e..ba277ca 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -1301,7 +1301,7 @@
// 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());
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 55dbf8b..e6b6a9d 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -1735,12 +1735,13 @@
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 @@
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 @@
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());
diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
index c289743..4151bef 100644
--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
@@ -164,7 +164,7 @@
}
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 @@
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
index 0000000..04bd5f0
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGDesiredStructureChains.cpp
@@ -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
index 0000000..553e962
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGDesiredStructureChains.h
@@ -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
+
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index f54f2fa..a1b7220 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -445,6 +445,12 @@
}
}
+bool Graph::isStillValid() const
+{
+ return m_watchpoints.areStillValid()
+ && m_chains.areStillValid();
+}
+
} } // namespace JSC::DFG
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 87cf0a0..83e9765 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -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 @@
}
}
+ bool isStillValid() const;
+
VM& m_vm;
CodeBlock* m_codeBlock;
RefPtr<Profiler::Compilation> m_compilation;
@@ -729,6 +732,7 @@
Operands<JSValue> m_mustHandleValues;
DesiredWatchpoints m_watchpoints;
DesiredIdentifiers m_identifiers;
+ DesiredStructureChains m_chains;
OptimizationFixpointState m_fixpointState;
GraphForm m_form;
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index 0e89d4f..80063c3 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -272,7 +272,7 @@
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::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
index e69de29..0000000
--- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
+++ /dev/null
diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h
deleted file mode 100644
index e69de29..0000000
--- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h
+++ /dev/null
diff --git a/Source/JavaScriptCore/ftl/FTLLink.cpp b/Source/JavaScriptCore/ftl/FTLLink.cpp
index a65ec00..4f85a58 100644
--- a/Source/JavaScriptCore/ftl/FTLLink.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLink.cpp
@@ -49,7 +49,7 @@
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
index 0000000..b38dae9
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp
@@ -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
index 0000000..40af95c
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/IntendedStructureChain.h
@@ -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
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index b2190aa..20f05f5 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -970,13 +970,9 @@
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 @@
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, PropertyName propertyName)
-{
- return prototypeChainMayInterceptStoreTo(vm, propertyName.uid());
-}
-
#if DO_PROPERTYMAP_CONSTENCY_CHECK
void PropertyTable::checkConsistency()
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 12a411b..51a119c 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -154,6 +154,8 @@
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 @@
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; }
diff --git a/Source/JavaScriptCore/runtime/StructureInlines.h b/Source/JavaScriptCore/runtime/StructureInlines.h
index 4e4286d9..3a905654 100644
--- a/Source/JavaScriptCore/runtime/StructureInlines.h
+++ b/Source/JavaScriptCore/runtime/StructureInlines.h
@@ -56,6 +56,22 @@
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());