| Differences between
and this patch
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj -4 / +28 lines
Lines 86-91 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
86
		0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
86
		0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
87
		0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
87
		0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
88
		0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
88
		0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
89
		0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0A75201B94BFA900110660 /* InferredType.cpp */; };
90
		0F0A75231B94BFA900110660 /* InferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0A75211B94BFA900110660 /* InferredType.h */; settings = {ATTRIBUTES = (Private, ); }; };
89
		0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
91
		0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
90
		0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
92
		0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
91
		0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
93
		0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 745-750 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
745
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
747
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
746
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
748
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
747
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
749
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
750
		0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */; };
751
		0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
752
		0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */; };
753
		0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
748
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
754
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
749
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
755
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
750
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
756
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 1915-1920 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
1915
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1921
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1916
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1922
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1917
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1923
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1924
		0F0A75201B94BFA900110660 /* InferredType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredType.cpp; sourceTree = "<group>"; };
1925
		0F0A75211B94BFA900110660 /* InferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredType.h; sourceTree = "<group>"; };
1918
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1926
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1919
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1927
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1920
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
1928
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
Lines 2571-2576 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
2571
		0FF9CE721B9CD6D0004EDCA6 /* PolymorphicAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccess.h; sourceTree = "<group>"; };
2579
		0FF9CE721B9CD6D0004EDCA6 /* PolymorphicAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccess.h; sourceTree = "<group>"; };
2572
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2580
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2573
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2581
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2582
		0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredTypeTable.cpp; sourceTree = "<group>"; };
2583
		0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredTypeTable.h; sourceTree = "<group>"; };
2584
		0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredInferredType.h; path = dfg/DFGDesiredInferredType.h; sourceTree = "<group>"; };
2585
		0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropertyTypeKey.h; path = dfg/DFGPropertyTypeKey.h; sourceTree = "<group>"; };
2574
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2586
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2575
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2587
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2576
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
2588
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
Lines 4647-4654 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
4647
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4659
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4648
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4660
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4649
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4661
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4650
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4651
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4662
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4663
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4652
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4664
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4653
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4665
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4654
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
4666
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
Lines 4682-4687 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
4682
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4694
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4683
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4695
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4684
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4696
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4697
				0F0A75201B94BFA900110660 /* InferredType.cpp */,
4698
				0F0A75211B94BFA900110660 /* InferredType.h */,
4699
				0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */,
4700
				0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */,
4685
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4701
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4686
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4702
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4687
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
4703
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
Lines 4732-4741 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
4732
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4748
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4733
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4749
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4734
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4750
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4735
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4736
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4737
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4751
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4738
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4752
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4753
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4754
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4739
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4755
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4740
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4756
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4741
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
4757
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
Lines 5039-5047 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
5039
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5055
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5040
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5056
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5041
				E18E3A560DF9278C00D90B34 /* VM.h */,
5057
				E18E3A560DF9278C00D90B34 /* VM.h */,
5042
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5043
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5058
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5044
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5059
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5060
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5045
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5061
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5046
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5062
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5047
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
5063
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
Lines 5193-5198 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
5193
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5209
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5194
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5210
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5195
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5211
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5212
				0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */,
5196
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5213
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5197
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5214
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5198
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
5215
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
Lines 5340-5345 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec10
5340
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5357
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5341
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5358
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5342
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5359
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5360
				0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */,
5343
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5361
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5344
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5362
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5345
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
5363
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
Lines 5928-5933 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec11
5928
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5946
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5929
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5947
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5930
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5948
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5949
				0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
5931
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5950
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5932
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5951
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5933
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
5952
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
Lines 6041-6046 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec12
6041
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6060
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6042
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6061
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6043
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6062
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6063
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
6044
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6064
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6045
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6065
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6046
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
6066
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
Lines 6325-6330 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec13
6325
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6345
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6326
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6346
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6327
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6347
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6348
				0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */,
6328
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6349
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6329
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6350
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6330
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
6351
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
Lines 6490-6495 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec14
6490
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6511
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6491
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6512
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6492
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6513
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6514
				0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
6493
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6515
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6494
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6516
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6495
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
6517
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
Lines 7432-7437 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec15
7432
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7454
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7433
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7455
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7434
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7456
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7457
				0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
7435
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7458
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7436
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7459
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7437
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
7460
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
Lines 7846-7851 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec16
7846
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7869
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7847
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7870
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7848
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7871
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7872
				0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
7849
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7873
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7850
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7874
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7851
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
7875
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
- Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp +6 lines
Lines 686-691 void AccessCase::generate(AccessGenerati Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp_sec1
686
    }
686
    }
687
687
688
    case Replace: {
688
    case Replace: {
689
        if (InferredType* type = structure()->inferredTypeFor(ident.uid())) {
690
            state.failAndRepatch.append(jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor()));
691
        
689
        if (isInlineOffset(m_offset)) {
692
        if (isInlineOffset(m_offset)) {
690
            jit.storeValue(
693
            jit.storeValue(
691
                valueRegs,
694
                valueRegs,
Lines 709-714 void AccessCase::generate(AccessGenerati Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp_sec2
709
        RELEASE_ASSERT(GPRInfo::numberOfRegisters >= 6 || !structure()->outOfLineCapacity() || structure()->outOfLineCapacity() == newStructure()->outOfLineCapacity());
712
        RELEASE_ASSERT(GPRInfo::numberOfRegisters >= 6 || !structure()->outOfLineCapacity() || structure()->outOfLineCapacity() == newStructure()->outOfLineCapacity());
710
        RELEASE_ASSERT(!structure()->couldHaveIndexingHeader());
713
        RELEASE_ASSERT(!structure()->couldHaveIndexingHeader());
711
714
715
        if (InferredType* type = structure()->inferredTypeFor(ident.uid())) {
716
            state.failAndRepatch.append(jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor()));
717
        
712
        CCallHelpers::JumpList slowPath;
718
        CCallHelpers::JumpList slowPath;
713
719
714
        ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
720
        ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
- Source/JavaScriptCore/bytecode/PutByIdFlags.cpp -7 / +6 lines
Lines 26-31 Source/JavaScriptCore/bytecode/PutByIdFlags.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "PutByIdFlags.h"
27
#include "PutByIdFlags.h"
28
28
29
#include "InferredType.h"
29
#include <wtf/CommaPrinter.h>
30
#include <wtf/CommaPrinter.h>
30
#include <wtf/PrintStream.h>
31
#include <wtf/PrintStream.h>
31
#include <wtf/StringPrintStream.h>
32
#include <wtf/StringPrintStream.h>
Lines 35-50 namespace WTF { Source/JavaScriptCore/bytecode/PutByIdFlags.cpp_sec2
35
using namespace JSC;
36
using namespace JSC;
36
37
37
void printInternal(PrintStream& out, PutByIdFlags flags) {
38
void printInternal(PrintStream& out, PutByIdFlags flags) {
38
    StringPrintStream stringOut;
39
    CommaPrinter comma("|");
39
    CommaPrinter comma("|");
40
    if (flags & PutByIdIsDirect)
40
    if (flags & PutByIdIsDirect)
41
        stringOut.print(comma, "IsDirect");
41
        out.print(comma, "IsDirect");
42
42
43
    CString string = stringOut.toCString();
43
    InferredType::Kind kind = InferredType::kindForFlags(flags);
44
    if (!string.length())
44
    out.print(comma, kind);
45
        out.print("None");
45
    if (InferredType::hasStructure(kind))
46
    else
46
        out.print(":", bitwise_cast<int32_t>(decodeStructureID(flags)));
47
        out.print(string);
48
}
47
}
49
48
50
} // namespace WTF
49
} // namespace WTF
- Source/JavaScriptCore/bytecode/PutByIdFlags.h -2 / +56 lines
Lines 26-38 Source/JavaScriptCore/bytecode/PutByIdFlags.h_sec1
26
#ifndef PutByIdFlags_h
26
#ifndef PutByIdFlags_h
27
#define PutByIdFlags_h
27
#define PutByIdFlags_h
28
28
29
#include "StructureIDTable.h"
30
29
namespace JSC {
31
namespace JSC {
30
32
31
enum PutByIdFlags {
33
enum PutByIdFlags : intptr_t {
32
    PutByIdNone = 0,
34
    PutByIdNone = 0,
33
    PutByIdIsDirect = 1
35
36
    // This flag indicates that the put_by_id is direct. That means that we store the property without
37
    // checking if the prototype chain has a setter.
38
    PutByIdIsDirect = 0x1,
39
40
    // Determining the required inferred type involves first checking the primary type mask, and then
41
    // using that to figure out the meaning of the secondary mask:
42
    // switch (flags & PutByIdPrimaryTypeMask) {
43
    // case PutByIdPrimaryTypeSecondary:
44
    //     switch (flags & PutByIdSecondaryTypeMask) {
45
    //     ...
46
    //     }
47
    //     break;
48
    // case PutByIdPrimaryTypeObjectWithStructure:
49
    // case PutByIdPrimaryTypeObjectWithStructureOrOther:
50
    //     StructureID structureID = decodeStructureID(flags);
51
    //     break;
52
    // }
53
    PutByIdPrimaryTypeMask = 0x6,
54
    PutByIdPrimaryTypeSecondary = 0x0, // Need to check the secondary type mask for the type.
55
    PutByIdPrimaryTypeObjectWithStructure = 0x2, // Secondary type has structure ID.
56
    PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4, // Secondary type has structure ID.
57
58
    PutByIdSecondaryTypeMask = -0x8,
59
    PutByIdSecondaryTypeBottom = 0x0,
60
    PutByIdSecondaryTypeBoolean = 0x8,
61
    PutByIdSecondaryTypeOther = 0x10,
62
    PutByIdSecondaryTypeInt32 = 0x18,
63
    PutByIdSecondaryTypeNumber = 0x20,
64
    PutByIdSecondaryTypeString = 0x28,
65
    PutByIdSecondaryTypeObject = 0x30,
66
    PutByIdSecondaryTypeObjectOrOther = 0x38,
67
    PutByIdSecondaryTypeTop = 0x40
34
};
68
};
35
69
70
inline PutByIdFlags encodeStructureID(StructureID id)
71
{
72
#if USE(JSVALUE64)
73
    return static_cast<PutByIdFlags>(id) << 3;
74
#else
75
    PutByIdFlags result = bitwise_cast<PutByIdFlags>(id);
76
    ASSERT(!(result & ~PutByIdSecondaryTypeMask));
77
    return result;
78
#endif
79
}
80
81
inline StructureID decodeStructureID(PutByIdFlags flagsWord)
82
{
83
#if USE(JSVALUE64)
84
    return static_cast<StructureID>(flags >> 3);
85
#else
86
    return bitwise_cast<StructureID>(flags & PutByIdSecondaryTypeMask);
87
#endif
88
}
89
36
} // namespace JSC
90
} // namespace JSC
37
91
38
namespace WTF {
92
namespace WTF {
- Source/JavaScriptCore/bytecode/PutByIdStatus.cpp -9 / +17 lines
Lines 83-89 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec1
83
        if (!isValidOffset(offset))
83
        if (!isValidOffset(offset))
84
            return PutByIdStatus(NoInformation);
84
            return PutByIdStatus(NoInformation);
85
        
85
        
86
        return PutByIdVariant::replace(structure, offset);
86
        return PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
87
    }
87
    }
88
88
89
    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
89
    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
Lines 103-109 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec2
103
            return PutByIdStatus(NoInformation);
103
            return PutByIdStatus(NoInformation);
104
    }
104
    }
105
    
105
    
106
    return PutByIdVariant::transition(structure, newStructure, conditionSet, offset);
106
    return PutByIdVariant::transition(
107
        structure, newStructure, conditionSet, offset, newStructure->inferredTypeDescriptorFor(uid));
107
}
108
}
108
109
109
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid)
110
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid)
Lines 162-168 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec3
162
            stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
163
            stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
163
        if (isValidOffset(offset)) {
164
        if (isValidOffset(offset)) {
164
            return PutByIdVariant::replace(
165
            return PutByIdVariant::replace(
165
                stubInfo->u.byIdSelf.baseObjectStructure.get(), offset);
166
                stubInfo->u.byIdSelf.baseObjectStructure.get(), offset, InferredType::Top);
166
        }
167
        }
167
        return PutByIdStatus(TakesSlowPath);
168
        return PutByIdStatus(TakesSlowPath);
168
    }
169
    }
Lines 193-199 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec4
193
                PropertyOffset offset = structure->getConcurrently(uid);
194
                PropertyOffset offset = structure->getConcurrently(uid);
194
                if (!isValidOffset(offset))
195
                if (!isValidOffset(offset))
195
                    return PutByIdStatus(slowPathState);
196
                    return PutByIdStatus(slowPathState);
196
                variant = PutByIdVariant::replace(structure, offset);
197
                variant = PutByIdVariant::replace(
198
                    structure, offset, structure->inferredTypeDescriptorFor(uid));
197
                break;
199
                break;
198
            }
200
            }
199
                
201
                
Lines 206-212 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec5
206
                if (!conditionSet.structuresEnsureValidity())
208
                if (!conditionSet.structuresEnsureValidity())
207
                    return PutByIdStatus(slowPathState);
209
                    return PutByIdStatus(slowPathState);
208
                variant = PutByIdVariant::transition(
210
                variant = PutByIdVariant::transition(
209
                    access.structure(), access.newStructure(), conditionSet, offset);
211
                    access.structure(), access.newStructure(), conditionSet, offset,
212
                    access.newStructure()->inferredTypeDescriptorFor(uid));
210
                break;
213
                break;
211
            }
214
            }
212
                
215
                
Lines 329-336 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec6
329
                // So, better leave this alone and take slow path.
332
                // So, better leave this alone and take slow path.
330
                return PutByIdStatus(TakesSlowPath);
333
                return PutByIdStatus(TakesSlowPath);
331
            }
334
            }
332
            
335
333
            if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
336
            PutByIdVariant variant =
337
                PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
338
            if (!result.appendVariant(variant))
334
                return PutByIdStatus(TakesSlowPath);
339
                return PutByIdStatus(TakesSlowPath);
335
            continue;
340
            continue;
336
        }
341
        }
Lines 356-368 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec7
356
        }
361
        }
357
    
362
    
358
        // We only optimize if there is already a structure that the transition is cached to.
363
        // We only optimize if there is already a structure that the transition is cached to.
359
        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
364
        Structure* transition =
365
            Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
360
        if (!transition)
366
        if (!transition)
361
            return PutByIdStatus(TakesSlowPath);
367
            return PutByIdStatus(TakesSlowPath);
362
        ASSERT(isValidOffset(offset));
368
        ASSERT(isValidOffset(offset));
363
    
369
    
364
        bool didAppend = result.appendVariant(
370
        bool didAppend = result.appendVariant(
365
            PutByIdVariant::transition(structure, transition, conditionSet, offset));
371
            PutByIdVariant::transition(
372
                structure, transition, conditionSet, offset,
373
                transition->inferredTypeDescriptorFor(uid)));
366
        if (!didAppend)
374
        if (!didAppend)
367
            return PutByIdStatus(TakesSlowPath);
375
            return PutByIdStatus(TakesSlowPath);
368
    }
376
    }
- Source/JavaScriptCore/bytecode/PutByIdVariant.cpp -5 / +16 lines
Lines 45-50 PutByIdVariant& PutByIdVariant::operator Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec1
45
    m_newStructure = other.m_newStructure;
45
    m_newStructure = other.m_newStructure;
46
    m_conditionSet = other.m_conditionSet;
46
    m_conditionSet = other.m_conditionSet;
47
    m_offset = other.m_offset;
47
    m_offset = other.m_offset;
48
    m_requiredType = other.m_requiredType;
48
    if (other.m_callLinkStatus)
49
    if (other.m_callLinkStatus)
49
        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
50
        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
50
    else
51
    else
Lines 52-69 PutByIdVariant& PutByIdVariant::operator Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec2
52
    return *this;
53
    return *this;
53
}
54
}
54
55
55
PutByIdVariant PutByIdVariant::replace(const StructureSet& structure, PropertyOffset offset)
56
PutByIdVariant PutByIdVariant::replace(
57
    const StructureSet& structure, PropertyOffset offset, const InferredType::Descriptor& requiredType)
56
{
58
{
57
    PutByIdVariant result;
59
    PutByIdVariant result;
58
    result.m_kind = Replace;
60
    result.m_kind = Replace;
59
    result.m_oldStructure = structure;
61
    result.m_oldStructure = structure;
60
    result.m_offset = offset;
62
    result.m_offset = offset;
63
    result.m_requiredType = requiredType;
61
    return result;
64
    return result;
62
}
65
}
63
66
64
PutByIdVariant PutByIdVariant::transition(
67
PutByIdVariant PutByIdVariant::transition(
65
    const StructureSet& oldStructure, Structure* newStructure,
68
    const StructureSet& oldStructure, Structure* newStructure,
66
    const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset)
69
    const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset,
70
    const InferredType::Descriptor& requiredType)
