| 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 754-759 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
754
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
756
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
755
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
757
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
756
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
758
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
759
		0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */; };
760
		0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
761
		0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */; };
762
		0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
757
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
763
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
758
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
764
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
759
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
765
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 1907-1912 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
1907
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1913
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1908
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1914
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1909
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1915
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1916
		0F0A75201B94BFA900110660 /* InferredType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredType.cpp; sourceTree = "<group>"; };
1917
		0F0A75211B94BFA900110660 /* InferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredType.h; sourceTree = "<group>"; };
1910
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1918
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1911
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1919
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1912
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
1920
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
Lines 2572-2577 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
2572
		0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
2580
		0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
2573
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2581
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2574
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2582
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2583
		0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredTypeTable.cpp; sourceTree = "<group>"; };
2584
		0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredTypeTable.h; sourceTree = "<group>"; };
2585
		0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredInferredType.h; path = dfg/DFGDesiredInferredType.h; sourceTree = "<group>"; };
2586
		0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropertyTypeKey.h; path = dfg/DFGPropertyTypeKey.h; sourceTree = "<group>"; };
2575
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2587
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2576
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2588
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2577
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
2589
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
Lines 4628-4635 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
4628
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4640
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4629
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4641
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4630
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4642
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4631
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4632
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4643
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4644
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4633
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4645
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4634
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4646
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4635
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
4647
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
Lines 4662-4667 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
4662
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4674
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4663
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4675
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4664
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4676
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4677
				0F0A75201B94BFA900110660 /* InferredType.cpp */,
4678
				0F0A75211B94BFA900110660 /* InferredType.h */,
4679
				0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */,
4680
				0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */,
4665
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4681
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4666
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4682
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4667
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
4683
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
Lines 4712-4721 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
4712
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4728
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4713
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4729
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4714
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4730
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4715
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4716
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4717
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4731
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4718
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4732
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4733
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4734
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4719
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4735
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4720
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4736
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4721
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
4737
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
Lines 5013-5021 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
5013
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5029
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5014
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5030
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5015
				E18E3A560DF9278C00D90B34 /* VM.h */,
5031
				E18E3A560DF9278C00D90B34 /* VM.h */,
5016
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5017
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5032
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5018
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5033
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5034
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5019
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5035
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5020
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5036
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5021
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
5037
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
Lines 5167-5172 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
5167
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5183
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5168
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5184
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5169
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5185
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5186
				0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */,
5170
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5187
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5171
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5188
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5172
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
5189
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
Lines 5312-5317 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec10
5312
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5329
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5313
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5330
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5314
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5331
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5332
				0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */,
5315
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5333
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5316
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5334
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5317
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
5335
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
Lines 5895-5900 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec11
5895
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5913
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5896
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5914
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5897
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5915
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5916
				0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
5898
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5917
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5899
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5918
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5900
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
5919
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
Lines 6008-6013 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec12
6008
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6027
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6009
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6028
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6010
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6029
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6030
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
6011
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6031
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6012
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6032
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6013
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
6033
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
Lines 6292-6297 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec13
6292
				0F235BE417178E1C00690C7F /* FTLValueFormat.h in Headers */,
6312
				0F235BE417178E1C00690C7F /* FTLValueFormat.h in Headers */,
6293
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6313
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6294
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6314
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6315
				0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */,
6295
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6316
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6296
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6317
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6297
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
6318
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
Lines 6457-6462 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec14
6457
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6478
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6458
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6479
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6459
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6480
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6481
				0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
6460
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6482
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6461
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6483
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6462
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
6484
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
Lines 7397-7402 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec15
7397
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7419
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7398
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7420
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7399
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7421
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7422
				0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
7400
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7423
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7401
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7424
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7402
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
7425
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
Lines 7811-7816 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec16
7811
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7834
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7812
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7835
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7813
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7836
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7837
				0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
7814
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7838
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7815
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7839
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7816
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
7840
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
- Source/JavaScriptCore/bytecode/Watchpoint.h -1 / +33 lines
Lines 335-341 public: Source/JavaScriptCore/bytecode/Watchpoint.h_sec1
335
    {
335
    {
336
        touch(StringFireDetail(reason));
336
        touch(StringFireDetail(reason));
337
    }
337
    }
338
    
338
339
    // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like:
340
    //
341
    // if (w.isBeingWatched())
342
    //     w.fireAll()
343
    //
344
    // Concurrently to this, the DFG could do:
345
    //
346
    // if (w.isStillValid())
347
    //     perform optimizations;
348
    // if (!w.isStillValid())
349
    //     retry compilation;
350
    //
351
    // Note that the DFG algorithm is widespread, and sound, because fireAll() and invalidate() will leave
352
    // the watchpoint in a !isStillValid() state. Hence, if fireAll() or invalidate() interleaved between
353
    // the first isStillValid() check and the second one, then it would simply cause the DFG to retry
354
    // compilation later.
355
    //
356
    // But, if you change some piece of state that the DFG might optimize for, but invalidate the
357
    // watchpoint by doing:
358
    //
359
    // if (w.isBeingWatched())
