| 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 752-757 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
752
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
754
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
753
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
755
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
754
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
756
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
757
		0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */; };
758
		0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
759
		0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */; };
760
		0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
755
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
761
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
756
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
762
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
757
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
763
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 1920-1925 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
1920
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1926
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1921
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1927
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1922
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1928
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1929
		0F0A75201B94BFA900110660 /* InferredType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredType.cpp; sourceTree = "<group>"; };
1930
		0F0A75211B94BFA900110660 /* InferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredType.h; sourceTree = "<group>"; };
1923
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1931
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1924
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1932
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1925
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
1933
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
Lines 2583-2588 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
2583
		0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
2591
		0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
2584
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2592
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2585
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2593
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2594
		0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredTypeTable.cpp; sourceTree = "<group>"; };
2595
		0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredTypeTable.h; sourceTree = "<group>"; };
2596
		0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredInferredType.h; path = dfg/DFGDesiredInferredType.h; sourceTree = "<group>"; };
2597
		0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropertyTypeKey.h; path = dfg/DFGPropertyTypeKey.h; sourceTree = "<group>"; };
2586
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2598
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2587
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2599
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2588
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
2600
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
Lines 4657-4664 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
4657
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4669
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4658
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4670
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4659
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4671
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4660
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4661
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4672
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4673
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4662
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4674
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4663
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4675
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4664
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
4676
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
Lines 4692-4697 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
4692
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4704
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4693
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4705
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4694
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4706
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4707
				0F0A75201B94BFA900110660 /* InferredType.cpp */,
4708
				0F0A75211B94BFA900110660 /* InferredType.h */,
4709
				0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */,
4710
				0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */,
4695
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4711
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4696
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4712
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4697
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
4713
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
Lines 4742-4751 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
4742
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4758
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4743
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4759
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4744
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4760
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4745
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4746
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4747
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4761
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4748
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4762
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4763
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4764
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4749
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4765
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4750
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4766
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4751
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
4767
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
Lines 5049-5057 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
5049
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5065
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5050
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5066
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5051
				E18E3A560DF9278C00D90B34 /* VM.h */,
5067
				E18E3A560DF9278C00D90B34 /* VM.h */,
5052
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5053
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5068
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5054
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5069
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5070
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5055
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5071
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5056
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5072
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5057
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
5073
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
Lines 5203-5208 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
5203
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5219
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5204
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5220
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5205
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5221
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5222
				0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */,
5206
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5223
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5207
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5224
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5208
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
5225
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
Lines 5350-5355 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec10
5350
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5367
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5351
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5368
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5352
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5369
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5370
				0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */,
5353
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5371
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5354
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5372
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5355
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
5373
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
Lines 5940-5945 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec11
5940
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5958
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5941
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5959
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5942
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5960
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5961
				0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
5943
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5962
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5944
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5963
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5945
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
5964
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
Lines 6053-6058 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec12
6053
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6072
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6054
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6073
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6055
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6074
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6075
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
6056
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6076
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6057
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6077
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6058
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
6078
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
Lines 6338-6343 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec13
6338
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6358
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6339
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6359
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6340
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6360
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6361
				0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */,
6341
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6362
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6342
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6363
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6343
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
6364
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
Lines 6504-6509 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec14
6504
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6525
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6505
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6526
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6506
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6527
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6528
				0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
6507
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6529
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6508
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6530
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6509
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
6531
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
Lines 7448-7453 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec15
7448
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7470
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7449
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7471
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7450
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7472
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7473
				0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
7451
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7474
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7452
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7475
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7453
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
7476
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
Lines 7863-7868 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec16
7863
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7886
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7864
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7887
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7865
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7888
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7889
				0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
7866
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7890
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7867
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7891
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7868
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
7892
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
- 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 -42 / +71 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 2615-2623 void AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec8
2615
2644
2616
template<typename AbstractStateType>
2645
template<typename AbstractStateType>
2617
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2646
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2618
    AbstractValue& value, const StructureSet& set)
2647
    AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
2619
{
2648
{
2620
    if (value.filter(m_graph, set) == FiltrationOK)
2649
    if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
2621
        return FiltrationOK;
2650
        return FiltrationOK;
2622
    m_state.setIsValid(false);
2651
    m_state.setIsValid(false);
2623
    return Contradiction;
2652
    return Contradiction;
- Source/JavaScriptCore/dfg/DFGAbstractValue.cpp -2 / +58 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::Double:
136
        setType(SpecBytecodeDouble);
137
        return;
138
    case InferredType::Number:
139
        setType(SpecBytecodeNumber);
140
        return;
141
    case InferredType::String:
142
        set(graph, graph.m_vm.stringStructure.get());
143
        return;
144
    case InferredType::ObjectWithStructure:
145
        set(graph, descriptor.structure());
146
        return;
147
    case InferredType::ObjectWithStructureOrOther:
148
        set(graph, descriptor.structure());
149
        merge(SpecOther);
150
        return;
151
    case InferredType::Object:
152
        setType(graph, SpecObject);
153
        return;
154
    case InferredType::ObjectOrOther:
155
        setType(graph, SpecObject | SpecOther);
156
        return;
157
    case InferredType::Top:
158
        makeHeapTop();
159
        return;
160
    }
161
162
    RELEASE_ASSERT_NOT_REACHED();
163
}
164
165
void AbstractValue::set(
166
    Graph& graph, const InferredType::Descriptor& descriptor, StructureClobberState clobberState)