67
{
71
{
68
    PutByIdVariant result;
72
    PutByIdVariant result;
69
    result.m_kind = Transition;
73
    result.m_kind = Transition;
Lines 71-76 PutByIdVariant PutByIdVariant::transitio Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec3
71
    result.m_newStructure = newStructure;
75
    result.m_newStructure = newStructure;
72
    result.m_conditionSet = conditionSet;
76
    result.m_conditionSet = conditionSet;
73
    result.m_offset = offset;
77
    result.m_offset = offset;
78
    result.m_requiredType = requiredType;
74
    return result;
79
    return result;
75
}
80
}
76
81
Lines 85-90 PutByIdVariant PutByIdVariant::setter( Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec4
85
    result.m_conditionSet = conditionSet;
90
    result.m_conditionSet = conditionSet;
86
    result.m_offset = offset;
91
    result.m_offset = offset;
87
    result.m_callLinkStatus = WTF::move(callLinkStatus);
92
    result.m_callLinkStatus = WTF::move(callLinkStatus);
93
    result.m_requiredType = InferredType::Top;
88
    return result;
94
    return result;
89
}
95
}
90
96
Lines 134-142 bool PutByIdVariant::attemptToMerge(cons Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec5
134
{
140
{
135
    if (m_offset != other.m_offset)
141
    if (m_offset != other.m_offset)
136
        return false;
142
        return false;
143
144
    if (m_requiredType != other.m_requiredType)
145
        return false;
137
    
146
    
138
    switch (m_kind) {
147
    switch (m_kind) {
139
    case Replace:
148
    case Replace: {
140
        switch (other.m_kind) {
149
        switch (other.m_kind) {
141
        case Replace: {
150
        case Replace: {
142
            ASSERT(m_conditionSet.isEmpty());
151
            ASSERT(m_conditionSet.isEmpty());
Lines 158-163 bool PutByIdVariant::attemptToMerge(cons Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec6
158
        default:
167
        default:
159
            return false;
168
            return false;
160
        }
169
        }
170
    }
161
        
171
        
162
    case Transition:
172
    case Transition:
163
        switch (other.m_kind) {
173
        switch (other.m_kind) {
Lines 210-223 void PutByIdVariant::dumpInContext(Print Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec7
210
        
220
        
211
    case Replace:
221
    case Replace:
212
        out.print(
222
        out.print(
213
            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ">");
223
            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ", ", requiredType(),
224
            ">");
214
        return;
225
        return;
215
        
226
        
216
    case Transition:
227
    case Transition:
217
        out.print(
228
        out.print(
218
            "<Transition: ", inContext(oldStructure(), context), " -> ",
229
            "<Transition: ", inContext(oldStructure(), context), " -> ",
219
            pointerDumpInContext(newStructure(), context), ", [",
230
            pointerDumpInContext(newStructure(), context), ", [",
220
            inContext(m_conditionSet, context), "], offset = ", offset(), ">");
231
            inContext(m_conditionSet, context), "], offset = ", offset(), ", ", requiredType(), ">");
221
        return;
232
        return;
222
        
233
        
223
    case Setter:
234
    case Setter:
- Source/JavaScriptCore/bytecode/PutByIdVariant.h -2 / +8 lines
Lines 53-63 public: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec1
53
    PutByIdVariant(const PutByIdVariant&);
53
    PutByIdVariant(const PutByIdVariant&);
54
    PutByIdVariant& operator=(const PutByIdVariant&);
54
    PutByIdVariant& operator=(const PutByIdVariant&);
55
55
56
    static PutByIdVariant replace(const StructureSet&, PropertyOffset);
56
    static PutByIdVariant replace(const StructureSet&, PropertyOffset, const InferredType::Descriptor&);
57
    
57
    
58
    static PutByIdVariant transition(
58
    static PutByIdVariant transition(
59
        const StructureSet& oldStructure, Structure* newStructure,
59
        const StructureSet& oldStructure, Structure* newStructure,
60
        const ObjectPropertyConditionSet&, PropertyOffset);
60
        const ObjectPropertyConditionSet&, PropertyOffset, const InferredType::Descriptor&);
61
    
61
    
62
    static PutByIdVariant setter(
62
    static PutByIdVariant setter(
63
        const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
63
        const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
Lines 99-104 public: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec2
99
        return m_newStructure;
99
        return m_newStructure;
100
    }
100
    }
101
101
102
    InferredType::Descriptor requiredType() const
103
    {
104
        return m_requiredType;
105
    }
106
102
    bool writesStructures() const;
107
    bool writesStructures() const;
103
    bool reallocatesStorage() const;
108
    bool reallocatesStorage() const;
104
    bool makesCalls() const;
109
    bool makesCalls() const;
Lines 130-135 private: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec3
130
    Structure* m_newStructure;
135
    Structure* m_newStructure;
131
    ObjectPropertyConditionSet m_conditionSet;
136
    ObjectPropertyConditionSet m_conditionSet;
132
    PropertyOffset m_offset;
137
    PropertyOffset m_offset;
138
    InferredType::Descriptor m_requiredType;
133
    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
139
    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
134
};
140
};
135
141
- Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h -3 lines
Lines 36-42 Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec1
36
#include "JSCell.h"
36
#include "JSCell.h"
37
#include "JSString.h"
37
#include "JSString.h"
38
#include "ParserModes.h"
38
#include "ParserModes.h"
39
#include "PutByIdFlags.h"
40
#include "RegExp.h"
39
#include "RegExp.h"
41
#include "SpecialPointer.h"
40
#include "SpecialPointer.h"
42
#include "UnlinkedFunctionExecutable.h"
41
#include "UnlinkedFunctionExecutable.h"
Lines 98-109 struct UnlinkedInstruction { Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec2
98
    UnlinkedInstruction() { u.operand = 0; }
97
    UnlinkedInstruction() { u.operand = 0; }
99
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
98
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
100
    UnlinkedInstruction(int operand) { u.operand = operand; }
99
    UnlinkedInstruction(int operand) { u.operand = operand; }
101
    UnlinkedInstruction(PutByIdFlags flags) { u.putByIdFlags = flags; }
102
    union {
100
    union {
103
        OpcodeID opcode;
101
        OpcodeID opcode;
104
        int32_t operand;
102
        int32_t operand;
105
        unsigned index;
103
        unsigned index;
106
        PutByIdFlags putByIdFlags;
107
    } u;
104
    } u;
108
};
105
};
109
106
- Source/JavaScriptCore/bytecode/Watchpoint.h -1 / +33 lines
Lines 336-342 public: Source/JavaScriptCore/bytecode/Watchpoint.h_sec1
336
    {
336
    {
337
        touch(StringFireDetail(reason));
337
        touch(StringFireDetail(reason));
338
    }
338
    }
339
    
339
340
    // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like:
341
    //
342
    // if (w.isBeingWatched())
343
    //     w.fireAll()
344
    //
345
    // Concurrently to this, the DFG could do:
346
    //
347
    // if (w.isStillValid())
348
    //     perform optimizations;
349
    // if (!w.isStillValid())
350
    //     retry compilation;
351
    //
352
    // Note that the DFG algorithm is widespread, and sound, because fireAll() and invalidate() will leave
353
    // the watchpoint in a !isStillValid() state. Hence, if fireAll() or invalidate() interleaved between
354
    // the first isStillValid() check and the second one, then it would simply cause the DFG to retry
355
    // compilation later.
356
    //
357
    // But, if you change some piece of state that the DFG might optimize for, but invalidate the
358
    // watchpoint by doing:
359
    //
360
    // if (w.isBeingWatched())
361
    //     w.fireAll()
362
    //
363
    // then the DFG would never know that you invalidated state between the two checks.
364
    //
365
    // There are two ways to work around this:
366
    //
367
    // - Call fireAll() without a isBeingWatched() check. Then, the DFG will know that the watchpoint has
368
    //   been invalidated when it does its second check.
369
    //
370
    // - Do not expose the watchpoint set to the DFG directly, and have your own way of validating whether
371
    //   the assumptions that the DFG thread used are still valid when the DFG code is installed.
340
    bool isBeingWatched() const
372
    bool isBeingWatched() const
341
    {
373
    {
342
        if (isFat())
374
        if (isFat())
- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h -3 / +3 lines
Lines 116-124 public: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec1
116
    void dump(PrintStream& out);
116
    void dump(PrintStream& out);
117
    
117
    
118
    template<typename T>
118
    template<typename T>
119
    FiltrationResult filter(T node, const StructureSet& set)
119
    FiltrationResult filter(T node, const StructureSet& set, SpeculatedType admittedTypes = SpecNone)
120
    {
120
    {
121
        return filter(forNode(node), set);
121
        return filter(forNode(node), set, admittedTypes);
122
    }
122
    }
123
    
123
    
124
    template<typename T>
124
    template<typename T>
Lines 139-145 public: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec2
139
        return filterByValue(forNode(node), value);
139
        return filterByValue(forNode(node), value);
140
    }
140
    }
141
    
141
    
142
    FiltrationResult filter(AbstractValue&, const StructureSet&);
142
    FiltrationResult filter(AbstractValue&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
143
    FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
143
    FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
144
    FiltrationResult filter(AbstractValue&, SpeculatedType);
144
    FiltrationResult filter(AbstractValue&, SpeculatedType);
145
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
145
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h -44 / +83 lines
Lines 1829-1838 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec1
1829
        }
1829
        }
1830
        
1830
        
1831
        AbstractValue& value = forNode(node->child1());
1831
        AbstractValue& value = forNode(node->child1());
1832
        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
1832
        if (value.m_structure.isFinite()
1833
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1833
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1834
            GetByIdStatus status = GetByIdStatus::computeFor(
1834
            UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
1835
                value.m_structure.set(), m_graph.identifiers()[node->identifierNumber()]);
1835
            GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
1836
            if (status.isSimple()) {
1836
            if (status.isSimple()) {
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1838
                // something more subtle?
1838
                // something more subtle?
Lines 1841-1862 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec2
1841
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1841
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1842
                    // have more work to do here.
1842
                    // have more work to do here.
1843
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1843
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1844
                    
1844
1845
                    JSValue constantResult =
1845
                    result.merge(
1846
                        m_graph.tryGetConstantProperty(value, status[i].offset());
1846
                        m_graph.inferredValueForProperty(
1847
                    if (!constantResult) {
1847
                            value, uid, status[i].offset(), m_graph.structureClobberState()));
1848
                        result.makeHeapTop();
1849
                        break;
1850
                    }
1851
                    
1852
                    AbstractValue thisResult;
1853
                    thisResult.set(
1854
                        m_graph, *m_graph.freeze(constantResult),
1855
                        m_state.structureClobberState());
1856
                    result.merge(thisResult);
1857
                }
1848
                }
1858
                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1849
                m_state.setFoundConstants(true);
1859
                    m_state.setFoundConstants(true);
1860
                forNode(node) = result;
1850
                forNode(node) = result;
1861
                break;
1851
                break;
1862
            }
1852
            }
Lines 1880-1886 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec3
1880
        
1870
        
1881
    case CheckStructure: {
1871
    case CheckStructure: {
1882
        AbstractValue& value = forNode(node->child1());
1872
        AbstractValue& value = forNode(node->child1());
1883
        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1884
1873
1885
        StructureSet& set = node->structureSet();
1874
        StructureSet& set = node->structureSet();
1886
        
1875
        
Lines 1888-1899 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec4
1888
        // that includes the set we're testing. In that case we could make the structure check
1877
        // that includes the set we're testing. In that case we could make the structure check
1889
        // more efficient. We currently don't.
1878
        // more efficient. We currently don't.
1890
        
1879
        
1891
        if (value.m_structure.isSubsetOf(set)) {
1880
        if (value.m_structure.isSubsetOf(set))
1892
            m_state.setFoundConstants(true);
1881
            m_state.setFoundConstants(true);
1882
1883
        SpeculatedType admittedTypes = SpecNone;
1884
        switch (node->child1().useKind()) {
1885
        case CellUse:
1886
            admittedTypes = SpecNone;
1887
            break;
1888
        case CellOrOther:
1889
            admittedTypes = SpecOther;
1890
            break;
1891
        default:
1892
            DFG_CRASH(m_graph, node, "Bad use kind");
1893
            break;
1893
            break;
1894
        }
1894
        }
1895
1895
        
1896
        filter(value, set);
1896
        filter(value, set, admittedTypes);
1897
        break;
1897
        break;
1898
    }
1898
    }
1899
        
1899
        
Lines 2084-2096 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec5
2084
        
2084
        
2085
    case GetByOffset: {
2085
    case GetByOffset: {
2086
        StorageAccessData& data = node->storageAccessData();
2086
        StorageAccessData& data = node->storageAccessData();
2087
        JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2087
        UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2088
        if (result) {
2088
2089
            setConstant(node, *m_graph.freeze(result));
2089
        // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2090
            break;
2090
        // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2091
        }
2091
        // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2092
        
2092
        // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2093
        forNode(node).makeHeapTop();
2093
        // on the type that ByteCodeParser was able to prove.
2094
        AbstractValue value = m_graph.inferredValueForProperty(
2095
            forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2096
2097
        // It's possible that the type that ByteCodeParser came up with is better.
2098
        AbstractValue typeFromParsing;
2099
        typeFromParsing.set(m_graph, data->inferredType, m_state.structureClobberState());
2100
        value.filter(typeFromParsing);
2101
2102
        // If we decide that there does not exist any value that this can return, then it's probably
2103
        // because the compilation was already invalidated.
2104
        if (value.isClear())
2105
            m_state.setIsValid(false);
2106
2107
        forNode(node) = value;
2108
        if (value.m_value)
2109
            m_state.setFoundConstants(true);
2094
        break;
2110
        break;
2095
    }
2111
    }
2096
        
2112
        
Lines 2120-2125 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec6
2120
        // because of the effect on compile times, but this node is FTL-only.
2136
        // because of the effect on compile times, but this node is FTL-only.
2121
        m_state.setFoundConstants(true);
2137
        m_state.setFoundConstants(true);
2122
        
2138
        
2139
        UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2140
2123
        AbstractValue base = forNode(node->child1());
2141
        AbstractValue base = forNode(node->child1());
2124
        StructureSet baseSet;
2142
        StructureSet baseSet;
2125
        AbstractValue result;
2143
        AbstractValue result;
Lines 2129-2146 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec7
2129
            if (set.isEmpty())
2147
            if (set.isEmpty())
2130
                continue;
2148
                continue;
2131
            baseSet.merge(set);
2149
            baseSet.merge(set);
2132
            
2150
2133
            if (getCase.method().kind() != GetByOffsetMethod::Constant) {
2151
            switch (getCase.method().kind()) {
2134
                result.makeHeapTop();
2152
            case GetByOffsetMethod::Constant: {
2135
                continue;
2153
                AbstractValue thisResult;
2154
                thisResult.set(
2155
                    m_graph,
2156
                    *getCase.method().constant(),
2157
                    m_state.structureClobberState());
2158
                result.merge(thisResult);
2159
                break;
2136
            }
2160
            }
2137
            
2161
2138
            AbstractValue thisResult;
2162
            case GetByOffetMethod::Load: {
2139
            thisResult.set(
2163
                result.merge(
2140
                m_graph,
2164
                    m_graph.inferredValueForProperty(
2141
                *getCase.method().constant(),
2165
                        set, uid, getCase.method().offset(), m_graph.structureClobberState()));
2142
                m_state.structureClobberState());
2166
                break;
2143
            result.merge(thisResult);
2167
            }
2168
2169
            default: {
2170
                result.makeHeapTop();
2171
                break;
2172
            } }
2144
        }
2173
        }
2145
        
2174
        
2146
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2175
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
Lines 2163-2168 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec8
2163
        m_state.setFoundConstants(true);
2192
        m_state.setFoundConstants(true);
2164
        
2193
        
2165
        AbstractValue base = forNode(node->child1());
2194
        AbstractValue base = forNode(node->child1());
2195
        AbstractValue originalValue = forNode(node->child2());
2196
        AbstractValue resultingValue;
2166
        
2197
        
2167
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2198
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2168
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
2199
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
Lines 2170-2175 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec9
2170
            thisSet.filter(base);
2201
            thisSet.filter(base);
2171
            if (thisSet.isEmpty())
2202
            if (thisSet.isEmpty())
2172
                continue;
2203
                continue;
2204
2205
            AbstractValue thisValue = originalValue;
2206
            thisValue.filter(m_graph, variant.requiredType());
2207
            resultingValue.merge(thisvalue);
2208
            
2173
            if (variant.kind() == PutByIdVariant::Transition) {
2209
            if (variant.kind() == PutByIdVariant::Transition) {
2174
                if (thisSet.onlyStructure() != variant.newStructure()) {
2210
                if (thisSet.onlyStructure() != variant.newStructure()) {
2175
                    transitions.append(
2211
                    transitions.append(
Lines 2185-2190 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec10
2185
        observeTransitions(clobberLimit, transitions);
2221
        observeTransitions(clobberLimit, transitions);
2186
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2222
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2187
            m_state.setIsValid(false);
2223
            m_state.setIsValid(false);
2224
        for(node(node->child2()) = resultingValue;
2225
        if (!!originalValue && !resultingValue)
2226
            m_state.setIsValid(false);
2188
        break;
2227
        break;
2189
    }
2228
    }
2190
        
2229
        
Lines 2264-2276 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec11
2264
    case PutByIdFlush:
2303
    case PutByIdFlush:
2265
    case PutByIdDirect: {
2304
    case PutByIdDirect: {
2266
        AbstractValue& value = forNode(node->child1());
2305
        AbstractValue& value = forNode(node->child1());
2267
        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
2306
        if (value.m_structure.isFinite()) {
2268
            PutByIdStatus status = PutByIdStatus::computeFor(
2307
            PutByIdStatus status = PutByIdStatus::computeFor(
2269
                m_graph.globalObjectFor(node->origin.semantic),
2308
                m_graph.globalObjectFor(node->origin.semantic),
2270
                value.m_structure.set(),
2309
                value.m_structure.set(),
2271
                m_graph.identifiers()[node->identifierNumber()],
2310
                m_graph.identifiers()[node->identifierNumber()],
2272
                node->op() == PutByIdDirect);
2311
                node->op() == PutByIdDirect);
2273
            
2312
2274
            if (status.isSimple()) {
2313
            if (status.isSimple()) {
2275
                StructureSet newSet;
2314
                StructureSet newSet;
2276
                TransitionVector transitions;
2315
                TransitionVector transitions;
Lines 2615-2623 void AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec12
2615
2654
2616
template<typename AbstractStateType>
2655
template<typename AbstractStateType>
2617
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2656
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2618
    AbstractValue& value, const StructureSet& set)
2657
    AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
2619
{
2658
{
2620
    if (value.filter(m_graph, set) == FiltrationOK)
2659
    if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
2621
        return FiltrationOK;
2660
        return FiltrationOK;
2622
    m_state.setIsValid(false);
2661
    m_state.setIsValid(false);
2623
    return Contradiction;
2662
    return Contradiction;
- Source/JavaScriptCore/dfg/DFGAbstractValue.cpp -2 / +73 lines
Lines 117-122 void AbstractValue::setType(Graph& graph Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec1
117
    checkConsistency();
117
    checkConsistency();
118
}
118
}
119
119
120
void AbstractValue::set(Graph& graph, const InferredType::Descriptor& descriptor)
121
{
122
    switch (descriptor.kind()) {
123
    case InferredType::Bottom:
124
        clear();
125
        return;
126
    case InferredType::Boolean:
127
        setType(SpecBoolean);
128
        return;
129
    case InferredType::Other:
130
        setType(SpecOther);
131
        return;
132
    case InferredType::Int32:
133
        setType(SpecInt32);
134
        return;
135
    case InferredType::Number:
136
        setType(SpecBytecodeNumber);
137
        return;
138
    case InferredType::String:
139
        set(graph, graph.m_vm.stringStructure.get());
140
        return;
141
    case InferredType::ObjectWithStructure:
142
        set(graph, descriptor.structure());
143
        return;
144
    case InferredType::ObjectWithStructureOrOther:
145
        set(graph, descriptor.structure());
146
        merge(SpecOther);
147
        return;
148
    case InferredType::Object:
149
        setType(graph, SpecObject);
150
        return;
151
    case InferredType::ObjectOrOther:
152
        setType(graph, SpecObject | SpecOther);
153
        return;
154
    case InferredType::Top:
155
        makeHeapTop();
156
        return;
157
    }
158
159
    RELEASE_ASSERT_NOT_REACHED();
160
}
161
162
void AbstractValue::set(
163
    Graph& graph, const InferredType::Descriptor& descriptor, StructureClobberState clobberState)
164
{
165
    set(graph, descriptor);
166
    if (clobberState == StructuresAreClobbered)
167
        clobberStructures();
168
}
169
120
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
170
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
121
{
171
{
122
    if (representation == NodeResultDouble) {
172
    if (representation == NodeResultDouble) {
Lines 189-196 bool AbstractValue::mergeOSREntryValue(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec2
189
    return oldMe != *this;
239
    return oldMe != *this;
190
}
240
}
191
241
192
FiltrationResult AbstractValue::filter(Graph& graph, const StructureSet& other)
242
bool AbstractValue::isType(Graph& graph, const InferredType::Descriptor& inferredType) const
193
{
243
{
244
    AbstractValue typeValue;
245
    typeValue.set(graph, inferredType);
246
247
    AbstractValue mergedValue = *this;
248
    mergedValue.merge(typeValue);
249
250
    return mergedValue == typeValue;
251
}
252
253
FiltrationResult AbstractValue::filter(
254
    Graph& graph, const StructureSet& other, SpeculatedType admittedTypes)
255
{
256
    ASSERT(!(admittedTypes & SpecCell));
257
    
194
    if (isClear())
258
    if (isClear())
195
        return FiltrationOK;
259
        return FiltrationOK;
196
    
260
    
Lines 198-204 FiltrationResult AbstractValue::filter(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec3
198
    // having structures, array modes, or a specific value.
262
    // having structures, array modes, or a specific value.
199
    // https://bugs.webkit.org/show_bug.cgi?id=109663
263
    // https://bugs.webkit.org/show_bug.cgi?id=109663
200
    
264
    
201
    m_type &= other.speculationFromStructures();
265
    m_type &= other.speculationFromStructures() | admittedTypes;
202
    m_arrayModes &= other.arrayModesFromStructures();
266
    m_arrayModes &= other.arrayModesFromStructures();
203
    m_structure.filter(other);
267
    m_structure.filter(other);
204
    
268
    
Lines 315-320 FiltrationResult AbstractValue::filter(c Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec4
315
    return Contradiction;
379
    return Contradiction;
316
}
380
}
317
381
382
FiltrationResult AbstractValue::filter(Graph& graph, const InferredType::Descriptor& descriptor)
383
{
384
    AbstractValue filterValue;
385
    filterValue.set(graph, descriptor);
386
    return filter(filterValue);
387
}
388
318
void AbstractValue::filterValueByType()
389
void AbstractValue::filterValueByType()
319
{
390
{
320
    // We could go further, and ensure that if the futurePossibleStructure contravenes
391
    // We could go further, and ensure that if the futurePossibleStructure contravenes
- Source/JavaScriptCore/dfg/DFGAbstractValue.h -3 / +17 lines
Lines 34-39 Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec1
34
#include "DFGNodeFlags.h"
34
#include "DFGNodeFlags.h"
35
#include "DFGStructureAbstractValue.h"
35
#include "DFGStructureAbstractValue.h"
36
#include "DFGStructureClobberState.h"
36
#include "DFGStructureClobberState.h"
37
#include "InferredType.h"
37
#include "JSCell.h"
38
#include "JSCell.h"
38
#include "SpeculatedType.h"
39
#include "SpeculatedType.h"
39
#include "DumpContext.h"
40
#include "DumpContext.h"
Lines 214-220 struct AbstractValue { Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec2
214
        m_value = JSValue();
215
        m_value = JSValue();
215
        checkConsistency();
216
        checkConsistency();
216
    }
217
    }
217
    
218
219
    void set(Graph&, const InferredType::Descriptor&);
220
    void set(Graph&, const InferredType::Descriptor&, StructureClobberState);
221
218
    void fixTypeForRepresentation(Graph&, NodeFlags representation, Node* = nullptr);
222
    void fixTypeForRepresentation(Graph&, NodeFlags representation, Node* = nullptr);
219
    void fixTypeForRepresentation(Graph&, Node*);
223
    void fixTypeForRepresentation(Graph&, Node*);
220
    
224
    
Lines 280-296 struct AbstractValue { Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec3
280
    {
284
    {
281
        return !(m_type & ~desiredType);
285
        return !(m_type & ~desiredType);
282
    }
286
    }
287
288
    bool isType(Graph&, const InferredType::Descriptor&) const;
289
290
    // Filters the value using the given structure set. If the admittedTypes argument is not passed, this
291
    // implicitly filters by the types implied by the structure set, which are usually a subset of
292
    // SpecCell. Hence, after this call, the value will no longer have any non-cell members. But, you can
293
    // use admittedTypes to preserve some non-cell types. Note that it's wrong for admittedTypes to overlap
294
    // with SpecCell.
295
    FiltrationResult filter(Graph&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
283
    
296
    
284
    FiltrationResult filter(Graph&, const StructureSet&);
285
    FiltrationResult filterArrayModes(ArrayModes);
297
    FiltrationResult filterArrayModes(ArrayModes);
286
    FiltrationResult filter(SpeculatedType);
298
    FiltrationResult filter(SpeculatedType);
287
    FiltrationResult filterByValue(const FrozenValue& value);
299
    FiltrationResult filterByValue(const FrozenValue& value);
288
    FiltrationResult filter(const AbstractValue&);
300
    FiltrationResult filter(const AbstractValue&);
301
302
    FiltrationResult filter(Graph&, const InferredType::Descriptor&);
289
    
303
    
290
    FiltrationResult changeStructure(Graph&, const StructureSet&);
304
    FiltrationResult changeStructure(Graph&, const StructureSet&);
291
    
305
    
292
    bool contains(Structure*) const;
306
    bool contains(Structure*) const;
293
    
307
294
    bool validate(JSValue value) const
308
    bool validate(JSValue value) const
295
    {
309
    {
296
        if (isHeapTop())
310
        if (isHeapTop())
- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp -10 / +23 lines
Lines 206-214 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec1
206
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
206
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
207
    template<typename ChecksFunctor>
207
    template<typename ChecksFunctor>
208
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
208
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
209
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
209
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value);
210
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType = GetByOffset);
210
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset);
211
    Node* handleGetByOffset(SpeculatedType, Node* base, UniquedStringImpl*, PropertyOffset, NodeType = GetByOffset);
212
211
213
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
212
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
214
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
213
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
Lines 2304-2310 bool ByteCodeParser::handleConstantInter Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
2304
    return false;
2303
    return false;
2305
}
2304
}
2306
2305
2307
Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
2306
Node* ByteCodeParser::handleGetByOffset(
2307
    SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
2308
    const InferredType::Descriptor& inferredType, NodeType op)
2308
{
2309
{
2309
    Node* propertyStorage;
2310
    Node* propertyStorage;
2310
    if (isInlineOffset(offset))
2311
    if (isInlineOffset(offset))
Lines 2315-2327 Node* ByteCodeParser::handleGetByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
2315
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2316
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2316
    data->offset = offset;
2317
    data->offset = offset;
2317
    data->identifierNumber = identifierNumber;
2318
    data->identifierNumber = identifierNumber;
2319
    data->inferredType = inferredType;
2318
    
2320
    
2319
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2321
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2320
2322
2321
    return getByOffset;
2323
    return getByOffset;
2322
}
2324
}
2323
2325
2324
Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
2326
Node* ByteCodeParser::handlePutByOffset(
2327
    Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor& inferredType,
2328
    Node* value)
2325
{
2329
{
2326
    Node* propertyStorage;
2330
    Node* propertyStorage;
2327
    if (isInlineOffset(offset))
2331
    if (isInlineOffset(offset))
Lines 2332-2337 Node* ByteCodeParser::handlePutByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec4
2332
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2336
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2333
    data->offset = offset;
2337
    data->offset = offset;
2334
    data->identifierNumber = identifier;
2338
    data->identifierNumber = identifier;
2339
    data->inferredType = inferredType;
2335
    
2340
    
2336
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2341
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2337
    
2342
    
Lines 2446-2452 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec5
2446
        return addToGraph(JSConstant, OpInfo(method.constant()));
2451
        return addToGraph(JSConstant, OpInfo(method.constant()));
2447
    case GetByOffsetMethod::LoadFromPrototype: {
2452
    case GetByOffsetMethod::LoadFromPrototype: {
2448
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2453
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2449
        return handleGetByOffset(prediction, baseNode, identifierNumber, method.offset(), op);
2454
        return handleGetByOffset(
2455
            prediction, baseNode, identifierNumber, method.offset(), InferredType::Top, op);
2450
    }
2456
    }
2451
    case GetByOffsetMethod::Load:
2457
    case GetByOffsetMethod::Load:
2452
        // Will never see this from planLoad().
2458
        // Will never see this from planLoad().
Lines 2552-2564 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec6
2552
    
2558
    
2553
    bool needStructureCheck = true;
2559
    bool needStructureCheck = true;
2554
    
2560
    
2561
    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2562
    
2555
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2563
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2556
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2564
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2557
        // if the base's structure is watched.
2565
        // if the base's structure is watched.
2558
        Structure* structure = base->constant()->structure();
2566
        Structure* structure = base->constant()->structure();
2559
        if (!structure->dfgShouldWatch()) {
2567
        if (!structure->dfgShouldWatch()) {
2560
            UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2561
            
2562
            if (!variant.conditionSet().isEmpty()) {
2568
            if (!variant.conditionSet().isEmpty()) {
2563
                // This means that we're loading from a prototype. We expect the base not to have the
2569
                // This means that we're loading from a prototype. We expect the base not to have the
2564
                // property. We can only use ObjectPropertyCondition if all of the structures in the
2570
                // property. We can only use ObjectPropertyCondition if all of the structures in the
Lines 2623-2631 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec7
2623
            if (constant)
2629
            if (constant)
2624
                return weakJSConstant(constant);
2630
                return weakJSConstant(constant);
2625
        }
2631
        }
2632
2633
        InferredType::Descriptor inferredType;
2634
        if (needStructureCheck) {
2635
            for (Structure* structure : variant.structureSet())
2636
                inferredType.merge(m_graph.inferredTypeForProperty(structure, uid));
2637
        } else
2638
            inferredType = InferredType::Top;
2626
        
2639
        
2627
        loadedValue = handleGetByOffset(
2640
        loadedValue = handleGetByOffset(
2628
            loadPrediction, base, identifierNumber, variant.offset(), loadOp);
2641
            loadPrediction, base, identifierNumber, variant.offset(), inferredType, loadOp);
2629
    }
2642
    }
2630
2643
2631
    return loadedValue;
2644
    return loadedValue;
Lines 2636-2642 Node* ByteCodeParser::store(Node* base, Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec8
2636
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2649
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2637
2650
2638
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2651
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2639
    return handlePutByOffset(base, identifier, variant.offset(), value);
2652
    return handlePutByOffset(base, identifier, variant.offset(), variant.inferredType(), value);
2640
}
2653
}
2641
2654
2642
void ByteCodeParser::handleGetById(
2655
void ByteCodeParser::handleGetById(
- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp -1 / +5 lines
Lines 33-38 Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec1
33
#include "DFGBasicBlock.h"
33
#include "DFGBasicBlock.h"
34
#include "DFGGraph.h"
34
#include "DFGGraph.h"
35
#include "DFGInPlaceAbstractState.h"
35
#include "DFGInPlaceAbstractState.h"
36
#include "DFGInferredTypeCheck.h"
36
#include "DFGInsertionSet.h"
37
#include "DFGInsertionSet.h"
37
#include "DFGPhase.h"
38
#include "DFGPhase.h"
38
#include "GetByIdStatus.h"
39
#include "GetByIdStatus.h"
Lines 448-453 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec2
448
                ASSERT(childEdge.useKind() == CellUse);
449
                ASSERT(childEdge.useKind() == CellUse);
449
                
450
                
450
                AbstractValue baseValue = m_state.forNode(child);
451
                AbstractValue baseValue = m_state.forNode(child);
452
                AbstractValue valueValue = m_state.forNode(node->child2());
451
453
452
                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
454
                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
453
                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
455
                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
Lines 463-469 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec3
463
                
465
                
464
                if (!status.isSimple())
466
                if (!status.isSimple())
465
                    break;
467
                    break;
466
                
468
467
                ASSERT(status.numVariants());
469
                ASSERT(status.numVariants());
468
                
470
                
469
                if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
471
                if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
Lines 666-671 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec4
666
        Edge childEdge = node->child1();
668
        Edge childEdge = node->child1();
667
        
669
        
668
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
670
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
671
        insertInferredTypeCheck(
672
            m_insertionSet, indexInBlock, origin, node->child3().node(), variant.requiredType());
669
673
670
        node->child1().setUseKind(KnownCellUse);
674
        node->child1().setUseKind(KnownCellUse);
671
        childEdge.setUseKind(KnownCellUse);
675
        childEdge.setUseKind(KnownCellUse);
- Source/JavaScriptCore/dfg/DFGDesiredInferredType.h +132 lines
Line 0 Source/JavaScriptCore/dfg/DFGDesiredInferredType.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGDesiredInferredType_h
27
#define DFGDesiredInferredType_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "InferredType.h"
32
#include <wtf/HashMap.h>
33
34
namespace JSC { namespace DFG {
35
36
// This documents the DFG's expectation for an InferredType: specifically, that we want it to have a live
37
// InferredType object and that this object has the type that we originally saw.
38
39
class DesiredInferredType {
40
public:
41
    DesiredInferredType()
42
        : m_object(nullptr)
43
    {
44
    }
45
    
46
    DesiredInferredType(InferredType* object, const InferredType::Descriptor& expected)
47
        : m_object(object)
48
        , m_expected(expected)
49
    {
50
    }
51
52
    DesiredInferredType(WTF::HashTableDeletedValueType)
53
        : m_object(nullptr)
54
        , m_expected(Top)
55
    {
56
    }
57
58
    explicit operator bool() const { return m_object && m_expected; }
59
60
    InferredType* object() const { return m_object; }
61
    InferredType::Descriptor expected() const { return m_expected; }
62
63
    bool isStillValid() const
64
    {
65
        return m_object->canWatch(m_expected);
66
    }
67
68
    void add(Watchpoint* watchpoint) const
69
    {
70
        m_object->addWatchpoint(watchpoint);
71
    }
72
73
    bool operator==(const DesiredInferredType& other) const
74
    {
75
        return m_object == other.m_object
76
            && m_expected == other.m_expected;
77
    }
78
79
    bool operator!=(const DesiredInferredType& other) const
80
    {
81
        return !(*this == other);
82
    }
83
84
    bool isHashTableDeletedValue() const
85
    {
86
        return !m_object && m_expected == Top;
87
    }
88
89
    unsigned hash() const
90
    {
91
        return WTF::PtrHash<InferredType*>::hash(m_object) + m_expected.hash() * 7;
92
    }
93
94
    void dumpInContext(PrintStream& out, DumpContext* context) const
95
    {
96
        out.print(inContext(m_expected, context), " for ", RawPointer(m_object));
97
    }
98
99
    void dump(PrintStream& out) const
100
    {
101
        dumpInContext(out, context);
102
    }
103
104
private:
105
    InferredType* m_object;
106
    InferredType::Descriptor m_expected;
107
};
108
109
struct DesiredInferredTypeHash {
110
    static unsigned hash(const DesiredInferredType& key) { return key.hash(); }
111
    static bool equal(const DesiredInferredType& a, const DesiredInferredType& b) { return a == b; }
112
    static const bool safeToCompareToEmptyOrDeleted = true;
113
};
114
115
} } // namespace JSC::DFG
116
117
namespace WTF {
118
119
template<typename T> struct DefaultHash;
120
template<> struct DefaultHash<JSC::DFG::DesiredInferredType> {
121
    typedef JSC::DFG::DesiredInferredTypeHash Hash;
122
};
123
124
template<typename T> struct HashTraits;
125
template<> struct HashTraits<JSC::DFG::DesiredInferredType> : SimpleClassHashTraits<JSC::DFG::DesiredInferredType> { };
126
127
} // namespace WTF
128
129
#endif // ENABLE(DFG_JIT)
130
131
#endif // DFGDesiredInferredType_h
132
- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp -1 / +14 lines
Lines 65-70 void AdaptiveStructureWatchpointAdaptor: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec1
65
    }
65
    }
66
}
66
}
67
67
68
void InferredTypeAdaptor::add(CodeBlock* codeBlock, const DesiredInferredType& key, CommonData& common)
69
{
70
    key.add(common.watchpoints.add(codeBlock));
71
}
72
68
DesiredWatchpoints::DesiredWatchpoints() { }
73
DesiredWatchpoints::DesiredWatchpoints() { }
69
DesiredWatchpoints::~DesiredWatchpoints() { }
74
DesiredWatchpoints::~DesiredWatchpoints() { }
70
75
Lines 93-98 void DesiredWatchpoints::addLazily(const Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec2
93
    m_adaptiveStructureSets.addLazily(key);
98
    m_adaptiveStructureSets.addLazily(key);
94
}
99
}
95
100
101
void DesiredWatchpoints::addLazily(const DesiredInferredType& key)
102
{
103
    m_inferredTypes.addLazily(key);
104
}
105
96
bool DesiredWatchpoints::consider(Structure* structure)
106
bool DesiredWatchpoints::consider(Structure* structure)
97
{
107
{
98
    if (!structure->dfgShouldWatch())
108
    if (!structure->dfgShouldWatch())
Lines 108-113 void DesiredWatchpoints::reallyAdd(CodeB Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec3
108
    m_inferredValues.reallyAdd(codeBlock, commonData);
118
    m_inferredValues.reallyAdd(codeBlock, commonData);
109
    m_bufferViews.reallyAdd(codeBlock, commonData);
119
    m_bufferViews.reallyAdd(codeBlock, commonData);
110
    m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
120
    m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
121
    m_inferredTypes.reallyAdd(codeBlock, commonData);
111
}
122
}
112
123
113
bool DesiredWatchpoints::areStillValid() const
124
bool DesiredWatchpoints::areStillValid() const
Lines 116-122 bool DesiredWatchpoints::areStillValid() Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec4
116
        && m_inlineSets.areStillValid()
127
        && m_inlineSets.areStillValid()
117
        && m_inferredValues.areStillValid()
128
        && m_inferredValues.areStillValid()
118
        && m_bufferViews.areStillValid()
129
        && m_bufferViews.areStillValid()
119
        && m_adaptiveStructureSets.areStillValid();
130
        && m_adaptiveStructureSets.areStillValid()
131
        && m_inferredTypes.areStillValid();
120
}
132
}
121
133
122
void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
134
void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
Lines 127-132 void DesiredWatchpoints::dumpInContext(P Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec5
127
    out.print("    Inferred values: ", inContext(m_inferredValues, context), "\n");
139
    out.print("    Inferred values: ", inContext(m_inferredValues, context), "\n");
128
    out.print("    Buffer views: ", inContext(m_bufferViews, context), "\n");
140
    out.print("    Buffer views: ", inContext(m_bufferViews, context), "\n");
129
    out.print("    Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
141
    out.print("    Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
142
    out.print("    Inferred types: ", inContext(m_inferredTypes, context), "\n");
130
}
143
}
131
144
132
} } // namespace JSC::DFG
145
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h +22 lines
Lines 30-35 Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec1
30
30
31
#include "CodeOrigin.h"
31
#include "CodeOrigin.h"
32
#include "DFGCommonData.h"
32
#include "DFGCommonData.h"
33
#include "DFGDesiredInferredType.h"
33
#include "InferredValue.h"
34
#include "InferredValue.h"
34
#include "JSArrayBufferView.h"
35
#include "JSArrayBufferView.h"
35
#include "ObjectPropertyCondition.h"
36
#include "ObjectPropertyCondition.h"
Lines 91-96 struct AdaptiveStructureWatchpointAdapto Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec2
91
    }
92
    }
92
};
93
};
93
94
95
struct InferredTypeAdaptor {
96
    static void add(CodeBlock*, const DesiredInferredType&, CommonData&);
97
    static bool hasBeenInvalidated(const DesiredInferredType& key)
98
    {
99
        return !key.isStillValid();
100
    }
101
    static void dumpInContext(PrintStream& out, const DesiredInferredType& key, DumpContext* context)
102
    {
103
        out.print(inContext(key, context));
104
    }
105
};
106
94
template<typename WatchpointSetType, typename Adaptor = SetPointerAdaptor<WatchpointSetType>>
107
template<typename WatchpointSetType, typename Adaptor = SetPointerAdaptor<WatchpointSetType>>
95
class GenericDesiredWatchpoints {
108
class GenericDesiredWatchpoints {
96
#if !ASSERT_DISABLED
109
#if !ASSERT_DISABLED
Lines 159-164 public: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec3
159
    // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
172
    // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
160
    // the required GC magic as well as some other bookkeeping.
173
    // the required GC magic as well as some other bookkeeping.
161
    void addLazily(const ObjectPropertyCondition&);
174
    void addLazily(const ObjectPropertyCondition&);
175
176
    // It's recommended that you don't call this directly. Use Graph::inferredTypeFor(), which does
177
    // the required GC magic.
178
    void addLazily(const DesiredInferredType&);
162
    
179
    
163
    bool consider(Structure*);
180
    bool consider(Structure*);
164
    
181
    
Lines 186-191 public: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec4
186
    {
203
    {
187
        return m_adaptiveStructureSets.isWatched(key);
204
        return m_adaptiveStructureSets.isWatched(key);
188
    }
205
    }
206
    bool isWatched(const DesiredInferredType& key)
207
    {
208
        return m_inferredTypes.isWatched(key);
209
    }
189
210
190
    void dumpInContext(PrintStream&, DumpContext*) const;
211
    void dumpInContext(PrintStream&, DumpContext*) const;
191
    void dump(PrintStream&) const;
212
    void dump(PrintStream&) const;
Lines 196-201 private: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec5
196
    GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
217
    GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
197
    GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
218
    GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
198
    GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
219
    GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
220
    GenericDesiredWatchpoints<DesiredInferredType, InferredTypeAdaptor> m_inferredTypes;
199
};
221
};
200
222
201
} } // namespace JSC::DFG
223
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +3 lines
Lines 1092-1097 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec1
1092
            if (!node->child1()->hasStorageResult())
1092
            if (!node->child1()->hasStorageResult())
1093
                fixEdge<KnownCellUse>(node->child1());
1093
                fixEdge<KnownCellUse>(node->child1());
1094
            fixEdge<KnownCellUse>(node->child2());
1094
            fixEdge<KnownCellUse>(node->child2());
1095
            insertInferredTypeCheck(
1096
                m_insertionSet, m_indexInBlock, node->origin, node->child3().node(),
1097
                node->storageAccessData().inferredType);
1095
            speculateForBarrier(node->child3());
1098
            speculateForBarrier(node->child3());
1096
            break;
1099
            break;
1097
        }
1100
        }
- Source/JavaScriptCore/dfg/DFGGraph.cpp -1 / +74 lines
Lines 887-892 bool Graph::isSafeToLoad(JSObject* base, Source/JavaScriptCore/dfg/DFGGraph.cpp_sec1
887
    return m_safeToLoad.contains(std::make_pair(base, offset));
887
    return m_safeToLoad.contains(std::make_pair(base, offset));
888
}
888
}
889
889
890
InferredType::Descriptor Graph::inferredTypeFor(const PropertyTypeKey& key)
891
{
892
    assertIsRegistered(key.structure());
893
    
894
    auto iter = m_inferredTypes.get(key);
895
    if (iter != m_inferredTypes.end())
896
        return iter->value;
897
898
    InferredType* typeObject = key.structure()->inferredTypeFor(key.uid());
899
    if (!typeObject) {
900
        m_inferredTypes.add(key, InferredType::Top);
901
        return InferredType::Top;
902
    }
903
904
    InferredType::Descriptor typeDescriptor = typeObject->descriptor();
905
    if (!typeDescriptor.isStillValid()) {
906
        m_inferredTypes.add(key, InferredType::Top);
907
        return InferredType::Top;
908
    }
909
    
910
    m_inferredTypes.add(key, typeDescriptor);
911
912
    m_plan.weakReferences.addLazily(typeObject);
913
    if (typeDescriptor.structure())
914
        registerStructure(typeDescriptor.structure());
915
916
    // Note that we may already be watching this desired inferred type, because multiple structures may
917
    // point to the same InferredType instance.
918
    m_plan.watchpoints.addLazily(DesiredInferredType(typeObject, typeDescriptor));
919
920
    return typeDescriptor;
921
}
922
923
bool Graph::watchDesiredType(const DesiredInferredType& key)
924
{
925
    if (!key.isStillValid())
926
        return false;
927
928
    m_plan.weakReferences.addLazily(key.object());
929
    if (Structure* structure = key.expected().structure())
930
        registerStructure(structure);
931
    m_plan.watchpoints.addLazily(key);
932
}
933
890
FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
934
FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
891
{
935
{
892
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
936
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
Lines 1061-1067 JSValue Graph::tryGetConstantProperty(JS Source/JavaScriptCore/dfg/DFGGraph.cpp_sec2
1061
JSValue Graph::tryGetConstantProperty(
1105
JSValue Graph::tryGetConstantProperty(
1062
    JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
1106
    JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
1063
{
1107
{
1064
    if (structure.isTop() || structure.isClobbered()) {
1108
    if (structure.isInfinite()) {
1065
        // FIXME: If we just converted the offset to a uid, we could do ObjectPropertyCondition
1109
        // FIXME: If we just converted the offset to a uid, we could do ObjectPropertyCondition
1066
        // watching to constant-fold the property.
1110
        // watching to constant-fold the property.
1067
        // https://bugs.webkit.org/show_bug.cgi?id=147271
1111
        // https://bugs.webkit.org/show_bug.cgi?id=147271
Lines 1076-1081 JSValue Graph::tryGetConstantProperty(co Source/JavaScriptCore/dfg/DFGGraph.cpp_sec3
1076
    return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1120
    return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1077
}
1121
}
1078
1122
1123
AbstractValue Graph::inferredValueForProperty(
1124
    const StructureSet& base, UniquedStringImpl* uid, StructureClobberState clobberState)
1125
{
1126
    AbstractValue result;
1127
    base.forEach(
1128
        [&] (Structure* structure) {
1129
            AbstractValue value;
1130
            value.set(*this, inferredTypeForProperty(structure, uid));
1131
            result.merge(value);
1132
        });
1133
    return result;
1134
}
1135
1136
AbstractValue Graph::inferredValueForProperty(
1137
    const AbstractValue& base, UniquedStringImpl* uid, PropertyOffset offset,
1138
    StructureClobberState clobberState)
1139
{
1140
    if (JSValue value = tryGetConstantProperty(base, offset)) {
1141
        AbstractValue result;
1142
        result.set(*this, *freeze(value), clobberState);
1143
        return result;
1144
    }
1145
1146
    if (base.m_structure.isFinite())
1147
        return inferredValueForProperty(base.m_structure.set(), uid, clobberState);
1148
1149
    return AbstractValue::heapTop();
1150
}
1151
1079
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1152
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1080
{
1153
{
1081
    // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
1154
    // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
- Source/JavaScriptCore/dfg/DFGGraph.h +16 lines
Lines 675-680 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec1
675
    // Checks if it's known that loading from the given object at the given offset is fine. This is
675
    // Checks if it's known that loading from the given object at the given offset is fine. This is
676
    // computed by tracking which conditions we track with watchCondition().
676
    // computed by tracking which conditions we track with watchCondition().
677
    bool isSafeToLoad(JSObject* base, PropertyOffset);
677
    bool isSafeToLoad(JSObject* base, PropertyOffset);
678
679
    // Tells us what inferred type we are able to prove the property to have now and in the future.
680
    InferredType::Descriptor inferredTypeFor(const PropertyTypeKey&);
681
    InferredType::Descriptor inferredTypeForProperty(Structure* structure, UniquedStringImpl* uid)
682
    {
683
        return inferredTypeFor(PropertyTypeKey(structure, uid));
684
    }
685
686
    AbstractValue inferredValueForProperty(
687
        const StructureSet& base, UniquedStringImpl* uid, StructureClobberState);
688
689
    // This uses either constant property inference or property type inference to derive a good abstract
690
    // value for some property accessed with the given abstract value base.
691
    AbstractValue inferredValueForProperty(
692
        const AbstractValue& base, UniquedStringImpl* uid, PropertyOffset, StructureClobberState);
678
    
693
    
679
    FullBytecodeLiveness& livenessFor(CodeBlock*);
694
    FullBytecodeLiveness& livenessFor(CodeBlock*);
680
    FullBytecodeLiveness& livenessFor(InlineCallFrame*);
695
    FullBytecodeLiveness& livenessFor(InlineCallFrame*);
Lines 856-861 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec2
856
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
871
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
857
    HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
872
    HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
858
    HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
873
    HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
874
    HashMap<PropertyTypeKey, InferredType::Descriptor> m_inferredTypes;
859
    Dominators m_dominators;
875
    Dominators m_dominators;
860
    PrePostNumbering m_prePostNumbering;
876
    PrePostNumbering m_prePostNumbering;
861
    NaturalLoops m_naturalLoops;
877
    NaturalLoops m_naturalLoops;
- Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp +96 lines
Line 0 Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "DFGInferredTypeCheck.h"
28
29
#if ENABLE(DFG_JIT)
30
31
#include "JSCInlines.h"
32
33
namespace JSC { namespace DFG {
34
35
void insertInferredTypeCheck(
36
    InsertionSet& insertionSet, unsigned nodeIndex, NodeOrigin origin, Node* baseNode,
37
    const InferredType::Descriptor& type)
38
{
39
    switch (type.kind()) {
40
    case InferredType::Bottom:
41
        insertionSet.insertNode(nodeIndex, SpecNone, ForceOSRExit, origin);
42
        return;
43
44
    case InferredType::Boolean:
45
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(BooleanUse, baseNode));
46
        return;
47
48
    case InferredType::Other:
49
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(OtherUse, baseNode));
50
        return;
51
52
    case InferredType::Int32:
53
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(Int32Use, baseNode));
54
        return;
55
56
    case InferredType::Number:
57
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(NumberUse, baseNode));
58
        return;
59
60
    case InferredType::String:
61
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(StringUse, baseNode));
62
        return;
63
64
    case InferredType::ObjectWithStructure:
65
        insertionSet.insertNode(
66
            nodeIndex, SpecNone, CheckStructure, origin,
67
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
68
            Edge(CellUse, baseNode));
69
        return;
70
71
    case InferredType::ObjectWithStructure:
72
        insertionSet.insertNode(
73
            nodeIndex, SpecNone, CheckStructure, origin,
74
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
75
            Edge(CellOrOtherUse, baseNode));
76
        return;
77
78
    case InferredType::Object:
79
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(ObjectUse, baseNode));
80
        return;
81
82
    case InferredType::ObjectOrOther:
83
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(ObjectOrOtherUse, baseNode));
84
        return;
85
86
    case Inferredtype::Top:
87
        return;
88
    }
89
90
    DFG_CRASH(insertionSet.graph(), baseNode, "Bad inferred type");
91
}
92
93
} } // namespace JSC::DFG
94
95
#endif // ENABLE(DFG_JIT)
96
- Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h +45 lines
Line 0 Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef DFGInferredTypeCheck_h
27
#define DFGInferredTypeCheck_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGInsertionSet.h"
32
#include "InferredType.h"
33
34
namespace JSC { namespace DFG {
35
36
// Inserts a type check that ensures that baseNode has the given inferred type.
37
void insertInferredTypeCheck(
38
    InsertionSet&, unsigned nodeIndex, NodeOrigin, Node* baseNode, const InferredType::Descriptor&);
39
40
} } // namespace JSC::DFG
41
42
#endif // ENABLE(DFG_JIT)
43
44
#endif // DFGInferredTypeCheck_h
45
- Source/JavaScriptCore/dfg/DFGNode.h +5 lines
Lines 64-69 struct BasicBlock; Source/JavaScriptCore/dfg/DFGNode.h_sec1
64
struct StorageAccessData {
64
struct StorageAccessData {
65
    PropertyOffset offset;
65
    PropertyOffset offset;
66
    unsigned identifierNumber;
66
    unsigned identifierNumber;
67
68
    // This needs to know the inferred type. For puts, this is necessary because we need to remember
69
    // what check is needed. For gets, this is necessary because otherwise AI might forget what type is
70
    // guaranteed.
71
    InferredType::Descriptor inferredType;
67
};
72
};
68
73
69
struct MultiPutByOffsetData {
74
struct MultiPutByOffsetData {
- Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h +128 lines
Line 0 Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGPropertyTypeKey_h
27
#define DFGPropertyTypeKey_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include <wtf/HashMap.h>
32
33
namespace JSC { namespace DFG {
34
35
// This object is a key for finding a property's type. It's a tuple of Structure* and UniquedStringImpl*.
36
37
class PropertyTypeKey {
38
public:
39
    PropertyTypeKey()
40
        : m_structure(nullptr)
41
        , m_uid(nullptr)
42
    {
43
    }
44
45
    PropertyTypeKey(Structure* structure, UniquedStringImpl* uid)
46
        : m_structure(structure)
47
        , m_uid(uid)
48
    {
49
    }
50
51
    PropertyTypeKey(WTF::HashTableDeletedValueType)
52
        : m_object(nullptr)
53
        , m_uid(deletedUID())
54
    {
55
    }
56
57
    explicit operator bool() const { return m_structure && m_uid; }
58
59
    Structure* structure() const { return m_structure; }
60
    PropertyOffset uid() const { return m_uid; }
61
62
    bool operator==(const PropertyTypeKey& other) const
63
    {
64
        return m_structure == other.m_structure
65
            && m_uid == other.m_uid;
66
    }
67
68
    bool operator!=(const PropertyTypeKey& other) const
69
    {
70
        return !(*this == other);
71
    }
72
73
    unsigned hash() const
74
    {
75
        return WTF::PtrHash<Structure*>::hash(m_structure) + WTF::PtrHash<UniquedStringImpl*>::hash(m_uid);
76
    }
77
78
    bool isHashTableDeletedValue() const
79
    {
80
        return !m_object && m_uid == deletedUID();
81
    }
82
83
    void dumpInContext(PrintStream& out, DumpContext* context) const
84
    {
85
        out.print(pointerDumpInContext(m_structure, context), "+", m_uid);
86
    }
87
88
    void dump(PrintStream& out) const
89
    {
90
        dumpInContext(out, context);
91
    }
92
93
private:
94
    static UniquedStringImpl* deletedUID()
95
    {
96
        return bitwise_cast<UniquedStringImpl*>(static_cast<intptr_t>(1));
97
    }
98
    
99
    Structure* m_structure;
100
    UniquedStringImpl* m_uid;
101
};
102
103
struct PropertyTypeKeyHash {
104
    static unsigned hash(const PropertyTypeKey& key) { return key.hash(); }
105
    static bool equal(const PropertyTypeKey& a, const PropertyTypeKey& b) { return a == b; }
106
    static const bool safeToCompareToEmptyOrDeleted = true;
107
};
108
109
} } // namespace JSC::DFG
110
111
namespace WTF {
112
113
template<typename T> struct DefaultHash;
114
template<> struct DefaultHash<JSC::DFG::PropertyTypeKey> {
115
    typedef JSC::DFG::PropertyTypeKeyHash Hash;
116
};
117
118
template<typename T> struct HashTraits;
119
template<> struct HashTraits<JSC::DFG::PropertyTypeKey> : SimpleClassHashTraits<JSC::DFG::PropertyTypeKey> {
120
    static const bool emptyValueIsZero = false;
121
};
122
123
} // namespace WTF
124
125
#endif // ENABLE(DFG_JIT)
126
127
#endif // DFGPropertyTypeKey_h
128
- Source/JavaScriptCore/dfg/DFGSafeToExecute.h +1 lines
Lines 53-58 public: Source/JavaScriptCore/dfg/DFGSafeToExecute.h_sec1
53
        case RealNumberUse:
53
        case RealNumberUse:
54
        case BooleanUse:
54
        case BooleanUse:
55
        case CellUse:
55
        case CellUse:
56
        case CellOrOtherUse:
56
        case ObjectUse:
57
        case ObjectUse:
57
        case FunctionUse:
58
        case FunctionUse:
58
        case FinalObjectUse:
59
        case FinalObjectUse:
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +93 lines
Lines 5232-5237 void SpeculativeJIT::compileTypeOf(Node* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec1
5232
    cellResult(resultGPR, node);
5232
    cellResult(resultGPR, node);
5233
}
5233
}
5234
5234
5235
void SpeculativeJIT::compileCheckStructure(Node* node, GPRReg cellGPR, GPRReg tempGPR)
5236
{
5237
    ASSERT(node->structureSet().size());
5238
    
5239
    if (node->structureSet().size() == 1) {
5240
        speculationCheck(
5241
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5242
            m_jit.branchWeakStructure(
5243
                JITCompiler::NotEqual,
5244
                JITCompiler::Address(cellGPR, JSCell::structureIDOffset()),
5245
                node->structureSet()[0]));
5246
    } else {
5247
        std::unique_ptr<GPRTemporary> structure;
5248
        GPRReg structureGPR;
5249
        
5250
        if (tempGPR == InvalidGPR) {
5251
            structure = std::make_unique<GPRTemporary>(this);
5252
            structureGPR = structure->gpr();
5253
        } else
5254
            structureGPR = tempGPR;
5255
        
5256
        m_jit.load32(JITCompiler::Address(cellGPR, JSCell::structureIDOffset()), structureGPR);
5257
        
5258
        JITCompiler::JumpList done;
5259
        
5260
        for (size_t i = 0; i < node->structureSet().size() - 1; ++i) {
5261
            done.append(
5262
                m_jit.branchWeakStructur(JITCompiler::Equal, structureGPR, node->structureSet()[i]));
5263
        }
5264
        
5265
        speculationCheck(
5266
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5267
            m_jit.branchWeakStructure(
5268
                JITCompiler::NotEqual, structureGPR, node->structureSet().last()));
5269
        
5270
        done.link(&m_jit);
5271
    }
5272
}
5273
5274
void SpeculativeJIT::compileCheckStructure(Node* node)
5275
{
5276
    switch (node->child1().useKind()) {
5277
    case CellUse: {
5278
        SpeculateCellOperand cell(this, node->child1());
5279
        compileCheckStructure(node, cell.gpr(), InvalidGPRReg);
5280
        noResult(node);
5281
        return;
5282
    }
5283
5284
    case CellOrOtherUse: {
5285
        JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
5286
        GPRTemporary temp(this);
5287
5288
        JSValueRegs valueRegs = value.jsValueRegs();
5289
        GPRReg tempGPR = temp.gpr();
5290
5291
        JITCompiler::Jump cell = m_jit.branchIfCell(valueRegs);
5292
        DFG_TYPE_CHECK(
5293
            valueRegs, node->child1(), SpecCell | SpecOther,
5294
            m_jit.branchIfNotOther(valueRegs, tempGPR));
5295
        JITCompiler::Jump done = m_jit.jump();
5296
        cell.link(&m_jit);
5297
        compileCheckStructure(node, valueRegs.payloadGPR(), tempGPR);
5298
        done.link(&m_jit);
5299
        noResult(this);
5300
        return;
5301
    }
5302
5303
    default:
5304
        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
5305
        return;
5306
    }
5307
}
5308
5235
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5309
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5236
{
5310
{
5237
    if (node->transition()->previous->couldHaveIndexingHeader()) {
5311
    if (node->transition()->previous->couldHaveIndexingHeader()) {
Lines 5636-5641 void SpeculativeJIT::speculateCell(Edge Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec2
5636
    (SpeculateCellOperand(this, edge)).gpr();
5710
    (SpeculateCellOperand(this, edge)).gpr();
5637
}
5711
}
5638
5712
5713
void SpeculativeJIT::speculateCellOrOther(Edge edge)
5714
{
5715
    if (!needsTypeCheck(edge, SpecCell | SpecOther))
5716
        return;
5717
    
5718
    JSValueOperand operand(this, edge, ManualOperandSpeculation);
5719
    GPRTemporary temp(this);
5720
    GPRReg tempGPR = temp.gpr();
5721
5722
    MacroAssembler::Jump ok = m_jit.branchIfCell(operand.jsValueRegs());
5723
    DFG_TYPE_CHECK(
5724
        operand.jsValueRegs(), edge, SpecCell | SpecOther,
5725
        m_jit.branchIfNotOther(operand.jsValueRegs(), tempGPR));
5726
    ok.link(&m_jit);
5727
}
5728
5639
void SpeculativeJIT::speculateObject(Edge edge)
5729
void SpeculativeJIT::speculateObject(Edge edge)
5640
{
5730
{
5641
    if (!needsTypeCheck(edge, SpecObject))
5731
    if (!needsTypeCheck(edge, SpecObject))
Lines 5916-5921 void SpeculativeJIT::speculate(Node*, Ed Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec3
5916
    case CellUse:
6006
    case CellUse:
5917
        speculateCell(edge);
6007
        speculateCell(edge);
5918
        break;
6008
        break;
6009
    case CellOrOtherUse:
6010
        speculateCellOrOther(edge);
6011
        break;
5919
    case ObjectUse:
6012
    case ObjectUse:
5920
        speculateObject(edge);
6013
        speculateObject(edge);
5921
        break;
6014
        break;
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +3 lines
Lines 2215-2220 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec1
2215
    void compileIsObjectOrNull(Node*);
2215
    void compileIsObjectOrNull(Node*);
2216
    void compileIsFunction(Node*);
2216
    void compileIsFunction(Node*);
2217
    void compileTypeOf(Node*);
2217
    void compileTypeOf(Node*);
2218
    void compileCheckStructure(Node*, GPRReg cellGPR, GPRReg tempGPR);
2219
    void compileCheckStructure(Node*);
2218
    
2220
    
2219
    void moveTrueTo(GPRReg);
2221
    void moveTrueTo(GPRReg);
2220
    void moveFalseTo(GPRReg);
2222
    void moveFalseTo(GPRReg);
Lines 2374-2379 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec2
2374
    void speculateDoubleRepReal(Edge);
2376
    void speculateDoubleRepReal(Edge);
2375
    void speculateBoolean(Edge);
2377
    void speculateBoolean(Edge);
2376
    void speculateCell(Edge);
2378
    void speculateCell(Edge);
2379
    void speculateCellOrOther(Edge);
2377
    void speculateObject(Edge);
2380
    void speculateObject(Edge);
2378
    void speculateFunction(Edge);
2381
    void speculateFunction(Edge);
2379
    void speculateFinalObject(Edge);
2382
    void speculateFinalObject(Edge);
- Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h -1 / +8 lines
Lines 192-198 public: Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h_sec1
192
    }
192
    }
193
    
193
    
194
    Structure* operator[](size_t i) const { return at(i); }
194
    Structure* operator[](size_t i) const { return at(i); }
195
    
195
196
    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
196
    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
197
    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
197
    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
198
    // meaningfully special, like for transitions.
198
    // meaningfully special, like for transitions.
Lines 202-207 public: Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h_sec2
202
            return nullptr;
202
            return nullptr;
203
        return m_set.onlyStructure();
203
        return m_set.onlyStructure();
204
    }
204
    }
205
206
    template<typename Functor>
207
    void forEach(const Functor& functor) const
208
    {
209
        ASSERT(!isTop());
210
        m_set.forEach(functor);
211
    }
205
    
212
    
206
    void dumpInContext(PrintStream&, DumpContext*) const;
213
    void dumpInContext(PrintStream&, DumpContext*) const;
207
    void dump(PrintStream&) const;
214
    void dump(PrintStream&) const;
- Source/JavaScriptCore/dfg/DFGUseKind.cpp +3 lines
Lines 79-84 void printInternal(PrintStream& out, Use Source/JavaScriptCore/dfg/DFGUseKind.cpp_sec1
79
    case KnownCellUse:
79
    case KnownCellUse:
80
        out.print("KnownCell");
80
        out.print("KnownCell");
81
        return;
81
        return;
82
    case CellOrOtherUse:
83
        out.print("CellOrOther");
84
        return;
82
    case ObjectUse:
85
    case ObjectUse:
83
        out.print("Object");
86
        out.print("Object");
84
        return;
87
        return;
- Source/JavaScriptCore/dfg/DFGUseKind.h +3 lines
Lines 51-56 enum UseKind { Source/JavaScriptCore/dfg/DFGUseKind.h_sec1
51
    KnownBooleanUse,
51
    KnownBooleanUse,
52
    CellUse,
52
    CellUse,
53
    KnownCellUse,
53
    KnownCellUse,
54
    CellOrOtherUse,
54
    ObjectUse,
55
    ObjectUse,
55
    FunctionUse,
56
    FunctionUse,
56
    FinalObjectUse,
57
    FinalObjectUse,
Lines 108-113 inline SpeculatedType typeFilterFor(UseK Source/JavaScriptCore/dfg/DFGUseKind.h_sec2
108
    case CellUse:
109
    case CellUse:
109
    case KnownCellUse:
110
    case KnownCellUse:
110
        return SpecCell;
111
        return SpecCell;
112
    case CellOrOtherUse:
113
        return SpecCell | SpecOther;
111
    case ObjectUse:
114
    case ObjectUse:
112
        return SpecObject;
115
        return SpecObject;
113
    case FunctionUse:
116
    case FunctionUse:
- Source/JavaScriptCore/ftl/FTLCapabilities.cpp +1 lines
Lines 418-423 CapabilityLevel canCompile(Graph& graph) Source/JavaScriptCore/ftl/FTLCapabilities.cpp_sec1
418
                case KnownBooleanUse:
418
                case KnownBooleanUse:
419
                case CellUse:
419
                case CellUse:
420
                case KnownCellUse:
420
                case KnownCellUse:
421
                case CellOrOtherUse:
421
                case ObjectUse:
422
                case ObjectUse:
422
                case FunctionUse:
423
                case FunctionUse:
423
                case ObjectOrOtherUse:
424
                case ObjectOrOtherUse:
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -11 / +203 lines
Lines 2026-2046 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
2026
    
2026
    
2027
    void compileCheckStructure()
2027
    void compileCheckStructure()
2028
    {
2028
    {
2029
        LValue cell = lowCell(m_node->child1());
2030
        
2031
        ExitKind exitKind;
2029
        ExitKind exitKind;
2032
        if (m_node->child1()->hasConstant())
2030
        if (m_node->child1()->hasConstant())
2033
            exitKind = BadConstantCache;
2031
            exitKind = BadConstantCache;
2034
        else
2032
        else
2035
            exitKind = BadCache;
2033
            exitKind = BadCache;
2036
        
2034
2037
        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2035
        switch (m_node->child1().useKind()) {
2038
        
2036
        case CellUse: {
2039
        checkStructure(
2037
            LValue cell = lowCell(m_node->child1());
2040
            structureID, jsValueValue(cell), exitKind, m_node->structureSet(),
2038
            
2041
            [this] (Structure* structure) {
2039
            checkStructure(
2042
                return weakStructureID(structure);
2040
                m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
2043
            });
2041
                exitKind, m_node->structureSet(),
2042
                [&] (Structure* structure) {
2043
                    return weakStructureID(structure);
2044
                });
2045
            return;
2046
        }
2047
2048
        case CellOrOtherUse: {
2049
            LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
2050
2051
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse cell case"));
2052
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse not cell case"));
2053
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse continuation"));
2054
2055
            m_out.branch(
2056
                isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
2057
2058
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
2059
            checkStructure(
2060
                m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
2061
                exitKind, m_node->structureSet(),
2062
                [&] (Structure* structure) {
2063
                    return weakStructureID(structure);
2064
                });
2065
            m_out.jump(continuation);
2066
2067
            m_out.appendTo(notCellCase, continuation);
2068
            FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecCell | SpecOther, isNotOther(value));
2069
            m_out.jump(continuation);
2070
2071
            m_out.appendTo(continuation, lastNext);
2072
            return;
2073
        }
2074
2075
        default:
2076
            DFG_CRASH(m_graph, m_node, "Bad use kind");
2077
            return;
2078
        }
2044
    }
2079
    }
2045
    
2080
    
2046
    void compileCheckCell()
2081
    void compileCheckCell()
Lines 4022-4027 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
4022
            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
4057
            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
4023
            
4058
            
4024
            PutByIdVariant variant = data.variants[i];
4059
            PutByIdVariant variant = data.variants[i];
4060
4061
            checkInferredType(m_node->child2(), value, variant.requiredType());
4025
            
4062
            
4026
            LValue storage;
4063
            LValue storage;
4027
            if (variant.kind() == PutByIdVariant::Replace) {
4064
            if (variant.kind() == PutByIdVariant::Replace) {
Lines 5669-5674 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
5669
        m_out.appendTo(continuation, lastNext);
5706
        m_out.appendTo(continuation, lastNext);
5670
        return m_out.phi(m_out.int32, results);
5707
        return m_out.phi(m_out.int32, results);
5671
    }
5708
    }
5709
5710
    void checkInferredType(Edge edge, LValue value, const InferredType::Descriptor& type)
5711
    {
5712
        // This cannot use FTL_TYPE_CHECK or typeCheck() because it is called partially, as in a node like:
5713
        //
5714
        //     MultiPutByOffset(...)
5715
        //
5716
        // may be lowered to:
5717
        //
5718
        //     switch (object->structure) {
5719
        //     case 42:
5720
        //         checkInferredType(..., type1);
5721
        //         ...
5722
        //         break;
5723
        //     case 43:
5724
        //         checkInferredType(..., type2);
5725
        //         ...
5726
        //         break;
5727
        //     }
5728
        //
5729
        // where type1 and type2 are different. Using typeCheck() would mean that the edge would be
5730
        // filtered by type1 & type2, instead of type1 | type2.
5731
        
5732
        switch (type.kind()) {
5733
        case InferredType::Bottom:
5734
            speculate(BadType, jsValueValue(value), edge.node(), m_out.booleanTrue);
5735
            return;
5736
5737
        case InferredType::Boolean:
5738
            speculate(BadType, jsValueValue(value), edge.node(), isNotBoolean(value, provenType(edge)));
5739
            return;
5740
5741
        case InferredType::Other:
5742
            speculate(BadType, jsValueValue(value), edge.node(), isNotOther(value, provenType(edge)));
5743
            return;
5744
5745
        case InferredType::Int32:
5746
            speculate(BadType, jsValueValue(value), edge.node(), isNotInt32(value, provenType(edge)));
5747
            return;
5748
5749
        case InferredType::Number:
5750
            speculate(BadType, jsValueValue(value), edge.node(), isNotNumber(value, provenType(edge)));
5751
            return;
5752
5753
        case InferredType::String:
5754
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5755
            speculate(BadType, jsValueValue(value), edge.node(), isNotString(value, provenType(edge)));
5756
            return;
5757
5758
        case InferredType::ObjectWithStructure:
5759
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5760
            if (!abstractValue(edge).m_structure.isSubsetOf(type.structure())) {
5761
                speculate(
5762
                    BadType, jsValueValue(value), edge.node(),
5763
                    m_out.notEqual(
5764
                        m_out.load32(value, m_heaps.JSCell_structureID),
5765
                        weakStructureID(type.structure())));
5766
            }
5767
            return;
5768
5769
        case InferredType::ObjectWithStructureOrOther: {
5770
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther cell case"));
5771
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther not cell case"));
5772
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther continuation"));
5773
5774
            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
5775
5776
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
5777
5778
            if (!abstractValue(edge).m_structure.isSubsetOf(type.structure())) {
5779
                speculate(
5780
                    BadType, jsValueValue(value), edge.node(),
5781
                    m_out.notEqual(
5782
                        m_out.load32(value, m_heaps.JSCell_structureID),
5783
                        weakStructureID(type.structure())));
5784
            }
5785
5786
            m_out.jump(continuation);
5787
5788
            m_out.appendTo(notCellCase, continuation);
5789
5790
            speculate(
5791
                BadType, jsValueValue(value), edge.node(), isNotOther(value, provenType & ~SpecCell));
5792
5793
            m_out.jump(continuation);
5794
5795
            m_out.appendTo(continuation, lastNext);
5796
            return;
5797
        }
5798
5799
        case InferredType::Object:
5800
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5801
            speculate(BadType, jsValueValue(value), edge.node(), isNotObject(value, provenType(edge)));
5802
            return;
5803
5804
        case InferredType::ObjectOrOther: {
5805
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther cell case"));
5806
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther not cell case"));
5807
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther continuation"));
5808
5809
            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
5810
5811
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
5812
5813
            speculate(
5814
                BadType, jsValueValue(value), edge.node(),
5815
                isNotObject(value, provenType(edge) & SpecCell));
5816
5817
            m_out.jump(continuation);
5818
5819
            m_out.appendTo(notCellCase, continuation);
5820
5821
            speculate(
5822
                BadType, jsValueValue(value), edge.node(),
5823
                isNotOther(value, provenType(edge) & ~SpecCell));
5824
5825
            m_out.jump(continuation);
5826
5827
            m_out.appendTo(continuation, lastNext);
5828
            return;
5829
        }
5830
5831
        case InferredType::Top:
5832
            return;
5833
        }
5834
5835
        DFG_CRASH(m_graph, m_node, "Bad inferred type");
5836
    }
5672
    
5837
    
5673
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
5838
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
5674
    {
5839
    {
Lines 7509-7514 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
7509
        case CellUse:
7674
        case CellUse:
7510
            speculateCell(edge);
7675
            speculateCell(edge);
7511
            break;
7676
            break;
7677
        case CellOrOtherUse:
7678
            speculateCellOrOther(edge);
7679
            break;
7512
        case KnownCellUse:
7680
        case KnownCellUse:
7513
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7681
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7514
            break;
7682
            break;
Lines 7589-7594 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
7589
        lowCell(edge);
7757
        lowCell(edge);
7590
    }
7758
    }
7591
    
7759
    
7760
    void speculateCellOrOther(Edge edge)
7761
    {
7762
        LValue value = lowJSValue(edge, ManualOperandSpeculation);
7763
7764
        LBasicBlock isNotCell = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther not cell"));
7765
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther continuation"));
7766
7767
        m_out.branch(isCell(value, provenType(edge)), unsure(continuation), unsure(isNotCell));
7768
7769
        LBasicBlock lastNext = m_out.appendTo(isNotCell, continuation);
7770
        FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
7771
        m_out.jump(continuation);
7772
7773
        m_out.appendTo(continuation, lastNext);
7774
    }
7775
    
7592
    void speculateMachineInt(Edge edge)
7776
    void speculateMachineInt(Edge edge)
7593
    {
7777
    {
7594
        if (!m_interpreter.needsTypeCheck(edge))
7778
        if (!m_interpreter.needsTypeCheck(edge))
Lines 8122-8127 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
8122
            }
8306
            }
8123
        }
8307
        }
8124
8308
8309
        if (failCondition == m_out.booleanFalse)
8310
            return;
8311
8125
        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
8312
        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
8126
        
8313
        
8127
        m_ftlState.jitCode->osrExit.append(OSRExit(
8314
        m_ftlState.jitCode->osrExit.append(OSRExit(
Lines 8130-8138 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
8130
            availabilityMap().m_locals.numberOfArguments(),
8317
            availabilityMap().m_locals.numberOfArguments(),
8131
            availabilityMap().m_locals.numberOfLocals()));
8318
            availabilityMap().m_locals.numberOfLocals()));
8132
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
8319
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
8133
        
8320
8134
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
8321
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
8135
8322
8323
        if (failCondition == m_out.booleanTrue) {
8324
            emitOSRExitCall(exit, lowValue);
8325
            return;
8326
        }
8327
8136
        LBasicBlock lastNext = nullptr;
8328
        LBasicBlock lastNext = nullptr;
8137
        LBasicBlock continuation = nullptr;
8329
        LBasicBlock continuation = nullptr;
8138
        
8330
        
- Source/JavaScriptCore/jit/AssemblyHelpers.cpp +64 lines
Lines 55-60 Vector<BytecodeAndMachineOffset>& Assemb Source/JavaScriptCore/jit/AssemblyHelpers.cpp_sec1
55
    return result.iterator->value;
55
    return result.iterator->value;
56
}
56
}
57
57
58
AssemblyHelpers::JumpList AssemblyHelpers::branchIfNotType(
59
    JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor& descriptor)
60
{
61
    AssemblyHelpers::JumpList result;
62
63
    switch (descriptor.kind()) {
64
    case InferredType::Bottom:
65
        result.append(jump());
66
        break;
67
68
    case InferredType::Boolean:
69
        result.append(branchIfNotBoolean(regs, tempGPR));
70
        break;
71
72
    case InferredType::Other:
73
        result.append(branchIfNotOther(regs, tempGPR));
74
        break;
75
76
    case InferredType::Int32:
77
        result.append(branchIfNotInt32(regs));
78
        break;
79
80
    case InferredType::Number:
81
        result.append(branchIfNotNumber(regs));
82
        break;
83
84
    case InferredType::String:
85
        result.append(branchIfNotCell(regs));
86
        result.append(branchIfNotString(regs.payloadGPR()));
87
        break;
88
89
    case InferredType::ObjectWithStructure:
90
        result.append(branchIfNotCell(regs));
91
        result.append(branchStructure(regs.payloadGPR(), descriptor.structure()));
92
        break;
93
94
    case InferredType::ObjectWithStructureOrOther: {
95
        Jump ok = branchIfOther(regs, tempGPR);
96
        result.append(branchIfNotCell(regs));
97
        result.append(branchStructure(regs.payloadGPR(), descriptor.structure()));
98
        ok.link(this);
99
        break;
100
    }
101
102
    case InferredType::Object:
103
        result.append(branchIfNotCell(regs));
104
        result.append(branchIfNotObject(regs.payloadGPR()));
105
        break;
106
107
    case InferredType::ObjectOrOther: {
108
        Jump ok = branchIfOther(regs, tempGPR);
109
        result.append(branchIfNotCell(regs));
110
        result.append(branchIfNotObject(regs.payloadGPR()));
111
        ok.link(this);
112
        break;
113
    }
114
115
    case InferredType::Top:
116
        break;
117
    }
118
119
    return result;
120
}
121
58
void AssemblyHelpers::purifyNaN(FPRReg fpr)
122
void AssemblyHelpers::purifyNaN(FPRReg fpr)
59
{
123
{
60
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
124
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
- Source/JavaScriptCore/jit/AssemblyHelpers.h +2 lines
Lines 719-724 public: Source/JavaScriptCore/jit/AssemblyHelpers.h_sec1
719
#endif
719
#endif
720
    }
720
    }
721
721
722
    JumpList branchIfNotType(JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor&);
723
722
    template<typename T>
724
    template<typename T>
723
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
725
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
724
    {
726
    {
- Source/JavaScriptCore/jit/Repatch.cpp -1 / +2 lines
Lines 377-383 static InlineCacheAction tryCachePutByID Source/JavaScriptCore/jit/Repatch.cpp_sec1
377
            ptrdiff_t offsetToPatchedStorage = offsetRelativeToPatchedStorage(slot.cachedOffset());
377
            ptrdiff_t offsetToPatchedStorage = offsetRelativeToPatchedStorage(slot.cachedOffset());
378
            if (stubInfo.cacheType == CacheType::Unset
378
            if (stubInfo.cacheType == CacheType::Unset
379
                && MacroAssembler::isPtrAlignedAddressOffset(offsetToPatchedStorage)
379
                && MacroAssembler::isPtrAlignedAddressOffset(offsetToPatchedStorage)
380
                && !structure->needImpurePropertyWatchpoint()) {
380
                && !structure->needImpurePropertyWatchpoint()
381
                && !structure->inferredTypeFor(ident.impl())) {
381
382
382
                repatchByIdSelfAccess(
383
                repatchByIdSelfAccess(
383
                    codeBlock, stubInfo, structure, slot.cachedOffset(),
384
                    codeBlock, stubInfo, structure, slot.cachedOffset(),
- Source/JavaScriptCore/runtime/InferredType.cpp +506 lines
Line 0 Source/JavaScriptCore/runtime/InferredType.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "InferredType.h"
28
29
#include "JSCInlines.h"
30
31
namespace JSC {
32
33
const ClassInfo InferredType::s_info = { "InferredType", 0, 0, CREATE_METHOD_TABLE(InferredType) };
34
35
InferredType* InferredType::create(VM& vm)
36
{
37
    InferredType* result = new (NotNull, allocateCell<InferredType>(vm.heap)) InferredType(vm);
38
    result->finishCreation(vm);
39
    return result;
40
}
41
42
void InferredType::destroy(JSCell* cell)
43
{
44
    InferredType* inferredType = static_cast<InferredType*>(cell);
45
    inferredType->InferredType::~InferredType();
46
}
47
48
Structure* InferredType::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
49
{
50
    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
51
}
52
53
void InferredType::visitChildren(JSCell* cell, SlotVisitor& visitor)
54
{
55
    InferredType* inferredType = jsCast<InferredType*>(cell);
56
57
    if (inferredType->m_structure)
58
        visitor.addUnconditionalFinalizer(inferredType->m_structure.get());
59
}
60
61
InferredType::Kind InferredType::kindForFlags(PutByIdFlags flags)
62
{
63
    switch (flags & PutByIdPrimaryTypeMask) {
64
    case PutByIdPrimaryTypeSecondary:
65
        switch (flags & PutByIdSecondaryTypeMask) {
66
        case PutByIdSecondaryTypeBottom:
67
            return Bottom;
68
        case PutByIdSecondaryTypeBoolean:
69
            return Boolean;
70
        case PutByIdSecondaryTypeOther:
71
            return Other;
72
        case PutByIdSecondaryTypeInt32:
73
            return Int32;
74
        case PutByIdSecondaryTypeNumber:
75
            return Number;
76
        case PutByIdSecondaryTypeString:
77
            return String;
78
        case PutByIdSecondaryTypeObject:
79
            return Object;
80
        case PutByIdSecondaryTypeObjectOrOther:
81
            return ObjectOrOther;
82
        case PutByIdSecondaryTypeTop:
83
            return Top;
84
        default:
85
            RELEASE_ASSERT_NOT_REACHED();
86
            return Bottom;
87
        }
88
    case PutByIdPrimaryTypeObjectWithStructure:
89
        return ObjectWithStructure;
90
    case PutByIdPrimaryTypeObjectWithStructureOrOther:
91
        return ObjectWithStructureOrOther;
92
    default:
93
        RELEASE_ASSERT_NOT_REACHED();
94
        return Bottom;
95
    }
96
}
97
98
InferredType::Descriptor InferredType::Descriptor::forValue(JSValue value)
99
{
100
    if (value.isBoolean())
101
        return Boolean;
102
    if (value.isUndefinedOrNull())
103
        return Other;
104
    if (value.isInt32())
105
        return Int32;
106
    if (value.isNumber())
107
        return Number;
108
    if (value.isCell()) {
109
        JSCell* cell = value.asCell();
110
        if (cell->isString())
111
            return String;
112
        if (cell->isObject()) {
113
            if (cell->structure()->transitionWatchpointSetIsStillValid())
114
                return Descriptor(ObjectWithStructure, cell->structure());
115
            return Object;
116
        }
117
    }
118
    return Top;
119
}
120
121
InferredType::Descriptor InferredType::Descriptor::forFlags(VM& vm, PutByIdFlags flags)
122
{
123
    Kind kind = kindForFlags(flags);
124
    Structure* structure;
125
    if (hasStructure(kind))
126
        structure = vm.heap.structureIDTable().get(decodeStructureID(flags));
127
    else
128
        structure = nullptr;
129
    return Descriptor(kind, structure);
130
}
131
132
PutByIdFlags InferredType::Descriptor::putByIdFlags() const
133
{
134
    switch (m_kind) {
135
    case Bottom:
136
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBottom;
137
    case Boolean:
138
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBoolean;
139
    case Other:
140
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeOther;
141
    case Int32:
142
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeInt32;
143
    case Number:
144
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeNumber;
145
    case String:
146
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeString;
147
    case Object:
148
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObject;
149
    case ObjectOrOther:
150
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObjectOrOther;
151
    case Top:
152
        return PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeTop;
153
    case ObjectWithStructure:
154
        return PutByIdPrimaryTypeObjectWithStructure | encodeStructureID(m_structure->id());
155
    case ObjectWithStructureOrOther:
156
        return PutByIdPrimaryTypeObjectWithStructureOrOther | encodeStructureID(m_structure->id());
157
    }
158
    RELEASE_ASSERT_NOT_REACHED();
159
    return PutByIdNone;
160
}
161
162
void InferredType::Descriptor::merge(const Descriptor& other)
163
{
164
    if (*this == other)
165
        return;
166
    
167
    switch (m_kind) {
168
    case Bottom:
169
        *this = other;
170
        return;
171
    case Boolean:
172
    case String:
173
        *this = Top;
174
        return;
175
    case Other:
176
        switch (other.m_kind) {
177
        case ObjectWithStructure:
178
            m_kind = ObjectWithStructureOrOther;
179
            return;
180
        case Object:
181
            m_kind = ObjectOrOther;
182
            return;
183
        default:
184
            *this = Top;
185
            return;
186
        }
187
    case Int32:
188
        switch (other.m_kind) {
189
        case Number:
190
            m_kind = Number;
191
            return;
192
        default:
193
            *this = Top;
194
            return;
195
        }
196
    case Number:
197
        switch (other.m_kind) {
198
        case Int32:
199
            return;
200
        default:
201
            *this = Top;
202
            return;
203
        }
204
    case ObjectWithStructure:
205
        switch (other.m_kind) {
206
        case ObjectWithStructure:
207
        case Object:
208
            *this = Object;
209
            return;
210
        case ObjectWithStructureOrOther:
211
            if (m_structure == other.m_structure) {
212
                *this = other;
213
                return;
214
            }
215
            *this = ObjectOrOther;
216
            return;
217
        case ObjectOrOther:
218
            *this = ObjectOrOther;
219
            return;
220
        case Other:
221
            m_kind = ObjectWithStructureOrOther;
222
            return;
223
        default:
224
            *this = Top;
225
            return;
226
        }
227
    case ObjectWithStructureOrOther:
228
        switch (other.m_kind) {
229
        case ObjectWithStructure:
230
            if (m_structure == other.m_structure)
231
                return;
232
            *this = ObjectOrOther;
233
            return;
234
        case Object:
235
        case ObjectWithStructureOrOther:
236
        case ObjectOrOther:
237
            *this = ObjectOrOther;
238
            return;
239
        case Other:
240
            return;
241
        default:
242
            *this = Top;
243
            return;
244
        }
245
    case Object:
246
        switch (other.m_kind) {
247
        case ObjectWithStructure:
248
            return;
249
        case ObjectWithStructureOrOther:
250
        case ObjectOrOther:
251
        case Other:
252
            m_kind = ObjectOrOther;
253
            return;
254
        default:
255
            *this = Top;
256
            return;
257
        }
258
    case ObjectOrOther:
259
        switch (other.m_kind) {
260
        case ObjectWithStructure:
261
        case ObjectWithStructureOrOther:
262
        case Object:
263
        case Other:
264
            return;
265
        default:
266
            *this = Top;
267
            return;
268
        }
269
    case Top:
270
        return;
271
    }
272
273
    RELEASE_ASSERT_NOT_REACHED();
274
}
275
276
void InferredType::Descriptor::removeStructure()
277
{
278
    switch (m_kind) {
279
    case ObjectWithStructure:
280
        *this = Object;
281
        return;
282
    case ObjectWithStructureOrOther:
283
        *this = ObjectOrOther;
284
        return;
285
    default:
286
        return;
287
    }
288
}
289
290
bool InferredType::Descriptor::subsumes(const Descriptor& other) const
291
{
292
    Descriptor merged = *this;
293
    merged.merge(other);
294
    return *this == merged;
295
}
296
297
void InferredType::Descriptor::dumpInContext(PrintStream& out, DumpContext* context) const
298
{
299
    out.print(m_kind);
300
    if (m_structure)
301
        out.print(":", inContext(*m_structure, context));
302
}
303
304
void InferredType::Descriptor::dump(PrintStream& out) const
305
{
306
    dumpInContext(out, nullptr);
307
}
308
309
InferredType::InferredType(VM& vm)
310
    : Base(vm, vm.inferredTypeStructure.get())
311
    , m_watchpointSet(ClearWatchpoint)
312
{
313
}
314
315
InferredType::~InferredType()
316
{
317
}
318
319
bool InferredType::isStillValid(const ConcurrentJITLocker& locker, const Descriptor& expected)
320
{
321
    if (expected.kind() == Top)
322
        return false;
323
    
324
    return descriptor(locker) == expected;
325
}
326
327
bool InferredType::isStillValid(const Descriptor& expected)
328
{
329
    ConcurrentJITLocker locker(m_lock);
330
    return isStillValid(locker, expected);
331
}
332
333
void InferredType::addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint* watchpoint)
334
{
335
    RELEASE_ASSERT(descriptor(locker).kind() != Top);
336
337
    m_watchpointSet.add(watchpoint);
338
}
339
340
void InferredType::addWatchpoint(Watchpoint* watchpoint)
341
{
342
    ConcurrentJITLocker locker(m_lock);
343
    addWatchpoint(locker, watchpoint);
344
}
345
346
void InferredType::dump(PrintStream& out) const
347
{
348
    out.print(RawPointer(this), ":", descriptor());
349
}
350
351
void InferredType::willStoreValueSlow(VM& vm, JSValue value)
352
{
353
    ConcurrentJITLocker locker(m_lock);
354
    Descriptor myType = descriptor(locker);
355
    Descriptor otherType = Descriptor::forValue(value);
356
357
    myType.merge(otherType);
358
359
    ASSERT(descriptor(locker) != myType); // The type must have changed if we're on the slow path.
360
361
    set(locker, vm, myType);
362
}
363
364
void InferredType::makeTopSlow(VM& vm)
365
{
366
    ConcurrentJITLocker locker(m_lock);
367
    set(locker, vm, Top);
368
}
369
370
void InferredType::set(const ConcurrentJITLocker& locker, VM& vm, Descriptor newDescriptor)
371
{
372
    // We will trigger write barriers while holding our lock. Currently, write barriers don't GC, but that
373
    // could change. If it does, we don't want to deadlock. Note that we could have used
374
    // GCSafeConcurrentJITLocker in the caller, but the caller is on a fast path so maybe that wouldn't be
375
    // a good idea.
376
    DeferGCForAWhile deferGC(vm.heap);
377
    
378
    // Be defensive: if we're not really changing the type, then we don't have to do anything.
379
    if (descriptor(locker) == newDescriptor)
380
        return;
381
382
    // The new descriptor must be more general than the previous one.
383
    ASSERT(newDescriptor.subsumes(descriptor(locker)));
384
385
    // If the new descriptors have different structures, then it can only be because one is null.
386
    if (descriptor(locker).structure() != newDescriptor.structure())
387
        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());
388
389
    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
390
    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
391
    if (m_watchpointSet.state() != ClearWatchpoint) {
392
        // We cannot have been invalidated, since if we were, then we'd already be at Top.
393
        ASSERT(m_watchpointSet.state() != IsInvalidated);
394
395
        // We're about to do expensive things because some compiler thread decided to watch this type and
396
        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
397
        // it.
398
        newDescriptor = Top;
399
400
        m_watchpointSet.fireAll("Inferred type changed");
401
    }
402
403
    // Remove the old InferredStructure object if we no longer need it.
404
    if (!newDescriptor.structure())
405
        m_structure = nullptr;
406
407
    // Add a new InferredStructure object if we need one now.
408
    if (newDescriptor.structure()) {
409
        if (m_structure) {
410
            // We should agree on the structures if we get here.
411
            ASSERT(newDescriptor.structure() == m_structure->structure());
412
        } else {
413
            m_structure = std::make_unique<InferredStructure>(this, newDescriptor.structure());
414
            newDescriptor.structure()->addTransitionWatchpoint(m_structure.get());
415
        }
416
    }
417
418
    // Finally, set the descriptor kind.
419
    m_kind = newDescriptor.kind();
420
421
    // Assert that we did things.
422
    ASSERT(descriptor(locker) == newDescriptor);
423
}
424
425
void InferredType::removeStructure()
426
{
427
    VM& vm = *Heap::heap(this)->vm();
428
429
    ConcurrentJITLocker locker(m_parent->m_lock);
430
    
431
    Descriptor newDescriptor = descriptor(locker);
432
    newDescriptor.removeStructure();
433
    
434
    set(locker, vm, newDescriptor);
435
}
436
437
void InferredType::InferredStructure::InferredStructure(InferredType* parent, Structure* structure)
438
    : m_parent(parent)
439
    , m_structure(vm, parent, structure)
440
{
441
}
442
443
void InferredType::InferredStructure::fireInternal(const FireDetail&)
444
{
445
    m_parent->removeStructure();
446
}
447
448
void InferredType::InferredStructure::finalizeUnconditionally()
449
{
450
    VM& vm = *Heap::heap(m_parent)->vm();
451
452
    ASSERT(Heap::isMarked(m_parent));
453
    
454
    if (!Heap::isMarked(m_structure.get()))
455
        m_parent->removeStructure();
456
}
457
458
} // namespace JSC
459
460
namespace WTF {
461
462
using namespace JSC;
463
464
void printInternal(PrintStream& out, InferredType::Kind kind)
465
{
466
    switch (kind) {
467
    case InferredType::Bottom:
468
        out.print("Bottom");
469
        return;
470
    case InferredType::Boolean:
471
        out.print("Boolean");
472
        return;
473
    case InferredType::Other:
474
        out.print("Other");
475
        return;
476
    case InferredType::Int32:
477
        out.print("Int32");
478
        return;
479
    case InferredType::Number:
480
        out.print("Number");
481
        return;
482
    case InferredType::String:
483
        out.print("String");
484
        return;
485
    case InferredType::ObjectWithStructure:
486
        out.print("ObjectWithStructure");
487
        return;
488
    case InferredType::ObjectWithStructureOrOther:
489
        out.print("ObjectWithStructureOrOther");
490
        return;
491
    case InferredType::Object:
492
        out.print("Object");
493
        return;
494
    case InferredType::ObjectOrOther:
495
        out.print("ObjectOrOther");
496
        return;
497
    case InferredType::Top:
498
        out.print("Top");
499
        return;
500
    }
501
502
    RELEASE_ASSERT_NOT_REACHED();
503
}
504
505
} // namespace WTF
506
- Source/JavaScriptCore/runtime/InferredType.h +263 lines
Line 0 Source/JavaScriptCore/runtime/InferredType.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#infdef InferredType_h
27
#define InferredType_h
28
29
#include "ConcurrentJITLock.h"
30
#include "JSCell.h"
31
#include "PutByIdFlags.h"
32
33
namespace JSC {
34
35
// This is an object used for the inference of the types of object properties.
36
37
class InferredType final : public JSCell {
38
public:
39
    typedef JSCell Base;
40
41
    static InferredType* create(VM&);
42
43
    static const bool needsDestruction = true;
44
    static void destroy(JSCell*);
45
46
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
47
48
    static void visitChildren(JSCell*, SlotVisitor&);
49
50
    DECLARE_INFO;
51
52
    enum Kind : uint8_t {
53
        Bottom,
54
        Boolean,
55
        Other,
56
        Int32,
57
        Number,
58
        String,
59
        ObjectWithStructure,
60
        ObjectWithStructureOrOther,
61
        Object,
62
        ObjectOrOther,
63
        Top
64
    };
65
66
    Kind kindForFlags(PutByIdFlags);
67
    
68
    bool hasStructure(Kind kind)
69
    {
70
        switch (kind) {
71
        case ObjectWithStructure:
72
        case ObjectWithStructureOrOther:
73
            return true;
74
        default:
75
            return false;
76
        }
77
    }
78
79
    class Descriptor {
80
    public:
81
        Descriptor()
82
            : m_kind(Bottom)
83
            , m_structure(nullptr)
84
        {
85
        }
86
87
        Descriptor(Kind kind, Structure* structure = nullptr)
88
            : m_kind(kind)
89
            , m_structure(structure)
90
        {
91
        }
92
93
        static Descriptor forValue(JSValue);
94
95
        static Descriptor forFlags(VM&, PutByIdFlags);
96
97
        explicit operator bool() const
98
        {
99
            return m_kind == Bottom && !m_structure;
100
        }
101
102
        Kind kind() const { return m_kind; }
103
        Structure* structure() const { return m_structure; }
104
105
        PutByIdFlags putByIdFlags() const;
106
107
        ALWAYS_INLINE bool includesValue(JSValue value)
108
        {
109
            switch (m_kind) {
110
            case Bottom:
111
                return false;
112
            case Boolean:
113
                return value.isBoolean();
114
            case Other:
115
                return value.isUndefinedOrNull();
116
            case Int32:
117
                return value.isInt32();
118
            case Number:
119
                return value.isNumber();
120
            case String:
121
                return value.isString();
122
            case ObjectWithStructure:
123
                return value.isCell() && value.asCell()->structure() == m_structure;
124
            case ObjectWithStructureOrOther:
125
                return value.isUndefinedOrNull()
126
                    || (value.isCell() && value.asCell()->structure() == m_structure);
127
            case Object:
128
                return value.isObject();
129
            case ObjectOrOther:
130
                return value.isUndefinedOrNull() || value.isObject();
131
            case Top:
132
                return true;
133
            }
134
135
            RELEASE_ASSERT_NOT_REACHED();
136
        }
137
138
        bool operator==(const Descriptor& other)
139
        {
140
            return m_kind == other.m_kind
141
                && m_structure == other.m_structure;
142
        }
143
144
        bool operator!=(const Descriptor& other)
145
        {
146
            return !(*this == other);
147
        }
148
149
        unsigned hash() const
150
        {
151
            return WTF::PtrHash<Structure*>::hash(m_structure) ^ static_cast<unsigned>(m_kind);
152
        }
153
    
154
        void merge(const Descriptor&);
155
        void removeStructure();
156
157
        // Returns true if this descriptor is more general than the other one.
158
        bool subsumes(const Descriptor&) const;
159
160
        void dumpInContext(PrintStream&, DumpContext*) const;
161
        void dump(PrintStream&) const;
162
163
    private:
164
        Kind m_kind;
165
        Structure* m_structure;
166
    };
167
168
    ConcurrentJITLock& lock() const { return m_lock; }
169
170
    Descriptor descriptorMainThread() const
171
    {
172
        return Descriptor(m_kind, m_structure ? m_structure->structure() : nullptr);
173
    }
174
    
175
    Descriptor descriptor(const ConcurrentJITLocker&) const
176
    {
177
        return descriptorMainThread();
178
    }
179
    Descriptor descriptor() const
180
    {
181
        ConcurrentJITLocker locker(m_lock);
182
        return descriptor(locker);
183
    }
184
    
185
    Kind kind(const ConcurrentJITLocker& locker) const { return descriptor().kind(); }
186
    Structure* structure(const ConcurrentJITLocker& locker) const { return descriptor().structure(); }
187
188
    bool isTop() const { return m_kind == Top; }
189
    bool isRelevant() const { return m_kind != Top; }
190
191
    // Returns true if the InferredType is still relevant after the store. It's not relevant if it's Top.
192
    ALWAYS_INLINE bool willStoreValue(VM& vm, JSValue value)
193
    {
194
        Descriptor currentDescriptor = descriptorMainThread();
195
        if (currentDescriptor.includesValue(value))
196
            return currentDescriptor.kind() != Top;
197
        return willStoreValueSlow(vm, value);
198
    }
199
200
    // Immediately makes this type irrelevant.
201
    void makeTop(VM& vm)
202
    {
203
        if (isTop())
204
            return;
205
        makeTopSlow(vm);
206
    }
207
208
    // Returns true if it currently makes sense to watch this InferredType for this descriptor. Note that
209
    // this will always return false for Top.
210
    bool canWatch(const ConcurrentJITLocker& locker, const Descriptor&);
211
    bool canWatch(const Descriptor&);
212
    
213
    void addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint*);
214
    void addWatchpoint(Watchpoint*);
215
216
    void dump(PrintStream&) const;
217
218
private:
219
    InferredType(VM&);
220
    ~InferredType();
221
222
    void willStoreValueSlow(VM&, JSValue);
223
    void makeTopSlow(VM&);
224
    void set(const ConcurrentJITLocker&, VM&, Descriptor);
225
    void removeStructure();
226
227
    mutable ConcurrentJITLock m_lock;
228
    
229
    Kind m_kind { Bottom };
230
231
    class InferredStructure : public Watchpoint, public UnconditionalFinalizer {
232
    public:
233
        InferredStructure(InferredType* parent, Structure*);
234
235
        Structure* structure() const { return m_structure.get(); };
236
237
    protected:
238
        void fireInternal(const FireDetail&) override;
239
        void finalizeUnconditionally() override;
240
241
    private:
242
        InferredType* m_parent;
243
        WriteBarrier<Structure> m_structure;
244
    };
245
246
    std::unique_ptr<InferredStructure> m_structure;
247
248
    // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
249
    // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
250
    // thread. The DFG will use the InferredType as the thing that it watches.
251
    InlineWatchpointSet m_watchpointSet;
252
};
253
254
} // namespace JSC
255
256
namespace WTF {
257
258
void printInternal(PrintStream&, JSC::InferredType::Kind);
259
260
} // namespace WTF
261
262
#endif // InferredType_h
263
- Source/JavaScriptCore/runtime/InferredTypeTable.cpp +152 lines
Line 0 Source/JavaScriptCore/runtime/InferredTypeTable.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "InferredTypeTable.h"
28
29
#include "JSCInlines.h"
30
31
namespace JSC {
32
33
const ClassInfo InferredTypeTable::s_info = { "InferredTypeTable", 0, 0, CREATE_METHOD_TABLE(InferredTypeTable) };
34
35
InferredTypeTable* InferredTypeTable::create(VM& vm)
36
{
37
    InferredTypeTable* result = new (NotNull, allocateCell<InferredTypeTable>(vm.heap)) InferredTypeTable(vm);
38
    result->finishCreation(vm);
39
    return result;
40
}
41
42
void InferredTypeTable::destroy(JSCell* cell)
43
{
44
    InferredTypeTable* inferredTypeTable = static_cast<InferredTypeTable*>(cell);
45
    inferredTypeTable->InferredTypeTable::~InferredTypeTable();
46
}
47
48
Structure* InferredTypeTable::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
49
{
50
    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
51
}
52
53
void InferredTypeTable::visitChildren(JSCell* cell, SlotVisitor& visitor)
54
{
55
    InferredTypeTable* inferredTypeTable = jsCast<InferredTypeTable*>(cell);
56
57
    ConcurrentJITLocker locker(m_lock);
58
    
59
    for (auto& entry : m_table) {
60
        if (entry.value->isRelevant())
61
            visitor.append(&entry.value);
62
        else
63
            entry.value.clear();
64
    }
65
}
66
67
InferredType* InferredTypeTable::get(const ConcurrentJITLocker& locker, UniquedStringImpl* uid)
68
{
69
    auto iter = m_table.find(uid);
70
    if (iter == m_table.end() || !iter->value)
71
        return nullptr;
72
73
    // Take this opportunity to prune invalidated types.
74
    if (!iter->value->isRelevant()) {
75
        iter->value.clear();
76
        return nullptr;
77
    }
78
79
    return iter->value.get();
80
}
81
82
InferredType* InferredTypeTable::get(UniquedStringImpl* uid)
83
{
84
    ConcurrentJITLocker locker(m_lock);
85
    return get(locker, uid);
86
}
87
88
InferredType* InferredTypeTable::get(PropertyName propertyName)
89
{
90
    return get(propertyName.uid());
91
}
92
93
bool InferredTypeTable::willStoreValue(
94
    VM& vm, PropertyName propertyName, JSValue value, StoredPropertyAge age)
95
{
96
    // The algorithm here relies on the fact that only one thread modifies the hash map.
97
    
98
    if (age == OldProperty) {
99
        TypeTable::iterator iter = m_table.find(propertyName);
100
        if (iter == m_table.end() || !iter->value)
101
            return false; // Absence on replace => top.
102
        
103
        if (iter->value->willStoreValue(vm, value))
104
            return true;
105
        
106
        iter->value.clear();
107
        return false;
108
    }
109
110
    TypeTable::AddResult result;
111
    {
112
        ConcurrentJITLocker locker(m_lock);
113
        result = m_table.add(propertyName, WriteBarrier<InferredType>());
114
    }
115
    if (result.isNewEntry) {
116
        InferredType* inferredType = InferredType::create(vm);
117
        WTF::storeStoreFence();
118
        result.iterator->value.set(vm, this, inferredType);
119
    } else if (!result.iterator->value)
120
        return false;
121
    
122
    if (result.iterator->value->willStoreValue(vm, value))
123
        return true;
124
    
125
    result.iterator->value.clear();
126
    return false;
127
}
128
129
void InferredTypeTable::makeTop(VM& vm, PropertyName propertyName, StoredPropertyAge age)
130
{
131
    // The algorithm here relies on the fact that only one thread modifies the hash map.
132
    if (age == OldProperty) {
133
        TypeTable::iterator iter = m_table.find(propertyName);
134
        if (iter == m_table.end() || !iter->value)
135
            return; // Absence on replace => top.
136
137
        iter->value->makeTop();
138
        iter->value.clear();
139
        return;
140
    }
141
    
142
    ConcurrentJITLocker locker(m_lock);
143
    TypeTable::AddResult result = m_table.add(propertyName, WriteBarrier<InferredType>());
144
    if (!result.iterator->value)
145
        return;
146
    
147
    result.iterator->value->makeTop();
148
    result.iterator->value.clear();
149
}
150
151
} // namespace JSC
152
- Source/JavaScriptCore/runtime/InferredTypeTable.h +111 lines
Line 0 Source/JavaScriptCore/runtime/InferredTypeTable.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef InferredTypeTable_h
27
#define InferredTypeTable_h
28
29
#include "InferredType.h"
30
#include "JSCell.h"
31
32
namespace JSC {
33
34
// A table of inferred types for some structure. This is a JSCell because that simplifies the Structure
35
// destructor and makes lifetype easier to manage. For example, since it's a cell, we know that this thing
36
// cannot be deleted while the DFG is running. This is separate from PropertyTable because most properties
37
// will not have an InferredType, since most properties are in dictionaries (if you think of "a property"
38
// as being "a property in some Structure"). Also, this will happily conflate the types of properties from
39
// different structures even if the structures represent disjoint sets of objects.
40
41
class InferredTypeTable final : public JSCell {
42
public:
43
    typedef JSCell Base;
44
45
    static InferredTypeTable* create(VM&);
46
47
    static const bool needsDestruction = true;
48
    static void destroy(JSCell*);
49
50
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
51
52
    static void visitChildren(JSCell*, SlotVisitor&);
53
54
    DECLARE_INFO;
55
56
    ConcurrentJITLock& lock() { return m_lock; }
57
58
    bool isEmpty() const { return m_table.isEmpty(); }
59
60
    // Get the current inferred type. Returns nullptr for both Top and Bottom. Null means Bottom if the
61
    // owning Structure doesn't know about the property.
62
    InferredType* get(const ConcurrentJITLocker&, UniquedStringImpl*);
63
    InferredType* get(UniquedStringImpl*);
64
    InferredType* get(PropertyName);
65
66
    enum StoredPropertyAge {
67
        NewProperty,
68
        OldProperty
69
    };
70
    
71
    // Returns true if the InferredType for this property is still relevant after the store. It's not
72
    // relevant if it's Top. Note that this table will internally prune Top entries.
73
    bool willStoreValue(VM&, PropertyName, JSValue, StoredPropertyAge);
74
75
    // Invalidates the type for the property. Useful if we detect a store in a reflective context.
76
    void makeTop(VM&, PropertyName, StoredPropertyAge);
77
78
private:
79
    InferredTypeTable(VM&);
80
    ~InferredTypeTable();
81
82
    // Bottom: absence from table.
83
    // Top: null value in table, !value->isRelevant(), or absence from table.
84
    //
85
    // We know how to determine if absence from the table is bottom or top depending on whether the
86
    // property is present in the owning structure. Hence, depending on the structure, absence may have
87
    // different meanings. The way that this class determines if the owning structure knows of the property
88
    // is that we differentiate between actions: replace or transition. If we're adding a new property
89
    // (transition), then absence means bottom. If we're storing to an existing property (replace, then
90
    // absence means top. To make this work, we have to watch out for the case where two structures, S1 and
91
    // S2, share the same InferredTypeTable and neither of them initially know about property P. S1 may
92
    // want to add P without a type, while S2 may want to add P with a type. If S1 added P and used absence
93
    // to indicate Top, then S2 would use that absence to mean Bottom and would end up creating a non-Top
94
    // entry in the table. Then S1 would forget that it wanted Top, and would use S2's type. Clearly,
95
    // that's bad. We avoid such confusion by ensuring that a transition always adds an entry. Hence,
96
    // absence-means-bottom only comes into play for properties added before the InferredTypeTable was
97
    // created.
98
    typedef HashMap<RefPtr<UniquedStringImpl>, WriteBarrier<InferredType>, IdentifierRepHash, HashTraits<UniquedStringImpl*>> TableType;
99
    
100
    TableType m_table;
101
102
    // We only grab this lock when we're doing modifications on the main thread, or reads on the compiler
103
    // thread. The compiler thread is not allowed to do modifications.
104
    ConcurrentJITLock m_lock;
105
};
106
107
} // namespace JSC
108
109
#endif // InferredTypeTable_h
110
111
- Source/JavaScriptCore/runtime/JSObject.h -1 / +10 lines
Lines 1189-1194 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec1
1189
1189
1190
    Structure* structure = this->structure(vm);
1190
    Structure* structure = this->structure(vm);
1191
    if (structure->isDictionary()) {
1191
    if (structure->isDictionary()) {
1192
        ASSERT(!structure->hasInferredTypes());
1193
        
1192
        unsigned currentAttributes;
1194
        unsigned currentAttributes;
1193
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1195
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1194
        if (offset != invalidOffset) {
1196
        if (offset != invalidOffset) {
Lines 1228-1233 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec2
1228
    PropertyOffset offset;
1230
    PropertyOffset offset;
1229
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1231
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1230
    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) {
1232
    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) {
1233
        structure->willStoreValueForTransition(vm, propertyName, value, slot.context() == PutById);
1234
        
1231
        DeferGC deferGC(vm.heap);
1235
        DeferGC deferGC(vm.heap);
1232
        Butterfly* newButterfly = butterfly();
1236
        Butterfly* newButterfly = butterfly();
1233
        if (currentCapacity != structure->outOfLineCapacity()) {
1237
        if (currentCapacity != structure->outOfLineCapacity()) {
Lines 1244-1255 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec3
1244
    }
1248
    }
1245
1249
1246
    unsigned currentAttributes;
1250
    unsigned currentAttributes;
1247
    offset = structure->get(vm, propertyName, currentAttributes);
1251
    bool hasInferredType;
1252
    offset = structure->get(vm, propertyName, currentAttributes, hasInferredType);
1248
    if (offset != invalidOffset) {
1253
    if (offset != invalidOffset) {
1249
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1254
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1250
            return false;
1255
            return false;
1251
1256
1252
        structure->didReplaceProperty(offset);
1257
        structure->didReplaceProperty(offset);
1258
        if (UNLIKELY(hasInferredType))
1259
            structure->willStoreValueForReplace(vm, propertyName, value, slot.context() == PutById);
1260
1253
        slot.setExistingProperty(this, offset);
1261
        slot.setExistingProperty(this, offset);
1254
        putDirect(vm, offset, value);
1262
        putDirect(vm, offset, value);
1255
1263
Lines 1269-1274 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec4
1269
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1277
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1270
    
1278
    
1271
    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1279
    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1280
    structure->willStoreValueForTransition(vm, propertyName, value, slot.context() == PutById);
1272
    
1281
    
1273
    validateOffset(offset);
1282
    validateOffset(offset);
1274
    ASSERT(structure->isValidOffset(offset));
1283
    ASSERT(structure->isValidOffset(offset));
- Source/JavaScriptCore/runtime/Structure.cpp +62 lines
Lines 350-360 void Structure::materializePropertyMap(V Source/JavaScriptCore/runtime/Structure.cpp_sec1
350
    else
350
    else
351
        propertyTable().set(vm, this, table);
351
        propertyTable().set(vm, this, table);
352
352
353
    InferredTypeTable* typeTable = m_inferredTypeTable.get();
354
353
    for (size_t i = structures.size(); i--;) {
355
    for (size_t i = structures.size(); i--;) {
354
        structure = structures[i];
356
        structure = structures[i];
355
        if (!structure->m_nameInPrevious)
357
        if (!structure->m_nameInPrevious)
356
            continue;
358
            continue;
357
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
359
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
360
        if (typeTable && typeTable->get(structure->m_nameInPrevious.get()))
361
            entry.hasInferredType = true;
358
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
362
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
359
    }
363
    }
360
    
364
    
Lines 464-469 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec2
464
    transition->setAttributesInPrevious(attributes);
468
    transition->setAttributesInPrevious(attributes);
465
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
469
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
466
    transition->m_offset = structure->m_offset;
470
    transition->m_offset = structure->m_offset;
471
    transition->m_inferredTypeTable.setMayBeNull(vm, transition, structure->m_inferredTypeTable.get());
467
472
468
    offset = transition->add(vm, propertyName, attributes);
473
    offset = transition->add(vm, propertyName, attributes);
469
474
Lines 479-484 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec3
479
484
480
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
485
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
481
{
486
{
487
    // NOTE: There are some good reasons why this goes directly to uncacheable dictionary rather than
488
    // caching the removal. We can fix all of these things, but we must remember to do so, if we ever try
489
    // to optimize this case.
490
    //
491
    // - Cached transitions usually steal the property table, and assume that this is possible because they
492
    //   can just rebuild the table by looking at past transitions. That code assumes that the table only
493
    //   grew and never shrank. To support removals, we'd have to change the property table materialization
494
    //   code to handle deletions. Also, we have logic to get the list of properties on a structure that
495
    //   lacks a property table by just looking back through the set of transitions since the last
496
    //   structure that had a pinned table. That logic would also have to be changed to handle cached
497
    //   removals.
498
    //
499
    // - InferredTypeTable assumes that removal has never happened. This is important since if we could
500
    //   remove a property and then re-add it later, then the "absence means top" optimization wouldn't
501
    //   work anymore, unless removal also either poisoned type inference (by doing something equivalent to
502
    //   hasBeenDictionary) or by strongly marking the entry as Top by ensuring that it is not absent, but
503
    //   instead, has a null entry.
504
    
482
    ASSERT(!structure->isUncacheableDictionary());
505
    ASSERT(!structure->isUncacheableDictionary());
483
506
484
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
507
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
Lines 841-846 void Structure::startWatchingInternalPro Source/JavaScriptCore/runtime/Structure.cpp_sec4
841
    setDidWatchInternalProperties(true);
864
    setDidWatchInternalProperties(true);
842
}
865
}
843
866
867
void Structure::willStoreValueSlow(
868
    VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize,
869
    InferredTypeTable::StoredPropertyAge age)
870
{
871
    ASSERT(!isCompilationThread());
872
    ASSERT(structure()->classInfo() == info());
873
    ASSERT(!hadBeenDictionary());
874
875
    // Create the inferred type table before doing anything else, so that we don't GC after we have already
876
    // grabbed a pointer into the property map.
877
    InferredTypeTable* table = m_inferredTypeTable.get();
878
    if (!table) {
879
        table = InferredTypeTable::create(vm);
880
        WTF::storeStoreBarrier();
881
        m_inferredTypeTable.set(vm, this, table);
882
    }
883
884
    // This only works if we've got a property table.
885
    PropertyTable* propertyTable;
886
    materializePropertyMapIfNecessary(vm, propertyTable);
887
888
    // We must be calling this after having created the given property or confirmed that it was present
889
    // already, so we must have a property table now.
890
    ASSERT(propertyTable);
891
892
    // ... and the property must be present.
893
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
894
    ASSERT(entry);
895
896
    if (shouldOptimize)
897
        entry->hasInferredType = table->willStoreValue(vm, propertyName, value, age);
898
    else {
899
        table->makeTop(vm, propertyName, age);
900
        entry->hasInferredType = false;
901
    }
902
}
903
844
#if DUMP_PROPERTYMAP_STATS
904
#if DUMP_PROPERTYMAP_STATS
845
905
846
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
906
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
Lines 1058-1063 void Structure::visitChildren(JSCell* ce Source/JavaScriptCore/runtime/Structure.cpp_sec5
1058
        visitor.append(&thisObject->m_propertyTableUnsafe);
1118
        visitor.append(&thisObject->m_propertyTableUnsafe);
1059
    } else if (thisObject->m_propertyTableUnsafe)
1119
    } else if (thisObject->m_propertyTableUnsafe)
1060
        thisObject->m_propertyTableUnsafe.clear();
1120
        thisObject->m_propertyTableUnsafe.clear();
1121
1122
    visitor.append(&thisObject->m_inferredTypeTable);
1061
}
1123
}
1062
1124
1063
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
1125
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
- Source/JavaScriptCore/runtime/Structure.h +45 lines
Lines 29-34 Source/JavaScriptCore/runtime/Structure.h_sec1
29
#include "ClassInfo.h"
29
#include "ClassInfo.h"
30
#include "ConcurrentJITLock.h"
30
#include "ConcurrentJITLock.h"
31
#include "IndexingType.h"
31
#include "IndexingType.h"
32
#include "InferredTypeTable.h"
32
#include "JSCJSValue.h"
33
#include "JSCJSValue.h"
33
#include "JSCell.h"
34
#include "JSCell.h"
34
#include "JSType.h"
35
#include "JSType.h"
Lines 81-91 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec2
81
    UniquedStringImpl* key;
82
    UniquedStringImpl* key;
82
    PropertyOffset offset;
83
    PropertyOffset offset;
83
    uint8_t attributes;
84
    uint8_t attributes;
85
    bool hasInferredType; // This caches whether or not a property has an inferred type in the inferred type table, and is used for a fast check in JSObject::putDirectInternal().
84
86
85
    PropertyMapEntry()
87
    PropertyMapEntry()
86
        : key(nullptr)
88
        : key(nullptr)
87
        , offset(invalidOffset)
89
        , offset(invalidOffset)
88
        , attributes(0)
90
        , attributes(0)
91
        , hasInferredType(false)
89
    {
92
    {
90
    }
93
    }
91
    
94
    
Lines 93-98 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec3
93
        : key(key)
96
        : key(key)
94
        , offset(offset)
97
        , offset(offset)
95
        , attributes(attributes)
98
        , attributes(attributes)
99
        , hasInferredType(false)
96
    {
100
    {
97
        ASSERT(this->attributes == attributes);
101
        ASSERT(this->attributes == attributes);
98
    }
102
    }
Lines 323-328 public: Source/JavaScriptCore/runtime/Structure.h_sec4
323
327
324
    PropertyOffset get(VM&, PropertyName);
328
    PropertyOffset get(VM&, PropertyName);
325
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
329
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
330
    PropertyOffset get(VM&, PropertyName, unsigned& attributes, bool& hasInferredType);
326
331
327
    // This is a somewhat internalish method. It will call your functor while possibly holding the
332
    // This is a somewhat internalish method. It will call your functor while possibly holding the
328
    // Structure's lock. There is no guarantee whether the lock is held or not in any particular
333
    // Structure's lock. There is no guarantee whether the lock is held or not in any particular
Lines 481-486 public: Source/JavaScriptCore/runtime/Structure.h_sec5
481
            structure->startWatchingInternalPropertiesIfNecessary(vm);
486
            structure->startWatchingInternalPropertiesIfNecessary(vm);
482
    }
487
    }
483
488
489
    bool hasInferredTypes() const
490
    {
491
        return !!m_inferredTypeTable;
492
    }
493
494
    InferredType* inferredTypeFor(UniquedStringImpl* uid)
495
    {
496
        if (InferredTypeTable* table = m_inferredTypeTable.get())
497
            return table->get(uid);
498
        return nullptr;
499
    }
500
501
    InferredType::Descriptor inferredTypeDescriptorFor(UniquedStringImpl* uid)
502
    {
503
        if (InferredType* result = inferredTypeFor(uid))
504
            return resut->descriptor();
505
        return InferredType::Top;
506
    }
507
508
    // Returns true if the type of the property is still valid.
509
    ALWAYS_INLINE void willStoreValueForTransition(
510
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
511
    {
512
        if (hasBeenDictionary() || (!shouldOptimize && !m_inferredTypeTable))
513
            return;
514
        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::NewProperty);
515
    }
516
    ALWAYS_INLINE void willStoreValueForReplace(
517
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
518
    {
519
        if (hasBeenDictionary())
520
            return;
521
        willSloreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::OldProperty);
522
    }
523
484
    PassRefPtr<StructureShape> toStructureShape(JSValue);
524
    PassRefPtr<StructureShape> toStructureShape(JSValue);
485
    
525
    
486
    // Determines if the two structures match enough that this one could be used for allocations
526
    // Determines if the two structures match enough that this one could be used for allocations
Lines 632-637 private: Source/JavaScriptCore/runtime/Structure.h_sec6
632
    
672
    
633
    void startWatchingInternalProperties(VM&);
673
    void startWatchingInternalProperties(VM&);
634
674
675
    void willStoreValueSlow(
676
        VM&, PropertyOffset, PropertyName, JSValue, bool, InferredTypeTable::StoredPropertyAge);
677
635
    static const int s_maxTransitionLength = 64;
678
    static const int s_maxTransitionLength = 64;
636
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
679
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
637
680
Lines 655-660 private: Source/JavaScriptCore/runtime/Structure.h_sec7
655
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
698
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
656
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
699
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
657
700
701
    WriteBarrier<InferredTypeTable> m_inferredTypeTable;
702
658
    mutable InlineWatchpointSet m_transitionWatchpointSet;
703
    mutable InlineWatchpointSet m_transitionWatchpointSet;
659
704
660
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
705
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
- Source/JavaScriptCore/runtime/StructureInlines.h -9 / +10 lines
Lines 75-93 inline Structure* Structure::storedProto Source/JavaScriptCore/runtime/StructureInlines.h_sec1
75
75
76
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
76
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
77
{
77
{
78
    ASSERT(!isCompilationThread());
78
    unsigned attributes;
79
    ASSERT(structure()->classInfo() == info());
79
    bool hasInferredType;
80
    PropertyTable* propertyTable;
80
    return get(vm, propertyName, attributes, hasInferredType);
81
    materializePropertyMapIfNecessary(vm, propertyTable);
82
    if (!propertyTable)
83
        return invalidOffset;
84
85
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
86
    return entry ? entry->offset : invalidOffset;
87
}
81
}
88
    
82
    
89
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
83
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
90
{
84
{
85
    bool hasInferredType;
86
    return get(vm, propertyName, attributes, hasInferredType);
87
}
88
89
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, bool& hasInferredType)
90
{
91
    ASSERT(!isCompilationThread());
91
    ASSERT(!isCompilationThread());
92
    ASSERT(structure()->classInfo() == info());
92
    ASSERT(structure()->classInfo() == info());
93
93
Lines 101-106 ALWAYS_INLINE PropertyOffset Structure:: Source/JavaScriptCore/runtime/StructureInlines.h_sec2
101
        return invalidOffset;
101
        return invalidOffset;
102
102
103
    attributes = entry->attributes;
103
    attributes = entry->attributes;
104
    hasInferredType = entry->hasInferredType;
104
    return entry->offset;
105
    return entry->offset;
105
}
106
}
106
107

Return to Bug 148610