360
    //     w.fireAll()
361
    //
362
    // then the DFG would never know that you invalidated state between the two checks.
363
    //
364
    // There are two ways to work around this:
365
    //
366
    // - Call fireAll() without a isBeingWatched() check. Then, the DFG will know that the watchpoint has
367
    //   been invalidated when it does its second check.
368
    //
369
    // - Do not expose the watchpoint set to the DFG directly, and have your own way of validating whether
370
    //   the assumptions that the DFG thread used are still valid when the DFG code is installed.
339
    bool isBeingWatched() const
371
    bool isBeingWatched() const
340
    {
372
    {
341
        if (isFat())
373
        if (isFat())
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h -34 / +42 lines
Lines 1823-1829 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec1
1823
        }
1823
        }
1824
        
1824
        
1825
        AbstractValue& value = forNode(node->child1());
1825
        AbstractValue& value = forNode(node->child1());
1826
        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
1826
        if (value.m_structure.isFinite()
1827
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1827
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1828
            GetByIdStatus status = GetByIdStatus::computeFor(
1828
            GetByIdStatus status = GetByIdStatus::computeFor(
1829
                value.m_structure.set(), m_graph.identifiers()[node->identifierNumber()]);
1829
                value.m_structure.set(), m_graph.identifiers()[node->identifierNumber()]);
Lines 1835-1856 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec2
1835
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1835
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1836
                    // have more work to do here.
1836
                    // have more work to do here.
1837
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1837
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1838
                    
1838
1839
                    JSValue constantResult =
1839
                    result.merge(
1840
                        m_graph.tryGetConstantProperty(value, status[i].offset());
1840
                        m_graph.inferredValueForProperty(
1841
                    if (!constantResult) {
1841
                            value, status[i].offset(), m_graph.structureClobberState()));
1842
                        result.makeHeapTop();
1843
                        break;
1844
                    }
1845
                    
1846
                    AbstractValue thisResult;
1847
                    thisResult.set(
1848
                        m_graph, *m_graph.freeze(constantResult),
1849
                        m_state.structureClobberState());
1850
                    result.merge(thisResult);
1851
                }
1842
                }
1852
                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1843
                m_state.setFoundConstants(true);
1853
                    m_state.setFoundConstants(true);
1854
                forNode(node) = result;
1844
                forNode(node) = result;
1855
                break;
1845
                break;
1856
            }
1846
            }
Lines 2078-2090 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec3
2078
        
2068
        
2079
    case GetByOffset: {
2069
    case GetByOffset: {
2080
        StorageAccessData& data = node->storageAccessData();
2070
        StorageAccessData& data = node->storageAccessData();
2081
        JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2071
2082
        if (result) {
2072
        // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2083
            setConstant(node, *m_graph.freeze(result));
2073
        // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2084
            break;
2074
        // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2085
        }
2075
        // at the point where GetByOffset runs. Currently, when that happens, we'll forget what the proven
2086
        
2076
        // type should have been, even though we would have known it at parse time. It might be worthwhile
2087
        forNode(node).makeHeapTop();
2077
        // to put an inferred type into the StorageAccessData. Note that this might become particularly
2078
        // unfortunate due to https://bugs.webkit.org/show_bug.cgi?id=148649.
2079
        AbstractValue value = m_graph.inferredValueForProperty(
2080
            forNode(node->child2()), data.offset, m_state.structureClobberState());
2081
2082
        forNode(node) = value;
2083
        if (value.m_value)
2084
            m_state.setFoundConstants(true);
2088
        break;
2085
        break;
2089
    }
2086
    }
2090
        
2087
        
Lines 2123-2140 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec4
2123
            if (set.isEmpty())
2120
            if (set.isEmpty())
2124
                continue;
2121
                continue;
2125
            baseSet.merge(set);
2122
            baseSet.merge(set);
2126
            
2123
2127
            if (getCase.method().kind() != GetByOffsetMethod::Constant) {
2124
            switch (getCase.method().kind()) {
2128
                result.makeHeapTop();
2125
            case GetByOffsetMethod::Constant: {
2129
                continue;
2126
                AbstractValue thisResult;
2127
                thisResult.set(
2128
                    m_graph,
2129
                    *getCase.method().constant(),
2130
                    m_state.structureClobberState());
2131
                result.merge(thisResult);
2132
                break;
2130
            }
2133
            }
2131
            
2134
2132
            AbstractValue thisResult;
2135
            case GetByOffetMethod::Load: {
2133
            thisResult.set(
2136
                result.merge(
2134
                m_graph,
2137
                    m_graph.inferredValueForProperty(
2135
                *getCase.method().constant(),
2138
                        set, getCase.method().offset(), m_graph.structureClobberState()));
2136
                m_state.structureClobberState());
2139
                break;
2137
            result.merge(thisResult);
2140
            }
2141
2142
            default: {
2143
                result.makeHeapTop();
2144
                break;
2145
            } }
2138
        }
2146
        }
2139
        
2147
        