167
{
168
    set(graph, descriptor);
169
    if (clobberState == StructuresAreClobbered)
170
        clobberStructures();
171
}
172
120
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
173
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
121
{
174
{
122
    if (representation == NodeResultDouble) {
175
    if (representation == NodeResultDouble) {
Lines 189-196 bool AbstractValue::mergeOSREntryValue(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec2
189
    return oldMe != *this;
242
    return oldMe != *this;
190
}
243
}
191
244
192
FiltrationResult AbstractValue::filter(Graph& graph, const StructureSet& other)
245
FiltrationResult AbstractValue::filter(
246
    Graph& graph, const StructureSet& other, SpeculatedType admittedTypes)
193
{
247
{
248
    ASSERT(!(admittedTypes & SpecCell));
249
    
194
    if (isClear())
250
    if (isClear())
195
        return FiltrationOK;
251
        return FiltrationOK;
196
    
252
    
Lines 198-204 FiltrationResult AbstractValue::filter(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec3
198
    // having structures, array modes, or a specific value.
254
    // having structures, array modes, or a specific value.
199
    // https://bugs.webkit.org/show_bug.cgi?id=109663
255
    // https://bugs.webkit.org/show_bug.cgi?id=109663
200
    
256
    
201
    m_type &= other.speculationFromStructures();
257
    m_type &= other.speculationFromStructures() | admittedTypes;
202
    m_arrayModes &= other.arrayModesFromStructures();
258
    m_arrayModes &= other.arrayModesFromStructures();
203
    m_structure.filter(other);
259
    m_structure.filter(other);
204
    
260
    
- Source/JavaScriptCore/dfg/DFGAbstractValue.h -2 / +12 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-287 struct AbstractValue { Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec3
280
    {
284
    {
281
        return !(m_type & ~desiredType);
285
        return !(m_type & ~desiredType);
282
    }
286
    }
287
288
    // Filters the value using the given structure set. If the admittedTypes argument is not passed, this
289
    // implicitly filters by the types implied by the structure set, which are usually a subset of
290
    // SpecCell. Hence, after this call, the value will no longer have any non-cell members. But, you can
291
    // use admittedTypes to preserve some non-cell types. Note that it's wrong for admittedTypes to overlap
292
    // with SpecCell.
293
    FiltrationResult filter(Graph&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
283
    
294
    
284
    FiltrationResult filter(Graph&, const StructureSet&);
285
    FiltrationResult filterArrayModes(ArrayModes);
295
    FiltrationResult filterArrayModes(ArrayModes);
286
    FiltrationResult filter(SpeculatedType);
296
    FiltrationResult filter(SpeculatedType);
287
    FiltrationResult filterByValue(const FrozenValue& value);
297
    FiltrationResult filterByValue(const FrozenValue& value);
- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp -10 / +23 lines
Lines 205-213 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec1
205
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
205
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
206
    template<typename ChecksFunctor>
206
    template<typename ChecksFunctor>
207
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
207
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
208
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
208
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value);
209
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType = GetByOffset);
209
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset);
210
    Node* handleGetByOffset(SpeculatedType, Node* base, UniquedStringImpl*, PropertyOffset, NodeType = GetByOffset);
211
210
212
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
211
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
213
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
212
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
Lines 2303-2309 bool ByteCodeParser::handleConstantInter Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
2303
    return false;
2302
    return false;
2304
}
2303
}
2305
2304
2306
Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
2305
Node* ByteCodeParser::handleGetByOffset(
2306
    SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
2307
    const InferredType::Descriptor& inferredType, NodeType op)
2307
{
2308
{
2308
    Node* propertyStorage;
2309
    Node* propertyStorage;
2309
    if (isInlineOffset(offset))
2310
    if (isInlineOffset(offset))
Lines 2314-2326 Node* ByteCodeParser::handleGetByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
2314
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2315
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2315
    data->offset = offset;
2316
    data->offset = offset;
2316
    data->identifierNumber = identifierNumber;
2317
    data->identifierNumber = identifierNumber;
2318
    data->inferredType = inferredType;
2317
    
2319
    
2318
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2320
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2319
2321
2320
    return getByOffset;
2322
    return getByOffset;
2321
}
2323
}
2322
2324
2323
Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
2325
Node* ByteCodeParser::handlePutByOffset(
2326
    Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor& inferredType,
2327
    Node* value)
2324
{
2328
{
2325
    Node* propertyStorage;
2329
    Node* propertyStorage;
2326
    if (isInlineOffset(offset))
2330
    if (isInlineOffset(offset))
Lines 2331-2336 Node* ByteCodeParser::handlePutByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec4
2331
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2335
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2332
    data->offset = offset;
2336
    data->offset = offset;
2333
    data->identifierNumber = identifier;
2337
    data->identifierNumber = identifier;
2338
    data->inferredType = inferredType;
2334
    
2339
    
2335
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2340
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2336
    
2341
    
Lines 2445-2451 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec5
2445
        return addToGraph(JSConstant, OpInfo(method.constant()));
2450
        return addToGraph(JSConstant, OpInfo(method.constant()));
2446
    case GetByOffsetMethod::LoadFromPrototype: {
2451
    case GetByOffsetMethod::LoadFromPrototype: {
2447
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2452
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2448
        return handleGetByOffset(prediction, baseNode, identifierNumber, method.offset(), op);
2453
        return handleGetByOffset(
2454
            prediction, baseNode, identifierNumber, method.offset(), InferredType::Top, op);
2449
    }
2455
    }
2450
    case GetByOffsetMethod::Load:
2456
    case GetByOffsetMethod::Load:
2451
        // Will never see this from planLoad().
2457
        // Will never see this from planLoad().
Lines 2551-2563 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec6
2551
    
2557
    
2552
    bool needStructureCheck = true;
2558
    bool needStructureCheck = true;
2553
    
2559
    
2560
    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2561
    
2554
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2562
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2555
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2563
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2556
        // if the base's structure is watched.
2564
        // if the base's structure is watched.
2557
        Structure* structure = base->constant()->structure();
2565
        Structure* structure = base->constant()->structure();
2558
        if (!structure->dfgShouldWatch()) {
2566
        if (!structure->dfgShouldWatch()) {
2559
            UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2560
            
2561
            if (!variant.conditionSet().isEmpty()) {
2567
            if (!variant.conditionSet().isEmpty()) {
2562
                // This means that we're loading from a prototype. We expect the base not to have the
2568
                // This means that we're loading from a prototype. We expect the base not to have the
2563
                // property. We can only use ObjectPropertyCondition if all of the structures in the
2569
                // property. We can only use ObjectPropertyCondition if all of the structures in the
Lines 2622-2630 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec7
2622
            if (constant)
2628
            if (constant)
2623
                return weakJSConstant(constant);
2629
                return weakJSConstant(constant);
2624
        }
2630
        }
2631
2632
        InferredType::Descriptor inferredType;
2633
        if (needStructureCheck) {
2634
            for (Structure* structure : variant.structureSet())
2635
                inferredType.merge(m_graph.inferredTypeForProperty(structure, uid));
2636
        } else
2637
            inferredType = InferredType::Top;
2625
        
2638
        
2626
        loadedValue = handleGetByOffset(
2639
        loadedValue = handleGetByOffset(
2627
            loadPrediction, base, identifierNumber, variant.offset(), loadOp);
2640
            loadPrediction, base, identifierNumber, variant.offset(), inferredType, loadOp);
2628
    }
2641
    }
2629
2642
2630
    return loadedValue;
2643
    return loadedValue;
Lines 2635-2641 Node* ByteCodeParser::store(Node* base, Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec8
2635
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2648
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2636
2649
2637
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2650
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2638
    return handlePutByOffset(base, identifier, variant.offset(), value);
2651
    return handlePutByOffset(base, identifier, variant.offset(), variant.inferredType(), value);
2639
}
2652
}
2640
2653
2641
void ByteCodeParser::handleGetById(
2654
void ByteCodeParser::handleGetById(
- 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/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/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 5229-5234 void SpeculativeJIT::compileTypeOf(Node* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec1
5229
    cellResult(resultGPR, node);
5229
    cellResult(resultGPR, node);
5230
}
5230
}
5231
5231
5232
void SpeculativeJIT::compileCheckStructure(Node* node, GPRReg cellGPR, GPRReg tempGPR)
5233
{
5234
    ASSERT(node->structureSet().size());
5235
    
5236
    if (node->structureSet().size() == 1) {
5237
        speculationCheck(
5238
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5239
            m_jit.branchWeakStructure(
5240
                JITCompiler::NotEqual,
5241
                JITCompiler::Address(cellGPR, JSCell::structureIDOffset()),
5242
                node->structureSet()[0]));
5243
    } else {
5244
        std::unique_ptr<GPRTemporary> structure;
5245
        GPRReg structureGPR;
5246
        
5247
        if (tempGPR == InvalidGPR) {
5248
            structure = std::make_unique<GPRTemporary>(this);
5249
            structureGPR = structure->gpr();
5250
        } else
5251
            structureGPR = tempGPR;
5252
        
5253
        m_jit.load32(JITCompiler::Address(cellGPR, JSCell::structureIDOffset()), structureGPR);
5254
        
5255
        JITCompiler::JumpList done;
5256
        
5257
        for (size_t i = 0; i < node->structureSet().size() - 1; ++i) {
5258
            done.append(
5259
                m_jit.branchWeakStructur(JITCompiler::Equal, structureGPR, node->structureSet()[i]));
5260
        }
5261
        
5262
        speculationCheck(
5263
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5264
            m_jit.branchWeakStructure(
5265
                JITCompiler::NotEqual, structureGPR, node->structureSet().last()));
5266
        
5267
        done.link(&m_jit);
5268
    }
5269
}
5270
5271
void SpeculativeJIT::compileCheckStructure(Node* node)
5272
{
5273
    switch (node->child1().useKind()) {
5274
    case CellUse: {
5275
        SpeculateCellOperand cell(this, node->child1());
5276
        compileCheckStructure(node, cell.gpr(), InvalidGPRReg);
5277
        noResult(node);
5278
        return;
5279
    }
5280
5281
    case CellOrOtherUse: {
5282
        JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
5283
        GPRTemporary temp(this);
5284
5285
        JSValueRegs valueRegs = value.jsValueRegs();
5286
        GPRReg tempGPR = temp.gpr();
5287
5288
        JITCompiler::Jump cell = m_jit.branchIfCell(valueRegs);
5289
        DFG_TYPE_CHECK(
5290
            valueRegs, node->child1(), SpecCell | SpecOther,
5291
            m_jit.branchIfNotOther(valueRegs, tempGPR));
5292
        JITCompiler::Jump done = m_jit.jump();
5293
        cell.link(&m_jit);
5294
        compileCheckStructure(node, valueRegs.payloadGPR(), tempGPR);
5295
        done.link(&m_jit);
5296
        noResult(this);
5297
        return;
5298
    }
5299
5300
    default:
5301
        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
5302
        return;
5303
    }
5304
}
5305
5232
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5306
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5233
{
5307
{
5234
    if (node->transition()->previous->couldHaveIndexingHeader()) {
5308
    if (node->transition()->previous->couldHaveIndexingHeader()) {
Lines 5633-5638 void SpeculativeJIT::speculateCell(Edge Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec2
5633
    (SpeculateCellOperand(this, edge)).gpr();
5707
    (SpeculateCellOperand(this, edge)).gpr();
5634
}
5708
}
5635
5709
5710
void SpeculativeJIT::speculateCellOrOther(Edge edge)
5711
{
5712
    if (!needsTypeCheck(edge, SpecCell | SpecOther))
5713
        return;
5714
    
5715
    JSValueOperand operand(this, edge, ManualOperandSpeculation);
5716
    GPRTemporary temp(this);
5717
    GPRReg tempGPR = temp.gpr();
5718
5719
    MacroAssembler::Jump ok = m_jit.branchIfCell(operand.jsValueRegs());
5720
    DFG_TYPE_CHECK(
5721
        operand.jsValueRegs(), edge, SpecCell | SpecOther,
5722
        m_jit.branchIfNotOther(operand.jsValueRegs(), tempGPR));
5723
    ok.link(&m_jit);
5724
}
5725
5636
void SpeculativeJIT::speculateObject(Edge edge)
5726
void SpeculativeJIT::speculateObject(Edge edge)
5637
{
5727
{
5638
    if (!needsTypeCheck(edge, SpecObject))
5728
    if (!needsTypeCheck(edge, SpecObject))
Lines 5913-5918 void SpeculativeJIT::speculate(Node*, Ed Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec3
5913
    case CellUse:
6003
    case CellUse:
5914
        speculateCell(edge);
6004
        speculateCell(edge);
5915
        break;
6005
        break;
6006
    case CellOrOtherUse:
6007
        speculateCellOrOther(edge);
6008
        break;
5916
    case ObjectUse:
6009
    case ObjectUse:
5917
        speculateObject(edge);
6010
        speculateObject(edge);
5918
        break;
6011
        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 -10 / +64 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 7509-7514 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
7509
        case CellUse:
7544
        case CellUse:
7510
            speculateCell(edge);
7545
            speculateCell(edge);
7511
            break;
7546
            break;
7547
        case CellOrOtherUse:
7548
            speculateCellOrOther(edge);
7549
            break;
7512
        case KnownCellUse:
7550
        case KnownCellUse:
7513
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7551
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7514
            break;
7552
            break;
Lines 7589-7594 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
7589
        lowCell(edge);
7627
        lowCell(edge);
7590
    }
7628
    }
7591
    
7629
    
7630
    void speculateCellOrOther(Edge edge)
7631
    {
7632
        LValue value = lowJSValue(edge, ManualOperandSpeculation);
7633
7634
        LBasicBlock isNotCell = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther not cell"));
7635
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther continuation"));
7636
7637
        m_out.branch(isCell(value, provenType(edge)), unsure(continuation), unsure(isNotCell));
7638
7639
        LBasicBlock lastNext = m_out.appendTo(isNotCell, continuation);
7640
        FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
7641
        m_out.jump(continuation);
7642
7643
        m_out.appendTo(continuation, lastNext);
7644
    }
7645
    
7592
    void speculateMachineInt(Edge edge)
7646
    void speculateMachineInt(Edge edge)
7593
    {
7647
    {
7594
        if (!m_interpreter.needsTypeCheck(edge))
7648
        if (!m_interpreter.needsTypeCheck(edge))
- Source/JavaScriptCore/jit/AssemblyHelpers.cpp +69 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::Double:
81
        result.append(branchIfInt32(regs));
82
        result.append(branchIfNotNumber(regs));
83
        break;
84
85
    case InferredType::Number:
86
        result.append(branchIfNotNumber(regs));
87
        break;
88
89
    case InferredType::String:
90
        result.append(branchIfNotCell(regs));
91
        result.append(branchIfNotString(regs.payloadGPR()));
92
        break;
93
94
    case InferredType::ObjectWithStructure:
95
        result.append(branchIfNotCell(regs));
96
        result.append(branchStructure(regs.payloadGPR(), descriptor.structure()));
97
        break;
98
99
    case InferredType::ObjectWithStructureOrOther: {
100
        Jump ok = branchIfOther(regs, tempGPR);
101
        result.append(branchIfNotCell(regs));
102
        result.append(branchStructure(regs.payloadGPR(), descriptor.structure()));
103
        ok.link(this);
104
        break;
105
    }
106
107
    case InferredType::Object:
108
        result.append(branchIfNotCell(regs));
109
        result.append(branchIfNotObject(regs.payloadGPR()));
110
        break;
111
112
    case InferredType::ObjectOrOther: {
113
        Jump ok = branchIfOther(regs, tempGPR);
114
        result.append(branchIfNotCell(regs));
115
        result.append(branchIfNotObject(regs.payloadGPR()));
116
        ok.link(this);
117
        break;
118
    }
119
120
    case InferredType::Top:
121
        break;
122
    }
123
124
    return result;
125
}
126
58
void AssemblyHelpers::purifyNaN(FPRReg fpr)
127
void AssemblyHelpers::purifyNaN(FPRReg fpr)
59
{
128
{
60
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
129
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
- Source/JavaScriptCore/jit/AssemblyHelpers.h +12 lines
Lines 563-568 public: Source/JavaScriptCore/jit/AssemblyHelpers.h_sec1
563
        return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::EmptyValueTag));
563
        return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::EmptyValueTag));
564
#endif
564
#endif
565
    }
565
    }
566
567
    JumpList branchIfNotType(JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor&);
568
569
    template<typename T>
570
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
571
    {
572
#if USE(JSVALUE64)
573
        return branch32(condition, leftHandSide, TrustedImm32(structure->id()));
574
#else
575
        return branchPtr(condition, leftHandSide, TrustedImmPtr(structure));
576
#endif
577
    }
566
    
578
    
567
    template<typename T>
579
    template<typename T>
568
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
580
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
- Source/JavaScriptCore/runtime/InferredType.cpp +443 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::Descriptor InferredType::Descriptor::forValue(JSValue value)
62
{
63
    if (value.isBoolean())
64
        return Boolean;
65
    if (value.isUndefinedOrNull())
66
        return Other;
67
    if (value.isInt32())
68
        return Int32;
69
    if (value.isDouble())
70
        return Double;
71
    if (value.isCell()) {
72
        JSCell* cell = value.asCell();
73
        if (cell->isString())
74
            return String;
75
        if (cell->isObject()) {
76
            if (cell->structure()->transitionWatchpointSetIsStillValid())
77
                return Descriptor(ObjectWithStructure, cell->structure());
78
            return Object;
79
        }
80
    }
81
    return Top;
82
}
83
84
void InferredType::Descriptor::merge(const Descriptor& other)
85
{
86
    if (*this == other)
87
        return;
88
    
89
    switch (m_kind) {
90
    case Bottom:
91
        *this = other;
92
        return;
93
    case Boolean:
94
    case String:
95
        *this = Top;
96
        return;
97
    case Other:
98
        switch (other.m_kind) {
99
        case ObjectWithStructure:
100
            m_kind = ObjectWithStructureOrOther;
101
            return;
102
        case Object:
103
            m_kind = ObjectOrOther;
104
            return;
105
        default:
106
            *this = Top;
107
            return;
108
        }
109
    case Int32:
110
        switch (other.m_kind) {
111
        case Double:
112
        case Number:
113
            m_kind = Number;
114
            return;
115
        default:
116
            *this = Top;
117
            return;
118
        }
119
    case Double:
120
        switch (other.m_kind) {
121
        case Int32:
122
        case Number:
123
            m_kind = Number;
124
            return;
125
        default:
126
            *this = Top;
127
            return;
128
        }
129
    case Number:
130
        switch (other.m_kind) {
131
        case Int32:
132
        case Double:
133
            return;
134
        default:
135
            *this = Top;
136
            return;
137
        }
138
    case ObjectWithStructure:
139
        switch (other.m_kind) {
140
        case ObjectWithStructure:
141
        case Object:
142
            *this = Object;
143
            return;
144
        case ObjectWithStructureOrOther:
145
            if (m_structure == other.m_structure) {
146
                *this = other;
147
                return;
148
            }
149
            *this = ObjectOrOther;
150
            return;
151
        case ObjectOrOther:
152
            *this = ObjectOrOther;
153
            return;
154
        case Other:
155
            m_kind = ObjectWithStructureOrOther;
156
            return;
157
        default:
158
            *this = Top;
159
            return;
160
        }
161
    case ObjectWithStructureOrOther:
162
        switch (other.m_kind) {
163
        case ObjectWithStructure:
164
            if (m_structure == other.m_structure)
165
                return;
166
            *this = ObjectOrOther;
167
            return;
168
        case Object:
169
        case ObjectWithStructureOrOther:
170
        case ObjectOrOther:
171
            *this = ObjectOrOther;
172
            return;
173
        case Other:
174
            return;
175
        default:
176
            *this = Top;
177
            return;
178
        }
179
    case Object:
180
        switch (other.m_kind) {
181
        case ObjectWithStructure:
182
            return;
183
        case ObjectWithStructureOrOther:
184
        case ObjectOrOther:
185
        case Other:
186
            m_kind = ObjectOrOther;
187
            return;
188
        default:
189
            *this = Top;
190
            return;
191
        }
192
    case ObjectOrOther:
193
        switch (other.m_kind) {
194
        case ObjectWithStructure:
195
        case ObjectWithStructureOrOther:
196
        case Object:
197
        case Other:
198
            return;
199
        default:
200
            *this = Top;
201
            return;
202
        }
203
    case Top:
204
        return;
205
    }
206
207
    RELEASE_ASSERT_NOT_REACHED();
208
}
209
210
void InferredType::Descriptor::removeStructure()
211
{
212
    switch (m_kind) {
213
    case ObjectWithStructure:
214
        *this = Object;
215
        return;
216
    case ObjectWithStructureOrOther:
217
        *this = ObjectOrOther;
218
        return;
219
    default:
220
        return;
221
    }
222
}
223
224
bool InferredType::Descriptor::subsumes(const Descriptor& other) const
225
{
226
    Descriptor merged = *this;
227
    merged.merge(other);
228
    return *this == merged;
229
}
230
231
void InferredType::Descriptor::dumpInContext(PrintStream& out, DumpContext* context) const
232
{
233
    out.print(m_kind);
234
    if (m_structure)
235
        out.print(":", inContext(*m_structure, context));
236
}
237
238
void InferredType::Descriptor::dump(PrintStream& out) const
239
{
240
    dumpInContext(out, nullptr);
241
}
242
243
InferredType::InferredType(VM& vm)
244
    : Base(vm, vm.inferredTypeStructure.get())
245
    , m_watchpointSet(ClearWatchpoint)
246
{
247
}
248
249
InferredType::~InferredType()
250
{
251
}
252
253
bool InferredType::isStillValid(const ConcurrentJITLocker& locker, const Descriptor& expected)
254
{
255
    if (expected.kind() == Top)
256
        return false;
257
    
258
    return descriptor(locker) == expected;
259
}
260
261
bool InferredType::isStillValid(const Descriptor& expected)
262
{
263
    ConcurrentJITLocker locker(m_lock);
264
    return isStillValid(locker, expected);
265
}
266
267
void InferredType::addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint* watchpoint)
268
{
269
    RELEASE_ASSERT(descriptor(locker).kind() != Top);
270
271
    m_watchpointSet.add(watchpoint);
272
}
273
274
void InferredType::addWatchpoint(Watchpoint* watchpoint)
275
{
276
    ConcurrentJITLocker locker(m_lock);
277
    addWatchpoint(locker, watchpoint);
278
}
279
280
void InferredType::dump(PrintStream& out) const
281
{
282
    out.print(RawPointer(this), ":", descriptor());
283
}
284
285
void InferredType::willStoreValueSlow(VM& vm, JSValue value)
286
{
287
    ConcurrentJITLocker locker(m_lock);
288
    Descriptor myType = descriptor(locker);
289
    Descriptor otherType = Descriptor::forValue(value);
290
291
    myType.merge(otherType);
292
293
    ASSERT(descriptor(locker) != myType); // The type must have changed if we're on the slow path.
294
295
    set(locker, vm, myType);
296
}
297
298
void InferredType::makeTopSlow(VM& vm)
299
{
300
    ConcurrentJITLocker locker(m_lock);
301
    set(locker, vm, Top);
302
}
303
304
void InferredType::set(const ConcurrentJITLocker& locker, VM& vm, Descriptor newDescriptor)
305
{
306
    // We will trigger write barriers while holding our lock. Currently, write barriers don't GC, but that
307
    // could change. If it does, we don't want to deadlock. Note that we could have used
308
    // GCSafeConcurrentJITLocker in the caller, but the caller is on a fast path so maybe that wouldn't be
309
    // a good idea.
310
    DeferGCForAWhile deferGC(vm.heap);
311
    
312
    // Be defensive: if we're not really changing the type, then we don't have to do anything.
313
    if (descriptor(locker) == newDescriptor)
314
        return;
315
316
    // The new descriptor must be more general than the previous one.
317
    ASSERT(newDescriptor.subsumes(descriptor(locker)));
318
319
    // If the new descriptors have different structures, then it can only be because one is null.
320
    if (descriptor(locker).structure() != newDescriptor.structure())
321
        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());
322
323
    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
324
    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
325
    if (m_watchpointSet.state() != ClearWatchpoint) {
326
        // We cannot have been invalidated, since if we were, then we'd already be at Top.
327
        ASSERT(m_watchpointSet.state() != IsInvalidated);
328
329
        // We're about to do expensive things because some compiler thread decided to watch this type and
330
        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
331
        // it.
332
        newDescriptor = Top;
333
334
        m_watchpointSet.fireAll("Inferred type changed");
335
    }
336
337
    // Remove the old InferredStructure object if we no longer need it.
338
    if (!newDescriptor.structure())
339
        m_structure = nullptr;
340
341
    // Add a new InferredStructure object if we need one now.
342
    if (newDescriptor.structure()) {
343
        if (m_structure) {
344
            // We should agree on the structures if we get here.
345
            ASSERT(newDescriptor.structure() == m_structure->structure());
346
        } else {
347
            m_structure = std::make_unique<InferredStructure>(this, newDescriptor.structure());
348
            newDescriptor.structure()->addTransitionWatchpoint(m_structure.get());
349
        }
350
    }
351
352
    // Finally, set the descriptor kind.
353
    m_kind = newDescriptor.kind();
354
355
    // Assert that we did things.
356
    ASSERT(descriptor(locker) == newDescriptor);
357
}
358
359
void InferredType::removeStructure()
360
{
361
    VM& vm = *Heap::heap(this)->vm();
362
363
    ConcurrentJITLocker locker(m_parent->m_lock);
364
    
365
    Descriptor newDescriptor = descriptor(locker);
366
    newDescriptor.removeStructure();
367
    
368
    set(locker, vm, newDescriptor);
369
}
370
371
void InferredType::InferredStructure::InferredStructure(InferredType* parent, Structure* structure)
372
    : m_parent(parent)
373
    , m_structure(vm, parent, structure)
374
{
375
}
376
377
void InferredType::InferredStructure::fireInternal(const FireDetail&)
378
{
379
    m_parent->removeStructure();
380
}
381
382
void InferredType::InferredStructure::finalizeUnconditionally()
383
{
384
    VM& vm = *Heap::heap(m_parent)->vm();
385
386
    ASSERT(Heap::isMarked(m_parent));
387
    
388
    if (!Heap::isMarked(m_structure.get()))
389
        m_parent->removeStructure();
390
}
391
392
} // namespace JSC
393
394
namespace WTF {
395
396
using namespace JSC;
397
398
void printInternal(PrintStream& out, InferredType::Kind kind)
399
{
400
    switch (kind) {
401
    case InferredType::Bottom:
402
        out.print("Bottom");
403
        return;
404
    case InferredType::Boolean:
405
        out.print("Boolean");
406
        return;
407
    case InferredType::Other:
408
        out.print("Other");
409
        return;
410
    case InferredType::Int32:
411
        out.print("Int32");
412
        return;
413
    case InferredType::Double:
414
        out.print("Double");
415
        return;
416
    case InferredType::Number:
417
        out.print("Number");
418
        return;
419
    case InferredType::String:
420
        out.print("String");
421
        return;
422
    case InferredType::ObjectWithStructure:
423
        out.print("ObjectWithStructure");
424
        return;
425
    case InferredType::ObjectWithStructureOrOther:
426
        out.print("ObjectWithStructureOrOther");
427
        return;
428
    case InferredType::Object:
429
        out.print("Object");
430
        return;
431
    case InferredType::ObjectOrOther:
432
        out.print("ObjectOrOther");
433
        return;
434
    case InferredType::Top:
435
        out.print("Top");
436
        return;
437
    }
438
439
    RELEASE_ASSERT_NOT_REACHED();
440
}
441
442
} // namespace WTF
443
- Source/JavaScriptCore/runtime/InferredType.h +248 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
32
namespace JSC {
33
34
// This is an object used for the inference of the types of object properties.
35
36
class InferredType final : public JSCell {
37
public:
38
    typedef JSCell Base;
39
40
    static InferredType* create(VM&);
41
42
    static const bool needsDestruction = true;
43
    static void destroy(JSCell*);
44
45
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
46
47
    static void visitChildren(JSCell*, SlotVisitor&);
48
49
    DECLARE_INFO;
50
51
    enum Kind : uint8_t {
52
        Bottom,
53
        Boolean,
54
        Other,
55
        Int32,
56
        Double,
57
        Number,
58
        String,
59
        ObjectWithStructure,
60
        ObjectWithStructureOrOther,
61
        Object,
62
        ObjectOrOther,
63
        Top
64
    };
65
66
    class Descriptor {
67
    public:
68
        Descriptor()
69
            : m_kind(Bottom)
70
            , m_structure(nullptr)
71
        {
72
        }
73
74
        Descriptor(Kind kind, Structure* structure = nullptr)
75
            : m_kind(kind)
76
            , m_structure(structure)
77
        {
78
        }
79
80
        static Descriptor forValue(JSValue);
81
82
        explicit operator bool() const
83
        {
84
            return m_kind == Bottom && !m_structure;
85
        }
86
87
        Kind kind() const { return m_kind; }
88
        Structure* structure() const { return m_structure; }
89
90
        ALWAYS_INLINE bool includesValue(JSValue value)
91
        {
92
            switch (m_kind) {
93
            case Bottom:
94
                return false;
95
            case Boolean:
96
                return value.isBoolean();
97
            case Other:
98
                return value.isUndefinedOrNull();
99
            case Int32:
100
                return value.isInt32();
101
            case Double:
102
                return value.isDouble();
103
            case Number:
104
                return value.isNumber();
105
            case String:
106
                return value.isString();
107
            case ObjectWithStructure:
108
                return value.isCell() && value.asCell()->structure() == m_structure;
109
            case ObjectWithStructureOrOther:
110
                return value.isUndefinedOrNull()
111
                    || (value.isCell() && value.asCell()->structure() == m_structure);
112
            case Object:
113
                return value.isObject();
114
            case ObjectOrOther:
115
                return value.isUndefinedOrNull() || value.isObject();
116
            case Top:
117
                return true;
118
            }
119
120
            RELEASE_ASSERT_NOT_REACHED();
121
        }
122
123
        bool operator==(const Descriptor& other)
124
        {
125
            return m_kind == other.m_kind
126
                && m_structure == other.m_structure;
127
        }
128
129
        bool operator!=(const Descriptor& other)
130
        {
131
            return !(*this == other);
132
        }
133
134
        unsigned hash() const
135
        {
136
            return WTF::PtrHash<Structure*>::hash(m_structure) ^ static_cast<unsigned>(m_kind);
137
        }
138
    
139
        void merge(const Descriptor&);
140
        void removeStructure();
141
142
        // Returns true if this descriptor is more general than the other one.
143
        bool subsumes(const Descriptor&) const;
144
145
        void dumpInContext(PrintStream&, DumpContext*) const;
146
        void dump(PrintStream&) const;
147
148
    private:
149
        Kind m_kind;
150
        Structure* m_structure;
151
    };
152
153
    ConcurrentJITLock& lock() const { return m_lock; }
154
155
    Descriptor descriptorMainThread() const
156
    {
157
        return Descriptor(m_kind, m_structure ? m_structure->structure() : nullptr);
158
    }
159
    
160
    Descriptor descriptor(const ConcurrentJITLocker&) const
161
    {
162
        return descriptorMainThread();
163
    }
164
    Descriptor descriptor() const
165
    {
166
        ConcurrentJITLocker locker(m_lock);
167
        return descriptor(locker);
168
    }
169
    
170
    Kind kind(const ConcurrentJITLocker& locker) const { return descriptor().kind(); }
171
    Structure* structure(const ConcurrentJITLocker& locker) const { return descriptor().structure(); }
172
173
    bool isTop() const { return m_kind == Top; }
174
    bool isRelevant() const { return m_kind != Top; }
175
176
    // Returns true if the InferredType is still relevant after the store. It's not relevant if it's Top.
177
    ALWAYS_INLINE bool willStoreValue(VM& vm, JSValue value)
178
    {
179
        Descriptor currentDescriptor = descriptorMainThread();
180
        if (currentDescriptor.includesValue(value))
181
            return currentDescriptor.kind() != Top;
182
        return willStoreValueSlow(vm, value);
183
    }
184
185
    // Immediately makes this type irrelevant.
186
    void makeTop(VM& vm)
187
    {
188
        if (isTop())
189
            return;
190
        makeTopSlow(vm);
191
    }
192
193
    // Returns true if it currently makes sense to watch this InferredType for this descriptor. Note that
194
    // this will always return false for Top.
195
    bool canWatch(const ConcurrentJITLocker& locker, const Descriptor&);
196
    bool canWatch(const Descriptor&);
197
    
198
    void addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint*);
199
    void addWatchpoint(Watchpoint*);
200
201
    void dump(PrintStream&) const;
202
203
private:
204
    InferredType(VM&);
205
    ~InferredType();
206
207
    void willStoreValueSlow(VM&, JSValue);
208
    void makeTopSlow(VM&);
209
    void set(const ConcurrentJITLocker&, VM&, Descriptor);
210
    void removeStructure();
211
212
    mutable ConcurrentJITLock m_lock;
213
    
214
    Kind m_kind { Bottom };
215
216
    class InferredStructure : public Watchpoint, public UnconditionalFinalizer {
217
    public:
218
        InferredStructure(InferredType* parent, Structure*);
219
220
        Structure* structure() const { return m_structure.get(); };
221
222
    protected:
223
        void fireInternal(const FireDetail&) override;
224
        void finalizeUnconditionally() override;
225
226
    private:
227
        InferredType* m_parent;
228
        WriteBarrier<Structure> m_structure;
229
    };
230
231
    std::unique_ptr<InferredStructure> m_structure;
232
233
    // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
234
    // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
235
    // thread. The DFG will use the InferredType as the thing that it watches.
236
    InlineWatchpointSet m_watchpointSet;
237
};
238
239
} // namespace JSC
240
241
namespace WTF {
242
243
void printInternal(PrintStream&, JSC::InferredType::Kind);
244
245
} // namespace WTF
246
247
#endif // InferredType_h
248
- Source/JavaScriptCore/runtime/InferredTypeTable.cpp +156 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
void InferredTypeTable::makeTopForTransition(VM& vm, PropertyName propertyName)
152
{
153
}
154
155
} // namespace JSC
156
- 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 347-357 void Structure::materializePropertyMap(V Source/JavaScriptCore/runtime/Structure.cpp_sec1
347
    else
347
    else
348
        propertyTable().set(vm, this, table);
348
        propertyTable().set(vm, this, table);
349
349
350
    InferredTypeTable* typeTable = m_inferredTypeTable.get();
351
350
    for (size_t i = structures.size(); i--;) {
352
    for (size_t i = structures.size(); i--;) {
351
        structure = structures[i];
353
        structure = structures[i];
352
        if (!structure->m_nameInPrevious)
354
        if (!structure->m_nameInPrevious)
353
            continue;
355
            continue;
354
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
356
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
357
        if (typeTable && typeTable->get(structure->m_nameInPrevious.get()))
358
            entry.hasInferredType = true;
355
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
359
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
356
    }
360
    }
357
    
361
    
Lines 461-466 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec2
461
    transition->setAttributesInPrevious(attributes);
465
    transition->setAttributesInPrevious(attributes);
462
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
466
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
463
    transition->m_offset = structure->m_offset;
467
    transition->m_offset = structure->m_offset;
468
    transition->m_inferredTypeTable.setMayBeNull(vm, transition, structure->m_inferredTypeTable.get());
464
469
465
    offset = transition->add(vm, propertyName, attributes);
470
    offset = transition->add(vm, propertyName, attributes);
466
471
Lines 476-481 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec3
476
481
477
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
482
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
478
{
483
{
484
    // NOTE: There are some good reasons why this goes directly to uncacheable dictionary rather than
485
    // caching the removal. We can fix all of these things, but we must remember to do so, if we ever try
486
    // to optimize this case.
487
    //
488
    // - Cached transitions usually steal the property table, and assume that this is possible because they
489
    //   can just rebuild the table by looking at past transitions. That code assumes that the table only
490
    //   grew and never shrank. To support removals, we'd have to change the property table materialization
491
    //   code to handle deletions. Also, we have logic to get the list of properties on a structure that
492
    //   lacks a property table by just looking back through the set of transitions since the last
493
    //   structure that had a pinned table. That logic would also have to be changed to handle cached
494
    //   removals.
495
    //
496
    // - InferredTypeTable assumes that removal has never happened. This is important since if we could
497
    //   remove a property and then re-add it later, then the "absence means top" optimization wouldn't
498
    //   work anymore, unless removal also either poisoned type inference (by doing something equivalent to
499
    //   hasBeenDictionary) or by strongly marking the entry as Top by ensuring that it is not absent, but
500
    //   instead, has a null entry.
501
    
479
    ASSERT(!structure->isUncacheableDictionary());
502
    ASSERT(!structure->isUncacheableDictionary());
480
503
481
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
504
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
Lines 838-843 void Structure::startWatchingInternalPro Source/JavaScriptCore/runtime/Structure.cpp_sec4
838
    setDidWatchInternalProperties(true);
861
    setDidWatchInternalProperties(true);
839
}
862
}
840
863
864
void Structure::willStoreValueSlow(
865
    VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize,
866
    InferredTypeTable::StoredPropertyAge age)
867
{
868
    ASSERT(!isCompilationThread());
869
    ASSERT(structure()->classInfo() == info());
870
    ASSERT(!hadBeenDictionary());
871
872
    // Create the inferred type table before doing anything else, so that we don't GC after we have already
873
    // grabbed a pointer into the property map.
874
    InferredTypeTable* table = m_inferredTypeTable.get();
875
    if (!table) {
876
        table = InferredTypeTable::create(vm);
877
        WTF::storeStoreBarrier();
878
        m_inferredTypeTable.set(vm, this, table);
879
    }
880
881
    // This only works if we've got a property table.
882
    PropertyTable* propertyTable;
883
    materializePropertyMapIfNecessary(vm, propertyTable);
884
885
    // We must be calling this after having created the given property or confirmed that it was present
886
    // already, so we must have a property table now.
887
    ASSERT(propertyTable);
888
889
    // ... and the property must be present.
890
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
891
    ASSERT(entry);
892
893
    if (shouldOptimize)
894
        entry->hasInferredType = table->willStoreValue(vm, propertyName, value, age);
895
    else {
896
        table->makeTop(vm, propertyName, age);
897
        entry->hasInferredType = false;
898
    }
899
}
900
841
#if DUMP_PROPERTYMAP_STATS
901
#if DUMP_PROPERTYMAP_STATS
842
902
843
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
903
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
Lines 1055-1060 void Structure::visitChildren(JSCell* ce Source/JavaScriptCore/runtime/Structure.cpp_sec5
1055
        visitor.append(&thisObject->m_propertyTableUnsafe);
1115
        visitor.append(&thisObject->m_propertyTableUnsafe);
1056
    } else if (thisObject->m_propertyTableUnsafe)
1116
    } else if (thisObject->m_propertyTableUnsafe)