2140
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2148
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
- Source/JavaScriptCore/dfg/DFGAbstractValue.cpp +53 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) {
- Source/JavaScriptCore/dfg/DFGAbstractValue.h -1 / +5 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
    
- 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 / +73 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()->inferredTypeForOffset(key.offset());
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, PropertyOffset offset, StructureClobberState clobberState)
1125
{
1126
    AbstractValue result;
1127
    base.forEach(
1128
        [&] (Structure* structure) {
1129
            AbstractValue value;
1130
            value.set(*this, inferredTypeFor(structure, offset));
1131
            result.merge(value);
1132
        });
1133
    return result;
1134
}
1135
1136
AbstractValue Graph::inferredValueForProperty(
1137
    const AbstractValue& base, PropertyOffset offset, StructureClobberState clobberState)
1138
{
1139
    if (JSValue value = tryGetConstantProperty(base, offset)) {
1140
        AbstractValue result;
1141
        result.set(*this, *freeze(value), clobberState);
1142
        return result;
1143
    }
1144
1145
    if (base.m_structure.isFinite())
1146
        return inferredValueForProperty(base.m_structure.set(), offset, clobberState);
1147
1148
    return AbstractValue::heapTop();
1149
}
1150
1079
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1151
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1080
{
1152
{
1081
    // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
1153
    // 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 inferredValueForProperty(Structure* structure, PropertyOffset offset)
682
    {
683
        return inferredTypeFor(PropertyTypeKey(structure, offset));
684
    }
685
686
    AbstractValue inferredValueForProperty(
687
        const StructureSet& base, PropertyOffset, 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, 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/DFGPropertyTypeKey.h +123 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 PropertyOffset.
36
37
class PropertyTypeKey {
38
public:
39
    PropertyTypeKey()
40
        : m_structure(nullptr)
41
        , m_offset(invalidOffset)
42
    {
43
    }
44
45
    PropertyTypeKey(Structure* structure, PropertyOffset offset)
46
        : m_structure(structure)
47
        , m_offset(offset)
48
    {
49
    }
50
51
    PropertyTypeKey(WTF::HashTableDeletedValueType)
52
        : m_object(nullptr)
53
        , m_offset(invalidOffset - 1)
54
    {
55
    }
56
57
    explicit operator bool() const { return m_structure && m_offset != invalidOffset; }
58
59
    Structure* structure() const { return m_structure; }
60
    PropertyOffset offset() const { return m_offset; }
61
62
    bool operator==(const PropertyTypeKey& other) const
63
    {
64
        return m_structure == other.m_structure
65
            && m_offset == other.m_offset;
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) + m_offset;
76
    }
77
78
    bool isHashTableDeletedValue() const
79
    {
80
        return !m_object && m_offset == invalidOffset - 1;
81
    }
82
83
    void dumpInContext(PrintStream& out, DumpContext* context) const
84
    {
85
        out.print(pointerDumpInContext(m_structure, context), "+", m_offset);
86
    }
87
88
    void dump(PrintStream& out) const
89
    {
90
        dumpInContext(out, context);
91
    }
92
93
private:
94
    Structure* m_structure;
95
    PropertyOffset m_offset;
96
};
97
98
struct PropertyTypeKeyHash {
99
    static unsigned hash(const PropertyTypeKey& key) { return key.hash(); }
100
    static bool equal(const PropertyTypeKey& a, const PropertyTypeKey& b) { return a == b; }
101
    static const bool safeToCompareToEmptyOrDeleted = true;
102
};
103
104
} } // namespace JSC::DFG
105
106
namespace WTF {
107
108
template<typename T> struct DefaultHash;
109
template<> struct DefaultHash<JSC::DFG::PropertyTypeKey> {
110
    typedef JSC::DFG::PropertyTypeKeyHash Hash;
111
};
112
113
template<typename T> struct HashTraits;
114
template<> struct HashTraits<JSC::DFG::PropertyTypeKey> : SimpleClassHashTraits<JSC::DFG::PropertyTypeKey> {
115
    static const bool emptyValueIsZero = false;
116
};
117
118
} // namespace WTF
119
120
#endif // ENABLE(DFG_JIT)
121
122
#endif // DFGPropertyTypeKey_h
123
- 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/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
    static Address addressForByteOffset(ptrdiff_t byteOffset)
579
    static Address addressForByteOffset(ptrdiff_t byteOffset)
568
    {
580
    {
- Source/JavaScriptCore/jit/JIT.h -2 lines
Lines 404-411 namespace JSC { Source/JavaScriptCore/jit/JIT.h_sec1
404
404
405
        enum FinalObjectMode { MayBeFinal, KnownNotFinal };
405
        enum FinalObjectMode { MayBeFinal, KnownNotFinal };
406
406
407
        template <typename T> Jump branchStructure(RelationalCondition, T leftHandSide, Structure*);
408
409
#if USE(JSVALUE32_64)
407
#if USE(JSVALUE32_64)
410
        bool getOperandConstantImmediateInt(int op1, int op2, int& op, int32_t& constant);
408
        bool getOperandConstantImmediateInt(int op1, int op2, int& op, int32_t& constant);
411
409
- Source/JavaScriptCore/jit/JITInlines.h -20 lines
Lines 1259-1284 ALWAYS_INLINE void JIT::emitTagAsBoolImm Source/JavaScriptCore/jit/JITInlines.h_sec1
1259
1259
1260
#endif // USE(JSVALUE32_64)
1260
#endif // USE(JSVALUE32_64)
1261
1261
1262
template <typename T>
1263
JIT::Jump JIT::branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
1264
{
1265
#if USE(JSVALUE64)
1266
    return branch32(condition, leftHandSide, TrustedImm32(structure->id()));
1267
#else
1268
    return branchPtr(condition, leftHandSide, TrustedImmPtr(structure));
1269
#endif
1270
}
1271
1272
template <typename T>
1273
MacroAssembler::Jump branchStructure(MacroAssembler& jit, MacroAssembler::RelationalCondition condition, T leftHandSide, Structure* structure)
1274
{
1275
#if USE(JSVALUE64)
1276
    return jit.branch32(condition, leftHandSide, MacroAssembler::TrustedImm32(structure->id()));
1277
#else
1278
    return jit.branchPtr(condition, leftHandSide, MacroAssembler::TrustedImmPtr(structure));
1279
#endif
1280
}
1281
1282
} // namespace JSC
1262
} // namespace JSC
1283
1263
1284
#endif // ENABLE(JIT)
1264
#endif // ENABLE(JIT)
- Source/JavaScriptCore/runtime/InferredType.cpp +442 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(const ConcurrentJITLocker& locker, VM& vm, JSValue value)
286
{
287
    Descriptor myType = descriptor(locker);
288
    Descriptor otherType = Descriptor::forValue(value);
289
290
    myType.merge(otherType);
291
292
    ASSERT(descriptor(locker) != myType); // The type must have changed if we're on the slow path.
293
294
    set(locker, vm, myType);
295
}
296
297
void InferredType::makeTop(VM& vm)
298
{
299
    ConcurrentJITLocker locker(m_lock);
300
    set(locker, vm, Top);
301
}
302
303
void InferredType::set(const ConcurrentJITLocker& locker, VM& vm, Descriptor newDescriptor)
304
{
305
    // We will trigger write barriers while holding our lock. Currently, write barriers don't GC, but that
306
    // could change. If it does, we don't want to deadlock. Note that we could have used
307
    // GCSafeConcurrentJITLocker in the caller, but the caller is on a fast path so maybe that wouldn't be
308
    // a good idea.
309
    DeferGCForAWhile deferGC(vm.heap);
310
    
311
    // Be defensive: if we're not really changing the type, then we don't have to do anything.
312
    if (descriptor(locker) == newDescriptor)
313
        return;
314
315
    // The new descriptor must be more general than the previous one.
316
    ASSERT(newDescriptor.subsumes(descriptor(locker)));
317
318
    // If the new descriptors have different structures, then it can only be because one is null.
319
    if (descriptor(locker).structure() != newDescriptor.structure())
320
        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());
321
322
    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
323
    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
324
    if (m_watchpointSet.state() != ClearWatchpoint) {
325
        // We cannot have been invalidated, since if we were, then we'd already be at Top.
326
        ASSERT(m_watchpointSet.state() != IsInvalidated);
327
328
        // We're about to do expensive things because some compiler thread decided to watch this type and
329
        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
330
        // it.
331
        newDescriptor = Top;
332
333
        m_watchpointSet.fireAll("Inferred type changed");
334
    }
335
336
    // Remove the old InferredStructure object if we no longer need it.
337
    if (!newDescriptor.structure())
338
        m_structure = nullptr;
339
340
    // Add a new InferredStructure object if we need one now.
341
    if (newDescriptor.structure()) {
342
        if (m_structure) {
343
            // We should agree on the structures if we get here.
344
            ASSERT(newDescriptor.structure() == m_structure->structure());
345
        } else {
346
            m_structure = std::make_unique<InferredStructure>(this, newDescriptor.structure());
347
            newDescriptor.structure()->addTransitionWatchpoint(m_structure.get());
348
        }
349
    }
350
351
    // Finally, set the descriptor kind.
352
    m_kind = newDescriptor.kind();
353
354
    // Assert that we did things.
355
    ASSERT(descriptor(locker) == newDescriptor);
356
}
357
358
void InferredType::removeStructure()
359
{
360
    VM& vm = *Heap::heap(this)->vm();
361
362
    ConcurrentJITLocker locker(m_parent->m_lock);
363
    
364
    Descriptor newDescriptor = descriptor(locker);
365
    newDescriptor.removeStructure();
366
    
367
    set(locker, vm, newDescriptor);
368
}
369
370
void InferredType::InferredStructure::InferredStructure(InferredType* parent, Structure* structure)
371
    : m_parent(parent)
372
    , m_structure(vm, parent, structure)