1057
        thisObject->m_propertyTableUnsafe.clear();
1117
        thisObject->m_propertyTableUnsafe.clear();
1118
1119
    visitor.append(&thisObject->m_inferredTypeTable);
1058
}
1120
}
1059
1121
1060
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
1122
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
- Source/JavaScriptCore/runtime/Structure.h +38 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 477-482 public: Source/JavaScriptCore/runtime/Structure.h_sec5
477
            structure->startWatchingInternalPropertiesIfNecessary(vm);
482
            structure->startWatchingInternalPropertiesIfNecessary(vm);
478
    }
483
    }
479
484
485
    bool hasInferredTypes() const
486
    {
487
        return !!m_inferredTypeTable;
488
    }
489
490
    InferredType* inferredTypeFor(UniquedStringImpl* uid)
491
    {
492
        if (InferredTypeTable* table = m_inferredTypeTable.get())
493
            return table->get(uid);
494
        return nullptr;
495
    }
496
497
    // Returns true if the type of the property is still valid.
498
    ALWAYS_INLINE void willStoreValueForTransition(
499
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
500
    {
501
        if (hasBeenDictionary() || (!shouldOptimize && !m_inferredTypeTable))
502
            return;
503
        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::NewProperty);
504
    }
505
    ALWAYS_INLINE void willStoreValueForReplace(
506
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
507
    {
508
        if (hasBeenDictionary())
509
            return;
510
        willSloreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::OldProperty);
511
    }
512
480
    PassRefPtr<StructureShape> toStructureShape(JSValue);
513
    PassRefPtr<StructureShape> toStructureShape(JSValue);
481
    
514
    
482
    // Determines if the two structures match enough that this one could be used for allocations
515
    // Determines if the two structures match enough that this one could be used for allocations
Lines 627-632 private: Source/JavaScriptCore/runtime/Structure.h_sec6
627
    
660
    
628
    void startWatchingInternalProperties(VM&);
661
    void startWatchingInternalProperties(VM&);
629
662
663
    void willStoreValueSlow(
664
        VM&, PropertyOffset, PropertyName, JSValue, bool, InferredTypeTable::StoredPropertyAge);
665
630
    static const int s_maxTransitionLength = 64;
666
    static const int s_maxTransitionLength = 64;
631
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
667
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
632
668
Lines 650-655 private: Source/JavaScriptCore/runtime/Structure.h_sec7
650
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
686
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
651
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
687
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
652
688
689
    WriteBarrier<InferredTypeTable> m_inferredTypeTable;
690
653
    mutable InlineWatchpointSet m_transitionWatchpointSet;
691
    mutable InlineWatchpointSet m_transitionWatchpointSet;
654
692
655
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
693
    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