373
{
374
}
375
376
void InferredType::InferredStructure::fireInternal(const FireDetail&)
377
{
378
    m_parent->removeStructure();
379
}
380
381
void InferredType::InferredStructure::finalizeUnconditionally()
382
{
383
    VM& vm = *Heap::heap(m_parent)->vm();
384
385
    ASSERT(Heap::isMarked(m_parent));
386
    
387
    if (!Heap::isMarked(m_structure.get()))
388
        m_parent->removeStructure();
389
}
390
391
} // namespace JSC
392
393
namespace WTF {
394
395
using namespace JSC;
396
397
void printInternal(PrintStream& out, InferredType::Kind kind)
398
{
399
    switch (kind) {
400
    case InferredType::Bottom:
401
        out.print("Bottom");
402
        return;
403
    case InferredType::Boolean:
404
        out.print("Boolean");
405
        return;
406
    case InferredType::Other:
407
        out.print("Other");
408
        return;
409
    case InferredType::Int32:
410
        out.print("Int32");
411
        return;
412
    case InferredType::Double:
413
        out.print("Double");
414
        return;
415
    case InferredType::Number:
416
        out.print("Number");
417
        return;
418
    case InferredType::String:
419
        out.print("String");
420
        return;
421
    case InferredType::ObjectWithStructure:
422
        out.print("ObjectWithStructure");
423
        return;
424
    case InferredType::ObjectWithStructureOrOther:
425
        out.print("ObjectWithStructureOrOther");
426
        return;
427
    case InferredType::Object:
428
        out.print("Object");
429
        return;
430
    case InferredType::ObjectOrOther:
431
        out.print("ObjectOrOther");
432
        return;
433
    case InferredType::Top:
434
        out.print("Top");
435
        return;
436
    }
437
438
    RELEASE_ASSERT_NOT_REACHED();
439
}
440
441
} // namespace WTF
442
- Source/JavaScriptCore/runtime/InferredType.h +236 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 descriptor(const ConcurrentJITLocker&) const
156
    {
157
        return Descriptor(m_kind, m_structure ? m_structure->structure() : nullptr);
158
    }
159
    Descriptor descriptor() const
160
    {
161
        ConcurrentJITLocker locker(m_lock);
162
        return descriptor(locker);
163
    }
164
    
165
    Kind kind(const ConcurrentJITLocker& locker) const { return descriptor().kind(); }
166
    Structure* structure(const ConcurrentJITLocker& locker) const { return descriptor().structure(); }
167
168
    bool isRelevant() const { return m_kind != Top; }
169
170
    // Returns true if the InferredType is still relevant after the store. It's not relevant if it's Top.
171
    ALWAYS_INLINE bool willStoreValue(VM& vm, JSValue value)
172
    {
173
        ConcurrentJITLocker locker(m_lock);
174
        if (!descriptor(locker).includesValue(locker, value))
175
            willStoreValueSlow(locker, vm, value);
176
        return kind(locker) != Top;
177
    }
178
179
    // Immediately makes this type irrelevant.
180
    void makeTop(VM&);
181
182
    // Returns true if it currently makes sense to watch this InferredType for this descriptor. Note that
183
    // this will always return false for Top.
184
    bool canWatch(const ConcurrentJITLocker& locker, const Descriptor&);
185
    bool canWatch(const Descriptor&);
186
    
187
    void addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint*);
188
    void addWatchpoint(Watchpoint*);
189
190
    void dump(PrintStream&) const;
191
192
private:
193
    InferredType(VM&);
194
    ~InferredType();
195
196
    void willStoreValueSlow(const ConcurrentJITLocker&, VM&, JSValue);
197
    void set(const ConcurrentJITLocker&, VM&, Descriptor);
198
    void removeStructure();
199
200
    mutable ConcurrentJITLock m_lock;
201
    
202
    Kind m_kind { Bottom };
203
204
    class InferredStructure : public Watchpoint, public UnconditionalFinalizer {
205
    public:
206
        InferredStructure(InferredType* parent, Structure*);
207
208
        Structure* structure() const { return m_structure.get(); };
209
210
    protected:
211
        void fireInternal(const FireDetail&) override;
212
        void finalizeUnconditionally() override;
213
214
    private:
215
        InferredType* m_parent;
216
        WriteBarrier<Structure> m_structure;
217
    };
218
219
    std::unique_ptr<InferredStructure> m_structure;
220
221
    // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
222
    // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
223
    // thread. The DFG will use the InferredType as the thing that it watches.
224
    InlineWatchpointSet m_watchpointSet;
225
};
226
227
} // namespace JSC
228
229
namespace WTF {
230
231
void printInternal(PrintStream&, JSC::InferredType::Kind);
232
233
} // namespace WTF
234
235
#endif // InferredType_h
236
- Source/JavaScriptCore/runtime/InferredTypeTable.cpp +153 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
    Vector<PropertyOffset> toRemove;
60
    
61
    for (auto& entry : m_table) {
62
        if (entry.value->isRelevant())
63
            visitor.append(&entry.value);
64
        else
65
            toRemove.append(entry.key);
66
    }
67
68
    for (PropertyOffset offset : toRemove)
69
        m_table.remove(offset);
70
}
71
72
InferredTypeTable* InferredTypeTable::clone(VM& vm)
73
{
74
    Vector<TableType::KeyValuePairType, 8> toAdd;
75
    
76
    {
77
        ConcurrentJITLocker locker(m_lock);
78
        for (auto& entry : m_table) {
79
            if (entry.value->isRelevant())
80
                toAdd.append(entry);
81
        }
82
    }
83
84
    InferredTypeTable* result = create(vm);
85
86
    for (auto& entry : toAdd)
87
        result->m_table.add(entry.key, WriteBarrier<InferredType>(vm, result, entry.get()));
88
89
    return result;
90
}
91
92
InferredType* InferredTypeTable::get(const ConcurrentJITLocker& locker, PropertyOffset offset)
93
{
94
    InferredType* result = m_table.get(offset);
95
    if (!result)
96
        return nullptr;
97
98
    // Take this opportunity to prune invalidated types.
99
    if (!result->isRelevant()) {
100
        m_table.remove(offset);
101
        return nullptr;
102
    }
103
104
    return result;
105
}
106
107
InferredType* InferredTypeTable::get(PropertyOffset offset)
108
{
109
    ConcurrentJITLocker locker(m_lock);
110
    return get(locker, offset);
111
}
112
113
bool InferredTypeTable::willStoreValue(VM& vm, PropertyOffset offset, JSValue value)
114
{
115
    ConcurrentJITLocker locker(m_lock);
116
    InferredType* type = m_table.get(offset);
117
    if (!type)
118
        return false;
119
120
    if (type->willStoreValue(vm, value))
121
        return true;
122
123
    m_table.remove(offset);
124
    return false;
125
}
126
127
void InferredTypeTable::makeTop(VM& vm, PropertyOffset offset)
128
{
129
    ConcurrentJITlocker locker(m_lock);
130
    InferredType* type = m_table.take(offset);
131
    if (!type)
132
        return;
133
134
    type->makeTop();
135
}
136
137
bool InferredTypeTable::createInferredTypeForNewProperty(VM& vm, PropertyOffset offset, JSValue value)
138
{
139
    InferredType* type = InferredType::create(vm);
140
    if (!type->willStoreValue(vm, value))
141
        return false;
142
143
    // Fire the barrier before grabbing the lock.
144
    WriteBarrier<InferredType> typeBarrier(vm, this, type);
145
    
146
    ConcurrentJITLocker locker(m_lock);
147
    auto result = m_table.add(offset, typeBarrier);
148
    RELEASE_ASSERT(result.isNewEntry);
149
    return true;
150
}
151
152
} // namespace JSC
153
- Source/JavaScriptCore/runtime/InferredTypeTable.h +90 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").
39
40
class InferredTypeTable final : public JSCell {
41
public:
42
    typedef JSCell Base;
43
44
    static InferredTypeTable* create(VM&);
45
46
    static const bool needsDestruction = true;
47
    static void destroy(JSCell*);
48
49
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
50
51
    static void visitChildren(JSCell*, SlotVisitor&);
52
53
    DECLARE_INFO;
54
55
    InferredTypeTable* clone(VM&);
56
57
    ConcurrentJITLock& lock() { return m_lock; }
58
59
    bool isEmpty() const { return m_table.isEmpty(); }
60
61
    InferredType* get(const ConcurrentJITLocker&, PropertyOffset);
62
    InferredType* get(PropertyOffset);
63
64
    // Returns true if the InferredType for this property is still relevant after the store. It's not
65
    // relevant if it's Top. Note that this table will internally prune Top entries.
66
    bool willStoreValue(VM&, PropertyOffset, JSValue);
67
68
    // Invalidates the type for the property. Useful if we detect a store in a reflective context.
69
    void makeTop(VM&, PropertyOffset);
70
71
    // This creates a new InferredType for this property. Note that this method is needed because
72
    // willStoreValue() assumes that if there isn't an InferredType object for the property, then it's
73
    // because we've already concluded that the property should not have a type.
74
    bool createInferredTypeForNewProperty(VM&, PropertyOffset, JSValue);
75
76
private:
77
    InferredTypeTable(VM&);
78
    ~InferredTypeTable();
79
80
    typedef HashMap<PropertyOffset, WriteBarrier<InferredType>, WTF::IntHash<PropertyOffset>, WTF::UnsignedWithZeroKeyHashTraits<PropertyOffset>> TableType;
81
    
82
    TableType m_table;
83
    ConcurrentJITLock m_lock;
84
};
85
86
} // namespace JSC
87
88
#endif // InferredTypeTable_h
89
90
- Source/JavaScriptCore/runtime/JSObject.h -1 / +19 lines
Lines 1214-1219 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec1
1214
1214
1215
    Structure* structure = this->structure(vm);
1215
    Structure* structure = this->structure(vm);
1216
    if (structure->isDictionary()) {
1216
    if (structure->isDictionary()) {
1217
        ASSERT(!structure->hasInferredTypes());
1218
        
1217
        unsigned currentAttributes;
1219
        unsigned currentAttributes;
1218
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1220
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1219
        if (offset != invalidOffset) {
1221
        if (offset != invalidOffset) {
Lines 1253-1258 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec2
1253
    PropertyOffset offset;
1255
    PropertyOffset offset;
1254
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1256
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1255
    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) {
1257
    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) {
1258
        // Check if we should do type inference.
1259
        if (slot.context() == PutById)
1260
            structure->createInferredTypeForNewProperty(vm, propertyName, value);
1261
        
1256
        DeferGC deferGC(vm.heap);
1262
        DeferGC deferGC(vm.heap);
1257
        Butterfly* newButterfly = butterfly();
1263
        Butterfly* newButterfly = butterfly();
1258
        if (currentCapacity != structure->outOfLineCapacity()) {
1264
        if (currentCapacity != structure->outOfLineCapacity()) {
Lines 1269-1280 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec3
1269
    }
1275
    }
1270
1276
1271
    unsigned currentAttributes;
1277
    unsigned currentAttributes;
1272
    offset = structure->get(vm, propertyName, currentAttributes);
1278
    bool hasInferredType;
1279
    offset = structure->get(vm, propertyName, currentAttributes, hasInferredType);
1273
    if (offset != invalidOffset) {
1280
    if (offset != invalidOffset) {
1274
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1281
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1275
            return false;
1282
            return false;
1276
1283
1277
        structure->didReplaceProperty(offset);
1284
        structure->didReplaceProperty(offset);
1285
        if (UNLIKELY(hasInferredType)) {
1286
            bool isStillValid;
1287
            if (slot.context() == PutById)
1288
                isStillValid = structure->willStoreValue(vm, offset, value);
1289
            else
1290
                isStillValid = structure->makeTop(vm, offset);
1291
            if (UNLIKELY(!isStillValid))
1292
                structure->updateHasInferredTypeForProperty(vm, propertyName);
1293
        }
1278
        slot.setExistingProperty(this, offset);
1294
        slot.setExistingProperty(this, offset);
1279
        putDirect(vm, offset, value);
1295
        putDirect(vm, offset, value);
1280
1296
Lines 1294-1299 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec4
1294
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1310
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1295
    
1311
    
1296
    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1312
    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1313
    if (slot.context() == PutById)
1314
        structure->createInferredTypeForNewProperty(vm, propertyName, value);
1297
    
1315
    
1298
    validateOffset(offset);
1316
    validateOffset(offset);
1299
    ASSERT(structure->isValidOffset(offset));
1317
    ASSERT(structure->isValidOffset(offset));
- Source/JavaScriptCore/runtime/Structure.cpp +73 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_offset))
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
    if (structure->m_inferredTypeTable) {
469
        // FIXME: We could probably get some space savings by having transitions share a table with their
470
        // predecessors. This means that the first property name you use when creating an object determines
471
        // the "space" of inferred types that the structure lives in, and thereafter, everything is shared.
472
        // Unfortunately, this currently won't work, because of how adding new properties works. We assume
473
        // that the inferred type table had never seen the property before. We could fix this by ensuring
474
        // that the InferredTypeTable doesn't forget that it had an entry for type whenever that type goes
475
        // to Top.
476
        transition->m_inferredTypeTable = structure->m_inferredTypeTable->clone(vm);
477
    }
464
478
465
    offset = transition->add(vm, propertyName, attributes);
479
    offset = transition->add(vm, propertyName, attributes);
466
480
Lines 838-843 void Structure::startWatchingInternalPro Source/JavaScriptCore/runtime/Structure.cpp_sec3
838
    setDidWatchInternalProperties(true);
852
    setDidWatchInternalProperties(true);
839
}
853
}
840
854
855
void Structure::updateInferredTypeForProperty(VM& vm, PropertyName propertyName)
856
{
857
    ASSERT(!isCompilationThread());
858
    ASSERT(structure()->classInfo() == info());
859
860
    // This only works if we've got a property table.
861
    PropertyTable* propertyTable;
862
    materializePropertyMapIfNecessary(vm, propertyTable);
863
864
    if (!propertyTable)
865
        return;
866
867
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
868
    if (!entry)
869
        return;
870
871
    if (InferredTypeTable* table = m_inferredTypeTable.get())
872
        entry->hasInferredType = table->get(entry->offset);
873
    else
874
        entry->hasInferredType = false;
875
}
876
877
void Structure::createInferredTypeForNewProperty(VM& vm, PropertyName propertyName, JSValue value)
878
{
879
    ASSERT(!isCompilationThread());
880
    ASSERT(structure()->classInfo() == info());
881
882
    // Create the inferred type table before doing anything else, so that we don't GC after we have already
883
    // grabbed a pointer into the property map.
884
    InferredTypeTable* table = m_inferredTypeTable.get();
885
    if (!table) {
886
        table = InferredTypeTable::create(vm);
887
        WTF::storeStoreBarrier();
888
        m_inferredTypeTable.set(vm, this, table);
889
    }
890
891
    // This only works if we've got a property table.
892
    PropertyTable* propertyTable;
893
    materializePropertyMapIfNecessary(vm, propertyTable);
894
895
    // We must be calling this after having created the given property, so we must have a property table
896
    // now.
897
    ASSERT(propertyTable);
898
899
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
900
    ASSERT(entry);
901
902
    // Since this is a new property, we must not have set hasInferredType previously.
903
    ASSERT(!entry->hasInferredType);
904
    
905
    if (!table->createInferredTypeForNewProperty(vm, entry->offset, value)) {
906
        // This is super rare and weird, but we need to handle it. It'll occur if the value has a type that
907
        // we don't have type inference rules for.
908
        return;
909
    }
910
911
    entry->hasInferredType = true;
912
}
913
841
#if DUMP_PROPERTYMAP_STATS
914
#if DUMP_PROPERTYMAP_STATS
842
915
843
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
916
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
- Source/JavaScriptCore/runtime/Structure.h +56 lines
Lines 81-91 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec1
81
    UniquedStringImpl* key;
81
    UniquedStringImpl* key;
82
    PropertyOffset offset;
82
    PropertyOffset offset;
83
    uint8_t attributes;
83
    uint8_t attributes;
84
    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
85
85
    PropertyMapEntry()
86
    PropertyMapEntry()
86
        : key(nullptr)
87
        : key(nullptr)
87
        , offset(invalidOffset)
88
        , offset(invalidOffset)
88
        , attributes(0)
89
        , attributes(0)
90
        , hasInferredType(false)
89
    {
91
    {
90
    }
92
    }
91
    
93
    
Lines 93-98 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec2
93
        : key(key)
95
        : key(key)
94
        , offset(offset)
96
        , offset(offset)
95
        , attributes(attributes)
97
        , attributes(attributes)
98
        , hasInferredType(false)
96
    {
99
    {
97
        ASSERT(this->attributes == attributes);
100
        ASSERT(this->attributes == attributes);
98
    }
101
    }
Lines 323-328 public: Source/JavaScriptCore/runtime/Structure.h_sec3
323
326
324
    PropertyOffset get(VM&, PropertyName);
327
    PropertyOffset get(VM&, PropertyName);
325
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
328
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
329
    PropertyOffset get(VM&, PropertyName, unsigned& attributes, bool& hasInferredType);
326
330
327
    // This is a somewhat internalish method. It will call your functor while possibly holding the
331
    // 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
332
    // 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_sec4
477
            structure->startWatchingInternalPropertiesIfNecessary(vm);
481
            structure->startWatchingInternalPropertiesIfNecessary(vm);
478
    }
482
    }
479
483
484
    bool hasInferredTypes() const
485
    {
486
        return !!m_inferredTypeTable;
487
    }
488
489
    InferredType* inferredTypeForOffset(PropertyOffset offset)
490
    {
491
        if (InferredTypeTable* table = m_inferredTypeTable.get())
492
            return table->get(offset);
493
        return nullptr;
494
    }
495
496
    // Returns true if the type of the property is still valid.
497
    ALWAYS_INLINE bool willStoreValue(VM& vm, PropertyOffset offset, JSValue value)
498
    {
499
        InferredTypeTable* table = m_inferredTypeTable.get();
500
        if (LIKELY(!table))
501
            return false;
502
        bool result = table->willStoreValue(vm, offset, value);
503
        if (table->isEmpty())
504
            m_inferredTypeTable.clear();
505
        return result;
506
    }
507
508
    // Returns false always, to match the return value semantics of willStoreValue(): if it returns false,
509
    // then the property type is invalid (which is always).
510
    ALWAYS_INLINE bool makeTop(VM& vm, PropertyOffset offset)
511
    {
512
        InferredTypeTable* table = m_inferredTypeTable.get();
513
        if (LIKELY(!table))
514
            return false;
515
        table->makeTop(vm, offset);
516
        if (table->isEmpty())
517
            m_inferredTypeTable.clear();
518
        return false;
519
    }
520
521
    void updateHasInferredTypeForProperty(VM&, PropertyName);
522
523
    ALWAYS_INLINE void createInferredTypeForNewProperty(VM& vm, PropertyName propertyName, JSValue value)
524
    {
525
        // FIXME: These conditions could probably be refined.
526
        if (isDictionary() || transitionWatchpointIsLikelyToBeFired())
527
            return;
528
529
        createInferredTypeForNewPropertySlow(vm, propertyName, value);
530
    }
531
480
    PassRefPtr<StructureShape> toStructureShape(JSValue);
532
    PassRefPtr<StructureShape> toStructureShape(JSValue);
481
    
533
    
482
    // Determines if the two structures match enough that this one could be used for allocations
534
    // Determines if the two structures match enough that this one could be used for allocations
Lines 627-632 private: Source/JavaScriptCore/runtime/Structure.h_sec5
627
    
679
    
628
    void startWatchingInternalProperties(VM&);
680
    void startWatchingInternalProperties(VM&);
629
681
682
    void createInferredTypeForNewPropertySlow(VM&, PropertyName, JSValue);
683
630
    static const int s_maxTransitionLength = 64;
684
    static const int s_maxTransitionLength = 64;
631
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
685
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
632
686
Lines 650-655 private: Source/JavaScriptCore/runtime/Structure.h_sec6
650
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
704
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
651
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
705
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
652
706
707
    WriteBarrier<InferredTypeTable> m_inferredTypeTable;
708
653
    mutable InlineWatchpointSet m_transitionWatchpointSet;
709
    mutable InlineWatchpointSet m_transitionWatchpointSet;
654
710
655
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
711
    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